Subject: Re: patch for if_bge.c
To: None <andreas@planix.com>
From: SAITOH Masanobu <masanobu@iij.ad.jp>
List: current-users
Date: 09/27/2007 09:26:35
----Next_Part(Thu_Sep_27_09_26_35_2007_122)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit


 BTW, I made a jumbo patch for netbsd-3.


----Next_Part(Thu_Sep_27_09_26_35_2007_122)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="bgefornetbsd-3.dif"

sys/dev/pci/if_bge.c				1.89,1.95,1.97,1.101,1.103,
						1.105,1.107,1.117-1.122,
						1.128-1.131,1.133-1.135
						via patch
sys/dev/pci/if_bgereg.h				1.31,1.34-1.39,1.42-1.43
sys/dev/pci/pcidevs				patch
sys/dev/pci/pcidevs.h				regen
sys/dev/pci/pcidevs_data			regen


	Some cleanups(typo, whitespace, debug message).
	Add TSO support to bge(4)
	Add support for BCM5715, BCM5752M, BCM5754, BCM5755, BCM5786 and 5787.
	Add support for BCM5789. Fixes PR/33828 from Pawel Chwalowskibg.
	Add support for BCM5753 and BCM5753M Fixes PR kern/36139 from
	Mustafa Dogan.
	Add and fix some BGE_CHIPIDs. From FreeBSD and OpenBSD.
	In bge_ioctl(), don't call bge_init() if the interface is already up
	(Makes ifwatchd work on this interface).
	BCM5701 B2 requires BGE_QUIRK_ONLY_PHY_1 quirk. From Brian Baird in
	PR kern/23778.
	Move TX ring full sanity check further up and check the number of DMA
	segments from the DMA map, instead of counting the DMA segments in the
	for loop and breaking out later.
	Unload the DMA map if encountering an error condition.
	Fix a NULL reference on failing mbuf allocation.
	In bge_start return if IFF_OACTIVE is set in combination with
	IFF_RUNNING, drop obscure check for length of interface queue.
	Remove message about failing bge_encap, it can happen just too easily
	because of full descriptor rings.


Index: pcidevs
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pcidevs,v
retrieving revision 1.701.2.44
diff -u -r1.701.2.44 pcidevs
--- pcidevs	13 Sep 2007 19:47:14 -0000	1.701.2.44
+++ pcidevs	18 Sep 2007 06:58:41 -0000
@@ -1156,42 +1156,65 @@
 product BLUESTEEL 5601		0x5601	5601
 
 /* Broadcom products */
+product BROADCOM BCM5752	0x1600	BCM5752 10/100/1000 Ethernet
+product BROADCOM BCM5752M	0x1601	BCM5752M 10/100/1000 Ethernet
+product BROADCOM BCM5709	0x1639	BCM5709 NetXtreme II 1000baseT Ethernet
 product BROADCOM BCM5700	0x1644	BCM5700 10/100/1000 Ethernet
 product BROADCOM BCM5701	0x1645	BCM5701 10/100/1000 Ethernet
 product BROADCOM BCM5702	0x1646	BCM5702 10/100/1000 Ethernet
-product BROADCOM BCM5702X	0x16a6	BCM5702X 10/100/1000 Ethernet
-product BROADCOM BCM5702FE	0x164d	BCM5702FE 10/100 Ethernet
 product BROADCOM BCM5703	0x1647	BCM5703 10/100/1000 Ethernet
-product BROADCOM BCM5703X	0x16a7	BCM5703X 10/100/1000 Ethernet
-product BROADCOM BCM5703A3	0x16c7	BCM5703 10/100/1000 Ethernet
 product BROADCOM BCM5704C	0x1648	BCM5704C 1000baseT Ethernet
+product BROADCOM BCM5704S_ALT	0x1649	BCM5704S 1000baseSX Ethernet
 product BROADCOM BCM5706	0x164a	BCM5706 NetXtreme II 1000baseT Ethernet
 product BROADCOM BCM5708	0x164c	BCM5708 NetXtreme II 1000baseT Ethernet
-product BROADCOM BCM5704S	0x16a8	BCM5704S 1000baseX Ethernet
-product BROADCOM BCM5706S	0x16aa	BCM5706 NetXtreme II 1000baseSX
-product BROADCOM BCM5708S	0x16ac	BCM5708 NetXtreme II 1000baseSX
+product BROADCOM BCM5702FE	0x164d	BCM5702FE 10/100 Ethernet
 product BROADCOM BCM5705	0x1653	BCM5705 10/100/1000 Ethernet
 product BROADCOM BCM5705K	0x1654	BCM5705K 10/100/1000 Ethernet
+product BROADCOM BCM5720	0x1658	BCM5720 NetXtreme 1000baseT Ethernet
+product BROADCOM BCM5721	0x1659	BCM5721 NetXtreme 1000baseT Ethernet
+product BROADCOM BCM5722	0x165a	BCM5722 NetXtreme 1000baseT Ethernet
 product BROADCOM BCM5705M	0x165d	BCM5705M 10/100/1000 Ethernet
-product BROADCOM BCM5705_ALT	0x165e	BCM5705 10/100/1000 Ethernet
-product BROADCOM BCM5714	0x1668	BCM5714 10/100/1000 Ethernet
-product BROADCOM BCM5714S	0x1669	BCM5714S 1000baseX Ethernet
-product BROADCOM BCM5715	0x1678	BCM5715 10/100/1000 Ethernet
-product BROADCOM BCM5715S	0x1679	BCM5715S 1000baseX Ethernet
-product BROADCOM BCM5721	0x1659	BCM5721 10/100/1000 Ethernet
+product BROADCOM BCM5705M_ALT	0x165e	BCM5705M 10/100/1000 Ethernet
+product BROADCOM BCM5714	0x1668	BCM5714 1000baseT Ethernet
+product BROADCOM BCM5714S	0x1669	BCM5714S 1000baseSX Ethernet
+product BROADCOM BCM5780	0x166a	BCM5780 NetXtreme 1000baseT Ethernet
+product BROADCOM BCM5780S	0x166b	BCM5780S NetXtreme 1000baseSX Ethernet
+product BROADCOM BCM5705F	0x166e	BCM5705F 10/100 Ethernet
+product BROADCOM BCM5754M	0x1672	BCM5754M NetXtreme 1000baseT Ethernet
+product BROADCOM BCM5755M	0x1673	BCM5755M NetXtreme 1000baseT Ethernet
+product BROADCOM BCM5756	0x1674	BCM5756 10/100/1000 Ethernet
 product BROADCOM BCM5750	0x1676	BCM5750 10/100/1000 Ethernet
 product BROADCOM BCM5751	0x1677	BCM5751 10/100/1000 Ethernet
-product BROADCOM BCM5752	0x1600	BCM5752 10/100/1000 Ethernet
+product BROADCOM BCM5715	0x1678	BCM5715 1000baseT Ethernet
+product BROADCOM BCM5715S	0x1679	BCM5715S 1000baseSX Ethernet
+product BROADCOM BCM5754	0x167a	BCM5754 10/100/1000 Ethernet
+product BROADCOM BCM5755	0x167b	BCM5755 NetXtreme 1000baseT Ethernet
 product BROADCOM BCM5750M	0x167c	BCM5750M 10/100/1000 Ethernet
 product BROADCOM BCM5751M	0x167d	BCM5751M 10/100/1000 Ethernet
-product BROADCOM BCM5780	0x166a	BCM5780 1000baseT Ethernet
-product BROADCOM BCM5780S	0x166b	BCM5780S 1000baseX Ethernet
+product BROADCOM BCM5751F	0x167e	BCM5751F 10/100/1000 Ethernet
+product BROADCOM BCM5787M	0x1693	BCM5787M 10/100/1000 Ethernet
 product BROADCOM BCM5782	0x1696	BCM5782 10/100/1000 Ethernet
