diff mbox

[U-Boot,RFC] Tigon III (bcm57xx) Driver on fsl platforms

Message ID 293C5061-60B5-458B-B586-D66B0ED36983@servergy.com
State Rejected
Delegated to: Wolfgang Denk
Headers show

Commit Message

Benjamin Collins Dec. 19, 2013, 3:50 p.m. UTC
Hello all,

(Note, I am not subscribed to the list, so please make sure to keep me in Cc)

I am working on a p4080 based system (Freescale 32-bit Power). In order to support specific peripherals, I needed to have the tg3 driver. The old bcm570x driver that was removed from U-Boot some time ago does not support the 5720 chip that I'm working with (not to mention, the code is horrid), so I took the larger step of porting the FreeBSD if_bge driver to U-Boot.

This has been largely successful. The PCIe chip is detected and probed. I can RX packets without any issues, however TX has some odd issues where even though the SBD consumer ACKs the packet as coalesced (which shows that it was DMAd to the Write-FIFO), the packet never shows up on the wire. This is generally an ARP-Request packet. For the most part, once ARP succeeds, things like TFTP request and ACK packets are sent without issues. All of these packets are, for the most part, less than 60 bytes (which means the tg3 chip pads them out to 60).

Using wireshark confirms that packets are not being sent, and reading the HCOutOctets stat register after coalescing a packet confirms that it did indeed write this packet.

Another issue I'm having is that I'm currently having to pace the CSR_READ_4()/CSR_WRITE_4() macros (readl/writel) with a udelay to take care of a random hang during register read/write.

All of these issues are reproducible on a p4080ds and t4240qds. I'm not sure if either of them are specific to the platform (perhaps issues with memory mapping and DMA?), but I would appreciate some help on these problems.

Driver code attached:

From fa8d4292bae02dbaf0afa9ce6a4a288bf762174f Mon Sep 17 00:00:00 2001
From: Ben Collins <ben.c@servergy.com>
Date: Thu, 19 Dec 2013 10:05:16 -0500
Subject: [PATCH] if_bge: New driver to support Broadcom Tigon III (NetXtreme)
ethernet

This driver was ported from FreeBSD.

Signed-off-by: Ben Collins <ben.c@servergy.com>
---
drivers/net/Makefile    |    1 +
drivers/net/if_bge.c    | 3884 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/if_bgereg.h | 3010 ++++++++++++++++++++++++++++++++++++
include/netdev.h        |    4 +
4 files changed, 6899 insertions(+)
create mode 100644 drivers/net/if_bge.c
create mode 100644 drivers/net/if_bgereg.h

Comments

Wolfgang Denk Dec. 19, 2013, 7:52 p.m. UTC | #1
Dear Ben Collins,

In message <293C5061-60B5-458B-B586-D66B0ED36983@servergy.com> you wrote:
> 
> (Note, I am not subscribed to the list, so please make sure to keep me
> in Cc)

No, please subscribe if you plan to submit patches.

> I am working on a p4080 based system (Freescale 32-bit Power). In order
> to support specific peripherals, I needed to have the tg3 driver. The
> old bcm570x driver that was removed from U-Boot some time ago does not
> support the 5720 chip that I'm working with (not to mention, the code is
> horrid), so I took the larger step of porting the FreeBSD if_bge driver
> to U-Boot.

May I ask why you did not rather use corresponding the Linux driver?

> drivers/net/Makefile    |    1 +
> drivers/net/if_bge.c    | 3884
> +++++++++++++++++++++++++++++++++++++++++++++++
> drivers/net/if_bgereg.h | 3010 ++++++++++++++++++++++++++++++++++++

Urgh.  Are you really, really sure all of this is needed?

...
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. All advertising materials mentioning features or use of this software
> + *    must display the following acknowledgement:
> + *	This product includes software developed by Bill Paul.
> + * 4. Neither the name of the author nor the names of any co-contributors
> + *    may be used to endorse or promote products derived from this software
> + *    without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
> + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> + * THE POSSIBILITY OF SUCH DAMAGE.
> + */

This is the original aka “4-clause" BSD license with the obnoxious BSD
advertising clause.  It is not compatible with the GNU GPL, so we
cannot accept this code.  Please check if it can be relicensed (which
may be difficult as you will probably need permission from the
original author).

Please also note that we do not include full license headers in
U-Boot; we use SPDX license IDs instead.

In addition, checkpatch reports 679 errors, 311 warnings for your file
that would need to be cleaned up before you submit it again.

...
...
> +static void
> +bge_writemem_direct(struct bge_softc *sc, int off, int val)
> +{
> +	CSR_WRITE_4(sc, off, val);
> +}
...
> +/*
> + * BAR0 MAC register access macros. The Tigon always uses memory mapped
> register
> + * accesses and all registers must be accessed with 32 bit operations.
> + */
> +#if 1
> +#define CSR_WRITE_4(sc, reg, val) \
> +	({ bus_write_4(sc->bge_res, reg, val); udelay(10); })
> +#define CSR_READ_4(sc, reg) \
> +	({ u32 val = bus_read_4(sc->bge_res, reg); udelay(10); val; })

This is totally unacceptable.  Please make sure to use proper I/O
accessors instead (which include the required memory barriers so your
delays will not be needed).


Sorry, but this code cannot go into mainline in it's current form.

Best regards,

Wolfgang Denk
Benjamin Collins Dec. 19, 2013, 9:07 p.m. UTC | #2
To answer most of your questions, I'm not entirely worried about the issues you are, I am just looking for help getting it working right now. I'll cross the license/submit bridge when I get to it. 

> On Dec 19, 2013, at 2:52 PM, Wolfgang Denk <wd@denx.de> wrote:
> 
> Dear Ben Collins,
> 
> In message <293C5061-60B5-458B-B586-D66B0ED36983@servergy.com> you wrote:
>> 
>> (Note, I am not subscribed to the list, so please make sure to keep me
>> in Cc)
> 
> No, please subscribe if you plan to submit patches.
> 
>> I am working on a p4080 based system (Freescale 32-bit Power). In order
>> to support specific peripherals, I needed to have the tg3 driver. The
>> old bcm570x driver that was removed from U-Boot some time ago does not
>> support the 5720 chip that I'm working with (not to mention, the code is
>> horrid), so I took the larger step of porting the FreeBSD if_bge driver
>> to U-Boot.
> 
> May I ask why you did not rather use corresponding the Linux driver?
> 
>> drivers/net/Makefile    |    1 +
>> drivers/net/if_bge.c    | 3884
>> +++++++++++++++++++++++++++++++++++++++++++++++
>> drivers/net/if_bgereg.h | 3010 ++++++++++++++++++++++++++++++++++++
> 
> Urgh.  Are you really, really sure all of this is needed?
> 
> ...
>> + * Redistribution and use in source and binary forms, with or without
>> + * modification, are permitted provided that the following conditions
>> + * are met:
>> + * 1. Redistributions of source code must retain the above copyright
>> + *    notice, this list of conditions and the following disclaimer.
>> + * 2. Redistributions in binary form must reproduce the above copyright
>> + *    notice, this list of conditions and the following disclaimer in the
>> + *    documentation and/or other materials provided with the distribution.
>> + * 3. All advertising materials mentioning features or use of this software
>> + *    must display the following acknowledgement:
>> + *    This product includes software developed by Bill Paul.
>> + * 4. Neither the name of the author nor the names of any co-contributors
>> + *    may be used to endorse or promote products derived from this software
>> + *    without specific prior written permission.
>> + *
>> + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
>> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
>> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
>> + * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
>> + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
>> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
>> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
>> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
>> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
>> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
>> + * THE POSSIBILITY OF SUCH DAMAGE.
>> + */
> 
> This is the original aka “4-clause" BSD license with the obnoxious BSD
> advertising clause.  It is not compatible with the GNU GPL, so we
> cannot accept this code.  Please check if it can be relicensed (which
> may be difficult as you will probably need permission from the
> original author).
> 
> Please also note that we do not include full license headers in
> U-Boot; we use SPDX license IDs instead.
> 
> In addition, checkpatch reports 679 errors, 311 warnings for your file
> that would need to be cleaned up before you submit it again.
> 
> ...
> ...
>> +static void
>> +bge_writemem_direct(struct bge_softc *sc, int off, int val)
>> +{
>> +    CSR_WRITE_4(sc, off, val);
>> +}
> ...
>> +/*
>> + * BAR0 MAC register access macros. The Tigon always uses memory mapped
>> register
>> + * accesses and all registers must be accessed with 32 bit operations.
>> + */
>> +#if 1
>> +#define CSR_WRITE_4(sc, reg, val) \
>> +    ({ bus_write_4(sc->bge_res, reg, val); udelay(10); })
>> +#define CSR_READ_4(sc, reg) \
>> +    ({ u32 val = bus_read_4(sc->bge_res, reg); udelay(10); val; })
> 
> This is totally unacceptable.  Please make sure to use proper I/O
> accessors instead (which include the required memory barriers so your
> delays will not be needed).
> 
> 
> Sorry, but this code cannot go into mainline in it's current form.
> 
> Best regards,
> 
> Wolfgang Denk
> 
> -- 
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
> You got to learn three things. What's  real,  what's  not  real,  and
> what's the difference."           - Terry Pratchett, _Witches Abroad_
Wolfgang Denk Dec. 20, 2013, 7:01 a.m. UTC | #3
Dear Ben Collins,

Please don't top post / full quote.

In message <DC9085B5-25ED-465A-B42F-B243FC9D78A2@servergy.com> you wrote:
> To answer most of your questions, I'm not entirely worried about the issues
> you are, I am just looking for help getting it working right now. I'll cross
> the license/submit bridge when I get to it.

Hm... I would expect it was easier to get the Linux driver adapted.
There is a large number of issues (techincal and formal) with the code
you have, so adapting it so make it acceptable for U-Boot looks like a
major reqork to me.

Best regards,

Wolfgang Denk
Benjamin Collins Dec. 20, 2013, 4:02 p.m. UTC | #4
On Dec 20, 2013, at 2:01 AM, Wolfgang Denk <wd@denx.de> wrote:

> Dear Ben Collins,
> 
> Please don't top post / full quote.

I top posted because I didn't want to underpost each comment. I full quoted because I was on my phone. It's ok.

> In message <DC9085B5-25ED-465A-B42F-B243FC9D78A2@servergy.com> you wrote:
>> To answer most of your questions, I'm not entirely worried about the issues
>> you are, I am just looking for help getting it working right now. I'll cross
>> the license/submit bridge when I get to it.
> 
> Hm... I would expect it was easier to get the Linux driver adapted.
> There is a large number of issues (techincal and formal) with the code
> you have, so adapting it so make it acceptable for U-Boot looks like a
> major reqork to me.

Obviously you haven't looked at the Linux driver. It's twice as much code (the code I sent is 1/2 of what the original BGE driver is and 1/4 of what the Linux driver is). While I know the tg3 Linux driver is a great driver, it was an exceptional amount of work to get it ported. I need this driver done yesterday.

The one "technical issue" you pointed out is in fact not a technical issue. The driver uses writel/readl (follow the macros). I have only begun to port this driver and as such, a lot of wrappers are still there to alleviate a lot of code changes from the original driver to make it easier to compare and contrast during this initial porting phase.

Seriously, I don't want this driver reviewed from an inclusion perspective. Obviously you didn't see the top of my post where I said "RFC" and how I was asking with help with functional issues concerning this driver. Please ignore it until I send a formal request to include something.

--
Ben Collins - Principal Architect
Servergy, Inc. - www.servergy.com
Tom Rini Dec. 20, 2013, 9:30 p.m. UTC | #5
On Fri, Dec 20, 2013 at 11:02:01AM -0500, Ben Collins wrote:
> On Dec 20, 2013, at 2:01 AM, Wolfgang Denk <wd@denx.de> wrote:
[snip]
> > In message <DC9085B5-25ED-465A-B42F-B243FC9D78A2@servergy.com> you wrote:
> >> To answer most of your questions, I'm not entirely worried about the issues
> >> you are, I am just looking for help getting it working right now. I'll cross
> >> the license/submit bridge when I get to it.
> > 
> > Hm... I would expect it was easier to get the Linux driver adapted.
> > There is a large number of issues (techincal and formal) with the code
> > you have, so adapting it so make it acceptable for U-Boot looks like a
> > major reqork to me.
> 
> Obviously you haven't looked at the Linux driver. It's twice as much code (the code I sent is 1/2 of what the original BGE driver is and 1/4 of what the Linux driver is). While I know the tg3 Linux driver is a great driver, it was an exceptional amount of work to get it ported. I need this driver done yesterday.
> 
> The one "technical issue" you pointed out is in fact not a technical issue. The driver uses writel/readl (follow the macros). I have only begun to port this driver and as such, a lot of wrappers are still there to alleviate a lot of code changes from the original driver to make it easier to compare and contrast during this initial porting phase.

The bit where it's damned near impossible to "easily" see that oh, crazy
complex macro has been ported to use the right thing in the end means
that fixing your technical issues is something you're unlikely to get
support for, outside of anyone else that happens to need this driver,
and have some time, and not be worried about the legal problem (which,
uh, at the end of the day is a problem you need to solve I suspect for
your uses).

As you say, it's an RFC, and the main comments are "Uh, port the Linux
kernel driver, we've got lots of compat wrappers as needed already and
we know what they do, so we don't get bogged down in general WTF is this
doing? problems".
Wolfgang Denk Dec. 20, 2013, 10:38 p.m. UTC | #6
Dear Ben Collins,

In message <9828628C-230D-48DE-AEAC-8F7A46E29BC9@servergy.com> you wrote:
> 
> Seriously, I don't want this driver reviewed from an inclusion
> perspective. Obviously you didn't see the top of my post where I said
> "RFC" and how I was asking with help with functional issues concerning
> this driver. Please ignore it until I send a formal request to include
> something.

Well, we are discussing mainline code here, and if you submit a patch,
we assume it is intended for mainline.  If it is not, I will not spend
any more efforts on a review.  Thanks for pointing out.

Best regards,

Wolfgang Denk
diff mbox

Patch

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 7f9ce90..f9d58ec 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -11,6 +11,7 @@  obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
+obj-$(CONFIG_BGE_ETH) += if_bge.o
obj-$(CONFIG_CALXEDA_XGMAC) += calxedaxgmac.o
obj-$(CONFIG_CS8900) += cs8900.o
obj-$(CONFIG_TULIP) += dc2114x.o
diff --git a/drivers/net/if_bge.c b/drivers/net/if_bge.c
new file mode 100644
index 0000000..8a50069
--- /dev/null
+++ b/drivers/net/if_bge.c
@@ -0,0 +1,3884 @@ 
+/*-
+ * Copyright (c) 2001 Wind River Systems
+ * Copyright (c) 1997, 1998, 1999, 2001
+ *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
+ * Copyright (c) 2013 Servergy, Inc.
+ *	Ben Collins <ben.c@servergy.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Broadcom BCM57xx(x)/BCM590x NetXtreme and NetLink family Ethernet driver
+ *
+ * The Broadcom BCM5700 is based on technology originally developed by
+ * Alteon Networks as part of the Tigon I and Tigon II Gigabit Ethernet
+ * MAC chips. The BCM5700, sometimes referred to as the Tigon III, has
+ * two on-board MIPS R4000 CPUs and can have as much as 16MB of external
+ * SSRAM. The BCM5700 supports TCP, UDP and IP checksum offload, jumbo
+ * frames, highly configurable RX filtering, and 16 RX and TX queues
+ * (which, along with RX filter rules, can be used for QOS applications).
+ * Other features, such as TCP segmentation, may be available as part
+ * of value-added firmware updates. Unlike the Tigon I and Tigon II,
+ * firmware images can be stored in hardware and need not be compiled
+ * into the driver.
+ *
+ * The BCM5700 supports the PCI v2.2 and PCI-X v1.0 standards, and will
+ * function in a 32-bit/64-bit 33/66Mhz bus, or a 64-bit/133Mhz bus.
+ *
+ * The BCM5701 is a single-chip solution incorporating both the BCM5700
+ * MAC and a BCM5401 10/100/1000 PHY. Unlike the BCM5700, the BCM5701
+ * does not support external SSRAM.
+ *
+ * Broadcom also produces a variation of the BCM5700 under the "Altima"
+ * brand name, which is functionally similar but lacks PCI-X support.
+ *
+ * Without external SSRAM, you can only have at most 4 TX rings,
+ * and the use of the mini RX ring is disabled. This seems to imply
+ * that these features are simply not available on the BCM5701. As a
+ * result, this driver does not implement any support for the mini RX
+ * ring.
+ */
+
+#include <common.h>
+
+#include <errno.h>
+#include <net.h>
+#include <pci.h>
+#include <malloc.h>
+#include <miiphy.h>
+#include <linux/compat.h>
+
+/* Compatibility with FreeBSD functions and such */
+
+#define device_printf(__d, __fmt, __args...) \
+		printf("BGE@%02x:%02x.%d: " __fmt, PCI_BUS(__d), \
+		       PCI_DEV(__d), PCI_FUNC(__d), ##__args)
+
+#define bswap32(__x)		swab32(__x)
+#define bzero(__b, __l)		memset(__b, 0, __l)
+
+#define bus_read_4(__r, __a)		readl(__r + __a)
+#define bus_write_4(__r, __a, __v)	writel(__v, __r + __a)
+
+#define pci_get_function(__d)		PCI_FUNC(__d)
+
+#define DELAY				udelay
+
+#define ETHER_ADDR_LEN		6	/* length of an Ethernet address */
+#define ETHER_TYPE_LEN		2	/* length of the Ethernet type field */
+#define ETHER_CRC_LEN		4	/* length of the Ethernet CRC */
+#define ETHER_HDR_LEN		(ETHER_ADDR_LEN*2+ETHER_TYPE_LEN)
+#define ETHER_MAX_LEN		1518	/* maximum frame len, including CRC */
+#define ETHER_MAX_LEN_JUMBO	9018	/* max jumbo frame len, including CRC */
+#define ETHER_VLAN_ENCAP_LEN	4	/* len of 802.1Q VLAN encapsulation */
+#define ETHER_ALIGN		2
+
+#define MCLSHIFT			11		/* convert bytes to mbuf clusters */
+#define MCLBYTES			(1 << MCLSHIFT)	/* size of an mbuf cluster */
+#define MJUM9BYTES			(9 * 1024)	/* jumbo cluster 9k */
+#define BGE_DEFAULT_MTU			1500
+#define ETHERMTU			(ETHER_MAX_LEN_JUMBO - ETHER_HDR_LEN - ETHER_CRC_LEN)
+
+#define BRGPHY_MII_1000CTL      0x09    /* 1000baseT control */
+#define BRGPHY_MII_AUXCTL       0x18    /* AUX control */
+
+/* PCIY and PCIE definitiaions taken from pciregs.h in FreeBSD */
+/* Capability Identification Numbers */
+#define PCIY_PMG	0x01	/* PCI Power Management */
+#define PCIY_AGP	0x02	/* AGP */
+#define PCIY_VPD	0x03	/* Vital Product Data */
+#define PCIY_SLOTID	0x04	/* Slot Identification */
+#define PCIY_MSI	0x05	/* Message Signaled Interrupts */
+#define PCIY_CHSWP	0x06	/* CompactPCI Hot Swap */
+#define PCIY_PCIX	0x07	/* PCI-X */
+#define PCIY_HT		0x08	/* HyperTransport */
+#define PCIY_VENDOR	0x09	/* Vendor Unique */
+#define PCIY_DEBUG	0x0a	/* Debug port */
+#define PCIY_CRES	0x0b	/* CompactPCI central resource control */
+#define PCIY_HOTPLUG	0x0c	/* PCI Hot-Plug */
+#define PCIY_SUBVENDOR	0x0d	/* PCI-PCI bridge subvendor ID */
+#define PCIY_AGP8X	0x0e	/* AGP 8x */
+#define PCIY_SECDEV	0x0f	/* Secure Device */
+#define PCIY_EXPRESS	0x10	/* PCI Express */
+#define PCIY_MSIX	0x11	/* MSI-X */
+#define PCIY_SATA	0x12	/* SATA */
+#define PCIY_PCIAF	0x13	/* PCI Advanced Features */
+
+#define PCIXR_COMMAND			0x2
+#define  PCIXM_COMMAND_DPERR_E          0x0001  /* Data Parity Error Recovery */
+#define  PCIXM_COMMAND_ERO              0x0002  /* Enable Relaxed Ordering */
+#define  PCIXM_COMMAND_MAX_READ         0x000c  /* Maximum Burst Read Count */
+#define  PCIXM_COMMAND_MAX_READ_512     0x0000
+#define  PCIXM_COMMAND_MAX_READ_1024    0x0004
+#define  PCIXM_COMMAND_MAX_READ_2048    0x0008
+#define  PCIXM_COMMAND_MAX_READ_4096    0x000c
+#define  PCIXM_COMMAND_MAX_SPLITS       0x0070  /* Maximum Split Transactions */
+#define  PCIXM_COMMAND_MAX_SPLITS_1     0x0000
+#define  PCIXM_COMMAND_MAX_SPLITS_2     0x0010
+#define  PCIXM_COMMAND_MAX_SPLITS_3     0x0020
+#define  PCIXM_COMMAND_MAX_SPLITS_4     0x0030
+#define  PCIXM_COMMAND_MAX_SPLITS_8     0x0040
+#define  PCIXM_COMMAND_MAX_SPLITS_12    0x0050
+#define  PCIXM_COMMAND_MAX_SPLITS_16    0x0060
+#define  PCIXM_COMMAND_MAX_SPLITS_32    0x0070
+#define  PCIXM_COMMAND_VERSION          0x3000
+#define PCIR_MSI_CTRL			0x2
+#define  PCIM_MSICTRL_MSI_ENABLE	0x0001
+#define PCIER_DEVICE_CAP		0x4
+#define  PCIEM_CAP_MAX_PAYLOAD		0x00000007
+#define PCIER_DEVICE_CTL		0x8
+#define  PCIEM_CTL_COR_ENABLE		0x0001
+#define  PCIEM_CTL_NFER_ENABLE		0x0002
+#define  PCIEM_CTL_FER_ENABLE		0x0004
+#define  PCIEM_CTL_URR_ENABLE		0x0008
+#define  PCIEM_CTL_RELAXED_ORD_ENABLE	0x0010
+#define  PCIEM_CTL_MAX_PAYLOAD		0x00e0
+#define  PCIEM_CTL_EXT_TAG_FIELD	0x0100
+#define  PCIEM_CTL_PHANTHOM_FUNCS	0x0200
+#define  PCIEM_CTL_AUX_POWER_PM		0x0400
+#define  PCIEM_CTL_NOSNOOP_ENABLE	0x0800
+#define  PCIEM_CTL_MAX_READ_REQUEST	0x7000
+#define  PCIEM_CTL_BRDG_CFG_RETRY	0x8000  /* PCI-E - PCI/PCI-X bridges */
+#define  PCIEM_CTL_INITIATE_FLR		0x8000  /* FLR capable endpoints */
+#define PCIER_DEVICE_STA		0xa
+#define  PCIEM_STA_CORRECTABLE_ERROR	0x0001
+#define  PCIEM_STA_NON_FATAL_ERROR	0x0002
+#define  PCIEM_STA_FATAL_ERROR		0x0004
+#define  PCIEM_STA_UNSUPPORTED_REQ	0x0008
+#define  PCIEM_STA_AUX_POWER		0x0010
+#define  PCIEM_STA_TRANSACTION_PND	0x0020
+
+typedef uint32_t bus_size_t;
+typedef pci_dev_t device_t;
+
+#ifdef DEBUG
+#define bootverbose 1
+#else
+#define bootverbose 0
+#endif
+
+static uint32_t pci_read_config(pci_dev_t dev, int where, int len)
+{
+	uint8_t val8;
+	uint16_t val16;
+	uint32_t val32;
+
+	switch (len) {
+	case 1:
+		pci_read_config_byte(dev, where, &val8);
+		return val8;
+
+	case 2:
+		pci_read_config_word(dev, where, &val16);
+		return val16;
+
+	case 4:
+		pci_read_config_dword(dev, where, &val32);
+		return val32;
+
+	default:
+		device_printf(dev, "Invalid PCI read length: %d\n", len);
+	}
+
+	return ~0;
+}
+
+static void pci_write_config(pci_dev_t dev, int where, uint32_t val, int len)
+{
+	if (len == 1)
+		pci_write_config_byte(dev, where, (uint8_t)val);
+	else if (len == 2)
+		pci_write_config_word(dev, where, (uint16_t)val);
+	else if (len == 4)
+		pci_write_config_dword(dev, where, val);
+	else
+		device_printf(dev, "Invalid PCI write length: %d\n", len);
+}
+
+#define pci_get_vendor(__d) \
+		pci_read_config(__d, PCI_VENDOR_ID, 2)
+#define pci_get_device(__d) \
+		pci_read_config(__d, PCI_DEVICE_ID, 2)
+#define pci_get_subvendor(__d) \
+		pci_read_config(__d, PCI_SUBSYSTEM_VENDOR_ID, 2)
+
+/* Taken from dev/pci/pci.c in FreeBSD */
+static int pci_set_max_read_req(pci_dev_t dev, int size)
+{
+	int pos;
+	uint16_t val;
+
+	pos = pci_hose_find_capability(pci_bus_to_hose(PCI_BUS(dev)), dev,
+				       PCIY_EXPRESS);
+	if (!pos)
+		return 0;
+
+	if (size < 128)
+		size = 128;
+	if (size > 4096)
+		size = 4096;
+	size = 1 << (fls(size) - 1);
+	val = pci_read_config(dev, pos + PCIER_DEVICE_CTL, 2);
+	val &= ~PCIEM_CTL_MAX_READ_REQUEST;
+	val |= (fls(size) - 8) << 12;
+	pci_write_config(dev, pos + PCIER_DEVICE_CTL, val, 2);
+
+	return size;
+}
+
+/* TODO Stub. Fill this in some day */
+static int pci_get_vpd_ident(pci_dev_t dev, const char **identptr)
+{
+	return EINVAL;
+}
+
+/* End compatibility section */
+
+#include "if_bgereg.h"
+
+/*
+ * Various supported device vendors/types and their names. Note: the
+ * spec seems to indicate that the hardware still has Alteon's vendor
+ * ID burned into it, though it will always be overriden by the vendor
+ * ID in the EEPROM. Just to be safe, we cover all possibilities.
+ */
+static struct pci_device_id bge_devs[] = {
+	{ ALTEON_VENDORID,	ALTEON_DEVICEID_BCM5700 },
+	{ ALTEON_VENDORID,	ALTEON_DEVICEID_BCM5701 },
+
+	{ ALTIMA_VENDORID,	ALTIMA_DEVICE_AC1000 },
+	{ ALTIMA_VENDORID,	ALTIMA_DEVICE_AC1002 },
+	{ ALTIMA_VENDORID,	ALTIMA_DEVICE_AC9100 },
+
+	{ APPLE_VENDORID,	APPLE_DEVICE_BCM5701 },
+
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5700 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5701 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5702 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5702_ALT },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5702X },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5703 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5703_ALT },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5703X },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5704C },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5704S },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5704S_ALT },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5705 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5705F },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5705K },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5705M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5705M_ALT },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5714C },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5714S },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5715 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5715S },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5717 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5718 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5719 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5720 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5721 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5722 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5723 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5725 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5727 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5750 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5750M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5751 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5751F },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5751M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5752 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5752M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5753 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5753F },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5753M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5754 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5754M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5755 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5755M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5756 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5761 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5761E },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5761S },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5761SE },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5762 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5764 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5780 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5780S },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5781 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5782 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5784 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5785F },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5785G },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5786 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5787 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5787F },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5787M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5788 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5789 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5901 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5901A2 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5903M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5906 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM5906M },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57760 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57761 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57762 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57764 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57765 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57766 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57767 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57780 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57781 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57782 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57785 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57786 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57787 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57788 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57790 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57791 },
+	{ BCOM_VENDORID,	BCOM_DEVICEID_BCM57795 },
+
+	{ SK_VENDORID,		SK_DEVICEID_ALTIMA },
+
+	{ TC_VENDORID,		TC_DEVICEID_3C996 },
+
+	{ FJTSU_VENDORID,	FJTSU_DEVICEID_PW008GE4 },
+	{ FJTSU_VENDORID,	FJTSU_DEVICEID_PW008GE5 },
+	{ FJTSU_VENDORID,	FJTSU_DEVICEID_PP250450 },
+
+	{ 0, 0 }
+};
+
+static const struct bge_vendor {
+	uint16_t	v_id;
+	const char	*v_name;
+} bge_vendors[] = {
+	{ ALTEON_VENDORID,	"Alteon" },
+	{ ALTIMA_VENDORID,	"Altima" },
+	{ APPLE_VENDORID,	"Apple" },
+	{ BCOM_VENDORID,	"Broadcom" },
+	{ SK_VENDORID,		"SysKonnect" },
+	{ TC_VENDORID,		"3Com" },
+	{ FJTSU_VENDORID,	"Fujitsu" },
+
+	{ 0, NULL }
+};
+
+static const struct bge_revision {
+	uint32_t	br_chipid;
+	const char	*br_name;
+} bge_revisions[] = {
+	{ BGE_CHIPID_BCM5700_A0,	"BCM5700 A0" },
+	{ BGE_CHIPID_BCM5700_A1,	"BCM5700 A1" },
+	{ BGE_CHIPID_BCM5700_B0,	"BCM5700 B0" },
+	{ BGE_CHIPID_BCM5700_B1,	"BCM5700 B1" },
+	{ BGE_CHIPID_BCM5700_B2,	"BCM5700 B2" },
+	{ BGE_CHIPID_BCM5700_B3,	"BCM5700 B3" },
+	{ BGE_CHIPID_BCM5700_ALTIMA,	"BCM5700 Altima" },
+	{ BGE_CHIPID_BCM5700_C0,	"BCM5700 C0" },
+	{ BGE_CHIPID_BCM5701_A0,	"BCM5701 A0" },
+	{ BGE_CHIPID_BCM5701_B0,	"BCM5701 B0" },
+	{ BGE_CHIPID_BCM5701_B2,	"BCM5701 B2" },
+	{ BGE_CHIPID_BCM5701_B5,	"BCM5701 B5" },
+	{ BGE_CHIPID_BCM5703_A0,	"BCM5703 A0" },
+	{ BGE_CHIPID_BCM5703_A1,	"BCM5703 A1" },
+	{ BGE_CHIPID_BCM5703_A2,	"BCM5703 A2" },
+	{ BGE_CHIPID_BCM5703_A3,	"BCM5703 A3" },
+	{ BGE_CHIPID_BCM5703_B0,	"BCM5703 B0" },
+	{ BGE_CHIPID_BCM5704_A0,	"BCM5704 A0" },
+	{ BGE_CHIPID_BCM5704_A1,	"BCM5704 A1" },
+	{ BGE_CHIPID_BCM5704_A2,	"BCM5704 A2" },
+	{ BGE_CHIPID_BCM5704_A3,	"BCM5704 A3" },
+	{ BGE_CHIPID_BCM5704_B0,	"BCM5704 B0" },
+	{ BGE_CHIPID_BCM5705_A0,	"BCM5705 A0" },
+	{ BGE_CHIPID_BCM5705_A1,	"BCM5705 A1" },
+	{ BGE_CHIPID_BCM5705_A2,	"BCM5705 A2" },
+	{ BGE_CHIPID_BCM5705_A3,	"BCM5705 A3" },
+	{ BGE_CHIPID_BCM5750_A0,	"BCM5750 A0" },
+	{ BGE_CHIPID_BCM5750_A1,	"BCM5750 A1" },
+	{ BGE_CHIPID_BCM5750_A3,	"BCM5750 A3" },
+	{ BGE_CHIPID_BCM5750_B0,	"BCM5750 B0" },
+	{ BGE_CHIPID_BCM5750_B1,	"BCM5750 B1" },
+	{ BGE_CHIPID_BCM5750_C0,	"BCM5750 C0" },
+	{ BGE_CHIPID_BCM5750_C1,	"BCM5750 C1" },
+	{ BGE_CHIPID_BCM5750_C2,	"BCM5750 C2" },
+	{ BGE_CHIPID_BCM5714_A0,	"BCM5714 A0" },
+	{ BGE_CHIPID_BCM5752_A0,	"BCM5752 A0" },
+	{ BGE_CHIPID_BCM5752_A1,	"BCM5752 A1" },
+	{ BGE_CHIPID_BCM5752_A2,	"BCM5752 A2" },
+	{ BGE_CHIPID_BCM5714_B0,	"BCM5714 B0" },
+	{ BGE_CHIPID_BCM5714_B3,	"BCM5714 B3" },
+	{ BGE_CHIPID_BCM5715_A0,	"BCM5715 A0" },
+	{ BGE_CHIPID_BCM5715_A1,	"BCM5715 A1" },
+	{ BGE_CHIPID_BCM5715_A3,	"BCM5715 A3" },
+	{ BGE_CHIPID_BCM5717_A0,	"BCM5717 A0" },
+	{ BGE_CHIPID_BCM5717_B0,	"BCM5717 B0" },
+	{ BGE_CHIPID_BCM5719_A0,	"BCM5719 A0" },
+	{ BGE_CHIPID_BCM5720_A0,	"BCM5720 A0" },
+	{ BGE_CHIPID_BCM5755_A0,	"BCM5755 A0" },
+	{ BGE_CHIPID_BCM5755_A1,	"BCM5755 A1" },
+	{ BGE_CHIPID_BCM5755_A2,	"BCM5755 A2" },
+	{ BGE_CHIPID_BCM5722_A0,	"BCM5722 A0" },
+	{ BGE_CHIPID_BCM5761_A0,	"BCM5761 A0" },
+	{ BGE_CHIPID_BCM5761_A1,	"BCM5761 A1" },
+	{ BGE_CHIPID_BCM5762_A0,	"BCM5762 A0" },
+	{ BGE_CHIPID_BCM5784_A0,	"BCM5784 A0" },
+	{ BGE_CHIPID_BCM5784_A1,	"BCM5784 A1" },
+	/* 5754 and 5787 share the same ASIC ID */
+	{ BGE_CHIPID_BCM5787_A0,	"BCM5754/5787 A0" },
+	{ BGE_CHIPID_BCM5787_A1,	"BCM5754/5787 A1" },
+	{ BGE_CHIPID_BCM5787_A2,	"BCM5754/5787 A2" },
+	{ BGE_CHIPID_BCM5906_A1,	"BCM5906 A1" },
+	{ BGE_CHIPID_BCM5906_A2,	"BCM5906 A2" },
+	{ BGE_CHIPID_BCM57765_A0,	"BCM57765 A0" },
+	{ BGE_CHIPID_BCM57765_B0,	"BCM57765 B0" },
+	{ BGE_CHIPID_BCM57780_A0,	"BCM57780 A0" },
+	{ BGE_CHIPID_BCM57780_A1,	"BCM57780 A1" },
+
+	{ 0, NULL }
+};
+
+/*
+ * Some defaults for major revisions, so that newer steppings
+ * that we don't know about have a shot at working.
+ */
+static const struct bge_revision bge_majorrevs[] = {
+	{ BGE_ASICREV_BCM5700,		"unknown BCM5700" },
+	{ BGE_ASICREV_BCM5701,		"unknown BCM5701" },
+	{ BGE_ASICREV_BCM5703,		"unknown BCM5703" },
+	{ BGE_ASICREV_BCM5704,		"unknown BCM5704" },
+	{ BGE_ASICREV_BCM5705,		"unknown BCM5705" },
+	{ BGE_ASICREV_BCM5750,		"unknown BCM5750" },
+	{ BGE_ASICREV_BCM5714_A0,	"unknown BCM5714" },
+	{ BGE_ASICREV_BCM5752,		"unknown BCM5752" },
+	{ BGE_ASICREV_BCM5780,		"unknown BCM5780" },
+	{ BGE_ASICREV_BCM5714,		"unknown BCM5714" },
+	{ BGE_ASICREV_BCM5755,		"unknown BCM5755" },
+	{ BGE_ASICREV_BCM5761,		"unknown BCM5761" },
+	{ BGE_ASICREV_BCM5784,		"unknown BCM5784" },
+	{ BGE_ASICREV_BCM5785,		"unknown BCM5785" },
+	/* 5754 and 5787 share the same ASIC ID */
+	{ BGE_ASICREV_BCM5787,		"unknown BCM5754/5787" },
+	{ BGE_ASICREV_BCM5906,		"unknown BCM5906" },
+	{ BGE_ASICREV_BCM57765,		"unknown BCM57765" },
+	{ BGE_ASICREV_BCM57766,		"unknown BCM57766" },
+	{ BGE_ASICREV_BCM57780,		"unknown BCM57780" },
+	{ BGE_ASICREV_BCM5717,		"unknown BCM5717" },
+	{ BGE_ASICREV_BCM5719,		"unknown BCM5719" },
+	{ BGE_ASICREV_BCM5720,		"unknown BCM5720" },
+	{ BGE_ASICREV_BCM5762,		"unknown BCM5762" },
+
+	{ 0, NULL }
+};
+
+#define	BGE_IS_JUMBO_CAPABLE(sc)	((sc)->bge_flags & BGE_FLAG_JUMBO)
+#define	BGE_IS_5700_FAMILY(sc)		((sc)->bge_flags & BGE_FLAG_5700_FAMILY)
+#define	BGE_IS_5705_PLUS(sc)		((sc)->bge_flags & BGE_FLAG_5705_PLUS)
+#define	BGE_IS_5714_FAMILY(sc)		((sc)->bge_flags & BGE_FLAG_5714_FAMILY)
+#define	BGE_IS_575X_PLUS(sc)		((sc)->bge_flags & BGE_FLAG_575X_PLUS)
+#define	BGE_IS_5755_PLUS(sc)		((sc)->bge_flags & BGE_FLAG_5755_PLUS)
+#define	BGE_IS_5717_PLUS(sc)		((sc)->bge_flags & BGE_FLAG_5717_PLUS)
+#define	BGE_IS_57765_PLUS(sc)		((sc)->bge_flags & BGE_FLAG_57765_PLUS)
+
+static uint32_t bge_chipid(device_t);
+
+typedef int (*bge_eaddr_fcn_t)(struct bge_softc *, uint8_t[]);
+
+static int bge_attach(struct bge_softc *);
+static int bge_get_eaddr_mem(struct bge_softc *, uint8_t[]);
+static int bge_get_eaddr_nvram(struct bge_softc *, uint8_t[]);
+static int bge_get_eaddr_eeprom(struct bge_softc *, uint8_t[]);
+static int bge_get_eaddr(struct bge_softc *, uint8_t[]);
+static void bge_asf_driver_up (struct bge_softc *);
+static int bge_init(struct eth_device *bge_dev, bd_t *bis);
+static void bge_stop_block(struct bge_softc *, bus_size_t, uint32_t);
+static void bge_stop(struct bge_softc *);
+static void bge_free_rx_ring_std(struct bge_softc *);
+
+#define	BGE_RESET_SHUTDOWN	0
+#define	BGE_RESET_START		1
+#define	BGE_RESET_SUSPEND	2
+static int bge_reset(struct bge_softc *);
+
+static void bge_ape_lock_init(struct bge_softc *);
+static void bge_ape_read_fw_ver(struct bge_softc *);
+static int bge_ape_lock(struct bge_softc *, int);
+static void bge_ape_unlock(struct bge_softc *, int);
+
+static uint32_t
+bge_readmem_ind(struct bge_softc *sc, int off)
+{
+	device_t dev;
+	uint32_t val;
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906 &&
+	    off >= BGE_STATS_BLOCK && off < BGE_SEND_RING_1_TO_4)
+		return (0);
+
+	dev = sc->bge_dev;
+
+	pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4);
+	val = pci_read_config(dev, BGE_PCI_MEMWIN_DATA, 4);
+	pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4);
+	return (val);
+}
+
+static void
+bge_writemem_ind(struct bge_softc *sc, int off, int val)
+{
+	device_t dev;
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906 &&
+	    off >= BGE_STATS_BLOCK && off < BGE_SEND_RING_1_TO_4)
+		return;
+
+	dev = sc->bge_dev;
+
+	pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4);
+	pci_write_config(dev, BGE_PCI_MEMWIN_DATA, val, 4);
+	pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4);
+}
+
+#ifdef notdef
+static uint32_t
+bge_readreg_ind(struct bge_softc *sc, int off)
+{
+	device_t dev;
+
+	dev = sc->bge_dev;
+
+	pci_write_config(dev, BGE_PCI_REG_BASEADDR, off, 4);
+	return (pci_read_config(dev, BGE_PCI_REG_DATA, 4));
+}
+#endif
+
+static void
+bge_writereg_ind(struct bge_softc *sc, int off, int val)
+{
+	device_t dev;
+
+	dev = sc->bge_dev;
+
+	pci_write_config(dev, BGE_PCI_REG_BASEADDR, off, 4);
+	pci_write_config(dev, BGE_PCI_REG_DATA, val, 4);
+}
+
+static void
+bge_writemem_direct(struct bge_softc *sc, int off, int val)
+{
+	CSR_WRITE_4(sc, off, val);
+}
+
+static void
+bge_writembx(struct bge_softc *sc, int off, int val)
+{
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906)
+		off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI;
+
+	CSR_WRITE_4(sc, off, val);
+	if ((sc->bge_flags & BGE_FLAG_MBOX_REORDER) != 0)
+		CSR_READ_4(sc, off);
+}
+
+/*
+ * Clear all stale locks and select the lock for this driver instance.
+ */
+static void
+bge_ape_lock_init(struct bge_softc *sc)
+{
+	uint32_t bit, regbase;
+	int i;
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+		regbase = BGE_APE_LOCK_GRANT;
+	else
+		regbase = BGE_APE_PER_LOCK_GRANT;
+
+	/* Clear any stale locks. */
+	for (i = BGE_APE_LOCK_PHY0; i <= BGE_APE_LOCK_GPIO; i++) {
+		switch (i) {
+		case BGE_APE_LOCK_PHY0:
+		case BGE_APE_LOCK_PHY1:
+		case BGE_APE_LOCK_PHY2:
+		case BGE_APE_LOCK_PHY3:
+			bit = BGE_APE_LOCK_GRANT_DRIVER0;
+			break;
+		default:
+			if (sc->bge_func_addr == 0)
+				bit = BGE_APE_LOCK_GRANT_DRIVER0;
+			else
+				bit = (1 << sc->bge_func_addr);
+		}
+		APE_WRITE_4(sc, regbase + 4 * i, bit);
+	}
+
+	/* Select the PHY lock based on the device's function number. */
+	switch (sc->bge_func_addr) {
+	case 0:
+		sc->bge_phy_ape_lock = BGE_APE_LOCK_PHY0;
+		break;
+	case 1:
+		sc->bge_phy_ape_lock = BGE_APE_LOCK_PHY1;
+		break;
+	case 2:
+		sc->bge_phy_ape_lock = BGE_APE_LOCK_PHY2;
+		break;
+	case 3:
+		sc->bge_phy_ape_lock = BGE_APE_LOCK_PHY3;
+		break;
+	default:
+		device_printf(sc->bge_dev,
+		    "PHY lock not supported on this function\n");
+	}
+}
+
+/*
+ * Check for APE firmware, set flags, and print version info.
+ */
+static void
+bge_ape_read_fw_ver(struct bge_softc *sc)
+{
+	const char *fwtype;
+	uint32_t apedata, features;
+
+	/* Check for a valid APE signature in shared memory. */
+	apedata = APE_READ_4(sc, BGE_APE_SEG_SIG);
+	if (apedata != BGE_APE_SEG_SIG_MAGIC) {
+		sc->bge_mfw_flags &= ~ BGE_MFW_ON_APE;
+		return;
+	}
+
+	/* Check if APE firmware is running. */
+	apedata = APE_READ_4(sc, BGE_APE_FW_STATUS);
+	if ((apedata & BGE_APE_FW_STATUS_READY) == 0) {
+		device_printf(sc->bge_dev, "APE signature found "
+		    "but FW status not ready! 0x%08x\n", apedata);
+		return;
+	}
+
+	sc->bge_mfw_flags |= BGE_MFW_ON_APE;
+
+	/* Fetch the APE firwmare type and version. */
+	apedata = APE_READ_4(sc, BGE_APE_FW_VERSION);
+	features = APE_READ_4(sc, BGE_APE_FW_FEATURES);
+	if ((features & BGE_APE_FW_FEATURE_NCSI) != 0) {
+		sc->bge_mfw_flags |= BGE_MFW_TYPE_NCSI;
+		fwtype = "NCSI";
+	} else if ((features & BGE_APE_FW_FEATURE_DASH) != 0) {
+		sc->bge_mfw_flags |= BGE_MFW_TYPE_DASH;
+		fwtype = "DASH";
+	} else
+		fwtype = "UNKN";
+
+	/* Print the APE firmware version. */
+	device_printf(sc->bge_dev, "APE FW version: %s v%d.%d.%d.%d\n",
+	    fwtype,
+	    (apedata & BGE_APE_FW_VERSION_MAJMSK) >> BGE_APE_FW_VERSION_MAJSFT,
+	    (apedata & BGE_APE_FW_VERSION_MINMSK) >> BGE_APE_FW_VERSION_MINSFT,
+	    (apedata & BGE_APE_FW_VERSION_REVMSK) >> BGE_APE_FW_VERSION_REVSFT,
+	    (apedata & BGE_APE_FW_VERSION_BLDMSK));
+}
+
+static int
+bge_ape_lock(struct bge_softc *sc, int locknum)
+{
+	uint32_t bit, gnt, req, status;
+	int i, off;
+
+	if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) == 0)
+		return (0);
+
+	/* Lock request/grant registers have different bases. */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5761) {
+		req = BGE_APE_LOCK_REQ;
+		gnt = BGE_APE_LOCK_GRANT;
+	} else {
+		req = BGE_APE_PER_LOCK_REQ;
+		gnt = BGE_APE_PER_LOCK_GRANT;
+	}
+
+	off = 4 * locknum;
+
+	switch (locknum) {
+	case BGE_APE_LOCK_GPIO:
+		/* Lock required when using GPIO. */
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+			return (0);
+		if (sc->bge_func_addr == 0)
+			bit = BGE_APE_LOCK_REQ_DRIVER0;
+		else
+			bit = (1 << sc->bge_func_addr);
+		break;
+	case BGE_APE_LOCK_GRC:
+		/* Lock required to reset the device. */
+		if (sc->bge_func_addr == 0)
+			bit = BGE_APE_LOCK_REQ_DRIVER0;
+		else
+			bit = (1 << sc->bge_func_addr);
+		break;
+	case BGE_APE_LOCK_MEM:
+		/* Lock required when accessing certain APE memory. */
+		if (sc->bge_func_addr == 0)
+			bit = BGE_APE_LOCK_REQ_DRIVER0;
+		else
+			bit = (1 << sc->bge_func_addr);
+		break;
+	case BGE_APE_LOCK_PHY0:
+	case BGE_APE_LOCK_PHY1:
+	case BGE_APE_LOCK_PHY2:
+	case BGE_APE_LOCK_PHY3:
+		/* Lock required when accessing PHYs. */
+		bit = BGE_APE_LOCK_REQ_DRIVER0;
+		break;
+	default:
+		return (EINVAL);
+	}
+
+	/* Request a lock. */
+	APE_WRITE_4(sc, req + off, bit);
+
+	/* Wait up to 1 second to acquire lock. */
+	for (i = 0; i < 20000; i++) {
+		status = APE_READ_4(sc, gnt + off);
+		if (status == bit)
+			break;
+		DELAY(50);
+	}
+
+	/* Handle any errors. */
+	if (status != bit) {
+		device_printf(sc->bge_dev, "APE lock %d request failed! "
+		    "request = 0x%04x[0x%04x], status = 0x%04x[0x%04x]\n",
+		    locknum, req + off, bit & 0xFFFF, gnt + off,
+		    status & 0xFFFF);
+		/* Revoke the lock request. */
+		APE_WRITE_4(sc, gnt + off, bit);
+		return (EBUSY);
+	}
+
+	return (0);
+}
+
+static void
+bge_ape_unlock(struct bge_softc *sc, int locknum)
+{
+	uint32_t bit, gnt;
+	int off;
+
+	if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) == 0)
+		return;
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+		gnt = BGE_APE_LOCK_GRANT;
+	else
+		gnt = BGE_APE_PER_LOCK_GRANT;
+
+	off = 4 * locknum;
+
+	switch (locknum) {
+	case BGE_APE_LOCK_GPIO:
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+			return;
+		if (sc->bge_func_addr == 0)
+			bit = BGE_APE_LOCK_GRANT_DRIVER0;
+		else
+			bit = (1 << sc->bge_func_addr);
+		break;
+	case BGE_APE_LOCK_GRC:
+		if (sc->bge_func_addr == 0)
+			bit = BGE_APE_LOCK_GRANT_DRIVER0;
+		else
+			bit = (1 << sc->bge_func_addr);
+		break;
+	case BGE_APE_LOCK_MEM:
+		if (sc->bge_func_addr == 0)
+			bit = BGE_APE_LOCK_GRANT_DRIVER0;
+		else
+			bit = (1 << sc->bge_func_addr);
+		break;
+	case BGE_APE_LOCK_PHY0:
+	case BGE_APE_LOCK_PHY1:
+	case BGE_APE_LOCK_PHY2:
+	case BGE_APE_LOCK_PHY3:
+		bit = BGE_APE_LOCK_GRANT_DRIVER0;
+		break;
+	default:
+		return;
+	}
+
+	APE_WRITE_4(sc, gnt + off, bit);
+}
+
+/*
+ * Send an event to the APE firmware.
+ */
+static void
+bge_ape_send_event(struct bge_softc *sc, uint32_t event)
+{
+	uint32_t apedata;
+	int i;
+
+	/* NCSI does not support APE events. */
+	if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) == 0)
+		return;
+
+	/* Wait up to 1ms for APE to service previous event. */
+	for (i = 10; i > 0; i--) {
+		if (bge_ape_lock(sc, BGE_APE_LOCK_MEM) != 0)
+			break;
+		apedata = APE_READ_4(sc, BGE_APE_EVENT_STATUS);
+		if ((apedata & BGE_APE_EVENT_STATUS_EVENT_PENDING) == 0) {
+			APE_WRITE_4(sc, BGE_APE_EVENT_STATUS, event |
+			    BGE_APE_EVENT_STATUS_EVENT_PENDING);
+			bge_ape_unlock(sc, BGE_APE_LOCK_MEM);
+			APE_WRITE_4(sc, BGE_APE_EVENT, BGE_APE_EVENT_1);
+			break;
+		}
+		bge_ape_unlock(sc, BGE_APE_LOCK_MEM);
+		DELAY(100);
+	}
+	if (i == 0)
+		device_printf(sc->bge_dev, "APE event 0x%08x send timed out\n",
+		    event);
+}
+
+static void
+bge_ape_driver_state_change(struct bge_softc *sc, int kind)
+{
+	uint32_t apedata, event;
+
+	if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) == 0)
+		return;
+
+	switch (kind) {
+	case BGE_RESET_START:
+		/* If this is the first load, clear the load counter. */
+		apedata = APE_READ_4(sc, BGE_APE_HOST_SEG_SIG);
+		if (apedata != BGE_APE_HOST_SEG_SIG_MAGIC)
+			APE_WRITE_4(sc, BGE_APE_HOST_INIT_COUNT, 0);
+		else {
+			apedata = APE_READ_4(sc, BGE_APE_HOST_INIT_COUNT);
+			APE_WRITE_4(sc, BGE_APE_HOST_INIT_COUNT, ++apedata);
+		}
+		APE_WRITE_4(sc, BGE_APE_HOST_SEG_SIG,
+		    BGE_APE_HOST_SEG_SIG_MAGIC);
+		APE_WRITE_4(sc, BGE_APE_HOST_SEG_LEN,
+		    BGE_APE_HOST_SEG_LEN_MAGIC);
+
+		/* Add some version info if bge(4) supports it. */
+		APE_WRITE_4(sc, BGE_APE_HOST_DRIVER_ID,
+		    BGE_APE_HOST_DRIVER_ID_MAGIC(1, 0));
+		APE_WRITE_4(sc, BGE_APE_HOST_BEHAVIOR,
+		    BGE_APE_HOST_BEHAV_NO_PHYLOCK);
+		APE_WRITE_4(sc, BGE_APE_HOST_HEARTBEAT_INT_MS,
+		    BGE_APE_HOST_HEARTBEAT_INT_DISABLE);
+		APE_WRITE_4(sc, BGE_APE_HOST_DRVR_STATE,
+		    BGE_APE_HOST_DRVR_STATE_START);
+		event = BGE_APE_EVENT_STATUS_STATE_START;
+		break;
+	case BGE_RESET_SHUTDOWN:
+		APE_WRITE_4(sc, BGE_APE_HOST_DRVR_STATE,
+		    BGE_APE_HOST_DRVR_STATE_UNLOAD);
+		event = BGE_APE_EVENT_STATUS_STATE_UNLOAD;
+		break;
+	case BGE_RESET_SUSPEND:
+		event = BGE_APE_EVENT_STATUS_STATE_SUSPEND;
+		break;
+	default:
+		return;
+	}
+
+	bge_ape_send_event(sc, event | BGE_APE_EVENT_STATUS_DRIVER_EVNT |
+	    BGE_APE_EVENT_STATUS_STATE_CHNGE);
+}
+
+static uint8_t
+bge_nvram_getbyte(struct bge_softc *sc, int addr, uint8_t *dest)
+{
+	uint32_t access, byte = 0;
+	int i;
+
+	/* Lock. */
+	CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1);
+	for (i = 0; i < 8000; i++) {
+		if (CSR_READ_4(sc, BGE_NVRAM_SWARB) & BGE_NVRAMSWARB_GNT1)
+			break;
+		DELAY(20);
+	}
+	if (i == 8000)
+		return (1);
+
+	/* Enable access. */
+	access = CSR_READ_4(sc, BGE_NVRAM_ACCESS);
+	CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access | BGE_NVRAMACC_ENABLE);
+
+	CSR_WRITE_4(sc, BGE_NVRAM_ADDR, addr & 0xfffffffc);
+	CSR_WRITE_4(sc, BGE_NVRAM_CMD, BGE_NVRAM_READCMD);
+	for (i = 0; i < BGE_TIMEOUT * 10; i++) {
+		DELAY(10);
+		if (CSR_READ_4(sc, BGE_NVRAM_CMD) & BGE_NVRAMCMD_DONE) {
+			DELAY(10);
+			break;
+		}
+	}
+
+	if (i == BGE_TIMEOUT * 10) {
+		device_printf(sc->bge_dev, "nvram read timed out\n");
+		return (1);
+	}
+
+	/* Get result. */
+	byte = CSR_READ_4(sc, BGE_NVRAM_RDDATA);
+
+	*dest = (bswap32(byte) >> ((addr % 4) * 8)) & 0xFF;
+
+	/* Disable access. */
+	CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access);
+
+	/* Unlock. */
+	CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1);
+	CSR_READ_4(sc, BGE_NVRAM_SWARB);
+
+	return (0);
+}
+
+/*
+ * Read a sequence of bytes from NVRAM.
+ */
+static int
+bge_read_nvram(struct bge_softc *sc, caddr_t dest, int off, int cnt)
+{
+	int err = 0, i;
+	uint8_t byte = 0;
+
+	if (sc->bge_asicrev != BGE_ASICREV_BCM5906)
+		return (1);
+
+	for (i = 0; i < cnt; i++) {
+		err = bge_nvram_getbyte(sc, off + i, &byte);
+		if (err)
+			break;
+		*(dest + i) = byte;
+	}
+
+	return (err ? 1 : 0);
+}
+
+/*
+ * Read a byte of data stored in the EEPROM at address 'addr.' The
+ * BCM570x supports both the traditional bitbang interface and an
+ * auto access interface for reading the EEPROM. We use the auto
+ * access method.
+ */
+static uint8_t
+bge_eeprom_getbyte(struct bge_softc *sc, int addr, uint8_t *dest)
+{
+	int i;
+	uint32_t byte = 0;
+
+	/*
+	 * Enable use of auto EEPROM access so we can avoid
+	 * having to use the bitbang method.
+	 */
+	BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_AUTO_EEPROM);
+
+	/* Reset the EEPROM, load the clock period. */
+	CSR_WRITE_4(sc, BGE_EE_ADDR,
+	    BGE_EEADDR_RESET | BGE_EEHALFCLK(BGE_HALFCLK_384SCL));
+	DELAY(20);
+
+	/* Issue the read EEPROM command. */
+	CSR_WRITE_4(sc, BGE_EE_ADDR, BGE_EE_READCMD | addr);
+
+	/* Wait for completion */
+	for(i = 0; i < BGE_TIMEOUT * 10; i++) {
+		DELAY(10);
+		if (CSR_READ_4(sc, BGE_EE_ADDR) & BGE_EEADDR_DONE)
+			break;
+	}
+
+	if (i == BGE_TIMEOUT * 10) {
+		device_printf(sc->bge_dev, "EEPROM read timed out\n");
+		return (1);
+	}
+
+	/* Get result. */
+	byte = CSR_READ_4(sc, BGE_EE_DATA);
+
+	*dest = (byte >> ((addr % 4) * 8)) & 0xFF;
+
+	return (0);
+}
+
+/*
+ * Read a sequence of bytes from the EEPROM.
+ */
+static int
+bge_read_eeprom(struct bge_softc *sc, caddr_t dest, int off, int cnt)
+{
+	int i, error = 0;
+	uint8_t byte = 0;
+
+	for (i = 0; i < cnt; i++) {
+		error = bge_eeprom_getbyte(sc, off + i, &byte);
+		if (error)
+			break;
+		*(dest + i) = byte;
+	}
+
+	return (error ? 1 : 0);
+}
+
+static int
+bge_miibus_readreg(const char *devname, unsigned char phy,
+    unsigned char reg, unsigned short *retval)
+{
+	struct eth_device *bge_eth = eth_get_dev_by_name(devname);
+	struct bge_softc *sc;
+	uint32_t val;
+	int i;
+
+	*retval = 0;
+
+	if (!bge_eth)
+		return -ENODEV;
+
+	sc = bge_eth->priv;
+
+	if (phy != sc->bge_phy_addr)
+		return -ENODEV;
+
+	if (bge_ape_lock(sc, sc->bge_phy_ape_lock) != 0)
+		return -EBUSY;
+
+	/* Clear the autopoll bit if set, otherwise may trigger PCI errors. */
+	if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
+		CSR_WRITE_4(sc, BGE_MI_MODE,
+		    sc->bge_mi_mode & ~BGE_MIMODE_AUTOPOLL);
+		DELAY(80);
+	}
+
+	CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ | BGE_MICOMM_BUSY |
+	    BGE_MIPHY(phy) | BGE_MIREG(reg));
+
+	/* Poll for the PHY register access to complete. */
+	for (i = 0; i < BGE_TIMEOUT; i++) {
+		DELAY(10);
+		val = CSR_READ_4(sc, BGE_MI_COMM);
+		if ((val & BGE_MICOMM_BUSY) == 0) {
+			DELAY(5);
+			val = CSR_READ_4(sc, BGE_MI_COMM);
+			break;
+		}
+	}
+
+	if (i == BGE_TIMEOUT) {
+		device_printf(sc->bge_dev,
+		    "PHY read timed out (phy %d, reg %d, val 0x%08x)\n",
+		    phy, reg, val);
+		val = 0;
+	}
+
+	/* Restore the autopoll bit if necessary. */
+	if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
+		CSR_WRITE_4(sc, BGE_MI_MODE, sc->bge_mi_mode);
+		DELAY(80);
+	}
+
+	bge_ape_unlock(sc, sc->bge_phy_ape_lock);
+
+	if (val & BGE_MICOMM_READFAIL)
+		return -ENXIO;
+
+	*retval = (val & 0xFFFF);
+
+	return 0;
+}
+
+static int
+bge_miibus_writereg(const char *devname, unsigned char phy,
+    unsigned char reg, unsigned short val)
+{
+	struct eth_device *bge_eth = eth_get_dev_by_name(devname);
+	struct bge_softc *sc;
+	int i;
+
+	if (!bge_eth)
+		return -ENODEV;
+
+	sc = bge_eth->priv;
+
+	if (phy != sc->bge_phy_addr)
+		return -ENODEV;
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906 &&
+	    (reg == BRGPHY_MII_1000CTL || reg == BRGPHY_MII_AUXCTL))
+		return -EINVAL;
+
+	if (bge_ape_lock(sc, sc->bge_phy_ape_lock) != 0)
+		return -EBUSY;
+
+	/* Clear the autopoll bit if set, otherwise may trigger PCI errors. */
+	if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
+		CSR_WRITE_4(sc, BGE_MI_MODE,
+		    sc->bge_mi_mode & ~BGE_MIMODE_AUTOPOLL);
+		DELAY(80);
+	}
+
+	CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY |
+	    BGE_MIPHY(phy) | BGE_MIREG(reg) | val);
+
+	for (i = 0; i < BGE_TIMEOUT; i++) {
+		DELAY(10);
+		if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) {
+			DELAY(5);
+			CSR_READ_4(sc, BGE_MI_COMM); /* dummy read */
+			break;
+		}
+	}
+
+	/* Restore the autopoll bit if necessary. */
+	if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
+		CSR_WRITE_4(sc, BGE_MI_MODE, sc->bge_mi_mode);
+		DELAY(80);
+	}
+
+	bge_ape_unlock(sc, sc->bge_phy_ape_lock);
+
+	if (i == BGE_TIMEOUT)
+		device_printf(sc->bge_dev,
+		    "PHY write timed out (phy %d, reg %d, val 0x%04x)\n",
+		    phy, reg, val);
+
+	return (0);
+}
+
+/*
+ * Intialize a standard receive ring descriptor.
+ */
+static int
+bge_newbuf_std(struct bge_softc *sc, int i)
+{
+	void *data;
+	struct bge_rx_bd *r;
+	int len;
+	phys_addr_t paddr;
+
+	if (sc->bge_flags & BGE_FLAG_JUMBO_STD &&
+	    (BGE_DEFAULT_MTU + ETHER_HDR_LEN + ETHER_CRC_LEN +
+	    ETHER_VLAN_ENCAP_LEN > (MCLBYTES - ETHER_ALIGN)))
+		len = MJUM9BYTES;
+	else
+		len = MCLBYTES;
+
+	data = malloc(len);
+	if (data == NULL)
+		return ENOBUFS;
+
+	paddr = virt_to_phys(data);
+
+	sc->bge_cdata.bge_rx_std_chain[i] = data;
+	sc->bge_cdata.bge_rx_std_seglen[i] = len;
+	r = &sc->bge_ldata.bge_rx_std_ring[sc->bge_std];
+	r->bge_addr.bge_addr_lo = BGE_ADDR_LO(paddr);
+	r->bge_addr.bge_addr_hi = BGE_ADDR_HI(paddr);
+	r->bge_flags = BGE_RXBDFLAG_END;
+	r->bge_len = len;
+	r->bge_idx = i;
+
+	return (0);
+}
+
+/*
+ * Initialize a jumbo receive ring descriptor. This allocates
+ * a jumbo buffer from the pool managed internally by the driver.
+ */
+static int
+bge_newbuf_jumbo(struct bge_softc *sc, int i)
+{
+	phys_addr_t paddr;
+	struct bge_extrx_bd *r;
+	void *data;
+
+	data = malloc(MJUM9BYTES);
+	if (data == NULL)
+		return ENOBUFS;
+
+	paddr = virt_to_phys(data);
+
+	sc->bge_cdata.bge_rx_jumbo_chain[i] = data;
+
+	/*
+	 * Fill in the extended RX buffer descriptor.
+	 */
+	r = &sc->bge_ldata.bge_rx_jumbo_ring[sc->bge_jumbo];
+	r->bge_flags = BGE_RXBDFLAG_JUMBO_RING | BGE_RXBDFLAG_END;
+	r->bge_idx = i;
+	r->bge_len3 = r->bge_len2 = r->bge_len1 = 0;
+	r->bge_addr0.bge_addr_lo = BGE_ADDR_LO(paddr);
+	r->bge_addr0.bge_addr_hi = BGE_ADDR_HI(paddr);
+	r->bge_len0 = MJUM9BYTES;
+
+	return (0);
+}
+
+static int
+bge_init_rx_ring_std(struct bge_softc *sc)
+{
+	int error, i;
+
+	bzero(sc->bge_ldata.bge_rx_std_ring, BGE_STD_RX_RING_SZ);
+	sc->bge_std = 0;
+	for (i = 0; i < BGE_STD_RX_RING_CNT; i++) {
+		if ((error = bge_newbuf_std(sc, i)) != 0)
+			return (error);
+		BGE_INC(sc->bge_std, BGE_STD_RX_RING_CNT);
+	}
+
+	sc->bge_std = 0;
+	bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, BGE_STD_RX_RING_CNT - 1);
+
+	return (0);
+}
+
+static void
+bge_free_rx_ring_std(struct bge_softc *sc)
+{
+	int i;
+
+	for (i = 0; i < BGE_STD_RX_RING_CNT; i++) {
+		if (sc->bge_cdata.bge_rx_std_chain[i] != NULL) {
+			free(sc->bge_cdata.bge_rx_std_chain[i]);
+			sc->bge_cdata.bge_rx_std_chain[i] = NULL;
+		}
+		bzero((char *)&sc->bge_ldata.bge_rx_std_ring[i],
+		    sizeof(struct bge_rx_bd));
+	}
+}
+
+static int
+bge_init_rx_ring_jumbo(struct bge_softc *sc)
+{
+	struct bge_rcb *rcb;
+	int error, i;
+
+	bzero(sc->bge_ldata.bge_rx_jumbo_ring, BGE_JUMBO_RX_RING_SZ);
+	sc->bge_jumbo = 0;
+	for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) {
+		if ((error = bge_newbuf_jumbo(sc, i)) != 0)
+			return (error);
+		BGE_INC(sc->bge_jumbo, BGE_JUMBO_RX_RING_CNT);
+	}
+
+	sc->bge_jumbo = 0;
+
+	/* Enable the jumbo receive producer ring. */
+	rcb = &sc->bge_ldata.bge_info.bge_jumbo_rx_rcb;
+	rcb->bge_maxlen_flags =
+	    BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_USE_EXT_RX_BD);
+	CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags);
+
+	bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, BGE_JUMBO_RX_RING_CNT - 1);
+
+	return (0);
+}
+
+static void
+bge_free_rx_ring_jumbo(struct bge_softc *sc)
+{
+	int i;
+
+	for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) {
+		if (sc->bge_cdata.bge_rx_jumbo_chain[i] != NULL) {
+			free(sc->bge_cdata.bge_rx_jumbo_chain[i]);
+			sc->bge_cdata.bge_rx_jumbo_chain[i] = NULL;
+		}
+		bzero((char *)&sc->bge_ldata.bge_rx_jumbo_ring[i],
+		    sizeof(struct bge_extrx_bd));
+	}
+}
+
+static void
+bge_free_tx_ring(struct bge_softc *sc)
+{
+	int i;
+
+	if (sc->bge_ldata.bge_tx_ring == NULL)
+		return;
+
+	for (i = 0; i < BGE_TX_RING_CNT; i++) {
+		bzero((char *)&sc->bge_ldata.bge_tx_ring[i],
+		    sizeof(struct bge_tx_bd));
+	}
+}
+
+static int
+bge_init_tx_ring(struct bge_softc *sc)
+{
+	sc->bge_tx_saved_considx = 0;
+
+	bzero(sc->bge_ldata.bge_tx_ring, BGE_TX_RING_SZ);
+
+	/* Initialize transmit producer index for host-memory send ring. */
+	sc->bge_tx_prodidx = 0;
+	bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
+
+	/* 5700 b2 errata */
+	if (sc->bge_chiprev == BGE_CHIPREV_5700_BX)
+		bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
+
+	/* NIC-memory send ring not used; initialize to zero. */
+	bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
+	/* 5700 b2 errata */
+	if (sc->bge_chiprev == BGE_CHIPREV_5700_BX)
+		bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
+
+	return (0);
+}
+
+static void
+bge_setpromisc(struct bge_softc *sc)
+{
+	static int default_promisc;
+
+	/* Enable or disable promiscuous mode as needed. */
+	if (default_promisc)
+		BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC);
+	else
+		BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC);
+}
+
+static void
+bge_setvlan(struct bge_softc *sc)
+{
+	static int default_vlan;
+
+	/* Enable or disable VLAN tag stripping as needed. */
+	if (default_vlan)
+		BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_KEEP_VLAN_DIAG);
+	else
+		BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_KEEP_VLAN_DIAG);
+}
+
+static void
+bge_sig_pre_reset(struct bge_softc *sc, int type)
+{
+
+	/*
+	 * Some chips don't like this so only do this if ASF is enabled
+	 */
+	if (sc->bge_asf_mode)
+		bge_writemem_ind(sc, BGE_SRAM_FW_MB, BGE_SRAM_FW_MB_MAGIC);
+
+	if (sc->bge_asf_mode & ASF_NEW_HANDSHAKE) {
+		switch (type) {
+		case BGE_RESET_START:
+			bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+			    BGE_FW_DRV_STATE_START);
+			break;
+		case BGE_RESET_SHUTDOWN:
+			bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+			    BGE_FW_DRV_STATE_UNLOAD);
+			break;
+		case BGE_RESET_SUSPEND:
+			bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+			    BGE_FW_DRV_STATE_SUSPEND);
+			break;
+		}
+	}
+
+	if (type == BGE_RESET_START || type == BGE_RESET_SUSPEND)
+		bge_ape_driver_state_change(sc, type);
+}
+
+static void
+bge_sig_post_reset(struct bge_softc *sc, int type)
+{
+
+	if (sc->bge_asf_mode & ASF_NEW_HANDSHAKE) {
+		switch (type) {
+		case BGE_RESET_START:
+			bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+			    BGE_FW_DRV_STATE_START_DONE);
+			/* START DONE */
+			break;
+		case BGE_RESET_SHUTDOWN:
+			bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+			    BGE_FW_DRV_STATE_UNLOAD_DONE);
+			break;
+		}
+	}
+	if (type == BGE_RESET_SHUTDOWN)
+		bge_ape_driver_state_change(sc, type);
+}
+
+static void
+bge_sig_legacy(struct bge_softc *sc, int type)
+{
+
+	if (sc->bge_asf_mode) {
+		switch (type) {
+		case BGE_RESET_START:
+			bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+			    BGE_FW_DRV_STATE_START);
+			break;
+		case BGE_RESET_SHUTDOWN:
+			bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+			    BGE_FW_DRV_STATE_UNLOAD);
+			break;
+		}
+	}
+}
+
+static void
+bge_stop_fw(struct bge_softc *sc)
+{
+	int i;
+
+	if (sc->bge_asf_mode) {
+		bge_writemem_ind(sc, BGE_SRAM_FW_CMD_MB, BGE_FW_CMD_PAUSE);
+		CSR_WRITE_4(sc, BGE_RX_CPU_EVENT,
+		    CSR_READ_4(sc, BGE_RX_CPU_EVENT) | BGE_RX_CPU_DRV_EVENT);
+
+		for (i = 0; i < 100; i++ ) {
+			if (!(CSR_READ_4(sc, BGE_RX_CPU_EVENT) &
+			    BGE_RX_CPU_DRV_EVENT))
+				break;
+			DELAY(10);
+		}
+	}
+}
+
+static uint32_t
+bge_dma_swap_options(struct bge_softc *sc)
+{
+	uint32_t dma_options;
+
+	dma_options = BGE_MODECTL_WORDSWAP_NONFRAME |
+	    BGE_MODECTL_BYTESWAP_DATA | BGE_MODECTL_WORDSWAP_DATA;
+#ifdef __BIG_ENDIAN
+	dma_options |= BGE_MODECTL_BYTESWAP_NONFRAME;
+#endif
+	return (dma_options);
+}
+
+/*
+ * Do endian, PCI and DMA initialization.
+ */
+static int
+bge_chipinit(struct bge_softc *sc)
+{
+	uint32_t dma_rw_ctl, misc_ctl, mode_ctl;
+	uint16_t val;
+	int i;
+
+	/* Set endianness before we access any non-PCI registers. */
+	misc_ctl = BGE_INIT;
+	pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, misc_ctl, 4);
+
+	/*
+	 * Clear the MAC statistics block in the NIC's
+	 * internal memory.
+	 */
+	for (i = BGE_STATS_BLOCK;
+	    i < BGE_STATS_BLOCK_END + 1; i += sizeof(uint32_t))
+		BGE_MEMWIN_WRITE(sc, i, 0);
+
+	for (i = BGE_STATUS_BLOCK;
+	    i < BGE_STATUS_BLOCK_END + 1; i += sizeof(uint32_t))
+		BGE_MEMWIN_WRITE(sc, i, 0);
+
+	if (sc->bge_chiprev == BGE_CHIPREV_5704_BX) {
+		/*
+		 *  Fix data corruption caused by non-qword write with WB.
+		 *  Fix master abort in PCI mode.
+		 *  Fix PCI latency timer.
+		 */
+		val = pci_read_config(sc->bge_dev, BGE_PCI_MSI_DATA + 2, 2);
+		val |= (1 << 10) | (1 << 12) | (1 << 13);
+		pci_write_config(sc->bge_dev, BGE_PCI_MSI_DATA + 2, val, 2);
+	}
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM57765 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM57766) {
+		/*
+		 * For the 57766 and non Ax versions of 57765, bootcode
+		 * needs to setup the PCIE Fast Training Sequence (FTS)
+		 * value to prevent transmit hangs.
+		 */
+		if (sc->bge_chiprev != BGE_CHIPREV_57765_AX) {
+			CSR_WRITE_4(sc, BGE_CPMU_PADRNG_CTL,
+			    CSR_READ_4(sc, BGE_CPMU_PADRNG_CTL) |
+			    BGE_CPMU_PADRNG_CTL_RDIV2);
+		}
+	}
+
+	/*
+	 * Set up the PCI DMA control register.
+	 */
+	dma_rw_ctl = BGE_PCIDMARWCTL_RD_CMD_SHIFT(6) |
+	    BGE_PCIDMARWCTL_WR_CMD_SHIFT(7);
+	if (sc->bge_flags & BGE_FLAG_PCIE) {
+		if (sc->bge_mps >= 256)
+			dma_rw_ctl |= BGE_PCIDMARWCTL_WR_WAT_SHIFT(7);
+		else
+			dma_rw_ctl |= BGE_PCIDMARWCTL_WR_WAT_SHIFT(3);
+	} else if (sc->bge_flags & BGE_FLAG_PCIX) {
+		if (BGE_IS_5714_FAMILY(sc)) {
+			/* 256 bytes for read and write. */
+			dma_rw_ctl |= BGE_PCIDMARWCTL_RD_WAT_SHIFT(2) |
+			    BGE_PCIDMARWCTL_WR_WAT_SHIFT(2);
+			dma_rw_ctl |= (sc->bge_asicrev == BGE_ASICREV_BCM5780) ?
+			    BGE_PCIDMARWCTL_ONEDMA_ATONCE_GLOBAL :
+			    BGE_PCIDMARWCTL_ONEDMA_ATONCE_LOCAL;
+		} else if (sc->bge_asicrev == BGE_ASICREV_BCM5703) {
+			/*
+			 * In the BCM5703, the DMA read watermark should
+			 * be set to less than or equal to the maximum
+			 * memory read byte count of the PCI-X command
+			 * register.
+			 */
+			dma_rw_ctl |= BGE_PCIDMARWCTL_RD_WAT_SHIFT(4) |
+			    BGE_PCIDMARWCTL_WR_WAT_SHIFT(3);
+		} else if (sc->bge_asicrev == BGE_ASICREV_BCM5704) {
+			/* 1536 bytes for read, 384 bytes for write. */
+			dma_rw_ctl |= BGE_PCIDMARWCTL_RD_WAT_SHIFT(7) |
+			    BGE_PCIDMARWCTL_WR_WAT_SHIFT(3);
+		} else {
+			/* 384 bytes for read and write. */
+			dma_rw_ctl |= BGE_PCIDMARWCTL_RD_WAT_SHIFT(3) |
+			    BGE_PCIDMARWCTL_WR_WAT_SHIFT(3) |
+			    0x0F;
+		}
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5703 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5704) {
+			uint32_t tmp;
+
+			/* Set ONE_DMA_AT_ONCE for hardware workaround. */
+			tmp = CSR_READ_4(sc, BGE_PCI_CLKCTL) & 0x1F;
+			if (tmp == 6 || tmp == 7)
+				dma_rw_ctl |=
+				    BGE_PCIDMARWCTL_ONEDMA_ATONCE_GLOBAL;
+
+			/* Set PCI-X DMA write workaround. */
+			dma_rw_ctl |= BGE_PCIDMARWCTL_ASRT_ALL_BE;
+		}
+	} else {
+		/* Conventional PCI bus: 256 bytes for read and write. */
+		dma_rw_ctl |= BGE_PCIDMARWCTL_RD_WAT_SHIFT(7) |
+		    BGE_PCIDMARWCTL_WR_WAT_SHIFT(7);
+
+		if (sc->bge_asicrev != BGE_ASICREV_BCM5705 &&
+		    sc->bge_asicrev != BGE_ASICREV_BCM5750)
+			dma_rw_ctl |= 0x0F;
+	}
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5700 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5701)
+		dma_rw_ctl |= BGE_PCIDMARWCTL_USE_MRM |
+		    BGE_PCIDMARWCTL_ASRT_ALL_BE;
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5703 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5704)
+		dma_rw_ctl &= ~BGE_PCIDMARWCTL_MINDMA;
+	if (BGE_IS_5717_PLUS(sc)) {
+		dma_rw_ctl &= ~BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT;
+		if (sc->bge_chipid == BGE_CHIPID_BCM57765_A0)
+			dma_rw_ctl &= ~BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK;
+		/*
+		 * Enable HW workaround for controllers that misinterpret
+		 * a status tag update and leave interrupts permanently
+		 * disabled.
+		 */
+		if (!BGE_IS_57765_PLUS(sc) &&
+		    sc->bge_asicrev != BGE_ASICREV_BCM5717 &&
+		    sc->bge_asicrev != BGE_ASICREV_BCM5762)
+			dma_rw_ctl |= BGE_PCIDMARWCTL_TAGGED_STATUS_WA;
+	}
+	pci_write_config(sc->bge_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4);
+
+	/*
+	 * Set up general mode register.
+	 */
+	mode_ctl = bge_dma_swap_options(sc);
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5720 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5762) {
+		/* Retain Host-2-BMC settings written by APE firmware. */
+		mode_ctl |= CSR_READ_4(sc, BGE_MODE_CTL) &
+		    (BGE_MODECTL_BYTESWAP_B2HRX_DATA |
+		    BGE_MODECTL_WORDSWAP_B2HRX_DATA |
+		    BGE_MODECTL_B2HRX_ENABLE | BGE_MODECTL_HTX2B_ENABLE);
+	}
+	mode_ctl |= BGE_MODECTL_MAC_ATTN_INTR | BGE_MODECTL_HOST_SEND_BDS |
+	    BGE_MODECTL_TX_NO_PHDR_CSUM;
+
+	/*
+	 * BCM5701 B5 have a bug causing data corruption when using
+	 * 64-bit DMA reads, which can be terminated early and then
+	 * completed later as 32-bit accesses, in combination with
+	 * certain bridges.
+	 */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5701 &&
+	    sc->bge_chipid == BGE_CHIPID_BCM5701_B5)
+		mode_ctl |= BGE_MODECTL_FORCE_PCI32;
+
+	/*
+	 * Tell the firmware the driver is running
+	 */
+	if (sc->bge_asf_mode & ASF_STACKUP)
+		mode_ctl |= BGE_MODECTL_STACKUP;
+
+	CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl);
+
+	/*
+	 * Disable memory write invalidate.  Apparently it is not supported
+	 * properly by these devices.  Also ensure that INTx isn't disabled,
+	 * as these chips need it even when using MSI.
+	 */
+	PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD,
+	    PCIM_CMD_INTxDIS | PCIM_CMD_MWIEN, 4);
+
+	/* Set the timer prescaler (always 66 MHz). */
+	CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
+
+	/* XXX: The Linux tg3 driver does this at the start of brgphy_reset. */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
+		DELAY(40);	/* XXX */
+
+		/* Put PHY into ready state */
+		BGE_CLRBIT(sc, BGE_MISC_CFG, BGE_MISCCFG_EPHY_IDDQ);
+		CSR_READ_4(sc, BGE_MISC_CFG); /* Flush */
+		DELAY(40);
+	}
+
+	return (0);
+}
+
+static int
+bge_blockinit(struct bge_softc *sc)
+{
+	struct bge_rcb *rcb;
+	bus_size_t vrcb;
+	bge_hostaddr taddr;
+	uint32_t dmactl, rdmareg, val;
+	int i, limit;
+
+	/*
+	 * Initialize the memory window pointer register so that
+	 * we can access the first 32K of internal NIC RAM. This will
+	 * allow us to set up the TX send ring RCBs and the RX return
+	 * ring RCBs, plus other things which live in NIC memory.
+	 */
+	CSR_WRITE_4(sc, BGE_PCI_MEMWIN_BASEADDR, 0);
+
+	/* Note: the BCM5704 has a smaller buf space than other chips. */
+
+	if (!(BGE_IS_5705_PLUS(sc))) {
+		/* Configure buf memory pool */
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_BASEADDR, BGE_BUFFPOOL_1);
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5704)
+			CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x10000);
+		else
+			CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x18000);
+
+		/* Configure DMA resource pool */
+		CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_BASEADDR,
+		    BGE_DMA_DESCRIPTORS);
+		CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LEN, 0x2000);
+	}
+
+	/* Configure buf pool watermarks */
+	if (BGE_IS_5717_PLUS(sc)) {
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0);
+		if (BGE_DEFAULT_MTU > ETHERMTU) {
+			CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x7e);
+			CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xea);
+		} else {
+			CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x2a);
+			CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xa0);
+		}
+	} else if (!BGE_IS_5705_PLUS(sc)) {
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50);
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20);
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60);
+	} else if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0);
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x04);
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x10);
+	} else {
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0);
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10);
+		CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60);
+	}
+
+	/* Configure DMA resource watermarks */
+	CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LOWAT, 5);
+	CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10);
+
+	/* Enable buffer manager */
+	val = BGE_BMANMODE_ENABLE | BGE_BMANMODE_LOMBUF_ATTN;
+	/*
+	 * Change the arbitration algorithm of TXMBUF read request to
+	 * round-robin instead of priority based for BCM5719.  When
+	 * TXFIFO is almost empty, RDMA will hold its request until
+	 * TXFIFO is not almost empty.
+	 */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
+		val |= BGE_BMANMODE_NO_TX_UNDERRUN;
+	CSR_WRITE_4(sc, BGE_BMAN_MODE, val);
+
+	/* Poll for buffer manager start indication */
+	for (i = 0; i < BGE_TIMEOUT; i++) {
+		DELAY(10);
+		if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE)
+			break;
+	}
+
+	if (i == BGE_TIMEOUT) {
+		device_printf(sc->bge_dev, "buffer manager failed to start\n");
+		return (ENXIO);
+	}
+
+	/* Enable flow-through queues */
+	CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF);
+	CSR_WRITE_4(sc, BGE_FTQ_RESET, 0);
+
+	/* Wait until queue initialization is complete */
+	for (i = 0; i < BGE_TIMEOUT; i++) {
+		DELAY(10);
+		if (CSR_READ_4(sc, BGE_FTQ_RESET) == 0)
+			break;
+	}
+
+	if (i == BGE_TIMEOUT) {
+		device_printf(sc->bge_dev, "flow-through queue init failed\n");
+		return (ENXIO);
+	}
+
+	/*
+	 * Summary of rings supported by the controller:
+	 *
+	 * Standard Receive Producer Ring
+	 * - This ring is used to feed receive buffers for "standard"
+	 *   sized frames (typically 1536 bytes) to the controller.
+	 *
+	 * Jumbo Receive Producer Ring
+	 * - This ring is used to feed receive buffers for jumbo sized
+	 *   frames (i.e. anything bigger than the "standard" frames)
+	 *   to the controller.
+	 *
+	 * Mini Receive Producer Ring
+	 * - This ring is used to feed receive buffers for "mini"
+	 *   sized frames to the controller.
+	 * - This feature required external memory for the controller
+	 *   but was never used in a production system.  Should always
+	 *   be disabled.
+	 *
+	 * Receive Return Ring
+	 * - After the controller has placed an incoming frame into a
+	 *   receive buffer that buffer is moved into a receive return
+	 *   ring.  The driver is then responsible to passing the
+	 *   buffer up to the stack.  Many versions of the controller
+	 *   support multiple RR rings.
+	 *
+	 * Send Ring
+	 * - This ring is used for outgoing frames.  Many versions of
+	 *   the controller support multiple send rings.
+	 */
+
+	/* Initialize the standard receive producer ring control block. */
+	rcb = &sc->bge_ldata.bge_info.bge_std_rx_rcb;
+	rcb->bge_hostaddr.bge_addr_lo =
+	    BGE_ADDR_LO(sc->bge_ldata.bge_rx_std_ring_paddr);
+	rcb->bge_hostaddr.bge_addr_hi =
+	    BGE_ADDR_HI(sc->bge_ldata.bge_rx_std_ring_paddr);
+	if (BGE_IS_5717_PLUS(sc)) {
+		/*
+		 * Bits 31-16: Programmable ring size (2048, 1024, 512, .., 32)
+		 * Bits 15-2 : Maximum RX frame size
+		 * Bit 1     : 1 = Ring Disabled, 0 = Ring ENabled
+		 * Bit 0     : Reserved
+		 */
+		rcb->bge_maxlen_flags =
+		    BGE_RCB_MAXLEN_FLAGS(512, BGE_MAX_FRAMELEN << 2);
+	} else if (BGE_IS_5705_PLUS(sc)) {
+		/*
+		 * Bits 31-16: Programmable ring size (512, 256, 128, 64, 32)
+		 * Bits 15-2 : Reserved (should be 0)
+		 * Bit 1     : 1 = Ring Disabled, 0 = Ring Enabled
+		 * Bit 0     : Reserved
+		 */
+		rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(512, 0);
+	} else {
+		/*
+		 * Ring size is always XXX entries
+		 * Bits 31-16: Maximum RX frame size
+		 * Bits 15-2 : Reserved (should be 0)
+		 * Bit 1     : 1 = Ring Disabled, 0 = Ring Enabled
+		 * Bit 0     : Reserved
+		 */
+		rcb->bge_maxlen_flags =
+		    BGE_RCB_MAXLEN_FLAGS(BGE_MAX_FRAMELEN, 0);
+	}
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5720)
+		rcb->bge_nicaddr = BGE_STD_RX_RINGS_5717;
+	else
+		rcb->bge_nicaddr = BGE_STD_RX_RINGS;
+	/* Write the standard receive producer ring control block. */
+	CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi);
+	CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_LO, rcb->bge_hostaddr.bge_addr_lo);
+	CSR_WRITE_4(sc, BGE_RX_STD_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags);
+	CSR_WRITE_4(sc, BGE_RX_STD_RCB_NICADDR, rcb->bge_nicaddr);
+
+	/* Reset the standard receive producer ring producer index. */
+	bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0);
+
+	/*
+	 * Initialize the jumbo RX producer ring control
+	 * block.  We set the 'ring disabled' bit in the
+	 * flags field until we're actually ready to start
+	 * using this ring (i.e. once we set the MTU
+	 * high enough to require it).
+	 */
+	if (BGE_IS_JUMBO_CAPABLE(sc)) {
+		rcb = &sc->bge_ldata.bge_info.bge_jumbo_rx_rcb;
+		/* Get the jumbo receive producer ring RCB parameters. */
+		rcb->bge_hostaddr.bge_addr_lo =
+		    BGE_ADDR_LO(sc->bge_ldata.bge_rx_jumbo_ring_paddr);
+		rcb->bge_hostaddr.bge_addr_hi =
+		    BGE_ADDR_HI(sc->bge_ldata.bge_rx_jumbo_ring_paddr);
+		rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(0,
+		    BGE_RCB_FLAG_USE_EXT_RX_BD | BGE_RCB_FLAG_RING_DISABLED);
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5720)
+			rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS_5717;
+		else
+			rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS;
+		CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI,
+		    rcb->bge_hostaddr.bge_addr_hi);
+		CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_LO,
+		    rcb->bge_hostaddr.bge_addr_lo);
+		/* Program the jumbo receive producer ring RCB parameters. */
+		CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS,
+		    rcb->bge_maxlen_flags);
+		CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_NICADDR, rcb->bge_nicaddr);
+		/* Reset the jumbo receive producer ring producer index. */
+		bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0);
+	}
+
+	/* Disable the mini receive producer ring RCB. */
+	if (BGE_IS_5700_FAMILY(sc)) {
+		rcb = &sc->bge_ldata.bge_info.bge_mini_rx_rcb;
+		rcb->bge_maxlen_flags =
+		    BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_RING_DISABLED);
+		CSR_WRITE_4(sc, BGE_RX_MINI_RCB_MAXLEN_FLAGS,
+		    rcb->bge_maxlen_flags);
+		/* Reset the mini receive producer ring producer index. */
+		bge_writembx(sc, BGE_MBX_RX_MINI_PROD_LO, 0);
+	}
+
+	/* Choose de-pipeline mode for BCM5906 A0, A1 and A2. */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
+		if (sc->bge_chipid == BGE_CHIPID_BCM5906_A0 ||
+		    sc->bge_chipid == BGE_CHIPID_BCM5906_A1 ||
+		    sc->bge_chipid == BGE_CHIPID_BCM5906_A2)
+			CSR_WRITE_4(sc, BGE_ISO_PKT_TX,
+			    (CSR_READ_4(sc, BGE_ISO_PKT_TX) & ~3) | 2);
+	}
+	/*
+	 * The BD ring replenish thresholds control how often the
+	 * hardware fetches new BD's from the producer rings in host
+	 * memory.  Setting the value too low on a busy system can
+	 * starve the hardware and recue the throughpout.
+	 *
+	 * Set the BD ring replentish thresholds. The recommended
+	 * values are 1/8th the number of descriptors allocated to
+	 * each ring.
+	 * XXX The 5754 requires a lower threshold, so it might be a
+	 * requirement of all 575x family chips.  The Linux driver sets
+	 * the lower threshold for all 5705 family chips as well, but there
+	 * are reports that it might not need to be so strict.
+	 *
+	 * XXX Linux does some extra fiddling here for the 5906 parts as
+	 * well.
+	 */
+	if (BGE_IS_5705_PLUS(sc))
+		val = 8;
+	else
+		val = BGE_STD_RX_RING_CNT / 8;
+	CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, val);
+	if (BGE_IS_JUMBO_CAPABLE(sc))
+		CSR_WRITE_4(sc, BGE_RBDI_JUMBO_REPL_THRESH,
+		    BGE_JUMBO_RX_RING_CNT/8);
+	if (BGE_IS_5717_PLUS(sc)) {
+		CSR_WRITE_4(sc, BGE_STD_REPLENISH_LWM, 32);
+		CSR_WRITE_4(sc, BGE_JMB_REPLENISH_LWM, 16);
+	}
+
+	/*
+	 * Disable all send rings by setting the 'ring disabled' bit
+	 * in the flags field of all the TX send ring control blocks,
+	 * located in NIC memory.
+	 */
+	if (!BGE_IS_5705_PLUS(sc))
+		/* 5700 to 5704 had 16 send rings. */
+		limit = BGE_TX_RINGS_EXTSSRAM_MAX;
+	else if (BGE_IS_57765_PLUS(sc) ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5762)
+		limit = 2;
+	else if (BGE_IS_5717_PLUS(sc))
+		limit = 4;
+	else
+		limit = 1;
+	vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB;
+	for (i = 0; i < limit; i++) {
+		RCB_WRITE_4(sc, vrcb, bge_maxlen_flags,
+		    BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_RING_DISABLED));
+		RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0);
+		vrcb += sizeof(struct bge_rcb);
+	}
+
+	/* Configure send ring RCB 0 (we use only the first ring) */
+	vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB;
+	BGE_HOSTADDR(taddr, sc->bge_ldata.bge_tx_ring_paddr);
+	RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, taddr.bge_addr_hi);
+	RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo);
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5720)
+		RCB_WRITE_4(sc, vrcb, bge_nicaddr, BGE_SEND_RING_5717);
+	else
+		RCB_WRITE_4(sc, vrcb, bge_nicaddr,
+		    BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT));
+	RCB_WRITE_4(sc, vrcb, bge_maxlen_flags,
+	    BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0));
+
+	/*
+	 * Disable all receive return rings by setting the
+	 * 'ring diabled' bit in the flags field of all the receive
+	 * return ring control blocks, located in NIC memory.
+	 */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+		/* Should be 17, use 16 until we get an SRAM map. */
+		limit = 16;
+	} else if (!BGE_IS_5705_PLUS(sc))
+		limit = BGE_RX_RINGS_MAX;
+	else if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5762 ||
+	    BGE_IS_57765_PLUS(sc))
+		limit = 4;
+	else
+		limit = 1;
+	/* Disable all receive return rings. */
+	vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB;
+	for (i = 0; i < limit; i++) {
+		RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, 0);
+		RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, 0);
+		RCB_WRITE_4(sc, vrcb, bge_maxlen_flags,
+		    BGE_RCB_FLAG_RING_DISABLED);
+		RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0);
+		bge_writembx(sc, BGE_MBX_RX_CONS0_LO +
+		    (i * (sizeof(uint64_t))), 0);
+		vrcb += sizeof(struct bge_rcb);
+	}
+
+	/*
+	 * Set up receive return ring 0.  Note that the NIC address
+	 * for RX return rings is 0x0.  The return rings live entirely
+	 * within the host, so the nicaddr field in the RCB isn't used.
+	 */
+	vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB;
+	BGE_HOSTADDR(taddr, sc->bge_ldata.bge_rx_return_ring_paddr);
+	RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, taddr.bge_addr_hi);
+	RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo);
+	RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0);
+	RCB_WRITE_4(sc, vrcb, bge_maxlen_flags,
+	    BGE_RCB_MAXLEN_FLAGS(sc->bge_return_ring_cnt, 0));
+
+	/* Set random backoff seed for TX */
+	CSR_WRITE_4(sc, BGE_TX_RANDOM_BACKOFF,
+	    (sc->bge_eth.enetaddr[0] + sc->bge_eth.enetaddr[1] +
+	    sc->bge_eth.enetaddr[2] + sc->bge_eth.enetaddr[3] +
+	    sc->bge_eth.enetaddr[4] + sc->bge_eth.enetaddr[5]) &
+	    BGE_TX_BACKOFF_SEED_MASK);
+
+	/* Set inter-packet gap */
+	val = 0x2620;
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5720 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5762)
+		val |= CSR_READ_4(sc, BGE_TX_LENGTHS) &
+		    (BGE_TXLEN_JMB_FRM_LEN_MSK | BGE_TXLEN_CNT_DN_VAL_MSK);
+	CSR_WRITE_4(sc, BGE_TX_LENGTHS, val);
+
+	/*
+	 * Specify which ring to use for packets that don't match
+	 * any RX rules.
+	 */
+	CSR_WRITE_4(sc, BGE_RX_RULES_CFG, 0x08);
+
+	/*
+	 * Configure number of RX lists. One interrupt distribution
+	 * list, sixteen active lists, one bad frames class.
+	 */
+	CSR_WRITE_4(sc, BGE_RXLP_CFG, 0x181);
+
+	/* Inialize RX list placement stats mask. */
+	CSR_WRITE_4(sc, BGE_RXLP_STATS_ENABLE_MASK, 0x007FFFFF);
+	CSR_WRITE_4(sc, BGE_RXLP_STATS_CTL, 0x1);
+
+	/* Disable host coalescing until we get it set up */
+	CSR_WRITE_4(sc, BGE_HCC_MODE, 0x00000000);
+
+	/* Poll to make sure it's shut down. */
+	for (i = 0; i < BGE_TIMEOUT; i++) {
+		DELAY(10);
+		if (!(CSR_READ_4(sc, BGE_HCC_MODE) & BGE_HCCMODE_ENABLE))
+			break;
+	}
+
+	if (i == BGE_TIMEOUT) {
+		device_printf(sc->bge_dev,
+		    "host coalescing engine failed to idle\n");
+		return (ENXIO);
+	}
+
+	/* Set up host coalescing defaults. Default values taken from
+	 * PG suggestions for systems wishing to get status block
+	 * updates for each and every RX and TX packet coalescing -- BenC */
+	CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS, 1);
+	CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, 0);
+	CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, 1);
+	CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, 1);
+	if (!(BGE_IS_5705_PLUS(sc))) {
+		CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS_INT, 0);
+		CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS_INT, 0);
+	}
+	CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 1);
+	CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 1);
+
+	/* Set up address of statistics block */
+	if (!(BGE_IS_5705_PLUS(sc))) {
+		CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_HI,
+		    BGE_ADDR_HI(sc->bge_ldata.bge_stats_paddr));
+		CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_LO,
+		    BGE_ADDR_LO(sc->bge_ldata.bge_stats_paddr));
+		CSR_WRITE_4(sc, BGE_HCC_STATS_BASEADDR, BGE_STATS_BLOCK);
+		CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_BASEADDR, BGE_STATUS_BLOCK);
+		CSR_WRITE_4(sc, BGE_HCC_STATS_TICKS, BGE_TICKS_PER_SEC);
+	}
+
+	/* Set up address of status block */
+	CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_HI,
+	    BGE_ADDR_HI(sc->bge_ldata.bge_status_block_paddr));
+	CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_LO,
+	    BGE_ADDR_LO(sc->bge_ldata.bge_status_block_paddr));
+
+	/* Set up status block size. */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5700 &&
+	    sc->bge_chipid != BGE_CHIPID_BCM5700_C0) {
+		val = BGE_STATBLKSZ_FULL;
+		bzero(sc->bge_ldata.bge_status_block, BGE_STATUS_BLK_SZ);
+	} else {
+		val = BGE_STATBLKSZ_32BYTE;
+		bzero(sc->bge_ldata.bge_status_block, 32);
+	}
+
+	/* Turn on host coalescing state machine */
+	CSR_WRITE_4(sc, BGE_HCC_MODE, val | BGE_HCCMODE_ENABLE);
+
+	/* Turn on RX BD completion state machine and enable attentions */
+	CSR_WRITE_4(sc, BGE_RBDC_MODE,
+	    BGE_RBDCMODE_ENABLE | BGE_RBDCMODE_ATTN);
+
+	/* Turn on RX list placement state machine */
+	CSR_WRITE_4(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE);
+
+	/* Turn on RX list selector state machine. */
+	if (!(BGE_IS_5705_PLUS(sc)))
+		CSR_WRITE_4(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE);
+
+	/* Turn on DMA, clear stats. */
+	val = BGE_MACMODE_TXDMA_ENB | BGE_MACMODE_RXDMA_ENB |
+	    BGE_MACMODE_RX_STATS_CLEAR | BGE_MACMODE_TX_STATS_CLEAR |
+	    BGE_MACMODE_RX_STATS_ENB | BGE_MACMODE_TX_STATS_ENB |
+	    BGE_MACMODE_FRMHDR_DMA_ENB;
+
+	if (sc->bge_flags & BGE_FLAG_TBI)
+		val |= BGE_PORTMODE_TBI;
+	else if (sc->bge_flags & BGE_FLAG_MII_SERDES)
+		val |= BGE_PORTMODE_GMII;
+	else
+		val |= BGE_PORTMODE_MII;
+
+	/* Allow APE to send/receive frames. */
+	if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) != 0)
+		val |= BGE_MACMODE_APE_RX_EN | BGE_MACMODE_APE_TX_EN;
+
+	CSR_WRITE_4(sc, BGE_MAC_MODE, val);
+	DELAY(40);
+
+	/* Set misc. local control, enable interrupts on attentions */
+	BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN);
+
+#ifdef notdef
+	/* Assert GPIO pins for PHY reset */
+	BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUT0 |
+	    BGE_MLC_MISCIO_OUT1 | BGE_MLC_MISCIO_OUT2);
+	BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUTEN0 |
+	    BGE_MLC_MISCIO_OUTEN1 | BGE_MLC_MISCIO_OUTEN2);
+#endif
+
+	/* Turn on DMA completion state machine */
+	if (!(BGE_IS_5705_PLUS(sc)))
+		CSR_WRITE_4(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE);
+
+	val = BGE_WDMAMODE_ENABLE | BGE_WDMAMODE_ALL_ATTNS;
+
+	/* Enable host coalescing bug fix. */
+	if (BGE_IS_5755_PLUS(sc))
+		val |= BGE_WDMAMODE_STATUS_TAG_FIX;
+
+	/* Request larger DMA burst size to get better performance. */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5785)
+		val |= BGE_WDMAMODE_BURST_ALL_DATA;
+
+	/* Turn on write DMA state machine */
+	CSR_WRITE_4(sc, BGE_WDMA_MODE, val);
+	DELAY(40);
+
+	/* Turn on read DMA state machine */
+	val = BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS;
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5717)
+		val |= BGE_RDMAMODE_MULT_DMA_RD_DIS;
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5785 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM57780)
+		val |= BGE_RDMAMODE_BD_SBD_CRPT_ATTN |
+		    BGE_RDMAMODE_MBUF_RBD_CRPT_ATTN |
+		    BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN;
+	if (sc->bge_flags & BGE_FLAG_PCIE)
+		val |= BGE_RDMAMODE_FIFO_LONG_BURST;
+	if (sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) {
+		val |= BGE_RDMAMODE_TSO4_ENABLE;
+		if (sc->bge_flags & BGE_FLAG_TSO3 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5785 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM57780)
+			val |= BGE_RDMAMODE_TSO6_ENABLE;
+	}
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5720 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5762) {
+		val |= CSR_READ_4(sc, BGE_RDMA_MODE) &
+			BGE_RDMAMODE_H2BNC_VLAN_DET;
+		/*
+		 * Allow multiple outstanding read requests from
+		 * non-LSO read DMA engine.
+		 */
+		val &= ~BGE_RDMAMODE_MULT_DMA_RD_DIS;
+	}
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5761 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5785 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM57780 ||
+	    BGE_IS_5717_PLUS(sc) || BGE_IS_57765_PLUS(sc)) {
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5762)
+			rdmareg = BGE_RDMA_RSRVCTRL_REG2;
+		else
+			rdmareg = BGE_RDMA_RSRVCTRL;
+		dmactl = CSR_READ_4(sc, rdmareg);
+		/*
+		 * Adjust tx margin to prevent TX data corruption and
+		 * fix internal FIFO overflow.
+		 */
+		if (sc->bge_chipid == BGE_CHIPID_BCM5719_A0 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5762) {
+			dmactl &= ~(BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK |
+			    BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK |
+			    BGE_RDMA_RSRVCTRL_TXMRGN_MASK);
+			dmactl |= BGE_RDMA_RSRVCTRL_FIFO_LWM_1_5K |
+			    BGE_RDMA_RSRVCTRL_FIFO_HWM_1_5K |
+			    BGE_RDMA_RSRVCTRL_TXMRGN_320B;
+		}
+		/*
+		 * Enable fix for read DMA FIFO overruns.
+		 * The fix is to limit the number of RX BDs
+		 * the hardware would fetch at a fime.
+		 */
+		CSR_WRITE_4(sc, rdmareg, dmactl |
+		    BGE_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
+	}
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5719) {
+		CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL,
+		    CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) |
+		    BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K |
+		    BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K);
+	} else if (sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+		/*
+		 * Allow 4KB burst length reads for non-LSO frames.
+		 * Enable 512B burst length reads for buffer descriptors.
+		 */
+		CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL,
+		    CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) |
+		    BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 |
+		    BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K);
+	} else if (sc->bge_asicrev == BGE_ASICREV_BCM5762) {
+		CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL_REG2,
+		    CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL_REG2) |
+		    BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K |
+		    BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K);
+	}
+
+	CSR_WRITE_4(sc, BGE_RDMA_MODE, val);
+	DELAY(40);
+
+	if (sc->bge_flags & BGE_FLAG_RDMA_BUG) {
+		for (i = 0; i < BGE_NUM_RDMA_CHANNELS / 2; i++) {
+			val = CSR_READ_4(sc, BGE_RDMA_LENGTH + i * 4);
+			if ((val & 0xFFFF) > BGE_FRAMELEN)
+				break;
+			if (((val >> 16) & 0xFFFF) > BGE_FRAMELEN)
+				break;
+		}
+		if (i != BGE_NUM_RDMA_CHANNELS / 2) {
+			val = CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL);
+			if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
+				val |= BGE_RDMA_TX_LENGTH_WA_5719;
+			else
+				val |= BGE_RDMA_TX_LENGTH_WA_5720;
+			CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, val);
+		}
+	}
+
+	/* Turn on RX data completion state machine */
+	CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
+
+	/* Turn on RX BD initiator state machine */
+	CSR_WRITE_4(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE);
+
+	/* Turn on RX data and RX BD initiator state machine */
+	CSR_WRITE_4(sc, BGE_RDBDI_MODE, BGE_RDBDIMODE_ENABLE);
+
+	/* Turn on Mbuf cluster free state machine */
+	if (!(BGE_IS_5705_PLUS(sc)))
+		CSR_WRITE_4(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE);
+
+	/* Turn on send BD completion state machine */
+	CSR_WRITE_4(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE);
+
+	/* Turn on send data completion state machine */
+	val = BGE_SDCMODE_ENABLE;
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+		val |= BGE_SDCMODE_CDELAY;
+	CSR_WRITE_4(sc, BGE_SDC_MODE, val);
+
+	/* Turn on send data initiator state machine */
+	if (sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3))
+		CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE |
+		    BGE_SDIMODE_HW_LSO_PRE_DMA);
+	else
+		CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE);
+
+	/* Turn on send BD initiator state machine */
+	CSR_WRITE_4(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE);
+
+	/* Turn on send BD selector state machine */
+	CSR_WRITE_4(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE);
+
+	CSR_WRITE_4(sc, BGE_SDI_STATS_ENABLE_MASK, 0x007FFFFF);
+	CSR_WRITE_4(sc, BGE_SDI_STATS_CTL,
+	    BGE_SDISTATSCTL_ENABLE | BGE_SDISTATSCTL_FASTER);
+
+	/* ack/clear link change events */
+	CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED |
+	    BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE |
+	    BGE_MACSTAT_LINK_CHANGED);
+	CSR_WRITE_4(sc, BGE_MI_STS, 0);
+
+	/*
+	 * Enable attention when the link has changed state for
+	 * devices that use auto polling.
+	 */
+	if (sc->bge_flags & BGE_FLAG_TBI) {
+		CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK);
+	} else {
+		if (sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) {
+			CSR_WRITE_4(sc, BGE_MI_MODE, sc->bge_mi_mode);
+			DELAY(80);
+		}
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5700 &&
+		    sc->bge_chipid != BGE_CHIPID_BCM5700_B2)
+			CSR_WRITE_4(sc, BGE_MAC_EVT_ENB,
+			    BGE_EVTENB_MI_INTERRUPT);
+	}
+
+	/*
+	 * Clear any pending link state attention.
+	 * Otherwise some link state change events may be lost until attention
+	 * is cleared by bge_intr() -> bge_link_upd() sequence.
+	 * It's not necessary on newer BCM chips - perhaps enabling link
+	 * state change attentions implies clearing pending attention.
+	 */
+	CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED |
+	    BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE |
+	    BGE_MACSTAT_LINK_CHANGED);
+
+	/* Enable link state change attentions. */
+	BGE_SETBIT(sc, BGE_MAC_EVT_ENB, BGE_EVTENB_LINK_CHANGED);
+
+	return (0);
+}
+
+static const struct bge_revision *
+bge_lookup_rev(uint32_t chipid)
+{
+	const struct bge_revision *br;
+
+	for (br = bge_revisions; br->br_name != NULL; br++) {
+		if (br->br_chipid == chipid)
+			return (br);
+	}
+
+	for (br = bge_majorrevs; br->br_name != NULL; br++) {
+		if (br->br_chipid == BGE_ASICREV(chipid))
+			return (br);
+	}
+
+	return (NULL);
+}
+
+static const struct bge_vendor *
+bge_lookup_vendor(uint16_t vid)
+{
+	const struct bge_vendor *v;
+
+	for (v = bge_vendors; v->v_name != NULL; v++)
+		if (v->v_id == vid)
+			return (v);
+
+	return (NULL);
+}
+
+static uint32_t
+bge_chipid(device_t dev)
+{
+	uint32_t id;
+
+	id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
+	    BGE_PCIMISCCTL_ASICREV_SHIFT;
+	if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) {
+		/*
+		 * Find the ASCI revision.  Different chips use different
+		 * registers.
+		 */
+		switch (pci_get_device(dev)) {
+		case BCOM_DEVICEID_BCM5717:
+		case BCOM_DEVICEID_BCM5718:
+		case BCOM_DEVICEID_BCM5719:
+		case BCOM_DEVICEID_BCM5720:
+		case BCOM_DEVICEID_BCM5725:
+		case BCOM_DEVICEID_BCM5727:
+		case BCOM_DEVICEID_BCM5762:
+		case BCOM_DEVICEID_BCM57764:
+		case BCOM_DEVICEID_BCM57767:
+		case BCOM_DEVICEID_BCM57787:
+			id = pci_read_config(dev,
+			    BGE_PCI_GEN2_PRODID_ASICREV, 4);
+			break;
+		case BCOM_DEVICEID_BCM57761:
+		case BCOM_DEVICEID_BCM57762:
+		case BCOM_DEVICEID_BCM57765:
+		case BCOM_DEVICEID_BCM57766:
+		case BCOM_DEVICEID_BCM57781:
+		case BCOM_DEVICEID_BCM57782:
+		case BCOM_DEVICEID_BCM57785:
+		case BCOM_DEVICEID_BCM57786:
+		case BCOM_DEVICEID_BCM57791:
+		case BCOM_DEVICEID_BCM57795:
+			id = pci_read_config(dev,
+			    BGE_PCI_GEN15_PRODID_ASICREV, 4);
+			break;
+		default:
+			id = pci_read_config(dev, BGE_PCI_PRODID_ASICREV, 4);
+		}
+	}
+	return (id);
+}
+
+/*
+ * Probe for a Broadcom chip. Check the PCI vendor and device IDs
+ * against our list and return its name if we find a match.
+ *
+ * Note that since the Broadcom controller contains VPD support, we
+ * try to get the device name string from the controller itself instead
+ * of the compiled-in string. It guarantees we'll always announce the
+ * right product name. We fall back to the compiled-in string when
+ * VPD is unavailable or corrupt.
+ */
+static int
+bge_probe(struct bge_softc *sc)
+{
+	char buf[96];
+	char model[64];
+	const struct bge_revision *br;
+	const char *pname;
+	pci_dev_t dev = sc->bge_dev;
+	const struct pci_device_id *t = bge_devs;
+	const struct bge_vendor *v;
+	uint32_t id;
+	uint16_t did, vid;
+
+	vid = pci_get_vendor(dev);
+	did = pci_get_device(dev);
+	while(t->vendor != 0) {
+		if ((vid == t->vendor) && (did == t->device)) {
+			id = bge_chipid(dev);
+			br = bge_lookup_rev(id);
+			if (pci_get_vpd_ident(dev, &pname) == 0)
+				snprintf(model, sizeof(model), "%s", pname);
+			else {
+				v = bge_lookup_vendor(vid);
+				snprintf(model, sizeof(model), "%s %s",
+				    v != NULL ? v->v_name : "Unknown",
+				    br != NULL ? br->br_name :
+				    "NetXtreme/NetLink Ethernet Controller");
+			}
+			snprintf(buf, sizeof(buf), "%s, %sASIC rev. %#08x",
+			    model, br != NULL ? "" : "unknown ", id);
+			device_printf(dev, "%s\n", buf);
+			return 0;
+		}
+		t++;
+	}
+
+	return ENXIO;
+}
+
+// #define BGE_DMA_MIN_ALIGN	ARCH_DMA_MINALIGN
+#define BGE_DMA_MIN_ALIGN	128
+
+/* Allocate areas used for DMA blocks. */
+static int
+bge_dma_alloc(struct bge_softc *sc)
+{
+	bus_size_t asize, sbsz = 0;
+	void *p;
+
+	asize = BGE_STD_RX_RING_SZ + BGE_RX_RTN_RING_SZ(sc) +
+	    BGE_TX_RING_SZ + BGE_STATS_SZ;
+
+	if (BGE_IS_JUMBO_CAPABLE(sc))
+		asize += BGE_JUMBO_RX_RING_SZ;
+
+	/*
+	 * Because we only use single Tx/Rx/Rx return ring, use
+	 * minimum status block size except BCM5700 AX/BX which
+	 * seems to want to see full status block size regardless
+	 * of configured number of ring.
+	 */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5700 &&
+	    sc->bge_chipid != BGE_CHIPID_BCM5700_C0)
+		sbsz += BGE_STATUS_BLK_SZ;
+	else
+		sbsz += 32;
+	asize += sbsz;
+
+	/* To help with alignment */
+	asize += PAGE_SIZE;
+
+	p = malloc(asize);
+	if (p == NULL) {
+		device_printf(sc->bge_dev, "Out of memory while allocating"
+		    " DMA areas\n");
+		return ENOMEM;
+	}
+
+	memset(p, 0, asize);
+	sc->dma_area = p;
+	p = (void *)ALIGN((unsigned long)p, BGE_DMA_MIN_ALIGN);
+
+#define SET_BLOCK(__b, __s)					\
+do {	sc->bge_ldata.bge_##__b = p;				\
+	sc->bge_ldata.bge_##__b##_paddr = virt_to_phys(p);	\
+	p += __s; p = (void *)ALIGN((unsigned long)p,		\
+	    BGE_DMA_MIN_ALIGN);					\
+} while (0)
+
+	SET_BLOCK(rx_std_ring, BGE_STD_RX_RING_SZ);
+	SET_BLOCK(rx_return_ring, BGE_RX_RTN_RING_SZ(sc));
+	SET_BLOCK(tx_ring, BGE_TX_RING_SZ);
+	SET_BLOCK(status_block, sbsz);
+	SET_BLOCK(stats, BGE_STATS_SZ);
+
+	if (BGE_IS_JUMBO_CAPABLE(sc))
+		SET_BLOCK(rx_jumbo_ring, BGE_JUMBO_RX_RING_SZ);
+
+#undef SET_BLOCK
+
+	return 0;
+}
+
+static void
+bge_devinfo(struct bge_softc *sc)
+{
+	pci_dev_t dev = sc->bge_dev;
+	uint32_t cfg, clk;
+
+	device_printf(sc->bge_dev,
+	    "CHIP ID 0x%08x; ASIC REV 0x%02x; CHIP REV 0x%02x; ",
+	    sc->bge_chipid, sc->bge_asicrev, sc->bge_chiprev);
+	if (sc->bge_flags & BGE_FLAG_PCIE)
+		printf("PCI-E\n");
+	else if (sc->bge_flags & BGE_FLAG_PCIX) {
+		printf("PCI-X ");
+		cfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID_MASK;
+		if (cfg == BGE_MISCCFG_BOARD_ID_5704CIOBE)
+			clk = 133;
+		else {
+			clk = CSR_READ_4(sc, BGE_PCI_CLKCTL) & 0x1F;
+			switch (clk) {
+			case 0:
+				clk = 33;
+				break;
+			case 2:
+				clk = 50;
+				break;
+			case 4:
+				clk = 66;
+				break;
+			case 6:
+				clk = 100;
+				break;
+			case 7:
+				clk = 133;
+				break;
+			}
+		}
+		printf("%u MHz\n", clk);
+	} else {
+		if (sc->bge_pcixcap != 0)
+			printf("PCI on PCI-X ");
+		else
+			printf("PCI ");
+		cfg = pci_read_config(dev, BGE_PCI_PCISTATE, 4);
+		if (cfg & BGE_PCISTATE_PCI_BUSSPEED)
+			clk = 66;
+		else
+			clk = 33;
+		if (cfg & BGE_PCISTATE_32BIT_BUS)
+			printf("%u MHz; 32bit\n", clk);
+		else
+			printf("%u MHz; 64bit\n", clk);
+	}
+}
+
+static int
+bge_attach(struct bge_softc *sc)
+{
+	uint32_t hwcfg = 0, misccfg, pcistate;
+	u_char eaddr[ETHER_ADDR_LEN];
+	int error = 0, reg;
+	pci_dev_t dev = sc->bge_dev;
+
+	/*
+	 * Map control/status registers.
+	 */
+	sc->bge_res = pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+	    PCI_REGION_MEM);
+	sc->bge_eth.iobase = (unsigned long)sc->bge_res;
+
+	/* Save various chip information. */
+	sc->bge_func_addr = pci_get_function(dev);
+	sc->bge_chipid = bge_chipid(dev);
+	sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
+	sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
+
+	/* Set default PHY address. */
+	sc->bge_phy_addr = 1;
+	 /*
+	  * PHY address mapping for various devices.
+	  *
+	  *          | F0 Cu | F0 Sr | F1 Cu | F1 Sr |
+	  * ---------+-------+-------+-------+-------+
+	  * BCM57XX  |   1   |   X   |   X   |   X   |
+	  * BCM5704  |   1   |   X   |   1   |   X   |
+	  * BCM5717  |   1   |   8   |   2   |   9   |
+	  * BCM5719  |   1   |   8   |   2   |   9   |
+	  * BCM5720  |   1   |   8   |   2   |   9   |
+	  *
+	  *          | F2 Cu | F2 Sr | F3 Cu | F3 Sr |
+	  * ---------+-------+-------+-------+-------+
+	  * BCM57XX  |   X   |   X   |   X   |   X   |
+	  * BCM5704  |   X   |   X   |   X   |   X   |
+	  * BCM5717  |   X   |   X   |   X   |   X   |
+	  * BCM5719  |   3   |   10  |   4   |   11  |
+	  * BCM5720  |   X   |   X   |   X   |   X   |
+	  *
+	  * Other addresses may respond but they are not
+	  * IEEE compliant PHYs and should be ignored.
+	  */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+		if (sc->bge_chipid != BGE_CHIPID_BCM5717_A0) {
+			if (CSR_READ_4(sc, BGE_SGDIG_STS) &
+			    BGE_SGDIGSTS_IS_SERDES)
+				sc->bge_phy_addr = sc->bge_func_addr + 8;
+			else
+				sc->bge_phy_addr = sc->bge_func_addr + 1;
+		} else {
+			if (CSR_READ_4(sc, BGE_CPMU_PHY_STRAP) &
+			    BGE_CPMU_PHY_STRAP_IS_SERDES)
+				sc->bge_phy_addr = sc->bge_func_addr + 8;
+			else
+				sc->bge_phy_addr = sc->bge_func_addr + 1;
+		}
+	}
+
+	sc->bge_flags |= BGE_FLAG_EADDR;
+
+	/* Save chipset family. */
+	switch (sc->bge_asicrev) {
+	case BGE_ASICREV_BCM5762:
+	case BGE_ASICREV_BCM57765:
+	case BGE_ASICREV_BCM57766:
+		sc->bge_flags |= BGE_FLAG_57765_PLUS;
+		/* FALLTHROUGH */
+	case BGE_ASICREV_BCM5717:
+	case BGE_ASICREV_BCM5719:
+	case BGE_ASICREV_BCM5720:
+		sc->bge_flags |= BGE_FLAG_5717_PLUS | BGE_FLAG_5755_PLUS |
+		    BGE_FLAG_575X_PLUS | BGE_FLAG_5705_PLUS | BGE_FLAG_JUMBO |
+		    BGE_FLAG_JUMBO_FRAME;
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+			/*
+			 * Enable work around for DMA engine miscalculation
+			 * of TXMBUF available space.
+			 */
+			sc->bge_flags |= BGE_FLAG_RDMA_BUG;
+			if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
+			    sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
+				/* Jumbo frame on BCM5719 A0 does not work. */
+				sc->bge_flags &= ~BGE_FLAG_JUMBO;
+			}
+		}
+		break;
+	case BGE_ASICREV_BCM5755:
+	case BGE_ASICREV_BCM5761:
+	case BGE_ASICREV_BCM5784:
+	case BGE_ASICREV_BCM5785:
+	case BGE_ASICREV_BCM5787:
+	case BGE_ASICREV_BCM57780:
+		sc->bge_flags |= BGE_FLAG_5755_PLUS | BGE_FLAG_575X_PLUS |
+		    BGE_FLAG_5705_PLUS;
+		break;
+	case BGE_ASICREV_BCM5700:
+	case BGE_ASICREV_BCM5701:
+	case BGE_ASICREV_BCM5703:
+	case BGE_ASICREV_BCM5704:
+		sc->bge_flags |= BGE_FLAG_5700_FAMILY | BGE_FLAG_JUMBO;
+		break;
+	case BGE_ASICREV_BCM5714_A0:
+	case BGE_ASICREV_BCM5780:
+	case BGE_ASICREV_BCM5714:
+		sc->bge_flags |= BGE_FLAG_5714_FAMILY | BGE_FLAG_JUMBO_STD;
+		/* FALLTHROUGH */
+	case BGE_ASICREV_BCM5750:
+	case BGE_ASICREV_BCM5752:
+	case BGE_ASICREV_BCM5906:
+		sc->bge_flags |= BGE_FLAG_575X_PLUS;
+		/* FALLTHROUGH */
+	case BGE_ASICREV_BCM5705:
+		sc->bge_flags |= BGE_FLAG_5705_PLUS;
+		break;
+	}
+
+	/* Identify chips with APE processor. */
+	switch (sc->bge_asicrev) {
+	case BGE_ASICREV_BCM5717:
+	case BGE_ASICREV_BCM5719:
+	case BGE_ASICREV_BCM5720:
+	case BGE_ASICREV_BCM5761:
+	case BGE_ASICREV_BCM5762:
+		sc->bge_flags |= BGE_FLAG_APE;
+		break;
+	}
+
+	/* Chips with APE need BAR2 access for APE registers/memory. */
+	if ((sc->bge_flags & BGE_FLAG_APE) != 0) {
+		sc->bge_res2 = pci_map_bar(dev, PCI_BASE_ADDRESS_2,
+		    PCI_REGION_MEM);
+
+		/* Enable APE register/memory access by host driver. */
+		pcistate = pci_read_config(dev, BGE_PCI_PCISTATE, 4);
+		pcistate |= BGE_PCISTATE_ALLOW_APE_CTLSPC_WR |
+		    BGE_PCISTATE_ALLOW_APE_SHMEM_WR |
+		    BGE_PCISTATE_ALLOW_APE_PSPACE_WR;
+		pci_write_config(dev, BGE_PCI_PCISTATE, pcistate, 4);
+
+		bge_ape_lock_init(sc);
+		bge_ape_read_fw_ver(sc);
+	}
+
+	/* Identify the chips that use an CPMU. */
+	if (BGE_IS_5717_PLUS(sc) ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5761 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5785 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM57780)
+		sc->bge_flags |= BGE_FLAG_CPMU_PRESENT;
+	if ((sc->bge_flags & BGE_FLAG_CPMU_PRESENT) != 0)
+		sc->bge_mi_mode = BGE_MIMODE_500KHZ_CONST;
+	else
+		sc->bge_mi_mode = BGE_MIMODE_BASE;
+	/* Enable auto polling for BCM570[0-5]. */
+	if (BGE_IS_5700_FAMILY(sc) || sc->bge_asicrev == BGE_ASICREV_BCM5705)
+		sc->bge_mi_mode |= BGE_MIMODE_AUTOPOLL;
+
+	/*
+	 * All Broadcom controllers have 4GB boundary DMA bug.
+	 * Whenever an address crosses a multiple of the 4GB boundary
+	 * (including 4GB, 8Gb, 12Gb, etc.) and makes the transition
+	 * from 0xX_FFFF_FFFF to 0x(X+1)_0000_0000 an internal DMA
+	 * state machine will lockup and cause the device to hang.
+	 */
+	sc->bge_flags |= BGE_FLAG_4G_BNDRY_BUG;
+
+	/* BCM5755 or higher and BCM5906 have short DMA bug. */
+	if (BGE_IS_5755_PLUS(sc) || sc->bge_asicrev == BGE_ASICREV_BCM5906)
+		sc->bge_flags |= BGE_FLAG_SHORT_DMA_BUG;
+
+	/*
+	 * BCM5719 cannot handle DMA requests for DMA segments that
+	 * have larger than 4KB in size.  However the maximum DMA
+	 * segment size created in DMA tag is 4KB for TSO, so we
+	 * wouldn't encounter the issue here.
+	 */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
+		sc->bge_flags |= BGE_FLAG_4K_RDMA_BUG;
+
+	misccfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID_MASK;
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5705) {
+		if (misccfg == BGE_MISCCFG_BOARD_ID_5788 ||
+		    misccfg == BGE_MISCCFG_BOARD_ID_5788M)
+			sc->bge_flags |= BGE_FLAG_5788;
+	}
+
+	/*
+	 * Some controllers seem to require a special firmware to use
+	 * TSO. But the firmware is not available to FreeBSD and Linux
+	 * claims that the TSO performed by the firmware is slower than
+	 * hardware based TSO. Moreover the firmware based TSO has one
+	 * known bug which can't handle TSO if Ethernet header + IP/TCP
+	 * header is greater than 80 bytes. A workaround for the TSO
+	 * bug exist but it seems it's too expensive than not using
+	 * TSO at all. Some hardwares also have the TSO bug so limit
+	 * the TSO to the controllers that are not affected TSO issues
+	 * (e.g. 5755 or higher).
+	 */
+	if (BGE_IS_5717_PLUS(sc)) {
+		/* BCM5717 requires different TSO configuration. */
+		sc->bge_flags |= BGE_FLAG_TSO3;
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
+		    sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
+			/* TSO on BCM5719 A0 does not work. */
+			sc->bge_flags &= ~BGE_FLAG_TSO3;
+		}
+	} else if (BGE_IS_5755_PLUS(sc)) {
+		/*
+		 * BCM5754 and BCM5787 shares the same ASIC id so
+		 * explicit device id check is required.
+		 * Due to unknown reason TSO does not work on BCM5755M.
+		 */
+		if (pci_get_device(dev) != BCOM_DEVICEID_BCM5754 &&
+		    pci_get_device(dev) != BCOM_DEVICEID_BCM5754M &&
+		    pci_get_device(dev) != BCOM_DEVICEID_BCM5755M)
+			sc->bge_flags |= BGE_FLAG_TSO;
+	}
+
+	/*
+	 * Check if this is a PCI-X or PCI Express device.
+	 */
+	reg = pci_hose_find_capability(pci_bus_to_hose(PCI_BUS(dev)), dev,
+				       PCIY_EXPRESS);
+	if (reg) {
+		/*
+		 * Found a PCI Express capabilities register, this
+		 * must be a PCI Express device.
+		 */
+		sc->bge_flags |= BGE_FLAG_PCIE;
+		sc->bge_expcap = reg;
+		/* Extract supported maximum payload size. */
+		sc->bge_mps = pci_read_config(dev, sc->bge_expcap +
+		    PCIER_DEVICE_CAP, 2);
+		sc->bge_mps = 128 << (sc->bge_mps & PCIEM_CAP_MAX_PAYLOAD);
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5720)
+			sc->bge_expmrq = 2048;
+		else
+			sc->bge_expmrq = 4096;
+		pci_set_max_read_req(dev, sc->bge_expmrq);
+	} else {
+		/*
+		 * Check if the device is in PCI-X Mode.
+		 * (This bit is not valid on PCI Express controllers.)
+		 */
+		reg = pci_hose_find_capability(pci_bus_to_hose(PCI_BUS(dev)),
+					       dev, PCIY_PCIX);
+		if (reg)
+			sc->bge_pcixcap = reg;
+		if ((pci_read_config(dev, BGE_PCI_PCISTATE, 4) &
+		    BGE_PCISTATE_PCI_BUSMODE) == 0)
+			sc->bge_flags |= BGE_FLAG_PCIX;
+	}
+
+	/*
+	 * The 40bit DMA bug applies to the 5714/5715 controllers and is
+	 * not actually a MAC controller bug but an issue with the embedded
+	 * PCIe to PCI-X bridge in the device. Use 40bit DMA workaround.
+	 */
+	if (BGE_IS_5714_FAMILY(sc) && (sc->bge_flags & BGE_FLAG_PCIX))
+		sc->bge_flags |= BGE_FLAG_40BIT_BUG;
+
+	bge_devinfo(sc);
+
+	sc->bge_asf_mode = 0;
+	/* No ASF if APE present. */
+	if ((sc->bge_flags & BGE_FLAG_APE) == 0) {
+		if (bge_readmem_ind(sc, BGE_SRAM_DATA_SIG) ==
+		    BGE_SRAM_DATA_SIG_MAGIC) {
+			if (bge_readmem_ind(sc, BGE_SRAM_DATA_CFG) &
+			    BGE_HWCFG_ASF) {
+				sc->bge_asf_mode |= ASF_ENABLE;
+				sc->bge_asf_mode |= ASF_STACKUP;
+				if (BGE_IS_575X_PLUS(sc))
+					sc->bge_asf_mode |= ASF_NEW_HANDSHAKE;
+			}
+		}
+	}
+
+	bge_stop_fw(sc);
+	bge_sig_pre_reset(sc, BGE_RESET_SHUTDOWN);
+	if (bge_reset(sc)) {
+		device_printf(sc->bge_dev, "chip reset failed\n");
+		error = ENXIO;
+		goto fail;
+	}
+
+	bge_sig_legacy(sc, BGE_RESET_SHUTDOWN);
+	bge_sig_post_reset(sc, BGE_RESET_SHUTDOWN);
+
+	if (bge_chipinit(sc)) {
+		device_printf(sc->bge_dev, "chip initialization failed\n");
+		error = ENXIO;
+		goto fail;
+	}
+
+	error = bge_get_eaddr(sc, eaddr);
+	if (error) {
+		device_printf(sc->bge_dev,
+		    "failed to read station address\n");
+		error = ENXIO;
+		goto fail;
+	}
+	device_printf(dev, "EADDR %pM\n", eaddr);
+	/* TODO Figure out how to handle env passed enetaddr -- BenC */
+	// memcpy(sc->bge_eth.enetaddr, eaddr, ETHER_ADDR_LEN);
+
+	/* 5705 limits RX return ring to 512 entries. */
+	if (BGE_IS_5717_PLUS(sc))
+		sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT;
+	else if (BGE_IS_5705_PLUS(sc))
+		sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT_5705;
+	else
+		sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT;
+
+	if (bge_dma_alloc(sc)) {
+		device_printf(sc->bge_dev,
+		    "failed to allocate DMA resources\n");
+		error = ENXIO;
+		goto fail;
+	}
+
+	/*
+	 * Figure out what sort of media we have by checking the
+	 * hardware config word in the first 32k of NIC internal memory,
+	 * or fall back to examining the EEPROM if necessary.
+	 * Note: on some BCM5700 cards, this value appears to be unset.
+	 * If that's the case, we have to rely on identifying the NIC
+	 * by its PCI subsystem ID, as we do below for the SysKonnect
+	 * SK-9D41.
+	 */
+	if (bge_readmem_ind(sc, BGE_SRAM_DATA_SIG) == BGE_SRAM_DATA_SIG_MAGIC)
+		hwcfg = bge_readmem_ind(sc, BGE_SRAM_DATA_CFG);
+	else if ((sc->bge_flags & BGE_FLAG_EADDR) &&
+	    (sc->bge_asicrev != BGE_ASICREV_BCM5906)) {
+		if (bge_read_eeprom(sc, (caddr_t)&hwcfg, BGE_EE_HWCFG_OFFSET,
+		    sizeof(hwcfg))) {
+			device_printf(sc->bge_dev, "failed to read EEPROM\n");
+			error = ENXIO;
+			goto fail;
+		}
+		hwcfg = ntohl(hwcfg);
+	}
+
+	/* The SysKonnect SK-9D41 is a 1000baseSX card. */
+	if ((pci_read_config(dev, BGE_PCI_SUBSYS, 4) >> 16) ==
+	    SK_SUBSYSID_9D41 || (hwcfg & BGE_HWCFG_MEDIA) == BGE_MEDIA_FIBER) {
+		if (BGE_IS_5705_PLUS(sc)) {
+			sc->bge_flags |= BGE_FLAG_MII_SERDES;
+			sc->bge_phy_flags |= BGE_PHY_NO_WIRESPEED;
+		} else
+			sc->bge_flags |= BGE_FLAG_TBI;
+	}
+
+	/* Set various PHY bug flags. */
+	if (sc->bge_chipid == BGE_CHIPID_BCM5701_A0 ||
+	    sc->bge_chipid == BGE_CHIPID_BCM5701_B0)
+		sc->bge_phy_flags |= BGE_PHY_CRC_BUG;
+	if (sc->bge_chiprev == BGE_CHIPREV_5703_AX ||
+	    sc->bge_chiprev == BGE_CHIPREV_5704_AX)
+		sc->bge_phy_flags |= BGE_PHY_ADC_BUG;
+	if (sc->bge_chipid == BGE_CHIPID_BCM5704_A0)
+		sc->bge_phy_flags |= BGE_PHY_5704_A0_BUG;
+	if (pci_get_subvendor(dev) == DELL_VENDORID)
+		sc->bge_phy_flags |= BGE_PHY_NO_3LED;
+	if ((BGE_IS_5705_PLUS(sc)) &&
+	    sc->bge_asicrev != BGE_ASICREV_BCM5906 &&
+	    sc->bge_asicrev != BGE_ASICREV_BCM5785 &&
+	    sc->bge_asicrev != BGE_ASICREV_BCM57780 &&
+	    !BGE_IS_5717_PLUS(sc)) {
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5761 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5787) {
+			if (pci_get_device(dev) != BCOM_DEVICEID_BCM5722 &&
+			    pci_get_device(dev) != BCOM_DEVICEID_BCM5756)
+				sc->bge_phy_flags |= BGE_PHY_JITTER_BUG;
+			if (pci_get_device(dev) == BCOM_DEVICEID_BCM5755M)
+				sc->bge_phy_flags |= BGE_PHY_ADJUST_TRIM;
+		} else
+			sc->bge_phy_flags |= BGE_PHY_BER_BUG;
+	}
+
+	/*
+	 * Don't enable Ethernet@WireSpeed for the 5700 or the
+	 * 5705 A0 and A1 chips.
+	 */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5700 ||
+	    (sc->bge_asicrev == BGE_ASICREV_BCM5705 &&
+	    (sc->bge_chipid != BGE_CHIPID_BCM5705_A0 &&
+	    sc->bge_chipid != BGE_CHIPID_BCM5705_A1)))
+		sc->bge_phy_flags |= BGE_PHY_NO_WIRESPEED;
+
+	if (!(sc->bge_flags & BGE_FLAG_TBI)) {
+		/*
+		 * Do transceiver setup and tell the firmware the
+		 * driver is down so we can try to get access the
+		 * probe if ASF is running.
+		 */
+		BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+		bge_asf_driver_up(sc);
+		/*
+		 * Now tell the firmware we are going up after probing the PHY
+		 */
+		if (sc->bge_asf_mode & ASF_STACKUP)
+			BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+	}
+	/*
+	 * When using the BCM5701 in PCI-X mode, data corruption has
+	 * been observed in the first few bytes of some received packets.
+	 * Aligning the packet buffer in memory eliminates the corruption.
+	 * Unfortunately, this misaligns the packet payloads.  On platforms
+	 * which do not support unaligned accesses, we will realign the
+	 * payloads by copying the received packets.
+	 */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5701 &&
+	    sc->bge_flags & BGE_FLAG_PCIX)
+                sc->bge_flags |= BGE_FLAG_RX_ALIGNBUG;
+
+fail:
+	if (error)
+		bge_stop(sc);
+	return (error);
+}
+
+static int
+bge_reset(struct bge_softc *sc)
+{
+	device_t dev;
+	uint32_t cachesize, command, mac_mode, mac_mode_mask, reset, val;
+	void (*write_op)(struct bge_softc *, int, int);
+	uint16_t devctl;
+	int i;
+
+	dev = sc->bge_dev;
+
+	mac_mode_mask = BGE_MACMODE_HALF_DUPLEX | BGE_MACMODE_PORTMODE;
+	if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) != 0)
+		mac_mode_mask |= BGE_MACMODE_APE_RX_EN | BGE_MACMODE_APE_TX_EN;
+	mac_mode = CSR_READ_4(sc, BGE_MAC_MODE) & mac_mode_mask;
+
+	if (BGE_IS_575X_PLUS(sc) && !BGE_IS_5714_FAMILY(sc) &&
+	    (sc->bge_asicrev != BGE_ASICREV_BCM5906)) {
+		if (sc->bge_flags & BGE_FLAG_PCIE)
+			write_op = bge_writemem_direct;
+		else
+			write_op = bge_writemem_ind;
+	} else
+		write_op = bge_writereg_ind;
+
+	if (sc->bge_asicrev != BGE_ASICREV_BCM5700 &&
+	    sc->bge_asicrev != BGE_ASICREV_BCM5701) {
+		CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1);
+		for (i = 0; i < 8000; i++) {
+			if (CSR_READ_4(sc, BGE_NVRAM_SWARB) &
+			    BGE_NVRAMSWARB_GNT1)
+				break;
+			DELAY(20);
+		}
+		if (i == 8000) {
+			if (bootverbose)
+				device_printf(dev, "NVRAM lock timedout!\n");
+		}
+	}
+	/* Take APE lock when performing reset. */
+	bge_ape_lock(sc, BGE_APE_LOCK_GRC);
+
+	/* Save some important PCI state. */
+	cachesize = pci_read_config(dev, BGE_PCI_CACHESZ, 4);
+	command = pci_read_config(dev, BGE_PCI_CMD, 4);
+
+	pci_write_config(dev, BGE_PCI_MISC_CTL,
+	    BGE_PCIMISCCTL_INDIRECT_ACCESS | BGE_PCIMISCCTL_MASK_PCI_INTR |
+	    BGE_HIF_SWAP_OPTIONS | BGE_PCIMISCCTL_PCISTATE_RW, 4);
+
+	/* Disable fastboot on controllers that support it. */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5752 ||
+	    BGE_IS_5755_PLUS(sc)) {
+		if (bootverbose)
+			device_printf(dev, "Disabling fastboot\n");
+		CSR_WRITE_4(sc, BGE_FASTBOOT_PC, 0x0);
+	}
+
+	/*
+	 * Write the magic number to SRAM at offset 0xB50.
+	 * When firmware finishes its initialization it will
+	 * write ~BGE_SRAM_FW_MB_MAGIC to the same location.
+	 */
+	bge_writemem_ind(sc, BGE_SRAM_FW_MB, BGE_SRAM_FW_MB_MAGIC);
+
+	reset = BGE_MISCCFG_RESET_CORE_CLOCKS | BGE_32BITTIME_66MHZ;
+
+	/* XXX: Broadcom Linux driver. */
+	if (sc->bge_flags & BGE_FLAG_PCIE) {
+		if (sc->bge_asicrev != BGE_ASICREV_BCM5785 &&
+		    (sc->bge_flags & BGE_FLAG_5717_PLUS) == 0) {
+			if (CSR_READ_4(sc, 0x7E2C) == 0x60)	/* PCIE 1.0 */
+				CSR_WRITE_4(sc, 0x7E2C, 0x20);
+		}
+		if (sc->bge_chipid != BGE_CHIPID_BCM5750_A0) {
+			/* Prevent PCIE link training during global reset */
+			CSR_WRITE_4(sc, BGE_MISC_CFG, 1 << 29);
+			reset |= 1 << 29;
+		}
+	}
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
+		val = CSR_READ_4(sc, BGE_VCPU_STATUS);
+		CSR_WRITE_4(sc, BGE_VCPU_STATUS,
+		    val | BGE_VCPU_STATUS_DRV_RESET);
+		val = CSR_READ_4(sc, BGE_VCPU_EXT_CTRL);
+		CSR_WRITE_4(sc, BGE_VCPU_EXT_CTRL,
+		    val & ~BGE_VCPU_EXT_CTRL_HALT_CPU);
+	}
+
+	/*
+	 * Set GPHY Power Down Override to leave GPHY
+	 * powered up in D0 uninitialized.
+	 */
+	if (BGE_IS_5705_PLUS(sc) &&
+	    (sc->bge_flags & BGE_FLAG_CPMU_PRESENT) == 0)
+		reset |= BGE_MISCCFG_GPHY_PD_OVERRIDE;
+
+	/* Issue global reset */
+	write_op(sc, BGE_MISC_CFG, reset);
+
+	if (sc->bge_flags & BGE_FLAG_PCIE)
+		DELAY(100 * 1000);
+	else
+		DELAY(1000);
+
+	/* XXX: Broadcom Linux driver. */
+	if (sc->bge_flags & BGE_FLAG_PCIE) {
+		if (sc->bge_chipid == BGE_CHIPID_BCM5750_A0) {
+			DELAY(500000); /* wait for link training to complete */
+			val = pci_read_config(dev, 0xC4, 4);
+			pci_write_config(dev, 0xC4, val | (1 << 15), 4);
+		}
+		devctl = pci_read_config(dev,
+		    sc->bge_expcap + PCIER_DEVICE_CTL, 2);
+		/* Clear enable no snoop and disable relaxed ordering. */
+		devctl &= ~(PCIEM_CTL_RELAXED_ORD_ENABLE |
+		    PCIEM_CTL_NOSNOOP_ENABLE);
+		pci_write_config(dev, sc->bge_expcap + PCIER_DEVICE_CTL,
+		    devctl, 2);
+		pci_set_max_read_req(dev, sc->bge_expmrq);
+		/* Clear error status. */
+		pci_write_config(dev, sc->bge_expcap + PCIER_DEVICE_STA,
+		    PCIEM_STA_CORRECTABLE_ERROR |
+		    PCIEM_STA_NON_FATAL_ERROR | PCIEM_STA_FATAL_ERROR |
+		    PCIEM_STA_UNSUPPORTED_REQ, 2);
+	}
+
+	/* Reset some of the PCI state that got zapped by reset. */
+	pci_write_config(dev, BGE_PCI_MISC_CTL,
+	    BGE_PCIMISCCTL_INDIRECT_ACCESS | BGE_PCIMISCCTL_MASK_PCI_INTR |
+	    BGE_HIF_SWAP_OPTIONS | BGE_PCIMISCCTL_PCISTATE_RW, 4);
+	val = BGE_PCISTATE_ROM_ENABLE | BGE_PCISTATE_ROM_RETRY_ENABLE;
+	if (sc->bge_chipid == BGE_CHIPID_BCM5704_A0 &&
+	    (sc->bge_flags & BGE_FLAG_PCIX) != 0)
+		val |= BGE_PCISTATE_RETRY_SAME_DMA;
+	if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) != 0)
+		val |= BGE_PCISTATE_ALLOW_APE_CTLSPC_WR |
+		    BGE_PCISTATE_ALLOW_APE_SHMEM_WR |
+		    BGE_PCISTATE_ALLOW_APE_PSPACE_WR;
+	pci_write_config(dev, BGE_PCI_PCISTATE, val, 4);
+	pci_write_config(dev, BGE_PCI_CACHESZ, cachesize, 4);
+	pci_write_config(dev, BGE_PCI_CMD, command, 4);
+	/*
+	 * Disable PCI-X relaxed ordering to ensure status block update
+	 * comes first then packet buffer DMA. Otherwise driver may
+	 * read stale status block.
+	 */
+	if (sc->bge_flags & BGE_FLAG_PCIX) {
+		devctl = pci_read_config(dev,
+		    sc->bge_pcixcap + PCIXR_COMMAND, 2);
+		devctl &= ~PCIXM_COMMAND_ERO;
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5703) {
+			devctl &= ~PCIXM_COMMAND_MAX_READ;
+			devctl |= PCIXM_COMMAND_MAX_READ_2048;
+		} else if (sc->bge_asicrev == BGE_ASICREV_BCM5704) {
+			devctl &= ~(PCIXM_COMMAND_MAX_SPLITS |
+			    PCIXM_COMMAND_MAX_READ);
+			devctl |= PCIXM_COMMAND_MAX_READ_2048;
+		}
+		pci_write_config(dev, sc->bge_pcixcap + PCIXR_COMMAND,
+		    devctl, 2);
+	}
+	/* Re-enable MSI, if necessary, and enable the memory arbiter. */
+	if (BGE_IS_5714_FAMILY(sc)) {
+		/* This chip disables MSI on reset. */
+		if (sc->bge_flags & BGE_FLAG_MSI) {
+			val = pci_read_config(dev,
+			    sc->bge_msicap + PCIR_MSI_CTRL, 2);
+			pci_write_config(dev,
+			    sc->bge_msicap + PCIR_MSI_CTRL,
+			    val | PCIM_MSICTRL_MSI_ENABLE, 2);
+			val = CSR_READ_4(sc, BGE_MSI_MODE);
+			CSR_WRITE_4(sc, BGE_MSI_MODE,
+			    val | BGE_MSIMODE_ENABLE);
+		}
+		val = CSR_READ_4(sc, BGE_MARB_MODE);
+		CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE | val);
+	} else
+		CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE);
+
+	/* Fix up byte swapping. */
+	CSR_WRITE_4(sc, BGE_MODE_CTL, bge_dma_swap_options(sc));
+
+	val = CSR_READ_4(sc, BGE_MAC_MODE);
+	val = (val & ~mac_mode_mask) | mac_mode;
+	CSR_WRITE_4(sc, BGE_MAC_MODE, val);
+	DELAY(40);
+
+	bge_ape_unlock(sc, BGE_APE_LOCK_GRC);
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
+		for (i = 0; i < BGE_TIMEOUT; i++) {
+			val = CSR_READ_4(sc, BGE_VCPU_STATUS);
+			if (val & BGE_VCPU_STATUS_INIT_DONE)
+				break;
+			DELAY(100);
+		}
+		if (i == BGE_TIMEOUT) {
+			device_printf(dev, "reset timed out\n");
+			return (1);
+		}
+	} else {
+		/*
+		 * Poll until we see the 1's complement of the magic number.
+		 * This indicates that the firmware initialization is complete.
+		 * We expect this to fail if no chip containing the Ethernet
+		 * address is fitted though.
+		 */
+		for (i = 0; i < BGE_TIMEOUT; i++) {
+			DELAY(10);
+			val = bge_readmem_ind(sc, BGE_SRAM_FW_MB);
+			if (val == ~BGE_SRAM_FW_MB_MAGIC)
+				break;
+		}
+
+		if ((sc->bge_flags & BGE_FLAG_EADDR) && i == BGE_TIMEOUT)
+			device_printf(dev,
+			    "firmware handshake timed out, found 0x%08x\n",
+			    val);
+		/* BCM57765 A0 needs additional time before accessing. */
+		if (sc->bge_chipid == BGE_CHIPID_BCM57765_A0)
+			DELAY(10 * 1000);	/* XXX */
+	}
+
+	/*
+	 * The 5704 in TBI mode apparently needs some special
+	 * adjustment to insure the SERDES drive level is set
+	 * to 1.2V.
+	 */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5704 &&
+	    sc->bge_flags & BGE_FLAG_TBI) {
+		val = CSR_READ_4(sc, BGE_SERDES_CFG);
+		val = (val & ~0xFFF) | 0x880;
+		CSR_WRITE_4(sc, BGE_SERDES_CFG, val);
+	}
+
+	/* XXX: Broadcom Linux driver. */
+	if (sc->bge_flags & BGE_FLAG_PCIE &&
+	    !BGE_IS_5717_PLUS(sc) &&
+	    sc->bge_chipid != BGE_CHIPID_BCM5750_A0 &&
+	    sc->bge_asicrev != BGE_ASICREV_BCM5785) {
+		/* Enable Data FIFO protection. */
+		val = CSR_READ_4(sc, 0x7C00);
+		CSR_WRITE_4(sc, 0x7C00, val | (1 << 25));
+	}
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5720)
+		BGE_CLRBIT(sc, BGE_CPMU_CLCK_ORIDE,
+		    CPMU_CLCK_ORIDE_MAC_ORIDE_EN);
+	return (0);
+}
+
+static __inline void
+bge_rxreuse_std(struct bge_softc *sc, int i)
+{
+	struct bge_rx_bd *r;
+
+	r = &sc->bge_ldata.bge_rx_std_ring[sc->bge_std];
+	r->bge_flags = BGE_RXBDFLAG_END;
+	r->bge_len = sc->bge_cdata.bge_rx_std_seglen[i];
+	r->bge_idx = i;
+	BGE_INC(sc->bge_std, BGE_STD_RX_RING_CNT);
+}
+
+static __inline void
+bge_rxreuse_jumbo(struct bge_softc *sc, int i)
+{
+	struct bge_extrx_bd *r;
+
+	r = &sc->bge_ldata.bge_rx_jumbo_ring[sc->bge_jumbo];
+	r->bge_flags = BGE_RXBDFLAG_JUMBO_RING | BGE_RXBDFLAG_END;
+	r->bge_len3 = r->bge_len2 = r->bge_len1 = 0;
+        r->bge_len0 = MJUM9BYTES;
+	r->bge_idx = i;
+	BGE_INC(sc->bge_jumbo, BGE_JUMBO_RX_RING_CNT);
+}
+
+/*
+ * Frame reception handling. This is called if there's a frame
+ * on the receive return list.
+ *
+ * Note: we have to be able to handle two possibilities here:
+ * 1) the frame is from the jumbo receive ring
+ * 2) the frame is from the standard receive ring
+ */
+
+static int
+bge_rxeof(struct bge_softc *sc)
+{
+	int rx_npkts = 0, stdcnt = 0, jumbocnt = 0;
+	uint16_t rx_cons, rx_prod;
+
+	rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx;
+	rx_cons = sc->bge_rx_saved_considx;
+
+	/* Nothing to do. */
+	if (rx_cons == rx_prod)
+		return 0;
+
+	while (rx_cons != rx_prod) {
+		void *packet;
+		int len;
+		struct bge_rx_bd	*cur_rx;
+		uint32_t		rxidx;
+
+		cur_rx = &sc->bge_ldata.bge_rx_return_ring[rx_cons];
+
+		rxidx = cur_rx->bge_idx;
+		BGE_INC(rx_cons, sc->bge_return_ring_cnt);
+
+		if (cur_rx->bge_flags & BGE_RXBDFLAG_JUMBO_RING) {
+			jumbocnt++;
+			packet = sc->bge_cdata.bge_rx_jumbo_chain[rxidx];
+		} else {
+			stdcnt++;
+			packet = sc->bge_cdata.bge_rx_std_chain[rxidx];
+		}
+
+		len = cur_rx->bge_len - ETHER_CRC_LEN;
+
+		/* Pass the packet to the protocol layer */
+		NetReceive(packet, len);
+		rx_npkts++;
+
+		if (cur_rx->bge_flags & BGE_RXBDFLAG_JUMBO_RING)
+			bge_rxreuse_jumbo(sc, rxidx);
+		else
+			bge_rxreuse_std(sc, rxidx);
+	}
+
+	sc->bge_rx_saved_considx = rx_cons;
+	bge_writembx(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
+	if (stdcnt)
+		bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, (sc->bge_std +
+		    BGE_STD_RX_RING_CNT - 1) % BGE_STD_RX_RING_CNT);
+	if (jumbocnt)
+		bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, (sc->bge_jumbo +
+		    BGE_JUMBO_RX_RING_CNT - 1) % BGE_JUMBO_RX_RING_CNT);
+
+	return rx_npkts;
+}
+
+static void
+bge_asf_driver_up(struct bge_softc *sc)
+{
+	if (sc->bge_asf_mode & ASF_STACKUP) {
+		/* Send ASF heartbeat aprox. every 2s */
+		if (sc->bge_asf_count)
+			sc->bge_asf_count --;
+		else {
+			sc->bge_asf_count = 2;
+			bge_writemem_ind(sc, BGE_SRAM_FW_CMD_MB,
+			    BGE_FW_CMD_DRV_ALIVE);
+			bge_writemem_ind(sc, BGE_SRAM_FW_CMD_LEN_MB, 4);
+			bge_writemem_ind(sc, BGE_SRAM_FW_CMD_DATA_MB,
+			    BGE_FW_HB_TIMEOUT_SEC);
+			CSR_WRITE_4(sc, BGE_RX_CPU_EVENT,
+			    CSR_READ_4(sc, BGE_RX_CPU_EVENT) |
+			    BGE_RX_CPU_DRV_EVENT);
+		}
+	}
+}
+
+/*
+ * Encapsulate a packet in the tx ring by coupling the data
+ * pointer to descriptors.
+ */
+static void
+bge_encap(struct bge_softc *sc, void *packet, int length, uint32_t idx)
+{
+	phys_addr_t		paddr;
+	struct bge_tx_bd	*d;
+
+	paddr = virt_to_phys(packet);
+
+	d = &sc->bge_ldata.bge_tx_ring[idx];
+	d->bge_addr.bge_addr_lo = BGE_ADDR_LO(paddr);
+	d->bge_addr.bge_addr_hi = BGE_ADDR_HI(paddr);
+	d->bge_len = length;
+	d->bge_vlan_tag = 0;
+	d->bge_mss = 0;
+	d->bge_flags = BGE_TXBDFLAG_END | BGE_TXBDFLAG_COAL_NOW |
+	    BGE_TXBDFLAG_NO_CRC;
+}
+
+/*
+ * Main transmit routine.
+ */
+static int
+bge_send(struct eth_device *dev, void *packet, int length)
+{
+	struct bge_softc *sc = dev->priv;
+	uint32_t prodidx;
+	int start_time;
+
+	prodidx = sc->bge_tx_prodidx;
+
+	/* Pack the data into the transmit ring. */
+	bge_encap(sc, packet, length, prodidx);
+	BGE_INC(prodidx, BGE_TX_RING_CNT);
+
+	/* Transmit. */
+	bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
+	/* 5700 b2 errata */
+	if (sc->bge_chiprev == BGE_CHIPREV_5700_BX)
+		bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
+
+	sc->bge_tx_prodidx = prodidx;
+
+	/* Wait for transmission */
+	start_time = get_timer(0);
+	while (1) {
+		uint16_t tx_cons = sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx;
+
+		if (sc->bge_tx_saved_considx != tx_cons) {
+			while (sc->bge_tx_saved_considx != tx_cons)
+				BGE_INC(sc->bge_tx_saved_considx, BGE_TX_RING_CNT);
+			break;
+		}
+
+		if (get_timer(start_time) > CONFIG_SYS_HZ) {
+			device_printf(sc->bge_dev, "TX timeout!\n");
+			return 0;
+		}
+		udelay(10);
+	}
+#if 0
+	udelay(100);
+
+	device_printf(sc->bge_dev, "HCOut[%u] IErr[%u] DfrTX[%u] Coll[%u]\n",
+	    CSR_READ_4(sc, BGE_TX_MAC_STATS_OCTETS),
+	    CSR_READ_4(sc, BGE_TX_MAC_STATS_ERRORS),
+	    CSR_READ_4(sc, BGE_TX_MAC_STATS_DEFERRED),
+	    CSR_READ_4(sc, BGE_TX_MAC_STATS_COLLS));
+
+	device_printf(sc->bge_dev, "BGE_MAC_STS[%08x]\n",
+	    CSR_READ_4(sc, BGE_MAC_STS));
+#endif
+
+	return length;
+}
+
+static int
+bge_init(struct eth_device *bge_eth, bd_t *bis)
+{
+	struct bge_softc *sc = bge_eth->priv;
+	uint16_t *m;
+	uint32_t mode;
+
+	/* Cancel pending I/O and flush buffers. */
+	bge_stop(sc);
+
+	bge_stop_fw(sc);
+	bge_sig_pre_reset(sc, BGE_RESET_START);
+	bge_reset(sc);
+	bge_sig_legacy(sc, BGE_RESET_START);
+	bge_sig_post_reset(sc, BGE_RESET_START);
+
+	bge_chipinit(sc);
+
+	/*
+	 * Init the various state machines, ring
+	 * control blocks and firmware.
+	 */
+	if (bge_blockinit(sc)) {
+		device_printf(sc->bge_dev, "initialization failure\n");
+		return -1;
+	}
+
+	/* Specify MTU. */
+	CSR_WRITE_4(sc, BGE_RX_MTU, BGE_DEFAULT_MTU +
+	    ETHER_HDR_LEN + ETHER_CRC_LEN);
+
+	/* Load our MAC address. */
+	m = (uint16_t *)(sc->bge_eth.enetaddr);
+	CSR_WRITE_4(sc, BGE_MAC_ADDR1_LO, htons(m[0]));
+	CSR_WRITE_4(sc, BGE_MAC_ADDR1_HI, (htons(m[1]) << 16) | htons(m[2]));
+
+	phy_config(sc->bge_phydev);
+	if (phy_startup(sc->bge_phydev))
+		return -1;
+
+	if (!sc->bge_phydev->link) {
+		device_printf(sc->bge_dev, "Link down.\n");
+		return -1;
+	}
+
+	/* Program promiscuous mode. */
+	bge_setpromisc(sc);
+
+	/* Program VLAN tag stripping. */
+	bge_setvlan(sc);
+
+	/* Init RX ring. */
+	if (bge_init_rx_ring_std(sc) != 0) {
+		device_printf(sc->bge_dev, "no memory for std Rx buffers.\n");
+		bge_stop(sc);
+		return -1;
+	}
+
+	/*
+	 * Workaround for a bug in 5705 ASIC rev A0. Poll the NIC's
+	 * memory to insure that the chip has in fact read the first
+	 * entry of the ring.
+	 */
+	if (sc->bge_chipid == BGE_CHIPID_BCM5705_A0) {
+		uint32_t		v, i;
+		for (i = 0; i < 10; i++) {
+			DELAY(20);
+			v = bge_readmem_ind(sc, BGE_STD_RX_RINGS + 8);
+			if (v == (MCLBYTES - ETHER_ALIGN))
+				break;
+		}
+		if (i == 10)
+			device_printf (sc->bge_dev,
+			    "5705 A0 chip failed to load RX ring\n");
+	}
+
+	/* Init jumbo RX ring. */
+	if (BGE_IS_JUMBO_CAPABLE(sc) &&
+	    BGE_DEFAULT_MTU + ETHER_HDR_LEN + ETHER_CRC_LEN +
+	    ETHER_VLAN_ENCAP_LEN > (MCLBYTES - ETHER_ALIGN)) {
+		if (bge_init_rx_ring_jumbo(sc) != 0) {
+			device_printf(sc->bge_dev,
+			    "no memory for jumbo Rx buffers.\n");
+			bge_stop(sc);
+			return -1;
+		}
+	}
+
+	/* Init our RX return ring index. */
+	sc->bge_rx_saved_considx = 0;
+
+	/* Init TX ring. */
+	bge_init_tx_ring(sc);
+
+	/* Enable TX MAC state machine lockup fix. */
+	mode = CSR_READ_4(sc, BGE_TX_MODE);
+	if (BGE_IS_5755_PLUS(sc) || sc->bge_asicrev == BGE_ASICREV_BCM5906)
+		mode |= BGE_TXMODE_MBUF_LOCKUP_FIX;
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5720 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5762) {
+		mode &= ~(BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE);
+		mode |= CSR_READ_4(sc, BGE_TX_MODE) &
+		    (BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE);
+	}
+	/* Turn on transmitter. */
+	CSR_WRITE_4(sc, BGE_TX_MODE, mode | BGE_TXMODE_ENABLE);
+	DELAY(100);
+
+	/* Turn on receiver. */
+	mode = CSR_READ_4(sc, BGE_RX_MODE);
+	if (BGE_IS_5755_PLUS(sc))
+		mode |= BGE_RXMODE_IPV6_ENABLE;
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5762)
+		mode |= BGE_RXMODE_IPV4_FRAG_FIX;
+	CSR_WRITE_4(sc,BGE_RX_MODE, mode | BGE_RXMODE_ENABLE);
+	DELAY(10);
+
+	/*
+	 * Set the number of good frames to receive after RX MBUF
+	 * Low Watermark has been reached. After the RX MAC receives
+	 * this number of frames, it will drop subsequent incoming
+	 * frames until the MBUF High Watermark is reached.
+	 */
+	if (BGE_IS_57765_PLUS(sc))
+		CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1);
+	else
+		CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2);
+
+	/* Tell firmware we're alive. */
+	BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+
+	/* Disable interrupts since we are polling. */
+	BGE_SETBIT(sc, BGE_PCI_MISC_CTL,
+	    BGE_PCIMISCCTL_MASK_PCI_INTR);
+	bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
+
+	return 0;
+}
+
+static void
+bge_stop_block(struct bge_softc *sc, bus_size_t reg, uint32_t bit)
+{
+	int i;
+
+	BGE_CLRBIT(sc, reg, bit);
+
+	for (i = 0; i < BGE_TIMEOUT; i++) {
+		if ((CSR_READ_4(sc, reg) & bit) == 0)
+			return;
+		DELAY(100);
+        }
+}
+
+/*
+ * Stop the adapter and free any buffers allocated to the
+ * RX and TX lists.
+ */
+static void
+bge_stop(struct bge_softc *sc)
+{
+	/* Disable host interrupts. */
+	BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
+	bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
+
+	/*
+	 * Tell firmware we're shutting down.
+	 */
+	bge_stop_fw(sc);
+	bge_sig_pre_reset(sc, BGE_RESET_SHUTDOWN);
+
+	/*
+	 * Disable all of the receiver blocks.
+	 */
+	bge_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE);
+	bge_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE);
+	bge_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE);
+	if (BGE_IS_5700_FAMILY(sc))
+		bge_stop_block(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE);
+	bge_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE);
+	bge_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
+	bge_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE);
+
+	/*
+	 * Disable all of the transmit blocks.
+	 */
+	bge_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE);
+	bge_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE);
+	bge_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE);
+	bge_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE);
+	bge_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE);
+	if (BGE_IS_5700_FAMILY(sc))
+		bge_stop_block(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE);
+	bge_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE);
+
+	/*
+	 * Shut down all of the memory managers and related
+	 * state machines.
+	 */
+	bge_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE);
+	bge_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE);
+	if (BGE_IS_5700_FAMILY(sc))
+		bge_stop_block(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE);
+
+	CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF);
+	CSR_WRITE_4(sc, BGE_FTQ_RESET, 0);
+	if (!(BGE_IS_5705_PLUS(sc))) {
+		BGE_CLRBIT(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE);
+		BGE_CLRBIT(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE);
+	}
+
+	bge_reset(sc);
+	bge_sig_legacy(sc, BGE_RESET_SHUTDOWN);
+	bge_sig_post_reset(sc, BGE_RESET_SHUTDOWN);
+
+	/*
+	 * Keep the ASF firmware running if up.
+	 */
+	if (sc->bge_asf_mode & ASF_STACKUP)
+		BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+	else
+		BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+
+	/* Free the RX lists. */
+	bge_free_rx_ring_std(sc);
+
+	/* Free jumbo RX list. */
+	if (BGE_IS_JUMBO_CAPABLE(sc))
+		bge_free_rx_ring_jumbo(sc);
+
+	/* Free TX buffers. */
+	bge_free_tx_ring(sc);
+
+	sc->bge_tx_saved_considx = BGE_TXCONS_UNSET;
+}
+
+static int
+bge_get_eaddr_mem(struct bge_softc *sc, uint8_t ether_addr[])
+{
+	uint32_t mac_addr;
+
+	mac_addr = bge_readmem_ind(sc, BGE_SRAM_MAC_ADDR_HIGH_MB);
+	if ((mac_addr >> 16) == 0x484b) {
+		ether_addr[0] = (uint8_t)(mac_addr >> 8);
+		ether_addr[1] = (uint8_t)mac_addr;
+		mac_addr = bge_readmem_ind(sc, BGE_SRAM_MAC_ADDR_LOW_MB);
+		ether_addr[2] = (uint8_t)(mac_addr >> 24);
+		ether_addr[3] = (uint8_t)(mac_addr >> 16);
+		ether_addr[4] = (uint8_t)(mac_addr >> 8);
+		ether_addr[5] = (uint8_t)mac_addr;
+		return (0);
+	}
+	return (1);
+}
+
+static int
+bge_write_hwaddr(struct eth_device *dev)
+{
+	struct bge_softc *sc = dev->priv;
+	uint8_t *ea = dev->enetaddr;
+	uint32_t mac_addr;
+
+	mac_addr = ea[0] << 8 | ea[1];
+	bge_writemem_ind(sc, BGE_SRAM_MAC_ADDR_HIGH_MB, mac_addr);
+	mac_addr = ea[2] << 24 | ea[3] << 16 | ea[4] << 8 | ea[5];
+	bge_writemem_ind(sc, BGE_SRAM_MAC_ADDR_LOW_MB, mac_addr);
+
+	return 0;
+}
+
+static int
+bge_get_eaddr_nvram(struct bge_softc *sc, uint8_t ether_addr[])
+{
+	int mac_offset = BGE_EE_MAC_OFFSET;
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906)
+		mac_offset = BGE_EE_MAC_OFFSET_5906;
+
+	return (bge_read_nvram(sc, (caddr_t)ether_addr, mac_offset + 2,
+	    ETHER_ADDR_LEN));
+}
+
+static int
+bge_get_eaddr_eeprom(struct bge_softc *sc, uint8_t ether_addr[])
+{
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906)
+		return (1);
+
+	return (bge_read_eeprom(sc, (caddr_t)ether_addr,
+	   BGE_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN));
+}
+
+static int
+bge_get_eaddr(struct bge_softc *sc, uint8_t eaddr[])
+{
+	static const bge_eaddr_fcn_t bge_eaddr_funcs[] = {
+		/* NOTE: Order is critical */
+		bge_get_eaddr_mem,
+		bge_get_eaddr_nvram,
+		bge_get_eaddr_eeprom,
+		NULL
+	};
+	const bge_eaddr_fcn_t *func;
+
+	for (func = bge_eaddr_funcs; *func != NULL; ++func) {
+		if ((*func)(sc, eaddr) == 0)
+			break;
+	}
+	return (*func == NULL ? ENXIO : 0);
+}
+
+static int bge_recv(struct eth_device *dev)
+{
+	struct bge_softc *sc = dev->priv;
+	int start_time, rxpkts;
+
+	/* Wait for transmission */
+        for (start_time = get_timer(0), rxpkts = 0; !rxpkts; udelay(10)) {
+		rxpkts = bge_rxeof(sc);
+
+		if (get_timer(start_time) > CONFIG_SYS_HZ)
+			break;
+	}
+
+	return rxpkts;
+}
+
+static void bge_halt(struct eth_device *dev)
+{
+	struct bge_softc *sc = dev->priv;
+	bge_stop(sc);
+}
+
+/* Initialization for U-Boot NET_MULTI interface. Probe and register known
+ * devices. */
+int bge_register(bd_t *bis)
+{
+        int dev_nr;
+        pci_dev_t pdev;
+	struct mii_dev *bus;
+        struct eth_device *dev;
+	struct bge_softc *sc;
+        u32 val;
+
+        /* Find PCI device, if it exists, configure ...  */
+        for (dev_nr = 0 ;; dev_nr++) {
+                if ((pdev = pci_find_devices(bge_devs, dev_nr)) < 0)
+                        break;
+
+                pci_write_config_dword(pdev, PCI_COMMAND,
+				       PCI_COMMAND_MEMORY |
+				       PCI_COMMAND_MASTER);
+
+		/* Check to make sure MMIO and MASTER are set */
+		pci_read_config_dword(pdev, PCI_COMMAND, &val);
+		if (!(val & PCI_COMMAND_MEMORY) ||
+		    !(val & PCI_COMMAND_MASTER)) {
+			device_printf(pdev, "Could not enable MMIO and/or "
+			    "PCI MASTER\n");
+			continue;
+		}
+
+		/* Allocate BGE device structure */
+		sc = malloc(sizeof(*sc));
+		if (!sc) {
+			device_printf(pdev, "Can not allocate memory\n");
+			break;
+		}
+
+		memset(sc, 0, sizeof(*sc));
+		dev = &sc->bge_eth;
+		sc->bge_dev = pdev;
+
+		dev->priv = sc;
+		sprintf(dev->name, "BGE@%02x:%02x.%d", PCI_BUS(pdev),
+			PCI_DEV(pdev), PCI_FUNC(pdev));
+
+		bge_probe(sc);
+
+		if (bge_attach(sc)) {
+			bge_stop(sc);
+			free(sc);
+			continue;
+		}
+
+		dev->init = bge_init;
+		dev->halt = bge_halt;
+		dev->send = bge_send;
+		dev->recv = bge_recv;
+		dev->write_hwaddr = bge_write_hwaddr;
+
+		eth_register(dev);
+
+		/* Register mii command access routines */
+		miiphy_register(dev->name, bge_miibus_readreg,
+				bge_miibus_writereg);
+		bus = miiphy_get_dev_by_name(dev->name);
+		sc->bge_phydev = phy_connect(bus, sc->bge_phy_addr,
+		    dev, PHY_INTERFACE_MODE_MII);
+	}
+
+	return dev_nr;
+}
diff --git a/drivers/net/if_bgereg.h b/drivers/net/if_bgereg.h
new file mode 100644
index 0000000..8c27c13
--- /dev/null
+++ b/drivers/net/if_bgereg.h
@@ -0,0 +1,3010 @@ 
+/*-
+ * Copyright (c) 2001 Wind River Systems
+ * Copyright (c) 1997, 1998, 1999, 2001
+ *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * BCM570x memory map. The internal memory layout varies somewhat
+ * depending on whether or not we have external SSRAM attached.
+ * The BCM5700 can have up to 16MB of external memory. The BCM5701
+ * is apparently not designed to use external SSRAM. The mappings
+ * up to the first 4 send rings are the same for both internal and
+ * external memory configurations. Note that mini RX ring space is
+ * only available with external SSRAM configurations, which means
+ * the mini RX ring is not supported on the BCM5701.
+ *
+ * The NIC's memory can be accessed by the host in one of 3 ways:
+ *
+ * 1) Indirect register access. The MEMWIN_BASEADDR and MEMWIN_DATA
+ *    registers in PCI config space can be used to read any 32-bit
+ *    address within the NIC's memory.
+ *
+ * 2) Memory window access. The MEMWIN_BASEADDR register in PCI config
+ *    space can be used in conjunction with the memory window in the
+ *    device register space at offset 0x8000 to read any 32K chunk
+ *    of NIC memory.
+ *
+ * 3) Flat mode. If the 'flat mode' bit in the PCI state register is
+ *    set, the device I/O mapping consumes 32MB of host address space,
+ *    allowing all of the registers and internal NIC memory to be
+ *    accessed directly. NIC memory addresses are offset by 0x01000000.
+ *    Flat mode consumes so much host address space that it is not
+ *    recommended.
+ */
+#define	BGE_PAGE_ZERO			0x00000000
+#define	BGE_PAGE_ZERO_END		0x000000FF
+#define	BGE_SEND_RING_RCB		0x00000100
+#define	BGE_SEND_RING_RCB_END		0x000001FF
+#define	BGE_RX_RETURN_RING_RCB		0x00000200
+#define	BGE_RX_RETURN_RING_RCB_END	0x000002FF
+#define	BGE_STATS_BLOCK			0x00000300
+#define	BGE_STATS_BLOCK_END		0x00000AFF
+#define	BGE_STATUS_BLOCK		0x00000B00
+#define	BGE_STATUS_BLOCK_END		0x00000B4F
+#define	BGE_SRAM_FW_MB			0x00000B50
+#define	BGE_SRAM_DATA_SIG		0x00000B54
+#define	BGE_SRAM_DATA_CFG		0x00000B58
+#define	BGE_SRAM_FW_CMD_MB		0x00000B78
+#define	BGE_SRAM_FW_CMD_LEN_MB		0x00000B7C
+#define	BGE_SRAM_FW_CMD_DATA_MB		0x00000B80
+#define	BGE_SRAM_FW_DRV_STATE_MB	0x00000C04
+#define	BGE_SRAM_MAC_ADDR_HIGH_MB	0x00000C14
+#define	BGE_SRAM_MAC_ADDR_LOW_MB	0x00000C18
+#define	BGE_SOFTWARE_GENCOMM_END	0x00000FFF
+#define	BGE_UNMAPPED			0x00001000
+#define	BGE_UNMAPPED_END		0x00001FFF
+#define	BGE_DMA_DESCRIPTORS		0x00002000
+#define	BGE_DMA_DESCRIPTORS_END		0x00003FFF
+#define	BGE_SEND_RING_5717		0x00004000
+#define	BGE_SEND_RING_1_TO_4		0x00004000
+#define	BGE_SEND_RING_1_TO_4_END	0x00005FFF
+
+/* Firmware interface */
+#define	BGE_SRAM_DATA_SIG_MAGIC		0x4B657654	/* 'KevT' */
+
+#define	BGE_FW_CMD_DRV_ALIVE		0x00000001
+#define	BGE_FW_CMD_PAUSE		0x00000002
+#define	BGE_FW_CMD_IPV4_ADDR_CHANGE	0x00000003
+#define	BGE_FW_CMD_IPV6_ADDR_CHANGE	0x00000004
+#define	BGE_FW_CMD_LINK_UPDATE		0x0000000C
+#define	BGE_FW_CMD_DRV_ALIVE2		0x0000000D
+#define	BGE_FW_CMD_DRV_ALIVE3		0x0000000E
+
+#define	BGE_FW_HB_TIMEOUT_SEC		3
+
+#define	BGE_FW_DRV_STATE_START		0x00000001
+#define	BGE_FW_DRV_STATE_START_DONE	0x80000001
+#define	BGE_FW_DRV_STATE_UNLOAD		0x00000002
+#define	BGE_FW_DRV_STATE_UNLOAD_DONE	0x80000002
+#define	BGE_FW_DRV_STATE_WOL		0x00000003
+#define	BGE_FW_DRV_STATE_SUSPEND	0x00000004
+
+/* Mappings for internal memory configuration */
+#define	BGE_STD_RX_RINGS		0x00006000
+#define	BGE_STD_RX_RINGS_END		0x00006FFF
+#define	BGE_JUMBO_RX_RINGS		0x00007000
+#define	BGE_JUMBO_RX_RINGS_END		0x00007FFF
+#define	BGE_BUFFPOOL_1			0x00008000
+#define	BGE_BUFFPOOL_1_END		0x0000FFFF
+#define	BGE_BUFFPOOL_2			0x00010000 /* or expansion ROM */
+#define	BGE_BUFFPOOL_2_END		0x00017FFF
+#define	BGE_BUFFPOOL_3			0x00018000 /* or expansion ROM */
+#define	BGE_BUFFPOOL_3_END		0x0001FFFF
+#define	BGE_STD_RX_RINGS_5717		0x00040000
+#define	BGE_JUMBO_RX_RINGS_5717		0x00044400
+
+/* Mappings for external SSRAM configurations */
+#define	BGE_SEND_RING_5_TO_6		0x00006000
+#define	BGE_SEND_RING_5_TO_6_END	0x00006FFF
+#define	BGE_SEND_RING_7_TO_8		0x00007000
+#define	BGE_SEND_RING_7_TO_8_END	0x00007FFF
+#define	BGE_SEND_RING_9_TO_16		0x00008000
+#define	BGE_SEND_RING_9_TO_16_END	0x0000BFFF
+#define	BGE_EXT_STD_RX_RINGS		0x0000C000
+#define	BGE_EXT_STD_RX_RINGS_END	0x0000CFFF
+#define	BGE_EXT_JUMBO_RX_RINGS		0x0000D000
+#define	BGE_EXT_JUMBO_RX_RINGS_END	0x0000DFFF
+#define	BGE_MINI_RX_RINGS		0x0000E000
+#define	BGE_MINI_RX_RINGS_END		0x0000FFFF
+#define	BGE_AVAIL_REGION1		0x00010000 /* or expansion ROM */
+#define	BGE_AVAIL_REGION1_END		0x00017FFF
+#define	BGE_AVAIL_REGION2		0x00018000 /* or expansion ROM */
+#define	BGE_AVAIL_REGION2_END		0x0001FFFF
+#define	BGE_EXT_SSRAM			0x00020000
+#define	BGE_EXT_SSRAM_END		0x000FFFFF
+
+
+/*
+ * BCM570x register offsets. These are memory mapped registers
+ * which can be accessed with the CSR_READ_4()/CSR_WRITE_4() macros.
+ * Each register must be accessed using 32 bit operations.
+ *
+ * All registers are accessed through a 32K shared memory block.
+ * The first group of registers are actually copies of the PCI
+ * configuration space registers.
+ */
+
+/*
+ * PCI registers defined in the PCI 2.2 spec.
+ */
+#define	BGE_PCI_VID			0x00
+#define	BGE_PCI_DID			0x02
+#define	BGE_PCI_CMD			0x04
+#define	BGE_PCI_STS			0x06
+#define	BGE_PCI_REV			0x08
+#define	BGE_PCI_CLASS			0x09
+#define	BGE_PCI_CACHESZ			0x0C
+#define	BGE_PCI_LATTIMER		0x0D
+#define	BGE_PCI_HDRTYPE			0x0E
+#define	BGE_PCI_BIST			0x0F
+#define	BGE_PCI_BAR0			0x10
+#define	BGE_PCI_BAR1			0x14
+#define	BGE_PCI_SUBSYS			0x2C
+#define	BGE_PCI_SUBVID			0x2E
+#define	BGE_PCI_ROMBASE			0x30
+#define	BGE_PCI_CAPPTR			0x34
+#define	BGE_PCI_INTLINE			0x3C
+#define	BGE_PCI_INTPIN			0x3D
+#define	BGE_PCI_MINGNT			0x3E
+#define	BGE_PCI_MAXLAT			0x3F
+#define	BGE_PCI_PCIXCAP			0x40
+#define	BGE_PCI_NEXTPTR_PM		0x41
+#define	BGE_PCI_PCIX_CMD		0x42
+#define	BGE_PCI_PCIX_STS		0x44
+#define	BGE_PCI_PWRMGMT_CAPID		0x48
+#define	BGE_PCI_NEXTPTR_VPD		0x49
+#define	BGE_PCI_PWRMGMT_CAPS		0x4A
+#define	BGE_PCI_PWRMGMT_CMD		0x4C
+#define	BGE_PCI_PWRMGMT_STS		0x4D
+#define	BGE_PCI_PWRMGMT_DATA		0x4F
+#define	BGE_PCI_VPD_CAPID		0x50
+#define	BGE_PCI_NEXTPTR_MSI		0x51
+#define	BGE_PCI_VPD_ADDR		0x52
+#define	BGE_PCI_VPD_DATA		0x54
+#define	BGE_PCI_MSI_CAPID		0x58
+#define	BGE_PCI_NEXTPTR_NONE		0x59
+#define	BGE_PCI_MSI_CTL			0x5A
+#define	BGE_PCI_MSI_ADDR_HI		0x5C
+#define	BGE_PCI_MSI_ADDR_LO		0x60
+#define	BGE_PCI_MSI_DATA		0x64
+
+/*
+ * PCI Express definitions
+ * According to
+ * PCI Express base specification, REV. 1.0a
+ */
+
+/* PCI Express device control, 16bits */
+#define	BGE_PCIE_DEVCTL			0x08
+#define	BGE_PCIE_DEVCTL_MAX_READRQ_MASK	0x7000
+#define	BGE_PCIE_DEVCTL_MAX_READRQ_128	0x0000
+#define	BGE_PCIE_DEVCTL_MAX_READRQ_256	0x1000
+#define	BGE_PCIE_DEVCTL_MAX_READRQ_512	0x2000
+#define	BGE_PCIE_DEVCTL_MAX_READRQ_1024	0x3000
+#define	BGE_PCIE_DEVCTL_MAX_READRQ_2048	0x4000
+#define	BGE_PCIE_DEVCTL_MAX_READRQ_4096	0x5000
+
+/* PCI MSI. ??? */
+#define	BGE_PCIE_CAPID_REG		0xD0
+#define	BGE_PCIE_CAPID			0x10
+
+/*
+ * PCI registers specific to the BCM570x family.
+ */
+#define	BGE_PCI_MISC_CTL		0x68
+#define	BGE_PCI_DMA_RW_CTL		0x6C
+#define	BGE_PCI_PCISTATE		0x70
+#define	BGE_PCI_CLKCTL			0x74
+#define	BGE_PCI_REG_BASEADDR		0x78
+#define	BGE_PCI_MEMWIN_BASEADDR		0x7C
+#define	BGE_PCI_REG_DATA		0x80
+#define	BGE_PCI_MEMWIN_DATA		0x84
+#define	BGE_PCI_MODECTL			0x88
+#define	BGE_PCI_MISC_CFG		0x8C
+#define	BGE_PCI_MISC_LOCALCTL		0x90
+#define	BGE_PCI_UNDI_RX_STD_PRODIDX_HI	0x98
+#define	BGE_PCI_UNDI_RX_STD_PRODIDX_LO	0x9C
+#define	BGE_PCI_UNDI_RX_RTN_CONSIDX_HI	0xA0
+#define	BGE_PCI_UNDI_RX_RTN_CONSIDX_LO	0xA4
+#define	BGE_PCI_UNDI_TX_BD_PRODIDX_HI	0xA8
+#define	BGE_PCI_UNDI_TX_BD_PRODIDX_LO	0xAC
+#define	BGE_PCI_ISR_MBX_HI		0xB0
+#define	BGE_PCI_ISR_MBX_LO		0xB4
+#define	BGE_PCI_PRODID_ASICREV		0xBC
+#define	BGE_PCI_GEN2_PRODID_ASICREV	0xF4
+#define	BGE_PCI_GEN15_PRODID_ASICREV	0xFC
+
+/* PCI Misc. Host control register */
+#define	BGE_PCIMISCCTL_CLEAR_INTA	0x00000001
+#define	BGE_PCIMISCCTL_MASK_PCI_INTR	0x00000002
+#define	BGE_PCIMISCCTL_ENDIAN_BYTESWAP	0x00000004
+#define	BGE_PCIMISCCTL_ENDIAN_WORDSWAP	0x00000008
+#define	BGE_PCIMISCCTL_PCISTATE_RW	0x00000010
+#define	BGE_PCIMISCCTL_CLOCKCTL_RW	0x00000020
+#define	BGE_PCIMISCCTL_REG_WORDSWAP	0x00000040
+#define	BGE_PCIMISCCTL_INDIRECT_ACCESS	0x00000080
+#define	BGE_PCIMISCCTL_TAGGED_STATUS	0x00000200
+#define	BGE_PCIMISCCTL_ASICREV		0xFFFF0000
+#define	BGE_PCIMISCCTL_ASICREV_SHIFT	16
+
+#define	BGE_HIF_SWAP_OPTIONS	(BGE_PCIMISCCTL_ENDIAN_WORDSWAP)
+
+#define	BGE_INIT \
+	(BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_CLEAR_INTA| \
+	 BGE_PCIMISCCTL_MASK_PCI_INTR|BGE_PCIMISCCTL_INDIRECT_ACCESS)
+
+#define	BGE_CHIPID_TIGON_I		0x4000
+#define	BGE_CHIPID_TIGON_II		0x6000
+#define	BGE_CHIPID_BCM5700_A0		0x7000
+#define	BGE_CHIPID_BCM5700_A1		0x7001
+#define	BGE_CHIPID_BCM5700_B0		0x7100
+#define	BGE_CHIPID_BCM5700_B1		0x7101
+#define	BGE_CHIPID_BCM5700_B2		0x7102
+#define	BGE_CHIPID_BCM5700_B3		0x7103
+#define	BGE_CHIPID_BCM5700_ALTIMA	0x7104
+#define	BGE_CHIPID_BCM5700_C0		0x7200
+#define	BGE_CHIPID_BCM5701_A0		0x0000	/* grrrr */
+#define	BGE_CHIPID_BCM5701_B0		0x0100
+#define	BGE_CHIPID_BCM5701_B2		0x0102
+#define	BGE_CHIPID_BCM5701_B5		0x0105
+#define	BGE_CHIPID_BCM5703_A0		0x1000
+#define	BGE_CHIPID_BCM5703_A1		0x1001
+#define	BGE_CHIPID_BCM5703_A2		0x1002
+#define	BGE_CHIPID_BCM5703_A3		0x1003
+#define	BGE_CHIPID_BCM5703_B0		0x1100
+#define	BGE_CHIPID_BCM5704_A0		0x2000
+#define	BGE_CHIPID_BCM5704_A1		0x2001
+#define	BGE_CHIPID_BCM5704_A2		0x2002
+#define	BGE_CHIPID_BCM5704_A3		0x2003
+#define	BGE_CHIPID_BCM5704_B0		0x2100
+#define	BGE_CHIPID_BCM5705_A0		0x3000
+#define	BGE_CHIPID_BCM5705_A1		0x3001
+#define	BGE_CHIPID_BCM5705_A2		0x3002
+#define	BGE_CHIPID_BCM5705_A3		0x3003
+#define	BGE_CHIPID_BCM5750_A0		0x4000
+#define	BGE_CHIPID_BCM5750_A1		0x4001
+#define	BGE_CHIPID_BCM5750_A3		0x4000
+#define	BGE_CHIPID_BCM5750_B0		0x4100
+#define	BGE_CHIPID_BCM5750_B1		0x4101
+#define	BGE_CHIPID_BCM5750_C0		0x4200
+#define	BGE_CHIPID_BCM5750_C1		0x4201
+#define	BGE_CHIPID_BCM5750_C2		0x4202
+#define	BGE_CHIPID_BCM5714_A0		0x5000
+#define	BGE_CHIPID_BCM5752_A0		0x6000
+#define	BGE_CHIPID_BCM5752_A1		0x6001
+#define	BGE_CHIPID_BCM5752_A2		0x6002
+#define	BGE_CHIPID_BCM5714_B0		0x8000
+#define	BGE_CHIPID_BCM5714_B3		0x8003
+#define	BGE_CHIPID_BCM5715_A0		0x9000
+#define	BGE_CHIPID_BCM5715_A1		0x9001
+#define	BGE_CHIPID_BCM5715_A3		0x9003
+#define	BGE_CHIPID_BCM5755_A0		0xa000
+#define	BGE_CHIPID_BCM5755_A1		0xa001
+#define	BGE_CHIPID_BCM5755_A2		0xa002
+#define	BGE_CHIPID_BCM5722_A0		0xa200
+#define	BGE_CHIPID_BCM5754_A0		0xb000
+#define	BGE_CHIPID_BCM5754_A1		0xb001
+#define	BGE_CHIPID_BCM5754_A2		0xb002
+#define	BGE_CHIPID_BCM5761_A0		0x5761000
+#define	BGE_CHIPID_BCM5761_A1		0x5761100
+#define	BGE_CHIPID_BCM5784_A0		0x5784000
+#define	BGE_CHIPID_BCM5784_A1		0x5784100
+#define	BGE_CHIPID_BCM5787_A0		0xb000
+#define	BGE_CHIPID_BCM5787_A1		0xb001
+#define	BGE_CHIPID_BCM5787_A2		0xb002
+#define	BGE_CHIPID_BCM5906_A0		0xc000
+#define	BGE_CHIPID_BCM5906_A1		0xc001
+#define	BGE_CHIPID_BCM5906_A2		0xc002
+#define	BGE_CHIPID_BCM57780_A0		0x57780000
+#define	BGE_CHIPID_BCM57780_A1		0x57780001
+#define	BGE_CHIPID_BCM5717_A0		0x05717000
+#define	BGE_CHIPID_BCM5717_B0		0x05717100
+#define	BGE_CHIPID_BCM5719_A0		0x05719000
+#define	BGE_CHIPID_BCM5720_A0		0x05720000
+#define	BGE_CHIPID_BCM5762_A0		0x05762000
+#define	BGE_CHIPID_BCM57765_A0		0x57785000
+#define	BGE_CHIPID_BCM57765_B0		0x57785100
+
+/* shorthand one */
+#define	BGE_ASICREV(x)			((x) >> 12)
+#define	BGE_ASICREV_BCM5701		0x00
+#define	BGE_ASICREV_BCM5703		0x01
+#define	BGE_ASICREV_BCM5704		0x02
+#define	BGE_ASICREV_BCM5705		0x03
+#define	BGE_ASICREV_BCM5750		0x04
+#define	BGE_ASICREV_BCM5714_A0		0x05
+#define	BGE_ASICREV_BCM5752		0x06
+#define	BGE_ASICREV_BCM5700		0x07
+#define	BGE_ASICREV_BCM5780		0x08
+#define	BGE_ASICREV_BCM5714		0x09
+#define	BGE_ASICREV_BCM5755		0x0a
+#define	BGE_ASICREV_BCM5754		0x0b
+#define	BGE_ASICREV_BCM5787		0x0b
+#define	BGE_ASICREV_BCM5906		0x0c
+/* Should consult BGE_PCI_PRODID_ASICREV for ChipID */
+#define	BGE_ASICREV_USE_PRODID_REG	0x0f
+/* BGE_PCI_PRODID_ASICREV ASIC rev. identifiers. */
+#define	BGE_ASICREV_BCM5717		0x5717
+#define	BGE_ASICREV_BCM5719		0x5719
+#define	BGE_ASICREV_BCM5720		0x5720
+#define	BGE_ASICREV_BCM5761		0x5761
+#define	BGE_ASICREV_BCM5762		0x5762
+#define	BGE_ASICREV_BCM5784		0x5784
+#define	BGE_ASICREV_BCM5785		0x5785
+#define	BGE_ASICREV_BCM57765		0x57785
+#define	BGE_ASICREV_BCM57766		0x57766
+#define	BGE_ASICREV_BCM57780		0x57780
+
+/* chip revisions */
+#define	BGE_CHIPREV(x)			((x) >> 8)
+#define	BGE_CHIPREV_5700_AX		0x70
+#define	BGE_CHIPREV_5700_BX		0x71
+#define	BGE_CHIPREV_5700_CX		0x72
+#define	BGE_CHIPREV_5701_AX		0x00
+#define	BGE_CHIPREV_5703_AX		0x10
+#define	BGE_CHIPREV_5704_AX		0x20
+#define	BGE_CHIPREV_5704_BX		0x21
+#define	BGE_CHIPREV_5750_AX		0x40
+#define	BGE_CHIPREV_5750_BX		0x41
+/* BGE_PCI_PRODID_ASICREV chip rev. identifiers. */
+#define	BGE_CHIPREV_5717_AX		0x57170
+#define	BGE_CHIPREV_5717_BX		0x57171
+#define	BGE_CHIPREV_5761_AX		0x57611
+#define	BGE_CHIPREV_57765_AX		0x577850
+#define	BGE_CHIPREV_5784_AX		0x57841
+
+/* PCI DMA Read/Write Control register */
+#define	BGE_PCIDMARWCTL_MINDMA		0x000000FF
+#define	BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT	0x00000001
+#define	BGE_PCIDMARWCTL_RDADRR_BNDRY	0x00000700
+#define	BGE_PCIDMARWCTL_WRADDR_BNDRY	0x00003800
+#define	BGE_PCIDMARWCTL_ONEDMA_ATONCE	0x0000C000
+#define	BGE_PCIDMARWCTL_ONEDMA_ATONCE_GLOBAL	0x00004000
+#define	BGE_PCIDMARWCTL_ONEDMA_ATONCE_LOCAL	0x00008000
+#define	BGE_PCIDMARWCTL_RD_WAT		0x00070000
+#define	BGE_PCIDMARWCTL_WR_WAT		0x00380000
+#define	BGE_PCIDMARWCTL_USE_MRM		0x00400000
+#define	BGE_PCIDMARWCTL_ASRT_ALL_BE	0x00800000
+#define	BGE_PCIDMARWCTL_DFLT_PCI_RD_CMD	0x0F000000
+#define	BGE_PCIDMARWCTL_DFLT_PCI_WR_CMD	0xF0000000
+
+#define	BGE_PCIDMARWCTL_RD_WAT_SHIFT(x)	((x) << 16)
+#define	BGE_PCIDMARWCTL_WR_WAT_SHIFT(x)	((x) << 19)
+#define	BGE_PCIDMARWCTL_RD_CMD_SHIFT(x)	((x) << 24)
+#define	BGE_PCIDMARWCTL_WR_CMD_SHIFT(x)	((x) << 28)
+
+#define	BGE_PCIDMARWCTL_TAGGED_STATUS_WA	0x00000080
+#define	BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK	0x00000380
+
+#define	BGE_PCI_READ_BNDRY_DISABLE	0x00000000
+#define	BGE_PCI_READ_BNDRY_16BYTES	0x00000100
+#define	BGE_PCI_READ_BNDRY_32BYTES	0x00000200
+#define	BGE_PCI_READ_BNDRY_64BYTES	0x00000300
+#define	BGE_PCI_READ_BNDRY_128BYTES	0x00000400
+#define	BGE_PCI_READ_BNDRY_256BYTES	0x00000500
+#define	BGE_PCI_READ_BNDRY_512BYTES	0x00000600
+#define	BGE_PCI_READ_BNDRY_1024BYTES	0x00000700
+
+#define	BGE_PCI_WRITE_BNDRY_DISABLE	0x00000000
+#define	BGE_PCI_WRITE_BNDRY_16BYTES	0x00000800
+#define	BGE_PCI_WRITE_BNDRY_32BYTES	0x00001000
+#define	BGE_PCI_WRITE_BNDRY_64BYTES	0x00001800
+#define	BGE_PCI_WRITE_BNDRY_128BYTES	0x00002000
+#define	BGE_PCI_WRITE_BNDRY_256BYTES	0x00002800
+#define	BGE_PCI_WRITE_BNDRY_512BYTES	0x00003000
+#define	BGE_PCI_WRITE_BNDRY_1024BYTES	0x00003800
+
+/*
+ * PCI state register -- note, this register is read only
+ * unless the PCISTATE_WR bit of the PCI Misc. Host Control
+ * register is set.
+ */
+#define	BGE_PCISTATE_FORCE_RESET	0x00000001
+#define	BGE_PCISTATE_INTR_STATE		0x00000002
+#define	BGE_PCISTATE_PCI_BUSMODE	0x00000004 /* 1 = PCI, 0 = PCI-X */
+#define	BGE_PCISTATE_PCI_BUSSPEED	0x00000008 /* 1 = 66/133, 0 = 33/66 */
+#define	BGE_PCISTATE_32BIT_BUS		0x00000010 /* 1 = 32bit, 0 = 64bit */
+#define	BGE_PCISTATE_ROM_ENABLE		0x00000020
+#define	BGE_PCISTATE_ROM_RETRY_ENABLE	0x00000040
+#define	BGE_PCISTATE_FLATVIEW_MODE	0x00000100
+#define	BGE_PCISTATE_PCI_TGT_RETRY_MAX	0x00000E00
+#define	BGE_PCISTATE_RETRY_SAME_DMA	0x00002000
+#define	BGE_PCISTATE_ALLOW_APE_CTLSPC_WR	0x00010000
+#define	BGE_PCISTATE_ALLOW_APE_SHMEM_WR	0x00020000
+#define	BGE_PCISTATE_ALLOW_APE_PSPACE_WR	0x00040000
+
+/*
+ * PCI Clock Control register -- note, this register is read only
+ * unless the CLOCKCTL_RW bit of the PCI Misc. Host Control
+ * register is set.
+ */
+#define	BGE_PCICLOCKCTL_DETECTED_SPEED	0x0000000F
+#define	BGE_PCICLOCKCTL_M66EN		0x00000080
+#define	BGE_PCICLOCKCTL_LOWPWR_CLKMODE	0x00000200
+#define	BGE_PCICLOCKCTL_RXCPU_CLK_DIS	0x00000400
+#define	BGE_PCICLOCKCTL_TXCPU_CLK_DIS	0x00000800
+#define	BGE_PCICLOCKCTL_ALTCLK		0x00001000
+#define	BGE_PCICLOCKCTL_ALTCLK_SRC	0x00002000
+#define	BGE_PCICLOCKCTL_PCIPLL_DISABLE	0x00004000
+#define	BGE_PCICLOCKCTL_SYSPLL_DISABLE	0x00008000
+#define	BGE_PCICLOCKCTL_BIST_ENABLE	0x00010000
+
+
+#ifndef PCIM_CMD_MWIEN
+#define	PCIM_CMD_MWIEN			0x0010
+#endif
+#ifndef PCIM_CMD_INTxDIS
+#define	PCIM_CMD_INTxDIS		0x0400
+#endif
+
+/* BAR0 (MAC) Register Definitions */
+
+/*
+ * High priority mailbox registers
+ * Each mailbox is 64-bits wide, though we only use the
+ * lower 32 bits. To write a 64-bit value, write the upper 32 bits
+ * first. The NIC will load the mailbox after the lower 32 bit word
+ * has been updated.
+ */
+#define	BGE_MBX_IRQ0_HI			0x0200
+#define	BGE_MBX_IRQ0_LO			0x0204
+#define	BGE_MBX_IRQ1_HI			0x0208
+#define	BGE_MBX_IRQ1_LO			0x020C
+#define	BGE_MBX_IRQ2_HI			0x0210
+#define	BGE_MBX_IRQ2_LO			0x0214
+#define	BGE_MBX_IRQ3_HI			0x0218
+#define	BGE_MBX_IRQ3_LO			0x021C
+#define	BGE_MBX_GEN0_HI			0x0220
+#define	BGE_MBX_GEN0_LO			0x0224
+#define	BGE_MBX_GEN1_HI			0x0228
+#define	BGE_MBX_GEN1_LO			0x022C
+#define	BGE_MBX_GEN2_HI			0x0230
+#define	BGE_MBX_GEN2_LO			0x0234
+#define	BGE_MBX_GEN3_HI			0x0228
+#define	BGE_MBX_GEN3_LO			0x022C
+#define	BGE_MBX_GEN4_HI			0x0240
+#define	BGE_MBX_GEN4_LO			0x0244
+#define	BGE_MBX_GEN5_HI			0x0248
+#define	BGE_MBX_GEN5_LO			0x024C
+#define	BGE_MBX_GEN6_HI			0x0250
+#define	BGE_MBX_GEN6_LO			0x0254
+#define	BGE_MBX_GEN7_HI			0x0258
+#define	BGE_MBX_GEN7_LO			0x025C
+#define	BGE_MBX_RELOAD_STATS_HI		0x0260
+#define	BGE_MBX_RELOAD_STATS_LO		0x0264
+#define	BGE_MBX_RX_STD_PROD_HI		0x0268
+#define	BGE_MBX_RX_STD_PROD_LO		0x026C
+#define	BGE_MBX_RX_JUMBO_PROD_HI	0x0270
+#define	BGE_MBX_RX_JUMBO_PROD_LO	0x0274
+#define	BGE_MBX_RX_MINI_PROD_HI		0x0278
+#define	BGE_MBX_RX_MINI_PROD_LO		0x027C
+#define	BGE_MBX_RX_CONS0_HI		0x0280
+#define	BGE_MBX_RX_CONS0_LO		0x0284
+#define	BGE_MBX_RX_CONS1_HI		0x0288
+#define	BGE_MBX_RX_CONS1_LO		0x028C
+#define	BGE_MBX_RX_CONS2_HI		0x0290
+#define	BGE_MBX_RX_CONS2_LO		0x0294
+#define	BGE_MBX_RX_CONS3_HI		0x0298
+#define	BGE_MBX_RX_CONS3_LO		0x029C
+#define	BGE_MBX_RX_CONS4_HI		0x02A0
+#define	BGE_MBX_RX_CONS4_LO		0x02A4
+#define	BGE_MBX_RX_CONS5_HI		0x02A8
+#define	BGE_MBX_RX_CONS5_LO		0x02AC
+#define	BGE_MBX_RX_CONS6_HI		0x02B0
+#define	BGE_MBX_RX_CONS6_LO		0x02B4
+#define	BGE_MBX_RX_CONS7_HI		0x02B8
+#define	BGE_MBX_RX_CONS7_LO		0x02BC
+#define	BGE_MBX_RX_CONS8_HI		0x02C0
+#define	BGE_MBX_RX_CONS8_LO		0x02C4
+#define	BGE_MBX_RX_CONS9_HI		0x02C8
+#define	BGE_MBX_RX_CONS9_LO		0x02CC
+#define	BGE_MBX_RX_CONS10_HI		0x02D0
+#define	BGE_MBX_RX_CONS10_LO		0x02D4
+#define	BGE_MBX_RX_CONS11_HI		0x02D8
+#define	BGE_MBX_RX_CONS11_LO		0x02DC
+#define	BGE_MBX_RX_CONS12_HI		0x02E0
+#define	BGE_MBX_RX_CONS12_LO		0x02E4
+#define	BGE_MBX_RX_CONS13_HI		0x02E8
+#define	BGE_MBX_RX_CONS13_LO		0x02EC
+#define	BGE_MBX_RX_CONS14_HI		0x02F0
+#define	BGE_MBX_RX_CONS14_LO		0x02F4
+#define	BGE_MBX_RX_CONS15_HI		0x02F8
+#define	BGE_MBX_RX_CONS15_LO		0x02FC
+#define	BGE_MBX_TX_HOST_PROD0_HI	0x0300
+#define	BGE_MBX_TX_HOST_PROD0_LO	0x0304
+#define	BGE_MBX_TX_HOST_PROD1_HI	0x0308
+#define	BGE_MBX_TX_HOST_PROD1_LO	0x030C
+#define	BGE_MBX_TX_HOST_PROD2_HI	0x0310
+#define	BGE_MBX_TX_HOST_PROD2_LO	0x0314
+#define	BGE_MBX_TX_HOST_PROD3_HI	0x0318
+#define	BGE_MBX_TX_HOST_PROD3_LO	0x031C
+#define	BGE_MBX_TX_HOST_PROD4_HI	0x0320
+#define	BGE_MBX_TX_HOST_PROD4_LO	0x0324
+#define	BGE_MBX_TX_HOST_PROD5_HI	0x0328
+#define	BGE_MBX_TX_HOST_PROD5_LO	0x032C
+#define	BGE_MBX_TX_HOST_PROD6_HI	0x0330
+#define	BGE_MBX_TX_HOST_PROD6_LO	0x0334
+#define	BGE_MBX_TX_HOST_PROD7_HI	0x0338
+#define	BGE_MBX_TX_HOST_PROD7_LO	0x033C
+#define	BGE_MBX_TX_HOST_PROD8_HI	0x0340
+#define	BGE_MBX_TX_HOST_PROD8_LO	0x0344
+#define	BGE_MBX_TX_HOST_PROD9_HI	0x0348
+#define	BGE_MBX_TX_HOST_PROD9_LO	0x034C
+#define	BGE_MBX_TX_HOST_PROD10_HI	0x0350
+#define	BGE_MBX_TX_HOST_PROD10_LO	0x0354
+#define	BGE_MBX_TX_HOST_PROD11_HI	0x0358
+#define	BGE_MBX_TX_HOST_PROD11_LO	0x035C
+#define	BGE_MBX_TX_HOST_PROD12_HI	0x0360
+#define	BGE_MBX_TX_HOST_PROD12_LO	0x0364
+#define	BGE_MBX_TX_HOST_PROD13_HI	0x0368
+#define	BGE_MBX_TX_HOST_PROD13_LO	0x036C
+#define	BGE_MBX_TX_HOST_PROD14_HI	0x0370
+#define	BGE_MBX_TX_HOST_PROD14_LO	0x0374
+#define	BGE_MBX_TX_HOST_PROD15_HI	0x0378
+#define	BGE_MBX_TX_HOST_PROD15_LO	0x037C
+#define	BGE_MBX_TX_NIC_PROD0_HI		0x0380
+#define	BGE_MBX_TX_NIC_PROD0_LO		0x0384
+#define	BGE_MBX_TX_NIC_PROD1_HI		0x0388
+#define	BGE_MBX_TX_NIC_PROD1_LO		0x038C
+#define	BGE_MBX_TX_NIC_PROD2_HI		0x0390
+#define	BGE_MBX_TX_NIC_PROD2_LO		0x0394
+#define	BGE_MBX_TX_NIC_PROD3_HI		0x0398
+#define	BGE_MBX_TX_NIC_PROD3_LO		0x039C
+#define	BGE_MBX_TX_NIC_PROD4_HI		0x03A0
+#define	BGE_MBX_TX_NIC_PROD4_LO		0x03A4
+#define	BGE_MBX_TX_NIC_PROD5_HI		0x03A8
+#define	BGE_MBX_TX_NIC_PROD5_LO		0x03AC
+#define	BGE_MBX_TX_NIC_PROD6_HI		0x03B0
+#define	BGE_MBX_TX_NIC_PROD6_LO		0x03B4
+#define	BGE_MBX_TX_NIC_PROD7_HI		0x03B8
+#define	BGE_MBX_TX_NIC_PROD7_LO		0x03BC
+#define	BGE_MBX_TX_NIC_PROD8_HI		0x03C0
+#define	BGE_MBX_TX_NIC_PROD8_LO		0x03C4
+#define	BGE_MBX_TX_NIC_PROD9_HI		0x03C8
+#define	BGE_MBX_TX_NIC_PROD9_LO		0x03CC
+#define	BGE_MBX_TX_NIC_PROD10_HI	0x03D0
+#define	BGE_MBX_TX_NIC_PROD10_LO	0x03D4
+#define	BGE_MBX_TX_NIC_PROD11_HI	0x03D8
+#define	BGE_MBX_TX_NIC_PROD11_LO	0x03DC
+#define	BGE_MBX_TX_NIC_PROD12_HI	0x03E0
+#define	BGE_MBX_TX_NIC_PROD12_LO	0x03E4
+#define	BGE_MBX_TX_NIC_PROD13_HI	0x03E8
+#define	BGE_MBX_TX_NIC_PROD13_LO	0x03EC
+#define	BGE_MBX_TX_NIC_PROD14_HI	0x03F0
+#define	BGE_MBX_TX_NIC_PROD14_LO	0x03F4
+#define	BGE_MBX_TX_NIC_PROD15_HI	0x03F8
+#define	BGE_MBX_TX_NIC_PROD15_LO	0x03FC
+
+#define	BGE_TX_RINGS_MAX		4
+#define	BGE_TX_RINGS_EXTSSRAM_MAX	16
+#define	BGE_RX_RINGS_MAX		16
+#define	BGE_RX_RINGS_MAX_5717		17
+
+/* Ethernet MAC control registers */
+#define	BGE_MAC_MODE			0x0400
+#define	BGE_MAC_STS			0x0404
+#define	BGE_MAC_EVT_ENB			0x0408
+#define	BGE_MAC_LED_CTL			0x040C
+#define	BGE_MAC_ADDR1_LO		0x0410
+#define	BGE_MAC_ADDR1_HI		0x0414
+#define	BGE_MAC_ADDR2_LO		0x0418
+#define	BGE_MAC_ADDR2_HI		0x041C
+#define	BGE_MAC_ADDR3_LO		0x0420
+#define	BGE_MAC_ADDR3_HI		0x0424
+#define	BGE_MAC_ADDR4_LO		0x0428
+#define	BGE_MAC_ADDR4_HI		0x042C
+#define	BGE_WOL_PATPTR			0x0430
+#define	BGE_WOL_PATCFG			0x0434
+#define	BGE_TX_RANDOM_BACKOFF		0x0438
+#define	BGE_RX_MTU			0x043C
+#define	BGE_GBIT_PCS_TEST		0x0440
+#define	BGE_TX_TBI_AUTONEG		0x0444
+#define	BGE_RX_TBI_AUTONEG		0x0448
+#define	BGE_MI_COMM			0x044C
+#define	BGE_MI_STS			0x0450
+#define	BGE_MI_MODE			0x0454
+#define	BGE_AUTOPOLL_STS		0x0458
+#define	BGE_TX_MODE			0x045C
+#define	BGE_TX_STS			0x0460
+#define	BGE_TX_LENGTHS			0x0464
+#define	BGE_RX_MODE			0x0468
+#define	BGE_RX_STS			0x046C
+#define	BGE_MAR0			0x0470
+#define	BGE_MAR1			0x0474
+#define	BGE_MAR2			0x0478
+#define	BGE_MAR3			0x047C
+#define	BGE_RX_BD_RULES_CTL0		0x0480
+#define	BGE_RX_BD_RULES_MASKVAL0	0x0484
+#define	BGE_RX_BD_RULES_CTL1		0x0488
+#define	BGE_RX_BD_RULES_MASKVAL1	0x048C
+#define	BGE_RX_BD_RULES_CTL2		0x0490
+#define	BGE_RX_BD_RULES_MASKVAL2	0x0494
+#define	BGE_RX_BD_RULES_CTL3		0x0498
+#define	BGE_RX_BD_RULES_MASKVAL3	0x049C
+#define	BGE_RX_BD_RULES_CTL4		0x04A0
+#define	BGE_RX_BD_RULES_MASKVAL4	0x04A4
+#define	BGE_RX_BD_RULES_CTL5		0x04A8
+#define	BGE_RX_BD_RULES_MASKVAL5	0x04AC
+#define	BGE_RX_BD_RULES_CTL6		0x04B0
+#define	BGE_RX_BD_RULES_MASKVAL6	0x04B4
+#define	BGE_RX_BD_RULES_CTL7		0x04B8
+#define	BGE_RX_BD_RULES_MASKVAL7	0x04BC
+#define	BGE_RX_BD_RULES_CTL8		0x04C0
+#define	BGE_RX_BD_RULES_MASKVAL8	0x04C4
+#define	BGE_RX_BD_RULES_CTL9		0x04C8
+#define	BGE_RX_BD_RULES_MASKVAL9	0x04CC
+#define	BGE_RX_BD_RULES_CTL10		0x04D0
+#define	BGE_RX_BD_RULES_MASKVAL10	0x04D4
+#define	BGE_RX_BD_RULES_CTL11		0x04D8
+#define	BGE_RX_BD_RULES_MASKVAL11	0x04DC
+#define	BGE_RX_BD_RULES_CTL12		0x04E0
+#define	BGE_RX_BD_RULES_MASKVAL12	0x04E4
+#define	BGE_RX_BD_RULES_CTL13		0x04E8
+#define	BGE_RX_BD_RULES_MASKVAL13	0x04EC
+#define	BGE_RX_BD_RULES_CTL14		0x04F0
+#define	BGE_RX_BD_RULES_MASKVAL14	0x04F4
+#define	BGE_RX_BD_RULES_CTL15		0x04F8
+#define	BGE_RX_BD_RULES_MASKVAL15	0x04FC
+#define	BGE_RX_RULES_CFG		0x0500
+#define	BGE_MAX_RX_FRAME_LOWAT		0x0504
+#define	BGE_SERDES_CFG			0x0590
+#define	BGE_SERDES_STS			0x0594
+#define	BGE_SGDIG_CFG			0x05B0
+#define	BGE_SGDIG_STS			0x05B4
+#define	BGE_TX_MAC_STATS_OCTETS		0x0800
+#define	BGE_TX_MAC_STATS_RESERVE_0	0x0804
+#define	BGE_TX_MAC_STATS_COLLS		0x0808
+#define	BGE_TX_MAC_STATS_XON_SENT	0x080C
+#define	BGE_TX_MAC_STATS_XOFF_SENT	0x0810
+#define	BGE_TX_MAC_STATS_RESERVE_1	0x0814
+#define	BGE_TX_MAC_STATS_ERRORS		0x0818
+#define	BGE_TX_MAC_STATS_SINGLE_COLL	0x081C
+#define	BGE_TX_MAC_STATS_MULTI_COLL	0x0820
+#define	BGE_TX_MAC_STATS_DEFERRED	0x0824
+#define	BGE_TX_MAC_STATS_RESERVE_2	0x0828
+#define	BGE_TX_MAC_STATS_EXCESS_COLL	0x082C
+#define	BGE_TX_MAC_STATS_LATE_COLL	0x0830
+#define	BGE_TX_MAC_STATS_RESERVE_3	0x0834
+#define	BGE_TX_MAC_STATS_RESERVE_4	0x0838
+#define	BGE_TX_MAC_STATS_RESERVE_5	0x083C
+#define	BGE_TX_MAC_STATS_RESERVE_6	0x0840
+#define	BGE_TX_MAC_STATS_RESERVE_7	0x0844
+#define	BGE_TX_MAC_STATS_RESERVE_8	0x0848
+#define	BGE_TX_MAC_STATS_RESERVE_9	0x084C
+#define	BGE_TX_MAC_STATS_RESERVE_10	0x0850
+#define	BGE_TX_MAC_STATS_RESERVE_11	0x0854
+#define	BGE_TX_MAC_STATS_RESERVE_12	0x0858
+#define	BGE_TX_MAC_STATS_RESERVE_13	0x085C
+#define	BGE_TX_MAC_STATS_RESERVE_14	0x0860
+#define	BGE_TX_MAC_STATS_RESERVE_15	0x0864
+#define	BGE_TX_MAC_STATS_RESERVE_16	0x0868
+#define	BGE_TX_MAC_STATS_UCAST		0x086C
+#define	BGE_TX_MAC_STATS_MCAST		0x0870
+#define	BGE_TX_MAC_STATS_BCAST		0x0874
+#define	BGE_TX_MAC_STATS_RESERVE_17	0x0878
+#define	BGE_TX_MAC_STATS_RESERVE_18	0x087C
+#define	BGE_RX_MAC_STATS_OCTESTS	0x0880
+#define	BGE_RX_MAC_STATS_RESERVE_0	0x0884
+#define	BGE_RX_MAC_STATS_FRAGMENTS	0x0888
+#define	BGE_RX_MAC_STATS_UCAST		0x088C
+#define	BGE_RX_MAC_STATS_MCAST		0x0890
+#define	BGE_RX_MAC_STATS_BCAST		0x0894
+#define	BGE_RX_MAC_STATS_FCS_ERRORS	0x0898
+#define	BGE_RX_MAC_STATS_ALGIN_ERRORS	0x089C
+#define	BGE_RX_MAC_STATS_XON_RCVD	0x08A0
+#define	BGE_RX_MAC_STATS_XOFF_RCVD	0x08A4
+#define	BGE_RX_MAC_STATS_CTRL_RCVD	0x08A8
+#define	BGE_RX_MAC_STATS_XOFF_ENTERED	0x08AC
+#define	BGE_RX_MAC_STATS_FRAME_TOO_LONG	0x08B0
+#define	BGE_RX_MAC_STATS_JABBERS	0x08B4
+#define	BGE_RX_MAC_STATS_UNDERSIZE	0x08B8
+
+/* Ethernet MAC Mode register */
+#define	BGE_MACMODE_RESET		0x00000001
+#define	BGE_MACMODE_HALF_DUPLEX		0x00000002
+#define	BGE_MACMODE_PORTMODE		0x0000000C
+#define	BGE_MACMODE_LOOPBACK		0x00000010
+#define	BGE_MACMODE_RX_TAGGEDPKT	0x00000080
+#define	BGE_MACMODE_TX_BURST_ENB	0x00000100
+#define	BGE_MACMODE_MAX_DEFER		0x00000200
+#define	BGE_MACMODE_LINK_POLARITY	0x00000400
+#define	BGE_MACMODE_RX_STATS_ENB	0x00000800
+#define	BGE_MACMODE_RX_STATS_CLEAR	0x00001000
+#define	BGE_MACMODE_RX_STATS_FLUSH	0x00002000
+#define	BGE_MACMODE_TX_STATS_ENB	0x00004000
+#define	BGE_MACMODE_TX_STATS_CLEAR	0x00008000
+#define	BGE_MACMODE_TX_STATS_FLUSH	0x00010000
+#define	BGE_MACMODE_TBI_SEND_CFGS	0x00020000
+#define	BGE_MACMODE_MAGIC_PKT_ENB	0x00040000
+#define	BGE_MACMODE_ACPI_PWRON_ENB	0x00080000
+#define	BGE_MACMODE_MIP_ENB		0x00100000
+#define	BGE_MACMODE_TXDMA_ENB		0x00200000
+#define	BGE_MACMODE_RXDMA_ENB		0x00400000
+#define	BGE_MACMODE_FRMHDR_DMA_ENB	0x00800000
+#define	BGE_MACMODE_APE_RX_EN		0x08000000
+#define	BGE_MACMODE_APE_TX_EN		0x10000000
+
+#define	BGE_PORTMODE_NONE		0x00000000
+#define	BGE_PORTMODE_MII		0x00000004
+#define	BGE_PORTMODE_GMII		0x00000008
+#define	BGE_PORTMODE_TBI		0x0000000C
+
+/* MAC Status register */
+#define	BGE_MACSTAT_TBI_PCS_SYNCHED	0x00000001
+#define	BGE_MACSTAT_TBI_SIGNAL_DETECT	0x00000002
+#define	BGE_MACSTAT_RX_CFG		0x00000004
+#define	BGE_MACSTAT_CFG_CHANGED		0x00000008
+#define	BGE_MACSTAT_SYNC_CHANGED	0x00000010
+#define	BGE_MACSTAT_PORT_DECODE_ERROR	0x00000400
+#define	BGE_MACSTAT_LINK_CHANGED	0x00001000
+#define	BGE_MACSTAT_MI_COMPLETE		0x00400000
+#define	BGE_MACSTAT_MI_INTERRUPT	0x00800000
+#define	BGE_MACSTAT_AUTOPOLL_ERROR	0x01000000
+#define	BGE_MACSTAT_ODI_ERROR		0x02000000
+#define	BGE_MACSTAT_RXSTAT_OFLOW	0x04000000
+#define	BGE_MACSTAT_TXSTAT_OFLOW	0x08000000
+
+/* MAC Event Enable Register */
+#define	BGE_EVTENB_PORT_DECODE_ERROR	0x00000400
+#define	BGE_EVTENB_LINK_CHANGED		0x00001000
+#define	BGE_EVTENB_MI_COMPLETE		0x00400000
+#define	BGE_EVTENB_MI_INTERRUPT		0x00800000
+#define	BGE_EVTENB_AUTOPOLL_ERROR	0x01000000
+#define	BGE_EVTENB_ODI_ERROR		0x02000000
+#define	BGE_EVTENB_RXSTAT_OFLOW		0x04000000
+#define	BGE_EVTENB_TXSTAT_OFLOW		0x08000000
+
+/* LED Control Register */
+#define	BGE_LEDCTL_LINKLED_OVERRIDE	0x00000001
+#define	BGE_LEDCTL_1000MBPS_LED		0x00000002
+#define	BGE_LEDCTL_100MBPS_LED		0x00000004
+#define	BGE_LEDCTL_10MBPS_LED		0x00000008
+#define	BGE_LEDCTL_TRAFLED_OVERRIDE	0x00000010
+#define	BGE_LEDCTL_TRAFLED_BLINK	0x00000020
+#define	BGE_LEDCTL_TRAFLED_BLINK_2	0x00000040
+#define	BGE_LEDCTL_1000MBPS_STS		0x00000080
+#define	BGE_LEDCTL_100MBPS_STS		0x00000100
+#define	BGE_LEDCTL_10MBPS_STS		0x00000200
+#define	BGE_LEDCTL_TRAFLED_STS		0x00000400
+#define	BGE_LEDCTL_BLINKPERIOD		0x7FF80000
+#define	BGE_LEDCTL_BLINKPERIOD_OVERRIDE	0x80000000
+
+/* TX backoff seed register */
+#define	BGE_TX_BACKOFF_SEED_MASK	0x3FF
+
+/* Autopoll status register */
+#define	BGE_AUTOPOLLSTS_ERROR		0x00000001
+
+/* Transmit MAC mode register */
+#define	BGE_TXMODE_RESET		0x00000001
+#define	BGE_TXMODE_ENABLE		0x00000002
+#define	BGE_TXMODE_FLOWCTL_ENABLE	0x00000010
+#define	BGE_TXMODE_BIGBACKOFF_ENABLE	0x00000020
+#define	BGE_TXMODE_LONGPAUSE_ENABLE	0x00000040
+#define	BGE_TXMODE_MBUF_LOCKUP_FIX	0x00000100
+#define	BGE_TXMODE_JMB_FRM_LEN		0x00400000
+#define	BGE_TXMODE_CNT_DN_MODE		0x00800000
+
+/* Transmit MAC status register */
+#define	BGE_TXSTAT_RX_XOFFED		0x00000001
+#define	BGE_TXSTAT_SENT_XOFF		0x00000002
+#define	BGE_TXSTAT_SENT_XON		0x00000004
+#define	BGE_TXSTAT_LINK_UP		0x00000008
+#define	BGE_TXSTAT_ODI_UFLOW		0x00000010
+#define	BGE_TXSTAT_ODI_OFLOW		0x00000020
+
+/* Transmit MAC lengths register */
+#define	BGE_TXLEN_SLOTTIME		0x000000FF
+#define	BGE_TXLEN_IPG			0x00000F00
+#define	BGE_TXLEN_CRS			0x00003000
+#define	BGE_TXLEN_JMB_FRM_LEN_MSK	0x00FF0000
+#define	BGE_TXLEN_CNT_DN_VAL_MSK	0xFF000000
+
+/* Receive MAC mode register */
+#define	BGE_RXMODE_RESET		0x00000001
+#define	BGE_RXMODE_ENABLE		0x00000002
+#define	BGE_RXMODE_FLOWCTL_ENABLE	0x00000004
+#define	BGE_RXMODE_RX_GIANTS		0x00000020
+#define	BGE_RXMODE_RX_RUNTS		0x00000040
+#define	BGE_RXMODE_8022_LENCHECK	0x00000080
+#define	BGE_RXMODE_RX_PROMISC		0x00000100
+#define	BGE_RXMODE_RX_NO_CRC_CHECK	0x00000200
+#define	BGE_RXMODE_RX_KEEP_VLAN_DIAG	0x00000400
+#define	BGE_RXMODE_IPV6_ENABLE		0x01000000
+#define	BGE_RXMODE_IPV4_FRAG_FIX	0x02000000
+
+/* Receive MAC status register */
+#define	BGE_RXSTAT_REMOTE_XOFFED	0x00000001
+#define	BGE_RXSTAT_RCVD_XOFF		0x00000002
+#define	BGE_RXSTAT_RCVD_XON		0x00000004
+
+/* Receive Rules Control register */
+#define	BGE_RXRULECTL_OFFSET		0x000000FF
+#define	BGE_RXRULECTL_CLASS		0x00001F00
+#define	BGE_RXRULECTL_HDRTYPE		0x0000E000
+#define	BGE_RXRULECTL_COMPARE_OP	0x00030000
+#define	BGE_RXRULECTL_MAP		0x01000000
+#define	BGE_RXRULECTL_DISCARD		0x02000000
+#define	BGE_RXRULECTL_MASK		0x04000000
+#define	BGE_RXRULECTL_ACTIVATE_PROC3	0x08000000
+#define	BGE_RXRULECTL_ACTIVATE_PROC2	0x10000000
+#define	BGE_RXRULECTL_ACTIVATE_PROC1	0x20000000
+#define	BGE_RXRULECTL_ANDWITHNEXT	0x40000000
+
+/* Receive Rules Mask register */
+#define	BGE_RXRULEMASK_VALUE		0x0000FFFF
+#define	BGE_RXRULEMASK_MASKVAL		0xFFFF0000
+
+/* SERDES configuration register */
+#define	BGE_SERDESCFG_RXR		0x00000007 /* phase interpolator */
+#define	BGE_SERDESCFG_RXG		0x00000018 /* rx gain setting */
+#define	BGE_SERDESCFG_RXEDGESEL		0x00000040 /* rising/falling egde */
+#define	BGE_SERDESCFG_TX_BIAS		0x00000380 /* TXDAC bias setting */
+#define	BGE_SERDESCFG_IBMAX		0x00000400 /* bias current +25% */
+#define	BGE_SERDESCFG_IBMIN		0x00000800 /* bias current -25% */
+#define	BGE_SERDESCFG_TXMODE		0x00001000
+#define	BGE_SERDESCFG_TXEDGESEL		0x00002000 /* rising/falling edge */
+#define	BGE_SERDESCFG_MODE		0x00004000 /* TXCP/TXCN disabled */
+#define	BGE_SERDESCFG_PLLTEST		0x00008000 /* PLL test mode */
+#define	BGE_SERDESCFG_CDET		0x00010000 /* comma detect enable */
+#define	BGE_SERDESCFG_TBILOOP		0x00020000 /* local loopback */
+#define	BGE_SERDESCFG_REMLOOP		0x00040000 /* remote loopback */
+#define	BGE_SERDESCFG_INVPHASE		0x00080000 /* Reverse 125Mhz clock */
+#define	BGE_SERDESCFG_12REGCTL		0x00300000 /* 1.2v regulator ctl */
+#define	BGE_SERDESCFG_REGCTL		0x00C00000 /* regulator ctl (2.5v) */
+
+/* SERDES status register */
+#define	BGE_SERDESSTS_RXSTAT		0x0000000F /* receive status bits */
+#define	BGE_SERDESSTS_CDET		0x00000010 /* comma code detected */
+
+/* SGDIG config (not documented) */
+#define	BGE_SGDIGCFG_PAUSE_CAP		0x00000800
+#define	BGE_SGDIGCFG_ASYM_PAUSE		0x00001000
+#define	BGE_SGDIGCFG_SEND		0x40000000
+#define	BGE_SGDIGCFG_AUTO		0x80000000
+
+/* SGDIG status (not documented) */
+#define	BGE_SGDIGSTS_DONE		0x00000002
+#define	BGE_SGDIGSTS_IS_SERDES		0x00000100
+#define	BGE_SGDIGSTS_PAUSE_CAP		0x00080000
+#define	BGE_SGDIGSTS_ASYM_PAUSE		0x00100000
+
+
+/* MI communication register */
+#define	BGE_MICOMM_DATA			0x0000FFFF
+#define	BGE_MICOMM_REG			0x001F0000
+#define	BGE_MICOMM_PHY			0x03E00000
+#define	BGE_MICOMM_CMD			0x0C000000
+#define	BGE_MICOMM_READFAIL		0x10000000
+#define	BGE_MICOMM_BUSY			0x20000000
+
+#define	BGE_MIREG(x)	((x & 0x1F) << 16)
+#define	BGE_MIPHY(x)	((x & 0x1F) << 21)
+#define	BGE_MICMD_WRITE			0x04000000
+#define	BGE_MICMD_READ			0x08000000
+
+/* MI status register */
+#define	BGE_MISTS_LINK			0x00000001
+#define	BGE_MISTS_10MBPS		0x00000002
+
+#define	BGE_MIMODE_CLK_10MHZ		0x00000001
+#define	BGE_MIMODE_SHORTPREAMBLE	0x00000002
+#define	BGE_MIMODE_AUTOPOLL		0x00000010
+#define	BGE_MIMODE_CLKCNT		0x001F0000
+#define	BGE_MIMODE_500KHZ_CONST		0x00008000
+#define	BGE_MIMODE_BASE			0x000C0000
+
+
+/*
+ * Send data initiator control registers.
+ */
+#define	BGE_SDI_MODE			0x0C00
+#define	BGE_SDI_STATUS			0x0C04
+#define	BGE_SDI_STATS_CTL		0x0C08
+#define	BGE_SDI_STATS_ENABLE_MASK	0x0C0C
+#define	BGE_SDI_STATS_INCREMENT_MASK	0x0C10
+#define	BGE_ISO_PKT_TX			0x0C20
+#define	BGE_LOCSTATS_COS0		0x0C80
+#define	BGE_LOCSTATS_COS1		0x0C84
+#define	BGE_LOCSTATS_COS2		0x0C88
+#define	BGE_LOCSTATS_COS3		0x0C8C
+#define	BGE_LOCSTATS_COS4		0x0C90
+#define	BGE_LOCSTATS_COS5		0x0C84
+#define	BGE_LOCSTATS_COS6		0x0C98
+#define	BGE_LOCSTATS_COS7		0x0C9C
+#define	BGE_LOCSTATS_COS8		0x0CA0
+#define	BGE_LOCSTATS_COS9		0x0CA4
+#define	BGE_LOCSTATS_COS10		0x0CA8
+#define	BGE_LOCSTATS_COS11		0x0CAC
+#define	BGE_LOCSTATS_COS12		0x0CB0
+#define	BGE_LOCSTATS_COS13		0x0CB4
+#define	BGE_LOCSTATS_COS14		0x0CB8
+#define	BGE_LOCSTATS_COS15		0x0CBC
+#define	BGE_LOCSTATS_DMA_RQ_FULL	0x0CC0
+#define	BGE_LOCSTATS_DMA_HIPRIO_RQ_FULL	0x0CC4
+#define	BGE_LOCSTATS_SDC_QUEUE_FULL	0x0CC8
+#define	BGE_LOCSTATS_NIC_SENDPROD_SET	0x0CCC
+#define	BGE_LOCSTATS_STATS_UPDATED	0x0CD0
+#define	BGE_LOCSTATS_IRQS		0x0CD4
+#define	BGE_LOCSTATS_AVOIDED_IRQS	0x0CD8
+#define	BGE_LOCSTATS_TX_THRESH_HIT	0x0CDC
+
+/* Send Data Initiator mode register */
+#define	BGE_SDIMODE_RESET		0x00000001
+#define	BGE_SDIMODE_ENABLE		0x00000002
+#define	BGE_SDIMODE_STATS_OFLOW_ATTN	0x00000004
+#define	BGE_SDIMODE_HW_LSO_PRE_DMA	0x00000008
+
+/* Send Data Initiator stats register */
+#define	BGE_SDISTAT_STATS_OFLOW_ATTN	0x00000004
+
+/* Send Data Initiator stats control register */
+#define	BGE_SDISTATSCTL_ENABLE		0x00000001
+#define	BGE_SDISTATSCTL_FASTER		0x00000002
+#define	BGE_SDISTATSCTL_CLEAR		0x00000004
+#define	BGE_SDISTATSCTL_FORCEFLUSH	0x00000008
+#define	BGE_SDISTATSCTL_FORCEZERO	0x00000010
+
+/*
+ * Send Data Completion Control registers
+ */
+#define	BGE_SDC_MODE			0x1000
+#define	BGE_SDC_STATUS			0x1004
+
+/* Send Data completion mode register */
+#define	BGE_SDCMODE_RESET		0x00000001
+#define	BGE_SDCMODE_ENABLE		0x00000002
+#define	BGE_SDCMODE_ATTN		0x00000004
+#define	BGE_SDCMODE_CDELAY		0x00000010
+
+/* Send Data completion status register */
+#define	BGE_SDCSTAT_ATTN		0x00000004
+
+/*
+ * Send BD Ring Selector Control registers
+ */
+#define	BGE_SRS_MODE			0x1400
+#define	BGE_SRS_STATUS			0x1404
+#define	BGE_SRS_HWDIAG			0x1408
+#define	BGE_SRS_LOC_NIC_CONS0		0x1440
+#define	BGE_SRS_LOC_NIC_CONS1		0x1444
+#define	BGE_SRS_LOC_NIC_CONS2		0x1448
+#define	BGE_SRS_LOC_NIC_CONS3		0x144C
+#define	BGE_SRS_LOC_NIC_CONS4		0x1450
+#define	BGE_SRS_LOC_NIC_CONS5		0x1454
+#define	BGE_SRS_LOC_NIC_CONS6		0x1458
+#define	BGE_SRS_LOC_NIC_CONS7		0x145C
+#define	BGE_SRS_LOC_NIC_CONS8		0x1460
+#define	BGE_SRS_LOC_NIC_CONS9		0x1464
+#define	BGE_SRS_LOC_NIC_CONS10		0x1468
+#define	BGE_SRS_LOC_NIC_CONS11		0x146C
+#define	BGE_SRS_LOC_NIC_CONS12		0x1470
+#define	BGE_SRS_LOC_NIC_CONS13		0x1474
+#define	BGE_SRS_LOC_NIC_CONS14		0x1478
+#define	BGE_SRS_LOC_NIC_CONS15		0x147C
+
+/* Send BD Ring Selector Mode register */
+#define	BGE_SRSMODE_RESET		0x00000001
+#define	BGE_SRSMODE_ENABLE		0x00000002
+#define	BGE_SRSMODE_ATTN		0x00000004
+
+/* Send BD Ring Selector Status register */
+#define	BGE_SRSSTAT_ERROR		0x00000004
+
+/* Send BD Ring Selector HW Diagnostics register */
+#define	BGE_SRSHWDIAG_STATE		0x0000000F
+#define	BGE_SRSHWDIAG_CURRINGNUM	0x000000F0
+#define	BGE_SRSHWDIAG_STAGEDRINGNUM	0x00000F00
+#define	BGE_SRSHWDIAG_RINGNUM_IN_MBX	0x0000F000
+
+/*
+ * Send BD Initiator Selector Control registers
+ */
+#define	BGE_SBDI_MODE			0x1800
+#define	BGE_SBDI_STATUS			0x1804
+#define	BGE_SBDI_LOC_NIC_PROD0		0x1808
+#define	BGE_SBDI_LOC_NIC_PROD1		0x180C
+#define	BGE_SBDI_LOC_NIC_PROD2		0x1810
+#define	BGE_SBDI_LOC_NIC_PROD3		0x1814
+#define	BGE_SBDI_LOC_NIC_PROD4		0x1818
+#define	BGE_SBDI_LOC_NIC_PROD5		0x181C
+#define	BGE_SBDI_LOC_NIC_PROD6		0x1820
+#define	BGE_SBDI_LOC_NIC_PROD7		0x1824
+#define	BGE_SBDI_LOC_NIC_PROD8		0x1828
+#define	BGE_SBDI_LOC_NIC_PROD9		0x182C
+#define	BGE_SBDI_LOC_NIC_PROD10		0x1830
+#define	BGE_SBDI_LOC_NIC_PROD11		0x1834
+#define	BGE_SBDI_LOC_NIC_PROD12		0x1838
+#define	BGE_SBDI_LOC_NIC_PROD13		0x183C
+#define	BGE_SBDI_LOC_NIC_PROD14		0x1840
+#define	BGE_SBDI_LOC_NIC_PROD15		0x1844
+
+/* Send BD Initiator Mode register */
+#define	BGE_SBDIMODE_RESET		0x00000001
+#define	BGE_SBDIMODE_ENABLE		0x00000002
+#define	BGE_SBDIMODE_ATTN		0x00000004
+
+/* Send BD Initiator Status register */
+#define	BGE_SBDISTAT_ERROR		0x00000004
+
+/*
+ * Send BD Completion Control registers
+ */
+#define	BGE_SBDC_MODE			0x1C00
+#define	BGE_SBDC_STATUS			0x1C04
+
+/* Send BD Completion Control Mode register */
+#define	BGE_SBDCMODE_RESET		0x00000001
+#define	BGE_SBDCMODE_ENABLE		0x00000002
+#define	BGE_SBDCMODE_ATTN		0x00000004
+
+/* Send BD Completion Control Status register */
+#define	BGE_SBDCSTAT_ATTN		0x00000004
+
+/*
+ * Receive List Placement Control registers
+ */
+#define	BGE_RXLP_MODE			0x2000
+#define	BGE_RXLP_STATUS			0x2004
+#define	BGE_RXLP_SEL_LIST_LOCK		0x2008
+#define	BGE_RXLP_SEL_NON_EMPTY_BITS	0x200C
+#define	BGE_RXLP_CFG			0x2010
+#define	BGE_RXLP_STATS_CTL		0x2014
+#define	BGE_RXLP_STATS_ENABLE_MASK	0x2018
+#define	BGE_RXLP_STATS_INCREMENT_MASK	0x201C
+#define	BGE_RXLP_HEAD0			0x2100
+#define	BGE_RXLP_TAIL0			0x2104
+#define	BGE_RXLP_COUNT0			0x2108
+#define	BGE_RXLP_HEAD1			0x2110
+#define	BGE_RXLP_TAIL1			0x2114
+#define	BGE_RXLP_COUNT1			0x2118
+#define	BGE_RXLP_HEAD2			0x2120
+#define	BGE_RXLP_TAIL2			0x2124
+#define	BGE_RXLP_COUNT2			0x2128
+#define	BGE_RXLP_HEAD3			0x2130
+#define	BGE_RXLP_TAIL3			0x2134
+#define	BGE_RXLP_COUNT3			0x2138
+#define	BGE_RXLP_HEAD4			0x2140
+#define	BGE_RXLP_TAIL4			0x2144
+#define	BGE_RXLP_COUNT4			0x2148
+#define	BGE_RXLP_HEAD5			0x2150
+#define	BGE_RXLP_TAIL5			0x2154
+#define	BGE_RXLP_COUNT5			0x2158
+#define	BGE_RXLP_HEAD6			0x2160
+#define	BGE_RXLP_TAIL6			0x2164
+#define	BGE_RXLP_COUNT6			0x2168
+#define	BGE_RXLP_HEAD7			0x2170
+#define	BGE_RXLP_TAIL7			0x2174
+#define	BGE_RXLP_COUNT7			0x2178
+#define	BGE_RXLP_HEAD8			0x2180
+#define	BGE_RXLP_TAIL8			0x2184
+#define	BGE_RXLP_COUNT8			0x2188
+#define	BGE_RXLP_HEAD9			0x2190
+#define	BGE_RXLP_TAIL9			0x2194
+#define	BGE_RXLP_COUNT9			0x2198
+#define	BGE_RXLP_HEAD10			0x21A0
+#define	BGE_RXLP_TAIL10			0x21A4
+#define	BGE_RXLP_COUNT10		0x21A8
+#define	BGE_RXLP_HEAD11			0x21B0
+#define	BGE_RXLP_TAIL11			0x21B4
+#define	BGE_RXLP_COUNT11		0x21B8
+#define	BGE_RXLP_HEAD12			0x21C0
+#define	BGE_RXLP_TAIL12			0x21C4
+#define	BGE_RXLP_COUNT12		0x21C8
+#define	BGE_RXLP_HEAD13			0x21D0
+#define	BGE_RXLP_TAIL13			0x21D4
+#define	BGE_RXLP_COUNT13		0x21D8
+#define	BGE_RXLP_HEAD14			0x21E0
+#define	BGE_RXLP_TAIL14			0x21E4
+#define	BGE_RXLP_COUNT14		0x21E8
+#define	BGE_RXLP_HEAD15			0x21F0
+#define	BGE_RXLP_TAIL15			0x21F4
+#define	BGE_RXLP_COUNT15		0x21F8
+#define	BGE_RXLP_LOCSTAT_COS0		0x2200
+#define	BGE_RXLP_LOCSTAT_COS1		0x2204
+#define	BGE_RXLP_LOCSTAT_COS2		0x2208
+#define	BGE_RXLP_LOCSTAT_COS3		0x220C
+#define	BGE_RXLP_LOCSTAT_COS4		0x2210
+#define	BGE_RXLP_LOCSTAT_COS5		0x2214
+#define	BGE_RXLP_LOCSTAT_COS6		0x2218
+#define	BGE_RXLP_LOCSTAT_COS7		0x221C
+#define	BGE_RXLP_LOCSTAT_COS8		0x2220
+#define	BGE_RXLP_LOCSTAT_COS9		0x2224
+#define	BGE_RXLP_LOCSTAT_COS10		0x2228
+#define	BGE_RXLP_LOCSTAT_COS11		0x222C
+#define	BGE_RXLP_LOCSTAT_COS12		0x2230
+#define	BGE_RXLP_LOCSTAT_COS13		0x2234
+#define	BGE_RXLP_LOCSTAT_COS14		0x2238
+#define	BGE_RXLP_LOCSTAT_COS15		0x223C
+#define	BGE_RXLP_LOCSTAT_FILTDROP	0x2240
+#define	BGE_RXLP_LOCSTAT_DMA_WRQ_FULL	0x2244
+#define	BGE_RXLP_LOCSTAT_DMA_HPWRQ_FULL	0x2248
+#define	BGE_RXLP_LOCSTAT_OUT_OF_BDS	0x224C
+#define	BGE_RXLP_LOCSTAT_IFIN_DROPS	0x2250
+#define	BGE_RXLP_LOCSTAT_IFIN_ERRORS	0x2254
+#define	BGE_RXLP_LOCSTAT_RXTHRESH_HIT	0x2258
+
+
+/* Receive List Placement mode register */
+#define	BGE_RXLPMODE_RESET		0x00000001
+#define	BGE_RXLPMODE_ENABLE		0x00000002
+#define	BGE_RXLPMODE_CLASS0_ATTN	0x00000004
+#define	BGE_RXLPMODE_MAPOUTRANGE_ATTN	0x00000008
+#define	BGE_RXLPMODE_STATSOFLOW_ATTN	0x00000010
+
+/* Receive List Placement Status register */
+#define	BGE_RXLPSTAT_CLASS0_ATTN	0x00000004
+#define	BGE_RXLPSTAT_MAPOUTRANGE_ATTN	0x00000008
+#define	BGE_RXLPSTAT_STATSOFLOW_ATTN	0x00000010
+
+/*
+ * Receive Data and Receive BD Initiator Control Registers
+ */
+#define	BGE_RDBDI_MODE			0x2400
+#define	BGE_RDBDI_STATUS		0x2404
+#define	BGE_RX_JUMBO_RCB_HADDR_HI	0x2440
+#define	BGE_RX_JUMBO_RCB_HADDR_LO	0x2444
+#define	BGE_RX_JUMBO_RCB_MAXLEN_FLAGS	0x2448
+#define	BGE_RX_JUMBO_RCB_NICADDR	0x244C
+#define	BGE_RX_STD_RCB_HADDR_HI		0x2450
+#define	BGE_RX_STD_RCB_HADDR_LO		0x2454
+#define	BGE_RX_STD_RCB_MAXLEN_FLAGS	0x2458
+#define	BGE_RX_STD_RCB_NICADDR		0x245C
+#define	BGE_RX_MINI_RCB_HADDR_HI	0x2460
+#define	BGE_RX_MINI_RCB_HADDR_LO	0x2464
+#define	BGE_RX_MINI_RCB_MAXLEN_FLAGS	0x2468
+#define	BGE_RX_MINI_RCB_NICADDR		0x246C
+#define	BGE_RDBDI_JUMBO_RX_CONS		0x2470
+#define	BGE_RDBDI_STD_RX_CONS		0x2474
+#define	BGE_RDBDI_MINI_RX_CONS		0x2478
+#define	BGE_RDBDI_RETURN_PROD0		0x2480
+#define	BGE_RDBDI_RETURN_PROD1		0x2484
+#define	BGE_RDBDI_RETURN_PROD2		0x2488
+#define	BGE_RDBDI_RETURN_PROD3		0x248C
+#define	BGE_RDBDI_RETURN_PROD4		0x2490
+#define	BGE_RDBDI_RETURN_PROD5		0x2494
+#define	BGE_RDBDI_RETURN_PROD6		0x2498
+#define	BGE_RDBDI_RETURN_PROD7		0x249C
+#define	BGE_RDBDI_RETURN_PROD8		0x24A0
+#define	BGE_RDBDI_RETURN_PROD9		0x24A4
+#define	BGE_RDBDI_RETURN_PROD10		0x24A8
+#define	BGE_RDBDI_RETURN_PROD11		0x24AC
+#define	BGE_RDBDI_RETURN_PROD12		0x24B0
+#define	BGE_RDBDI_RETURN_PROD13		0x24B4
+#define	BGE_RDBDI_RETURN_PROD14		0x24B8
+#define	BGE_RDBDI_RETURN_PROD15		0x24BC
+#define	BGE_RDBDI_HWDIAG		0x24C0
+
+
+/* Receive Data and Receive BD Initiator Mode register */
+#define	BGE_RDBDIMODE_RESET		0x00000001
+#define	BGE_RDBDIMODE_ENABLE		0x00000002
+#define	BGE_RDBDIMODE_JUMBO_ATTN	0x00000004
+#define	BGE_RDBDIMODE_GIANT_ATTN	0x00000008
+#define	BGE_RDBDIMODE_BADRINGSZ_ATTN	0x00000010
+
+/* Receive Data and Receive BD Initiator Status register */
+#define	BGE_RDBDISTAT_JUMBO_ATTN	0x00000004
+#define	BGE_RDBDISTAT_GIANT_ATTN	0x00000008
+#define	BGE_RDBDISTAT_BADRINGSZ_ATTN	0x00000010
+
+
+/*
+ * Receive Data Completion Control registers
+ */
+#define	BGE_RDC_MODE			0x2800
+
+/* Receive Data Completion Mode register */
+#define	BGE_RDCMODE_RESET		0x00000001
+#define	BGE_RDCMODE_ENABLE		0x00000002
+#define	BGE_RDCMODE_ATTN		0x00000004
+
+/*
+ * Receive BD Initiator Control registers
+ */
+#define	BGE_RBDI_MODE			0x2C00
+#define	BGE_RBDI_STATUS			0x2C04
+#define	BGE_RBDI_NIC_JUMBO_BD_PROD	0x2C08
+#define	BGE_RBDI_NIC_STD_BD_PROD	0x2C0C
+#define	BGE_RBDI_NIC_MINI_BD_PROD	0x2C10
+#define	BGE_RBDI_MINI_REPL_THRESH	0x2C14
+#define	BGE_RBDI_STD_REPL_THRESH	0x2C18
+#define	BGE_RBDI_JUMBO_REPL_THRESH	0x2C1C
+
+#define	BGE_STD_REPLENISH_LWM		0x2D00
+#define	BGE_JMB_REPLENISH_LWM		0x2D04
+
+/* Receive BD Initiator Mode register */
+#define	BGE_RBDIMODE_RESET		0x00000001
+#define	BGE_RBDIMODE_ENABLE		0x00000002
+#define	BGE_RBDIMODE_ATTN		0x00000004
+
+/* Receive BD Initiator Status register */
+#define	BGE_RBDISTAT_ATTN		0x00000004
+
+/*
+ * Receive BD Completion Control registers
+ */
+#define	BGE_RBDC_MODE			0x3000
+#define	BGE_RBDC_STATUS			0x3004
+#define	BGE_RBDC_JUMBO_BD_PROD		0x3008
+#define	BGE_RBDC_STD_BD_PROD		0x300C
+#define	BGE_RBDC_MINI_BD_PROD		0x3010
+
+/* Receive BD completion mode register */
+#define	BGE_RBDCMODE_RESET		0x00000001
+#define	BGE_RBDCMODE_ENABLE		0x00000002
+#define	BGE_RBDCMODE_ATTN		0x00000004
+
+/* Receive BD completion status register */
+#define	BGE_RBDCSTAT_ERROR		0x00000004
+
+/*
+ * Receive List Selector Control registers
+ */
+#define	BGE_RXLS_MODE			0x3400
+#define	BGE_RXLS_STATUS			0x3404
+
+/* Receive List Selector Mode register */
+#define	BGE_RXLSMODE_RESET		0x00000001
+#define	BGE_RXLSMODE_ENABLE		0x00000002
+#define	BGE_RXLSMODE_ATTN		0x00000004
+
+/* Receive List Selector Status register */
+#define	BGE_RXLSSTAT_ERROR		0x00000004
+
+#define	BGE_CPMU_CTRL			0x3600
+#define	BGE_CPMU_LSPD_10MB_CLK		0x3604
+#define	BGE_CPMU_LSPD_1000MB_CLK	0x360C
+#define	BGE_CPMU_LNK_AWARE_PWRMD	0x3610
+#define	BGE_CPMU_HST_ACC		0x361C
+#define	BGE_CPMU_CLCK_ORIDE		0x3624
+#define	BGE_CPMU_CLCK_STAT		0x3630
+#define	BGE_CPMU_MUTEX_REQ		0x365C
+#define	BGE_CPMU_MUTEX_GNT		0x3660
+#define	BGE_CPMU_PHY_STRAP		0x3664
+#define	BGE_CPMU_PADRNG_CTL		0x3668
+
+/* Central Power Management Unit (CPMU) register */
+#define	BGE_CPMU_CTRL_LINK_IDLE_MODE	0x00000200
+#define	BGE_CPMU_CTRL_LINK_AWARE_MODE	0x00000400
+#define	BGE_CPMU_CTRL_LINK_SPEED_MODE	0x00004000
+#define	BGE_CPMU_CTRL_GPHY_10MB_RXONLY	0x00010000
+
+/* Link Speed 10MB/No Link Power Mode Clock Policy register */
+#define	BGE_CPMU_LSPD_10MB_MACCLK_MASK	0x001F0000
+#define	BGE_CPMU_LSPD_10MB_MACCLK_6_25	0x00130000
+
+/* Link Speed 1000MB Power Mode Clock Policy register */
+#define	BGE_CPMU_LSPD_1000MB_MACCLK_62_5	0x00000000
+#define	BGE_CPMU_LSPD_1000MB_MACCLK_12_5	0x00110000
+#define	BGE_CPMU_LSPD_1000MB_MACCLK_MASK	0x001F0000
+
+/* Link Aware Power Mode Clock Policy register */
+#define	BGE_CPMU_LNK_AWARE_MACCLK_MASK	0x001F0000
+#define	BGE_CPMU_LNK_AWARE_MACCLK_6_25	0x00130000
+
+#define	BGE_CPMU_HST_ACC_MACCLK_MASK	0x001F0000
+#define	BGE_CPMU_HST_ACC_MACCLK_6_25	0x00130000
+
+/* Clock Speed Override Policy register */
+#define	CPMU_CLCK_ORIDE_MAC_ORIDE_EN	0x80000000
+
+/* CPMU Clock Status register */
+#define	BGE_CPMU_CLCK_STAT_MAC_CLCK_MASK	0x001F0000
+#define	BGE_CPMU_CLCK_STAT_MAC_CLCK_62_5	0x00000000
+#define	BGE_CPMU_CLCK_STAT_MAC_CLCK_12_5	0x00110000
+#define	BGE_CPMU_CLCK_STAT_MAC_CLCK_6_25	0x00130000
+
+/* CPMU Mutex Request register */
+#define	BGE_CPMU_MUTEX_REQ_DRIVER	0x00001000
+#define	BGE_CPMU_MUTEX_GNT_DRIVER	0x00001000
+
+/* CPMU GPHY Strap register */
+#define	BGE_CPMU_PHY_STRAP_IS_SERDES	0x00000020
+
+/* CPMU Padring Control register */
+#define	BGE_CPMU_PADRNG_CTL_RDIV2	0x00040000
+
+/*
+ * Mbuf Cluster Free registers (has nothing to do with BSD mbufs)
+ */
+#define	BGE_MBCF_MODE			0x3800
+#define	BGE_MBCF_STATUS			0x3804
+
+/* Mbuf Cluster Free mode register */
+#define	BGE_MBCFMODE_RESET		0x00000001
+#define	BGE_MBCFMODE_ENABLE		0x00000002
+#define	BGE_MBCFMODE_ATTN		0x00000004
+
+/* Mbuf Cluster Free status register */
+#define	BGE_MBCFSTAT_ERROR		0x00000004
+
+/*
+ * Host Coalescing Control registers
+ */
+#define	BGE_HCC_MODE			0x3C00
+#define	BGE_HCC_STATUS			0x3C04
+#define	BGE_HCC_RX_COAL_TICKS		0x3C08
+#define	BGE_HCC_TX_COAL_TICKS		0x3C0C
+#define	BGE_HCC_RX_MAX_COAL_BDS		0x3C10
+#define	BGE_HCC_TX_MAX_COAL_BDS		0x3C14
+#define	BGE_HCC_RX_COAL_TICKS_INT	0x3C18 /* ticks during interrupt */
+#define	BGE_HCC_TX_COAL_TICKS_INT	0x3C1C /* ticks during interrupt */
+#define	BGE_HCC_RX_MAX_COAL_BDS_INT	0x3C20 /* BDs during interrupt */
+#define	BGE_HCC_TX_MAX_COAL_BDS_INT	0x3C24 /* BDs during interrupt */
+#define	BGE_HCC_STATS_TICKS		0x3C28
+#define	BGE_HCC_STATS_ADDR_HI		0x3C30
+#define	BGE_HCC_STATS_ADDR_LO		0x3C34
+#define	BGE_HCC_STATUSBLK_ADDR_HI	0x3C38
+#define	BGE_HCC_STATUSBLK_ADDR_LO	0x3C3C
+#define	BGE_HCC_STATS_BASEADDR		0x3C40 /* address in NIC memory */
+#define	BGE_HCC_STATUSBLK_BASEADDR	0x3C44 /* address in NIC memory */
+#define	BGE_FLOW_ATTN			0x3C48
+#define	BGE_HCC_JUMBO_BD_CONS		0x3C50
+#define	BGE_HCC_STD_BD_CONS		0x3C54
+#define	BGE_HCC_MINI_BD_CONS		0x3C58
+#define	BGE_HCC_RX_RETURN_PROD0		0x3C80
+#define	BGE_HCC_RX_RETURN_PROD1		0x3C84
+#define	BGE_HCC_RX_RETURN_PROD2		0x3C88
+#define	BGE_HCC_RX_RETURN_PROD3		0x3C8C
+#define	BGE_HCC_RX_RETURN_PROD4		0x3C90
+#define	BGE_HCC_RX_RETURN_PROD5		0x3C94
+#define	BGE_HCC_RX_RETURN_PROD6		0x3C98
+#define	BGE_HCC_RX_RETURN_PROD7		0x3C9C
+#define	BGE_HCC_RX_RETURN_PROD8		0x3CA0
+#define	BGE_HCC_RX_RETURN_PROD9		0x3CA4
+#define	BGE_HCC_RX_RETURN_PROD10	0x3CA8
+#define	BGE_HCC_RX_RETURN_PROD11	0x3CAC
+#define	BGE_HCC_RX_RETURN_PROD12	0x3CB0
+#define	BGE_HCC_RX_RETURN_PROD13	0x3CB4
+#define	BGE_HCC_RX_RETURN_PROD14	0x3CB8
+#define	BGE_HCC_RX_RETURN_PROD15	0x3CBC
+#define	BGE_HCC_TX_BD_CONS0		0x3CC0
+#define	BGE_HCC_TX_BD_CONS1		0x3CC4
+#define	BGE_HCC_TX_BD_CONS2		0x3CC8
+#define	BGE_HCC_TX_BD_CONS3		0x3CCC
+#define	BGE_HCC_TX_BD_CONS4		0x3CD0
+#define	BGE_HCC_TX_BD_CONS5		0x3CD4
+#define	BGE_HCC_TX_BD_CONS6		0x3CD8
+#define	BGE_HCC_TX_BD_CONS7		0x3CDC
+#define	BGE_HCC_TX_BD_CONS8		0x3CE0
+#define	BGE_HCC_TX_BD_CONS9		0x3CE4
+#define	BGE_HCC_TX_BD_CONS10		0x3CE8
+#define	BGE_HCC_TX_BD_CONS11		0x3CEC
+#define	BGE_HCC_TX_BD_CONS12		0x3CF0
+#define	BGE_HCC_TX_BD_CONS13		0x3CF4
+#define	BGE_HCC_TX_BD_CONS14		0x3CF8
+#define	BGE_HCC_TX_BD_CONS15		0x3CFC
+
+
+/* Host coalescing mode register */
+#define	BGE_HCCMODE_RESET		0x00000001
+#define	BGE_HCCMODE_ENABLE		0x00000002
+#define	BGE_HCCMODE_ATTN		0x00000004
+#define	BGE_HCCMODE_COAL_NOW		0x00000008
+#define	BGE_HCCMODE_MSI_BITS		0x00000070
+#define	BGE_HCCMODE_STATBLK_SIZE	0x00000180
+
+#define	BGE_STATBLKSZ_FULL		0x00000000
+#define	BGE_STATBLKSZ_64BYTE		0x00000080
+#define	BGE_STATBLKSZ_32BYTE		0x00000100
+
+/* Host coalescing status register */
+#define	BGE_HCCSTAT_ERROR		0x00000004
+
+/* Flow attention register */
+#define	BGE_FLOWATTN_MB_LOWAT		0x00000040
+#define	BGE_FLOWATTN_MEMARB		0x00000080
+#define	BGE_FLOWATTN_HOSTCOAL		0x00008000
+#define	BGE_FLOWATTN_DMADONE_DISCARD	0x00010000
+#define	BGE_FLOWATTN_RCB_INVAL		0x00020000
+#define	BGE_FLOWATTN_RXDATA_CORRUPT	0x00040000
+#define	BGE_FLOWATTN_RDBDI		0x00080000
+#define	BGE_FLOWATTN_RXLS		0x00100000
+#define	BGE_FLOWATTN_RXLP		0x00200000
+#define	BGE_FLOWATTN_RBDC		0x00400000
+#define	BGE_FLOWATTN_RBDI		0x00800000
+#define	BGE_FLOWATTN_SDC		0x08000000
+#define	BGE_FLOWATTN_SDI		0x10000000
+#define	BGE_FLOWATTN_SRS		0x20000000
+#define	BGE_FLOWATTN_SBDC		0x40000000
+#define	BGE_FLOWATTN_SBDI		0x80000000
+
+/*
+ * Memory arbiter registers
+ */
+#define	BGE_MARB_MODE			0x4000
+#define	BGE_MARB_STATUS			0x4004
+#define	BGE_MARB_TRAPADDR_HI		0x4008
+#define	BGE_MARB_TRAPADDR_LO		0x400C
+
+/* Memory arbiter mode register */
+#define	BGE_MARBMODE_RESET		0x00000001
+#define	BGE_MARBMODE_ENABLE		0x00000002
+#define	BGE_MARBMODE_TX_ADDR_TRAP	0x00000004
+#define	BGE_MARBMODE_RX_ADDR_TRAP	0x00000008
+#define	BGE_MARBMODE_DMAW1_TRAP		0x00000010
+#define	BGE_MARBMODE_DMAR1_TRAP		0x00000020
+#define	BGE_MARBMODE_RXRISC_TRAP	0x00000040
+#define	BGE_MARBMODE_TXRISC_TRAP	0x00000080
+#define	BGE_MARBMODE_PCI_TRAP		0x00000100
+#define	BGE_MARBMODE_DMAR2_TRAP		0x00000200
+#define	BGE_MARBMODE_RXQ_TRAP		0x00000400
+#define	BGE_MARBMODE_RXDI1_TRAP		0x00000800
+#define	BGE_MARBMODE_RXDI2_TRAP		0x00001000
+#define	BGE_MARBMODE_DC_GRPMEM_TRAP	0x00002000
+#define	BGE_MARBMODE_HCOAL_TRAP		0x00004000
+#define	BGE_MARBMODE_MBUF_TRAP		0x00008000
+#define	BGE_MARBMODE_TXDI_TRAP		0x00010000
+#define	BGE_MARBMODE_SDC_DMAC_TRAP	0x00020000
+#define	BGE_MARBMODE_TXBD_TRAP		0x00040000
+#define	BGE_MARBMODE_BUFFMAN_TRAP	0x00080000
+#define	BGE_MARBMODE_DMAW2_TRAP		0x00100000
+#define	BGE_MARBMODE_XTSSRAM_ROFLO_TRAP	0x00200000
+#define	BGE_MARBMODE_XTSSRAM_RUFLO_TRAP 0x00400000
+#define	BGE_MARBMODE_XTSSRAM_WOFLO_TRAP	0x00800000
+#define	BGE_MARBMODE_XTSSRAM_WUFLO_TRAP	0x01000000
+#define	BGE_MARBMODE_XTSSRAM_PERR_TRAP	0x02000000
+
+/* Memory arbiter status register */
+#define	BGE_MARBSTAT_TX_ADDR_TRAP	0x00000004
+#define	BGE_MARBSTAT_RX_ADDR_TRAP	0x00000008
+#define	BGE_MARBSTAT_DMAW1_TRAP		0x00000010
+#define	BGE_MARBSTAT_DMAR1_TRAP		0x00000020
+#define	BGE_MARBSTAT_RXRISC_TRAP	0x00000040
+#define	BGE_MARBSTAT_TXRISC_TRAP	0x00000080
+#define	BGE_MARBSTAT_PCI_TRAP		0x00000100
+#define	BGE_MARBSTAT_DMAR2_TRAP		0x00000200
+#define	BGE_MARBSTAT_RXQ_TRAP		0x00000400
+#define	BGE_MARBSTAT_RXDI1_TRAP		0x00000800
+#define	BGE_MARBSTAT_RXDI2_TRAP		0x00001000
+#define	BGE_MARBSTAT_DC_GRPMEM_TRAP	0x00002000
+#define	BGE_MARBSTAT_HCOAL_TRAP		0x00004000
+#define	BGE_MARBSTAT_MBUF_TRAP		0x00008000
+#define	BGE_MARBSTAT_TXDI_TRAP		0x00010000
+#define	BGE_MARBSTAT_SDC_DMAC_TRAP	0x00020000
+#define	BGE_MARBSTAT_TXBD_TRAP		0x00040000
+#define	BGE_MARBSTAT_BUFFMAN_TRAP	0x00080000
+#define	BGE_MARBSTAT_DMAW2_TRAP		0x00100000
+#define	BGE_MARBSTAT_XTSSRAM_ROFLO_TRAP	0x00200000
+#define	BGE_MARBSTAT_XTSSRAM_RUFLO_TRAP 0x00400000
+#define	BGE_MARBSTAT_XTSSRAM_WOFLO_TRAP	0x00800000
+#define	BGE_MARBSTAT_XTSSRAM_WUFLO_TRAP	0x01000000
+#define	BGE_MARBSTAT_XTSSRAM_PERR_TRAP	0x02000000
+
+/*
+ * Buffer manager control registers
+ */
+#define	BGE_BMAN_MODE			0x4400
+#define	BGE_BMAN_STATUS			0x4404
+#define	BGE_BMAN_MBUFPOOL_BASEADDR	0x4408
+#define	BGE_BMAN_MBUFPOOL_LEN		0x440C
+#define	BGE_BMAN_MBUFPOOL_READDMA_LOWAT	0x4410
+#define	BGE_BMAN_MBUFPOOL_MACRX_LOWAT	0x4414
+#define	BGE_BMAN_MBUFPOOL_HIWAT		0x4418
+#define	BGE_BMAN_RXCPU_MBALLOC_REQ	0x441C
+#define	BGE_BMAN_RXCPU_MBALLOC_RESP	0x4420
+#define	BGE_BMAN_TXCPU_MBALLOC_REQ	0x4424
+#define	BGE_BMAN_TXCPU_MBALLOC_RESP	0x4428
+#define	BGE_BMAN_DMA_DESCPOOL_BASEADDR	0x442C
+#define	BGE_BMAN_DMA_DESCPOOL_LEN	0x4430
+#define	BGE_BMAN_DMA_DESCPOOL_LOWAT	0x4434
+#define	BGE_BMAN_DMA_DESCPOOL_HIWAT	0x4438
+#define	BGE_BMAN_RXCPU_DMAALLOC_REQ	0x443C
+#define	BGE_BMAN_RXCPU_DMAALLOC_RESP	0x4440
+#define	BGE_BMAN_TXCPU_DMAALLOC_REQ	0x4444
+#define	BGE_BMAN_TXCPU_DMALLLOC_RESP	0x4448
+#define	BGE_BMAN_HWDIAG_1		0x444C
+#define	BGE_BMAN_HWDIAG_2		0x4450
+#define	BGE_BMAN_HWDIAG_3		0x4454
+
+/* Buffer manager mode register */
+#define	BGE_BMANMODE_RESET		0x00000001
+#define	BGE_BMANMODE_ENABLE		0x00000002
+#define	BGE_BMANMODE_ATTN		0x00000004
+#define	BGE_BMANMODE_TESTMODE		0x00000008
+#define	BGE_BMANMODE_LOMBUF_ATTN	0x00000010
+#define	BGE_BMANMODE_NO_TX_UNDERRUN	0x80000000
+
+/* Buffer manager status register */
+#define	BGE_BMANSTAT_ERRO		0x00000004
+#define	BGE_BMANSTAT_LOWMBUF_ERROR	0x00000010
+
+
+/*
+ * Read DMA Control registers
+ */
+#define	BGE_RDMA_MODE			0x4800
+#define	BGE_RDMA_STATUS			0x4804
+#define	BGE_RDMA_RSRVCTRL_REG2		0x4890
+#define	BGE_RDMA_LSO_CRPTEN_CTRL_REG2	0x48A0
+#define	BGE_RDMA_RSRVCTRL		0x4900
+#define	BGE_RDMA_LSO_CRPTEN_CTRL	0x4910
+
+/* Read DMA mode register */
+#define	BGE_RDMAMODE_RESET		0x00000001
+#define	BGE_RDMAMODE_ENABLE		0x00000002
+#define	BGE_RDMAMODE_PCI_TGT_ABRT_ATTN	0x00000004
+#define	BGE_RDMAMODE_PCI_MSTR_ABRT_ATTN	0x00000008
+#define	BGE_RDMAMODE_PCI_PERR_ATTN	0x00000010
+#define	BGE_RDMAMODE_PCI_ADDROFLOW_ATTN	0x00000020
+#define	BGE_RDMAMODE_PCI_FIFOOFLOW_ATTN	0x00000040
+#define	BGE_RDMAMODE_PCI_FIFOUFLOW_ATTN	0x00000080
+#define	BGE_RDMAMODE_PCI_FIFOOREAD_ATTN	0x00000100
+#define	BGE_RDMAMODE_LOCWRITE_TOOBIG	0x00000200
+#define	BGE_RDMAMODE_ALL_ATTNS		0x000003FC
+#define	BGE_RDMAMODE_BD_SBD_CRPT_ATTN	0x00000800
+#define	BGE_RDMAMODE_MBUF_RBD_CRPT_ATTN	0x00001000
+#define	BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN	0x00002000
+#define	BGE_RDMAMODE_FIFO_SIZE_128	0x00020000
+#define	BGE_RDMAMODE_FIFO_LONG_BURST	0x00030000
+#define	BGE_RDMAMODE_MULT_DMA_RD_DIS	0x01000000
+#define	BGE_RDMAMODE_TSO4_ENABLE	0x08000000
+#define	BGE_RDMAMODE_TSO6_ENABLE	0x10000000
+#define	BGE_RDMAMODE_H2BNC_VLAN_DET	0x20000000
+
+/* Read DMA status register */
+#define	BGE_RDMASTAT_PCI_TGT_ABRT_ATTN	0x00000004
+#define	BGE_RDMASTAT_PCI_MSTR_ABRT_ATTN	0x00000008
+#define	BGE_RDMASTAT_PCI_PERR_ATTN	0x00000010
+#define	BGE_RDMASTAT_PCI_ADDROFLOW_ATTN	0x00000020
+#define	BGE_RDMASTAT_PCI_FIFOOFLOW_ATTN	0x00000040
+#define	BGE_RDMASTAT_PCI_FIFOUFLOW_ATTN	0x00000080
+#define	BGE_RDMASTAT_PCI_FIFOOREAD_ATTN	0x00000100
+#define	BGE_RDMASTAT_LOCWRITE_TOOBIG	0x00000200
+
+/* Read DMA Reserved Control register */
+#define	BGE_RDMA_RSRVCTRL_FIFO_OFLW_FIX	0x00000004
+#define	BGE_RDMA_RSRVCTRL_FIFO_LWM_1_5K	0x00000C00
+#define	BGE_RDMA_RSRVCTRL_FIFO_HWM_1_5K	0x000C0000
+#define	BGE_RDMA_RSRVCTRL_TXMRGN_320B	0x28000000
+#define	BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK	0x00000FF0
+#define	BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK	0x000FF000
+#define	BGE_RDMA_RSRVCTRL_TXMRGN_MASK	0xFFE00000
+
+#define	BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512	0x00020000
+#define	BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K	0x00030000
+#define	BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K	0x000C0000
+#define	BGE_RDMA_TX_LENGTH_WA_5719		0x02000000
+#define	BGE_RDMA_TX_LENGTH_WA_5720		0x00200000
+
+/* BD Read DMA Mode register */
+#define	BGE_RDMA_BD_MODE		0x4A00
+/* BD Read DMA Mode status register */
+#define	BGE_RDMA_BD_STATUS		0x4A04
+
+#define	BGE_RDMA_BD_MODE_RESET		0x00000001
+#define	BGE_RDMA_BD_MODE_ENABLE		0x00000002
+
+/* Non-LSO Read DMA Mode register */
+#define	BGE_RDMA_NON_LSO_MODE		0x4B00
+/* Non-LSO Read DMA Mode status register */
+#define	BGE_RDMA_NON_LSO_STATUS		0x4B04
+
+#define	BGE_RDMA_NON_LSO_MODE_RESET	0x00000001
+#define	BGE_RDMA_NON_LSO_MODE_ENABLE	0x00000002
+
+#define	BGE_RDMA_LENGTH			0x4BE0
+#define	BGE_NUM_RDMA_CHANNELS		4
+
+/*
+ * Write DMA control registers
+ */
+#define	BGE_WDMA_MODE			0x4C00
+#define	BGE_WDMA_STATUS			0x4C04
+
+/* Write DMA mode register */
+#define	BGE_WDMAMODE_RESET		0x00000001
+#define	BGE_WDMAMODE_ENABLE		0x00000002
+#define	BGE_WDMAMODE_PCI_TGT_ABRT_ATTN	0x00000004
+#define	BGE_WDMAMODE_PCI_MSTR_ABRT_ATTN	0x00000008
+#define	BGE_WDMAMODE_PCI_PERR_ATTN	0x00000010
+#define	BGE_WDMAMODE_PCI_ADDROFLOW_ATTN	0x00000020
+#define	BGE_WDMAMODE_PCI_FIFOOFLOW_ATTN	0x00000040
+#define	BGE_WDMAMODE_PCI_FIFOUFLOW_ATTN	0x00000080
+#define	BGE_WDMAMODE_PCI_FIFOOREAD_ATTN	0x00000100
+#define	BGE_WDMAMODE_LOCREAD_TOOBIG	0x00000200
+#define	BGE_WDMAMODE_ALL_ATTNS		0x000003FC
+#define	BGE_WDMAMODE_STATUS_TAG_FIX	0x20000000
+#define	BGE_WDMAMODE_BURST_ALL_DATA	0xC0000000
+
+/* Write DMA status register */
+#define	BGE_WDMASTAT_PCI_TGT_ABRT_ATTN	0x00000004
+#define	BGE_WDMASTAT_PCI_MSTR_ABRT_ATTN	0x00000008
+#define	BGE_WDMASTAT_PCI_PERR_ATTN	0x00000010
+#define	BGE_WDMASTAT_PCI_ADDROFLOW_ATTN	0x00000020
+#define	BGE_WDMASTAT_PCI_FIFOOFLOW_ATTN	0x00000040
+#define	BGE_WDMASTAT_PCI_FIFOUFLOW_ATTN	0x00000080
+#define	BGE_WDMASTAT_PCI_FIFOOREAD_ATTN	0x00000100
+#define	BGE_WDMASTAT_LOCREAD_TOOBIG	0x00000200
+
+
+/*
+ * RX CPU registers
+ */
+#define	BGE_RXCPU_MODE			0x5000
+#define	BGE_RXCPU_STATUS		0x5004
+#define	BGE_RXCPU_PC			0x501C
+
+/* RX CPU mode register */
+#define	BGE_RXCPUMODE_RESET		0x00000001
+#define	BGE_RXCPUMODE_SINGLESTEP	0x00000002
+#define	BGE_RXCPUMODE_P0_DATAHLT_ENB	0x00000004
+#define	BGE_RXCPUMODE_P0_INSTRHLT_ENB	0x00000008
+#define	BGE_RXCPUMODE_WR_POSTBUF_ENB	0x00000010
+#define	BGE_RXCPUMODE_DATACACHE_ENB	0x00000020
+#define	BGE_RXCPUMODE_ROMFAIL		0x00000040
+#define	BGE_RXCPUMODE_WATCHDOG_ENB	0x00000080
+#define	BGE_RXCPUMODE_INSTRCACHE_PRF	0x00000100
+#define	BGE_RXCPUMODE_INSTRCACHE_FLUSH	0x00000200
+#define	BGE_RXCPUMODE_HALTCPU		0x00000400
+#define	BGE_RXCPUMODE_INVDATAHLT_ENB	0x00000800
+#define	BGE_RXCPUMODE_MADDRTRAPHLT_ENB	0x00001000
+#define	BGE_RXCPUMODE_RADDRTRAPHLT_ENB	0x00002000
+
+/* RX CPU status register */
+#define	BGE_RXCPUSTAT_HW_BREAKPOINT	0x00000001
+#define	BGE_RXCPUSTAT_HLTINSTR_EXECUTED	0x00000002
+#define	BGE_RXCPUSTAT_INVALID_INSTR	0x00000004
+#define	BGE_RXCPUSTAT_P0_DATAREF	0x00000008
+#define	BGE_RXCPUSTAT_P0_INSTRREF	0x00000010
+#define	BGE_RXCPUSTAT_INVALID_DATAACC	0x00000020
+#define	BGE_RXCPUSTAT_INVALID_INSTRFTCH	0x00000040
+#define	BGE_RXCPUSTAT_BAD_MEMALIGN	0x00000080
+#define	BGE_RXCPUSTAT_MADDR_TRAP	0x00000100
+#define	BGE_RXCPUSTAT_REGADDR_TRAP	0x00000200
+#define	BGE_RXCPUSTAT_DATAACC_STALL	0x00001000
+#define	BGE_RXCPUSTAT_INSTRFETCH_STALL	0x00002000
+#define	BGE_RXCPUSTAT_MA_WR_FIFOOFLOW	0x08000000
+#define	BGE_RXCPUSTAT_MA_RD_FIFOOFLOW	0x10000000
+#define	BGE_RXCPUSTAT_MA_DATAMASK_OFLOW	0x20000000
+#define	BGE_RXCPUSTAT_MA_REQ_FIFOOFLOW	0x40000000
+#define	BGE_RXCPUSTAT_BLOCKING_READ	0x80000000
+
+/*
+ * V? CPU registers
+ */
+#define	BGE_VCPU_STATUS			0x5100
+#define	BGE_VCPU_EXT_CTRL		0x6890
+
+#define	BGE_VCPU_STATUS_INIT_DONE	0x04000000
+#define	BGE_VCPU_STATUS_DRV_RESET 	0x08000000
+
+#define	BGE_VCPU_EXT_CTRL_HALT_CPU	0x00400000
+#define	BGE_VCPU_EXT_CTRL_DISABLE_WOL	0x20000000
+
+/*
+ * TX CPU registers
+ */
+#define	BGE_TXCPU_MODE			0x5400
+#define	BGE_TXCPU_STATUS		0x5404
+#define	BGE_TXCPU_PC			0x541C
+
+/* TX CPU mode register */
+#define	BGE_TXCPUMODE_RESET		0x00000001
+#define	BGE_TXCPUMODE_SINGLESTEP	0x00000002
+#define	BGE_TXCPUMODE_P0_DATAHLT_ENB	0x00000004
+#define	BGE_TXCPUMODE_P0_INSTRHLT_ENB	0x00000008
+#define	BGE_TXCPUMODE_WR_POSTBUF_ENB	0x00000010
+#define	BGE_TXCPUMODE_DATACACHE_ENB	0x00000020
+#define	BGE_TXCPUMODE_ROMFAIL		0x00000040
+#define	BGE_TXCPUMODE_WATCHDOG_ENB	0x00000080
+#define	BGE_TXCPUMODE_INSTRCACHE_PRF	0x00000100
+#define	BGE_TXCPUMODE_INSTRCACHE_FLUSH	0x00000200
+#define	BGE_TXCPUMODE_HALTCPU		0x00000400
+#define	BGE_TXCPUMODE_INVDATAHLT_ENB	0x00000800
+#define	BGE_TXCPUMODE_MADDRTRAPHLT_ENB	0x00001000
+
+/* TX CPU status register */
+#define	BGE_TXCPUSTAT_HW_BREAKPOINT	0x00000001
+#define	BGE_TXCPUSTAT_HLTINSTR_EXECUTED	0x00000002
+#define	BGE_TXCPUSTAT_INVALID_INSTR	0x00000004
+#define	BGE_TXCPUSTAT_P0_DATAREF	0x00000008
+#define	BGE_TXCPUSTAT_P0_INSTRREF	0x00000010
+#define	BGE_TXCPUSTAT_INVALID_DATAACC	0x00000020
+#define	BGE_TXCPUSTAT_INVALID_INSTRFTCH	0x00000040
+#define	BGE_TXCPUSTAT_BAD_MEMALIGN	0x00000080
+#define	BGE_TXCPUSTAT_MADDR_TRAP	0x00000100
+#define	BGE_TXCPUSTAT_REGADDR_TRAP	0x00000200
+#define	BGE_TXCPUSTAT_DATAACC_STALL	0x00001000
+#define	BGE_TXCPUSTAT_INSTRFETCH_STALL	0x00002000
+#define	BGE_TXCPUSTAT_MA_WR_FIFOOFLOW	0x08000000
+#define	BGE_TXCPUSTAT_MA_RD_FIFOOFLOW	0x10000000
+#define	BGE_TXCPUSTAT_MA_DATAMASK_OFLOW	0x20000000
+#define	BGE_TXCPUSTAT_MA_REQ_FIFOOFLOW	0x40000000
+#define	BGE_TXCPUSTAT_BLOCKING_READ	0x80000000
+
+
+/*
+ * Low priority mailbox registers
+ */
+#define	BGE_LPMBX_IRQ0_HI		0x5800
+#define	BGE_LPMBX_IRQ0_LO		0x5804
+#define	BGE_LPMBX_IRQ1_HI		0x5808
+#define	BGE_LPMBX_IRQ1_LO		0x580C
+#define	BGE_LPMBX_IRQ2_HI		0x5810
+#define	BGE_LPMBX_IRQ2_LO		0x5814
+#define	BGE_LPMBX_IRQ3_HI		0x5818
+#define	BGE_LPMBX_IRQ3_LO		0x581C
+#define	BGE_LPMBX_GEN0_HI		0x5820
+#define	BGE_LPMBX_GEN0_LO		0x5824
+#define	BGE_LPMBX_GEN1_HI		0x5828
+#define	BGE_LPMBX_GEN1_LO		0x582C
+#define	BGE_LPMBX_GEN2_HI		0x5830
+#define	BGE_LPMBX_GEN2_LO		0x5834
+#define	BGE_LPMBX_GEN3_HI		0x5828
+#define	BGE_LPMBX_GEN3_LO		0x582C
+#define	BGE_LPMBX_GEN4_HI		0x5840
+#define	BGE_LPMBX_GEN4_LO		0x5844
+#define	BGE_LPMBX_GEN5_HI		0x5848
+#define	BGE_LPMBX_GEN5_LO		0x584C
+#define	BGE_LPMBX_GEN6_HI		0x5850
+#define	BGE_LPMBX_GEN6_LO		0x5854
+#define	BGE_LPMBX_GEN7_HI		0x5858
+#define	BGE_LPMBX_GEN7_LO		0x585C
+#define	BGE_LPMBX_RELOAD_STATS_HI	0x5860
+#define	BGE_LPMBX_RELOAD_STATS_LO	0x5864
+#define	BGE_LPMBX_RX_STD_PROD_HI	0x5868
+#define	BGE_LPMBX_RX_STD_PROD_LO	0x586C
+#define	BGE_LPMBX_RX_JUMBO_PROD_HI	0x5870
+#define	BGE_LPMBX_RX_JUMBO_PROD_LO	0x5874
+#define	BGE_LPMBX_RX_MINI_PROD_HI	0x5878
+#define	BGE_LPMBX_RX_MINI_PROD_LO	0x587C
+#define	BGE_LPMBX_RX_CONS0_HI		0x5880
+#define	BGE_LPMBX_RX_CONS0_LO		0x5884
+#define	BGE_LPMBX_RX_CONS1_HI		0x5888
+#define	BGE_LPMBX_RX_CONS1_LO		0x588C
+#define	BGE_LPMBX_RX_CONS2_HI		0x5890
+#define	BGE_LPMBX_RX_CONS2_LO		0x5894
+#define	BGE_LPMBX_RX_CONS3_HI		0x5898
+#define	BGE_LPMBX_RX_CONS3_LO		0x589C
+#define	BGE_LPMBX_RX_CONS4_HI		0x58A0
+#define	BGE_LPMBX_RX_CONS4_LO		0x58A4
+#define	BGE_LPMBX_RX_CONS5_HI		0x58A8
+#define	BGE_LPMBX_RX_CONS5_LO		0x58AC
+#define	BGE_LPMBX_RX_CONS6_HI		0x58B0
+#define	BGE_LPMBX_RX_CONS6_LO		0x58B4
+#define	BGE_LPMBX_RX_CONS7_HI		0x58B8
+#define	BGE_LPMBX_RX_CONS7_LO		0x58BC
+#define	BGE_LPMBX_RX_CONS8_HI		0x58C0
+#define	BGE_LPMBX_RX_CONS8_LO		0x58C4
+#define	BGE_LPMBX_RX_CONS9_HI		0x58C8
+#define	BGE_LPMBX_RX_CONS9_LO		0x58CC
+#define	BGE_LPMBX_RX_CONS10_HI		0x58D0
+#define	BGE_LPMBX_RX_CONS10_LO		0x58D4
+#define	BGE_LPMBX_RX_CONS11_HI		0x58D8
+#define	BGE_LPMBX_RX_CONS11_LO		0x58DC
+#define	BGE_LPMBX_RX_CONS12_HI		0x58E0
+#define	BGE_LPMBX_RX_CONS12_LO		0x58E4
+#define	BGE_LPMBX_RX_CONS13_HI		0x58E8
+#define	BGE_LPMBX_RX_CONS13_LO		0x58EC
+#define	BGE_LPMBX_RX_CONS14_HI		0x58F0
+#define	BGE_LPMBX_RX_CONS14_LO		0x58F4
+#define	BGE_LPMBX_RX_CONS15_HI		0x58F8
+#define	BGE_LPMBX_RX_CONS15_LO		0x58FC
+#define	BGE_LPMBX_TX_HOST_PROD0_HI	0x5900
+#define	BGE_LPMBX_TX_HOST_PROD0_LO	0x5904
+#define	BGE_LPMBX_TX_HOST_PROD1_HI	0x5908
+#define	BGE_LPMBX_TX_HOST_PROD1_LO	0x590C
+#define	BGE_LPMBX_TX_HOST_PROD2_HI	0x5910
+#define	BGE_LPMBX_TX_HOST_PROD2_LO	0x5914
+#define	BGE_LPMBX_TX_HOST_PROD3_HI	0x5918
+#define	BGE_LPMBX_TX_HOST_PROD3_LO	0x591C
+#define	BGE_LPMBX_TX_HOST_PROD4_HI	0x5920
+#define	BGE_LPMBX_TX_HOST_PROD4_LO	0x5924
+#define	BGE_LPMBX_TX_HOST_PROD5_HI	0x5928
+#define	BGE_LPMBX_TX_HOST_PROD5_LO	0x592C
+#define	BGE_LPMBX_TX_HOST_PROD6_HI	0x5930
+#define	BGE_LPMBX_TX_HOST_PROD6_LO	0x5934
+#define	BGE_LPMBX_TX_HOST_PROD7_HI	0x5938
+#define	BGE_LPMBX_TX_HOST_PROD7_LO	0x593C
+#define	BGE_LPMBX_TX_HOST_PROD8_HI	0x5940
+#define	BGE_LPMBX_TX_HOST_PROD8_LO	0x5944
+#define	BGE_LPMBX_TX_HOST_PROD9_HI	0x5948
+#define	BGE_LPMBX_TX_HOST_PROD9_LO	0x594C
+#define	BGE_LPMBX_TX_HOST_PROD10_HI	0x5950
+#define	BGE_LPMBX_TX_HOST_PROD10_LO	0x5954
+#define	BGE_LPMBX_TX_HOST_PROD11_HI	0x5958
+#define	BGE_LPMBX_TX_HOST_PROD11_LO	0x595C
+#define	BGE_LPMBX_TX_HOST_PROD12_HI	0x5960
+#define	BGE_LPMBX_TX_HOST_PROD12_LO	0x5964
+#define	BGE_LPMBX_TX_HOST_PROD13_HI	0x5968
+#define	BGE_LPMBX_TX_HOST_PROD13_LO	0x596C
+#define	BGE_LPMBX_TX_HOST_PROD14_HI	0x5970
+#define	BGE_LPMBX_TX_HOST_PROD14_LO	0x5974
+#define	BGE_LPMBX_TX_HOST_PROD15_HI	0x5978
+#define	BGE_LPMBX_TX_HOST_PROD15_LO	0x597C
+#define	BGE_LPMBX_TX_NIC_PROD0_HI	0x5980
+#define	BGE_LPMBX_TX_NIC_PROD0_LO	0x5984
+#define	BGE_LPMBX_TX_NIC_PROD1_HI	0x5988
+#define	BGE_LPMBX_TX_NIC_PROD1_LO	0x598C
+#define	BGE_LPMBX_TX_NIC_PROD2_HI	0x5990
+#define	BGE_LPMBX_TX_NIC_PROD2_LO	0x5994
+#define	BGE_LPMBX_TX_NIC_PROD3_HI	0x5998
+#define	BGE_LPMBX_TX_NIC_PROD3_LO	0x599C
+#define	BGE_LPMBX_TX_NIC_PROD4_HI	0x59A0
+#define	BGE_LPMBX_TX_NIC_PROD4_LO	0x59A4
+#define	BGE_LPMBX_TX_NIC_PROD5_HI	0x59A8
+#define	BGE_LPMBX_TX_NIC_PROD5_LO	0x59AC
+#define	BGE_LPMBX_TX_NIC_PROD6_HI	0x59B0
+#define	BGE_LPMBX_TX_NIC_PROD6_LO	0x59B4
+#define	BGE_LPMBX_TX_NIC_PROD7_HI	0x59B8
+#define	BGE_LPMBX_TX_NIC_PROD7_LO	0x59BC
+#define	BGE_LPMBX_TX_NIC_PROD8_HI	0x59C0
+#define	BGE_LPMBX_TX_NIC_PROD8_LO	0x59C4
+#define	BGE_LPMBX_TX_NIC_PROD9_HI	0x59C8
+#define	BGE_LPMBX_TX_NIC_PROD9_LO	0x59CC
+#define	BGE_LPMBX_TX_NIC_PROD10_HI	0x59D0
+#define	BGE_LPMBX_TX_NIC_PROD10_LO	0x59D4
+#define	BGE_LPMBX_TX_NIC_PROD11_HI	0x59D8
+#define	BGE_LPMBX_TX_NIC_PROD11_LO	0x59DC
+#define	BGE_LPMBX_TX_NIC_PROD12_HI	0x59E0
+#define	BGE_LPMBX_TX_NIC_PROD12_LO	0x59E4
+#define	BGE_LPMBX_TX_NIC_PROD13_HI	0x59E8
+#define	BGE_LPMBX_TX_NIC_PROD13_LO	0x59EC
+#define	BGE_LPMBX_TX_NIC_PROD14_HI	0x59F0
+#define	BGE_LPMBX_TX_NIC_PROD14_LO	0x59F4
+#define	BGE_LPMBX_TX_NIC_PROD15_HI	0x59F8
+#define	BGE_LPMBX_TX_NIC_PROD15_LO	0x59FC
+
+/*
+ * Flow throw Queue reset register
+ */
+#define	BGE_FTQ_RESET			0x5C00
+
+#define	BGE_FTQRESET_DMAREAD		0x00000002
+#define	BGE_FTQRESET_DMAHIPRIO_RD	0x00000004
+#define	BGE_FTQRESET_DMADONE		0x00000010
+#define	BGE_FTQRESET_SBDC		0x00000020
+#define	BGE_FTQRESET_SDI		0x00000040
+#define	BGE_FTQRESET_WDMA		0x00000080
+#define	BGE_FTQRESET_DMAHIPRIO_WR	0x00000100
+#define	BGE_FTQRESET_TYPE1_SOFTWARE	0x00000200
+#define	BGE_FTQRESET_SDC		0x00000400
+#define	BGE_FTQRESET_HCC		0x00000800
+#define	BGE_FTQRESET_TXFIFO		0x00001000
+#define	BGE_FTQRESET_MBC		0x00002000
+#define	BGE_FTQRESET_RBDC		0x00004000
+#define	BGE_FTQRESET_RXLP		0x00008000
+#define	BGE_FTQRESET_RDBDI		0x00010000
+#define	BGE_FTQRESET_RDC		0x00020000
+#define	BGE_FTQRESET_TYPE2_SOFTWARE	0x00040000
+
+/*
+ * Message Signaled Interrupt registers
+ */
+#define	BGE_MSI_MODE			0x6000
+#define	BGE_MSI_STATUS			0x6004
+#define	BGE_MSI_FIFOACCESS		0x6008
+
+/* MSI mode register */
+#define	BGE_MSIMODE_RESET		0x00000001
+#define	BGE_MSIMODE_ENABLE		0x00000002
+#define	BGE_MSIMODE_ONE_SHOT_DISABLE	0x00000020
+#define	BGE_MSIMODE_MULTIVEC_ENABLE	0x00000080
+
+/* MSI status register */
+#define	BGE_MSISTAT_PCI_TGT_ABRT_ATTN	0x00000004
+#define	BGE_MSISTAT_PCI_MSTR_ABRT_ATTN	0x00000008
+#define	BGE_MSISTAT_PCI_PERR_ATTN	0x00000010
+#define	BGE_MSISTAT_MSI_FIFOUFLOW_ATTN	0x00000020
+#define	BGE_MSISTAT_MSI_FIFOOFLOW_ATTN	0x00000040
+
+
+/*
+ * DMA Completion registers
+ */
+#define	BGE_DMAC_MODE			0x6400
+
+/* DMA Completion mode register */
+#define	BGE_DMACMODE_RESET		0x00000001
+#define	BGE_DMACMODE_ENABLE		0x00000002
+
+
+/*
+ * General control registers.
+ */
+#define	BGE_MODE_CTL			0x6800
+#define	BGE_MISC_CFG			0x6804
+#define	BGE_MISC_LOCAL_CTL		0x6808
+#define	BGE_RX_CPU_EVENT		0x6810
+#define	BGE_TX_CPU_EVENT		0x6820
+#define	BGE_EE_ADDR			0x6838
+#define	BGE_EE_DATA			0x683C
+#define	BGE_EE_CTL			0x6840
+#define	BGE_MDI_CTL			0x6844
+#define	BGE_EE_DELAY			0x6848
+#define	BGE_FASTBOOT_PC			0x6894
+
+#define	BGE_RX_CPU_DRV_EVENT		0x00004000
+
+/*
+ * NVRAM Control registers
+ */
+#define	BGE_NVRAM_CMD			0x7000
+#define	BGE_NVRAM_STAT			0x7004
+#define	BGE_NVRAM_WRDATA		0x7008
+#define	BGE_NVRAM_ADDR			0x700c
+#define	BGE_NVRAM_RDDATA		0x7010
+#define	BGE_NVRAM_CFG1			0x7014
+#define	BGE_NVRAM_CFG2			0x7018
+#define	BGE_NVRAM_CFG3			0x701c
+#define	BGE_NVRAM_SWARB			0x7020
+#define	BGE_NVRAM_ACCESS		0x7024
+#define	BGE_NVRAM_WRITE1		0x7028
+
+#define	BGE_NVRAMCMD_RESET		0x00000001
+#define	BGE_NVRAMCMD_DONE		0x00000008
+#define	BGE_NVRAMCMD_START		0x00000010
+#define	BGE_NVRAMCMD_WR			0x00000020 /* 1 = wr, 0 = rd */
+#define	BGE_NVRAMCMD_ERASE		0x00000040
+#define	BGE_NVRAMCMD_FIRST		0x00000080
+#define	BGE_NVRAMCMD_LAST		0x00000100
+
+#define	BGE_NVRAM_READCMD \
+	(BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \
+	BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE)
+#define	BGE_NVRAM_WRITECMD \
+	(BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \
+	BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE|BGE_NVRAMCMD_WR)
+
+#define	BGE_NVRAMSWARB_SET0		0x00000001
+#define	BGE_NVRAMSWARB_SET1		0x00000002
+#define	BGE_NVRAMSWARB_SET2		0x00000003
+#define	BGE_NVRAMSWARB_SET3		0x00000004
+#define	BGE_NVRAMSWARB_CLR0		0x00000010
+#define	BGE_NVRAMSWARB_CLR1		0x00000020
+#define	BGE_NVRAMSWARB_CLR2		0x00000040
+#define	BGE_NVRAMSWARB_CLR3		0x00000080
+#define	BGE_NVRAMSWARB_GNT0		0x00000100
+#define	BGE_NVRAMSWARB_GNT1		0x00000200
+#define	BGE_NVRAMSWARB_GNT2		0x00000400
+#define	BGE_NVRAMSWARB_GNT3		0x00000800
+#define	BGE_NVRAMSWARB_REQ0		0x00001000
+#define	BGE_NVRAMSWARB_REQ1		0x00002000
+#define	BGE_NVRAMSWARB_REQ2		0x00004000
+#define	BGE_NVRAMSWARB_REQ3		0x00008000
+
+#define	BGE_NVRAMACC_ENABLE		0x00000001
+#define	BGE_NVRAMACC_WRENABLE		0x00000002
+
+/* Mode control register */
+#define	BGE_MODECTL_INT_SNDCOAL_ONLY	0x00000001
+#define	BGE_MODECTL_BYTESWAP_NONFRAME	0x00000002
+#define	BGE_MODECTL_WORDSWAP_NONFRAME	0x00000004
+#define	BGE_MODECTL_BYTESWAP_DATA	0x00000010
+#define	BGE_MODECTL_WORDSWAP_DATA	0x00000020
+#define	BGE_MODECTL_BYTESWAP_B2HRX_DATA	0x00000040
+#define	BGE_MODECTL_WORDSWAP_B2HRX_DATA	0x00000080
+#define	BGE_MODECTL_NO_FRAME_CRACKING	0x00000200
+#define	BGE_MODECTL_NO_RX_CRC		0x00000400
+#define	BGE_MODECTL_RX_BADFRAMES	0x00000800
+#define	BGE_MODECTL_NO_TX_INTR		0x00002000
+#define	BGE_MODECTL_NO_RX_INTR		0x00004000
+#define	BGE_MODECTL_FORCE_PCI32		0x00008000
+#define	BGE_MODECTL_B2HRX_ENABLE	0x00008000
+#define	BGE_MODECTL_STACKUP		0x00010000
+#define	BGE_MODECTL_HOST_SEND_BDS	0x00020000
+#define	BGE_MODECTL_HTX2B_ENABLE	0x00040000
+#define	BGE_MODECTL_TX_NO_PHDR_CSUM	0x00100000
+#define	BGE_MODECTL_RX_NO_PHDR_CSUM	0x00800000
+#define	BGE_MODECTL_TX_ATTN_INTR	0x01000000
+#define	BGE_MODECTL_RX_ATTN_INTR	0x02000000
+#define	BGE_MODECTL_MAC_ATTN_INTR	0x04000000
+#define	BGE_MODECTL_DMA_ATTN_INTR	0x08000000
+#define	BGE_MODECTL_FLOWCTL_ATTN_INTR	0x10000000
+#define	BGE_MODECTL_4X_SENDRING_SZ	0x20000000
+#define	BGE_MODECTL_FW_PROCESS_MCASTS	0x40000000
+
+/* Misc. config register */
+#define	BGE_MISCCFG_RESET_CORE_CLOCKS	0x00000001
+#define	BGE_MISCCFG_TIMER_PRESCALER	0x000000FE
+#define	BGE_MISCCFG_BOARD_ID_MASK	0x0001E000
+#define	BGE_MISCCFG_BOARD_ID_5704	0x00000000
+#define	BGE_MISCCFG_BOARD_ID_5704CIOBE	0x00004000
+#define	BGE_MISCCFG_BOARD_ID_5788	0x00010000
+#define	BGE_MISCCFG_BOARD_ID_5788M	0x00018000
+#define	BGE_MISCCFG_EPHY_IDDQ		0x00200000
+#define	BGE_MISCCFG_GPHY_PD_OVERRIDE	0x04000000
+
+#define	BGE_32BITTIME_66MHZ		(0x41 << 1)
+
+/* Misc. Local Control */
+#define	BGE_MLC_INTR_STATE		0x00000001
+#define	BGE_MLC_INTR_CLR		0x00000002
+#define	BGE_MLC_INTR_SET		0x00000004
+#define	BGE_MLC_INTR_ONATTN		0x00000008
+#define	BGE_MLC_MISCIO_IN0		0x00000100
+#define	BGE_MLC_MISCIO_IN1		0x00000200
+#define	BGE_MLC_MISCIO_IN2		0x00000400
+#define	BGE_MLC_MISCIO_OUTEN0		0x00000800
+#define	BGE_MLC_MISCIO_OUTEN1		0x00001000
+#define	BGE_MLC_MISCIO_OUTEN2		0x00002000
+#define	BGE_MLC_MISCIO_OUT0		0x00004000
+#define	BGE_MLC_MISCIO_OUT1		0x00008000
+#define	BGE_MLC_MISCIO_OUT2		0x00010000
+#define	BGE_MLC_EXTRAM_ENB		0x00020000
+#define	BGE_MLC_SRAM_SIZE		0x001C0000
+#define	BGE_MLC_BANK_SEL		0x00200000 /* 0 = 2 banks, 1 == 1 */
+#define	BGE_MLC_SSRAM_TYPE		0x00400000 /* 1 = ZBT, 0 = standard */
+#define	BGE_MLC_SSRAM_CYC_DESEL		0x00800000
+#define	BGE_MLC_AUTO_EEPROM		0x01000000
+
+#define	BGE_SSRAMSIZE_256KB		0x00000000
+#define	BGE_SSRAMSIZE_512KB		0x00040000
+#define	BGE_SSRAMSIZE_1MB		0x00080000
+#define	BGE_SSRAMSIZE_2MB		0x000C0000
+#define	BGE_SSRAMSIZE_4MB		0x00100000
+#define	BGE_SSRAMSIZE_8MB		0x00140000
+#define	BGE_SSRAMSIZE_16M		0x00180000
+
+/* EEPROM address register */
+#define	BGE_EEADDR_ADDRESS		0x0000FFFC
+#define	BGE_EEADDR_HALFCLK		0x01FF0000
+#define	BGE_EEADDR_START		0x02000000
+#define	BGE_EEADDR_DEVID		0x1C000000
+#define	BGE_EEADDR_RESET		0x20000000
+#define	BGE_EEADDR_DONE			0x40000000
+#define	BGE_EEADDR_RW			0x80000000 /* 1 = rd, 0 = wr */
+
+#define	BGE_EEDEVID(x)			((x & 7) << 26)
+#define	BGE_EEHALFCLK(x)		((x & 0x1FF) << 16)
+#define	BGE_HALFCLK_384SCL		0x60
+#define	BGE_EE_READCMD \
+	(BGE_EEHALFCLK(BGE_HALFCLK_384SCL)|BGE_EEDEVID(0)|	\
+	BGE_EEADDR_START|BGE_EEADDR_RW|BGE_EEADDR_DONE)
+#define	BGE_EE_WRCMD \
+	(BGE_EEHALFCLK(BGE_HALFCLK_384SCL)|BGE_EEDEVID(0)|	\
+	BGE_EEADDR_START|BGE_EEADDR_DONE)
+
+/* EEPROM Control register */
+#define	BGE_EECTL_CLKOUT_TRISTATE	0x00000001
+#define	BGE_EECTL_CLKOUT		0x00000002
+#define	BGE_EECTL_CLKIN			0x00000004
+#define	BGE_EECTL_DATAOUT_TRISTATE	0x00000008
+#define	BGE_EECTL_DATAOUT		0x00000010
+#define	BGE_EECTL_DATAIN		0x00000020
+
+/* MDI (MII/GMII) access register */
+#define	BGE_MDI_DATA			0x00000001
+#define	BGE_MDI_DIR			0x00000002
+#define	BGE_MDI_SEL			0x00000004
+#define	BGE_MDI_CLK			0x00000008
+
+#define	BGE_MEMWIN_START		0x00008000
+#define	BGE_MEMWIN_END			0x0000FFFF
+
+/* BAR1 (APE) Register Definitions */
+
+#define	BGE_APE_GPIO_MSG		0x0008
+#define	BGE_APE_EVENT			0x000C
+#define	BGE_APE_LOCK_REQ		0x002C
+#define	BGE_APE_LOCK_GRANT		0x004C
+
+#define	BGE_APE_GPIO_MSG_SHIFT		4
+
+#define	BGE_APE_EVENT_1			0x00000001
+
+#define	BGE_APE_LOCK_REQ_DRIVER0	0x00001000
+
+#define	BGE_APE_LOCK_GRANT_DRIVER0	0x00001000
+
+/* APE Shared Memory block (writable by APE only) */
+#define	BGE_APE_SEG_SIG			0x4000
+#define	BGE_APE_FW_STATUS		0x400C
+#define	BGE_APE_FW_FEATURES		0x4010
+#define	BGE_APE_FW_BEHAVIOR		0x4014
+#define	BGE_APE_FW_VERSION		0x4018
+#define	BGE_APE_FW_HEARTBEAT_INTERVAL	0x4024
+#define	BGE_APE_FW_HEARTBEAT		0x4028
+#define	BGE_APE_FW_ERROR_FLAGS		0x4074
+
+#define	BGE_APE_SEG_SIG_MAGIC		0x41504521	/* 'APE!' */
+
+#define	BGE_APE_FW_STATUS_READY		0x00000100
+
+#define	BGE_APE_FW_FEATURE_DASH		0x00000001
+#define	BGE_APE_FW_FEATURE_NCSI		0x00000002
+
+#define	BGE_APE_FW_VERSION_MAJMSK	0xFF000000
+#define	BGE_APE_FW_VERSION_MAJSFT	24
+#define	BGE_APE_FW_VERSION_MINMSK	0x00FF0000
+#define	BGE_APE_FW_VERSION_MINSFT	16
+#define	BGE_APE_FW_VERSION_REVMSK	0x0000FF00
+#define	BGE_APE_FW_VERSION_REVSFT	8
+#define	BGE_APE_FW_VERSION_BLDMSK	0x000000FF
+
+/* Host Shared Memory block (writable by host only) */
+#define	BGE_APE_HOST_SEG_SIG		0x4200
+#define	BGE_APE_HOST_SEG_LEN		0x4204
+#define	BGE_APE_HOST_INIT_COUNT		0x4208
+#define	BGE_APE_HOST_DRIVER_ID		0x420C
+#define	BGE_APE_HOST_BEHAVIOR		0x4210
+#define	BGE_APE_HOST_HEARTBEAT_INT_MS	0x4214
+#define	BGE_APE_HOST_HEARTBEAT_COUNT	0x4218
+#define	BGE_APE_HOST_DRVR_STATE		0x421C
+#define	BGE_APE_HOST_WOL_SPEED		0x4224
+
+#define	BGE_APE_HOST_SEG_SIG_MAGIC	0x484F5354
+
+#define	BGE_APE_HOST_SEG_LEN_MAGIC	0x00000020
+
+#define	BGE_APE_HOST_DRIVER_ID_FBSD	0xF6000000
+#define	BGE_APE_HOST_DRIVER_ID_MAGIC(maj, min)				\
+	(BGE_APE_HOST_DRIVER_ID_FBSD |					\
+	((maj) & 0xffd) << 16 | ((min) & 0xff) << 8)
+
+#define	BGE_APE_HOST_BEHAV_NO_PHYLOCK	0x00000001
+
+#define	BGE_APE_HOST_HEARTBEAT_INT_DISABLE	0
+#define	BGE_APE_HOST_HEARTBEAT_INT_5SEC	5000
+
+#define	BGE_APE_HOST_DRVR_STATE_START	0x00000001
+#define	BGE_APE_HOST_DRVR_STATE_UNLOAD	0x00000002
+#define	BGE_APE_HOST_DRVR_STATE_WOL	0x00000003
+#define	BGE_APE_HOST_DRVR_STATE_SUSPEND	0x00000004
+
+#define	BGE_APE_HOST_WOL_SPEED_AUTO	0x00008000
+
+#define	BGE_APE_EVENT_STATUS		0x4300
+
+#define	BGE_APE_EVENT_STATUS_DRIVER_EVNT	0x00000010
+#define	BGE_APE_EVENT_STATUS_STATE_CHNGE	0x00000500
+#define	BGE_APE_EVENT_STATUS_STATE_START	0x00010000
+#define	BGE_APE_EVENT_STATUS_STATE_UNLOAD	0x00020000
+#define	BGE_APE_EVENT_STATUS_STATE_WOL		0x00030000
+#define	BGE_APE_EVENT_STATUS_STATE_SUSPEND	0x00040000
+#define	BGE_APE_EVENT_STATUS_EVENT_PENDING	0x80000000
+
+#define	BGE_APE_DEBUG_LOG		0x4E00
+#define	BGE_APE_DEBUG_LOG_LEN		0x0100
+
+#define	BGE_APE_PER_LOCK_REQ		0x8400
+#define	BGE_APE_PER_LOCK_GRANT		0x8420
+
+#define	BGE_APE_LOCK_PER_REQ_DRIVER0	0x00001000
+#define	BGE_APE_LOCK_PER_REQ_DRIVER1	0x00000002
+#define	BGE_APE_LOCK_PER_REQ_DRIVER2	0x00000004
+#define	BGE_APE_LOCK_PER_REQ_DRIVER3	0x00000008
+
+#define	BGE_APE_PER_LOCK_GRANT_DRIVER0	0x00001000
+#define	BGE_APE_PER_LOCK_GRANT_DRIVER1	0x00000002
+#define	BGE_APE_PER_LOCK_GRANT_DRIVER2	0x00000004
+#define	BGE_APE_PER_LOCK_GRANT_DRIVER3	0x00000008
+
+/* APE Mutex Resources */
+#define	BGE_APE_LOCK_PHY0		0
+#define	BGE_APE_LOCK_GRC		1
+#define	BGE_APE_LOCK_PHY1		2
+#define	BGE_APE_LOCK_PHY2		3
+#define	BGE_APE_LOCK_MEM		4
+#define	BGE_APE_LOCK_PHY3		5
+#define	BGE_APE_LOCK_GPIO		7
+
+#define	BGE_MEMWIN_READ(sc, x, val)					\
+	do {								\
+		pci_write_config(sc->bge_dev, BGE_PCI_MEMWIN_BASEADDR,	\
+		    (0xFFFF0000 & x), 4);				\
+		val = CSR_READ_4(sc, BGE_MEMWIN_START + (x & 0xFFFF));	\
+	} while(0)
+
+#define	BGE_MEMWIN_WRITE(sc, x, val)					\
+	do {								\
+		pci_write_config(sc->bge_dev, BGE_PCI_MEMWIN_BASEADDR,	\
+		    (0xFFFF0000 & x), 4);				\
+		CSR_WRITE_4(sc, BGE_MEMWIN_START + (x & 0xFFFF), val);	\
+	} while(0)
+
+/*
+ * This magic number is written to the firmware mailbox at 0xb50
+ * before a software reset is issued.  After the internal firmware
+ * has completed its initialization it will write the opposite of
+ * this value, ~BGE_SRAM_FW_MB_MAGIC, to the same location,
+ * allowing the driver to synchronize with the firmware.
+ */
+#define	BGE_SRAM_FW_MB_MAGIC	0x4B657654
+
+typedef struct {
+	volatile uint32_t		bge_addr_hi;
+	volatile uint32_t		bge_addr_lo;
+} bge_hostaddr;
+
+#define	BGE_HOSTADDR(x, y)						\
+	do {								\
+		(x).bge_addr_lo = ((uint64_t) (y) & 0xffffffff);	\
+		(x).bge_addr_hi = ((uint64_t) (y) >> 32);		\
+	} while(0)
+
+#define	BGE_ADDR_LO(y)	\
+	((uint64_t) (y) & 0xFFFFFFFF)
+#define	BGE_ADDR_HI(y)	\
+	((uint64_t) (y) >> 32)
+
+/* Ring control block structure */
+struct bge_rcb {
+	volatile bge_hostaddr		bge_hostaddr;
+	volatile uint32_t		bge_maxlen_flags;
+	volatile uint32_t		bge_nicaddr;
+};
+
+#define	RCB_WRITE_4(sc, rcb, offset, val) \
+	bus_write_4(sc->bge_res, rcb + offsetof(struct bge_rcb, offset), val)
+#define RCB_READ_4(sc, rcb, offset) \
+	bus_read_4(sc->bge_res, rcb + offsetof(struct bge_rcb, offset))
+#define	BGE_RCB_MAXLEN_FLAGS(maxlen, flags)	((maxlen) << 16 | (flags))
+
+#define	BGE_RCB_FLAG_USE_EXT_RX_BD	0x0001
+#define	BGE_RCB_FLAG_RING_DISABLED	0x0002
+
+struct bge_tx_bd {
+	volatile bge_hostaddr		bge_addr;
+#ifdef __LITTLE_ENDIAN
+	volatile uint16_t		bge_flags;
+	volatile uint16_t		bge_len;
+	volatile uint16_t		bge_vlan_tag;
+	volatile uint16_t		bge_mss;
+#else
+	volatile uint16_t		bge_len;
+	volatile uint16_t		bge_flags;
+	volatile uint16_t		bge_mss;
+	volatile uint16_t		bge_vlan_tag;
+#endif
+};
+
+#define	BGE_TXBDFLAG_TCP_UDP_CSUM	0x0001
+#define	BGE_TXBDFLAG_IP_CSUM		0x0002
+#define	BGE_TXBDFLAG_END		0x0004
+#define	BGE_TXBDFLAG_IP_FRAG		0x0008
+#define	BGE_TXBDFLAG_JUMBO_FRAME	0x0008	/* 5717 */
+#define	BGE_TXBDFLAG_IP_FRAG_END	0x0010
+#define	BGE_TXBDFLAG_HDRLEN_BIT2	0x0010	/* 5717 */
+#define	BGE_TXBDFLAG_SNAP		0x0020	/* 5717 */
+#define	BGE_TXBDFLAG_VLAN_TAG		0x0040
+#define	BGE_TXBDFLAG_COAL_NOW		0x0080
+#define	BGE_TXBDFLAG_CPU_PRE_DMA	0x0100
+#define	BGE_TXBDFLAG_CPU_POST_DMA	0x0200
+#define	BGE_TXBDFLAG_HDRLEN_BIT3	0x0400	/* 5717 */
+#define	BGE_TXBDFLAG_HDRLEN_BIT4	0x0800	/* 5717 */
+#define	BGE_TXBDFLAG_INSERT_SRC_ADDR	0x1000
+#define	BGE_TXBDFLAG_HDRLEN_BIT5	0x1000	/* 5717 */
+#define	BGE_TXBDFLAG_HDRLEN_BIT6	0x2000	/* 5717 */
+#define	BGE_TXBDFLAG_HDRLEN_BIT7	0x4000	/* 5717 */
+#define	BGE_TXBDFLAG_CHOOSE_SRC_ADDR	0x6000
+#define	BGE_TXBDFLAG_NO_CRC		0x8000
+
+#define	BGE_TXBDFLAG_MSS_SIZE_MASK	0x3FFF	/* 5717 */
+/* Bits [1:0] of the MSS header length. */
+#define	BGE_TXBDFLAG_MSS_HDRLEN_MASK	0xC000	/* 5717 */
+
+#define	BGE_NIC_TXRING_ADDR(ringno, size)	\
+	BGE_SEND_RING_1_TO_4 +			\
+	((ringno * sizeof(struct bge_tx_bd) * size) / 4)
+
+struct bge_rx_bd {
+	volatile bge_hostaddr		bge_addr;
+#ifdef __LITTLE_ENDIAN
+	volatile uint16_t		bge_len;
+	volatile uint16_t		bge_idx;
+	volatile uint16_t		bge_flags;
+	volatile uint16_t		bge_type;
+	volatile uint16_t		bge_tcp_udp_csum;
+	volatile uint16_t		bge_ip_csum;
+	volatile uint16_t		bge_vlan_tag;
+	volatile uint16_t		bge_error_flag;
+#else
+	volatile uint16_t		bge_idx;
+	volatile uint16_t		bge_len;
+	volatile uint16_t		bge_type;
+	volatile uint16_t		bge_flags;
+	volatile uint16_t		bge_ip_csum;
+	volatile uint16_t		bge_tcp_udp_csum;
+	volatile uint16_t		bge_error_flag;
+	volatile uint16_t		bge_vlan_tag;
+#endif
+	volatile uint32_t		bge_rsvd;
+	volatile uint32_t		bge_opaque;
+};
+
+struct bge_extrx_bd {
+	volatile bge_hostaddr		bge_addr1;
+	volatile bge_hostaddr		bge_addr2;
+	volatile bge_hostaddr		bge_addr3;
+#ifdef __LITTLE_ENDIAN
+	volatile uint16_t		bge_len2;
+	volatile uint16_t		bge_len1;
+	volatile uint16_t		bge_rsvd1;
+	volatile uint16_t		bge_len3;
+#else
+	volatile uint16_t		bge_len1;
+	volatile uint16_t		bge_len2;
+	volatile uint16_t		bge_len3;
+	volatile uint16_t		bge_rsvd1;
+#endif
+	volatile bge_hostaddr		bge_addr0;
+#ifdef __LITTLE_ENDIAN
+	volatile uint16_t		bge_len0;
+	volatile uint16_t		bge_idx;
+	volatile uint16_t		bge_flags;
+	volatile uint16_t		bge_type;
+	volatile uint16_t		bge_tcp_udp_csum;
+	volatile uint16_t		bge_ip_csum;
+	volatile uint16_t		bge_vlan_tag;
+	volatile uint16_t		bge_error_flag;
+#else
+	volatile uint16_t		bge_idx;
+	volatile uint16_t		bge_len0;
+	volatile uint16_t		bge_type;
+	volatile uint16_t		bge_flags;
+	volatile uint16_t		bge_ip_csum;
+	volatile uint16_t		bge_tcp_udp_csum;
+	volatile uint16_t		bge_error_flag;
+	volatile uint16_t		bge_vlan_tag;
+#endif
+	volatile uint32_t		bge_rsvd0;
+	volatile uint32_t		bge_opaque;
+};
+
+#define	BGE_RXBDFLAG_END		0x0004
+#define	BGE_RXBDFLAG_JUMBO_RING		0x0020
+#define	BGE_RXBDFLAG_VLAN_TAG		0x0040
+#define	BGE_RXBDFLAG_ERROR		0x0400
+#define	BGE_RXBDFLAG_MINI_RING		0x0800
+#define	BGE_RXBDFLAG_IP_CSUM		0x1000
+#define	BGE_RXBDFLAG_TCP_UDP_CSUM	0x2000
+#define	BGE_RXBDFLAG_TCP_UDP_IS_TCP	0x4000
+#define	BGE_RXBDFLAG_IPV6		0x8000
+
+#define	BGE_RXERRFLAG_BAD_CRC		0x0001
+#define	BGE_RXERRFLAG_COLL_DETECT	0x0002
+#define	BGE_RXERRFLAG_LINK_LOST		0x0004
+#define	BGE_RXERRFLAG_PHY_DECODE_ERR	0x0008
+#define	BGE_RXERRFLAG_MAC_ABORT		0x0010
+#define	BGE_RXERRFLAG_RUNT		0x0020
+#define	BGE_RXERRFLAG_TRUNC_NO_RSRCS	0x0040
+#define	BGE_RXERRFLAG_GIANT		0x0080
+#define	BGE_RXERRFLAG_IP_CSUM_NOK	0x1000	/* 5717 */
+
+struct bge_sts_idx {
+#ifdef __LITTLE_ENDIAN
+	volatile uint16_t		bge_rx_prod_idx;
+	volatile uint16_t		bge_tx_cons_idx;
+#else
+	volatile uint16_t		bge_tx_cons_idx;
+	volatile uint16_t		bge_rx_prod_idx;
+#endif
+};
+
+struct bge_status_block {
+	volatile uint32_t		bge_status;
+	volatile uint32_t		bge_status_tag;
+#ifdef __LITTLE_ENDIAN
+	volatile uint16_t		bge_rx_jumbo_cons_idx;
+	volatile uint16_t		bge_rx_std_cons_idx;
+	volatile uint16_t		bge_rx_mini_cons_idx;
+	volatile uint16_t		bge_rsvd1;
+#else
+	volatile uint16_t		bge_rx_std_cons_idx;
+	volatile uint16_t		bge_rx_jumbo_cons_idx;
+	volatile uint16_t		bge_rsvd1;
+	volatile uint16_t		bge_rx_mini_cons_idx;
+#endif
+	volatile struct bge_sts_idx	bge_idx[16];
+};
+
+#define	BGE_STATFLAG_UPDATED		0x00000001
+#define	BGE_STATFLAG_LINKSTATE_CHANGED	0x00000002
+#define	BGE_STATFLAG_ERROR		0x00000004
+
+
+/*
+ * Broadcom Vendor ID
+ * (Note: the BCM570x still defaults to the Alteon PCI vendor ID
+ * even though they're now manufactured by Broadcom)
+ */
+#define	BCOM_VENDORID			0x14E4
+#define	BCOM_DEVICEID_BCM5700		0x1644
+#define	BCOM_DEVICEID_BCM5701		0x1645
+#define	BCOM_DEVICEID_BCM5702		0x1646
+#define	BCOM_DEVICEID_BCM5702X		0x16A6
+#define	BCOM_DEVICEID_BCM5702_ALT	0x16C6
+#define	BCOM_DEVICEID_BCM5703		0x1647
+#define	BCOM_DEVICEID_BCM5703X		0x16A7
+#define	BCOM_DEVICEID_BCM5703_ALT	0x16C7
+#define	BCOM_DEVICEID_BCM5704C		0x1648
+#define	BCOM_DEVICEID_BCM5704S		0x16A8
+#define	BCOM_DEVICEID_BCM5704S_ALT	0x1649
+#define	BCOM_DEVICEID_BCM5705		0x1653
+#define	BCOM_DEVICEID_BCM5705K		0x1654
+#define	BCOM_DEVICEID_BCM5705F		0x166E
+#define	BCOM_DEVICEID_BCM5705M		0x165D
+#define	BCOM_DEVICEID_BCM5705M_ALT	0x165E
+#define	BCOM_DEVICEID_BCM5714C		0x1668
+#define	BCOM_DEVICEID_BCM5714S		0x1669
+#define	BCOM_DEVICEID_BCM5715		0x1678
+#define	BCOM_DEVICEID_BCM5715S		0x1679
+#define	BCOM_DEVICEID_BCM5717		0x1655
+#define	BCOM_DEVICEID_BCM5718		0x1656
+#define	BCOM_DEVICEID_BCM5719		0x1657
+#define	BCOM_DEVICEID_BCM5720_PP	0x1658	/* Not released to public. */
+#define	BCOM_DEVICEID_BCM5720		0x165F
+#define	BCOM_DEVICEID_BCM5721		0x1659
+#define	BCOM_DEVICEID_BCM5722		0x165A
+#define	BCOM_DEVICEID_BCM5723		0x165B
+#define	BCOM_DEVICEID_BCM5725		0x1643
+#define	BCOM_DEVICEID_BCM5727		0x16F3
+#define	BCOM_DEVICEID_BCM5750		0x1676
+#define	BCOM_DEVICEID_BCM5750M		0x167C
+#define	BCOM_DEVICEID_BCM5751		0x1677
+#define	BCOM_DEVICEID_BCM5751F		0x167E
+#define	BCOM_DEVICEID_BCM5751M		0x167D
+#define	BCOM_DEVICEID_BCM5752		0x1600
+#define	BCOM_DEVICEID_BCM5752M		0x1601
+#define	BCOM_DEVICEID_BCM5753		0x16F7
+#define	BCOM_DEVICEID_BCM5753F		0x16FE
+#define	BCOM_DEVICEID_BCM5753M		0x16FD
+#define	BCOM_DEVICEID_BCM5754		0x167A
+#define	BCOM_DEVICEID_BCM5754M		0x1672
+#define	BCOM_DEVICEID_BCM5755		0x167B
+#define	BCOM_DEVICEID_BCM5755M		0x1673
+#define	BCOM_DEVICEID_BCM5756		0x1674
+#define	BCOM_DEVICEID_BCM5761		0x1681
+#define	BCOM_DEVICEID_BCM5761E		0x1680
+#define	BCOM_DEVICEID_BCM5761S		0x1688
+#define	BCOM_DEVICEID_BCM5761SE		0x1689
+#define	BCOM_DEVICEID_BCM5762		0x1687
+#define	BCOM_DEVICEID_BCM5764		0x1684
+#define	BCOM_DEVICEID_BCM5780		0x166A
+#define	BCOM_DEVICEID_BCM5780S		0x166B
+#define	BCOM_DEVICEID_BCM5781		0x16DD
+#define	BCOM_DEVICEID_BCM5782		0x1696
+#define	BCOM_DEVICEID_BCM5784		0x1698
+#define	BCOM_DEVICEID_BCM5785F		0x16a0
+#define	BCOM_DEVICEID_BCM5785G		0x1699
+#define	BCOM_DEVICEID_BCM5786		0x169A
+#define	BCOM_DEVICEID_BCM5787		0x169B
+#define	BCOM_DEVICEID_BCM5787M		0x1693
+#define	BCOM_DEVICEID_BCM5787F		0x167f
+#define	BCOM_DEVICEID_BCM5788		0x169C
+#define	BCOM_DEVICEID_BCM5789		0x169D
+#define	BCOM_DEVICEID_BCM5901		0x170D
+#define	BCOM_DEVICEID_BCM5901A2		0x170E
+#define	BCOM_DEVICEID_BCM5903M		0x16FF
+#define	BCOM_DEVICEID_BCM5906		0x1712
+#define	BCOM_DEVICEID_BCM5906M		0x1713
+#define	BCOM_DEVICEID_BCM57760		0x1690
+#define	BCOM_DEVICEID_BCM57761		0x16B0
+#define	BCOM_DEVICEID_BCM57762		0x1682
+#define	BCOM_DEVICEID_BCM57764		0x1642
+#define	BCOM_DEVICEID_BCM57765		0x16B4
+#define	BCOM_DEVICEID_BCM57766		0x1686
+#define	BCOM_DEVICEID_BCM57767		0x1683
+#define	BCOM_DEVICEID_BCM57780		0x1692
+#define	BCOM_DEVICEID_BCM57781		0x16B1
+#define	BCOM_DEVICEID_BCM57782		0x16B7
+#define	BCOM_DEVICEID_BCM57785		0x16B5
+#define	BCOM_DEVICEID_BCM57786		0x16B3
+#define	BCOM_DEVICEID_BCM57787		0x1641
+#define	BCOM_DEVICEID_BCM57788		0x1691
+#define	BCOM_DEVICEID_BCM57790		0x1694
+#define	BCOM_DEVICEID_BCM57791		0x16B2
+#define	BCOM_DEVICEID_BCM57795		0x16B6
+
+/*
+ * Alteon AceNIC PCI vendor/device ID.
+ */
+#define	ALTEON_VENDORID			0x12AE
+#define	ALTEON_DEVICEID_ACENIC		0x0001
+#define	ALTEON_DEVICEID_ACENIC_COPPER	0x0002
+#define	ALTEON_DEVICEID_BCM5700		0x0003
+#define	ALTEON_DEVICEID_BCM5701		0x0004
+
+/*
+ * 3Com 3c996 PCI vendor/device ID.
+ */
+#define	TC_VENDORID			0x10B7
+#define	TC_DEVICEID_3C996		0x0003
+
+/*
+ * SysKonnect PCI vendor ID
+ */
+#define	SK_VENDORID			0x1148
+#define	SK_DEVICEID_ALTIMA		0x4400
+#define	SK_SUBSYSID_9D21		0x4421
+#define	SK_SUBSYSID_9D41		0x4441
+
+/*
+ * Altima PCI vendor/device ID.
+ */
+#define	ALTIMA_VENDORID			0x173b
+#define	ALTIMA_DEVICE_AC1000		0x03e8
+#define	ALTIMA_DEVICE_AC1002		0x03e9
+#define	ALTIMA_DEVICE_AC9100		0x03ea
+
+/*
+ * Dell PCI vendor ID
+ */
+
+#define	DELL_VENDORID			0x1028
+
+/*
+ * Apple PCI vendor ID.
+ */
+#define	APPLE_VENDORID			0x106b
+#define	APPLE_DEVICE_BCM5701		0x1645
+
+/*
+ * Sun PCI vendor ID
+ */
+#define	SUN_VENDORID			0x108e
+
+/*
+ * Fujitsu vendor/device IDs
+ */
+#define	FJTSU_VENDORID			0x10cf
+#define	FJTSU_DEVICEID_PW008GE5		0x11a1
+#define	FJTSU_DEVICEID_PW008GE4		0x11a2
+#define	FJTSU_DEVICEID_PP250450		0x11cc		/* PRIMEPOWER250/450 LAN */
+
+/*
+ * Offset of MAC address inside EEPROM.
+ */
+#define	BGE_EE_MAC_OFFSET		0x7C
+#define	BGE_EE_MAC_OFFSET_5906		0x10
+#define	BGE_EE_HWCFG_OFFSET		0xC8
+
+#define	BGE_HWCFG_VOLTAGE		0x00000003
+#define	BGE_HWCFG_PHYLED_MODE		0x0000000C
+#define	BGE_HWCFG_MEDIA			0x00000030
+#define	BGE_HWCFG_ASF			0x00000080
+
+#define	BGE_VOLTAGE_1POINT3		0x00000000
+#define	BGE_VOLTAGE_1POINT8		0x00000001
+
+#define	BGE_PHYLEDMODE_UNSPEC		0x00000000
+#define	BGE_PHYLEDMODE_TRIPLELED	0x00000004
+#define	BGE_PHYLEDMODE_SINGLELED	0x00000008
+
+#define	BGE_MEDIA_UNSPEC		0x00000000
+#define	BGE_MEDIA_COPPER		0x00000010
+#define	BGE_MEDIA_FIBER			0x00000020
+
+#define	BGE_TICKS_PER_SEC		1000000
+
+/*
+ * Ring size constants.
+ */
+#define	BGE_EVENT_RING_CNT	256
+#define	BGE_CMD_RING_CNT	64
+#define	BGE_STD_RX_RING_CNT	512
+#define	BGE_JUMBO_RX_RING_CNT	256
+#define	BGE_MINI_RX_RING_CNT	1024
+#define	BGE_RETURN_RING_CNT	1024
+
+/* 5705 has smaller return ring size */
+
+#define	BGE_RETURN_RING_CNT_5705	512
+
+/*
+ * Possible TX ring sizes.
+ */
+#define	BGE_TX_RING_CNT_128	128
+#define	BGE_TX_RING_BASE_128	0x3800
+
+#define	BGE_TX_RING_CNT_256	256
+#define	BGE_TX_RING_BASE_256	0x3000
+
+#define	BGE_TX_RING_CNT_512	512
+#define	BGE_TX_RING_BASE_512	0x2000
+
+#define	BGE_TX_RING_CNT		BGE_TX_RING_CNT_512
+#define	BGE_TX_RING_BASE	BGE_TX_RING_BASE_512
+
+/*
+ * Tigon III statistics counters.
+ */
+/* Statistics maintained MAC Receive block. */
+struct bge_rx_mac_stats {
+	bge_hostaddr		ifHCInOctets;
+	bge_hostaddr		Reserved1;
+	bge_hostaddr		etherStatsFragments;
+	bge_hostaddr		ifHCInUcastPkts;
+	bge_hostaddr		ifHCInMulticastPkts;
+	bge_hostaddr		ifHCInBroadcastPkts;
+	bge_hostaddr		dot3StatsFCSErrors;
+	bge_hostaddr		dot3StatsAlignmentErrors;
+	bge_hostaddr		xonPauseFramesReceived;
+	bge_hostaddr		xoffPauseFramesReceived;
+	bge_hostaddr		macControlFramesReceived;
+	bge_hostaddr		xoffStateEntered;
+	bge_hostaddr		dot3StatsFramesTooLong;
+	bge_hostaddr		etherStatsJabbers;
+	bge_hostaddr		etherStatsUndersizePkts;
+	bge_hostaddr		inRangeLengthError;
+	bge_hostaddr		outRangeLengthError;
+	bge_hostaddr		etherStatsPkts64Octets;
+	bge_hostaddr		etherStatsPkts65Octetsto127Octets;
+	bge_hostaddr		etherStatsPkts128Octetsto255Octets;
+	bge_hostaddr		etherStatsPkts256Octetsto511Octets;
+	bge_hostaddr		etherStatsPkts512Octetsto1023Octets;
+	bge_hostaddr		etherStatsPkts1024Octetsto1522Octets;
+	bge_hostaddr		etherStatsPkts1523Octetsto2047Octets;
+	bge_hostaddr		etherStatsPkts2048Octetsto4095Octets;
+	bge_hostaddr		etherStatsPkts4096Octetsto8191Octets;
+	bge_hostaddr		etherStatsPkts8192Octetsto9022Octets;
+};
+
+
+/* Statistics maintained MAC Transmit block. */
+struct bge_tx_mac_stats {
+	bge_hostaddr		ifHCOutOctets;
+	bge_hostaddr		Reserved2;
+	bge_hostaddr		etherStatsCollisions;
+	bge_hostaddr		outXonSent;
+	bge_hostaddr		outXoffSent;
+	bge_hostaddr		flowControlDone;
+	bge_hostaddr		dot3StatsInternalMacTransmitErrors;
+	bge_hostaddr		dot3StatsSingleCollisionFrames;
+	bge_hostaddr		dot3StatsMultipleCollisionFrames;
+	bge_hostaddr		dot3StatsDeferredTransmissions;
+	bge_hostaddr		Reserved3;
+	bge_hostaddr		dot3StatsExcessiveCollisions;
+	bge_hostaddr		dot3StatsLateCollisions;
+	bge_hostaddr		dot3Collided2Times;
+	bge_hostaddr		dot3Collided3Times;
+	bge_hostaddr		dot3Collided4Times;
+	bge_hostaddr		dot3Collided5Times;
+	bge_hostaddr		dot3Collided6Times;
+	bge_hostaddr		dot3Collided7Times;
+	bge_hostaddr		dot3Collided8Times;
+	bge_hostaddr		dot3Collided9Times;
+	bge_hostaddr		dot3Collided10Times;
+	bge_hostaddr		dot3Collided11Times;
+	bge_hostaddr		dot3Collided12Times;
+	bge_hostaddr		dot3Collided13Times;
+	bge_hostaddr		dot3Collided14Times;
+	bge_hostaddr		dot3Collided15Times;
+	bge_hostaddr		ifHCOutUcastPkts;
+	bge_hostaddr		ifHCOutMulticastPkts;
+	bge_hostaddr		ifHCOutBroadcastPkts;
+	bge_hostaddr		dot3StatsCarrierSenseErrors;
+	bge_hostaddr		ifOutDiscards;
+	bge_hostaddr		ifOutErrors;
+};
+
+/* Stats counters access through registers */
+struct bge_mac_stats {
+	/* TX MAC statistics */
+	uint64_t		ifHCOutOctets;
+	uint64_t		Reserved0;
+	uint64_t		etherStatsCollisions;
+	uint64_t		outXonSent;
+	uint64_t		outXoffSent;
+	uint64_t		Reserved1;
+	uint64_t		dot3StatsInternalMacTransmitErrors;
+	uint64_t		dot3StatsSingleCollisionFrames;
+	uint64_t		dot3StatsMultipleCollisionFrames;
+	uint64_t		dot3StatsDeferredTransmissions;
+	uint64_t		Reserved2;
+	uint64_t		dot3StatsExcessiveCollisions;
+	uint64_t		dot3StatsLateCollisions;
+	uint64_t		Reserved3[14];
+	uint64_t		ifHCOutUcastPkts;
+	uint64_t		ifHCOutMulticastPkts;
+	uint64_t		ifHCOutBroadcastPkts;
+	uint64_t		Reserved4[2];
+	/* RX MAC statistics */
+	uint64_t		ifHCInOctets;
+	uint64_t		Reserved5;
+	uint64_t		etherStatsFragments;
+	uint64_t		ifHCInUcastPkts;
+	uint64_t		ifHCInMulticastPkts;
+	uint64_t		ifHCInBroadcastPkts;
+	uint64_t		dot3StatsFCSErrors;
+	uint64_t		dot3StatsAlignmentErrors;
+	uint64_t		xonPauseFramesReceived;
+	uint64_t		xoffPauseFramesReceived;
+	uint64_t		macControlFramesReceived;
+	uint64_t		xoffStateEntered;
+	uint64_t		dot3StatsFramesTooLong;
+	uint64_t		etherStatsJabbers;
+	uint64_t		etherStatsUndersizePkts;
+	/* Receive List Placement control */
+	uint64_t		FramesDroppedDueToFilters;
+	uint64_t		DmaWriteQueueFull;
+	uint64_t		DmaWriteHighPriQueueFull;
+	uint64_t		NoMoreRxBDs;
+	uint64_t		InputDiscards;
+	uint64_t		InputErrors;
+	uint64_t		RecvThresholdHit;
+};
+
+struct bge_stats {
+	uint8_t		Reserved0[256];
+
+	/* Statistics maintained by Receive MAC. */
+	struct bge_rx_mac_stats rxstats;
+
+	bge_hostaddr		Unused1[37];
+
+	/* Statistics maintained by Transmit MAC. */
+	struct bge_tx_mac_stats txstats;
+
+	bge_hostaddr		Unused2[31];
+
+	/* Statistics maintained by Receive List Placement. */
+	bge_hostaddr		COSIfHCInPkts[16];
+	bge_hostaddr		COSFramesDroppedDueToFilters;
+	bge_hostaddr		nicDmaWriteQueueFull;
+	bge_hostaddr		nicDmaWriteHighPriQueueFull;
+	bge_hostaddr		nicNoMoreRxBDs;
+	bge_hostaddr		ifInDiscards;
+	bge_hostaddr		ifInErrors;
+	bge_hostaddr		nicRecvThresholdHit;
+
+	bge_hostaddr		Unused3[9];
+
+	/* Statistics maintained by Send Data Initiator. */
+	bge_hostaddr		COSIfHCOutPkts[16];
+	bge_hostaddr		nicDmaReadQueueFull;
+	bge_hostaddr		nicDmaReadHighPriQueueFull;
+	bge_hostaddr		nicSendDataCompQueueFull;
+
+	/* Statistics maintained by Host Coalescing. */
+	bge_hostaddr		nicRingSetSendProdIndex;
+	bge_hostaddr		nicRingStatusUpdate;
+	bge_hostaddr		nicInterrupts;
+	bge_hostaddr		nicAvoidedInterrupts;
+	bge_hostaddr		nicSendThresholdHit;
+
+	uint8_t		Reserved4[320];
+};
+
+/*
+ * Tigon general information block. This resides in host memory
+ * and contains the status counters, ring control blocks and
+ * producer pointers.
+ */
+
+struct bge_gib {
+	struct bge_stats	bge_stats;
+	struct bge_rcb		bge_tx_rcb[16];
+	struct bge_rcb		bge_std_rx_rcb;
+	struct bge_rcb		bge_jumbo_rx_rcb;
+	struct bge_rcb		bge_mini_rx_rcb;
+	struct bge_rcb		bge_return_rcb;
+};
+
+#define	BGE_FRAMELEN		1518
+#define	BGE_MAX_FRAMELEN	1536
+#define	BGE_JUMBO_FRAMELEN	9018
+#define	BGE_JUMBO_MTU		(BGE_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
+#define	BGE_MIN_FRAMELEN		60
+
+/*
+ * Other utility macros.
+ */
+#define	BGE_INC(x, y)	(x) = (x + 1) % y
+
+/*
+ * BAR0 MAC register access macros. The Tigon always uses memory mapped register
+ * accesses and all registers must be accessed with 32 bit operations.
+ */
+#if 1
+#define CSR_WRITE_4(sc, reg, val) \
+	({ bus_write_4(sc->bge_res, reg, val); udelay(10); })
+#define CSR_READ_4(sc, reg) \
+	({ u32 val = bus_read_4(sc->bge_res, reg); udelay(10); val; })
+#else
+#define CSR_WRITE_4(sc, reg, val)	\
+	bus_write_4(sc->bge_res, reg, val)
+#define CSR_READ_4(sc, reg)		\
+	bus_read_4(sc->bge_res, reg)
+#endif
+
+#define	BGE_SETBIT(sc, reg, x)			\
+do {						\
+	u32 val = CSR_READ_4(sc, reg) | (x);	\
+	CSR_WRITE_4(sc, reg, val);		\
+} while (0)
+
+#define	BGE_CLRBIT(sc, reg, x)			\
+do {						\
+	u32 val = CSR_READ_4(sc, reg) & ~(x);	\
+	CSR_WRITE_4(sc, reg, val);		\
+} while (0)
+
+/* BAR2 APE register access macros. */
+#define	APE_WRITE_4(sc, reg, val)	\
+	bus_write_4(sc->bge_res2, reg, val)
+
+#define	APE_READ_4(sc, reg)		\
+	bus_read_4(sc->bge_res2, reg)
+
+#define	APE_SETBIT(sc, reg, x)	\
+	APE_WRITE_4(sc, reg, (APE_READ_4(sc, reg) | (x)))
+#define	APE_CLRBIT(sc, reg, x)	\
+	APE_WRITE_4(sc, reg, (APE_READ_4(sc, reg) & ~(x)))
+
+#define	PCI_SETBIT(dev, reg, x, s)	\
+	pci_write_config(dev, reg, (pci_read_config(dev, reg, s) | (x)), s)
+#define	PCI_CLRBIT(dev, reg, x, s)	\
+	pci_write_config(dev, reg, (pci_read_config(dev, reg, s) & ~(x)), s)
+
+/*
+ * Memory management stuff.
+ */
+
+#define	BGE_NSEG_JUMBO	4
+#define	BGE_NSEG_NEW	32
+#define	BGE_TSOSEG_SZ	4096
+
+/* Maximum DMA address for controllers that have 40bit DMA address bug. */
+#if (BUS_SPACE_MAXADDR < 0xFFFFFFFFFF)
+#define	BGE_DMA_MAXADDR		BUS_SPACE_MAXADDR
+#else
+#define	BGE_DMA_MAXADDR		0xFFFFFFFFFF
+#endif
+
+/*
+ * Ring structures. Most of these reside in host memory and we tell
+ * the NIC where they are via the ring control blocks. The exceptions
+ * are the tx and command rings, which live in NIC memory and which
+ * we access via the shared memory window.
+ */
+
+struct bge_ring_data {
+	struct bge_rx_bd	*bge_rx_std_ring;
+	phys_addr_t		bge_rx_std_ring_paddr;
+	struct bge_extrx_bd	*bge_rx_jumbo_ring;
+	phys_addr_t		bge_rx_jumbo_ring_paddr;
+	struct bge_rx_bd	*bge_rx_return_ring;
+	phys_addr_t		bge_rx_return_ring_paddr;
+	struct bge_tx_bd 	*bge_tx_ring;
+	phys_addr_t		bge_tx_ring_paddr;
+	struct bge_status_block	*bge_status_block;
+	phys_addr_t		bge_status_block_paddr;
+	struct bge_stats	*bge_stats;
+	phys_addr_t		bge_stats_paddr;
+	struct bge_gib		bge_info;
+};
+
+#define	BGE_STD_RX_RING_SZ	\
+	(sizeof(struct bge_rx_bd) * BGE_STD_RX_RING_CNT)
+#define	BGE_JUMBO_RX_RING_SZ	\
+	(sizeof(struct bge_extrx_bd) * BGE_JUMBO_RX_RING_CNT)
+#define	BGE_TX_RING_SZ		\
+	(sizeof(struct bge_tx_bd) * BGE_TX_RING_CNT)
+#define	BGE_RX_RTN_RING_SZ(x)	\
+	(sizeof(struct bge_rx_bd) * x->bge_return_ring_cnt)
+
+#define	BGE_STATUS_BLK_SZ	sizeof (struct bge_status_block)
+
+#define	BGE_STATS_SZ		sizeof (struct bge_stats)
+
+/*
+ * Mbuf pointers. We need these to keep track of the virtual addresses
+ * of our mbuf chains since we can only convert from physical to virtual,
+ * not the other way around.
+ */
+struct bge_chain_data {
+	void	*bge_rx_std_chain[BGE_STD_RX_RING_CNT];
+	void	*bge_rx_jumbo_chain[BGE_JUMBO_RX_RING_CNT];
+	int	bge_rx_std_seglen[BGE_STD_RX_RING_CNT];
+};
+
+#define	BGE_HWREV_TIGON		0x01
+#define	BGE_HWREV_TIGON_II	0x02
+#define	BGE_TIMEOUT		100000
+#define	BGE_TXCONS_UNSET	0xFFFF	/* impossible value */
+#define	BGE_TX_TIMEOUT		5
+
+#define	ASF_ENABLE		1
+#define	ASF_NEW_HANDSHAKE	2
+#define	ASF_STACKUP		4
+
+struct bge_softc {
+	struct eth_device	bge_eth;
+	struct phy_device	*bge_phydev;
+	device_t		bge_dev;
+	void __iomem		*bge_res;	/* MAC mapped I/O */
+	void __iomem		*bge_res2;	/* APE mapped I/O */
+	int			bge_expcap;
+	int			bge_expmrq;
+	int			bge_msicap;
+	int			bge_pcixcap;
+	uint32_t		bge_flags;
+#define	BGE_FLAG_TBI		0x00000001
+#define	BGE_FLAG_JUMBO		0x00000002
+#define	BGE_FLAG_JUMBO_STD	0x00000004
+#define	BGE_FLAG_EADDR		0x00000008
+#define	BGE_FLAG_MII_SERDES	0x00000010
+#define	BGE_FLAG_CPMU_PRESENT	0x00000020
+#define	BGE_FLAG_TAGGED_STATUS	0x00000040
+#define	BGE_FLAG_APE		0x00000080
+#define	BGE_FLAG_MSI		0x00000100
+#define	BGE_FLAG_PCIX		0x00000200
+#define	BGE_FLAG_PCIE		0x00000400
+#define	BGE_FLAG_TSO		0x00000800
+#define	BGE_FLAG_TSO3		0x00001000
+#define	BGE_FLAG_JUMBO_FRAME	0x00002000
+#define	BGE_FLAG_5700_FAMILY	0x00010000
+#define	BGE_FLAG_5705_PLUS	0x00020000
+#define	BGE_FLAG_5714_FAMILY	0x00040000
+#define	BGE_FLAG_575X_PLUS	0x00080000
+#define	BGE_FLAG_5755_PLUS	0x00100000
+#define	BGE_FLAG_5788		0x00200000
+#define	BGE_FLAG_5717_PLUS	0x00400000
+#define	BGE_FLAG_57765_PLUS	0x00800000
+#define	BGE_FLAG_40BIT_BUG	0x01000000
+#define	BGE_FLAG_4G_BNDRY_BUG	0x02000000
+#define	BGE_FLAG_RX_ALIGNBUG	0x04000000
+#define	BGE_FLAG_SHORT_DMA_BUG	0x08000000
+#define	BGE_FLAG_4K_RDMA_BUG	0x10000000
+#define	BGE_FLAG_MBOX_REORDER	0x20000000
+#define	BGE_FLAG_RDMA_BUG	0x40000000
+	uint32_t		bge_mfw_flags;	/* Management F/W flags */
+#define	BGE_MFW_ON_RXCPU	0x00000001
+#define	BGE_MFW_ON_APE		0x00000002
+#define	BGE_MFW_TYPE_NCSI	0x00000004
+#define	BGE_MFW_TYPE_DASH	0x00000008
+	int			bge_phy_ape_lock;
+	int			bge_func_addr;
+	int			bge_phy_addr;
+	uint32_t		bge_phy_flags;
+#define	BGE_PHY_NO_WIRESPEED	0x00000001
+#define	BGE_PHY_ADC_BUG		0x00000002
+#define	BGE_PHY_5704_A0_BUG	0x00000004
+#define	BGE_PHY_JITTER_BUG	0x00000008
+#define	BGE_PHY_BER_BUG		0x00000010
+#define	BGE_PHY_ADJUST_TRIM	0x00000020
+#define	BGE_PHY_CRC_BUG		0x00000040
+#define	BGE_PHY_NO_3LED		0x00000080
+	uint32_t		bge_chipid;
+	uint32_t		bge_asicrev;
+	uint32_t		bge_chiprev;
+	uint8_t			bge_asf_mode;
+	uint8_t			bge_asf_count;
+	uint16_t		bge_mps;
+	void			*dma_area;
+	struct bge_ring_data	bge_ldata;	/* rings */
+	struct bge_chain_data	bge_cdata;	/* mbufs */
+	uint16_t		bge_tx_saved_considx;
+	uint16_t		bge_rx_saved_considx;
+	uint16_t		bge_return_ring_cnt;
+	uint16_t		bge_std;	/* current std ring head */
+	uint16_t		bge_jumbo;	/* current jumo ring head */
+	uint32_t		bge_tx_prodidx;
+	uint32_t		bge_mi_mode;
+	int			bge_txcnt;
+};
diff --git a/include/netdev.h b/include/netdev.h
index 47fa80d..5391d45 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -32,6 +32,7 @@  int at91emac_register(bd_t *bis, unsigned long iobase);
int au1x00_enet_initialize(bd_t*);
int ax88180_initialize(bd_t *bis);
int bfin_EMAC_initialize(bd_t *bis);
+int bge_register(bd_t *bis);
int calxedaxgmac_initialize(u32 id, ulong base_addr);
int cs8900_initialize(u8 dev_num, int base_addr);
int davinci_emac_initialize(void);
@@ -138,6 +139,9 @@  static inline int pci_eth_init(bd_t *bis)
#if defined(CONFIG_ULI526X)
 	num += uli526x_initialize(bis);
#endif
+#if defined(CONFIG_BGE_ETH)
+	num += bge_register(bis);
+#endif

#endif  /* CONFIG_PCI */
 	return num;