Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Nov 2008 22:40:16 +0000 (UTC)
From:      Xin LI <delphij@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r184826 - in stable/7/sys: . dev/bce
Message-ID:  <200811102240.mAAMeGfs084286@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: delphij
Date: Mon Nov 10 22:40:16 2008
New Revision: 184826
URL: http://svn.freebsd.org/changeset/base/184826

Log:
  Merge the following bce(4) changes:
  
  	r176448,178132,178853,179436,179695,179771,182293
  
  r176448 (davidch)
  
   - Added loose RX MTU functionality to allow frames larger than 1500
     bytes to be accepted even though the interface MTU is set to 1500.
   - Implemented new TCP header splitting/jumbo frame support which uses
     two chains for receive traffic rather than the original single
     receive chain.
   - Added additional debug support code.
  
  r178132 (davidch)
  
   - Fixed a problem with the send chain consumer index which would cause
     TX traffic to sit in the send chain until a received packet kick
     started the interrupt handler.  This would cause extremely slow
     performance when used with NFS over UDP.
   - Removed untested polling code.
   - Updated copyright year in the file header.
   - Removed inadvertent ^M's created by DOS text editor.
  
  r178853 (scottl)
  
  The BCE chips appear to have an undocumented requirement that RX frames
  be aligned on an 8 byte boundary.  Prior to rev 1.36 (now r176448) this
  wasn't a problem because mbuf clusters tend be naturally aligned.  The
  switch to using split buffers with the first buffer being the embedded
  data area of the mbuf has broken this assumption, at least on i386,
  causing a complete failure of RX functionality.  Fix this for now by
  using a full cluster for the first RX buffer.  A more sophisticated
  approach could be done with the old buffer scheme to realign the m_data
  pointer with m_adj(), but I'm also not clear on performance benefits of
  this old scheme or the performance implications of adding an m_adj()
  call to every allocation.
  
  r179436 (jhb)
  
  Trim an extra semi-colon.
  
  r179695 (davidch)
  
   - Fixed kern/123696 by increasing firmware timeout value from 100 to
     1000.
   - Fixed a problem on i386 architecture when using split header/jumbo
     frame firmware caused by hardware alignment requirements.
   - Added #define BCE_USE_SPLIT_HEADER to allow the feature to be
     enabled/disabled.  Enabled by default.
  
  PR:             kern/123696
  
  r179771 (davidch)
  
   - Added support for BCM5709 and BCM5716 controllers.
  
  r182293 (davidch)
  
   - Updated support for 5716.
   - Added some additional code for debug builds.
   - Fixed a problem printing physical memory on 64bit system during
     debugging.
   - Modified some of the context memory and mailbox register names to
     more clearly distinguish their use.
   - Added memory barriers for Intel CPUs when accessing host memory data
     structures which are written by hardware.
  
  Approved by:	re (kib)

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/dev/bce/if_bce.c
  stable/7/sys/dev/bce/if_bcefw.h
  stable/7/sys/dev/bce/if_bcereg.h

Modified: stable/7/sys/dev/bce/if_bce.c
==============================================================================
--- stable/7/sys/dev/bce/if_bce.c	Mon Nov 10 22:06:24 2008	(r184825)
+++ stable/7/sys/dev/bce/if_bce.c	Mon Nov 10 22:40:16 2008	(r184826)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2006-2007 Broadcom Corporation
+ * Copyright (c) 2006-2008 Broadcom Corporation
  *	David Christensen <davidch@broadcom.com>.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,13 +34,19 @@ __FBSDID("$FreeBSD$");
 /*
  * The following controllers are supported by this driver:
  *   BCM5706C A2, A3
+ *   BCM5706S A2, A3
  *   BCM5708C B1, B2
+ *   BCM5708S B1, B2
+ *   BCM5709C A1, C0
+ *   BCM5716  C0
  *
  * The following controllers are not supported by this driver:
- *   BCM5706C A0, A1
- *   BCM5706S A0, A1, A2, A3
- *   BCM5708C A0, B0
- *   BCM5708S A0, B0, B1, B2
+ *   BCM5706C A0, A1 (pre-production)
+ *   BCM5706S A0, A1 (pre-production)
+ *   BCM5708C A0, B0 (pre-production)
+ *   BCM5708S A0, B0 (pre-production)
+ *   BCM5709C A0  B0, B1, B2 (pre-production)
+ *   BCM5709S A0, A1, B0, B1, B2, C0 (pre-production)
  */
 
 #include "opt_bce.h"
@@ -80,6 +86,12 @@ __FBSDID("$FreeBSD$");
 	int bce_debug_bootcode_running_failure = 0;
 #endif
 
+/****************************************************************************/
+/* BCE Build Time Options                                                   */
+/****************************************************************************/
+#define BCE_USE_SPLIT_HEADER 1
+/* #define BCE_NVRAM_WRITE_SUPPORT 1 */
+
 
 /****************************************************************************/
 /* PCI Device ID Table                                                      */
@@ -110,6 +122,19 @@ static struct bce_type bce_devs[] = {
 	/* BCM5708S controllers and OEM boards. */
 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S,  PCI_ANY_ID,  PCI_ANY_ID,
 		"Broadcom NetXtreme II BCM5708 1000Base-SX" },
+
+	/* BCM5709C controllers and OEM boards. */
+	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709,  PCI_ANY_ID,  PCI_ANY_ID,
+		"Broadcom NetXtreme II BCM5709 1000Base-T" },
+
+	/* BCM5709S controllers and OEM boards. */
+	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S,  PCI_ANY_ID,  PCI_ANY_ID,
+		"Broadcom NetXtreme II BCM5709 1000Base-SX" },
+
+	/* BCM5716 controllers and OEM boards. */
+	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5716,  PCI_ANY_ID,  PCI_ANY_ID,
+		"Broadcom NetXtreme II BCM5716 1000Base-T" },
+
 	{ 0, 0, 0, 0, NULL }
 };
 