+product BROADCOM BCM5786	0x169a	BCM5786 NetLink 1000baseT Ethernet
+product BROADCOM BCM5787	0x169b	BCM5787 NetLink 1000baseT Ethernet
 product BROADCOM BCM5788	0x169c	BCM5788 10/100/1000 Ethernet
 product BROADCOM BCM5789	0x169d	BCM5789 10/100/1000 Ethernet
+product BROADCOM BCM5702X	0x16a6	BCM5702X 10/100/1000 Ethernet
+product BROADCOM BCM5703X	0x16a7	BCM5703X 10/100/1000 Ethernet
+product BROADCOM BCM5704S	0x16a8	BCM5704S 1000baseSX Ethernet
+product BROADCOM BCM5706S	0x16aa	BCM5706 NetXtreme II 1000baseSX
+product BROADCOM BCM5708S	0x16ac	BCM5708 NetXtreme II 1000baseSX
+product BROADCOM BCM5702_ALT	0x16c6	BCM5702 10/100/1000 Ethernet
+product BROADCOM BCM5703_ALT	0x16c7	BCM5703 10/100/1000 Ethernet
+product BROADCOM BCM5781	0x16dd	BCM5781 10/100/1000 Ethernet
+product BROADCOM BCM5753	0x16f7	BCM5753 10/100/1000 Ethernet
+product BROADCOM BCM5753M	0x16fd	BCM5753M 10/100/1000 Ethernet
+product BROADCOM BCM5753F	0x16fe	BCM5753F 10/100 Ethernet
+product BROADCOM BCM5903M	0x16ff	BCM5903M 10/100/1000 Ethernet
 product BROADCOM BCM4401_B0	0x170c	BCM4401-B0 10/100 Ethernet
 product BROADCOM BCM5901	0x170d	BCM5901 10/100 Ethernet
 product BROADCOM BCM5901A2	0x170e	BCM5901A 10/100 Ethernet
+product BROADCOM BCM5906	0x1712	BCM5906 NetLink Fast Ethernet
+product BROADCOM BCM5906M	0x1713	BCM5906M NetLink Fast Ethernet
 product BROADCOM BCM4401	0x4401	BCM4401 10/100 Ethernet
 product BROADCOM 5801		0x5801	5801 Security processor
 product BROADCOM 5802		0x5802	5802 Security processor
Index: if_bge.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bge.c,v
retrieving revision 1.87.2.6
diff -u -r1.87.2.6 if_bge.c
--- if_bge.c	5 Mar 2007 15:07:14 -0000	1.87.2.6
+++ if_bge.c	18 Sep 2007 06:58:41 -0000
@@ -107,11 +107,11 @@
 #include <netinet/ip.h>
 #endif
 
-/* XXX TSO */
-#include <netinet/in.h>			/* XXX for struct ip */
-#include <netinet/in_systm.h>		/* XXX for struct ip */
-#include <netinet/ip.h>			/* XXX for struct ip */
-#include <netinet/tcp.h>		/* XXX for struct tcphdr */
+/* Headers for TCP  Segmentation Offload (TSO) */
+#include <netinet/in_systm.h>		/* n_time for <netinet/ip.h>... */
+#include <netinet/in.h>			/* ip_{src,dst}, for <netinet/ip.h> */
+#include <netinet/ip.h>			/* for struct ip */
+#include <netinet/tcp.h>		/* for struct tcphdr */
 
 
 #if NBPFILTER > 0
@@ -290,28 +290,28 @@
 
 /*
  * XXX: how to handle variants based on 5750 and derivatives:
- * 5750 5751, 5721, possibly 5714, 5752, and 5708?, which 
+ * 5750 5751, 5721, possibly 5714, 5752, and 5708?, which
  * in general behave like a 5705, except with additional quirks.
  * This driver's current handling of the 5721 is wrong;
  * how we map ASIC revision to "quirks" needs more thought.
  * (defined here until the thought is done).
  */
-#define BGE_IS_5750_OR_BEYOND(sc)  \
-	(BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5750 ||	\
-	 BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5714 ||	\
-	 BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 ||	\
+#define BGE_IS_5714_FAMILY(sc) \
+	(BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5714_A0 || \
 	 BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5780 ||	\
-	 BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5715)
+	 BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5714 )
+
+#define BGE_IS_5750_OR_BEYOND(sc)  \
+	(BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5750 || \
+	 BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 || \
+	 BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 || \
+	 BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787 || \
+	 BGE_IS_5714_FAMILY(sc) )
 
 #define BGE_IS_5705_OR_BEYOND(sc)  \
 	( ((sc)->bge_quirks & BGE_QUIRK_5705_CORE) || \
 	  BGE_IS_5750_OR_BEYOND(sc) )
 
-#define BGE_IS_5714_FAMILY(sc) \
-	 (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5714 ||	\
-	  BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5780 ||	\
-	  BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5715)
-
 
 /* following bugs are common to bcm5700 rev B, all flavours */
 #define BGE_QUIRK_5700_COMMON \
@@ -780,7 +780,7 @@
 
 	state = 4;
 	sc->bge_cdata.bge_jumbo_buf = (caddr_t)kva;
-	DPRINTFN(1,("bge_jumbo_buf = 0x%p\n", sc->bge_cdata.bge_jumbo_buf));
+	DPRINTFN(1,("bge_jumbo_buf = %p\n", sc->bge_cdata.bge_jumbo_buf));
 
 	SLIST_INIT(&sc->bge_jfree_listhead);
 	SLIST_INIT(&sc->bge_jinuse_listhead);
@@ -1179,8 +1179,7 @@
 
 	SLIST_INIT(&sc->txdma_list);
 	for (i = 0; i < BGE_RSLOTS; i++) {
-		if (bus_dmamap_create(sc->bge_dmatag, 
-				      /*ETHER_MAX_LEN_JUMBO*/BGE_TXDMA_MAX,
+		if (bus_dmamap_create(sc->bge_dmatag, BGE_TXDMA_MAX,
 		    BGE_NTXSEG, ETHER_MAX_LEN_JUMBO, 0, BUS_DMA_NOWAIT,
 		    &dmamap))
 			return(ENOBUFS);
@@ -1342,7 +1341,7 @@
 		    (0x2 << BGE_PCIDMARWCTL_WR_WAT_SHIFT));
 
 		/* jonathan: alternative from Linux driver */
-#define DMA_CTRL_WRITE_PCIE_H20MARK_128         0x00180000 
+#define DMA_CTRL_WRITE_PCIE_H20MARK_128         0x00180000
 #define DMA_CTRL_WRITE_PCIE_H20MARK_256         0x00380000
 
 		dma_rw_ctl =   0x76000000; /* XXX XXX XXX */;
@@ -1350,19 +1349,18 @@
 					   BGE_PCI_CONF_DEV_CTRL);
 		DPRINTFN(4, ("%s: pcie mode=0x%x\n", sc->bge_dev.dv_xname, device_ctl));
 
-#if 0
-		if (device_ctl & 0x00e0) {
-		  dma_rw_ctl |= DMA_CTRL_WRITE_PCIE_H20MARK_256;
+		if ((device_ctl & 0x00e0) && 0) {
+			/*
+			 * XXX jonathan@NetBSD.org:
+			 * This clause is exactly what the Broadcom-supplied
+			 * Linux does; but given overall register programming
+			 * by if_bge(4), this larger DMA-write watermark
+			 * value causes bcm5721 chips to totally wedge.
+			 */
+			dma_rw_ctl |= BGE_PCIDMA_RWCTL_PCIE_WRITE_WATRMARK_256;
 		} else {
-		  dma_rw_ctl |= DMA_CTRL_WRITE_PCIE_H20MARK_128;
+			dma_rw_ctl |= BGE_PCIDMA_RWCTL_PCIE_WRITE_WATRMARK_128;
 		}
-#else
-		dma_rw_ctl |= DMA_CTRL_WRITE_PCIE_H20MARK_128;
-#endif
-		aprint_error("%s: PCI-Express DMA setting 0x%8x,"
-			     " expected 0x%08x\n",
-		    sc->bge_dev.dv_xname, dma_rw_ctl,
-			     0x76180000);
 	} else if (pci_conf_read(pa->pa_pc, pa->pa_tag,BGE_PCI_PCISTATE) &
 	    BGE_PCISTATE_PCI_BUSMODE) {
 		/* Conventional PCI bus */
@@ -1396,11 +1394,17 @@
 		else if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5703) {
 			dma_rw_ctl &=  0xfffffff0;
 			dma_rw_ctl |= BGE_PCIDMARWCTL_ONEDMA_ATONCE;
-		} else if (BGE_IS_5714_FAMILY(sc)) {
-			dma_rw_ctl = BGE_PCI_READ_CMD | BGE_PCI_WRITE_CMD |
-			  (1 << 20) | (1 << 18) |
-			  BGE_PCIDMARWCTL_ONEDMA_ATONCE;
-		} 
+		}
+		else if (BGE_IS_5714_FAMILY(sc)) {
+			dma_rw_ctl = BGE_PCI_READ_CMD|BGE_PCI_WRITE_CMD;
+			dma_rw_ctl &= ~BGE_PCIDMARWCTL_ONEDMA_ATONCE; /* XXX */
+			/* XXX magic values, Broadcom-supplied Linux driver */
+			if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5780)
+				dma_rw_ctl |= (1 << 20) | (1 << 18) |
+				  BGE_PCIDMARWCTL_ONEDMA_ATONCE;
+			else
+				dma_rw_ctl |= (1<<20) | (1<<18) | (1 << 15);
+		}
 	}
 
 	pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, dma_rw_ctl);
