]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tg3] New tg3 driver
authorThomas Miletich <thomas.miletich@gmail.com>
Mon, 30 Jan 2012 23:10:52 +0000 (23:10 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 30 Jan 2012 23:10:53 +0000 (23:10 +0000)
Replace the old Etherboot tg3 driver with a more up-to-date driver
using the iPXE API.

Signed-off-by: Thomas Miletich <thomas.miletich@gmail.com>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/Makefile
src/drivers/net/tg3.c [deleted file]
src/drivers/net/tg3/tg3.c [new file with mode: 0644]
src/drivers/net/tg3/tg3.h [moved from src/drivers/net/tg3.h with 50% similarity]
src/drivers/net/tg3/tg3_hw.c [new file with mode: 0644]
src/drivers/net/tg3/tg3_phy.c [new file with mode: 0644]

index e2425d7637857cb11996001aa453f5518771f24a..c30dc5c9728ef43c0596ccdcd65f21064d558c35 100644 (file)
@@ -73,6 +73,7 @@ SRCDIRS               += drivers/net/ath/ath5k
 SRCDIRS                += drivers/net/ath/ath9k
 SRCDIRS                += drivers/net/vxge
 SRCDIRS                += drivers/net/efi
+SRCDIRS                += drivers/net/tg3
 SRCDIRS                += drivers/block
 SRCDIRS                += drivers/nvs
 SRCDIRS                += drivers/bitbash
diff --git a/src/drivers/net/tg3.c b/src/drivers/net/tg3.c
deleted file mode 100644 (file)
index e1562d4..0000000
+++ /dev/null
@@ -1,3435 +0,0 @@
-/* $Id$
- * tg3.c: Broadcom Tigon3 ethernet driver.
- *
- * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)
- * Copyright (C) 2001, 2002 Jeff Garzik (jgarzik@mandrakesoft.com)
- * Copyright (C) 2003 Eric Biederman (ebiederman@lnxi.com)  [etherboot port]
- */
-
-FILE_LICENCE ( GPL2_ONLY );
-
-/* 11-13-2003  timlegge        Fix Issue with NetGear GA302T 
- * 11-18-2003   ebiederm        Generalize NetGear Fix to what the code was supposed to be.
- * 01-06-2005   Alf (Frederic Olivie) Add Dell bcm 5751 (0x1677) support
- * 04-15-2005   Martin Vogt Add Fujitsu Siemens Computer (FSC) 0x1734 bcm 5751 0x105d support
- */
-
-#include "etherboot.h"
-#include "nic.h"
-#include <errno.h>
-#include <ipxe/pci.h>
-#include <ipxe/ethernet.h>
-#include "string.h"
-#include <mii.h>
-#include "tg3.h"
-
-#define SUPPORT_COPPER_PHY  1
-#define SUPPORT_FIBER_PHY   1
-#define SUPPORT_LINK_REPORT 1
-#define SUPPORT_PARTNO_STR  1
-#define SUPPORT_PHY_STR     1
-
-static struct tg3 tg3;
-
-/* These numbers seem to be hard coded in the NIC firmware somehow.
- * You can't change the ring sizes, but you can change where you place
- * them in the NIC onboard memory.
- */
-#define TG3_RX_RING_SIZE               512
-#define TG3_DEF_RX_RING_PENDING                20      /* RX_RING_PENDING seems to be o.k. at 20 and 200 */
-#define TG3_RX_RCB_RING_SIZE   1024
-
-/*     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ? \
-        512 : 1024) */
-#define TG3_TX_RING_SIZE               512
-#define TG3_DEF_TX_RING_PENDING                (TG3_TX_RING_SIZE - 1)
-
-#define TG3_RX_RING_BYTES      (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_RING_SIZE)
-#define TG3_RX_RCB_RING_BYTES  (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_RCB_RING_SIZE)
-
-#define TG3_TX_RING_BYTES      (sizeof(struct tg3_tx_buffer_desc) * TG3_TX_RING_SIZE)
-#define NEXT_TX(N)             (((N) + 1) & (TG3_TX_RING_SIZE - 1))
-#define PREV_TX(N)             (((N) - 1) & (TG3_TX_RING_SIZE - 1))
-
-#define RX_PKT_BUF_SZ          (1536 + 2 + 64)
-
-struct eth_frame {
-       uint8_t  dst_addr[ETH_ALEN];
-       uint8_t  src_addr[ETH_ALEN];
-       uint16_t type;
-       uint8_t  data [ETH_FRAME_LEN - ETH_HLEN];
-};
-
-struct bss {
-       struct tg3_rx_buffer_desc rx_std[TG3_RX_RING_SIZE];
-       struct tg3_rx_buffer_desc rx_rcb[TG3_RX_RCB_RING_SIZE];
-       struct tg3_tx_buffer_desc tx_ring[TG3_TX_RING_SIZE];
-       struct tg3_hw_status      hw_status;
-       struct tg3_hw_stats       hw_stats;
-       unsigned char             rx_bufs[TG3_DEF_RX_RING_PENDING][RX_PKT_BUF_SZ];
-       struct eth_frame          tx_frame[2];
-} tg3_bss __shared;
-
-/**
- * pci_save_state - save the PCI configuration space of a device before suspending
- * @dev: - PCI device that we're dealing with
- * @buffer: - buffer to hold config space context
- *
- * @buffer must be large enough to hold the entire PCI 2.2 config space 
- * (>= 64 bytes).
- */
-static int pci_save_state(struct pci_device *dev, uint32_t *buffer)
-{
-       int i;
-       for (i = 0; i < 16; i++)
-               pci_read_config_dword(dev, i * 4,&buffer[i]);
-       return 0;
-}
-
-/** 
- * pci_restore_state - Restore the saved state of a PCI device
- * @dev: - PCI device that we're dealing with
- * @buffer: - saved PCI config space
- *
- */
-static int pci_restore_state(struct pci_device *dev, uint32_t *buffer)
-{
-       int i;
-
-       for (i = 0; i < 16; i++)
-               pci_write_config_dword(dev,i * 4, buffer[i]);
-       return 0;
-}
-
-static void tg3_write_indirect_reg32(uint32_t off, uint32_t val)
-{
-       pci_write_config_dword(tg3.pdev, TG3PCI_REG_BASE_ADDR, off);
-       pci_write_config_dword(tg3.pdev, TG3PCI_REG_DATA, val);
-}
-
-#define tw32(reg,val)          tg3_write_indirect_reg32((reg),(val))
-#define tw32_mailbox(reg, val) writel(((val) & 0xffffffff), tg3.regs + (reg))
-#define tw16(reg,val)          writew(((val) & 0xffff), tg3.regs + (reg))
-#define tw8(reg,val)           writeb(((val) & 0xff), tg3.regs + (reg))
-#define tr32(reg)              readl(tg3.regs + (reg))
-#define tr16(reg)              readw(tg3.regs + (reg))
-#define tr8(reg)               readb(tg3.regs + (reg))
-
-static void tw32_carefully(uint32_t reg, uint32_t val)
-{
-       tw32(reg, val);
-       tr32(reg);
-       udelay(100);
-}
-
-static void tw32_mailbox2(uint32_t reg, uint32_t val)
-{
-       tw32_mailbox(reg, val);
-       tr32(reg);
-}
-
-static void tg3_write_mem(uint32_t off, uint32_t val)
-{
-       pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-       pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_DATA, val);
-
-       /* Always leave this as zero. */
-       pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-}
-
-static void tg3_read_mem(uint32_t off, uint32_t *val)
-{
-       pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-       pci_read_config_dword(tg3.pdev, TG3PCI_MEM_WIN_DATA, val);
-
-       /* Always leave this as zero. */
-       pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-}
-
-static void tg3_disable_ints(struct tg3 *tp)
-{
-       tw32(TG3PCI_MISC_HOST_CTRL,
-            (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
-       tw32_mailbox2(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
-}
-
-static void tg3_switch_clocks(struct tg3 *tp)
-{
-       uint32_t orig_clock_ctrl, clock_ctrl;
-
-       clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
-
-       orig_clock_ctrl = clock_ctrl;
-       clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE | 0x1f);
-       tp->pci_clock_ctrl = clock_ctrl;
-       
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
-           (!((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
-              && (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) &&
-               (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE)!=0) {
-               tw32_carefully(TG3PCI_CLOCK_CTRL, 
-                       clock_ctrl | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
-               tw32_carefully(TG3PCI_CLOCK_CTRL, 
-                       clock_ctrl | (CLOCK_CTRL_ALTCLK));
-       }
-       tw32_carefully(TG3PCI_CLOCK_CTRL, clock_ctrl);
-}
-
-#define PHY_BUSY_LOOPS 5000
-
-static int tg3_readphy(struct tg3 *tp, int reg, uint32_t *val)
-{
-       uint32_t frame_val;
-       int loops, ret;
-
-       tw32_carefully(MAC_MI_MODE, tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL);
-
-       *val = 0xffffffff;
-
-       frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
-                     MI_COM_PHY_ADDR_MASK);
-       frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
-                     MI_COM_REG_ADDR_MASK);
-       frame_val |= (MI_COM_CMD_READ | MI_COM_START);
-       
-       tw32_carefully(MAC_MI_COM, frame_val);
-
-       loops = PHY_BUSY_LOOPS;
-       while (loops-- > 0) {
-               udelay(10);
-               frame_val = tr32(MAC_MI_COM);
-
-               if ((frame_val & MI_COM_BUSY) == 0) {
-                       udelay(5);
-                       frame_val = tr32(MAC_MI_COM);
-                       break;
-               }
-       }
-
-       ret = -EBUSY;
-       if (loops > 0) {
-               *val = frame_val & MI_COM_DATA_MASK;
-               ret = 0;
-       }
-
-       tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
-       return ret;
-}
-
-static int tg3_writephy(struct tg3 *tp, int reg, uint32_t val)
-{
-       uint32_t frame_val;
-       int loops, ret;
-
-       tw32_carefully(MAC_MI_MODE, tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL);
-
-       frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
-                     MI_COM_PHY_ADDR_MASK);
-       frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
-                     MI_COM_REG_ADDR_MASK);
-       frame_val |= (val & MI_COM_DATA_MASK);
-       frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
-       
-       tw32_carefully(MAC_MI_COM, frame_val);
-
-       loops = PHY_BUSY_LOOPS;
-       while (loops-- > 0) {
-               udelay(10);
-               frame_val = tr32(MAC_MI_COM);
-               if ((frame_val & MI_COM_BUSY) == 0) {
-                       udelay(5);
-                       frame_val = tr32(MAC_MI_COM);
-                       break;
-               }
-       }
-
-       ret = -EBUSY;
-       if (loops > 0)
-               ret = 0;
-
-       tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
-       return ret;
-}
-
-static int tg3_writedsp(struct tg3 *tp, uint16_t addr, uint16_t val)
-{
-       int err;
-       err  = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, addr);
-       err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
-       return err;
-}
-
-
-static void tg3_phy_set_wirespeed(struct tg3 *tp)
-{
-       uint32_t val;
-
-       if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED)
-               return;
-
-       tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007);
-       tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
-       tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4)));
-}
-
-static int tg3_bmcr_reset(struct tg3 *tp)
-{
-       uint32_t phy_control;
-       int limit, err;
-
-       /* OK, reset it, and poll the BMCR_RESET bit until it
-        * clears or we time out.
-        */
-       phy_control = BMCR_RESET;
-       err = tg3_writephy(tp, MII_BMCR, phy_control);
-       if (err != 0)
-               return -EBUSY;
-
-       limit = 5000;
-       while (limit--) {
-               err = tg3_readphy(tp, MII_BMCR, &phy_control);
-               if (err != 0)
-                       return -EBUSY;
-
-               if ((phy_control & BMCR_RESET) == 0) {
-                       udelay(40);
-                       break;
-               }
-               udelay(10);
-       }
-       if (limit <= 0)
-               return -EBUSY;
-
-       return 0;
-}
-
-static int tg3_wait_macro_done(struct tg3 *tp)
-{
-       int limit = 100;
-
-       while (limit--) {
-               uint32_t tmp32;
-
-               tg3_readphy(tp, 0x16, &tmp32);
-               if ((tmp32 & 0x1000) == 0)
-                       break;
-       }
-       if (limit <= 0)
-               return -EBUSY;
-
-       return 0;
-}
-
-static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
-{
-       static const uint32_t test_pat[4][6] = {
-       { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
-       { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
-       { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
-       { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
-       };
-       int chan;
-
-       for (chan = 0; chan < 4; chan++) {
-               int i;
-
-               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
-                       (chan * 0x2000) | 0x0200);
-               tg3_writephy(tp, 0x16, 0x0002);
-
-               for (i = 0; i < 6; i++)
-                       tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
-                               test_pat[chan][i]);
-
-               tg3_writephy(tp, 0x16, 0x0202);
-               if (tg3_wait_macro_done(tp)) {
-                       *resetp = 1;
-                       return -EBUSY;
-               }
-
-               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
-                            (chan * 0x2000) | 0x0200);
-               tg3_writephy(tp, 0x16, 0x0082);
-               if (tg3_wait_macro_done(tp)) {
-                       *resetp = 1;
-                       return -EBUSY;
-               }
-
-               tg3_writephy(tp, 0x16, 0x0802);
-               if (tg3_wait_macro_done(tp)) {
-                       *resetp = 1;
-                       return -EBUSY;
-               }
-
-               for (i = 0; i < 6; i += 2) {
-                       uint32_t low, high;
-
-                       tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low);
-                       tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high);
-                       if (tg3_wait_macro_done(tp)) {
-                               *resetp = 1;
-                               return -EBUSY;
-                       }
-                       low &= 0x7fff;
-                       high &= 0x000f;
-                       if (low != test_pat[chan][i] ||
-                           high != test_pat[chan][i+1]) {
-                               tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
-                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
-                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
-
-                               return -EBUSY;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int tg3_phy_reset_chanpat(struct tg3 *tp)
-{
-       int chan;
-
-       for (chan = 0; chan < 4; chan++) {
-               int i;
-
-               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
-                            (chan * 0x2000) | 0x0200);
-               tg3_writephy(tp, 0x16, 0x0002);
-               for (i = 0; i < 6; i++)
-                       tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
-               tg3_writephy(tp, 0x16, 0x0202);
-               if (tg3_wait_macro_done(tp))
-                       return -EBUSY;
-       }
-
-       return 0;
-}
-
-static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
-{
-       uint32_t reg32, phy9_orig;
-       int retries, do_phy_reset, err;
-
-       retries = 10;
-       do_phy_reset = 1;
-       do {
-               if (do_phy_reset) {
-                       err = tg3_bmcr_reset(tp);
-                       if (err)
-                               return err;
-                       do_phy_reset = 0;
-               }
-               
-               /* Disable transmitter and interrupt.  */
-               tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32);
-               reg32 |= 0x3000;
-               tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
-
-               /* Set full-duplex, 1000 mbps.  */
-               tg3_writephy(tp, MII_BMCR,
-                       BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
-
-               /* Set to master mode.  */
-               tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig);
-               tg3_writephy(tp, MII_TG3_CTRL,
-                       (MII_TG3_CTRL_AS_MASTER |
-                               MII_TG3_CTRL_ENABLE_AS_MASTER));
-
-               /* Enable SM_DSP_CLOCK and 6dB.  */
-               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
-
-               /* Block the PHY control access.  */
-               tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
-               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800);
-
-               err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
-               if (!err)
-                       break;
-       } while (--retries);
-
-       err = tg3_phy_reset_chanpat(tp);
-       if (err)
-               return err;
-
-       tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
-       tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000);
-
-       tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
-       tg3_writephy(tp, 0x16, 0x0000);
-
-       tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
-
-       tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
-
-       tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32);
-       reg32 &= ~0x3000;
-       tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
-
-       return err;
-}
-
-/* This will reset the tigon3 PHY if there is no valid
- * link.
- */
-static int tg3_phy_reset(struct tg3 *tp)
-{
-       uint32_t phy_status;
-       int err;
-
-       err  = tg3_readphy(tp, MII_BMSR, &phy_status);
-       err |= tg3_readphy(tp, MII_BMSR, &phy_status);
-       if (err != 0)
-               return -EBUSY;
-
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
-               (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-               (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
-               err = tg3_phy_reset_5703_4_5(tp);
-               if (err)
-                       return err;
-               goto out;
-       }
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
-         // Taken from Broadcom's source code
-         tg3_writephy(tp, 0x18, 0x0c00);
-         tg3_writephy(tp, 0x17, 0x000a);
-         tg3_writephy(tp, 0x15, 0x310b);
-         tg3_writephy(tp, 0x17, 0x201f);
-         tg3_writephy(tp, 0x15, 0x9506);
-         tg3_writephy(tp, 0x17, 0x401f);
-         tg3_writephy(tp, 0x15, 0x14e2);
-         tg3_writephy(tp, 0x18, 0x0400);
-       }
-       err = tg3_bmcr_reset(tp);
-       if (err)
-               return err;
- out:
-       tg3_phy_set_wirespeed(tp);
-       return 0;
-}
-
-static void tg3_set_power_state_0(struct tg3 *tp)
-{
-       uint16_t power_control;
-       int pm = tp->pm_cap;
-
-       /* Make sure register accesses (indirect or otherwise)
-        * will function correctly.
-        */
-       pci_write_config_dword(tp->pdev,  TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
-
-       pci_read_config_word(tp->pdev, pm + PCI_PM_CTRL, &power_control);
-
-       power_control |= PCI_PM_CTRL_PME_STATUS;
-       power_control &= ~(PCI_PM_CTRL_STATE_MASK);
-       power_control |= 0;
-       pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
-
-       tw32_carefully(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-
-       return;
-}
-
-
-#if SUPPORT_LINK_REPORT
-static void tg3_link_report(struct tg3 *tp)
-{
-       if (!tp->carrier_ok) {
-               printf("Link is down.\n");
-       } else {
-               printf("Link is up at %d Mbps, %s duplex. %s %s %s\n",
-                       (tp->link_config.active_speed == SPEED_1000 ?
-                              1000 :
-                       (tp->link_config.active_speed == SPEED_100 ?
-                               100 : 10)),
-                       (tp->link_config.active_duplex == DUPLEX_FULL ?  
-                               "full" : "half"),
-                       (tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "TX" : "",
-                       (tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "RX" : "",
-                       (tp->tg3_flags & (TG3_FLAG_TX_PAUSE |TG3_FLAG_RX_PAUSE)) ? "flow control" : "");
-       }
-}
-#else
-#define tg3_link_report(tp)
-#endif
-
-static void tg3_setup_flow_control(struct tg3 *tp, uint32_t local_adv, uint32_t remote_adv)
-{
-       uint32_t new_tg3_flags = 0;
-
-       if (local_adv & ADVERTISE_PAUSE_CAP) {
-               if (local_adv & ADVERTISE_PAUSE_ASYM) {
-                       if (remote_adv & LPA_PAUSE_CAP)
-                               new_tg3_flags |=
-                                       (TG3_FLAG_RX_PAUSE |
-                                        TG3_FLAG_TX_PAUSE);
-                       else if (remote_adv & LPA_PAUSE_ASYM)
-                               new_tg3_flags |=
-                                       (TG3_FLAG_RX_PAUSE);
-               } else {
-                       if (remote_adv & LPA_PAUSE_CAP)
-                               new_tg3_flags |=
-                                       (TG3_FLAG_RX_PAUSE |
-                                        TG3_FLAG_TX_PAUSE);
-               }
-       } else if (local_adv & ADVERTISE_PAUSE_ASYM) {
-               if ((remote_adv & LPA_PAUSE_CAP) &&
-                   (remote_adv & LPA_PAUSE_ASYM))
-                       new_tg3_flags |= TG3_FLAG_TX_PAUSE;
-       }
-
-       tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
-       tp->tg3_flags |= new_tg3_flags;
-
-       if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
-               tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
-       else
-               tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
-
-       if (new_tg3_flags & TG3_FLAG_TX_PAUSE)
-               tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
-       else
-               tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
-}
-
-#if SUPPORT_COPPER_PHY
-static void tg3_aux_stat_to_speed_duplex(
-       struct tg3 *tp __unused, uint32_t val, uint8_t *speed, uint8_t *duplex)
-{
-       static const uint8_t map[] = {
-               [0] = (SPEED_INVALID << 2) | DUPLEX_INVALID,
-               [MII_TG3_AUX_STAT_10HALF >> 8]   = (SPEED_10 << 2) | DUPLEX_HALF,
-               [MII_TG3_AUX_STAT_10FULL >> 8]   = (SPEED_10 << 2) | DUPLEX_FULL,
-               [MII_TG3_AUX_STAT_100HALF >> 8]  = (SPEED_100 << 2) | DUPLEX_HALF,
-               [MII_TG3_AUX_STAT_100_4 >> 8] = (SPEED_INVALID << 2) | DUPLEX_INVALID,
-               [MII_TG3_AUX_STAT_100FULL >> 8]  = (SPEED_100 << 2) | DUPLEX_FULL,
-               [MII_TG3_AUX_STAT_1000HALF >> 8] = (SPEED_1000 << 2) | DUPLEX_HALF,
-               [MII_TG3_AUX_STAT_1000FULL >> 8] = (SPEED_1000 << 2) | DUPLEX_FULL,
-       };
-       uint8_t result;
-       result = map[(val & MII_TG3_AUX_STAT_SPDMASK) >> 8];
-       *speed = result >> 2;
-       *duplex = result & 3;
-}
-
-static int tg3_phy_copper_begin(struct tg3 *tp)
-{
-       uint32_t new_adv;
-
-       tp->link_config.advertising =
-               (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
-                       ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
-                       ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
-                       ADVERTISED_Autoneg | ADVERTISED_MII);
-       
-       if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) {
-               tp->link_config.advertising &=
-                       ~(ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
-       }
-       
-       new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
-       if (tp->link_config.advertising & ADVERTISED_10baseT_Half) {
-               new_adv |= ADVERTISE_10HALF;
-       }
-       if (tp->link_config.advertising & ADVERTISED_10baseT_Full) {
-               new_adv |= ADVERTISE_10FULL;
-       }
-       if (tp->link_config.advertising & ADVERTISED_100baseT_Half) {
-               new_adv |= ADVERTISE_100HALF;
-       }
-       if (tp->link_config.advertising & ADVERTISED_100baseT_Full) {
-               new_adv |= ADVERTISE_100FULL;
-       }
-       tg3_writephy(tp, MII_ADVERTISE, new_adv);
-       
-       if (tp->link_config.advertising &
-               (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) {
-               new_adv = 0;
-               if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) {
-                       new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
-               }
-               if (tp->link_config.advertising & ADVERTISED_1000baseT_Full) {
-                       new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
-               }
-               if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY) &&
-                       (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
-                               tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)) {
-                       new_adv |= (MII_TG3_CTRL_AS_MASTER |
-                               MII_TG3_CTRL_ENABLE_AS_MASTER);
-               }
-               tg3_writephy(tp, MII_TG3_CTRL, new_adv);
-       } else {
-               tg3_writephy(tp, MII_TG3_CTRL, 0);
-       }
-
-       tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
-
-       return 0;
-}
-
-static int tg3_init_5401phy_dsp(struct tg3 *tp)
-{
-       int err;
-
-       /* Turn off tap power management. */
-       err  = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c20);
-       
-       err |= tg3_writedsp(tp, 0x0012, 0x1804);
-       err |= tg3_writedsp(tp, 0x0013, 0x1204);
-       err |= tg3_writedsp(tp, 0x8006, 0x0132);
-       err |= tg3_writedsp(tp, 0x8006, 0x0232);
-       err |= tg3_writedsp(tp, 0x201f, 0x0a20);
-
-       udelay(40);
-
-       return err;
-}
-
-static int tg3_setup_copper_phy(struct tg3 *tp)
-{
-       int current_link_up;
-       uint32_t bmsr, dummy;
-       int i, err;
-
-       tw32_carefully(MAC_STATUS,
-               (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED
-                | MAC_STATUS_LNKSTATE_CHANGED));
-
-       tp->mi_mode = MAC_MI_MODE_BASE;
-       tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
-       tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
-
-       /* Some third-party PHYs need to be reset on link going
-        * down.
-        */
-       if (    (       (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
-                       (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-                       (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0)) &&
-               (tp->carrier_ok)) {
-               tg3_readphy(tp, MII_BMSR, &bmsr);
-               tg3_readphy(tp, MII_BMSR, &bmsr);
-               if (!(bmsr & BMSR_LSTATUS))
-                       tg3_phy_reset(tp);
-       }
-
-       if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
-               tg3_readphy(tp, MII_BMSR, &bmsr);
-               tg3_readphy(tp, MII_BMSR, &bmsr);
-
-               if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE))
-                       bmsr = 0;
-
-               if (!(bmsr & BMSR_LSTATUS)) {
-                       err = tg3_init_5401phy_dsp(tp);
-                       if (err)
-                               return err;
-
-                       tg3_readphy(tp, MII_BMSR, &bmsr);
-                       for (i = 0; i < 1000; i++) {
-                               udelay(10);
-                               tg3_readphy(tp, MII_BMSR, &bmsr);
-                               if (bmsr & BMSR_LSTATUS) {
-                                       udelay(40);
-                                       break;
-                               }
-                       }
-
-                       if ((tp->phy_id & PHY_ID_REV_MASK) == PHY_REV_BCM5401_B0 &&
-                           !(bmsr & BMSR_LSTATUS) &&
-                           tp->link_config.active_speed == SPEED_1000) {
-                               err = tg3_phy_reset(tp);
-                               if (!err)
-                                       err = tg3_init_5401phy_dsp(tp);
-                               if (err)
-                                       return err;
-                       }
-               }
-       } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
-                  tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
-               /* 5701 {A0,B0} CRC bug workaround */
-               tg3_writephy(tp, 0x15, 0x0a75);
-               tg3_writephy(tp, 0x1c, 0x8c68);
-               tg3_writephy(tp, 0x1c, 0x8d68);
-               tg3_writephy(tp, 0x1c, 0x8c68);
-       }
-
-       /* Clear pending interrupts... */
-       tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
-       tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
-
-       tg3_writephy(tp, MII_TG3_IMASK, ~0);
-
-       if (tp->led_mode == led_mode_three_link)
-               tg3_writephy(tp, MII_TG3_EXT_CTRL,
-                            MII_TG3_EXT_CTRL_LNK3_LED_MODE);
-       else
-               tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
-
-       current_link_up = 0;
-
-       tg3_readphy(tp, MII_BMSR, &bmsr);
-       tg3_readphy(tp, MII_BMSR, &bmsr);
-
-       if (bmsr & BMSR_LSTATUS) {
-               uint32_t aux_stat, bmcr;
-
-               tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
-               for (i = 0; i < 2000; i++) {
-                       udelay(10);
-                       tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
-                       if (aux_stat)
-                               break;
-               }
-
-               tg3_aux_stat_to_speed_duplex(tp, aux_stat,
-                       &tp->link_config.active_speed,
-                       &tp->link_config.active_duplex);
-               tg3_readphy(tp, MII_BMCR, &bmcr);
-               tg3_readphy(tp, MII_BMCR, &bmcr);
-               if (bmcr & BMCR_ANENABLE) {
-                       uint32_t gig_ctrl;
-                       
-                       current_link_up = 1;
-                       
-                       /* Force autoneg restart if we are exiting
-                        * low power mode.
-                        */
-                       tg3_readphy(tp, MII_TG3_CTRL, &gig_ctrl);
-                       if (!(gig_ctrl & (MII_TG3_CTRL_ADV_1000_HALF |
-                                     MII_TG3_CTRL_ADV_1000_FULL))) {
-                               current_link_up = 0;
-                       }
-               } else {
-                       current_link_up = 0;
-               }
-       }
-
-       if (current_link_up == 1 &&
-               (tp->link_config.active_duplex == DUPLEX_FULL)) {
-               uint32_t local_adv, remote_adv;
-
-               tg3_readphy(tp, MII_ADVERTISE, &local_adv);
-               local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
-
-               tg3_readphy(tp, MII_LPA, &remote_adv);
-               remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
-
-               /* If we are not advertising full pause capability,
-                * something is wrong.  Bring the link down and reconfigure.
-                */
-               if (local_adv != ADVERTISE_PAUSE_CAP) {
-                       current_link_up = 0;
-               } else {
-                       tg3_setup_flow_control(tp, local_adv, remote_adv);
-               }
-       }
-
-       if (current_link_up == 0) {
-               uint32_t tmp;
-
-               tg3_phy_copper_begin(tp);
-
-               tg3_readphy(tp, MII_BMSR, &tmp);
-               tg3_readphy(tp, MII_BMSR, &tmp);
-               if (tmp & BMSR_LSTATUS)
-                       current_link_up = 1;
-       }
-
-       tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
-       if (current_link_up == 1) {
-               if (tp->link_config.active_speed == SPEED_100 ||
-                   tp->link_config.active_speed == SPEED_10)
-                       tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
-               else
-                       tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
-       } else
-               tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
-
-       tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
-       if (tp->link_config.active_duplex == DUPLEX_HALF)
-               tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
-
-       tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
-               if ((tp->led_mode == led_mode_link10) ||
-                   (current_link_up == 1 &&
-                    tp->link_config.active_speed == SPEED_10))
-                       tp->mac_mode |= MAC_MODE_LINK_POLARITY;
-       } else {
-               if (current_link_up == 1)
-                       tp->mac_mode |= MAC_MODE_LINK_POLARITY;
-               tw32(MAC_LED_CTRL, LED_CTRL_PHY_MODE_1);
-       }
-
-       /* ??? Without this setting Netgear GA302T PHY does not
-        * ??? send/receive packets...
-        * With this other PHYs cannot bring up the link
-        */
-       if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 &&
-               tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
-               tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
-               tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-       }
-
-       tw32_carefully(MAC_MODE, tp->mac_mode);
-
-       /* Link change polled. */
-       tw32_carefully(MAC_EVENT, 0);
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
-           current_link_up == 1 &&
-           tp->link_config.active_speed == SPEED_1000 &&
-           ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ||
-            (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) {
-               udelay(120);
-               tw32_carefully(MAC_STATUS,
-                       (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
-               tg3_write_mem(
-                             NIC_SRAM_FIRMWARE_MBOX,
-                             NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
-       }
-
-       if (current_link_up != tp->carrier_ok) {
-               tp->carrier_ok = current_link_up;
-               tg3_link_report(tp);
-       }
-
-       return 0;
-}
-#else
-#define tg3_setup_copper_phy(TP) (-EINVAL)
-#endif /* SUPPORT_COPPER_PHY */
-
-#if SUPPORT_FIBER_PHY
-struct tg3_fiber_aneginfo {
-       int state;
-#define ANEG_STATE_UNKNOWN             0
-#define ANEG_STATE_AN_ENABLE           1
-#define ANEG_STATE_RESTART_INIT                2
-#define ANEG_STATE_RESTART             3
-#define ANEG_STATE_DISABLE_LINK_OK     4
-#define ANEG_STATE_ABILITY_DETECT_INIT 5
-#define ANEG_STATE_ABILITY_DETECT      6
-#define ANEG_STATE_ACK_DETECT_INIT     7
-#define ANEG_STATE_ACK_DETECT          8
-#define ANEG_STATE_COMPLETE_ACK_INIT   9
-#define ANEG_STATE_COMPLETE_ACK                10
-#define ANEG_STATE_IDLE_DETECT_INIT    11
-#define ANEG_STATE_IDLE_DETECT         12
-#define ANEG_STATE_LINK_OK             13
-#define ANEG_STATE_NEXT_PAGE_WAIT_INIT 14
-#define ANEG_STATE_NEXT_PAGE_WAIT      15
-
-       uint32_t flags;
-#define MR_AN_ENABLE           0x00000001
-#define MR_RESTART_AN          0x00000002
-#define MR_AN_COMPLETE         0x00000004
-#define MR_PAGE_RX             0x00000008
-#define MR_NP_LOADED           0x00000010
-#define MR_TOGGLE_TX           0x00000020
-#define MR_LP_ADV_FULL_DUPLEX  0x00000040
-#define MR_LP_ADV_HALF_DUPLEX  0x00000080
-#define MR_LP_ADV_SYM_PAUSE    0x00000100
-#define MR_LP_ADV_ASYM_PAUSE   0x00000200
-#define MR_LP_ADV_REMOTE_FAULT1        0x00000400
-#define MR_LP_ADV_REMOTE_FAULT2        0x00000800
-#define MR_LP_ADV_NEXT_PAGE    0x00001000
-#define MR_TOGGLE_RX           0x00002000
-#define MR_NP_RX               0x00004000
-
-#define MR_LINK_OK             0x80000000
-
-       unsigned long link_time, cur_time;
-
-       uint32_t ability_match_cfg;
-       int ability_match_count;
-
-       char ability_match, idle_match, ack_match;
-
-       uint32_t txconfig, rxconfig;
-#define ANEG_CFG_NP            0x00000080
-#define ANEG_CFG_ACK           0x00000040
-#define ANEG_CFG_RF2           0x00000020
-#define ANEG_CFG_RF1           0x00000010
-#define ANEG_CFG_PS2           0x00000001
-#define ANEG_CFG_PS1           0x00008000
-#define ANEG_CFG_HD            0x00004000
-#define ANEG_CFG_FD            0x00002000
-#define ANEG_CFG_INVAL         0x00001f06
-
-};
-#define ANEG_OK                0
-#define ANEG_DONE      1
-#define ANEG_TIMER_ENAB        2
-#define ANEG_FAILED    -1
-
-#define ANEG_STATE_SETTLE_TIME 10000
-
-static int tg3_fiber_aneg_smachine(struct tg3 *tp,
-                                  struct tg3_fiber_aneginfo *ap)
-{
-       unsigned long delta;
-       uint32_t rx_cfg_reg;
-       int ret;
-
-       if (ap->state == ANEG_STATE_UNKNOWN) {
-               ap->rxconfig = 0;
-               ap->link_time = 0;
-               ap->cur_time = 0;
-               ap->ability_match_cfg = 0;
-               ap->ability_match_count = 0;
-               ap->ability_match = 0;
-               ap->idle_match = 0;
-               ap->ack_match = 0;
-       }
-       ap->cur_time++;
-
-       if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
-               rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);
-
-               if (rx_cfg_reg != ap->ability_match_cfg) {
-                       ap->ability_match_cfg = rx_cfg_reg;
-                       ap->ability_match = 0;
-                       ap->ability_match_count = 0;
-               } else {
-                       if (++ap->ability_match_count > 1) {
-                               ap->ability_match = 1;
-                               ap->ability_match_cfg = rx_cfg_reg;
-                       }
-               }
-               if (rx_cfg_reg & ANEG_CFG_ACK)
-                       ap->ack_match = 1;
-               else
-                       ap->ack_match = 0;
-
-               ap->idle_match = 0;
-       } else {
-               ap->idle_match = 1;
-               ap->ability_match_cfg = 0;
-               ap->ability_match_count = 0;
-               ap->ability_match = 0;
-               ap->ack_match = 0;
-
-               rx_cfg_reg = 0;
-       }
-
-       ap->rxconfig = rx_cfg_reg;
-       ret = ANEG_OK;
-
-       switch(ap->state) {
-       case ANEG_STATE_UNKNOWN:
-               if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
-                       ap->state = ANEG_STATE_AN_ENABLE;
-
-               /* fallthru */
-       case ANEG_STATE_AN_ENABLE:
-               ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
-               if (ap->flags & MR_AN_ENABLE) {
-                       ap->link_time = 0;
-                       ap->cur_time = 0;
-                       ap->ability_match_cfg = 0;
-                       ap->ability_match_count = 0;
-                       ap->ability_match = 0;
-                       ap->idle_match = 0;
-                       ap->ack_match = 0;
-
-                       ap->state = ANEG_STATE_RESTART_INIT;
-               } else {
-                       ap->state = ANEG_STATE_DISABLE_LINK_OK;
-               }
-               break;
-
-       case ANEG_STATE_RESTART_INIT:
-               ap->link_time = ap->cur_time;
-               ap->flags &= ~(MR_NP_LOADED);
-               ap->txconfig = 0;
-               tw32(MAC_TX_AUTO_NEG, 0);
-               tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-               tw32_carefully(MAC_MODE, tp->mac_mode);
-
-               ret = ANEG_TIMER_ENAB;
-               ap->state = ANEG_STATE_RESTART;
-
-               /* fallthru */
-       case ANEG_STATE_RESTART:
-               delta = ap->cur_time - ap->link_time;
-               if (delta > ANEG_STATE_SETTLE_TIME) {
-                       ap->state = ANEG_STATE_ABILITY_DETECT_INIT;
-               } else {
-                       ret = ANEG_TIMER_ENAB;
-               }
-               break;
-
-       case ANEG_STATE_DISABLE_LINK_OK:
-               ret = ANEG_DONE;
-               break;
-
-       case ANEG_STATE_ABILITY_DETECT_INIT:
-               ap->flags &= ~(MR_TOGGLE_TX);
-               ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);
-               tw32(MAC_TX_AUTO_NEG, ap->txconfig);
-               tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-               tw32_carefully(MAC_MODE, tp->mac_mode);
-
-               ap->state = ANEG_STATE_ABILITY_DETECT;
-               break;
-
-       case ANEG_STATE_ABILITY_DETECT:
-               if (ap->ability_match != 0 && ap->rxconfig != 0) {
-                       ap->state = ANEG_STATE_ACK_DETECT_INIT;
-               }
-               break;
-
-       case ANEG_STATE_ACK_DETECT_INIT:
-               ap->txconfig |= ANEG_CFG_ACK;
-               tw32(MAC_TX_AUTO_NEG, ap->txconfig);
-               tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-               tw32_carefully(MAC_MODE, tp->mac_mode);
-
-               ap->state = ANEG_STATE_ACK_DETECT;
-
-               /* fallthru */
-       case ANEG_STATE_ACK_DETECT:
-               if (ap->ack_match != 0) {
-                       if ((ap->rxconfig & ~ANEG_CFG_ACK) ==
-                           (ap->ability_match_cfg & ~ANEG_CFG_ACK)) {
-                               ap->state = ANEG_STATE_COMPLETE_ACK_INIT;
-                       } else {
-                               ap->state = ANEG_STATE_AN_ENABLE;
-                       }
-               } else if (ap->ability_match != 0 &&
-                          ap->rxconfig == 0) {
-                       ap->state = ANEG_STATE_AN_ENABLE;
-               }
-               break;
-
-       case ANEG_STATE_COMPLETE_ACK_INIT:
-               if (ap->rxconfig & ANEG_CFG_INVAL) {
-                       ret = ANEG_FAILED;
-                       break;
-               }
-               ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX |
-                              MR_LP_ADV_HALF_DUPLEX |
-                              MR_LP_ADV_SYM_PAUSE |
-                              MR_LP_ADV_ASYM_PAUSE |
-                              MR_LP_ADV_REMOTE_FAULT1 |
-                              MR_LP_ADV_REMOTE_FAULT2 |
-                              MR_LP_ADV_NEXT_PAGE |
-                              MR_TOGGLE_RX |
-                              MR_NP_RX);
-               if (ap->rxconfig & ANEG_CFG_FD)
-                       ap->flags |= MR_LP_ADV_FULL_DUPLEX;
-               if (ap->rxconfig & ANEG_CFG_HD)
-                       ap->flags |= MR_LP_ADV_HALF_DUPLEX;
-               if (ap->rxconfig & ANEG_CFG_PS1)
-                       ap->flags |= MR_LP_ADV_SYM_PAUSE;
-               if (ap->rxconfig & ANEG_CFG_PS2)
-                       ap->flags |= MR_LP_ADV_ASYM_PAUSE;
-               if (ap->rxconfig & ANEG_CFG_RF1)
-                       ap->flags |= MR_LP_ADV_REMOTE_FAULT1;
-               if (ap->rxconfig & ANEG_CFG_RF2)
-                       ap->flags |= MR_LP_ADV_REMOTE_FAULT2;
-               if (ap->rxconfig & ANEG_CFG_NP)
-                       ap->flags |= MR_LP_ADV_NEXT_PAGE;
-
-               ap->link_time = ap->cur_time;
-
-               ap->flags ^= (MR_TOGGLE_TX);
-               if (ap->rxconfig & 0x0008)
-                       ap->flags |= MR_TOGGLE_RX;
-               if (ap->rxconfig & ANEG_CFG_NP)
-                       ap->flags |= MR_NP_RX;
-               ap->flags |= MR_PAGE_RX;
-
-               ap->state = ANEG_STATE_COMPLETE_ACK;
-               ret = ANEG_TIMER_ENAB;
-               break;
-
-       case ANEG_STATE_COMPLETE_ACK:
-               if (ap->ability_match != 0 &&
-                   ap->rxconfig == 0) {
-                       ap->state = ANEG_STATE_AN_ENABLE;
-                       break;
-               }
-               delta = ap->cur_time - ap->link_time;
-               if (delta > ANEG_STATE_SETTLE_TIME) {
-                       if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) {
-                               ap->state = ANEG_STATE_IDLE_DETECT_INIT;
-                       } else {
-                               if ((ap->txconfig & ANEG_CFG_NP) == 0 &&
-                                   !(ap->flags & MR_NP_RX)) {
-                                       ap->state = ANEG_STATE_IDLE_DETECT_INIT;
-                               } else {
-                                       ret = ANEG_FAILED;
-                               }
-                       }
-               }
-               break;
-
-       case ANEG_STATE_IDLE_DETECT_INIT:
-               ap->link_time = ap->cur_time;
-               tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-               tw32_carefully(MAC_MODE, tp->mac_mode);
-
-               ap->state = ANEG_STATE_IDLE_DETECT;
-               ret = ANEG_TIMER_ENAB;
-               break;
-
-       case ANEG_STATE_IDLE_DETECT:
-               if (ap->ability_match != 0 &&
-                   ap->rxconfig == 0) {
-                       ap->state = ANEG_STATE_AN_ENABLE;
-                       break;
-               }
-               delta = ap->cur_time - ap->link_time;
-               if (delta > ANEG_STATE_SETTLE_TIME) {
-                       /* XXX another gem from the Broadcom driver :( */
-                       ap->state = ANEG_STATE_LINK_OK;
-               }
-               break;
-
-       case ANEG_STATE_LINK_OK:
-               ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK);
-               ret = ANEG_DONE;
-               break;
-
-       case ANEG_STATE_NEXT_PAGE_WAIT_INIT:
-               /* ??? unimplemented */
-               break;
-
-       case ANEG_STATE_NEXT_PAGE_WAIT:
-               /* ??? unimplemented */
-               break;
-
-       default:
-               ret = ANEG_FAILED;
-               break;
-       };
-
-       return ret;
-}
-
-static int tg3_setup_fiber_phy(struct tg3 *tp)
-{
-       uint32_t orig_pause_cfg;
-       uint16_t orig_active_speed;
-       uint8_t orig_active_duplex;
-       int current_link_up;
-       int i;
-
-       orig_pause_cfg =
-               (tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
-                                 TG3_FLAG_TX_PAUSE));
-       orig_active_speed = tp->link_config.active_speed;
-       orig_active_duplex = tp->link_config.active_duplex;
-
-       tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
-       tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
-       tw32_carefully(MAC_MODE, tp->mac_mode);
-
-       /* Reset when initting first time or we have a link. */
-       if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
-           (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
-               /* Set PLL lock range. */
-               tg3_writephy(tp, 0x16, 0x8007);
-
-               /* SW reset */
-               tg3_writephy(tp, MII_BMCR, BMCR_RESET);
-
-               /* Wait for reset to complete. */
-               mdelay(5);
-
-               /* Config mode; select PMA/Ch 1 regs. */
-               tg3_writephy(tp, 0x10, 0x8411);
-
-               /* Enable auto-lock and comdet, select txclk for tx. */
-               tg3_writephy(tp, 0x11, 0x0a10);
-
-               tg3_writephy(tp, 0x18, 0x00a0);
-               tg3_writephy(tp, 0x16, 0x41ff);
-
-               /* Assert and deassert POR. */
-               tg3_writephy(tp, 0x13, 0x0400);
-               udelay(40);
-               tg3_writephy(tp, 0x13, 0x0000);
-
-               tg3_writephy(tp, 0x11, 0x0a50);
-               udelay(40);
-               tg3_writephy(tp, 0x11, 0x0a10);
-
-               /* Wait for signal to stabilize */
-               mdelay(150);
-
-               /* Deselect the channel register so we can read the PHYID
-                * later.
-                */
-               tg3_writephy(tp, 0x10, 0x8011);
-       }
-
-       /* Disable link change interrupt.  */
-       tw32_carefully(MAC_EVENT, 0);
-
-       current_link_up = 0;
-       if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
-               if (!(tp->tg3_flags & TG3_FLAG_GOT_SERDES_FLOWCTL)) {
-                       struct tg3_fiber_aneginfo aninfo;
-                       int status = ANEG_FAILED;
-                       unsigned int tick;
-                       uint32_t tmp;
-
-                       memset(&aninfo, 0, sizeof(aninfo));
-                       aninfo.flags |= (MR_AN_ENABLE);
-
-                       tw32(MAC_TX_AUTO_NEG, 0);
-
-                       tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
-                       tw32_carefully(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
-
-                       tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
-
-                       aninfo.state = ANEG_STATE_UNKNOWN;
-                       aninfo.cur_time = 0;
-                       tick = 0;
-                       while (++tick < 195000) {
-                               status = tg3_fiber_aneg_smachine(tp, &aninfo);
-                               if (status == ANEG_DONE ||
-                                   status == ANEG_FAILED)
-                                       break;
-
-                               udelay(1);
-                       }
-
-                       tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-                       tw32_carefully(MAC_MODE, tp->mac_mode);
-
-                       if (status == ANEG_DONE &&
-                           (aninfo.flags &
-                            (MR_AN_COMPLETE | MR_LINK_OK |
-                             MR_LP_ADV_FULL_DUPLEX))) {
-                               uint32_t local_adv, remote_adv;
-
-                               local_adv = ADVERTISE_PAUSE_CAP;
-                               remote_adv = 0;
-                               if (aninfo.flags & MR_LP_ADV_SYM_PAUSE)
-                                       remote_adv |= LPA_PAUSE_CAP;
-                               if (aninfo.flags & MR_LP_ADV_ASYM_PAUSE)
-                                       remote_adv |= LPA_PAUSE_ASYM;
-
-                               tg3_setup_flow_control(tp, local_adv, remote_adv);
-
-                               tp->tg3_flags |=
-                                       TG3_FLAG_GOT_SERDES_FLOWCTL;
-                               current_link_up = 1;
-                       }
-                       for (i = 0; i < 60; i++) {
-                               udelay(20);
-                               tw32_carefully(MAC_STATUS,
-                                       (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
-                               if ((tr32(MAC_STATUS) &
-                                    (MAC_STATUS_SYNC_CHANGED |
-                                     MAC_STATUS_CFG_CHANGED)) == 0)
-                                       break;
-                       }
-                       if (current_link_up == 0 &&
-                           (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
-                               current_link_up = 1;
-                       }
-               } else {
-                       /* Forcing 1000FD link up. */
-                       current_link_up = 1;
-               }
-       }
-
-       tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
-       tw32_carefully(MAC_MODE, tp->mac_mode);
-
-       tp->hw_status->status =
-               (SD_STATUS_UPDATED |
-                (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
-
-       for (i = 0; i < 100; i++) {
-               udelay(20);
-               tw32_carefully(MAC_STATUS,
-                       (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
-               if ((tr32(MAC_STATUS) &
-                    (MAC_STATUS_SYNC_CHANGED |
-                     MAC_STATUS_CFG_CHANGED)) == 0)
-                       break;
-       }
-
-       if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0)
-               current_link_up = 0;
-
-       if (current_link_up == 1) {
-               tp->link_config.active_speed = SPEED_1000;
-               tp->link_config.active_duplex = DUPLEX_FULL;
-       } else {
-               tp->link_config.active_speed = SPEED_INVALID;
-               tp->link_config.active_duplex = DUPLEX_INVALID;
-       }
-
-       if (current_link_up != tp->carrier_ok) {
-               tp->carrier_ok = current_link_up;
-               tg3_link_report(tp);
-       } else {
-               uint32_t now_pause_cfg =
-                       tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
-                                        TG3_FLAG_TX_PAUSE);
-               if (orig_pause_cfg != now_pause_cfg ||
-                   orig_active_speed != tp->link_config.active_speed ||
-                   orig_active_duplex != tp->link_config.active_duplex)
-                       tg3_link_report(tp);
-       }
-
-       if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
-               tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
-               if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
-                       tw32_carefully(MAC_MODE, tp->mac_mode);
-               }
-       }
-
-       return 0;
-}
-#else
-#define tg3_setup_fiber_phy(TP) (-EINVAL)
-#endif /* SUPPORT_FIBER_PHY */
-
-static int tg3_setup_phy(struct tg3 *tp)
-{
-       int err;
-
-       if (tp->phy_id == PHY_ID_SERDES) {
-               err = tg3_setup_fiber_phy(tp);
-       } else {
-               err = tg3_setup_copper_phy(tp);
-       }
-
-       if (tp->link_config.active_speed == SPEED_1000 &&
-           tp->link_config.active_duplex == DUPLEX_HALF)
-               tw32(MAC_TX_LENGTHS,
-                    ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
-                     (6 << TX_LENGTHS_IPG_SHIFT) |
-                     (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)));
-       else
-               tw32(MAC_TX_LENGTHS,
-                    ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
-                     (6 << TX_LENGTHS_IPG_SHIFT) |
-                     (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
-
-       return err;
-}
-
-
-#define MAX_WAIT_CNT 1000
-
-/* To stop a block, clear the enable bit and poll till it
- * clears.  
- */
-static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, uint32_t enable_bit)
-{
-       unsigned int i;
-       uint32_t val;
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
-               switch(ofs) {
-               case RCVLSC_MODE:
-               case DMAC_MODE:
-               case MBFREE_MODE:
-               case BUFMGR_MODE:
-               case MEMARB_MODE:
-                       /* We can't enable/disable these bits of the
-                        * 5705 or 5787, just say success.
-                        */
-                       return 0;
-               default:
-                       break;
-               }
-       }
-       val = tr32(ofs);
-       val &= ~enable_bit;
-       tw32(ofs, val);
-       tr32(ofs);
-
-       for (i = 0; i < MAX_WAIT_CNT; i++) {
-               udelay(100);
-               val = tr32(ofs);
-               if ((val & enable_bit) == 0)
-                       break;
-       }
-
-       if (i == MAX_WAIT_CNT) {
-               printf( "tg3_stop_block timed out, ofs=%#lx enable_bit=%3x\n",
-                      ofs, enable_bit );
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-static int tg3_abort_hw(struct tg3 *tp)
-{
-       int i, err;
-       uint32_t val;
-
-       tg3_disable_ints(tp);
-
-       tp->rx_mode &= ~RX_MODE_ENABLE;
-       tw32_carefully(MAC_RX_MODE, tp->rx_mode);
-
-       err  = tg3_stop_block(tp, RCVBDI_MODE,   RCVBDI_MODE_ENABLE);
-       err |= tg3_stop_block(tp, RCVLPC_MODE,   RCVLPC_MODE_ENABLE);
-       err |= tg3_stop_block(tp, RCVLSC_MODE,   RCVLSC_MODE_ENABLE);
-       err |= tg3_stop_block(tp, RCVDBDI_MODE,  RCVDBDI_MODE_ENABLE);
-       err |= tg3_stop_block(tp, RCVDCC_MODE,   RCVDCC_MODE_ENABLE);
-       err |= tg3_stop_block(tp, RCVCC_MODE,    RCVCC_MODE_ENABLE);
-
-       err |= tg3_stop_block(tp, SNDBDS_MODE,   SNDBDS_MODE_ENABLE);
-       err |= tg3_stop_block(tp, SNDBDI_MODE,   SNDBDI_MODE_ENABLE);
-       err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
-       err |= tg3_stop_block(tp, RDMAC_MODE,    RDMAC_MODE_ENABLE);
-       err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
-       err |= tg3_stop_block(tp, SNDBDC_MODE,   SNDBDC_MODE_ENABLE);
-       if (err)
-               goto out;
-
-       tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
-       tw32_carefully(MAC_MODE, tp->mac_mode);
-
-       tp->tx_mode &= ~TX_MODE_ENABLE;
-       tw32_carefully(MAC_TX_MODE, tp->tx_mode);
-
-       for (i = 0; i < MAX_WAIT_CNT; i++) {
-               udelay(100);
-               if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE))
-                       break;
-       }
-       if (i >= MAX_WAIT_CNT) {
-               printf("tg3_abort_hw timed out TX_MODE_ENABLE will not clear MAC_TX_MODE=%x\n",
-                      (unsigned int) tr32(MAC_TX_MODE));
-               return -ENODEV;
-       }
-
-       err  = tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE);
-       err |= tg3_stop_block(tp, WDMAC_MODE,  WDMAC_MODE_ENABLE);
-       err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE);
-
-       val = tr32(FTQ_RESET);
-       val |= FTQ_RESET_DMA_READ_QUEUE | FTQ_RESET_DMA_HIGH_PRI_READ |
-              FTQ_RESET_SEND_BD_COMPLETION | FTQ_RESET_DMA_WRITE |
-              FTQ_RESET_DMA_HIGH_PRI_WRITE | FTQ_RESET_SEND_DATA_COMPLETION |
-              FTQ_RESET_HOST_COALESCING | FTQ_RESET_MAC_TX |
-              FTQ_RESET_RX_BD_COMPLETE | FTQ_RESET_RX_LIST_PLCMT |
-               FTQ_RESET_RX_DATA_COMPLETION;
-       tw32(FTQ_RESET, val);
-
-       err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE);
-       err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE);
-       if (err)
-               goto out;
-
-       memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
-
-out:
-       return err;
-}
-
-static void tg3_chip_reset(struct tg3 *tp)
-{
-       uint32_t val;
-
-       if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
-               /* Force NVRAM to settle.
-                * This deals with a chip bug which can result in EEPROM
-                * corruption.
-                */
-               if (tp->tg3_flags & TG3_FLAG_NVRAM) {
-                       int i;
-       
-                       tw32(NVRAM_SWARB, SWARB_REQ_SET1);
-                       for (i = 0; i < 100000; i++) {
-                               if (tr32(NVRAM_SWARB) & SWARB_GNT1)
-                                       break;
-                               udelay(10);
-                       }
-               }
-       }
-       /* In Etherboot we don't need to worry about the 5701
-        * REG_WRITE_BUG because we do all register writes indirectly.
-        */
-
-       // Alf: here patched
-       /* do the reset */
-       val = GRC_MISC_CFG_CORECLK_RESET;
-       if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
-               if (tr32(0x7e2c) == 0x60) {
-                       tw32(0x7e2c, 0x20);
-               }
-               if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
-                       tw32(GRC_MISC_CFG, (1 << 29));
-                       val |= (1 << 29);
-               }
-       }
-       
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
-           || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
-           || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) {
-               val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
-       }
-
-       // Alf : Please VALIDATE THIS.
-       // It is necessary in my case (5751) to prevent a reboot, but
-       // I have no idea about a side effect on any other version.
-       // It appears to be what's done in tigon3.c from Broadcom
-       if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
-         tw32(GRC_MISC_CFG, 0x20000000) ;
-         val |= 0x20000000 ;
-       }
-
-       tw32(GRC_MISC_CFG, val);
-
-       /* Flush PCI posted writes.  The normal MMIO registers
-        * are inaccessible at this time so this is the only
-        * way to make this reliably.  I tried to use indirect
-        * register read/write but this upset some 5701 variants.
-        */
-       pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
-
-       udelay(120);
-
-       /* Re-enable indirect register accesses. */
-       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
-                              tp->misc_host_ctrl);
-
-       /* Set MAX PCI retry to zero. */
-       val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
-           (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
-               val |= PCISTATE_RETRY_SAME_DMA;
-       pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
-
-       pci_restore_state(tp->pdev, tp->pci_cfg_state);
-
-       /* Make sure PCI-X relaxed ordering bit is clear. */
-       pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
-       val &= ~PCIX_CAPS_RELAXED_ORDERING;
-       pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
-
-       tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
-
-       if (((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0) &&
-               (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
-               tp->pci_clock_ctrl |=
-                       (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE);
-               tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
-       }
-
-       tw32(TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
-}
-
-static void tg3_stop_fw(struct tg3 *tp)
-{
-       if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
-               uint32_t val;
-               int i;
-
-               tg3_write_mem(NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
-               val = tr32(GRC_RX_CPU_EVENT);
-               val |= (1 << 14);
-               tw32(GRC_RX_CPU_EVENT, val);
-
-               /* Wait for RX cpu to ACK the event.  */
-               for (i = 0; i < 100; i++) {
-                       if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14)))
-                               break;
-                       udelay(1);
-               }
-       }
-}
-
-static int tg3_restart_fw(struct tg3 *tp, uint32_t state)
-{
-       uint32_t val;
-       int i;
-       
-       tg3_write_mem(NIC_SRAM_FIRMWARE_MBOX, 
-               NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
-       /* Wait for firmware initialization to complete. */
-       for (i = 0; i < 100000; i++) {
-               tg3_read_mem(NIC_SRAM_FIRMWARE_MBOX, &val);
-               if (val == (uint32_t) ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
-                       break;
-               udelay(10);
-       }
-       if (i >= 100000 &&
-                   !(tp->tg3_flags2 & TG3_FLG2_SUN_5704) &&
-                   !(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) {
-               printf ( "Firmware will not restart magic=%#x\n",
-                       val );
-               return -ENODEV;
-       }
-       if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
-         state = DRV_STATE_SUSPEND;
-       }
-
-       if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
-           (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0)) {
-         // Enable PCIE bug fix
-         tg3_read_mem(0x7c00, &val);
-         tg3_write_mem(0x7c00, val | 0x02000000);
-       }
-       tg3_write_mem(NIC_SRAM_FW_DRV_STATE_MBOX, state);
-       return 0;
-}
-
-static int tg3_halt(struct tg3 *tp)
-{
-       tg3_stop_fw(tp);
-       tg3_abort_hw(tp);
-       tg3_chip_reset(tp);
-       return tg3_restart_fw(tp, DRV_STATE_UNLOAD);
-}
-
-static void __tg3_set_mac_addr(struct tg3 *tp)
-{
-       uint32_t addr_high, addr_low;
-       int i;
-
-       addr_high = ((tp->nic->node_addr[0] << 8) |
-                    tp->nic->node_addr[1]);
-       addr_low = ((tp->nic->node_addr[2] << 24) |
-                   (tp->nic->node_addr[3] << 16) |
-                   (tp->nic->node_addr[4] <<  8) |
-                   (tp->nic->node_addr[5] <<  0));
-       for (i = 0; i < 4; i++) {
-               tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
-               tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
-       }
-
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
-               (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
-               (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)) {
-               for(i = 0; i < 12; i++) {
-                       tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
-                       tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
-               }
-       }
-       addr_high = (tp->nic->node_addr[0] +
-                    tp->nic->node_addr[1] +
-                    tp->nic->node_addr[2] +
-                    tp->nic->node_addr[3] +
-                    tp->nic->node_addr[4] +
-                    tp->nic->node_addr[5]) &
-               TX_BACKOFF_SEED_MASK;
-       tw32(MAC_TX_BACKOFF_SEED, addr_high);
-}
-
-static void tg3_set_bdinfo(struct tg3 *tp, uint32_t bdinfo_addr,
-                          dma_addr_t mapping, uint32_t maxlen_flags,
-                          uint32_t nic_addr)
-{
-       tg3_write_mem((bdinfo_addr +
-                      TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH),
-                     ((uint64_t) mapping >> 32));
-       tg3_write_mem((bdinfo_addr +
-                      TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW),
-                     ((uint64_t) mapping & 0xffffffff));
-       tg3_write_mem((bdinfo_addr +
-                      TG3_BDINFO_MAXLEN_FLAGS),
-                      maxlen_flags);
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
-               tg3_write_mem((bdinfo_addr + TG3_BDINFO_NIC_ADDR), nic_addr);
-       }
-}
-
-
-static void tg3_init_rings(struct tg3 *tp)
-{
-       unsigned i;
-
-       /* Zero out the tg3 variables */
-       memset(&tg3_bss, 0, sizeof(tg3_bss));
-       tp->rx_std    = &tg3_bss.rx_std[0];
-       tp->rx_rcb    = &tg3_bss.rx_rcb[0];
-       tp->tx_ring   = &tg3_bss.tx_ring[0];
-       tp->hw_status = &tg3_bss.hw_status;
-       tp->hw_stats  = &tg3_bss.hw_stats;
-       tp->mac_mode  = 0;
-
-
-       /* Initialize tx/rx rings for packet processing.
-        *
-        * The chip has been shut down and the driver detached from
-        * the networking, so no interrupts or new tx packets will
-        * end up in the driver.
-        */
-
-       /* Initialize invariants of the rings, we only set this
-        * stuff once.  This works because the card does not
-        * write into the rx buffer posting rings.
-        */
-       for (i = 0; i < TG3_RX_RING_SIZE; i++) {
-               struct tg3_rx_buffer_desc *rxd;
-
-               rxd = &tp->rx_std[i];
-               rxd->idx_len = (RX_PKT_BUF_SZ - 2 - 64) << RXD_LEN_SHIFT;
-               rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT);
-               rxd->opaque = (RXD_OPAQUE_RING_STD | (i << RXD_OPAQUE_INDEX_SHIFT));
-
-               /* Note where the receive buffer for the ring is placed */
-               rxd->addr_hi = 0;
-               rxd->addr_lo = virt_to_bus(
-                       &tg3_bss.rx_bufs[i%TG3_DEF_RX_RING_PENDING][2]);
-       }
-}
-
-#define TG3_WRITE_SETTINGS(TABLE) \
-do { \
-       const uint32_t *_table, *_end; \
-       _table = TABLE; \
-       _end = _table + sizeof(TABLE)/sizeof(TABLE[0]);  \
-       for(; _table < _end; _table += 2) { \
-               tw32(_table[0], _table[1]); \
-       } \
-} while(0)
-
-
-/* initialize/reset the tg3 */
-static int tg3_setup_hw(struct tg3 *tp)
-{
-       uint32_t val, rdmac_mode;
-       int i, err, limit;
-
-       /* Simply don't support setups with extremly buggy firmware in etherboot */
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
-               printf("Error 5701_A0 firmware bug detected\n");
-               return -EINVAL;
-       }
-
-       tg3_disable_ints(tp);
-
-       /* Originally this was all in tg3_init_hw */
-
-       /* Force the chip into D0. */
-       tg3_set_power_state_0(tp);
-
-       tg3_switch_clocks(tp);
-
-       tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
-
-       // This should go somewhere else
-#define T3_PCIE_CAPABILITY_ID_REG           0xD0
-#define T3_PCIE_CAPABILITY_ID               0x10
-#define T3_PCIE_CAPABILITY_REG              0xD2
-
-       /* Originally this was all in tg3_reset_hw */
-
-       tg3_stop_fw(tp);
-
-       /* No need to call tg3_abort_hw here, it is called before tg3_setup_hw. */
-
-       tg3_chip_reset(tp);
-
-       tw32(GRC_MODE, tp->grc_mode);  /* Redundant? */
-
-       err = tg3_restart_fw(tp, DRV_STATE_START);
-       if (err)
-               return err;
-
-       if (tp->phy_id == PHY_ID_SERDES) {
-               tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
-       }
-       tw32_carefully(MAC_MODE, tp->mac_mode);
-
-
-       /* This works around an issue with Athlon chipsets on
-        * B3 tigon3 silicon.  This bit has no effect on any
-        * other revision.
-        * Alf: Except 5750 ! (which reboots)
-        */
-
-        if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
-         tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
-       tw32_carefully(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
-
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
-           (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
-               val = tr32(TG3PCI_PCISTATE);
-               val |= PCISTATE_RETRY_SAME_DMA;
-               tw32(TG3PCI_PCISTATE, val);
-       }
-
-       /* Descriptor ring init may make accesses to the
-        * NIC SRAM area to setup the TX descriptors, so we
-        * can only do this after the hardware has been
-        * successfully reset.
-        */
-       tg3_init_rings(tp);
-
-       /* Clear statistics/status block in chip */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
-               for (i = NIC_SRAM_STATS_BLK;
-                    i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
-                    i += sizeof(uint32_t)) {
-                       tg3_write_mem(i, 0);
-                       udelay(40);
-               }
-       }
-
-       /* This value is determined during the probe time DMA
-        * engine test, tg3_setup_dma.
-        */
-       tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
-
-       tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS |
-                         GRC_MODE_4X_NIC_SEND_RINGS |
-                         GRC_MODE_NO_TX_PHDR_CSUM |
-                         GRC_MODE_NO_RX_PHDR_CSUM);
-       tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
-       tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
-       tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
-
-       tw32(GRC_MODE,
-               tp->grc_mode | 
-               (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
-
-       /* Setup the timer prescalar register.  Clock is always 66Mhz. */
-       tw32(GRC_MISC_CFG,
-            (65 << GRC_MISC_CFG_PRESCALAR_SHIFT));
-
-       /* Initialize MBUF/DESC pool. */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
-               /* Do nothing. */
-       } else if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
-               (tp->pci_chip_rev_id != CHIPREV_ID_5721)) {
-               tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
-                       tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64);
-               else
-                       tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96);
-               tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE);
-               tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE);
-       }
-       if (!(tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)) {
-               tw32(BUFMGR_MB_RDMA_LOW_WATER,
-                    tp->bufmgr_config.mbuf_read_dma_low_water);
-               tw32(BUFMGR_MB_MACRX_LOW_WATER,
-                    tp->bufmgr_config.mbuf_mac_rx_low_water);
-               tw32(BUFMGR_MB_HIGH_WATER,
-                    tp->bufmgr_config.mbuf_high_water);
-       } else {
-               tw32(BUFMGR_MB_RDMA_LOW_WATER,
-                    tp->bufmgr_config.mbuf_read_dma_low_water_jumbo);
-               tw32(BUFMGR_MB_MACRX_LOW_WATER,
-                    tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo);
-               tw32(BUFMGR_MB_HIGH_WATER,
-                    tp->bufmgr_config.mbuf_high_water_jumbo);
-       }
-       tw32(BUFMGR_DMA_LOW_WATER,
-            tp->bufmgr_config.dma_low_water);
-       tw32(BUFMGR_DMA_HIGH_WATER,
-            tp->bufmgr_config.dma_high_water);
-
-       tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
-       for (i = 0; i < 2000; i++) {
-               if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
-                       break;
-               udelay(10);
-       }
-       if (i >= 2000) {
-               printf("tg3_setup_hw cannot enable BUFMGR\n");
-               return -ENODEV;
-       }
-
-       tw32(FTQ_RESET, 0xffffffff);
-       tw32(FTQ_RESET, 0x00000000);
-       for (i = 0; i < 2000; i++) {
-               if (tr32(FTQ_RESET) == 0x00000000)
-                       break;
-               udelay(10);
-       }
-       if (i >= 2000) {
-               printf("tg3_setup_hw cannot reset FTQ\n");
-               return -ENODEV;
-       }
-
-       /* Initialize TG3_BDINFO's at:
-        *  RCVDBDI_STD_BD:     standard eth size rx ring
-        *  RCVDBDI_JUMBO_BD:   jumbo frame rx ring
-        *  RCVDBDI_MINI_BD:    small frame rx ring (??? does not work)
-        *
-        * like so:
-        *  TG3_BDINFO_HOST_ADDR:       high/low parts of DMA address of ring
-        *  TG3_BDINFO_MAXLEN_FLAGS:    (rx max buffer size << 16) |
-        *                              ring attribute flags
-        *  TG3_BDINFO_NIC_ADDR:        location of descriptors in nic SRAM
-        *
-        * Standard receive ring @ NIC_SRAM_RX_BUFFER_DESC, 512 entries.
-        * Jumbo receive ring @ NIC_SRAM_RX_JUMBO_BUFFER_DESC, 256 entries.
-        *
-        * ??? No space allocated for mini receive ring? :(
-        *
-        * The size of each ring is fixed in the firmware, but the location is
-        * configurable.
-        */
-       {
-               static const uint32_t table_all[] = {
-                       /* Setup replenish thresholds. */
-                       RCVBDI_STD_THRESH, TG3_DEF_RX_RING_PENDING / 8,
-
-                       /* Etherboot lives below 4GB */
-                       RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, 0,
-                       RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC,
-               };
-               static const uint32_t table_not_5705[] = {
-                       /* Buffer maximum length */
-                       RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT,
-                       
-                       /* Disable the mini frame rx ring */
-                       RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS,      BDINFO_FLAGS_DISABLED,
-                       
-                       /* Disable the jumbo frame rx ring */
-                       RCVBDI_JUMBO_THRESH, 0,
-                       RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED,
-                       
-                       
-               };
-               TG3_WRITE_SETTINGS(table_all);
-               tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, 
-                       virt_to_bus(tp->rx_std));
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
-                       tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS,
-                               RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT);
-               } else {
-                       TG3_WRITE_SETTINGS(table_not_5705);
-               }
-       }
-
-       
-       /* There is only one send ring on 5705 and 5787, no need to explicitly
-        * disable the others.
-        */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) {
-               /* Clear out send RCB ring in SRAM. */
-               for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE)
-                       tg3_write_mem(i + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED);
-       }
-
-       tp->tx_prod = 0;
-       tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-       tw32_mailbox2(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-
-       tg3_set_bdinfo(tp,
-               NIC_SRAM_SEND_RCB,
-               virt_to_bus(tp->tx_ring),
-               (TG3_TX_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT),
-               NIC_SRAM_TX_BUFFER_DESC);
-
-       /* There is only one receive return ring on 5705 and 5787, no need to
-        * explicitly disable the others.
-        */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) {
-               for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK; i += TG3_BDINFO_SIZE) {
-                       tg3_write_mem(i + TG3_BDINFO_MAXLEN_FLAGS,
-                               BDINFO_FLAGS_DISABLED);
-               }
-       }
-
-       tp->rx_rcb_ptr = 0;
-       tw32_mailbox2(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
-
-       tg3_set_bdinfo(tp,
-               NIC_SRAM_RCV_RET_RCB,
-               virt_to_bus(tp->rx_rcb),
-               (TG3_RX_RCB_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT),
-               0);
-
-       tp->rx_std_ptr = TG3_DEF_RX_RING_PENDING;
-       tw32_mailbox2(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
-                    tp->rx_std_ptr);
-
-       tw32_mailbox2(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, 0);
-
-       /* Initialize MAC address and backoff seed. */
-       __tg3_set_mac_addr(tp);
-
-       /* Calculate RDMAC_MODE setting early, we need it to determine
-        * the RCVLPC_STATE_ENABLE mask.
-        */
-       rdmac_mode = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB |
-               RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB |
-               RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
-               RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
-               RDMAC_MODE_LNGREAD_ENAB);
-       if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
-               rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-               if (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
-                       if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
-                               !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
-                               rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
-                       }
-               }
-       }
-
-       /* Setup host coalescing engine. */
-       tw32(HOSTCC_MODE, 0);
-       for (i = 0; i < 2000; i++) {
-               if (!(tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE))
-                       break;
-               udelay(10);
-       }
-
-       tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
-               MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
-       tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
-
-       tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
-               tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
-                                      GRC_LCLCTRL_GPIO_OUTPUT1);
-       tw32_carefully(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-
-       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
-       tr32(MAILBOX_INTERRUPT_0);
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
-               tw32_carefully(DMAC_MODE, DMAC_MODE_ENABLE);
-       }
-
-       val = ( WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB |
-               WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB |
-               WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB |
-               WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
-               WDMAC_MODE_LNGREAD_ENAB);
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
-               ((tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0) &&
-               !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
-               val |= WDMAC_MODE_RX_ACCEL;
-       }
-
-       /* Host coalescing bug fix */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
-               val |= (1 << 29);
-
-       tw32_carefully(WDMAC_MODE, val);
-
-       if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
-               val = tr32(TG3PCI_X_CAPS);
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
-                       val &= PCIX_CAPS_BURST_MASK;
-                       val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
-               } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
-                       val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
-                       val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
-                       if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
-                               val |= (tp->split_mode_max_reqs <<
-                                       PCIX_CAPS_SPLIT_SHIFT);
-               }
-               tw32(TG3PCI_X_CAPS, val);
-       }
-
-       tw32_carefully(RDMAC_MODE, rdmac_mode);
-       {
-               static const uint32_t table_all[] = {
-                       /* MTU + ethernet header + FCS + optional VLAN tag */
-                       MAC_RX_MTU_SIZE, ETH_MAX_MTU + ETH_HLEN + 8,
-                       
-                       /* The slot time is changed by tg3_setup_phy if we
-                        * run at gigabit with half duplex.
-                        */
-                       MAC_TX_LENGTHS, 
-                       (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
-                       (6 << TX_LENGTHS_IPG_SHIFT) |
-                       (32 << TX_LENGTHS_SLOT_TIME_SHIFT),
-                       
-                       /* Receive rules. */
-                       MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS,
-                       RCVLPC_CONFIG, 0x0181,
-                       
-                       /* Receive/send statistics. */
-                       RCVLPC_STATS_ENABLE, 0xffffff,
-                       RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE,
-                       SNDDATAI_STATSENAB, 0xffffff,
-                       SNDDATAI_STATSCTRL, (SNDDATAI_SCTRL_ENABLE |SNDDATAI_SCTRL_FASTUPD),
-                       
-                       /* Host coalescing engine */
-                       HOSTCC_RXCOL_TICKS, 0,
-                       HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS,
-                       HOSTCC_RXMAX_FRAMES, 1,
-                       HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES,
-                       HOSTCC_RXCOAL_MAXF_INT, 1,
-                       HOSTCC_TXCOAL_MAXF_INT, 0,
-                       
-                       /* Status/statistics block address. */
-                       /* Etherboot lives below 4GB, so HIGH == 0 */
-                       HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, 0,
-
-                       /* No need to enable 32byte coalesce mode. */
-                       HOSTCC_MODE, HOSTCC_MODE_ENABLE | 0,
-                       
-                       RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE,
-                       RCVLPC_MODE, RCVLPC_MODE_ENABLE,
-                       
-                       RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE,
-
-                       SNDDATAC_MODE, SNDDATAC_MODE_ENABLE,
-                       SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE,
-                       RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB,
-                       RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ,
-                       SNDDATAI_MODE, SNDDATAI_MODE_ENABLE,
-                       SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE,
-                       SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE,
-                       
-                       /* Accept all multicast frames. */
-                       MAC_HASH_REG_0, 0xffffffff,
-                       MAC_HASH_REG_1, 0xffffffff,
-                       MAC_HASH_REG_2, 0xffffffff,
-                       MAC_HASH_REG_3, 0xffffffff,
-               };
-               static const uint32_t table_not_5705[] = {
-                       /* Host coalescing engine */
-                       HOSTCC_RXCOAL_TICK_INT, 0,
-                       HOSTCC_TXCOAL_TICK_INT, 0,
-
-                       /* Status/statistics block address. */
-                       /* Etherboot lives below 4GB, so HIGH == 0 */
-                       HOSTCC_STAT_COAL_TICKS, DEFAULT_STAT_COAL_TICKS,
-                       HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, 0,
-                       HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK,
-                       HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK,
-
-                       RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE,
-
-                       MBFREE_MODE, MBFREE_MODE_ENABLE,
-               };
-               TG3_WRITE_SETTINGS(table_all);
-               tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
-                       virt_to_bus(tp->hw_stats));
-               tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
-                       virt_to_bus(tp->hw_status));
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
-                   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) {
-                       TG3_WRITE_SETTINGS(table_not_5705);
-               }
-       }
-
-       tp->tx_mode = TX_MODE_ENABLE;
-       tw32_carefully(MAC_TX_MODE, tp->tx_mode);
-
-       tp->rx_mode = RX_MODE_ENABLE;
-       tw32_carefully(MAC_RX_MODE, tp->rx_mode);
-
-       tp->mi_mode = MAC_MI_MODE_BASE;
-       tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
-       tw32(MAC_LED_CTRL, 0);
-       tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
-       if (tp->phy_id == PHY_ID_SERDES) {
-               tw32_carefully(MAC_RX_MODE, RX_MODE_RESET);
-       }
-       tp->rx_mode |= RX_MODE_KEEP_VLAN_TAG; /* drop tagged vlan packets */
-       tw32_carefully(MAC_RX_MODE, tp->rx_mode);
-
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
-               tw32(MAC_SERDES_CFG, 0x616000);
-
-       /* Prevent chip from dropping frames when flow control
-        * is enabled.
-        */
-       tw32(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
-       tr32(MAC_LOW_WMARK_MAX_RX_FRAME);
-
-       err = tg3_setup_phy(tp);
-
-       /* Ignore CRC stats */
-
-       /* Initialize receive rules. */
-       tw32(MAC_RCV_RULE_0,  0xc2000000 & RCV_RULE_DISABLE_MASK);
-       tw32(MAC_RCV_VALUE_0, 0xffffffff & RCV_RULE_DISABLE_MASK);
-       tw32(MAC_RCV_RULE_1,  0x86000004 & RCV_RULE_DISABLE_MASK);
-       tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
-
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
-           || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750))
-               limit = 8;
-       else
-               limit = 16;
-       if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF)
-               limit -= 4;
-       switch (limit) {
-       case 16:        tw32(MAC_RCV_RULE_15,  0); tw32(MAC_RCV_VALUE_15,  0);
-       case 15:        tw32(MAC_RCV_RULE_14,  0); tw32(MAC_RCV_VALUE_14,  0);
-       case 14:        tw32(MAC_RCV_RULE_13,  0); tw32(MAC_RCV_VALUE_13,  0);
-       case 13:        tw32(MAC_RCV_RULE_12,  0); tw32(MAC_RCV_VALUE_12,  0);
-       case 12:        tw32(MAC_RCV_RULE_11,  0); tw32(MAC_RCV_VALUE_11,  0);
-       case 11:        tw32(MAC_RCV_RULE_10,  0); tw32(MAC_RCV_VALUE_10,  0);
-       case 10:        tw32(MAC_RCV_RULE_9,  0);  tw32(MAC_RCV_VALUE_9,  0);
-       case 9:         tw32(MAC_RCV_RULE_8,  0);  tw32(MAC_RCV_VALUE_8,  0);
-       case 8:         tw32(MAC_RCV_RULE_7,  0);  tw32(MAC_RCV_VALUE_7,  0);
-       case 7:         tw32(MAC_RCV_RULE_6,  0);  tw32(MAC_RCV_VALUE_6,  0);
-       case 6:         tw32(MAC_RCV_RULE_5,  0);  tw32(MAC_RCV_VALUE_5,  0);
-       case 5:         tw32(MAC_RCV_RULE_4,  0);  tw32(MAC_RCV_VALUE_4,  0);
-       case 4:         /* tw32(MAC_RCV_RULE_3,  0); tw32(MAC_RCV_VALUE_3,  0); */
-       case 3:         /* tw32(MAC_RCV_RULE_2,  0); tw32(MAC_RCV_VALUE_2,  0); */
-       case 2:
-       case 1:
-       default:
-               break;
-       };
-
-       return err;
-}
-
-
-
-/* Chips other than 5700/5701 use the NVRAM for fetching info. */
-static void tg3_nvram_init(struct tg3 *tp)
-{
-       tw32(GRC_EEPROM_ADDR,
-            (EEPROM_ADDR_FSM_RESET |
-             (EEPROM_DEFAULT_CLOCK_PERIOD <<
-              EEPROM_ADDR_CLKPERD_SHIFT)));
-
-       mdelay(1);
-
-       /* Enable seeprom accesses. */
-       tw32_carefully(GRC_LOCAL_CTRL,
-               tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
-               uint32_t nvcfg1 = tr32(NVRAM_CFG1);
-
-               tp->tg3_flags |= TG3_FLAG_NVRAM;
-               if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) {
-                       if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE)
-                               tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
-               } else {
-                       nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
-                       tw32(NVRAM_CFG1, nvcfg1);
-               }
-
-       } else {
-               tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED);
-       }
-}
-
-
-static int tg3_nvram_read_using_eeprom(
-       struct tg3 *tp __unused, uint32_t offset, uint32_t *val)
-{
-       uint32_t tmp;
-       int i;
-
-       if (offset > EEPROM_ADDR_ADDR_MASK ||
-               (offset % 4) != 0) {
-               return -EINVAL;
-       }
-
-       tmp = tr32(GRC_EEPROM_ADDR) & ~(EEPROM_ADDR_ADDR_MASK |
-                                       EEPROM_ADDR_DEVID_MASK |
-                                       EEPROM_ADDR_READ);
-       tw32(GRC_EEPROM_ADDR,
-            tmp |
-            (0 << EEPROM_ADDR_DEVID_SHIFT) |
-            ((offset << EEPROM_ADDR_ADDR_SHIFT) &
-             EEPROM_ADDR_ADDR_MASK) |
-            EEPROM_ADDR_READ | EEPROM_ADDR_START);
-
-       for (i = 0; i < 10000; i++) {
-               tmp = tr32(GRC_EEPROM_ADDR);
-
-               if (tmp & EEPROM_ADDR_COMPLETE)
-                       break;
-               udelay(100);
-       }
-       if (!(tmp & EEPROM_ADDR_COMPLETE)) {
-               return -EBUSY;
-       }
-
-       *val = tr32(GRC_EEPROM_DATA);
-       return 0;
-}
-
-static int tg3_nvram_read(struct tg3 *tp, uint32_t offset, uint32_t *val)
-{
-       int i, saw_done_clear;
-
-       if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
-               return tg3_nvram_read_using_eeprom(tp, offset, val);
-
-       if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED)
-               offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) <<
-                         NVRAM_BUFFERED_PAGE_POS) +
-                       (offset % NVRAM_BUFFERED_PAGE_SIZE);
-
-       if (offset > NVRAM_ADDR_MSK)
-               return -EINVAL;
-
-       tw32(NVRAM_SWARB, SWARB_REQ_SET1);
-       for (i = 0; i < 1000; i++) {
-               if (tr32(NVRAM_SWARB) & SWARB_GNT1)
-                       break;
-               udelay(20);
-       }
-
-       tw32(NVRAM_ADDR, offset);
-       tw32(NVRAM_CMD,
-            NVRAM_CMD_RD | NVRAM_CMD_GO |
-            NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
-
-       /* Wait for done bit to clear then set again. */
-       saw_done_clear = 0;
-       for (i = 0; i < 1000; i++) {
-               udelay(10);
-               if (!saw_done_clear &&
-                   !(tr32(NVRAM_CMD) & NVRAM_CMD_DONE))
-                       saw_done_clear = 1;
-               else if (saw_done_clear &&
-                        (tr32(NVRAM_CMD) & NVRAM_CMD_DONE))
-                       break;
-       }
-       if (i >= 1000) {
-               tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
-               return -EBUSY;
-       }
-
-       *val = bswap_32(tr32(NVRAM_RDDATA));
-       tw32(NVRAM_SWARB, 0x20);
-
-       return 0;
-}
-
-struct subsys_tbl_ent {
-       uint16_t subsys_vendor, subsys_devid;
-       uint32_t phy_id;
-};
-
-static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
-       /* Broadcom boards. */
-       { 0x14e4, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */
-       { 0x14e4, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
-       { 0x14e4, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */
-       { 0x14e4, 0x0003, PHY_ID_SERDES  }, /* BCM95700A9 */
-       { 0x14e4, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */
-       { 0x14e4, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */
-       { 0x14e4, 0x0007, PHY_ID_SERDES  }, /* BCM95701A7 */
-       { 0x14e4, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
-       { 0x14e4, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
-       { 0x14e4, 0x0009, PHY_ID_BCM5701 }, /* BCM95703Ax1 */
-       { 0x14e4, 0x8009, PHY_ID_BCM5701 }, /* BCM95703Ax2 */
-
-       /* 3com boards. */
-       { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
-       { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */
-       /* { PCI_VENDOR_ID_3COM, 0x1002, PHY_ID_XXX },     3C996CT */
-       /* { PCI_VENDOR_ID_3COM, 0x1003, PHY_ID_XXX },     3C997T */
-       { PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES  }, /* 3C996SX */
-       /* { PCI_VENDOR_ID_3COM, 0x1005, PHY_ID_XXX },     3C997SZ */
-       { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */
-       { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
-
-       /* DELL boards. */
-       { PCI_VENDOR_ID_DELL, 0x00d1, PHY_ID_BCM5401 }, /* VIPER */
-       { PCI_VENDOR_ID_DELL, 0x0106, PHY_ID_BCM5401 }, /* JAGUAR */
-       { PCI_VENDOR_ID_DELL, 0x0109, PHY_ID_BCM5411 }, /* MERLOT */
-       { PCI_VENDOR_ID_DELL, 0x010a, PHY_ID_BCM5411 }, /* SLIM_MERLOT */
-       { PCI_VENDOR_ID_DELL, 0x0179, PHY_ID_BCM5751 }, /* EtherXpress */
-       
-       /* Fujitsu Siemens Computer */
-       { PCI_VENDOR_ID_FSC, 0x105d, PHY_ID_BCM5751 }, /* Futro C200 */ 
-
-       /* Compaq boards. */
-       { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
-       { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */
-       { PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES  }, /* CHANGELING */
-       { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */
-       { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }  /* NC7780_2 */
-};
-
-static int tg3_phy_probe(struct tg3 *tp)
-{
-       uint32_t eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
-       uint32_t hw_phy_id, hw_phy_id_masked;
-       enum phy_led_mode eeprom_led_mode;
-       uint32_t val;
-       unsigned i;
-       int eeprom_signature_found, err;
-
-       tp->phy_id = PHY_ID_INVALID;
-
-       for (i = 0; i < sizeof(subsys_id_to_phy_id)/sizeof(subsys_id_to_phy_id[0]); i++) {
-               if ((subsys_id_to_phy_id[i].subsys_vendor == tp->subsystem_vendor) &&
-                       (subsys_id_to_phy_id[i].subsys_devid == tp->subsystem_device)) {
-                       tp->phy_id = subsys_id_to_phy_id[i].phy_id;
-                       break;
-               }
-       }
-
-       eeprom_phy_id = PHY_ID_INVALID;
-       eeprom_led_mode = led_mode_auto;
-       eeprom_signature_found = 0;
-       tg3_read_mem(NIC_SRAM_DATA_SIG, &val);
-       if (val == NIC_SRAM_DATA_SIG_MAGIC) {
-               uint32_t nic_cfg;
-
-               tg3_read_mem(NIC_SRAM_DATA_CFG, &nic_cfg);
-               tp->nic_sram_data_cfg = nic_cfg;
-
-               eeprom_signature_found = 1;
-
-               if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
-                   NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) {
-                       eeprom_phy_id = PHY_ID_SERDES;
-               } else {
-                       uint32_t nic_phy_id;
-
-                       tg3_read_mem(NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
-                       if (nic_phy_id != 0) {
-                               uint32_t id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
-                               uint32_t id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
-
-                               eeprom_phy_id  = (id1 >> 16) << 10;
-                               eeprom_phy_id |= (id2 & 0xfc00) << 16;
-                               eeprom_phy_id |= (id2 & 0x03ff) <<  0;
-                       }
-               }
-
-               switch (nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK) {
-               case NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD:
-                       eeprom_led_mode = led_mode_three_link;
-                       break;
-
-               case NIC_SRAM_DATA_CFG_LED_LINK_SPD:
-                       eeprom_led_mode = led_mode_link10;
-                       break;
-
-               default:
-                       eeprom_led_mode = led_mode_auto;
-                       break;
-               };
-               if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
-                       (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-                       (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) &&
-                       (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) {
-                       tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
-               }
-
-               if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE)
-                       tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
-               if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
-                       tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
-       }
-
-       /* Now read the physical PHY_ID from the chip and verify
-        * that it is sane.  If it doesn't look good, we fall back
-        * to either the hard-coded table based PHY_ID and failing
-        * that the value found in the eeprom area.
-        */
-       err  = tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
-       err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
-
-       hw_phy_id  = (hw_phy_id_1 & 0xffff) << 10;
-       hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
-       hw_phy_id |= (hw_phy_id_2 & 0x03ff) <<  0;
-
-       hw_phy_id_masked = hw_phy_id & PHY_ID_MASK;
-
-       if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
-               tp->phy_id = hw_phy_id;
-       } else {
-               /* phy_id currently holds the value found in the
-                * subsys_id_to_phy_id[] table or PHY_ID_INVALID
-                * if a match was not found there.
-                */
-               if (tp->phy_id == PHY_ID_INVALID) {
-                       if (!eeprom_signature_found ||
-                           !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
-                               return -ENODEV;
-                       tp->phy_id = eeprom_phy_id;
-               }
-       }
-
-       err = tg3_phy_reset(tp);
-       if (err)
-               return err;
-
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
-           tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
-               uint32_t mii_tg3_ctrl;
-               
-               /* These chips, when reset, only advertise 10Mb
-                * capabilities.  Fix that.
-                */
-               err  = tg3_writephy(tp, MII_ADVERTISE,
-                                   (ADVERTISE_CSMA |
-                                    ADVERTISE_PAUSE_CAP |
-                                    ADVERTISE_10HALF |
-                                    ADVERTISE_10FULL |
-                                    ADVERTISE_100HALF |
-                                    ADVERTISE_100FULL));
-               mii_tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF |
-                               MII_TG3_CTRL_ADV_1000_FULL |
-                               MII_TG3_CTRL_AS_MASTER |
-                               MII_TG3_CTRL_ENABLE_AS_MASTER);
-               if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
-                       mii_tg3_ctrl = 0;
-
-               err |= tg3_writephy(tp, MII_TG3_CTRL, mii_tg3_ctrl);
-               err |= tg3_writephy(tp, MII_BMCR,
-                                   (BMCR_ANRESTART | BMCR_ANENABLE));
-       }
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
-               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
-               tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
-               tg3_writedsp(tp, MII_TG3_DSP_RW_PORT, 0x2aaa);
-       }
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
-               tg3_writephy(tp, 0x1c, 0x8d68);
-               tg3_writephy(tp, 0x1c, 0x8d68);
-       }
-
-       /* Enable Ethernet@WireSpeed */
-       tg3_phy_set_wirespeed(tp);
-
-       if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) {
-               err = tg3_init_5401phy_dsp(tp);
-       }
-
-       /* Determine the PHY led mode. 
-        * Be careful if this gets set wrong it can result in an inability to 
-        * establish a link.
-        */
-       if (tp->phy_id == PHY_ID_SERDES) {
-               tp->led_mode = led_mode_three_link;
-       }
-       else if (tp->subsystem_vendor == PCI_VENDOR_ID_DELL) {
-               tp->led_mode = led_mode_link10;
-       } else {
-               tp->led_mode = led_mode_three_link;
-               if (eeprom_signature_found &&
-                   eeprom_led_mode != led_mode_auto)
-                       tp->led_mode = eeprom_led_mode;
-       }
-
-       if (tp->phy_id == PHY_ID_SERDES)
-               tp->link_config.advertising =
-                       (ADVERTISED_1000baseT_Half |
-                        ADVERTISED_1000baseT_Full |
-                        ADVERTISED_Autoneg |
-                        ADVERTISED_FIBRE);
-       if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
-               tp->link_config.advertising &=
-                       ~(ADVERTISED_1000baseT_Half |
-                         ADVERTISED_1000baseT_Full);
-
-       return err;
-}
-
-#if SUPPORT_PARTNO_STR
-static void tg3_read_partno(struct tg3 *tp)
-{
-       unsigned char vpd_data[256];
-       int i;
-
-       for (i = 0; i < 256; i += 4) {
-               uint32_t tmp;
-
-               if (tg3_nvram_read(tp, 0x100 + i, &tmp))
-                       goto out_not_found;
-
-               vpd_data[i + 0] = ((tmp >>  0) & 0xff);
-               vpd_data[i + 1] = ((tmp >>  8) & 0xff);
-               vpd_data[i + 2] = ((tmp >> 16) & 0xff);
-               vpd_data[i + 3] = ((tmp >> 24) & 0xff);
-       }
-
-       /* Now parse and find the part number. */
-       for (i = 0; i < 256; ) {
-               unsigned char val = vpd_data[i];
-               int block_end;
-
-               if (val == 0x82 || val == 0x91) {
-                       i = (i + 3 +
-                            (vpd_data[i + 1] +
-                             (vpd_data[i + 2] << 8)));
-                       continue;
-               }
-
-               if (val != 0x90)
-                       goto out_not_found;
-
-               block_end = (i + 3 +
-                            (vpd_data[i + 1] +
-                             (vpd_data[i + 2] << 8)));
-               i += 3;
-               while (i < block_end) {
-                       if (vpd_data[i + 0] == 'P' &&
-                           vpd_data[i + 1] == 'N') {
-                               int partno_len = vpd_data[i + 2];
-
-                               if (partno_len > 24)
-                                       goto out_not_found;
-
-                               memcpy(tp->board_part_number,
-                                      &vpd_data[i + 3],
-                                      partno_len);
-
-                               /* Success. */
-                               return;
-                       }
-               }
-
-               /* Part number not found. */
-               goto out_not_found;
-       }
-
-out_not_found:
-       memcpy(tp->board_part_number, "none", sizeof("none"));
-}
-#else
-#define tg3_read_partno(TP) ((TP)->board_part_number[0] = '\0')
-#endif
-
-static int tg3_get_invariants(struct tg3 *tp)
-{
-       uint32_t misc_ctrl_reg;
-       uint32_t pci_state_reg, grc_misc_cfg;
-       uint16_t pci_cmd;
-       uint8_t  pci_latency;
-       uint32_t val ;
-       int err;
-
-       /* Read the subsystem vendor and device ids */
-       pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->subsystem_vendor);
-       pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_ID, &tp->subsystem_device);
-
-       /* The sun_5704 code needs infrastructure etherboot does have
-        * ignore it for now.
-        */
-
-       /* If we have an AMD 762 or Intel ICH/ICH0 chipset, write
-        * reordering to the mailbox registers done by the host
-        * controller can cause major troubles.  We read back from
-        * every mailbox register write to force the writes to be
-        * posted to the chip in order.
-        *
-        * TG3_FLAG_MBOX_WRITE_REORDER has been forced on.
-        */
-
-       /* Force memory write invalidate off.  If we leave it on,
-        * then on 5700_BX chips we have to enable a workaround.
-        * The workaround is to set the TG3PCI_DMA_RW_CTRL boundry
-        * to match the cacheline size.  The Broadcom driver have this
-        * workaround but turns MWI off all the times so never uses
-        * it.  This seems to suggest that the workaround is insufficient.
-        */
-       pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
-       pci_cmd &= ~PCI_COMMAND_INVALIDATE;
-       /* Also, force SERR#/PERR# in PCI command. */
-       pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
-       pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
-
-       /* It is absolutely critical that TG3PCI_MISC_HOST_CTRL
-        * has the register indirect write enable bit set before
-        * we try to access any of the MMIO registers.  It is also
-        * critical that the PCI-X hw workaround situation is decided
-        * before that as well.
-        */
-       pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, &misc_ctrl_reg);
-
-       tp->pci_chip_rev_id = (misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT);
-
-       /* Initialize misc host control in PCI block. */
-       tp->misc_host_ctrl |= (misc_ctrl_reg &
-                              MISC_HOST_CTRL_CHIPREV);
-       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
-                              tp->misc_host_ctrl);
-
-       pci_read_config_byte(tp->pdev, PCI_LATENCY_TIMER, &pci_latency);
-       if (pci_latency < 64) {
-               pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, 64);
-       }
-
-       pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg);
-
-       /* If this is a 5700 BX chipset, and we are in PCI-X
-        * mode, enable register write workaround.
-        *
-        * The workaround is to use indirect register accesses
-        * for all chip writes not to mailbox registers.
-        *
-        * In etherboot to simplify things we just always use this work around.
-        */
-       if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
-               tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
-       }
-       /* Back to back register writes can cause problems on the 5701,
-        * the workaround is to read back all reg writes except those to
-        * mailbox regs.
-        * In etherboot we always use indirect register accesses so
-        * we don't see this.
-        */
-
-       if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
-               tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
-       if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
-               tp->tg3_flags |= TG3_FLAG_PCI_32BIT;
-
-       /* Chip-specific fixup from Broadcom driver */
-       if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) &&
-           (!(pci_state_reg & PCISTATE_RETRY_SAME_DMA))) {
-               pci_state_reg |= PCISTATE_RETRY_SAME_DMA;
-               pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
-       }
-
-       /* determine if it is PCIE system */
-       // Alf : I have no idea what this is about...
-       // But it's definitely usefull
-       val = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
-       if (val)
-               tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
-
-       /* Force the chip into D0. */
-       tg3_set_power_state_0(tp);
-
-       /* Etherboot does not ask the tg3 to do checksums */
-       /* Etherboot does not ask the tg3 to do jumbo frames */
-       /* Ehterboot does not ask the tg3 to use WakeOnLan. */
-
-       /* A few boards don't want Ethernet@WireSpeed phy feature */
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ||
-               ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
-                       (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
-                       (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1))) {
-               tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
-       }
-
-       /* Avoid tagged irq status etherboot does not use irqs */
-
-       /* Only 5701 and later support tagged irq status mode.
-        * Also, 5788 chips cannot use tagged irq status.
-        *
-        * However, since etherboot does not use irqs avoid tagged irqs
-        * status  because the interrupt condition is more difficult to
-        * fully clear in that mode.
-        */
-       
-       /* Since some 5700_AX && 5700_BX have problems with 32BYTE
-        * coalesce_mode, and the rest work fine anything set.
-        * Don't enable HOST_CC_MODE_32BYTE in etherboot.
-        */
-
-       /* Initialize MAC MI mode, polling disabled. */
-       tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
-       /* Initialize data/descriptor byte/word swapping. */
-       tw32(GRC_MODE, tp->grc_mode);
-
-       tg3_switch_clocks(tp);
-
-       /* Clear this out for sanity. */
-       tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
-
-       /* Etherboot does not need to check if the PCIX_TARGET_HWBUG
-        * is needed.  It always uses it.
-        */
-       
-       udelay(50);
-       tg3_nvram_init(tp);
-
-       /* The TX descriptors will reside in main memory.
-        */
-
-       /* See which board we are using.
-        */
-       grc_misc_cfg = tr32(GRC_MISC_CFG);
-       grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-           grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
-               tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
-               tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
-       }
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
-           (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
-            grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
-               tp->tg3_flags2 |= TG3_FLG2_IS_5788;
-
-#define PCI_DEVICE_ID_TIGON3_5901      0x170d
-#define PCI_DEVICE_ID_TIGON3_5901_2    0x170e
-
-       /* these are limited to 10/100 only */
-       if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) &&
-                   ((grc_misc_cfg == 0x8000) || (grc_misc_cfg == 0x4000))) ||
-               ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
-                       (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM) &&
-                       ((tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901) ||
-                               (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2)))) {
-               tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
-       }
-
-       err = tg3_phy_probe(tp);
-       if (err) {
-               printf("phy probe failed, err %d\n", err);
-       }
-
-       tg3_read_partno(tp);
-
-
-       /* 5700 BX chips need to have their TX producer index mailboxes
-        * written twice to workaround a bug.
-        * In etherboot we do this unconditionally to simplify things.
-        */
-
-       /* 5700 chips can get confused if TX buffers straddle the
-        * 4GB address boundary in some cases.
-        * 
-        * In etherboot we can ignore the problem as etherboot lives below 4GB.
-        */
-
-       /* In etherboot wake-on-lan is unconditionally disabled */
-       return err;
-}
-
-static int  tg3_get_device_address(struct tg3 *tp)
-{
-       struct nic *nic = tp->nic;
-       uint32_t hi, lo, mac_offset;
-
-       if (PCI_FUNC(tp->pdev->busdevfn) == 0)
-               mac_offset = 0x7c;
-       else
-               mac_offset = 0xcc;
-
-       /* First try to get it from MAC address mailbox. */
-       tg3_read_mem(NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
-       if ((hi >> 16) == 0x484b) {
-               nic->node_addr[0] = (hi >>  8) & 0xff;
-               nic->node_addr[1] = (hi >>  0) & 0xff;
-
-               tg3_read_mem(NIC_SRAM_MAC_ADDR_LOW_MBOX, &lo);
-               nic->node_addr[2] = (lo >> 24) & 0xff;
-               nic->node_addr[3] = (lo >> 16) & 0xff;
-               nic->node_addr[4] = (lo >>  8) & 0xff;
-               nic->node_addr[5] = (lo >>  0) & 0xff;
-       }
-       /* Next, try NVRAM. */
-       else if (!tg3_nvram_read(tp, mac_offset + 0, &hi) &&
-                !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
-               nic->node_addr[0] = ((hi >> 16) & 0xff);
-               nic->node_addr[1] = ((hi >> 24) & 0xff);
-               nic->node_addr[2] = ((lo >>  0) & 0xff);
-               nic->node_addr[3] = ((lo >>  8) & 0xff);
-               nic->node_addr[4] = ((lo >> 16) & 0xff);
-               nic->node_addr[5] = ((lo >> 24) & 0xff);
-       }
-       /* Finally just fetch it out of the MAC control regs. */
-       else {
-               hi = tr32(MAC_ADDR_0_HIGH);
-               lo = tr32(MAC_ADDR_0_LOW);
-
-               nic->node_addr[5] = lo & 0xff;
-               nic->node_addr[4] = (lo >> 8) & 0xff;
-               nic->node_addr[3] = (lo >> 16) & 0xff;
-               nic->node_addr[2] = (lo >> 24) & 0xff;
-               nic->node_addr[1] = hi & 0xff;
-               nic->node_addr[0] = (hi >> 8) & 0xff;
-       }
-
-       return 0;
-}
-
-
-static int tg3_setup_dma(struct tg3 *tp)
-{
-       tw32(TG3PCI_CLOCK_CTRL, 0);
-
-       if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) == 0) {
-               tp->dma_rwctrl =
-                       (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
-                       (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
-                       (0x7 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
-                       (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) |
-                       (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT);
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-                       tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA << DMA_RWCTRL_MIN_DMA_SHIFT);
-               }
-       } else {
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
-                       tp->dma_rwctrl =
-                               (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
-                               (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
-                               (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
-                               (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) |
-                               (0x00 << DMA_RWCTRL_MIN_DMA_SHIFT);
-               else
-                       tp->dma_rwctrl =
-                               (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
-                               (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
-                               (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
-                               (0x3 << DMA_RWCTRL_READ_WATER_SHIFT) |
-                               (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT);
-
-               /* Wheee, some more chip bugs... */
-               if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
-                       (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)) {
-                       uint32_t ccval = tr32(TG3PCI_CLOCK_CTRL) & 0x1f;
-
-                       if ((ccval == 0x6) || (ccval == 0x7)) {
-                               tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
-                       }
-               }
-       }
-
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
-               (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)) {
-               tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA << DMA_RWCTRL_MIN_DMA_SHIFT);
-       }
-
-       /*
-         Alf : Tried that, but it does not work. Should be this way though :-(
-       if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
-         tp->dma_rwctrl |= 0x001f0000;
-       }
-       */
-       tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE;
-
-       tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
-
-       return 0;
-}
-
-static void tg3_init_link_config(struct tg3 *tp)
-{
-       tp->link_config.advertising =
-               (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
-                ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
-                ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
-                ADVERTISED_Autoneg | ADVERTISED_MII);
-       tp->carrier_ok = 0;
-       tp->link_config.active_speed = SPEED_INVALID;
-       tp->link_config.active_duplex = DUPLEX_INVALID;
-}
-
-
-#if SUPPORT_PHY_STR
-static const char * tg3_phy_string(struct tg3 *tp)
-{
-       switch (tp->phy_id & PHY_ID_MASK) {
-       case PHY_ID_BCM5400:    return "5400";
-       case PHY_ID_BCM5401:    return "5401";
-       case PHY_ID_BCM5411:    return "5411";
-       case PHY_ID_BCM5701:    return "5701";
-       case PHY_ID_BCM5703:    return "5703";
-       case PHY_ID_BCM5704:    return "5704";
-        case PHY_ID_BCM5705:    return "5705";
-        case PHY_ID_BCM5750:    return "5750";
-       case PHY_ID_BCM5751:    return "5751"; 
-       case PHY_ID_BCM5787:    return "5787";
-       case PHY_ID_BCM8002:    return "8002/serdes";
-       case PHY_ID_SERDES:     return "serdes";
-       default:                return "unknown";
-       };
-}
-#else
-#define tg3_phy_string(TP) "?"
-#endif
-
-
-static void tg3_poll_link(struct tg3 *tp)
-{
-       uint32_t mac_stat;
-
-       mac_stat = tr32(MAC_STATUS);
-       if (tp->phy_id == PHY_ID_SERDES) {
-               if (tp->carrier_ok?
-                       (mac_stat & MAC_STATUS_LNKSTATE_CHANGED):
-                       (mac_stat & MAC_STATUS_PCS_SYNCED)) {
-                       tw32_carefully(MAC_MODE, tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK);
-                       tw32_carefully(MAC_MODE, tp->mac_mode);
-
-                       tg3_setup_phy(tp);
-               }
-       }
-       else {
-               if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED) {
-                       tg3_setup_phy(tp);
-               }
-       }
-}
-
-/**************************************************************************
-POLL - Wait for a frame
-***************************************************************************/
-static void tg3_ack_irqs(struct tg3 *tp)
-{
-       if (tp->hw_status->status & SD_STATUS_UPDATED) {
-               /*
-                * writing any value to intr-mbox-0 clears PCI INTA# and
-                * chip-internal interrupt pending events.
-                * writing non-zero to intr-mbox-0 additional tells the
-                * NIC to stop sending us irqs, engaging "in-intr-handler"
-                * event coalescing.
-                */
-               tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 
-                       0x00000001);
-               /*
-                * Flush PCI write.  This also guarantees that our
-                * status block has been flushed to host memory.
-                */
-               tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
-               tp->hw_status->status &= ~SD_STATUS_UPDATED;
-       }
-}
-
-static int tg3_poll(struct nic *nic, int retrieve)
-{
-       /* return true if there's an ethernet packet ready to read */
-       /* nic->packet should contain data on return */
-       /* nic->packetlen should contain length of data */
-
-       struct tg3 *tp = &tg3;
-       int result;
-
-       result = 0;
-
-       if ( (tp->hw_status->idx[0].rx_producer != tp->rx_rcb_ptr) && !retrieve ) 
-         return 1;
-
-       tg3_ack_irqs(tp);
-
-       if (tp->hw_status->idx[0].rx_producer != tp->rx_rcb_ptr) {
-               struct tg3_rx_buffer_desc *desc;
-               unsigned int len;
-               desc = &tp->rx_rcb[tp->rx_rcb_ptr];
-               if ((desc->opaque & RXD_OPAQUE_RING_MASK) == RXD_OPAQUE_RING_STD) {
-                       len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */
-                       
-                       nic->packetlen = len;
-                       memcpy(nic->packet, bus_to_virt(desc->addr_lo), len);
-                       result = 1;
-               }
-               tp->rx_rcb_ptr = (tp->rx_rcb_ptr + 1) % TG3_RX_RCB_RING_SIZE;
-               
-               /* ACK the status ring */
-               tw32_mailbox2(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, tp->rx_rcb_ptr);
-
-               /* Refill RX ring. */
-               if (result) {
-                       tp->rx_std_ptr = (tp->rx_std_ptr + 1) % TG3_RX_RING_SIZE;
-                       tw32_mailbox2(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, tp->rx_std_ptr);
-               }
-       }
-       tg3_poll_link(tp);
-       return result;
-}
-
-/**************************************************************************
-TRANSMIT - Transmit a frame
-***************************************************************************/
-#if 0
-static void tg3_set_txd(struct tg3 *tp, int entry,
-       dma_addr_t mapping, int len, uint32_t flags,
-       uint32_t mss_and_is_end)
-{
-       struct tg3_tx_buffer_desc *txd =  &tp->tx_ring[entry];
-       int is_end = (mss_and_is_end & 0x1);
-       if (is_end) {
-               flags |= TXD_FLAG_END;
-       }
-
-       txd->addr_hi   = 0;
-       txd->addr_lo   = mapping & 0xffffffff;
-       txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
-       txd->vlan_tag  = 0 << TXD_VLAN_TAG_SHIFT;
-}
-#endif
-
-static void tg3_transmit(struct nic *nic, const char *dst_addr,
-       unsigned int type, unsigned int size, const char *packet)
-{
-       static int frame_idx;
-       struct eth_frame *frame;
-       
-       /* send the packet to destination */
-       struct tg3_tx_buffer_desc *txd;
-       struct tg3 *tp;
-       uint32_t entry;
-       int i;
-
-       /* Wait until there is a free packet frame */
-       tp = &tg3;
-       i = 0;
-       entry = tp->tx_prod;
-       while((tp->hw_status->idx[0].tx_consumer != entry) &&
-               (tp->hw_status->idx[0].tx_consumer != PREV_TX(entry))) {
-               mdelay(10);     /* give the nick a chance */
-               if (++i > 500) { /* timeout 5s for transmit */
-                       printf("transmit timed out\n");
-                       tg3_halt(tp);
-                       tg3_setup_hw(tp);
-                       return;
-               }
-       }
-       if (i != 0) {
-               printf("#");
-       }
-       
-       /* Copy the packet to the our local buffer */
-       frame = &tg3_bss.tx_frame[frame_idx];
-       memcpy(frame->dst_addr, dst_addr, ETH_ALEN);
-       memcpy(frame->src_addr, nic->node_addr, ETH_ALEN);
-       frame->type = htons(type);
-       memset(frame->data, 0, sizeof(frame->data));
-       memcpy(frame->data, packet, size);
-
-       /* Setup the ring buffer entry to transmit */
-       txd            = &tp->tx_ring[entry];
-       txd->addr_hi   = 0; /* Etherboot runs under 4GB */
-       txd->addr_lo   = virt_to_bus(frame);
-       txd->len_flags = ((size + ETH_HLEN) << TXD_LEN_SHIFT) | TXD_FLAG_END;
-       txd->vlan_tag  = 0 << TXD_VLAN_TAG_SHIFT;
-
-       /* Advance to the next entry */
-       entry = NEXT_TX(entry);
-       frame_idx ^= 1;
-
-       /* Packets are ready, update Tx producer idx local and on card */
-       tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
-       tw32_mailbox2((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
-       tp->tx_prod = entry;
-}
-
-/**************************************************************************
-DISABLE - Turn off ethernet interface
-***************************************************************************/
-static void tg3_disable ( struct nic *nic __unused ) {
-       struct tg3 *tp = &tg3;
-       /* put the card in its initial state */
-       /* This function serves 3 purposes.
-        * This disables DMA and interrupts so we don't receive
-        *  unexpected packets or interrupts from the card after
-        *  etherboot has finished. 
-        * This frees resources so etherboot may use
-        *  this driver on another interface
-        * This allows etherboot to reinitialize the interface
-        *  if something is something goes wrong.
-        */
-       tg3_halt(tp);
-       tp->tg3_flags &= ~(TG3_FLAG_INIT_COMPLETE|TG3_FLAG_GOT_SERDES_FLOWCTL);
-       tp->carrier_ok = 0;
-       iounmap((void *)tp->regs);
-}
-
-/**************************************************************************
-IRQ - Enable, Disable, or Force interrupts
-***************************************************************************/
-static void tg3_irq(struct nic *nic __unused, irq_action_t action __unused)
-{
-  switch ( action ) {
-  case DISABLE :
-    break;
-  case ENABLE :
-    break;
-  case FORCE :
-    break;
-  }
-}
-
-static struct nic_operations tg3_operations = {
-       .connect        = dummy_connect,
-       .poll           = tg3_poll,
-       .transmit       = tg3_transmit,
-       .irq            = tg3_irq,
-
-};
-
-/**************************************************************************
-PROBE - Look for an adapter, this routine's visible to the outside
-You should omit the last argument struct pci_device * for a non-PCI NIC
-***************************************************************************/
-static int tg3_probe ( struct nic *nic, struct pci_device *pdev ) {
-
-       struct tg3 *tp = &tg3;
-       unsigned long tg3reg_base, tg3reg_len;
-       int i, err, pm_cap;
-
-       memset(tp, 0, sizeof(*tp));
-
-       adjust_pci_device(pdev);
-
-       nic->irqno  = 0;
-        nic->ioaddr = pdev->ioaddr;
-
-       /* Find power-management capability. */
-       pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
-       if (pm_cap == 0) {
-               printf("Cannot find PowerManagement capability, aborting.\n");
-               return 0;
-       }
-       tg3reg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
-       if (tg3reg_base == -1UL) {
-               printf("Unuseable bar\n");
-               return 0;
-       }
-       tg3reg_len  = pci_bar_size(pdev,  PCI_BASE_ADDRESS_0);
-
-       tp->pdev       = pdev;
-       tp->nic        = nic;
-       tp->pm_cap     = pm_cap;
-       tp->rx_mode    = 0;
-       tp->tx_mode    = 0;
-       tp->mi_mode    = MAC_MI_MODE_BASE;
-       tp->tg3_flags  = 0 & ~TG3_FLAG_INIT_COMPLETE; 
-       
-       /* The word/byte swap controls here control register access byte
-        * swapping.  DMA data byte swapping is controlled in the GRC_MODE
-        * setting below.
-        */
-       tp->misc_host_ctrl =
-               MISC_HOST_CTRL_MASK_PCI_INT |
-               MISC_HOST_CTRL_WORD_SWAP |
-               MISC_HOST_CTRL_INDIR_ACCESS |
-               MISC_HOST_CTRL_PCISTATE_RW;
-
-       /* The NONFRM (non-frame) byte/word swap controls take effect
-        * on descriptor entries, anything which isn't packet data.
-        *
-        * The StrongARM chips on the board (one for tx, one for rx)
-        * are running in big-endian mode.
-        */
-       tp->grc_mode = (GRC_MODE_WSWAP_DATA | GRC_MODE_BSWAP_DATA |
-                       GRC_MODE_WSWAP_NONFRM_DATA);
-#if __BYTE_ORDER == __BIG_ENDIAN
-       tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA;
-#endif
-       tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len);
-       if (tp->regs == 0UL) {
-               printf("Cannot map device registers, aborting\n");
-               return 0;
-       }
-
-       tg3_init_link_config(tp);
-
-       err = tg3_get_invariants(tp);
-       if (err) {
-               printf("Problem fetching invariants of chip, aborting.\n");
-               goto err_out_iounmap;
-       }
-
-       err = tg3_get_device_address(tp);
-       if (err) {
-               printf("Could not obtain valid ethernet address, aborting.\n");
-               goto err_out_iounmap;
-       }
-
-       DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
-
-       tg3_setup_dma(tp);
-
-       /* Now that we have fully setup the chip, save away a snapshot
-        * of the PCI config space.  We need to restore this after
-        * GRC_MISC_CFG core clock resets and some resume events.
-        */
-       pci_save_state(tp->pdev, tp->pci_cfg_state);
-
-       printf("Tigon3 [partno(%s) rev %hx PHY(%s)] (PCI%s:%s:%s)\n",
-               tp->board_part_number,
-               tp->pci_chip_rev_id,
-               tg3_phy_string(tp),
-               ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""),
-               ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ?
-                       ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") :
-                       ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")),
-               ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"));
-
-
-       err = tg3_setup_hw(tp); 
-       if (err) {
-               goto err_out_disable;
-       } 
-       tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
-
-       /* Wait for a reasonable time for the link to come up */
-       tg3_poll_link(tp);
-       for(i = 0; !tp->carrier_ok && (i < VALID_LINK_TIMEOUT*100); i++) {
-               mdelay(1);
-               tg3_poll_link(tp);
-       }
-       if (!tp->carrier_ok){
-               printf("Valid link not established\n");
-               goto err_out_disable;
-       }
-
-       nic->nic_op     = &tg3_operations;
-       return 1;
-
- err_out_iounmap:
-       iounmap((void *)tp->regs);
-       return 0;
- err_out_disable:
-       tg3_disable(nic);
-       return 0;
-}
-
-
-static struct pci_device_id tg3_nics[] = {
-PCI_ROM(0x14e4, 0x1644, "tg3-5700",        "Broadcom Tigon 3 5700", 0),
-PCI_ROM(0x14e4, 0x1645, "tg3-5701",        "Broadcom Tigon 3 5701", 0),
-PCI_ROM(0x14e4, 0x1646, "tg3-5702",        "Broadcom Tigon 3 5702", 0),
-PCI_ROM(0x14e4, 0x1647, "tg3-5703",        "Broadcom Tigon 3 5703", 0),
-PCI_ROM(0x14e4, 0x1648, "tg3-5704",        "Broadcom Tigon 3 5704", 0),
-PCI_ROM(0x14e4, 0x164d, "tg3-5702FE",      "Broadcom Tigon 3 5702FE", 0),
-PCI_ROM(0x14e4, 0x1653, "tg3-5705",        "Broadcom Tigon 3 5705", 0),
-PCI_ROM(0x14e4, 0x1654, "tg3-5705_2",      "Broadcom Tigon 3 5705_2", 0),
-PCI_ROM(0x14e4, 0x1659, "tg3-5721",        "Broadcom Tigon 3 5721", 0),
-PCI_ROM(0x14e4, 0x165d, "tg3-5705M",       "Broadcom Tigon 3 5705M", 0),
-PCI_ROM(0x14e4, 0x165e, "tg3-5705M_2",     "Broadcom Tigon 3 5705M_2", 0),
-PCI_ROM(0x14e4, 0x1677, "tg3-5751",        "Broadcom Tigon 3 5751", 0),
-PCI_ROM(0x14e4, 0x167a, "tg3-5754",        "Broadcom Tigon 3 5754", 0),
-PCI_ROM(0x14e4, 0x1693, "tg3-5787",       "Broadcom Tigon 3 5787", 0),
-PCI_ROM(0x14e4, 0x1696, "tg3-5782",        "Broadcom Tigon 3 5782", 0),
-PCI_ROM(0x14e4, 0x169a, "tg3-5786",        "Broadcom Tigon 3 5786", 0),
-PCI_ROM(0x14e4, 0x169c, "tg3-5788",        "Broadcom Tigon 3 5788", 0),
-PCI_ROM(0x14e4, 0x169d, "tg3-5789",        "Broadcom Tigon 3 5789", 0),
-PCI_ROM(0x14e4, 0x16a6, "tg3-5702X",       "Broadcom Tigon 3 5702X", 0),
-PCI_ROM(0x14e4, 0x16a7, "tg3-5703X",       "Broadcom Tigon 3 5703X", 0),
-PCI_ROM(0x14e4, 0x16a8, "tg3-5704S",       "Broadcom Tigon 3 5704S", 0),
-PCI_ROM(0x14e4, 0x16c6, "tg3-5702A3",      "Broadcom Tigon 3 5702A3", 0),
-PCI_ROM(0x14e4, 0x16c7, "tg3-5703A3",      "Broadcom Tigon 3 5703A3", 0),
-PCI_ROM(0x14e4, 0x170d, "tg3-5901",        "Broadcom Tigon 3 5901", 0),
-PCI_ROM(0x14e4, 0x170e, "tg3-5901_2",      "Broadcom Tigon 3 5901_2", 0),
-PCI_ROM(0x1148, 0x4400, "tg3-9DXX",        "Syskonnect 9DXX", 0),
-PCI_ROM(0x1148, 0x4500, "tg3-9MXX",        "Syskonnect 9MXX", 0),
-PCI_ROM(0x173b, 0x03e8, "tg3-ac1000",      "Altima AC1000", 0),
-PCI_ROM(0x173b, 0x03e9, "tg3-ac1001",      "Altima AC1001", 0),
-PCI_ROM(0x173b, 0x03ea, "tg3-ac9100",      "Altima AC9100", 0),
-PCI_ROM(0x173b, 0x03eb, "tg3-ac1003",      "Altima AC1003", 0),
-PCI_ROM(0x0e11, 0x00ca, "tg3-hp",         "HP Tigon 3", 0),
-};
-
-PCI_DRIVER ( tg3_driver, tg3_nics, PCI_NO_CLASS );
-
-DRIVER ( "TG3", nic_driver, pci_driver, tg3_driver,
-        tg3_probe, tg3_disable );
-
-/*
- * Local variables:
- *  c-basic-offset: 8
- *  c-indent-level: 8
- *  tab-width: 8
- * End:
- */
diff --git a/src/drivers/net/tg3/tg3.c b/src/drivers/net/tg3/tg3.c
new file mode 100644 (file)
index 0000000..9d6b26d
--- /dev/null
@@ -0,0 +1,942 @@
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <mii.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/timer.h>
+#include <ipxe/malloc.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/netdevice.h>
+
+#include "tg3.h"
+
+#define TG3_DEF_RX_MODE                0
+#define TG3_DEF_TX_MODE                0
+
+static void tg3_refill_prod_ring(struct tg3 *tp);
+
+/* Do not place this n-ring entries value into the tp struct itself,
+ * we really want to expose these constants to GCC so that modulo et
+ * al.  operations are done with shifts and masks instead of with
+ * hw multiply/modulo instructions.  Another solution would be to
+ * replace things like '% foo' with '& (foo - 1)'.
+ */
+
+#define TG3_TX_RING_BYTES      (sizeof(struct tg3_tx_buffer_desc) * \
+                                TG3_TX_RING_SIZE)
+
+/* FIXME: does TG3_RX_RET_MAX_SIZE_5705 work for all cards? */
+#define TG3_RX_RCB_RING_BYTES(tp) \
+       (sizeof(struct tg3_rx_buffer_desc) * (TG3_RX_RET_MAX_SIZE_5705))
+
+#define TG3_RX_STD_RING_BYTES(tp) \
+       (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
+
+void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr)
+{      DBGP("%s\n", __func__);
+
+       if (tpr->rx_std) {
+               free_dma(tpr->rx_std, TG3_RX_STD_RING_BYTES(tp));
+               tpr->rx_std = NULL;
+       }
+}
+
+/*
+ * Must not be invoked with interrupt sources disabled and
+ * the hardware shutdown down.
+ */
+static void tg3_free_consistent(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       if (tp->tx_ring) {
+               free_dma(tp->tx_ring, TG3_TX_RING_BYTES);
+               tp->tx_ring = NULL;
+       }
+
+       free(tp->tx_buffers);
+       tp->tx_buffers = NULL;
+
+       if (tp->rx_rcb) {
+               free_dma(tp->rx_rcb, TG3_RX_RCB_RING_BYTES(tp));
+               tp->rx_rcb_mapping = 0;
+               tp->rx_rcb = NULL;
+       }
+
+       tg3_rx_prodring_fini(&tp->prodring);
+
+       if (tp->hw_status) {
+               free_dma(tp->hw_status, TG3_HW_STATUS_SIZE);
+               tp->status_mapping = 0;
+               tp->hw_status = NULL;
+       }
+}
+
+/*
+ * Must not be invoked with interrupt sources disabled and
+ * the hardware shutdown down.  Can sleep.
+ */
+int tg3_alloc_consistent(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       struct tg3_hw_status *sblk;
+       struct tg3_rx_prodring_set *tpr = &tp->prodring;
+
+       tp->hw_status = malloc_dma(TG3_HW_STATUS_SIZE, TG3_DMA_ALIGNMENT);
+       if (!tp->hw_status) {
+               DBGC(tp->dev, "hw_status alloc failed\n");
+               goto err_out;
+       }
+       tp->status_mapping = virt_to_bus(tp->hw_status);
+
+       memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+       sblk = tp->hw_status;
+
+       tpr->rx_std = malloc_dma(TG3_RX_STD_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
+       if (!tpr->rx_std) {
+               DBGC(tp->dev, "rx prodring alloc failed\n");
+               goto err_out;
+       }
+       tpr->rx_std_mapping = virt_to_bus(tpr->rx_std);
+       memset(tpr->rx_std, 0, TG3_RX_STD_RING_BYTES(tp));
+
+       tp->tx_buffers = zalloc(sizeof(struct ring_info) * TG3_TX_RING_SIZE);
+       if (!tp->tx_buffers)
+               goto err_out;
+
+       tp->tx_ring = malloc_dma(TG3_TX_RING_BYTES, TG3_DMA_ALIGNMENT);
+       if (!tp->tx_ring)
+               goto err_out;
+       tp->tx_desc_mapping = virt_to_bus(tp->tx_ring);
+
+       /*
+        * When RSS is enabled, the status block format changes
+        * slightly.  The "rx_jumbo_consumer", "reserved",
+        * and "rx_mini_consumer" members get mapped to the
+        * other three rx return ring producer indexes.
+        */
+
+       tp->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
+
+       tp->rx_rcb = malloc_dma(TG3_RX_RCB_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
+       if (!tp->rx_rcb)
+               goto err_out;
+       tp->rx_rcb_mapping = virt_to_bus(tp->rx_rcb);
+
+       memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+
+       return 0;
+
+err_out:
+       tg3_free_consistent(tp);
+       return -ENOMEM;
+}
+
+#define TG3_RX_STD_BUFF_RING_BYTES(tp) \
+       (sizeof(struct ring_info) * TG3_RX_STD_MAX_SIZE_5700)
+#define TG3_RX_STD_RING_BYTES(tp) \
+       (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
+
+/* Initialize rx rings for packet processing.
+ *
+ * The chip has been shut down and the driver detached from
+ * the networking, so no interrupts or new tx packets will
+ * end up in the driver.
+ */
+static int tg3_rx_prodring_alloc(struct tg3 __unused *tp,
+                                struct tg3_rx_prodring_set *tpr)
+{      DBGP("%s\n", __func__);
+
+       u32 i;
+
+       tpr->rx_std_cons_idx = 0;
+       tpr->rx_std_prod_idx = 0;
+
+       /* Initialize invariants of the rings, we only set this
+        * stuff once.  This works because the card does not
+        * write into the rx buffer posting rings.
+        */
+       /* FIXME: does TG3_RX_STD_MAX_SIZE_5700 work on all cards? */
+       for (i = 0; i < TG3_RX_STD_MAX_SIZE_5700; i++) {
+               struct tg3_rx_buffer_desc *rxd;
+
+               rxd = &tpr->rx_std[i];
+               rxd->idx_len = (TG3_RX_STD_DMA_SZ - 64 - 2) << RXD_LEN_SHIFT;
+               rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT);
+               rxd->opaque = (RXD_OPAQUE_RING_STD |
+                              (i << RXD_OPAQUE_INDEX_SHIFT));
+       }
+
+       return 0;
+}
+
+static void tg3_rx_iob_free(struct io_buffer *iobs[], int i)
+{      DBGP("%s\n", __func__);
+
+       if (iobs[i] == NULL)
+               return;
+
+       free_iob(iobs[i]);
+       iobs[i] = NULL;
+}
+
+static void tg3_rx_prodring_free(struct tg3_rx_prodring_set *tpr)
+{      DBGP("%s\n", __func__);
+
+       unsigned int i;
+
+       for (i = 0; i < TG3_DEF_RX_RING_PENDING; i++)
+               tg3_rx_iob_free(tpr->rx_iobufs, i);
+}
+
+/* Initialize tx/rx rings for packet processing.
+ *
+ * The chip has been shut down and the driver detached from
+ * the networking, so no interrupts or new tx packets will
+ * end up in the driver.
+ */
+int tg3_init_rings(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       /* Free up all the SKBs. */
+///    tg3_free_rings(tp);
+
+       tp->last_tag = 0;
+       tp->last_irq_tag = 0;
+       tp->hw_status->status = 0;
+       tp->hw_status->status_tag = 0;
+       memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+       tp->tx_prod = 0;
+       tp->tx_cons = 0;
+       if (tp->tx_ring)
+               memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
+
+       tp->rx_rcb_ptr = 0;
+       if (tp->rx_rcb)
+               memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+
+       if (tg3_rx_prodring_alloc(tp, &tp->prodring)) {
+               DBGC(tp->dev, "tg3_rx_prodring_alloc() failed\n");
+               tg3_rx_prodring_free(&tp->prodring);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int tg3_open(struct net_device *dev)
+{      DBGP("%s\n", __func__);
+
+       struct tg3 *tp = netdev_priv(dev);
+       struct tg3_rx_prodring_set *tpr = &tp->prodring;
+       int err = 0;
+
+       tg3_set_power_state_0(tp);
+
+       /* Initialize MAC address and backoff seed. */
+       __tg3_set_mac_addr(tp, 0);
+
+       err = tg3_alloc_consistent(tp);
+       if (err)
+               return err;
+
+       tpr->rx_std_iob_cnt = 0;
+       tg3_refill_prod_ring(tp);
+
+       err = tg3_init_hw(tp, 1);
+       if (err != 0)
+               DBGC(tp->dev, "tg3_init_hw failed: %s\n", strerror(err));
+
+       return err;
+}
+
+static inline u32 tg3_tx_avail(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       /* Tell compiler to fetch tx indices from memory. */
+       barrier();
+       return TG3_DEF_TX_RING_PENDING -
+              ((tp->tx_prod - tp->tx_cons) & (TG3_TX_RING_SIZE - 1));
+}
+
+#if 0
+/**
+ *
+ * Prints all registers that could cause a set ERR bit in hw_status->status
+ */
+static void tg3_dump_err_reg(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+               printf("FLOW_ATTN: %#08x\n", tr32(HOSTCC_FLOW_ATTN));
+               printf("MAC ATTN: %#08x\n", tr32(MAC_STATUS));
+               printf("MSI STATUS: %#08x\n", tr32(MSGINT_STATUS));
+               printf("DMA RD: %#08x\n", tr32(RDMAC_STATUS));
+               printf("DMA WR: %#08x\n", tr32(WDMAC_STATUS));
+               printf("TX CPU STATE: %#08x\n", tr32(TX_CPU_STATE));
+               printf("RX CPU STATE: %#08x\n", tr32(RX_CPU_STATE));
+}
+
+static void __unused tw32_mailbox2(struct tg3 *tp, uint32_t reg, uint32_t val)
+{      DBGP("%s\n", __func__);
+
+       tw32_mailbox(reg, val);
+       tr32(reg);
+}
+#endif
+
+#define NEXT_TX(N)             (((N) + 1) & (TG3_TX_RING_SIZE - 1))
+
+/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
+ * support TG3_FLAG_HW_TSO_1 or firmware TSO only.
+ */
+static int tg3_transmit(struct net_device *dev, struct io_buffer *iob)
+{      DBGP("%s\n", __func__);
+
+       struct tg3 *tp = netdev_priv(dev);
+       u32 len, entry;
+       dma_addr_t mapping;
+       u32 bmsr;
+
+       if (tg3_tx_avail(tp) < 1) {
+               DBGC(dev, "Transmit ring full\n");
+               return -ENOBUFS;
+       }
+
+       entry = tp->tx_prod;
+
+       iob_pad(iob, ETH_ZLEN);
+       mapping = virt_to_bus(iob->data);
+       len = iob_len(iob);
+
+       tp->tx_buffers[entry].iob = iob;
+
+       tg3_set_txd(tp, entry, mapping, len, TXD_FLAG_END);
+
+       entry = NEXT_TX(entry);
+
+       /* Packets are ready, update Tx producer idx local and on card. */
+       tw32_tx_mbox(tp->prodmbox, entry);
+
+       writel(entry, tp->regs + MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+
+       tp->tx_prod = entry;
+
+       mb();
+
+       tg3_readphy(tp, MII_BMSR, &bmsr);
+
+       return 0;
+}
+
+static void tg3_tx_complete(struct net_device *dev)
+{      DBGP("%s\n", __func__);
+
+       struct tg3 *tp = netdev_priv(dev);
+       u32 hw_idx = tp->hw_status->idx[0].tx_consumer;
+       u32 sw_idx = tp->tx_cons;
+
+       while (sw_idx != hw_idx) {
+               struct io_buffer *iob = tp->tx_buffers[sw_idx].iob;
+
+               DBGC2(dev, "Transmitted packet: %zd bytes\n", iob_len(iob));
+
+               netdev_tx_complete(dev, iob);
+               sw_idx = NEXT_TX(sw_idx);
+       }
+
+       tp->tx_cons = sw_idx;
+}
+
+#define TG3_RX_STD_BUFF_RING_BYTES(tp) \
+       (sizeof(struct ring_info) * TG3_RX_STD_MAX_SIZE_5700)
+#define TG3_RX_STD_RING_BYTES(tp) \
+       (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
+
+/* Returns 0 or < 0 on error.
+ *
+ * We only need to fill in the address because the other members
+ * of the RX descriptor are invariant, see tg3_init_rings.
+ *
+ * Note the purposeful assymetry of cpu vs. chip accesses.  For
+ * posting buffers we only dirty the first cache line of the RX
+ * descriptor (containing the address).  Whereas for the RX status
+ * buffers the cpu only reads the last cacheline of the RX descriptor
+ * (to fetch the error flags, vlan tag, checksum, and opaque cookie).
+ */
+static int tg3_alloc_rx_iob(struct tg3_rx_prodring_set *tpr, u32 dest_idx_unmasked)
+{      DBGP("%s\n", __func__);
+
+       struct tg3_rx_buffer_desc *desc;
+       struct io_buffer *iob;
+       dma_addr_t mapping;
+       int dest_idx, iob_idx;
+
+       dest_idx = dest_idx_unmasked & (TG3_RX_STD_MAX_SIZE_5700 - 1);
+       desc = &tpr->rx_std[dest_idx];
+
+       /* Do not overwrite any of the map or rp information
+        * until we are sure we can commit to a new buffer.
+        *
+        * Callers depend upon this behavior and assume that
+        * we leave everything unchanged if we fail.
+        */
+       iob = alloc_iob(TG3_RX_STD_DMA_SZ);
+       if (iob == NULL)
+               return -ENOMEM;
+
+       iob_idx = dest_idx % TG3_DEF_RX_RING_PENDING;
+       tpr->rx_iobufs[iob_idx] = iob;
+
+       mapping = virt_to_bus(iob->data);
+
+       desc->addr_hi = ((u64)mapping >> 32);
+       desc->addr_lo = ((u64)mapping & 0xffffffff);
+
+       return 0;
+}
+
+static void tg3_refill_prod_ring(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       struct tg3_rx_prodring_set *tpr = &tp->prodring;
+       int idx = tpr->rx_std_prod_idx;
+
+       DBGCP(tp->dev, "%s\n", __func__);
+
+       while (tpr->rx_std_iob_cnt < TG3_DEF_RX_RING_PENDING) {
+               if (tpr->rx_iobufs[idx % TG3_DEF_RX_RING_PENDING] == NULL) {
+                       if (tg3_alloc_rx_iob(tpr, idx) < 0) {
+                               DBGC(tp->dev, "alloc_iob() failed for descriptor %d\n", idx);
+                               break;
+                       }
+                       DBGC2(tp->dev, "allocated iob_buffer for descriptor %d\n", idx);
+               }
+
+               idx = (idx + 1) % TG3_RX_STD_MAX_SIZE_5700;
+               tpr->rx_std_iob_cnt++;
+       }
+
+       tpr->rx_std_prod_idx = idx;
+       tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx);
+}
+
+static void tg3_rx_complete(struct net_device *dev)
+{      DBGP("%s\n", __func__);
+
+       struct tg3 *tp = netdev_priv(dev);
+
+       u32 sw_idx = tp->rx_rcb_ptr;
+       u16 hw_idx;
+       struct tg3_rx_prodring_set *tpr = &tp->prodring;
+
+       hw_idx = *(tp->rx_rcb_prod_idx);
+
+       while (sw_idx != hw_idx) {
+               struct tg3_rx_buffer_desc *desc = &tp->rx_rcb[sw_idx];
+               u32 desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
+               int iob_idx = desc_idx % TG3_DEF_RX_RING_PENDING;
+               struct io_buffer *iob = tpr->rx_iobufs[iob_idx];
+               unsigned int len;
+
+               DBGC2(dev, "RX - desc_idx: %d sw_idx: %d hw_idx: %d\n", desc_idx, sw_idx, hw_idx);
+
+               assert(iob != NULL);
+
+               if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
+                   (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) {
+                       /* drop packet */
+                       DBGC(dev, "Corrupted packet received\n");
+                       netdev_rx_err(dev, iob, -EINVAL);
+               } else {
+                       len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) -
+                               ETH_FCS_LEN;
+                       iob_put(iob, len);
+                       netdev_rx(dev, iob);
+
+                       DBGC2(dev, "Received packet: %d bytes %d %d\n", len, sw_idx, hw_idx);
+               }
+
+               sw_idx++;
+               sw_idx &= TG3_RX_RET_MAX_SIZE_5705 - 1;
+
+               tpr->rx_iobufs[iob_idx] = NULL;
+               tpr->rx_std_iob_cnt--;
+       }
+
+       tp->rx_rcb_ptr = sw_idx;
+
+       tg3_refill_prod_ring(tp);
+}
+
+static void tg3_poll(struct net_device *dev)
+{      DBGP("%s\n", __func__);
+
+       struct tg3 *tp = netdev_priv(dev);
+
+       /* ACK interrupts */
+       tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00);
+       tp->hw_status->status &= ~SD_STATUS_UPDATED;
+
+       tg3_poll_link(tp);
+       tg3_tx_complete(dev);
+       tg3_rx_complete(dev);
+}
+
+static void tg3_close(struct net_device *dev)
+{      DBGP("%s\n", __func__);
+
+       struct tg3 *tp = netdev_priv(dev);
+
+       DBGP("%s\n", __func__);
+
+       tg3_halt(tp);
+       tg3_rx_prodring_free(&tp->prodring);
+       tg3_flag_clear(tp, INIT_COMPLETE);
+
+       tg3_free_consistent(tp);
+
+}
+
+static void tg3_irq(struct net_device *dev, int enable)
+{      DBGP("%s\n", __func__);
+
+       struct tg3 *tp = netdev_priv(dev);
+
+       DBGP("%s: %d\n", __func__, enable);
+
+       if (enable)
+               tg3_enable_ints(tp);
+       else
+               tg3_disable_ints(tp);
+}
+
+static struct net_device_operations tg3_netdev_ops = {
+       .open = tg3_open,
+       .close = tg3_close,
+       .poll = tg3_poll,
+       .transmit = tg3_transmit,
+       .irq = tg3_irq,
+};
+
+#define TEST_BUFFER_SIZE       0x2000
+
+int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device);
+void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val);
+
+static int tg3_test_dma(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       dma_addr_t buf_dma;
+       u32 *buf, saved_dma_rwctrl;
+       int ret = 0;
+
+       buf = malloc_dma(TEST_BUFFER_SIZE, TG3_DMA_ALIGNMENT);
+       if (!buf) {
+               ret = -ENOMEM;
+               goto out_nofree;
+       }
+       buf_dma = virt_to_bus(buf);
+       DBGC2(tp->dev, "dma test buffer, virt: %p phys: %#08x\n", buf, buf_dma);
+
+       tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
+                         (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT));
+
+       tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl);
+
+       if (tg3_flag(tp, 57765_PLUS))
+               goto out;
+
+       if (tg3_flag(tp, PCI_EXPRESS)) {
+               /* DMA read watermark not used on PCIE */
+               tp->dma_rwctrl |= 0x00180000;
+       } else if (!tg3_flag(tp, PCIX_MODE)) {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+                       tp->dma_rwctrl |= 0x003f0000;
+               else
+                       tp->dma_rwctrl |= 0x003f000f;
+       } else {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+                       u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
+                       u32 read_water = 0x7;
+
+                       if (ccval == 0x6 || ccval == 0x7)
+                               tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
+
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703)
+                               read_water = 4;
+                       /* Set bit 23 to enable PCIX hw bug fix */
+                       tp->dma_rwctrl |=
+                               (read_water << DMA_RWCTRL_READ_WATER_SHIFT) |
+                               (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
+                               (1 << 23);
+               } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+                       /* 5780 always in PCIX mode */
+                       tp->dma_rwctrl |= 0x00144000;
+               } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+                       /* 5714 always in PCIX mode */
+                       tp->dma_rwctrl |= 0x00148000;
+               } else {
+                       tp->dma_rwctrl |= 0x001b000f;
+               }
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+               tp->dma_rwctrl &= 0xfffffff0;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+               /* Remove this if it causes problems for some boards. */
+               tp->dma_rwctrl |= DMA_RWCTRL_USE_MEM_READ_MULT;
+
+               /* On 5700/5701 chips, we need to set this bit.
+                * Otherwise the chip will issue cacheline transactions
+                * to streamable DMA memory with not all the byte
+                * enables turned on.  This is an error on several
+                * RISC PCI controllers, in particular sparc64.
+                *
+                * On 5703/5704 chips, this bit has been reassigned
+                * a different meaning.  In particular, it is used
+                * on those chips to enable a PCI-X workaround.
+                */
+               tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE;
+       }
+
+       tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
+#if 0
+       /* Unneeded, already done by tg3_get_invariants.  */
+       tg3_switch_clocks(tp);
+#endif
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
+               goto out;
+
+       /* It is best to perform DMA test with maximum write burst size
+        * to expose the 5700/5701 write DMA bug.
+        */
+       saved_dma_rwctrl = tp->dma_rwctrl;
+       tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+       tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
+       while (1) {
+               u32 *p = buf, i;
+
+               for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++)
+                       p[i] = i;
+
+               /* Send the buffer to the chip. */
+               ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1);
+               if (ret) {
+                       DBGC(&tp->pdev->dev,
+                               "%s: Buffer write failed. err = %d\n",
+                               __func__, ret);
+                       break;
+               }
+
+               /* validate data reached card RAM correctly. */
+               for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
+                       u32 val;
+                       tg3_read_mem(tp, 0x2100 + (i*4), &val);
+                       if (le32_to_cpu(val) != p[i]) {
+                               DBGC(&tp->pdev->dev,
+                                       "%s: Buffer corrupted on device! "
+                                       "(%d != %d)\n", __func__, val, i);
+                               /* ret = -ENODEV here? */
+                       }
+                       p[i] = 0;
+               }
+
+               /* Now read it back. */
+               ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0);
+               if (ret) {
+                       DBGC(&tp->pdev->dev, "%s: Buffer read failed. "
+                               "err = %d\n", __func__, ret);
+                       break;
+               }
+
+               /* Verify it. */
+               for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
+                       if (p[i] == i)
+                               continue;
+
+                       if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+                           DMA_RWCTRL_WRITE_BNDRY_16) {
+                               tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+                               tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
+                               tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+                               break;
+                       } else {
+                               DBGC(&tp->pdev->dev,
+                                       "%s: Buffer corrupted on read back! "
+                                       "(%d != %d)\n", __func__, p[i], i);
+                               ret = -ENODEV;
+                               goto out;
+                       }
+               }
+
+               if (i == (TEST_BUFFER_SIZE / sizeof(u32))) {
+                       /* Success. */
+                       ret = 0;
+                       break;
+               }
+       }
+
+       if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+           DMA_RWCTRL_WRITE_BNDRY_16) {
+               /* DMA test passed without adjusting DMA boundary,
+                * now look for chipsets that are known to expose the
+                * DMA bug without failing the test.
+                */
+               tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+               tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
+
+               tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+       }
+
+out:
+       free_dma(buf, TEST_BUFFER_SIZE);
+out_nofree:
+       return ret;
+}
+
+static int tg3_init_one(struct pci_device *pdev)
+{      DBGP("%s\n", __func__);
+
+       struct net_device *dev;
+       struct tg3 *tp;
+       int err = 0;
+       unsigned long reg_base, reg_size;
+
+       adjust_pci_device(pdev);
+
+       dev = alloc_etherdev(sizeof(*tp));
+       if (!dev) {
+               DBGC(&pdev->dev, "Failed to allocate etherdev\n");
+               err = -ENOMEM;
+               goto err_out_disable_pdev;
+       }
+
+       netdev_init(dev, &tg3_netdev_ops);
+       pci_set_drvdata(pdev, dev);
+
+       dev->dev = &pdev->dev;
+
+       tp = netdev_priv(dev);
+       tp->pdev = pdev;
+       tp->dev = dev;
+       tp->rx_mode = TG3_DEF_RX_MODE;
+       tp->tx_mode = TG3_DEF_TX_MODE;
+
+       /* Subsystem IDs are required later */
+       pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->subsystem_vendor);
+       pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_ID, &tp->subsystem_device);
+
+       /* The word/byte swap controls here control register access byte
+        * swapping.  DMA data byte swapping is controlled in the GRC_MODE
+        * setting below.
+        */
+       tp->misc_host_ctrl =
+               MISC_HOST_CTRL_MASK_PCI_INT |
+               MISC_HOST_CTRL_WORD_SWAP |
+               MISC_HOST_CTRL_INDIR_ACCESS |
+               MISC_HOST_CTRL_PCISTATE_RW;
+
+       /* The NONFRM (non-frame) byte/word swap controls take effect
+        * on descriptor entries, anything which isn't packet data.
+        *
+        * The StrongARM chips on the board (one for tx, one for rx)
+        * are running in big-endian mode.
+        */
+       tp->grc_mode = (GRC_MODE_WSWAP_DATA | GRC_MODE_BSWAP_DATA |
+                       GRC_MODE_WSWAP_NONFRM_DATA);
+#if __BYTE_ORDER == __BIG_ENDIAN
+       tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA;
+#endif
+
+       /* FIXME: how can we detect errors here? */
+       reg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+       reg_size = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
+
+       tp->regs = ioremap(reg_base, reg_size);
+       if (!tp->regs) {
+               DBGC(&pdev->dev, "Failed to remap device registers\n");
+               errno = -ENOENT;
+               goto err_out_disable_pdev;
+       }
+
+       err = tg3_get_invariants(tp);
+       if (err) {
+               DBGC(&pdev->dev, "Problem fetching invariants of chip, aborting\n");
+               goto err_out_iounmap;
+       }
+
+       tg3_init_bufmgr_config(tp);
+
+       err = tg3_get_device_address(tp);
+       if (err) {
+               DBGC(&pdev->dev, "Could not obtain valid ethernet address, aborting\n");
+               goto err_out_iounmap;
+       }
+
+       /*
+        * Reset chip in case UNDI or EFI driver did not shutdown
+        * DMA self test will enable WDMAC and we'll see (spurious)
+        * pending DMA on the PCI bus at that point.
+        */
+       if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
+           (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+               tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+               tg3_halt(tp);
+       }
+
+       err = tg3_test_dma(tp);
+       if (err) {
+               DBGC(&pdev->dev, "DMA engine test failed, aborting\n");
+               goto err_out_iounmap;
+       }
+
+       tp->int_mbox = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
+       tp->consmbox = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
+       tp->prodmbox = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+
+       tp->coal_now = HOSTCC_MODE_NOW;
+
+       err = register_netdev(dev);
+       if (err) {
+               DBGC(&pdev->dev, "Cannot register net device, aborting\n");
+               goto err_out_iounmap;
+       }
+
+       /* Call tg3_setup_phy() to start autoneg process, which saves time
+        * over starting autoneg in tg3_open();
+        */
+       err = tg3_setup_phy(tp, 0);
+       if (err) {
+               DBGC(tp->dev, "tg3_setup_phy() call failed in %s\n", __func__);
+               goto err_out_iounmap;
+       }
+
+       return 0;
+
+err_out_iounmap:
+       if (tp->regs) {
+               iounmap(tp->regs);
+               tp->regs = NULL;
+       }
+
+       netdev_put(dev);
+
+err_out_disable_pdev:
+       pci_set_drvdata(pdev, NULL);
+       return err;
+}
+
+static void tg3_remove_one(struct pci_device *pci)
+{      DBGP("%s\n", __func__);
+
+       struct net_device *netdev = pci_get_drvdata(pci);
+
+       unregister_netdev(netdev);
+       netdev_nullify(netdev);
+       netdev_put(netdev);
+}
+
+static struct pci_device_id tg3_nics[] = {
+       PCI_ROM(0x14e4, 0x1644, "14e4-1644", "14e4-1644", 0),
+       PCI_ROM(0x14e4, 0x1645, "14e4-1645", "14e4-1645", 0),
+       PCI_ROM(0x14e4, 0x1646, "14e4-1646", "14e4-1646", 0),
+       PCI_ROM(0x14e4, 0x1647, "14e4-1647", "14e4-1647", 0),
+       PCI_ROM(0x14e4, 0x1648, "14e4-1648", "14e4-1648", 0),
+       PCI_ROM(0x14e4, 0x164d, "14e4-164d", "14e4-164d", 0),
+       PCI_ROM(0x14e4, 0x1653, "14e4-1653", "14e4-1653", 0),
+       PCI_ROM(0x14e4, 0x1654, "14e4-1654", "14e4-1654", 0),
+       PCI_ROM(0x14e4, 0x165d, "14e4-165d", "14e4-165d", 0),
+       PCI_ROM(0x14e4, 0x165e, "14e4-165e", "14e4-165e", 0),
+       PCI_ROM(0x14e4, 0x16a6, "14e4-16a6", "14e4-16a6", 0),
+       PCI_ROM(0x14e4, 0x16a7, "14e4-16a7", "14e4-16a7", 0),
+       PCI_ROM(0x14e4, 0x16a8, "14e4-16a8", "14e4-16a8", 0),
+       PCI_ROM(0x14e4, 0x16c6, "14e4-16c6", "14e4-16c6", 0),
+       PCI_ROM(0x14e4, 0x16c7, "14e4-16c7", "14e4-16c7", 0),
+       PCI_ROM(0x14e4, 0x1696, "14e4-1696", "14e4-1696", 0),
+       PCI_ROM(0x14e4, 0x169c, "14e4-169c", "14e4-169c", 0),
+       PCI_ROM(0x14e4, 0x169d, "14e4-169d", "14e4-169d", 0),
+       PCI_ROM(0x14e4, 0x170d, "14e4-170d", "14e4-170d", 0),
+       PCI_ROM(0x14e4, 0x170e, "14e4-170e", "14e4-170e", 0),
+       PCI_ROM(0x14e4, 0x1649, "14e4-1649", "14e4-1649", 0),
+       PCI_ROM(0x14e4, 0x166e, "14e4-166e", "14e4-166e", 0),
+       PCI_ROM(0x14e4, 0x1659, "14e4-1659", "14e4-1659", 0),
+       PCI_ROM(0x14e4, 0x165a, "14e4-165a", "14e4-165a", 0),
+       PCI_ROM(0x14e4, 0x1677, "14e4-1677", "14e4-1677", 0),
+       PCI_ROM(0x14e4, 0x167d, "14e4-167d", "14e4-167d", 0),
+       PCI_ROM(0x14e4, 0x167e, "14e4-167e", "14e4-167e", 0),
+       PCI_ROM(0x14e4, 0x1600, "14e4-1600", "14e4-1600", 0),
+       PCI_ROM(0x14e4, 0x1601, "14e4-1601", "14e4-1601", 0),
+       PCI_ROM(0x14e4, 0x16f7, "14e4-16f7", "14e4-16f7", 0),
+       PCI_ROM(0x14e4, 0x16fd, "14e4-16fd", "14e4-16fd", 0),
+       PCI_ROM(0x14e4, 0x16fe, "14e4-16fe", "14e4-16fe", 0),
+       PCI_ROM(0x14e4, 0x167a, "14e4-167a", "14e4-167a", 0),
+       PCI_ROM(0x14e4, 0x1672, "14e4-1672", "14e4-1672", 0),
+       PCI_ROM(0x14e4, 0x167b, "14e4-167b", "14e4-167b", 0),
+       PCI_ROM(0x14e4, 0x1673, "14e4-1673", "14e4-1673", 0),
+       PCI_ROM(0x14e4, 0x1674, "14e4-1674", "14e4-1674", 0),
+       PCI_ROM(0x14e4, 0x169a, "14e4-169a", "14e4-169a", 0),
+       PCI_ROM(0x14e4, 0x169b, "14e4-169b", "14e4-169b", 0),
+       PCI_ROM(0x14e4, 0x1693, "14e4-1693", "14e4-1693", 0),
+       PCI_ROM(0x14e4, 0x167f, "14e4-167f", "14e4-167f", 0),
+       PCI_ROM(0x14e4, 0x1668, "14e4-1668", "14e4-1668", 0),
+       PCI_ROM(0x14e4, 0x1669, "14e4-1669", "14e4-1669", 0),
+       PCI_ROM(0x14e4, 0x1678, "14e4-1678", "14e4-1678", 0),
+       PCI_ROM(0x14e4, 0x1679, "14e4-1679", "14e4-1679", 0),
+       PCI_ROM(0x14e4, 0x166a, "14e4-166a", "14e4-166a", 0),
+       PCI_ROM(0x14e4, 0x166b, "14e4-166b", "14e4-166b", 0),
+       PCI_ROM(0x14e4, 0x16dd, "14e4-16dd", "14e4-16dd", 0),
+       PCI_ROM(0x14e4, 0x1712, "14e4-1712", "14e4-1712", 0),
+       PCI_ROM(0x14e4, 0x1713, "14e4-1713", "14e4-1713", 0),
+       PCI_ROM(0x14e4, 0x1698, "14e4-1698", "14e4-1698", 0),
+       PCI_ROM(0x14e4, 0x1684, "14e4-1684", "14e4-1684", 0),
+       PCI_ROM(0x14e4, 0x165b, "14e4-165b", "14e4-165b", 0),
+       PCI_ROM(0x14e4, 0x1681, "14e4-1681", "14e4-1681", 0),
+       PCI_ROM(0x14e4, 0x1680, "14e4-1680", "14e4-1680", 0),
+       PCI_ROM(0x14e4, 0x1688, "14e4-1688", "14e4-1688", 0),
+       PCI_ROM(0x14e4, 0x1689, "14e4-1689", "14e4-1689", 0),
+       PCI_ROM(0x14e4, 0x1699, "14e4-1699", "14e4-1699", 0),
+       PCI_ROM(0x14e4, 0x16a0, "14e4-16a0", "14e4-16a0", 0),
+       PCI_ROM(0x14e4, 0x1692, "14e4-1692", "14e4-1692", 0),
+       PCI_ROM(0x14e4, 0x1690, "14e4-1690", "14e4-1690", 0),
+       PCI_ROM(0x14e4, 0x1694, "14e4-1694", "14e4-1694", 0),
+       PCI_ROM(0x14e4, 0x1691, "14e4-1691", "14e4-1691", 0),
+       PCI_ROM(0x14e4, 0x1655, "14e4-1655", "14e4-1655", 0),
+       PCI_ROM(0x14e4, 0x1656, "14e4-1656", "14e4-1656", 0),
+       PCI_ROM(0x14e4, 0x16b1, "14e4-16b1", "14e4-16b1", 0),
+       PCI_ROM(0x14e4, 0x16b5, "14e4-16b5", "14e4-16b5", 0),
+       PCI_ROM(0x14e4, 0x16b0, "14e4-16b0", "14e4-16b0", 0),
+       PCI_ROM(0x14e4, 0x16b4, "14e4-16b4", "14e4-16b4", 0),
+       PCI_ROM(0x14e4, 0x16b2, "14e4-16b2", "14e4-16b2", 0),
+       PCI_ROM(0x14e4, 0x16b6, "14e4-16b6", "14e4-16b6", 0),
+       PCI_ROM(0x14e4, 0x1657, "14e4-1657", "14e4-1657", 0),
+       PCI_ROM(0x14e4, 0x165f, "14e4-165f", "14e4-165f", 0),
+       PCI_ROM(0x1148, 0x4400, "1148-4400", "1148-4400", 0),
+       PCI_ROM(0x1148, 0x4500, "1148-4500", "1148-4500", 0),
+       PCI_ROM(0x173b, 0x03e8, "173b-03e8", "173b-03e8", 0),
+       PCI_ROM(0x173b, 0x03e9, "173b-03e9", "173b-03e9", 0),
+       PCI_ROM(0x173b, 0x03eb, "173b-03eb", "173b-03eb", 0),
+       PCI_ROM(0x173b, 0x03ea, "173b-03ea", "173b-03ea", 0),
+       PCI_ROM(0x106b, 0x1645, "106b-1645", "106b-1645", 0),
+};
+
+struct pci_driver tg3_pci_driver __pci_driver = {
+       .ids = tg3_nics,
+       .id_count = ARRAY_SIZE(tg3_nics),
+       .probe = tg3_init_one,
+       .remove = tg3_remove_one,
+};
similarity index 50%
rename from src/drivers/net/tg3.h
rename to src/drivers/net/tg3/tg3.h
index deeb0adde1c539d44d53419a4591a0e9d93ec720..ac24387551ba5492bbbe87ec0d7fa55fee5aece6 100644 (file)
-/* $Id$
+/* $Id: tg3.h,v 1.37.2.32 2002/03/11 12:18:18 davem Exp $
  * tg3.h: Definitions for Broadcom Tigon3 ethernet driver.
  *
- * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)
- * Copyright (C) 2001 Jeff Garzik (jgarzik@mandrakesoft.com)
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (C) 2007-2011 Broadcom Corporation.
  */
 
-FILE_LICENCE ( GPL2_ONLY );
-
 #ifndef _T3_H
 #define _T3_H
 
-#include "stdint.h"
-
-typedef unsigned long dma_addr_t;
-
-/* From mii.h */
-
-/* Indicates what features are advertised by the interface. */
-#define ADVERTISED_10baseT_Half                (1 << 0)
-#define ADVERTISED_10baseT_Full                (1 << 1)
-#define ADVERTISED_100baseT_Half       (1 << 2)
-#define ADVERTISED_100baseT_Full       (1 << 3)
-#define ADVERTISED_1000baseT_Half      (1 << 4)
-#define ADVERTISED_1000baseT_Full      (1 << 5)
-#define ADVERTISED_Autoneg             (1 << 6)
-#define ADVERTISED_TP                  (1 << 7)
-#define ADVERTISED_AUI                 (1 << 8)
-#define ADVERTISED_MII                 (1 << 9)
-#define ADVERTISED_FIBRE               (1 << 10)
-#define ADVERTISED_BNC                 (1 << 11)
-
-/* The following are all involved in forcing a particular link
- * mode for the device for setting things.  When getting the
- * devices settings, these indicate the current mode and whether
- * it was foced up into this mode or autonegotiated.
- */
-
-/* The forced speed, 10Mb, 100Mb, gigabit. */
-#define SPEED_10               0
-#define SPEED_100              1
-#define SPEED_1000             2
-#define SPEED_INVALID           3
-
-
-/* Duplex, half or full. */
-#define DUPLEX_HALF            0x00
-#define DUPLEX_FULL            0x01
-#define DUPLEX_INVALID          0x02
-
-/* Which connector port. */
-#define PORT_TP                        0x00
-#define PORT_AUI               0x01
-#define PORT_MII               0x02
-#define PORT_FIBRE             0x03
-#define PORT_BNC               0x04
-
-/* Which tranceiver to use. */
-#define XCVR_INTERNAL          0x00
-#define XCVR_EXTERNAL          0x01
-#define XCVR_DUMMY1            0x02
-#define XCVR_DUMMY2            0x03
-#define XCVR_DUMMY3            0x04
-
-/* Enable or disable autonegotiation.  If this is set to enable,
- * the forced link modes above are completely ignored.
- */
-#define AUTONEG_DISABLE                0x00
-#define AUTONEG_ENABLE         0x01
-
-/* Wake-On-Lan options. */
-#define WAKE_PHY               (1 << 0)
-#define WAKE_UCAST             (1 << 1)
-#define WAKE_MCAST             (1 << 2)
-#define WAKE_BCAST             (1 << 3)
-#define WAKE_ARP               (1 << 4)
-#define WAKE_MAGIC             (1 << 5)
-#define WAKE_MAGICSECURE       (1 << 6) /* only meaningful if WAKE_MAGIC */
-
-/* From tg3.h */
+#undef ERRFILE
+#define ERRFILE ERRFILE_tg3
+
+/* From linux/include/linux/pci_regs.h: */
+#define PCI_EXP_LNKCTL          16      /* Link Control */
+#define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */
+#define  PCI_CAP_ID_PCIX        0x07    /* PCI-X */
+
+#define  PCI_X_CMD_READ_2K      0x0008  /* 2Kbyte maximum read byte count */
+#define  PCI_X_CMD_MAX_READ     0x000c  /* Max Memory Read Byte Count */
+
+#define  PCI_X_CMD_MAX_SPLIT    0x0070  /* Max Outstanding Split Transactions */
+/* </pci_regs.h> */
+
+/* ethtool.h: */
+#define ADVERTISED_10baseT_Half         (1 << 0)
+#define ADVERTISED_10baseT_Full         (1 << 1)
+#define ADVERTISED_100baseT_Half        (1 << 2)
+#define ADVERTISED_100baseT_Full        (1 << 3)
+#define ADVERTISED_1000baseT_Half       (1 << 4)
+#define ADVERTISED_1000baseT_Full       (1 << 5)
+#define ADVERTISED_Autoneg              (1 << 6)
+/* </ethtool.h> */
+
+/* mdio.h: */
+#define MDIO_AN_EEE_ADV                60      /* EEE advertisement */
+
+#define MDIO_MMD_AN            7       /* Auto-Negotiation */
+
+#define MDIO_AN_EEE_ADV_100TX          0x0002  /* Advertise 100TX EEE cap */
+#define MDIO_AN_EEE_ADV_1000T          0x0004  /* Advertise 1000T EEE cap */
+/* </mdio.h> */
+
+/* mii.h */
+#define FLOW_CTRL_TX           0x01
+#define FLOW_CTRL_RX           0x02
+/* </mii.h> */
+
+/* pci_regs.h */
+#define PCI_X_CMD                      2       /* Modes & Features */
+#define PCI_X_CMD_ERO                  0x0002  /* Enable Relaxed Ordering */
+
+#define PCI_EXP_DEVCTL                 8       /* Device Control */
+#define PCI_EXP_DEVCTL_RELAX_EN                0x0010 /* Enable relaxed ordering */
+#define PCI_EXP_DEVCTL_NOSNOOP_EN      0x0800  /* Enable No Snoop */
+#define PCI_EXP_DEVCTL_PAYLOAD         0x00e0  /* Max_Payload_Size */
+#define PCI_EXP_DEVSTA                 10      /* Device Status */
+#define PCI_EXP_DEVSTA_CED             0x01    /* Correctable Error Detected */
+#define PCI_EXP_DEVSTA_NFED            0x02    /* Non-Fatal Error Detected */
+#define PCI_EXP_DEVSTA_FED             0x04    /* Fatal Error Detected */
+#define PCI_EXP_DEVSTA_URD             0x08    /* Unsupported Request Detected */
+/* </pci_regs.h> */
+
+/* pci_ids.h: */
+#define PCI_VENDOR_ID_BROADCOM         0x14e4
+#define PCI_DEVICE_ID_TIGON3_5752      0x1600
+#define PCI_DEVICE_ID_TIGON3_5752M     0x1601
+#define PCI_DEVICE_ID_NX2_5709         0x1639
+#define PCI_DEVICE_ID_NX2_5709S                0x163a
+#define PCI_DEVICE_ID_TIGON3_5700      0x1644
+#define PCI_DEVICE_ID_TIGON3_5701      0x1645
+#define PCI_DEVICE_ID_TIGON3_5702      0x1646
+#define PCI_DEVICE_ID_TIGON3_5703      0x1647
+#define PCI_DEVICE_ID_TIGON3_5704      0x1648
+#define PCI_DEVICE_ID_TIGON3_5704S_2   0x1649
+#define PCI_DEVICE_ID_NX2_5706         0x164a
+#define PCI_DEVICE_ID_NX2_5708         0x164c
+#define PCI_DEVICE_ID_TIGON3_5702FE    0x164d
+#define PCI_DEVICE_ID_NX2_57710                0x164e
+#define PCI_DEVICE_ID_NX2_57711                0x164f
+#define PCI_DEVICE_ID_NX2_57711E       0x1650
+#define PCI_DEVICE_ID_TIGON3_5705      0x1653
+#define PCI_DEVICE_ID_TIGON3_5705_2    0x1654
+#define PCI_DEVICE_ID_TIGON3_5721      0x1659
+#define PCI_DEVICE_ID_TIGON3_5722      0x165a
+#define PCI_DEVICE_ID_TIGON3_5723      0x165b
+#define PCI_DEVICE_ID_TIGON3_5705M     0x165d
+#define PCI_DEVICE_ID_TIGON3_5705M_2   0x165e
+#define PCI_DEVICE_ID_NX2_57712                0x1662
+#define PCI_DEVICE_ID_NX2_57712E       0x1663
+#define PCI_DEVICE_ID_TIGON3_5714      0x1668
+#define PCI_DEVICE_ID_TIGON3_5714S     0x1669
+#define PCI_DEVICE_ID_TIGON3_5780      0x166a
+#define PCI_DEVICE_ID_TIGON3_5780S     0x166b
+#define PCI_DEVICE_ID_TIGON3_5705F     0x166e
+#define PCI_DEVICE_ID_TIGON3_5754M     0x1672
+#define PCI_DEVICE_ID_TIGON3_5755M     0x1673
+#define PCI_DEVICE_ID_TIGON3_5756      0x1674
+#define PCI_DEVICE_ID_TIGON3_5751      0x1677
+#define PCI_DEVICE_ID_TIGON3_5715      0x1678
+#define PCI_DEVICE_ID_TIGON3_5715S     0x1679
+#define PCI_DEVICE_ID_TIGON3_5754      0x167a
+#define PCI_DEVICE_ID_TIGON3_5755      0x167b
+#define PCI_DEVICE_ID_TIGON3_5751M     0x167d
+#define PCI_DEVICE_ID_TIGON3_5751F     0x167e
+#define PCI_DEVICE_ID_TIGON3_5787F     0x167f
+#define PCI_DEVICE_ID_TIGON3_5761E     0x1680
+#define PCI_DEVICE_ID_TIGON3_5761      0x1681
+#define PCI_DEVICE_ID_TIGON3_5764      0x1684
+#define PCI_DEVICE_ID_TIGON3_5787M     0x1693
+#define PCI_DEVICE_ID_TIGON3_5782      0x1696
+#define PCI_DEVICE_ID_TIGON3_5784      0x1698
+#define PCI_DEVICE_ID_TIGON3_5786      0x169a
+#define PCI_DEVICE_ID_TIGON3_5787      0x169b
+#define PCI_DEVICE_ID_TIGON3_5788      0x169c
+#define PCI_DEVICE_ID_TIGON3_5789      0x169d
+#define PCI_DEVICE_ID_TIGON3_5702X     0x16a6
+#define PCI_DEVICE_ID_TIGON3_5703X     0x16a7
+#define PCI_DEVICE_ID_TIGON3_5704S     0x16a8
+#define PCI_DEVICE_ID_NX2_5706S                0x16aa
+#define PCI_DEVICE_ID_NX2_5708S                0x16ac
+#define PCI_DEVICE_ID_TIGON3_5702A3    0x16c6
+#define PCI_DEVICE_ID_TIGON3_5703A3    0x16c7
+#define PCI_DEVICE_ID_TIGON3_5781      0x16dd
+#define PCI_DEVICE_ID_TIGON3_5753      0x16f7
+#define PCI_DEVICE_ID_TIGON3_5753M     0x16fd
+#define PCI_DEVICE_ID_TIGON3_5753F     0x16fe
+#define PCI_DEVICE_ID_TIGON3_5901      0x170d
+#define PCI_DEVICE_ID_TIGON3_5901_2    0x170e
+#define PCI_DEVICE_ID_TIGON3_5906      0x1712
+#define PCI_DEVICE_ID_TIGON3_5906M     0x1713
+/* </pci_ids.h> */
+
+#define SPEED_10                       10
+#define SPEED_100                      100
+#define SPEED_1000                     1000
+
+#define DUPLEX_HALF                    0x00
+#define DUPLEX_FULL                    0x01
 
 #define TG3_64BIT_REG_HIGH             0x00UL
 #define TG3_64BIT_REG_LOW              0x04UL
@@ -92,11 +153,13 @@ typedef unsigned long dma_addr_t;
 #define TG3_BDINFO_NIC_ADDR            0xcUL /* 32-bit */
 #define TG3_BDINFO_SIZE                        0x10UL
 
-#define RX_COPY_THRESHOLD              256
-
-#define RX_STD_MAX_SIZE                        1536
-#define RX_STD_MAX_SIZE_5705           512
-#define RX_JUMBO_MAX_SIZE              0xdeadbeef /* XXX */
+#define TG3_RX_STD_MAX_SIZE_5700       512
+#define TG3_RX_STD_MAX_SIZE_5717       2048
+#define TG3_RX_JMB_MAX_SIZE_5700       256
+#define TG3_RX_JMB_MAX_SIZE_5717       1024
+#define TG3_RX_RET_MAX_SIZE_5700       1024
+#define TG3_RX_RET_MAX_SIZE_5705       512
+#define TG3_RX_RET_MAX_SIZE_5717       4096
 
 /* First 256 bytes are a mirror of PCI config space. */
 #define TG3PCI_VENDOR                  0x00000000
@@ -106,51 +169,57 @@ typedef unsigned long dma_addr_t;
 #define  TG3PCI_DEVICE_TIGON3_2                 0x1645 /* BCM5701 */
 #define  TG3PCI_DEVICE_TIGON3_3                 0x1646 /* BCM5702 */
 #define  TG3PCI_DEVICE_TIGON3_4                 0x1647 /* BCM5703 */
-#define TG3PCI_COMMAND                 0x00000004
-#define TG3PCI_STATUS                  0x00000006
-#define TG3PCI_CCREVID                 0x00000008
-#define TG3PCI_CACHELINESZ             0x0000000c
-#define TG3PCI_LATTIMER                        0x0000000d
-#define TG3PCI_HEADERTYPE              0x0000000e
-#define TG3PCI_BIST                    0x0000000f
-#define TG3PCI_BASE0_LOW               0x00000010
-#define TG3PCI_BASE0_HIGH              0x00000014
-/* 0x18 --> 0x2c unused */
-#define TG3PCI_SUBSYSVENID             0x0000002c
-#define TG3PCI_SUBSYSID                        0x0000002e
-#define TG3PCI_ROMADDR                 0x00000030
-#define TG3PCI_CAPLIST                 0x00000034
-/* 0x35 --> 0x3c unused */
-#define TG3PCI_IRQ_LINE                        0x0000003c
-#define TG3PCI_IRQ_PIN                 0x0000003d
-#define TG3PCI_MIN_GNT                 0x0000003e
-#define TG3PCI_MAX_LAT                 0x0000003f
-#define TG3PCI_X_CAPS                  0x00000040
-#define  PCIX_CAPS_RELAXED_ORDERING     0x00020000
-#define  PCIX_CAPS_SPLIT_MASK           0x00700000
-#define  PCIX_CAPS_SPLIT_SHIFT          20
-#define  PCIX_CAPS_BURST_MASK           0x000c0000
-#define  PCIX_CAPS_BURST_SHIFT          18
-#define  PCIX_CAPS_MAX_BURST_CPIOB      2
-#define TG3PCI_PM_CAP_PTR              0x00000041
-#define TG3PCI_X_COMMAND               0x00000042
-#define TG3PCI_X_STATUS                        0x00000044
-#define TG3PCI_PM_CAP_ID               0x00000048
-#define TG3PCI_VPD_CAP_PTR             0x00000049
-#define TG3PCI_PM_CAPS                 0x0000004a
-#define TG3PCI_PM_CTRL_STAT            0x0000004c
-#define TG3PCI_BR_SUPP_EXT             0x0000004e
-#define TG3PCI_PM_DATA                 0x0000004f
-#define TG3PCI_VPD_CAP_ID              0x00000050
-#define TG3PCI_MSI_CAP_PTR             0x00000051
-#define TG3PCI_VPD_ADDR_FLAG           0x00000052
-#define  VPD_ADDR_FLAG_WRITE           0x00008000
-#define TG3PCI_VPD_DATA                        0x00000054
-#define TG3PCI_MSI_CAP_ID              0x00000058
-#define TG3PCI_NXT_CAP_PTR             0x00000059
-#define TG3PCI_MSI_CTRL                        0x0000005a
-#define TG3PCI_MSI_ADDR_LOW            0x0000005c
-#define TG3PCI_MSI_ADDR_HIGH           0x00000060
+#define  TG3PCI_DEVICE_TIGON3_5761S     0x1688
+#define  TG3PCI_DEVICE_TIGON3_5761SE    0x1689
+#define  TG3PCI_DEVICE_TIGON3_57780     0x1692
+#define  TG3PCI_DEVICE_TIGON3_57760     0x1690
+#define  TG3PCI_DEVICE_TIGON3_57790     0x1694
+#define  TG3PCI_DEVICE_TIGON3_57788     0x1691
+#define  TG3PCI_DEVICE_TIGON3_5785_G    0x1699 /* GPHY */
+#define  TG3PCI_DEVICE_TIGON3_5785_F    0x16a0 /* 10/100 only */
+#define  TG3PCI_DEVICE_TIGON3_5717      0x1655
+#define  TG3PCI_DEVICE_TIGON3_5718      0x1656
+#define  TG3PCI_DEVICE_TIGON3_57781     0x16b1
+#define  TG3PCI_DEVICE_TIGON3_57785     0x16b5
+#define  TG3PCI_DEVICE_TIGON3_57761     0x16b0
+#define  TG3PCI_DEVICE_TIGON3_57765     0x16b4
+#define  TG3PCI_DEVICE_TIGON3_57791     0x16b2
+#define  TG3PCI_DEVICE_TIGON3_57795     0x16b6
+#define  TG3PCI_DEVICE_TIGON3_5719      0x1657
+#define  TG3PCI_DEVICE_TIGON3_5720      0x165f
+/* 0x04 --> 0x2c unused */
+#define TG3PCI_SUBVENDOR_ID_BROADCOM           PCI_VENDOR_ID_BROADCOM
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6   0x1644
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5   0x0001
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6   0x0002
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9   0x0003
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1   0x0005
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8   0x0006
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7   0x0007
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10  0x0008
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12  0x8008
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1  0x0009
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2  0x8009
+#define TG3PCI_SUBVENDOR_ID_3COM               PCI_VENDOR_ID_3COM
+#define TG3PCI_SUBDEVICE_ID_3COM_3C996T                0x1000
+#define TG3PCI_SUBDEVICE_ID_3COM_3C996BT       0x1006
+#define TG3PCI_SUBDEVICE_ID_3COM_3C996SX       0x1004
+#define TG3PCI_SUBDEVICE_ID_3COM_3C1000T       0x1007
+#define TG3PCI_SUBDEVICE_ID_3COM_3C940BR01     0x1008
+#define TG3PCI_SUBVENDOR_ID_DELL               PCI_VENDOR_ID_DELL
+#define TG3PCI_SUBDEVICE_ID_DELL_VIPER         0x00d1
+#define TG3PCI_SUBDEVICE_ID_DELL_JAGUAR                0x0106
+#define TG3PCI_SUBDEVICE_ID_DELL_MERLOT                0x0109
+#define TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT   0x010a
+#define TG3PCI_SUBVENDOR_ID_COMPAQ             PCI_VENDOR_ID_COMPAQ
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE     0x007c
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2   0x009a
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING  0x007d
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780      0x0085
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2    0x0099
+#define TG3PCI_SUBVENDOR_ID_IBM                        PCI_VENDOR_ID_IBM
+#define TG3PCI_SUBDEVICE_ID_IBM_5703SAX2       0x0281
+/* 0x30 --> 0x64 unused */
 #define TG3PCI_MSI_DATA                        0x00000064
 /* 0x66 --> 0x68 unused */
 #define TG3PCI_MISC_HOST_CTRL          0x00000068
@@ -187,14 +256,26 @@ typedef unsigned long dma_addr_t;
 #define  CHIPREV_ID_5704_A0             0x2000
 #define  CHIPREV_ID_5704_A1             0x2001
 #define  CHIPREV_ID_5704_A2             0x2002
+#define  CHIPREV_ID_5704_A3             0x2003
 #define  CHIPREV_ID_5705_A0             0x3000
 #define  CHIPREV_ID_5705_A1             0x3001
-#define         CHIPREV_ID_5705_A2              0x3002
-#define  CHIPREV_ID_5705_A3              0x3003
-#define  CHIPREV_ID_5721                 0x4101
-#define  CHIPREV_ID_5750_A0              0x4000
-#define  CHIPREV_ID_5750_A1              0x4001
-#define  CHIPREV_ID_5750_A3              0x4003
+#define  CHIPREV_ID_5705_A2             0x3002
+#define  CHIPREV_ID_5705_A3             0x3003
+#define  CHIPREV_ID_5750_A0             0x4000
+#define  CHIPREV_ID_5750_A1             0x4001
+#define  CHIPREV_ID_5750_A3             0x4003
+#define  CHIPREV_ID_5750_C2             0x4202
+#define  CHIPREV_ID_5752_A0_HW          0x5000
+#define  CHIPREV_ID_5752_A0             0x6000
+#define  CHIPREV_ID_5752_A1             0x6001
+#define  CHIPREV_ID_5714_A2             0x9002
+#define  CHIPREV_ID_5906_A1             0xc001
+#define  CHIPREV_ID_57780_A0            0x57780000
+#define  CHIPREV_ID_57780_A1            0x57780001
+#define  CHIPREV_ID_5717_A0             0x05717000
+#define  CHIPREV_ID_57765_A0            0x57785000
+#define  CHIPREV_ID_5719_A0             0x05719000
+#define  CHIPREV_ID_5720_A0             0x05720000
 #define  GET_ASIC_REV(CHIP_REV_ID)     ((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700                         0x07
 #define   ASIC_REV_5701                         0x00
@@ -202,12 +283,34 @@ typedef unsigned long dma_addr_t;
 #define   ASIC_REV_5704                         0x02
 #define   ASIC_REV_5705                         0x03
 #define   ASIC_REV_5750                         0x04
+#define   ASIC_REV_5752                         0x06
+#define   ASIC_REV_5780                         0x08
+#define   ASIC_REV_5714                         0x09
+#define   ASIC_REV_5755                         0x0a
 #define   ASIC_REV_5787                         0x0b
+#define   ASIC_REV_5906                         0x0c
+#define   ASIC_REV_USE_PROD_ID_REG      0x0f
+#define   ASIC_REV_5784                         0x5784
+#define   ASIC_REV_5761                         0x5761
+#define   ASIC_REV_5785                         0x5785
+#define   ASIC_REV_57780                0x57780
+#define   ASIC_REV_5717                         0x5717
+#define   ASIC_REV_57765                0x57785
+#define   ASIC_REV_5719                         0x5719
+#define   ASIC_REV_5720                         0x5720
 #define  GET_CHIP_REV(CHIP_REV_ID)     ((CHIP_REV_ID) >> 8)
 #define   CHIPREV_5700_AX               0x70
 #define   CHIPREV_5700_BX               0x71
 #define   CHIPREV_5700_CX               0x72
 #define   CHIPREV_5701_AX               0x00
+#define   CHIPREV_5703_AX               0x10
+#define   CHIPREV_5704_AX               0x20
+#define   CHIPREV_5704_BX               0x21
+#define   CHIPREV_5750_AX               0x40
+#define   CHIPREV_5750_BX               0x41
+#define   CHIPREV_5784_AX               0x57840
+#define   CHIPREV_5761_AX               0x57610
+#define   CHIPREV_57765_AX              0x577650
 #define  GET_METAL_REV(CHIP_REV_ID)    ((CHIP_REV_ID) & 0xff)
 #define   METAL_REV_A0                  0x00
 #define   METAL_REV_A1                  0x01
@@ -215,13 +318,17 @@ typedef unsigned long dma_addr_t;
 #define   METAL_REV_B1                  0x01
 #define   METAL_REV_B2                  0x02
 #define TG3PCI_DMA_RW_CTRL             0x0000006c
-#define  DMA_RWCTRL_MIN_DMA             0x000000ff
-#define  DMA_RWCTRL_MIN_DMA_SHIFT       0
+#define  DMA_RWCTRL_DIS_CACHE_ALIGNMENT  0x00000001
+#define  DMA_RWCTRL_TAGGED_STAT_WA      0x00000080
+#define  DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK 0x00000380
 #define  DMA_RWCTRL_READ_BNDRY_MASK     0x00000700
 #define  DMA_RWCTRL_READ_BNDRY_DISAB    0x00000000
 #define  DMA_RWCTRL_READ_BNDRY_16       0x00000100
+#define  DMA_RWCTRL_READ_BNDRY_128_PCIX         0x00000100
 #define  DMA_RWCTRL_READ_BNDRY_32       0x00000200
+#define  DMA_RWCTRL_READ_BNDRY_256_PCIX         0x00000200
 #define  DMA_RWCTRL_READ_BNDRY_64       0x00000300
+#define  DMA_RWCTRL_READ_BNDRY_384_PCIX         0x00000300
 #define  DMA_RWCTRL_READ_BNDRY_128      0x00000400
 #define  DMA_RWCTRL_READ_BNDRY_256      0x00000500
 #define  DMA_RWCTRL_READ_BNDRY_512      0x00000600
@@ -229,8 +336,11 @@ typedef unsigned long dma_addr_t;
 #define  DMA_RWCTRL_WRITE_BNDRY_MASK    0x00003800
 #define  DMA_RWCTRL_WRITE_BNDRY_DISAB   0x00000000
 #define  DMA_RWCTRL_WRITE_BNDRY_16      0x00000800
+#define  DMA_RWCTRL_WRITE_BNDRY_128_PCIX 0x00000800
 #define  DMA_RWCTRL_WRITE_BNDRY_32      0x00001000
+#define  DMA_RWCTRL_WRITE_BNDRY_256_PCIX 0x00001000
 #define  DMA_RWCTRL_WRITE_BNDRY_64      0x00001800
+#define  DMA_RWCTRL_WRITE_BNDRY_384_PCIX 0x00001800
 #define  DMA_RWCTRL_WRITE_BNDRY_128     0x00002000
 #define  DMA_RWCTRL_WRITE_BNDRY_256     0x00002800
 #define  DMA_RWCTRL_WRITE_BNDRY_512     0x00003000
@@ -246,6 +356,9 @@ typedef unsigned long dma_addr_t;
 #define  DMA_RWCTRL_PCI_READ_CMD_SHIFT  24
 #define  DMA_RWCTRL_PCI_WRITE_CMD       0xf0000000
 #define  DMA_RWCTRL_PCI_WRITE_CMD_SHIFT         28
+#define  DMA_RWCTRL_WRITE_BNDRY_64_PCIE         0x10000000
+#define  DMA_RWCTRL_WRITE_BNDRY_128_PCIE 0x30000000
+#define  DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE 0x70000000
 #define TG3PCI_PCISTATE                        0x00000070
 #define  PCISTATE_FORCE_RESET           0x00000001
 #define  PCISTATE_INT_NOT_ACTIVE        0x00000002
@@ -256,6 +369,9 @@ typedef unsigned long dma_addr_t;
 #define  PCISTATE_ROM_RETRY_ENABLE      0x00000040
 #define  PCISTATE_FLAT_VIEW             0x00000100
 #define  PCISTATE_RETRY_SAME_DMA        0x00002000
+#define  PCISTATE_ALLOW_APE_CTLSPC_WR   0x00010000
+#define  PCISTATE_ALLOW_APE_SHMEM_WR    0x00020000
+#define  PCISTATE_ALLOW_APE_PSPACE_WR   0x00040000
 #define TG3PCI_CLOCK_CTRL              0x00000074
 #define  CLOCK_CTRL_CORECLK_DISABLE     0x00000200
 #define  CLOCK_CTRL_RXCLK_DISABLE       0x00000400
@@ -271,16 +387,25 @@ typedef unsigned long dma_addr_t;
 #define TG3PCI_MEM_WIN_BASE_ADDR       0x0000007c
 #define TG3PCI_REG_DATA                        0x00000080
 #define TG3PCI_MEM_WIN_DATA            0x00000084
-#define TG3PCI_MODE_CTRL               0x00000088
-#define TG3PCI_MISC_CFG                        0x0000008c
 #define TG3PCI_MISC_LOCAL_CTRL         0x00000090
 /* 0x94 --> 0x98 unused */
 #define TG3PCI_STD_RING_PROD_IDX       0x00000098 /* 64-bit */
 #define TG3PCI_RCV_RET_RING_CON_IDX    0x000000a0 /* 64-bit */
-#define TG3PCI_SND_PROD_IDX            0x000000a8 /* 64-bit */
-/* 0xb0 --> 0x100 unused */
-
-/* 0x100 --> 0x200 unused */
+/* 0xa8 --> 0xb8 unused */
+#define TG3PCI_DUAL_MAC_CTRL           0x000000b8
+#define  DUAL_MAC_CTRL_CH_MASK          0x00000003
+#define  DUAL_MAC_CTRL_ID               0x00000004
+#define TG3PCI_PRODID_ASICREV          0x000000bc
+#define  PROD_ID_ASIC_REV_MASK          0x0fffffff
+/* 0xc0 --> 0xf4 unused */
+
+#define TG3PCI_GEN2_PRODID_ASICREV     0x000000f4
+#define TG3PCI_GEN15_PRODID_ASICREV    0x000000fc
+/* 0xf8 --> 0x200 unused */
+
+#define TG3_CORR_ERR_STAT              0x00000110
+#define  TG3_CORR_ERR_STAT_CLEAR       0xffffffff
+/* 0x114 --> 0x200 unused */
 
 /* Mailbox registers */
 #define MAILBOX_INTERRUPT_0            0x00000200 /* 64-bit */
@@ -297,7 +422,11 @@ typedef unsigned long dma_addr_t;
 #define MAILBOX_GENERAL_7              0x00000258 /* 64-bit */
 #define MAILBOX_RELOAD_STAT            0x00000260 /* 64-bit */
 #define MAILBOX_RCV_STD_PROD_IDX       0x00000268 /* 64-bit */
+#define TG3_RX_STD_PROD_IDX_REG                (MAILBOX_RCV_STD_PROD_IDX + \
+                                        TG3_64BIT_REG_LOW)
 #define MAILBOX_RCV_JUMBO_PROD_IDX     0x00000270 /* 64-bit */
+#define TG3_RX_JMB_PROD_IDX_REG                (MAILBOX_RCV_JUMBO_PROD_IDX + \
+                                        TG3_64BIT_REG_LOW)
 #define MAILBOX_RCV_MINI_PROD_IDX      0x00000278 /* 64-bit */
 #define MAILBOX_RCVRET_CON_IDX_0       0x00000280 /* 64-bit */
 #define MAILBOX_RCVRET_CON_IDX_1       0x00000288 /* 64-bit */
@@ -375,6 +504,9 @@ typedef unsigned long dma_addr_t;
 #define  MAC_MODE_TDE_ENABLE            0x00200000
 #define  MAC_MODE_RDE_ENABLE            0x00400000
 #define  MAC_MODE_FHDE_ENABLE           0x00800000
+#define  MAC_MODE_KEEP_FRAME_IN_WOL     0x01000000
+#define  MAC_MODE_APE_RX_EN             0x08000000
+#define  MAC_MODE_APE_TX_EN             0x10000000
 #define MAC_STATUS                     0x00000404
 #define  MAC_STATUS_PCS_SYNCED          0x00000001
 #define  MAC_STATUS_SIGNAL_DET          0x00000002
@@ -410,9 +542,12 @@ typedef unsigned long dma_addr_t;
 #define  LED_CTRL_100MBPS_STATUS        0x00000100
 #define  LED_CTRL_10MBPS_STATUS                 0x00000200
 #define  LED_CTRL_TRAFFIC_STATUS        0x00000400
-#define  LED_CTRL_MAC_MODE              0x00000000
-#define  LED_CTRL_PHY_MODE_1            0x00000800
-#define  LED_CTRL_PHY_MODE_2            0x00001000
+#define  LED_CTRL_MODE_MAC              0x00000000
+#define  LED_CTRL_MODE_PHY_1            0x00000800
+#define  LED_CTRL_MODE_PHY_2            0x00001000
+#define  LED_CTRL_MODE_SHASTA_MAC       0x00002000
+#define  LED_CTRL_MODE_SHARED           0x00004000
+#define  LED_CTRL_MODE_COMBO            0x00008000
 #define  LED_CTRL_BLINK_RATE_MASK       0x7ff80000
 #define  LED_CTRL_BLINK_RATE_SHIFT      19
 #define  LED_CTRL_BLINK_PER_OVERRIDE    0x00080000
@@ -459,11 +594,12 @@ typedef unsigned long dma_addr_t;
 #define  MI_COM_DATA_MASK               0x0000ffff
 #define MAC_MI_STAT                    0x00000450
 #define  MAC_MI_STAT_LNKSTAT_ATTN_ENAB  0x00000001
+#define  MAC_MI_STAT_10MBPS_MODE        0x00000002
 #define MAC_MI_MODE                    0x00000454
 #define  MAC_MI_MODE_CLK_10MHZ          0x00000001
 #define  MAC_MI_MODE_SHORT_PREAMBLE     0x00000002
 #define  MAC_MI_MODE_AUTO_POLL          0x00000010
-#define  MAC_MI_MODE_CORE_CLK_62MHZ     0x00008000
+#define  MAC_MI_MODE_500KHZ_CONST       0x00008000
 #define  MAC_MI_MODE_BASE               0x000c0000 /* XXX magic values XXX */
 #define MAC_AUTO_POLL_STATUS           0x00000458
 #define  MAC_AUTO_POLL_ERROR            0x00000001
@@ -473,6 +609,9 @@ typedef unsigned long dma_addr_t;
 #define  TX_MODE_FLOW_CTRL_ENABLE       0x00000010
 #define  TX_MODE_BIG_BCKOFF_ENABLE      0x00000020
 #define  TX_MODE_LONG_PAUSE_ENABLE      0x00000040
+#define  TX_MODE_MBUF_LOCKUP_FIX        0x00000100
+#define  TX_MODE_JMB_FRM_LEN            0x00400000
+#define  TX_MODE_CNT_DN_MODE            0x00800000
 #define MAC_TX_STATUS                  0x00000460
 #define  TX_STATUS_XOFFED               0x00000001
 #define  TX_STATUS_SENT_XOFF            0x00000002
@@ -487,6 +626,8 @@ typedef unsigned long dma_addr_t;
 #define  TX_LENGTHS_IPG_SHIFT           8
 #define  TX_LENGTHS_IPG_CRS_MASK        0x00003000
 #define  TX_LENGTHS_IPG_CRS_SHIFT       12
+#define  TX_LENGTHS_JMB_FRM_LEN_MSK     0x00ff0000
+#define  TX_LENGTHS_CNT_DWN_VAL_MSK     0xff000000
 #define MAC_RX_MODE                    0x00000468
 #define  RX_MODE_RESET                  0x00000001
 #define  RX_MODE_ENABLE                         0x00000002
@@ -499,6 +640,13 @@ typedef unsigned long dma_addr_t;
 #define  RX_MODE_PROMISC                0x00000100
 #define  RX_MODE_NO_CRC_CHECK           0x00000200
 #define  RX_MODE_KEEP_VLAN_TAG          0x00000400
+#define  RX_MODE_RSS_IPV4_HASH_EN       0x00010000
+#define  RX_MODE_RSS_TCP_IPV4_HASH_EN   0x00020000
+#define  RX_MODE_RSS_IPV6_HASH_EN       0x00040000
+#define  RX_MODE_RSS_TCP_IPV6_HASH_EN   0x00080000
+#define  RX_MODE_RSS_ITBL_HASH_BITS_7   0x00700000
+#define  RX_MODE_RSS_ENABLE             0x00800000
+#define  RX_MODE_IPV6_CSUM_ENABLE       0x01000000
 #define MAC_RX_STATUS                  0x0000046c
 #define  RX_STATUS_REMOTE_TX_XOFFED     0x00000001
 #define  RX_STATUS_XOFF_RCVD            0x00000002
@@ -573,11 +721,192 @@ typedef unsigned long dma_addr_t;
 #define MAC_EXTADDR_11_HIGH            0x00000588
 #define MAC_EXTADDR_11_LOW             0x0000058c
 #define MAC_SERDES_CFG                 0x00000590
+#define  MAC_SERDES_CFG_EDGE_SELECT     0x00001000
 #define MAC_SERDES_STAT                        0x00000594
-/* 0x598 --> 0x600 unused */
+/* 0x598 --> 0x5a0 unused */
+#define MAC_PHYCFG1                    0x000005a0
+#define  MAC_PHYCFG1_RGMII_INT          0x00000001
+#define  MAC_PHYCFG1_RXCLK_TO_MASK      0x00001ff0
+#define  MAC_PHYCFG1_RXCLK_TIMEOUT      0x00001000
+#define  MAC_PHYCFG1_TXCLK_TO_MASK      0x01ff0000
+#define  MAC_PHYCFG1_TXCLK_TIMEOUT      0x01000000
+#define  MAC_PHYCFG1_RGMII_EXT_RX_DEC   0x02000000
+#define  MAC_PHYCFG1_RGMII_SND_STAT_EN  0x04000000
+#define  MAC_PHYCFG1_TXC_DRV            0x20000000
+#define MAC_PHYCFG2                    0x000005a4
+#define  MAC_PHYCFG2_INBAND_ENABLE      0x00000001
+#define  MAC_PHYCFG2_EMODE_MASK_MASK    0x000001c0
+#define  MAC_PHYCFG2_EMODE_MASK_AC131   0x000000c0
+#define  MAC_PHYCFG2_EMODE_MASK_50610   0x00000100
+#define  MAC_PHYCFG2_EMODE_MASK_RT8211  0x00000000
+#define  MAC_PHYCFG2_EMODE_MASK_RT8201  0x000001c0
+#define  MAC_PHYCFG2_EMODE_COMP_MASK    0x00000e00
+#define  MAC_PHYCFG2_EMODE_COMP_AC131   0x00000600
+#define  MAC_PHYCFG2_EMODE_COMP_50610   0x00000400
+#define  MAC_PHYCFG2_EMODE_COMP_RT8211  0x00000800
+#define  MAC_PHYCFG2_EMODE_COMP_RT8201  0x00000000
+#define  MAC_PHYCFG2_FMODE_MASK_MASK    0x00007000
+#define  MAC_PHYCFG2_FMODE_MASK_AC131   0x00006000
+#define  MAC_PHYCFG2_FMODE_MASK_50610   0x00004000
+#define  MAC_PHYCFG2_FMODE_MASK_RT8211  0x00000000
+#define  MAC_PHYCFG2_FMODE_MASK_RT8201  0x00007000
+#define  MAC_PHYCFG2_FMODE_COMP_MASK    0x00038000
+#define  MAC_PHYCFG2_FMODE_COMP_AC131   0x00030000
+#define  MAC_PHYCFG2_FMODE_COMP_50610   0x00008000
+#define  MAC_PHYCFG2_FMODE_COMP_RT8211  0x00038000
+#define  MAC_PHYCFG2_FMODE_COMP_RT8201  0x00000000
+#define  MAC_PHYCFG2_GMODE_MASK_MASK    0x001c0000
+#define  MAC_PHYCFG2_GMODE_MASK_AC131   0x001c0000
+#define  MAC_PHYCFG2_GMODE_MASK_50610   0x00100000
+#define  MAC_PHYCFG2_GMODE_MASK_RT8211  0x00000000
+#define  MAC_PHYCFG2_GMODE_MASK_RT8201  0x001c0000
+#define  MAC_PHYCFG2_GMODE_COMP_MASK    0x00e00000
+#define  MAC_PHYCFG2_GMODE_COMP_AC131   0x00e00000
+#define  MAC_PHYCFG2_GMODE_COMP_50610   0x00000000
+#define  MAC_PHYCFG2_GMODE_COMP_RT8211  0x00200000
+#define  MAC_PHYCFG2_GMODE_COMP_RT8201  0x00000000
+#define  MAC_PHYCFG2_ACT_MASK_MASK      0x03000000
+#define  MAC_PHYCFG2_ACT_MASK_AC131     0x03000000
+#define  MAC_PHYCFG2_ACT_MASK_50610     0x01000000
+#define  MAC_PHYCFG2_ACT_MASK_RT8211    0x03000000
+#define  MAC_PHYCFG2_ACT_MASK_RT8201    0x01000000
+#define  MAC_PHYCFG2_ACT_COMP_MASK      0x0c000000
+#define  MAC_PHYCFG2_ACT_COMP_AC131     0x00000000
+#define  MAC_PHYCFG2_ACT_COMP_50610     0x00000000
+#define  MAC_PHYCFG2_ACT_COMP_RT8211    0x00000000
+#define  MAC_PHYCFG2_ACT_COMP_RT8201    0x08000000
+#define  MAC_PHYCFG2_QUAL_MASK_MASK     0x30000000
+#define  MAC_PHYCFG2_QUAL_MASK_AC131    0x30000000
+#define  MAC_PHYCFG2_QUAL_MASK_50610    0x30000000
+#define  MAC_PHYCFG2_QUAL_MASK_RT8211   0x30000000
+#define  MAC_PHYCFG2_QUAL_MASK_RT8201   0x30000000
+#define  MAC_PHYCFG2_QUAL_COMP_MASK     0xc0000000
+#define  MAC_PHYCFG2_QUAL_COMP_AC131    0x00000000
+#define  MAC_PHYCFG2_QUAL_COMP_50610    0x00000000
+#define  MAC_PHYCFG2_QUAL_COMP_RT8211   0x00000000
+#define  MAC_PHYCFG2_QUAL_COMP_RT8201   0x00000000
+#define MAC_PHYCFG2_50610_LED_MODES \
+       (MAC_PHYCFG2_EMODE_MASK_50610 | \
+        MAC_PHYCFG2_EMODE_COMP_50610 | \
+        MAC_PHYCFG2_FMODE_MASK_50610 | \
+        MAC_PHYCFG2_FMODE_COMP_50610 | \
+        MAC_PHYCFG2_GMODE_MASK_50610 | \
+        MAC_PHYCFG2_GMODE_COMP_50610 | \
+        MAC_PHYCFG2_ACT_MASK_50610 | \
+        MAC_PHYCFG2_ACT_COMP_50610 | \
+        MAC_PHYCFG2_QUAL_MASK_50610 | \
+        MAC_PHYCFG2_QUAL_COMP_50610)
+#define MAC_PHYCFG2_AC131_LED_MODES \
+       (MAC_PHYCFG2_EMODE_MASK_AC131 | \
+        MAC_PHYCFG2_EMODE_COMP_AC131 | \
+        MAC_PHYCFG2_FMODE_MASK_AC131 | \
+        MAC_PHYCFG2_FMODE_COMP_AC131 | \
+        MAC_PHYCFG2_GMODE_MASK_AC131 | \
+        MAC_PHYCFG2_GMODE_COMP_AC131 | \
+        MAC_PHYCFG2_ACT_MASK_AC131 | \
+        MAC_PHYCFG2_ACT_COMP_AC131 | \
+        MAC_PHYCFG2_QUAL_MASK_AC131 | \
+        MAC_PHYCFG2_QUAL_COMP_AC131)
+#define MAC_PHYCFG2_RTL8211C_LED_MODES \
+       (MAC_PHYCFG2_EMODE_MASK_RT8211 | \
+        MAC_PHYCFG2_EMODE_COMP_RT8211 | \
+        MAC_PHYCFG2_FMODE_MASK_RT8211 | \
+        MAC_PHYCFG2_FMODE_COMP_RT8211 | \
+        MAC_PHYCFG2_GMODE_MASK_RT8211 | \
+        MAC_PHYCFG2_GMODE_COMP_RT8211 | \
+        MAC_PHYCFG2_ACT_MASK_RT8211 | \
+        MAC_PHYCFG2_ACT_COMP_RT8211 | \
+        MAC_PHYCFG2_QUAL_MASK_RT8211 | \
+        MAC_PHYCFG2_QUAL_COMP_RT8211)
+#define MAC_PHYCFG2_RTL8201E_LED_MODES \
+       (MAC_PHYCFG2_EMODE_MASK_RT8201 | \
+        MAC_PHYCFG2_EMODE_COMP_RT8201 | \
+        MAC_PHYCFG2_FMODE_MASK_RT8201 | \
+        MAC_PHYCFG2_FMODE_COMP_RT8201 | \
+        MAC_PHYCFG2_GMODE_MASK_RT8201 | \
+        MAC_PHYCFG2_GMODE_COMP_RT8201 | \
+        MAC_PHYCFG2_ACT_MASK_RT8201 | \
+        MAC_PHYCFG2_ACT_COMP_RT8201 | \
+        MAC_PHYCFG2_QUAL_MASK_RT8201 | \
+        MAC_PHYCFG2_QUAL_COMP_RT8201)
+#define MAC_EXT_RGMII_MODE             0x000005a8
+#define  MAC_RGMII_MODE_TX_ENABLE       0x00000001
+#define  MAC_RGMII_MODE_TX_LOWPWR       0x00000002
+#define  MAC_RGMII_MODE_TX_RESET        0x00000004
+#define  MAC_RGMII_MODE_RX_INT_B        0x00000100
+#define  MAC_RGMII_MODE_RX_QUALITY      0x00000200
+#define  MAC_RGMII_MODE_RX_ACTIVITY     0x00000400
+#define  MAC_RGMII_MODE_RX_ENG_DET      0x00000800
+/* 0x5ac --> 0x5b0 unused */
+#define SERDES_RX_CTRL                 0x000005b0      /* 5780/5714 only */
+#define  SERDES_RX_SIG_DETECT           0x00000400
+#define SG_DIG_CTRL                    0x000005b0
+#define  SG_DIG_USING_HW_AUTONEG        0x80000000
+#define  SG_DIG_SOFT_RESET              0x40000000
+#define  SG_DIG_DISABLE_LINKRDY                 0x20000000
+#define  SG_DIG_CRC16_CLEAR_N           0x01000000
+#define  SG_DIG_EN10B                   0x00800000
+#define  SG_DIG_CLEAR_STATUS            0x00400000
+#define  SG_DIG_LOCAL_DUPLEX_STATUS     0x00200000
+#define  SG_DIG_LOCAL_LINK_STATUS       0x00100000
+#define  SG_DIG_SPEED_STATUS_MASK       0x000c0000
+#define  SG_DIG_SPEED_STATUS_SHIFT      18
+#define  SG_DIG_JUMBO_PACKET_DISABLE    0x00020000
+#define  SG_DIG_RESTART_AUTONEG                 0x00010000
+#define  SG_DIG_FIBER_MODE              0x00008000
+#define  SG_DIG_REMOTE_FAULT_MASK       0x00006000
+#define  SG_DIG_PAUSE_MASK              0x00001800
+#define  SG_DIG_PAUSE_CAP               0x00000800
+#define  SG_DIG_ASYM_PAUSE              0x00001000
+#define  SG_DIG_GBIC_ENABLE             0x00000400
+#define  SG_DIG_CHECK_END_ENABLE        0x00000200
+#define  SG_DIG_SGMII_AUTONEG_TIMER     0x00000100
+#define  SG_DIG_CLOCK_PHASE_SELECT      0x00000080
+#define  SG_DIG_GMII_INPUT_SELECT       0x00000040
+#define  SG_DIG_MRADV_CRC16_SELECT      0x00000020
+#define  SG_DIG_COMMA_DETECT_ENABLE     0x00000010
+#define  SG_DIG_AUTONEG_TIMER_REDUCE    0x00000008
+#define  SG_DIG_AUTONEG_LOW_ENABLE      0x00000004
+#define  SG_DIG_REMOTE_LOOPBACK                 0x00000002
+#define  SG_DIG_LOOPBACK                0x00000001
+#define  SG_DIG_COMMON_SETUP (SG_DIG_CRC16_CLEAR_N | \
+                             SG_DIG_LOCAL_DUPLEX_STATUS | \
+                             SG_DIG_LOCAL_LINK_STATUS | \
+                             (0x2 << SG_DIG_SPEED_STATUS_SHIFT) | \
+                             SG_DIG_FIBER_MODE | SG_DIG_GBIC_ENABLE)
+#define SG_DIG_STATUS                  0x000005b4
+#define  SG_DIG_CRC16_BUS_MASK          0xffff0000
+#define  SG_DIG_PARTNER_FAULT_MASK      0x00600000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_ASYM_PAUSE      0x00100000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_PAUSE_CAPABLE   0x00080000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_HALF_DUPLEX     0x00040000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_FULL_DUPLEX     0x00020000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_NEXT_PAGE       0x00010000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_AUTONEG_STATE_MASK      0x00000ff0
+#define  SG_DIG_IS_SERDES               0x00000100
+#define  SG_DIG_COMMA_DETECTOR          0x00000008
+#define  SG_DIG_MAC_ACK_STATUS          0x00000004
+#define  SG_DIG_AUTONEG_COMPLETE        0x00000002
+#define  SG_DIG_AUTONEG_ERROR           0x00000001
+/* 0x5b8 --> 0x600 unused */
 #define MAC_TX_MAC_STATE_BASE          0x00000600 /* 16 bytes */
 #define MAC_RX_MAC_STATE_BASE          0x00000610 /* 20 bytes */
-/* 0x624 --> 0x800 unused */
+/* 0x624 --> 0x670 unused */
+
+#define MAC_RSS_INDIR_TBL_0            0x00000630
+
+#define MAC_RSS_HASH_KEY_0             0x00000670
+#define MAC_RSS_HASH_KEY_1             0x00000674
+#define MAC_RSS_HASH_KEY_2             0x00000678
+#define MAC_RSS_HASH_KEY_3             0x0000067c
+#define MAC_RSS_HASH_KEY_4             0x00000680
+#define MAC_RSS_HASH_KEY_5             0x00000684
+#define MAC_RSS_HASH_KEY_6             0x00000688
+#define MAC_RSS_HASH_KEY_7             0x0000068c
+#define MAC_RSS_HASH_KEY_8             0x00000690
+#define MAC_RSS_HASH_KEY_9             0x00000694
+/* 0x698 --> 0x800 unused */
+
 #define MAC_TX_STATS_OCTETS            0x00000800
 #define MAC_TX_STATS_RESV1             0x00000804
 #define MAC_TX_STATS_COLLISIONS                0x00000808
@@ -642,7 +971,8 @@ typedef unsigned long dma_addr_t;
 #define  SNDDATAI_SCTRL_FORCE_ZERO      0x00000010
 #define SNDDATAI_STATSENAB             0x00000c0c
 #define SNDDATAI_STATSINCMASK          0x00000c10
-/* 0xc14 --> 0xc80 unused */
+#define ISO_PKT_TX                     0x00000c20
+/* 0xc24 --> 0xc80 unused */
 #define SNDDATAI_COS_CNT_0             0x00000c80
 #define SNDDATAI_COS_CNT_1             0x00000c84
 #define SNDDATAI_COS_CNT_2             0x00000c88
@@ -673,6 +1003,7 @@ typedef unsigned long dma_addr_t;
 #define SNDDATAC_MODE                  0x00001000
 #define  SNDDATAC_MODE_RESET            0x00000001
 #define  SNDDATAC_MODE_ENABLE           0x00000002
+#define  SNDDATAC_MODE_CDELAY           0x00000010
 /* 0x1004 --> 0x1400 unused */
 
 /* Send BD ring selector */
@@ -707,6 +1038,7 @@ typedef unsigned long dma_addr_t;
 #define  SNDBDI_MODE_RESET              0x00000001
 #define  SNDBDI_MODE_ENABLE             0x00000002
 #define  SNDBDI_MODE_ATTN_ENABLE        0x00000004
+#define  SNDBDI_MODE_MULTI_TXQ_EN       0x00000020
 #define SNDBDI_STATUS                  0x00001804
 #define  SNDBDI_STATUS_ERROR_ATTN       0x00000004
 #define SNDBDI_IN_PROD_IDX_0           0x00001808
@@ -757,6 +1089,8 @@ typedef unsigned long dma_addr_t;
 #define  RCVLPC_STATSCTRL_ENABLE        0x00000001
 #define  RCVLPC_STATSCTRL_FASTUPD       0x00000002
 #define RCVLPC_STATS_ENABLE            0x00002018
+#define  RCVLPC_STATSENAB_ASF_FIX       0x00000002
+#define  RCVLPC_STATSENAB_DACK_FIX      0x00040000
 #define  RCVLPC_STATSENAB_LNGBRST_RFIX  0x00400000
 #define RCVLPC_STATS_INCMASK           0x0000201c
 /* 0x2020 --> 0x2100 unused */
@@ -781,6 +1115,7 @@ typedef unsigned long dma_addr_t;
 #define  RCVDBDI_MODE_JUMBOBD_NEEDED    0x00000004
 #define  RCVDBDI_MODE_FRM_TOO_BIG       0x00000008
 #define  RCVDBDI_MODE_INV_RING_SZ       0x00000010
+#define  RCVDBDI_MODE_LRG_RING_SZ       0x00010000
 #define RCVDBDI_STATUS                 0x00002404
 #define  RCVDBDI_STATUS_JUMBOBD_NEEDED  0x00000004
 #define  RCVDBDI_STATUS_FRM_TOO_BIG     0x00000008
@@ -833,7 +1168,11 @@ typedef unsigned long dma_addr_t;
 #define RCVBDI_MINI_THRESH             0x00002c14
 #define RCVBDI_STD_THRESH              0x00002c18
 #define RCVBDI_JUMBO_THRESH            0x00002c1c
-/* 0x2c20 --> 0x3000 unused */
+/* 0x2c20 --> 0x2d00 unused */
+
+#define STD_REPLENISH_LWM              0x00002d00
+#define JMB_REPLENISH_LWM              0x00002d04
+/* 0x2d08 --> 0x3000 unused */
 
 /* Receive BD Completion Control Registers */
 #define RCVCC_MODE                     0x00003000
@@ -854,7 +1193,75 @@ typedef unsigned long dma_addr_t;
 #define  RCVLSC_MODE_ATTN_ENABLE        0x00000004
 #define RCVLSC_STATUS                  0x00003404
 #define  RCVLSC_STATUS_ERROR_ATTN       0x00000004
-/* 0x3408 --> 0x3800 unused */
+/* 0x3408 --> 0x3600 unused */
+
+/* CPMU registers */
+#define TG3_CPMU_CTRL                  0x00003600
+#define  CPMU_CTRL_LINK_IDLE_MODE       0x00000200
+#define  CPMU_CTRL_LINK_AWARE_MODE      0x00000400
+#define  CPMU_CTRL_LINK_SPEED_MODE      0x00004000
+#define  CPMU_CTRL_GPHY_10MB_RXONLY     0x00010000
+#define TG3_CPMU_LSPD_10MB_CLK         0x00003604
+#define  CPMU_LSPD_10MB_MACCLK_MASK     0x001f0000
+#define  CPMU_LSPD_10MB_MACCLK_6_25     0x00130000
+/* 0x3608 --> 0x360c unused */
+
+#define TG3_CPMU_LSPD_1000MB_CLK       0x0000360c
+#define  CPMU_LSPD_1000MB_MACCLK_62_5   0x00000000
+#define  CPMU_LSPD_1000MB_MACCLK_12_5   0x00110000
+#define  CPMU_LSPD_1000MB_MACCLK_MASK   0x001f0000
+#define TG3_CPMU_LNK_AWARE_PWRMD       0x00003610
+#define  CPMU_LNK_AWARE_MACCLK_MASK     0x001f0000
+#define  CPMU_LNK_AWARE_MACCLK_6_25     0x00130000
+/* 0x3614 --> 0x361c unused */
+
+#define TG3_CPMU_HST_ACC               0x0000361c
+#define  CPMU_HST_ACC_MACCLK_MASK       0x001f0000
+#define  CPMU_HST_ACC_MACCLK_6_25       0x00130000
+/* 0x3620 --> 0x3630 unused */
+
+#define TG3_CPMU_CLCK_ORIDE            0x00003624
+#define  CPMU_CLCK_ORIDE_MAC_ORIDE_EN   0x80000000
+
+#define TG3_CPMU_CLCK_STAT             0x00003630
+#define  CPMU_CLCK_STAT_MAC_CLCK_MASK   0x001f0000
+#define  CPMU_CLCK_STAT_MAC_CLCK_62_5   0x00000000
+#define  CPMU_CLCK_STAT_MAC_CLCK_12_5   0x00110000
+#define  CPMU_CLCK_STAT_MAC_CLCK_6_25   0x00130000
+/* 0x3634 --> 0x365c unused */
+
+#define TG3_CPMU_MUTEX_REQ             0x0000365c
+#define  CPMU_MUTEX_REQ_DRIVER          0x00001000
+#define TG3_CPMU_MUTEX_GNT             0x00003660
+#define  CPMU_MUTEX_GNT_DRIVER          0x00001000
+#define TG3_CPMU_PHY_STRAP             0x00003664
+#define TG3_CPMU_PHY_STRAP_IS_SERDES    0x00000020
+/* 0x3664 --> 0x36b0 unused */
+
+#define TG3_CPMU_EEE_MODE              0x000036b0
+#define  TG3_CPMU_EEEMD_APE_TX_DET_EN   0x00000004
+#define  TG3_CPMU_EEEMD_ERLY_L1_XIT_DET         0x00000008
+#define  TG3_CPMU_EEEMD_SND_IDX_DET_EN  0x00000040
+#define  TG3_CPMU_EEEMD_LPI_ENABLE      0x00000080
+#define  TG3_CPMU_EEEMD_LPI_IN_TX       0x00000100
+#define  TG3_CPMU_EEEMD_LPI_IN_RX       0x00000200
+#define  TG3_CPMU_EEEMD_EEE_ENABLE      0x00100000
+#define TG3_CPMU_EEE_DBTMR1            0x000036b4
+#define  TG3_CPMU_DBTMR1_PCIEXIT_2047US         0x07ff0000
+#define  TG3_CPMU_DBTMR1_LNKIDLE_2047US         0x000070ff
+#define TG3_CPMU_EEE_DBTMR2            0x000036b8
+#define  TG3_CPMU_DBTMR2_APE_TX_2047US  0x07ff0000
+#define  TG3_CPMU_DBTMR2_TXIDXEQ_2047US         0x000070ff
+#define TG3_CPMU_EEE_LNKIDL_CTRL       0x000036bc
+#define  TG3_CPMU_EEE_LNKIDL_PCIE_NL0   0x01000000
+#define  TG3_CPMU_EEE_LNKIDL_UART_IDL   0x00000004
+/* 0x36c0 --> 0x36d0 unused */
+
+#define TG3_CPMU_EEE_CTRL              0x000036d0
+#define TG3_CPMU_EEE_CTRL_EXIT_16_5_US  0x0000019d
+#define TG3_CPMU_EEE_CTRL_EXIT_36_US    0x00000384
+#define TG3_CPMU_EEE_CTRL_EXIT_20_1_US  0x000001f8
+/* 0x36d4 --> 0x3800 unused */
 
 /* Mbuf cluster free registers */
 #define MBFREE_MODE                    0x00003800
@@ -876,40 +1283,56 @@ typedef unsigned long dma_addr_t;
 #define  HOSTCC_MODE_CLRTICK_TXBD       0x00000400
 #define  HOSTCC_MODE_NOINT_ON_NOW       0x00000800
 #define  HOSTCC_MODE_NOINT_ON_FORCE     0x00001000
+#define  HOSTCC_MODE_COAL_VEC1_NOW      0x00002000
 #define HOSTCC_STATUS                  0x00003c04
 #define  HOSTCC_STATUS_ERROR_ATTN       0x00000004
 #define HOSTCC_RXCOL_TICKS             0x00003c08
 #define  LOW_RXCOL_TICKS                0x00000032
+#define  LOW_RXCOL_TICKS_CLRTCKS        0x00000014
 #define  DEFAULT_RXCOL_TICKS            0x00000048
 #define  HIGH_RXCOL_TICKS               0x00000096
+#define  MAX_RXCOL_TICKS                0x000003ff
 #define HOSTCC_TXCOL_TICKS             0x00003c0c
 #define  LOW_TXCOL_TICKS                0x00000096
+#define  LOW_TXCOL_TICKS_CLRTCKS        0x00000048
 #define  DEFAULT_TXCOL_TICKS            0x0000012c
 #define  HIGH_TXCOL_TICKS               0x00000145
+#define  MAX_TXCOL_TICKS                0x000003ff
 #define HOSTCC_RXMAX_FRAMES            0x00003c10
 #define  LOW_RXMAX_FRAMES               0x00000005
 #define  DEFAULT_RXMAX_FRAMES           0x00000008
 #define  HIGH_RXMAX_FRAMES              0x00000012
+#define  MAX_RXMAX_FRAMES               0x000000ff
 #define HOSTCC_TXMAX_FRAMES            0x00003c14
 #define  LOW_TXMAX_FRAMES               0x00000035
 #define  DEFAULT_TXMAX_FRAMES           0x0000004b
 #define  HIGH_TXMAX_FRAMES              0x00000052
+#define  MAX_TXMAX_FRAMES               0x000000ff
 #define HOSTCC_RXCOAL_TICK_INT         0x00003c18
 #define  DEFAULT_RXCOAL_TICK_INT        0x00000019
+#define  DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014
+#define  MAX_RXCOAL_TICK_INT            0x000003ff
 #define HOSTCC_TXCOAL_TICK_INT         0x00003c1c
 #define  DEFAULT_TXCOAL_TICK_INT        0x00000019
+#define  DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014
+#define  MAX_TXCOAL_TICK_INT            0x000003ff
 #define HOSTCC_RXCOAL_MAXF_INT         0x00003c20
 #define  DEFAULT_RXCOAL_MAXF_INT        0x00000005
+#define  MAX_RXCOAL_MAXF_INT            0x000000ff
 #define HOSTCC_TXCOAL_MAXF_INT         0x00003c24
 #define  DEFAULT_TXCOAL_MAXF_INT        0x00000005
+#define  MAX_TXCOAL_MAXF_INT            0x000000ff
 #define HOSTCC_STAT_COAL_TICKS         0x00003c28
 #define  DEFAULT_STAT_COAL_TICKS        0x000f4240
+#define  MAX_STAT_COAL_TICKS            0xd693d400
+#define  MIN_STAT_COAL_TICKS            0x00000064
 /* 0x3c2c --> 0x3c30 unused */
 #define HOSTCC_STATS_BLK_HOST_ADDR     0x00003c30 /* 64-bit */
 #define HOSTCC_STATUS_BLK_HOST_ADDR    0x00003c38 /* 64-bit */
 #define HOSTCC_STATS_BLK_NIC_ADDR      0x00003c40
 #define HOSTCC_STATUS_BLK_NIC_ADDR     0x00003c44
 #define HOSTCC_FLOW_ATTN               0x00003c48
+#define HOSTCC_FLOW_ATTN_MBUF_LWM       0x00000040
 /* 0x3c4c --> 0x3c50 unused */
 #define HOSTCC_JUMBO_CON_IDX           0x00003c50
 #define HOSTCC_STD_CON_IDX             0x00003c54
@@ -947,7 +1370,16 @@ typedef unsigned long dma_addr_t;
 #define HOSTCC_SND_CON_IDX_13          0x00003cf4
 #define HOSTCC_SND_CON_IDX_14          0x00003cf8
 #define HOSTCC_SND_CON_IDX_15          0x00003cfc
-/* 0x3d00 --> 0x4000 unused */
+#define HOSTCC_STATBLCK_RING1          0x00003d00
+/* 0x3d00 --> 0x3d80 unused */
+
+#define HOSTCC_RXCOL_TICKS_VEC1                0x00003d80
+#define HOSTCC_TXCOL_TICKS_VEC1                0x00003d84
+#define HOSTCC_RXMAX_FRAMES_VEC1       0x00003d88
+#define HOSTCC_TXMAX_FRAMES_VEC1       0x00003d8c
+#define HOSTCC_RXCOAL_MAXF_INT_VEC1    0x00003d90
+#define HOSTCC_TXCOAL_MAXF_INT_VEC1    0x00003d94
+/* 0x3d98 --> 0x4000 unused */
 
 /* Memory arbiter control registers */
 #define MEMARB_MODE                    0x00004000
@@ -965,6 +1397,7 @@ typedef unsigned long dma_addr_t;
 #define  BUFMGR_MODE_ATTN_ENABLE        0x00000004
 #define  BUFMGR_MODE_BM_TEST            0x00000008
 #define  BUFMGR_MODE_MBLOW_ATTN_ENAB    0x00000010
+#define  BUFMGR_MODE_NO_TX_UNDERRUN     0x80000000
 #define BUFMGR_STATUS                  0x00004404
 #define  BUFMGR_STATUS_ERROR            0x00000004
 #define  BUFMGR_STATUS_MBLOW            0x00000010
@@ -974,14 +1407,23 @@ typedef unsigned long dma_addr_t;
 #define  DEFAULT_MB_RDMA_LOW_WATER      0x00000050
 #define  DEFAULT_MB_RDMA_LOW_WATER_5705         0x00000000
 #define  DEFAULT_MB_RDMA_LOW_WATER_JUMBO 0x00000130
+#define  DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780 0x00000000
 #define BUFMGR_MB_MACRX_LOW_WATER      0x00004414
 #define  DEFAULT_MB_MACRX_LOW_WATER      0x00000020
 #define  DEFAULT_MB_MACRX_LOW_WATER_5705  0x00000010
+#define  DEFAULT_MB_MACRX_LOW_WATER_5906  0x00000004
+#define  DEFAULT_MB_MACRX_LOW_WATER_57765 0x0000002a
 #define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098
+#define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b
+#define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765 0x0000007e
 #define BUFMGR_MB_HIGH_WATER           0x00004418
 #define  DEFAULT_MB_HIGH_WATER          0x00000060
 #define  DEFAULT_MB_HIGH_WATER_5705     0x00000060
+#define  DEFAULT_MB_HIGH_WATER_5906     0x00000010
+#define  DEFAULT_MB_HIGH_WATER_57765    0x000000a0
 #define  DEFAULT_MB_HIGH_WATER_JUMBO    0x0000017c
+#define  DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096
+#define  DEFAULT_MB_HIGH_WATER_JUMBO_57765 0x000000ea
 #define BUFMGR_RX_MB_ALLOC_REQ         0x0000441c
 #define  BUFMGR_MB_ALLOC_BIT            0x10000000
 #define BUFMGR_RX_MB_ALLOC_RESP                0x00004420
@@ -1015,9 +1457,16 @@ typedef unsigned long dma_addr_t;
 #define  RDMAC_MODE_FIFOOREAD_ENAB      0x00000100
 #define  RDMAC_MODE_LNGREAD_ENAB        0x00000200
 #define  RDMAC_MODE_SPLIT_ENABLE        0x00000800
+#define  RDMAC_MODE_BD_SBD_CRPT_ENAB    0x00000800
 #define  RDMAC_MODE_SPLIT_RESET                 0x00001000
+#define  RDMAC_MODE_MBUF_RBD_CRPT_ENAB  0x00001000
+#define  RDMAC_MODE_MBUF_SBD_CRPT_ENAB  0x00002000
 #define  RDMAC_MODE_FIFO_SIZE_128       0x00020000
 #define  RDMAC_MODE_FIFO_LONG_BURST     0x00030000
+#define  RDMAC_MODE_MULT_DMA_RD_DIS     0x01000000
+#define  RDMAC_MODE_IPV4_LSO_EN                 0x08000000
+#define  RDMAC_MODE_IPV6_LSO_EN                 0x10000000
+#define  RDMAC_MODE_H2BNC_VLAN_DET      0x20000000
 #define RDMAC_STATUS                   0x00004804
 #define  RDMAC_STATUS_TGTABORT          0x00000004
 #define  RDMAC_STATUS_MSTABORT          0x00000008
@@ -1027,7 +1476,22 @@ typedef unsigned long dma_addr_t;
 #define  RDMAC_STATUS_FIFOURUN          0x00000080
 #define  RDMAC_STATUS_FIFOOREAD                 0x00000100
 #define  RDMAC_STATUS_LNGREAD           0x00000200
-/* 0x4808 --> 0x4c00 unused */
+/* 0x4808 --> 0x4900 unused */
+
+#define TG3_RDMA_RSRVCTRL_REG          0x00004900
+#define TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX         0x00000004
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K         0x00000c00
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK         0x00000ff0
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K         0x000c0000
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK         0x000ff000
+#define TG3_RDMA_RSRVCTRL_TXMRGN_320B   0x28000000
+#define TG3_RDMA_RSRVCTRL_TXMRGN_MASK   0xffe00000
+/* 0x4904 --> 0x4910 unused */
+
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL     0x00004910
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K   0x00030000
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K  0x000c0000
+/* 0x4914 --> 0x4c00 unused */
 
 /* Write DMA control registers */
 #define WDMAC_MODE                     0x00004c00
@@ -1041,7 +1505,9 @@ typedef unsigned long dma_addr_t;
 #define  WDMAC_MODE_FIFOURUN_ENAB       0x00000080
 #define  WDMAC_MODE_FIFOOREAD_ENAB      0x00000100
 #define  WDMAC_MODE_LNGREAD_ENAB        0x00000200
-#define  WDMAC_MODE_RX_ACCEL            0x00000400
+#define  WDMAC_MODE_RX_ACCEL            0x00000400
+#define  WDMAC_MODE_STATUS_TAG_FIX      0x20000000
+#define  WDMAC_MODE_BURST_ALL_DATA      0xc0000000
 #define WDMAC_STATUS                   0x00004c04
 #define  WDMAC_STATUS_TGTABORT          0x00000004
 #define  WDMAC_STATUS_MSTABORT          0x00000008
@@ -1107,9 +1573,26 @@ typedef unsigned long dma_addr_t;
 /* 0x280 --> 0x400 unused */
 
 #define RX_CPU_BASE                    0x00005000
+#define RX_CPU_MODE                    0x00005000
+#define RX_CPU_STATE                   0x00005004
+#define RX_CPU_PGMCTR                  0x0000501c
+#define RX_CPU_HWBKPT                  0x00005034
 #define TX_CPU_BASE                    0x00005400
+#define TX_CPU_MODE                    0x00005400
+#define TX_CPU_STATE                   0x00005404
+#define TX_CPU_PGMCTR                  0x0000541c
+
+#define VCPU_STATUS                    0x00005100
+#define  VCPU_STATUS_INIT_DONE          0x04000000
+#define  VCPU_STATUS_DRV_RESET          0x08000000
+
+#define VCPU_CFGSHDW                   0x00005104
+#define  VCPU_CFGSHDW_WOL_ENABLE        0x00000001
+#define  VCPU_CFGSHDW_WOL_MAGPKT        0x00000004
+#define  VCPU_CFGSHDW_ASPM_DBNC                 0x00001000
 
 /* Mailboxes */
+#define GRCMBOX_BASE                   0x00005600
 #define GRCMBOX_INTERRUPT_0            0x00005800 /* 64-bit */
 #define GRCMBOX_INTERRUPT_1            0x00005808 /* 64-bit */
 #define GRCMBOX_INTERRUPT_2            0x00005810 /* 64-bit */
@@ -1182,17 +1665,6 @@ typedef unsigned long dma_addr_t;
 
 /* Flow Through queues */
 #define FTQ_RESET                      0x00005c00
-#define FTQ_RESET_DMA_READ_QUEUE       (1 << 1)
-#define FTQ_RESET_DMA_HIGH_PRI_READ    (1 << 2)
-#define FTQ_RESET_SEND_BD_COMPLETION   (1 << 4)
-#define FTQ_RESET_DMA_WRITE            (1 << 6)
-#define FTQ_RESET_DMA_HIGH_PRI_WRITE   (1 << 7)
-#define FTQ_RESET_SEND_DATA_COMPLETION (1 << 9)
-#define FTQ_RESET_HOST_COALESCING      (1 << 10)
-#define FTQ_RESET_MAC_TX               (1 << 11)
-#define FTQ_RESET_RX_BD_COMPLETE       (1 << 13)
-#define FTQ_RESET_RX_LIST_PLCMT                (1 << 14)
-#define FTQ_RESET_RX_DATA_COMPLETION   (1 << 16)
 /* 0x5c04 --> 0x5c10 unused */
 #define FTQ_DMA_NORM_READ_CTL          0x00005c10
 #define FTQ_DMA_NORM_READ_FULL_CNT     0x00005c14
@@ -1268,7 +1740,10 @@ typedef unsigned long dma_addr_t;
 #define MSGINT_MODE                    0x00006000
 #define  MSGINT_MODE_RESET              0x00000001
 #define  MSGINT_MODE_ENABLE             0x00000002
+#define  MSGINT_MODE_ONE_SHOT_DISABLE   0x00000020
+#define  MSGINT_MODE_MULTIVEC_EN        0x00000080
 #define MSGINT_STATUS                  0x00006004
+#define  MSGINT_STATUS_MSI_REQ          0x00000001
 #define MSGINT_FIFO                    0x00006008
 /* 0x600c --> 0x6400 unused */
 
@@ -1285,6 +1760,8 @@ typedef unsigned long dma_addr_t;
 #define  GRC_MODE_WSWAP_NONFRM_DATA    0x00000004
 #define  GRC_MODE_BSWAP_DATA           0x00000010
 #define  GRC_MODE_WSWAP_DATA           0x00000020
+#define  GRC_MODE_BYTE_SWAP_B2HRX_DATA 0x00000040
+#define  GRC_MODE_WORD_SWAP_B2HRX_DATA 0x00000080
 #define  GRC_MODE_SPLITHDR             0x00000100
 #define  GRC_MODE_NOFRM_CRACKING       0x00000200
 #define  GRC_MODE_INCL_CRC             0x00000400
@@ -1292,9 +1769,14 @@ typedef unsigned long dma_addr_t;
 #define  GRC_MODE_NOIRQ_ON_SENDS       0x00002000
 #define  GRC_MODE_NOIRQ_ON_RCV         0x00004000
 #define  GRC_MODE_FORCE_PCI32BIT       0x00008000
+#define  GRC_MODE_B2HRX_ENABLE         0x00008000
 #define  GRC_MODE_HOST_STACKUP         0x00010000
 #define  GRC_MODE_HOST_SENDBDS         0x00020000
+#define  GRC_MODE_HTX2B_ENABLE         0x00040000
 #define  GRC_MODE_NO_TX_PHDR_CSUM      0x00100000
+#define  GRC_MODE_NVRAM_WR_ENABLE      0x00200000
+#define  GRC_MODE_PCIE_TL_SEL          0x00000000
+#define  GRC_MODE_PCIE_PL_SEL          0x00400000
 #define  GRC_MODE_NO_RX_PHDR_CSUM      0x00800000
 #define  GRC_MODE_IRQ_ON_TX_CPU_ATTN   0x01000000
 #define  GRC_MODE_IRQ_ON_RX_CPU_ATTN   0x02000000
@@ -1302,7 +1784,13 @@ typedef unsigned long dma_addr_t;
 #define  GRC_MODE_IRQ_ON_DMA_ATTN      0x08000000
 #define  GRC_MODE_IRQ_ON_FLOW_ATTN     0x10000000
 #define  GRC_MODE_4X_NIC_SEND_RINGS    0x20000000
+#define  GRC_MODE_PCIE_DL_SEL          0x20000000
 #define  GRC_MODE_MCAST_FRM_ENABLE     0x40000000
+#define  GRC_MODE_PCIE_HI_1K_EN                0x80000000
+#define  GRC_MODE_PCIE_PORT_MASK       (GRC_MODE_PCIE_TL_SEL | \
+                                        GRC_MODE_PCIE_PL_SEL | \
+                                        GRC_MODE_PCIE_DL_SEL | \
+                                        GRC_MODE_PCIE_HI_1K_EN)
 #define GRC_MISC_CFG                   0x00006804
 #define  GRC_MISC_CFG_CORECLK_RESET    0x00000001
 #define  GRC_MISC_CFG_PRESCALAR_MASK   0x000000fe
@@ -1319,12 +1807,19 @@ typedef unsigned long dma_addr_t;
 #define  GRC_MISC_CFG_BOARD_ID_5788    0x00010000
 #define  GRC_MISC_CFG_BOARD_ID_5788M   0x00018000
 #define  GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000
+#define  GRC_MISC_CFG_EPHY_IDDQ                0x00200000
 #define  GRC_MISC_CFG_KEEP_GPHY_POWER  0x04000000
 #define GRC_LOCAL_CTRL                 0x00006808
 #define  GRC_LCLCTRL_INT_ACTIVE                0x00000001
 #define  GRC_LCLCTRL_CLEARINT          0x00000002
 #define  GRC_LCLCTRL_SETINT            0x00000004
 #define  GRC_LCLCTRL_INT_ON_ATTN       0x00000008
+#define  GRC_LCLCTRL_GPIO_UART_SEL     0x00000010      /* 5755 only */
+#define  GRC_LCLCTRL_USE_SIG_DETECT    0x00000010      /* 5714/5780 only */
+#define  GRC_LCLCTRL_USE_EXT_SIG_DETECT        0x00000020      /* 5714/5780 only */
+#define  GRC_LCLCTRL_GPIO_INPUT3       0x00000020
+#define  GRC_LCLCTRL_GPIO_OE3          0x00000040
+#define  GRC_LCLCTRL_GPIO_OUTPUT3      0x00000080
 #define  GRC_LCLCTRL_GPIO_INPUT0       0x00000100
 #define  GRC_LCLCTRL_GPIO_INPUT1       0x00000200
 #define  GRC_LCLCTRL_GPIO_INPUT2       0x00000400
@@ -1348,6 +1843,7 @@ typedef unsigned long dma_addr_t;
 #define  GRC_LCLCTRL_AUTO_SEEPROM      0x01000000
 #define GRC_TIMER                      0x0000680c
 #define GRC_RX_CPU_EVENT               0x00006810
+#define  GRC_RX_CPU_DRIVER_EVENT       0x00004000
 #define GRC_RX_TIMER_REF               0x00006814
 #define GRC_RX_CPU_SEM                 0x00006818
 #define GRC_REMOTE_RX_CPU_ATTN         0x0000681c
@@ -1373,7 +1869,11 @@ typedef unsigned long dma_addr_t;
 #define GRC_EEPROM_CTRL                        0x00006840
 #define GRC_MDI_CTRL                   0x00006844
 #define GRC_SEEPROM_DELAY              0x00006848
-/* 0x684c --> 0x6c00 unused */
+/* 0x684c --> 0x6890 unused */
+#define GRC_VCPU_EXT_CTRL              0x00006890
+#define GRC_VCPU_EXT_CTRL_HALT_CPU      0x00400000
+#define GRC_VCPU_EXT_CTRL_DISABLE_WOL   0x20000000
+#define GRC_FASTBOOT_PC                        0x00006894      /* 5752, 5755, 5787 */
 
 /* 0x6c00 --> 0x7000 unused */
 
@@ -1387,6 +1887,8 @@ typedef unsigned long dma_addr_t;
 #define  NVRAM_CMD_ERASE                0x00000040
 #define  NVRAM_CMD_FIRST                0x00000080
 #define  NVRAM_CMD_LAST                         0x00000100
+#define  NVRAM_CMD_WREN                         0x00010000
+#define  NVRAM_CMD_WRDI                         0x00020000
 #define NVRAM_STAT                     0x00007004
 #define NVRAM_WRDATA                   0x00007008
 #define NVRAM_ADDR                     0x0000700c
@@ -1396,8 +1898,117 @@ typedef unsigned long dma_addr_t;
 #define  NVRAM_CFG1_FLASHIF_ENAB        0x00000001
 #define  NVRAM_CFG1_BUFFERED_MODE       0x00000002
 #define  NVRAM_CFG1_PASS_THRU           0x00000004
+#define  NVRAM_CFG1_STATUS_BITS                 0x00000070
 #define  NVRAM_CFG1_BIT_BANG            0x00000008
+#define  NVRAM_CFG1_FLASH_SIZE          0x02000000
 #define  NVRAM_CFG1_COMPAT_BYPASS       0x80000000
+#define  NVRAM_CFG1_VENDOR_MASK                 0x03000003
+#define  FLASH_VENDOR_ATMEL_EEPROM      0x02000000
+#define  FLASH_VENDOR_ATMEL_FLASH_BUFFERED      0x02000003
+#define  FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED    0x00000003
+#define  FLASH_VENDOR_ST                        0x03000001
+#define  FLASH_VENDOR_SAIFUN            0x01000003
+#define  FLASH_VENDOR_SST_SMALL                 0x00000001
+#define  FLASH_VENDOR_SST_LARGE                 0x02000001
+#define  NVRAM_CFG1_5752VENDOR_MASK     0x03c00003
+#define  FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ    0x00000000
+#define  FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ   0x02000000
+#define  FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED  0x02000003
+#define  FLASH_5752VENDOR_ST_M45PE10    0x02400000
+#define  FLASH_5752VENDOR_ST_M45PE20    0x02400002
+#define  FLASH_5752VENDOR_ST_M45PE40    0x02400001
+#define  FLASH_5755VENDOR_ATMEL_FLASH_1         0x03400001
+#define  FLASH_5755VENDOR_ATMEL_FLASH_2         0x03400002
+#define  FLASH_5755VENDOR_ATMEL_FLASH_3         0x03400000
+#define  FLASH_5755VENDOR_ATMEL_FLASH_4         0x00000003
+#define  FLASH_5755VENDOR_ATMEL_FLASH_5         0x02000003
+#define  FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ    0x03c00003
+#define  FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ   0x03c00002
+#define  FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ    0x03000003
+#define  FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ   0x03000002
+#define  FLASH_5787VENDOR_MICRO_EEPROM_64KHZ    0x03000000
+#define  FLASH_5787VENDOR_MICRO_EEPROM_376KHZ   0x02000000
+#define  FLASH_5761VENDOR_ATMEL_MDB021D         0x00800003
+#define  FLASH_5761VENDOR_ATMEL_MDB041D         0x00800000
+#define  FLASH_5761VENDOR_ATMEL_MDB081D         0x00800002
+#define  FLASH_5761VENDOR_ATMEL_MDB161D         0x00800001
+#define  FLASH_5761VENDOR_ATMEL_ADB021D         0x00000003
+#define  FLASH_5761VENDOR_ATMEL_ADB041D         0x00000000
+#define  FLASH_5761VENDOR_ATMEL_ADB081D         0x00000002
+#define  FLASH_5761VENDOR_ATMEL_ADB161D         0x00000001
+#define  FLASH_5761VENDOR_ST_M_M45PE20  0x02800001
+#define  FLASH_5761VENDOR_ST_M_M45PE40  0x02800000
+#define  FLASH_5761VENDOR_ST_M_M45PE80  0x02800002
+#define  FLASH_5761VENDOR_ST_M_M45PE16  0x02800003
+#define  FLASH_5761VENDOR_ST_A_M45PE20  0x02000001
+#define  FLASH_5761VENDOR_ST_A_M45PE40  0x02000000
+#define  FLASH_5761VENDOR_ST_A_M45PE80  0x02000002
+#define  FLASH_5761VENDOR_ST_A_M45PE16  0x02000003
+#define  FLASH_57780VENDOR_ATMEL_AT45DB011D 0x00400000
+#define  FLASH_57780VENDOR_ATMEL_AT45DB011B 0x03400000
+#define  FLASH_57780VENDOR_ATMEL_AT45DB021D 0x00400002
+#define  FLASH_57780VENDOR_ATMEL_AT45DB021B 0x03400002
+#define  FLASH_57780VENDOR_ATMEL_AT45DB041D 0x00400001
+#define  FLASH_57780VENDOR_ATMEL_AT45DB041B 0x03400001
+#define  FLASH_5717VENDOR_ATMEL_EEPROM  0x02000001
+#define  FLASH_5717VENDOR_MICRO_EEPROM  0x02000003
+#define  FLASH_5717VENDOR_ATMEL_MDB011D         0x01000001
+#define  FLASH_5717VENDOR_ATMEL_MDB021D         0x01000003
+#define  FLASH_5717VENDOR_ST_M_M25PE10  0x02000000
+#define  FLASH_5717VENDOR_ST_M_M25PE20  0x02000002
+#define  FLASH_5717VENDOR_ST_M_M45PE10  0x00000001
+#define  FLASH_5717VENDOR_ST_M_M45PE20  0x00000003
+#define  FLASH_5717VENDOR_ATMEL_ADB011B         0x01400000
+#define  FLASH_5717VENDOR_ATMEL_ADB021B         0x01400002
+#define  FLASH_5717VENDOR_ATMEL_ADB011D         0x01400001
+#define  FLASH_5717VENDOR_ATMEL_ADB021D         0x01400003
+#define  FLASH_5717VENDOR_ST_A_M25PE10  0x02400000
+#define  FLASH_5717VENDOR_ST_A_M25PE20  0x02400002
+#define  FLASH_5717VENDOR_ST_A_M45PE10  0x02400001
+#define  FLASH_5717VENDOR_ST_A_M45PE20  0x02400003
+#define  FLASH_5717VENDOR_ATMEL_45USPT  0x03400000
+#define  FLASH_5717VENDOR_ST_25USPT     0x03400002
+#define  FLASH_5717VENDOR_ST_45USPT     0x03400001
+#define  FLASH_5720_EEPROM_HD           0x00000001
+#define  FLASH_5720_EEPROM_LD           0x00000003
+#define  FLASH_5720VENDOR_M_ATMEL_DB011D 0x01000000
+#define  FLASH_5720VENDOR_M_ATMEL_DB021D 0x01000002
+#define  FLASH_5720VENDOR_M_ATMEL_DB041D 0x01000001
+#define  FLASH_5720VENDOR_M_ATMEL_DB081D 0x01000003
+#define  FLASH_5720VENDOR_M_ST_M25PE10  0x02000000
+#define  FLASH_5720VENDOR_M_ST_M25PE20  0x02000002
+#define  FLASH_5720VENDOR_M_ST_M25PE40  0x02000001
+#define  FLASH_5720VENDOR_M_ST_M25PE80  0x02000003
+#define  FLASH_5720VENDOR_M_ST_M45PE10  0x03000000
+#define  FLASH_5720VENDOR_M_ST_M45PE20  0x03000002
+#define  FLASH_5720VENDOR_M_ST_M45PE40  0x03000001
+#define  FLASH_5720VENDOR_M_ST_M45PE80  0x03000003
+#define  FLASH_5720VENDOR_A_ATMEL_DB011B 0x01800000
+#define  FLASH_5720VENDOR_A_ATMEL_DB021B 0x01800002
+#define  FLASH_5720VENDOR_A_ATMEL_DB041B 0x01800001
+#define  FLASH_5720VENDOR_A_ATMEL_DB011D 0x01c00000
+#define  FLASH_5720VENDOR_A_ATMEL_DB021D 0x01c00002
+#define  FLASH_5720VENDOR_A_ATMEL_DB041D 0x01c00001
+#define  FLASH_5720VENDOR_A_ATMEL_DB081D 0x01c00003
+#define  FLASH_5720VENDOR_A_ST_M25PE10  0x02800000
+#define  FLASH_5720VENDOR_A_ST_M25PE20  0x02800002
+#define  FLASH_5720VENDOR_A_ST_M25PE40  0x02800001
+#define  FLASH_5720VENDOR_A_ST_M25PE80  0x02800003
+#define  FLASH_5720VENDOR_A_ST_M45PE10  0x02c00000
+#define  FLASH_5720VENDOR_A_ST_M45PE20  0x02c00002
+#define  FLASH_5720VENDOR_A_ST_M45PE40  0x02c00001
+#define  FLASH_5720VENDOR_A_ST_M45PE80  0x02c00003
+#define  FLASH_5720VENDOR_ATMEL_45USPT  0x03c00000
+#define  FLASH_5720VENDOR_ST_25USPT     0x03c00002
+#define  FLASH_5720VENDOR_ST_45USPT     0x03c00001
+#define  NVRAM_CFG1_5752PAGE_SIZE_MASK  0x70000000
+#define  FLASH_5752PAGE_SIZE_256        0x00000000
+#define  FLASH_5752PAGE_SIZE_512        0x10000000
+#define  FLASH_5752PAGE_SIZE_1K                 0x20000000
+#define  FLASH_5752PAGE_SIZE_2K                 0x30000000
+#define  FLASH_5752PAGE_SIZE_4K                 0x40000000
+#define  FLASH_5752PAGE_SIZE_264        0x50000000
+#define  FLASH_5752PAGE_SIZE_528        0x60000000
 #define NVRAM_CFG2                     0x00007018
 #define NVRAM_CFG3                     0x0000701c
 #define NVRAM_SWARB                    0x00007020
@@ -1417,11 +2028,142 @@ typedef unsigned long dma_addr_t;
 #define  SWARB_REQ1                     0x00002000
 #define  SWARB_REQ2                     0x00004000
 #define  SWARB_REQ3                     0x00008000
-#define    NVRAM_BUFFERED_PAGE_SIZE       264
-#define    NVRAM_BUFFERED_PAGE_POS        9
-/* 0x7024 --> 0x7400 unused */
+#define NVRAM_ACCESS                   0x00007024
+#define  ACCESS_ENABLE                  0x00000001
+#define  ACCESS_WR_ENABLE               0x00000002
+#define NVRAM_WRITE1                   0x00007028
+/* 0x702c unused */
+
+#define NVRAM_ADDR_LOCKOUT             0x00007030
+/* 0x7034 --> 0x7500 unused */
+
+#define OTP_MODE                       0x00007500
+#define OTP_MODE_OTP_THRU_GRC           0x00000001
+#define OTP_CTRL                       0x00007504
+#define OTP_CTRL_OTP_PROG_ENABLE        0x00200000
+#define OTP_CTRL_OTP_CMD_READ           0x00000000
+#define OTP_CTRL_OTP_CMD_INIT           0x00000008
+#define OTP_CTRL_OTP_CMD_START          0x00000001
+#define OTP_STATUS                     0x00007508
+#define OTP_STATUS_CMD_DONE             0x00000001
+#define OTP_ADDRESS                    0x0000750c
+#define OTP_ADDRESS_MAGIC1              0x000000a0
+#define OTP_ADDRESS_MAGIC2              0x00000080
+/* 0x7510 unused */
+
+#define OTP_READ_DATA                  0x00007514
+/* 0x7518 --> 0x7c04 unused */
+
+#define PCIE_TRANSACTION_CFG           0x00007c04
+#define PCIE_TRANS_CFG_1SHOT_MSI        0x20000000
+#define PCIE_TRANS_CFG_LOM              0x00000020
+/* 0x7c08 --> 0x7d28 unused */
+
+#define PCIE_PWR_MGMT_THRESH           0x00007d28
+#define PCIE_PWR_MGMT_L1_THRESH_MSK     0x0000ff00
+#define PCIE_PWR_MGMT_L1_THRESH_4MS     0x0000ff00
+#define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN   0x01000000
+/* 0x7d2c --> 0x7d54 unused */
+
+#define TG3_PCIE_LNKCTL                        0x00007d54
+#define  TG3_PCIE_LNKCTL_L1_PLL_PD_EN   0x00000008
+#define  TG3_PCIE_LNKCTL_L1_PLL_PD_DIS  0x00000080
+/* 0x7d58 --> 0x7e70 unused */
+
+#define TG3_PCIE_PHY_TSTCTL            0x00007e2c
+#define  TG3_PCIE_PHY_TSTCTL_PCIE10     0x00000040
+#define  TG3_PCIE_PHY_TSTCTL_PSCRAM     0x00000020
+
+#define TG3_PCIE_EIDLE_DELAY           0x00007e70
+#define  TG3_PCIE_EIDLE_DELAY_MASK      0x0000001f
+#define  TG3_PCIE_EIDLE_DELAY_13_CLKS   0x0000000c
+/* 0x7e74 --> 0x8000 unused */
+
+
+/* Alternate PCIE definitions */
+#define TG3_PCIE_TLDLPL_PORT           0x00007c00
+#define TG3_PCIE_DL_LO_FTSMAX          0x0000000c
+#define TG3_PCIE_DL_LO_FTSMAX_MSK      0x000000ff
+#define TG3_PCIE_DL_LO_FTSMAX_VAL      0x0000002c
+#define TG3_PCIE_PL_LO_PHYCTL1          0x00000004
+#define TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN        0x00001000
+#define TG3_PCIE_PL_LO_PHYCTL5          0x00000014
+#define TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ      0x80000000
+
+#define TG3_REG_BLK_SIZE               0x00008000
+
+/* OTP bit definitions */
+#define TG3_OTP_AGCTGT_MASK            0x000000e0
+#define TG3_OTP_AGCTGT_SHIFT           1
+#define TG3_OTP_HPFFLTR_MASK           0x00000300
+#define TG3_OTP_HPFFLTR_SHIFT          1
+#define TG3_OTP_HPFOVER_MASK           0x00000400
+#define TG3_OTP_HPFOVER_SHIFT          1
+#define TG3_OTP_LPFDIS_MASK            0x00000800
+#define TG3_OTP_LPFDIS_SHIFT           11
+#define TG3_OTP_VDAC_MASK              0xff000000
+#define TG3_OTP_VDAC_SHIFT             24
+#define TG3_OTP_10BTAMP_MASK           0x0000f000
+#define TG3_OTP_10BTAMP_SHIFT          8
+#define TG3_OTP_ROFF_MASK              0x00e00000
+#define TG3_OTP_ROFF_SHIFT             11
+#define TG3_OTP_RCOFF_MASK             0x001c0000
+#define TG3_OTP_RCOFF_SHIFT            16
+
+#define TG3_OTP_DEFAULT                        0x286c1640
+
+
+/* Hardware Legacy NVRAM layout */
+#define TG3_NVM_VPD_OFF                        0x100
+#define TG3_NVM_VPD_LEN                        256
+
+/* Hardware Selfboot NVRAM layout */
+#define TG3_NVM_HWSB_CFG1              0x00000004
+#define  TG3_NVM_HWSB_CFG1_MAJMSK      0xf8000000
+#define  TG3_NVM_HWSB_CFG1_MAJSFT      27
+#define  TG3_NVM_HWSB_CFG1_MINMSK      0x07c00000
+#define  TG3_NVM_HWSB_CFG1_MINSFT      22
+
+#define TG3_EEPROM_MAGIC               0x669955aa
+#define TG3_EEPROM_MAGIC_FW            0xa5000000
+#define TG3_EEPROM_MAGIC_FW_MSK                0xff000000
+#define TG3_EEPROM_SB_FORMAT_MASK      0x00e00000
+#define TG3_EEPROM_SB_FORMAT_1         0x00200000
+#define TG3_EEPROM_SB_REVISION_MASK    0x001f0000
+#define TG3_EEPROM_SB_REVISION_0       0x00000000
+#define TG3_EEPROM_SB_REVISION_2       0x00020000
+#define TG3_EEPROM_SB_REVISION_3       0x00030000
+#define TG3_EEPROM_SB_REVISION_4       0x00040000
+#define TG3_EEPROM_SB_REVISION_5       0x00050000
+#define TG3_EEPROM_SB_REVISION_6       0x00060000
+#define TG3_EEPROM_MAGIC_HW            0xabcd
+#define TG3_EEPROM_MAGIC_HW_MSK                0xffff
+
+#define TG3_NVM_DIR_START              0x18
+#define TG3_NVM_DIR_END                        0x78
+#define TG3_NVM_DIRENT_SIZE            0xc
+#define TG3_NVM_DIRTYPE_SHIFT          24
+#define TG3_NVM_DIRTYPE_LENMSK         0x003fffff
+#define TG3_NVM_DIRTYPE_ASFINI         1
+#define TG3_NVM_DIRTYPE_EXTVPD         20
+#define TG3_NVM_PTREV_BCVER            0x94
+#define TG3_NVM_BCVER_MAJMSK           0x0000ff00
+#define TG3_NVM_BCVER_MAJSFT           8
+#define TG3_NVM_BCVER_MINMSK           0x000000ff
+
+#define TG3_EEPROM_SB_F1R0_EDH_OFF     0x10
+#define TG3_EEPROM_SB_F1R2_EDH_OFF     0x14
+#define TG3_EEPROM_SB_F1R2_MBA_OFF     0x10
+#define TG3_EEPROM_SB_F1R3_EDH_OFF     0x18
+#define TG3_EEPROM_SB_F1R4_EDH_OFF     0x1c
+#define TG3_EEPROM_SB_F1R5_EDH_OFF     0x20
+#define TG3_EEPROM_SB_F1R6_EDH_OFF     0x4c
+#define TG3_EEPROM_SB_EDH_MAJ_MASK     0x00000700
+#define TG3_EEPROM_SB_EDH_MAJ_SHFT     8
+#define TG3_EEPROM_SB_EDH_MIN_MASK     0x000000ff
+#define TG3_EEPROM_SB_EDH_BLD_MASK     0x0000f800
+#define TG3_EEPROM_SB_EDH_BLD_SHFT     11
 
-/* 0x7400 --> 0x8000 unused */
 
 /* 32K Window into NIC internal memory */
 #define NIC_SRAM_WIN_BASE              0x00008000
@@ -1442,11 +2184,9 @@ typedef unsigned long dma_addr_t;
 
 #define NIC_SRAM_DATA_CFG                      0x00000b58
 #define  NIC_SRAM_DATA_CFG_LED_MODE_MASK        0x0000000c
-#define  NIC_SRAM_DATA_CFG_LED_MODE_UNKNOWN     0x00000000
-#define  NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD       0x00000004
-#define  NIC_SRAM_DATA_CFG_LED_OPEN_DRAIN       0x00000004
-#define  NIC_SRAM_DATA_CFG_LED_LINK_SPD                 0x00000008
-#define  NIC_SRAM_DATA_CFG_LED_OUTPUT           0x00000008
+#define  NIC_SRAM_DATA_CFG_LED_MODE_MAC                 0x00000000
+#define  NIC_SRAM_DATA_CFG_LED_MODE_PHY_1       0x00000004
+#define  NIC_SRAM_DATA_CFG_LED_MODE_PHY_2       0x00000008
 #define  NIC_SRAM_DATA_CFG_PHY_TYPE_MASK        0x00000030
 #define  NIC_SRAM_DATA_CFG_PHY_TYPE_UNKNOWN     0x00000000
 #define  NIC_SRAM_DATA_CFG_PHY_TYPE_COPPER      0x00000010
@@ -1456,6 +2196,11 @@ typedef unsigned long dma_addr_t;
 #define  NIC_SRAM_DATA_CFG_EEPROM_WP            0x00000100
 #define  NIC_SRAM_DATA_CFG_MINI_PCI             0x00001000
 #define  NIC_SRAM_DATA_CFG_FIBER_WOL            0x00004000
+#define  NIC_SRAM_DATA_CFG_NO_GPIO2             0x00100000
+#define  NIC_SRAM_DATA_CFG_APE_ENABLE           0x00200000
+
+#define NIC_SRAM_DATA_VER                      0x00000b5c
+#define  NIC_SRAM_DATA_VER_SHIFT                16
 
 #define NIC_SRAM_DATA_PHY_ID           0x00000b74
 #define  NIC_SRAM_DATA_PHY_ID1_MASK     0xffff0000
@@ -1468,12 +2213,17 @@ typedef unsigned long dma_addr_t;
 #define  FWCMD_NICDRV_IPV6ADDR_CHG      0x00000004
 #define  FWCMD_NICDRV_FIX_DMAR          0x00000005
 #define  FWCMD_NICDRV_FIX_DMAW          0x00000006
+#define  FWCMD_NICDRV_LINK_UPDATE       0x0000000c
+#define  FWCMD_NICDRV_ALIVE2            0x0000000d
+#define  FWCMD_NICDRV_ALIVE3            0x0000000e
 #define NIC_SRAM_FW_CMD_LEN_MBOX       0x00000b7c
 #define NIC_SRAM_FW_CMD_DATA_MBOX      0x00000b80
 #define NIC_SRAM_FW_ASF_STATUS_MBOX    0x00000c00
 #define NIC_SRAM_FW_DRV_STATE_MBOX     0x00000c04
 #define  DRV_STATE_START                0x00000001
+#define  DRV_STATE_START_DONE           0x80000001
 #define  DRV_STATE_UNLOAD               0x00000002
+#define  DRV_STATE_UNLOAD_DONE          0x80000002
 #define  DRV_STATE_WOL                  0x00000003
 #define  DRV_STATE_SUSPEND              0x00000004
 
@@ -1482,6 +2232,30 @@ typedef unsigned long dma_addr_t;
 #define NIC_SRAM_MAC_ADDR_HIGH_MBOX    0x00000c14
 #define NIC_SRAM_MAC_ADDR_LOW_MBOX     0x00000c18
 
+#define NIC_SRAM_WOL_MBOX              0x00000d30
+#define  WOL_SIGNATURE                  0x474c0000
+#define  WOL_DRV_STATE_SHUTDOWN                 0x00000001
+#define  WOL_DRV_WOL                    0x00000002
+#define  WOL_SET_MAGIC_PKT              0x00000004
+
+#define NIC_SRAM_DATA_CFG_2            0x00000d38
+
+#define  NIC_SRAM_DATA_CFG_2_APD_EN     0x00000400
+#define  SHASTA_EXT_LED_MODE_MASK       0x00018000
+#define  SHASTA_EXT_LED_LEGACY          0x00000000
+#define  SHASTA_EXT_LED_SHARED          0x00008000
+#define  SHASTA_EXT_LED_MAC             0x00010000
+#define  SHASTA_EXT_LED_COMBO           0x00018000
+
+#define NIC_SRAM_DATA_CFG_3            0x00000d3c
+#define  NIC_SRAM_ASPM_DEBOUNCE                 0x00000002
+
+#define NIC_SRAM_DATA_CFG_4            0x00000d60
+#define  NIC_SRAM_GMII_MODE             0x00000002
+#define  NIC_SRAM_RGMII_INBAND_DISABLE  0x00000004
+#define  NIC_SRAM_RGMII_EXT_IBND_RX_EN  0x00000008
+#define  NIC_SRAM_RGMII_EXT_IBND_TX_EN  0x00000010
+
 #define NIC_SRAM_RX_MINI_BUFFER_DESC   0x00001000
 
 #define NIC_SRAM_DMA_DESC_POOL_BASE    0x00002000
@@ -1495,10 +2269,19 @@ typedef unsigned long dma_addr_t;
 #define  NIC_SRAM_MBUF_POOL_BASE5705   0x00010000
 #define  NIC_SRAM_MBUF_POOL_SIZE5705   0x0000e000
 
+#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5700      128
+#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5755      64
+#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5906      32
+
+#define TG3_SRAM_RX_JMB_BDCACHE_SIZE_5700      64
+#define TG3_SRAM_RX_JMB_BDCACHE_SIZE_5717      16
+
+
 /* Currently this is fixed. */
-#define PHY_ADDR               0x01
+#define TG3_PHY_MII_ADDR               0x01
+
 
-/* Tigon3 specific PHY MII registers. */
+/*** Tigon3 specific PHY MII registers. ***/
 #define  TG3_BMCR_SPEED1000            0x0040
 
 #define MII_TG3_CTRL                   0x09 /* 1000-baseT control register */
@@ -1507,20 +2290,67 @@ typedef unsigned long dma_addr_t;
 #define  MII_TG3_CTRL_AS_MASTER                0x0800
 #define  MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000
 
+#define MII_TG3_MMD_CTRL               0x0d /* MMD Access Control register */
+#define MII_TG3_MMD_CTRL_DATA_NOINC    0x4000
+#define MII_TG3_MMD_ADDRESS            0x0e /* MMD Address Data register */
+
 #define MII_TG3_EXT_CTRL               0x10 /* Extended control register */
+#define  MII_TG3_EXT_CTRL_FIFO_ELASTIC 0x0001
 #define  MII_TG3_EXT_CTRL_LNK3_LED_MODE        0x0002
+#define  MII_TG3_EXT_CTRL_FORCE_LED_OFF        0x0008
 #define  MII_TG3_EXT_CTRL_TBI          0x8000
 
 #define MII_TG3_EXT_STAT               0x11 /* Extended status register */
 #define  MII_TG3_EXT_STAT_LPASS                0x0100
 
+#define MII_TG3_RXR_COUNTERS           0x14 /* Local/Remote Receiver Counts */
 #define MII_TG3_DSP_RW_PORT            0x15 /* DSP coefficient read/write port */
-
+#define MII_TG3_DSP_CONTROL            0x16 /* DSP control register */
 #define MII_TG3_DSP_ADDRESS            0x17 /* DSP address register */
 
-#define MII_TG3_AUX_CTRL               0x18 /* auxilliary control register */
-
-#define MII_TG3_AUX_STAT               0x19 /* auxilliary status register */
+#define MII_TG3_DSP_TAP1               0x0001
+#define  MII_TG3_DSP_TAP1_AGCTGT_DFLT  0x0007
+#define MII_TG3_DSP_TAP26              0x001a
+#define  MII_TG3_DSP_TAP26_ALNOKO      0x0001
+#define  MII_TG3_DSP_TAP26_RMRXSTO     0x0002
+#define  MII_TG3_DSP_TAP26_OPCSINPT    0x0004
+#define MII_TG3_DSP_AADJ1CH0           0x001f
+#define MII_TG3_DSP_CH34TP2            0x4022
+#define MII_TG3_DSP_CH34TP2_HIBW01     0x017b
+#define MII_TG3_DSP_AADJ1CH3           0x601f
+#define  MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002
+#define MII_TG3_DSP_EXP1_INT_STAT      0x0f01
+#define MII_TG3_DSP_EXP8               0x0f08
+#define  MII_TG3_DSP_EXP8_REJ2MHz      0x0001
+#define  MII_TG3_DSP_EXP8_AEDW         0x0200
+#define MII_TG3_DSP_EXP75              0x0f75
+#define MII_TG3_DSP_EXP96              0x0f96
+#define MII_TG3_DSP_EXP97              0x0f97
+
+#define MII_TG3_AUX_CTRL               0x18 /* auxiliary control register */
+
+#define MII_TG3_AUXCTL_SHDWSEL_AUXCTL  0x0000
+#define MII_TG3_AUXCTL_ACTL_TX_6DB     0x0400
+#define MII_TG3_AUXCTL_ACTL_SMDSP_ENA  0x0800
+#define MII_TG3_AUXCTL_ACTL_EXTPKTLEN  0x4000
+
+#define MII_TG3_AUXCTL_SHDWSEL_PWRCTL  0x0002
+#define MII_TG3_AUXCTL_PCTL_WOL_EN     0x0008
+#define MII_TG3_AUXCTL_PCTL_100TX_LPWR 0x0010
+#define MII_TG3_AUXCTL_PCTL_SPR_ISOLATE        0x0020
+#define MII_TG3_AUXCTL_PCTL_CL_AB_TXDAC        0x0040
+#define MII_TG3_AUXCTL_PCTL_VREG_11V   0x0180
+
+#define MII_TG3_AUXCTL_SHDWSEL_MISCTEST        0x0004
+
+#define MII_TG3_AUXCTL_SHDWSEL_MISC    0x0007
+#define MII_TG3_AUXCTL_MISC_WIRESPD_EN 0x0010
+#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX        0x0200
+#define MII_TG3_AUXCTL_MISC_RDSEL_SHIFT        12
+#define MII_TG3_AUXCTL_MISC_WREN       0x8000
+
+
+#define MII_TG3_AUX_STAT               0x19 /* auxiliary status register */
 #define MII_TG3_AUX_STAT_LPASS         0x0004
 #define MII_TG3_AUX_STAT_SPDMASK       0x0700
 #define MII_TG3_AUX_STAT_10HALF                0x0100
@@ -1530,6 +2360,8 @@ typedef unsigned long dma_addr_t;
 #define MII_TG3_AUX_STAT_100FULL       0x0500
 #define MII_TG3_AUX_STAT_1000HALF      0x0600
 #define MII_TG3_AUX_STAT_1000FULL      0x0700
+#define MII_TG3_AUX_STAT_100           0x0008
+#define MII_TG3_AUX_STAT_FULL          0x0001
 
 #define MII_TG3_ISTAT                  0x1a /* IRQ status register */
 #define MII_TG3_IMASK                  0x1b /* IRQ mask register */
@@ -1540,13 +2372,121 @@ typedef unsigned long dma_addr_t;
 #define MII_TG3_INT_DUPLEXCHG          0x0008
 #define MII_TG3_INT_ANEG_PAGE_RX       0x0400
 
+#define MII_TG3_MISC_SHDW              0x1c
+#define MII_TG3_MISC_SHDW_WREN         0x8000
+
+#define MII_TG3_MISC_SHDW_APD_WKTM_84MS        0x0001
+#define MII_TG3_MISC_SHDW_APD_ENABLE   0x0020
+#define MII_TG3_MISC_SHDW_APD_SEL      0x2800
+
+#define MII_TG3_MISC_SHDW_SCR5_C125OE  0x0001
+#define MII_TG3_MISC_SHDW_SCR5_DLLAPD  0x0002
+#define MII_TG3_MISC_SHDW_SCR5_SDTL    0x0004
+#define MII_TG3_MISC_SHDW_SCR5_DLPTLM  0x0008
+#define MII_TG3_MISC_SHDW_SCR5_LPED    0x0010
+#define MII_TG3_MISC_SHDW_SCR5_SEL     0x1400
+
+#define MII_TG3_TEST1                  0x1e
+#define MII_TG3_TEST1_TRIM_EN          0x0010
+#define MII_TG3_TEST1_CRC_EN           0x8000
+
+/* Clause 45 expansion registers */
+#define TG3_CL45_D7_EEERES_STAT                0x803e
+#define TG3_CL45_D7_EEERES_STAT_LP_100TX       0x0002
+#define TG3_CL45_D7_EEERES_STAT_LP_1000T       0x0004
+
+
+/* Fast Ethernet Tranceiver definitions */
+#define MII_TG3_FET_PTEST              0x17
+#define  MII_TG3_FET_PTEST_FRC_TX_LINK 0x1000
+#define  MII_TG3_FET_PTEST_FRC_TX_LOCK 0x0800
+
+#define MII_TG3_FET_TEST               0x1f
+#define  MII_TG3_FET_SHADOW_EN         0x0080
+
+#define MII_TG3_FET_SHDW_MISCCTRL      0x10
+#define  MII_TG3_FET_SHDW_MISCCTRL_MDIX        0x4000
+
+#define MII_TG3_FET_SHDW_AUXMODE4      0x1a
+#define MII_TG3_FET_SHDW_AUXMODE4_SBPD 0x0008
+
+#define MII_TG3_FET_SHDW_AUXSTAT2      0x1b
+#define  MII_TG3_FET_SHDW_AUXSTAT2_APD 0x0020
+
+
+/* APE registers.  Accessible through BAR1 */
+#define TG3_APE_EVENT                  0x000c
+#define  APE_EVENT_1                    0x00000001
+#define TG3_APE_LOCK_REQ               0x002c
+#define  APE_LOCK_REQ_DRIVER            0x00001000
+#define TG3_APE_LOCK_GRANT             0x004c
+#define  APE_LOCK_GRANT_DRIVER          0x00001000
+#define TG3_APE_SEG_SIG                        0x4000
+#define  APE_SEG_SIG_MAGIC              0x41504521
+
+/* APE shared memory.  Accessible through BAR1 */
+#define TG3_APE_FW_STATUS              0x400c
+#define  APE_FW_STATUS_READY            0x00000100
+#define TG3_APE_FW_FEATURES            0x4010
+#define  TG3_APE_FW_FEATURE_NCSI        0x00000002
+#define TG3_APE_FW_VERSION             0x4018
+#define  APE_FW_VERSION_MAJMSK          0xff000000
+#define  APE_FW_VERSION_MAJSFT          24
+#define  APE_FW_VERSION_MINMSK          0x00ff0000
+#define  APE_FW_VERSION_MINSFT          16
+#define  APE_FW_VERSION_REVMSK          0x0000ff00
+#define  APE_FW_VERSION_REVSFT          8
+#define  APE_FW_VERSION_BLDMSK          0x000000ff
+#define TG3_APE_HOST_SEG_SIG           0x4200
+#define  APE_HOST_SEG_SIG_MAGIC                 0x484f5354
+#define TG3_APE_HOST_SEG_LEN           0x4204
+#define  APE_HOST_SEG_LEN_MAGIC                 0x00000020
+#define TG3_APE_HOST_INIT_COUNT                0x4208
+#define TG3_APE_HOST_DRIVER_ID         0x420c
+#define  APE_HOST_DRIVER_ID_LINUX       0xf0000000
+#define  APE_HOST_DRIVER_ID_MAGIC(maj, min)    \
+       (APE_HOST_DRIVER_ID_LINUX | (maj & 0xff) << 16 | (min & 0xff) << 8)
+#define TG3_APE_HOST_BEHAVIOR          0x4210
+#define  APE_HOST_BEHAV_NO_PHYLOCK      0x00000001
+#define TG3_APE_HOST_HEARTBEAT_INT_MS  0x4214
+#define  APE_HOST_HEARTBEAT_INT_DISABLE         0
+#define  APE_HOST_HEARTBEAT_INT_5SEC    5000
+#define TG3_APE_HOST_HEARTBEAT_COUNT   0x4218
+#define TG3_APE_HOST_DRVR_STATE                0x421c
+#define TG3_APE_HOST_DRVR_STATE_START   0x00000001
+#define TG3_APE_HOST_DRVR_STATE_UNLOAD  0x00000002
+#define TG3_APE_HOST_DRVR_STATE_WOL     0x00000003
+#define TG3_APE_HOST_WOL_SPEED         0x4224
+#define TG3_APE_HOST_WOL_SPEED_AUTO     0x00008000
+
+#define TG3_APE_EVENT_STATUS           0x4300
+
+#define  APE_EVENT_STATUS_DRIVER_EVNT   0x00000010
+#define  APE_EVENT_STATUS_STATE_CHNGE   0x00000500
+#define  APE_EVENT_STATUS_STATE_START   0x00010000
+#define  APE_EVENT_STATUS_STATE_UNLOAD  0x00020000
+#define  APE_EVENT_STATUS_STATE_WOL     0x00030000
+#define  APE_EVENT_STATUS_STATE_SUSPEND         0x00040000
+#define  APE_EVENT_STATUS_EVENT_PENDING         0x80000000
+
+#define TG3_APE_PER_LOCK_REQ           0x8400
+#define  APE_LOCK_PER_REQ_DRIVER        0x00001000
+#define TG3_APE_PER_LOCK_GRANT         0x8420
+#define  APE_PER_LOCK_GRANT_DRIVER      0x00001000
+
+/* APE convenience enumerations. */
+#define TG3_APE_LOCK_GRC                1
+#define TG3_APE_LOCK_MEM                4
+
+#define TG3_EEPROM_SB_F1R2_MBA_OFF     0x10
+
 
 /* There are two ways to manage the TX descriptors on the tigon3.
  * Either the descriptors are in host DMA'able memory, or they
  * exist only in the cards on-chip SRAM.  All 16 send bds are under
  * the same mode, they may not be configured individually.
  *
- * The mode we use is controlled by TG3_FLAG_HOST_TXDS in tp->tg3_flags.
+ * This driver always uses host memory TX descriptors.
  *
  * To use host memory TX descriptors:
  *     1) Set GRC_MODE_HOST_SENDBDS in GRC_MODE register.
@@ -1578,14 +2518,15 @@ typedef unsigned long dma_addr_t;
  * TG3_BDINFO_MAXLEN_FLAGS of all unused SEND_RCB indices.
  */
 struct tg3_tx_buffer_desc {
-       uint32_t                        addr_hi;
-       uint32_t                        addr_lo;
+       u32                             addr_hi;
+       u32                             addr_lo;
 
-       uint32_t                        len_flags;
+       u32                             len_flags;
 #define TXD_FLAG_TCPUDP_CSUM           0x0001
 #define TXD_FLAG_IP_CSUM               0x0002
 #define TXD_FLAG_END                   0x0004
 #define TXD_FLAG_IP_FRAG               0x0008
+#define TXD_FLAG_JMB_PKT               0x0008
 #define TXD_FLAG_IP_FRAG_END           0x0010
 #define TXD_FLAG_VLAN                  0x0040
 #define TXD_FLAG_COAL_NOW              0x0080
@@ -1596,7 +2537,7 @@ struct tg3_tx_buffer_desc {
 #define TXD_FLAG_NO_CRC                        0x8000
 #define TXD_LEN_SHIFT                  16
 
-       uint32_t                        vlan_tag;
+       u32                             vlan_tag;
 #define TXD_VLAN_TAG_SHIFT             0
 #define TXD_MSS_SHIFT                  16
 };
@@ -1607,16 +2548,16 @@ struct tg3_tx_buffer_desc {
 #define TXD_SIZE                       0x10UL
 
 struct tg3_rx_buffer_desc {
-       uint32_t                        addr_hi;
-       uint32_t                        addr_lo;
+       u32                             addr_hi;
+       u32                             addr_lo;
 
-       uint32_t                        idx_len;
+       u32                             idx_len;
 #define RXD_IDX_MASK   0xffff0000
 #define RXD_IDX_SHIFT  16
 #define RXD_LEN_MASK   0x0000ffff
 #define RXD_LEN_SHIFT  0
 
-       uint32_t                        type_flags;
+       u32                             type_flags;
 #define RXD_TYPE_SHIFT 16
 #define RXD_FLAGS_SHIFT        0
 
@@ -1629,13 +2570,13 @@ struct tg3_rx_buffer_desc {
 #define RXD_FLAG_TCPUDP_CSUM           0x2000
 #define RXD_FLAG_IS_TCP                        0x4000
 
-       uint32_t                        ip_tcp_csum;
+       u32                             ip_tcp_csum;
 #define RXD_IPCSUM_MASK                0xffff0000
 #define RXD_IPCSUM_SHIFT       16
 #define RXD_TCPCSUM_MASK       0x0000ffff
 #define RXD_TCPCSUM_SHIFT      0
 
-       uint32_t                        err_vlan;
+       u32                             err_vlan;
 
 #define RXD_VLAN_MASK                  0x0000ffff
 
@@ -1650,8 +2591,8 @@ struct tg3_rx_buffer_desc {
 #define RXD_ERR_HUGE_FRAME             0x01000000
 #define RXD_ERR_MASK                   0xffff0000
 
-       uint32_t                        reserved;
-       uint32_t                        opaque;
+       u32                             reserved;
+       u32                             opaque;
 #define RXD_OPAQUE_INDEX_MASK          0x0000ffff
 #define RXD_OPAQUE_INDEX_SHIFT         0
 #define RXD_OPAQUE_RING_STD            0x00010000
@@ -1662,11 +2603,11 @@ struct tg3_rx_buffer_desc {
 
 struct tg3_ext_rx_buffer_desc {
        struct {
-               uint32_t                addr_hi;
-               uint32_t                addr_lo;
+               u32                     addr_hi;
+               u32                     addr_lo;
        }                               addrlist[3];
-       uint32_t                        len2_len1;
-       uint32_t                        resv_len3;
+       u32                             len2_len1;
+       u32                             resv_len3;
        struct tg3_rx_buffer_desc       std;
 };
 
@@ -1675,68 +2616,68 @@ struct tg3_ext_rx_buffer_desc {
  * descriptors used by the chip at NIC_SRAM_DMA_DESCS.
  */
 struct tg3_internal_buffer_desc {
-       uint32_t                        addr_hi;
-       uint32_t                        addr_lo;
-       uint32_t                        nic_mbuf;
+       u32                             addr_hi;
+       u32                             addr_lo;
+       u32                             nic_mbuf;
        /* XXX FIX THIS */
 #if __BYTE_ORDER == __BIG_ENDIAN
-       uint16_t                        cqid_sqid;
-       uint16_t                        len;
+       u16                             cqid_sqid;
+       u16                             len;
 #else
-       uint16_t                        len;
-       uint16_t                        cqid_sqid;
+       u16                             len;
+       u16                             cqid_sqid;
 #endif
-       uint32_t                        flags;
-       uint32_t                        __cookie1;
-       uint32_t                        __cookie2;
-       uint32_t                        __cookie3;
+       u32                             flags;
+       u32                             __cookie1;
+       u32                             __cookie2;
+       u32                             __cookie3;
 };
 
 #define TG3_HW_STATUS_SIZE             0x50
 struct tg3_hw_status {
-       uint32_t                        status;
+       u32                             status;
 #define SD_STATUS_UPDATED              0x00000001
 #define SD_STATUS_LINK_CHG             0x00000002
 #define SD_STATUS_ERROR                        0x00000004
 
-       uint32_t                        status_tag;
+       u32                             status_tag;
 
 #if __BYTE_ORDER == __BIG_ENDIAN
-       uint16_t                        rx_consumer;
-       uint16_t                        rx_jumbo_consumer;
+       u16                             rx_consumer;
+       u16                             rx_jumbo_consumer;
 #else
-       uint16_t                        rx_jumbo_consumer;
-       uint16_t                        rx_consumer;
+       u16                             rx_jumbo_consumer;
+       u16                             rx_consumer;
 #endif
 
-#if __BYTE_ORDER ==  __BIG_ENDIAN
-       uint16_t                        reserved;
-       uint16_t                        rx_mini_consumer;
+#if __BYTE_ORDER == __BIG_ENDIAN
+       u16                             reserved;
+       u16                             rx_mini_consumer;
 #else
-       uint16_t                        rx_mini_consumer;
-       uint16_t                        reserved;
+       u16                             rx_mini_consumer;
+       u16                             reserved;
 #endif
        struct {
-#if __BYTE_ORDER ==  __BIG_ENDIAN
-               uint16_t                tx_consumer;
-               uint16_t                rx_producer;
+#if __BYTE_ORDER == __BIG_ENDIAN
+               u16                     tx_consumer;
+               u16                     rx_producer;
 #else
-               uint16_t                rx_producer;
-               uint16_t                tx_consumer;
+               u16                     rx_producer;
+               u16                     tx_consumer;
 #endif
        }                               idx[16];
 };
 
 typedef struct {
-       uint32_t high, low;
+       u32 high, low;
 } tg3_stat64_t;
 
 struct tg3_hw_stats {
-       uint8_t                         __reserved0[0x400-0x300];
+       u8                              __reserved0[0x400-0x300];
 
        /* Statistics maintained by Receive MAC. */
        tg3_stat64_t                    rx_octets;
-       uint64_t                        __reserved1;
+       u64                             __reserved1;
        tg3_stat64_t                    rx_fragments;
        tg3_stat64_t                    rx_ucast_packets;
        tg3_stat64_t                    rx_mcast_packets;
@@ -1763,11 +2704,11 @@ struct tg3_hw_stats {
        tg3_stat64_t                    rx_4096_to_8191_octet_packets;
        tg3_stat64_t                    rx_8192_to_9022_octet_packets;
 
-       uint64_t                        __unused0[37];
+       u64                             __unused0[37];
 
        /* Statistics maintained by Transmit MAC. */
        tg3_stat64_t                    tx_octets;
-       uint64_t                        __reserved2;
+       u64                             __reserved2;
        tg3_stat64_t                    tx_collisions;
        tg3_stat64_t                    tx_xon_sent;
        tg3_stat64_t                    tx_xoff_sent;
@@ -1776,7 +2717,7 @@ struct tg3_hw_stats {
        tg3_stat64_t                    tx_single_collisions;
        tg3_stat64_t                    tx_mult_collisions;
        tg3_stat64_t                    tx_deferred;
-       uint64_t                        __reserved3;
+       u64                             __reserved3;
        tg3_stat64_t                    tx_excessive_collisions;
        tg3_stat64_t                    tx_late_collisions;
        tg3_stat64_t                    tx_collide_2times;
@@ -1800,7 +2741,7 @@ struct tg3_hw_stats {
        tg3_stat64_t                    tx_discards;
        tg3_stat64_t                    tx_errors;
 
-       uint64_t                        __unused1[31];
+       u64                             __unused1[31];
 
        /* Statistics maintained by Receive List Placement. */
        tg3_stat64_t                    COS_rx_packets[16];
@@ -1812,7 +2753,7 @@ struct tg3_hw_stats {
        tg3_stat64_t                    rx_errors;
        tg3_stat64_t                    rx_threshold_hit;
 
-       uint64_t                        __unused2[9];
+       u64                             __unused2[9];
 
        /* Statistics maintained by Send Data Initiator. */
        tg3_stat64_t                    COS_out_packets[16];
@@ -1827,295 +2768,658 @@ struct tg3_hw_stats {
        tg3_stat64_t                    nic_avoided_irqs;
        tg3_stat64_t                    nic_tx_threshold_hit;
 
-       uint8_t                         __reserved4[0xb00-0x9c0];
-};
+       /* NOT a part of the hardware statistics block format.
+        * These stats are here as storage for tg3_periodic_fetch_stats().
+        */
+       tg3_stat64_t                    mbuf_lwm_thresh_hit;
 
-enum phy_led_mode {
-       led_mode_auto,
-       led_mode_three_link,
-       led_mode_link10
+       u8                              __reserved4[0xb00-0x9c8];
 };
 
-#if 0
+typedef u32 dma_addr_t;
+
 /* 'mapping' is superfluous as the chip does not write into
  * the tx/rx post rings so we could just fetch it from there.
  * But the cache behavior is better how we are doing it now.
  */
 struct ring_info {
-       struct sk_buff                  *skb;
-       DECLARE_PCI_UNMAP_ADDR(mapping)
-};
-
-struct tx_ring_info {
-       struct sk_buff                  *skb;
-       DECLARE_PCI_UNMAP_ADDR(mapping)
-       uint32_t                        prev_vlan_tag;
-};
-#endif
-
-struct tg3_config_info {
-       uint32_t                        flags;
+       struct io_buffer                        *iob;
+///    dma_addr_t mapping;
 };
 
 struct tg3_link_config {
        /* Describes what we're trying to get. */
-       uint32_t                        advertising;
-#if 0
-       uint16_t                        speed;
-       uint8_t                         duplex;
-       uint8_t                         autoneg;
+       u32                             advertising;
+       u16                             speed;
+       u8                              duplex;
+       u8                              autoneg;
+       u8                              flowctrl;
+
+       /* Describes what we actually have. */
+       u8                              active_flowctrl;
+
+       u8                              active_duplex;
 #define SPEED_INVALID          0xffff
 #define DUPLEX_INVALID         0xff
 #define AUTONEG_INVALID                0xff
-#endif
-
-       /* Describes what we actually have. */
-       uint8_t                         active_speed;
-       uint8_t                         active_duplex;
+       u16                             active_speed;
 
        /* When we go in and out of low power mode we need
         * to swap with this state.
         */
-#if 0
-       int                             phy_is_low_power;
-       uint16_t                        orig_speed;
-       uint8_t                         orig_duplex;
-       uint8_t                         orig_autoneg;
-#endif
+       u16                             orig_speed;
+       u8                              orig_duplex;
+       u8                              orig_autoneg;
+       u32                             orig_advertising;
 };
 
 struct tg3_bufmgr_config {
-       uint32_t                mbuf_read_dma_low_water;
-       uint32_t                mbuf_mac_rx_low_water;
-       uint32_t                mbuf_high_water;
+       u32             mbuf_read_dma_low_water;
+       u32             mbuf_mac_rx_low_water;
+       u32             mbuf_high_water;
 
-       uint32_t                mbuf_read_dma_low_water_jumbo;
-       uint32_t                mbuf_mac_rx_low_water_jumbo;
-       uint32_t                mbuf_high_water_jumbo;
+       u32             mbuf_read_dma_low_water_jumbo;
+       u32             mbuf_mac_rx_low_water_jumbo;
+       u32             mbuf_high_water_jumbo;
 
-       uint32_t                dma_low_water;
-       uint32_t                dma_high_water;
+       u32             dma_low_water;
+       u32             dma_high_water;
 };
 
+struct tg3_ethtool_stats {
+       /* Statistics maintained by Receive MAC. */
+       u64             rx_octets;
+       u64             rx_fragments;
+       u64             rx_ucast_packets;
+       u64             rx_mcast_packets;
+       u64             rx_bcast_packets;
+       u64             rx_fcs_errors;
+       u64             rx_align_errors;
+       u64             rx_xon_pause_rcvd;
+       u64             rx_xoff_pause_rcvd;
+       u64             rx_mac_ctrl_rcvd;
+       u64             rx_xoff_entered;
+       u64             rx_frame_too_long_errors;
+       u64             rx_jabbers;
+       u64             rx_undersize_packets;
+       u64             rx_in_length_errors;
+       u64             rx_out_length_errors;
+       u64             rx_64_or_less_octet_packets;
+       u64             rx_65_to_127_octet_packets;
+       u64             rx_128_to_255_octet_packets;
+       u64             rx_256_to_511_octet_packets;
+       u64             rx_512_to_1023_octet_packets;
+       u64             rx_1024_to_1522_octet_packets;
+       u64             rx_1523_to_2047_octet_packets;
+       u64             rx_2048_to_4095_octet_packets;
+       u64             rx_4096_to_8191_octet_packets;
+       u64             rx_8192_to_9022_octet_packets;
+
+       /* Statistics maintained by Transmit MAC. */
+       u64             tx_octets;
+       u64             tx_collisions;
+       u64             tx_xon_sent;
+       u64             tx_xoff_sent;
+       u64             tx_flow_control;
+       u64             tx_mac_errors;
+       u64             tx_single_collisions;
+       u64             tx_mult_collisions;
+       u64             tx_deferred;
+       u64             tx_excessive_collisions;
+       u64             tx_late_collisions;
+       u64             tx_collide_2times;
+       u64             tx_collide_3times;
+       u64             tx_collide_4times;
+       u64             tx_collide_5times;
+       u64             tx_collide_6times;
+       u64             tx_collide_7times;
+       u64             tx_collide_8times;
+       u64             tx_collide_9times;
+       u64             tx_collide_10times;
+       u64             tx_collide_11times;
+       u64             tx_collide_12times;
+       u64             tx_collide_13times;
+       u64             tx_collide_14times;
+       u64             tx_collide_15times;
+       u64             tx_ucast_packets;
+       u64             tx_mcast_packets;
+       u64             tx_bcast_packets;
+       u64             tx_carrier_sense_errors;
+       u64             tx_discards;
+       u64             tx_errors;
+
+       /* Statistics maintained by Receive List Placement. */
+       u64             dma_writeq_full;
+       u64             dma_write_prioq_full;
+       u64             rxbds_empty;
+       u64             rx_discards;
+       u64             rx_errors;
+       u64             rx_threshold_hit;
+
+       /* Statistics maintained by Send Data Initiator. */
+       u64             dma_readq_full;
+       u64             dma_read_prioq_full;
+       u64             tx_comp_queue_full;
+
+       /* Statistics maintained by Host Coalescing. */
+       u64             ring_set_send_prod_index;
+       u64             ring_status_update;
+       u64             nic_irqs;
+       u64             nic_avoided_irqs;
+       u64             nic_tx_threshold_hit;
+
+       u64             mbuf_lwm_thresh_hit;
+};
+
+/* number of io_buffers to allocate */
+#define TG3_DEF_RX_RING_PENDING                8
+
+struct tg3_rx_prodring_set {
+       u32                             rx_std_prod_idx;
+       u32                             rx_std_cons_idx;
+       u32                             rx_std_iob_cnt;
+       struct tg3_rx_buffer_desc       *rx_std;
+       struct io_buffer                *rx_iobufs[TG3_DEF_RX_RING_PENDING];
+       dma_addr_t                      rx_std_mapping;
+};
+
+#define TG3_IRQ_MAX_VECS_RSS           5
+#define TG3_IRQ_MAX_VECS               TG3_IRQ_MAX_VECS_RSS
+
+enum TG3_FLAGS {
+       TG3_FLAG_TAGGED_STATUS = 0,
+       TG3_FLAG_TXD_MBOX_HWBUG,
+       TG3_FLAG_USE_LINKCHG_REG,
+       TG3_FLAG_ERROR_PROCESSED,
+       TG3_FLAG_ENABLE_ASF,
+       TG3_FLAG_ASPM_WORKAROUND,
+       TG3_FLAG_POLL_SERDES,
+       TG3_FLAG_MBOX_WRITE_REORDER,
+       TG3_FLAG_PCIX_TARGET_HWBUG,
+       TG3_FLAG_WOL_SPEED_100MB,
+       TG3_FLAG_WOL_ENABLE,
+       TG3_FLAG_EEPROM_WRITE_PROT,
+       TG3_FLAG_NVRAM,
+       TG3_FLAG_NVRAM_BUFFERED,
+       TG3_FLAG_SUPPORT_MSI,
+       TG3_FLAG_SUPPORT_MSIX,
+       TG3_FLAG_PCIX_MODE,
+       TG3_FLAG_PCI_HIGH_SPEED,
+       TG3_FLAG_PCI_32BIT,
+       TG3_FLAG_SRAM_USE_CONFIG,
+       TG3_FLAG_TX_RECOVERY_PENDING,
+       TG3_FLAG_WOL_CAP,
+       TG3_FLAG_JUMBO_RING_ENABLE,
+       TG3_FLAG_PAUSE_AUTONEG,
+       TG3_FLAG_CPMU_PRESENT,
+       TG3_FLAG_BROKEN_CHECKSUMS,
+       TG3_FLAG_JUMBO_CAPABLE,
+       TG3_FLAG_CHIP_RESETTING,
+       TG3_FLAG_INIT_COMPLETE,
+       TG3_FLAG_RESTART_TIMER,
+       TG3_FLAG_TSO_BUG,
+       TG3_FLAG_IS_5788,
+       TG3_FLAG_MAX_RXPEND_64,
+       TG3_FLAG_TSO_CAPABLE,
+       TG3_FLAG_PCI_EXPRESS,
+       TG3_FLAG_ASF_NEW_HANDSHAKE,
+       TG3_FLAG_HW_AUTONEG,
+       TG3_FLAG_IS_NIC,
+       TG3_FLAG_FLASH,
+       TG3_FLAG_HW_TSO_1,
+       TG3_FLAG_5705_PLUS,
+       TG3_FLAG_5750_PLUS,
+       TG3_FLAG_HW_TSO_3,
+       TG3_FLAG_USING_MSI,
+       TG3_FLAG_USING_MSIX,
+       TG3_FLAG_ICH_WORKAROUND,
+       TG3_FLAG_5780_CLASS,
+       TG3_FLAG_HW_TSO_2,
+       TG3_FLAG_1SHOT_MSI,
+       TG3_FLAG_NO_FWARE_REPORTED,
+       TG3_FLAG_NO_NVRAM_ADDR_TRANS,
+       TG3_FLAG_ENABLE_APE,
+       TG3_FLAG_PROTECTED_NVRAM,
+       TG3_FLAG_MDIOBUS_INITED,
+       TG3_FLAG_LRG_PROD_RING_CAP,
+       TG3_FLAG_RGMII_INBAND_DISABLE,
+       TG3_FLAG_RGMII_EXT_IBND_RX_EN,
+       TG3_FLAG_RGMII_EXT_IBND_TX_EN,
+       TG3_FLAG_CLKREQ_BUG,
+       TG3_FLAG_5755_PLUS,
+       TG3_FLAG_NO_NVRAM,
+       TG3_FLAG_ENABLE_RSS,
+       TG3_FLAG_ENABLE_TSS,
+       TG3_FLAG_4G_DMA_BNDRY_BUG,
+       TG3_FLAG_USE_JUMBO_BDFLAG,
+       TG3_FLAG_L1PLLPD_EN,
+       TG3_FLAG_57765_PLUS,
+       TG3_FLAG_APE_HAS_NCSI,
+       TG3_FLAG_5717_PLUS,
+
+       /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */
+       TG3_FLAG_NUMBER_OF_FLAGS,       /* Last entry in enum TG3_FLAGS */
+};
+
+/* Following definition is copied from linux-3.0rc1/include/linux/kernel.h */
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+/* bitops.h */
+#define BITS_PER_BYTE           8
+#define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+/* types.h: */
+#define DECLARE_BITMAP(name,bits) \
+       unsigned long name[BITS_TO_LONGS(bits)]
+
 struct tg3 {
-#if 0
+       /* begin "general, frequently-used members" cacheline section */
+
+       /* If the IRQ handler (which runs lockless) needs to be
+        * quiesced, the following bitmask state is used.  The
+        * SYNC flag is set by non-IRQ context code to initiate
+        * the quiescence.
+        *
+        * When the IRQ handler notices that SYNC is set, it
+        * disables interrupts and returns.
+        *
+        * When all outstanding IRQ handlers have returned after
+        * the SYNC flag has been set, the setter can be assured
+        * that interrupts will no longer get run.
+        *
+        * In this way all SMP driver locks are never acquired
+        * in hw IRQ context, only sw IRQ context or lower.
+        */
+       unsigned int                    irq_sync;
+
        /* SMP locking strategy:
         *
-        * lock: Held during all operations except TX packet
-        *       processing.
+        * lock: Held during reset, PHY access, timer, and when
+        *       updating tg3_flags.
+        *
+        * netif_tx_lock: Held during tg3_start_xmit. tg3_tx holds
+        *                netif_tx_lock when it needs to call
+        *                netif_wake_queue.
         *
-        * tx_lock: Held during tg3_start_xmit{,_4gbug} and tg3_tx
+        * Both of these locks are to be held with BH safety.
         *
-        * If you want to shut up all asynchronous processing you must
-        * acquire both locks, 'lock' taken before 'tx_lock'.  IRQs must
-        * be disabled to take 'lock' but only softirq disabling is
-        * necessary for acquisition of 'tx_lock'.
+        * Because the IRQ handler, tg3_poll, and tg3_start_xmit
+        * are running lockless, it is necessary to completely
+        * quiesce the chip with tg3_netif_stop and tg3_full_lock
+        * before reconfiguring the device.
+        *
+        * indirect_lock: Held when accessing registers indirectly
+        *                with IRQ disabling.
         */
-       spinlock_t                      lock;
-       spinlock_t                      tx_lock;
-#endif
 
-       uint32_t                        tx_prod;
-#if 0
-       uint32_t                        tx_cons;
-#endif
-       uint32_t                        rx_rcb_ptr;
-       uint32_t                        rx_std_ptr;
-#if 0
-       uint32_t                        rx_jumbo_ptr;
-       spinlock_t                      indirect_lock;
-
-       struct net_device_stats         net_stats;
-       struct net_device_stats         net_stats_prev;
-#endif
-       unsigned long                   phy_crc_errors;
+       u32                             (*read32_mbox) (struct tg3 *, u32);
+       void                            (*write32_mbox) (struct tg3 *, u32,
+                                                        u32);
+       void                            *regs;
+       struct net_device               *dev;
+       struct pci_device               *pdev;
 
-#if 0
-       uint32_t                        rx_offset;
-#endif
-       uint32_t                        tg3_flags;
-#if 0
-#define TG3_FLAG_HOST_TXDS             0x00000001
-#endif
-#define TG3_FLAG_TXD_MBOX_HWBUG                0x00000002
-#define TG3_FLAG_RX_CHECKSUMS          0x00000004
-#define TG3_FLAG_USE_LINKCHG_REG       0x00000008
-#define TG3_FLAG_USE_MI_INTERRUPT      0x00000010
-#define TG3_FLAG_ENABLE_ASF            0x00000020
-#define TG3_FLAG_5701_REG_WRITE_BUG    0x00000040
-#define TG3_FLAG_POLL_SERDES           0x00000080
-#define TG3_FLAG_MBOX_WRITE_REORDER    0x00000100
-#define TG3_FLAG_PCIX_TARGET_HWBUG     0x00000200
-#define TG3_FLAG_WOL_SPEED_100MB       0x00000400
-#define TG3_FLAG_WOL_ENABLE            0x00000800
-#define TG3_FLAG_EEPROM_WRITE_PROT     0x00001000
-#define TG3_FLAG_NVRAM                 0x00002000
-#define TG3_FLAG_NVRAM_BUFFERED                0x00004000
-#define TG3_FLAG_RX_PAUSE              0x00008000
-#define TG3_FLAG_TX_PAUSE              0x00010000
-#define TG3_FLAG_PCIX_MODE             0x00020000
-#define TG3_FLAG_PCI_HIGH_SPEED                0x00040000
-#define TG3_FLAG_PCI_32BIT             0x00080000
-#define TG3_FLAG_NO_TX_PSEUDO_CSUM     0x00100000
-#define TG3_FLAG_NO_RX_PSEUDO_CSUM     0x00200000
-#define TG3_FLAG_SERDES_WOL_CAP                0x00400000
-#define TG3_FLAG_JUMBO_ENABLE          0x00800000
-#define TG3_FLAG_10_100_ONLY           0x01000000
-#define TG3_FLAG_PAUSE_AUTONEG         0x02000000
-#define TG3_FLAG_PAUSE_RX              0x04000000
-#define TG3_FLAG_PAUSE_TX              0x08000000
-#define TG3_FLAG_BROKEN_CHECKSUMS      0x10000000
-#define TG3_FLAG_GOT_SERDES_FLOWCTL    0x20000000
-#define TG3_FLAG_SPLIT_MODE            0x40000000
-#define TG3_FLAG_INIT_COMPLETE         0x80000000
-
-       uint32_t                        tg3_flags2;
-#define TG3_FLG2_RESTART_TIMER         0x00000001
-#define TG3_FLG2_SUN_5704              0x00000002
-#define TG3_FLG2_NO_ETH_WIRE_SPEED     0x00000004
-#define TG3_FLG2_IS_5788               0x00000008
-#define TG3_FLG2_MAX_RXPEND_64         0x00000010
-#define TG3_FLG2_TSO_CAPABLE           0x00000020
-  // Alf: Hope I'm not breaking anything here !
-#define TG3_FLG2_PCI_EXPRESS            0x00000040
-
-
-
-       uint32_t                        split_mode_max_reqs;
-#define SPLIT_MODE_5704_MAX_REQ                3
-
-#if 0
-       struct timer_list               timer;
-       uint16_t                        timer_counter;
-       uint16_t                        timer_multiplier;
-       uint32_t                        timer_offset;
-       uint16_t                        asf_counter;
-       uint16_t                        asf_multiplier;
-#endif
+       u32                             msg_enable;
 
-       struct tg3_link_config          link_config;
-       struct tg3_bufmgr_config        bufmgr_config;
+       /* begin "tx thread" cacheline section */
+       void                            (*write32_tx_mbox) (struct tg3 *, u32,
+                                                           u32);
 
-#if 0
-       uint32_t                        rx_pending;
-       uint32_t                        rx_jumbo_pending;
-       uint32_t                        tx_pending;
-#endif
+       /* begin "rx thread" cacheline section */
+       void                            (*write32_rx_mbox) (struct tg3 *, u32,
+                                                           u32);
+       u32                             rx_std_max_post;
+       u32                             rx_pkt_map_sz;
 
-       /* cache h/w values, often passed straight to h/w */
-       uint32_t                        rx_mode;
-       uint32_t                        tx_mode;
-       uint32_t                        mac_mode;
-       uint32_t                        mi_mode;
-       uint32_t                        misc_host_ctrl;
-       uint32_t                        grc_mode;
-       uint32_t                        grc_local_ctrl;
-       uint32_t                        dma_rwctrl;
-#if 0
-       uint32_t                        coalesce_mode;
-#endif
+       /* was struct tg3_napi: */
+       struct tg3_hw_status            *hw_status;
 
-       /* PCI block */
-       uint16_t                        pci_chip_rev_id;
-#if 0
-       uint8_t                         pci_cacheline_sz;
-       uint8_t                         pci_lat_timer;
-       uint8_t                         pci_hdr_type;
-       uint8_t                         pci_bist;
-#endif
-       uint32_t                        pci_cfg_state[64 / sizeof(uint32_t)];
+       u32                             last_tag;
+       u32                             last_irq_tag;
+       u32                             int_mbox;
+       /* NOTE: there was a coal_now in struct tg3_napi and struct tg3. We
+        * didn't use coal_now in struct tg3, so it was removed */
+       u32                             coal_now;
+
+       u32                             consmbox;
+       u32                             rx_rcb_ptr;
+       u16                             *rx_rcb_prod_idx;
+       struct tg3_rx_prodring_set      prodring;
+       struct tg3_rx_buffer_desc       *rx_rcb;
 
-       int                             pm_cap;
+       u32                             tx_prod;
+       u32                             tx_cons;
+       u32                             prodmbox;
+       struct tg3_tx_buffer_desc       *tx_ring;
+       struct ring_info                *tx_buffers;
 
-       /* PHY info */
-       uint32_t                        phy_id;
-#define PHY_ID_MASK                    0xfffffff0
-#define PHY_ID_BCM5400                 0x60008040
-#define PHY_ID_BCM5401                 0x60008050
-#define PHY_ID_BCM5411                 0x60008070
-#define PHY_ID_BCM5701                 0x60008110
-#define PHY_ID_BCM5703                 0x60008160
-#define PHY_ID_BCM5704                 0x60008190
-#define PHY_ID_BCM5705                 0x600081a0
-#define PHY_ID_BCM5750                 0x60008180
-#define PHY_ID_BCM5787                 0xbc050ce0
-#define PHY_ID_BCM8002                 0x60010140
-#define PHY_ID_BCM5751                 0x00206180
-#define PHY_ID_SERDES                  0xfeedbee0
-#define PHY_ID_INVALID                 0xffffffff
-#define PHY_ID_REV_MASK                        0x0000000f
-#define PHY_REV_BCM5401_B0             0x1
-#define PHY_REV_BCM5401_B2             0x3
-#define PHY_REV_BCM5401_C0             0x6
-#define PHY_REV_BCM5411_X0             0x1 /* Found on Netgear GA302T */
-
-       enum phy_led_mode               led_mode;
-
-       char                            board_part_number[24];
-       uint32_t                        nic_sram_data_cfg;
-       uint32_t                        pci_clock_ctrl;
-#if 0
-       struct pci_device               *pdev_peer;
-#endif
+       dma_addr_t                      status_mapping;
+       dma_addr_t                      rx_rcb_mapping;
+       dma_addr_t                      tx_desc_mapping;
+       /* end tg3_napi */
 
-       /* This macro assumes the passed PHY ID is already masked
-        * with PHY_ID_MASK.
-        */
-#define KNOWN_PHY_ID(X)                \
-       ((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \
-        (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
-        (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
-        (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
-        (X) == PHY_ID_BCM5751 || (X) == PHY_ID_BCM5787 || \
-        (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES)
-
-       unsigned long                   regs;
-       struct pci_device               *pdev;
-       struct nic                      *nic;
-#if 0
-       struct net_device               *dev;
-#endif
-#if TG3_VLAN_TAG_USED
-       struct vlan_group               *vlgrp;
-#endif
+       /* begin "everything else" cacheline(s) section */
+       unsigned long                   rx_dropped;
 
-       struct tg3_rx_buffer_desc       *rx_std;
-#if 0
-       struct ring_info                *rx_std_buffers;
-       dma_addr_t                      rx_std_mapping;
-       struct tg3_rx_buffer_desc       *rx_jumbo;
-       struct ring_info                *rx_jumbo_buffers;
-       dma_addr_t                      rx_jumbo_mapping;
-#endif
+       DECLARE_BITMAP(tg3_flags, TG3_FLAG_NUMBER_OF_FLAGS);
 
-       struct tg3_rx_buffer_desc       *rx_rcb;
-#if 0
-       dma_addr_t                      rx_rcb_mapping;
-#endif
+       union {
+       unsigned long                   phy_crc_errors;
+       };
 
-       /* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */
-       struct tg3_tx_buffer_desc       *tx_ring;
-#if 0
-       struct tx_ring_info             *tx_buffers;
-       dma_addr_t                      tx_desc_mapping;
-#endif
+       u16                             timer_counter;
+       u16                             timer_multiplier;
+       u32                             timer_offset;
+       u16                             asf_counter;
+       u16                             asf_multiplier;
 
-       struct tg3_hw_status            *hw_status;
-#if 0
-       dma_addr_t                      status_mapping;
-#endif
-#if 0
-       uint32_t                        msg_enable;
-#endif
+       /* 1 second counter for transient serdes link events */
+       u32                             serdes_counter;
+#define SERDES_AN_TIMEOUT_5704S                2
+#define SERDES_PARALLEL_DET_TIMEOUT    1
+#define SERDES_AN_TIMEOUT_5714S                1
 
-       struct tg3_hw_stats             *hw_stats;
-#if 0
-       dma_addr_t                      stats_mapping;
-#endif
+       struct tg3_link_config          link_config;
+       struct tg3_bufmgr_config        bufmgr_config;
+
+       /* cache h/w values, often passed straight to h/w */
+       u32                             rx_mode;
+       u32                             tx_mode;
+       u32                             mac_mode;
+       u32                             mi_mode;
+       u32                             misc_host_ctrl;
+       u32                             grc_mode;
+       u32                             grc_local_ctrl;
+       u32                             dma_rwctrl;
+       u32                             coalesce_mode;
+
+       /* PCI block */
+       u32                             pci_chip_rev_id;
+       u16                             pci_cmd;
+       u8                              pci_cacheline_sz;
+       u8                              pci_lat_timer;
 
-       int                             carrier_ok;
-       uint16_t                        subsystem_vendor;
-       uint16_t                        subsystem_device;
+       int                             pm_cap;
+       union {
+       int                             pcix_cap;
+       int                             pcie_cap;
+       };
+       int                             pcie_readrq;
+
+       u8                              phy_addr;
+
+       /* PHY info */
+       u32                             phy_id;
+#define TG3_PHY_ID_MASK                        0xfffffff0
+#define TG3_PHY_ID_BCM5400             0x60008040
+#define TG3_PHY_ID_BCM5401             0x60008050
+#define TG3_PHY_ID_BCM5411             0x60008070
+#define TG3_PHY_ID_BCM5701             0x60008110
+#define TG3_PHY_ID_BCM5703             0x60008160
+#define TG3_PHY_ID_BCM5704             0x60008190
+#define TG3_PHY_ID_BCM5705             0x600081a0
+#define TG3_PHY_ID_BCM5750             0x60008180
+#define TG3_PHY_ID_BCM5752             0x60008100
+#define TG3_PHY_ID_BCM5714             0x60008340
+#define TG3_PHY_ID_BCM5780             0x60008350
+#define TG3_PHY_ID_BCM5755             0xbc050cc0
+#define TG3_PHY_ID_BCM5787             0xbc050ce0
+#define TG3_PHY_ID_BCM5756             0xbc050ed0
+#define TG3_PHY_ID_BCM5784             0xbc050fa0
+#define TG3_PHY_ID_BCM5761             0xbc050fd0
+#define TG3_PHY_ID_BCM5718C            0x5c0d8a00
+#define TG3_PHY_ID_BCM5718S            0xbc050ff0
+#define TG3_PHY_ID_BCM57765            0x5c0d8a40
+#define TG3_PHY_ID_BCM5719C            0x5c0d8a20
+#define TG3_PHY_ID_BCM5720C            0x5c0d8b60
+#define TG3_PHY_ID_BCM5906             0xdc00ac40
+#define TG3_PHY_ID_BCM8002             0x60010140
+#define TG3_PHY_ID_INVALID             0xffffffff
+
+#define PHY_ID_RTL8211C                        0x001cc910
+#define PHY_ID_RTL8201E                        0x00008200
+
+#define TG3_PHY_ID_REV_MASK            0x0000000f
+#define TG3_PHY_REV_BCM5401_B0         0x1
+
+       /* This macro assumes the passed PHY ID is
+        * already masked with TG3_PHY_ID_MASK.
+        */
+#define TG3_KNOWN_PHY_ID(X)            \
+       ((X) == TG3_PHY_ID_BCM5400 || (X) == TG3_PHY_ID_BCM5401 || \
+        (X) == TG3_PHY_ID_BCM5411 || (X) == TG3_PHY_ID_BCM5701 || \
+        (X) == TG3_PHY_ID_BCM5703 || (X) == TG3_PHY_ID_BCM5704 || \
+        (X) == TG3_PHY_ID_BCM5705 || (X) == TG3_PHY_ID_BCM5750 || \
+        (X) == TG3_PHY_ID_BCM5752 || (X) == TG3_PHY_ID_BCM5714 || \
+        (X) == TG3_PHY_ID_BCM5780 || (X) == TG3_PHY_ID_BCM5787 || \
+        (X) == TG3_PHY_ID_BCM5755 || (X) == TG3_PHY_ID_BCM5756 || \
+        (X) == TG3_PHY_ID_BCM5906 || (X) == TG3_PHY_ID_BCM5761 || \
+        (X) == TG3_PHY_ID_BCM5718C || (X) == TG3_PHY_ID_BCM5718S || \
+        (X) == TG3_PHY_ID_BCM57765 || (X) == TG3_PHY_ID_BCM5719C || \
+        (X) == TG3_PHY_ID_BCM8002)
+
+       u32                             phy_flags;
+#define TG3_PHYFLG_IS_LOW_POWER                0x00000001
+#define TG3_PHYFLG_IS_CONNECTED                0x00000002
+#define TG3_PHYFLG_USE_MI_INTERRUPT    0x00000004
+#define TG3_PHYFLG_PHY_SERDES          0x00000010
+#define TG3_PHYFLG_MII_SERDES          0x00000020
+#define TG3_PHYFLG_ANY_SERDES          (TG3_PHYFLG_PHY_SERDES |        \
+                                       TG3_PHYFLG_MII_SERDES)
+#define TG3_PHYFLG_IS_FET              0x00000040
+#define TG3_PHYFLG_10_100_ONLY         0x00000080
+#define TG3_PHYFLG_ENABLE_APD          0x00000100
+#define TG3_PHYFLG_CAPACITIVE_COUPLING 0x00000200
+#define TG3_PHYFLG_NO_ETH_WIRE_SPEED   0x00000400
+#define TG3_PHYFLG_JITTER_BUG          0x00000800
+#define TG3_PHYFLG_ADJUST_TRIM         0x00001000
+#define TG3_PHYFLG_ADC_BUG             0x00002000
+#define TG3_PHYFLG_5704_A0_BUG         0x00004000
+#define TG3_PHYFLG_BER_BUG             0x00008000
+#define TG3_PHYFLG_SERDES_PREEMPHASIS  0x00010000
+#define TG3_PHYFLG_PARALLEL_DETECT     0x00020000
+#define TG3_PHYFLG_EEE_CAP             0x00040000
+
+       u32                             led_ctrl;
+       u32                             phy_otp;
+       u32                             setlpicnt;
+
+#define TG3_BPN_SIZE                   24
+       char                            board_part_number[TG3_BPN_SIZE];
+#define TG3_VER_SIZE                   32
+       char                            fw_ver[TG3_VER_SIZE];
+       u32                             nic_sram_data_cfg;
+       u32                             pci_clock_ctrl;
+       struct pci_device                       *pdev_peer;
+
+       int                             nvram_lock_cnt;
+       u32                             nvram_size;
+#define TG3_NVRAM_SIZE_2KB             0x00000800
+#define TG3_NVRAM_SIZE_64KB            0x00010000
+#define TG3_NVRAM_SIZE_128KB           0x00020000
+#define TG3_NVRAM_SIZE_256KB           0x00040000
+#define TG3_NVRAM_SIZE_512KB           0x00080000
+#define TG3_NVRAM_SIZE_1MB             0x00100000
+#define TG3_NVRAM_SIZE_2MB             0x00200000
+
+       u32                             nvram_pagesize;
+       u32                             nvram_jedecnum;
+
+#define JEDEC_ATMEL                    0x1f
+#define JEDEC_ST                       0x20
+#define JEDEC_SAIFUN                   0x4f
+#define JEDEC_SST                      0xbf
+
+#define ATMEL_AT24C02_CHIP_SIZE                TG3_NVRAM_SIZE_2KB
+#define ATMEL_AT24C02_PAGE_SIZE                (8)
+
+#define ATMEL_AT24C64_CHIP_SIZE                TG3_NVRAM_SIZE_64KB
+#define ATMEL_AT24C64_PAGE_SIZE                (32)
+
+#define ATMEL_AT24C512_CHIP_SIZE       TG3_NVRAM_SIZE_512KB
+#define ATMEL_AT24C512_PAGE_SIZE       (128)
+
+#define ATMEL_AT45DB0X1B_PAGE_POS      9
+#define ATMEL_AT45DB0X1B_PAGE_SIZE     264
+
+#define ATMEL_AT25F512_PAGE_SIZE       256
+
+#define ST_M45PEX0_PAGE_SIZE           256
+
+#define SAIFUN_SA25F0XX_PAGE_SIZE      256
+
+#define SST_25VF0X0_PAGE_SIZE          4098
+
+       u16                             subsystem_vendor;
+       u16                             subsystem_device;
 };
 
+#define ARRAY_SIZE(x) ( sizeof(x) / sizeof((x)[0]) )
+
+#define TG3_TX_RING_SIZE               512
+#define TG3_DEF_TX_RING_PENDING                (TG3_TX_RING_SIZE - 1)
+
+/* FIXME: look up alignment requirement in datasheet, page align for now */
+#define        TG3_DMA_ALIGNMENT       4096
+
+#define TG3_RX_STD_DMA_SZ              (1536 + 64 + 2)
+
+static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
+{
+       tp->write32_mbox(tp, off, val);
+///    if (!tg3_flag(tp, MBOX_WRITE_REORDER) && !tg3_flag(tp, ICH_WORKAROUND))
+///            tp->read32_mbox(tp, off);
+}
+
+u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off);
+void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val);
+u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off);
+void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val);
+
+#define tw32(reg, val)                 tg3_write_indirect_reg32(tp, reg, val)
+///#define tw32_mailbox(reg, val)              tg3_write_indirect_mbox(((val) & 0xffffffff), tp->regs + (reg))
+#define tw32_mailbox(reg, val)         tg3_write_indirect_mbox(tp, (reg), (val))
+#define tw32_mailbox_f(reg, val)       tw32_mailbox_flush(tp, (reg), (val))
+#define tw32_f(reg, val)               _tw32_flush(tp, (reg), (val), 0)
+#define tw32_wait_f(reg, val, us)      _tw32_flush(tp, (reg), (val), (us))
+
+#define tw32_tx_mbox(reg, val)         tp->write32_tx_mbox(tp, reg, val)
+#define tw32_rx_mbox(reg, val)         tp->write32_rx_mbox(tp, reg, val)
+
+#define tr32(reg)                      tg3_read_indirect_reg32(tp, reg)
+#define tr32_mailbox(reg)              tp->read32_mbox(tp, reg)
+
+/* Functions & macros to verify TG3_FLAGS types */
+
+static inline int variable_test_bit(int nr, volatile const unsigned long *addr)
+{
+       int oldbit;
+
+       asm volatile("bt %2,%1\n\t"
+                    "sbb %0,%0"
+                    : "=r" (oldbit)
+                    : "m" (*(unsigned long *)addr), "Ir" (nr));
+
+       return oldbit;
+}
+
+static inline int _tg3_flag(enum TG3_FLAGS flag, unsigned long *bits)
+{
+       return variable_test_bit(flag, bits);
+}
+
+#define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
+
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+       asm volatile("bts %1,%0" : BITOP_ADDR(addr) : "Ir" (nr) : "memory");
+}
+
+static inline void _tg3_flag_set(enum TG3_FLAGS flag, unsigned long *bits)
+{
+       __set_bit(flag, bits);
+}
+
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+       asm volatile("btr %1,%0" : BITOP_ADDR(addr) : "Ir" (nr));
+}
+
+static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
+{
+       __clear_bit(flag, bits);
+}
+
+#define tg3_flag(tp, flag)                             \
+       _tg3_flag(TG3_FLAG_##flag, (tp)->tg3_flags)
+#define tg3_flag_set(tp, flag)                         \
+       _tg3_flag_set(TG3_FLAG_##flag, (tp)->tg3_flags)
+#define tg3_flag_clear(tp, flag)                       \
+       _tg3_flag_clear(TG3_FLAG_##flag, (tp)->tg3_flags)
+
+/* tg3_main.c forward declarations */
+int tg3_init_rings(struct tg3 *tp);
+void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr);
+///int tg3_rx_prodring_init(struct tg3 *tp, struct tg3_rx_prodring_set *tpr);
+
+/* tg3_phy.c forward declarations */
+u32 tg3_read_otp_phycfg(struct tg3 *tp);
+void tg3_mdio_init(struct tg3 *tp);
+int tg3_phy_probe(struct tg3 *tp);
+int tg3_phy_reset(struct tg3 *tp);
+int tg3_setup_phy(struct tg3 *tp, int force_reset);
+int tg3_readphy(struct tg3 *tp, int reg, u32 *val);
+int tg3_writephy(struct tg3 *tp, int reg, u32 val);
+
+/* tg3_hw.c forward declarations */
+void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait);
+void tg3_write_mem(struct tg3 *tp, u32 off, u32 val);
+int tg3_get_invariants(struct tg3 *tp);
+void tg3_init_bufmgr_config(struct tg3 *tp);
+int tg3_get_device_address(struct tg3 *tp);
+int tg3_halt(struct tg3 *tp);
+void tg3_set_txd(struct tg3 *tp, int entry, dma_addr_t mapping, int len, u32 flags);
+void tg3_set_power_state_0(struct tg3 *tp);
+int tg3_alloc_consistent(struct tg3 *tp);
+int tg3_init_hw(struct tg3 *tp, int reset_phy);
+u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val);
+void tg3_poll_link(struct tg3 *tp);
+void tg3_wait_for_event_ack(struct tg3 *tp);
+void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1);
+void tg3_disable_ints(struct tg3 *tp);
+void tg3_enable_ints(struct tg3 *tp);
+
+static inline void tg3_generate_fw_event(struct tg3 *tp)
+{
+       u32 val;
+
+       val = tr32(GRC_RX_CPU_EVENT);
+       val |= GRC_RX_CPU_DRIVER_EVENT;
+       tw32_f(GRC_RX_CPU_EVENT, val);
+}
+
+/* linux-2.6.39, include/linux/mii.h: */
+/**
+ * mii_resolve_flowctrl_fdx
+ * @lcladv: value of MII ADVERTISE register
+ * @rmtadv: value of MII LPA register
+ *
+ * Resolve full duplex flow control as per IEEE 802.3-2005 table 28B-3
+ */
+static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
+{
+       u8 cap = 0;
+
+       if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
+               cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+       } else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
+               if (lcladv & ADVERTISE_PAUSE_CAP)
+                       cap = FLOW_CTRL_RX;
+               else if (rmtadv & ADVERTISE_PAUSE_CAP)
+                       cap = FLOW_CTRL_TX;
+       }
+
+       return cap;
+}
+
+#define ETH_FCS_LEN 4
+
 #endif /* !(_T3_H) */
diff --git a/src/drivers/net/tg3/tg3_hw.c b/src/drivers/net/tg3/tg3_hw.c
new file mode 100644 (file)
index 0000000..036c246
--- /dev/null
@@ -0,0 +1,2676 @@
+/*
+ * tg3.c: Broadcom Tigon3 ethernet driver.
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (C) 2005-2011 Broadcom Corporation.
+ *
+ * Firmware is:
+ *     Derived from proprietary unpublished source code,
+ *     Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ *     Permission is hereby granted for the distribution of this firmware
+ *     data in hexadecimal or equivalent format, provided this copyright
+ *     notice is accompanying it.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <mii.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/timer.h>
+#include <ipxe/malloc.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/netdevice.h>
+
+#include "tg3.h"
+
+#define RESET_KIND_SHUTDOWN    0
+#define RESET_KIND_INIT                1
+#define RESET_KIND_SUSPEND     2
+
+#define TG3_DEF_MAC_MODE       0
+
+void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
+{      DBGP("%s\n", __func__);
+
+       pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+       pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+}
+
+u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off)
+{      DBGP("%s\n", __func__);
+
+       u32 val;
+
+       pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+       pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+       return val;
+}
+
+static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off)
+{      DBGP("%s\n", __func__);
+
+       return readl(tp->regs + off + GRCMBOX_BASE);
+}
+
+static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val)
+{      DBGP("%s\n", __func__);
+
+       writel(val, tp->regs + off + GRCMBOX_BASE);
+}
+
+void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val)
+{      DBGP("%s\n", __func__);
+
+       if (off == (MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW)) {
+               pci_write_config_dword(tp->pdev, TG3PCI_RCV_RET_RING_CON_IDX +
+                                      TG3_64BIT_REG_LOW, val);
+               return;
+       }
+       if (off == TG3_RX_STD_PROD_IDX_REG) {
+               pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX +
+                                      TG3_64BIT_REG_LOW, val);
+               return;
+       }
+
+       pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+       pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+
+       /* In indirect mode when disabling interrupts, we also need
+        * to clear the interrupt bit in the GRC local ctrl register.
+        */
+       if ((off == (MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW)) &&
+           (val == 0x1)) {
+               pci_write_config_dword(tp->pdev, TG3PCI_MISC_LOCAL_CTRL,
+                                      tp->grc_local_ctrl|GRC_LCLCTRL_CLEARINT);
+       }
+}
+
+u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off)
+{      DBGP("%s\n", __func__);
+
+       u32 val;
+
+       pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+       pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+
+       return val;
+}
+
+/* usec_wait specifies the wait time in usec when writing to certain registers
+ * where it is unsafe to read back the register without some delay.
+ * GRC_LOCAL_CTRL is one example if the GPIOs are toggled to switch power.
+ * TG3PCI_CLOCK_CTRL is another example if the clock frequencies are changed.
+ */
+void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait)
+{      DBGP("%s\n", __func__);
+
+       tw32(off, val);
+       if (usec_wait)
+               udelay(usec_wait);
+       tr32(off);
+
+       /* Wait again after the read for the posted method to guarantee that
+        * the wait time is met.
+        */
+       if (usec_wait)
+               udelay(usec_wait);
+}
+
+/* stolen from legacy etherboot tg3 driver */
+void tg3_set_power_state_0(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       uint16_t power_control;
+       int pm = tp->pm_cap;
+
+       /* Make sure register accesses (indirect or otherwise)
+        * will function correctly.
+        */
+       pci_write_config_dword(tp->pdev,  TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
+
+       pci_read_config_word(tp->pdev, pm + PCI_PM_CTRL, &power_control);
+
+       power_control |= PCI_PM_CTRL_PME_STATUS;
+       power_control &= ~(PCI_PM_CTRL_STATE_MASK);
+       power_control |= 0;
+       pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
+
+       tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
+
+       return;
+}
+
+void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
+{      DBGP("%s\n", __func__);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
+           (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) {
+               *val = 0;
+               return;
+       }
+
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+       pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+
+       /* Always leave this as zero. */
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+}
+
+#define PCI_VENDOR_ID_ARIMA                0x161f
+
+static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 val;
+       u16 pmcsr;
+
+       /* On some early chips the SRAM cannot be accessed in D3hot state,
+        * so need make sure we're in D0.
+        */
+       pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr);
+       pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+       pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr);
+       mdelay(1);
+
+       /* Make sure register accesses (indirect or otherwise)
+        * will function correctly.
+        */
+       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                              tp->misc_host_ctrl);
+
+       /* The memory arbiter has to be enabled in order for SRAM accesses
+        * to succeed.  Normally on powerup the tg3 chip firmware will make
+        * sure it is enabled, but other entities such as system netboot
+        * code might disable it.
+        */
+       val = tr32(MEMARB_MODE);
+       tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
+       tp->phy_id = TG3_PHY_ID_INVALID;
+       tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
+       /* Assume an onboard device by default.  */
+       tg3_flag_set(tp, EEPROM_WRITE_PROT);
+
+       tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
+       if (val == NIC_SRAM_DATA_SIG_MAGIC) {
+               u32 nic_cfg, led_cfg;
+               u32 nic_phy_id, ver, cfg2 = 0, cfg4 = 0, eeprom_phy_id;
+               int eeprom_phy_serdes = 0;
+
+               tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
+               tp->nic_sram_data_cfg = nic_cfg;
+
+               tg3_read_mem(tp, NIC_SRAM_DATA_VER, &ver);
+               ver >>= NIC_SRAM_DATA_VER_SHIFT;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+                   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
+                   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703 &&
+                   (ver > 0) && (ver < 0x100))
+                       tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2);
+
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+                       tg3_read_mem(tp, NIC_SRAM_DATA_CFG_4, &cfg4);
+
+               if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
+                   NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
+                       eeprom_phy_serdes = 1;
+
+               tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
+               if (nic_phy_id != 0) {
+                       u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
+                       u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
+
+                       eeprom_phy_id  = (id1 >> 16) << 10;
+                       eeprom_phy_id |= (id2 & 0xfc00) << 16;
+                       eeprom_phy_id |= (id2 & 0x03ff) <<  0;
+               } else
+                       eeprom_phy_id = 0;
+
+               tp->phy_id = eeprom_phy_id;
+               if (eeprom_phy_serdes) {
+                       if (!tg3_flag(tp, 5705_PLUS))
+                               tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
+                       else
+                               tp->phy_flags |= TG3_PHYFLG_MII_SERDES;
+               }
+
+               if (tg3_flag(tp, 5750_PLUS))
+                       led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK |
+                                   SHASTA_EXT_LED_MODE_MASK);
+               else
+                       led_cfg = nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK;
+
+               switch (led_cfg) {
+               default:
+               case NIC_SRAM_DATA_CFG_LED_MODE_PHY_1:
+                       tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+                       break;
+
+               case NIC_SRAM_DATA_CFG_LED_MODE_PHY_2:
+                       tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+                       break;
+
+               case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
+                       tp->led_ctrl = LED_CTRL_MODE_MAC;
+
+                       /* Default to PHY_1_MODE if 0 (MAC_MODE) is
+                        * read on some older 5700/5701 bootcode.
+                        */
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+                           ASIC_REV_5700 ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) ==
+                           ASIC_REV_5701)
+                               tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
+                       break;
+
+               case SHASTA_EXT_LED_SHARED:
+                       tp->led_ctrl = LED_CTRL_MODE_SHARED;
+                       if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
+                           tp->pci_chip_rev_id != CHIPREV_ID_5750_A1)
+                               tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
+                                                LED_CTRL_MODE_PHY_2);
+                       break;
+
+               case SHASTA_EXT_LED_MAC:
+                       tp->led_ctrl = LED_CTRL_MODE_SHASTA_MAC;
+                       break;
+
+               case SHASTA_EXT_LED_COMBO:
+                       tp->led_ctrl = LED_CTRL_MODE_COMBO;
+                       if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0)
+                               tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
+                                                LED_CTRL_MODE_PHY_2);
+                       break;
+
+               }
+
+               if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) &&
+                   tp->subsystem_vendor == PCI_VENDOR_ID_DELL)
+                       tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+
+               if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX)
+                       tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
+               if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
+                       tg3_flag_set(tp, EEPROM_WRITE_PROT);
+                       if ((tp->subsystem_vendor ==
+                            PCI_VENDOR_ID_ARIMA) &&
+                           (tp->subsystem_device == 0x205a ||
+                            tp->subsystem_device == 0x2063))
+                               tg3_flag_clear(tp, EEPROM_WRITE_PROT);
+               } else {
+                       tg3_flag_clear(tp, EEPROM_WRITE_PROT);
+                       tg3_flag_set(tp, IS_NIC);
+               }
+
+               if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
+                       tg3_flag_set(tp, ENABLE_ASF);
+                       if (tg3_flag(tp, 5750_PLUS))
+                               tg3_flag_set(tp, ASF_NEW_HANDSHAKE);
+               }
+
+               if ((nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) &&
+                   tg3_flag(tp, 5750_PLUS))
+                       tg3_flag_set(tp, ENABLE_APE);
+
+               if (cfg2 & (1 << 17))
+                       tp->phy_flags |= TG3_PHYFLG_CAPACITIVE_COUPLING;
+
+               /* serdes signal pre-emphasis in register 0x590 set by */
+               /* bootcode if bit 18 is set */
+               if (cfg2 & (1 << 18))
+                       tp->phy_flags |= TG3_PHYFLG_SERDES_PREEMPHASIS;
+
+               if ((tg3_flag(tp, 57765_PLUS) ||
+                    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+                     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) &&
+                   (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN))
+                       tp->phy_flags |= TG3_PHYFLG_ENABLE_APD;
+
+               if (tg3_flag(tp, PCI_EXPRESS) &&
+                   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+                   !tg3_flag(tp, 57765_PLUS)) {
+                       u32 cfg3;
+
+                       tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3);
+               }
+
+               if (cfg4 & NIC_SRAM_RGMII_INBAND_DISABLE)
+                       tg3_flag_set(tp, RGMII_INBAND_DISABLE);
+               if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_RX_EN)
+                       tg3_flag_set(tp, RGMII_EXT_IBND_RX_EN);
+               if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN)
+                       tg3_flag_set(tp, RGMII_EXT_IBND_TX_EN);
+       }
+}
+
+static void tg3_switch_clocks(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 clock_ctrl;
+       u32 orig_clock_ctrl;
+
+       if (tg3_flag(tp, CPMU_PRESENT) || tg3_flag(tp, 5780_CLASS))
+               return;
+
+       clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
+
+       orig_clock_ctrl = clock_ctrl;
+       clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN |
+                      CLOCK_CTRL_CLKRUN_OENABLE |
+                      0x1f);
+       tp->pci_clock_ctrl = clock_ctrl;
+
+       if (tg3_flag(tp, 5705_PLUS)) {
+               if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
+                       tw32_wait_f(TG3PCI_CLOCK_CTRL,
+                                   clock_ctrl | CLOCK_CTRL_625_CORE, 40);
+               }
+       } else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
+               tw32_wait_f(TG3PCI_CLOCK_CTRL,
+                           clock_ctrl |
+                           (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK),
+                           40);
+               tw32_wait_f(TG3PCI_CLOCK_CTRL,
+                           clock_ctrl | (CLOCK_CTRL_ALTCLK),
+                           40);
+       }
+       tw32_wait_f(TG3PCI_CLOCK_CTRL, clock_ctrl, 40);
+}
+
+int tg3_get_invariants(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 misc_ctrl_reg;
+       u32 pci_state_reg, grc_misc_cfg;
+       u32 val;
+       u16 pci_cmd;
+       int err;
+
+       /* Force memory write invalidate off.  If we leave it on,
+        * then on 5700_BX chips we have to enable a workaround.
+        * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
+        * to match the cacheline size.  The Broadcom driver have this
+        * workaround but turns MWI off all the times so never uses
+        * it.  This seems to suggest that the workaround is insufficient.
+        */
+       pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+       pci_cmd &= ~PCI_COMMAND_INVALIDATE;
+       pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+
+       /* It is absolutely critical that TG3PCI_MISC_HOST_CTRL
+        * has the register indirect write enable bit set before
+        * we try to access any of the MMIO registers.  It is also
+        * critical that the PCI-X hw workaround situation is decided
+        * before that as well.
+        */
+       pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                             &misc_ctrl_reg);
+
+       tp->pci_chip_rev_id = (misc_ctrl_reg >>
+                              MISC_HOST_CTRL_CHIPREV_SHIFT);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
+               u32 prod_id_asic_rev;
+
+               if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720)
+                       pci_read_config_dword(tp->pdev,
+                                             TG3PCI_GEN2_PRODID_ASICREV,
+                                             &prod_id_asic_rev);
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 ||
+                        tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 ||
+                        tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 ||
+                        tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 ||
+                        tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
+                        tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
+                       pci_read_config_dword(tp->pdev,
+                                             TG3PCI_GEN15_PRODID_ASICREV,
+                                             &prod_id_asic_rev);
+               else
+                       pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
+                                             &prod_id_asic_rev);
+
+               tp->pci_chip_rev_id = prod_id_asic_rev;
+       }
+
+       /* Wrong chip ID in 5752 A0. This code can be removed later
+        * as A0 is not in production.
+        */
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
+               tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
+
+       /* Initialize misc host control in PCI block. */
+       tp->misc_host_ctrl |= (misc_ctrl_reg &
+                              MISC_HOST_CTRL_CHIPREV);
+       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                              tp->misc_host_ctrl);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               tg3_flag_set(tp, 5717_PLUS);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 ||
+           tg3_flag(tp, 5717_PLUS))
+               tg3_flag_set(tp, 57765_PLUS);
+
+       /* Intentionally exclude ASIC_REV_5906 */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+           tg3_flag(tp, 57765_PLUS))
+               tg3_flag_set(tp, 5755_PLUS);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
+           tg3_flag(tp, 5755_PLUS) ||
+           tg3_flag(tp, 5780_CLASS))
+               tg3_flag_set(tp, 5750_PLUS);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+           tg3_flag(tp, 5750_PLUS))
+               tg3_flag_set(tp, 5705_PLUS);
+
+       if (tg3_flag(tp, 5717_PLUS))
+               tg3_flag_set(tp, LRG_PROD_RING_CAP);
+
+       pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
+                             &pci_state_reg);
+
+       tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
+       if (tp->pcie_cap != 0) {
+               u16 lnkctl;
+
+               tg3_flag_set(tp, PCI_EXPRESS);
+
+               pci_read_config_word(tp->pdev,
+                                    tp->pcie_cap + PCI_EXP_LNKCTL,
+                                    &lnkctl);
+               if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+                           tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 ||
+                           tp->pci_chip_rev_id == CHIPREV_ID_57780_A1)
+                               tg3_flag_set(tp, CLKREQ_BUG);
+               } else if (tp->pci_chip_rev_id == CHIPREV_ID_5717_A0) {
+                       tg3_flag_set(tp, L1PLLPD_EN);
+               }
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+               tg3_flag_set(tp, PCI_EXPRESS);
+       } else if (!tg3_flag(tp, 5705_PLUS) ||
+                  tg3_flag(tp, 5780_CLASS)) {
+               tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
+               if (!tp->pcix_cap) {
+                       DBGC(&tp->pdev->dev,
+                               "Cannot find PCI-X capability, aborting\n");
+                       return -EIO;
+               }
+
+               if (!(pci_state_reg & PCISTATE_CONV_PCI_MODE))
+                       tg3_flag_set(tp, PCIX_MODE);
+       }
+
+       /* If we have an AMD 762 or VIA K8T800 chipset, write
+        * reordering to the mailbox registers done by the host
+        * controller can cause major troubles.  We read back from
+        * every mailbox register write to force the writes to be
+        * posted to the chip in order.
+        */
+
+       pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+                            &tp->pci_cacheline_sz);
+       pci_read_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+                            &tp->pci_lat_timer);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+           tp->pci_lat_timer < 64) {
+               tp->pci_lat_timer = 64;
+               pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+                                     tp->pci_lat_timer);
+       }
+
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
+               /* 5700 BX chips need to have their TX producer index
+                * mailboxes written twice to workaround a bug.
+                */
+               tg3_flag_set(tp, TXD_MBOX_HWBUG);
+
+               /* If we are in PCI-X mode, enable register write workaround.
+                *
+                * The workaround is to use indirect register accesses
+                * for all chip writes not to mailbox registers.
+                */
+               if (tg3_flag(tp, PCIX_MODE)) {
+                       u32 pm_reg;
+
+                       tg3_flag_set(tp, PCIX_TARGET_HWBUG);
+
+                       /* The chip can have it's power management PCI config
+                        * space registers clobbered due to this bug.
+                        * So explicitly force the chip into D0 here.
+                        */
+                       pci_read_config_dword(tp->pdev,
+                                             tp->pm_cap + PCI_PM_CTRL,
+                                             &pm_reg);
+                       pm_reg &= ~PCI_PM_CTRL_STATE_MASK;
+                       pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */;
+                       pci_write_config_dword(tp->pdev,
+                                              tp->pm_cap + PCI_PM_CTRL,
+                                              pm_reg);
+
+                       /* Also, force SERR#/PERR# in PCI command. */
+                       pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+                       pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+                       pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+               }
+       }
+
+       if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
+               tg3_flag_set(tp, PCI_HIGH_SPEED);
+       if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
+               tg3_flag_set(tp, PCI_32BIT);
+
+       /* Chip-specific fixup from Broadcom driver */
+       if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) &&
+           (!(pci_state_reg & PCISTATE_RETRY_SAME_DMA))) {
+               pci_state_reg |= PCISTATE_RETRY_SAME_DMA;
+               pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
+       }
+
+       tp->write32_mbox = tg3_write_indirect_reg32;
+       tp->write32_rx_mbox = tg3_write_indirect_mbox;
+       tp->write32_tx_mbox = tg3_write_indirect_mbox;
+       tp->read32_mbox = tg3_read_indirect_mbox;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               tp->read32_mbox = tg3_read32_mbox_5906;
+               tp->write32_mbox = tg3_write32_mbox_5906;
+               tp->write32_tx_mbox = tg3_write32_mbox_5906;
+               tp->write32_rx_mbox = tg3_write32_mbox_5906;
+       }
+
+       /* Get eeprom hw config before calling tg3_set_power_state().
+        * In particular, the TG3_FLAG_IS_NIC flag must be
+        * determined before calling tg3_set_power_state() so that
+        * we know whether or not to switch out of Vaux power.
+        * When the flag is set, it means that GPIO1 is used for eeprom
+        * write protect and also implies that it is a LOM where GPIOs
+        * are not used to switch power.
+        */
+       tg3_get_eeprom_hw_cfg(tp);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+           tg3_flag(tp, 57765_PLUS))
+               tg3_flag_set(tp, CPMU_PRESENT);
+
+       /* Set up tp->grc_local_ctrl before calling tg3_power_up().
+        * GPIO1 driven high will bring 5700's external PHY out of reset.
+        * It is also used as eeprom write protect on LOMs.
+        */
+       tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+           tg3_flag(tp, EEPROM_WRITE_PROT))
+               tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+                                      GRC_LCLCTRL_GPIO_OUTPUT1);
+       /* Unused GPIO3 must be driven as output on 5752 because there
+        * are no pull-up resistors on unused GPIO pins.
+        */
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+               tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+               tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+
+       if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+           tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
+               /* Turn off the debug UART. */
+               tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+               if (tg3_flag(tp, IS_NIC))
+                       /* Keep VMain power. */
+                       tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
+                                             GRC_LCLCTRL_GPIO_OUTPUT0;
+       }
+
+       /* Force the chip into D0. */
+       tg3_set_power_state_0(tp);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+               tp->phy_flags |= TG3_PHYFLG_IS_FET;
+
+       /* A few boards don't want Ethernet@WireSpeed phy feature */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+            (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
+            (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) ||
+           (tp->phy_flags & TG3_PHYFLG_IS_FET) ||
+           (tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+               tp->phy_flags |= TG3_PHYFLG_NO_ETH_WIRE_SPEED;
+
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX ||
+           GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX)
+               tp->phy_flags |= TG3_PHYFLG_ADC_BUG;
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
+               tp->phy_flags |= TG3_PHYFLG_5704_A0_BUG;
+
+       if (tg3_flag(tp, 5705_PLUS) &&
+           !(tp->phy_flags & TG3_PHYFLG_IS_FET) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 &&
+           !tg3_flag(tp, 57765_PLUS)) {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
+                       if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 &&
+                           tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722)
+                               tp->phy_flags |= TG3_PHYFLG_JITTER_BUG;
+                       if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
+                               tp->phy_flags |= TG3_PHYFLG_ADJUST_TRIM;
+               } else
+                       tp->phy_flags |= TG3_PHYFLG_BER_BUG;
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+           GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
+               tp->phy_otp = tg3_read_otp_phycfg(tp);
+               if (tp->phy_otp == 0)
+                       tp->phy_otp = TG3_OTP_DEFAULT;
+       }
+
+       if (tg3_flag(tp, CPMU_PRESENT))
+               tp->mi_mode = MAC_MI_MODE_500KHZ_CONST;
+       else
+               tp->mi_mode = MAC_MI_MODE_BASE;
+
+       tp->coalesce_mode = 0;
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
+           GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
+               tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
+
+       /* Set these bits to enable statistics workaround. */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+           tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 ||
+           tp->pci_chip_rev_id == CHIPREV_ID_5720_A0) {
+               tp->coalesce_mode |= HOSTCC_MODE_ATTN;
+               tp->grc_mode |= GRC_MODE_IRQ_ON_FLOW_ATTN;
+       }
+
+       tg3_mdio_init(tp);
+
+       /* Initialize data/descriptor byte/word swapping. */
+       val = tr32(GRC_MODE);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               val &= (GRC_MODE_BYTE_SWAP_B2HRX_DATA |
+                       GRC_MODE_WORD_SWAP_B2HRX_DATA |
+                       GRC_MODE_B2HRX_ENABLE |
+                       GRC_MODE_HTX2B_ENABLE |
+                       GRC_MODE_HOST_STACKUP);
+       else
+               val &= GRC_MODE_HOST_STACKUP;
+
+       tw32(GRC_MODE, val | tp->grc_mode);
+
+       tg3_switch_clocks(tp);
+
+       /* Clear this out for sanity. */
+       tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+
+       pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
+                             &pci_state_reg);
+       if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 &&
+           !tg3_flag(tp, PCIX_TARGET_HWBUG)) {
+               u32 chiprevid = GET_CHIP_REV_ID(tp->misc_host_ctrl);
+
+               if (chiprevid == CHIPREV_ID_5701_A0 ||
+                   chiprevid == CHIPREV_ID_5701_B0 ||
+                   chiprevid == CHIPREV_ID_5701_B2 ||
+                   chiprevid == CHIPREV_ID_5701_B5) {
+                       void *sram_base;
+
+                       /* Write some dummy words into the SRAM status block
+                        * area, see if it reads back correctly.  If the return
+                        * value is bad, force enable the PCIX workaround.
+                        */
+                       sram_base = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_STATS_BLK;
+
+                       writel(0x00000000, sram_base);
+                       writel(0x00000000, sram_base + 4);
+                       writel(0xffffffff, sram_base + 4);
+                       if (readl(sram_base) != 0x00000000)
+                               tg3_flag_set(tp, PCIX_TARGET_HWBUG);
+               }
+       }
+
+       udelay(50);
+       /* FIXME: do we need nvram access? */
+///    tg3_nvram_init(tp);
+
+       grc_misc_cfg = tr32(GRC_MISC_CFG);
+       grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+           (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
+            grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
+               tg3_flag_set(tp, IS_5788);
+
+       if (!tg3_flag(tp, IS_5788) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+               tg3_flag_set(tp, TAGGED_STATUS);
+       if (tg3_flag(tp, TAGGED_STATUS)) {
+               tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD |
+                                     HOSTCC_MODE_CLRTICK_TXBD);
+
+               tp->misc_host_ctrl |= MISC_HOST_CTRL_TAGGED_STATUS;
+               pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                                      tp->misc_host_ctrl);
+       }
+
+       /* Preserve the APE MAC_MODE bits */
+       if (tg3_flag(tp, ENABLE_APE))
+               tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+       else
+               tp->mac_mode = TG3_DEF_MAC_MODE;
+
+       /* these are limited to 10/100 only */
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+            (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+            tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
+            (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
+             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
+             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
+           (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
+            (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
+             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
+             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
+           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 ||
+           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
+           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 ||
+           (tp->phy_flags & TG3_PHYFLG_IS_FET))
+               tp->phy_flags |= TG3_PHYFLG_10_100_ONLY;
+
+       err = tg3_phy_probe(tp);
+       if (err) {
+               DBGC(&tp->pdev->dev, "phy probe failed, err: %s\n", strerror(err));
+               /* ... but do not return immediately ... */
+       }
+
+       if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+               tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT;
+       } else {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
+                       tp->phy_flags |= TG3_PHYFLG_USE_MI_INTERRUPT;
+               else
+                       tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT;
+       }
+
+       /* For all SERDES we poll the MAC status register. */
+       if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
+               tg3_flag_set(tp, POLL_SERDES);
+       else
+               tg3_flag_clear(tp, POLL_SERDES);
+
+       /* Increment the rx prod index on the rx std ring by at most
+        * 8 for these chips to workaround hw errata.
+        */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+               tp->rx_std_max_post = 8;
+
+       return err;
+}
+
+void tg3_init_bufmgr_config(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       if (tg3_flag(tp, 57765_PLUS)) {
+               tp->bufmgr_config.mbuf_read_dma_low_water =
+                       DEFAULT_MB_RDMA_LOW_WATER_5705;
+               tp->bufmgr_config.mbuf_mac_rx_low_water =
+                       DEFAULT_MB_MACRX_LOW_WATER_57765;
+               tp->bufmgr_config.mbuf_high_water =
+                       DEFAULT_MB_HIGH_WATER_57765;
+
+               tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
+                       DEFAULT_MB_RDMA_LOW_WATER_5705;
+               tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
+                       DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765;
+               tp->bufmgr_config.mbuf_high_water_jumbo =
+                       DEFAULT_MB_HIGH_WATER_JUMBO_57765;
+       } else if (tg3_flag(tp, 5705_PLUS)) {
+               tp->bufmgr_config.mbuf_read_dma_low_water =
+                       DEFAULT_MB_RDMA_LOW_WATER_5705;
+               tp->bufmgr_config.mbuf_mac_rx_low_water =
+                       DEFAULT_MB_MACRX_LOW_WATER_5705;
+               tp->bufmgr_config.mbuf_high_water =
+                       DEFAULT_MB_HIGH_WATER_5705;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+                       tp->bufmgr_config.mbuf_mac_rx_low_water =
+                               DEFAULT_MB_MACRX_LOW_WATER_5906;
+                       tp->bufmgr_config.mbuf_high_water =
+                               DEFAULT_MB_HIGH_WATER_5906;
+               }
+
+               tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
+                       DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780;
+               tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
+                       DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780;
+               tp->bufmgr_config.mbuf_high_water_jumbo =
+                       DEFAULT_MB_HIGH_WATER_JUMBO_5780;
+       } else {
+               tp->bufmgr_config.mbuf_read_dma_low_water =
+                       DEFAULT_MB_RDMA_LOW_WATER;
+               tp->bufmgr_config.mbuf_mac_rx_low_water =
+                       DEFAULT_MB_MACRX_LOW_WATER;
+               tp->bufmgr_config.mbuf_high_water =
+                       DEFAULT_MB_HIGH_WATER;
+
+               tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
+                       DEFAULT_MB_RDMA_LOW_WATER_JUMBO;
+               tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
+                       DEFAULT_MB_MACRX_LOW_WATER_JUMBO;
+               tp->bufmgr_config.mbuf_high_water_jumbo =
+                       DEFAULT_MB_HIGH_WATER_JUMBO;
+       }
+
+       tp->bufmgr_config.dma_low_water = DEFAULT_DMA_LOW_WATER;
+       tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER;
+}
+
+#define TG3_FW_EVENT_TIMEOUT_USEC 2500
+
+void tg3_wait_for_event_ack(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int i;
+
+       for (i = 0; i < TG3_FW_EVENT_TIMEOUT_USEC / 10; i++) {
+               if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
+                       break;
+
+               udelay(10);
+       }
+}
+
+void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
+{      DBGP("%s\n", __func__);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
+           (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC))
+               return;
+
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+
+       /* Always leave this as zero. */
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+}
+
+static void tg3_stop_fw(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       if (tg3_flag(tp, ENABLE_ASF) && !tg3_flag(tp, ENABLE_APE)) {
+               /* Wait for RX cpu to ACK the previous event. */
+               tg3_wait_for_event_ack(tp);
+
+               tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
+
+               tg3_generate_fw_event(tp);
+
+               /* Wait for RX cpu to ACK this event. */
+               tg3_wait_for_event_ack(tp);
+       }
+}
+
+static void tg3_write_sig_pre_reset(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+                     NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
+}
+
+void tg3_disable_ints(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       tw32(TG3PCI_MISC_HOST_CTRL,
+            (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
+
+       tw32_mailbox_f(tp->int_mbox, 0x00000001);
+}
+
+void tg3_enable_ints(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       tw32(TG3PCI_MISC_HOST_CTRL,
+            (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
+
+       tp->coal_now = tp->coalesce_mode | HOSTCC_MODE_ENABLE;
+
+       tw32_mailbox_f(tp->int_mbox, tp->last_tag << 24);
+
+       /* Force an initial interrupt */
+       if (!tg3_flag(tp, TAGGED_STATUS) &&
+           (tp->hw_status->status & SD_STATUS_UPDATED))
+               tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+       else
+               tw32(HOSTCC_MODE, tp->coal_now);
+}
+
+#define MAX_WAIT_CNT 1000
+
+/* To stop a block, clear the enable bit and poll till it clears. */
+static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit)
+{      DBGP("%s\n", __func__);
+
+       unsigned int i;
+       u32 val;
+
+       if (tg3_flag(tp, 5705_PLUS)) {
+               switch (ofs) {
+               case RCVLSC_MODE:
+               case DMAC_MODE:
+               case MBFREE_MODE:
+               case BUFMGR_MODE:
+               case MEMARB_MODE:
+                       /* We can't enable/disable these bits of the
+                        * 5705/5750, just say success.
+                        */
+                       return 0;
+
+               default:
+                       break;
+               }
+       }
+
+       val = tr32(ofs);
+       val &= ~enable_bit;
+       tw32_f(ofs, val);
+
+       for (i = 0; i < MAX_WAIT_CNT; i++) {
+               udelay(100);
+               val = tr32(ofs);
+               if ((val & enable_bit) == 0)
+                       break;
+       }
+
+       if (i == MAX_WAIT_CNT) {
+               DBGC(&tp->pdev->dev,
+                       "tg3_stop_block timed out, ofs=%lx enable_bit=%x\n",
+                       ofs, enable_bit);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int tg3_abort_hw(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int i, err;
+
+       tg3_disable_ints(tp);
+
+       tp->rx_mode &= ~RX_MODE_ENABLE;
+       tw32_f(MAC_RX_MODE, tp->rx_mode);
+       udelay(10);
+
+       err  = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
+       err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE);
+       err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE);
+       err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE);
+       err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE);
+       err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE);
+
+       err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE);
+       err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE);
+       err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
+       err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE);
+       err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+       err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE);
+       err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE);
+
+       tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
+       tw32_f(MAC_MODE, tp->mac_mode);
+       udelay(40);
+
+       tp->tx_mode &= ~TX_MODE_ENABLE;
+       tw32_f(MAC_TX_MODE, tp->tx_mode);
+
+       for (i = 0; i < MAX_WAIT_CNT; i++) {
+               udelay(100);
+               if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE))
+                       break;
+       }
+       if (i >= MAX_WAIT_CNT) {
+               DBGC(&tp->pdev->dev,
+                       "%s timed out, TX_MODE_ENABLE will not clear "
+                       "MAC_TX_MODE=%08x\n", __func__, tr32(MAC_TX_MODE));
+               err |= -ENODEV;
+       }
+
+       err |= tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE);
+       err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE);
+       err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE);
+
+       tw32(FTQ_RESET, 0xffffffff);
+       tw32(FTQ_RESET, 0x00000000);
+
+       err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE);
+       err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE);
+
+       if (tp->hw_status)
+               memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+       return err;
+}
+
+void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
+{      DBGP("%s\n", __func__);
+
+       u32 addr_high, addr_low;
+       int i;
+
+       addr_high = ((tp->dev->ll_addr[0] << 8) |
+                    tp->dev->ll_addr[1]);
+       addr_low = ((tp->dev->ll_addr[2] << 24) |
+                   (tp->dev->ll_addr[3] << 16) |
+                   (tp->dev->ll_addr[4] <<  8) |
+                   (tp->dev->ll_addr[5] <<  0));
+       for (i = 0; i < 4; i++) {
+               if (i == 1 && skip_mac_1)
+                       continue;
+               tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
+               tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+               for (i = 0; i < 12; i++) {
+                       tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
+                       tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
+               }
+       }
+
+       addr_high = (tp->dev->ll_addr[0] +
+                    tp->dev->ll_addr[1] +
+                    tp->dev->ll_addr[2] +
+                    tp->dev->ll_addr[3] +
+                    tp->dev->ll_addr[4] +
+                    tp->dev->ll_addr[5]) &
+               TX_BACKOFF_SEED_MASK;
+       tw32(MAC_TX_BACKOFF_SEED, addr_high);
+}
+
+/* Save PCI command register before chip reset */
+static void tg3_save_pci_state(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
+}
+
+/* Restore PCI state after chip reset */
+static void tg3_restore_pci_state(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 val;
+
+       /* Re-enable indirect register accesses. */
+       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                              tp->misc_host_ctrl);
+
+       /* Set MAX PCI retry to zero. */
+       val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+           tg3_flag(tp, PCIX_MODE))
+               val |= PCISTATE_RETRY_SAME_DMA;
+
+       pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
+
+       pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
+                       pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+                                             tp->pci_cacheline_sz);
+                       pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+                                             tp->pci_lat_timer);
+       }
+
+
+       /* Make sure PCI-X relaxed ordering bit is clear. */
+       if (tg3_flag(tp, PCIX_MODE)) {
+               u16 pcix_cmd;
+
+               pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+                                    &pcix_cmd);
+               pcix_cmd &= ~PCI_X_CMD_ERO;
+               pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+                                     pcix_cmd);
+       }
+}
+
+static int tg3_poll_fw(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int i;
+       u32 val;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               /* Wait up to 20ms for init done. */
+               for (i = 0; i < 200; i++) {
+                       if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
+                               return 0;
+                       udelay(100);
+               }
+               return -ENODEV;
+       }
+
+       /* Wait for firmware initialization to complete. */
+       for (i = 0; i < 100000; i++) {
+               tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+               if (val == (u32)~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+                       break;
+               udelay(10);
+       }
+
+       /* Chip might not be fitted with firmware.  Some Sun onboard
+        * parts are configured like that.  So don't signal the timeout
+        * of the above loop as an error, but do report the lack of
+        * running firmware once.
+        */
+       if (i >= 100000 && !tg3_flag(tp, NO_FWARE_REPORTED)) {
+               tg3_flag_set(tp, NO_FWARE_REPORTED);
+
+               DBGC(tp->dev, "No firmware running\n");
+       }
+
+       if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
+               /* The 57765 A0 needs a little more
+                * time to do some important work.
+                */
+               mdelay(10);
+       }
+
+       return 0;
+}
+
+static int tg3_nvram_lock(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       if (tg3_flag(tp, NVRAM)) {
+               int i;
+
+               if (tp->nvram_lock_cnt == 0) {
+                       tw32(NVRAM_SWARB, SWARB_REQ_SET1);
+                       for (i = 0; i < 8000; i++) {
+                               if (tr32(NVRAM_SWARB) & SWARB_GNT1)
+                                       break;
+                               udelay(20);
+                       }
+                       if (i == 8000) {
+                               tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
+                               return -ENODEV;
+                       }
+               }
+               tp->nvram_lock_cnt++;
+       }
+       return 0;
+}
+
+static void tg3_nvram_unlock(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       if (tg3_flag(tp, NVRAM)) {
+               if (tp->nvram_lock_cnt > 0)
+                       tp->nvram_lock_cnt--;
+               if (tp->nvram_lock_cnt == 0)
+                       tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+       }
+}
+
+static int tg3_chip_reset(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 val;
+       int err;
+
+       tg3_nvram_lock(tp);
+
+
+       /* No matching tg3_nvram_unlock() after this because
+        * chip reset below will undo the nvram lock.
+        */
+       tp->nvram_lock_cnt = 0;
+
+       /* GRC_MISC_CFG core clock reset will clear the memory
+        * enable bit in PCI register 4 and the MSI enable bit
+        * on some chips, so we save relevant registers here.
+        */
+       tg3_save_pci_state(tp);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+           tg3_flag(tp, 5755_PLUS))
+               tw32(GRC_FASTBOOT_PC, 0);
+
+#if 0
+       /*
+        * We must avoid the readl() that normally takes place.
+        * It locks machines, causes machine checks, and other
+        * fun things.  So, temporarily disable the 5701
+        * hardware workaround, while we do the reset.
+        */
+       write_op = tp->write32;
+       if (write_op == tg3_write_flush_reg32)
+               tp->write32 = tg3_write32;
+#endif
+
+       /* Prevent the irq handler from reading or writing PCI registers
+        * during chip reset when the memory enable bit in the PCI command
+        * register may be cleared.  The chip does not generate interrupt
+        * at this time, but the irq handler may still be called due to irq
+        * sharing or irqpoll.
+        */
+       tg3_flag_set(tp, CHIP_RESETTING);
+
+       if (tp->hw_status) {
+               tp->hw_status->status = 0;
+               tp->hw_status->status_tag = 0;
+       }
+       tp->last_tag = 0;
+       tp->last_irq_tag = 0;
+
+       mb();
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+               val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
+               tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS);
+       }
+
+       /* do the reset */
+       val = GRC_MISC_CFG_CORECLK_RESET;
+
+       if (tg3_flag(tp, PCI_EXPRESS)) {
+               /* Force PCIe 1.0a mode */
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+                   !tg3_flag(tp, 57765_PLUS) &&
+                   tr32(TG3_PCIE_PHY_TSTCTL) ==
+                   (TG3_PCIE_PHY_TSTCTL_PCIE10 | TG3_PCIE_PHY_TSTCTL_PSCRAM))
+                       tw32(TG3_PCIE_PHY_TSTCTL, TG3_PCIE_PHY_TSTCTL_PSCRAM);
+
+               if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
+                       tw32(GRC_MISC_CFG, (1 << 29));
+                       val |= (1 << 29);
+               }
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               tw32(VCPU_STATUS, tr32(VCPU_STATUS) | VCPU_STATUS_DRV_RESET);
+               tw32(GRC_VCPU_EXT_CTRL,
+                    tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU);
+       }
+
+       /* Manage gphy power for all CPMU absent PCIe devices. */
+       if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, CPMU_PRESENT))
+               val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
+
+       tw32(GRC_MISC_CFG, val);
+
+       /* Unfortunately, we have to delay before the PCI read back.
+        * Some 575X chips even will not respond to a PCI cfg access
+        * when the reset command is given to the chip.
+        *
+        * How do these hardware designers expect things to work
+        * properly if the PCI write is posted for a long period
+        * of time?  It is always necessary to have some method by
+        * which a register read back can occur to push the write
+        * out which does the reset.
+        *
+        * For most tg3 variants the trick below was working.
+        * Ho hum...
+        */
+       udelay(120);
+
+       /* Flush PCI posted writes.  The normal MMIO registers
+        * are inaccessible at this time so this is the only
+        * way to make this reliably (actually, this is no longer
+        * the case, see above).  I tried to use indirect
+        * register read/write but this upset some 5701 variants.
+        */
+       pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
+
+       udelay(120);
+
+       if (tg3_flag(tp, PCI_EXPRESS) && tp->pcie_cap) {
+               u16 val16;
+
+               if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
+                       int i;
+                       u32 cfg_val;
+
+                       /* Wait for link training to complete.  */
+                       for (i = 0; i < 5000; i++)
+                               udelay(100);
+
+                       pci_read_config_dword(tp->pdev, 0xc4, &cfg_val);
+                       pci_write_config_dword(tp->pdev, 0xc4,
+                                              cfg_val | (1 << 15));
+               }
+
+               /* Clear the "no snoop" and "relaxed ordering" bits. */
+               pci_read_config_word(tp->pdev,
+                                    tp->pcie_cap + PCI_EXP_DEVCTL,
+                                    &val16);
+               val16 &= ~(PCI_EXP_DEVCTL_RELAX_EN |
+                          PCI_EXP_DEVCTL_NOSNOOP_EN);
+               /*
+                * Older PCIe devices only support the 128 byte
+                * MPS setting.  Enforce the restriction.
+                */
+               if (!tg3_flag(tp, CPMU_PRESENT))
+                       val16 &= ~PCI_EXP_DEVCTL_PAYLOAD;
+               pci_write_config_word(tp->pdev,
+                                     tp->pcie_cap + PCI_EXP_DEVCTL,
+                                     val16);
+
+               /* Clear error status */
+               pci_write_config_word(tp->pdev,
+                                     tp->pcie_cap + PCI_EXP_DEVSTA,
+                                     PCI_EXP_DEVSTA_CED |
+                                     PCI_EXP_DEVSTA_NFED |
+                                     PCI_EXP_DEVSTA_FED |
+                                     PCI_EXP_DEVSTA_URD);
+       }
+
+       tg3_restore_pci_state(tp);
+
+       tg3_flag_clear(tp, CHIP_RESETTING);
+       tg3_flag_clear(tp, ERROR_PROCESSED);
+
+       val = 0;
+       if (tg3_flag(tp, 5780_CLASS))
+               val = tr32(MEMARB_MODE);
+       tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
+               tg3_stop_fw(tp);
+               tw32(0x5000, 0x400);
+       }
+
+       tw32(GRC_MODE, tp->grc_mode);
+
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
+               val = tr32(0xc4);
+
+               tw32(0xc4, val | (1 << 15));
+       }
+
+       if ((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+               tp->pci_clock_ctrl |= CLOCK_CTRL_CLKRUN_OENABLE;
+               if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0)
+                       tp->pci_clock_ctrl |= CLOCK_CTRL_FORCE_CLKRUN;
+               tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+       }
+
+       if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+               tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+               val = tp->mac_mode;
+       } else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
+               tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+               val = tp->mac_mode;
+       } else
+               val = 0;
+
+       tw32_f(MAC_MODE, val);
+       udelay(40);
+
+       err = tg3_poll_fw(tp);
+       if (err)
+               return err;
+
+       if (tg3_flag(tp, PCI_EXPRESS) &&
+           tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+           !tg3_flag(tp, 57765_PLUS)) {
+               val = tr32(0x7c00);
+
+               tw32(0x7c00, val | (1 << 25));
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+               val = tr32(TG3_CPMU_CLCK_ORIDE);
+               tw32(TG3_CPMU_CLCK_ORIDE, val & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN);
+       }
+
+       return 0;
+}
+
+int tg3_halt(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int err;
+
+       tg3_stop_fw(tp);
+
+       tg3_write_sig_pre_reset(tp);
+
+       tg3_abort_hw(tp);
+       err = tg3_chip_reset(tp);
+
+       __tg3_set_mac_addr(tp, 0);
+
+       if (err)
+               return err;
+
+       return 0;
+}
+
+static int tg3_nvram_read_using_eeprom(struct tg3 *tp,
+                                       u32 offset, u32 *val)
+{      DBGP("%s\n", __func__);
+
+       u32 tmp;
+       int i;
+
+       if (offset > EEPROM_ADDR_ADDR_MASK || (offset % 4) != 0)
+               return -EINVAL;
+
+       tmp = tr32(GRC_EEPROM_ADDR) & ~(EEPROM_ADDR_ADDR_MASK |
+                                       EEPROM_ADDR_DEVID_MASK |
+                                       EEPROM_ADDR_READ);
+       tw32(GRC_EEPROM_ADDR,
+            tmp |
+            (0 << EEPROM_ADDR_DEVID_SHIFT) |
+            ((offset << EEPROM_ADDR_ADDR_SHIFT) &
+             EEPROM_ADDR_ADDR_MASK) |
+            EEPROM_ADDR_READ | EEPROM_ADDR_START);
+
+       for (i = 0; i < 1000; i++) {
+               tmp = tr32(GRC_EEPROM_ADDR);
+
+               if (tmp & EEPROM_ADDR_COMPLETE)
+                       break;
+               mdelay(1);
+       }
+       if (!(tmp & EEPROM_ADDR_COMPLETE))
+               return -EBUSY;
+
+       tmp = tr32(GRC_EEPROM_DATA);
+
+       /*
+        * The data will always be opposite the native endian
+        * format.  Perform a blind byteswap to compensate.
+        */
+       *val = bswap_32(tmp);
+
+       return 0;
+}
+
+static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr)
+{      DBGP("%s\n", __func__);
+
+       if (tg3_flag(tp, NVRAM) &&
+           tg3_flag(tp, NVRAM_BUFFERED) &&
+           tg3_flag(tp, FLASH) &&
+           !tg3_flag(tp, NO_NVRAM_ADDR_TRANS) &&
+           (tp->nvram_jedecnum == JEDEC_ATMEL))
+
+               addr = ((addr / tp->nvram_pagesize) <<
+                       ATMEL_AT45DB0X1B_PAGE_POS) +
+                      (addr % tp->nvram_pagesize);
+
+       return addr;
+}
+
+static void tg3_enable_nvram_access(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) {
+               u32 nvaccess = tr32(NVRAM_ACCESS);
+
+               tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
+       }
+}
+
+static void tg3_disable_nvram_access(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) {
+               u32 nvaccess = tr32(NVRAM_ACCESS);
+
+               tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
+       }
+}
+
+#define NVRAM_CMD_TIMEOUT 10000
+
+static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd)
+{      DBGP("%s\n", __func__);
+
+       int i;
+
+       tw32(NVRAM_CMD, nvram_cmd);
+       for (i = 0; i < NVRAM_CMD_TIMEOUT; i++) {
+               udelay(10);
+               if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) {
+                       udelay(10);
+                       break;
+               }
+       }
+
+       if (i == NVRAM_CMD_TIMEOUT)
+               return -EBUSY;
+
+       return 0;
+}
+
+/* NOTE: Data read in from NVRAM is byteswapped according to
+ * the byteswapping settings for all other register accesses.
+ * tg3 devices are BE devices, so on a BE machine, the data
+ * returned will be exactly as it is seen in NVRAM.  On a LE
+ * machine, the 32-bit value will be byteswapped.
+ */
+static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
+{      DBGP("%s\n", __func__);
+
+       int ret;
+
+       if (!tg3_flag(tp, NVRAM))
+               return tg3_nvram_read_using_eeprom(tp, offset, val);
+
+       offset = tg3_nvram_phys_addr(tp, offset);
+
+       if (offset > NVRAM_ADDR_MSK)
+               return -EINVAL;
+
+       ret = tg3_nvram_lock(tp);
+       if (ret)
+               return ret;
+
+       tg3_enable_nvram_access(tp);
+
+       tw32(NVRAM_ADDR, offset);
+       ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_RD | NVRAM_CMD_GO |
+               NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
+
+       if (ret == 0)
+               *val = tr32(NVRAM_RDDATA);
+
+       tg3_disable_nvram_access(tp);
+
+       tg3_nvram_unlock(tp);
+
+       return ret;
+}
+
+/* Ensures NVRAM data is in bytestream format. */
+static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, u32 *val)
+{      DBGP("%s\n", __func__);
+
+       u32 v = 0;
+       int res = tg3_nvram_read(tp, offset, &v);
+       if (!res)
+               *val = cpu_to_be32(v);
+       return res;
+}
+
+int tg3_get_device_address(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       struct net_device *dev = tp->dev;
+       u32 hi, lo, mac_offset;
+       int addr_ok = 0;
+
+       mac_offset = 0x7c;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+           tg3_flag(tp, 5780_CLASS)) {
+               if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
+                       mac_offset = 0xcc;
+               if (tg3_nvram_lock(tp))
+                       tw32_f(NVRAM_CMD, NVRAM_CMD_RESET);
+               else
+                       tg3_nvram_unlock(tp);
+       } else if (tg3_flag(tp, 5717_PLUS)) {
+               if (PCI_FUNC(tp->pdev->busdevfn) & 1)
+                       mac_offset = 0xcc;
+               if (PCI_FUNC(tp->pdev->busdevfn) > 1)
+                       mac_offset += 0x18c;
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+               mac_offset = 0x10;
+
+       /* First try to get it from MAC address mailbox. */
+       tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
+       if ((hi >> 16) == 0x484b) {
+               dev->hw_addr[0] = (hi >>  8) & 0xff;
+               dev->hw_addr[1] = (hi >>  0) & 0xff;
+
+               tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_LOW_MBOX, &lo);
+               dev->hw_addr[2] = (lo >> 24) & 0xff;
+               dev->hw_addr[3] = (lo >> 16) & 0xff;
+               dev->hw_addr[4] = (lo >>  8) & 0xff;
+               dev->hw_addr[5] = (lo >>  0) & 0xff;
+
+               /* Some old bootcode may report a 0 MAC address in SRAM */
+               addr_ok = is_valid_ether_addr(&dev->hw_addr[0]);
+       }
+       if (!addr_ok) {
+               /* Next, try NVRAM. */
+               if (!tg3_flag(tp, NO_NVRAM) &&
+                   !tg3_nvram_read_be32(tp, mac_offset + 0, &hi) &&
+                   !tg3_nvram_read_be32(tp, mac_offset + 4, &lo)) {
+                       memcpy(&dev->hw_addr[0], ((char *)&hi) + 2, 2);
+                       memcpy(&dev->hw_addr[2], (char *)&lo, sizeof(lo));
+               }
+               /* Finally just fetch it out of the MAC control regs. */
+               else {
+                       hi = tr32(MAC_ADDR_0_HIGH);
+                       lo = tr32(MAC_ADDR_0_LOW);
+
+                       dev->hw_addr[5] = lo & 0xff;
+                       dev->hw_addr[4] = (lo >> 8) & 0xff;
+                       dev->hw_addr[3] = (lo >> 16) & 0xff;
+                       dev->hw_addr[2] = (lo >> 24) & 0xff;
+                       dev->hw_addr[1] = hi & 0xff;
+                       dev->hw_addr[0] = (hi >> 8) & 0xff;
+               }
+       }
+
+       if (!is_valid_ether_addr(&dev->hw_addr[0])) {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void __tg3_set_rx_mode(struct net_device *dev)
+{      DBGP("%s\n", __func__);
+
+       struct tg3 *tp = netdev_priv(dev);
+       u32 rx_mode;
+
+       rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
+                                 RX_MODE_KEEP_VLAN_TAG);
+
+       rx_mode |= RX_MODE_KEEP_VLAN_TAG;
+
+       /* Accept all multicast. */
+       tw32(MAC_HASH_REG_0, 0xffffffff);
+       tw32(MAC_HASH_REG_1, 0xffffffff);
+       tw32(MAC_HASH_REG_2, 0xffffffff);
+       tw32(MAC_HASH_REG_3, 0xffffffff);
+
+       if (rx_mode != tp->rx_mode) {
+               tp->rx_mode = rx_mode;
+               tw32_f(MAC_RX_MODE, rx_mode);
+               udelay(10);
+       }
+}
+
+static void __tg3_set_coalesce(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+
+       tw32(HOSTCC_RXCOL_TICKS, 0);
+       tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
+       tw32(HOSTCC_RXMAX_FRAMES, 1);
+       /* FIXME: mix between TXMAX and RXMAX taken from legacy driver */
+       tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
+       tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
+       tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
+
+       if (!tg3_flag(tp, 5705_PLUS)) {
+               u32 val = DEFAULT_STAT_COAL_TICKS;
+
+               tw32(HOSTCC_RXCOAL_TICK_INT, DEFAULT_RXCOAL_TICK_INT);
+               tw32(HOSTCC_TXCOAL_TICK_INT, DEFAULT_TXCOAL_TICK_INT);
+
+               if (!netdev_link_ok(tp->dev))
+                       val = 0;
+
+               tw32(HOSTCC_STAT_COAL_TICKS, val);
+       }
+}
+
+static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
+                          dma_addr_t mapping, u32 maxlen_flags,
+                          u32 nic_addr)
+{      DBGP("%s\n", __func__);
+
+       tg3_write_mem(tp,
+                     (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH),
+                     ((u64) mapping >> 32));
+       tg3_write_mem(tp,
+                     (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW),
+                     ((u64) mapping & 0xffffffff));
+       tg3_write_mem(tp,
+                     (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS),
+                      maxlen_flags);
+
+       if (!tg3_flag(tp, 5705_PLUS))
+               tg3_write_mem(tp,
+                             (bdinfo_addr + TG3_BDINFO_NIC_ADDR),
+                             nic_addr);
+}
+
+static void tg3_rings_reset(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int i;
+       u32 stblk, txrcb, rxrcb, limit;
+
+       /* Disable all transmit rings but the first. */
+       if (!tg3_flag(tp, 5705_PLUS))
+               limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16;
+       else if (tg3_flag(tp, 5717_PLUS))
+               limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4;
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+               limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2;
+       else
+               limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+
+       for (txrcb = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+            txrcb < limit; txrcb += TG3_BDINFO_SIZE)
+               tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS,
+                             BDINFO_FLAGS_DISABLED);
+
+
+       /* Disable all receive return rings but the first. */
+       if (tg3_flag(tp, 5717_PLUS))
+               limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17;
+       else if (!tg3_flag(tp, 5705_PLUS))
+               limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16;
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+                GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+               limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4;
+       else
+               limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+
+       for (rxrcb = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+            rxrcb < limit; rxrcb += TG3_BDINFO_SIZE)
+               tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS,
+                             BDINFO_FLAGS_DISABLED);
+
+       /* Disable interrupts */
+       tw32_mailbox_f(tp->int_mbox, 1);
+
+       tp->tx_prod = 0;
+       tp->tx_cons = 0;
+       tw32_mailbox(tp->prodmbox, 0);
+       tw32_rx_mbox(tp->consmbox, 0);
+
+       /* Make sure the NIC-based send BD rings are disabled. */
+       if (!tg3_flag(tp, 5705_PLUS)) {
+               u32 mbox = MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+               for (i = 0; i < 16; i++)
+                       tw32_tx_mbox(mbox + i * 8, 0);
+       }
+
+       txrcb = NIC_SRAM_SEND_RCB;
+       rxrcb = NIC_SRAM_RCV_RET_RCB;
+
+       /* Clear status block in ram. */
+       memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+       /* Set status block DMA address */
+       tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
+            ((u64) tp->status_mapping >> 32));
+       tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
+            ((u64) tp->status_mapping & 0xffffffff));
+
+       if (tp->tx_ring) {
+               tg3_set_bdinfo(tp, txrcb, tp->tx_desc_mapping,
+                              (TG3_TX_RING_SIZE <<
+                               BDINFO_FLAGS_MAXLEN_SHIFT),
+                              NIC_SRAM_TX_BUFFER_DESC);
+               txrcb += TG3_BDINFO_SIZE;
+       }
+
+       /* FIXME: will TG3_RX_RET_MAX_SIZE_5705 work on all cards? */
+       if (tp->rx_rcb) {
+               tg3_set_bdinfo(tp, rxrcb, tp->rx_rcb_mapping,
+                               TG3_RX_RET_MAX_SIZE_5705 <<
+                               BDINFO_FLAGS_MAXLEN_SHIFT, 0);
+               rxrcb += TG3_BDINFO_SIZE;
+       }
+
+       stblk = HOSTCC_STATBLCK_RING1;
+}
+
+static void tg3_setup_rxbd_thresholds(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 val, bdcache_maxcnt;
+
+       if (!tg3_flag(tp, 5750_PLUS) ||
+           tg3_flag(tp, 5780_CLASS) ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+               bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5700;
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+                GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+               bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5755;
+       else
+               bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5906;
+
+
+       /* NOTE: legacy driver uses RX_PENDING / 8, we only use 4 descriptors
+        * for now, use / 4 so the result is > 0
+        */
+       val = TG3_DEF_RX_RING_PENDING / 4;
+       tw32(RCVBDI_STD_THRESH, val);
+
+       if (tg3_flag(tp, 57765_PLUS))
+               tw32(STD_REPLENISH_LWM, bdcache_maxcnt);
+}
+
+static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
+{      DBGP("%s\n", __func__);
+
+       u32 val, rdmac_mode;
+       int i, err, limit;
+       struct tg3_rx_prodring_set *tpr = &tp->prodring;
+
+       tg3_stop_fw(tp);
+
+       tg3_write_sig_pre_reset(tp);
+
+       if (tg3_flag(tp, INIT_COMPLETE))
+               tg3_abort_hw(tp);
+
+       if (reset_phy)
+               tg3_phy_reset(tp);
+
+       err = tg3_chip_reset(tp);
+       if (err)
+               return err;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+               val = tr32(PCIE_PWR_MGMT_THRESH) & ~PCIE_PWR_MGMT_L1_THRESH_MSK;
+               val |= PCIE_PWR_MGMT_EXT_ASPM_TMR_EN |
+                      PCIE_PWR_MGMT_L1_THRESH_4MS;
+               tw32(PCIE_PWR_MGMT_THRESH, val);
+
+               val = tr32(TG3_PCIE_EIDLE_DELAY) & ~TG3_PCIE_EIDLE_DELAY_MASK;
+               tw32(TG3_PCIE_EIDLE_DELAY, val | TG3_PCIE_EIDLE_DELAY_13_CLKS);
+
+               tw32(TG3_CORR_ERR_STAT, TG3_CORR_ERR_STAT_CLEAR);
+
+               val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
+               tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS);
+       }
+
+       if (tg3_flag(tp, L1PLLPD_EN)) {
+               u32 grc_mode = tr32(GRC_MODE);
+
+               /* Access the lower 1K of PL PCIE block registers. */
+               val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+               tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL);
+
+               val = tr32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1);
+               tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1,
+                    val | TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN);
+
+               tw32(GRC_MODE, grc_mode);
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) {
+               if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
+                       u32 grc_mode = tr32(GRC_MODE);
+
+                       /* Access the lower 1K of PL PCIE block registers. */
+                       val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+                       tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL);
+
+                       val = tr32(TG3_PCIE_TLDLPL_PORT +
+                                  TG3_PCIE_PL_LO_PHYCTL5);
+                       tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL5,
+                            val | TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ);
+
+                       tw32(GRC_MODE, grc_mode);
+               }
+
+               if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_57765_AX) {
+                       u32 grc_mode = tr32(GRC_MODE);
+
+                       /* Access the lower 1K of DL PCIE block registers. */
+                       val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+                       tw32(GRC_MODE, val | GRC_MODE_PCIE_DL_SEL);
+
+                       val = tr32(TG3_PCIE_TLDLPL_PORT +
+                                  TG3_PCIE_DL_LO_FTSMAX);
+                       val &= ~TG3_PCIE_DL_LO_FTSMAX_MSK;
+                       tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_DL_LO_FTSMAX,
+                            val | TG3_PCIE_DL_LO_FTSMAX_VAL);
+
+                       tw32(GRC_MODE, grc_mode);
+               }
+
+               val = tr32(TG3_CPMU_LSPD_10MB_CLK);
+               val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
+               val |= CPMU_LSPD_10MB_MACCLK_6_25;
+               tw32(TG3_CPMU_LSPD_10MB_CLK, val);
+       }
+
+       /* This works around an issue with Athlon chipsets on
+        * B3 tigon3 silicon.  This bit has no effect on any
+        * other revision.  But do not set this on PCI Express
+        * chips and don't even touch the clocks if the CPMU is present.
+        */
+       if (!tg3_flag(tp, CPMU_PRESENT)) {
+               if (!tg3_flag(tp, PCI_EXPRESS))
+                       tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
+               tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+       }
+
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+           tg3_flag(tp, PCIX_MODE)) {
+               val = tr32(TG3PCI_PCISTATE);
+               val |= PCISTATE_RETRY_SAME_DMA;
+               tw32(TG3PCI_PCISTATE, val);
+       }
+
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) {
+               /* Enable some hw fixes.  */
+               val = tr32(TG3PCI_MSI_DATA);
+               val |= (1 << 26) | (1 << 28) | (1 << 29);
+               tw32(TG3PCI_MSI_DATA, val);
+       }
+
+       /* Descriptor ring init may make accesses to the
+        * NIC SRAM area to setup the TX descriptors, so we
+        * can only do this after the hardware has been
+        * successfully reset.
+        */
+       err = tg3_init_rings(tp);
+       if (err)
+               return err;
+
+       if (tg3_flag(tp, 57765_PLUS)) {
+               val = tr32(TG3PCI_DMA_RW_CTRL) &
+                     ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT;
+               if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0)
+                       val &= ~DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765 &&
+                   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717)
+                       val |= DMA_RWCTRL_TAGGED_STAT_WA;
+               tw32(TG3PCI_DMA_RW_CTRL, val | tp->dma_rwctrl);
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
+                  GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) {
+               /* This value is determined during the probe time DMA
+                * engine test, tg3_test_dma.
+                */
+               tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+       }
+
+       tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS |
+                         GRC_MODE_4X_NIC_SEND_RINGS |
+                         GRC_MODE_NO_TX_PHDR_CSUM |
+                         GRC_MODE_NO_RX_PHDR_CSUM);
+       tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
+       tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
+
+       /* Pseudo-header checksum is done by hardware logic and not
+        * the offload processers, so make the chip do the pseudo-
+        * header checksums on receive.  For transmit it is more
+        * convenient to do the pseudo-header checksum in software
+        * as Linux does that on transmit for us in all cases.
+        */
+       tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
+
+       tw32(GRC_MODE,
+            tp->grc_mode |
+            (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
+
+       /* Setup the timer prescalar register.  Clock is always 66Mhz. */
+       val = tr32(GRC_MISC_CFG);
+       val &= ~0xff;
+       val |= (65 << GRC_MISC_CFG_PRESCALAR_SHIFT);
+       tw32(GRC_MISC_CFG, val);
+
+       /* Initialize MBUF/DESC pool. */
+       if (tg3_flag(tp, 5750_PLUS)) {
+               /* Do nothing.  */
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+               tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+                       tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64);
+               else
+                       tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96);
+               tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE);
+               tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE);
+       }
+
+       tw32(BUFMGR_MB_RDMA_LOW_WATER,
+            tp->bufmgr_config.mbuf_read_dma_low_water);
+       tw32(BUFMGR_MB_MACRX_LOW_WATER,
+            tp->bufmgr_config.mbuf_mac_rx_low_water);
+       tw32(BUFMGR_MB_HIGH_WATER,
+            tp->bufmgr_config.mbuf_high_water);
+
+       tw32(BUFMGR_DMA_LOW_WATER,
+            tp->bufmgr_config.dma_low_water);
+       tw32(BUFMGR_DMA_HIGH_WATER,
+            tp->bufmgr_config.dma_high_water);
+
+       val = BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+               val |= BUFMGR_MODE_NO_TX_UNDERRUN;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+           tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 ||
+           tp->pci_chip_rev_id == CHIPREV_ID_5720_A0)
+               val |= BUFMGR_MODE_MBLOW_ATTN_ENAB;
+       tw32(BUFMGR_MODE, val);
+       for (i = 0; i < 2000; i++) {
+               if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
+                       break;
+               udelay(10);
+       }
+       if (i >= 2000) {
+               DBGC(tp->dev, "%s cannot enable BUFMGR\n", __func__);
+               return -ENODEV;
+       }
+
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1)
+               tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2);
+
+       tg3_setup_rxbd_thresholds(tp);
+
+       /* Initialize TG3_BDINFO's at:
+        *  RCVDBDI_STD_BD:     standard eth size rx ring
+        *  RCVDBDI_JUMBO_BD:   jumbo frame rx ring
+        *  RCVDBDI_MINI_BD:    small frame rx ring (??? does not work)
+        *
+        * like so:
+        *  TG3_BDINFO_HOST_ADDR:       high/low parts of DMA address of ring
+        *  TG3_BDINFO_MAXLEN_FLAGS:    (rx max buffer size << 16) |
+        *                              ring attribute flags
+        *  TG3_BDINFO_NIC_ADDR:        location of descriptors in nic SRAM
+        *
+        * Standard receive ring @ NIC_SRAM_RX_BUFFER_DESC, 512 entries.
+        * Jumbo receive ring @ NIC_SRAM_RX_JUMBO_BUFFER_DESC, 256 entries.
+        *
+        * The size of each ring is fixed in the firmware, but the location is
+        * configurable.
+        */
+       tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH,
+            ((u64) tpr->rx_std_mapping >> 32));
+       tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
+            ((u64) tpr->rx_std_mapping & 0xffffffff));
+       if (!tg3_flag(tp, 5717_PLUS))
+               tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR,
+                    NIC_SRAM_RX_BUFFER_DESC);
+
+       /* Disable the mini ring */
+       if (!tg3_flag(tp, 5705_PLUS))
+               tw32(RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS,
+                    BDINFO_FLAGS_DISABLED);
+
+       val = TG3_RX_STD_MAX_SIZE_5700 << BDINFO_FLAGS_MAXLEN_SHIFT;
+
+       tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val);
+
+       tpr->rx_std_prod_idx = TG3_DEF_RX_RING_PENDING;
+
+       /* std prod index is updated by tg3_refill_prod_ring() */
+       tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, 0);
+       tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, 0);
+
+       tg3_rings_reset(tp);
+
+#define        TG3_MAX_MTU     1522
+       /* MTU + ethernet header + FCS + optional VLAN tag */
+       tw32(MAC_RX_MTU_SIZE, TG3_MAX_MTU);
+
+       /* The slot time is changed by tg3_setup_phy if we
+        * run at gigabit with half duplex.
+        */
+       val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+             (6 << TX_LENGTHS_IPG_SHIFT) |
+             (32 << TX_LENGTHS_SLOT_TIME_SHIFT);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               val |= tr32(MAC_TX_LENGTHS) &
+                      (TX_LENGTHS_JMB_FRM_LEN_MSK |
+                       TX_LENGTHS_CNT_DWN_VAL_MSK);
+
+       tw32(MAC_TX_LENGTHS, val);
+
+       /* Receive rules. */
+       tw32(MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS);
+       tw32(RCVLPC_CONFIG, 0x0181);
+
+       /* Calculate RDMAC_MODE setting early, we need it to determine
+        * the RCVLPC_STATE_ENABLE mask.
+        */
+       rdmac_mode = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB |
+                     RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB |
+                     RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
+                     RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
+                     RDMAC_MODE_LNGREAD_ENAB);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+               rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+               rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB |
+                             RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
+                             RDMAC_MODE_MBUF_SBD_CRPT_ENAB;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+           tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
+               if (tg3_flag(tp, TSO_CAPABLE) &&
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+                       rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
+               } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
+                          !tg3_flag(tp, IS_5788)) {
+                       rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
+               }
+       }
+
+       if (tg3_flag(tp, PCI_EXPRESS))
+               rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               rdmac_mode |= tr32(RDMAC_MODE) & RDMAC_MODE_H2BNC_VLAN_DET;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+           tg3_flag(tp, 57765_PLUS)) {
+               val = tr32(TG3_RDMA_RSRVCTRL_REG);
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+                       val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK |
+                                TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK |
+                                TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK);
+                       val |= TG3_RDMA_RSRVCTRL_TXMRGN_320B |
+                              TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K |
+                              TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K;
+               }
+               tw32(TG3_RDMA_RSRVCTRL_REG,
+                    val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+               val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
+               tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val |
+                    TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K |
+                    TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K);
+       }
+
+       /* Receive/send statistics. */
+       if (tg3_flag(tp, 5750_PLUS)) {
+               val = tr32(RCVLPC_STATS_ENABLE);
+               val &= ~RCVLPC_STATSENAB_DACK_FIX;
+               tw32(RCVLPC_STATS_ENABLE, val);
+       } else if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) &&
+                  tg3_flag(tp, TSO_CAPABLE)) {
+               val = tr32(RCVLPC_STATS_ENABLE);
+               val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX;
+               tw32(RCVLPC_STATS_ENABLE, val);
+       } else {
+               tw32(RCVLPC_STATS_ENABLE, 0xffffff);
+       }
+       tw32(RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE);
+       tw32(SNDDATAI_STATSENAB, 0xffffff);
+       tw32(SNDDATAI_STATSCTRL,
+            (SNDDATAI_SCTRL_ENABLE |
+             SNDDATAI_SCTRL_FASTUPD));
+
+       /* Setup host coalescing engine. */
+       tw32(HOSTCC_MODE, 0);
+       for (i = 0; i < 2000; i++) {
+               if (!(tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE))
+                       break;
+               udelay(10);
+       }
+
+       __tg3_set_coalesce(tp);
+
+       if (!tg3_flag(tp, 5705_PLUS)) {
+               /* Status/statistics block address.  See tg3_timer,
+                * the tg3_periodic_fetch_stats call there, and
+                * tg3_get_stats to see how this works for 5705/5750 chips.
+                * NOTE: stats block removed for iPXE
+                */
+               tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK);
+
+               /* Clear statistics and status block memory areas */
+               for (i = NIC_SRAM_STATS_BLK;
+                    i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
+                    i += sizeof(u32)) {
+                       tg3_write_mem(tp, i, 0);
+                       udelay(40);
+               }
+       }
+
+       tw32(HOSTCC_MODE, HOSTCC_MODE_ENABLE | tp->coalesce_mode);
+
+       tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE);
+       tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE);
+       if (!tg3_flag(tp, 5705_PLUS))
+               tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE);
+
+       if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
+               tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
+               /* reset to prevent losing 1st rx packet intermittently */
+               tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+               udelay(10);
+       }
+
+       if (tg3_flag(tp, ENABLE_APE))
+               tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+       else
+               tp->mac_mode = 0;
+       tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
+               MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
+       if (!tg3_flag(tp, 5705_PLUS) &&
+           !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+               tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+       tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
+       udelay(40);
+
+       /* tp->grc_local_ctrl is partially set up during tg3_get_invariants().
+        * If TG3_FLAG_IS_NIC is zero, we should read the
+        * register to preserve the GPIO settings for LOMs. The GPIOs,
+        * whether used as inputs or outputs, are set by boot code after
+        * reset.
+        */
+       if (!tg3_flag(tp, IS_NIC)) {
+               u32 gpio_mask;
+
+               gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 |
+                           GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 |
+                           GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2;
+
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+                       gpio_mask |= GRC_LCLCTRL_GPIO_OE3 |
+                                    GRC_LCLCTRL_GPIO_OUTPUT3;
+
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+                       gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL;
+
+               tp->grc_local_ctrl &= ~gpio_mask;
+               tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
+
+               /* GPIO1 must be driven high for eeprom write protect */
+               if (tg3_flag(tp, EEPROM_WRITE_PROT))
+                       tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+                                              GRC_LCLCTRL_GPIO_OUTPUT1);
+       }
+       tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+       udelay(100);
+
+       if (!tg3_flag(tp, 5705_PLUS)) {
+               tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
+               udelay(40);
+       }
+
+       val = (WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB |
+              WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB |
+              WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB |
+              WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
+              WDMAC_MODE_LNGREAD_ENAB);
+
+       /* Enable host coalescing bug fix */
+       if (tg3_flag(tp, 5755_PLUS))
+               val |= WDMAC_MODE_STATUS_TAG_FIX;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+               val |= WDMAC_MODE_BURST_ALL_DATA;
+
+       tw32_f(WDMAC_MODE, val);
+       udelay(40);
+
+       if (tg3_flag(tp, PCIX_MODE)) {
+               u16 pcix_cmd;
+
+               pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+                                    &pcix_cmd);
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
+                       pcix_cmd &= ~PCI_X_CMD_MAX_READ;
+                       pcix_cmd |= PCI_X_CMD_READ_2K;
+               } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+                       pcix_cmd &= ~(PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ);
+                       pcix_cmd |= PCI_X_CMD_READ_2K;
+               }
+               pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+                                     pcix_cmd);
+       }
+
+       tw32_f(RDMAC_MODE, rdmac_mode);
+       udelay(40);
+
+       tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
+       if (!tg3_flag(tp, 5705_PLUS))
+               tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+               tw32(SNDDATAC_MODE,
+                    SNDDATAC_MODE_ENABLE | SNDDATAC_MODE_CDELAY);
+       else
+               tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+
+       tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
+       tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
+       val = RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ;
+       if (tg3_flag(tp, LRG_PROD_RING_CAP))
+               val |= RCVDBDI_MODE_LRG_RING_SZ;
+       tw32(RCVDBDI_MODE, val);
+       tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
+
+       val = SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE;
+       if (tg3_flag(tp, ENABLE_TSS))
+               val |= SNDBDI_MODE_MULTI_TXQ_EN;
+       tw32(SNDBDI_MODE, val);
+       tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE);
+
+
+       /* FIXME: 5701 firmware fix? */
+#if 0
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
+               err = tg3_load_5701_a0_firmware_fix(tp);
+               if (err)
+                       return err;
+       }
+#endif
+
+       tp->tx_mode = TX_MODE_ENABLE;
+
+       if (tg3_flag(tp, 5755_PLUS) ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+               tp->tx_mode |= TX_MODE_MBUF_LOCKUP_FIX;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+               val = TX_MODE_JMB_FRM_LEN | TX_MODE_CNT_DN_MODE;
+               tp->tx_mode &= ~val;
+               tp->tx_mode |= tr32(MAC_TX_MODE) & val;
+       }
+
+       tw32_f(MAC_TX_MODE, tp->tx_mode);
+       udelay(100);
+
+       tp->rx_mode = RX_MODE_ENABLE;
+
+       tw32_f(MAC_RX_MODE, tp->rx_mode);
+       udelay(10);
+
+       tw32(MAC_LED_CTRL, tp->led_ctrl);
+
+       tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+       if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+               tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+               udelay(10);
+       }
+       tw32_f(MAC_RX_MODE, tp->rx_mode);
+       udelay(10);
+
+       if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+               if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) &&
+                       !(tp->phy_flags & TG3_PHYFLG_SERDES_PREEMPHASIS)) {
+                       /* Set drive transmission level to 1.2V  */
+                       /* only if the signal pre-emphasis bit is not set  */
+                       val = tr32(MAC_SERDES_CFG);
+                       val &= 0xfffff000;
+                       val |= 0x880;
+                       tw32(MAC_SERDES_CFG, val);
+               }
+               if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
+                       tw32(MAC_SERDES_CFG, 0x616000);
+       }
+
+       /* Prevent chip from dropping frames when flow control
+        * is enabled.
+        */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+               val = 1;
+       else
+               val = 2;
+       tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, val);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+           (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) {
+               /* Use hardware link auto-negotiation */
+               tg3_flag_set(tp, HW_AUTONEG);
+       }
+
+       if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+               u32 tmp;
+
+               tmp = tr32(SERDES_RX_CTRL);
+               tw32(SERDES_RX_CTRL, tmp | SERDES_RX_SIG_DETECT);
+               tp->grc_local_ctrl &= ~GRC_LCLCTRL_USE_EXT_SIG_DETECT;
+               tp->grc_local_ctrl |= GRC_LCLCTRL_USE_SIG_DETECT;
+               tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+       }
+
+       err = tg3_setup_phy(tp, 0);
+       if (err)
+               return err;
+
+       if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+           !(tp->phy_flags & TG3_PHYFLG_IS_FET)) {
+               u32 tmp;
+
+               /* Clear CRC stats. */
+               if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) {
+                       tg3_writephy(tp, MII_TG3_TEST1,
+                                    tmp | MII_TG3_TEST1_CRC_EN);
+                       tg3_readphy(tp, MII_TG3_RXR_COUNTERS, &tmp);
+               }
+       }
+
+       __tg3_set_rx_mode(tp->dev);
+
+       /* Initialize receive rules. */
+       tw32(MAC_RCV_RULE_0,  0xc2000000 & RCV_RULE_DISABLE_MASK);
+       tw32(MAC_RCV_VALUE_0, 0xffffffff & RCV_RULE_DISABLE_MASK);
+       tw32(MAC_RCV_RULE_1,  0x86000004 & RCV_RULE_DISABLE_MASK);
+       tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
+
+       if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, 5780_CLASS))
+               limit = 8;
+       else
+               limit = 16;
+       if (tg3_flag(tp, ENABLE_ASF))
+               limit -= 4;
+       switch (limit) {
+       case 16:
+               tw32(MAC_RCV_RULE_15,  0); tw32(MAC_RCV_VALUE_15,  0);
+       case 15:
+               tw32(MAC_RCV_RULE_14,  0); tw32(MAC_RCV_VALUE_14,  0);
+       case 14:
+               tw32(MAC_RCV_RULE_13,  0); tw32(MAC_RCV_VALUE_13,  0);
+       case 13:
+               tw32(MAC_RCV_RULE_12,  0); tw32(MAC_RCV_VALUE_12,  0);
+       case 12:
+               tw32(MAC_RCV_RULE_11,  0); tw32(MAC_RCV_VALUE_11,  0);
+       case 11:
+               tw32(MAC_RCV_RULE_10,  0); tw32(MAC_RCV_VALUE_10,  0);
+       case 10:
+               tw32(MAC_RCV_RULE_9,  0); tw32(MAC_RCV_VALUE_9,  0);
+       case 9:
+               tw32(MAC_RCV_RULE_8,  0); tw32(MAC_RCV_VALUE_8,  0);
+       case 8:
+               tw32(MAC_RCV_RULE_7,  0); tw32(MAC_RCV_VALUE_7,  0);
+       case 7:
+               tw32(MAC_RCV_RULE_6,  0); tw32(MAC_RCV_VALUE_6,  0);
+       case 6:
+               tw32(MAC_RCV_RULE_5,  0); tw32(MAC_RCV_VALUE_5,  0);
+       case 5:
+               tw32(MAC_RCV_RULE_4,  0); tw32(MAC_RCV_VALUE_4,  0);
+       case 4:
+               /* tw32(MAC_RCV_RULE_3,  0); tw32(MAC_RCV_VALUE_3,  0); */
+       case 3:
+               /* tw32(MAC_RCV_RULE_2,  0); tw32(MAC_RCV_VALUE_2,  0); */
+       case 2:
+       case 1:
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+/* Called at device open time to get the chip ready for
+ * packet processing.  Invoked with tp->lock held.
+ */
+int tg3_init_hw(struct tg3 *tp, int reset_phy)
+{      DBGP("%s\n", __func__);
+
+       tg3_switch_clocks(tp);
+
+       tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+
+       return tg3_reset_hw(tp, reset_phy);
+}
+
+void tg3_set_txd(struct tg3 *tp, int entry,
+                       dma_addr_t mapping, int len, u32 flags)
+{      DBGP("%s\n", __func__);
+
+       struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
+
+       txd->addr_hi = ((u64) mapping >> 32);
+       txd->addr_lo = ((u64) mapping & 0xffffffff);
+       txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
+       txd->vlan_tag = 0;
+}
+
+u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+{      DBGP("%s\n", __func__);
+
+       int cacheline_size;
+       u8 byte;
+
+       pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
+       if (byte == 0)
+               cacheline_size = 1024;
+       else
+               cacheline_size = (int) byte * 4;
+
+       /* On 5703 and later chips, the boundary bits have no
+        * effect.
+        */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
+           !tg3_flag(tp, PCI_EXPRESS))
+               goto out;
+
+       if (tg3_flag(tp, 57765_PLUS))
+               val = DMA_RWCTRL_DIS_CACHE_ALIGNMENT;
+
+out:
+       return val;
+}
+
+int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device)
+{      DBGP("%s\n", __func__);
+
+       struct tg3_internal_buffer_desc test_desc;
+       u32 sram_dma_descs;
+       int ret;
+       unsigned int i;
+
+       sram_dma_descs = NIC_SRAM_DMA_DESC_POOL_BASE;
+
+       tw32(FTQ_RCVBD_COMP_FIFO_ENQDEQ, 0);
+       tw32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ, 0);
+       tw32(RDMAC_STATUS, 0);
+       tw32(WDMAC_STATUS, 0);
+
+       tw32(BUFMGR_MODE, 0);
+       tw32(FTQ_RESET, 0);
+
+       test_desc.addr_hi = ((u64) buf_dma) >> 32;
+       test_desc.addr_lo = buf_dma & 0xffffffff;
+       test_desc.nic_mbuf = 0x00002100;
+       test_desc.len = size;
+
+       /*
+        * HP ZX1 was seeing test failures for 5701 cards running at 33Mhz
+        * the *second* time the tg3 driver was getting loaded after an
+        * initial scan.
+        *
+        * Broadcom tells me:
+        *   ...the DMA engine is connected to the GRC block and a DMA
+        *   reset may affect the GRC block in some unpredictable way...
+        *   The behavior of resets to individual blocks has not been tested.
+        *
+        * Broadcom noted the GRC reset will also reset all sub-components.
+        */
+       if (to_device) {
+               test_desc.cqid_sqid = (13 << 8) | 2;
+
+               tw32_f(RDMAC_MODE, RDMAC_MODE_ENABLE);
+               udelay(40);
+       } else {
+               test_desc.cqid_sqid = (16 << 8) | 7;
+
+               tw32_f(WDMAC_MODE, WDMAC_MODE_ENABLE);
+               udelay(40);
+       }
+       test_desc.flags = 0x00000005;
+
+       for (i = 0; i < (sizeof(test_desc) / sizeof(u32)); i++) {
+               u32 val;
+
+               val = *(((u32 *)&test_desc) + i);
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR,
+                                      sram_dma_descs + (i * sizeof(u32)));
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+       }
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+
+       if (to_device)
+               tw32(FTQ_DMA_HIGH_READ_FIFO_ENQDEQ, sram_dma_descs);
+       else
+               tw32(FTQ_DMA_HIGH_WRITE_FIFO_ENQDEQ, sram_dma_descs);
+
+       ret = -ENODEV;
+       for (i = 0; i < 40; i++) {
+               u32 val;
+
+               if (to_device)
+                       val = tr32(FTQ_RCVBD_COMP_FIFO_ENQDEQ);
+               else
+                       val = tr32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ);
+               if ((val & 0xffff) == sram_dma_descs) {
+                       ret = 0;
+                       break;
+               }
+
+               udelay(100);
+       }
+
+       return ret;
+}
diff --git a/src/drivers/net/tg3/tg3_phy.c b/src/drivers/net/tg3/tg3_phy.c
new file mode 100644 (file)
index 0000000..542e027
--- /dev/null
@@ -0,0 +1,1608 @@
+
+#include <mii.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+
+#include "tg3.h"
+
+static void tg3_link_report(struct tg3 *tp);
+
+void tg3_mdio_init(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       if (tg3_flag(tp, 5717_PLUS)) {
+               u32 is_serdes;
+
+               tp->phy_addr = PCI_FUNC(tp->pdev->busdevfn) + 1;
+
+               if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
+                       is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
+               else
+                       is_serdes = tr32(TG3_CPMU_PHY_STRAP) &
+                                   TG3_CPMU_PHY_STRAP_IS_SERDES;
+               if (is_serdes)
+                       tp->phy_addr += 7;
+       } else
+               tp->phy_addr = TG3_PHY_MII_ADDR;
+}
+
+static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+{      DBGP("%s\n", __func__);
+
+       int i;
+       u32 val;
+
+       tw32(OTP_CTRL, cmd | OTP_CTRL_OTP_CMD_START);
+       tw32(OTP_CTRL, cmd);
+
+       /* Wait for up to 1 ms for command to execute. */
+       for (i = 0; i < 100; i++) {
+               val = tr32(OTP_STATUS);
+               if (val & OTP_STATUS_CMD_DONE)
+                       break;
+               udelay(10);
+       }
+
+       return (val & OTP_STATUS_CMD_DONE) ? 0 : -EBUSY;
+}
+
+/* Read the gphy configuration from the OTP region of the chip.  The gphy
+ * configuration is a 32-bit value that straddles the alignment boundary.
+ * We do two 32-bit reads and then shift and merge the results.
+ */
+u32 tg3_read_otp_phycfg(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 bhalf_otp, thalf_otp;
+
+       tw32(OTP_MODE, OTP_MODE_OTP_THRU_GRC);
+
+       if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_INIT))
+               return 0;
+
+       tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC1);
+
+       if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+               return 0;
+
+       thalf_otp = tr32(OTP_READ_DATA);
+
+       tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC2);
+
+       if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+               return 0;
+
+       bhalf_otp = tr32(OTP_READ_DATA);
+
+       return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
+}
+
+#define PHY_BUSY_LOOPS 5000
+
+int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
+{      DBGP("%s\n", __func__);
+
+       u32 frame_val;
+       unsigned int loops;
+       int ret;
+
+       if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+               tw32_f(MAC_MI_MODE,
+                    (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+               udelay(80);
+       }
+
+       *val = 0x0;
+
+       frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
+                     MI_COM_PHY_ADDR_MASK);
+       frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
+                     MI_COM_REG_ADDR_MASK);
+       frame_val |= (MI_COM_CMD_READ | MI_COM_START);
+
+       tw32_f(MAC_MI_COM, frame_val);
+
+       loops = PHY_BUSY_LOOPS;
+       while (loops != 0) {
+               udelay(10);
+               frame_val = tr32(MAC_MI_COM);
+
+               if ((frame_val & MI_COM_BUSY) == 0) {
+                       udelay(5);
+                       frame_val = tr32(MAC_MI_COM);
+                       break;
+               }
+               loops -= 1;
+       }
+
+       ret = -EBUSY;
+       if (loops != 0) {
+               *val = frame_val & MI_COM_DATA_MASK;
+               ret = 0;
+       }
+
+       if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+               tw32_f(MAC_MI_MODE, tp->mi_mode);
+               udelay(80);
+       }
+
+       return ret;
+}
+
+struct subsys_tbl_ent {
+       u16 subsys_vendor, subsys_devid;
+       u32 phy_id;
+};
+
+static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
+       /* Broadcom boards. */
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6, TG3_PHY_ID_BCM8002 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9, 0 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7, 0 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1, TG3_PHY_ID_BCM5703 },
+       { TG3PCI_SUBVENDOR_ID_BROADCOM,
+         TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2, TG3_PHY_ID_BCM5703 },
+
+       /* 3com boards. */
+       { TG3PCI_SUBVENDOR_ID_3COM,
+         TG3PCI_SUBDEVICE_ID_3COM_3C996T, TG3_PHY_ID_BCM5401 },
+       { TG3PCI_SUBVENDOR_ID_3COM,
+         TG3PCI_SUBDEVICE_ID_3COM_3C996BT, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_3COM,
+         TG3PCI_SUBDEVICE_ID_3COM_3C996SX, 0 },
+       { TG3PCI_SUBVENDOR_ID_3COM,
+         TG3PCI_SUBDEVICE_ID_3COM_3C1000T, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_3COM,
+         TG3PCI_SUBDEVICE_ID_3COM_3C940BR01, TG3_PHY_ID_BCM5701 },
+
+       /* DELL boards. */
+       { TG3PCI_SUBVENDOR_ID_DELL,
+         TG3PCI_SUBDEVICE_ID_DELL_VIPER, TG3_PHY_ID_BCM5401 },
+       { TG3PCI_SUBVENDOR_ID_DELL,
+         TG3PCI_SUBDEVICE_ID_DELL_JAGUAR, TG3_PHY_ID_BCM5401 },
+       { TG3PCI_SUBVENDOR_ID_DELL,
+         TG3PCI_SUBDEVICE_ID_DELL_MERLOT, TG3_PHY_ID_BCM5411 },
+       { TG3PCI_SUBVENDOR_ID_DELL,
+         TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT, TG3_PHY_ID_BCM5411 },
+
+       /* Compaq boards. */
+       { TG3PCI_SUBVENDOR_ID_COMPAQ,
+         TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_COMPAQ,
+         TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_COMPAQ,
+         TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING, 0 },
+       { TG3PCI_SUBVENDOR_ID_COMPAQ,
+         TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780, TG3_PHY_ID_BCM5701 },
+       { TG3PCI_SUBVENDOR_ID_COMPAQ,
+         TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2, TG3_PHY_ID_BCM5701 },
+
+       /* IBM boards. */
+       { TG3PCI_SUBVENDOR_ID_IBM,
+         TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 }
+};
+
+static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int i;
+
+       DBGC(tp->dev, "Matching with: %x:%x\n", tp->subsystem_vendor, tp->subsystem_device);
+
+       for (i = 0; i < (int) ARRAY_SIZE(subsys_id_to_phy_id); i++) {
+               if ((subsys_id_to_phy_id[i].subsys_vendor ==
+                    tp->subsystem_vendor) &&
+                   (subsys_id_to_phy_id[i].subsys_devid ==
+                    tp->subsystem_device))
+                       return &subsys_id_to_phy_id[i];
+       }
+       return NULL;
+}
+
+int tg3_writephy(struct tg3 *tp, int reg, u32 val)
+{      DBGP("%s\n", __func__);
+
+       u32 frame_val;
+       unsigned int loops;
+       int ret;
+
+       if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
+           (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
+               return 0;
+
+       if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+               tw32_f(MAC_MI_MODE,
+                    (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+               udelay(80);
+       }
+
+       frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
+                     MI_COM_PHY_ADDR_MASK);
+       frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
+                     MI_COM_REG_ADDR_MASK);
+       frame_val |= (val & MI_COM_DATA_MASK);
+       frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
+
+       tw32_f(MAC_MI_COM, frame_val);
+
+       loops = PHY_BUSY_LOOPS;
+       while (loops != 0) {
+               udelay(10);
+               frame_val = tr32(MAC_MI_COM);
+               if ((frame_val & MI_COM_BUSY) == 0) {
+                       udelay(5);
+                       frame_val = tr32(MAC_MI_COM);
+                       break;
+               }
+               loops -= 1;
+       }
+
+       ret = -EBUSY;
+       if (loops != 0)
+               ret = 0;
+
+       if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+               tw32_f(MAC_MI_MODE, tp->mi_mode);
+               udelay(80);
+       }
+
+       return ret;
+}
+
+static int tg3_bmcr_reset(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 phy_control;
+       int limit, err;
+
+       /* OK, reset it, and poll the BMCR_RESET bit until it
+        * clears or we time out.
+        */
+       phy_control = BMCR_RESET;
+       err = tg3_writephy(tp, MII_BMCR, phy_control);
+       if (err != 0)
+               return -EBUSY;
+
+       limit = 5000;
+       while (limit--) {
+               err = tg3_readphy(tp, MII_BMCR, &phy_control);
+               if (err != 0)
+                       return -EBUSY;
+
+               if ((phy_control & BMCR_RESET) == 0) {
+                       udelay(40);
+                       break;
+               }
+               udelay(10);
+       }
+       if (limit < 0)
+               return -EBUSY;
+
+       return 0;
+}
+
+static int tg3_wait_macro_done(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int limit = 100;
+
+       while (limit--) {
+               u32 tmp32;
+
+               if (!tg3_readphy(tp, MII_TG3_DSP_CONTROL, &tmp32)) {
+                       if ((tmp32 & 0x1000) == 0)
+                               break;
+               }
+       }
+       if (limit < 0)
+               return -EBUSY;
+
+       return 0;
+}
+
+static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
+{      DBGP("%s\n", __func__);
+
+       static const u32 test_pat[4][6] = {
+       { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
+       { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
+       { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
+       { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
+       };
+       int chan;
+
+       for (chan = 0; chan < 4; chan++) {
+               int i;
+
+               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+                            (chan * 0x2000) | 0x0200);
+               tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
+
+               for (i = 0; i < 6; i++)
+                       tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
+                                    test_pat[chan][i]);
+
+               tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
+               if (tg3_wait_macro_done(tp)) {
+                       *resetp = 1;
+                       return -EBUSY;
+               }
+
+               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+                            (chan * 0x2000) | 0x0200);
+               tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0082);
+               if (tg3_wait_macro_done(tp)) {
+                       *resetp = 1;
+                       return -EBUSY;
+               }
+
+               tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0802);
+               if (tg3_wait_macro_done(tp)) {
+                       *resetp = 1;
+                       return -EBUSY;
+               }
+
+               for (i = 0; i < 6; i += 2) {
+                       u32 low, high;
+
+                       if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) ||
+                           tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) ||
+                           tg3_wait_macro_done(tp)) {
+                               *resetp = 1;
+                               return -EBUSY;
+                       }
+                       low &= 0x7fff;
+                       high &= 0x000f;
+                       if (low != test_pat[chan][i] ||
+                           high != test_pat[chan][i+1]) {
+                               tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
+                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
+                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
+
+                               return -EBUSY;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int tg3_phy_reset_chanpat(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int chan;
+
+       for (chan = 0; chan < 4; chan++) {
+               int i;
+
+               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+                            (chan * 0x2000) | 0x0200);
+               tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
+               for (i = 0; i < 6; i++)
+                       tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
+               tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
+               if (tg3_wait_macro_done(tp))
+                       return -EBUSY;
+       }
+
+       return 0;
+}
+
+static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
+{      DBGP("%s\n", __func__);
+
+       int err;
+
+       err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
+       if (!err)
+               err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
+
+       return err;
+}
+
+static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set)
+{      DBGP("%s\n", __func__);
+
+       if (reg == MII_TG3_AUXCTL_SHDWSEL_MISC)
+               set |= MII_TG3_AUXCTL_MISC_WREN;
+
+       return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg);
+}
+
+#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \
+       tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
+                            MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \
+                            MII_TG3_AUXCTL_ACTL_TX_6DB)
+
+#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \
+       tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
+                            MII_TG3_AUXCTL_ACTL_TX_6DB);
+
+static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 reg32, phy9_orig;
+       int retries, do_phy_reset, err;
+
+       retries = 10;
+       do_phy_reset = 1;
+       do {
+               if (do_phy_reset) {
+                       err = tg3_bmcr_reset(tp);
+                       if (err)
+                               return err;
+                       do_phy_reset = 0;
+               }
+
+               /* Disable transmitter and interrupt.  */
+               if (tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32))
+                       continue;
+
+               reg32 |= 0x3000;
+               tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+
+               /* Set full-duplex, 1000 mbps.  */
+               tg3_writephy(tp, MII_BMCR,
+                            BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
+
+               /* Set to master mode.  */
+               if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
+                       continue;
+
+               tg3_writephy(tp, MII_TG3_CTRL,
+                            (MII_TG3_CTRL_AS_MASTER |
+                             MII_TG3_CTRL_ENABLE_AS_MASTER));
+
+               err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+               if (err)
+                       return err;
+
+               /* Block the PHY control access.  */
+               tg3_phydsp_write(tp, 0x8005, 0x0800);
+
+               err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
+               if (!err)
+                       break;
+       } while (--retries);
+
+       err = tg3_phy_reset_chanpat(tp);
+       if (err)
+               return err;
+
+       tg3_phydsp_write(tp, 0x8005, 0x0000);
+
+       tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
+       tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000);
+
+       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+
+       tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
+
+       if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
+               reg32 &= ~0x3000;
+               tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+       } else if (!err)
+               err = -EBUSY;
+
+       return err;
+}
+
+static void tg3_phy_apply_otp(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 otp, phy;
+
+       if (!tp->phy_otp)
+               return;
+
+       otp = tp->phy_otp;
+
+       if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp))
+               return;
+
+       phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT);
+       phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT;
+       tg3_phydsp_write(tp, MII_TG3_DSP_TAP1, phy);
+
+       phy = ((otp & TG3_OTP_HPFFLTR_MASK) >> TG3_OTP_HPFFLTR_SHIFT) |
+             ((otp & TG3_OTP_HPFOVER_MASK) >> TG3_OTP_HPFOVER_SHIFT);
+       tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH0, phy);
+
+       phy = ((otp & TG3_OTP_LPFDIS_MASK) >> TG3_OTP_LPFDIS_SHIFT);
+       phy |= MII_TG3_DSP_AADJ1CH3_ADCCKADJ;
+       tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH3, phy);
+
+       phy = ((otp & TG3_OTP_VDAC_MASK) >> TG3_OTP_VDAC_SHIFT);
+       tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, phy);
+
+       phy = ((otp & TG3_OTP_10BTAMP_MASK) >> TG3_OTP_10BTAMP_SHIFT);
+       tg3_phydsp_write(tp, MII_TG3_DSP_EXP96, phy);
+
+       phy = ((otp & TG3_OTP_ROFF_MASK) >> TG3_OTP_ROFF_SHIFT) |
+             ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);
+       tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy);
+
+       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+}
+
+static int tg3_phy_auxctl_read(struct tg3 *tp, int reg, u32 *val)
+{      DBGP("%s\n", __func__);
+
+       int err;
+
+       err = tg3_writephy(tp, MII_TG3_AUX_CTRL,
+                          (reg << MII_TG3_AUXCTL_MISC_RDSEL_SHIFT) |
+                          MII_TG3_AUXCTL_SHDWSEL_MISC);
+       if (!err)
+               err = tg3_readphy(tp, MII_TG3_AUX_CTRL, val);
+
+       return err;
+}
+
+static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
+{      DBGP("%s\n", __func__);
+
+       u32 phy;
+
+       if (!tg3_flag(tp, 5705_PLUS) ||
+           (tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+               return;
+
+       if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+               u32 ephy;
+
+               if (!tg3_readphy(tp, MII_TG3_FET_TEST, &ephy)) {
+                       u32 reg = MII_TG3_FET_SHDW_MISCCTRL;
+
+                       tg3_writephy(tp, MII_TG3_FET_TEST,
+                                    ephy | MII_TG3_FET_SHADOW_EN);
+                       if (!tg3_readphy(tp, reg, &phy)) {
+                               if (enable)
+                                       phy |= MII_TG3_FET_SHDW_MISCCTRL_MDIX;
+                               else
+                                       phy &= ~MII_TG3_FET_SHDW_MISCCTRL_MDIX;
+                               tg3_writephy(tp, reg, phy);
+                       }
+                       tg3_writephy(tp, MII_TG3_FET_TEST, ephy);
+               }
+       } else {
+               int ret;
+
+               ret = tg3_phy_auxctl_read(tp,
+                                         MII_TG3_AUXCTL_SHDWSEL_MISC, &phy);
+               if (!ret) {
+                       if (enable)
+                               phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+                       else
+                               phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+                       tg3_phy_auxctl_write(tp,
+                                            MII_TG3_AUXCTL_SHDWSEL_MISC, phy);
+               }
+       }
+}
+
+static void tg3_phy_set_wirespeed(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int ret;
+       u32 val;
+
+       if (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED)
+               return;
+
+       ret = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_MISC, &val);
+       if (!ret)
+               tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_MISC,
+                                    val | MII_TG3_AUXCTL_MISC_WIRESPD_EN);
+}
+
+/* This will reset the tigon3 PHY if there is no valid
+ * link unless the FORCE argument is non-zero.
+ */
+int tg3_phy_reset(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 val, cpmuctrl;
+       int err;
+
+       DBGCP(&tp->pdev->dev, "%s\n", __func__);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               val = tr32(GRC_MISC_CFG);
+               tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
+               udelay(40);
+       }
+       err  = tg3_readphy(tp, MII_BMSR, &val);
+       err |= tg3_readphy(tp, MII_BMSR, &val);
+       if (err != 0)
+               return -EBUSY;
+
+       netdev_link_down(tp->dev);
+       tg3_link_report(tp);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+               err = tg3_phy_reset_5703_4_5(tp);
+               if (err)
+                       return err;
+               goto out;
+       }
+
+       cpmuctrl = 0;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+           GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
+               cpmuctrl = tr32(TG3_CPMU_CTRL);
+               if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY)
+                       tw32(TG3_CPMU_CTRL,
+                            cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY);
+       }
+
+       err = tg3_bmcr_reset(tp);
+       if (err)
+               return err;
+
+       if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) {
+               val = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
+               tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, val);
+
+               tw32(TG3_CPMU_CTRL, cpmuctrl);
+       }
+
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+           GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
+               val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+               if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
+                   CPMU_LSPD_1000MB_MACCLK_12_5) {
+                       val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+                       udelay(40);
+                       tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+               }
+       }
+
+       if (tg3_flag(tp, 5717_PLUS) &&
+           (tp->phy_flags & TG3_PHYFLG_MII_SERDES))
+               return 0;
+
+       tg3_phy_apply_otp(tp);
+
+out:
+       if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) &&
+           !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+               tg3_phydsp_write(tp, 0x201f, 0x2aaa);
+               tg3_phydsp_write(tp, 0x000a, 0x0323);
+               TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+       }
+
+       if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
+               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+       }
+
+       if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
+               if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+                       tg3_phydsp_write(tp, 0x000a, 0x310b);
+                       tg3_phydsp_write(tp, 0x201f, 0x9506);
+                       tg3_phydsp_write(tp, 0x401f, 0x14e2);
+                       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+               }
+       } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
+               if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+                       tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+                       if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {
+                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
+                               tg3_writephy(tp, MII_TG3_TEST1,
+                                            MII_TG3_TEST1_TRIM_EN | 0x4);
+                       } else
+                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
+
+                       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+               }
+       }
+
+       if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+               /* Cannot do read-modify-write on 5401 */
+               tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               /* adjust output voltage */
+               tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12);
+       }
+
+       tg3_phy_toggle_automdix(tp, 1);
+       tg3_phy_set_wirespeed(tp);
+       return 0;
+}
+
+static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
+{      DBGP("%s\n", __func__);
+
+       u32 adv_reg, all_mask = 0;
+
+       if (mask & ADVERTISED_10baseT_Half)
+               all_mask |= ADVERTISE_10HALF;
+       if (mask & ADVERTISED_10baseT_Full)
+               all_mask |= ADVERTISE_10FULL;
+       if (mask & ADVERTISED_100baseT_Half)
+               all_mask |= ADVERTISE_100HALF;
+       if (mask & ADVERTISED_100baseT_Full)
+               all_mask |= ADVERTISE_100FULL;
+
+       if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
+               return 0;
+
+       if ((adv_reg & all_mask) != all_mask)
+               return 0;
+       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
+               u32 tg3_ctrl;
+
+               all_mask = 0;
+               if (mask & ADVERTISED_1000baseT_Half)
+                       all_mask |= ADVERTISE_1000HALF;
+               if (mask & ADVERTISED_1000baseT_Full)
+                       all_mask |= ADVERTISE_1000FULL;
+
+               if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
+                       return 0;
+
+               if ((tg3_ctrl & all_mask) != all_mask)
+                       return 0;
+       }
+       return 1;
+}
+
+static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
+{      DBGP("%s\n", __func__);
+
+       u16 miireg;
+
+       if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
+               miireg = ADVERTISE_PAUSE_CAP;
+       else if (flow_ctrl & FLOW_CTRL_TX)
+               miireg = ADVERTISE_PAUSE_ASYM;
+       else if (flow_ctrl & FLOW_CTRL_RX)
+               miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+       else
+               miireg = 0;
+
+       return miireg;
+}
+
+static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
+{      DBGP("%s\n", __func__);
+
+       int err = 0;
+       u32 val __unused, new_adv;
+
+       new_adv = ADVERTISE_CSMA;
+       if (advertise & ADVERTISED_10baseT_Half)
+               new_adv |= ADVERTISE_10HALF;
+       if (advertise & ADVERTISED_10baseT_Full)
+               new_adv |= ADVERTISE_10FULL;
+       if (advertise & ADVERTISED_100baseT_Half)
+               new_adv |= ADVERTISE_100HALF;
+       if (advertise & ADVERTISED_100baseT_Full)
+               new_adv |= ADVERTISE_100FULL;
+
+       new_adv |= tg3_advert_flowctrl_1000T(flowctrl);
+
+       err = tg3_writephy(tp, MII_ADVERTISE, new_adv);
+       if (err)
+               goto done;
+
+       if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+               goto done;
+
+       new_adv = 0;
+       if (advertise & ADVERTISED_1000baseT_Half)
+               new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
+       if (advertise & ADVERTISED_1000baseT_Full)
+               new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
+
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+           tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
+               new_adv |= (MII_TG3_CTRL_AS_MASTER |
+                           MII_TG3_CTRL_ENABLE_AS_MASTER);
+
+       err = tg3_writephy(tp, MII_TG3_CTRL, new_adv);
+       if (err)
+               goto done;
+
+       if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+               goto done;
+
+done:
+       return err;
+}
+
+static int tg3_init_5401phy_dsp(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       int err;
+
+       /* Turn off tap power management. */
+       /* Set Extended packet length bit */
+       err = tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
+
+       err |= tg3_phydsp_write(tp, 0x0012, 0x1804);
+       err |= tg3_phydsp_write(tp, 0x0013, 0x1204);
+       err |= tg3_phydsp_write(tp, 0x8006, 0x0132);
+       err |= tg3_phydsp_write(tp, 0x8006, 0x0232);
+       err |= tg3_phydsp_write(tp, 0x201f, 0x0a20);
+
+       udelay(40);
+
+       return err;
+}
+
+#define ADVERTISED_Autoneg              (1 << 6)
+#define ADVERTISED_Pause                (1 << 13)
+#define ADVERTISED_TP                   (1 << 7)
+#define ADVERTISED_FIBRE                (1 << 10)
+
+#define AUTONEG_ENABLE          0x01
+
+static void tg3_phy_init_link_config(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 adv = ADVERTISED_Autoneg |
+                 ADVERTISED_Pause;
+
+
+       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
+               adv |= ADVERTISED_1000baseT_Half |
+                      ADVERTISED_1000baseT_Full;
+       if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+               adv |= ADVERTISED_100baseT_Half |
+                      ADVERTISED_100baseT_Full |
+                      ADVERTISED_10baseT_Half |
+                      ADVERTISED_10baseT_Full |
+                      ADVERTISED_TP;
+       else
+               adv |= ADVERTISED_FIBRE;
+
+       tp->link_config.advertising = adv;
+       tp->link_config.speed = SPEED_INVALID;
+       tp->link_config.duplex = DUPLEX_INVALID;
+       tp->link_config.autoneg = AUTONEG_ENABLE;
+       tp->link_config.active_speed = SPEED_INVALID;
+       tp->link_config.active_duplex = DUPLEX_INVALID;
+       tp->link_config.orig_speed = SPEED_INVALID;
+       tp->link_config.orig_duplex = DUPLEX_INVALID;
+       tp->link_config.orig_autoneg = AUTONEG_INVALID;
+}
+
+int tg3_phy_probe(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 hw_phy_id_1, hw_phy_id_2;
+       u32 hw_phy_id, hw_phy_id_masked;
+       int err;
+
+       /* flow control autonegotiation is default behavior */
+       tg3_flag_set(tp, PAUSE_AUTONEG);
+       tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+
+       /* Reading the PHY ID register can conflict with ASF
+        * firmware access to the PHY hardware.
+        */
+       err = 0;
+       if (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE)) {
+               hw_phy_id = hw_phy_id_masked = TG3_PHY_ID_INVALID;
+       } else {
+               /* Now read the physical PHY_ID from the chip and verify
+                * that it is sane.  If it doesn't look good, we fall back
+                * to either the hard-coded table based PHY_ID and failing
+                * that the value found in the eeprom area.
+                */
+               err |= tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
+               err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
+
+               hw_phy_id  = (hw_phy_id_1 & 0xffff) << 10;
+               hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
+               hw_phy_id |= (hw_phy_id_2 & 0x03ff) <<  0;
+
+               hw_phy_id_masked = hw_phy_id & TG3_PHY_ID_MASK;
+       }
+
+       if (!err && TG3_KNOWN_PHY_ID(hw_phy_id_masked)) {
+               tp->phy_id = hw_phy_id;
+               if (hw_phy_id_masked == TG3_PHY_ID_BCM8002)
+                       tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
+               else
+                       tp->phy_flags &= ~TG3_PHYFLG_PHY_SERDES;
+       } else {
+               if (tp->phy_id != TG3_PHY_ID_INVALID) {
+                       /* Do nothing, phy ID already set up in
+                        * tg3_get_eeprom_hw_cfg().
+                        */
+               } else {
+                       struct subsys_tbl_ent *p;
+
+                       /* No eeprom signature?  Try the hardcoded
+                        * subsys device table.
+                        */
+                       p = tg3_lookup_by_subsys(tp);
+                       if (!p) {
+                               DBGC(&tp->pdev->dev, "lookup by subsys failed\n");
+                               return -ENODEV;
+                       }
+
+                       tp->phy_id = p->phy_id;
+                       if (!tp->phy_id ||
+                           tp->phy_id == TG3_PHY_ID_BCM8002)
+                               tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
+               }
+       }
+
+       if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+           ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
+             tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) ||
+            (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
+             tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
+               tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
+
+       tg3_phy_init_link_config(tp);
+
+       if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+           !tg3_flag(tp, ENABLE_APE) &&
+           !tg3_flag(tp, ENABLE_ASF)) {
+               u32 bmsr;
+               u32 mask;
+
+               tg3_readphy(tp, MII_BMSR, &bmsr);
+               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+                   (bmsr & BMSR_LSTATUS))
+                       goto skip_phy_reset;
+
+               err = tg3_phy_reset(tp);
+               if (err)
+                       return err;
+
+               tg3_phy_set_wirespeed(tp);
+
+               mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+                       ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+                       ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
+               if (!tg3_copper_is_advertising_all(tp, mask)) {
+                       tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
+                                           tp->link_config.flowctrl);
+
+                       tg3_writephy(tp, MII_BMCR,
+                                    BMCR_ANENABLE | BMCR_ANRESTART);
+               }
+       }
+
+skip_phy_reset:
+       if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+               err = tg3_init_5401phy_dsp(tp);
+               if (err)
+                       return err;
+
+               err = tg3_init_5401phy_dsp(tp);
+       }
+
+       return err;
+}
+
+void tg3_poll_link(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 mac_stat;
+
+       mac_stat = tr32(MAC_STATUS);
+
+       if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)
+               tg3_setup_phy(tp, 0);
+}
+
+static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
+{      DBGP("%s\n", __func__);
+
+       switch (val & MII_TG3_AUX_STAT_SPDMASK) {
+       case MII_TG3_AUX_STAT_10HALF:
+               *speed = SPEED_10;
+               *duplex = DUPLEX_HALF;
+               break;
+
+       case MII_TG3_AUX_STAT_10FULL:
+               *speed = SPEED_10;
+               *duplex = DUPLEX_FULL;
+               break;
+
+       case MII_TG3_AUX_STAT_100HALF:
+               *speed = SPEED_100;
+               *duplex = DUPLEX_HALF;
+               break;
+
+       case MII_TG3_AUX_STAT_100FULL:
+               *speed = SPEED_100;
+               *duplex = DUPLEX_FULL;
+               break;
+
+       case MII_TG3_AUX_STAT_1000HALF:
+               *speed = SPEED_1000;
+               *duplex = DUPLEX_HALF;
+               break;
+
+       case MII_TG3_AUX_STAT_1000FULL:
+               *speed = SPEED_1000;
+               *duplex = DUPLEX_FULL;
+               break;
+
+       default:
+               if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+                       *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
+                                SPEED_10;
+                       *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
+                                 DUPLEX_HALF;
+                       break;
+               }
+               *speed = SPEED_INVALID;
+               *duplex = DUPLEX_INVALID;
+               break;
+       }
+}
+
+static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv)
+{      DBGP("%s\n", __func__);
+
+       u32 curadv, reqadv;
+
+       if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
+               return 1;
+
+       curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+       reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+
+       if (tp->link_config.active_duplex == DUPLEX_FULL) {
+               if (curadv != reqadv)
+                       return 0;
+
+               if (tg3_flag(tp, PAUSE_AUTONEG))
+                       tg3_readphy(tp, MII_LPA, rmtadv);
+       } else {
+               /* Reprogram the advertisement register, even if it
+                * does not affect the current link.  If the link
+                * gets renegotiated in the future, we can save an
+                * additional renegotiation cycle by advertising
+                * it correctly in the first place.
+                */
+               if (curadv != reqadv) {
+                       *lcladv &= ~(ADVERTISE_PAUSE_CAP |
+                                    ADVERTISE_PAUSE_ASYM);
+                       tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv);
+               }
+       }
+
+       return 1;
+}
+
+static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
+{      DBGP("%s\n", __func__);
+
+       u8 cap = 0;
+
+       if (lcladv & ADVERTISE_1000XPAUSE) {
+               if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+                       if (rmtadv & LPA_1000XPAUSE)
+                               cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+                       else if (rmtadv & LPA_1000XPAUSE_ASYM)
+                               cap = FLOW_CTRL_RX;
+               } else {
+                       if (rmtadv & LPA_1000XPAUSE)
+                               cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+               }
+       } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+               if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
+                       cap = FLOW_CTRL_TX;
+       }
+
+       return cap;
+}
+
+static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
+{      DBGP("%s\n", __func__);
+
+       u8 autoneg;
+       u8 flowctrl = 0;
+       u32 old_rx_mode = tp->rx_mode;
+       u32 old_tx_mode = tp->tx_mode;
+
+       autoneg = tp->link_config.autoneg;
+
+       if (tg3_flag(tp, PAUSE_AUTONEG)) {
+               if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)
+                       flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv);
+               else
+                       flowctrl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+       } else
+               flowctrl = tp->link_config.flowctrl;
+
+       tp->link_config.active_flowctrl = flowctrl;
+
+       if (flowctrl & FLOW_CTRL_RX)
+               tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
+       else
+               tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
+
+       if (old_rx_mode != tp->rx_mode)
+               tw32_f(MAC_RX_MODE, tp->rx_mode);
+
+       if (flowctrl & FLOW_CTRL_TX)
+               tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
+       else
+               tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
+
+       if (old_tx_mode != tp->tx_mode)
+               tw32_f(MAC_TX_MODE, tp->tx_mode);
+}
+
+static void tg3_phy_copper_begin(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 new_adv;
+
+       if (tp->link_config.speed == SPEED_INVALID) {
+               if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+                       tp->link_config.advertising &=
+                               ~(ADVERTISED_1000baseT_Half |
+                                 ADVERTISED_1000baseT_Full);
+
+               tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
+                                   tp->link_config.flowctrl);
+       } else {
+               /* Asking for a specific link mode. */
+               if (tp->link_config.speed == SPEED_1000) {
+                       if (tp->link_config.duplex == DUPLEX_FULL)
+                               new_adv = ADVERTISED_1000baseT_Full;
+                       else
+                               new_adv = ADVERTISED_1000baseT_Half;
+               } else if (tp->link_config.speed == SPEED_100) {
+                       if (tp->link_config.duplex == DUPLEX_FULL)
+                               new_adv = ADVERTISED_100baseT_Full;
+                       else
+                               new_adv = ADVERTISED_100baseT_Half;
+               } else {
+                       if (tp->link_config.duplex == DUPLEX_FULL)
+                               new_adv = ADVERTISED_10baseT_Full;
+                       else
+                               new_adv = ADVERTISED_10baseT_Half;
+               }
+
+               tg3_phy_autoneg_cfg(tp, new_adv,
+                                   tp->link_config.flowctrl);
+       }
+
+       tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
+}
+
+static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
+{      DBGP("%s\n", __func__);
+
+       if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
+               return 1;
+       else if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411) {
+               if (speed != SPEED_10)
+                       return 1;
+       } else if (speed == SPEED_10)
+               return 1;
+
+       return 0;
+}
+
+#if 1
+
+static void tg3_ump_link_report(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       u32 reg;
+       u32 val;
+
+       if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
+               return;
+
+       tg3_wait_for_event_ack(tp);
+
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
+
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
+
+       val = 0;
+       if (!tg3_readphy(tp, MII_BMCR, &reg))
+               val = reg << 16;
+       if (!tg3_readphy(tp, MII_BMSR, &reg))
+               val |= (reg & 0xffff);
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
+
+       val = 0;
+       if (!tg3_readphy(tp, MII_ADVERTISE, &reg))
+               val = reg << 16;
+       if (!tg3_readphy(tp, MII_LPA, &reg))
+               val |= (reg & 0xffff);
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
+
+       val = 0;
+       if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) {
+               if (!tg3_readphy(tp, MII_CTRL1000, &reg))
+                       val = reg << 16;
+               if (!tg3_readphy(tp, MII_STAT1000, &reg))
+                       val |= (reg & 0xffff);
+       }
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
+
+       if (!tg3_readphy(tp, MII_PHYADDR, &reg))
+               val = reg << 16;
+       else
+               val = 0;
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
+
+       tg3_generate_fw_event(tp);
+}
+
+/* NOTE: Debugging only code */
+static void tg3_link_report(struct tg3 *tp)
+{      DBGP("%s\n", __func__);
+
+       if (!netdev_link_ok(tp->dev)) {
+               DBGC(tp->dev, "Link is down\n");
+               tg3_ump_link_report(tp);
+       } else {
+               DBGC(tp->dev, "Link is up at %d Mbps, %s duplex\n",
+                           (tp->link_config.active_speed == SPEED_1000 ?
+                            1000 :
+                            (tp->link_config.active_speed == SPEED_100 ?
+                             100 : 10)),
+                           (tp->link_config.active_duplex == DUPLEX_FULL ?
+                            "full" : "half"));
+
+               DBGC(tp->dev, "Flow control is %s for TX and %s for RX\n",
+                           (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ?
+                           "on" : "off",
+                           (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ?
+                           "on" : "off");
+
+               if (tp->phy_flags & TG3_PHYFLG_EEE_CAP)
+                       DBGC(tp->dev, "EEE is %s\n",
+                                   tp->setlpicnt ? "enabled" : "disabled");
+
+               tg3_ump_link_report(tp);
+       }
+}
+#endif
+
+static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
+{      DBGP("%s\n", __func__);
+
+       int current_link_up;
+       u32 bmsr, val;
+       u32 lcl_adv, rmt_adv;
+       u16 current_speed;
+       u8 current_duplex;
+       int i, err;
+
+       tw32(MAC_EVENT, 0);
+
+       tw32_f(MAC_STATUS,
+            (MAC_STATUS_SYNC_CHANGED |
+             MAC_STATUS_CFG_CHANGED |
+             MAC_STATUS_MI_COMPLETION |
+             MAC_STATUS_LNKSTATE_CHANGED));
+       udelay(40);
+
+       if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+               tw32_f(MAC_MI_MODE,
+                    (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+               udelay(80);
+       }
+
+       tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, 0);
+
+       /* Some third-party PHYs need to be reset on link going
+        * down.
+        */
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
+           netdev_link_ok(tp->dev)) {
+               tg3_readphy(tp, MII_BMSR, &bmsr);
+               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+                   !(bmsr & BMSR_LSTATUS))
+                       force_reset = 1;
+       }
+       if (force_reset)
+               tg3_phy_reset(tp);
+
+       if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+               tg3_readphy(tp, MII_BMSR, &bmsr);
+               if (tg3_readphy(tp, MII_BMSR, &bmsr) ||
+                   !tg3_flag(tp, INIT_COMPLETE))
+                       bmsr = 0;
+
+               if (!(bmsr & BMSR_LSTATUS)) {
+                       err = tg3_init_5401phy_dsp(tp);
+                       if (err)
+                               return err;
+
+                       tg3_readphy(tp, MII_BMSR, &bmsr);
+                       for (i = 0; i < 1000; i++) {
+                               udelay(10);
+                               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+                                   (bmsr & BMSR_LSTATUS)) {
+                                       udelay(40);
+                                       break;
+                               }
+                       }
+
+                       if ((tp->phy_id & TG3_PHY_ID_REV_MASK) ==
+                           TG3_PHY_REV_BCM5401_B0 &&
+                           !(bmsr & BMSR_LSTATUS) &&
+                           tp->link_config.active_speed == SPEED_1000) {
+                               err = tg3_phy_reset(tp);
+                               if (!err)
+                                       err = tg3_init_5401phy_dsp(tp);
+                               if (err)
+                                       return err;
+                       }
+               }
+       } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+                  tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
+               /* 5701 {A0,B0} CRC bug workaround */
+               tg3_writephy(tp, 0x15, 0x0a75);
+               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
+               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
+       }
+
+       /* Clear pending interrupts... */
+       tg3_readphy(tp, MII_TG3_ISTAT, &val);
+       tg3_readphy(tp, MII_TG3_ISTAT, &val);
+
+       if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
+               tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
+       else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET))
+               tg3_writephy(tp, MII_TG3_IMASK, ~0);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+               if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
+                       tg3_writephy(tp, MII_TG3_EXT_CTRL,
+                                    MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+               else
+                       tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
+       }
+
+       current_link_up = 0;
+       current_speed = SPEED_INVALID;
+       current_duplex = DUPLEX_INVALID;
+
+       if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
+               err = tg3_phy_auxctl_read(tp,
+                                         MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
+                                         &val);
+               if (!err && !(val & (1 << 10))) {
+                       tg3_phy_auxctl_write(tp,
+                                            MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
+                                            val | (1 << 10));
+                       goto relink;
+               }
+       }
+
+       bmsr = 0;
+       for (i = 0; i < 100; i++) {
+               tg3_readphy(tp, MII_BMSR, &bmsr);
+               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+                   (bmsr & BMSR_LSTATUS))
+                       break;
+               udelay(40);
+       }
+
+       if (bmsr & BMSR_LSTATUS) {
+               u32 aux_stat, bmcr;
+
+               tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
+               for (i = 0; i < 2000; i++) {
+                       udelay(10);
+                       if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) &&
+                           aux_stat)
+                               break;
+               }
+
+               tg3_aux_stat_to_speed_duplex(tp, aux_stat,
+                                            &current_speed,
+                                            &current_duplex);
+
+               bmcr = 0;
+               for (i = 0; i < 200; i++) {
+                       tg3_readphy(tp, MII_BMCR, &bmcr);
+                       if (tg3_readphy(tp, MII_BMCR, &bmcr))
+                               continue;
+                       if (bmcr && bmcr != 0x7fff)
+                               break;
+                       udelay(10);
+               }
+
+               lcl_adv = 0;
+               rmt_adv = 0;
+
+               tp->link_config.active_speed = current_speed;
+               tp->link_config.active_duplex = current_duplex;
+
+               if ((bmcr & BMCR_ANENABLE) &&
+                   tg3_copper_is_advertising_all(tp,
+                                       tp->link_config.advertising)) {
+                       if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv,
+                                                         &rmt_adv)) {
+                               current_link_up = 1;
+                       }
+               }
+
+               if (current_link_up == 1 &&
+                   tp->link_config.active_duplex == DUPLEX_FULL)
+                       tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
+       }
+
+relink:
+       if (current_link_up == 0) {
+               tg3_phy_copper_begin(tp);
+
+               tg3_readphy(tp, MII_BMSR, &bmsr);
+               if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
+                   (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
+                       current_link_up = 1;
+       }
+
+       tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
+       if (current_link_up == 1) {
+               if (tp->link_config.active_speed == SPEED_100 ||
+                   tp->link_config.active_speed == SPEED_10)
+                       tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+               else
+                       tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+       } else if (tp->phy_flags & TG3_PHYFLG_IS_FET)
+               tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+       else
+               tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+
+       tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
+       if (tp->link_config.active_duplex == DUPLEX_HALF)
+               tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+               if (current_link_up == 1 &&
+                   tg3_5700_link_polarity(tp, tp->link_config.active_speed))
+                       tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+               else
+                       tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
+       }
+
+       /* ??? Without this setting Netgear GA302T PHY does not
+        * ??? send/receive packets...
+        */
+       if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 &&
+           tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
+               tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
+               tw32_f(MAC_MI_MODE, tp->mi_mode);
+               udelay(80);
+       }
+
+       tw32_f(MAC_MODE, tp->mac_mode);
+       udelay(40);
+
+       /* We always use the link change register */
+       /* NOTE: this freezes for mdc? */
+       tw32_f(MAC_EVENT, 0);
+       udelay(40);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
+           current_link_up == 1 &&
+           tp->link_config.active_speed == SPEED_1000 &&
+           (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) {
+               udelay(120);
+               /* NOTE: this freezes for mdc? */
+               tw32_f(MAC_STATUS,
+                    (MAC_STATUS_SYNC_CHANGED |
+                     MAC_STATUS_CFG_CHANGED));
+               udelay(40);
+               tg3_write_mem(tp,
+                             NIC_SRAM_FIRMWARE_MBOX,
+                             NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
+       }
+
+       /* Prevent send BD corruption. */
+       if (tg3_flag(tp, CLKREQ_BUG)) {
+               u16 oldlnkctl, newlnkctl;
+
+               pci_read_config_word(tp->pdev,
+                                    tp->pcie_cap + PCI_EXP_LNKCTL,
+                                    &oldlnkctl);
+               if (tp->link_config.active_speed == SPEED_100 ||
+                   tp->link_config.active_speed == SPEED_10)
+                       newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
+               else
+                       newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
+               if (newlnkctl != oldlnkctl)
+                       pci_write_config_word(tp->pdev,
+                                             tp->pcie_cap + PCI_EXP_LNKCTL,
+                                             newlnkctl);
+       }
+
+       if (current_link_up != netdev_link_ok(tp->dev)) {
+               if (current_link_up)
+                       netdev_link_up(tp->dev);
+               else
+                       netdev_link_down(tp->dev);
+               tg3_link_report(tp);
+       }
+
+       return 0;
+}
+
+int tg3_setup_phy(struct tg3 *tp, int force_reset)
+{      DBGP("%s\n", __func__);
+
+       u32 val;
+       int err;
+
+#if 0
+       if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
+               err = tg3_setup_fiber_phy(tp, force_reset);
+       else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+               err = tg3_setup_fiber_mii_phy(tp, force_reset);
+       else
+#endif
+       /* FIXME: add only copper phy variants for now */
+       err = tg3_setup_copper_phy(tp, force_reset);
+
+       val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+             (6 << TX_LENGTHS_IPG_SHIFT);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               val |= tr32(MAC_TX_LENGTHS) &
+                      (TX_LENGTHS_JMB_FRM_LEN_MSK |
+                       TX_LENGTHS_CNT_DWN_VAL_MSK);
+
+       if (tp->link_config.active_speed == SPEED_1000 &&
+           tp->link_config.active_duplex == DUPLEX_HALF)
+               tw32(MAC_TX_LENGTHS, val |
+                    (0xff << TX_LENGTHS_SLOT_TIME_SHIFT));
+       else
+               tw32(MAC_TX_LENGTHS, val |
+                    (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
+
+       if (!tg3_flag(tp, 5705_PLUS)) {
+               if (netdev_link_ok(tp->dev)) {
+                       tw32(HOSTCC_STAT_COAL_TICKS, DEFAULT_STAT_COAL_TICKS);
+               } else {
+                       tw32(HOSTCC_STAT_COAL_TICKS, 0);
+               }
+       }
+
+       val = tr32(PCIE_PWR_MGMT_THRESH);
+       if (!netdev_link_ok(tp->dev))
+               val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK);
+       else
+               val |= PCIE_PWR_MGMT_L1_THRESH_MSK;
+       tw32(PCIE_PWR_MGMT_THRESH, val);
+
+       return err;
+}