@@ -119,91 +144,110 @@ static struct bce_type bce_devs[] = {
 /****************************************************************************/
 static struct flash_spec flash_table[] =
 {
+#define BUFFERED_FLAGS		(BCE_NV_BUFFERED | BCE_NV_TRANSLATE)
+#define NONBUFFERED_FLAGS	(BCE_NV_WREN)
+
 	/* Slow EEPROM */
 	{0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
-	 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+	 BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
 	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
 	 "EEPROM - slow"},
 	/* Expansion entry 0001 */
 	{0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
-	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
 	 "Entry 0001"},
 	/* Saifun SA25F010 (non-buffered flash) */
 	/* strap, cfg1, & write1 need updates */
 	{0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
-	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
 	 "Non-buffered flash (128kB)"},
 	/* Saifun SA25F020 (non-buffered flash) */
 	/* strap, cfg1, & write1 need updates */
 	{0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
-	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
 	 "Non-buffered flash (256kB)"},
 	/* Expansion entry 0100 */
 	{0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
-	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
 	 "Entry 0100"},
 	/* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
 	{0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
-	 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
 	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
 	 "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
 	/* Entry 0110: ST M45PE20 (non-buffered flash)*/
 	{0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
-	 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
 	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
 	 "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
 	/* Saifun SA25F005 (non-buffered flash) */
 	/* strap, cfg1, & write1 need updates */
 	{0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
-	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
 	 "Non-buffered flash (64kB)"},
 	/* Fast EEPROM */
 	{0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
-	 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+	 BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
 	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
 	 "EEPROM - fast"},
 	/* Expansion entry 1001 */
 	{0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
-	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
 	 "Entry 1001"},
 	/* Expansion entry 1010 */
 	{0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
-	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
 	 "Entry 1010"},
 	/* ATMEL AT45DB011B (buffered flash) */
 	{0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
-	 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
 	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
 	 "Buffered flash (128kB)"},
 	/* Expansion entry 1100 */
 	{0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
-	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
 	 "Entry 1100"},
 	/* Expansion entry 1101 */
 	{0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
-	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
 	 "Entry 1101"},
 	/* Ateml Expansion entry 1110 */
 	{0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
-	 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
 	 BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
 	 "Entry 1110 (Atmel)"},
 	/* ATMEL AT45DB021B (buffered flash) */
 	{0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
-	 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
 	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
 	 "Buffered flash (256kB)"},
 };
 
+/*
+ * The BCM5709 controllers transparently handle the
+ * differences between Atmel 264 byte pages and all
+ * flash devices which use 256 byte pages, so no
+ * logical-to-physical mapping is required in the
+ * driver.
+ */
+static struct flash_spec flash_5709 = {
+	.flags		= BCE_NV_BUFFERED,
+	.page_bits	= BCM5709_FLASH_PAGE_BITS,
+	.page_size	= BCM5709_FLASH_PAGE_SIZE,
+	.addr_mask	= BCM5709_FLASH_BYTE_ADDR_MASK,
+	.total_size	= BUFFERED_FLASH_TOTAL_SIZE * 2,
+	.name		= "5709/5716 buffered flash (256kB)",
+};
+
 
 /****************************************************************************/
 /* FreeBSD device entry points.                                             */
@@ -218,19 +262,41 @@ static int  bce_shutdown			(device_t);
 /* BCE Debug Data Structure Dump Routines                                   */
 /****************************************************************************/
 #ifdef BCE_DEBUG
+static u32	bce_reg_rd				(struct bce_softc *, u32);
+static void	bce_reg_wr				(struct bce_softc *, u32, u32);
+static void	bce_reg_wr16			(struct bce_softc *, u32, u16);
+static u32  bce_ctx_rd				(struct bce_softc *, u32, u32);
+static void bce_dump_enet           (struct bce_softc *, struct mbuf *);
 static void bce_dump_mbuf 			(struct bce_softc *, struct mbuf *);
-static void bce_dump_tx_mbuf_chain	(struct bce_softc *, int, int);
-static void bce_dump_rx_mbuf_chain	(struct bce_softc *, int, int);
+static void bce_dump_tx_mbuf_chain	(struct bce_softc *, u16, int);
+static void bce_dump_rx_mbuf_chain	(struct bce_softc *, u16, int);
+#ifdef BCE_USE_SPLIT_HEADER
+static void bce_dump_pg_mbuf_chain	(struct bce_softc *, u16, int);
+#endif
 static void bce_dump_txbd			(struct bce_softc *, int, struct tx_bd *);
 static void bce_dump_rxbd			(struct bce_softc *, int, struct rx_bd *);
+#ifdef BCE_USE_SPLIT_HEADER
+static void bce_dump_pgbd			(struct bce_softc *, int, struct rx_bd *);
+#endif
 static void bce_dump_l2fhdr			(struct bce_softc *, int, struct l2_fhdr *);
-static void bce_dump_tx_chain		(struct bce_softc *, int, int);
-static void bce_dump_rx_chain		(struct bce_softc *, int, int);
+static void bce_dump_ctx			(struct bce_softc *, u16);
+static void bce_dump_ftqs			(struct bce_softc *);
+static void bce_dump_tx_chain		(struct bce_softc *, u16, int);
+static void bce_dump_rx_chain		(struct bce_softc *, u16, int);
+#ifdef BCE_USE_SPLIT_HEADER
+static void bce_dump_pg_chain		(struct bce_softc *, u16, int);
+#endif
 static void bce_dump_status_block	(struct bce_softc *);
 static void bce_dump_stats_block	(struct bce_softc *);
 static void bce_dump_driver_state	(struct bce_softc *);
 static void bce_dump_hw_state		(struct bce_softc *);
+static void bce_dump_mq_regs        (struct bce_softc *);
 static void bce_dump_bc_state		(struct bce_softc *);
+static void bce_dump_txp_state		(struct bce_softc *, int);
+static void bce_dump_rxp_state		(struct bce_softc *, int);
+static void bce_dump_tpat_state		(struct bce_softc *, int);
+static void bce_dump_cp_state		(struct bce_softc *, int);
+static void bce_dump_com_state		(struct bce_softc *, int);
 static void bce_breakpoint			(struct bce_softc *);
 #endif
 
@@ -268,6 +334,7 @@ static int  bce_nvram_write			(struct bc
 /****************************************************************************/
 /*                                                                          */
 /****************************************************************************/
+static void bce_get_media			(struct bce_softc *);
 static void bce_dma_map_addr		(void *, bus_dma_segment_t *, int, int);
 static int  bce_dma_alloc			(device_t);
 static void bce_dma_free			(struct bce_softc *);
@@ -279,19 +346,34 @@ static void bce_release_resources	(struc
 static int  bce_fw_sync				(struct bce_softc *, u32);
 static void bce_load_rv2p_fw		(struct bce_softc *, u32 *, u32, u32);
 static void bce_load_cpu_fw			(struct bce_softc *, struct cpu_reg *, struct fw_info *);
+static void bce_init_rxp_cpu		(struct bce_softc *);
+static void bce_init_txp_cpu 		(struct bce_softc *);
+static void bce_init_tpat_cpu		(struct bce_softc *);
+static void bce_init_cp_cpu		  	(struct bce_softc *);
+static void bce_init_com_cpu	  	(struct bce_softc *);
 static void bce_init_cpus			(struct bce_softc *);
 
+static void	bce_print_adapter_info	(struct bce_softc *);
+static void bce_probe_pci_caps		(device_t, struct bce_softc *);
 static void bce_stop				(struct bce_softc *);
 static int  bce_reset				(struct bce_softc *, u32);
 static int  bce_chipinit 			(struct bce_softc *);
 static int  bce_blockinit 			(struct bce_softc *);
-static int  bce_get_buf				(struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *);
 
 static int  bce_init_tx_chain		(struct bce_softc *);
-static void bce_fill_rx_chain		(struct bce_softc *);
+static void bce_free_tx_chain		(struct bce_softc *);
+
+static int  bce_get_rx_buf			(struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *);
 static int  bce_init_rx_chain		(struct bce_softc *);
+static void bce_fill_rx_chain		(struct bce_softc *);
 static void bce_free_rx_chain		(struct bce_softc *);
-static void bce_free_tx_chain		(struct bce_softc *);
+
+#ifdef BCE_USE_SPLIT_HEADER
+static int  bce_get_pg_buf			(struct bce_softc *, struct mbuf *, u16 *, u16 *);
+static int  bce_init_pg_chain		(struct bce_softc *);
+static void bce_fill_pg_chain		(struct bce_softc *);
+static void bce_free_pg_chain		(struct bce_softc *);
+#endif
 
 static int  bce_tx_encap			(struct bce_softc *, struct mbuf **);
 static void bce_start_locked		(struct ifnet *);
@@ -305,19 +387,16 @@ static void bce_init_locked			(struct bc
 static void bce_init				(void *);
 static void bce_mgmt_init_locked	(struct bce_softc *sc);
 
-static void bce_init_context		(struct bce_softc *);
+static void bce_init_ctx			(struct bce_softc *);
 static void bce_get_mac_addr		(struct bce_softc *);
 static void bce_set_mac_addr		(struct bce_softc *);
 static void bce_phy_intr			(struct bce_softc *);
+static inline u16 bce_get_hw_rx_cons(struct bce_softc *);
 static void bce_rx_intr				(struct bce_softc *);
 static void bce_tx_intr				(struct bce_softc *);
 static void bce_disable_intr		(struct bce_softc *);
-static void bce_enable_intr			(struct bce_softc *);
+static void bce_enable_intr			(struct bce_softc *, int);
 
-#ifdef DEVICE_POLLING
-static void bce_poll_locked			(struct ifnet *, enum poll_cmd, int);
-static void bce_poll				(struct ifnet *, enum poll_cmd, int);
-#endif
 static void bce_intr				(void *);
 static void bce_set_rx_mode			(struct bce_softc *);
 static void bce_stats_update		(struct bce_softc *);
@@ -330,20 +409,28 @@ static void bce_add_sysctls			(struct bc
 /* FreeBSD device dispatch table.                                           */
 /****************************************************************************/
 static device_method_t bce_methods[] = {
-	/* Device interface */
+	/* Device interface (device_if.h) */
 	DEVMETHOD(device_probe,		bce_probe),
 	DEVMETHOD(device_attach,	bce_attach),
 	DEVMETHOD(device_detach,	bce_detach),
 	DEVMETHOD(device_shutdown,	bce_shutdown),
+/* Supported by device interface but not used here. */
+/*	DEVMETHOD(device_identify,	bce_identify),      */
+/*	DEVMETHOD(device_suspend,	bce_suspend),       */
+/*	DEVMETHOD(device_resume,	bce_resume),        */
+/*	DEVMETHOD(device_quiesce,	bce_quiesce),       */
 
-	/* bus interface */
+	/* Bus interface (bus_if.h) */
 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
 	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
 
-	/* MII interface */
+	/* MII interface (miibus_if.h) */
 	DEVMETHOD(miibus_readreg,	bce_miibus_read_reg),
 	DEVMETHOD(miibus_writereg,	bce_miibus_write_reg),
 	DEVMETHOD(miibus_statchg,	bce_miibus_statchg),
+/* Supported by MII interface but not used here.       */
+/*	DEVMETHOD(miibus_linkchg,	bce_miibus_linkchg),   */
+/*	DEVMETHOD(miibus_mediainit,	bce_miibus_mediainit), */
 
 	{ 0, 0 }
 };
@@ -367,19 +454,26 @@ DRIVER_MODULE(miibus, bce, miibus_driver
 /****************************************************************************/
 /* Tunable device values                                                    */
 /****************************************************************************/
-static int bce_tso_enable = TRUE;
-static int bce_msi_enable = 1;
+SYSCTL_NODE(_hw, OID_AUTO, bce, CTLFLAG_RD, 0, "bce driver parameters");
 
 /* Allowable values are TRUE or FALSE */
+static int bce_tso_enable = TRUE;
 TUNABLE_INT("hw.bce.tso_enable", &bce_tso_enable);
-/* Allowable values are 0 (IRQ only) and 1 (IRQ or MSI) */
-TUNABLE_INT("hw.bce.msi_enable", &bce_msi_enable);
-
-SYSCTL_NODE(_hw, OID_AUTO, bce, CTLFLAG_RD, 0, "bce driver parameters");
 SYSCTL_UINT(_hw_bce, OID_AUTO, tso_enable, CTLFLAG_RDTUN, &bce_tso_enable, 0,
 "TSO Enable/Disable");
+
+/* Allowable values are 0 (IRQ), 1 (MSI/IRQ), and 2 (MSI-X/MSI/IRQ) */
+/* ToDo: Add MSI-X support. */
+static int bce_msi_enable = 1;
+TUNABLE_INT("hw.bce.msi_enable", &bce_msi_enable);
 SYSCTL_UINT(_hw_bce, OID_AUTO, msi_enable, CTLFLAG_RDTUN, &bce_msi_enable, 0,
-"MSI | INTx selector");
+"MSI-X|MSI|INTx selector");
+
+/* ToDo: Add tunable to enable/disable strict MTU handling. */
+/* Currently allows "loose" RX MTU checking (i.e. sets the  */
+/* H/W RX MTU to the size of the largest receive buffer, or */
+/* 2048 bytes).                                             */
+
 
 /****************************************************************************/
 /* Device probe function.                                                   */
@@ -411,14 +505,14 @@ bce_probe(device_t dev)
 	svid = pci_get_subvendor(dev);
 	sdid = pci_get_subdevice(dev);
 
-	DBPRINT(sc, BCE_VERBOSE_LOAD, 
+	DBPRINT(sc, BCE_EXTREME_LOAD,
 		"%s(); VID = 0x%04X, DID = 0x%04X, SVID = 0x%04X, "
 		"SDID = 0x%04X\n", __FUNCTION__, vid, did, svid, sdid);
 
 	/* Look through the list of known devices for a match. */
 	while(t->bce_name != NULL) {
 
-		if ((vid == t->bce_vid) && (did == t->bce_did) && 
+		if ((vid == t->bce_vid) && (did == t->bce_did) &&
 			((svid == t->bce_svid) || (t->bce_svid == PCI_ANY_ID)) &&
 			((sdid == t->bce_sdid) || (t->bce_sdid == PCI_ANY_ID))) {
 
@@ -428,7 +522,7 @@ bce_probe(device_t dev)
 				return(ENOMEM);
 
 			/* Print out the device identity. */
-			snprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d)", 
+			snprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d)",
 				t->bce_name,
 			    (((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'),
 			    (pci_read_config(dev, PCIR_REVID, 4) & 0xf));
@@ -445,6 +539,109 @@ bce_probe(device_t dev)
 
 
 /****************************************************************************/
+/* PCI Capabilities Probe Function.                                         */
+/*                                                                          */
+/* Walks the PCI capabiites list for the device to find what features are   */
+/* supported.                                                               */
+/*                                                                          */
+/* Returns:                                                                 */
+/*   None.                                                                  */
+/****************************************************************************/
+static void
+bce_print_adapter_info(struct bce_softc *sc)
+{
+	DBENTER(BCE_VERBOSE_LOAD);
+
+	BCE_PRINTF("ASIC (0x%08X); ", sc->bce_chipid);
+	printf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A',
+		((BCE_CHIP_ID(sc) & 0x0ff0) >> 4));
+
+	/* Bus info. */
+	if (sc->bce_flags & BCE_PCIE_FLAG) {
+		printf("Bus (PCIe x%d, ", sc->link_width);
+		switch (sc->link_speed) {
+			case 1: printf("2.5Gbps); "); break;
+			case 2:	printf("5Gbps); "); break;
+			default: printf("Unknown link speed); ");
+		}
+	} else {
+		printf("Bus (PCI%s, %s, %dMHz); ",
+			((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""),
+			((sc->bce_flags & BCE_PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
+			sc->bus_speed_mhz);
+	}
+
+	/* Firmware version and device features. */
+	printf("F/W (0x%08X); Flags( ", sc->bce_fw_ver);
+#ifdef BCE_USE_SPLIT_HEADER
+	printf("SPLT ");
+#endif
+	if (sc->bce_flags & BCE_MFW_ENABLE_FLAG)
+		printf("MFW ");
+	if (sc->bce_flags & BCE_USING_MSI_FLAG)
+		printf("MSI ");
+	if (sc->bce_flags & BCE_USING_MSIX_FLAG)
+		printf("MSI-X ");
+	if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)
+		printf("2.5G ");
+	printf(")\n");
+
+	DBEXIT(BCE_VERBOSE_LOAD);
+}
+
+
+/****************************************************************************/
+/* PCI Capabilities Probe Function.                                         */
+/*                                                                          */
+/* Walks the PCI capabiites list for the device to find what features are   */
+/* supported.                                                               */
+/*                                                                          */
+/* Returns:                                                                 */
+/*   None.                                                                  */
+/****************************************************************************/
+static void
+bce_probe_pci_caps(device_t dev, struct bce_softc *sc)
+{
+	u32 reg;
+
+	DBENTER(BCE_VERBOSE_LOAD);
+
+	/* Check if PCI-X capability is enabled. */
+	if (pci_find_extcap(dev, PCIY_PCIX, &reg) == 0) {
+		if (reg != 0)
+			sc->bce_cap_flags |= BCE_PCIX_CAPABLE_FLAG;
+	}
+
+	/* Check if PCIe capability is enabled. */
+	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
+		if (reg != 0) {
+			u16 link_status = pci_read_config(dev, reg + 0x12, 2);
+			DBPRINT(sc, BCE_INFO_LOAD, "PCIe link_status = 0x%08X\n",
+				link_status);
+			sc->link_speed = link_status & 0xf;
+			sc->link_width = (link_status >> 4) & 0x3f;
+			sc->bce_cap_flags |= BCE_PCIE_CAPABLE_FLAG;
+			sc->bce_flags |= BCE_PCIE_FLAG;
+		}
+	}
+
+	/* Check if MSI capability is enabled. */
+	if (pci_find_extcap(dev, PCIY_MSI, &reg) == 0) {
+		if (reg != 0)
+			sc->bce_cap_flags |= BCE_MSI_CAPABLE_FLAG;
+	}
+
+	/* Check if MSI-X capability is enabled. */
+	if (pci_find_extcap(dev, PCIY_MSIX, &reg) == 0) {
+		if (reg != 0)
+			sc->bce_cap_flags |= BCE_MSIX_CAPABLE_FLAG;
+	}
+
+	DBEXIT(BCE_VERBOSE_LOAD);
+}
+
+
+/****************************************************************************/
 /* Device attach function.                                                  */
 /*                                                                          */
 /* Allocates device resources, performs secondary chip identification,      */
@@ -460,21 +657,19 @@ bce_attach(device_t dev)
 	struct bce_softc *sc;
 	struct ifnet *ifp;
 	u32 val;
-	int count, mbuf, rid, rc = 0;
+	int error, rid, rc = 0;
 
 	sc = device_get_softc(dev);
 	sc->bce_dev = dev;
 
-	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
+	DBENTER(BCE_VERBOSE_LOAD | BCE_VERBOSE_RESET);
 
-	mbuf = device_get_unit(dev);
+	sc->bce_unit = device_get_unit(dev);
 
 	/* Set initial device and PHY flags */
 	sc->bce_flags = 0;
 	sc->bce_phy_flags = 0;
 
-	sc->bce_unit = mbuf;
-
 	pci_enable_busmaster(dev);
 
 	/* Allocate PCI memory resources. */
@@ -483,7 +678,7 @@ bce_attach(device_t dev)
 		&rid, RF_ACTIVE | PCI_RF_DENSE);
 
 	if (sc->bce_res_mem == NULL) {
-		BCE_PRINTF("%s(%d): PCI memory allocation failed\n", 
+		BCE_PRINTF("%s(%d): PCI memory allocation failed\n",
 			__FILE__, __LINE__);
 		rc = ENXIO;
 		goto bce_attach_fail;
@@ -494,25 +689,74 @@ bce_attach(device_t dev)
 	sc->bce_bhandle = rman_get_bushandle(sc->bce_res_mem);
 	sc->bce_vhandle = (vm_offset_t) rman_get_virtual(sc->bce_res_mem);
 
-	/* If MSI is enabled in the driver, get the vector count. */
-	count = bce_msi_enable ? pci_msi_count(dev) : 0;
+	bce_probe_pci_caps(dev, sc);
 
-	/* Allocate PCI IRQ resources. */
-	if (count == 1 && pci_alloc_msi(dev, &count) == 0 && count == 1) {
-		rid = 1;
-		sc->bce_flags |= BCE_USING_MSI_FLAG;
-		DBPRINT(sc, BCE_VERBOSE_LOAD, 
-			"Allocating %d MSI interrupt(s)\n", count);
-	} else {
+	rid = 1;
+#if 0
+	/* Try allocating MSI-X interrupts. */
+	if ((sc->bce_cap_flags & BCE_MSIX_CAPABLE_FLAG) &&
+		(bce_msi_enable >= 2) &&
+		((sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+		&rid, RF_ACTIVE)) != NULL)) {
+
+		msi_needed = sc->bce_msi_count = 1;
+
+		if (((error = pci_alloc_msix(dev, &sc->bce_msi_count)) != 0) ||
+			(sc->bce_msi_count != msi_needed)) {
+			BCE_PRINTF("%s(%d): MSI-X allocation failed! Requested = %d,"
+				"Received = %d, error = %d\n", __FILE__, __LINE__,
+				msi_needed, sc->bce_msi_count, error);
+			sc->bce_msi_count = 0;
+			pci_release_msi(dev);
+			bus_release_resource(dev, SYS_RES_MEMORY, rid,
+				sc->bce_res_irq);
+			sc->bce_res_irq = NULL;
+		} else {
+			DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI-X interrupt.\n",
+				__FUNCTION__);
+			sc->bce_flags |= BCE_USING_MSIX_FLAG;
+			sc->bce_intr = bce_intr;
+		}
+	}
+#endif
+
+	/* Try allocating a MSI interrupt. */
+	if ((sc->bce_cap_flags & BCE_MSI_CAPABLE_FLAG) &&
+		(bce_msi_enable >= 1) && (sc->bce_msi_count == 0)) {
+		sc->bce_msi_count = 1;
+		if ((error = pci_alloc_msi(dev, &sc->bce_msi_count)) != 0) {
+			BCE_PRINTF("%s(%d): MSI allocation failed! error = %d\n",
+				__FILE__, __LINE__, error);
+			sc->bce_msi_count = 0;
+			pci_release_msi(dev);
+		} else {
+			DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI interrupt.\n",
+				__FUNCTION__);
+			sc->bce_flags |= BCE_USING_MSI_FLAG;
+			if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
+				(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716))
+				sc->bce_flags |= BCE_ONE_SHOT_MSI_FLAG;
+			sc->bce_irq_rid = 1;
+			sc->bce_intr = bce_intr;
+		}
+	}
+
+	/* Try allocating a legacy interrupt. */
+	if (sc->bce_msi_count == 0) {
+		DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using INTx interrupt.\n",
+			__FUNCTION__);
 		rid = 0;
-		DBPRINT(sc, BCE_VERBOSE_LOAD, "Allocating IRQ interrupt\n");
+		sc->bce_intr = bce_intr;
 	}
 
-	sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-	    RF_SHAREABLE | RF_ACTIVE);
+	sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+		&rid, RF_SHAREABLE | RF_ACTIVE);
+
+	sc->bce_irq_rid = rid;
 
+	/* Report any IRQ allocation errors. */
 	if (sc->bce_res_irq == NULL) {
-		BCE_PRINTF("%s(%d): PCI map interrupt failed!\n", 
+		BCE_PRINTF("%s(%d): PCI map interrupt failed!\n",
 			__FILE__, __LINE__);
 		rc = ENXIO;
 		goto bce_attach_fail;
@@ -540,18 +784,22 @@ bce_attach(device_t dev)
 		case BCE_CHIP_ID_5706_A1:
 		case BCE_CHIP_ID_5708_A0:
 		case BCE_CHIP_ID_5708_B0:
+		case BCE_CHIP_ID_5709_A0:
+		case BCE_CHIP_ID_5709_B0:
+		case BCE_CHIP_ID_5709_B1:
+		case BCE_CHIP_ID_5709_B2:
 			BCE_PRINTF("%s(%d): Unsupported controller revision (%c%d)!\n",
-				__FILE__, __LINE__, 
+				__FILE__, __LINE__,
 				(((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'),
 			    (pci_read_config(dev, PCIR_REVID, 4) & 0xf));
 			rc = ENODEV;
 			goto bce_attach_fail;
 	}
 
-	/* 
-	 * The embedded PCIe to PCI-X bridge (EPB) 
-	 * in the 5708 cannot address memory above 
-	 * 40 bits (E7_5708CB1_23043 & E6_5708SB1_23043). 
+	/*
+	 * The embedded PCIe to PCI-X bridge (EPB)
+	 * in the 5708 cannot address memory above
+	 * 40 bits (E7_5708CB1_23043 & E6_5708SB1_23043).
 	 */
 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708)
 		sc->max_bus_addr = BCE_BUS_SPACE_MAXADDR;
@@ -565,25 +813,23 @@ bce_attach(device_t dev)
 	 */
 	val = REG_RD_IND(sc, BCE_SHM_HDR_SIGNATURE);
 	if ((val & BCE_SHM_HDR_SIGNATURE_SIG_MASK) == BCE_SHM_HDR_SIGNATURE_SIG)
-		sc->bce_shmem_base = REG_RD_IND(sc, BCE_SHM_HDR_ADDR_0);
+		/* Multi-port devices use different offsets in shared memory. */
+		sc->bce_shmem_base = REG_RD_IND(sc, BCE_SHM_HDR_ADDR_0 +
+			(pci_get_function(sc->bce_dev) << 2));
 	else
 		sc->bce_shmem_base = HOST_VIEW_SHMEM_BASE;
 
-	DBPRINT(sc, BCE_VERBOSE_FIRMWARE, "%s(): bce_shmem_base = 0x%08X\n", 
+	DBPRINT(sc, BCE_VERBOSE_FIRMWARE, "%s(): bce_shmem_base = 0x%08X\n",
 		__FUNCTION__, sc->bce_shmem_base);
 
-	sc->bce_fw_ver = REG_RD_IND(sc, sc->bce_shmem_base + 
+	/* Fetch the bootcode revision. */
+	sc->bce_fw_ver = REG_RD_IND(sc, sc->bce_shmem_base +
 		BCE_DEV_INFO_BC_REV);
-	DBPRINT(sc, BCE_INFO_FIRMWARE, "%s(): bce_fw_ver = 0x%08X\n", 
-		__FUNCTION__, sc->bce_fw_ver);
 
 	/* Check if any management firmware is running. */
 	val = REG_RD_IND(sc, sc->bce_shmem_base + BCE_PORT_FEATURE);
-	if (val & (BCE_PORT_FEATURE_ASF_ENABLED | BCE_PORT_FEATURE_IMD_ENABLED)) {
+	if (val & (BCE_PORT_FEATURE_ASF_ENABLED | BCE_PORT_FEATURE_IMD_ENABLED))
 		sc->bce_flags |= BCE_MFW_ENABLE_FLAG;
-		DBPRINT(sc, BCE_INFO_LOAD, "%s(): BCE_MFW_ENABLE_FLAG\n", 
-			__FUNCTION__);
-	}
 
 	/* Get PCI bus information (speed and type). */
 	val = REG_RD(sc, BCE_PCICFG_MISC_STATUS);
@@ -632,7 +878,7 @@ bce_attach(device_t dev)
 
 	/* Reset the controller and announce to bootcode that driver is present. */
 	if (bce_reset(sc, BCE_DRV_MSG_CODE_RESET)) {
-		BCE_PRINTF("%s(%d): Controller reset failed!\n", 
+		BCE_PRINTF("%s(%d): Controller reset failed!\n",
 			__FILE__, __LINE__);
 		rc = ENXIO;
 		goto bce_attach_fail;
@@ -662,7 +908,7 @@ bce_attach(device_t dev)
 	 * should be ready before generating an
 	 * interrupt while ticks control how long
 	 * a BD can sit in the chain before
-	 * generating an interrupt.  Set the default 
+	 * generating an interrupt.  Set the default
 	 * values for the RX and TX chains.
 	 */
 
@@ -693,33 +939,14 @@ bce_attach(device_t dev)
 	/* Update statistics once every second. */
 	sc->bce_stats_ticks = 1000000 & 0xffff00;
 
-	/*
-	 * The SerDes based NetXtreme II controllers
-	 * that support 2.5Gb operation (currently 
-	 * 5708S) use a PHY at address 2, otherwise 
-	 * the PHY is present at address 1.
-	 */
-	sc->bce_phy_addr = 1;
-
-	if (BCE_CHIP_BOND_ID(sc) & BCE_CHIP_BOND_ID_SERDES_BIT) {
-		sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG;
-		sc->bce_flags |= BCE_NO_WOL_FLAG;
-		if (BCE_CHIP_NUM(sc) != BCE_CHIP_NUM_5706) {
-			sc->bce_phy_addr = 2;
-			val = REG_RD_IND(sc, sc->bce_shmem_base +
-					 BCE_SHARED_HW_CFG_CONFIG);
-			if (val & BCE_SHARED_HW_CFG_PHY_2_5G) {
-				sc->bce_phy_flags |= BCE_PHY_2_5G_CAPABLE_FLAG;
-				DBPRINT(sc, BCE_INFO_LOAD, "Found 2.5Gb capable adapter\n");
-			}
-		}
-	}
+	/* Find the media type for the adapter. */
+	bce_get_media(sc);
 
 	/* Store data needed by PHY driver for backplane applications */
 	sc->bce_shared_hw_cfg = REG_RD_IND(sc, sc->bce_shmem_base +
 		BCE_SHARED_HW_CFG_CONFIG);
 	sc->bce_port_hw_cfg   = REG_RD_IND(sc, sc->bce_shmem_base +
-		BCE_SHARED_HW_CFG_CONFIG);
+		BCE_PORT_HW_CFG_CONFIG);
 
 	/* Allocate DMA memory resources. */
 	if (bce_dma_alloc(dev)) {
@@ -732,7 +959,7 @@ bce_attach(device_t dev)
 	/* Allocate an ifnet structure. */
 	ifp = sc->bce_ifp = if_alloc(IFT_ETHER);
 	if (ifp == NULL) {
-		BCE_PRINTF("%s(%d): Interface allocation failed!\n", 
+		BCE_PRINTF("%s(%d): Interface allocation failed!\n",
 			__FILE__, __LINE__);
 		rc = ENXIO;
 		goto bce_attach_fail;
@@ -757,10 +984,24 @@ bce_attach(device_t dev)
 
 	ifp->if_capenable    = ifp->if_capabilities;
 
-	/* Assume a standard 1500 byte MTU size for mbuf allocations. */
-	sc->mbuf_alloc_size  = MCLBYTES;
-#ifdef DEVICE_POLLING
-	ifp->if_capabilities |= IFCAP_POLLING;
+	/*
+	 * Assume standard mbuf sizes for buffer allocation.
+	 * This may change later if the MTU size is set to
+	 * something other than 1500.
+	 */
+#ifdef BCE_USE_SPLIT_HEADER
+	sc->rx_bd_mbuf_alloc_size = MHLEN;
+	/* Make sure offset is 16 byte aligned for hardware. */
+	sc->rx_bd_mbuf_align_pad  = roundup2((MSIZE - MHLEN), 16) -
+		(MSIZE - MHLEN);
+	sc->rx_bd_mbuf_data_len   = sc->rx_bd_mbuf_alloc_size -
+		sc->rx_bd_mbuf_align_pad;
+	sc->pg_bd_mbuf_alloc_size = MCLBYTES;
+#else
+	sc->rx_bd_mbuf_alloc_size = MCLBYTES;
+	sc->rx_bd_mbuf_align_pad  = roundup2(MCLBYTES, 16) - MCLBYTES;
+	sc->rx_bd_mbuf_data_len   = sc->rx_bd_mbuf_alloc_size -
+		sc->rx_bd_mbuf_align_pad;
 #endif
 
 	ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD;
@@ -775,7 +1016,7 @@ bce_attach(device_t dev)
 	/* Check for an MII child bus by probing the PHY. */
 	if (mii_phy_probe(dev, &sc->bce_miibus, bce_ifmedia_upd,
 		bce_ifmedia_sts)) {
-		BCE_PRINTF("%s(%d): No PHY found on child MII bus!\n", 
+		BCE_PRINTF("%s(%d): No PHY found on child MII bus!\n",
 			__FILE__, __LINE__);
 		rc = ENXIO;
 		goto bce_attach_fail;
@@ -793,30 +1034,31 @@ bce_attach(device_t dev)
 #endif
 
 	/* Hookup IRQ last. */
-	rc = bus_setup_intr(dev, sc->bce_res_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL,
-	   bce_intr, sc, &sc->bce_intrhand);
+	rc = bus_setup_intr(dev, sc->bce_res_irq, INTR_TYPE_NET | INTR_MPSAFE,
+		NULL, bce_intr, sc, &sc->bce_intrhand);
 
 	if (rc) {
-		BCE_PRINTF("%s(%d): Failed to setup IRQ!\n", 
+		BCE_PRINTF("%s(%d): Failed to setup IRQ!\n",
 			__FILE__, __LINE__);
 		bce_detach(dev);
 		goto bce_attach_exit;
 	}
 
-	/* 
-	 * At this point we've acquired all the resources 
+	/*
+	 * At this point we've acquired all the resources
 	 * we need to run so there's no turning back, we're
 	 * cleared for launch.
 	 */
 
 	/* Print some important debugging info. */
-	DBRUN(BCE_INFO, bce_dump_driver_state(sc));
+	DBRUNMSG(BCE_INFO, bce_dump_driver_state(sc));
 
 	/* Add the supported sysctls to the kernel. */
 	bce_add_sysctls(sc);
 
 	BCE_LOCK(sc);
-	/* 
+
+	/*
 	 * The chip reset earlier notified the bootcode that
 	 * a driver is present.  We now need to start our pulse
 	 * routine so that the bootcode is reminded that we're
@@ -828,21 +1070,9 @@ bce_attach(device_t dev)
 	BCE_UNLOCK(sc);
 
 	/* Finally, print some useful adapter info */
-	BCE_PRINTF("ASIC (0x%08X); ", sc->bce_chipid);
-	printf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A',
-		((BCE_CHIP_ID(sc) & 0x0ff0) >> 4));
-	printf("Bus (PCI%s, %s, %dMHz); ",
-		((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""),
-		((sc->bce_flags & BCE_PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
-		sc->bus_speed_mhz);
-	printf("F/W (0x%08X); Flags( ", sc->bce_fw_ver);
-	if (sc->bce_flags & BCE_MFW_ENABLE_FLAG)
-		printf("MFW ");
-	if (sc->bce_flags & BCE_USING_MSI_FLAG)
-		printf("MSI ");
-	if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)
-		printf("2.5G ");
-	printf(")\n");
+	bce_print_adapter_info(sc);
+	DBPRINT(sc, BCE_FATAL, "%s(): sc = %p\n",
+		__FUNCTION__, sc);
 
 	goto bce_attach_exit;
 
@@ -851,7 +1081,7 @@ bce_attach_fail:
 
 bce_attach_exit:
 
-	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
+	DBEXIT(BCE_VERBOSE_LOAD | BCE_VERBOSE_RESET);
 
 	return(rc);
 }
@@ -872,26 +1102,23 @@ bce_detach(device_t dev)
 	struct ifnet *ifp;
 	u32 msg;
 
-	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
+	DBENTER(BCE_VERBOSE_UNLOAD | BCE_VERBOSE_RESET);
 
 	ifp = sc->bce_ifp;
 
-#ifdef DEVICE_POLLING
-	if (ifp->if_capenable & IFCAP_POLLING)
-		ether_poll_deregister(ifp);
-#endif
+	/* Stop and reset the controller. */
+	BCE_LOCK(sc);
 
 	/* Stop the pulse so the bootcode can go to driver absent state. */
 	callout_stop(&sc->bce_pulse_callout);
 
-	/* Stop and reset the controller. */
-	BCE_LOCK(sc);
 	bce_stop(sc);
 	if (sc->bce_flags & BCE_NO_WOL_FLAG)
 		msg = BCE_DRV_MSG_CODE_UNLOAD_LNK_DN;
 	else
 		msg = BCE_DRV_MSG_CODE_UNLOAD;
 	bce_reset(sc, msg);
+
 	BCE_UNLOCK(sc);
 
 	ether_ifdetach(ifp);
@@ -903,7 +1130,7 @@ bce_detach(device_t dev)
 	/* Release all remaining resources. */
 	bce_release_resources(sc);
 
-	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
+	DBEXIT(BCE_VERBOSE_UNLOAD | BCE_VERBOSE_RESET);
 
 	return(0);
 }
@@ -923,7 +1150,7 @@ bce_shutdown(device_t dev)
 	struct bce_softc *sc = device_get_softc(dev);
 	u32 msg;
 
-	DBPRINT(sc, BCE_VERBOSE_SPECIAL, "Entering %s()\n", __FUNCTION__);
+	DBENTER(BCE_VERBOSE);
 
 	BCE_LOCK(sc);
 	bce_stop(sc);
@@ -933,13 +1160,60 @@ bce_shutdown(device_t dev)
 		msg = BCE_DRV_MSG_CODE_UNLOAD;
 	bce_reset(sc, msg);
 	BCE_UNLOCK(sc);
-	
-	DBPRINT(sc, BCE_VERBOSE_SPECIAL, "Exiting %s()\n", __FUNCTION__);
+
+	DBEXIT(BCE_VERBOSE);
 
 	return (0);
 }
 
 
+#ifdef BCE_DEBUG
+/****************************************************************************/
+/* Register read.                                                           */
+/*                                                                          */
+/* Returns:                                                                 */
+/*   The value of the register.                                             */
+/****************************************************************************/
+static u32
+bce_reg_rd(struct bce_softc *sc, u32 offset)
+{
+	u32 val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, offset);
+	DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
+		__FUNCTION__, offset, val);
+	return val;
+}
+
+
+/****************************************************************************/
+/* Register write (16 bit).                                                 */
+/*                                                                          */
+/* Returns:                                                                 */
+/*   Nothing.                                                               */
+/****************************************************************************/
+static void
+bce_reg_wr16(struct bce_softc *sc, u32 offset, u16 val)
+{
+	DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%04X\n",
+		__FUNCTION__, offset, val);
+	bus_space_write_2(sc->bce_btag, sc->bce_bhandle, offset, val);
+}
+
+
+/****************************************************************************/
+/* Register write.                                                          */
+/*                                                                          */
+/* Returns:                                                                 */
+/*   Nothing.                                                               */
+/****************************************************************************/
+static void
+bce_reg_wr(struct bce_softc *sc, u32 offset, u32 val)
+{
+	DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
+		__FUNCTION__, offset, val);
+	bus_space_write_4(sc->bce_btag, sc->bce_bhandle, offset, val);
+}
+#endif
+
 /****************************************************************************/
 /* Indirect register read.                                                  */
 /*                                                                          */
@@ -961,7 +1235,7 @@ bce_reg_rd_ind(struct bce_softc *sc, u32
 	{
 		u32 val;
 		val = pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4);
-		DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n",
+		DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
 			__FUNCTION__, offset, val);
 		return val;
 	}
@@ -987,7 +1261,7 @@ bce_reg_wr_ind(struct bce_softc *sc, u32
 	device_t dev;
 	dev = sc->bce_dev;
 
-	DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n",
+	DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
 		__FUNCTION__, offset, val);
 
 	pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4);
@@ -995,6 +1269,58 @@ bce_reg_wr_ind(struct bce_softc *sc, u32
 }

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811102240.mAAMeGfs084286>