@@ -1560,22 +1564,20 @@
 	CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10);
 
 	/* Enable buffer manager */
-	{
-		CSR_WRITE_4(sc, BGE_BMAN_MODE,
-		    BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN);
+	CSR_WRITE_4(sc, BGE_BMAN_MODE,
+	    BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN);
 
-		/* Poll for buffer manager start indication */
-		for (i = 0; i < BGE_TIMEOUT; i++) {
-			if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE)
-				break;
-			DELAY(10);
-		}
+	/* Poll for buffer manager start indication */
+	for (i = 0; i < BGE_TIMEOUT; i++) {
+		if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE)
+			break;
+		DELAY(10);
+	}
 
-		if (i == BGE_TIMEOUT) {
-			printf("%s: buffer manager failed to start\n",
-			    sc->bge_dev.dv_xname);
-			return(ENXIO);
-		}
+	if (i == BGE_TIMEOUT) {
+		printf("%s: buffer manager failed to start\n",
+		    sc->bge_dev.dv_xname);
+		return(ENXIO);
 	}
 
 	/* Enable flow-through queues */
@@ -1661,11 +1663,24 @@
 	}
 
 	/*
-	 * Set the BD ring replentish thresholds. The recommended
+	 * Set the BD ring replenish thresholds. The recommended
 	 * values are 1/8th the number of descriptors allocated to
 	 * each ring.
 	 */
-	CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, BGE_STD_RX_RING_CNT/8);
+	i = BGE_STD_RX_RING_CNT / 8;
+
+	/*
+ 	 * Use a value of 8 for the following chips to workaround HW errata.
+	 * Some of these chips have been added based on empirical
+	 * evidence (they don't work unless this is done).
+	 */
+	if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5750 ||
+	    BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 ||
+	    BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 ||
+	    BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787)
+		i = 8;
+
+	CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, i);
 	CSR_WRITE_4(sc, BGE_RBDI_JUMBO_REPL_THRESH, BGE_JUMBO_RX_RING_CNT/8);
 
 	/*
@@ -1846,36 +1861,42 @@
 	}
 
 	/* Turn on write DMA state machine */
-	CSR_WRITE_4(sc, BGE_WDMA_MODE,
-	    BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS);
+	{
+		uint32_t bge_wdma_mode =
+			BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS;
+
+		if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 ||
+		    BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787)
+		  /* Enable host coalescing bug fix; see Linux tg3.c */
+		  bge_wdma_mode |= (1 << 29);
+
+		CSR_WRITE_4(sc, BGE_WDMA_MODE, bge_wdma_mode);
+        }
 
 	/* Turn on read DMA state machine */
 	{
 		uint32_t dma_read_modebits;
 
-#define DMA_READ_MODE_FIFO_LONG_BURST ((1<<17) || (1 << 16))
-#define DMA_READ_MODE_FIFO_SIZE_128                 (1 << 17)
-
 		dma_read_modebits =
 		  BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS;
 
-#if 1	/* XXXjrs does this help?  check again,2005-nov-14 */
 		if (sc->bge_pcie && 0) {
-			dma_read_modebits |= DMA_READ_MODE_FIFO_LONG_BURST;
+			dma_read_modebits |= BGE_RDMA_MODE_FIFO_LONG_BURST;
 		} else if ((sc->bge_quirks & BGE_QUIRK_5705_CORE)) {
-			dma_read_modebits |= DMA_READ_MODE_FIFO_SIZE_128;
+			dma_read_modebits |= BGE_RDMA_MODE_FIFO_SIZE_128;
 		}
 
-#endif
 		/* XXX broadcom-supplied linux driver; undocumented */
 		if (BGE_IS_5750_OR_BEYOND(sc)) {
+ 			/*
+			 * XXX: magic values.
+			 * From Broadcom-supplied Linux driver;  apparently
+			 * required to workaround a DMA bug affecting TSO
+			 * on bcm575x/bcm5721?
+			 */
 			dma_read_modebits |= (1 << 27);
-			printf("dma read modebits: set 575x tso bit: 0x%8x\n",
-			       dma_read_modebits);
 		}
-		printf("dma read modebits: 0x%8x\n", dma_read_modebits);
 		CSR_WRITE_4(sc, BGE_RDMA_MODE, dma_read_modebits);
-
 	}
 
 	/* Turn on RX data completion state machine */
@@ -1900,6 +1921,7 @@
 
 	/* Turn on send data initiator state machine */
 	if (BGE_IS_5750_OR_BEYOND(sc)) {
+		/* XXX: magic value from Linux driver */
 		CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE | 0x08);
 	} else {
 		CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE);
@@ -1961,6 +1983,10 @@
 	  BGE_QUIRK_LINK_STATE_BROKEN|BGE_QUIRK_5700_COMMON,
 	  "BCM5700 B2" },
 
+	{ BGE_CHIPID_BCM5700_B3,
+	  BGE_QUIRK_LINK_STATE_BROKEN|BGE_QUIRK_5700_COMMON,
+	  "BCM5700 B3" },
+
 	/* This is treated like a BCM5700 Bx */
 	{ BGE_CHIPID_BCM5700_ALTIMA,
 	  BGE_QUIRK_LINK_STATE_BROKEN|BGE_QUIRK_5700_COMMON,
@@ -1979,7 +2005,7 @@
 	  "BCM5701 B0" },
 
 	{ BGE_CHIPID_BCM5701_B2,
-	  BGE_QUIRK_PCIX_DMA_ALIGN_BUG,
+	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_PCIX_DMA_ALIGN_BUG,
 	  "BCM5701 B2" },
 
 	{ BGE_CHIPID_BCM5701_B5,
@@ -2002,6 +2028,10 @@
 	  BGE_QUIRK_ONLY_PHY_1,
 	  "BCM5703 A3" },
 
+	{ BGE_CHIPID_BCM5703_B0,
+	  BGE_QUIRK_ONLY_PHY_1,
+	  "BCM5703 B0" },
+
 	{ BGE_CHIPID_BCM5704_A0,
   	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_FEWER_MBUFS,
 	  "BCM5704 A0" },
@@ -2036,7 +2066,7 @@
 
 	{ BGE_CHIPID_BCM5750_A0,
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
-	  "BCM5750 A1" },
+	  "BCM5750 A0" },
 
 	{ BGE_CHIPID_BCM5750_A1,
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
@@ -2046,13 +2076,29 @@
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
 	  "BCM5751 A1" },
 
-	{ BGE_CHIPID_BCM5715_xx,
+	{ BGE_CHIPID_BCM5752_A0,
+	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+	  "BCM5752 A0" },
+
+	{ BGE_CHIPID_BCM5752_A1,
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
-	  "BCM5715 xx" },
+	  "BCM5752 A1" },
 
-	{ BGE_CHIPID_BCM5780_A0,
+	{ BGE_CHIPID_BCM5752_A2,
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
-	  "BCM5780 xx" },
+	  "BCM5752 A2" },
+
+	{ BGE_CHIPID_BCM5787_A0,
+	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+	  "BCM5754/5787 A0" },
+
+	{ BGE_CHIPID_BCM5787_A1,
+	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+	  "BCM5754/5787 A1" },
+
+	{ BGE_CHIPID_BCM5787_A2,
+	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+	  "BCM5754/5787 A2" },
 
 	{ 0, 0, NULL }
 };
@@ -2086,6 +2132,10 @@
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
 	  "unknown BCM575x family" },
 
+	{ BGE_ASICREV_BCM5714_A0,
+	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+	  "unknown BCM5714" },
+
 	{ BGE_ASICREV_BCM5714,
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
 	  "unknown BCM5714" },
@@ -2094,14 +2144,17 @@
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
 	  "unknown BCM5752 family" },
 
-
-	{ BGE_ASICREV_BCM5715,
+	{ BGE_ASICREV_BCM5755,
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
-	  "unknown BCM5715" },
+	  "unknown BCM5755" },
 
 	{ BGE_ASICREV_BCM5780,
 	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
-	  "unknown BCM5780/BCM5780S" },
+	  "unknown BCM5780" },
+
+	{ BGE_ASICREV_BCM5787,
+	  BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+	  "unknown BCM5787" },
 
 	{ 0,
 	  0,
@@ -2185,8 +2238,8 @@
 	  "Broadcom BCM5703X Gigabit Ethernet",
 	  },
 	{ PCI_VENDOR_BROADCOM,
-	  PCI_PRODUCT_BROADCOM_BCM5703A3,
-	  "Broadcom BCM5703A3 Gigabit Ethernet",
+	  PCI_PRODUCT_BROADCOM_BCM5703_ALT,
+	  "Broadcom BCM5703 Gigabit Ethernet",
 	  },
 
    	{ PCI_VENDOR_BROADCOM,
@@ -2207,24 +2260,26 @@
 	  "Broadcom BCM5705K Gigabit Ethernet",
 	  },
    	{ PCI_VENDOR_BROADCOM,
-	  PCI_PRODUCT_BROADCOM_BCM5705_ALT,
-	  "Broadcom BCM5705 Gigabit Ethernet",
+	  PCI_PRODUCT_BROADCOM_BCM5705M,
+	  "Broadcom BCM5705M Gigabit Ethernet",
 	  },
    	{ PCI_VENDOR_BROADCOM,
-	  PCI_PRODUCT_BROADCOM_BCM5705M,
+	  PCI_PRODUCT_BROADCOM_BCM5705M_ALT,
 	  "Broadcom BCM5705M Gigabit Ethernet",
 	  },
 
 	{ PCI_VENDOR_BROADCOM,
 	  PCI_PRODUCT_BROADCOM_BCM5714,
-	  "Broadcom BCM5714 Gigabit Ethernet",
+	  "Broadcom BCM5714/5715 Gigabit Ethernet",
 	  },
-
 	{ PCI_VENDOR_BROADCOM,
 	  PCI_PRODUCT_BROADCOM_BCM5715,
-	  "Broadcom BCM5715 Gigabit Ethernet",
+	  "Broadcom BCM5714/5715 Gigabit Ethernet",
+	  },
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5789,
+	  "Broadcom BCM5789 Gigabit Ethernet",
 	  },
-
 
 	{ PCI_VENDOR_BROADCOM,
 	  PCI_PRODUCT_BROADCOM_BCM5721,
@@ -2256,6 +2311,41 @@
 	  "Broadcom BCM5752 Gigabit Ethernet",
 	  },
 
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5752M,
+	  "Broadcom BCM5752M Gigabit Ethernet",
+	  },
+
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5753,
+	  "Broadcom BCM5753 Gigabit Ethernet",
+	  },
+
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5753M,
+	  "Broadcom BCM5753M Gigabit Ethernet",
+	  },
+
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5754,
+	  "Broadcom BCM5754 Gigabit Ethernet",
+	},
+
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5754M,
+	  "Broadcom BCM5754M Gigabit Ethernet",
+	},
+
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5755,
+	  "Broadcom BCM5755 Gigabit Ethernet",
+	},
+
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5755M,
+	  "Broadcom BCM5755M Gigabit Ethernet",
+	},
+
    	{ PCI_VENDOR_BROADCOM,
 	  PCI_PRODUCT_BROADCOM_BCM5780,
 	  "Broadcom BCM5780 Gigabit Ethernet",
@@ -2269,12 +2359,31 @@
    	{ PCI_VENDOR_BROADCOM,
 	  PCI_PRODUCT_BROADCOM_BCM5782,
 	  "Broadcom BCM5782 Gigabit Ethernet",
-	  },
+	},
+
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5786,
+	  "Broadcom BCM5786 Gigabit Ethernet",
+	},
+
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5787,
+	  "Broadcom BCM5787 Gigabit Ethernet",
+	},
+
+	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5787M,
+	  "Broadcom BCM5787M Gigabit Ethernet",
+	},
 
    	{ PCI_VENDOR_BROADCOM,
 	  PCI_PRODUCT_BROADCOM_BCM5788,
 	  "Broadcom BCM5788 Gigabit Ethernet",
 	  },
+   	{ PCI_VENDOR_BROADCOM,
+	  PCI_PRODUCT_BROADCOM_BCM5789,
+	  "Broadcom BCM5789 Gigabit Ethernet",
+	  },
 
    	{ PCI_VENDOR_BROADCOM,
 	  PCI_PRODUCT_BROADCOM_BCM5901,
@@ -2503,9 +2612,6 @@
 	else
 		sc->bge_pcie = 0;
 
-	DPRINTFN(4 ,("%s: asic %04x, pcie = %d\n", sc->bge_dev.dv_xname,
-	       BGE_ASICREV(sc->bge_chipid), sc->bge_pcie));	/* XXX jrs */
-
 	/* Try to reset the chip. */
 	DPRINTFN(5, ("bge_reset\n"));
 	bge_reset(sc);
@@ -2644,7 +2750,7 @@
 	sc->ethercom.ec_capabilities |=
 	    ETHERCAP_VLAN_HWTAGGING | ETHERCAP_VLAN_MTU;
 
-	if (sc->bge_pcie || BGE_IS_5714_FAMILY(sc))
+	if (sc->bge_pcie)
 		sc->ethercom.ec_if.if_capabilities |= IFCAP_TSOv4;
 
 	/*
@@ -2776,7 +2882,6 @@
 {
 	struct pci_attach_args *pa = &sc->bge_pa;
 	u_int32_t cachesize, command, pcistate, new_pcistate;
-	u_int32_t saved_msi_mode;
 	int i, val;
 
 	/* Save some important PCI state. */
@@ -2788,6 +2893,15 @@
 	    BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR|
 	    BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW);
 
+	/*
+	 * Disable the firmware fastboot feature on 5752 ASIC
+	 * to avoid firmware timeout.
+	 */
+	if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 ||
+	    BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 ||
+	    BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787)
+		CSR_WRITE_4(sc, BGE_FASTBOOT_PC, 0);
+
 	val = BGE_MISCCFG_RESET_CORE_CLOCKS | (65<<1);
 	/*
 	 * XXX: from FreeBSD/Linux; no documentation
@@ -2801,12 +2915,12 @@
 			val |= (1<<29);
 		}
 	}
-	/* Certain bcm5714/HT-2000 chips clobber MSI state on reset */
-	saved_msi_mode = 0;
-	if (BGE_IS_5714_FAMILY(sc)) {
-		saved_msi_mode =
-		  pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_MSI_CAPID);
-	}
+	/*
+	 * Write the magic number to the firmware mailbox at 0xb50
+	 * so that the driver can synchronize with the firmware.
+	 */
+	bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER);
+
 	/* Issue global reset */
 	bge_writereg_ind(sc, BGE_MISC_CFG, val);
 
@@ -2825,8 +2939,14 @@
 			pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_UNKNOWN0,
 			    reg | (1 << 15));
 		}
-		/* XXX: Magic Numbers */
-		pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_CONF_DEV_CTRL, 0xf5000);
+		/*
+		 * XXX: Magic Numbers.
+		 * Sets maximal PCI-e payload and clears any PCI-e errors.
+		 * Should be replaced with references to PCI config-space
+		 * capability block for PCI-Express.
+		 */
+		pci_conf_write(pa->pa_pc, pa->pa_tag,
+		    BGE_PCI_CONF_DEV_CTRL, 0xf5000);
 
 	}
 
@@ -2840,28 +2960,13 @@
 
 	/* Enable memory arbiter. */
 	{
-		 uint32_t marbmode = 0;
-		 if (BGE_IS_5714_FAMILY(sc)) {
+		uint32_t marbmode = 0;
+		if (BGE_IS_5714_FAMILY(sc)) {
 			marbmode = CSR_READ_4(sc, BGE_MARB_MODE);
-		 }
-		CSR_WRITE_4(sc, BGE_MARB_MODE, marbmode | BGE_MARBMODE_ENABLE);
-	}
-
-	if (BGE_IS_5714_FAMILY(sc)) {
-		uint32_t msi_mode;
-		msi_mode =
-		  pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_MSI_CAPID);
-		msi_mode |= (saved_msi_mode & (1 << 16));
-		pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_MSI_CAPID, msi_mode);
+		}
+		CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE | marbmode);
 	}
 
-
-	/*
-	 * Prevent PXE restart: write a magic number to the
-	 * general communications memory at 0xB50.
-	 */
-	bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER);
-
 	/*
 	 * Poll the value location we just wrote until
 	 * we see the 1's complement of the magic number.
@@ -2878,6 +2983,11 @@
 	if (i >= BGE_TIMEOUT) {
 		printf("%s: firmware handshake timed out, val = %x\n",
 		    sc->bge_dev.dv_xname, val);
+		/*
+		 * XXX: occasionally fired on bcm5721, but without
+		 * apparent harm.  For now, keep going if we timeout
+		 * against PCI-E devices.
+		 */
 		if (!sc->bge_pcie)
 		  return;
 	}
@@ -2911,11 +3021,11 @@
 	/* Enable memory arbiter. */
 	/* XXX why do this twice? */
 	{
-		 uint32_t marbmode = 0;
-		 if (BGE_IS_5714_FAMILY(sc)) {
+		uint32_t marbmode = 0;
+		if (BGE_IS_5714_FAMILY(sc)) {
 			marbmode = CSR_READ_4(sc, BGE_MARB_MODE);
-		 }
-		CSR_WRITE_4(sc, BGE_MARB_MODE, marbmode | BGE_MARBMODE_ENABLE);
+		}
+		CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE | marbmode);
 	}
 
 	/* Fix up byte swapping */
@@ -3183,7 +3293,7 @@
 	 * Process link state changes.
 	 * Grrr. The link status word in the status block does
 	 * not work correctly on the BCM5700 rev AX and BX chips,
-	 * according to all avaibable information. Hence, we have
+	 * according to all available information. Hence, we have
 	 * to enable MII interrupts in order to properly obtain
 	 * async link changes. Unfortunately, this also means that
 	 * we have to read the MAC status register to detect link
@@ -3395,7 +3505,7 @@
 		 * (thus perhaps avoiding the bcm5700 dma-min bug).
 		 */
 		for (last = pkt; last->m_next != NULL; last = last->m_next) {
-	      	       (void) 0; /* do nothing*/
+	      	       (void) 0; /* do nothing */
 		}
 
 		/* `last' now points to last in chain. */
@@ -3405,6 +3515,8 @@
 			/* Allocate new empty mbuf, pad it. Compact later. */
 			struct mbuf *n;
 			MGET(n, M_DONTWAIT, MT_DATA);
+			if (n == NULL)
+				return ENOBUFS;
 			n->m_len = 0;
 			last->m_next = n;
 			last = n;
@@ -3550,7 +3662,7 @@
 	u_int32_t *txidx;
 {
 	struct bge_tx_bd	*f = NULL;
-	u_int32_t		frag, cur, cnt = 0;
+	u_int32_t		frag, cur;
 	u_int16_t		csum_flags = 0;
 	u_int16_t		txbd_tso_flags = 0;
 	struct txdmamap_pool_entry *dma;
@@ -3558,7 +3670,7 @@
 	int			i = 0;
 	struct m_tag		*mtag;
 	int			use_tso, maxsegsize, error;
- 
+
 	cur = frag = *txidx;
 
 	if (m_head->m_pkthdr.csum_flags) {
@@ -3643,15 +3755,14 @@
 			return (ENOBUFS);
 		}
 
-			/*
-			 * TCP/IP headers are in the first mbuf; we can do
-			 * this the easy way.
-			 */
-			iphl =
-			  M_CSUM_DATA_IPv4_IPHL(m0->m_pkthdr.csum_data);
-			hlen = iphl + offset;
-			if (__predict_false(m0->m_len <
-				    (hlen + sizeof(struct tcphdr)))) {
+		/*
+		 * TCP/IP headers are in the first mbuf; we can do
+		 * this the easy way.
+		 */
+		iphl = M_CSUM_DATA_IPv4_IPHL(m0->m_pkthdr.csum_data);
+		hlen = iphl + offset;
+		if (__predict_false(m0->m_len <
+			(hlen + sizeof(struct tcphdr)))) {
 
 			struct ip ip;
 			struct tcphdr th;
@@ -3659,7 +3770,10 @@
 				 "ip/tcp hlen %d, not handled yet\n",
 				 m0->m_len, (int)(hlen+ sizeof(struct tcphdr)));
 #ifdef NOTYET
-
+			/*
+			 * XXX jonathan@NetBSD.org: untested.
+			 * how to force  this branch to be taken?
+			 */
 			BGE_EVCNT_INCR(&sc->sc_ev_txtsopain);
 
 			m_copydata(m0, offset, sizeof(ip), &ip);
@@ -3679,13 +3793,17 @@
 			hlen += th.th_off << 2;
 			iptcp_opt_words	= hlen;
 #else
+			/*
+			 * if_wm "hard" case not yet supported, can we not
+			 * mandate it out of existence?
+			 */
 			(void) ip; (void)th; (void) ip_tcp_hlen;
 			BGE_TSO_PRINTF(("%s: TSO hard case\n",
 			    sc->bge_dev.dv_xname));
 
 			return ENOBUFS;
 #endif
-			} else {
+		} else {
 			ip = (struct ip *) (mtod(m0, caddr_t) + offset);
 			th = (struct tcphdr *) (mtod(m0, caddr_t) + hlen);
 			ip_tcp_hlen = iphl +  (th->th_off << 2);
@@ -3694,16 +3812,21 @@
 			iptcp_opt_words = (ip_tcp_hlen
 				       - sizeof(struct tcphdr)
 				       - sizeof(struct ip)) >> 2;
-			}
+		}
 		if (BGE_IS_5750_OR_BEYOND(sc)) {
 			th->th_sum = 0;
 			csum_flags &= ~(BGE_TXBDFLAG_TCP_UDP_CSUM);
 		} else {
-			/* XXXjrs untested */
+			/*
+			 * XXX jonathan@NetBSD.org: 5705 untested.
+			 * Requires TSO firmware patch for 5701/5703/5704.
+			 */
+			th->th_sum = in_cksum_phdr(ip->ip_src.s_addr,
+			    ip->ip_dst.s_addr, htons(IPPROTO_TCP));
 		}
 
 		mss = m_head->m_pkthdr.segsz;
-		txbd_tso_flags |= 	
+		txbd_tso_flags |=
 		    BGE_TXBDFLAG_CPU_PRE_DMA |
 		    BGE_TXBDFLAG_CPU_POST_DMA;
 
@@ -3722,8 +3845,7 @@
 			if ( BGE_IS_5705_OR_BEYOND(sc)) {
 				tcp_seg_flags =
 					iptcp_opt_words << 11;
-			}
-			else {
+			} else {
 				txbd_tso_flags |=
 					iptcp_opt_words << 12;
 			}
@@ -3748,16 +3870,27 @@
 			    sc->bge_dev.dv_xname, error));
 				return(ENOBUFS);
 	}
+	/*
+	 * Sanity check: avoid coming within 16 descriptors
+	 * of the end of the ring.
+	 */
+	if (dmamap->dm_nsegs > (BGE_TX_RING_CNT - sc->bge_txcnt - 16)) {
+		BGE_TSO_PRINTF(("%s: "
+		    " dmamap_load_mbuf too close to ring wrap\n",
+		    sc->bge_dev.dv_xname));
+		goto fail_unload;
+	}
 
 	mtag = sc->ethercom.ec_nvlans ?
 	    m_tag_find(m_head, PACKET_TAG_VLAN, NULL) : NULL;
 
 
+	/* Iterate over dmap-map fragments. */
 	for (i = 0; i < dmamap->dm_nsegs; i++) {
 		f = &sc->bge_rdata->bge_tx_ring[frag];
 		if (sc->bge_cdata.bge_tx_chain[frag] != NULL)
 			break;
-	
+
 		bge_set_hostaddr(&f->bge_addr, dmamap->dm_segs[i].ds_addr);
 		f->bge_len = dmamap->dm_segs[i].ds_len;
 
@@ -3787,24 +3920,14 @@
 		} else {
 			f->bge_vlan_tag = 0;
 		}
-		/*
-		 * Sanity check: avoid coming within 16 descriptors
-		 * of the end of the ring.
-		 */
-		if ((BGE_TX_RING_CNT - (sc->bge_txcnt + cnt)) < 16) {
-			DPRINTFN(5, ("%s: Tx ring overfull heuristic\n",
-			    sc->bge_dev.dv_xname));
-			return EAGAIN;	/* XXX odd but unique */
-		}
 		cur = frag;
 		BGE_INC(frag, BGE_TX_RING_CNT);
-		cnt++;
 	}
 
 	if (i < dmamap->dm_nsegs) {
 		BGE_TSO_PRINTF(("%s: reached %d < dm_nsegs %d\n",
 		    sc->bge_dev.dv_xname, i, dmamap->dm_nsegs));
-		return ENOBUFS;
+		goto fail_unload;
 	}
 
 	bus_dmamap_sync(sc->bge_dmatag, dmamap, 0, dmamap->dm_mapsize,
@@ -3814,18 +3937,23 @@
 		BGE_TSO_PRINTF(("%s: frag %d = wrapped id %d?\n",
 		    sc->bge_dev.dv_xname, frag, sc->bge_tx_saved_considx));
 
-		return(ENOBUFS);
+		goto fail_unload;
 	}
 
 	sc->bge_rdata->bge_tx_ring[cur].bge_flags |= BGE_TXBDFLAG_END;
 	sc->bge_cdata.bge_tx_chain[cur] = m_head;
 	SLIST_REMOVE_HEAD(&sc->txdma_list, link);
 	sc->txdma[cur] = dma;
-	sc->bge_txcnt += cnt;
+	sc->bge_txcnt += dmamap->dm_nsegs;
 
 	*txidx = frag;
 
 	return(0);
+
+ fail_unload:
+	bus_dmamap_unload(sc->bge_dmatag, dmamap);
+
+	return ENOBUFS;
 }
 
 /*
@@ -3844,7 +3972,7 @@
 
 	sc = ifp->if_softc;
 
-	if (!sc->bge_link && ifp->if_snd.ifq_len < 10)
+	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
 		return;
 
  	prodidx = sc->bge_tx_prodidx;
@@ -3879,9 +4007,6 @@
 		 * for the NIC to drain the ring.
 		 */
 		if ((err = bge_encap(sc, m_head, &prodidx)) != 0) {
-		  	if (err != EAGAIN)
-				DPRINTFN(4, ("%s: bge_encap failed on len %d, err %d?\n",
-					    sc->bge_dev.dv_xname, m_head->m_pkthdr.len, err));
 			ifp->if_flags |= IFF_OACTIVE;
 			break;
 		}
@@ -3948,7 +4073,7 @@
 
 	/* Specify MTU. */
 	CSR_WRITE_4(sc, BGE_RX_MTU, ifp->if_mtu +
-	    ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN); 
+	    ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN);
 
 	/* Load our MAC address. */
 	m = (u_int16_t *)&(LLADDR(ifp->if_sadl)[0]);
@@ -4111,7 +4236,7 @@
 			    sc->bge_if_flags & IFF_PROMISC) {
 				BGE_CLRBIT(sc, BGE_RX_MODE,
 				    BGE_RXMODE_RX_PROMISC);
-			} else
+			} else if (!(sc->bge_if_flags & IFF_UP))
 				bge_init(ifp);
 		} else {
 			if (ifp->if_flags & IFF_RUNNING) {
Index: if_bgereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bgereg.h,v
retrieving revision 1.24.2.5
diff -u -r1.24.2.5 if_bgereg.h
--- if_bgereg.h	5 Mar 2007 15:07:14 -0000	1.24.2.5
+++ if_bgereg.h	18 Sep 2007 06:58:42 -0000
@@ -192,11 +192,16 @@
 #define BGE_PCI_UNDI_TX_BD_PRODIDX_LO	0xAC
 #define BGE_PCI_ISR_MBX_HI		0xB0
 #define BGE_PCI_ISR_MBX_LO		0xB4
-/* XXX: used in PCI-Express code for 575x chips */
+
 #define BGE_PCI_UNKNOWN0		0xC4
-#define BGE_PCI_UNKNOWN1		0xD8
-#define BGE_PCI_CONF_DEV_CTRL		0XD8
-#define BGE_PCI_CONF_DEV_STUS		0XDA
+/* XXX:
+ * Used in PCI-Express code for 575x chips.
+ * Should be replaced with checking for a PCI config-space
+ * capability for PCI-Express, and PCI-Express standard
+ * offsets into that capability block.
+ */
+#define BGE_PCI_CONF_DEV_CTRL		0xD8
+#define BGE_PCI_CONF_DEV_STUS		0xDA
 
 
 /* PCI Misc. Host control register */
@@ -230,8 +235,9 @@
 #define BGE_CHIPID_BCM5700_A0		0x70000000
 #define BGE_CHIPID_BCM5700_A1		0x70010000
 #define BGE_CHIPID_BCM5700_B0		0x71000000
-#define BGE_CHIPID_BCM5700_B1		0x71020000
-#define BGE_CHIPID_BCM5700_B2		0x71030000
+#define BGE_CHIPID_BCM5700_B1		0x71010000
+#define BGE_CHIPID_BCM5700_B2		0x71020000
+#define BGE_CHIPID_BCM5700_B3		0x71030000
 #define BGE_CHIPID_BCM5700_ALTIMA	0x71040000
 #define BGE_CHIPID_BCM5700_C0		0x72000000
 #define BGE_CHIPID_BCM5701_A0		0x00000000	/* grrrr */
@@ -241,41 +247,67 @@
 #define BGE_CHIPID_BCM5703_A0		0x10000000
 #define BGE_CHIPID_BCM5703_A1		0x10010000
 #define BGE_CHIPID_BCM5703_A2		0x10020000
-#define BGE_CHIPID_BCM5703_A3		0x11000000
+#define BGE_CHIPID_BCM5703_A3		0x10030000
+#define BGE_CHIPID_BCM5703_B0		0x11000000
 #define BGE_CHIPID_BCM5704_A0		0x20000000
 #define BGE_CHIPID_BCM5704_A1		0x20010000
 #define BGE_CHIPID_BCM5704_A2		0x20020000
 #define BGE_CHIPID_BCM5704_A3		0x20030000
+#define BGE_CHIPID_BCM5704_B0		0x21000000
 #define BGE_CHIPID_BCM5705_A0		0x30000000
 #define BGE_CHIPID_BCM5705_A1		0x30010000
 #define BGE_CHIPID_BCM5705_A2		0x30020000
 #define BGE_CHIPID_BCM5705_A3		0x30030000
 #define BGE_CHIPID_BCM5750_A0		0x40000000
 #define BGE_CHIPID_BCM5750_A1		0x40010000
+#define BGE_CHIPID_BCM5750_A3		0x40030000
+#define BGE_CHIPID_BCM5750_B0		0x40100000
 #define BGE_CHIPID_BCM5751_A1		0x41010000
+#define BGE_CHIPID_BCM5750_C0		0x42000000
+#define BGE_CHIPID_BCM5750_C1		0x42010000
+#define BGE_CHIPID_BCM5750_C2		0x42020000
 #define BGE_CHIPID_BCM5714_A0		0x50000000
-#define BGE_CHIPID_BCM5715_xx		0x90010000
-#define BGE_CHIPID_BCM5780_A0		0x166a0000
+#define BGE_CHIPID_BCM5752_A0		0x60000000
+#define BGE_CHIPID_BCM5752_A1		0x60010000
+#define BGE_CHIPID_BCM5752_A2		0x60020000
+#define BGE_CHIPID_BCM5714_B0		0x80000000
+#define BGE_CHIPID_BCM5714_B3		0x80030000
+#define BGE_CHIPID_BCM5715_A0		0x90000000
+#define BGE_CHIPID_BCM5715_A1		0x90010000
+#define BGE_CHIPID_BCM5715_A3		0x90030000
+#define BGE_CHIPID_BCM5787_A0		0xb0000000
+#define BGE_CHIPID_BCM5787_A1		0xb0010000
+#define BGE_CHIPID_BCM5787_A2		0xb0020000
+#define BGE_CHIPID_BCM5906_A1		0xc0010000
 
 /* shorthand one */
-#define BGE_ASICREV(x)                  ((x) >> 28)
-#define BGE_ASICREV_BCM5700             0x07
-#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             0x05
-#define BGE_ASICREV_BCM5752             0x06
-#define BGE_ASICREV_BCM5780             0x08
-#define BGE_ASICREV_BCM5715             0x09	/* XXX ??? */
+#define BGE_ASICREV(x)			((x) >> 28)
+#define BGE_ASICREV_BCM5700		0x07
+#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
+/* ASIC revision 0x07 is the original bcm5700 */
+#define BGE_ASICREV_BCM5780		0x08
+#define BGE_ASICREV_BCM5714		0x09
+#define BGE_ASICREV_BCM5755		0x0a
+#define BGE_ASICREV_BCM5787		0x0b
+#define BGE_ASICREV_BCM5706		0x0c
 
 /* chip revisions */
-#define BGE_CHIPREV(x)                  ((x) >> 24)
-#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(x)			((x) >> 24)
+#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
 
 /* PCI DMA Read/Write Control register */
 #define BGE_PCIDMARWCTL_MINDMA		0x000000FF
@@ -293,6 +325,9 @@
 #define BGE_PCIDMARWCTL_DFLT_PCI_WR_CMD	0xF0000000
 # define  BGE_PCIDMA_RWCTL_PCI_WR_CMD_SHIFT	 28
 
+/* PCI DMA Read/Write Control register, alternate usage for PCI-Express */
+#define BGE_PCIDMA_RWCTL_PCIE_WRITE_WATRMARK_128	0x00180000
+#define BGE_PCIDMA_RWCTL_PCIE_WRITE_WATRMARK_256	0x00380000
 
 #define BGE_PCI_READ_BNDRY_DISABLE	0x00000000
 #define BGE_PCI_READ_BNDRY_16BYTES	0x00000100
@@ -1094,7 +1129,7 @@
 #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	0x3C34 /* 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
@@ -1299,6 +1334,10 @@
 #define BGE_RDMAMODE_LOCWRITE_TOOBIG	0x00000200
 #define BGE_RDMAMODE_ALL_ATTNS		0x000003FC
 
+/* Alternate encodings for PCI-Express, from Broadcom-supplied Linux driver */
+#define BGE_RDMA_MODE_FIFO_LONG_BURST	((1<<17) || (1 << 16))
+#define BGE_RDMA_MODE_FIFO_SIZE_128	(1 << 17)
+
 /* Read DMA status register */
 #define BGE_RDMASTAT_PCI_TGT_ABRT_ATTN	0x00000004
 #define BGE_RDMASTAT_PCI_MSTR_ABRT_ATTN	0x00000008
@@ -1625,6 +1664,7 @@
 #define BGE_EE_CTL			0x6840
 #define BGE_MDI_CTL			0x6844
 #define BGE_EE_DELAY			0x6848
+#define BGE_FASTBOOT_PC			0x6894
 /*
  * XXX: Those names are made up as I have no documentation about it;
  *      I only know it is only used in the PCI-Express case.
@@ -1764,15 +1804,13 @@
  * firmware mailbox at 0xB50 in order to prevent the PXE boot
  * code from running.
  */
-#define BGE_MAGIC_NUMBER                0x4B657654
+#define BGE_MAGIC_NUMBER		0x4B657654
 
 typedef struct {
-	u_int32_t		bge_addr_hi;
-	u_int32_t		bge_addr_lo;
+	volatile u_int32_t	bge_addr_hi;
+	volatile u_int32_t	bge_addr_lo;
 } bge_hostaddr;
 
-#define BGE_HOSTADDR(x)	(x).bge_addr_lo
-
 static __inline void
 bge_set_hostaddr(volatile bge_hostaddr *x, bus_addr_t y)
 {
@@ -1786,8 +1824,8 @@
 /* Ring control block structure */
 struct bge_rcb {
 	bge_hostaddr		bge_hostaddr;
-	u_int32_t		bge_maxlen_flags;	/* two 16-bit fields */
-	u_int32_t		bge_nicaddr;
+	volatile u_int32_t	bge_maxlen_flags;	/* two 16-bit fields */
+	volatile u_int32_t	bge_nicaddr;
 };
 
 #define	BGE_RCB_MAXLEN_FLAGS(maxlen, flags)	((maxlen) << 16 | (flags))
@@ -1803,15 +1841,15 @@
 struct bge_tx_bd {
 	bge_hostaddr		bge_addr;
 #if BYTE_ORDER == BIG_ENDIAN
-	u_int16_t		bge_len;
-	u_int16_t		bge_flags;
-	u_int16_t		bge_rsvd;
-	u_int16_t		bge_vlan_tag;
+	volatile u_int16_t	bge_len;
+	volatile u_int16_t	bge_flags;
+	volatile u_int16_t	bge_rsvd;
+	volatile u_int16_t	bge_vlan_tag;
 #else
-	u_int16_t		bge_flags;
-	u_int16_t		bge_len;
-	u_int16_t		bge_vlan_tag;
-	u_int16_t		bge_rsvd;
+	volatile u_int16_t	bge_flags;
+	volatile u_int16_t	bge_len;
+	volatile u_int16_t	bge_vlan_tag;
+	volatile u_int16_t	bge_rsvd;
 #endif
 };
 
@@ -1835,26 +1873,26 @@
 struct bge_rx_bd {
 	bge_hostaddr		bge_addr;
 #if BYTE_ORDER == BIG_ENDIAN
-	u_int16_t		bge_idx;
-	u_int16_t		bge_len;
-	u_int16_t		bge_type;
-	u_int16_t		bge_flags;
-	u_int16_t		bge_ip_csum;
-	u_int16_t		bge_tcp_udp_csum;
-	u_int16_t		bge_error_flag;
-	u_int16_t		bge_vlan_tag;
+	volatile u_int16_t	bge_idx;
+	volatile u_int16_t	bge_len;
+	volatile u_int16_t	bge_type;
+	volatile u_int16_t	bge_flags;
+	volatile u_int16_t	bge_ip_csum;
+	volatile u_int16_t	bge_tcp_udp_csum;
+	volatile u_int16_t	bge_error_flag;
+	volatile u_int16_t	bge_vlan_tag;
 #else
-	u_int16_t		bge_len;
-	u_int16_t		bge_idx;
-	u_int16_t		bge_flags;
-	u_int16_t		bge_type;
-	u_int16_t		bge_tcp_udp_csum;
-	u_int16_t		bge_ip_csum;
-	u_int16_t		bge_vlan_tag;
-	u_int16_t		bge_error_flag;
+	volatile u_int16_t	bge_len;
+	volatile u_int16_t	bge_idx;
+	volatile u_int16_t	bge_flags;
+	volatile u_int16_t	bge_type;
+	volatile u_int16_t	bge_tcp_udp_csum;
+	volatile u_int16_t	bge_ip_csum;
+	volatile u_int16_t	bge_vlan_tag;
+	volatile u_int16_t	bge_error_flag;
 #endif
-	u_int32_t		bge_rsvd;
-	u_int32_t		bge_opaque;
+	volatile u_int32_t	bge_rsvd;
+	volatile u_int32_t	bge_opaque;
 };
 
 #define BGE_RXBDFLAG_END		0x0004
@@ -1877,27 +1915,27 @@
 
 struct bge_sts_idx {
 #if BYTE_ORDER == BIG_ENDIAN
-	u_int16_t		bge_tx_cons_idx;
-	u_int16_t		bge_rx_prod_idx;
+	volatile u_int16_t	bge_tx_cons_idx;
+	volatile u_int16_t	bge_rx_prod_idx;
 #else
-	u_int16_t		bge_rx_prod_idx;
-	u_int16_t		bge_tx_cons_idx;
+	volatile u_int16_t	bge_rx_prod_idx;
+	volatile u_int16_t	bge_tx_cons_idx;
 #endif
 };
 
 struct bge_status_block {
-	u_int32_t		bge_status;
-	u_int32_t		bge_rsvd0;
+	volatile u_int32_t	bge_status;
+	volatile u_int32_t	bge_rsvd0;
 #if BYTE_ORDER == BIG_ENDIAN
-	u_int16_t		bge_rx_std_cons_idx;
-	u_int16_t		bge_rx_jumbo_cons_idx;
-	u_int16_t		bge_rsvd1;
-	u_int16_t		bge_rx_mini_cons_idx;
+	volatile u_int16_t	bge_rx_std_cons_idx;
+	volatile u_int16_t	bge_rx_jumbo_cons_idx;
+	volatile u_int16_t	bge_rsvd1;
+	volatile u_int16_t	bge_rx_mini_cons_idx;
 #else
-	u_int16_t		bge_rx_jumbo_cons_idx;
-	u_int16_t		bge_rx_std_cons_idx;
-	u_int16_t		bge_rx_mini_cons_idx;
-	u_int16_t		bge_rsvd1;
+	volatile u_int16_t	bge_rx_jumbo_cons_idx;
+	volatile u_int16_t	bge_rx_std_cons_idx;
+	volatile u_int16_t	bge_rx_mini_cons_idx;
+	volatile u_int16_t	bge_rsvd1;
 #endif
 	struct bge_sts_idx	bge_idx[16];
 };
@@ -1918,6 +1956,7 @@
 #define BCOM_VENDORID			0x14E4
 #define BCOM_DEVICEID_BCM5700		0x1644
 #define BCOM_DEVICEID_BCM5701		0x1645
+#define BCOM_DEVICEID_BCM5789		0x169d
 
 /*
  * Alteon AceNIC PCI vendor/device ID.
@@ -2269,20 +2308,21 @@
  * no attempt is made to allocate physically contiguous memory.
  *
  */
-#if 0
+#if 0	/* pre-TSO values */
+#define BGE_TXDMA_MAX	ETHER_MAX_LEN_JUMBO
 #ifdef _LP64
-#define BGE_NTXSEG      30
+#define BGE_NTXSEG	30
 #else
-#define BGE_NTXSEG      31
+#define BGE_NTXSEG	31
 #endif
-#else	/* tso */
+#else	/* TSO values */
 #define BGE_TXDMA_MAX	(round_page(IP_MAXPACKET))	/* for TSO */
 #ifdef _LP64
-#define BGE_NTXSEG      120
+#define BGE_NTXSEG	120	/* XXX just a guess */
 #else
-#define BGE_NTXSEG      124
+#define BGE_NTXSEG	124	/* XXX just a guess */
 #endif
-#endif	/* tso */
+#endif	/* TSO values */
 
 
 /*
@@ -2318,7 +2358,7 @@
 #define BGE_TXCONS_UNSET		0xFFFF	/* impossible value */
 
 struct bge_jpool_entry {
-	int                             slot;
+	int				slot;
 	SLIST_ENTRY(bge_jpool_entry)	jpool_entries;
 };
 
@@ -2350,7 +2390,7 @@
 	struct ifmedia		bge_ifmedia;	/* media info */
 	u_int8_t		bge_extram;	/* has external SSRAM */
 	u_int8_t		bge_tbi;
-    	u_int8_t		bge_rx_alignment_bug;
+	u_int8_t		bge_rx_alignment_bug;
 	u_int8_t		bge_pcie;	/* on a PCI Express port */
 	u_int32_t		bge_return_ring_cnt;
 	u_int32_t		bge_tx_prodidx;
@@ -2394,7 +2434,7 @@
 	struct callout		bge_timeout;
 	char			*bge_vpd_prodname;
 	char			*bge_vpd_readonly;
-  	int			bge_pending_rxintr_change;
+	int			bge_pending_rxintr_change;
 	SLIST_HEAD(, txdmamap_pool_entry) txdma_list;
 	struct txdmamap_pool_entry *txdma[BGE_TX_RING_CNT];
 	void			*bge_powerhook;

----Next_Part(Thu_Sep_27_09_26_35_2007_122)----