xref: /dflybsd-src/sys/dev/netif/bce/if_bce.c (revision b51a4d98e96b0794eb3623d6874ea0f194649bc2)
143c2aeb0SSepherosa Ziehau /*-
243c2aeb0SSepherosa Ziehau  * Copyright (c) 2006-2007 Broadcom Corporation
343c2aeb0SSepherosa Ziehau  *	David Christensen <davidch@broadcom.com>.  All rights reserved.
443c2aeb0SSepherosa Ziehau  *
543c2aeb0SSepherosa Ziehau  * Redistribution and use in source and binary forms, with or without
643c2aeb0SSepherosa Ziehau  * modification, are permitted provided that the following conditions
743c2aeb0SSepherosa Ziehau  * are met:
843c2aeb0SSepherosa Ziehau  *
943c2aeb0SSepherosa Ziehau  * 1. Redistributions of source code must retain the above copyright
1043c2aeb0SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer.
1143c2aeb0SSepherosa Ziehau  * 2. Redistributions in binary form must reproduce the above copyright
1243c2aeb0SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer in the
1343c2aeb0SSepherosa Ziehau  *    documentation and/or other materials provided with the distribution.
1443c2aeb0SSepherosa Ziehau  * 3. Neither the name of Broadcom Corporation nor the name of its contributors
1543c2aeb0SSepherosa Ziehau  *    may be used to endorse or promote products derived from this software
1643c2aeb0SSepherosa Ziehau  *    without specific prior written consent.
1743c2aeb0SSepherosa Ziehau  *
1843c2aeb0SSepherosa Ziehau  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
1943c2aeb0SSepherosa Ziehau  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2043c2aeb0SSepherosa Ziehau  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2143c2aeb0SSepherosa Ziehau  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
2243c2aeb0SSepherosa Ziehau  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2343c2aeb0SSepherosa Ziehau  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2443c2aeb0SSepherosa Ziehau  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2543c2aeb0SSepherosa Ziehau  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2643c2aeb0SSepherosa Ziehau  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2743c2aeb0SSepherosa Ziehau  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2843c2aeb0SSepherosa Ziehau  * THE POSSIBILITY OF SUCH DAMAGE.
2943c2aeb0SSepherosa Ziehau  *
3043c2aeb0SSepherosa Ziehau  * $FreeBSD: src/sys/dev/bce/if_bce.c,v 1.31 2007/05/16 23:34:11 davidch Exp $
3143c2aeb0SSepherosa Ziehau  */
3243c2aeb0SSepherosa Ziehau 
3343c2aeb0SSepherosa Ziehau /*
3443c2aeb0SSepherosa Ziehau  * The following controllers are supported by this driver:
3543c2aeb0SSepherosa Ziehau  *   BCM5706C A2, A3
36d0092544SSepherosa Ziehau  *   BCM5706S A2, A3
3743c2aeb0SSepherosa Ziehau  *   BCM5708C B1, B2
38d0092544SSepherosa Ziehau  *   BCM5708S B1, B2
39d0092544SSepherosa Ziehau  *   BCM5709C A1, C0
40d0092544SSepherosa Ziehau  *   BCM5716  C0
4143c2aeb0SSepherosa Ziehau  *
4243c2aeb0SSepherosa Ziehau  * The following controllers are not supported by this driver:
4343c2aeb0SSepherosa Ziehau  *   BCM5706C A0, A1
44d0092544SSepherosa Ziehau  *   BCM5706S A0, A1
4543c2aeb0SSepherosa Ziehau  *   BCM5708C A0, B0
46d0092544SSepherosa Ziehau  *   BCM5708S A0, B0
47d0092544SSepherosa Ziehau  *   BCM5709C A0, B0, B1
48d0092544SSepherosa Ziehau  *   BCM5709S A0, A1, B0, B1, B2, C0
4943c2aeb0SSepherosa Ziehau  */
5043c2aeb0SSepherosa Ziehau 
5143c2aeb0SSepherosa Ziehau #include "opt_bce.h"
5243c2aeb0SSepherosa Ziehau #include "opt_polling.h"
5343c2aeb0SSepherosa Ziehau 
5443c2aeb0SSepherosa Ziehau #include <sys/param.h>
5543c2aeb0SSepherosa Ziehau #include <sys/bus.h>
5643c2aeb0SSepherosa Ziehau #include <sys/endian.h>
5743c2aeb0SSepherosa Ziehau #include <sys/kernel.h>
589db4b353SSepherosa Ziehau #include <sys/interrupt.h>
5943c2aeb0SSepherosa Ziehau #include <sys/mbuf.h>
6043c2aeb0SSepherosa Ziehau #include <sys/malloc.h>
6143c2aeb0SSepherosa Ziehau #include <sys/queue.h>
6243c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
6343c2aeb0SSepherosa Ziehau #include <sys/random.h>
6443c2aeb0SSepherosa Ziehau #endif
6543c2aeb0SSepherosa Ziehau #include <sys/rman.h>
6643c2aeb0SSepherosa Ziehau #include <sys/serialize.h>
6743c2aeb0SSepherosa Ziehau #include <sys/socket.h>
6843c2aeb0SSepherosa Ziehau #include <sys/sockio.h>
6943c2aeb0SSepherosa Ziehau #include <sys/sysctl.h>
7043c2aeb0SSepherosa Ziehau 
7143c2aeb0SSepherosa Ziehau #include <net/bpf.h>
7243c2aeb0SSepherosa Ziehau #include <net/ethernet.h>
7343c2aeb0SSepherosa Ziehau #include <net/if.h>
7443c2aeb0SSepherosa Ziehau #include <net/if_arp.h>
7543c2aeb0SSepherosa Ziehau #include <net/if_dl.h>
7643c2aeb0SSepherosa Ziehau #include <net/if_media.h>
7743c2aeb0SSepherosa Ziehau #include <net/if_types.h>
7843c2aeb0SSepherosa Ziehau #include <net/ifq_var.h>
7943c2aeb0SSepherosa Ziehau #include <net/vlan/if_vlan_var.h>
80b637f170SSepherosa Ziehau #include <net/vlan/if_vlan_ether.h>
8143c2aeb0SSepherosa Ziehau 
8243c2aeb0SSepherosa Ziehau #include <dev/netif/mii_layer/mii.h>
8343c2aeb0SSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h>
8443c2aeb0SSepherosa Ziehau 
8543c2aeb0SSepherosa Ziehau #include <bus/pci/pcireg.h>
8643c2aeb0SSepherosa Ziehau #include <bus/pci/pcivar.h>
8743c2aeb0SSepherosa Ziehau 
8843c2aeb0SSepherosa Ziehau #include "miibus_if.h"
8943c2aeb0SSepherosa Ziehau 
909382dc55SSepherosa Ziehau #include <dev/netif/bce/if_bcereg.h>
919382dc55SSepherosa Ziehau #include <dev/netif/bce/if_bcefw.h>
9243c2aeb0SSepherosa Ziehau 
9343c2aeb0SSepherosa Ziehau /****************************************************************************/
9443c2aeb0SSepherosa Ziehau /* BCE Debug Options                                                        */
9543c2aeb0SSepherosa Ziehau /****************************************************************************/
9643c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
9743c2aeb0SSepherosa Ziehau 
9843c2aeb0SSepherosa Ziehau static uint32_t	bce_debug = BCE_WARN;
9943c2aeb0SSepherosa Ziehau 
10043c2aeb0SSepherosa Ziehau /*
10143c2aeb0SSepherosa Ziehau  *          0 = Never
10243c2aeb0SSepherosa Ziehau  *          1 = 1 in 2,147,483,648
10343c2aeb0SSepherosa Ziehau  *        256 = 1 in     8,388,608
10443c2aeb0SSepherosa Ziehau  *       2048 = 1 in     1,048,576
10543c2aeb0SSepherosa Ziehau  *      65536 = 1 in        32,768
10643c2aeb0SSepherosa Ziehau  *    1048576 = 1 in         2,048
10743c2aeb0SSepherosa Ziehau  *  268435456 = 1 in             8
10843c2aeb0SSepherosa Ziehau  *  536870912 = 1 in             4
10943c2aeb0SSepherosa Ziehau  * 1073741824 = 1 in             2
11043c2aeb0SSepherosa Ziehau  *
11143c2aeb0SSepherosa Ziehau  * bce_debug_l2fhdr_status_check:
11243c2aeb0SSepherosa Ziehau  *     How often the l2_fhdr frame error check will fail.
11343c2aeb0SSepherosa Ziehau  *
11443c2aeb0SSepherosa Ziehau  * bce_debug_unexpected_attention:
11543c2aeb0SSepherosa Ziehau  *     How often the unexpected attention check will fail.
11643c2aeb0SSepherosa Ziehau  *
11743c2aeb0SSepherosa Ziehau  * bce_debug_mbuf_allocation_failure:
11843c2aeb0SSepherosa Ziehau  *     How often to simulate an mbuf allocation failure.
11943c2aeb0SSepherosa Ziehau  *
12043c2aeb0SSepherosa Ziehau  * bce_debug_dma_map_addr_failure:
12143c2aeb0SSepherosa Ziehau  *     How often to simulate a DMA mapping failure.
12243c2aeb0SSepherosa Ziehau  *
12343c2aeb0SSepherosa Ziehau  * bce_debug_bootcode_running_failure:
12443c2aeb0SSepherosa Ziehau  *     How often to simulate a bootcode failure.
12543c2aeb0SSepherosa Ziehau  */
12643c2aeb0SSepherosa Ziehau static int	bce_debug_l2fhdr_status_check = 0;
12743c2aeb0SSepherosa Ziehau static int	bce_debug_unexpected_attention = 0;
12843c2aeb0SSepherosa Ziehau static int	bce_debug_mbuf_allocation_failure = 0;
12943c2aeb0SSepherosa Ziehau static int	bce_debug_dma_map_addr_failure = 0;
13043c2aeb0SSepherosa Ziehau static int	bce_debug_bootcode_running_failure = 0;
13143c2aeb0SSepherosa Ziehau 
13243c2aeb0SSepherosa Ziehau #endif	/* BCE_DEBUG */
13343c2aeb0SSepherosa Ziehau 
13443c2aeb0SSepherosa Ziehau 
13543c2aeb0SSepherosa Ziehau /****************************************************************************/
13643c2aeb0SSepherosa Ziehau /* PCI Device ID Table                                                      */
13743c2aeb0SSepherosa Ziehau /*                                                                          */
13843c2aeb0SSepherosa Ziehau /* Used by bce_probe() to identify the devices supported by this driver.    */
13943c2aeb0SSepherosa Ziehau /****************************************************************************/
14043c2aeb0SSepherosa Ziehau #define BCE_DEVDESC_MAX		64
14143c2aeb0SSepherosa Ziehau 
14243c2aeb0SSepherosa Ziehau static struct bce_type bce_devs[] = {
14343c2aeb0SSepherosa Ziehau 	/* BCM5706C Controllers and OEM boards. */
14443c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  HP_VENDORID, 0x3101,
14543c2aeb0SSepherosa Ziehau 		"HP NC370T Multifunction Gigabit Server Adapter" },
14643c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  HP_VENDORID, 0x3106,
14743c2aeb0SSepherosa Ziehau 		"HP NC370i Multifunction Gigabit Server Adapter" },
1483482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  HP_VENDORID, 0x3070,
1493482f06cSSepherosa Ziehau 		"HP NC380T PCIe DP Multifunc Gig Server Adapter" },
1503482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  HP_VENDORID, 0x1709,
1513482f06cSSepherosa Ziehau 		"HP NC371i Multifunction Gigabit Server Adapter" },
15243c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  PCI_ANY_ID,  PCI_ANY_ID,
15343c2aeb0SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5706 1000Base-T" },
15443c2aeb0SSepherosa Ziehau 
15543c2aeb0SSepherosa Ziehau 	/* BCM5706S controllers and OEM boards. */
15643c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, HP_VENDORID, 0x3102,
15743c2aeb0SSepherosa Ziehau 		"HP NC370F Multifunction Gigabit Server Adapter" },
15843c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, PCI_ANY_ID,  PCI_ANY_ID,
15943c2aeb0SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5706 1000Base-SX" },
16043c2aeb0SSepherosa Ziehau 
16143c2aeb0SSepherosa Ziehau 	/* BCM5708C controllers and OEM boards. */
1623482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708,  HP_VENDORID, 0x7037,
1633482f06cSSepherosa Ziehau 		"HP NC373T PCIe Multifunction Gig Server Adapter" },
1643482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708,  HP_VENDORID, 0x7038,
1653482f06cSSepherosa Ziehau 		"HP NC373i Multifunction Gigabit Server Adapter" },
1663482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708,  HP_VENDORID, 0x7045,
1673482f06cSSepherosa Ziehau 		"HP NC374m PCIe Multifunction Adapter" },
16843c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708,  PCI_ANY_ID,  PCI_ANY_ID,
16943c2aeb0SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5708 1000Base-T" },
17043c2aeb0SSepherosa Ziehau 
17143c2aeb0SSepherosa Ziehau 	/* BCM5708S controllers and OEM boards. */
1723482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S,  HP_VENDORID, 0x1706,
1733482f06cSSepherosa Ziehau 		"HP NC373m Multifunction Gigabit Server Adapter" },
1743482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S,  HP_VENDORID, 0x703b,
1753482f06cSSepherosa Ziehau 		"HP NC373i Multifunction Gigabit Server Adapter" },
1763482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S,  HP_VENDORID, 0x703d,
1773482f06cSSepherosa Ziehau 		"HP NC373F PCIe Multifunc Giga Server Adapter" },
17843c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S,  PCI_ANY_ID,  PCI_ANY_ID,
17943c2aeb0SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5708S 1000Base-T" },
180d0092544SSepherosa Ziehau 
181d0092544SSepherosa Ziehau 	/* BCM5709C controllers and OEM boards. */
1823482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709,  HP_VENDORID, 0x7055,
1833482f06cSSepherosa Ziehau 		"HP NC382i DP Multifunction Gigabit Server Adapter" },
1843482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709,  HP_VENDORID, 0x7059,
1853482f06cSSepherosa Ziehau 		"HP NC382T PCIe DP Multifunction Gigabit Server Adapter" },
186d0092544SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709,  PCI_ANY_ID,  PCI_ANY_ID,
187d0092544SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5709 1000Base-T" },
188d0092544SSepherosa Ziehau 
189d0092544SSepherosa Ziehau 	/* BCM5709S controllers and OEM boards. */
1903482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S,  HP_VENDORID, 0x171d,
1913482f06cSSepherosa Ziehau 		"HP NC382m DP 1GbE Multifunction BL-c Adapter" },
1923482f06cSSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S,  HP_VENDORID, 0x7056,
1933482f06cSSepherosa Ziehau 		"HP NC382i DP Multifunction Gigabit Server Adapter" },
194d0092544SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S,  PCI_ANY_ID,  PCI_ANY_ID,
195d0092544SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5709 1000Base-SX" },
196d0092544SSepherosa Ziehau 
197d0092544SSepherosa Ziehau 	/* BCM5716 controllers and OEM boards. */
198d0092544SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5716,   PCI_ANY_ID,  PCI_ANY_ID,
199d0092544SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5716 1000Base-T" },
200d0092544SSepherosa Ziehau 
20143c2aeb0SSepherosa Ziehau 	{ 0, 0, 0, 0, NULL }
20243c2aeb0SSepherosa Ziehau };
20343c2aeb0SSepherosa Ziehau 
20443c2aeb0SSepherosa Ziehau 
20543c2aeb0SSepherosa Ziehau /****************************************************************************/
20643c2aeb0SSepherosa Ziehau /* Supported Flash NVRAM device data.                                       */
20743c2aeb0SSepherosa Ziehau /****************************************************************************/
20843c2aeb0SSepherosa Ziehau static const struct flash_spec flash_table[] =
20943c2aeb0SSepherosa Ziehau {
210d0092544SSepherosa Ziehau #define BUFFERED_FLAGS		(BCE_NV_BUFFERED | BCE_NV_TRANSLATE)
211d0092544SSepherosa Ziehau #define NONBUFFERED_FLAGS	(BCE_NV_WREN)
212d0092544SSepherosa Ziehau 
21343c2aeb0SSepherosa Ziehau 	/* Slow EEPROM */
21443c2aeb0SSepherosa Ziehau 	{0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
215d0092544SSepherosa Ziehau 	 BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
21643c2aeb0SSepherosa Ziehau 	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
21743c2aeb0SSepherosa Ziehau 	 "EEPROM - slow"},
21843c2aeb0SSepherosa Ziehau 	/* Expansion entry 0001 */
21943c2aeb0SSepherosa Ziehau 	{0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
220d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
22143c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
22243c2aeb0SSepherosa Ziehau 	 "Entry 0001"},
22343c2aeb0SSepherosa Ziehau 	/* Saifun SA25F010 (non-buffered flash) */
22443c2aeb0SSepherosa Ziehau 	/* strap, cfg1, & write1 need updates */
22543c2aeb0SSepherosa Ziehau 	{0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
226d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
22743c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
22843c2aeb0SSepherosa Ziehau 	 "Non-buffered flash (128kB)"},
22943c2aeb0SSepherosa Ziehau 	/* Saifun SA25F020 (non-buffered flash) */
23043c2aeb0SSepherosa Ziehau 	/* strap, cfg1, & write1 need updates */
23143c2aeb0SSepherosa Ziehau 	{0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
232d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
23343c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
23443c2aeb0SSepherosa Ziehau 	 "Non-buffered flash (256kB)"},
23543c2aeb0SSepherosa Ziehau 	/* Expansion entry 0100 */
23643c2aeb0SSepherosa Ziehau 	{0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
237d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
23843c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
23943c2aeb0SSepherosa Ziehau 	 "Entry 0100"},
24043c2aeb0SSepherosa Ziehau 	/* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
24143c2aeb0SSepherosa Ziehau 	{0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
242d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
24343c2aeb0SSepherosa Ziehau 	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
24443c2aeb0SSepherosa Ziehau 	 "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
24543c2aeb0SSepherosa Ziehau 	/* Entry 0110: ST M45PE20 (non-buffered flash)*/
24643c2aeb0SSepherosa Ziehau 	{0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
247d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
24843c2aeb0SSepherosa Ziehau 	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
24943c2aeb0SSepherosa Ziehau 	 "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
25043c2aeb0SSepherosa Ziehau 	/* Saifun SA25F005 (non-buffered flash) */
25143c2aeb0SSepherosa Ziehau 	/* strap, cfg1, & write1 need updates */
25243c2aeb0SSepherosa Ziehau 	{0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
253d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
25443c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
25543c2aeb0SSepherosa Ziehau 	 "Non-buffered flash (64kB)"},
25643c2aeb0SSepherosa Ziehau 	/* Fast EEPROM */
25743c2aeb0SSepherosa Ziehau 	{0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
258d0092544SSepherosa Ziehau 	 BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
25943c2aeb0SSepherosa Ziehau 	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
26043c2aeb0SSepherosa Ziehau 	 "EEPROM - fast"},
26143c2aeb0SSepherosa Ziehau 	/* Expansion entry 1001 */
26243c2aeb0SSepherosa Ziehau 	{0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
263d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
26443c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
26543c2aeb0SSepherosa Ziehau 	 "Entry 1001"},
26643c2aeb0SSepherosa Ziehau 	/* Expansion entry 1010 */
26743c2aeb0SSepherosa Ziehau 	{0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
268d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
26943c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
27043c2aeb0SSepherosa Ziehau 	 "Entry 1010"},
27143c2aeb0SSepherosa Ziehau 	/* ATMEL AT45DB011B (buffered flash) */
27243c2aeb0SSepherosa Ziehau 	{0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
273d0092544SSepherosa Ziehau 	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
27443c2aeb0SSepherosa Ziehau 	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
27543c2aeb0SSepherosa Ziehau 	 "Buffered flash (128kB)"},
27643c2aeb0SSepherosa Ziehau 	/* Expansion entry 1100 */
27743c2aeb0SSepherosa Ziehau 	{0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
278d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
27943c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
28043c2aeb0SSepherosa Ziehau 	 "Entry 1100"},
28143c2aeb0SSepherosa Ziehau 	/* Expansion entry 1101 */
28243c2aeb0SSepherosa Ziehau 	{0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
283d0092544SSepherosa Ziehau 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
28443c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
28543c2aeb0SSepherosa Ziehau 	 "Entry 1101"},
28643c2aeb0SSepherosa Ziehau 	/* Ateml Expansion entry 1110 */
28743c2aeb0SSepherosa Ziehau 	{0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
288d0092544SSepherosa Ziehau 	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
28943c2aeb0SSepherosa Ziehau 	 BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
29043c2aeb0SSepherosa Ziehau 	 "Entry 1110 (Atmel)"},
29143c2aeb0SSepherosa Ziehau 	/* ATMEL AT45DB021B (buffered flash) */
29243c2aeb0SSepherosa Ziehau 	{0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
293d0092544SSepherosa Ziehau 	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
29443c2aeb0SSepherosa Ziehau 	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
29543c2aeb0SSepherosa Ziehau 	 "Buffered flash (256kB)"},
29643c2aeb0SSepherosa Ziehau };
29743c2aeb0SSepherosa Ziehau 
298d0092544SSepherosa Ziehau /*
299d0092544SSepherosa Ziehau  * The BCM5709 controllers transparently handle the
300d0092544SSepherosa Ziehau  * differences between Atmel 264 byte pages and all
301d0092544SSepherosa Ziehau  * flash devices which use 256 byte pages, so no
302d0092544SSepherosa Ziehau  * logical-to-physical mapping is required in the
303d0092544SSepherosa Ziehau  * driver.
304d0092544SSepherosa Ziehau  */
305d0092544SSepherosa Ziehau static struct flash_spec flash_5709 = {
306d0092544SSepherosa Ziehau 	.flags		= BCE_NV_BUFFERED,
307d0092544SSepherosa Ziehau 	.page_bits	= BCM5709_FLASH_PAGE_BITS,
308d0092544SSepherosa Ziehau 	.page_size	= BCM5709_FLASH_PAGE_SIZE,
309d0092544SSepherosa Ziehau 	.addr_mask	= BCM5709_FLASH_BYTE_ADDR_MASK,
310d0092544SSepherosa Ziehau 	.total_size	= BUFFERED_FLASH_TOTAL_SIZE * 2,
311d0092544SSepherosa Ziehau 	.name		= "5709/5716 buffered flash (256kB)",
312d0092544SSepherosa Ziehau };
313d0092544SSepherosa Ziehau 
31443c2aeb0SSepherosa Ziehau 
31543c2aeb0SSepherosa Ziehau /****************************************************************************/
31643c2aeb0SSepherosa Ziehau /* DragonFly device entry points.                                           */
31743c2aeb0SSepherosa Ziehau /****************************************************************************/
31843c2aeb0SSepherosa Ziehau static int	bce_probe(device_t);
31943c2aeb0SSepherosa Ziehau static int	bce_attach(device_t);
32043c2aeb0SSepherosa Ziehau static int	bce_detach(device_t);
32143c2aeb0SSepherosa Ziehau static void	bce_shutdown(device_t);
32243c2aeb0SSepherosa Ziehau 
32343c2aeb0SSepherosa Ziehau /****************************************************************************/
32443c2aeb0SSepherosa Ziehau /* BCE Debug Data Structure Dump Routines                                   */
32543c2aeb0SSepherosa Ziehau /****************************************************************************/
32643c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
32743c2aeb0SSepherosa Ziehau static void	bce_dump_mbuf(struct bce_softc *, struct mbuf *);
32843c2aeb0SSepherosa Ziehau static void	bce_dump_tx_mbuf_chain(struct bce_softc *, int, int);
32943c2aeb0SSepherosa Ziehau static void	bce_dump_rx_mbuf_chain(struct bce_softc *, int, int);
33043c2aeb0SSepherosa Ziehau static void	bce_dump_txbd(struct bce_softc *, int, struct tx_bd *);
33143c2aeb0SSepherosa Ziehau static void	bce_dump_rxbd(struct bce_softc *, int, struct rx_bd *);
33243c2aeb0SSepherosa Ziehau static void	bce_dump_l2fhdr(struct bce_softc *, int,
33343c2aeb0SSepherosa Ziehau 				struct l2_fhdr *) __unused;
33443c2aeb0SSepherosa Ziehau static void	bce_dump_tx_chain(struct bce_softc *, int, int);
33543c2aeb0SSepherosa Ziehau static void	bce_dump_rx_chain(struct bce_softc *, int, int);
33643c2aeb0SSepherosa Ziehau static void	bce_dump_status_block(struct bce_softc *);
33743c2aeb0SSepherosa Ziehau static void	bce_dump_driver_state(struct bce_softc *);
33843c2aeb0SSepherosa Ziehau static void	bce_dump_stats_block(struct bce_softc *) __unused;
33943c2aeb0SSepherosa Ziehau static void	bce_dump_hw_state(struct bce_softc *);
34043c2aeb0SSepherosa Ziehau static void	bce_dump_txp_state(struct bce_softc *);
34143c2aeb0SSepherosa Ziehau static void	bce_dump_rxp_state(struct bce_softc *) __unused;
34243c2aeb0SSepherosa Ziehau static void	bce_dump_tpat_state(struct bce_softc *) __unused;
34343c2aeb0SSepherosa Ziehau static void	bce_freeze_controller(struct bce_softc *) __unused;
34443c2aeb0SSepherosa Ziehau static void	bce_unfreeze_controller(struct bce_softc *) __unused;
34543c2aeb0SSepherosa Ziehau static void	bce_breakpoint(struct bce_softc *);
34643c2aeb0SSepherosa Ziehau #endif	/* BCE_DEBUG */
34743c2aeb0SSepherosa Ziehau 
34843c2aeb0SSepherosa Ziehau 
34943c2aeb0SSepherosa Ziehau /****************************************************************************/
35043c2aeb0SSepherosa Ziehau /* BCE Register/Memory Access Routines                                      */
35143c2aeb0SSepherosa Ziehau /****************************************************************************/
35243c2aeb0SSepherosa Ziehau static uint32_t	bce_reg_rd_ind(struct bce_softc *, uint32_t);
35343c2aeb0SSepherosa Ziehau static void	bce_reg_wr_ind(struct bce_softc *, uint32_t, uint32_t);
354bc30d40dSSepherosa Ziehau static void	bce_shmem_wr(struct bce_softc *, uint32_t, uint32_t);
355bc30d40dSSepherosa Ziehau static uint32_t	bce_shmem_rd(struct bce_softc *, u32);
35643c2aeb0SSepherosa Ziehau static void	bce_ctx_wr(struct bce_softc *, uint32_t, uint32_t, uint32_t);
35743c2aeb0SSepherosa Ziehau static int	bce_miibus_read_reg(device_t, int, int);
35843c2aeb0SSepherosa Ziehau static int	bce_miibus_write_reg(device_t, int, int, int);
35943c2aeb0SSepherosa Ziehau static void	bce_miibus_statchg(device_t);
36043c2aeb0SSepherosa Ziehau 
36143c2aeb0SSepherosa Ziehau 
36243c2aeb0SSepherosa Ziehau /****************************************************************************/
36343c2aeb0SSepherosa Ziehau /* BCE NVRAM Access Routines                                                */
36443c2aeb0SSepherosa Ziehau /****************************************************************************/
36543c2aeb0SSepherosa Ziehau static int	bce_acquire_nvram_lock(struct bce_softc *);
36643c2aeb0SSepherosa Ziehau static int	bce_release_nvram_lock(struct bce_softc *);
36743c2aeb0SSepherosa Ziehau static void	bce_enable_nvram_access(struct bce_softc *);
36843c2aeb0SSepherosa Ziehau static void	bce_disable_nvram_access(struct bce_softc *);
36943c2aeb0SSepherosa Ziehau static int	bce_nvram_read_dword(struct bce_softc *, uint32_t, uint8_t *,
37043c2aeb0SSepherosa Ziehau 				     uint32_t);
37143c2aeb0SSepherosa Ziehau static int	bce_init_nvram(struct bce_softc *);
37243c2aeb0SSepherosa Ziehau static int	bce_nvram_read(struct bce_softc *, uint32_t, uint8_t *, int);
37343c2aeb0SSepherosa Ziehau static int	bce_nvram_test(struct bce_softc *);
37443c2aeb0SSepherosa Ziehau 
37543c2aeb0SSepherosa Ziehau /****************************************************************************/
37643c2aeb0SSepherosa Ziehau /* BCE DMA Allocate/Free Routines                                           */
37743c2aeb0SSepherosa Ziehau /****************************************************************************/
37843c2aeb0SSepherosa Ziehau static int	bce_dma_alloc(struct bce_softc *);
37943c2aeb0SSepherosa Ziehau static void	bce_dma_free(struct bce_softc *);
38043c2aeb0SSepherosa Ziehau static void	bce_dma_map_addr(void *, bus_dma_segment_t *, int, int);
38143c2aeb0SSepherosa Ziehau 
38243c2aeb0SSepherosa Ziehau /****************************************************************************/
38343c2aeb0SSepherosa Ziehau /* BCE Firmware Synchronization and Load                                    */
38443c2aeb0SSepherosa Ziehau /****************************************************************************/
38543c2aeb0SSepherosa Ziehau static int	bce_fw_sync(struct bce_softc *, uint32_t);
38643c2aeb0SSepherosa Ziehau static void	bce_load_rv2p_fw(struct bce_softc *, uint32_t *,
38743c2aeb0SSepherosa Ziehau 				 uint32_t, uint32_t);
38843c2aeb0SSepherosa Ziehau static void	bce_load_cpu_fw(struct bce_softc *, struct cpu_reg *,
38943c2aeb0SSepherosa Ziehau 				struct fw_info *);
3905d05a208SSepherosa Ziehau static void	bce_start_cpu(struct bce_softc *, struct cpu_reg *);
3915d05a208SSepherosa Ziehau static void	bce_halt_cpu(struct bce_softc *, struct cpu_reg *);
3925d05a208SSepherosa Ziehau static void	bce_start_rxp_cpu(struct bce_softc *);
393d0092544SSepherosa Ziehau static void	bce_init_rxp_cpu(struct bce_softc *);
394d0092544SSepherosa Ziehau static void	bce_init_txp_cpu(struct bce_softc *);
395d0092544SSepherosa Ziehau static void	bce_init_tpat_cpu(struct bce_softc *);
396d0092544SSepherosa Ziehau static void	bce_init_cp_cpu(struct bce_softc *);
397d0092544SSepherosa Ziehau static void	bce_init_com_cpu(struct bce_softc *);
39843c2aeb0SSepherosa Ziehau static void	bce_init_cpus(struct bce_softc *);
39943c2aeb0SSepherosa Ziehau 
40043c2aeb0SSepherosa Ziehau static void	bce_stop(struct bce_softc *);
40143c2aeb0SSepherosa Ziehau static int	bce_reset(struct bce_softc *, uint32_t);
40243c2aeb0SSepherosa Ziehau static int	bce_chipinit(struct bce_softc *);
40343c2aeb0SSepherosa Ziehau static int	bce_blockinit(struct bce_softc *);
404c36fd9eeSSepherosa Ziehau static int	bce_newbuf_std(struct bce_softc *, uint16_t *, uint16_t *,
405c36fd9eeSSepherosa Ziehau 			       uint32_t *, int);
406314a2fccSSepherosa Ziehau static void	bce_setup_rxdesc_std(struct bce_softc *, uint16_t, uint32_t *);
407d0092544SSepherosa Ziehau static void	bce_probe_pci_caps(struct bce_softc *);
408d0092544SSepherosa Ziehau static void	bce_print_adapter_info(struct bce_softc *);
409d0092544SSepherosa Ziehau static void	bce_get_media(struct bce_softc *);
41043c2aeb0SSepherosa Ziehau 
411d0092544SSepherosa Ziehau static void	bce_init_tx_context(struct bce_softc *);
41243c2aeb0SSepherosa Ziehau static int	bce_init_tx_chain(struct bce_softc *);
413d0092544SSepherosa Ziehau static void	bce_init_rx_context(struct bce_softc *);
41443c2aeb0SSepherosa Ziehau static int	bce_init_rx_chain(struct bce_softc *);
41543c2aeb0SSepherosa Ziehau static void	bce_free_rx_chain(struct bce_softc *);
41643c2aeb0SSepherosa Ziehau static void	bce_free_tx_chain(struct bce_softc *);
41743c2aeb0SSepherosa Ziehau 
41843c2aeb0SSepherosa Ziehau static int	bce_encap(struct bce_softc *, struct mbuf **);
41943c2aeb0SSepherosa Ziehau static void	bce_start(struct ifnet *);
42043c2aeb0SSepherosa Ziehau static int	bce_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
42143c2aeb0SSepherosa Ziehau static void	bce_watchdog(struct ifnet *);
42243c2aeb0SSepherosa Ziehau static int	bce_ifmedia_upd(struct ifnet *);
42343c2aeb0SSepherosa Ziehau static void	bce_ifmedia_sts(struct ifnet *, struct ifmediareq *);
42443c2aeb0SSepherosa Ziehau static void	bce_init(void *);
42543c2aeb0SSepherosa Ziehau static void	bce_mgmt_init(struct bce_softc *);
42643c2aeb0SSepherosa Ziehau 
4273a41a80bSSepherosa Ziehau static void	bce_init_ctx(struct bce_softc *);
42843c2aeb0SSepherosa Ziehau static void	bce_get_mac_addr(struct bce_softc *);
42943c2aeb0SSepherosa Ziehau static void	bce_set_mac_addr(struct bce_softc *);
43043c2aeb0SSepherosa Ziehau static void	bce_phy_intr(struct bce_softc *);
43143c2aeb0SSepherosa Ziehau static void	bce_rx_intr(struct bce_softc *, int);
43243c2aeb0SSepherosa Ziehau static void	bce_tx_intr(struct bce_softc *);
43343c2aeb0SSepherosa Ziehau static void	bce_disable_intr(struct bce_softc *);
434d0092544SSepherosa Ziehau static void	bce_enable_intr(struct bce_softc *, int);
43543c2aeb0SSepherosa Ziehau 
43643c2aeb0SSepherosa Ziehau #ifdef DEVICE_POLLING
43743c2aeb0SSepherosa Ziehau static void	bce_poll(struct ifnet *, enum poll_cmd, int);
43843c2aeb0SSepherosa Ziehau #endif
43943c2aeb0SSepherosa Ziehau static void	bce_intr(void *);
44043c2aeb0SSepherosa Ziehau static void	bce_set_rx_mode(struct bce_softc *);
44143c2aeb0SSepherosa Ziehau static void	bce_stats_update(struct bce_softc *);
44243c2aeb0SSepherosa Ziehau static void	bce_tick(void *);
44343c2aeb0SSepherosa Ziehau static void	bce_tick_serialized(struct bce_softc *);
444d0092544SSepherosa Ziehau static void	bce_pulse(void *);
44543c2aeb0SSepherosa Ziehau static void	bce_add_sysctls(struct bce_softc *);
44643c2aeb0SSepherosa Ziehau 
447bdeb8fffSSepherosa Ziehau static void	bce_coal_change(struct bce_softc *);
448bdeb8fffSSepherosa Ziehau static int	bce_sysctl_tx_bds_int(SYSCTL_HANDLER_ARGS);
449bdeb8fffSSepherosa Ziehau static int	bce_sysctl_tx_bds(SYSCTL_HANDLER_ARGS);
450bdeb8fffSSepherosa Ziehau static int	bce_sysctl_tx_ticks_int(SYSCTL_HANDLER_ARGS);
451bdeb8fffSSepherosa Ziehau static int	bce_sysctl_tx_ticks(SYSCTL_HANDLER_ARGS);
452bdeb8fffSSepherosa Ziehau static int	bce_sysctl_rx_bds_int(SYSCTL_HANDLER_ARGS);
453bdeb8fffSSepherosa Ziehau static int	bce_sysctl_rx_bds(SYSCTL_HANDLER_ARGS);
454bdeb8fffSSepherosa Ziehau static int	bce_sysctl_rx_ticks_int(SYSCTL_HANDLER_ARGS);
455bdeb8fffSSepherosa Ziehau static int	bce_sysctl_rx_ticks(SYSCTL_HANDLER_ARGS);
456bdeb8fffSSepherosa Ziehau static int	bce_sysctl_coal_change(SYSCTL_HANDLER_ARGS,
457bdeb8fffSSepherosa Ziehau 				       uint32_t *, uint32_t);
458bdeb8fffSSepherosa Ziehau 
4593fb4bb6cSSepherosa Ziehau /*
4603fb4bb6cSSepherosa Ziehau  * NOTE:
4613fb4bb6cSSepherosa Ziehau  * Don't set bce_tx_ticks_int/bce_tx_ticks to 1023.  Linux's bnx2
4623fb4bb6cSSepherosa Ziehau  * takes 1023 as the TX ticks limit.  However, using 1023 will
4633fb4bb6cSSepherosa Ziehau  * cause 5708(B2) to generate extra interrupts (~2000/s) even when
4643fb4bb6cSSepherosa Ziehau  * there is _no_ network activity on the NIC.
4653fb4bb6cSSepherosa Ziehau  */
4663fb4bb6cSSepherosa Ziehau static uint32_t	bce_tx_bds_int = 255;		/* bcm: 20 */
4673fb4bb6cSSepherosa Ziehau static uint32_t	bce_tx_bds = 255;		/* bcm: 20 */
4683fb4bb6cSSepherosa Ziehau static uint32_t	bce_tx_ticks_int = 1022;	/* bcm: 80 */
4693fb4bb6cSSepherosa Ziehau static uint32_t	bce_tx_ticks = 1022;		/* bcm: 80 */
4701af951abSSepherosa Ziehau static uint32_t	bce_rx_bds_int = 128;		/* bcm: 6 */
4711af951abSSepherosa Ziehau static uint32_t	bce_rx_bds = 128;		/* bcm: 6 */
4721af951abSSepherosa Ziehau static uint32_t	bce_rx_ticks_int = 125;		/* bcm: 18 */
4731af951abSSepherosa Ziehau static uint32_t	bce_rx_ticks = 125;		/* bcm: 18 */
474bdeb8fffSSepherosa Ziehau 
475bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_bds_int", &bce_tx_bds_int);
476bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_bds", &bce_tx_bds);
477bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_ticks_int", &bce_tx_ticks_int);
478bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_ticks", &bce_tx_ticks);
479bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_bds_int", &bce_rx_bds_int);
480bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_bds", &bce_rx_bds);
481bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_ticks_int", &bce_rx_ticks_int);
482bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_ticks", &bce_rx_ticks);
48343c2aeb0SSepherosa Ziehau 
48443c2aeb0SSepherosa Ziehau /****************************************************************************/
48543c2aeb0SSepherosa Ziehau /* DragonFly device dispatch table.                                         */
48643c2aeb0SSepherosa Ziehau /****************************************************************************/
48743c2aeb0SSepherosa Ziehau static device_method_t bce_methods[] = {
48843c2aeb0SSepherosa Ziehau 	/* Device interface */
48943c2aeb0SSepherosa Ziehau 	DEVMETHOD(device_probe,		bce_probe),
49043c2aeb0SSepherosa Ziehau 	DEVMETHOD(device_attach,	bce_attach),
49143c2aeb0SSepherosa Ziehau 	DEVMETHOD(device_detach,	bce_detach),
49243c2aeb0SSepherosa Ziehau 	DEVMETHOD(device_shutdown,	bce_shutdown),
49343c2aeb0SSepherosa Ziehau 
49443c2aeb0SSepherosa Ziehau 	/* bus interface */
49543c2aeb0SSepherosa Ziehau 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
49643c2aeb0SSepherosa Ziehau 	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
49743c2aeb0SSepherosa Ziehau 
49843c2aeb0SSepherosa Ziehau 	/* MII interface */
49943c2aeb0SSepherosa Ziehau 	DEVMETHOD(miibus_readreg,	bce_miibus_read_reg),
50043c2aeb0SSepherosa Ziehau 	DEVMETHOD(miibus_writereg,	bce_miibus_write_reg),
50143c2aeb0SSepherosa Ziehau 	DEVMETHOD(miibus_statchg,	bce_miibus_statchg),
50243c2aeb0SSepherosa Ziehau 
50343c2aeb0SSepherosa Ziehau 	{ 0, 0 }
50443c2aeb0SSepherosa Ziehau };
50543c2aeb0SSepherosa Ziehau 
50643c2aeb0SSepherosa Ziehau static driver_t bce_driver = {
50743c2aeb0SSepherosa Ziehau 	"bce",
50843c2aeb0SSepherosa Ziehau 	bce_methods,
50943c2aeb0SSepherosa Ziehau 	sizeof(struct bce_softc)
51043c2aeb0SSepherosa Ziehau };
51143c2aeb0SSepherosa Ziehau 
51243c2aeb0SSepherosa Ziehau static devclass_t bce_devclass;
51343c2aeb0SSepherosa Ziehau 
51443c2aeb0SSepherosa Ziehau 
515d0092544SSepherosa Ziehau DECLARE_DUMMY_MODULE(if_bce);
5161be78fa8SSepherosa Ziehau MODULE_DEPEND(bce, miibus, 1, 1, 1);
517aa2b9d05SSascha Wildner DRIVER_MODULE(if_bce, pci, bce_driver, bce_devclass, NULL, NULL);
518aa2b9d05SSascha Wildner DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, NULL, NULL);
51943c2aeb0SSepherosa Ziehau 
52043c2aeb0SSepherosa Ziehau 
52143c2aeb0SSepherosa Ziehau /****************************************************************************/
52243c2aeb0SSepherosa Ziehau /* Device probe function.                                                   */
52343c2aeb0SSepherosa Ziehau /*                                                                          */
52443c2aeb0SSepherosa Ziehau /* Compares the device to the driver's list of supported devices and        */
52543c2aeb0SSepherosa Ziehau /* reports back to the OS whether this is the right driver for the device.  */
52643c2aeb0SSepherosa Ziehau /*                                                                          */
52743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
52843c2aeb0SSepherosa Ziehau /*   BUS_PROBE_DEFAULT on success, positive value on failure.               */
52943c2aeb0SSepherosa Ziehau /****************************************************************************/
53043c2aeb0SSepherosa Ziehau static int
53143c2aeb0SSepherosa Ziehau bce_probe(device_t dev)
53243c2aeb0SSepherosa Ziehau {
53343c2aeb0SSepherosa Ziehau 	struct bce_type *t;
53443c2aeb0SSepherosa Ziehau 	uint16_t vid, did, svid, sdid;
53543c2aeb0SSepherosa Ziehau 
53643c2aeb0SSepherosa Ziehau 	/* Get the data for the device to be probed. */
53743c2aeb0SSepherosa Ziehau 	vid  = pci_get_vendor(dev);
53843c2aeb0SSepherosa Ziehau 	did  = pci_get_device(dev);
53943c2aeb0SSepherosa Ziehau 	svid = pci_get_subvendor(dev);
54043c2aeb0SSepherosa Ziehau 	sdid = pci_get_subdevice(dev);
54143c2aeb0SSepherosa Ziehau 
54243c2aeb0SSepherosa Ziehau 	/* Look through the list of known devices for a match. */
54343c2aeb0SSepherosa Ziehau 	for (t = bce_devs; t->bce_name != NULL; ++t) {
54443c2aeb0SSepherosa Ziehau 		if (vid == t->bce_vid && did == t->bce_did &&
54543c2aeb0SSepherosa Ziehau 		    (svid == t->bce_svid || t->bce_svid == PCI_ANY_ID) &&
54643c2aeb0SSepherosa Ziehau 		    (sdid == t->bce_sdid || t->bce_sdid == PCI_ANY_ID)) {
54743c2aeb0SSepherosa Ziehau 		    	uint32_t revid = pci_read_config(dev, PCIR_REVID, 4);
54843c2aeb0SSepherosa Ziehau 			char *descbuf;
54943c2aeb0SSepherosa Ziehau 
55043c2aeb0SSepherosa Ziehau 			descbuf = kmalloc(BCE_DEVDESC_MAX, M_TEMP, M_WAITOK);
55143c2aeb0SSepherosa Ziehau 
55243c2aeb0SSepherosa Ziehau 			/* Print out the device identity. */
55343c2aeb0SSepherosa Ziehau 			ksnprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d)",
55443c2aeb0SSepherosa Ziehau 				  t->bce_name,
55543c2aeb0SSepherosa Ziehau 				  ((revid & 0xf0) >> 4) + 'A', revid & 0xf);
55643c2aeb0SSepherosa Ziehau 
55743c2aeb0SSepherosa Ziehau 			device_set_desc_copy(dev, descbuf);
55843c2aeb0SSepherosa Ziehau 			kfree(descbuf, M_TEMP);
55943c2aeb0SSepherosa Ziehau 			return 0;
56043c2aeb0SSepherosa Ziehau 		}
56143c2aeb0SSepherosa Ziehau 	}
56243c2aeb0SSepherosa Ziehau 	return ENXIO;
56343c2aeb0SSepherosa Ziehau }
56443c2aeb0SSepherosa Ziehau 
56543c2aeb0SSepherosa Ziehau 
56643c2aeb0SSepherosa Ziehau /****************************************************************************/
567d0092544SSepherosa Ziehau /* PCI Capabilities Probe Function.                                         */
568d0092544SSepherosa Ziehau /*                                                                          */
569d0092544SSepherosa Ziehau /* Walks the PCI capabiites list for the device to find what features are   */
570d0092544SSepherosa Ziehau /* supported.                                                               */
571d0092544SSepherosa Ziehau /*                                                                          */
572d0092544SSepherosa Ziehau /* Returns:                                                                 */
573d0092544SSepherosa Ziehau /*   None.                                                                  */
574d0092544SSepherosa Ziehau /****************************************************************************/
575d0092544SSepherosa Ziehau static void
576d0092544SSepherosa Ziehau bce_print_adapter_info(struct bce_softc *sc)
577d0092544SSepherosa Ziehau {
578d0092544SSepherosa Ziehau 	device_printf(sc->bce_dev, "ASIC (0x%08X); ", sc->bce_chipid);
579d0092544SSepherosa Ziehau 
580d0092544SSepherosa Ziehau 	kprintf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A',
581d0092544SSepherosa Ziehau 		((BCE_CHIP_ID(sc) & 0x0ff0) >> 4));
582d0092544SSepherosa Ziehau 
583d0092544SSepherosa Ziehau 	/* Bus info. */
584d0092544SSepherosa Ziehau 	if (sc->bce_flags & BCE_PCIE_FLAG) {
585d0092544SSepherosa Ziehau 		kprintf("Bus (PCIe x%d, ", sc->link_width);
586d0092544SSepherosa Ziehau 		switch (sc->link_speed) {
587d0092544SSepherosa Ziehau 		case 1:
588d0092544SSepherosa Ziehau 			kprintf("2.5Gbps); ");
589d0092544SSepherosa Ziehau 			break;
590d0092544SSepherosa Ziehau 		case 2:
591d0092544SSepherosa Ziehau 			kprintf("5Gbps); ");
592d0092544SSepherosa Ziehau 			break;
593d0092544SSepherosa Ziehau 		default:
594d0092544SSepherosa Ziehau 			kprintf("Unknown link speed); ");
595d0092544SSepherosa Ziehau 			break;
596d0092544SSepherosa Ziehau 		}
597d0092544SSepherosa Ziehau 	} else {
598d0092544SSepherosa Ziehau 		kprintf("Bus (PCI%s, %s, %dMHz); ",
599d0092544SSepherosa Ziehau 		    ((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""),
600d0092544SSepherosa Ziehau 		    ((sc->bce_flags & BCE_PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
601d0092544SSepherosa Ziehau 		    sc->bus_speed_mhz);
602d0092544SSepherosa Ziehau 	}
603d0092544SSepherosa Ziehau 
604d0092544SSepherosa Ziehau 	/* Firmware version and device features. */
605bc30d40dSSepherosa Ziehau 	kprintf("B/C (%s)", sc->bce_bc_ver);
606d0092544SSepherosa Ziehau 
607cff16e71SSepherosa Ziehau 	if ((sc->bce_flags & BCE_MFW_ENABLE_FLAG) ||
608cff16e71SSepherosa Ziehau 	    (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)) {
609cff16e71SSepherosa Ziehau 		kprintf("; Flags(");
610d0092544SSepherosa Ziehau 		if (sc->bce_flags & BCE_MFW_ENABLE_FLAG)
611bc30d40dSSepherosa Ziehau 			kprintf("MFW[%s]", sc->bce_mfw_ver);
612d0092544SSepherosa Ziehau 		if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)
613d0092544SSepherosa Ziehau 			kprintf(" 2.5G");
614cff16e71SSepherosa Ziehau 		kprintf(")");
615cff16e71SSepherosa Ziehau 	}
616cff16e71SSepherosa Ziehau 	kprintf("\n");
617d0092544SSepherosa Ziehau }
618d0092544SSepherosa Ziehau 
619d0092544SSepherosa Ziehau 
620d0092544SSepherosa Ziehau /****************************************************************************/
621d0092544SSepherosa Ziehau /* PCI Capabilities Probe Function.                                         */
622d0092544SSepherosa Ziehau /*                                                                          */
623d0092544SSepherosa Ziehau /* Walks the PCI capabiites list for the device to find what features are   */
624d0092544SSepherosa Ziehau /* supported.                                                               */
625d0092544SSepherosa Ziehau /*                                                                          */
626d0092544SSepherosa Ziehau /* Returns:                                                                 */
627d0092544SSepherosa Ziehau /*   None.                                                                  */
628d0092544SSepherosa Ziehau /****************************************************************************/
629d0092544SSepherosa Ziehau static void
630d0092544SSepherosa Ziehau bce_probe_pci_caps(struct bce_softc *sc)
631d0092544SSepherosa Ziehau {
632d0092544SSepherosa Ziehau 	device_t dev = sc->bce_dev;
633d0092544SSepherosa Ziehau 	uint8_t ptr;
634d0092544SSepherosa Ziehau 
635d0092544SSepherosa Ziehau 	if (pci_is_pcix(dev))
636d0092544SSepherosa Ziehau 		sc->bce_cap_flags |= BCE_PCIX_CAPABLE_FLAG;
637d0092544SSepherosa Ziehau 
638d0092544SSepherosa Ziehau 	ptr = pci_get_pciecap_ptr(dev);
639d0092544SSepherosa Ziehau 	if (ptr) {
640d0092544SSepherosa Ziehau 		uint16_t link_status = pci_read_config(dev, ptr + 0x12, 2);
641d0092544SSepherosa Ziehau 
642d0092544SSepherosa Ziehau 		sc->link_speed = link_status & 0xf;
643d0092544SSepherosa Ziehau 		sc->link_width = (link_status >> 4) & 0x3f;
644d0092544SSepherosa Ziehau 		sc->bce_cap_flags |= BCE_PCIE_CAPABLE_FLAG;
645d0092544SSepherosa Ziehau 		sc->bce_flags |= BCE_PCIE_FLAG;
646d0092544SSepherosa Ziehau 	}
647d0092544SSepherosa Ziehau }
648d0092544SSepherosa Ziehau 
649d0092544SSepherosa Ziehau 
650d0092544SSepherosa Ziehau /****************************************************************************/
65143c2aeb0SSepherosa Ziehau /* Device attach function.                                                  */
65243c2aeb0SSepherosa Ziehau /*                                                                          */
65343c2aeb0SSepherosa Ziehau /* Allocates device resources, performs secondary chip identification,      */
65443c2aeb0SSepherosa Ziehau /* resets and initializes the hardware, and initializes driver instance     */
65543c2aeb0SSepherosa Ziehau /* variables.                                                               */
65643c2aeb0SSepherosa Ziehau /*                                                                          */
65743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
65843c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
65943c2aeb0SSepherosa Ziehau /****************************************************************************/
66043c2aeb0SSepherosa Ziehau static int
66143c2aeb0SSepherosa Ziehau bce_attach(device_t dev)
66243c2aeb0SSepherosa Ziehau {
66343c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
66443c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
66543c2aeb0SSepherosa Ziehau 	uint32_t val;
66643c2aeb0SSepherosa Ziehau 	int rid, rc = 0;
667bc30d40dSSepherosa Ziehau 	int i, j;
66843c2aeb0SSepherosa Ziehau #ifdef notyet
66943c2aeb0SSepherosa Ziehau 	int count;
67043c2aeb0SSepherosa Ziehau #endif
67143c2aeb0SSepherosa Ziehau 
67243c2aeb0SSepherosa Ziehau 	sc->bce_dev = dev;
67343c2aeb0SSepherosa Ziehau 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
67443c2aeb0SSepherosa Ziehau 
67543c2aeb0SSepherosa Ziehau 	pci_enable_busmaster(dev);
67643c2aeb0SSepherosa Ziehau 
677d0092544SSepherosa Ziehau 	bce_probe_pci_caps(sc);
678d0092544SSepherosa Ziehau 
67943c2aeb0SSepherosa Ziehau 	/* Allocate PCI memory resources. */
68043c2aeb0SSepherosa Ziehau 	rid = PCIR_BAR(0);
68143c2aeb0SSepherosa Ziehau 	sc->bce_res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
68243c2aeb0SSepherosa Ziehau 						 RF_ACTIVE | PCI_RF_DENSE);
68343c2aeb0SSepherosa Ziehau 	if (sc->bce_res_mem == NULL) {
68443c2aeb0SSepherosa Ziehau 		device_printf(dev, "PCI memory allocation failed\n");
68543c2aeb0SSepherosa Ziehau 		return ENXIO;
68643c2aeb0SSepherosa Ziehau 	}
68743c2aeb0SSepherosa Ziehau 	sc->bce_btag = rman_get_bustag(sc->bce_res_mem);
68843c2aeb0SSepherosa Ziehau 	sc->bce_bhandle = rman_get_bushandle(sc->bce_res_mem);
68943c2aeb0SSepherosa Ziehau 
69043c2aeb0SSepherosa Ziehau 	/* Allocate PCI IRQ resources. */
69143c2aeb0SSepherosa Ziehau #ifdef notyet
69243c2aeb0SSepherosa Ziehau 	count = pci_msi_count(dev);
69343c2aeb0SSepherosa Ziehau 	if (count == 1 && pci_alloc_msi(dev, &count) == 0) {
69443c2aeb0SSepherosa Ziehau 		rid = 1;
69543c2aeb0SSepherosa Ziehau 		sc->bce_flags |= BCE_USING_MSI_FLAG;
69643c2aeb0SSepherosa Ziehau 	} else
69743c2aeb0SSepherosa Ziehau #endif
69843c2aeb0SSepherosa Ziehau 	rid = 0;
69943c2aeb0SSepherosa Ziehau 	sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
70043c2aeb0SSepherosa Ziehau 						 RF_SHAREABLE | RF_ACTIVE);
70143c2aeb0SSepherosa Ziehau 	if (sc->bce_res_irq == NULL) {
70243c2aeb0SSepherosa Ziehau 		device_printf(dev, "PCI map interrupt failed\n");
70343c2aeb0SSepherosa Ziehau 		rc = ENXIO;
70443c2aeb0SSepherosa Ziehau 		goto fail;
70543c2aeb0SSepherosa Ziehau 	}
70643c2aeb0SSepherosa Ziehau 
70743c2aeb0SSepherosa Ziehau 	/*
70843c2aeb0SSepherosa Ziehau 	 * Configure byte swap and enable indirect register access.
70943c2aeb0SSepherosa Ziehau 	 * Rely on CPU to do target byte swapping on big endian systems.
71043c2aeb0SSepherosa Ziehau 	 * Access to registers outside of PCI configurtion space are not
71143c2aeb0SSepherosa Ziehau 	 * valid until this is done.
71243c2aeb0SSepherosa Ziehau 	 */
71343c2aeb0SSepherosa Ziehau 	pci_write_config(dev, BCE_PCICFG_MISC_CONFIG,
71443c2aeb0SSepherosa Ziehau 			 BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
71543c2aeb0SSepherosa Ziehau 			 BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP, 4);
71643c2aeb0SSepherosa Ziehau 
71743c2aeb0SSepherosa Ziehau 	/* Save ASIC revsion info. */
71843c2aeb0SSepherosa Ziehau 	sc->bce_chipid =  REG_RD(sc, BCE_MISC_ID);
71943c2aeb0SSepherosa Ziehau 
72043c2aeb0SSepherosa Ziehau 	/* Weed out any non-production controller revisions. */
72143c2aeb0SSepherosa Ziehau 	switch (BCE_CHIP_ID(sc)) {
72243c2aeb0SSepherosa Ziehau 	case BCE_CHIP_ID_5706_A0:
72343c2aeb0SSepherosa Ziehau 	case BCE_CHIP_ID_5706_A1:
72443c2aeb0SSepherosa Ziehau 	case BCE_CHIP_ID_5708_A0:
72543c2aeb0SSepherosa Ziehau 	case BCE_CHIP_ID_5708_B0:
726d0092544SSepherosa Ziehau 	case BCE_CHIP_ID_5709_A0:
727d0092544SSepherosa Ziehau 	case BCE_CHIP_ID_5709_B0:
728d0092544SSepherosa Ziehau 	case BCE_CHIP_ID_5709_B1:
729d0092544SSepherosa Ziehau #ifdef foo
730d0092544SSepherosa Ziehau 	/* 5709C B2 seems to work fine */
731d0092544SSepherosa Ziehau 	case BCE_CHIP_ID_5709_B2:
732d0092544SSepherosa Ziehau #endif
73343c2aeb0SSepherosa Ziehau 		device_printf(dev, "Unsupported chip id 0x%08x!\n",
73443c2aeb0SSepherosa Ziehau 			      BCE_CHIP_ID(sc));
73543c2aeb0SSepherosa Ziehau 		rc = ENODEV;
73643c2aeb0SSepherosa Ziehau 		goto fail;
73743c2aeb0SSepherosa Ziehau 	}
73843c2aeb0SSepherosa Ziehau 
73943c2aeb0SSepherosa Ziehau 	/*
74043c2aeb0SSepherosa Ziehau 	 * Find the base address for shared memory access.
74143c2aeb0SSepherosa Ziehau 	 * Newer versions of bootcode use a signature and offset
74243c2aeb0SSepherosa Ziehau 	 * while older versions use a fixed address.
74343c2aeb0SSepherosa Ziehau 	 */
74443c2aeb0SSepherosa Ziehau 	val = REG_RD_IND(sc, BCE_SHM_HDR_SIGNATURE);
745d0092544SSepherosa Ziehau 	if ((val & BCE_SHM_HDR_SIGNATURE_SIG_MASK) ==
746d0092544SSepherosa Ziehau 	    BCE_SHM_HDR_SIGNATURE_SIG) {
747d0092544SSepherosa Ziehau 		/* Multi-port devices use different offsets in shared memory. */
748d0092544SSepherosa Ziehau 		sc->bce_shmem_base = REG_RD_IND(sc,
749d0092544SSepherosa Ziehau 		    BCE_SHM_HDR_ADDR_0 + (pci_get_function(sc->bce_dev) << 2));
750d0092544SSepherosa Ziehau 	} else {
75143c2aeb0SSepherosa Ziehau 		sc->bce_shmem_base = HOST_VIEW_SHMEM_BASE;
752d0092544SSepherosa Ziehau 	}
75343c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "bce_shmem_base = 0x%08X\n", sc->bce_shmem_base);
75443c2aeb0SSepherosa Ziehau 
755d0092544SSepherosa Ziehau 	/* Fetch the bootcode revision. */
756bc30d40dSSepherosa Ziehau 	val = bce_shmem_rd(sc, BCE_DEV_INFO_BC_REV);
757bc30d40dSSepherosa Ziehau 	for (i = 0, j = 0; i < 3; i++) {
758bc30d40dSSepherosa Ziehau 		uint8_t num;
759bc30d40dSSepherosa Ziehau 		int k, skip0;
760d0092544SSepherosa Ziehau 
761bc30d40dSSepherosa Ziehau 		num = (uint8_t)(val >> (24 - (i * 8)));
762bc30d40dSSepherosa Ziehau 		for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) {
763bc30d40dSSepherosa Ziehau 			if (num >= k || !skip0 || k == 1) {
764bc30d40dSSepherosa Ziehau 				sc->bce_bc_ver[j++] = (num / k) + '0';
765bc30d40dSSepherosa Ziehau 				skip0 = 0;
766bc30d40dSSepherosa Ziehau 			}
767bc30d40dSSepherosa Ziehau 		}
768bc30d40dSSepherosa Ziehau 		if (i != 2)
769bc30d40dSSepherosa Ziehau 			sc->bce_bc_ver[j++] = '.';
770bc30d40dSSepherosa Ziehau 	}
771bc30d40dSSepherosa Ziehau 
772bc30d40dSSepherosa Ziehau 	/* Check if any management firwmare is running. */
773bc30d40dSSepherosa Ziehau 	val = bce_shmem_rd(sc, BCE_PORT_FEATURE);
774bc30d40dSSepherosa Ziehau 	if (val & BCE_PORT_FEATURE_ASF_ENABLED) {
775d0092544SSepherosa Ziehau 		sc->bce_flags |= BCE_MFW_ENABLE_FLAG;
776d0092544SSepherosa Ziehau 
777bc30d40dSSepherosa Ziehau 		/* Allow time for firmware to enter the running state. */
778bc30d40dSSepherosa Ziehau 		for (i = 0; i < 30; i++) {
779bc30d40dSSepherosa Ziehau 			val = bce_shmem_rd(sc, BCE_BC_STATE_CONDITION);
780bc30d40dSSepherosa Ziehau 			if (val & BCE_CONDITION_MFW_RUN_MASK)
781bc30d40dSSepherosa Ziehau 				break;
782bc30d40dSSepherosa Ziehau 			DELAY(10000);
783bc30d40dSSepherosa Ziehau 		}
784bc30d40dSSepherosa Ziehau 	}
785bc30d40dSSepherosa Ziehau 
786bc30d40dSSepherosa Ziehau 	/* Check the current bootcode state. */
787bc30d40dSSepherosa Ziehau 	val = bce_shmem_rd(sc, BCE_BC_STATE_CONDITION) &
788bc30d40dSSepherosa Ziehau 	    BCE_CONDITION_MFW_RUN_MASK;
789bc30d40dSSepherosa Ziehau 	if (val != BCE_CONDITION_MFW_RUN_UNKNOWN &&
790bc30d40dSSepherosa Ziehau 	    val != BCE_CONDITION_MFW_RUN_NONE) {
791bc30d40dSSepherosa Ziehau 		uint32_t addr = bce_shmem_rd(sc, BCE_MFW_VER_PTR);
792bc30d40dSSepherosa Ziehau 
793bc30d40dSSepherosa Ziehau 		for (i = 0, j = 0; j < 3; j++) {
794bc30d40dSSepherosa Ziehau 			val = bce_reg_rd_ind(sc, addr + j * 4);
795bc30d40dSSepherosa Ziehau 			val = bswap32(val);
796bc30d40dSSepherosa Ziehau 			memcpy(&sc->bce_mfw_ver[i], &val, 4);
797bc30d40dSSepherosa Ziehau 			i += 4;
798bc30d40dSSepherosa Ziehau 		}
799bc30d40dSSepherosa Ziehau 	}
800bc30d40dSSepherosa Ziehau 
80143c2aeb0SSepherosa Ziehau 	/* Get PCI bus information (speed and type). */
80243c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_PCICFG_MISC_STATUS);
80343c2aeb0SSepherosa Ziehau 	if (val & BCE_PCICFG_MISC_STATUS_PCIX_DET) {
80443c2aeb0SSepherosa Ziehau 		uint32_t clkreg;
80543c2aeb0SSepherosa Ziehau 
80643c2aeb0SSepherosa Ziehau 		sc->bce_flags |= BCE_PCIX_FLAG;
80743c2aeb0SSepherosa Ziehau 
80843c2aeb0SSepherosa Ziehau 		clkreg = REG_RD(sc, BCE_PCICFG_PCI_CLOCK_CONTROL_BITS) &
80943c2aeb0SSepherosa Ziehau 			 BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
81043c2aeb0SSepherosa Ziehau 		switch (clkreg) {
81143c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
81243c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 133;
81343c2aeb0SSepherosa Ziehau 			break;
81443c2aeb0SSepherosa Ziehau 
81543c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
81643c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 100;
81743c2aeb0SSepherosa Ziehau 			break;
81843c2aeb0SSepherosa Ziehau 
81943c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
82043c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
82143c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 66;
82243c2aeb0SSepherosa Ziehau 			break;
82343c2aeb0SSepherosa Ziehau 
82443c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
82543c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
82643c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 50;
82743c2aeb0SSepherosa Ziehau 			break;
82843c2aeb0SSepherosa Ziehau 
82943c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
83043c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
83143c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
83243c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 33;
83343c2aeb0SSepherosa Ziehau 			break;
83443c2aeb0SSepherosa Ziehau 		}
83543c2aeb0SSepherosa Ziehau 	} else {
83643c2aeb0SSepherosa Ziehau 		if (val & BCE_PCICFG_MISC_STATUS_M66EN)
83743c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 66;
83843c2aeb0SSepherosa Ziehau 		else
83943c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 33;
84043c2aeb0SSepherosa Ziehau 	}
84143c2aeb0SSepherosa Ziehau 
84243c2aeb0SSepherosa Ziehau 	if (val & BCE_PCICFG_MISC_STATUS_32BIT_DET)
84343c2aeb0SSepherosa Ziehau 		sc->bce_flags |= BCE_PCI_32BIT_FLAG;
84443c2aeb0SSepherosa Ziehau 
84543c2aeb0SSepherosa Ziehau 	/* Reset the controller. */
84643c2aeb0SSepherosa Ziehau 	rc = bce_reset(sc, BCE_DRV_MSG_CODE_RESET);
84743c2aeb0SSepherosa Ziehau 	if (rc != 0)
84843c2aeb0SSepherosa Ziehau 		goto fail;
84943c2aeb0SSepherosa Ziehau 
85043c2aeb0SSepherosa Ziehau 	/* Initialize the controller. */
85143c2aeb0SSepherosa Ziehau 	rc = bce_chipinit(sc);
85243c2aeb0SSepherosa Ziehau 	if (rc != 0) {
85343c2aeb0SSepherosa Ziehau 		device_printf(dev, "Controller initialization failed!\n");
85443c2aeb0SSepherosa Ziehau 		goto fail;
85543c2aeb0SSepherosa Ziehau 	}
85643c2aeb0SSepherosa Ziehau 
85743c2aeb0SSepherosa Ziehau 	/* Perform NVRAM test. */
85843c2aeb0SSepherosa Ziehau 	rc = bce_nvram_test(sc);
85943c2aeb0SSepherosa Ziehau 	if (rc != 0) {
86043c2aeb0SSepherosa Ziehau 		device_printf(dev, "NVRAM test failed!\n");
86143c2aeb0SSepherosa Ziehau 		goto fail;
86243c2aeb0SSepherosa Ziehau 	}
86343c2aeb0SSepherosa Ziehau 
86443c2aeb0SSepherosa Ziehau 	/* Fetch the permanent Ethernet MAC address. */
86543c2aeb0SSepherosa Ziehau 	bce_get_mac_addr(sc);
86643c2aeb0SSepherosa Ziehau 
86743c2aeb0SSepherosa Ziehau 	/*
86843c2aeb0SSepherosa Ziehau 	 * Trip points control how many BDs
86943c2aeb0SSepherosa Ziehau 	 * should be ready before generating an
87043c2aeb0SSepherosa Ziehau 	 * interrupt while ticks control how long
87143c2aeb0SSepherosa Ziehau 	 * a BD can sit in the chain before
87243c2aeb0SSepherosa Ziehau 	 * generating an interrupt.  Set the default
87343c2aeb0SSepherosa Ziehau 	 * values for the RX and TX rings.
87443c2aeb0SSepherosa Ziehau 	 */
87543c2aeb0SSepherosa Ziehau 
87643c2aeb0SSepherosa Ziehau #ifdef BCE_DRBUG
87743c2aeb0SSepherosa Ziehau 	/* Force more frequent interrupts. */
87843c2aeb0SSepherosa Ziehau 	sc->bce_tx_quick_cons_trip_int = 1;
87943c2aeb0SSepherosa Ziehau 	sc->bce_tx_quick_cons_trip     = 1;
88043c2aeb0SSepherosa Ziehau 	sc->bce_tx_ticks_int           = 0;
88143c2aeb0SSepherosa Ziehau 	sc->bce_tx_ticks               = 0;
88243c2aeb0SSepherosa Ziehau 
88343c2aeb0SSepherosa Ziehau 	sc->bce_rx_quick_cons_trip_int = 1;
88443c2aeb0SSepherosa Ziehau 	sc->bce_rx_quick_cons_trip     = 1;
88543c2aeb0SSepherosa Ziehau 	sc->bce_rx_ticks_int           = 0;
88643c2aeb0SSepherosa Ziehau 	sc->bce_rx_ticks               = 0;
88743c2aeb0SSepherosa Ziehau #else
888bdeb8fffSSepherosa Ziehau 	sc->bce_tx_quick_cons_trip_int = bce_tx_bds_int;
889bdeb8fffSSepherosa Ziehau 	sc->bce_tx_quick_cons_trip     = bce_tx_bds;
890bdeb8fffSSepherosa Ziehau 	sc->bce_tx_ticks_int           = bce_tx_ticks_int;
891bdeb8fffSSepherosa Ziehau 	sc->bce_tx_ticks               = bce_tx_ticks;
89243c2aeb0SSepherosa Ziehau 
893bdeb8fffSSepherosa Ziehau 	sc->bce_rx_quick_cons_trip_int = bce_rx_bds_int;
894bdeb8fffSSepherosa Ziehau 	sc->bce_rx_quick_cons_trip     = bce_rx_bds;
895bdeb8fffSSepherosa Ziehau 	sc->bce_rx_ticks_int           = bce_rx_ticks_int;
896bdeb8fffSSepherosa Ziehau 	sc->bce_rx_ticks               = bce_rx_ticks;
89743c2aeb0SSepherosa Ziehau #endif
89843c2aeb0SSepherosa Ziehau 
89943c2aeb0SSepherosa Ziehau 	/* Update statistics once every second. */
90043c2aeb0SSepherosa Ziehau 	sc->bce_stats_ticks = 1000000 & 0xffff00;
90143c2aeb0SSepherosa Ziehau 
902d0092544SSepherosa Ziehau 	/* Find the media type for the adapter. */
903d0092544SSepherosa Ziehau 	bce_get_media(sc);
90443c2aeb0SSepherosa Ziehau 
90543c2aeb0SSepherosa Ziehau 	/* Allocate DMA memory resources. */
90643c2aeb0SSepherosa Ziehau 	rc = bce_dma_alloc(sc);
90743c2aeb0SSepherosa Ziehau 	if (rc != 0) {
90843c2aeb0SSepherosa Ziehau 		device_printf(dev, "DMA resource allocation failed!\n");
90943c2aeb0SSepherosa Ziehau 		goto fail;
91043c2aeb0SSepherosa Ziehau 	}
91143c2aeb0SSepherosa Ziehau 
91243c2aeb0SSepherosa Ziehau 	/* Initialize the ifnet interface. */
91343c2aeb0SSepherosa Ziehau 	ifp->if_softc = sc;
91443c2aeb0SSepherosa Ziehau 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
91543c2aeb0SSepherosa Ziehau 	ifp->if_ioctl = bce_ioctl;
91643c2aeb0SSepherosa Ziehau 	ifp->if_start = bce_start;
91743c2aeb0SSepherosa Ziehau 	ifp->if_init = bce_init;
91843c2aeb0SSepherosa Ziehau 	ifp->if_watchdog = bce_watchdog;
91943c2aeb0SSepherosa Ziehau #ifdef DEVICE_POLLING
92043c2aeb0SSepherosa Ziehau 	ifp->if_poll = bce_poll;
92143c2aeb0SSepherosa Ziehau #endif
92243c2aeb0SSepherosa Ziehau 	ifp->if_mtu = ETHERMTU;
92343c2aeb0SSepherosa Ziehau 	ifp->if_hwassist = BCE_IF_HWASSIST;
92443c2aeb0SSepherosa Ziehau 	ifp->if_capabilities = BCE_IF_CAPABILITIES;
92543c2aeb0SSepherosa Ziehau 	ifp->if_capenable = ifp->if_capabilities;
92643c2aeb0SSepherosa Ziehau 	ifq_set_maxlen(&ifp->if_snd, USABLE_TX_BD);
92743c2aeb0SSepherosa Ziehau 	ifq_set_ready(&ifp->if_snd);
92843c2aeb0SSepherosa Ziehau 
92943c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)
93043c2aeb0SSepherosa Ziehau 		ifp->if_baudrate = IF_Gbps(2.5);
93143c2aeb0SSepherosa Ziehau 	else
93243c2aeb0SSepherosa Ziehau 		ifp->if_baudrate = IF_Gbps(1);
93343c2aeb0SSepherosa Ziehau 
93443c2aeb0SSepherosa Ziehau 	/* Assume a standard 1500 byte MTU size for mbuf allocations. */
93543c2aeb0SSepherosa Ziehau 	sc->mbuf_alloc_size  = MCLBYTES;
93643c2aeb0SSepherosa Ziehau 
93743c2aeb0SSepherosa Ziehau 	/* Look for our PHY. */
93843c2aeb0SSepherosa Ziehau 	rc = mii_phy_probe(dev, &sc->bce_miibus,
93943c2aeb0SSepherosa Ziehau 			   bce_ifmedia_upd, bce_ifmedia_sts);
94043c2aeb0SSepherosa Ziehau 	if (rc != 0) {
94143c2aeb0SSepherosa Ziehau 		device_printf(dev, "PHY probe failed!\n");
94243c2aeb0SSepherosa Ziehau 		goto fail;
94343c2aeb0SSepherosa Ziehau 	}
94443c2aeb0SSepherosa Ziehau 
94543c2aeb0SSepherosa Ziehau 	/* Attach to the Ethernet interface list. */
94643c2aeb0SSepherosa Ziehau 	ether_ifattach(ifp, sc->eaddr, NULL);
94743c2aeb0SSepherosa Ziehau 
948d0092544SSepherosa Ziehau 	callout_init(&sc->bce_tick_callout);
949d0092544SSepherosa Ziehau 	callout_init(&sc->bce_pulse_callout);
95043c2aeb0SSepherosa Ziehau 
95143c2aeb0SSepherosa Ziehau 	/* Hookup IRQ last. */
95295893fe4SSepherosa Ziehau 	rc = bus_setup_intr(dev, sc->bce_res_irq, INTR_MPSAFE, bce_intr, sc,
95343c2aeb0SSepherosa Ziehau 			    &sc->bce_intrhand, ifp->if_serializer);
95443c2aeb0SSepherosa Ziehau 	if (rc != 0) {
95543c2aeb0SSepherosa Ziehau 		device_printf(dev, "Failed to setup IRQ!\n");
95643c2aeb0SSepherosa Ziehau 		ether_ifdetach(ifp);
95743c2aeb0SSepherosa Ziehau 		goto fail;
95843c2aeb0SSepherosa Ziehau 	}
95943c2aeb0SSepherosa Ziehau 
9609db4b353SSepherosa Ziehau 	ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->bce_res_irq));
9619db4b353SSepherosa Ziehau 	KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus);
9629db4b353SSepherosa Ziehau 
96343c2aeb0SSepherosa Ziehau 	/* Print some important debugging info. */
96443c2aeb0SSepherosa Ziehau 	DBRUN(BCE_INFO, bce_dump_driver_state(sc));
96543c2aeb0SSepherosa Ziehau 
96643c2aeb0SSepherosa Ziehau 	/* Add the supported sysctls to the kernel. */
96743c2aeb0SSepherosa Ziehau 	bce_add_sysctls(sc);
96843c2aeb0SSepherosa Ziehau 
969d0092544SSepherosa Ziehau 	/*
970d0092544SSepherosa Ziehau 	 * The chip reset earlier notified the bootcode that
971d0092544SSepherosa Ziehau 	 * a driver is present.  We now need to start our pulse
972d0092544SSepherosa Ziehau 	 * routine so that the bootcode is reminded that we're
973d0092544SSepherosa Ziehau 	 * still running.
974d0092544SSepherosa Ziehau 	 */
975d0092544SSepherosa Ziehau 	bce_pulse(sc);
976d0092544SSepherosa Ziehau 
97743c2aeb0SSepherosa Ziehau 	/* Get the firmware running so IPMI still works */
97843c2aeb0SSepherosa Ziehau 	bce_mgmt_init(sc);
97943c2aeb0SSepherosa Ziehau 
980*b51a4d98SSepherosa Ziehau 	if (bootverbose)
981d0092544SSepherosa Ziehau 		bce_print_adapter_info(sc);
982d0092544SSepherosa Ziehau 
98343c2aeb0SSepherosa Ziehau 	return 0;
98443c2aeb0SSepherosa Ziehau fail:
98543c2aeb0SSepherosa Ziehau 	bce_detach(dev);
98643c2aeb0SSepherosa Ziehau 	return(rc);
98743c2aeb0SSepherosa Ziehau }
98843c2aeb0SSepherosa Ziehau 
98943c2aeb0SSepherosa Ziehau 
99043c2aeb0SSepherosa Ziehau /****************************************************************************/
99143c2aeb0SSepherosa Ziehau /* Device detach function.                                                  */
99243c2aeb0SSepherosa Ziehau /*                                                                          */
99343c2aeb0SSepherosa Ziehau /* Stops the controller, resets the controller, and releases resources.     */
99443c2aeb0SSepherosa Ziehau /*                                                                          */
99543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
99643c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
99743c2aeb0SSepherosa Ziehau /****************************************************************************/
99843c2aeb0SSepherosa Ziehau static int
99943c2aeb0SSepherosa Ziehau bce_detach(device_t dev)
100043c2aeb0SSepherosa Ziehau {
100143c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
100243c2aeb0SSepherosa Ziehau 
100343c2aeb0SSepherosa Ziehau 	if (device_is_attached(dev)) {
100443c2aeb0SSepherosa Ziehau 		struct ifnet *ifp = &sc->arpcom.ac_if;
1005d0092544SSepherosa Ziehau 		uint32_t msg;
100643c2aeb0SSepherosa Ziehau 
100743c2aeb0SSepherosa Ziehau 		/* Stop and reset the controller. */
100843c2aeb0SSepherosa Ziehau 		lwkt_serialize_enter(ifp->if_serializer);
1009d0092544SSepherosa Ziehau 		callout_stop(&sc->bce_pulse_callout);
101043c2aeb0SSepherosa Ziehau 		bce_stop(sc);
1011d0092544SSepherosa Ziehau 		if (sc->bce_flags & BCE_NO_WOL_FLAG)
1012d0092544SSepherosa Ziehau 			msg = BCE_DRV_MSG_CODE_UNLOAD_LNK_DN;
1013d0092544SSepherosa Ziehau 		else
1014d0092544SSepherosa Ziehau 			msg = BCE_DRV_MSG_CODE_UNLOAD;
1015d0092544SSepherosa Ziehau 		bce_reset(sc, msg);
101643c2aeb0SSepherosa Ziehau 		bus_teardown_intr(dev, sc->bce_res_irq, sc->bce_intrhand);
101743c2aeb0SSepherosa Ziehau 		lwkt_serialize_exit(ifp->if_serializer);
101843c2aeb0SSepherosa Ziehau 
101943c2aeb0SSepherosa Ziehau 		ether_ifdetach(ifp);
102043c2aeb0SSepherosa Ziehau 	}
102143c2aeb0SSepherosa Ziehau 
102243c2aeb0SSepherosa Ziehau 	/* If we have a child device on the MII bus remove it too. */
102343c2aeb0SSepherosa Ziehau 	if (sc->bce_miibus)
102443c2aeb0SSepherosa Ziehau 		device_delete_child(dev, sc->bce_miibus);
102543c2aeb0SSepherosa Ziehau 	bus_generic_detach(dev);
102643c2aeb0SSepherosa Ziehau 
102743c2aeb0SSepherosa Ziehau 	if (sc->bce_res_irq != NULL) {
102843c2aeb0SSepherosa Ziehau 		bus_release_resource(dev, SYS_RES_IRQ,
102943c2aeb0SSepherosa Ziehau 			sc->bce_flags & BCE_USING_MSI_FLAG ? 1 : 0,
103043c2aeb0SSepherosa Ziehau 			sc->bce_res_irq);
103143c2aeb0SSepherosa Ziehau 	}
103243c2aeb0SSepherosa Ziehau 
103343c2aeb0SSepherosa Ziehau #ifdef notyet
103443c2aeb0SSepherosa Ziehau 	if (sc->bce_flags & BCE_USING_MSI_FLAG)
103543c2aeb0SSepherosa Ziehau 		pci_release_msi(dev);
103643c2aeb0SSepherosa Ziehau #endif
103743c2aeb0SSepherosa Ziehau 
103843c2aeb0SSepherosa Ziehau 	if (sc->bce_res_mem != NULL) {
103943c2aeb0SSepherosa Ziehau 		bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
104043c2aeb0SSepherosa Ziehau 				     sc->bce_res_mem);
104143c2aeb0SSepherosa Ziehau 	}
104243c2aeb0SSepherosa Ziehau 
104343c2aeb0SSepherosa Ziehau 	bce_dma_free(sc);
104443c2aeb0SSepherosa Ziehau 
104543c2aeb0SSepherosa Ziehau 	if (sc->bce_sysctl_tree != NULL)
104643c2aeb0SSepherosa Ziehau 		sysctl_ctx_free(&sc->bce_sysctl_ctx);
104743c2aeb0SSepherosa Ziehau 
104843c2aeb0SSepherosa Ziehau 	return 0;
104943c2aeb0SSepherosa Ziehau }
105043c2aeb0SSepherosa Ziehau 
105143c2aeb0SSepherosa Ziehau 
105243c2aeb0SSepherosa Ziehau /****************************************************************************/
105343c2aeb0SSepherosa Ziehau /* Device shutdown function.                                                */
105443c2aeb0SSepherosa Ziehau /*                                                                          */
105543c2aeb0SSepherosa Ziehau /* Stops and resets the controller.                                         */
105643c2aeb0SSepherosa Ziehau /*                                                                          */
105743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
105843c2aeb0SSepherosa Ziehau /*   Nothing                                                                */
105943c2aeb0SSepherosa Ziehau /****************************************************************************/
106043c2aeb0SSepherosa Ziehau static void
106143c2aeb0SSepherosa Ziehau bce_shutdown(device_t dev)
106243c2aeb0SSepherosa Ziehau {
106343c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
106443c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
1065d0092544SSepherosa Ziehau 	uint32_t msg;
106643c2aeb0SSepherosa Ziehau 
106743c2aeb0SSepherosa Ziehau 	lwkt_serialize_enter(ifp->if_serializer);
106843c2aeb0SSepherosa Ziehau 	bce_stop(sc);
1069d0092544SSepherosa Ziehau 	if (sc->bce_flags & BCE_NO_WOL_FLAG)
1070d0092544SSepherosa Ziehau 		msg = BCE_DRV_MSG_CODE_UNLOAD_LNK_DN;
1071d0092544SSepherosa Ziehau 	else
1072d0092544SSepherosa Ziehau 		msg = BCE_DRV_MSG_CODE_UNLOAD;
1073d0092544SSepherosa Ziehau 	bce_reset(sc, msg);
107443c2aeb0SSepherosa Ziehau 	lwkt_serialize_exit(ifp->if_serializer);
107543c2aeb0SSepherosa Ziehau }
107643c2aeb0SSepherosa Ziehau 
107743c2aeb0SSepherosa Ziehau 
107843c2aeb0SSepherosa Ziehau /****************************************************************************/
107943c2aeb0SSepherosa Ziehau /* Indirect register read.                                                  */
108043c2aeb0SSepherosa Ziehau /*                                                                          */
108143c2aeb0SSepherosa Ziehau /* Reads NetXtreme II registers using an index/data register pair in PCI    */
108243c2aeb0SSepherosa Ziehau /* configuration space.  Using this mechanism avoids issues with posted     */
108343c2aeb0SSepherosa Ziehau /* reads but is much slower than memory-mapped I/O.                         */
108443c2aeb0SSepherosa Ziehau /*                                                                          */
108543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
108643c2aeb0SSepherosa Ziehau /*   The value of the register.                                             */
108743c2aeb0SSepherosa Ziehau /****************************************************************************/
108843c2aeb0SSepherosa Ziehau static uint32_t
108943c2aeb0SSepherosa Ziehau bce_reg_rd_ind(struct bce_softc *sc, uint32_t offset)
109043c2aeb0SSepherosa Ziehau {
109143c2aeb0SSepherosa Ziehau 	device_t dev = sc->bce_dev;
109243c2aeb0SSepherosa Ziehau 
109343c2aeb0SSepherosa Ziehau 	pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4);
109443c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
109543c2aeb0SSepherosa Ziehau 	{
109643c2aeb0SSepherosa Ziehau 		uint32_t val;
109743c2aeb0SSepherosa Ziehau 		val = pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4);
109843c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_EXCESSIVE,
109943c2aeb0SSepherosa Ziehau 			"%s(); offset = 0x%08X, val = 0x%08X\n",
110043c2aeb0SSepherosa Ziehau 			__func__, offset, val);
110143c2aeb0SSepherosa Ziehau 		return val;
110243c2aeb0SSepherosa Ziehau 	}
110343c2aeb0SSepherosa Ziehau #else
110443c2aeb0SSepherosa Ziehau 	return pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4);
110543c2aeb0SSepherosa Ziehau #endif
110643c2aeb0SSepherosa Ziehau }
110743c2aeb0SSepherosa Ziehau 
110843c2aeb0SSepherosa Ziehau 
110943c2aeb0SSepherosa Ziehau /****************************************************************************/
111043c2aeb0SSepherosa Ziehau /* Indirect register write.                                                 */
111143c2aeb0SSepherosa Ziehau /*                                                                          */
111243c2aeb0SSepherosa Ziehau /* Writes NetXtreme II registers using an index/data register pair in PCI   */
111343c2aeb0SSepherosa Ziehau /* configuration space.  Using this mechanism avoids issues with posted     */
111443c2aeb0SSepherosa Ziehau /* writes but is muchh slower than memory-mapped I/O.                       */
111543c2aeb0SSepherosa Ziehau /*                                                                          */
111643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
111743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
111843c2aeb0SSepherosa Ziehau /****************************************************************************/
111943c2aeb0SSepherosa Ziehau static void
112043c2aeb0SSepherosa Ziehau bce_reg_wr_ind(struct bce_softc *sc, uint32_t offset, uint32_t val)
112143c2aeb0SSepherosa Ziehau {
112243c2aeb0SSepherosa Ziehau 	device_t dev = sc->bce_dev;
112343c2aeb0SSepherosa Ziehau 
112443c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n",
112543c2aeb0SSepherosa Ziehau 		__func__, offset, val);
112643c2aeb0SSepherosa Ziehau 
112743c2aeb0SSepherosa Ziehau 	pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4);
112843c2aeb0SSepherosa Ziehau 	pci_write_config(dev, BCE_PCICFG_REG_WINDOW, val, 4);
112943c2aeb0SSepherosa Ziehau }
113043c2aeb0SSepherosa Ziehau 
113143c2aeb0SSepherosa Ziehau 
113243c2aeb0SSepherosa Ziehau /****************************************************************************/
1133bc30d40dSSepherosa Ziehau /* Shared memory write.                                                     */
1134bc30d40dSSepherosa Ziehau /*                                                                          */
1135bc30d40dSSepherosa Ziehau /* Writes NetXtreme II shared memory region.                                */
1136bc30d40dSSepherosa Ziehau /*                                                                          */
1137bc30d40dSSepherosa Ziehau /* Returns:                                                                 */
1138bc30d40dSSepherosa Ziehau /*   Nothing.                                                               */
1139bc30d40dSSepherosa Ziehau /****************************************************************************/
1140bc30d40dSSepherosa Ziehau static void
1141bc30d40dSSepherosa Ziehau bce_shmem_wr(struct bce_softc *sc, uint32_t offset, uint32_t val)
1142bc30d40dSSepherosa Ziehau {
1143bc30d40dSSepherosa Ziehau 	bce_reg_wr_ind(sc, sc->bce_shmem_base + offset, val);
1144bc30d40dSSepherosa Ziehau }
1145bc30d40dSSepherosa Ziehau 
1146bc30d40dSSepherosa Ziehau 
1147bc30d40dSSepherosa Ziehau /****************************************************************************/
1148bc30d40dSSepherosa Ziehau /* Shared memory read.                                                      */
1149bc30d40dSSepherosa Ziehau /*                                                                          */
1150bc30d40dSSepherosa Ziehau /* Reads NetXtreme II shared memory region.                                 */
1151bc30d40dSSepherosa Ziehau /*                                                                          */
1152bc30d40dSSepherosa Ziehau /* Returns:                                                                 */
1153bc30d40dSSepherosa Ziehau /*   The 32 bit value read.                                                 */
1154bc30d40dSSepherosa Ziehau /****************************************************************************/
1155bc30d40dSSepherosa Ziehau static u32
1156bc30d40dSSepherosa Ziehau bce_shmem_rd(struct bce_softc *sc, uint32_t offset)
1157bc30d40dSSepherosa Ziehau {
1158bc30d40dSSepherosa Ziehau 	return bce_reg_rd_ind(sc, sc->bce_shmem_base + offset);
1159bc30d40dSSepherosa Ziehau }
1160bc30d40dSSepherosa Ziehau 
1161bc30d40dSSepherosa Ziehau 
1162bc30d40dSSepherosa Ziehau /****************************************************************************/
116343c2aeb0SSepherosa Ziehau /* Context memory write.                                                    */
116443c2aeb0SSepherosa Ziehau /*                                                                          */
116543c2aeb0SSepherosa Ziehau /* The NetXtreme II controller uses context memory to track connection      */
116643c2aeb0SSepherosa Ziehau /* information for L2 and higher network protocols.                         */
116743c2aeb0SSepherosa Ziehau /*                                                                          */
116843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
116943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
117043c2aeb0SSepherosa Ziehau /****************************************************************************/
117143c2aeb0SSepherosa Ziehau static void
1172d0092544SSepherosa Ziehau bce_ctx_wr(struct bce_softc *sc, uint32_t cid_addr, uint32_t ctx_offset,
1173d0092544SSepherosa Ziehau     uint32_t ctx_val)
117443c2aeb0SSepherosa Ziehau {
1175d0092544SSepherosa Ziehau 	uint32_t idx, offset = ctx_offset + cid_addr;
1176d0092544SSepherosa Ziehau 	uint32_t val, retry_cnt = 5;
117743c2aeb0SSepherosa Ziehau 
1178d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
1179d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
1180d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_CTX_CTX_DATA, ctx_val);
1181d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_CTX_CTX_CTRL, (offset | BCE_CTX_CTX_CTRL_WRITE_REQ));
1182d0092544SSepherosa Ziehau 
1183d0092544SSepherosa Ziehau 		for (idx = 0; idx < retry_cnt; idx++) {
1184d0092544SSepherosa Ziehau 			val = REG_RD(sc, BCE_CTX_CTX_CTRL);
1185d0092544SSepherosa Ziehau 			if ((val & BCE_CTX_CTX_CTRL_WRITE_REQ) == 0)
1186d0092544SSepherosa Ziehau 				break;
1187d0092544SSepherosa Ziehau 			DELAY(5);
1188d0092544SSepherosa Ziehau 		}
1189d0092544SSepherosa Ziehau 
1190d0092544SSepherosa Ziehau 		if (val & BCE_CTX_CTX_CTRL_WRITE_REQ) {
1191d0092544SSepherosa Ziehau 			device_printf(sc->bce_dev,
1192d0092544SSepherosa Ziehau 			    "Unable to write CTX memory: "
1193d0092544SSepherosa Ziehau 			    "cid_addr = 0x%08X, offset = 0x%08X!\n",
1194d0092544SSepherosa Ziehau 			    cid_addr, ctx_offset);
1195d0092544SSepherosa Ziehau 		}
1196d0092544SSepherosa Ziehau 	} else {
119743c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_CTX_DATA_ADR, offset);
1198d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_CTX_DATA, ctx_val);
1199d0092544SSepherosa Ziehau 	}
120043c2aeb0SSepherosa Ziehau }
120143c2aeb0SSepherosa Ziehau 
120243c2aeb0SSepherosa Ziehau 
120343c2aeb0SSepherosa Ziehau /****************************************************************************/
120443c2aeb0SSepherosa Ziehau /* PHY register read.                                                       */
120543c2aeb0SSepherosa Ziehau /*                                                                          */
120643c2aeb0SSepherosa Ziehau /* Implements register reads on the MII bus.                                */
120743c2aeb0SSepherosa Ziehau /*                                                                          */
120843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
120943c2aeb0SSepherosa Ziehau /*   The value of the register.                                             */
121043c2aeb0SSepherosa Ziehau /****************************************************************************/
121143c2aeb0SSepherosa Ziehau static int
121243c2aeb0SSepherosa Ziehau bce_miibus_read_reg(device_t dev, int phy, int reg)
121343c2aeb0SSepherosa Ziehau {
121443c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
121543c2aeb0SSepherosa Ziehau 	uint32_t val;
121643c2aeb0SSepherosa Ziehau 	int i;
121743c2aeb0SSepherosa Ziehau 
121843c2aeb0SSepherosa Ziehau 	/* Make sure we are accessing the correct PHY address. */
121943c2aeb0SSepherosa Ziehau 	if (phy != sc->bce_phy_addr) {
122043c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE,
122143c2aeb0SSepherosa Ziehau 			"Invalid PHY address %d for PHY read!\n", phy);
122243c2aeb0SSepherosa Ziehau 		return 0;
122343c2aeb0SSepherosa Ziehau 	}
122443c2aeb0SSepherosa Ziehau 
122543c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
122643c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_EMAC_MDIO_MODE);
122743c2aeb0SSepherosa Ziehau 		val &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL;
122843c2aeb0SSepherosa Ziehau 
122943c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_MDIO_MODE, val);
123043c2aeb0SSepherosa Ziehau 		REG_RD(sc, BCE_EMAC_MDIO_MODE);
123143c2aeb0SSepherosa Ziehau 
123243c2aeb0SSepherosa Ziehau 		DELAY(40);
123343c2aeb0SSepherosa Ziehau 	}
123443c2aeb0SSepherosa Ziehau 
123543c2aeb0SSepherosa Ziehau 	val = BCE_MIPHY(phy) | BCE_MIREG(reg) |
123643c2aeb0SSepherosa Ziehau 	      BCE_EMAC_MDIO_COMM_COMMAND_READ | BCE_EMAC_MDIO_COMM_DISEXT |
123743c2aeb0SSepherosa Ziehau 	      BCE_EMAC_MDIO_COMM_START_BUSY;
123843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_MDIO_COMM, val);
123943c2aeb0SSepherosa Ziehau 
124043c2aeb0SSepherosa Ziehau 	for (i = 0; i < BCE_PHY_TIMEOUT; i++) {
124143c2aeb0SSepherosa Ziehau 		DELAY(10);
124243c2aeb0SSepherosa Ziehau 
124343c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_EMAC_MDIO_COMM);
124443c2aeb0SSepherosa Ziehau 		if (!(val & BCE_EMAC_MDIO_COMM_START_BUSY)) {
124543c2aeb0SSepherosa Ziehau 			DELAY(5);
124643c2aeb0SSepherosa Ziehau 
124743c2aeb0SSepherosa Ziehau 			val = REG_RD(sc, BCE_EMAC_MDIO_COMM);
124843c2aeb0SSepherosa Ziehau 			val &= BCE_EMAC_MDIO_COMM_DATA;
124943c2aeb0SSepherosa Ziehau 			break;
125043c2aeb0SSepherosa Ziehau 		}
125143c2aeb0SSepherosa Ziehau 	}
125243c2aeb0SSepherosa Ziehau 
125343c2aeb0SSepherosa Ziehau 	if (val & BCE_EMAC_MDIO_COMM_START_BUSY) {
125443c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
125543c2aeb0SSepherosa Ziehau 			  "Error: PHY read timeout! phy = %d, reg = 0x%04X\n",
125643c2aeb0SSepherosa Ziehau 			  phy, reg);
125743c2aeb0SSepherosa Ziehau 		val = 0x0;
125843c2aeb0SSepherosa Ziehau 	} else {
125943c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_EMAC_MDIO_COMM);
126043c2aeb0SSepherosa Ziehau 	}
126143c2aeb0SSepherosa Ziehau 
126243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE,
126343c2aeb0SSepherosa Ziehau 		"%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n",
126443c2aeb0SSepherosa Ziehau 		__func__, phy, (uint16_t)reg & 0xffff, (uint16_t) val & 0xffff);
126543c2aeb0SSepherosa Ziehau 
126643c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
126743c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_EMAC_MDIO_MODE);
126843c2aeb0SSepherosa Ziehau 		val |= BCE_EMAC_MDIO_MODE_AUTO_POLL;
126943c2aeb0SSepherosa Ziehau 
127043c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_MDIO_MODE, val);
127143c2aeb0SSepherosa Ziehau 		REG_RD(sc, BCE_EMAC_MDIO_MODE);
127243c2aeb0SSepherosa Ziehau 
127343c2aeb0SSepherosa Ziehau 		DELAY(40);
127443c2aeb0SSepherosa Ziehau 	}
127543c2aeb0SSepherosa Ziehau 	return (val & 0xffff);
127643c2aeb0SSepherosa Ziehau }
127743c2aeb0SSepherosa Ziehau 
127843c2aeb0SSepherosa Ziehau 
127943c2aeb0SSepherosa Ziehau /****************************************************************************/
128043c2aeb0SSepherosa Ziehau /* PHY register write.                                                      */
128143c2aeb0SSepherosa Ziehau /*                                                                          */
128243c2aeb0SSepherosa Ziehau /* Implements register writes on the MII bus.                               */
128343c2aeb0SSepherosa Ziehau /*                                                                          */
128443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
128543c2aeb0SSepherosa Ziehau /*   The value of the register.                                             */
128643c2aeb0SSepherosa Ziehau /****************************************************************************/
128743c2aeb0SSepherosa Ziehau static int
128843c2aeb0SSepherosa Ziehau bce_miibus_write_reg(device_t dev, int phy, int reg, int val)
128943c2aeb0SSepherosa Ziehau {
129043c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
129143c2aeb0SSepherosa Ziehau 	uint32_t val1;
129243c2aeb0SSepherosa Ziehau 	int i;
129343c2aeb0SSepherosa Ziehau 
129443c2aeb0SSepherosa Ziehau 	/* Make sure we are accessing the correct PHY address. */
129543c2aeb0SSepherosa Ziehau 	if (phy != sc->bce_phy_addr) {
129643c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_WARN,
129743c2aeb0SSepherosa Ziehau 			"Invalid PHY address %d for PHY write!\n", phy);
129843c2aeb0SSepherosa Ziehau 		return(0);
129943c2aeb0SSepherosa Ziehau 	}
130043c2aeb0SSepherosa Ziehau 
130143c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE,
130243c2aeb0SSepherosa Ziehau 		"%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n",
130343c2aeb0SSepherosa Ziehau 		__func__, phy, (uint16_t)(reg & 0xffff),
130443c2aeb0SSepherosa Ziehau 		(uint16_t)(val & 0xffff));
130543c2aeb0SSepherosa Ziehau 
130643c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
130743c2aeb0SSepherosa Ziehau 		val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE);
130843c2aeb0SSepherosa Ziehau 		val1 &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL;
130943c2aeb0SSepherosa Ziehau 
131043c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_MDIO_MODE, val1);
131143c2aeb0SSepherosa Ziehau 		REG_RD(sc, BCE_EMAC_MDIO_MODE);
131243c2aeb0SSepherosa Ziehau 
131343c2aeb0SSepherosa Ziehau 		DELAY(40);
131443c2aeb0SSepherosa Ziehau 	}
131543c2aeb0SSepherosa Ziehau 
131643c2aeb0SSepherosa Ziehau 	val1 = BCE_MIPHY(phy) | BCE_MIREG(reg) | val |
131743c2aeb0SSepherosa Ziehau 		BCE_EMAC_MDIO_COMM_COMMAND_WRITE |
131843c2aeb0SSepherosa Ziehau 		BCE_EMAC_MDIO_COMM_START_BUSY | BCE_EMAC_MDIO_COMM_DISEXT;
131943c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_MDIO_COMM, val1);
132043c2aeb0SSepherosa Ziehau 
132143c2aeb0SSepherosa Ziehau 	for (i = 0; i < BCE_PHY_TIMEOUT; i++) {
132243c2aeb0SSepherosa Ziehau 		DELAY(10);
132343c2aeb0SSepherosa Ziehau 
132443c2aeb0SSepherosa Ziehau 		val1 = REG_RD(sc, BCE_EMAC_MDIO_COMM);
132543c2aeb0SSepherosa Ziehau 		if (!(val1 & BCE_EMAC_MDIO_COMM_START_BUSY)) {
132643c2aeb0SSepherosa Ziehau 			DELAY(5);
132743c2aeb0SSepherosa Ziehau 			break;
132843c2aeb0SSepherosa Ziehau 		}
132943c2aeb0SSepherosa Ziehau 	}
133043c2aeb0SSepherosa Ziehau 
133143c2aeb0SSepherosa Ziehau 	if (val1 & BCE_EMAC_MDIO_COMM_START_BUSY)
133243c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "PHY write timeout!\n");
133343c2aeb0SSepherosa Ziehau 
133443c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
133543c2aeb0SSepherosa Ziehau 		val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE);
133643c2aeb0SSepherosa Ziehau 		val1 |= BCE_EMAC_MDIO_MODE_AUTO_POLL;
133743c2aeb0SSepherosa Ziehau 
133843c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_MDIO_MODE, val1);
133943c2aeb0SSepherosa Ziehau 		REG_RD(sc, BCE_EMAC_MDIO_MODE);
134043c2aeb0SSepherosa Ziehau 
134143c2aeb0SSepherosa Ziehau 		DELAY(40);
134243c2aeb0SSepherosa Ziehau 	}
134343c2aeb0SSepherosa Ziehau 	return 0;
134443c2aeb0SSepherosa Ziehau }
134543c2aeb0SSepherosa Ziehau 
134643c2aeb0SSepherosa Ziehau 
134743c2aeb0SSepherosa Ziehau /****************************************************************************/
134843c2aeb0SSepherosa Ziehau /* MII bus status change.                                                   */
134943c2aeb0SSepherosa Ziehau /*                                                                          */
135043c2aeb0SSepherosa Ziehau /* Called by the MII bus driver when the PHY establishes link to set the    */
135143c2aeb0SSepherosa Ziehau /* MAC interface registers.                                                 */
135243c2aeb0SSepherosa Ziehau /*                                                                          */
135343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
135443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
135543c2aeb0SSepherosa Ziehau /****************************************************************************/
135643c2aeb0SSepherosa Ziehau static void
135743c2aeb0SSepherosa Ziehau bce_miibus_statchg(device_t dev)
135843c2aeb0SSepherosa Ziehau {
135943c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
136043c2aeb0SSepherosa Ziehau 	struct mii_data *mii = device_get_softc(sc->bce_miibus);
136143c2aeb0SSepherosa Ziehau 
136243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "mii_media_active = 0x%08X\n",
136343c2aeb0SSepherosa Ziehau 		mii->mii_media_active);
136443c2aeb0SSepherosa Ziehau 
136543c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
136643c2aeb0SSepherosa Ziehau 	/* Decode the interface media flags. */
136743c2aeb0SSepherosa Ziehau 	if_printf(&sc->arpcom.ac_if, "Media: ( ");
136843c2aeb0SSepherosa Ziehau 	switch(IFM_TYPE(mii->mii_media_active)) {
136943c2aeb0SSepherosa Ziehau 	case IFM_ETHER:
137043c2aeb0SSepherosa Ziehau 		kprintf("Ethernet )");
137143c2aeb0SSepherosa Ziehau 		break;
137243c2aeb0SSepherosa Ziehau 	default:
137343c2aeb0SSepherosa Ziehau 		kprintf("Unknown )");
137443c2aeb0SSepherosa Ziehau 		break;
137543c2aeb0SSepherosa Ziehau 	}
137643c2aeb0SSepherosa Ziehau 
137743c2aeb0SSepherosa Ziehau 	kprintf(" Media Options: ( ");
137843c2aeb0SSepherosa Ziehau 	switch(IFM_SUBTYPE(mii->mii_media_active)) {
137943c2aeb0SSepherosa Ziehau 	case IFM_AUTO:
138043c2aeb0SSepherosa Ziehau 		kprintf("Autoselect )");
138143c2aeb0SSepherosa Ziehau 		break;
138243c2aeb0SSepherosa Ziehau 	case IFM_MANUAL:
138343c2aeb0SSepherosa Ziehau 		kprintf("Manual )");
138443c2aeb0SSepherosa Ziehau 		break;
138543c2aeb0SSepherosa Ziehau 	case IFM_NONE:
138643c2aeb0SSepherosa Ziehau 		kprintf("None )");
138743c2aeb0SSepherosa Ziehau 		break;
138843c2aeb0SSepherosa Ziehau 	case IFM_10_T:
138943c2aeb0SSepherosa Ziehau 		kprintf("10Base-T )");
139043c2aeb0SSepherosa Ziehau 		break;
139143c2aeb0SSepherosa Ziehau 	case IFM_100_TX:
139243c2aeb0SSepherosa Ziehau 		kprintf("100Base-TX )");
139343c2aeb0SSepherosa Ziehau 		break;
139443c2aeb0SSepherosa Ziehau 	case IFM_1000_SX:
139543c2aeb0SSepherosa Ziehau 		kprintf("1000Base-SX )");
139643c2aeb0SSepherosa Ziehau 		break;
139743c2aeb0SSepherosa Ziehau 	case IFM_1000_T:
139843c2aeb0SSepherosa Ziehau 		kprintf("1000Base-T )");
139943c2aeb0SSepherosa Ziehau 		break;
140043c2aeb0SSepherosa Ziehau 	default:
140143c2aeb0SSepherosa Ziehau 		kprintf("Other )");
140243c2aeb0SSepherosa Ziehau 		break;
140343c2aeb0SSepherosa Ziehau 	}
140443c2aeb0SSepherosa Ziehau 
140543c2aeb0SSepherosa Ziehau 	kprintf(" Global Options: (");
140643c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_FDX)
140743c2aeb0SSepherosa Ziehau 		kprintf(" FullDuplex");
140843c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_HDX)
140943c2aeb0SSepherosa Ziehau 		kprintf(" HalfDuplex");
141043c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_LOOP)
141143c2aeb0SSepherosa Ziehau 		kprintf(" Loopback");
141243c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_FLAG0)
141343c2aeb0SSepherosa Ziehau 		kprintf(" Flag0");
141443c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_FLAG1)
141543c2aeb0SSepherosa Ziehau 		kprintf(" Flag1");
141643c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_FLAG2)
141743c2aeb0SSepherosa Ziehau 		kprintf(" Flag2");
141843c2aeb0SSepherosa Ziehau 	kprintf(" )\n");
141943c2aeb0SSepherosa Ziehau #endif
142043c2aeb0SSepherosa Ziehau 
142143c2aeb0SSepherosa Ziehau 	BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT);
142243c2aeb0SSepherosa Ziehau 
142343c2aeb0SSepherosa Ziehau 	/*
142443c2aeb0SSepherosa Ziehau 	 * Set MII or GMII interface based on the speed negotiated
142543c2aeb0SSepherosa Ziehau 	 * by the PHY.
142643c2aeb0SSepherosa Ziehau 	 */
142743c2aeb0SSepherosa Ziehau 	if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
142843c2aeb0SSepherosa Ziehau 	    IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) {
142943c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting GMII interface.\n");
143043c2aeb0SSepherosa Ziehau 		BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_GMII);
143143c2aeb0SSepherosa Ziehau 	} else {
143243c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting MII interface.\n");
143343c2aeb0SSepherosa Ziehau 		BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_MII);
143443c2aeb0SSepherosa Ziehau 	}
143543c2aeb0SSepherosa Ziehau 
143643c2aeb0SSepherosa Ziehau 	/*
143743c2aeb0SSepherosa Ziehau 	 * Set half or full duplex based on the duplicity negotiated
143843c2aeb0SSepherosa Ziehau 	 * by the PHY.
143943c2aeb0SSepherosa Ziehau 	 */
144043c2aeb0SSepherosa Ziehau 	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
144143c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting Full-Duplex interface.\n");
144243c2aeb0SSepherosa Ziehau 		BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX);
144343c2aeb0SSepherosa Ziehau 	} else {
144443c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting Half-Duplex interface.\n");
144543c2aeb0SSepherosa Ziehau 		BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX);
144643c2aeb0SSepherosa Ziehau 	}
144743c2aeb0SSepherosa Ziehau }
144843c2aeb0SSepherosa Ziehau 
144943c2aeb0SSepherosa Ziehau 
145043c2aeb0SSepherosa Ziehau /****************************************************************************/
145143c2aeb0SSepherosa Ziehau /* Acquire NVRAM lock.                                                      */
145243c2aeb0SSepherosa Ziehau /*                                                                          */
145343c2aeb0SSepherosa Ziehau /* Before the NVRAM can be accessed the caller must acquire an NVRAM lock.  */
145443c2aeb0SSepherosa Ziehau /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is     */
145543c2aeb0SSepherosa Ziehau /* for use by the driver.                                                   */
145643c2aeb0SSepherosa Ziehau /*                                                                          */
145743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
145843c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
145943c2aeb0SSepherosa Ziehau /****************************************************************************/
146043c2aeb0SSepherosa Ziehau static int
146143c2aeb0SSepherosa Ziehau bce_acquire_nvram_lock(struct bce_softc *sc)
146243c2aeb0SSepherosa Ziehau {
146343c2aeb0SSepherosa Ziehau 	uint32_t val;
146443c2aeb0SSepherosa Ziehau 	int j;
146543c2aeb0SSepherosa Ziehau 
146643c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Acquiring NVRAM lock.\n");
146743c2aeb0SSepherosa Ziehau 
146843c2aeb0SSepherosa Ziehau 	/* Request access to the flash interface. */
146943c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_SET2);
147043c2aeb0SSepherosa Ziehau 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
147143c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_NVM_SW_ARB);
147243c2aeb0SSepherosa Ziehau 		if (val & BCE_NVM_SW_ARB_ARB_ARB2)
147343c2aeb0SSepherosa Ziehau 			break;
147443c2aeb0SSepherosa Ziehau 
147543c2aeb0SSepherosa Ziehau 		DELAY(5);
147643c2aeb0SSepherosa Ziehau 	}
147743c2aeb0SSepherosa Ziehau 
147843c2aeb0SSepherosa Ziehau 	if (j >= NVRAM_TIMEOUT_COUNT) {
147943c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_WARN, "Timeout acquiring NVRAM lock!\n");
148043c2aeb0SSepherosa Ziehau 		return EBUSY;
148143c2aeb0SSepherosa Ziehau 	}
148243c2aeb0SSepherosa Ziehau 	return 0;
148343c2aeb0SSepherosa Ziehau }
148443c2aeb0SSepherosa Ziehau 
148543c2aeb0SSepherosa Ziehau 
148643c2aeb0SSepherosa Ziehau /****************************************************************************/
148743c2aeb0SSepherosa Ziehau /* Release NVRAM lock.                                                      */
148843c2aeb0SSepherosa Ziehau /*                                                                          */
148943c2aeb0SSepherosa Ziehau /* When the caller is finished accessing NVRAM the lock must be released.   */
149043c2aeb0SSepherosa Ziehau /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is     */
149143c2aeb0SSepherosa Ziehau /* for use by the driver.                                                   */
149243c2aeb0SSepherosa Ziehau /*                                                                          */
149343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
149443c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
149543c2aeb0SSepherosa Ziehau /****************************************************************************/
149643c2aeb0SSepherosa Ziehau static int
149743c2aeb0SSepherosa Ziehau bce_release_nvram_lock(struct bce_softc *sc)
149843c2aeb0SSepherosa Ziehau {
149943c2aeb0SSepherosa Ziehau 	int j;
150043c2aeb0SSepherosa Ziehau 	uint32_t val;
150143c2aeb0SSepherosa Ziehau 
150243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Releasing NVRAM lock.\n");
150343c2aeb0SSepherosa Ziehau 
150443c2aeb0SSepherosa Ziehau 	/*
150543c2aeb0SSepherosa Ziehau 	 * Relinquish nvram interface.
150643c2aeb0SSepherosa Ziehau 	 */
150743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_CLR2);
150843c2aeb0SSepherosa Ziehau 
150943c2aeb0SSepherosa Ziehau 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
151043c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_NVM_SW_ARB);
151143c2aeb0SSepherosa Ziehau 		if (!(val & BCE_NVM_SW_ARB_ARB_ARB2))
151243c2aeb0SSepherosa Ziehau 			break;
151343c2aeb0SSepherosa Ziehau 
151443c2aeb0SSepherosa Ziehau 		DELAY(5);
151543c2aeb0SSepherosa Ziehau 	}
151643c2aeb0SSepherosa Ziehau 
151743c2aeb0SSepherosa Ziehau 	if (j >= NVRAM_TIMEOUT_COUNT) {
151843c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_WARN, "Timeout reeasing NVRAM lock!\n");
151943c2aeb0SSepherosa Ziehau 		return EBUSY;
152043c2aeb0SSepherosa Ziehau 	}
152143c2aeb0SSepherosa Ziehau 	return 0;
152243c2aeb0SSepherosa Ziehau }
152343c2aeb0SSepherosa Ziehau 
152443c2aeb0SSepherosa Ziehau 
152543c2aeb0SSepherosa Ziehau /****************************************************************************/
152643c2aeb0SSepherosa Ziehau /* Enable NVRAM access.                                                     */
152743c2aeb0SSepherosa Ziehau /*                                                                          */
152843c2aeb0SSepherosa Ziehau /* Before accessing NVRAM for read or write operations the caller must      */
152943c2aeb0SSepherosa Ziehau /* enabled NVRAM access.                                                    */
153043c2aeb0SSepherosa Ziehau /*                                                                          */
153143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
153243c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
153343c2aeb0SSepherosa Ziehau /****************************************************************************/
153443c2aeb0SSepherosa Ziehau static void
153543c2aeb0SSepherosa Ziehau bce_enable_nvram_access(struct bce_softc *sc)
153643c2aeb0SSepherosa Ziehau {
153743c2aeb0SSepherosa Ziehau 	uint32_t val;
153843c2aeb0SSepherosa Ziehau 
153943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Enabling NVRAM access.\n");
154043c2aeb0SSepherosa Ziehau 
154143c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE);
154243c2aeb0SSepherosa Ziehau 	/* Enable both bits, even on read. */
154343c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_ACCESS_ENABLE,
154443c2aeb0SSepherosa Ziehau 	       val | BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN);
154543c2aeb0SSepherosa Ziehau }
154643c2aeb0SSepherosa Ziehau 
154743c2aeb0SSepherosa Ziehau 
154843c2aeb0SSepherosa Ziehau /****************************************************************************/
154943c2aeb0SSepherosa Ziehau /* Disable NVRAM access.                                                    */
155043c2aeb0SSepherosa Ziehau /*                                                                          */
155143c2aeb0SSepherosa Ziehau /* When the caller is finished accessing NVRAM access must be disabled.     */
155243c2aeb0SSepherosa Ziehau /*                                                                          */
155343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
155443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
155543c2aeb0SSepherosa Ziehau /****************************************************************************/
155643c2aeb0SSepherosa Ziehau static void
155743c2aeb0SSepherosa Ziehau bce_disable_nvram_access(struct bce_softc *sc)
155843c2aeb0SSepherosa Ziehau {
155943c2aeb0SSepherosa Ziehau 	uint32_t val;
156043c2aeb0SSepherosa Ziehau 
156143c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Disabling NVRAM access.\n");
156243c2aeb0SSepherosa Ziehau 
156343c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE);
156443c2aeb0SSepherosa Ziehau 
156543c2aeb0SSepherosa Ziehau 	/* Disable both bits, even after read. */
156643c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_ACCESS_ENABLE,
156743c2aeb0SSepherosa Ziehau 	       val & ~(BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN));
156843c2aeb0SSepherosa Ziehau }
156943c2aeb0SSepherosa Ziehau 
157043c2aeb0SSepherosa Ziehau 
157143c2aeb0SSepherosa Ziehau /****************************************************************************/
157243c2aeb0SSepherosa Ziehau /* Read a dword (32 bits) from NVRAM.                                       */
157343c2aeb0SSepherosa Ziehau /*                                                                          */
157443c2aeb0SSepherosa Ziehau /* Read a 32 bit word from NVRAM.  The caller is assumed to have already    */
157543c2aeb0SSepherosa Ziehau /* obtained the NVRAM lock and enabled the controller for NVRAM access.     */
157643c2aeb0SSepherosa Ziehau /*                                                                          */
157743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
157843c2aeb0SSepherosa Ziehau /*   0 on success and the 32 bit value read, positive value on failure.     */
157943c2aeb0SSepherosa Ziehau /****************************************************************************/
158043c2aeb0SSepherosa Ziehau static int
158143c2aeb0SSepherosa Ziehau bce_nvram_read_dword(struct bce_softc *sc, uint32_t offset, uint8_t *ret_val,
158243c2aeb0SSepherosa Ziehau 		     uint32_t cmd_flags)
158343c2aeb0SSepherosa Ziehau {
158443c2aeb0SSepherosa Ziehau 	uint32_t cmd;
158543c2aeb0SSepherosa Ziehau 	int i, rc = 0;
158643c2aeb0SSepherosa Ziehau 
158743c2aeb0SSepherosa Ziehau 	/* Build the command word. */
158843c2aeb0SSepherosa Ziehau 	cmd = BCE_NVM_COMMAND_DOIT | cmd_flags;
158943c2aeb0SSepherosa Ziehau 
159043c2aeb0SSepherosa Ziehau 	/* Calculate the offset for buffered flash. */
1591d0092544SSepherosa Ziehau 	if (sc->bce_flash_info->flags & BCE_NV_TRANSLATE) {
159243c2aeb0SSepherosa Ziehau 		offset = ((offset / sc->bce_flash_info->page_size) <<
159343c2aeb0SSepherosa Ziehau 			  sc->bce_flash_info->page_bits) +
159443c2aeb0SSepherosa Ziehau 			 (offset % sc->bce_flash_info->page_size);
159543c2aeb0SSepherosa Ziehau 	}
159643c2aeb0SSepherosa Ziehau 
159743c2aeb0SSepherosa Ziehau 	/*
159843c2aeb0SSepherosa Ziehau 	 * Clear the DONE bit separately, set the address to read,
159943c2aeb0SSepherosa Ziehau 	 * and issue the read.
160043c2aeb0SSepherosa Ziehau 	 */
160143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE);
160243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE);
160343c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_COMMAND, cmd);
160443c2aeb0SSepherosa Ziehau 
160543c2aeb0SSepherosa Ziehau 	/* Wait for completion. */
160643c2aeb0SSepherosa Ziehau 	for (i = 0; i < NVRAM_TIMEOUT_COUNT; i++) {
160743c2aeb0SSepherosa Ziehau 		uint32_t val;
160843c2aeb0SSepherosa Ziehau 
160943c2aeb0SSepherosa Ziehau 		DELAY(5);
161043c2aeb0SSepherosa Ziehau 
161143c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_NVM_COMMAND);
161243c2aeb0SSepherosa Ziehau 		if (val & BCE_NVM_COMMAND_DONE) {
161343c2aeb0SSepherosa Ziehau 			val = REG_RD(sc, BCE_NVM_READ);
161443c2aeb0SSepherosa Ziehau 
161543c2aeb0SSepherosa Ziehau 			val = be32toh(val);
161643c2aeb0SSepherosa Ziehau 			memcpy(ret_val, &val, 4);
161743c2aeb0SSepherosa Ziehau 			break;
161843c2aeb0SSepherosa Ziehau 		}
161943c2aeb0SSepherosa Ziehau 	}
162043c2aeb0SSepherosa Ziehau 
162143c2aeb0SSepherosa Ziehau 	/* Check for errors. */
162243c2aeb0SSepherosa Ziehau 	if (i >= NVRAM_TIMEOUT_COUNT) {
162343c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
162443c2aeb0SSepherosa Ziehau 			  "Timeout error reading NVRAM at offset 0x%08X!\n",
162543c2aeb0SSepherosa Ziehau 			  offset);
162643c2aeb0SSepherosa Ziehau 		rc = EBUSY;
162743c2aeb0SSepherosa Ziehau 	}
162843c2aeb0SSepherosa Ziehau 	return rc;
162943c2aeb0SSepherosa Ziehau }
163043c2aeb0SSepherosa Ziehau 
163143c2aeb0SSepherosa Ziehau 
163243c2aeb0SSepherosa Ziehau /****************************************************************************/
163343c2aeb0SSepherosa Ziehau /* Initialize NVRAM access.                                                 */
163443c2aeb0SSepherosa Ziehau /*                                                                          */
163543c2aeb0SSepherosa Ziehau /* Identify the NVRAM device in use and prepare the NVRAM interface to      */
163643c2aeb0SSepherosa Ziehau /* access that device.                                                      */
163743c2aeb0SSepherosa Ziehau /*                                                                          */
163843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
163943c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
164043c2aeb0SSepherosa Ziehau /****************************************************************************/
164143c2aeb0SSepherosa Ziehau static int
164243c2aeb0SSepherosa Ziehau bce_init_nvram(struct bce_softc *sc)
164343c2aeb0SSepherosa Ziehau {
164443c2aeb0SSepherosa Ziehau 	uint32_t val;
164543c2aeb0SSepherosa Ziehau 	int j, entry_count, rc = 0;
164643c2aeb0SSepherosa Ziehau 	const struct flash_spec *flash;
164743c2aeb0SSepherosa Ziehau 
164843c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
164943c2aeb0SSepherosa Ziehau 
1650d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
1651d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
1652d0092544SSepherosa Ziehau 		sc->bce_flash_info = &flash_5709;
1653d0092544SSepherosa Ziehau 		goto bce_init_nvram_get_flash_size;
1654d0092544SSepherosa Ziehau 	}
1655d0092544SSepherosa Ziehau 
165643c2aeb0SSepherosa Ziehau 	/* Determine the selected interface. */
165743c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_NVM_CFG1);
165843c2aeb0SSepherosa Ziehau 
165943c2aeb0SSepherosa Ziehau 	entry_count = sizeof(flash_table) / sizeof(struct flash_spec);
166043c2aeb0SSepherosa Ziehau 
166143c2aeb0SSepherosa Ziehau 	/*
166243c2aeb0SSepherosa Ziehau 	 * Flash reconfiguration is required to support additional
166343c2aeb0SSepherosa Ziehau 	 * NVRAM devices not directly supported in hardware.
166443c2aeb0SSepherosa Ziehau 	 * Check if the flash interface was reconfigured
166543c2aeb0SSepherosa Ziehau 	 * by the bootcode.
166643c2aeb0SSepherosa Ziehau 	 */
166743c2aeb0SSepherosa Ziehau 
166843c2aeb0SSepherosa Ziehau 	if (val & 0x40000000) {
166943c2aeb0SSepherosa Ziehau 		/* Flash interface reconfigured by bootcode. */
167043c2aeb0SSepherosa Ziehau 
167143c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO_LOAD,
167243c2aeb0SSepherosa Ziehau 			"%s(): Flash WAS reconfigured.\n", __func__);
167343c2aeb0SSepherosa Ziehau 
167443c2aeb0SSepherosa Ziehau 		for (j = 0, flash = flash_table; j < entry_count;
167543c2aeb0SSepherosa Ziehau 		     j++, flash++) {
167643c2aeb0SSepherosa Ziehau 			if ((val & FLASH_BACKUP_STRAP_MASK) ==
167743c2aeb0SSepherosa Ziehau 			    (flash->config1 & FLASH_BACKUP_STRAP_MASK)) {
167843c2aeb0SSepherosa Ziehau 				sc->bce_flash_info = flash;
167943c2aeb0SSepherosa Ziehau 				break;
168043c2aeb0SSepherosa Ziehau 			}
168143c2aeb0SSepherosa Ziehau 		}
168243c2aeb0SSepherosa Ziehau 	} else {
168343c2aeb0SSepherosa Ziehau 		/* Flash interface not yet reconfigured. */
168443c2aeb0SSepherosa Ziehau 		uint32_t mask;
168543c2aeb0SSepherosa Ziehau 
168643c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO_LOAD,
168743c2aeb0SSepherosa Ziehau 			"%s(): Flash was NOT reconfigured.\n", __func__);
168843c2aeb0SSepherosa Ziehau 
168943c2aeb0SSepherosa Ziehau 		if (val & (1 << 23))
169043c2aeb0SSepherosa Ziehau 			mask = FLASH_BACKUP_STRAP_MASK;
169143c2aeb0SSepherosa Ziehau 		else
169243c2aeb0SSepherosa Ziehau 			mask = FLASH_STRAP_MASK;
169343c2aeb0SSepherosa Ziehau 
169443c2aeb0SSepherosa Ziehau 		/* Look for the matching NVRAM device configuration data. */
169543c2aeb0SSepherosa Ziehau 		for (j = 0, flash = flash_table; j < entry_count;
169643c2aeb0SSepherosa Ziehau 		     j++, flash++) {
169743c2aeb0SSepherosa Ziehau 			/* Check if the device matches any of the known devices. */
169843c2aeb0SSepherosa Ziehau 			if ((val & mask) == (flash->strapping & mask)) {
169943c2aeb0SSepherosa Ziehau 				/* Found a device match. */
170043c2aeb0SSepherosa Ziehau 				sc->bce_flash_info = flash;
170143c2aeb0SSepherosa Ziehau 
170243c2aeb0SSepherosa Ziehau 				/* Request access to the flash interface. */
170343c2aeb0SSepherosa Ziehau 				rc = bce_acquire_nvram_lock(sc);
170443c2aeb0SSepherosa Ziehau 				if (rc != 0)
170543c2aeb0SSepherosa Ziehau 					return rc;
170643c2aeb0SSepherosa Ziehau 
170743c2aeb0SSepherosa Ziehau 				/* Reconfigure the flash interface. */
170843c2aeb0SSepherosa Ziehau 				bce_enable_nvram_access(sc);
170943c2aeb0SSepherosa Ziehau 				REG_WR(sc, BCE_NVM_CFG1, flash->config1);
171043c2aeb0SSepherosa Ziehau 				REG_WR(sc, BCE_NVM_CFG2, flash->config2);
171143c2aeb0SSepherosa Ziehau 				REG_WR(sc, BCE_NVM_CFG3, flash->config3);
171243c2aeb0SSepherosa Ziehau 				REG_WR(sc, BCE_NVM_WRITE1, flash->write1);
171343c2aeb0SSepherosa Ziehau 				bce_disable_nvram_access(sc);
171443c2aeb0SSepherosa Ziehau 				bce_release_nvram_lock(sc);
171543c2aeb0SSepherosa Ziehau 				break;
171643c2aeb0SSepherosa Ziehau 			}
171743c2aeb0SSepherosa Ziehau 		}
171843c2aeb0SSepherosa Ziehau 	}
171943c2aeb0SSepherosa Ziehau 
172043c2aeb0SSepherosa Ziehau 	/* Check if a matching device was found. */
172143c2aeb0SSepherosa Ziehau 	if (j == entry_count) {
172243c2aeb0SSepherosa Ziehau 		sc->bce_flash_info = NULL;
172343c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "Unknown Flash NVRAM found!\n");
172443c2aeb0SSepherosa Ziehau 		rc = ENODEV;
172543c2aeb0SSepherosa Ziehau 	}
172643c2aeb0SSepherosa Ziehau 
1727d0092544SSepherosa Ziehau bce_init_nvram_get_flash_size:
172843c2aeb0SSepherosa Ziehau 	/* Write the flash config data to the shared memory interface. */
1729bc30d40dSSepherosa Ziehau 	val = bce_shmem_rd(sc, BCE_SHARED_HW_CFG_CONFIG2) &
173043c2aeb0SSepherosa Ziehau 	    BCE_SHARED_HW_CFG2_NVM_SIZE_MASK;
173143c2aeb0SSepherosa Ziehau 	if (val)
173243c2aeb0SSepherosa Ziehau 		sc->bce_flash_size = val;
173343c2aeb0SSepherosa Ziehau 	else
173443c2aeb0SSepherosa Ziehau 		sc->bce_flash_size = sc->bce_flash_info->total_size;
173543c2aeb0SSepherosa Ziehau 
173643c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_LOAD, "%s() flash->total_size = 0x%08X\n",
173743c2aeb0SSepherosa Ziehau 		__func__, sc->bce_flash_info->total_size);
173843c2aeb0SSepherosa Ziehau 
173943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __func__);
174043c2aeb0SSepherosa Ziehau 
174143c2aeb0SSepherosa Ziehau 	return rc;
174243c2aeb0SSepherosa Ziehau }
174343c2aeb0SSepherosa Ziehau 
174443c2aeb0SSepherosa Ziehau 
174543c2aeb0SSepherosa Ziehau /****************************************************************************/
174643c2aeb0SSepherosa Ziehau /* Read an arbitrary range of data from NVRAM.                              */
174743c2aeb0SSepherosa Ziehau /*                                                                          */
174843c2aeb0SSepherosa Ziehau /* Prepares the NVRAM interface for access and reads the requested data     */
174943c2aeb0SSepherosa Ziehau /* into the supplied buffer.                                                */
175043c2aeb0SSepherosa Ziehau /*                                                                          */
175143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
175243c2aeb0SSepherosa Ziehau /*   0 on success and the data read, positive value on failure.             */
175343c2aeb0SSepherosa Ziehau /****************************************************************************/
175443c2aeb0SSepherosa Ziehau static int
175543c2aeb0SSepherosa Ziehau bce_nvram_read(struct bce_softc *sc, uint32_t offset, uint8_t *ret_buf,
175643c2aeb0SSepherosa Ziehau 	       int buf_size)
175743c2aeb0SSepherosa Ziehau {
175843c2aeb0SSepherosa Ziehau 	uint32_t cmd_flags, offset32, len32, extra;
175943c2aeb0SSepherosa Ziehau 	int rc = 0;
176043c2aeb0SSepherosa Ziehau 
176143c2aeb0SSepherosa Ziehau 	if (buf_size == 0)
176243c2aeb0SSepherosa Ziehau 		return 0;
176343c2aeb0SSepherosa Ziehau 
176443c2aeb0SSepherosa Ziehau 	/* Request access to the flash interface. */
176543c2aeb0SSepherosa Ziehau 	rc = bce_acquire_nvram_lock(sc);
176643c2aeb0SSepherosa Ziehau 	if (rc != 0)
176743c2aeb0SSepherosa Ziehau 		return rc;
176843c2aeb0SSepherosa Ziehau 
176943c2aeb0SSepherosa Ziehau 	/* Enable access to flash interface */
177043c2aeb0SSepherosa Ziehau 	bce_enable_nvram_access(sc);
177143c2aeb0SSepherosa Ziehau 
177243c2aeb0SSepherosa Ziehau 	len32 = buf_size;
177343c2aeb0SSepherosa Ziehau 	offset32 = offset;
177443c2aeb0SSepherosa Ziehau 	extra = 0;
177543c2aeb0SSepherosa Ziehau 
177643c2aeb0SSepherosa Ziehau 	cmd_flags = 0;
177743c2aeb0SSepherosa Ziehau 
177843c2aeb0SSepherosa Ziehau 	/* XXX should we release nvram lock if read_dword() fails? */
177943c2aeb0SSepherosa Ziehau 	if (offset32 & 3) {
178043c2aeb0SSepherosa Ziehau 		uint8_t buf[4];
178143c2aeb0SSepherosa Ziehau 		uint32_t pre_len;
178243c2aeb0SSepherosa Ziehau 
178343c2aeb0SSepherosa Ziehau 		offset32 &= ~3;
178443c2aeb0SSepherosa Ziehau 		pre_len = 4 - (offset & 3);
178543c2aeb0SSepherosa Ziehau 
178643c2aeb0SSepherosa Ziehau 		if (pre_len >= len32) {
178743c2aeb0SSepherosa Ziehau 			pre_len = len32;
178843c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_FIRST | BCE_NVM_COMMAND_LAST;
178943c2aeb0SSepherosa Ziehau 		} else {
179043c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_FIRST;
179143c2aeb0SSepherosa Ziehau 		}
179243c2aeb0SSepherosa Ziehau 
179343c2aeb0SSepherosa Ziehau 		rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags);
179443c2aeb0SSepherosa Ziehau 		if (rc)
179543c2aeb0SSepherosa Ziehau 			return rc;
179643c2aeb0SSepherosa Ziehau 
179743c2aeb0SSepherosa Ziehau 		memcpy(ret_buf, buf + (offset & 3), pre_len);
179843c2aeb0SSepherosa Ziehau 
179943c2aeb0SSepherosa Ziehau 		offset32 += 4;
180043c2aeb0SSepherosa Ziehau 		ret_buf += pre_len;
180143c2aeb0SSepherosa Ziehau 		len32 -= pre_len;
180243c2aeb0SSepherosa Ziehau 	}
180343c2aeb0SSepherosa Ziehau 
180443c2aeb0SSepherosa Ziehau 	if (len32 & 3) {
180543c2aeb0SSepherosa Ziehau 		extra = 4 - (len32 & 3);
180643c2aeb0SSepherosa Ziehau 		len32 = (len32 + 4) & ~3;
180743c2aeb0SSepherosa Ziehau 	}
180843c2aeb0SSepherosa Ziehau 
180943c2aeb0SSepherosa Ziehau 	if (len32 == 4) {
181043c2aeb0SSepherosa Ziehau 		uint8_t buf[4];
181143c2aeb0SSepherosa Ziehau 
181243c2aeb0SSepherosa Ziehau 		if (cmd_flags)
181343c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_LAST;
181443c2aeb0SSepherosa Ziehau 		else
181543c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_FIRST |
181643c2aeb0SSepherosa Ziehau 				    BCE_NVM_COMMAND_LAST;
181743c2aeb0SSepherosa Ziehau 
181843c2aeb0SSepherosa Ziehau 		rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags);
181943c2aeb0SSepherosa Ziehau 
182043c2aeb0SSepherosa Ziehau 		memcpy(ret_buf, buf, 4 - extra);
182143c2aeb0SSepherosa Ziehau 	} else if (len32 > 0) {
182243c2aeb0SSepherosa Ziehau 		uint8_t buf[4];
182343c2aeb0SSepherosa Ziehau 
182443c2aeb0SSepherosa Ziehau 		/* Read the first word. */
182543c2aeb0SSepherosa Ziehau 		if (cmd_flags)
182643c2aeb0SSepherosa Ziehau 			cmd_flags = 0;
182743c2aeb0SSepherosa Ziehau 		else
182843c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_FIRST;
182943c2aeb0SSepherosa Ziehau 
183043c2aeb0SSepherosa Ziehau 		rc = bce_nvram_read_dword(sc, offset32, ret_buf, cmd_flags);
183143c2aeb0SSepherosa Ziehau 
183243c2aeb0SSepherosa Ziehau 		/* Advance to the next dword. */
183343c2aeb0SSepherosa Ziehau 		offset32 += 4;
183443c2aeb0SSepherosa Ziehau 		ret_buf += 4;
183543c2aeb0SSepherosa Ziehau 		len32 -= 4;
183643c2aeb0SSepherosa Ziehau 
183743c2aeb0SSepherosa Ziehau 		while (len32 > 4 && rc == 0) {
183843c2aeb0SSepherosa Ziehau 			rc = bce_nvram_read_dword(sc, offset32, ret_buf, 0);
183943c2aeb0SSepherosa Ziehau 
184043c2aeb0SSepherosa Ziehau 			/* Advance to the next dword. */
184143c2aeb0SSepherosa Ziehau 			offset32 += 4;
184243c2aeb0SSepherosa Ziehau 			ret_buf += 4;
184343c2aeb0SSepherosa Ziehau 			len32 -= 4;
184443c2aeb0SSepherosa Ziehau 		}
184543c2aeb0SSepherosa Ziehau 
184643c2aeb0SSepherosa Ziehau 		if (rc)
1847d0092544SSepherosa Ziehau 			goto bce_nvram_read_locked_exit;
184843c2aeb0SSepherosa Ziehau 
184943c2aeb0SSepherosa Ziehau 		cmd_flags = BCE_NVM_COMMAND_LAST;
185043c2aeb0SSepherosa Ziehau 		rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags);
185143c2aeb0SSepherosa Ziehau 
185243c2aeb0SSepherosa Ziehau 		memcpy(ret_buf, buf, 4 - extra);
185343c2aeb0SSepherosa Ziehau 	}
185443c2aeb0SSepherosa Ziehau 
1855d0092544SSepherosa Ziehau bce_nvram_read_locked_exit:
185643c2aeb0SSepherosa Ziehau 	/* Disable access to flash interface and release the lock. */
185743c2aeb0SSepherosa Ziehau 	bce_disable_nvram_access(sc);
185843c2aeb0SSepherosa Ziehau 	bce_release_nvram_lock(sc);
185943c2aeb0SSepherosa Ziehau 
186043c2aeb0SSepherosa Ziehau 	return rc;
186143c2aeb0SSepherosa Ziehau }
186243c2aeb0SSepherosa Ziehau 
186343c2aeb0SSepherosa Ziehau 
186443c2aeb0SSepherosa Ziehau /****************************************************************************/
186543c2aeb0SSepherosa Ziehau /* Verifies that NVRAM is accessible and contains valid data.               */
186643c2aeb0SSepherosa Ziehau /*                                                                          */
186743c2aeb0SSepherosa Ziehau /* Reads the configuration data from NVRAM and verifies that the CRC is     */
186843c2aeb0SSepherosa Ziehau /* correct.                                                                 */
186943c2aeb0SSepherosa Ziehau /*                                                                          */
187043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
187143c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
187243c2aeb0SSepherosa Ziehau /****************************************************************************/
187343c2aeb0SSepherosa Ziehau static int
187443c2aeb0SSepherosa Ziehau bce_nvram_test(struct bce_softc *sc)
187543c2aeb0SSepherosa Ziehau {
187643c2aeb0SSepherosa Ziehau 	uint32_t buf[BCE_NVRAM_SIZE / 4];
187743c2aeb0SSepherosa Ziehau 	uint32_t magic, csum;
187843c2aeb0SSepherosa Ziehau 	uint8_t *data = (uint8_t *)buf;
187943c2aeb0SSepherosa Ziehau 	int rc = 0;
188043c2aeb0SSepherosa Ziehau 
188143c2aeb0SSepherosa Ziehau 	/*
188243c2aeb0SSepherosa Ziehau 	 * Check that the device NVRAM is valid by reading
188343c2aeb0SSepherosa Ziehau 	 * the magic value at offset 0.
188443c2aeb0SSepherosa Ziehau 	 */
188543c2aeb0SSepherosa Ziehau 	rc = bce_nvram_read(sc, 0, data, 4);
188643c2aeb0SSepherosa Ziehau 	if (rc != 0)
188743c2aeb0SSepherosa Ziehau 		return rc;
188843c2aeb0SSepherosa Ziehau 
188943c2aeb0SSepherosa Ziehau 	magic = be32toh(buf[0]);
189043c2aeb0SSepherosa Ziehau 	if (magic != BCE_NVRAM_MAGIC) {
189143c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
189243c2aeb0SSepherosa Ziehau 			  "Invalid NVRAM magic value! Expected: 0x%08X, "
189343c2aeb0SSepherosa Ziehau 			  "Found: 0x%08X\n", BCE_NVRAM_MAGIC, magic);
189443c2aeb0SSepherosa Ziehau 		return ENODEV;
189543c2aeb0SSepherosa Ziehau 	}
189643c2aeb0SSepherosa Ziehau 
189743c2aeb0SSepherosa Ziehau 	/*
189843c2aeb0SSepherosa Ziehau 	 * Verify that the device NVRAM includes valid
189943c2aeb0SSepherosa Ziehau 	 * configuration data.
190043c2aeb0SSepherosa Ziehau 	 */
190143c2aeb0SSepherosa Ziehau 	rc = bce_nvram_read(sc, 0x100, data, BCE_NVRAM_SIZE);
190243c2aeb0SSepherosa Ziehau 	if (rc != 0)
190343c2aeb0SSepherosa Ziehau 		return rc;
190443c2aeb0SSepherosa Ziehau 
190543c2aeb0SSepherosa Ziehau 	csum = ether_crc32_le(data, 0x100);
190643c2aeb0SSepherosa Ziehau 	if (csum != BCE_CRC32_RESIDUAL) {
190743c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
190843c2aeb0SSepherosa Ziehau 			  "Invalid Manufacturing Information NVRAM CRC! "
190943c2aeb0SSepherosa Ziehau 			  "Expected: 0x%08X, Found: 0x%08X\n",
191043c2aeb0SSepherosa Ziehau 			  BCE_CRC32_RESIDUAL, csum);
191143c2aeb0SSepherosa Ziehau 		return ENODEV;
191243c2aeb0SSepherosa Ziehau 	}
191343c2aeb0SSepherosa Ziehau 
191443c2aeb0SSepherosa Ziehau 	csum = ether_crc32_le(data + 0x100, 0x100);
191543c2aeb0SSepherosa Ziehau 	if (csum != BCE_CRC32_RESIDUAL) {
191643c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
191743c2aeb0SSepherosa Ziehau 			  "Invalid Feature Configuration Information "
191843c2aeb0SSepherosa Ziehau 			  "NVRAM CRC! Expected: 0x%08X, Found: 08%08X\n",
191943c2aeb0SSepherosa Ziehau 			  BCE_CRC32_RESIDUAL, csum);
192043c2aeb0SSepherosa Ziehau 		rc = ENODEV;
192143c2aeb0SSepherosa Ziehau 	}
192243c2aeb0SSepherosa Ziehau 	return rc;
192343c2aeb0SSepherosa Ziehau }
192443c2aeb0SSepherosa Ziehau 
192543c2aeb0SSepherosa Ziehau 
192643c2aeb0SSepherosa Ziehau /****************************************************************************/
1927d0092544SSepherosa Ziehau /* Identifies the current media type of the controller and sets the PHY     */
1928d0092544SSepherosa Ziehau /* address.                                                                 */
1929d0092544SSepherosa Ziehau /*                                                                          */
1930d0092544SSepherosa Ziehau /* Returns:                                                                 */
1931d0092544SSepherosa Ziehau /*   Nothing.                                                               */
1932d0092544SSepherosa Ziehau /****************************************************************************/
1933d0092544SSepherosa Ziehau static void
1934d0092544SSepherosa Ziehau bce_get_media(struct bce_softc *sc)
1935d0092544SSepherosa Ziehau {
1936d0092544SSepherosa Ziehau 	uint32_t val;
1937d0092544SSepherosa Ziehau 
1938d0092544SSepherosa Ziehau 	sc->bce_phy_addr = 1;
1939d0092544SSepherosa Ziehau 
1940d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
1941d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
1942d0092544SSepherosa Ziehau  		uint32_t val = REG_RD(sc, BCE_MISC_DUAL_MEDIA_CTRL);
1943d0092544SSepherosa Ziehau 		uint32_t bond_id = val & BCE_MISC_DUAL_MEDIA_CTRL_BOND_ID;
1944d0092544SSepherosa Ziehau 		uint32_t strap;
1945d0092544SSepherosa Ziehau 
1946d0092544SSepherosa Ziehau 		/*
1947d0092544SSepherosa Ziehau 		 * The BCM5709S is software configurable
1948d0092544SSepherosa Ziehau 		 * for Copper or SerDes operation.
1949d0092544SSepherosa Ziehau 		 */
1950d0092544SSepherosa Ziehau 		if (bond_id == BCE_MISC_DUAL_MEDIA_CTRL_BOND_ID_C) {
1951d0092544SSepherosa Ziehau 			return;
1952d0092544SSepherosa Ziehau 		} else if (bond_id == BCE_MISC_DUAL_MEDIA_CTRL_BOND_ID_S) {
1953d0092544SSepherosa Ziehau 			sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG;
1954d0092544SSepherosa Ziehau 			return;
1955d0092544SSepherosa Ziehau 		}
1956d0092544SSepherosa Ziehau 
1957d0092544SSepherosa Ziehau 		if (val & BCE_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE) {
1958d0092544SSepherosa Ziehau 			strap = (val & BCE_MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21;
1959d0092544SSepherosa Ziehau 		} else {
1960d0092544SSepherosa Ziehau 			strap =
1961d0092544SSepherosa Ziehau 			(val & BCE_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8;
1962d0092544SSepherosa Ziehau 		}
1963d0092544SSepherosa Ziehau 
1964d0092544SSepherosa Ziehau 		if (pci_get_function(sc->bce_dev) == 0) {
1965d0092544SSepherosa Ziehau 			switch (strap) {
1966d0092544SSepherosa Ziehau 			case 0x4:
1967d0092544SSepherosa Ziehau 			case 0x5:
1968d0092544SSepherosa Ziehau 			case 0x6:
1969d0092544SSepherosa Ziehau 				sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG;
1970d0092544SSepherosa Ziehau 				break;
1971d0092544SSepherosa Ziehau 			}
1972d0092544SSepherosa Ziehau 		} else {
1973d0092544SSepherosa Ziehau 			switch (strap) {
1974d0092544SSepherosa Ziehau 			case 0x1:
1975d0092544SSepherosa Ziehau 			case 0x2:
1976d0092544SSepherosa Ziehau 			case 0x4:
1977d0092544SSepherosa Ziehau 				sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG;
1978d0092544SSepherosa Ziehau 				break;
1979d0092544SSepherosa Ziehau 			}
1980d0092544SSepherosa Ziehau 		}
1981d0092544SSepherosa Ziehau 	} else if (BCE_CHIP_BOND_ID(sc) & BCE_CHIP_BOND_ID_SERDES_BIT) {
1982d0092544SSepherosa Ziehau 		sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG;
1983d0092544SSepherosa Ziehau 	}
1984d0092544SSepherosa Ziehau 
1985d0092544SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_SERDES_FLAG) {
1986d0092544SSepherosa Ziehau 		sc->bce_flags |= BCE_NO_WOL_FLAG;
1987d0092544SSepherosa Ziehau 		if (BCE_CHIP_NUM(sc) != BCE_CHIP_NUM_5706) {
1988d0092544SSepherosa Ziehau 			sc->bce_phy_addr = 2;
1989bc30d40dSSepherosa Ziehau 			val = bce_shmem_rd(sc, BCE_SHARED_HW_CFG_CONFIG);
1990d0092544SSepherosa Ziehau 			if (val & BCE_SHARED_HW_CFG_PHY_2_5G)
1991d0092544SSepherosa Ziehau 				sc->bce_phy_flags |= BCE_PHY_2_5G_CAPABLE_FLAG;
1992d0092544SSepherosa Ziehau 		}
1993d0092544SSepherosa Ziehau 	} else if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) ||
1994d0092544SSepherosa Ziehau 	    (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708)) {
1995d0092544SSepherosa Ziehau 		sc->bce_phy_flags |= BCE_PHY_CRC_FIX_FLAG;
1996d0092544SSepherosa Ziehau 	}
1997d0092544SSepherosa Ziehau }
1998d0092544SSepherosa Ziehau 
1999d0092544SSepherosa Ziehau 
2000d0092544SSepherosa Ziehau /****************************************************************************/
200143c2aeb0SSepherosa Ziehau /* Free any DMA memory owned by the driver.                                 */
200243c2aeb0SSepherosa Ziehau /*                                                                          */
200343c2aeb0SSepherosa Ziehau /* Scans through each data structre that requires DMA memory and frees      */
200443c2aeb0SSepherosa Ziehau /* the memory if allocated.                                                 */
200543c2aeb0SSepherosa Ziehau /*                                                                          */
200643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
200743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
200843c2aeb0SSepherosa Ziehau /****************************************************************************/
200943c2aeb0SSepherosa Ziehau static void
201043c2aeb0SSepherosa Ziehau bce_dma_free(struct bce_softc *sc)
201143c2aeb0SSepherosa Ziehau {
201243c2aeb0SSepherosa Ziehau 	int i;
201343c2aeb0SSepherosa Ziehau 
201443c2aeb0SSepherosa Ziehau 	/* Destroy the status block. */
201543c2aeb0SSepherosa Ziehau 	if (sc->status_tag != NULL) {
201643c2aeb0SSepherosa Ziehau 		if (sc->status_block != NULL) {
201743c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->status_tag, sc->status_map);
201843c2aeb0SSepherosa Ziehau 			bus_dmamem_free(sc->status_tag, sc->status_block,
201943c2aeb0SSepherosa Ziehau 					sc->status_map);
202043c2aeb0SSepherosa Ziehau 		}
202143c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->status_tag);
202243c2aeb0SSepherosa Ziehau 	}
202343c2aeb0SSepherosa Ziehau 
202443c2aeb0SSepherosa Ziehau 
202543c2aeb0SSepherosa Ziehau 	/* Destroy the statistics block. */
202643c2aeb0SSepherosa Ziehau 	if (sc->stats_tag != NULL) {
202743c2aeb0SSepherosa Ziehau 		if (sc->stats_block != NULL) {
202843c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->stats_tag, sc->stats_map);
202943c2aeb0SSepherosa Ziehau 			bus_dmamem_free(sc->stats_tag, sc->stats_block,
203043c2aeb0SSepherosa Ziehau 					sc->stats_map);
203143c2aeb0SSepherosa Ziehau 		}
203243c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->stats_tag);
203343c2aeb0SSepherosa Ziehau 	}
203443c2aeb0SSepherosa Ziehau 
2035d0092544SSepherosa Ziehau 	/* Destroy the CTX DMA stuffs. */
2036d0092544SSepherosa Ziehau 	if (sc->ctx_tag != NULL) {
2037d0092544SSepherosa Ziehau 		for (i = 0; i < sc->ctx_pages; i++) {
2038d0092544SSepherosa Ziehau 			if (sc->ctx_block[i] != NULL) {
2039d0092544SSepherosa Ziehau 				bus_dmamap_unload(sc->ctx_tag, sc->ctx_map[i]);
2040d0092544SSepherosa Ziehau 				bus_dmamem_free(sc->ctx_tag, sc->ctx_block[i],
2041d0092544SSepherosa Ziehau 						sc->ctx_map[i]);
2042d0092544SSepherosa Ziehau 			}
2043d0092544SSepherosa Ziehau 		}
2044d0092544SSepherosa Ziehau 		bus_dma_tag_destroy(sc->ctx_tag);
2045d0092544SSepherosa Ziehau 	}
2046d0092544SSepherosa Ziehau 
204743c2aeb0SSepherosa Ziehau 	/* Destroy the TX buffer descriptor DMA stuffs. */
204843c2aeb0SSepherosa Ziehau 	if (sc->tx_bd_chain_tag != NULL) {
204943c2aeb0SSepherosa Ziehau 		for (i = 0; i < TX_PAGES; i++) {
205043c2aeb0SSepherosa Ziehau 			if (sc->tx_bd_chain[i] != NULL) {
205143c2aeb0SSepherosa Ziehau 				bus_dmamap_unload(sc->tx_bd_chain_tag,
205243c2aeb0SSepherosa Ziehau 						  sc->tx_bd_chain_map[i]);
205343c2aeb0SSepherosa Ziehau 				bus_dmamem_free(sc->tx_bd_chain_tag,
205443c2aeb0SSepherosa Ziehau 						sc->tx_bd_chain[i],
205543c2aeb0SSepherosa Ziehau 						sc->tx_bd_chain_map[i]);
205643c2aeb0SSepherosa Ziehau 			}
205743c2aeb0SSepherosa Ziehau 		}
205843c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->tx_bd_chain_tag);
205943c2aeb0SSepherosa Ziehau 	}
206043c2aeb0SSepherosa Ziehau 
206143c2aeb0SSepherosa Ziehau 	/* Destroy the RX buffer descriptor DMA stuffs. */
206243c2aeb0SSepherosa Ziehau 	if (sc->rx_bd_chain_tag != NULL) {
206343c2aeb0SSepherosa Ziehau 		for (i = 0; i < RX_PAGES; i++) {
206443c2aeb0SSepherosa Ziehau 			if (sc->rx_bd_chain[i] != NULL) {
206543c2aeb0SSepherosa Ziehau 				bus_dmamap_unload(sc->rx_bd_chain_tag,
206643c2aeb0SSepherosa Ziehau 						  sc->rx_bd_chain_map[i]);
206743c2aeb0SSepherosa Ziehau 				bus_dmamem_free(sc->rx_bd_chain_tag,
206843c2aeb0SSepherosa Ziehau 						sc->rx_bd_chain[i],
206943c2aeb0SSepherosa Ziehau 						sc->rx_bd_chain_map[i]);
207043c2aeb0SSepherosa Ziehau 			}
207143c2aeb0SSepherosa Ziehau 		}
207243c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->rx_bd_chain_tag);
207343c2aeb0SSepherosa Ziehau 	}
207443c2aeb0SSepherosa Ziehau 
207543c2aeb0SSepherosa Ziehau 	/* Destroy the TX mbuf DMA stuffs. */
207643c2aeb0SSepherosa Ziehau 	if (sc->tx_mbuf_tag != NULL) {
207743c2aeb0SSepherosa Ziehau 		for (i = 0; i < TOTAL_TX_BD; i++) {
207843c2aeb0SSepherosa Ziehau 			/* Must have been unloaded in bce_stop() */
207943c2aeb0SSepherosa Ziehau 			KKASSERT(sc->tx_mbuf_ptr[i] == NULL);
208043c2aeb0SSepherosa Ziehau 			bus_dmamap_destroy(sc->tx_mbuf_tag,
208143c2aeb0SSepherosa Ziehau 					   sc->tx_mbuf_map[i]);
208243c2aeb0SSepherosa Ziehau 		}
208343c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->tx_mbuf_tag);
208443c2aeb0SSepherosa Ziehau 	}
208543c2aeb0SSepherosa Ziehau 
208643c2aeb0SSepherosa Ziehau 	/* Destroy the RX mbuf DMA stuffs. */
208743c2aeb0SSepherosa Ziehau 	if (sc->rx_mbuf_tag != NULL) {
208843c2aeb0SSepherosa Ziehau 		for (i = 0; i < TOTAL_RX_BD; i++) {
208943c2aeb0SSepherosa Ziehau 			/* Must have been unloaded in bce_stop() */
209043c2aeb0SSepherosa Ziehau 			KKASSERT(sc->rx_mbuf_ptr[i] == NULL);
209143c2aeb0SSepherosa Ziehau 			bus_dmamap_destroy(sc->rx_mbuf_tag,
209243c2aeb0SSepherosa Ziehau 					   sc->rx_mbuf_map[i]);
209343c2aeb0SSepherosa Ziehau 		}
2094c36fd9eeSSepherosa Ziehau 		bus_dmamap_destroy(sc->rx_mbuf_tag, sc->rx_mbuf_tmpmap);
209543c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->rx_mbuf_tag);
209643c2aeb0SSepherosa Ziehau 	}
209743c2aeb0SSepherosa Ziehau 
209843c2aeb0SSepherosa Ziehau 	/* Destroy the parent tag */
209943c2aeb0SSepherosa Ziehau 	if (sc->parent_tag != NULL)
210043c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->parent_tag);
210143c2aeb0SSepherosa Ziehau }
210243c2aeb0SSepherosa Ziehau 
210343c2aeb0SSepherosa Ziehau 
210443c2aeb0SSepherosa Ziehau /****************************************************************************/
210543c2aeb0SSepherosa Ziehau /* Get DMA memory from the OS.                                              */
210643c2aeb0SSepherosa Ziehau /*                                                                          */
210743c2aeb0SSepherosa Ziehau /* Validates that the OS has provided DMA buffers in response to a          */
210843c2aeb0SSepherosa Ziehau /* bus_dmamap_load() call and saves the physical address of those buffers.  */
210943c2aeb0SSepherosa Ziehau /* When the callback is used the OS will return 0 for the mapping function  */
211043c2aeb0SSepherosa Ziehau /* (bus_dmamap_load()) so we use the value of map_arg->maxsegs to pass any  */
211143c2aeb0SSepherosa Ziehau /* failures back to the caller.                                             */
211243c2aeb0SSepherosa Ziehau /*                                                                          */
211343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
211443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
211543c2aeb0SSepherosa Ziehau /****************************************************************************/
211643c2aeb0SSepherosa Ziehau static void
211743c2aeb0SSepherosa Ziehau bce_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
211843c2aeb0SSepherosa Ziehau {
211943c2aeb0SSepherosa Ziehau 	bus_addr_t *busaddr = arg;
212043c2aeb0SSepherosa Ziehau 
212143c2aeb0SSepherosa Ziehau 	/*
212243c2aeb0SSepherosa Ziehau 	 * Simulate a mapping failure.
212343c2aeb0SSepherosa Ziehau 	 * XXX not correct.
212443c2aeb0SSepherosa Ziehau 	 */
212543c2aeb0SSepherosa Ziehau 	DBRUNIF(DB_RANDOMTRUE(bce_debug_dma_map_addr_failure),
212643c2aeb0SSepherosa Ziehau 		kprintf("bce: %s(%d): Simulating DMA mapping error.\n",
212743c2aeb0SSepherosa Ziehau 			__FILE__, __LINE__);
212843c2aeb0SSepherosa Ziehau 		error = ENOMEM);
212943c2aeb0SSepherosa Ziehau 
213043c2aeb0SSepherosa Ziehau 	/* Check for an error and signal the caller that an error occurred. */
213143c2aeb0SSepherosa Ziehau 	if (error)
213243c2aeb0SSepherosa Ziehau 		return;
213343c2aeb0SSepherosa Ziehau 
213443c2aeb0SSepherosa Ziehau 	KASSERT(nseg == 1, ("only one segment is allowed\n"));
213543c2aeb0SSepherosa Ziehau 	*busaddr = segs->ds_addr;
213643c2aeb0SSepherosa Ziehau }
213743c2aeb0SSepherosa Ziehau 
213843c2aeb0SSepherosa Ziehau 
213943c2aeb0SSepherosa Ziehau /****************************************************************************/
214043c2aeb0SSepherosa Ziehau /* Allocate any DMA memory needed by the driver.                            */
214143c2aeb0SSepherosa Ziehau /*                                                                          */
214243c2aeb0SSepherosa Ziehau /* Allocates DMA memory needed for the various global structures needed by  */
214343c2aeb0SSepherosa Ziehau /* hardware.                                                                */
214443c2aeb0SSepherosa Ziehau /*                                                                          */
2145cffea833SSepherosa Ziehau /* Memory alignment requirements:                                           */
2146d0092544SSepherosa Ziehau /* -----------------+----------+----------+----------+----------+           */
2147d0092544SSepherosa Ziehau /*  Data Structure  |   5706   |   5708   |   5709   |   5716   |           */
2148d0092544SSepherosa Ziehau /* -----------------+----------+----------+----------+----------+           */
2149d0092544SSepherosa Ziehau /* Status Block     | 8 bytes  | 8 bytes  | 16 bytes | 16 bytes |           */
2150d0092544SSepherosa Ziehau /* Statistics Block | 8 bytes  | 8 bytes  | 16 bytes | 16 bytes |           */
2151d0092544SSepherosa Ziehau /* RX Buffers       | 16 bytes | 16 bytes | 16 bytes | 16 bytes |           */
2152d0092544SSepherosa Ziehau /* PG Buffers       |   none   |   none   |   none   |   none   |           */
2153d0092544SSepherosa Ziehau /* TX Buffers       |   none   |   none   |   none   |   none   |           */
2154d0092544SSepherosa Ziehau /* Chain Pages(1)   |   4KiB   |   4KiB   |   4KiB   |   4KiB   |           */
2155d0092544SSepherosa Ziehau /* Context Pages(1) |   N/A    |   N/A    |   4KiB   |   4KiB   |           */
2156d0092544SSepherosa Ziehau /* -----------------+----------+----------+----------+----------+           */
2157cffea833SSepherosa Ziehau /*                                                                          */
2158cffea833SSepherosa Ziehau /* (1) Must align with CPU page size (BCM_PAGE_SZIE).                       */
2159cffea833SSepherosa Ziehau /*                                                                          */
216043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
216143c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
216243c2aeb0SSepherosa Ziehau /****************************************************************************/
216343c2aeb0SSepherosa Ziehau static int
216443c2aeb0SSepherosa Ziehau bce_dma_alloc(struct bce_softc *sc)
216543c2aeb0SSepherosa Ziehau {
216643c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
216743c2aeb0SSepherosa Ziehau 	int i, j, rc = 0;
2168d0092544SSepherosa Ziehau 	bus_addr_t busaddr, max_busaddr;
2169d0092544SSepherosa Ziehau 	bus_size_t status_align, stats_align;
2170d0092544SSepherosa Ziehau 
2171d0092544SSepherosa Ziehau 	/*
2172d0092544SSepherosa Ziehau 	 * The embedded PCIe to PCI-X bridge (EPB)
2173d0092544SSepherosa Ziehau 	 * in the 5708 cannot address memory above
2174d0092544SSepherosa Ziehau 	 * 40 bits (E7_5708CB1_23043 & E6_5708SB1_23043).
2175d0092544SSepherosa Ziehau 	 */
2176d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708)
2177d0092544SSepherosa Ziehau 		max_busaddr = BCE_BUS_SPACE_MAXADDR;
2178d0092544SSepherosa Ziehau 	else
2179d0092544SSepherosa Ziehau 		max_busaddr = BUS_SPACE_MAXADDR;
2180d0092544SSepherosa Ziehau 
2181d0092544SSepherosa Ziehau 	/*
2182d0092544SSepherosa Ziehau 	 * BCM5709 and BCM5716 uses host memory as cache for context memory.
2183d0092544SSepherosa Ziehau 	 */
2184d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
2185d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
2186d0092544SSepherosa Ziehau 		sc->ctx_pages = BCE_CTX_BLK_SZ / BCM_PAGE_SIZE;
2187d0092544SSepherosa Ziehau 		if (sc->ctx_pages == 0)
2188d0092544SSepherosa Ziehau 			sc->ctx_pages = 1;
2189d0092544SSepherosa Ziehau 		if (sc->ctx_pages > BCE_CTX_PAGES) {
2190d0092544SSepherosa Ziehau 			device_printf(sc->bce_dev, "excessive ctx pages %d\n",
2191d0092544SSepherosa Ziehau 			    sc->ctx_pages);
2192d0092544SSepherosa Ziehau 			return ENOMEM;
2193d0092544SSepherosa Ziehau 		}
2194d0092544SSepherosa Ziehau 		status_align = 16;
2195d0092544SSepherosa Ziehau 		stats_align = 16;
2196d0092544SSepherosa Ziehau 	} else {
2197d0092544SSepherosa Ziehau 		status_align = 8;
2198d0092544SSepherosa Ziehau 		stats_align = 8;
2199d0092544SSepherosa Ziehau 	}
220043c2aeb0SSepherosa Ziehau 
220143c2aeb0SSepherosa Ziehau 	/*
220243c2aeb0SSepherosa Ziehau 	 * Allocate the parent bus DMA tag appropriate for PCI.
220343c2aeb0SSepherosa Ziehau 	 */
220443c2aeb0SSepherosa Ziehau 	rc = bus_dma_tag_create(NULL, 1, BCE_DMA_BOUNDARY,
2205d0092544SSepherosa Ziehau 				max_busaddr, BUS_SPACE_MAXADDR,
220643c2aeb0SSepherosa Ziehau 				NULL, NULL,
220745010e4dSSepherosa Ziehau 				BUS_SPACE_MAXSIZE_32BIT, 0,
220843c2aeb0SSepherosa Ziehau 				BUS_SPACE_MAXSIZE_32BIT,
220943c2aeb0SSepherosa Ziehau 				0, &sc->parent_tag);
221043c2aeb0SSepherosa Ziehau 	if (rc != 0) {
221143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate parent DMA tag!\n");
221243c2aeb0SSepherosa Ziehau 		return rc;
221343c2aeb0SSepherosa Ziehau 	}
221443c2aeb0SSepherosa Ziehau 
221543c2aeb0SSepherosa Ziehau 	/*
22164a458e9dSSepherosa Ziehau 	 * Allocate status block.
221743c2aeb0SSepherosa Ziehau 	 */
22184a458e9dSSepherosa Ziehau 	sc->status_block = bus_dmamem_coherent_any(sc->parent_tag,
2219d0092544SSepherosa Ziehau 				status_align, BCE_STATUS_BLK_SZ,
222043c2aeb0SSepherosa Ziehau 				BUS_DMA_WAITOK | BUS_DMA_ZERO,
22214a458e9dSSepherosa Ziehau 				&sc->status_tag, &sc->status_map,
22224a458e9dSSepherosa Ziehau 				&sc->status_block_paddr);
22234a458e9dSSepherosa Ziehau 	if (sc->status_block == NULL) {
22244a458e9dSSepherosa Ziehau 		if_printf(ifp, "Could not allocate status block!\n");
22254a458e9dSSepherosa Ziehau 		return ENOMEM;
222643c2aeb0SSepherosa Ziehau 	}
222743c2aeb0SSepherosa Ziehau 
222843c2aeb0SSepherosa Ziehau 	/*
22294a458e9dSSepherosa Ziehau 	 * Allocate statistics block.
223043c2aeb0SSepherosa Ziehau 	 */
22314a458e9dSSepherosa Ziehau 	sc->stats_block = bus_dmamem_coherent_any(sc->parent_tag,
2232d0092544SSepherosa Ziehau 				stats_align, BCE_STATS_BLK_SZ,
223343c2aeb0SSepherosa Ziehau 				BUS_DMA_WAITOK | BUS_DMA_ZERO,
22344a458e9dSSepherosa Ziehau 				&sc->stats_tag, &sc->stats_map,
22354a458e9dSSepherosa Ziehau 				&sc->stats_block_paddr);
22364a458e9dSSepherosa Ziehau 	if (sc->stats_block == NULL) {
22374a458e9dSSepherosa Ziehau 		if_printf(ifp, "Could not allocate statistics block!\n");
22384a458e9dSSepherosa Ziehau 		return ENOMEM;
223943c2aeb0SSepherosa Ziehau 	}
224043c2aeb0SSepherosa Ziehau 
224143c2aeb0SSepherosa Ziehau 	/*
2242d0092544SSepherosa Ziehau 	 * Allocate context block, if needed
2243d0092544SSepherosa Ziehau 	 */
2244d0092544SSepherosa Ziehau 	if (sc->ctx_pages != 0) {
2245d0092544SSepherosa Ziehau 		rc = bus_dma_tag_create(sc->parent_tag, BCM_PAGE_SIZE, 0,
2246d0092544SSepherosa Ziehau 					BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
2247d0092544SSepherosa Ziehau 					NULL, NULL,
2248d0092544SSepherosa Ziehau 					BCM_PAGE_SIZE, 1, BCM_PAGE_SIZE,
2249d0092544SSepherosa Ziehau 					0, &sc->ctx_tag);
2250d0092544SSepherosa Ziehau 		if (rc != 0) {
2251d0092544SSepherosa Ziehau 			if_printf(ifp, "Could not allocate "
2252d0092544SSepherosa Ziehau 				  "context block DMA tag!\n");
2253d0092544SSepherosa Ziehau 			return rc;
2254d0092544SSepherosa Ziehau 		}
2255d0092544SSepherosa Ziehau 
2256d0092544SSepherosa Ziehau 		for (i = 0; i < sc->ctx_pages; i++) {
2257d0092544SSepherosa Ziehau 			rc = bus_dmamem_alloc(sc->ctx_tag,
2258d0092544SSepherosa Ziehau 					      (void **)&sc->ctx_block[i],
2259d0092544SSepherosa Ziehau 					      BUS_DMA_WAITOK | BUS_DMA_ZERO |
2260d0092544SSepherosa Ziehau 					      BUS_DMA_COHERENT,
2261d0092544SSepherosa Ziehau 					      &sc->ctx_map[i]);
2262d0092544SSepherosa Ziehau 			if (rc != 0) {
2263d0092544SSepherosa Ziehau 				if_printf(ifp, "Could not allocate %dth context "
2264d0092544SSepherosa Ziehau 					  "DMA memory!\n", i);
2265d0092544SSepherosa Ziehau 				return rc;
2266d0092544SSepherosa Ziehau 			}
2267d0092544SSepherosa Ziehau 
2268d0092544SSepherosa Ziehau 			rc = bus_dmamap_load(sc->ctx_tag, sc->ctx_map[i],
2269d0092544SSepherosa Ziehau 					     sc->ctx_block[i], BCM_PAGE_SIZE,
2270d0092544SSepherosa Ziehau 					     bce_dma_map_addr, &busaddr,
2271d0092544SSepherosa Ziehau 					     BUS_DMA_WAITOK);
2272d0092544SSepherosa Ziehau 			if (rc != 0) {
2273d0092544SSepherosa Ziehau 				if (rc == EINPROGRESS) {
2274d0092544SSepherosa Ziehau 					panic("%s coherent memory loading "
2275d0092544SSepherosa Ziehau 					      "is still in progress!", ifp->if_xname);
2276d0092544SSepherosa Ziehau 				}
2277d0092544SSepherosa Ziehau 				if_printf(ifp, "Could not map %dth context "
2278d0092544SSepherosa Ziehau 					  "DMA memory!\n", i);
2279d0092544SSepherosa Ziehau 				bus_dmamem_free(sc->ctx_tag, sc->ctx_block[i],
2280d0092544SSepherosa Ziehau 						sc->ctx_map[i]);
2281d0092544SSepherosa Ziehau 				sc->ctx_block[i] = NULL;
2282d0092544SSepherosa Ziehau 				return rc;
2283d0092544SSepherosa Ziehau 			}
2284d0092544SSepherosa Ziehau 			sc->ctx_paddr[i] = busaddr;
2285d0092544SSepherosa Ziehau 		}
2286d0092544SSepherosa Ziehau 	}
2287d0092544SSepherosa Ziehau 
2288d0092544SSepherosa Ziehau 	/*
228943c2aeb0SSepherosa Ziehau 	 * Create a DMA tag for the TX buffer descriptor chain,
229043c2aeb0SSepherosa Ziehau 	 * allocate and clear the  memory, and fetch the
229143c2aeb0SSepherosa Ziehau 	 * physical address of the block.
229243c2aeb0SSepherosa Ziehau 	 */
22934a458e9dSSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag, BCM_PAGE_SIZE, 0,
22944a458e9dSSepherosa Ziehau 				BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
229543c2aeb0SSepherosa Ziehau 				NULL, NULL,
229643c2aeb0SSepherosa Ziehau 				BCE_TX_CHAIN_PAGE_SZ, 1, BCE_TX_CHAIN_PAGE_SZ,
229743c2aeb0SSepherosa Ziehau 				0, &sc->tx_bd_chain_tag);
229843c2aeb0SSepherosa Ziehau 	if (rc != 0) {
229943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate "
230043c2aeb0SSepherosa Ziehau 			  "TX descriptor chain DMA tag!\n");
230143c2aeb0SSepherosa Ziehau 		return rc;
230243c2aeb0SSepherosa Ziehau 	}
230343c2aeb0SSepherosa Ziehau 
230443c2aeb0SSepherosa Ziehau 	for (i = 0; i < TX_PAGES; i++) {
230543c2aeb0SSepherosa Ziehau 		rc = bus_dmamem_alloc(sc->tx_bd_chain_tag,
230643c2aeb0SSepherosa Ziehau 				      (void **)&sc->tx_bd_chain[i],
23074a458e9dSSepherosa Ziehau 				      BUS_DMA_WAITOK | BUS_DMA_ZERO |
23084a458e9dSSepherosa Ziehau 				      BUS_DMA_COHERENT,
23094a458e9dSSepherosa Ziehau 				      &sc->tx_bd_chain_map[i]);
231043c2aeb0SSepherosa Ziehau 		if (rc != 0) {
231143c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Could not allocate %dth TX descriptor "
231243c2aeb0SSepherosa Ziehau 				  "chain DMA memory!\n", i);
231343c2aeb0SSepherosa Ziehau 			return rc;
231443c2aeb0SSepherosa Ziehau 		}
231543c2aeb0SSepherosa Ziehau 
231643c2aeb0SSepherosa Ziehau 		rc = bus_dmamap_load(sc->tx_bd_chain_tag,
231743c2aeb0SSepherosa Ziehau 				     sc->tx_bd_chain_map[i],
231843c2aeb0SSepherosa Ziehau 				     sc->tx_bd_chain[i], BCE_TX_CHAIN_PAGE_SZ,
231943c2aeb0SSepherosa Ziehau 				     bce_dma_map_addr, &busaddr,
232043c2aeb0SSepherosa Ziehau 				     BUS_DMA_WAITOK);
232143c2aeb0SSepherosa Ziehau 		if (rc != 0) {
23224a458e9dSSepherosa Ziehau 			if (rc == EINPROGRESS) {
23234a458e9dSSepherosa Ziehau 				panic("%s coherent memory loading "
23244a458e9dSSepherosa Ziehau 				      "is still in progress!", ifp->if_xname);
23254a458e9dSSepherosa Ziehau 			}
232643c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Could not map %dth TX descriptor "
232743c2aeb0SSepherosa Ziehau 				  "chain DMA memory!\n", i);
232843c2aeb0SSepherosa Ziehau 			bus_dmamem_free(sc->tx_bd_chain_tag,
232943c2aeb0SSepherosa Ziehau 					sc->tx_bd_chain[i],
233043c2aeb0SSepherosa Ziehau 					sc->tx_bd_chain_map[i]);
233143c2aeb0SSepherosa Ziehau 			sc->tx_bd_chain[i] = NULL;
233243c2aeb0SSepherosa Ziehau 			return rc;
233343c2aeb0SSepherosa Ziehau 		}
233443c2aeb0SSepherosa Ziehau 
233543c2aeb0SSepherosa Ziehau 		sc->tx_bd_chain_paddr[i] = busaddr;
233643c2aeb0SSepherosa Ziehau 		/* DRC - Fix for 64 bit systems. */
233743c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "tx_bd_chain_paddr[%d] = 0x%08X\n",
233843c2aeb0SSepherosa Ziehau 			i, (uint32_t)sc->tx_bd_chain_paddr[i]);
233943c2aeb0SSepherosa Ziehau 	}
234043c2aeb0SSepherosa Ziehau 
234143c2aeb0SSepherosa Ziehau 	/* Create a DMA tag for TX mbufs. */
234245010e4dSSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag, 1, 0,
234345010e4dSSepherosa Ziehau 				BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
234443c2aeb0SSepherosa Ziehau 				NULL, NULL,
234545010e4dSSepherosa Ziehau 				/* BCE_MAX_JUMBO_ETHER_MTU_VLAN */MCLBYTES,
234643c2aeb0SSepherosa Ziehau 				BCE_MAX_SEGMENTS, MCLBYTES,
234745010e4dSSepherosa Ziehau 				BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK |
234845010e4dSSepherosa Ziehau 				BUS_DMA_ONEBPAGE,
234945010e4dSSepherosa Ziehau 				&sc->tx_mbuf_tag);
235043c2aeb0SSepherosa Ziehau 	if (rc != 0) {
235143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate TX mbuf DMA tag!\n");
235243c2aeb0SSepherosa Ziehau 		return rc;
235343c2aeb0SSepherosa Ziehau 	}
235443c2aeb0SSepherosa Ziehau 
235543c2aeb0SSepherosa Ziehau 	/* Create DMA maps for the TX mbufs clusters. */
235643c2aeb0SSepherosa Ziehau 	for (i = 0; i < TOTAL_TX_BD; i++) {
235745010e4dSSepherosa Ziehau 		rc = bus_dmamap_create(sc->tx_mbuf_tag,
235845010e4dSSepherosa Ziehau 				       BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE,
235943c2aeb0SSepherosa Ziehau 				       &sc->tx_mbuf_map[i]);
236043c2aeb0SSepherosa Ziehau 		if (rc != 0) {
236143c2aeb0SSepherosa Ziehau 			for (j = 0; j < i; ++j) {
236243c2aeb0SSepherosa Ziehau 				bus_dmamap_destroy(sc->tx_mbuf_tag,
236343c2aeb0SSepherosa Ziehau 						   sc->tx_mbuf_map[i]);
236443c2aeb0SSepherosa Ziehau 			}
236543c2aeb0SSepherosa Ziehau 			bus_dma_tag_destroy(sc->tx_mbuf_tag);
236643c2aeb0SSepherosa Ziehau 			sc->tx_mbuf_tag = NULL;
236743c2aeb0SSepherosa Ziehau 
236843c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Unable to create "
236943c2aeb0SSepherosa Ziehau 				  "%dth TX mbuf DMA map!\n", i);
237043c2aeb0SSepherosa Ziehau 			return rc;
237143c2aeb0SSepherosa Ziehau 		}
237243c2aeb0SSepherosa Ziehau 	}
237343c2aeb0SSepherosa Ziehau 
237443c2aeb0SSepherosa Ziehau 	/*
237543c2aeb0SSepherosa Ziehau 	 * Create a DMA tag for the RX buffer descriptor chain,
237643c2aeb0SSepherosa Ziehau 	 * allocate and clear the  memory, and fetch the physical
237743c2aeb0SSepherosa Ziehau 	 * address of the blocks.
237843c2aeb0SSepherosa Ziehau 	 */
23794a458e9dSSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag, BCM_PAGE_SIZE, 0,
23804a458e9dSSepherosa Ziehau 				BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
238143c2aeb0SSepherosa Ziehau 				NULL, NULL,
238243c2aeb0SSepherosa Ziehau 				BCE_RX_CHAIN_PAGE_SZ, 1, BCE_RX_CHAIN_PAGE_SZ,
238343c2aeb0SSepherosa Ziehau 				0, &sc->rx_bd_chain_tag);
238443c2aeb0SSepherosa Ziehau 	if (rc != 0) {
238543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate "
238643c2aeb0SSepherosa Ziehau 			  "RX descriptor chain DMA tag!\n");
238743c2aeb0SSepherosa Ziehau 		return rc;
238843c2aeb0SSepherosa Ziehau 	}
238943c2aeb0SSepherosa Ziehau 
239043c2aeb0SSepherosa Ziehau 	for (i = 0; i < RX_PAGES; i++) {
239143c2aeb0SSepherosa Ziehau 		rc = bus_dmamem_alloc(sc->rx_bd_chain_tag,
239243c2aeb0SSepherosa Ziehau 				      (void **)&sc->rx_bd_chain[i],
23934a458e9dSSepherosa Ziehau 				      BUS_DMA_WAITOK | BUS_DMA_ZERO |
23944a458e9dSSepherosa Ziehau 				      BUS_DMA_COHERENT,
239543c2aeb0SSepherosa Ziehau 				      &sc->rx_bd_chain_map[i]);
239643c2aeb0SSepherosa Ziehau 		if (rc != 0) {
239743c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Could not allocate %dth RX descriptor "
239843c2aeb0SSepherosa Ziehau 				  "chain DMA memory!\n", i);
239943c2aeb0SSepherosa Ziehau 			return rc;
240043c2aeb0SSepherosa Ziehau 		}
240143c2aeb0SSepherosa Ziehau 
240243c2aeb0SSepherosa Ziehau 		rc = bus_dmamap_load(sc->rx_bd_chain_tag,
240343c2aeb0SSepherosa Ziehau 				     sc->rx_bd_chain_map[i],
240443c2aeb0SSepherosa Ziehau 				     sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ,
240543c2aeb0SSepherosa Ziehau 				     bce_dma_map_addr, &busaddr,
240643c2aeb0SSepherosa Ziehau 				     BUS_DMA_WAITOK);
240743c2aeb0SSepherosa Ziehau 		if (rc != 0) {
24084a458e9dSSepherosa Ziehau 			if (rc == EINPROGRESS) {
24094a458e9dSSepherosa Ziehau 				panic("%s coherent memory loading "
24104a458e9dSSepherosa Ziehau 				      "is still in progress!", ifp->if_xname);
24114a458e9dSSepherosa Ziehau 			}
241243c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Could not map %dth RX descriptor "
241343c2aeb0SSepherosa Ziehau 				  "chain DMA memory!\n", i);
241443c2aeb0SSepherosa Ziehau 			bus_dmamem_free(sc->rx_bd_chain_tag,
241543c2aeb0SSepherosa Ziehau 					sc->rx_bd_chain[i],
241643c2aeb0SSepherosa Ziehau 					sc->rx_bd_chain_map[i]);
241743c2aeb0SSepherosa Ziehau 			sc->rx_bd_chain[i] = NULL;
241843c2aeb0SSepherosa Ziehau 			return rc;
241943c2aeb0SSepherosa Ziehau 		}
242043c2aeb0SSepherosa Ziehau 
242143c2aeb0SSepherosa Ziehau 		sc->rx_bd_chain_paddr[i] = busaddr;
242243c2aeb0SSepherosa Ziehau 		/* DRC - Fix for 64 bit systems. */
242343c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "rx_bd_chain_paddr[%d] = 0x%08X\n",
242443c2aeb0SSepherosa Ziehau 			i, (uint32_t)sc->rx_bd_chain_paddr[i]);
242543c2aeb0SSepherosa Ziehau 	}
242643c2aeb0SSepherosa Ziehau 
242743c2aeb0SSepherosa Ziehau 	/* Create a DMA tag for RX mbufs. */
2428cffea833SSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag, BCE_DMA_RX_ALIGN, 0,
242945010e4dSSepherosa Ziehau 				BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
243043c2aeb0SSepherosa Ziehau 				NULL, NULL,
243145010e4dSSepherosa Ziehau 				MCLBYTES, 1, MCLBYTES,
2432cffea833SSepherosa Ziehau 				BUS_DMA_ALLOCNOW | BUS_DMA_ALIGNED |
2433cffea833SSepherosa Ziehau 				BUS_DMA_WAITOK,
243445010e4dSSepherosa Ziehau 				&sc->rx_mbuf_tag);
243543c2aeb0SSepherosa Ziehau 	if (rc != 0) {
243643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate RX mbuf DMA tag!\n");
243743c2aeb0SSepherosa Ziehau 		return rc;
243843c2aeb0SSepherosa Ziehau 	}
243943c2aeb0SSepherosa Ziehau 
2440c36fd9eeSSepherosa Ziehau 	/* Create tmp DMA map for RX mbuf clusters. */
2441c36fd9eeSSepherosa Ziehau 	rc = bus_dmamap_create(sc->rx_mbuf_tag, BUS_DMA_WAITOK,
2442c36fd9eeSSepherosa Ziehau 			       &sc->rx_mbuf_tmpmap);
2443c36fd9eeSSepherosa Ziehau 	if (rc != 0) {
2444c36fd9eeSSepherosa Ziehau 		bus_dma_tag_destroy(sc->rx_mbuf_tag);
2445c36fd9eeSSepherosa Ziehau 		sc->rx_mbuf_tag = NULL;
2446c36fd9eeSSepherosa Ziehau 
2447c36fd9eeSSepherosa Ziehau 		if_printf(ifp, "Could not create RX mbuf tmp DMA map!\n");
2448c36fd9eeSSepherosa Ziehau 		return rc;
2449c36fd9eeSSepherosa Ziehau 	}
2450c36fd9eeSSepherosa Ziehau 
245143c2aeb0SSepherosa Ziehau 	/* Create DMA maps for the RX mbuf clusters. */
245243c2aeb0SSepherosa Ziehau 	for (i = 0; i < TOTAL_RX_BD; i++) {
245343c2aeb0SSepherosa Ziehau 		rc = bus_dmamap_create(sc->rx_mbuf_tag, BUS_DMA_WAITOK,
245443c2aeb0SSepherosa Ziehau 				       &sc->rx_mbuf_map[i]);
245543c2aeb0SSepherosa Ziehau 		if (rc != 0) {
245643c2aeb0SSepherosa Ziehau 			for (j = 0; j < i; ++j) {
245743c2aeb0SSepherosa Ziehau 				bus_dmamap_destroy(sc->rx_mbuf_tag,
245843c2aeb0SSepherosa Ziehau 						   sc->rx_mbuf_map[j]);
245943c2aeb0SSepherosa Ziehau 			}
246043c2aeb0SSepherosa Ziehau 			bus_dma_tag_destroy(sc->rx_mbuf_tag);
246143c2aeb0SSepherosa Ziehau 			sc->rx_mbuf_tag = NULL;
246243c2aeb0SSepherosa Ziehau 
246343c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Unable to create "
246443c2aeb0SSepherosa Ziehau 				  "%dth RX mbuf DMA map!\n", i);
246543c2aeb0SSepherosa Ziehau 			return rc;
246643c2aeb0SSepherosa Ziehau 		}
246743c2aeb0SSepherosa Ziehau 	}
246843c2aeb0SSepherosa Ziehau 	return 0;
246943c2aeb0SSepherosa Ziehau }
247043c2aeb0SSepherosa Ziehau 
247143c2aeb0SSepherosa Ziehau 
247243c2aeb0SSepherosa Ziehau /****************************************************************************/
247343c2aeb0SSepherosa Ziehau /* Firmware synchronization.                                                */
247443c2aeb0SSepherosa Ziehau /*                                                                          */
247543c2aeb0SSepherosa Ziehau /* Before performing certain events such as a chip reset, synchronize with  */
247643c2aeb0SSepherosa Ziehau /* the firmware first.                                                      */
247743c2aeb0SSepherosa Ziehau /*                                                                          */
247843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
247943c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
248043c2aeb0SSepherosa Ziehau /****************************************************************************/
248143c2aeb0SSepherosa Ziehau static int
248243c2aeb0SSepherosa Ziehau bce_fw_sync(struct bce_softc *sc, uint32_t msg_data)
248343c2aeb0SSepherosa Ziehau {
248443c2aeb0SSepherosa Ziehau 	int i, rc = 0;
248543c2aeb0SSepherosa Ziehau 	uint32_t val;
248643c2aeb0SSepherosa Ziehau 
248743c2aeb0SSepherosa Ziehau 	/* Don't waste any time if we've timed out before. */
248843c2aeb0SSepherosa Ziehau 	if (sc->bce_fw_timed_out)
248943c2aeb0SSepherosa Ziehau 		return EBUSY;
249043c2aeb0SSepherosa Ziehau 
249143c2aeb0SSepherosa Ziehau 	/* Increment the message sequence number. */
249243c2aeb0SSepherosa Ziehau 	sc->bce_fw_wr_seq++;
249343c2aeb0SSepherosa Ziehau 	msg_data |= sc->bce_fw_wr_seq;
249443c2aeb0SSepherosa Ziehau 
249543c2aeb0SSepherosa Ziehau  	DBPRINT(sc, BCE_VERBOSE, "bce_fw_sync(): msg_data = 0x%08X\n", msg_data);
249643c2aeb0SSepherosa Ziehau 
249743c2aeb0SSepherosa Ziehau 	/* Send the message to the bootcode driver mailbox. */
2498bc30d40dSSepherosa Ziehau 	bce_shmem_wr(sc, BCE_DRV_MB, msg_data);
249943c2aeb0SSepherosa Ziehau 
250043c2aeb0SSepherosa Ziehau 	/* Wait for the bootcode to acknowledge the message. */
250143c2aeb0SSepherosa Ziehau 	for (i = 0; i < FW_ACK_TIME_OUT_MS; i++) {
250243c2aeb0SSepherosa Ziehau 		/* Check for a response in the bootcode firmware mailbox. */
2503bc30d40dSSepherosa Ziehau 		val = bce_shmem_rd(sc, BCE_FW_MB);
250443c2aeb0SSepherosa Ziehau 		if ((val & BCE_FW_MSG_ACK) == (msg_data & BCE_DRV_MSG_SEQ))
250543c2aeb0SSepherosa Ziehau 			break;
250643c2aeb0SSepherosa Ziehau 		DELAY(1000);
250743c2aeb0SSepherosa Ziehau 	}
250843c2aeb0SSepherosa Ziehau 
250943c2aeb0SSepherosa Ziehau 	/* If we've timed out, tell the bootcode that we've stopped waiting. */
251043c2aeb0SSepherosa Ziehau 	if ((val & BCE_FW_MSG_ACK) != (msg_data & BCE_DRV_MSG_SEQ) &&
251143c2aeb0SSepherosa Ziehau 	    (msg_data & BCE_DRV_MSG_DATA) != BCE_DRV_MSG_DATA_WAIT0) {
251243c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
251343c2aeb0SSepherosa Ziehau 			  "Firmware synchronization timeout! "
251443c2aeb0SSepherosa Ziehau 			  "msg_data = 0x%08X\n", msg_data);
251543c2aeb0SSepherosa Ziehau 
251643c2aeb0SSepherosa Ziehau 		msg_data &= ~BCE_DRV_MSG_CODE;
251743c2aeb0SSepherosa Ziehau 		msg_data |= BCE_DRV_MSG_CODE_FW_TIMEOUT;
251843c2aeb0SSepherosa Ziehau 
2519bc30d40dSSepherosa Ziehau 		bce_shmem_wr(sc, BCE_DRV_MB, msg_data);
252043c2aeb0SSepherosa Ziehau 
252143c2aeb0SSepherosa Ziehau 		sc->bce_fw_timed_out = 1;
252243c2aeb0SSepherosa Ziehau 		rc = EBUSY;
252343c2aeb0SSepherosa Ziehau 	}
252443c2aeb0SSepherosa Ziehau 	return rc;
252543c2aeb0SSepherosa Ziehau }
252643c2aeb0SSepherosa Ziehau 
252743c2aeb0SSepherosa Ziehau 
252843c2aeb0SSepherosa Ziehau /****************************************************************************/
252943c2aeb0SSepherosa Ziehau /* Load Receive Virtual 2 Physical (RV2P) processor firmware.               */
253043c2aeb0SSepherosa Ziehau /*                                                                          */
253143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
253243c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
253343c2aeb0SSepherosa Ziehau /****************************************************************************/
253443c2aeb0SSepherosa Ziehau static void
253543c2aeb0SSepherosa Ziehau bce_load_rv2p_fw(struct bce_softc *sc, uint32_t *rv2p_code,
253643c2aeb0SSepherosa Ziehau 		 uint32_t rv2p_code_len, uint32_t rv2p_proc)
253743c2aeb0SSepherosa Ziehau {
253843c2aeb0SSepherosa Ziehau 	int i;
253943c2aeb0SSepherosa Ziehau 	uint32_t val;
254043c2aeb0SSepherosa Ziehau 
254143c2aeb0SSepherosa Ziehau 	for (i = 0; i < rv2p_code_len; i += 8) {
254243c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_RV2P_INSTR_HIGH, *rv2p_code);
254343c2aeb0SSepherosa Ziehau 		rv2p_code++;
254443c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_RV2P_INSTR_LOW, *rv2p_code);
254543c2aeb0SSepherosa Ziehau 		rv2p_code++;
254643c2aeb0SSepherosa Ziehau 
254743c2aeb0SSepherosa Ziehau 		if (rv2p_proc == RV2P_PROC1) {
254843c2aeb0SSepherosa Ziehau 			val = (i / 8) | BCE_RV2P_PROC1_ADDR_CMD_RDWR;
254943c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_RV2P_PROC1_ADDR_CMD, val);
255043c2aeb0SSepherosa Ziehau 		} else {
255143c2aeb0SSepherosa Ziehau 			val = (i / 8) | BCE_RV2P_PROC2_ADDR_CMD_RDWR;
255243c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_RV2P_PROC2_ADDR_CMD, val);
255343c2aeb0SSepherosa Ziehau 		}
255443c2aeb0SSepherosa Ziehau 	}
255543c2aeb0SSepherosa Ziehau 
255643c2aeb0SSepherosa Ziehau 	/* Reset the processor, un-stall is done later. */
255743c2aeb0SSepherosa Ziehau 	if (rv2p_proc == RV2P_PROC1)
255843c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC1_RESET);
255943c2aeb0SSepherosa Ziehau 	else
256043c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC2_RESET);
256143c2aeb0SSepherosa Ziehau }
256243c2aeb0SSepherosa Ziehau 
256343c2aeb0SSepherosa Ziehau 
256443c2aeb0SSepherosa Ziehau /****************************************************************************/
256543c2aeb0SSepherosa Ziehau /* Load RISC processor firmware.                                            */
256643c2aeb0SSepherosa Ziehau /*                                                                          */
256743c2aeb0SSepherosa Ziehau /* Loads firmware from the file if_bcefw.h into the scratchpad memory       */
256843c2aeb0SSepherosa Ziehau /* associated with a particular processor.                                  */
256943c2aeb0SSepherosa Ziehau /*                                                                          */
257043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
257143c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
257243c2aeb0SSepherosa Ziehau /****************************************************************************/
257343c2aeb0SSepherosa Ziehau static void
257443c2aeb0SSepherosa Ziehau bce_load_cpu_fw(struct bce_softc *sc, struct cpu_reg *cpu_reg,
257543c2aeb0SSepherosa Ziehau 		struct fw_info *fw)
257643c2aeb0SSepherosa Ziehau {
25775d05a208SSepherosa Ziehau 	uint32_t offset;
257843c2aeb0SSepherosa Ziehau 	int j;
257943c2aeb0SSepherosa Ziehau 
25805d05a208SSepherosa Ziehau 	bce_halt_cpu(sc, cpu_reg);
258143c2aeb0SSepherosa Ziehau 
258243c2aeb0SSepherosa Ziehau 	/* Load the Text area. */
258343c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
258443c2aeb0SSepherosa Ziehau 	if (fw->text) {
258543c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->text_len / 4); j++, offset += 4)
258643c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->text[j]);
258743c2aeb0SSepherosa Ziehau 	}
258843c2aeb0SSepherosa Ziehau 
258943c2aeb0SSepherosa Ziehau 	/* Load the Data area. */
259043c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
259143c2aeb0SSepherosa Ziehau 	if (fw->data) {
259243c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->data_len / 4); j++, offset += 4)
259343c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->data[j]);
259443c2aeb0SSepherosa Ziehau 	}
259543c2aeb0SSepherosa Ziehau 
259643c2aeb0SSepherosa Ziehau 	/* Load the SBSS area. */
259743c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
259843c2aeb0SSepherosa Ziehau 	if (fw->sbss) {
259943c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4)
260043c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->sbss[j]);
260143c2aeb0SSepherosa Ziehau 	}
260243c2aeb0SSepherosa Ziehau 
260343c2aeb0SSepherosa Ziehau 	/* Load the BSS area. */
260443c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
260543c2aeb0SSepherosa Ziehau 	if (fw->bss) {
260643c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->bss_len/4); j++, offset += 4)
260743c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->bss[j]);
260843c2aeb0SSepherosa Ziehau 	}
260943c2aeb0SSepherosa Ziehau 
261043c2aeb0SSepherosa Ziehau 	/* Load the Read-Only area. */
261143c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base +
261243c2aeb0SSepherosa Ziehau 		(fw->rodata_addr - cpu_reg->mips_view_base);
261343c2aeb0SSepherosa Ziehau 	if (fw->rodata) {
261443c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4)
261543c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->rodata[j]);
261643c2aeb0SSepherosa Ziehau 	}
261743c2aeb0SSepherosa Ziehau 
26185d05a208SSepherosa Ziehau 	/* Clear the pre-fetch instruction and set the FW start address. */
261943c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->inst, 0);
262043c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->pc, fw->start_addr);
26215d05a208SSepherosa Ziehau }
26225d05a208SSepherosa Ziehau 
26235d05a208SSepherosa Ziehau 
26245d05a208SSepherosa Ziehau /****************************************************************************/
26255d05a208SSepherosa Ziehau /* Starts the RISC processor.                                               */
26265d05a208SSepherosa Ziehau /*                                                                          */
26275d05a208SSepherosa Ziehau /* Assumes the CPU starting address has already been set.                   */
26285d05a208SSepherosa Ziehau /*                                                                          */
26295d05a208SSepherosa Ziehau /* Returns:                                                                 */
26305d05a208SSepherosa Ziehau /*   Nothing.                                                               */
26315d05a208SSepherosa Ziehau /****************************************************************************/
26325d05a208SSepherosa Ziehau static void
26335d05a208SSepherosa Ziehau bce_start_cpu(struct bce_softc *sc, struct cpu_reg *cpu_reg)
26345d05a208SSepherosa Ziehau {
26355d05a208SSepherosa Ziehau 	uint32_t val;
263643c2aeb0SSepherosa Ziehau 
263743c2aeb0SSepherosa Ziehau 	/* Start the CPU. */
263843c2aeb0SSepherosa Ziehau 	val = REG_RD_IND(sc, cpu_reg->mode);
263943c2aeb0SSepherosa Ziehau 	val &= ~cpu_reg->mode_value_halt;
264043c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear);
264143c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->mode, val);
264243c2aeb0SSepherosa Ziehau }
264343c2aeb0SSepherosa Ziehau 
264443c2aeb0SSepherosa Ziehau 
264543c2aeb0SSepherosa Ziehau /****************************************************************************/
26465d05a208SSepherosa Ziehau /* Halts the RISC processor.                                                */
26475d05a208SSepherosa Ziehau /*                                                                          */
26485d05a208SSepherosa Ziehau /* Returns:                                                                 */
26495d05a208SSepherosa Ziehau /*   Nothing.                                                               */
26505d05a208SSepherosa Ziehau /****************************************************************************/
26515d05a208SSepherosa Ziehau static void
26525d05a208SSepherosa Ziehau bce_halt_cpu(struct bce_softc *sc, struct cpu_reg *cpu_reg)
26535d05a208SSepherosa Ziehau {
26545d05a208SSepherosa Ziehau 	uint32_t val;
26555d05a208SSepherosa Ziehau 
26565d05a208SSepherosa Ziehau 	/* Halt the CPU. */
26575d05a208SSepherosa Ziehau 	val = REG_RD_IND(sc, cpu_reg->mode);
26585d05a208SSepherosa Ziehau 	val |= cpu_reg->mode_value_halt;
26595d05a208SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->mode, val);
26605d05a208SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear);
26615d05a208SSepherosa Ziehau }
26625d05a208SSepherosa Ziehau 
26635d05a208SSepherosa Ziehau 
26645d05a208SSepherosa Ziehau /****************************************************************************/
26655d05a208SSepherosa Ziehau /* Start the RX CPU.                                                        */
26665d05a208SSepherosa Ziehau /*                                                                          */
26675d05a208SSepherosa Ziehau /* Returns:                                                                 */
26685d05a208SSepherosa Ziehau /*   Nothing.                                                               */
26695d05a208SSepherosa Ziehau /****************************************************************************/
26705d05a208SSepherosa Ziehau static void
26715d05a208SSepherosa Ziehau bce_start_rxp_cpu(struct bce_softc *sc)
26725d05a208SSepherosa Ziehau {
26735d05a208SSepherosa Ziehau 	struct cpu_reg cpu_reg;
26745d05a208SSepherosa Ziehau 
26755d05a208SSepherosa Ziehau 	cpu_reg.mode = BCE_RXP_CPU_MODE;
26765d05a208SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_RXP_CPU_MODE_SOFT_HALT;
26775d05a208SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_RXP_CPU_MODE_STEP_ENA;
26785d05a208SSepherosa Ziehau 	cpu_reg.state = BCE_RXP_CPU_STATE;
26795d05a208SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
26805d05a208SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_RXP_CPU_REG_FILE;
26815d05a208SSepherosa Ziehau 	cpu_reg.evmask = BCE_RXP_CPU_EVENT_MASK;
26825d05a208SSepherosa Ziehau 	cpu_reg.pc = BCE_RXP_CPU_PROGRAM_COUNTER;
26835d05a208SSepherosa Ziehau 	cpu_reg.inst = BCE_RXP_CPU_INSTRUCTION;
26845d05a208SSepherosa Ziehau 	cpu_reg.bp = BCE_RXP_CPU_HW_BREAKPOINT;
26855d05a208SSepherosa Ziehau 	cpu_reg.spad_base = BCE_RXP_SCRATCH;
26865d05a208SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
26875d05a208SSepherosa Ziehau 
26885d05a208SSepherosa Ziehau 	bce_start_cpu(sc, &cpu_reg);
26895d05a208SSepherosa Ziehau }
26905d05a208SSepherosa Ziehau 
26915d05a208SSepherosa Ziehau 
26925d05a208SSepherosa Ziehau /****************************************************************************/
2693d0092544SSepherosa Ziehau /* Initialize the RX CPU.                                                   */
269443c2aeb0SSepherosa Ziehau /*                                                                          */
269543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
269643c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
269743c2aeb0SSepherosa Ziehau /****************************************************************************/
269843c2aeb0SSepherosa Ziehau static void
2699d0092544SSepherosa Ziehau bce_init_rxp_cpu(struct bce_softc *sc)
270043c2aeb0SSepherosa Ziehau {
270143c2aeb0SSepherosa Ziehau 	struct cpu_reg cpu_reg;
270243c2aeb0SSepherosa Ziehau 	struct fw_info fw;
270343c2aeb0SSepherosa Ziehau 
270443c2aeb0SSepherosa Ziehau 	cpu_reg.mode = BCE_RXP_CPU_MODE;
270543c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_RXP_CPU_MODE_SOFT_HALT;
270643c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_RXP_CPU_MODE_STEP_ENA;
270743c2aeb0SSepherosa Ziehau 	cpu_reg.state = BCE_RXP_CPU_STATE;
270843c2aeb0SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
270943c2aeb0SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_RXP_CPU_REG_FILE;
271043c2aeb0SSepherosa Ziehau 	cpu_reg.evmask = BCE_RXP_CPU_EVENT_MASK;
271143c2aeb0SSepherosa Ziehau 	cpu_reg.pc = BCE_RXP_CPU_PROGRAM_COUNTER;
271243c2aeb0SSepherosa Ziehau 	cpu_reg.inst = BCE_RXP_CPU_INSTRUCTION;
271343c2aeb0SSepherosa Ziehau 	cpu_reg.bp = BCE_RXP_CPU_HW_BREAKPOINT;
271443c2aeb0SSepherosa Ziehau 	cpu_reg.spad_base = BCE_RXP_SCRATCH;
271543c2aeb0SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
271643c2aeb0SSepherosa Ziehau 
2717d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
2718d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
2719d0092544SSepherosa Ziehau  		fw.ver_major = bce_RXP_b09FwReleaseMajor;
2720d0092544SSepherosa Ziehau 		fw.ver_minor = bce_RXP_b09FwReleaseMinor;
2721d0092544SSepherosa Ziehau 		fw.ver_fix = bce_RXP_b09FwReleaseFix;
2722d0092544SSepherosa Ziehau 		fw.start_addr = bce_RXP_b09FwStartAddr;
2723d0092544SSepherosa Ziehau 
2724d0092544SSepherosa Ziehau 		fw.text_addr = bce_RXP_b09FwTextAddr;
2725d0092544SSepherosa Ziehau 		fw.text_len = bce_RXP_b09FwTextLen;
2726d0092544SSepherosa Ziehau 		fw.text_index = 0;
2727d0092544SSepherosa Ziehau 		fw.text = bce_RXP_b09FwText;
2728d0092544SSepherosa Ziehau 
2729d0092544SSepherosa Ziehau 		fw.data_addr = bce_RXP_b09FwDataAddr;
2730d0092544SSepherosa Ziehau 		fw.data_len = bce_RXP_b09FwDataLen;
2731d0092544SSepherosa Ziehau 		fw.data_index = 0;
2732d0092544SSepherosa Ziehau 		fw.data = bce_RXP_b09FwData;
2733d0092544SSepherosa Ziehau 
2734d0092544SSepherosa Ziehau 		fw.sbss_addr = bce_RXP_b09FwSbssAddr;
2735d0092544SSepherosa Ziehau 		fw.sbss_len = bce_RXP_b09FwSbssLen;
2736d0092544SSepherosa Ziehau 		fw.sbss_index = 0;
2737d0092544SSepherosa Ziehau 		fw.sbss = bce_RXP_b09FwSbss;
2738d0092544SSepherosa Ziehau 
2739d0092544SSepherosa Ziehau 		fw.bss_addr = bce_RXP_b09FwBssAddr;
2740d0092544SSepherosa Ziehau 		fw.bss_len = bce_RXP_b09FwBssLen;
2741d0092544SSepherosa Ziehau 		fw.bss_index = 0;
2742d0092544SSepherosa Ziehau 		fw.bss = bce_RXP_b09FwBss;
2743d0092544SSepherosa Ziehau 
2744d0092544SSepherosa Ziehau 		fw.rodata_addr = bce_RXP_b09FwRodataAddr;
2745d0092544SSepherosa Ziehau 		fw.rodata_len = bce_RXP_b09FwRodataLen;
2746d0092544SSepherosa Ziehau 		fw.rodata_index = 0;
2747d0092544SSepherosa Ziehau 		fw.rodata = bce_RXP_b09FwRodata;
2748d0092544SSepherosa Ziehau 	} else {
274943c2aeb0SSepherosa Ziehau 		fw.ver_major = bce_RXP_b06FwReleaseMajor;
275043c2aeb0SSepherosa Ziehau 		fw.ver_minor = bce_RXP_b06FwReleaseMinor;
275143c2aeb0SSepherosa Ziehau 		fw.ver_fix = bce_RXP_b06FwReleaseFix;
275243c2aeb0SSepherosa Ziehau 		fw.start_addr = bce_RXP_b06FwStartAddr;
275343c2aeb0SSepherosa Ziehau 
275443c2aeb0SSepherosa Ziehau 		fw.text_addr = bce_RXP_b06FwTextAddr;
275543c2aeb0SSepherosa Ziehau 		fw.text_len = bce_RXP_b06FwTextLen;
275643c2aeb0SSepherosa Ziehau 		fw.text_index = 0;
275743c2aeb0SSepherosa Ziehau 		fw.text = bce_RXP_b06FwText;
275843c2aeb0SSepherosa Ziehau 
275943c2aeb0SSepherosa Ziehau 		fw.data_addr = bce_RXP_b06FwDataAddr;
276043c2aeb0SSepherosa Ziehau 		fw.data_len = bce_RXP_b06FwDataLen;
276143c2aeb0SSepherosa Ziehau 		fw.data_index = 0;
276243c2aeb0SSepherosa Ziehau 		fw.data = bce_RXP_b06FwData;
276343c2aeb0SSepherosa Ziehau 
276443c2aeb0SSepherosa Ziehau 		fw.sbss_addr = bce_RXP_b06FwSbssAddr;
276543c2aeb0SSepherosa Ziehau 		fw.sbss_len = bce_RXP_b06FwSbssLen;
276643c2aeb0SSepherosa Ziehau 		fw.sbss_index = 0;
276743c2aeb0SSepherosa Ziehau 		fw.sbss = bce_RXP_b06FwSbss;
276843c2aeb0SSepherosa Ziehau 
276943c2aeb0SSepherosa Ziehau 		fw.bss_addr = bce_RXP_b06FwBssAddr;
277043c2aeb0SSepherosa Ziehau 		fw.bss_len = bce_RXP_b06FwBssLen;
277143c2aeb0SSepherosa Ziehau 		fw.bss_index = 0;
277243c2aeb0SSepherosa Ziehau 		fw.bss = bce_RXP_b06FwBss;
277343c2aeb0SSepherosa Ziehau 
277443c2aeb0SSepherosa Ziehau 		fw.rodata_addr = bce_RXP_b06FwRodataAddr;
277543c2aeb0SSepherosa Ziehau 		fw.rodata_len = bce_RXP_b06FwRodataLen;
277643c2aeb0SSepherosa Ziehau 		fw.rodata_index = 0;
277743c2aeb0SSepherosa Ziehau 		fw.rodata = bce_RXP_b06FwRodata;
2778d0092544SSepherosa Ziehau 	}
277943c2aeb0SSepherosa Ziehau 
278043c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RESET, "Loading RX firmware.\n");
278143c2aeb0SSepherosa Ziehau 	bce_load_cpu_fw(sc, &cpu_reg, &fw);
27825d05a208SSepherosa Ziehau 	/* Delay RXP start until initialization is complete. */
2783d0092544SSepherosa Ziehau }
278443c2aeb0SSepherosa Ziehau 
2785d0092544SSepherosa Ziehau 
2786d0092544SSepherosa Ziehau /****************************************************************************/
2787d0092544SSepherosa Ziehau /* Initialize the TX CPU.                                                   */
2788d0092544SSepherosa Ziehau /*                                                                          */
2789d0092544SSepherosa Ziehau /* Returns:                                                                 */
2790d0092544SSepherosa Ziehau /*   Nothing.                                                               */
2791d0092544SSepherosa Ziehau /****************************************************************************/
2792d0092544SSepherosa Ziehau static void
2793d0092544SSepherosa Ziehau bce_init_txp_cpu(struct bce_softc *sc)
2794d0092544SSepherosa Ziehau {
2795d0092544SSepherosa Ziehau 	struct cpu_reg cpu_reg;
2796d0092544SSepherosa Ziehau 	struct fw_info fw;
2797d0092544SSepherosa Ziehau 
279843c2aeb0SSepherosa Ziehau 	cpu_reg.mode = BCE_TXP_CPU_MODE;
279943c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_TXP_CPU_MODE_SOFT_HALT;
280043c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_TXP_CPU_MODE_STEP_ENA;
280143c2aeb0SSepherosa Ziehau 	cpu_reg.state = BCE_TXP_CPU_STATE;
280243c2aeb0SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
280343c2aeb0SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_TXP_CPU_REG_FILE;
280443c2aeb0SSepherosa Ziehau 	cpu_reg.evmask = BCE_TXP_CPU_EVENT_MASK;
280543c2aeb0SSepherosa Ziehau 	cpu_reg.pc = BCE_TXP_CPU_PROGRAM_COUNTER;
280643c2aeb0SSepherosa Ziehau 	cpu_reg.inst = BCE_TXP_CPU_INSTRUCTION;
280743c2aeb0SSepherosa Ziehau 	cpu_reg.bp = BCE_TXP_CPU_HW_BREAKPOINT;
280843c2aeb0SSepherosa Ziehau 	cpu_reg.spad_base = BCE_TXP_SCRATCH;
280943c2aeb0SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
281043c2aeb0SSepherosa Ziehau 
2811d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
2812d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
2813d0092544SSepherosa Ziehau 		fw.ver_major = bce_TXP_b09FwReleaseMajor;
2814d0092544SSepherosa Ziehau 		fw.ver_minor = bce_TXP_b09FwReleaseMinor;
2815d0092544SSepherosa Ziehau 		fw.ver_fix = bce_TXP_b09FwReleaseFix;
2816d0092544SSepherosa Ziehau 		fw.start_addr = bce_TXP_b09FwStartAddr;
2817d0092544SSepherosa Ziehau 
2818d0092544SSepherosa Ziehau 		fw.text_addr = bce_TXP_b09FwTextAddr;
2819d0092544SSepherosa Ziehau 		fw.text_len = bce_TXP_b09FwTextLen;
2820d0092544SSepherosa Ziehau 		fw.text_index = 0;
2821d0092544SSepherosa Ziehau 		fw.text = bce_TXP_b09FwText;
2822d0092544SSepherosa Ziehau 
2823d0092544SSepherosa Ziehau 		fw.data_addr = bce_TXP_b09FwDataAddr;
2824d0092544SSepherosa Ziehau 		fw.data_len = bce_TXP_b09FwDataLen;
2825d0092544SSepherosa Ziehau 		fw.data_index = 0;
2826d0092544SSepherosa Ziehau 		fw.data = bce_TXP_b09FwData;
2827d0092544SSepherosa Ziehau 
2828d0092544SSepherosa Ziehau 		fw.sbss_addr = bce_TXP_b09FwSbssAddr;
2829d0092544SSepherosa Ziehau 		fw.sbss_len = bce_TXP_b09FwSbssLen;
2830d0092544SSepherosa Ziehau 		fw.sbss_index = 0;
2831d0092544SSepherosa Ziehau 		fw.sbss = bce_TXP_b09FwSbss;
2832d0092544SSepherosa Ziehau 
2833d0092544SSepherosa Ziehau 		fw.bss_addr = bce_TXP_b09FwBssAddr;
2834d0092544SSepherosa Ziehau 		fw.bss_len = bce_TXP_b09FwBssLen;
2835d0092544SSepherosa Ziehau 		fw.bss_index = 0;
2836d0092544SSepherosa Ziehau 		fw.bss = bce_TXP_b09FwBss;
2837d0092544SSepherosa Ziehau 
2838d0092544SSepherosa Ziehau 		fw.rodata_addr = bce_TXP_b09FwRodataAddr;
2839d0092544SSepherosa Ziehau 		fw.rodata_len = bce_TXP_b09FwRodataLen;
2840d0092544SSepherosa Ziehau 		fw.rodata_index = 0;
2841d0092544SSepherosa Ziehau 		fw.rodata = bce_TXP_b09FwRodata;
2842d0092544SSepherosa Ziehau 	} else {
284343c2aeb0SSepherosa Ziehau 		fw.ver_major = bce_TXP_b06FwReleaseMajor;
284443c2aeb0SSepherosa Ziehau 		fw.ver_minor = bce_TXP_b06FwReleaseMinor;
284543c2aeb0SSepherosa Ziehau 		fw.ver_fix = bce_TXP_b06FwReleaseFix;
284643c2aeb0SSepherosa Ziehau 		fw.start_addr = bce_TXP_b06FwStartAddr;
284743c2aeb0SSepherosa Ziehau 
284843c2aeb0SSepherosa Ziehau 		fw.text_addr = bce_TXP_b06FwTextAddr;
284943c2aeb0SSepherosa Ziehau 		fw.text_len = bce_TXP_b06FwTextLen;
285043c2aeb0SSepherosa Ziehau 		fw.text_index = 0;
285143c2aeb0SSepherosa Ziehau 		fw.text = bce_TXP_b06FwText;
285243c2aeb0SSepherosa Ziehau 
285343c2aeb0SSepherosa Ziehau 		fw.data_addr = bce_TXP_b06FwDataAddr;
285443c2aeb0SSepherosa Ziehau 		fw.data_len = bce_TXP_b06FwDataLen;
285543c2aeb0SSepherosa Ziehau 		fw.data_index = 0;
285643c2aeb0SSepherosa Ziehau 		fw.data = bce_TXP_b06FwData;
285743c2aeb0SSepherosa Ziehau 
285843c2aeb0SSepherosa Ziehau 		fw.sbss_addr = bce_TXP_b06FwSbssAddr;
285943c2aeb0SSepherosa Ziehau 		fw.sbss_len = bce_TXP_b06FwSbssLen;
286043c2aeb0SSepherosa Ziehau 		fw.sbss_index = 0;
286143c2aeb0SSepherosa Ziehau 		fw.sbss = bce_TXP_b06FwSbss;
286243c2aeb0SSepherosa Ziehau 
286343c2aeb0SSepherosa Ziehau 		fw.bss_addr = bce_TXP_b06FwBssAddr;
286443c2aeb0SSepherosa Ziehau 		fw.bss_len = bce_TXP_b06FwBssLen;
286543c2aeb0SSepherosa Ziehau 		fw.bss_index = 0;
286643c2aeb0SSepherosa Ziehau 		fw.bss = bce_TXP_b06FwBss;
286743c2aeb0SSepherosa Ziehau 
286843c2aeb0SSepherosa Ziehau 		fw.rodata_addr = bce_TXP_b06FwRodataAddr;
286943c2aeb0SSepherosa Ziehau 		fw.rodata_len = bce_TXP_b06FwRodataLen;
287043c2aeb0SSepherosa Ziehau 		fw.rodata_index = 0;
287143c2aeb0SSepherosa Ziehau 		fw.rodata = bce_TXP_b06FwRodata;
2872d0092544SSepherosa Ziehau 	}
287343c2aeb0SSepherosa Ziehau 
287443c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RESET, "Loading TX firmware.\n");
287543c2aeb0SSepherosa Ziehau 	bce_load_cpu_fw(sc, &cpu_reg, &fw);
28765d05a208SSepherosa Ziehau 	bce_start_cpu(sc, &cpu_reg);
2877d0092544SSepherosa Ziehau }
287843c2aeb0SSepherosa Ziehau 
2879d0092544SSepherosa Ziehau 
2880d0092544SSepherosa Ziehau /****************************************************************************/
2881d0092544SSepherosa Ziehau /* Initialize the TPAT CPU.                                                 */
2882d0092544SSepherosa Ziehau /*                                                                          */
2883d0092544SSepherosa Ziehau /* Returns:                                                                 */
2884d0092544SSepherosa Ziehau /*   Nothing.                                                               */
2885d0092544SSepherosa Ziehau /****************************************************************************/
2886d0092544SSepherosa Ziehau static void
2887d0092544SSepherosa Ziehau bce_init_tpat_cpu(struct bce_softc *sc)
2888d0092544SSepherosa Ziehau {
2889d0092544SSepherosa Ziehau 	struct cpu_reg cpu_reg;
2890d0092544SSepherosa Ziehau 	struct fw_info fw;
2891d0092544SSepherosa Ziehau 
289243c2aeb0SSepherosa Ziehau 	cpu_reg.mode = BCE_TPAT_CPU_MODE;
289343c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_TPAT_CPU_MODE_SOFT_HALT;
289443c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_TPAT_CPU_MODE_STEP_ENA;
289543c2aeb0SSepherosa Ziehau 	cpu_reg.state = BCE_TPAT_CPU_STATE;
289643c2aeb0SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
289743c2aeb0SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_TPAT_CPU_REG_FILE;
289843c2aeb0SSepherosa Ziehau 	cpu_reg.evmask = BCE_TPAT_CPU_EVENT_MASK;
289943c2aeb0SSepherosa Ziehau 	cpu_reg.pc = BCE_TPAT_CPU_PROGRAM_COUNTER;
290043c2aeb0SSepherosa Ziehau 	cpu_reg.inst = BCE_TPAT_CPU_INSTRUCTION;
290143c2aeb0SSepherosa Ziehau 	cpu_reg.bp = BCE_TPAT_CPU_HW_BREAKPOINT;
290243c2aeb0SSepherosa Ziehau 	cpu_reg.spad_base = BCE_TPAT_SCRATCH;
290343c2aeb0SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
290443c2aeb0SSepherosa Ziehau 
2905d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
2906d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
2907d0092544SSepherosa Ziehau 		fw.ver_major = bce_TPAT_b09FwReleaseMajor;
2908d0092544SSepherosa Ziehau 		fw.ver_minor = bce_TPAT_b09FwReleaseMinor;
2909d0092544SSepherosa Ziehau 		fw.ver_fix = bce_TPAT_b09FwReleaseFix;
2910d0092544SSepherosa Ziehau 		fw.start_addr = bce_TPAT_b09FwStartAddr;
2911d0092544SSepherosa Ziehau 
2912d0092544SSepherosa Ziehau 		fw.text_addr = bce_TPAT_b09FwTextAddr;
2913d0092544SSepherosa Ziehau 		fw.text_len = bce_TPAT_b09FwTextLen;
2914d0092544SSepherosa Ziehau 		fw.text_index = 0;
2915d0092544SSepherosa Ziehau 		fw.text = bce_TPAT_b09FwText;
2916d0092544SSepherosa Ziehau 
2917d0092544SSepherosa Ziehau 		fw.data_addr = bce_TPAT_b09FwDataAddr;
2918d0092544SSepherosa Ziehau 		fw.data_len = bce_TPAT_b09FwDataLen;
2919d0092544SSepherosa Ziehau 		fw.data_index = 0;
2920d0092544SSepherosa Ziehau 		fw.data = bce_TPAT_b09FwData;
2921d0092544SSepherosa Ziehau 
2922d0092544SSepherosa Ziehau 		fw.sbss_addr = bce_TPAT_b09FwSbssAddr;
2923d0092544SSepherosa Ziehau 		fw.sbss_len = bce_TPAT_b09FwSbssLen;
2924d0092544SSepherosa Ziehau 		fw.sbss_index = 0;
2925d0092544SSepherosa Ziehau 		fw.sbss = bce_TPAT_b09FwSbss;
2926d0092544SSepherosa Ziehau 
2927d0092544SSepherosa Ziehau 		fw.bss_addr = bce_TPAT_b09FwBssAddr;
2928d0092544SSepherosa Ziehau 		fw.bss_len = bce_TPAT_b09FwBssLen;
2929d0092544SSepherosa Ziehau 		fw.bss_index = 0;
2930d0092544SSepherosa Ziehau 		fw.bss = bce_TPAT_b09FwBss;
2931d0092544SSepherosa Ziehau 
2932d0092544SSepherosa Ziehau 		fw.rodata_addr = bce_TPAT_b09FwRodataAddr;
2933d0092544SSepherosa Ziehau 		fw.rodata_len = bce_TPAT_b09FwRodataLen;
2934d0092544SSepherosa Ziehau 		fw.rodata_index = 0;
2935d0092544SSepherosa Ziehau 		fw.rodata = bce_TPAT_b09FwRodata;
2936d0092544SSepherosa Ziehau 	} else {
293743c2aeb0SSepherosa Ziehau 		fw.ver_major = bce_TPAT_b06FwReleaseMajor;
293843c2aeb0SSepherosa Ziehau 		fw.ver_minor = bce_TPAT_b06FwReleaseMinor;
293943c2aeb0SSepherosa Ziehau 		fw.ver_fix = bce_TPAT_b06FwReleaseFix;
294043c2aeb0SSepherosa Ziehau 		fw.start_addr = bce_TPAT_b06FwStartAddr;
294143c2aeb0SSepherosa Ziehau 
294243c2aeb0SSepherosa Ziehau 		fw.text_addr = bce_TPAT_b06FwTextAddr;
294343c2aeb0SSepherosa Ziehau 		fw.text_len = bce_TPAT_b06FwTextLen;
294443c2aeb0SSepherosa Ziehau 		fw.text_index = 0;
294543c2aeb0SSepherosa Ziehau 		fw.text = bce_TPAT_b06FwText;
294643c2aeb0SSepherosa Ziehau 
294743c2aeb0SSepherosa Ziehau 		fw.data_addr = bce_TPAT_b06FwDataAddr;
294843c2aeb0SSepherosa Ziehau 		fw.data_len = bce_TPAT_b06FwDataLen;
294943c2aeb0SSepherosa Ziehau 		fw.data_index = 0;
295043c2aeb0SSepherosa Ziehau 		fw.data = bce_TPAT_b06FwData;
295143c2aeb0SSepherosa Ziehau 
295243c2aeb0SSepherosa Ziehau 		fw.sbss_addr = bce_TPAT_b06FwSbssAddr;
295343c2aeb0SSepherosa Ziehau 		fw.sbss_len = bce_TPAT_b06FwSbssLen;
295443c2aeb0SSepherosa Ziehau 		fw.sbss_index = 0;
295543c2aeb0SSepherosa Ziehau 		fw.sbss = bce_TPAT_b06FwSbss;
295643c2aeb0SSepherosa Ziehau 
295743c2aeb0SSepherosa Ziehau 		fw.bss_addr = bce_TPAT_b06FwBssAddr;
295843c2aeb0SSepherosa Ziehau 		fw.bss_len = bce_TPAT_b06FwBssLen;
295943c2aeb0SSepherosa Ziehau 		fw.bss_index = 0;
296043c2aeb0SSepherosa Ziehau 		fw.bss = bce_TPAT_b06FwBss;
296143c2aeb0SSepherosa Ziehau 
296243c2aeb0SSepherosa Ziehau 		fw.rodata_addr = bce_TPAT_b06FwRodataAddr;
296343c2aeb0SSepherosa Ziehau 		fw.rodata_len = bce_TPAT_b06FwRodataLen;
296443c2aeb0SSepherosa Ziehau 		fw.rodata_index = 0;
296543c2aeb0SSepherosa Ziehau 		fw.rodata = bce_TPAT_b06FwRodata;
2966d0092544SSepherosa Ziehau 	}
296743c2aeb0SSepherosa Ziehau 
296843c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RESET, "Loading TPAT firmware.\n");
296943c2aeb0SSepherosa Ziehau 	bce_load_cpu_fw(sc, &cpu_reg, &fw);
29705d05a208SSepherosa Ziehau 	bce_start_cpu(sc, &cpu_reg);
2971d0092544SSepherosa Ziehau }
297243c2aeb0SSepherosa Ziehau 
2973d0092544SSepherosa Ziehau 
2974d0092544SSepherosa Ziehau /****************************************************************************/
2975d0092544SSepherosa Ziehau /* Initialize the CP CPU.                                                   */
2976d0092544SSepherosa Ziehau /*                                                                          */
2977d0092544SSepherosa Ziehau /* Returns:                                                                 */
2978d0092544SSepherosa Ziehau /*   Nothing.                                                               */
2979d0092544SSepherosa Ziehau /****************************************************************************/
2980d0092544SSepherosa Ziehau static void
2981d0092544SSepherosa Ziehau bce_init_cp_cpu(struct bce_softc *sc)
2982d0092544SSepherosa Ziehau {
2983d0092544SSepherosa Ziehau 	struct cpu_reg cpu_reg;
2984d0092544SSepherosa Ziehau 	struct fw_info fw;
2985d0092544SSepherosa Ziehau 
2986d0092544SSepherosa Ziehau 	cpu_reg.mode = BCE_CP_CPU_MODE;
2987d0092544SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_CP_CPU_MODE_SOFT_HALT;
2988d0092544SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_CP_CPU_MODE_STEP_ENA;
2989d0092544SSepherosa Ziehau 	cpu_reg.state = BCE_CP_CPU_STATE;
2990d0092544SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
2991d0092544SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_CP_CPU_REG_FILE;
2992d0092544SSepherosa Ziehau 	cpu_reg.evmask = BCE_CP_CPU_EVENT_MASK;
2993d0092544SSepherosa Ziehau 	cpu_reg.pc = BCE_CP_CPU_PROGRAM_COUNTER;
2994d0092544SSepherosa Ziehau 	cpu_reg.inst = BCE_CP_CPU_INSTRUCTION;
2995d0092544SSepherosa Ziehau 	cpu_reg.bp = BCE_CP_CPU_HW_BREAKPOINT;
2996d0092544SSepherosa Ziehau 	cpu_reg.spad_base = BCE_CP_SCRATCH;
2997d0092544SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
2998d0092544SSepherosa Ziehau 
2999d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3000d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3001d0092544SSepherosa Ziehau 		fw.ver_major = bce_CP_b09FwReleaseMajor;
3002d0092544SSepherosa Ziehau 		fw.ver_minor = bce_CP_b09FwReleaseMinor;
3003d0092544SSepherosa Ziehau 		fw.ver_fix = bce_CP_b09FwReleaseFix;
3004d0092544SSepherosa Ziehau 		fw.start_addr = bce_CP_b09FwStartAddr;
3005d0092544SSepherosa Ziehau 
3006d0092544SSepherosa Ziehau 		fw.text_addr = bce_CP_b09FwTextAddr;
3007d0092544SSepherosa Ziehau 		fw.text_len = bce_CP_b09FwTextLen;
3008d0092544SSepherosa Ziehau 		fw.text_index = 0;
3009d0092544SSepherosa Ziehau 		fw.text = bce_CP_b09FwText;
3010d0092544SSepherosa Ziehau 
3011d0092544SSepherosa Ziehau 		fw.data_addr = bce_CP_b09FwDataAddr;
3012d0092544SSepherosa Ziehau 		fw.data_len = bce_CP_b09FwDataLen;
3013d0092544SSepherosa Ziehau 		fw.data_index = 0;
3014d0092544SSepherosa Ziehau 		fw.data = bce_CP_b09FwData;
3015d0092544SSepherosa Ziehau 
3016d0092544SSepherosa Ziehau 		fw.sbss_addr = bce_CP_b09FwSbssAddr;
3017d0092544SSepherosa Ziehau 		fw.sbss_len = bce_CP_b09FwSbssLen;
3018d0092544SSepherosa Ziehau 		fw.sbss_index = 0;
3019d0092544SSepherosa Ziehau 		fw.sbss = bce_CP_b09FwSbss;
3020d0092544SSepherosa Ziehau 
3021d0092544SSepherosa Ziehau 		fw.bss_addr = bce_CP_b09FwBssAddr;
3022d0092544SSepherosa Ziehau 		fw.bss_len = bce_CP_b09FwBssLen;
3023d0092544SSepherosa Ziehau 		fw.bss_index = 0;
3024d0092544SSepherosa Ziehau 		fw.bss = bce_CP_b09FwBss;
3025d0092544SSepherosa Ziehau 
3026d0092544SSepherosa Ziehau 		fw.rodata_addr = bce_CP_b09FwRodataAddr;
3027d0092544SSepherosa Ziehau 		fw.rodata_len = bce_CP_b09FwRodataLen;
3028d0092544SSepherosa Ziehau 		fw.rodata_index = 0;
3029d0092544SSepherosa Ziehau 		fw.rodata = bce_CP_b09FwRodata;
3030d0092544SSepherosa Ziehau 	} else {
3031d0092544SSepherosa Ziehau 		fw.ver_major = bce_CP_b06FwReleaseMajor;
3032d0092544SSepherosa Ziehau 		fw.ver_minor = bce_CP_b06FwReleaseMinor;
3033d0092544SSepherosa Ziehau 		fw.ver_fix = bce_CP_b06FwReleaseFix;
3034d0092544SSepherosa Ziehau 		fw.start_addr = bce_CP_b06FwStartAddr;
3035d0092544SSepherosa Ziehau 
3036d0092544SSepherosa Ziehau 		fw.text_addr = bce_CP_b06FwTextAddr;
3037d0092544SSepherosa Ziehau 		fw.text_len = bce_CP_b06FwTextLen;
3038d0092544SSepherosa Ziehau 		fw.text_index = 0;
3039d0092544SSepherosa Ziehau 		fw.text = bce_CP_b06FwText;
3040d0092544SSepherosa Ziehau 
3041d0092544SSepherosa Ziehau 		fw.data_addr = bce_CP_b06FwDataAddr;
3042d0092544SSepherosa Ziehau 		fw.data_len = bce_CP_b06FwDataLen;
3043d0092544SSepherosa Ziehau 		fw.data_index = 0;
3044d0092544SSepherosa Ziehau 		fw.data = bce_CP_b06FwData;
3045d0092544SSepherosa Ziehau 
3046d0092544SSepherosa Ziehau 		fw.sbss_addr = bce_CP_b06FwSbssAddr;
3047d0092544SSepherosa Ziehau 		fw.sbss_len = bce_CP_b06FwSbssLen;
3048d0092544SSepherosa Ziehau 		fw.sbss_index = 0;
3049d0092544SSepherosa Ziehau 		fw.sbss = bce_CP_b06FwSbss;
3050d0092544SSepherosa Ziehau 
3051d0092544SSepherosa Ziehau 		fw.bss_addr = bce_CP_b06FwBssAddr;
3052d0092544SSepherosa Ziehau 		fw.bss_len = bce_CP_b06FwBssLen;
3053d0092544SSepherosa Ziehau 		fw.bss_index = 0;
3054d0092544SSepherosa Ziehau 		fw.bss = bce_CP_b06FwBss;
3055d0092544SSepherosa Ziehau 
3056d0092544SSepherosa Ziehau 		fw.rodata_addr = bce_CP_b06FwRodataAddr;
3057d0092544SSepherosa Ziehau 		fw.rodata_len = bce_CP_b06FwRodataLen;
3058d0092544SSepherosa Ziehau 		fw.rodata_index = 0;
3059d0092544SSepherosa Ziehau 		fw.rodata = bce_CP_b06FwRodata;
3060d0092544SSepherosa Ziehau 	}
3061d0092544SSepherosa Ziehau 
3062d0092544SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RESET, "Loading CP firmware.\n");
3063d0092544SSepherosa Ziehau 	bce_load_cpu_fw(sc, &cpu_reg, &fw);
30645d05a208SSepherosa Ziehau 	bce_start_cpu(sc, &cpu_reg);
3065d0092544SSepherosa Ziehau }
3066d0092544SSepherosa Ziehau 
3067d0092544SSepherosa Ziehau 
3068d0092544SSepherosa Ziehau /****************************************************************************/
3069d0092544SSepherosa Ziehau /* Initialize the COM CPU.                                                 */
3070d0092544SSepherosa Ziehau /*                                                                          */
3071d0092544SSepherosa Ziehau /* Returns:                                                                 */
3072d0092544SSepherosa Ziehau /*   Nothing.                                                               */
3073d0092544SSepherosa Ziehau /****************************************************************************/
3074d0092544SSepherosa Ziehau static void
3075d0092544SSepherosa Ziehau bce_init_com_cpu(struct bce_softc *sc)
3076d0092544SSepherosa Ziehau {
3077d0092544SSepherosa Ziehau 	struct cpu_reg cpu_reg;
3078d0092544SSepherosa Ziehau 	struct fw_info fw;
3079d0092544SSepherosa Ziehau 
308043c2aeb0SSepherosa Ziehau 	cpu_reg.mode = BCE_COM_CPU_MODE;
308143c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_COM_CPU_MODE_SOFT_HALT;
308243c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_COM_CPU_MODE_STEP_ENA;
308343c2aeb0SSepherosa Ziehau 	cpu_reg.state = BCE_COM_CPU_STATE;
308443c2aeb0SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
308543c2aeb0SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_COM_CPU_REG_FILE;
308643c2aeb0SSepherosa Ziehau 	cpu_reg.evmask = BCE_COM_CPU_EVENT_MASK;
308743c2aeb0SSepherosa Ziehau 	cpu_reg.pc = BCE_COM_CPU_PROGRAM_COUNTER;
308843c2aeb0SSepherosa Ziehau 	cpu_reg.inst = BCE_COM_CPU_INSTRUCTION;
308943c2aeb0SSepherosa Ziehau 	cpu_reg.bp = BCE_COM_CPU_HW_BREAKPOINT;
309043c2aeb0SSepherosa Ziehau 	cpu_reg.spad_base = BCE_COM_SCRATCH;
309143c2aeb0SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
309243c2aeb0SSepherosa Ziehau 
3093d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3094d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3095d0092544SSepherosa Ziehau 		fw.ver_major = bce_COM_b09FwReleaseMajor;
3096d0092544SSepherosa Ziehau 		fw.ver_minor = bce_COM_b09FwReleaseMinor;
3097d0092544SSepherosa Ziehau 		fw.ver_fix = bce_COM_b09FwReleaseFix;
3098d0092544SSepherosa Ziehau 		fw.start_addr = bce_COM_b09FwStartAddr;
3099d0092544SSepherosa Ziehau 
3100d0092544SSepherosa Ziehau 		fw.text_addr = bce_COM_b09FwTextAddr;
3101d0092544SSepherosa Ziehau 		fw.text_len = bce_COM_b09FwTextLen;
3102d0092544SSepherosa Ziehau 		fw.text_index = 0;
3103d0092544SSepherosa Ziehau 		fw.text = bce_COM_b09FwText;
3104d0092544SSepherosa Ziehau 
3105d0092544SSepherosa Ziehau 		fw.data_addr = bce_COM_b09FwDataAddr;
3106d0092544SSepherosa Ziehau 		fw.data_len = bce_COM_b09FwDataLen;
3107d0092544SSepherosa Ziehau 		fw.data_index = 0;
3108d0092544SSepherosa Ziehau 		fw.data = bce_COM_b09FwData;
3109d0092544SSepherosa Ziehau 
3110d0092544SSepherosa Ziehau 		fw.sbss_addr = bce_COM_b09FwSbssAddr;
3111d0092544SSepherosa Ziehau 		fw.sbss_len = bce_COM_b09FwSbssLen;
3112d0092544SSepherosa Ziehau 		fw.sbss_index = 0;
3113d0092544SSepherosa Ziehau 		fw.sbss = bce_COM_b09FwSbss;
3114d0092544SSepherosa Ziehau 
3115d0092544SSepherosa Ziehau 		fw.bss_addr = bce_COM_b09FwBssAddr;
3116d0092544SSepherosa Ziehau 		fw.bss_len = bce_COM_b09FwBssLen;
3117d0092544SSepherosa Ziehau 		fw.bss_index = 0;
3118d0092544SSepherosa Ziehau 		fw.bss = bce_COM_b09FwBss;
3119d0092544SSepherosa Ziehau 
3120d0092544SSepherosa Ziehau 		fw.rodata_addr = bce_COM_b09FwRodataAddr;
3121d0092544SSepherosa Ziehau 		fw.rodata_len = bce_COM_b09FwRodataLen;
3122d0092544SSepherosa Ziehau 		fw.rodata_index = 0;
3123d0092544SSepherosa Ziehau 		fw.rodata = bce_COM_b09FwRodata;
3124d0092544SSepherosa Ziehau 	} else {
312543c2aeb0SSepherosa Ziehau 		fw.ver_major = bce_COM_b06FwReleaseMajor;
312643c2aeb0SSepherosa Ziehau 		fw.ver_minor = bce_COM_b06FwReleaseMinor;
312743c2aeb0SSepherosa Ziehau 		fw.ver_fix = bce_COM_b06FwReleaseFix;
312843c2aeb0SSepherosa Ziehau 		fw.start_addr = bce_COM_b06FwStartAddr;
312943c2aeb0SSepherosa Ziehau 
313043c2aeb0SSepherosa Ziehau 		fw.text_addr = bce_COM_b06FwTextAddr;
313143c2aeb0SSepherosa Ziehau 		fw.text_len = bce_COM_b06FwTextLen;
313243c2aeb0SSepherosa Ziehau 		fw.text_index = 0;
313343c2aeb0SSepherosa Ziehau 		fw.text = bce_COM_b06FwText;
313443c2aeb0SSepherosa Ziehau 
313543c2aeb0SSepherosa Ziehau 		fw.data_addr = bce_COM_b06FwDataAddr;
313643c2aeb0SSepherosa Ziehau 		fw.data_len = bce_COM_b06FwDataLen;
313743c2aeb0SSepherosa Ziehau 		fw.data_index = 0;
313843c2aeb0SSepherosa Ziehau 		fw.data = bce_COM_b06FwData;
313943c2aeb0SSepherosa Ziehau 
314043c2aeb0SSepherosa Ziehau 		fw.sbss_addr = bce_COM_b06FwSbssAddr;
314143c2aeb0SSepherosa Ziehau 		fw.sbss_len = bce_COM_b06FwSbssLen;
314243c2aeb0SSepherosa Ziehau 		fw.sbss_index = 0;
314343c2aeb0SSepherosa Ziehau 		fw.sbss = bce_COM_b06FwSbss;
314443c2aeb0SSepherosa Ziehau 
314543c2aeb0SSepherosa Ziehau 		fw.bss_addr = bce_COM_b06FwBssAddr;
314643c2aeb0SSepherosa Ziehau 		fw.bss_len = bce_COM_b06FwBssLen;
314743c2aeb0SSepherosa Ziehau 		fw.bss_index = 0;
314843c2aeb0SSepherosa Ziehau 		fw.bss = bce_COM_b06FwBss;
314943c2aeb0SSepherosa Ziehau 
315043c2aeb0SSepherosa Ziehau 		fw.rodata_addr = bce_COM_b06FwRodataAddr;
315143c2aeb0SSepherosa Ziehau 		fw.rodata_len = bce_COM_b06FwRodataLen;
315243c2aeb0SSepherosa Ziehau 		fw.rodata_index = 0;
315343c2aeb0SSepherosa Ziehau 		fw.rodata = bce_COM_b06FwRodata;
3154d0092544SSepherosa Ziehau 	}
315543c2aeb0SSepherosa Ziehau 
315643c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RESET, "Loading COM firmware.\n");
315743c2aeb0SSepherosa Ziehau 	bce_load_cpu_fw(sc, &cpu_reg, &fw);
31585d05a208SSepherosa Ziehau 	bce_start_cpu(sc, &cpu_reg);
315943c2aeb0SSepherosa Ziehau }
316043c2aeb0SSepherosa Ziehau 
316143c2aeb0SSepherosa Ziehau 
316243c2aeb0SSepherosa Ziehau /****************************************************************************/
3163d0092544SSepherosa Ziehau /* Initialize the RV2P, RX, TX, TPAT, COM, and CP CPUs.                     */
3164d0092544SSepherosa Ziehau /*                                                                          */
3165d0092544SSepherosa Ziehau /* Loads the firmware for each CPU and starts the CPU.                      */
3166d0092544SSepherosa Ziehau /*                                                                          */
3167d0092544SSepherosa Ziehau /* Returns:                                                                 */
3168d0092544SSepherosa Ziehau /*   Nothing.                                                               */
3169d0092544SSepherosa Ziehau /****************************************************************************/
3170d0092544SSepherosa Ziehau static void
3171d0092544SSepherosa Ziehau bce_init_cpus(struct bce_softc *sc)
3172d0092544SSepherosa Ziehau {
3173d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3174d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3175cff16e71SSepherosa Ziehau 		if (BCE_CHIP_REV(sc) == BCE_CHIP_REV_Ax) {
3176cff16e71SSepherosa Ziehau 			bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc1,
3177cff16e71SSepherosa Ziehau 			    sizeof(bce_xi90_rv2p_proc1), RV2P_PROC1);
3178cff16e71SSepherosa Ziehau 			bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc2,
3179cff16e71SSepherosa Ziehau 			    sizeof(bce_xi90_rv2p_proc2), RV2P_PROC2);
3180d0092544SSepherosa Ziehau 		} else {
3181cff16e71SSepherosa Ziehau 			bce_load_rv2p_fw(sc, bce_xi_rv2p_proc1,
3182cff16e71SSepherosa Ziehau 			    sizeof(bce_xi_rv2p_proc1), RV2P_PROC1);
3183cff16e71SSepherosa Ziehau 			bce_load_rv2p_fw(sc, bce_xi_rv2p_proc2,
3184cff16e71SSepherosa Ziehau 			    sizeof(bce_xi_rv2p_proc2), RV2P_PROC2);
3185cff16e71SSepherosa Ziehau 		}
3186cff16e71SSepherosa Ziehau 	} else {
3187cff16e71SSepherosa Ziehau 		bce_load_rv2p_fw(sc, bce_rv2p_proc1,
3188cff16e71SSepherosa Ziehau 		    sizeof(bce_rv2p_proc1), RV2P_PROC1);
3189cff16e71SSepherosa Ziehau 		bce_load_rv2p_fw(sc, bce_rv2p_proc2,
3190cff16e71SSepherosa Ziehau 		    sizeof(bce_rv2p_proc2), RV2P_PROC2);
3191d0092544SSepherosa Ziehau 	}
3192d0092544SSepherosa Ziehau 
3193d0092544SSepherosa Ziehau 	bce_init_rxp_cpu(sc);
3194d0092544SSepherosa Ziehau 	bce_init_txp_cpu(sc);
3195d0092544SSepherosa Ziehau 	bce_init_tpat_cpu(sc);
3196d0092544SSepherosa Ziehau 	bce_init_com_cpu(sc);
3197d0092544SSepherosa Ziehau 	bce_init_cp_cpu(sc);
3198d0092544SSepherosa Ziehau }
3199d0092544SSepherosa Ziehau 
3200d0092544SSepherosa Ziehau 
3201d0092544SSepherosa Ziehau /****************************************************************************/
320243c2aeb0SSepherosa Ziehau /* Initialize context memory.                                               */
320343c2aeb0SSepherosa Ziehau /*                                                                          */
320443c2aeb0SSepherosa Ziehau /* Clears the memory associated with each Context ID (CID).                 */
320543c2aeb0SSepherosa Ziehau /*                                                                          */
320643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
320743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
320843c2aeb0SSepherosa Ziehau /****************************************************************************/
320943c2aeb0SSepherosa Ziehau static void
32103a41a80bSSepherosa Ziehau bce_init_ctx(struct bce_softc *sc)
321143c2aeb0SSepherosa Ziehau {
3212d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3213d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3214d0092544SSepherosa Ziehau 		/* DRC: Replace this constant value with a #define. */
3215d0092544SSepherosa Ziehau 		int i, retry_cnt = 10;
3216d0092544SSepherosa Ziehau 		uint32_t val;
321743c2aeb0SSepherosa Ziehau 
3218d0092544SSepherosa Ziehau 		/*
3219d0092544SSepherosa Ziehau 		 * BCM5709 context memory may be cached
3220d0092544SSepherosa Ziehau 		 * in host memory so prepare the host memory
3221d0092544SSepherosa Ziehau 		 * for access.
3222d0092544SSepherosa Ziehau 		 */
3223d0092544SSepherosa Ziehau 		val = BCE_CTX_COMMAND_ENABLED | BCE_CTX_COMMAND_MEM_INIT |
3224d0092544SSepherosa Ziehau 		    (1 << 12);
3225d0092544SSepherosa Ziehau 		val |= (BCM_PAGE_BITS - 8) << 16;
3226d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_CTX_COMMAND, val);
322743c2aeb0SSepherosa Ziehau 
3228d0092544SSepherosa Ziehau 		/* Wait for mem init command to complete. */
3229d0092544SSepherosa Ziehau 		for (i = 0; i < retry_cnt; i++) {
3230d0092544SSepherosa Ziehau 			val = REG_RD(sc, BCE_CTX_COMMAND);
3231d0092544SSepherosa Ziehau 			if (!(val & BCE_CTX_COMMAND_MEM_INIT))
3232d0092544SSepherosa Ziehau 				break;
3233d0092544SSepherosa Ziehau 			DELAY(2);
3234d0092544SSepherosa Ziehau 		}
323543c2aeb0SSepherosa Ziehau 
3236d0092544SSepherosa Ziehau 		for (i = 0; i < sc->ctx_pages; i++) {
3237d0092544SSepherosa Ziehau 			int j;
323843c2aeb0SSepherosa Ziehau 
3239d0092544SSepherosa Ziehau 			/*
3240d0092544SSepherosa Ziehau 			 * Set the physical address of the context
3241d0092544SSepherosa Ziehau 			 * memory cache.
3242d0092544SSepherosa Ziehau 			 */
3243d0092544SSepherosa Ziehau 			REG_WR(sc, BCE_CTX_HOST_PAGE_TBL_DATA0,
3244d0092544SSepherosa Ziehau 			    BCE_ADDR_LO(sc->ctx_paddr[i] & 0xfffffff0) |
3245d0092544SSepherosa Ziehau 			    BCE_CTX_HOST_PAGE_TBL_DATA0_VALID);
3246d0092544SSepherosa Ziehau 			REG_WR(sc, BCE_CTX_HOST_PAGE_TBL_DATA1,
3247d0092544SSepherosa Ziehau 			    BCE_ADDR_HI(sc->ctx_paddr[i]));
3248d0092544SSepherosa Ziehau 			REG_WR(sc, BCE_CTX_HOST_PAGE_TBL_CTRL,
3249d0092544SSepherosa Ziehau 			    i | BCE_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
3250d0092544SSepherosa Ziehau 
3251d0092544SSepherosa Ziehau 			/*
3252d0092544SSepherosa Ziehau 			 * Verify that the context memory write was successful.
3253d0092544SSepherosa Ziehau 			 */
3254d0092544SSepherosa Ziehau 			for (j = 0; j < retry_cnt; j++) {
3255d0092544SSepherosa Ziehau 				val = REG_RD(sc, BCE_CTX_HOST_PAGE_TBL_CTRL);
3256d0092544SSepherosa Ziehau 				if ((val &
3257d0092544SSepherosa Ziehau 				    BCE_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) == 0)
3258d0092544SSepherosa Ziehau 					break;
3259d0092544SSepherosa Ziehau 				DELAY(5);
3260d0092544SSepherosa Ziehau 			}
3261d0092544SSepherosa Ziehau 		}
3262d0092544SSepherosa Ziehau 	} else {
3263d0092544SSepherosa Ziehau 		uint32_t vcid_addr, offset;
3264d0092544SSepherosa Ziehau 
3265d0092544SSepherosa Ziehau 		/*
3266d0092544SSepherosa Ziehau 		 * For the 5706/5708, context memory is local to
3267d0092544SSepherosa Ziehau 		 * the controller, so initialize the controller
3268d0092544SSepherosa Ziehau 		 * context memory.
3269d0092544SSepherosa Ziehau 		 */
3270d0092544SSepherosa Ziehau 
3271d0092544SSepherosa Ziehau 		vcid_addr = GET_CID_ADDR(96);
3272d0092544SSepherosa Ziehau 		while (vcid_addr) {
3273d0092544SSepherosa Ziehau 			vcid_addr -= PHY_CTX_SIZE;
3274d0092544SSepherosa Ziehau 
3275d0092544SSepherosa Ziehau 			REG_WR(sc, BCE_CTX_VIRT_ADDR, 0);
3276d0092544SSepherosa Ziehau 			REG_WR(sc, BCE_CTX_PAGE_TBL, vcid_addr);
3277d0092544SSepherosa Ziehau 
3278d0092544SSepherosa Ziehau 			for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
3279d0092544SSepherosa Ziehau 				CTX_WR(sc, 0x00, offset, 0);
32803a41a80bSSepherosa Ziehau 
32813a41a80bSSepherosa Ziehau 			REG_WR(sc, BCE_CTX_VIRT_ADDR, vcid_addr);
3282d0092544SSepherosa Ziehau 			REG_WR(sc, BCE_CTX_PAGE_TBL, vcid_addr);
32833a41a80bSSepherosa Ziehau 		}
328443c2aeb0SSepherosa Ziehau 	}
328543c2aeb0SSepherosa Ziehau }
328643c2aeb0SSepherosa Ziehau 
328743c2aeb0SSepherosa Ziehau 
328843c2aeb0SSepherosa Ziehau /****************************************************************************/
328943c2aeb0SSepherosa Ziehau /* Fetch the permanent MAC address of the controller.                       */
329043c2aeb0SSepherosa Ziehau /*                                                                          */
329143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
329243c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
329343c2aeb0SSepherosa Ziehau /****************************************************************************/
329443c2aeb0SSepherosa Ziehau static void
329543c2aeb0SSepherosa Ziehau bce_get_mac_addr(struct bce_softc *sc)
329643c2aeb0SSepherosa Ziehau {
329743c2aeb0SSepherosa Ziehau 	uint32_t mac_lo = 0, mac_hi = 0;
329843c2aeb0SSepherosa Ziehau 
329943c2aeb0SSepherosa Ziehau 	/*
330043c2aeb0SSepherosa Ziehau 	 * The NetXtreme II bootcode populates various NIC
330143c2aeb0SSepherosa Ziehau 	 * power-on and runtime configuration items in a
330243c2aeb0SSepherosa Ziehau 	 * shared memory area.  The factory configured MAC
330343c2aeb0SSepherosa Ziehau 	 * address is available from both NVRAM and the
330443c2aeb0SSepherosa Ziehau 	 * shared memory area so we'll read the value from
330543c2aeb0SSepherosa Ziehau 	 * shared memory for speed.
330643c2aeb0SSepherosa Ziehau 	 */
330743c2aeb0SSepherosa Ziehau 
3308bc30d40dSSepherosa Ziehau 	mac_hi = bce_shmem_rd(sc,  BCE_PORT_HW_CFG_MAC_UPPER);
3309bc30d40dSSepherosa Ziehau 	mac_lo = bce_shmem_rd(sc, BCE_PORT_HW_CFG_MAC_LOWER);
331043c2aeb0SSepherosa Ziehau 
331143c2aeb0SSepherosa Ziehau 	if (mac_lo == 0 && mac_hi == 0) {
331243c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "Invalid Ethernet address!\n");
331343c2aeb0SSepherosa Ziehau 	} else {
331443c2aeb0SSepherosa Ziehau 		sc->eaddr[0] = (u_char)(mac_hi >> 8);
331543c2aeb0SSepherosa Ziehau 		sc->eaddr[1] = (u_char)(mac_hi >> 0);
331643c2aeb0SSepherosa Ziehau 		sc->eaddr[2] = (u_char)(mac_lo >> 24);
331743c2aeb0SSepherosa Ziehau 		sc->eaddr[3] = (u_char)(mac_lo >> 16);
331843c2aeb0SSepherosa Ziehau 		sc->eaddr[4] = (u_char)(mac_lo >> 8);
331943c2aeb0SSepherosa Ziehau 		sc->eaddr[5] = (u_char)(mac_lo >> 0);
332043c2aeb0SSepherosa Ziehau 	}
332143c2aeb0SSepherosa Ziehau 
332243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "Permanent Ethernet address = %6D\n", sc->eaddr, ":");
332343c2aeb0SSepherosa Ziehau }
332443c2aeb0SSepherosa Ziehau 
332543c2aeb0SSepherosa Ziehau 
332643c2aeb0SSepherosa Ziehau /****************************************************************************/
332743c2aeb0SSepherosa Ziehau /* Program the MAC address.                                                 */
332843c2aeb0SSepherosa Ziehau /*                                                                          */
332943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
333043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
333143c2aeb0SSepherosa Ziehau /****************************************************************************/
333243c2aeb0SSepherosa Ziehau static void
333343c2aeb0SSepherosa Ziehau bce_set_mac_addr(struct bce_softc *sc)
333443c2aeb0SSepherosa Ziehau {
333543c2aeb0SSepherosa Ziehau 	const uint8_t *mac_addr = sc->eaddr;
333643c2aeb0SSepherosa Ziehau 	uint32_t val;
333743c2aeb0SSepherosa Ziehau 
333843c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "Setting Ethernet address = %6D\n",
333943c2aeb0SSepherosa Ziehau 		sc->eaddr, ":");
334043c2aeb0SSepherosa Ziehau 
334143c2aeb0SSepherosa Ziehau 	val = (mac_addr[0] << 8) | mac_addr[1];
334243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_MAC_MATCH0, val);
334343c2aeb0SSepherosa Ziehau 
334443c2aeb0SSepherosa Ziehau 	val = (mac_addr[2] << 24) |
334543c2aeb0SSepherosa Ziehau 	      (mac_addr[3] << 16) |
334643c2aeb0SSepherosa Ziehau 	      (mac_addr[4] << 8) |
334743c2aeb0SSepherosa Ziehau 	      mac_addr[5];
334843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_MAC_MATCH1, val);
334943c2aeb0SSepherosa Ziehau }
335043c2aeb0SSepherosa Ziehau 
335143c2aeb0SSepherosa Ziehau 
335243c2aeb0SSepherosa Ziehau /****************************************************************************/
335343c2aeb0SSepherosa Ziehau /* Stop the controller.                                                     */
335443c2aeb0SSepherosa Ziehau /*                                                                          */
335543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
335643c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
335743c2aeb0SSepherosa Ziehau /****************************************************************************/
335843c2aeb0SSepherosa Ziehau static void
335943c2aeb0SSepherosa Ziehau bce_stop(struct bce_softc *sc)
336043c2aeb0SSepherosa Ziehau {
336143c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
336243c2aeb0SSepherosa Ziehau 	struct mii_data *mii = device_get_softc(sc->bce_miibus);
336343c2aeb0SSepherosa Ziehau 	struct ifmedia_entry *ifm;
336443c2aeb0SSepherosa Ziehau 	int mtmp, itmp;
336543c2aeb0SSepherosa Ziehau 
336643c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
336743c2aeb0SSepherosa Ziehau 
3368d0092544SSepherosa Ziehau 	callout_stop(&sc->bce_tick_callout);
336943c2aeb0SSepherosa Ziehau 
337043c2aeb0SSepherosa Ziehau 	/* Disable the transmit/receive blocks. */
3371d0092544SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS, BCE_MISC_ENABLE_CLR_DEFAULT);
337243c2aeb0SSepherosa Ziehau 	REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS);
337343c2aeb0SSepherosa Ziehau 	DELAY(20);
337443c2aeb0SSepherosa Ziehau 
337543c2aeb0SSepherosa Ziehau 	bce_disable_intr(sc);
337643c2aeb0SSepherosa Ziehau 
337743c2aeb0SSepherosa Ziehau 	/* Free the RX lists. */
337843c2aeb0SSepherosa Ziehau 	bce_free_rx_chain(sc);
337943c2aeb0SSepherosa Ziehau 
338043c2aeb0SSepherosa Ziehau 	/* Free TX buffers. */
338143c2aeb0SSepherosa Ziehau 	bce_free_tx_chain(sc);
338243c2aeb0SSepherosa Ziehau 
338343c2aeb0SSepherosa Ziehau 	/*
338443c2aeb0SSepherosa Ziehau 	 * Isolate/power down the PHY, but leave the media selection
338543c2aeb0SSepherosa Ziehau 	 * unchanged so that things will be put back to normal when
338643c2aeb0SSepherosa Ziehau 	 * we bring the interface back up.
3387db1e7fc4SSepherosa Ziehau 	 *
3388db1e7fc4SSepherosa Ziehau 	 * 'mii' may be NULL if bce_stop() is called by bce_detach().
338943c2aeb0SSepherosa Ziehau 	 */
3390db1e7fc4SSepherosa Ziehau 	if (mii != NULL) {
339143c2aeb0SSepherosa Ziehau 		itmp = ifp->if_flags;
339243c2aeb0SSepherosa Ziehau 		ifp->if_flags |= IFF_UP;
339343c2aeb0SSepherosa Ziehau 		ifm = mii->mii_media.ifm_cur;
339443c2aeb0SSepherosa Ziehau 		mtmp = ifm->ifm_media;
339543c2aeb0SSepherosa Ziehau 		ifm->ifm_media = IFM_ETHER | IFM_NONE;
339643c2aeb0SSepherosa Ziehau 		mii_mediachg(mii);
339743c2aeb0SSepherosa Ziehau 		ifm->ifm_media = mtmp;
339843c2aeb0SSepherosa Ziehau 		ifp->if_flags = itmp;
3399db1e7fc4SSepherosa Ziehau 	}
340043c2aeb0SSepherosa Ziehau 
340143c2aeb0SSepherosa Ziehau 	sc->bce_link = 0;
3402bdeb8fffSSepherosa Ziehau 	sc->bce_coalchg_mask = 0;
340343c2aeb0SSepherosa Ziehau 
340443c2aeb0SSepherosa Ziehau 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
340543c2aeb0SSepherosa Ziehau 	ifp->if_timer = 0;
340643c2aeb0SSepherosa Ziehau }
340743c2aeb0SSepherosa Ziehau 
340843c2aeb0SSepherosa Ziehau 
340943c2aeb0SSepherosa Ziehau static int
341043c2aeb0SSepherosa Ziehau bce_reset(struct bce_softc *sc, uint32_t reset_code)
341143c2aeb0SSepherosa Ziehau {
341243c2aeb0SSepherosa Ziehau 	uint32_t val;
341343c2aeb0SSepherosa Ziehau 	int i, rc = 0;
341443c2aeb0SSepherosa Ziehau 
341543c2aeb0SSepherosa Ziehau 	/* Wait for pending PCI transactions to complete. */
341643c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS,
341743c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
341843c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
341943c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
342043c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
342143c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS);
342243c2aeb0SSepherosa Ziehau 	DELAY(5);
342343c2aeb0SSepherosa Ziehau 
3424d0092544SSepherosa Ziehau 	/* Disable DMA */
3425d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3426d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3427d0092544SSepherosa Ziehau 		val = REG_RD(sc, BCE_MISC_NEW_CORE_CTL);
3428d0092544SSepherosa Ziehau 		val &= ~BCE_MISC_NEW_CORE_CTL_DMA_ENABLE;
3429d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_MISC_NEW_CORE_CTL, val);
3430d0092544SSepherosa Ziehau 	}
3431d0092544SSepherosa Ziehau 
343243c2aeb0SSepherosa Ziehau 	/* Assume bootcode is running. */
343343c2aeb0SSepherosa Ziehau 	sc->bce_fw_timed_out = 0;
343443c2aeb0SSepherosa Ziehau 
343543c2aeb0SSepherosa Ziehau 	/* Give the firmware a chance to prepare for the reset. */
343643c2aeb0SSepherosa Ziehau 	rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT0 | reset_code);
343743c2aeb0SSepherosa Ziehau 	if (rc) {
343843c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
343943c2aeb0SSepherosa Ziehau 			  "Firmware is not ready for reset\n");
344043c2aeb0SSepherosa Ziehau 		return rc;
344143c2aeb0SSepherosa Ziehau 	}
344243c2aeb0SSepherosa Ziehau 
344343c2aeb0SSepherosa Ziehau 	/* Set a firmware reminder that this is a soft reset. */
3444bc30d40dSSepherosa Ziehau 	bce_shmem_wr(sc, BCE_DRV_RESET_SIGNATURE,
344543c2aeb0SSepherosa Ziehau 	    BCE_DRV_RESET_SIGNATURE_MAGIC);
344643c2aeb0SSepherosa Ziehau 
344743c2aeb0SSepherosa Ziehau 	/* Dummy read to force the chip to complete all current transactions. */
344843c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_ID);
344943c2aeb0SSepherosa Ziehau 
345043c2aeb0SSepherosa Ziehau 	/* Chip reset. */
3451d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3452d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3453d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_MISC_COMMAND, BCE_MISC_COMMAND_SW_RESET);
3454d0092544SSepherosa Ziehau 		REG_RD(sc, BCE_MISC_COMMAND);
3455d0092544SSepherosa Ziehau 		DELAY(5);
3456d0092544SSepherosa Ziehau 
3457d0092544SSepherosa Ziehau 		val = BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
3458d0092544SSepherosa Ziehau 		    BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
3459d0092544SSepherosa Ziehau 
3460d0092544SSepherosa Ziehau 		pci_write_config(sc->bce_dev, BCE_PCICFG_MISC_CONFIG, val, 4);
3461d0092544SSepherosa Ziehau 	} else {
346243c2aeb0SSepherosa Ziehau 		val = BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
346343c2aeb0SSepherosa Ziehau 		    BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
346443c2aeb0SSepherosa Ziehau 		    BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
346543c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_PCICFG_MISC_CONFIG, val);
346643c2aeb0SSepherosa Ziehau 
346743c2aeb0SSepherosa Ziehau 		/* Allow up to 30us for reset to complete. */
346843c2aeb0SSepherosa Ziehau 		for (i = 0; i < 10; i++) {
346943c2aeb0SSepherosa Ziehau 			val = REG_RD(sc, BCE_PCICFG_MISC_CONFIG);
347043c2aeb0SSepherosa Ziehau 			if ((val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
3471d0092544SSepherosa Ziehau 			    BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0)
347243c2aeb0SSepherosa Ziehau 				break;
347343c2aeb0SSepherosa Ziehau 			DELAY(10);
347443c2aeb0SSepherosa Ziehau 		}
347543c2aeb0SSepherosa Ziehau 
347643c2aeb0SSepherosa Ziehau 		/* Check that reset completed successfully. */
347743c2aeb0SSepherosa Ziehau 		if (val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
347843c2aeb0SSepherosa Ziehau 		    BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
347943c2aeb0SSepherosa Ziehau 			if_printf(&sc->arpcom.ac_if, "Reset failed!\n");
348043c2aeb0SSepherosa Ziehau 			return EBUSY;
348143c2aeb0SSepherosa Ziehau 		}
3482d0092544SSepherosa Ziehau 	}
348343c2aeb0SSepherosa Ziehau 
348443c2aeb0SSepherosa Ziehau 	/* Make sure byte swapping is properly configured. */
348543c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_PCI_SWAP_DIAG0);
348643c2aeb0SSepherosa Ziehau 	if (val != 0x01020304) {
348743c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "Byte swap is incorrect!\n");
348843c2aeb0SSepherosa Ziehau 		return ENODEV;
348943c2aeb0SSepherosa Ziehau 	}
349043c2aeb0SSepherosa Ziehau 
349143c2aeb0SSepherosa Ziehau 	/* Just completed a reset, assume that firmware is running again. */
349243c2aeb0SSepherosa Ziehau 	sc->bce_fw_timed_out = 0;
349343c2aeb0SSepherosa Ziehau 
349443c2aeb0SSepherosa Ziehau 	/* Wait for the firmware to finish its initialization. */
349543c2aeb0SSepherosa Ziehau 	rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT1 | reset_code);
349643c2aeb0SSepherosa Ziehau 	if (rc) {
349743c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
349843c2aeb0SSepherosa Ziehau 			  "Firmware did not complete initialization!\n");
349943c2aeb0SSepherosa Ziehau 	}
350043c2aeb0SSepherosa Ziehau 	return rc;
350143c2aeb0SSepherosa Ziehau }
350243c2aeb0SSepherosa Ziehau 
350343c2aeb0SSepherosa Ziehau 
350443c2aeb0SSepherosa Ziehau static int
350543c2aeb0SSepherosa Ziehau bce_chipinit(struct bce_softc *sc)
350643c2aeb0SSepherosa Ziehau {
350743c2aeb0SSepherosa Ziehau 	uint32_t val;
350843c2aeb0SSepherosa Ziehau 	int rc = 0;
350943c2aeb0SSepherosa Ziehau 
351043c2aeb0SSepherosa Ziehau 	/* Make sure the interrupt is not active. */
351143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, BCE_PCICFG_INT_ACK_CMD_MASK_INT);
3512d0092544SSepherosa Ziehau 	REG_RD(sc, BCE_PCICFG_INT_ACK_CMD);
351343c2aeb0SSepherosa Ziehau 
351443c2aeb0SSepherosa Ziehau 	/*
351543c2aeb0SSepherosa Ziehau 	 * Initialize DMA byte/word swapping, configure the number of DMA
351643c2aeb0SSepherosa Ziehau 	 * channels and PCI clock compensation delay.
351743c2aeb0SSepherosa Ziehau 	 */
351843c2aeb0SSepherosa Ziehau 	val = BCE_DMA_CONFIG_DATA_BYTE_SWAP |
351943c2aeb0SSepherosa Ziehau 	      BCE_DMA_CONFIG_DATA_WORD_SWAP |
352043c2aeb0SSepherosa Ziehau #if BYTE_ORDER == BIG_ENDIAN
352143c2aeb0SSepherosa Ziehau 	      BCE_DMA_CONFIG_CNTL_BYTE_SWAP |
352243c2aeb0SSepherosa Ziehau #endif
352343c2aeb0SSepherosa Ziehau 	      BCE_DMA_CONFIG_CNTL_WORD_SWAP |
352443c2aeb0SSepherosa Ziehau 	      DMA_READ_CHANS << 12 |
352543c2aeb0SSepherosa Ziehau 	      DMA_WRITE_CHANS << 16;
352643c2aeb0SSepherosa Ziehau 
352743c2aeb0SSepherosa Ziehau 	val |= (0x2 << 20) | BCE_DMA_CONFIG_CNTL_PCI_COMP_DLY;
352843c2aeb0SSepherosa Ziehau 
352943c2aeb0SSepherosa Ziehau 	if ((sc->bce_flags & BCE_PCIX_FLAG) && sc->bus_speed_mhz == 133)
353043c2aeb0SSepherosa Ziehau 		val |= BCE_DMA_CONFIG_PCI_FAST_CLK_CMP;
353143c2aeb0SSepherosa Ziehau 
353243c2aeb0SSepherosa Ziehau 	/*
353343c2aeb0SSepherosa Ziehau 	 * This setting resolves a problem observed on certain Intel PCI
353443c2aeb0SSepherosa Ziehau 	 * chipsets that cannot handle multiple outstanding DMA operations.
353543c2aeb0SSepherosa Ziehau 	 * See errata E9_5706A1_65.
353643c2aeb0SSepherosa Ziehau 	 */
353743c2aeb0SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706 &&
353843c2aeb0SSepherosa Ziehau 	    BCE_CHIP_ID(sc) != BCE_CHIP_ID_5706_A0 &&
353943c2aeb0SSepherosa Ziehau 	    !(sc->bce_flags & BCE_PCIX_FLAG))
354043c2aeb0SSepherosa Ziehau 		val |= BCE_DMA_CONFIG_CNTL_PING_PONG_DMA;
354143c2aeb0SSepherosa Ziehau 
354243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_DMA_CONFIG, val);
354343c2aeb0SSepherosa Ziehau 
354443c2aeb0SSepherosa Ziehau 	/* Enable the RX_V2P and Context state machines before access. */
354543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
354643c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
354743c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
354843c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
354943c2aeb0SSepherosa Ziehau 
355043c2aeb0SSepherosa Ziehau 	/* Initialize context mapping and zero out the quick contexts. */
35513a41a80bSSepherosa Ziehau 	bce_init_ctx(sc);
355243c2aeb0SSepherosa Ziehau 
355343c2aeb0SSepherosa Ziehau 	/* Initialize the on-boards CPUs */
355443c2aeb0SSepherosa Ziehau 	bce_init_cpus(sc);
355543c2aeb0SSepherosa Ziehau 
35565d05a208SSepherosa Ziehau 	/* Enable management frames (NC-SI) to flow to the MCP. */
35575d05a208SSepherosa Ziehau 	if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) {
35585d05a208SSepherosa Ziehau 		val = REG_RD(sc, BCE_RPM_MGMT_PKT_CTRL) |
35595d05a208SSepherosa Ziehau 		    BCE_RPM_MGMT_PKT_CTRL_MGMT_EN;
35605d05a208SSepherosa Ziehau 		REG_WR(sc, BCE_RPM_MGMT_PKT_CTRL, val);
35615d05a208SSepherosa Ziehau 	}
35625d05a208SSepherosa Ziehau 
356343c2aeb0SSepherosa Ziehau 	/* Prepare NVRAM for access. */
356443c2aeb0SSepherosa Ziehau 	rc = bce_init_nvram(sc);
356543c2aeb0SSepherosa Ziehau 	if (rc != 0)
356643c2aeb0SSepherosa Ziehau 		return rc;
356743c2aeb0SSepherosa Ziehau 
356843c2aeb0SSepherosa Ziehau 	/* Set the kernel bypass block size */
356943c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MQ_CONFIG);
357043c2aeb0SSepherosa Ziehau 	val &= ~BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE;
357143c2aeb0SSepherosa Ziehau 	val |= BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
3572d0092544SSepherosa Ziehau 
3573d0092544SSepherosa Ziehau 	/* Enable bins used on the 5709/5716. */
3574d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3575d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3576d0092544SSepherosa Ziehau 		val |= BCE_MQ_CONFIG_BIN_MQ_MODE;
3577d0092544SSepherosa Ziehau 		if (BCE_CHIP_ID(sc) == BCE_CHIP_ID_5709_A1)
3578d0092544SSepherosa Ziehau 			val |= BCE_MQ_CONFIG_HALT_DIS;
3579d0092544SSepherosa Ziehau 	}
3580d0092544SSepherosa Ziehau 
358143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MQ_CONFIG, val);
358243c2aeb0SSepherosa Ziehau 
358343c2aeb0SSepherosa Ziehau 	val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
358443c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MQ_KNL_BYP_WIND_START, val);
358543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MQ_KNL_WIND_END, val);
358643c2aeb0SSepherosa Ziehau 
358743c2aeb0SSepherosa Ziehau 	/* Set the page size and clear the RV2P processor stall bits. */
358843c2aeb0SSepherosa Ziehau 	val = (BCM_PAGE_BITS - 8) << 24;
358943c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_RV2P_CONFIG, val);
359043c2aeb0SSepherosa Ziehau 
359143c2aeb0SSepherosa Ziehau 	/* Configure page size. */
359243c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_TBDR_CONFIG);
359343c2aeb0SSepherosa Ziehau 	val &= ~BCE_TBDR_CONFIG_PAGE_SIZE;
359443c2aeb0SSepherosa Ziehau 	val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
359543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_TBDR_CONFIG, val);
359643c2aeb0SSepherosa Ziehau 
3597d0092544SSepherosa Ziehau 	/* Set the perfect match control register to default. */
3598d0092544SSepherosa Ziehau 	REG_WR_IND(sc, BCE_RXP_PM_CTRL, 0);
3599d0092544SSepherosa Ziehau 
360043c2aeb0SSepherosa Ziehau 	return 0;
360143c2aeb0SSepherosa Ziehau }
360243c2aeb0SSepherosa Ziehau 
360343c2aeb0SSepherosa Ziehau 
360443c2aeb0SSepherosa Ziehau /****************************************************************************/
360543c2aeb0SSepherosa Ziehau /* Initialize the controller in preparation to send/receive traffic.        */
360643c2aeb0SSepherosa Ziehau /*                                                                          */
360743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
360843c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
360943c2aeb0SSepherosa Ziehau /****************************************************************************/
361043c2aeb0SSepherosa Ziehau static int
361143c2aeb0SSepherosa Ziehau bce_blockinit(struct bce_softc *sc)
361243c2aeb0SSepherosa Ziehau {
361343c2aeb0SSepherosa Ziehau 	uint32_t reg, val;
361443c2aeb0SSepherosa Ziehau 	int rc = 0;
361543c2aeb0SSepherosa Ziehau 
361643c2aeb0SSepherosa Ziehau 	/* Load the hardware default MAC address. */
361743c2aeb0SSepherosa Ziehau 	bce_set_mac_addr(sc);
361843c2aeb0SSepherosa Ziehau 
361943c2aeb0SSepherosa Ziehau 	/* Set the Ethernet backoff seed value */
362043c2aeb0SSepherosa Ziehau 	val = sc->eaddr[0] + (sc->eaddr[1] << 8) + (sc->eaddr[2] << 16) +
362143c2aeb0SSepherosa Ziehau 	      sc->eaddr[3] + (sc->eaddr[4] << 8) + (sc->eaddr[5] << 16);
362243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_BACKOFF_SEED, val);
362343c2aeb0SSepherosa Ziehau 
362443c2aeb0SSepherosa Ziehau 	sc->last_status_idx = 0;
362543c2aeb0SSepherosa Ziehau 	sc->rx_mode = BCE_EMAC_RX_MODE_SORT_MODE;
362643c2aeb0SSepherosa Ziehau 
362743c2aeb0SSepherosa Ziehau 	/* Set up link change interrupt generation. */
362843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_ATTENTION_ENA, BCE_EMAC_ATTENTION_ENA_LINK);
362943c2aeb0SSepherosa Ziehau 
363043c2aeb0SSepherosa Ziehau 	/* Program the physical address of the status block. */
363143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATUS_ADDR_L, BCE_ADDR_LO(sc->status_block_paddr));
363243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATUS_ADDR_H, BCE_ADDR_HI(sc->status_block_paddr));
363343c2aeb0SSepherosa Ziehau 
363443c2aeb0SSepherosa Ziehau 	/* Program the physical address of the statistics block. */
363543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATISTICS_ADDR_L,
363643c2aeb0SSepherosa Ziehau 	       BCE_ADDR_LO(sc->stats_block_paddr));
363743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATISTICS_ADDR_H,
363843c2aeb0SSepherosa Ziehau 	       BCE_ADDR_HI(sc->stats_block_paddr));
363943c2aeb0SSepherosa Ziehau 
364043c2aeb0SSepherosa Ziehau 	/* Program various host coalescing parameters. */
364143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
364243c2aeb0SSepherosa Ziehau 	       (sc->bce_tx_quick_cons_trip_int << 16) |
364343c2aeb0SSepherosa Ziehau 	       sc->bce_tx_quick_cons_trip);
364443c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
364543c2aeb0SSepherosa Ziehau 	       (sc->bce_rx_quick_cons_trip_int << 16) |
364643c2aeb0SSepherosa Ziehau 	       sc->bce_rx_quick_cons_trip);
364743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_COMP_PROD_TRIP,
364843c2aeb0SSepherosa Ziehau 	       (sc->bce_comp_prod_trip_int << 16) | sc->bce_comp_prod_trip);
364943c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_TX_TICKS,
365043c2aeb0SSepherosa Ziehau 	       (sc->bce_tx_ticks_int << 16) | sc->bce_tx_ticks);
365143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_RX_TICKS,
365243c2aeb0SSepherosa Ziehau 	       (sc->bce_rx_ticks_int << 16) | sc->bce_rx_ticks);
365343c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_COM_TICKS,
365443c2aeb0SSepherosa Ziehau 	       (sc->bce_com_ticks_int << 16) | sc->bce_com_ticks);
365543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_CMD_TICKS,
365643c2aeb0SSepherosa Ziehau 	       (sc->bce_cmd_ticks_int << 16) | sc->bce_cmd_ticks);
365743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATS_TICKS, (sc->bce_stats_ticks & 0xffff00));
365843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STAT_COLLECT_TICKS, 0xbb8);	/* 3ms */
365943c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_CONFIG,
366043c2aeb0SSepherosa Ziehau 	       BCE_HC_CONFIG_TX_TMR_MODE |
366143c2aeb0SSepherosa Ziehau 	       BCE_HC_CONFIG_COLLECT_STATS);
366243c2aeb0SSepherosa Ziehau 
366343c2aeb0SSepherosa Ziehau 	/* Clear the internal statistics counters. */
366443c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW);
366543c2aeb0SSepherosa Ziehau 
366643c2aeb0SSepherosa Ziehau 	/* Verify that bootcode is running. */
3667bc30d40dSSepherosa Ziehau 	reg = bce_shmem_rd(sc, BCE_DEV_INFO_SIGNATURE);
366843c2aeb0SSepherosa Ziehau 
366943c2aeb0SSepherosa Ziehau 	DBRUNIF(DB_RANDOMTRUE(bce_debug_bootcode_running_failure),
367043c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
367143c2aeb0SSepherosa Ziehau 			  "%s(%d): Simulating bootcode failure.\n",
367243c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__);
367343c2aeb0SSepherosa Ziehau 		reg = 0);
367443c2aeb0SSepherosa Ziehau 
367543c2aeb0SSepherosa Ziehau 	if ((reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
367643c2aeb0SSepherosa Ziehau 	    BCE_DEV_INFO_SIGNATURE_MAGIC) {
367743c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
367843c2aeb0SSepherosa Ziehau 			  "Bootcode not running! Found: 0x%08X, "
367943c2aeb0SSepherosa Ziehau 			  "Expected: 08%08X\n",
368043c2aeb0SSepherosa Ziehau 			  reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK,
368143c2aeb0SSepherosa Ziehau 			  BCE_DEV_INFO_SIGNATURE_MAGIC);
368243c2aeb0SSepherosa Ziehau 		return ENODEV;
368343c2aeb0SSepherosa Ziehau 	}
368443c2aeb0SSepherosa Ziehau 
3685d0092544SSepherosa Ziehau 	/* Enable DMA */
3686d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3687d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3688d0092544SSepherosa Ziehau 		val = REG_RD(sc, BCE_MISC_NEW_CORE_CTL);
3689d0092544SSepherosa Ziehau 		val |= BCE_MISC_NEW_CORE_CTL_DMA_ENABLE;
3690d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_MISC_NEW_CORE_CTL, val);
369143c2aeb0SSepherosa Ziehau 	}
369243c2aeb0SSepherosa Ziehau 
369343c2aeb0SSepherosa Ziehau 	/* Allow bootcode to apply any additional fixes before enabling MAC. */
369443c2aeb0SSepherosa Ziehau 	rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT2 | BCE_DRV_MSG_CODE_RESET);
369543c2aeb0SSepherosa Ziehau 
369643c2aeb0SSepherosa Ziehau 	/* Enable link state change interrupt generation. */
369743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
369843c2aeb0SSepherosa Ziehau 
36995d05a208SSepherosa Ziehau 	/* Enable the RXP. */
37005d05a208SSepherosa Ziehau 	bce_start_rxp_cpu(sc);
37015d05a208SSepherosa Ziehau 
37025d05a208SSepherosa Ziehau 	/* Disable management frames (NC-SI) from flowing to the MCP. */
37035d05a208SSepherosa Ziehau 	if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) {
37045d05a208SSepherosa Ziehau 		val = REG_RD(sc, BCE_RPM_MGMT_PKT_CTRL) &
37055d05a208SSepherosa Ziehau 		    ~BCE_RPM_MGMT_PKT_CTRL_MGMT_EN;
37065d05a208SSepherosa Ziehau 		REG_WR(sc, BCE_RPM_MGMT_PKT_CTRL, val);
37075d05a208SSepherosa Ziehau 	}
37085d05a208SSepherosa Ziehau 
370943c2aeb0SSepherosa Ziehau 	/* Enable all remaining blocks in the MAC. */
3710d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3711d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3712d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
3713d0092544SSepherosa Ziehau 		    BCE_MISC_ENABLE_DEFAULT_XI);
3714d0092544SSepherosa Ziehau 	} else {
3715d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, BCE_MISC_ENABLE_DEFAULT);
3716d0092544SSepherosa Ziehau 	}
371743c2aeb0SSepherosa Ziehau 	REG_RD(sc, BCE_MISC_ENABLE_SET_BITS);
371843c2aeb0SSepherosa Ziehau 	DELAY(20);
371943c2aeb0SSepherosa Ziehau 
3720d0092544SSepherosa Ziehau 	/* Save the current host coalescing block settings. */
3721d0092544SSepherosa Ziehau 	sc->hc_command = REG_RD(sc, BCE_HC_COMMAND);
3722d0092544SSepherosa Ziehau 
372343c2aeb0SSepherosa Ziehau 	return 0;
372443c2aeb0SSepherosa Ziehau }
372543c2aeb0SSepherosa Ziehau 
372643c2aeb0SSepherosa Ziehau 
372743c2aeb0SSepherosa Ziehau /****************************************************************************/
372843c2aeb0SSepherosa Ziehau /* Encapsulate an mbuf cluster into the rx_bd chain.                        */
372943c2aeb0SSepherosa Ziehau /*                                                                          */
373043c2aeb0SSepherosa Ziehau /* The NetXtreme II can support Jumbo frames by using multiple rx_bd's.     */
373143c2aeb0SSepherosa Ziehau /* This routine will map an mbuf cluster into 1 or more rx_bd's as          */
373243c2aeb0SSepherosa Ziehau /* necessary.                                                               */
373343c2aeb0SSepherosa Ziehau /*                                                                          */
373443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
373543c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
373643c2aeb0SSepherosa Ziehau /****************************************************************************/
373743c2aeb0SSepherosa Ziehau static int
3738c36fd9eeSSepherosa Ziehau bce_newbuf_std(struct bce_softc *sc, uint16_t *prod, uint16_t *chain_prod,
3739c36fd9eeSSepherosa Ziehau 	       uint32_t *prod_bseq, int init)
374043c2aeb0SSepherosa Ziehau {
374143c2aeb0SSepherosa Ziehau 	bus_dmamap_t map;
374243c2aeb0SSepherosa Ziehau 	bus_dma_segment_t seg;
374343c2aeb0SSepherosa Ziehau 	struct mbuf *m_new;
3744c36fd9eeSSepherosa Ziehau 	int error, nseg;
374543c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
374643c2aeb0SSepherosa Ziehau 	uint16_t debug_chain_prod = *chain_prod;
374743c2aeb0SSepherosa Ziehau #endif
374843c2aeb0SSepherosa Ziehau 
374943c2aeb0SSepherosa Ziehau 	/* Make sure the inputs are valid. */
375043c2aeb0SSepherosa Ziehau 	DBRUNIF((*chain_prod > MAX_RX_BD),
375143c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "%s(%d): "
375243c2aeb0SSepherosa Ziehau 			  "RX producer out of range: 0x%04X > 0x%04X\n",
375343c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__,
375443c2aeb0SSepherosa Ziehau 			  *chain_prod, (uint16_t)MAX_RX_BD));
375543c2aeb0SSepherosa Ziehau 
375643c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RECV, "%s(enter): prod = 0x%04X, chain_prod = 0x%04X, "
375743c2aeb0SSepherosa Ziehau 		"prod_bseq = 0x%08X\n", __func__, *prod, *chain_prod, *prod_bseq);
375843c2aeb0SSepherosa Ziehau 
375943c2aeb0SSepherosa Ziehau 	DBRUNIF(DB_RANDOMTRUE(bce_debug_mbuf_allocation_failure),
376043c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "%s(%d): "
376143c2aeb0SSepherosa Ziehau 			  "Simulating mbuf allocation failure.\n",
376243c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__);
376343c2aeb0SSepherosa Ziehau 		sc->mbuf_alloc_failed++;
376443c2aeb0SSepherosa Ziehau 		return ENOBUFS);
376543c2aeb0SSepherosa Ziehau 
376643c2aeb0SSepherosa Ziehau 	/* This is a new mbuf allocation. */
3767c36fd9eeSSepherosa Ziehau 	m_new = m_getcl(init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR);
376843c2aeb0SSepherosa Ziehau 	if (m_new == NULL)
376943c2aeb0SSepherosa Ziehau 		return ENOBUFS;
377043c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->rx_mbuf_alloc++);
3771c36fd9eeSSepherosa Ziehau 
377243c2aeb0SSepherosa Ziehau 	m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
377343c2aeb0SSepherosa Ziehau 
377443c2aeb0SSepherosa Ziehau 	/* Map the mbuf cluster into device memory. */
3775c36fd9eeSSepherosa Ziehau 	error = bus_dmamap_load_mbuf_segment(sc->rx_mbuf_tag,
3776c36fd9eeSSepherosa Ziehau 			sc->rx_mbuf_tmpmap, m_new, &seg, 1, &nseg,
3777c36fd9eeSSepherosa Ziehau 			BUS_DMA_NOWAIT);
3778c36fd9eeSSepherosa Ziehau 	if (error) {
3779c36fd9eeSSepherosa Ziehau 		m_freem(m_new);
3780c36fd9eeSSepherosa Ziehau 		if (init) {
378143c2aeb0SSepherosa Ziehau 			if_printf(&sc->arpcom.ac_if,
378243c2aeb0SSepherosa Ziehau 				  "Error mapping mbuf into RX chain!\n");
378343c2aeb0SSepherosa Ziehau 		}
3784c36fd9eeSSepherosa Ziehau 		DBRUNIF(1, sc->rx_mbuf_alloc--);
3785c36fd9eeSSepherosa Ziehau 		return error;
3786c36fd9eeSSepherosa Ziehau 	}
3787c36fd9eeSSepherosa Ziehau 
3788c36fd9eeSSepherosa Ziehau 	if (sc->rx_mbuf_ptr[*chain_prod] != NULL) {
3789c36fd9eeSSepherosa Ziehau 		bus_dmamap_unload(sc->rx_mbuf_tag,
3790c36fd9eeSSepherosa Ziehau 				  sc->rx_mbuf_map[*chain_prod]);
3791c36fd9eeSSepherosa Ziehau 	}
3792c36fd9eeSSepherosa Ziehau 
3793c36fd9eeSSepherosa Ziehau 	map = sc->rx_mbuf_map[*chain_prod];
3794c36fd9eeSSepherosa Ziehau 	sc->rx_mbuf_map[*chain_prod] = sc->rx_mbuf_tmpmap;
3795c36fd9eeSSepherosa Ziehau 	sc->rx_mbuf_tmpmap = map;
379643c2aeb0SSepherosa Ziehau 
379743c2aeb0SSepherosa Ziehau 	/* Watch for overflow. */
379843c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd > USABLE_RX_BD),
379943c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "%s(%d): "
380043c2aeb0SSepherosa Ziehau 			  "Too many free rx_bd (0x%04X > 0x%04X)!\n",
380143c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__, sc->free_rx_bd,
380243c2aeb0SSepherosa Ziehau 			  (uint16_t)USABLE_RX_BD));
380343c2aeb0SSepherosa Ziehau 
380443c2aeb0SSepherosa Ziehau 	/* Update some debug statistic counters */
380543c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
380643c2aeb0SSepherosa Ziehau 		sc->rx_low_watermark = sc->free_rx_bd);
380743c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd == 0), sc->rx_empty_count++);
380843c2aeb0SSepherosa Ziehau 
380943c2aeb0SSepherosa Ziehau 	/* Save the mbuf and update our counter. */
381043c2aeb0SSepherosa Ziehau 	sc->rx_mbuf_ptr[*chain_prod] = m_new;
3811314a2fccSSepherosa Ziehau 	sc->rx_mbuf_paddr[*chain_prod] = seg.ds_addr;
381243c2aeb0SSepherosa Ziehau 	sc->free_rx_bd--;
381343c2aeb0SSepherosa Ziehau 
3814314a2fccSSepherosa Ziehau 	bce_setup_rxdesc_std(sc, *chain_prod, prod_bseq);
3815314a2fccSSepherosa Ziehau 
381643c2aeb0SSepherosa Ziehau 	DBRUN(BCE_VERBOSE_RECV,
381743c2aeb0SSepherosa Ziehau 	      bce_dump_rx_mbuf_chain(sc, debug_chain_prod, 1));
381843c2aeb0SSepherosa Ziehau 
381943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RECV, "%s(exit): prod = 0x%04X, chain_prod = 0x%04X, "
382043c2aeb0SSepherosa Ziehau 		"prod_bseq = 0x%08X\n", __func__, *prod, *chain_prod, *prod_bseq);
382143c2aeb0SSepherosa Ziehau 
382243c2aeb0SSepherosa Ziehau 	return 0;
382343c2aeb0SSepherosa Ziehau }
382443c2aeb0SSepherosa Ziehau 
382543c2aeb0SSepherosa Ziehau 
3826314a2fccSSepherosa Ziehau static void
3827314a2fccSSepherosa Ziehau bce_setup_rxdesc_std(struct bce_softc *sc, uint16_t chain_prod, uint32_t *prod_bseq)
3828314a2fccSSepherosa Ziehau {
3829314a2fccSSepherosa Ziehau 	struct rx_bd *rxbd;
3830314a2fccSSepherosa Ziehau 	bus_addr_t paddr;
3831314a2fccSSepherosa Ziehau 	int len;
3832314a2fccSSepherosa Ziehau 
3833314a2fccSSepherosa Ziehau 	paddr = sc->rx_mbuf_paddr[chain_prod];
3834314a2fccSSepherosa Ziehau 	len = sc->rx_mbuf_ptr[chain_prod]->m_len;
3835314a2fccSSepherosa Ziehau 
3836314a2fccSSepherosa Ziehau 	/* Setup the rx_bd for the first segment. */
3837314a2fccSSepherosa Ziehau 	rxbd = &sc->rx_bd_chain[RX_PAGE(chain_prod)][RX_IDX(chain_prod)];
3838314a2fccSSepherosa Ziehau 
3839314a2fccSSepherosa Ziehau 	rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(paddr));
3840314a2fccSSepherosa Ziehau 	rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(paddr));
3841314a2fccSSepherosa Ziehau 	rxbd->rx_bd_len = htole32(len);
3842314a2fccSSepherosa Ziehau 	rxbd->rx_bd_flags = htole32(RX_BD_FLAGS_START);
3843314a2fccSSepherosa Ziehau 	*prod_bseq += len;
3844314a2fccSSepherosa Ziehau 
3845314a2fccSSepherosa Ziehau 	rxbd->rx_bd_flags |= htole32(RX_BD_FLAGS_END);
3846314a2fccSSepherosa Ziehau }
3847314a2fccSSepherosa Ziehau 
3848314a2fccSSepherosa Ziehau 
384943c2aeb0SSepherosa Ziehau /****************************************************************************/
3850d0092544SSepherosa Ziehau /* Initialize the TX context memory.                                        */
3851d0092544SSepherosa Ziehau /*                                                                          */
3852d0092544SSepherosa Ziehau /* Returns:                                                                 */
3853d0092544SSepherosa Ziehau /*   Nothing                                                                */
3854d0092544SSepherosa Ziehau /****************************************************************************/
3855d0092544SSepherosa Ziehau static void
3856d0092544SSepherosa Ziehau bce_init_tx_context(struct bce_softc *sc)
3857d0092544SSepherosa Ziehau {
3858d0092544SSepherosa Ziehau 	uint32_t val;
3859d0092544SSepherosa Ziehau 
3860d0092544SSepherosa Ziehau 	/* Initialize the context ID for an L2 TX chain. */
3861d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
3862d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
3863d0092544SSepherosa Ziehau 		/* Set the CID type to support an L2 connection. */
3864d0092544SSepherosa Ziehau 		val = BCE_L2CTX_TX_TYPE_TYPE_L2 | BCE_L2CTX_TX_TYPE_SIZE_L2;
3865d0092544SSepherosa Ziehau 		CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_TYPE_XI, val);
3866d0092544SSepherosa Ziehau 		val = BCE_L2CTX_TX_CMD_TYPE_TYPE_L2 | (8 << 16);
3867d0092544SSepherosa Ziehau 		CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_CMD_TYPE_XI, val);
3868d0092544SSepherosa Ziehau 
3869d0092544SSepherosa Ziehau 		/* Point the hardware to the first page in the chain. */
3870d0092544SSepherosa Ziehau 		val = BCE_ADDR_HI(sc->tx_bd_chain_paddr[0]);
3871d0092544SSepherosa Ziehau 		CTX_WR(sc, GET_CID_ADDR(TX_CID),
3872d0092544SSepherosa Ziehau 		    BCE_L2CTX_TX_TBDR_BHADDR_HI_XI, val);
3873d0092544SSepherosa Ziehau 		val = BCE_ADDR_LO(sc->tx_bd_chain_paddr[0]);
3874d0092544SSepherosa Ziehau 		CTX_WR(sc, GET_CID_ADDR(TX_CID),
3875d0092544SSepherosa Ziehau 		    BCE_L2CTX_TX_TBDR_BHADDR_LO_XI, val);
3876d0092544SSepherosa Ziehau 	} else {
3877d0092544SSepherosa Ziehau 		/* Set the CID type to support an L2 connection. */
3878d0092544SSepherosa Ziehau 		val = BCE_L2CTX_TX_TYPE_TYPE_L2 | BCE_L2CTX_TX_TYPE_SIZE_L2;
3879d0092544SSepherosa Ziehau 		CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_TYPE, val);
3880d0092544SSepherosa Ziehau 		val = BCE_L2CTX_TX_CMD_TYPE_TYPE_L2 | (8 << 16);
3881d0092544SSepherosa Ziehau 		CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_CMD_TYPE, val);
3882d0092544SSepherosa Ziehau 
3883d0092544SSepherosa Ziehau 		/* Point the hardware to the first page in the chain. */
3884d0092544SSepherosa Ziehau 		val = BCE_ADDR_HI(sc->tx_bd_chain_paddr[0]);
3885d0092544SSepherosa Ziehau 		CTX_WR(sc, GET_CID_ADDR(TX_CID),
3886d0092544SSepherosa Ziehau 		    BCE_L2CTX_TX_TBDR_BHADDR_HI, val);
3887d0092544SSepherosa Ziehau 		val = BCE_ADDR_LO(sc->tx_bd_chain_paddr[0]);
3888d0092544SSepherosa Ziehau 		CTX_WR(sc, GET_CID_ADDR(TX_CID),
3889d0092544SSepherosa Ziehau 		    BCE_L2CTX_TX_TBDR_BHADDR_LO, val);
3890d0092544SSepherosa Ziehau 	}
3891d0092544SSepherosa Ziehau }
3892d0092544SSepherosa Ziehau 
3893d0092544SSepherosa Ziehau 
3894d0092544SSepherosa Ziehau /****************************************************************************/
389543c2aeb0SSepherosa Ziehau /* Allocate memory and initialize the TX data structures.                   */
389643c2aeb0SSepherosa Ziehau /*                                                                          */
389743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
389843c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
389943c2aeb0SSepherosa Ziehau /****************************************************************************/
390043c2aeb0SSepherosa Ziehau static int
390143c2aeb0SSepherosa Ziehau bce_init_tx_chain(struct bce_softc *sc)
390243c2aeb0SSepherosa Ziehau {
390343c2aeb0SSepherosa Ziehau 	struct tx_bd *txbd;
390443c2aeb0SSepherosa Ziehau 	int i, rc = 0;
390543c2aeb0SSepherosa Ziehau 
390643c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
390743c2aeb0SSepherosa Ziehau 
390843c2aeb0SSepherosa Ziehau 	/* Set the initial TX producer/consumer indices. */
390943c2aeb0SSepherosa Ziehau 	sc->tx_prod = 0;
391043c2aeb0SSepherosa Ziehau 	sc->tx_cons = 0;
391143c2aeb0SSepherosa Ziehau 	sc->tx_prod_bseq   = 0;
391243c2aeb0SSepherosa Ziehau 	sc->used_tx_bd = 0;
391343c2aeb0SSepherosa Ziehau 	sc->max_tx_bd = USABLE_TX_BD;
391443c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->tx_hi_watermark = USABLE_TX_BD);
391543c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->tx_full_count = 0);
391643c2aeb0SSepherosa Ziehau 
391743c2aeb0SSepherosa Ziehau 	/*
391843c2aeb0SSepherosa Ziehau 	 * The NetXtreme II supports a linked-list structre called
391943c2aeb0SSepherosa Ziehau 	 * a Buffer Descriptor Chain (or BD chain).  A BD chain
392043c2aeb0SSepherosa Ziehau 	 * consists of a series of 1 or more chain pages, each of which
392143c2aeb0SSepherosa Ziehau 	 * consists of a fixed number of BD entries.
392243c2aeb0SSepherosa Ziehau 	 * The last BD entry on each page is a pointer to the next page
392343c2aeb0SSepherosa Ziehau 	 * in the chain, and the last pointer in the BD chain
392443c2aeb0SSepherosa Ziehau 	 * points back to the beginning of the chain.
392543c2aeb0SSepherosa Ziehau 	 */
392643c2aeb0SSepherosa Ziehau 
392743c2aeb0SSepherosa Ziehau 	/* Set the TX next pointer chain entries. */
392843c2aeb0SSepherosa Ziehau 	for (i = 0; i < TX_PAGES; i++) {
392943c2aeb0SSepherosa Ziehau 		int j;
393043c2aeb0SSepherosa Ziehau 
393143c2aeb0SSepherosa Ziehau 		txbd = &sc->tx_bd_chain[i][USABLE_TX_BD_PER_PAGE];
393243c2aeb0SSepherosa Ziehau 
393343c2aeb0SSepherosa Ziehau 		/* Check if we've reached the last page. */
393443c2aeb0SSepherosa Ziehau 		if (i == (TX_PAGES - 1))
393543c2aeb0SSepherosa Ziehau 			j = 0;
393643c2aeb0SSepherosa Ziehau 		else
393743c2aeb0SSepherosa Ziehau 			j = i + 1;
393843c2aeb0SSepherosa Ziehau 
393943c2aeb0SSepherosa Ziehau 		txbd->tx_bd_haddr_hi =
394043c2aeb0SSepherosa Ziehau 			htole32(BCE_ADDR_HI(sc->tx_bd_chain_paddr[j]));
394143c2aeb0SSepherosa Ziehau 		txbd->tx_bd_haddr_lo =
394243c2aeb0SSepherosa Ziehau 			htole32(BCE_ADDR_LO(sc->tx_bd_chain_paddr[j]));
394343c2aeb0SSepherosa Ziehau 	}
3944d0092544SSepherosa Ziehau 	bce_init_tx_context(sc);
394543c2aeb0SSepherosa Ziehau 
394643c2aeb0SSepherosa Ziehau 	return(rc);
394743c2aeb0SSepherosa Ziehau }
394843c2aeb0SSepherosa Ziehau 
394943c2aeb0SSepherosa Ziehau 
395043c2aeb0SSepherosa Ziehau /****************************************************************************/
395143c2aeb0SSepherosa Ziehau /* Free memory and clear the TX data structures.                            */
395243c2aeb0SSepherosa Ziehau /*                                                                          */
395343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
395443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
395543c2aeb0SSepherosa Ziehau /****************************************************************************/
395643c2aeb0SSepherosa Ziehau static void
395743c2aeb0SSepherosa Ziehau bce_free_tx_chain(struct bce_softc *sc)
395843c2aeb0SSepherosa Ziehau {
395943c2aeb0SSepherosa Ziehau 	int i;
396043c2aeb0SSepherosa Ziehau 
396143c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
396243c2aeb0SSepherosa Ziehau 
396343c2aeb0SSepherosa Ziehau 	/* Unmap, unload, and free any mbufs still in the TX mbuf chain. */
396443c2aeb0SSepherosa Ziehau 	for (i = 0; i < TOTAL_TX_BD; i++) {
396543c2aeb0SSepherosa Ziehau 		if (sc->tx_mbuf_ptr[i] != NULL) {
396643c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->tx_mbuf_tag, sc->tx_mbuf_map[i]);
396743c2aeb0SSepherosa Ziehau 			m_freem(sc->tx_mbuf_ptr[i]);
396843c2aeb0SSepherosa Ziehau 			sc->tx_mbuf_ptr[i] = NULL;
396943c2aeb0SSepherosa Ziehau 			DBRUNIF(1, sc->tx_mbuf_alloc--);
397043c2aeb0SSepherosa Ziehau 		}
397143c2aeb0SSepherosa Ziehau 	}
397243c2aeb0SSepherosa Ziehau 
397343c2aeb0SSepherosa Ziehau 	/* Clear each TX chain page. */
397443c2aeb0SSepherosa Ziehau 	for (i = 0; i < TX_PAGES; i++)
397543c2aeb0SSepherosa Ziehau 		bzero(sc->tx_bd_chain[i], BCE_TX_CHAIN_PAGE_SZ);
397624603545SSepherosa Ziehau 	sc->used_tx_bd = 0;
397743c2aeb0SSepherosa Ziehau 
397843c2aeb0SSepherosa Ziehau 	/* Check if we lost any mbufs in the process. */
397943c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->tx_mbuf_alloc),
398043c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
398143c2aeb0SSepherosa Ziehau 			  "%s(%d): Memory leak! "
398243c2aeb0SSepherosa Ziehau 			  "Lost %d mbufs from tx chain!\n",
398343c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__, sc->tx_mbuf_alloc));
398443c2aeb0SSepherosa Ziehau 
398543c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __func__);
398643c2aeb0SSepherosa Ziehau }
398743c2aeb0SSepherosa Ziehau 
398843c2aeb0SSepherosa Ziehau 
398943c2aeb0SSepherosa Ziehau /****************************************************************************/
3990d0092544SSepherosa Ziehau /* Initialize the RX context memory.                                        */
3991d0092544SSepherosa Ziehau /*                                                                          */
3992d0092544SSepherosa Ziehau /* Returns:                                                                 */
3993d0092544SSepherosa Ziehau /*   Nothing                                                                */
3994d0092544SSepherosa Ziehau /****************************************************************************/
3995d0092544SSepherosa Ziehau static void
3996d0092544SSepherosa Ziehau bce_init_rx_context(struct bce_softc *sc)
3997d0092544SSepherosa Ziehau {
3998d0092544SSepherosa Ziehau 	uint32_t val;
3999d0092544SSepherosa Ziehau 
4000d0092544SSepherosa Ziehau 	/* Initialize the context ID for an L2 RX chain. */
4001d0092544SSepherosa Ziehau 	val = BCE_L2CTX_RX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE |
4002d0092544SSepherosa Ziehau 	    BCE_L2CTX_RX_CTX_TYPE_SIZE_L2 | (0x02 << 8);
4003d0092544SSepherosa Ziehau 
4004d0092544SSepherosa Ziehau 	/*
4005d0092544SSepherosa Ziehau 	 * Set the level for generating pause frames
4006d0092544SSepherosa Ziehau 	 * when the number of available rx_bd's gets
4007d0092544SSepherosa Ziehau 	 * too low (the low watermark) and the level
4008d0092544SSepherosa Ziehau 	 * when pause frames can be stopped (the high
4009d0092544SSepherosa Ziehau 	 * watermark).
4010d0092544SSepherosa Ziehau 	 */
4011d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
4012d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
4013d0092544SSepherosa Ziehau 		uint32_t lo_water, hi_water;
4014d0092544SSepherosa Ziehau 
4015d0092544SSepherosa Ziehau 		lo_water = BCE_L2CTX_RX_LO_WATER_MARK_DEFAULT;
4016d0092544SSepherosa Ziehau 		hi_water = USABLE_RX_BD / 4;
4017d0092544SSepherosa Ziehau 
4018d0092544SSepherosa Ziehau 		lo_water /= BCE_L2CTX_RX_LO_WATER_MARK_SCALE;
4019d0092544SSepherosa Ziehau 		hi_water /= BCE_L2CTX_RX_HI_WATER_MARK_SCALE;
4020d0092544SSepherosa Ziehau 
4021d0092544SSepherosa Ziehau 		if (hi_water > 0xf)
4022d0092544SSepherosa Ziehau 			hi_water = 0xf;
4023d0092544SSepherosa Ziehau 		else if (hi_water == 0)
4024d0092544SSepherosa Ziehau 			lo_water = 0;
4025d0092544SSepherosa Ziehau 		val |= lo_water |
4026d0092544SSepherosa Ziehau 		    (hi_water << BCE_L2CTX_RX_HI_WATER_MARK_SHIFT);
4027d0092544SSepherosa Ziehau 	}
4028d0092544SSepherosa Ziehau 
4029d0092544SSepherosa Ziehau  	CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_CTX_TYPE, val);
4030d0092544SSepherosa Ziehau 
4031d0092544SSepherosa Ziehau 	/* Setup the MQ BIN mapping for l2_ctx_host_bseq. */
4032d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
4033d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
4034d0092544SSepherosa Ziehau 		val = REG_RD(sc, BCE_MQ_MAP_L2_5);
4035d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_MQ_MAP_L2_5, val | BCE_MQ_MAP_L2_5_ARM);
4036d0092544SSepherosa Ziehau 	}
4037d0092544SSepherosa Ziehau 
4038d0092544SSepherosa Ziehau 	/* Point the hardware to the first page in the chain. */
4039d0092544SSepherosa Ziehau 	val = BCE_ADDR_HI(sc->rx_bd_chain_paddr[0]);
4040d0092544SSepherosa Ziehau 	CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_NX_BDHADDR_HI, val);
4041d0092544SSepherosa Ziehau 	val = BCE_ADDR_LO(sc->rx_bd_chain_paddr[0]);
4042d0092544SSepherosa Ziehau 	CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_NX_BDHADDR_LO, val);
4043d0092544SSepherosa Ziehau }
4044d0092544SSepherosa Ziehau 
4045d0092544SSepherosa Ziehau 
4046d0092544SSepherosa Ziehau /****************************************************************************/
404743c2aeb0SSepherosa Ziehau /* Allocate memory and initialize the RX data structures.                   */
404843c2aeb0SSepherosa Ziehau /*                                                                          */
404943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
405043c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
405143c2aeb0SSepherosa Ziehau /****************************************************************************/
405243c2aeb0SSepherosa Ziehau static int
405343c2aeb0SSepherosa Ziehau bce_init_rx_chain(struct bce_softc *sc)
405443c2aeb0SSepherosa Ziehau {
405543c2aeb0SSepherosa Ziehau 	struct rx_bd *rxbd;
405643c2aeb0SSepherosa Ziehau 	int i, rc = 0;
405743c2aeb0SSepherosa Ziehau 	uint16_t prod, chain_prod;
4058d0092544SSepherosa Ziehau 	uint32_t prod_bseq;
405943c2aeb0SSepherosa Ziehau 
406043c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
406143c2aeb0SSepherosa Ziehau 
406243c2aeb0SSepherosa Ziehau 	/* Initialize the RX producer and consumer indices. */
406343c2aeb0SSepherosa Ziehau 	sc->rx_prod = 0;
406443c2aeb0SSepherosa Ziehau 	sc->rx_cons = 0;
406543c2aeb0SSepherosa Ziehau 	sc->rx_prod_bseq = 0;
406643c2aeb0SSepherosa Ziehau 	sc->free_rx_bd = USABLE_RX_BD;
406743c2aeb0SSepherosa Ziehau 	sc->max_rx_bd = USABLE_RX_BD;
406843c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->rx_low_watermark = USABLE_RX_BD);
406943c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->rx_empty_count = 0);
407043c2aeb0SSepherosa Ziehau 
407143c2aeb0SSepherosa Ziehau 	/* Initialize the RX next pointer chain entries. */
407243c2aeb0SSepherosa Ziehau 	for (i = 0; i < RX_PAGES; i++) {
407343c2aeb0SSepherosa Ziehau 		int j;
407443c2aeb0SSepherosa Ziehau 
407543c2aeb0SSepherosa Ziehau 		rxbd = &sc->rx_bd_chain[i][USABLE_RX_BD_PER_PAGE];
407643c2aeb0SSepherosa Ziehau 
407743c2aeb0SSepherosa Ziehau 		/* Check if we've reached the last page. */
407843c2aeb0SSepherosa Ziehau 		if (i == (RX_PAGES - 1))
407943c2aeb0SSepherosa Ziehau 			j = 0;
408043c2aeb0SSepherosa Ziehau 		else
408143c2aeb0SSepherosa Ziehau 			j = i + 1;
408243c2aeb0SSepherosa Ziehau 
408343c2aeb0SSepherosa Ziehau 		/* Setup the chain page pointers. */
408443c2aeb0SSepherosa Ziehau 		rxbd->rx_bd_haddr_hi =
408543c2aeb0SSepherosa Ziehau 			htole32(BCE_ADDR_HI(sc->rx_bd_chain_paddr[j]));
408643c2aeb0SSepherosa Ziehau 		rxbd->rx_bd_haddr_lo =
408743c2aeb0SSepherosa Ziehau 			htole32(BCE_ADDR_LO(sc->rx_bd_chain_paddr[j]));
408843c2aeb0SSepherosa Ziehau 	}
408943c2aeb0SSepherosa Ziehau 
409043c2aeb0SSepherosa Ziehau 	/* Allocate mbuf clusters for the rx_bd chain. */
409143c2aeb0SSepherosa Ziehau 	prod = prod_bseq = 0;
409243c2aeb0SSepherosa Ziehau 	while (prod < TOTAL_RX_BD) {
409343c2aeb0SSepherosa Ziehau 		chain_prod = RX_CHAIN_IDX(prod);
4094c36fd9eeSSepherosa Ziehau 		if (bce_newbuf_std(sc, &prod, &chain_prod, &prod_bseq, 1)) {
409543c2aeb0SSepherosa Ziehau 			if_printf(&sc->arpcom.ac_if,
409643c2aeb0SSepherosa Ziehau 				  "Error filling RX chain: rx_bd[0x%04X]!\n",
409743c2aeb0SSepherosa Ziehau 				  chain_prod);
409843c2aeb0SSepherosa Ziehau 			rc = ENOBUFS;
409943c2aeb0SSepherosa Ziehau 			break;
410043c2aeb0SSepherosa Ziehau 		}
410143c2aeb0SSepherosa Ziehau 		prod = NEXT_RX_BD(prod);
410243c2aeb0SSepherosa Ziehau 	}
410343c2aeb0SSepherosa Ziehau 
410443c2aeb0SSepherosa Ziehau 	/* Save the RX chain producer index. */
410543c2aeb0SSepherosa Ziehau 	sc->rx_prod = prod;
410643c2aeb0SSepherosa Ziehau 	sc->rx_prod_bseq = prod_bseq;
410743c2aeb0SSepherosa Ziehau 
410843c2aeb0SSepherosa Ziehau 	/* Tell the chip about the waiting rx_bd's. */
4109d0092544SSepherosa Ziehau 	REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BDIDX,
4110d0092544SSepherosa Ziehau 	    sc->rx_prod);
4111d0092544SSepherosa Ziehau 	REG_WR(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BSEQ,
4112d0092544SSepherosa Ziehau 	    sc->rx_prod_bseq);
411343c2aeb0SSepherosa Ziehau 
4114d0092544SSepherosa Ziehau 	bce_init_rx_context(sc);
411543c2aeb0SSepherosa Ziehau 
411643c2aeb0SSepherosa Ziehau 	return(rc);
411743c2aeb0SSepherosa Ziehau }
411843c2aeb0SSepherosa Ziehau 
411943c2aeb0SSepherosa Ziehau 
412043c2aeb0SSepherosa Ziehau /****************************************************************************/
412143c2aeb0SSepherosa Ziehau /* Free memory and clear the RX data structures.                            */
412243c2aeb0SSepherosa Ziehau /*                                                                          */
412343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
412443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
412543c2aeb0SSepherosa Ziehau /****************************************************************************/
412643c2aeb0SSepherosa Ziehau static void
412743c2aeb0SSepherosa Ziehau bce_free_rx_chain(struct bce_softc *sc)
412843c2aeb0SSepherosa Ziehau {
412943c2aeb0SSepherosa Ziehau 	int i;
413043c2aeb0SSepherosa Ziehau 
413143c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
413243c2aeb0SSepherosa Ziehau 
413343c2aeb0SSepherosa Ziehau 	/* Free any mbufs still in the RX mbuf chain. */
413443c2aeb0SSepherosa Ziehau 	for (i = 0; i < TOTAL_RX_BD; i++) {
413543c2aeb0SSepherosa Ziehau 		if (sc->rx_mbuf_ptr[i] != NULL) {
413643c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->rx_mbuf_tag, sc->rx_mbuf_map[i]);
413743c2aeb0SSepherosa Ziehau 			m_freem(sc->rx_mbuf_ptr[i]);
413843c2aeb0SSepherosa Ziehau 			sc->rx_mbuf_ptr[i] = NULL;
413943c2aeb0SSepherosa Ziehau 			DBRUNIF(1, sc->rx_mbuf_alloc--);
414043c2aeb0SSepherosa Ziehau 		}
414143c2aeb0SSepherosa Ziehau 	}
414243c2aeb0SSepherosa Ziehau 
414343c2aeb0SSepherosa Ziehau 	/* Clear each RX chain page. */
414443c2aeb0SSepherosa Ziehau 	for (i = 0; i < RX_PAGES; i++)
414543c2aeb0SSepherosa Ziehau 		bzero(sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ);
414643c2aeb0SSepherosa Ziehau 
414743c2aeb0SSepherosa Ziehau 	/* Check if we lost any mbufs in the process. */
414843c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->rx_mbuf_alloc),
414943c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
415043c2aeb0SSepherosa Ziehau 			  "%s(%d): Memory leak! "
415143c2aeb0SSepherosa Ziehau 			  "Lost %d mbufs from rx chain!\n",
415243c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__, sc->rx_mbuf_alloc));
415343c2aeb0SSepherosa Ziehau 
415443c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __func__);
415543c2aeb0SSepherosa Ziehau }
415643c2aeb0SSepherosa Ziehau 
415743c2aeb0SSepherosa Ziehau 
415843c2aeb0SSepherosa Ziehau /****************************************************************************/
415943c2aeb0SSepherosa Ziehau /* Set media options.                                                       */
416043c2aeb0SSepherosa Ziehau /*                                                                          */
416143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
416243c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
416343c2aeb0SSepherosa Ziehau /****************************************************************************/
416443c2aeb0SSepherosa Ziehau static int
416543c2aeb0SSepherosa Ziehau bce_ifmedia_upd(struct ifnet *ifp)
416643c2aeb0SSepherosa Ziehau {
416743c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
416843c2aeb0SSepherosa Ziehau 	struct mii_data *mii = device_get_softc(sc->bce_miibus);
416943c2aeb0SSepherosa Ziehau 
417043c2aeb0SSepherosa Ziehau 	/*
417143c2aeb0SSepherosa Ziehau 	 * 'mii' will be NULL, when this function is called on following
417243c2aeb0SSepherosa Ziehau 	 * code path: bce_attach() -> bce_mgmt_init()
417343c2aeb0SSepherosa Ziehau 	 */
417443c2aeb0SSepherosa Ziehau 	if (mii != NULL) {
417543c2aeb0SSepherosa Ziehau 		/* Make sure the MII bus has been enumerated. */
417643c2aeb0SSepherosa Ziehau 		sc->bce_link = 0;
417743c2aeb0SSepherosa Ziehau 		if (mii->mii_instance) {
417843c2aeb0SSepherosa Ziehau 			struct mii_softc *miisc;
417943c2aeb0SSepherosa Ziehau 
418043c2aeb0SSepherosa Ziehau 			LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
418143c2aeb0SSepherosa Ziehau 				mii_phy_reset(miisc);
418243c2aeb0SSepherosa Ziehau 		}
418343c2aeb0SSepherosa Ziehau 		mii_mediachg(mii);
418443c2aeb0SSepherosa Ziehau 	}
418543c2aeb0SSepherosa Ziehau 	return 0;
418643c2aeb0SSepherosa Ziehau }
418743c2aeb0SSepherosa Ziehau 
418843c2aeb0SSepherosa Ziehau 
418943c2aeb0SSepherosa Ziehau /****************************************************************************/
419043c2aeb0SSepherosa Ziehau /* Reports current media status.                                            */
419143c2aeb0SSepherosa Ziehau /*                                                                          */
419243c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
419343c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
419443c2aeb0SSepherosa Ziehau /****************************************************************************/
419543c2aeb0SSepherosa Ziehau static void
419643c2aeb0SSepherosa Ziehau bce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
419743c2aeb0SSepherosa Ziehau {
419843c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
419943c2aeb0SSepherosa Ziehau 	struct mii_data *mii = device_get_softc(sc->bce_miibus);
420043c2aeb0SSepherosa Ziehau 
420143c2aeb0SSepherosa Ziehau 	mii_pollstat(mii);
420243c2aeb0SSepherosa Ziehau 	ifmr->ifm_active = mii->mii_media_active;
420343c2aeb0SSepherosa Ziehau 	ifmr->ifm_status = mii->mii_media_status;
420443c2aeb0SSepherosa Ziehau }
420543c2aeb0SSepherosa Ziehau 
420643c2aeb0SSepherosa Ziehau 
420743c2aeb0SSepherosa Ziehau /****************************************************************************/
420843c2aeb0SSepherosa Ziehau /* Handles PHY generated interrupt events.                                  */
420943c2aeb0SSepherosa Ziehau /*                                                                          */
421043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
421143c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
421243c2aeb0SSepherosa Ziehau /****************************************************************************/
421343c2aeb0SSepherosa Ziehau static void
421443c2aeb0SSepherosa Ziehau bce_phy_intr(struct bce_softc *sc)
421543c2aeb0SSepherosa Ziehau {
421643c2aeb0SSepherosa Ziehau 	uint32_t new_link_state, old_link_state;
421743c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
421843c2aeb0SSepherosa Ziehau 
421943c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
422043c2aeb0SSepherosa Ziehau 
422143c2aeb0SSepherosa Ziehau 	new_link_state = sc->status_block->status_attn_bits &
422243c2aeb0SSepherosa Ziehau 			 STATUS_ATTN_BITS_LINK_STATE;
422343c2aeb0SSepherosa Ziehau 	old_link_state = sc->status_block->status_attn_bits_ack &
422443c2aeb0SSepherosa Ziehau 			 STATUS_ATTN_BITS_LINK_STATE;
422543c2aeb0SSepherosa Ziehau 
422643c2aeb0SSepherosa Ziehau 	/* Handle any changes if the link state has changed. */
422743c2aeb0SSepherosa Ziehau 	if (new_link_state != old_link_state) {	/* XXX redundant? */
422843c2aeb0SSepherosa Ziehau 		DBRUN(BCE_VERBOSE_INTR, bce_dump_status_block(sc));
422943c2aeb0SSepherosa Ziehau 
423043c2aeb0SSepherosa Ziehau 		/* Update the status_attn_bits_ack field in the status block. */
423143c2aeb0SSepherosa Ziehau 		if (new_link_state) {
423243c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_PCICFG_STATUS_BIT_SET_CMD,
423343c2aeb0SSepherosa Ziehau 			       STATUS_ATTN_BITS_LINK_STATE);
423443c2aeb0SSepherosa Ziehau 			if (bootverbose)
423543c2aeb0SSepherosa Ziehau 				if_printf(ifp, "Link is now UP.\n");
423643c2aeb0SSepherosa Ziehau 		} else {
423743c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_PCICFG_STATUS_BIT_CLEAR_CMD,
423843c2aeb0SSepherosa Ziehau 			       STATUS_ATTN_BITS_LINK_STATE);
423943c2aeb0SSepherosa Ziehau 			if (bootverbose)
424043c2aeb0SSepherosa Ziehau 				if_printf(ifp, "Link is now DOWN.\n");
424143c2aeb0SSepherosa Ziehau 		}
4242d0092544SSepherosa Ziehau 
4243d0092544SSepherosa Ziehau 		/*
4244d0092544SSepherosa Ziehau 		 * Assume link is down and allow tick routine to
4245d0092544SSepherosa Ziehau 		 * update the state based on the actual media state.
4246d0092544SSepherosa Ziehau 		 */
4247d0092544SSepherosa Ziehau 		sc->bce_link = 0;
4248d0092544SSepherosa Ziehau 		callout_stop(&sc->bce_tick_callout);
4249d0092544SSepherosa Ziehau 		bce_tick_serialized(sc);
425043c2aeb0SSepherosa Ziehau 	}
425143c2aeb0SSepherosa Ziehau 
425243c2aeb0SSepherosa Ziehau 	/* Acknowledge the link change interrupt. */
425343c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_STATUS, BCE_EMAC_STATUS_LINK_CHANGE);
425443c2aeb0SSepherosa Ziehau }
425543c2aeb0SSepherosa Ziehau 
425643c2aeb0SSepherosa Ziehau 
425743c2aeb0SSepherosa Ziehau /****************************************************************************/
425824603545SSepherosa Ziehau /* Reads the receive consumer value from the status block (skipping over    */
425924603545SSepherosa Ziehau /* chain page pointer if necessary).                                        */
426024603545SSepherosa Ziehau /*                                                                          */
426124603545SSepherosa Ziehau /* Returns:                                                                 */
426224603545SSepherosa Ziehau /*   hw_cons                                                                */
426324603545SSepherosa Ziehau /****************************************************************************/
426424603545SSepherosa Ziehau static __inline uint16_t
426524603545SSepherosa Ziehau bce_get_hw_rx_cons(struct bce_softc *sc)
426624603545SSepherosa Ziehau {
426724603545SSepherosa Ziehau 	uint16_t hw_cons = sc->status_block->status_rx_quick_consumer_index0;
426824603545SSepherosa Ziehau 
426924603545SSepherosa Ziehau 	if ((hw_cons & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE)
427024603545SSepherosa Ziehau 		hw_cons++;
427124603545SSepherosa Ziehau 	return hw_cons;
427224603545SSepherosa Ziehau }
427324603545SSepherosa Ziehau 
427424603545SSepherosa Ziehau 
427524603545SSepherosa Ziehau /****************************************************************************/
427643c2aeb0SSepherosa Ziehau /* Handles received frame interrupt events.                                 */
427743c2aeb0SSepherosa Ziehau /*                                                                          */
427843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
427943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
428043c2aeb0SSepherosa Ziehau /****************************************************************************/
428143c2aeb0SSepherosa Ziehau static void
428243c2aeb0SSepherosa Ziehau bce_rx_intr(struct bce_softc *sc, int count)
428343c2aeb0SSepherosa Ziehau {
428443c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
428543c2aeb0SSepherosa Ziehau 	uint16_t hw_cons, sw_cons, sw_chain_cons, sw_prod, sw_chain_prod;
428643c2aeb0SSepherosa Ziehau 	uint32_t sw_prod_bseq;
428777a7ee7dSSepherosa Ziehau 	struct mbuf_chain chain[MAXCPU];
428843c2aeb0SSepherosa Ziehau 
428943c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
429043c2aeb0SSepherosa Ziehau 
429177a7ee7dSSepherosa Ziehau 	ether_input_chain_init(chain);
429277a7ee7dSSepherosa Ziehau 
429343c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->rx_interrupts++);
429443c2aeb0SSepherosa Ziehau 
429543c2aeb0SSepherosa Ziehau 	/* Get the hardware's view of the RX consumer index. */
429624603545SSepherosa Ziehau 	hw_cons = sc->hw_rx_cons = bce_get_hw_rx_cons(sc);
429743c2aeb0SSepherosa Ziehau 
429843c2aeb0SSepherosa Ziehau 	/* Get working copies of the driver's view of the RX indices. */
429943c2aeb0SSepherosa Ziehau 	sw_cons = sc->rx_cons;
430043c2aeb0SSepherosa Ziehau 	sw_prod = sc->rx_prod;
430143c2aeb0SSepherosa Ziehau 	sw_prod_bseq = sc->rx_prod_bseq;
430243c2aeb0SSepherosa Ziehau 
430343c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RECV, "%s(enter): sw_prod = 0x%04X, "
430443c2aeb0SSepherosa Ziehau 		"sw_cons = 0x%04X, sw_prod_bseq = 0x%08X\n",
430543c2aeb0SSepherosa Ziehau 		__func__, sw_prod, sw_cons, sw_prod_bseq);
430643c2aeb0SSepherosa Ziehau 
430743c2aeb0SSepherosa Ziehau 	/* Prevent speculative reads from getting ahead of the status block. */
430843c2aeb0SSepherosa Ziehau 	bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
430943c2aeb0SSepherosa Ziehau 			  BUS_SPACE_BARRIER_READ);
431043c2aeb0SSepherosa Ziehau 
431143c2aeb0SSepherosa Ziehau 	/* Update some debug statistics counters */
431243c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
431343c2aeb0SSepherosa Ziehau 		sc->rx_low_watermark = sc->free_rx_bd);
431443c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd == 0), sc->rx_empty_count++);
431543c2aeb0SSepherosa Ziehau 
431643c2aeb0SSepherosa Ziehau 	/* Scan through the receive chain as long as there is work to do. */
431743c2aeb0SSepherosa Ziehau 	while (sw_cons != hw_cons) {
431843c2aeb0SSepherosa Ziehau 		struct mbuf *m = NULL;
431943c2aeb0SSepherosa Ziehau 		struct l2_fhdr *l2fhdr = NULL;
432043c2aeb0SSepherosa Ziehau 		struct rx_bd *rxbd;
432143c2aeb0SSepherosa Ziehau 		unsigned int len;
432243c2aeb0SSepherosa Ziehau 		uint32_t status = 0;
432343c2aeb0SSepherosa Ziehau 
43245205bd03SSepherosa Ziehau #ifdef DEVICE_POLLING
43255205bd03SSepherosa Ziehau 		if (count >= 0 && count-- == 0) {
43265205bd03SSepherosa Ziehau 			sc->hw_rx_cons = sw_cons;
432743c2aeb0SSepherosa Ziehau 			break;
43285205bd03SSepherosa Ziehau 		}
432943c2aeb0SSepherosa Ziehau #endif
433043c2aeb0SSepherosa Ziehau 
433143c2aeb0SSepherosa Ziehau 		/*
433243c2aeb0SSepherosa Ziehau 		 * Convert the producer/consumer indices
433343c2aeb0SSepherosa Ziehau 		 * to an actual rx_bd index.
433443c2aeb0SSepherosa Ziehau 		 */
433543c2aeb0SSepherosa Ziehau 		sw_chain_cons = RX_CHAIN_IDX(sw_cons);
433643c2aeb0SSepherosa Ziehau 		sw_chain_prod = RX_CHAIN_IDX(sw_prod);
433743c2aeb0SSepherosa Ziehau 
433843c2aeb0SSepherosa Ziehau 		/* Get the used rx_bd. */
433943c2aeb0SSepherosa Ziehau 		rxbd = &sc->rx_bd_chain[RX_PAGE(sw_chain_cons)]
434043c2aeb0SSepherosa Ziehau 				       [RX_IDX(sw_chain_cons)];
434143c2aeb0SSepherosa Ziehau 		sc->free_rx_bd++;
434243c2aeb0SSepherosa Ziehau 
434343c2aeb0SSepherosa Ziehau 		DBRUN(BCE_VERBOSE_RECV,
434443c2aeb0SSepherosa Ziehau 		      if_printf(ifp, "%s(): ", __func__);
434543c2aeb0SSepherosa Ziehau 		      bce_dump_rxbd(sc, sw_chain_cons, rxbd));
434643c2aeb0SSepherosa Ziehau 
434743c2aeb0SSepherosa Ziehau 		/* The mbuf is stored with the last rx_bd entry of a packet. */
434843c2aeb0SSepherosa Ziehau 		if (sc->rx_mbuf_ptr[sw_chain_cons] != NULL) {
434943c2aeb0SSepherosa Ziehau 			/* Validate that this is the last rx_bd. */
435043c2aeb0SSepherosa Ziehau 			DBRUNIF((!(rxbd->rx_bd_flags & RX_BD_FLAGS_END)),
435143c2aeb0SSepherosa Ziehau 				if_printf(ifp, "%s(%d): "
435243c2aeb0SSepherosa Ziehau 				"Unexpected mbuf found in rx_bd[0x%04X]!\n",
435343c2aeb0SSepherosa Ziehau 				__FILE__, __LINE__, sw_chain_cons);
435443c2aeb0SSepherosa Ziehau 				bce_breakpoint(sc));
435543c2aeb0SSepherosa Ziehau 
4356c36fd9eeSSepherosa Ziehau 			if (sw_chain_cons != sw_chain_prod) {
4357c36fd9eeSSepherosa Ziehau 				if_printf(ifp, "RX cons(%d) != prod(%d), "
4358c36fd9eeSSepherosa Ziehau 					  "drop!\n", sw_chain_cons,
4359c36fd9eeSSepherosa Ziehau 					  sw_chain_prod);
4360c36fd9eeSSepherosa Ziehau 				ifp->if_ierrors++;
4361c36fd9eeSSepherosa Ziehau 
4362c36fd9eeSSepherosa Ziehau 				bce_setup_rxdesc_std(sc, sw_chain_cons,
4363c36fd9eeSSepherosa Ziehau 						     &sw_prod_bseq);
4364c36fd9eeSSepherosa Ziehau 				m = NULL;
4365c36fd9eeSSepherosa Ziehau 				goto bce_rx_int_next_rx;
4366c36fd9eeSSepherosa Ziehau 			}
436743c2aeb0SSepherosa Ziehau 
436843c2aeb0SSepherosa Ziehau 			/* Unmap the mbuf from DMA space. */
436943c2aeb0SSepherosa Ziehau 			bus_dmamap_sync(sc->rx_mbuf_tag,
437043c2aeb0SSepherosa Ziehau 					sc->rx_mbuf_map[sw_chain_cons],
437143c2aeb0SSepherosa Ziehau 					BUS_DMASYNC_POSTREAD);
437243c2aeb0SSepherosa Ziehau 
4373c36fd9eeSSepherosa Ziehau 			/* Save the mbuf from the driver's chain. */
437443c2aeb0SSepherosa Ziehau 			m = sc->rx_mbuf_ptr[sw_chain_cons];
437543c2aeb0SSepherosa Ziehau 
437643c2aeb0SSepherosa Ziehau 			/*
437743c2aeb0SSepherosa Ziehau 			 * Frames received on the NetXteme II are prepended
437843c2aeb0SSepherosa Ziehau 			 * with an l2_fhdr structure which provides status
437943c2aeb0SSepherosa Ziehau 			 * information about the received frame (including
438043c2aeb0SSepherosa Ziehau 			 * VLAN tags and checksum info).  The frames are also
438143c2aeb0SSepherosa Ziehau 			 * automatically adjusted to align the IP header
438243c2aeb0SSepherosa Ziehau 			 * (i.e. two null bytes are inserted before the
4383cff16e71SSepherosa Ziehau 			 * Ethernet header).  As a result the data DMA'd by
4384cff16e71SSepherosa Ziehau 			 * the controller into the mbuf is as follows:
4385cff16e71SSepherosa Ziehau 			 *
4386cff16e71SSepherosa Ziehau 			 * +---------+-----+---------------------+-----+
4387cff16e71SSepherosa Ziehau 			 * | l2_fhdr | pad | packet data         | FCS |
4388cff16e71SSepherosa Ziehau 			 * +---------+-----+---------------------+-----+
4389cff16e71SSepherosa Ziehau 			 *
4390cff16e71SSepherosa Ziehau 			 * The l2_fhdr needs to be checked and skipped and the
4391cff16e71SSepherosa Ziehau 			 * FCS needs to be stripped before sending the packet
4392cff16e71SSepherosa Ziehau 			 * up the stack.
439343c2aeb0SSepherosa Ziehau 			 */
439443c2aeb0SSepherosa Ziehau 			l2fhdr = mtod(m, struct l2_fhdr *);
439543c2aeb0SSepherosa Ziehau 
439643c2aeb0SSepherosa Ziehau 			len = l2fhdr->l2_fhdr_pkt_len;
439743c2aeb0SSepherosa Ziehau 			status = l2fhdr->l2_fhdr_status;
439843c2aeb0SSepherosa Ziehau 
439943c2aeb0SSepherosa Ziehau 			DBRUNIF(DB_RANDOMTRUE(bce_debug_l2fhdr_status_check),
440043c2aeb0SSepherosa Ziehau 				if_printf(ifp,
440143c2aeb0SSepherosa Ziehau 				"Simulating l2_fhdr status error.\n");
440243c2aeb0SSepherosa Ziehau 				status = status | L2_FHDR_ERRORS_PHY_DECODE);
440343c2aeb0SSepherosa Ziehau 
440443c2aeb0SSepherosa Ziehau 			/* Watch for unusual sized frames. */
440543c2aeb0SSepherosa Ziehau 			DBRUNIF((len < BCE_MIN_MTU ||
440643c2aeb0SSepherosa Ziehau 				 len > BCE_MAX_JUMBO_ETHER_MTU_VLAN),
440743c2aeb0SSepherosa Ziehau 				if_printf(ifp,
440843c2aeb0SSepherosa Ziehau 				"%s(%d): Unusual frame size found. "
440943c2aeb0SSepherosa Ziehau 				"Min(%d), Actual(%d), Max(%d)\n",
441043c2aeb0SSepherosa Ziehau 				__FILE__, __LINE__,
441143c2aeb0SSepherosa Ziehau 				(int)BCE_MIN_MTU, len,
441243c2aeb0SSepherosa Ziehau 				(int)BCE_MAX_JUMBO_ETHER_MTU_VLAN);
441343c2aeb0SSepherosa Ziehau 				bce_dump_mbuf(sc, m);
441443c2aeb0SSepherosa Ziehau 		 		bce_breakpoint(sc));
441543c2aeb0SSepherosa Ziehau 
441643c2aeb0SSepherosa Ziehau 			len -= ETHER_CRC_LEN;
441743c2aeb0SSepherosa Ziehau 
441843c2aeb0SSepherosa Ziehau 			/* Check the received frame for errors. */
441943c2aeb0SSepherosa Ziehau 			if (status & (L2_FHDR_ERRORS_BAD_CRC |
442043c2aeb0SSepherosa Ziehau 				      L2_FHDR_ERRORS_PHY_DECODE |
442143c2aeb0SSepherosa Ziehau 				      L2_FHDR_ERRORS_ALIGNMENT |
442243c2aeb0SSepherosa Ziehau 				      L2_FHDR_ERRORS_TOO_SHORT |
442343c2aeb0SSepherosa Ziehau 				      L2_FHDR_ERRORS_GIANT_FRAME)) {
442443c2aeb0SSepherosa Ziehau 				ifp->if_ierrors++;
442543c2aeb0SSepherosa Ziehau 				DBRUNIF(1, sc->l2fhdr_status_errors++);
442643c2aeb0SSepherosa Ziehau 
442743c2aeb0SSepherosa Ziehau 				/* Reuse the mbuf for a new frame. */
4428c36fd9eeSSepherosa Ziehau 				bce_setup_rxdesc_std(sc, sw_chain_prod,
4429c36fd9eeSSepherosa Ziehau 						     &sw_prod_bseq);
443043c2aeb0SSepherosa Ziehau 				m = NULL;
443143c2aeb0SSepherosa Ziehau 				goto bce_rx_int_next_rx;
443243c2aeb0SSepherosa Ziehau 			}
443343c2aeb0SSepherosa Ziehau 
443443c2aeb0SSepherosa Ziehau 			/*
443543c2aeb0SSepherosa Ziehau 			 * Get a new mbuf for the rx_bd.   If no new
443643c2aeb0SSepherosa Ziehau 			 * mbufs are available then reuse the current mbuf,
443743c2aeb0SSepherosa Ziehau 			 * log an ierror on the interface, and generate
443843c2aeb0SSepherosa Ziehau 			 * an error in the system log.
443943c2aeb0SSepherosa Ziehau 			 */
4440c36fd9eeSSepherosa Ziehau 			if (bce_newbuf_std(sc, &sw_prod, &sw_chain_prod,
4441c36fd9eeSSepherosa Ziehau 					   &sw_prod_bseq, 0)) {
444243c2aeb0SSepherosa Ziehau 				DBRUN(BCE_WARN,
444343c2aeb0SSepherosa Ziehau 				      if_printf(ifp,
444443c2aeb0SSepherosa Ziehau 				      "%s(%d): Failed to allocate new mbuf, "
444543c2aeb0SSepherosa Ziehau 				      "incoming frame dropped!\n",
444643c2aeb0SSepherosa Ziehau 				      __FILE__, __LINE__));
444743c2aeb0SSepherosa Ziehau 
444843c2aeb0SSepherosa Ziehau 				ifp->if_ierrors++;
444943c2aeb0SSepherosa Ziehau 
445043c2aeb0SSepherosa Ziehau 				/* Try and reuse the exisitng mbuf. */
4451c36fd9eeSSepherosa Ziehau 				bce_setup_rxdesc_std(sc, sw_chain_prod,
4452c36fd9eeSSepherosa Ziehau 						     &sw_prod_bseq);
445343c2aeb0SSepherosa Ziehau 				m = NULL;
445443c2aeb0SSepherosa Ziehau 				goto bce_rx_int_next_rx;
445543c2aeb0SSepherosa Ziehau 			}
445643c2aeb0SSepherosa Ziehau 
445743c2aeb0SSepherosa Ziehau 			/*
445843c2aeb0SSepherosa Ziehau 			 * Skip over the l2_fhdr when passing
445943c2aeb0SSepherosa Ziehau 			 * the data up the stack.
446043c2aeb0SSepherosa Ziehau 			 */
446143c2aeb0SSepherosa Ziehau 			m_adj(m, sizeof(struct l2_fhdr) + ETHER_ALIGN);
446243c2aeb0SSepherosa Ziehau 
446343c2aeb0SSepherosa Ziehau 			m->m_pkthdr.len = m->m_len = len;
446443c2aeb0SSepherosa Ziehau 			m->m_pkthdr.rcvif = ifp;
446543c2aeb0SSepherosa Ziehau 
446643c2aeb0SSepherosa Ziehau 			DBRUN(BCE_VERBOSE_RECV,
446743c2aeb0SSepherosa Ziehau 			      struct ether_header *eh;
446843c2aeb0SSepherosa Ziehau 			      eh = mtod(m, struct ether_header *);
446943c2aeb0SSepherosa Ziehau 			      if_printf(ifp, "%s(): to: %6D, from: %6D, "
447043c2aeb0SSepherosa Ziehau 			      		"type: 0x%04X\n", __func__,
447143c2aeb0SSepherosa Ziehau 					eh->ether_dhost, ":",
447243c2aeb0SSepherosa Ziehau 					eh->ether_shost, ":",
447343c2aeb0SSepherosa Ziehau 					htons(eh->ether_type)));
447443c2aeb0SSepherosa Ziehau 
447543c2aeb0SSepherosa Ziehau 			/* Validate the checksum if offload enabled. */
447643c2aeb0SSepherosa Ziehau 			if (ifp->if_capenable & IFCAP_RXCSUM) {
447743c2aeb0SSepherosa Ziehau 				/* Check for an IP datagram. */
447843c2aeb0SSepherosa Ziehau 				if (status & L2_FHDR_STATUS_IP_DATAGRAM) {
447943c2aeb0SSepherosa Ziehau 					m->m_pkthdr.csum_flags |=
448043c2aeb0SSepherosa Ziehau 						CSUM_IP_CHECKED;
448143c2aeb0SSepherosa Ziehau 
448243c2aeb0SSepherosa Ziehau 					/* Check if the IP checksum is valid. */
448343c2aeb0SSepherosa Ziehau 					if ((l2fhdr->l2_fhdr_ip_xsum ^
448443c2aeb0SSepherosa Ziehau 					     0xffff) == 0) {
448543c2aeb0SSepherosa Ziehau 						m->m_pkthdr.csum_flags |=
448643c2aeb0SSepherosa Ziehau 							CSUM_IP_VALID;
448743c2aeb0SSepherosa Ziehau 					} else {
448843c2aeb0SSepherosa Ziehau 						DBPRINT(sc, BCE_WARN_RECV,
448943c2aeb0SSepherosa Ziehau 							"%s(): Invalid IP checksum = 0x%04X!\n",
449043c2aeb0SSepherosa Ziehau 							__func__, l2fhdr->l2_fhdr_ip_xsum);
449143c2aeb0SSepherosa Ziehau 					}
449243c2aeb0SSepherosa Ziehau 				}
449343c2aeb0SSepherosa Ziehau 
449443c2aeb0SSepherosa Ziehau 				/* Check for a valid TCP/UDP frame. */
449543c2aeb0SSepherosa Ziehau 				if (status & (L2_FHDR_STATUS_TCP_SEGMENT |
449643c2aeb0SSepherosa Ziehau 					      L2_FHDR_STATUS_UDP_DATAGRAM)) {
449743c2aeb0SSepherosa Ziehau 
449843c2aeb0SSepherosa Ziehau 					/* Check for a good TCP/UDP checksum. */
449943c2aeb0SSepherosa Ziehau 					if ((status &
450043c2aeb0SSepherosa Ziehau 					     (L2_FHDR_ERRORS_TCP_XSUM |
450143c2aeb0SSepherosa Ziehau 					      L2_FHDR_ERRORS_UDP_XSUM)) == 0) {
450243c2aeb0SSepherosa Ziehau 						m->m_pkthdr.csum_data =
450343c2aeb0SSepherosa Ziehau 						l2fhdr->l2_fhdr_tcp_udp_xsum;
450443c2aeb0SSepherosa Ziehau 						m->m_pkthdr.csum_flags |=
450543c2aeb0SSepherosa Ziehau 							CSUM_DATA_VALID |
450643c2aeb0SSepherosa Ziehau 							CSUM_PSEUDO_HDR;
450743c2aeb0SSepherosa Ziehau 					} else {
450843c2aeb0SSepherosa Ziehau 						DBPRINT(sc, BCE_WARN_RECV,
450943c2aeb0SSepherosa Ziehau 							"%s(): Invalid TCP/UDP checksum = 0x%04X!\n",
451043c2aeb0SSepherosa Ziehau 							__func__, l2fhdr->l2_fhdr_tcp_udp_xsum);
451143c2aeb0SSepherosa Ziehau 					}
451243c2aeb0SSepherosa Ziehau 				}
451343c2aeb0SSepherosa Ziehau 			}
451443c2aeb0SSepherosa Ziehau 
451543c2aeb0SSepherosa Ziehau 			ifp->if_ipackets++;
451643c2aeb0SSepherosa Ziehau bce_rx_int_next_rx:
451743c2aeb0SSepherosa Ziehau 			sw_prod = NEXT_RX_BD(sw_prod);
451843c2aeb0SSepherosa Ziehau 		}
451943c2aeb0SSepherosa Ziehau 
452043c2aeb0SSepherosa Ziehau 		sw_cons = NEXT_RX_BD(sw_cons);
452143c2aeb0SSepherosa Ziehau 
452243c2aeb0SSepherosa Ziehau 		/* If we have a packet, pass it up the stack */
452343c2aeb0SSepherosa Ziehau 		if (m) {
452443c2aeb0SSepherosa Ziehau 			DBPRINT(sc, BCE_VERBOSE_RECV,
452543c2aeb0SSepherosa Ziehau 				"%s(): Passing received frame up.\n", __func__);
452643c2aeb0SSepherosa Ziehau 
4527e6b5847cSSepherosa Ziehau 			if (status & L2_FHDR_STATUS_L2_VLAN_TAG) {
4528e6b5847cSSepherosa Ziehau 				m->m_flags |= M_VLANTAG;
4529e6b5847cSSepherosa Ziehau 				m->m_pkthdr.ether_vlantag =
4530e6b5847cSSepherosa Ziehau 					l2fhdr->l2_fhdr_vlan_tag;
4531e6b5847cSSepherosa Ziehau 			}
45322eb0d069SSepherosa Ziehau 			ether_input_chain(ifp, m, NULL, chain);
453343c2aeb0SSepherosa Ziehau 
453443c2aeb0SSepherosa Ziehau 			DBRUNIF(1, sc->rx_mbuf_alloc--);
453543c2aeb0SSepherosa Ziehau 		}
453643c2aeb0SSepherosa Ziehau 
453743c2aeb0SSepherosa Ziehau 		/*
453843c2aeb0SSepherosa Ziehau 		 * If polling(4) is not enabled, refresh hw_cons to see
453943c2aeb0SSepherosa Ziehau 		 * whether there's new work.
454043c2aeb0SSepherosa Ziehau 		 *
454143c2aeb0SSepherosa Ziehau 		 * If polling(4) is enabled, i.e count >= 0, refreshing
454243c2aeb0SSepherosa Ziehau 		 * should not be performed, so that we would not spend
454343c2aeb0SSepherosa Ziehau 		 * too much time in RX processing.
454443c2aeb0SSepherosa Ziehau 		 */
454524603545SSepherosa Ziehau 		if (count < 0 && sw_cons == hw_cons)
454624603545SSepherosa Ziehau 			hw_cons = sc->hw_rx_cons = bce_get_hw_rx_cons(sc);
454743c2aeb0SSepherosa Ziehau 
454843c2aeb0SSepherosa Ziehau 		/*
454943c2aeb0SSepherosa Ziehau 		 * Prevent speculative reads from getting ahead
455043c2aeb0SSepherosa Ziehau 		 * of the status block.
455143c2aeb0SSepherosa Ziehau 		 */
455243c2aeb0SSepherosa Ziehau 		bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
455343c2aeb0SSepherosa Ziehau 				  BUS_SPACE_BARRIER_READ);
455443c2aeb0SSepherosa Ziehau 	}
455543c2aeb0SSepherosa Ziehau 
455677a7ee7dSSepherosa Ziehau 	ether_input_dispatch(chain);
455777a7ee7dSSepherosa Ziehau 
455843c2aeb0SSepherosa Ziehau 	sc->rx_cons = sw_cons;
455943c2aeb0SSepherosa Ziehau 	sc->rx_prod = sw_prod;
456043c2aeb0SSepherosa Ziehau 	sc->rx_prod_bseq = sw_prod_bseq;
456143c2aeb0SSepherosa Ziehau 
4562d0092544SSepherosa Ziehau 	REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BDIDX,
4563d0092544SSepherosa Ziehau 	    sc->rx_prod);
4564d0092544SSepherosa Ziehau 	REG_WR(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BSEQ,
4565d0092544SSepherosa Ziehau 	    sc->rx_prod_bseq);
456643c2aeb0SSepherosa Ziehau 
456743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RECV, "%s(exit): rx_prod = 0x%04X, "
456843c2aeb0SSepherosa Ziehau 		"rx_cons = 0x%04X, rx_prod_bseq = 0x%08X\n",
456943c2aeb0SSepherosa Ziehau 		__func__, sc->rx_prod, sc->rx_cons, sc->rx_prod_bseq);
457043c2aeb0SSepherosa Ziehau }
457143c2aeb0SSepherosa Ziehau 
457243c2aeb0SSepherosa Ziehau 
457343c2aeb0SSepherosa Ziehau /****************************************************************************/
457424603545SSepherosa Ziehau /* Reads the transmit consumer value from the status block (skipping over   */
457524603545SSepherosa Ziehau /* chain page pointer if necessary).                                        */
457624603545SSepherosa Ziehau /*                                                                          */
457724603545SSepherosa Ziehau /* Returns:                                                                 */
457824603545SSepherosa Ziehau /*   hw_cons                                                                */
457924603545SSepherosa Ziehau /****************************************************************************/
458024603545SSepherosa Ziehau static __inline uint16_t
458124603545SSepherosa Ziehau bce_get_hw_tx_cons(struct bce_softc *sc)
458224603545SSepherosa Ziehau {
458324603545SSepherosa Ziehau 	uint16_t hw_cons = sc->status_block->status_tx_quick_consumer_index0;
458424603545SSepherosa Ziehau 
458524603545SSepherosa Ziehau 	if ((hw_cons & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE)
458624603545SSepherosa Ziehau 		hw_cons++;
458724603545SSepherosa Ziehau 	return hw_cons;
458824603545SSepherosa Ziehau }
458924603545SSepherosa Ziehau 
459024603545SSepherosa Ziehau 
459124603545SSepherosa Ziehau /****************************************************************************/
459243c2aeb0SSepherosa Ziehau /* Handles transmit completion interrupt events.                            */
459343c2aeb0SSepherosa Ziehau /*                                                                          */
459443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
459543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
459643c2aeb0SSepherosa Ziehau /****************************************************************************/
459743c2aeb0SSepherosa Ziehau static void
459843c2aeb0SSepherosa Ziehau bce_tx_intr(struct bce_softc *sc)
459943c2aeb0SSepherosa Ziehau {
460043c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
460143c2aeb0SSepherosa Ziehau 	uint16_t hw_tx_cons, sw_tx_cons, sw_tx_chain_cons;
460243c2aeb0SSepherosa Ziehau 
460343c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
460443c2aeb0SSepherosa Ziehau 
460543c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->tx_interrupts++);
460643c2aeb0SSepherosa Ziehau 
460743c2aeb0SSepherosa Ziehau 	/* Get the hardware's view of the TX consumer index. */
460824603545SSepherosa Ziehau 	hw_tx_cons = sc->hw_tx_cons = bce_get_hw_tx_cons(sc);
460943c2aeb0SSepherosa Ziehau 	sw_tx_cons = sc->tx_cons;
461043c2aeb0SSepherosa Ziehau 
461143c2aeb0SSepherosa Ziehau 	/* Prevent speculative reads from getting ahead of the status block. */
461243c2aeb0SSepherosa Ziehau 	bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
461343c2aeb0SSepherosa Ziehau 			  BUS_SPACE_BARRIER_READ);
461443c2aeb0SSepherosa Ziehau 
461543c2aeb0SSepherosa Ziehau 	/* Cycle through any completed TX chain page entries. */
461643c2aeb0SSepherosa Ziehau 	while (sw_tx_cons != hw_tx_cons) {
461743c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
461843c2aeb0SSepherosa Ziehau 		struct tx_bd *txbd = NULL;
461943c2aeb0SSepherosa Ziehau #endif
462043c2aeb0SSepherosa Ziehau 		sw_tx_chain_cons = TX_CHAIN_IDX(sw_tx_cons);
462143c2aeb0SSepherosa Ziehau 
462243c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO_SEND,
462343c2aeb0SSepherosa Ziehau 			"%s(): hw_tx_cons = 0x%04X, sw_tx_cons = 0x%04X, "
462443c2aeb0SSepherosa Ziehau 			"sw_tx_chain_cons = 0x%04X\n",
462543c2aeb0SSepherosa Ziehau 			__func__, hw_tx_cons, sw_tx_cons, sw_tx_chain_cons);
462643c2aeb0SSepherosa Ziehau 
462743c2aeb0SSepherosa Ziehau 		DBRUNIF((sw_tx_chain_cons > MAX_TX_BD),
462843c2aeb0SSepherosa Ziehau 			if_printf(ifp, "%s(%d): "
462943c2aeb0SSepherosa Ziehau 				  "TX chain consumer out of range! "
463043c2aeb0SSepherosa Ziehau 				  " 0x%04X > 0x%04X\n",
463143c2aeb0SSepherosa Ziehau 				  __FILE__, __LINE__, sw_tx_chain_cons,
463243c2aeb0SSepherosa Ziehau 				  (int)MAX_TX_BD);
463343c2aeb0SSepherosa Ziehau 			bce_breakpoint(sc));
463443c2aeb0SSepherosa Ziehau 
463543c2aeb0SSepherosa Ziehau 		DBRUNIF(1, txbd = &sc->tx_bd_chain[TX_PAGE(sw_tx_chain_cons)]
463643c2aeb0SSepherosa Ziehau 				[TX_IDX(sw_tx_chain_cons)]);
463743c2aeb0SSepherosa Ziehau 
463843c2aeb0SSepherosa Ziehau 		DBRUNIF((txbd == NULL),
463943c2aeb0SSepherosa Ziehau 			if_printf(ifp, "%s(%d): "
464043c2aeb0SSepherosa Ziehau 				  "Unexpected NULL tx_bd[0x%04X]!\n",
464143c2aeb0SSepherosa Ziehau 				  __FILE__, __LINE__, sw_tx_chain_cons);
464243c2aeb0SSepherosa Ziehau 			bce_breakpoint(sc));
464343c2aeb0SSepherosa Ziehau 
464443c2aeb0SSepherosa Ziehau 		DBRUN(BCE_INFO_SEND,
464543c2aeb0SSepherosa Ziehau 		      if_printf(ifp, "%s(): ", __func__);
464643c2aeb0SSepherosa Ziehau 		      bce_dump_txbd(sc, sw_tx_chain_cons, txbd));
464743c2aeb0SSepherosa Ziehau 
464843c2aeb0SSepherosa Ziehau 		/*
464943c2aeb0SSepherosa Ziehau 		 * Free the associated mbuf. Remember
465043c2aeb0SSepherosa Ziehau 		 * that only the last tx_bd of a packet
465143c2aeb0SSepherosa Ziehau 		 * has an mbuf pointer and DMA map.
465243c2aeb0SSepherosa Ziehau 		 */
465343c2aeb0SSepherosa Ziehau 		if (sc->tx_mbuf_ptr[sw_tx_chain_cons] != NULL) {
465443c2aeb0SSepherosa Ziehau 			/* Validate that this is the last tx_bd. */
465543c2aeb0SSepherosa Ziehau 			DBRUNIF((!(txbd->tx_bd_flags & TX_BD_FLAGS_END)),
465643c2aeb0SSepherosa Ziehau 				if_printf(ifp, "%s(%d): "
465743c2aeb0SSepherosa Ziehau 				"tx_bd END flag not set but "
465843c2aeb0SSepherosa Ziehau 				"txmbuf == NULL!\n", __FILE__, __LINE__);
465943c2aeb0SSepherosa Ziehau 				bce_breakpoint(sc));
466043c2aeb0SSepherosa Ziehau 
466143c2aeb0SSepherosa Ziehau 			DBRUN(BCE_INFO_SEND,
466243c2aeb0SSepherosa Ziehau 			      if_printf(ifp, "%s(): Unloading map/freeing mbuf "
466343c2aeb0SSepherosa Ziehau 			      		"from tx_bd[0x%04X]\n", __func__,
466443c2aeb0SSepherosa Ziehau 					sw_tx_chain_cons));
466543c2aeb0SSepherosa Ziehau 
466643c2aeb0SSepherosa Ziehau 			/* Unmap the mbuf. */
466743c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->tx_mbuf_tag,
466843c2aeb0SSepherosa Ziehau 					  sc->tx_mbuf_map[sw_tx_chain_cons]);
466943c2aeb0SSepherosa Ziehau 
467043c2aeb0SSepherosa Ziehau 			/* Free the mbuf. */
467143c2aeb0SSepherosa Ziehau 			m_freem(sc->tx_mbuf_ptr[sw_tx_chain_cons]);
467243c2aeb0SSepherosa Ziehau 			sc->tx_mbuf_ptr[sw_tx_chain_cons] = NULL;
467343c2aeb0SSepherosa Ziehau 			DBRUNIF(1, sc->tx_mbuf_alloc--);
467443c2aeb0SSepherosa Ziehau 
467543c2aeb0SSepherosa Ziehau 			ifp->if_opackets++;
467643c2aeb0SSepherosa Ziehau 		}
467743c2aeb0SSepherosa Ziehau 
467843c2aeb0SSepherosa Ziehau 		sc->used_tx_bd--;
467943c2aeb0SSepherosa Ziehau 		sw_tx_cons = NEXT_TX_BD(sw_tx_cons);
468043c2aeb0SSepherosa Ziehau 
468143c2aeb0SSepherosa Ziehau 		if (sw_tx_cons == hw_tx_cons) {
468243c2aeb0SSepherosa Ziehau 			/* Refresh hw_cons to see if there's new work. */
468324603545SSepherosa Ziehau 			hw_tx_cons = sc->hw_tx_cons = bce_get_hw_tx_cons(sc);
468443c2aeb0SSepherosa Ziehau 		}
468543c2aeb0SSepherosa Ziehau 
468643c2aeb0SSepherosa Ziehau 		/*
468743c2aeb0SSepherosa Ziehau 		 * Prevent speculative reads from getting
468843c2aeb0SSepherosa Ziehau 		 * ahead of the status block.
468943c2aeb0SSepherosa Ziehau 		 */
469043c2aeb0SSepherosa Ziehau 		bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
469143c2aeb0SSepherosa Ziehau 				  BUS_SPACE_BARRIER_READ);
469243c2aeb0SSepherosa Ziehau 	}
469343c2aeb0SSepherosa Ziehau 
469443c2aeb0SSepherosa Ziehau 	if (sc->used_tx_bd == 0) {
469543c2aeb0SSepherosa Ziehau 		/* Clear the TX timeout timer. */
469643c2aeb0SSepherosa Ziehau 		ifp->if_timer = 0;
469743c2aeb0SSepherosa Ziehau 	}
469843c2aeb0SSepherosa Ziehau 
469943c2aeb0SSepherosa Ziehau 	/* Clear the tx hardware queue full flag. */
470043c2aeb0SSepherosa Ziehau 	if (sc->max_tx_bd - sc->used_tx_bd >= BCE_TX_SPARE_SPACE) {
470143c2aeb0SSepherosa Ziehau 		DBRUNIF((ifp->if_flags & IFF_OACTIVE),
470243c2aeb0SSepherosa Ziehau 			DBPRINT(sc, BCE_WARN_SEND,
470343c2aeb0SSepherosa Ziehau 				"%s(): Open TX chain! %d/%d (used/total)\n",
470443c2aeb0SSepherosa Ziehau 				__func__, sc->used_tx_bd, sc->max_tx_bd));
470543c2aeb0SSepherosa Ziehau 		ifp->if_flags &= ~IFF_OACTIVE;
470643c2aeb0SSepherosa Ziehau 	}
470743c2aeb0SSepherosa Ziehau 	sc->tx_cons = sw_tx_cons;
470843c2aeb0SSepherosa Ziehau }
470943c2aeb0SSepherosa Ziehau 
471043c2aeb0SSepherosa Ziehau 
471143c2aeb0SSepherosa Ziehau /****************************************************************************/
471243c2aeb0SSepherosa Ziehau /* Disables interrupt generation.                                           */
471343c2aeb0SSepherosa Ziehau /*                                                                          */
471443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
471543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
471643c2aeb0SSepherosa Ziehau /****************************************************************************/
471743c2aeb0SSepherosa Ziehau static void
471843c2aeb0SSepherosa Ziehau bce_disable_intr(struct bce_softc *sc)
471943c2aeb0SSepherosa Ziehau {
472043c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, BCE_PCICFG_INT_ACK_CMD_MASK_INT);
472143c2aeb0SSepherosa Ziehau 	REG_RD(sc, BCE_PCICFG_INT_ACK_CMD);
472243c2aeb0SSepherosa Ziehau 	lwkt_serialize_handler_disable(sc->arpcom.ac_if.if_serializer);
472343c2aeb0SSepherosa Ziehau }
472443c2aeb0SSepherosa Ziehau 
472543c2aeb0SSepherosa Ziehau 
472643c2aeb0SSepherosa Ziehau /****************************************************************************/
472743c2aeb0SSepherosa Ziehau /* Enables interrupt generation.                                            */
472843c2aeb0SSepherosa Ziehau /*                                                                          */
472943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
473043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
473143c2aeb0SSepherosa Ziehau /****************************************************************************/
473243c2aeb0SSepherosa Ziehau static void
4733d0092544SSepherosa Ziehau bce_enable_intr(struct bce_softc *sc, int coal_now)
473443c2aeb0SSepherosa Ziehau {
473543c2aeb0SSepherosa Ziehau 	lwkt_serialize_handler_enable(sc->arpcom.ac_if.if_serializer);
473643c2aeb0SSepherosa Ziehau 
473743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
473843c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID |
473943c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_MASK_INT | sc->last_status_idx);
474043c2aeb0SSepherosa Ziehau 
474143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
474243c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx);
474343c2aeb0SSepherosa Ziehau 
4744d0092544SSepherosa Ziehau 	if (coal_now) {
4745d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_HC_COMMAND,
4746d0092544SSepherosa Ziehau 		    sc->hc_command | BCE_HC_COMMAND_COAL_NOW);
4747d0092544SSepherosa Ziehau 	}
474843c2aeb0SSepherosa Ziehau }
474943c2aeb0SSepherosa Ziehau 
475043c2aeb0SSepherosa Ziehau 
475143c2aeb0SSepherosa Ziehau /****************************************************************************/
475243c2aeb0SSepherosa Ziehau /* Handles controller initialization.                                       */
475343c2aeb0SSepherosa Ziehau /*                                                                          */
475443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
475543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
475643c2aeb0SSepherosa Ziehau /****************************************************************************/
475743c2aeb0SSepherosa Ziehau static void
475843c2aeb0SSepherosa Ziehau bce_init(void *xsc)
475943c2aeb0SSepherosa Ziehau {
476043c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = xsc;
476143c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
476243c2aeb0SSepherosa Ziehau 	uint32_t ether_mtu;
476343c2aeb0SSepherosa Ziehau 	int error;
476443c2aeb0SSepherosa Ziehau 
476543c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
476643c2aeb0SSepherosa Ziehau 
476743c2aeb0SSepherosa Ziehau 	/* Check if the driver is still running and bail out if it is. */
476843c2aeb0SSepherosa Ziehau 	if (ifp->if_flags & IFF_RUNNING)
476943c2aeb0SSepherosa Ziehau 		return;
477043c2aeb0SSepherosa Ziehau 
477143c2aeb0SSepherosa Ziehau 	bce_stop(sc);
477243c2aeb0SSepherosa Ziehau 
477343c2aeb0SSepherosa Ziehau 	error = bce_reset(sc, BCE_DRV_MSG_CODE_RESET);
477443c2aeb0SSepherosa Ziehau 	if (error) {
477543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Controller reset failed!\n");
477643c2aeb0SSepherosa Ziehau 		goto back;
477743c2aeb0SSepherosa Ziehau 	}
477843c2aeb0SSepherosa Ziehau 
477943c2aeb0SSepherosa Ziehau 	error = bce_chipinit(sc);
478043c2aeb0SSepherosa Ziehau 	if (error) {
478143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Controller initialization failed!\n");
478243c2aeb0SSepherosa Ziehau 		goto back;
478343c2aeb0SSepherosa Ziehau 	}
478443c2aeb0SSepherosa Ziehau 
478543c2aeb0SSepherosa Ziehau 	error = bce_blockinit(sc);
478643c2aeb0SSepherosa Ziehau 	if (error) {
478743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Block initialization failed!\n");
478843c2aeb0SSepherosa Ziehau 		goto back;
478943c2aeb0SSepherosa Ziehau 	}
479043c2aeb0SSepherosa Ziehau 
479143c2aeb0SSepherosa Ziehau 	/* Load our MAC address. */
479243c2aeb0SSepherosa Ziehau 	bcopy(IF_LLADDR(ifp), sc->eaddr, ETHER_ADDR_LEN);
479343c2aeb0SSepherosa Ziehau 	bce_set_mac_addr(sc);
479443c2aeb0SSepherosa Ziehau 
479543c2aeb0SSepherosa Ziehau 	/* Calculate and program the Ethernet MTU size. */
479643c2aeb0SSepherosa Ziehau 	ether_mtu = ETHER_HDR_LEN + EVL_ENCAPLEN + ifp->if_mtu + ETHER_CRC_LEN;
479743c2aeb0SSepherosa Ziehau 
479843c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "%s(): setting mtu = %d\n", __func__, ether_mtu);
479943c2aeb0SSepherosa Ziehau 
480043c2aeb0SSepherosa Ziehau 	/*
480143c2aeb0SSepherosa Ziehau 	 * Program the mtu, enabling jumbo frame
480243c2aeb0SSepherosa Ziehau 	 * support if necessary.  Also set the mbuf
480343c2aeb0SSepherosa Ziehau 	 * allocation count for RX frames.
480443c2aeb0SSepherosa Ziehau 	 */
480543c2aeb0SSepherosa Ziehau 	if (ether_mtu > ETHER_MAX_LEN + EVL_ENCAPLEN) {
480643c2aeb0SSepherosa Ziehau #ifdef notyet
480743c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_RX_MTU_SIZE,
480843c2aeb0SSepherosa Ziehau 		       min(ether_mtu, BCE_MAX_JUMBO_ETHER_MTU) |
480943c2aeb0SSepherosa Ziehau 		       BCE_EMAC_RX_MTU_SIZE_JUMBO_ENA);
481043c2aeb0SSepherosa Ziehau 		sc->mbuf_alloc_size = MJUM9BYTES;
481143c2aeb0SSepherosa Ziehau #else
481243c2aeb0SSepherosa Ziehau 		panic("jumbo buffer is not supported yet\n");
481343c2aeb0SSepherosa Ziehau #endif
481443c2aeb0SSepherosa Ziehau 	} else {
481543c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, ether_mtu);
481643c2aeb0SSepherosa Ziehau 		sc->mbuf_alloc_size = MCLBYTES;
481743c2aeb0SSepherosa Ziehau 	}
481843c2aeb0SSepherosa Ziehau 
481943c2aeb0SSepherosa Ziehau 	/* Calculate the RX Ethernet frame size for rx_bd's. */
482043c2aeb0SSepherosa Ziehau 	sc->max_frame_size = sizeof(struct l2_fhdr) + 2 + ether_mtu + 8;
482143c2aeb0SSepherosa Ziehau 
482243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO,
482343c2aeb0SSepherosa Ziehau 		"%s(): mclbytes = %d, mbuf_alloc_size = %d, "
482443c2aeb0SSepherosa Ziehau 		"max_frame_size = %d\n",
482543c2aeb0SSepherosa Ziehau 		__func__, (int)MCLBYTES, sc->mbuf_alloc_size,
482643c2aeb0SSepherosa Ziehau 		sc->max_frame_size);
482743c2aeb0SSepherosa Ziehau 
482843c2aeb0SSepherosa Ziehau 	/* Program appropriate promiscuous/multicast filtering. */
482943c2aeb0SSepherosa Ziehau 	bce_set_rx_mode(sc);
483043c2aeb0SSepherosa Ziehau 
483143c2aeb0SSepherosa Ziehau 	/* Init RX buffer descriptor chain. */
483243c2aeb0SSepherosa Ziehau 	bce_init_rx_chain(sc);	/* XXX return value */
483343c2aeb0SSepherosa Ziehau 
483443c2aeb0SSepherosa Ziehau 	/* Init TX buffer descriptor chain. */
483543c2aeb0SSepherosa Ziehau 	bce_init_tx_chain(sc);	/* XXX return value */
483643c2aeb0SSepherosa Ziehau 
483743c2aeb0SSepherosa Ziehau #ifdef DEVICE_POLLING
483843c2aeb0SSepherosa Ziehau 	/* Disable interrupts if we are polling. */
483943c2aeb0SSepherosa Ziehau 	if (ifp->if_flags & IFF_POLLING) {
484043c2aeb0SSepherosa Ziehau 		bce_disable_intr(sc);
484143c2aeb0SSepherosa Ziehau 
484243c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
484343c2aeb0SSepherosa Ziehau 		       (1 << 16) | sc->bce_rx_quick_cons_trip);
484443c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
484543c2aeb0SSepherosa Ziehau 		       (1 << 16) | sc->bce_tx_quick_cons_trip);
484643c2aeb0SSepherosa Ziehau 	} else
484743c2aeb0SSepherosa Ziehau #endif
484843c2aeb0SSepherosa Ziehau 	/* Enable host interrupts. */
4849d0092544SSepherosa Ziehau 	bce_enable_intr(sc, 1);
485043c2aeb0SSepherosa Ziehau 
485143c2aeb0SSepherosa Ziehau 	bce_ifmedia_upd(ifp);
485243c2aeb0SSepherosa Ziehau 
485343c2aeb0SSepherosa Ziehau 	ifp->if_flags |= IFF_RUNNING;
485443c2aeb0SSepherosa Ziehau 	ifp->if_flags &= ~IFF_OACTIVE;
485543c2aeb0SSepherosa Ziehau 
4856d0092544SSepherosa Ziehau 	callout_reset(&sc->bce_tick_callout, hz, bce_tick, sc);
485743c2aeb0SSepherosa Ziehau back:
485843c2aeb0SSepherosa Ziehau 	if (error)
485943c2aeb0SSepherosa Ziehau 		bce_stop(sc);
486043c2aeb0SSepherosa Ziehau }
486143c2aeb0SSepherosa Ziehau 
486243c2aeb0SSepherosa Ziehau 
486343c2aeb0SSepherosa Ziehau /****************************************************************************/
486443c2aeb0SSepherosa Ziehau /* Initialize the controller just enough so that any management firmware    */
486543c2aeb0SSepherosa Ziehau /* running on the device will continue to operate corectly.                 */
486643c2aeb0SSepherosa Ziehau /*                                                                          */
486743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
486843c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
486943c2aeb0SSepherosa Ziehau /****************************************************************************/
487043c2aeb0SSepherosa Ziehau static void
487143c2aeb0SSepherosa Ziehau bce_mgmt_init(struct bce_softc *sc)
487243c2aeb0SSepherosa Ziehau {
487343c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
487443c2aeb0SSepherosa Ziehau 
4875d0092544SSepherosa Ziehau 	/* Bail out if management firmware is not running. */
4876d0092544SSepherosa Ziehau 	if (!(sc->bce_flags & BCE_MFW_ENABLE_FLAG))
487743c2aeb0SSepherosa Ziehau 		return;
487843c2aeb0SSepherosa Ziehau 
487943c2aeb0SSepherosa Ziehau 	/* Enable all critical blocks in the MAC. */
4880d0092544SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 ||
4881d0092544SSepherosa Ziehau 	    BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) {
488243c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
4883d0092544SSepherosa Ziehau 		    BCE_MISC_ENABLE_DEFAULT_XI);
4884d0092544SSepherosa Ziehau 	} else {
4885d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, BCE_MISC_ENABLE_DEFAULT);
4886d0092544SSepherosa Ziehau 	}
488743c2aeb0SSepherosa Ziehau 	REG_RD(sc, BCE_MISC_ENABLE_SET_BITS);
488843c2aeb0SSepherosa Ziehau 	DELAY(20);
488943c2aeb0SSepherosa Ziehau 
489043c2aeb0SSepherosa Ziehau 	bce_ifmedia_upd(ifp);
489143c2aeb0SSepherosa Ziehau }
489243c2aeb0SSepherosa Ziehau 
489343c2aeb0SSepherosa Ziehau 
489443c2aeb0SSepherosa Ziehau /****************************************************************************/
489543c2aeb0SSepherosa Ziehau /* Encapsultes an mbuf cluster into the tx_bd chain structure and makes the */
489643c2aeb0SSepherosa Ziehau /* memory visible to the controller.                                        */
489743c2aeb0SSepherosa Ziehau /*                                                                          */
489843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
489943c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
490043c2aeb0SSepherosa Ziehau /****************************************************************************/
490143c2aeb0SSepherosa Ziehau static int
490243c2aeb0SSepherosa Ziehau bce_encap(struct bce_softc *sc, struct mbuf **m_head)
490343c2aeb0SSepherosa Ziehau {
490443c2aeb0SSepherosa Ziehau 	bus_dma_segment_t segs[BCE_MAX_SEGMENTS];
490543c2aeb0SSepherosa Ziehau 	bus_dmamap_t map, tmp_map;
490643c2aeb0SSepherosa Ziehau 	struct mbuf *m0 = *m_head;
490743c2aeb0SSepherosa Ziehau 	struct tx_bd *txbd = NULL;
490843c2aeb0SSepherosa Ziehau 	uint16_t vlan_tag = 0, flags = 0;
490943c2aeb0SSepherosa Ziehau 	uint16_t chain_prod, chain_prod_start, prod;
491043c2aeb0SSepherosa Ziehau 	uint32_t prod_bseq;
4911ba0809ceSSepherosa Ziehau 	int i, error, maxsegs, nsegs;
491243c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
491343c2aeb0SSepherosa Ziehau 	uint16_t debug_prod;
491443c2aeb0SSepherosa Ziehau #endif
491543c2aeb0SSepherosa Ziehau 
491643c2aeb0SSepherosa Ziehau 	/* Transfer any checksum offload flags to the bd. */
491743c2aeb0SSepherosa Ziehau 	if (m0->m_pkthdr.csum_flags) {
491843c2aeb0SSepherosa Ziehau 		if (m0->m_pkthdr.csum_flags & CSUM_IP)
491943c2aeb0SSepherosa Ziehau 			flags |= TX_BD_FLAGS_IP_CKSUM;
492043c2aeb0SSepherosa Ziehau 		if (m0->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))
492143c2aeb0SSepherosa Ziehau 			flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
492243c2aeb0SSepherosa Ziehau 	}
492343c2aeb0SSepherosa Ziehau 
492443c2aeb0SSepherosa Ziehau 	/* Transfer any VLAN tags to the bd. */
492583790f85SSepherosa Ziehau 	if (m0->m_flags & M_VLANTAG) {
492643c2aeb0SSepherosa Ziehau 		flags |= TX_BD_FLAGS_VLAN_TAG;
492783790f85SSepherosa Ziehau 		vlan_tag = m0->m_pkthdr.ether_vlantag;
492843c2aeb0SSepherosa Ziehau 	}
492943c2aeb0SSepherosa Ziehau 
493043c2aeb0SSepherosa Ziehau 	prod = sc->tx_prod;
493143c2aeb0SSepherosa Ziehau 	chain_prod_start = chain_prod = TX_CHAIN_IDX(prod);
493243c2aeb0SSepherosa Ziehau 
493343c2aeb0SSepherosa Ziehau 	/* Map the mbuf into DMAable memory. */
493443c2aeb0SSepherosa Ziehau 	map = sc->tx_mbuf_map[chain_prod_start];
493543c2aeb0SSepherosa Ziehau 
493643c2aeb0SSepherosa Ziehau 	maxsegs = sc->max_tx_bd - sc->used_tx_bd;
493743c2aeb0SSepherosa Ziehau 	KASSERT(maxsegs >= BCE_TX_SPARE_SPACE,
493843c2aeb0SSepherosa Ziehau 		("not enough segements %d\n", maxsegs));
493943c2aeb0SSepherosa Ziehau 	if (maxsegs > BCE_MAX_SEGMENTS)
494043c2aeb0SSepherosa Ziehau 		maxsegs = BCE_MAX_SEGMENTS;
494143c2aeb0SSepherosa Ziehau 
494243c2aeb0SSepherosa Ziehau 	/* Map the mbuf into our DMA address space. */
4943ba0809ceSSepherosa Ziehau 	error = bus_dmamap_load_mbuf_defrag(sc->tx_mbuf_tag, map, m_head,
4944ba0809ceSSepherosa Ziehau 			segs, maxsegs, &nsegs, BUS_DMA_NOWAIT);
4945ba0809ceSSepherosa Ziehau 	if (error)
4946ba0809ceSSepherosa Ziehau 		goto back;
4947ba0809ceSSepherosa Ziehau 	bus_dmamap_sync(sc->tx_mbuf_tag, map, BUS_DMASYNC_PREWRITE);
494843c2aeb0SSepherosa Ziehau 
4949ba0809ceSSepherosa Ziehau 	/* Reset m0 */
4950ba0809ceSSepherosa Ziehau 	m0 = *m_head;
495143c2aeb0SSepherosa Ziehau 
495243c2aeb0SSepherosa Ziehau 	/* prod points to an empty tx_bd at this point. */
495343c2aeb0SSepherosa Ziehau 	prod_bseq  = sc->tx_prod_bseq;
495443c2aeb0SSepherosa Ziehau 
495543c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
495643c2aeb0SSepherosa Ziehau 	debug_prod = chain_prod;
495743c2aeb0SSepherosa Ziehau #endif
495843c2aeb0SSepherosa Ziehau 
495943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_SEND,
496043c2aeb0SSepherosa Ziehau 		"%s(): Start: prod = 0x%04X, chain_prod = %04X, "
496143c2aeb0SSepherosa Ziehau 		"prod_bseq = 0x%08X\n",
496243c2aeb0SSepherosa Ziehau 		__func__, prod, chain_prod, prod_bseq);
496343c2aeb0SSepherosa Ziehau 
496443c2aeb0SSepherosa Ziehau 	/*
496543c2aeb0SSepherosa Ziehau 	 * Cycle through each mbuf segment that makes up
496643c2aeb0SSepherosa Ziehau 	 * the outgoing frame, gathering the mapping info
496743c2aeb0SSepherosa Ziehau 	 * for that segment and creating a tx_bd to for
496843c2aeb0SSepherosa Ziehau 	 * the mbuf.
496943c2aeb0SSepherosa Ziehau 	 */
4970ba0809ceSSepherosa Ziehau 	for (i = 0; i < nsegs; i++) {
497143c2aeb0SSepherosa Ziehau 		chain_prod = TX_CHAIN_IDX(prod);
497243c2aeb0SSepherosa Ziehau 		txbd= &sc->tx_bd_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)];
497343c2aeb0SSepherosa Ziehau 
497443c2aeb0SSepherosa Ziehau 		txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr));
497543c2aeb0SSepherosa Ziehau 		txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr));
497643c2aeb0SSepherosa Ziehau 		txbd->tx_bd_mss_nbytes = htole16(segs[i].ds_len);
497743c2aeb0SSepherosa Ziehau 		txbd->tx_bd_vlan_tag = htole16(vlan_tag);
497843c2aeb0SSepherosa Ziehau 		txbd->tx_bd_flags = htole16(flags);
497943c2aeb0SSepherosa Ziehau 		prod_bseq += segs[i].ds_len;
498043c2aeb0SSepherosa Ziehau 		if (i == 0)
498143c2aeb0SSepherosa Ziehau 			txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_START);
498243c2aeb0SSepherosa Ziehau 		prod = NEXT_TX_BD(prod);
498343c2aeb0SSepherosa Ziehau 	}
498443c2aeb0SSepherosa Ziehau 
498543c2aeb0SSepherosa Ziehau 	/* Set the END flag on the last TX buffer descriptor. */
498643c2aeb0SSepherosa Ziehau 	txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_END);
498743c2aeb0SSepherosa Ziehau 
498843c2aeb0SSepherosa Ziehau 	DBRUN(BCE_EXCESSIVE_SEND,
49891663812cSSepherosa Ziehau 	      bce_dump_tx_chain(sc, debug_prod, nsegs));
499043c2aeb0SSepherosa Ziehau 
499143c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_SEND,
499243c2aeb0SSepherosa Ziehau 		"%s(): End: prod = 0x%04X, chain_prod = %04X, "
499343c2aeb0SSepherosa Ziehau 		"prod_bseq = 0x%08X\n",
499443c2aeb0SSepherosa Ziehau 		__func__, prod, chain_prod, prod_bseq);
499543c2aeb0SSepherosa Ziehau 
499643c2aeb0SSepherosa Ziehau 	/*
499743c2aeb0SSepherosa Ziehau 	 * Ensure that the mbuf pointer for this transmission
499843c2aeb0SSepherosa Ziehau 	 * is placed at the array index of the last
499943c2aeb0SSepherosa Ziehau 	 * descriptor in this chain.  This is done
500043c2aeb0SSepherosa Ziehau 	 * because a single map is used for all
500143c2aeb0SSepherosa Ziehau 	 * segments of the mbuf and we don't want to
500243c2aeb0SSepherosa Ziehau 	 * unload the map before all of the segments
500343c2aeb0SSepherosa Ziehau 	 * have been freed.
500443c2aeb0SSepherosa Ziehau 	 */
500543c2aeb0SSepherosa Ziehau 	sc->tx_mbuf_ptr[chain_prod] = m0;
500643c2aeb0SSepherosa Ziehau 
500743c2aeb0SSepherosa Ziehau 	tmp_map = sc->tx_mbuf_map[chain_prod];
500843c2aeb0SSepherosa Ziehau 	sc->tx_mbuf_map[chain_prod] = map;
500943c2aeb0SSepherosa Ziehau 	sc->tx_mbuf_map[chain_prod_start] = tmp_map;
501043c2aeb0SSepherosa Ziehau 
5011ba0809ceSSepherosa Ziehau 	sc->used_tx_bd += nsegs;
501243c2aeb0SSepherosa Ziehau 
501343c2aeb0SSepherosa Ziehau 	/* Update some debug statistic counters */
501443c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->used_tx_bd > sc->tx_hi_watermark),
501543c2aeb0SSepherosa Ziehau 		sc->tx_hi_watermark = sc->used_tx_bd);
501643c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->used_tx_bd == sc->max_tx_bd), sc->tx_full_count++);
501743c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->tx_mbuf_alloc++);
501843c2aeb0SSepherosa Ziehau 
501943c2aeb0SSepherosa Ziehau 	DBRUN(BCE_VERBOSE_SEND,
50201663812cSSepherosa Ziehau 	      bce_dump_tx_mbuf_chain(sc, chain_prod, nsegs));
502143c2aeb0SSepherosa Ziehau 
502243c2aeb0SSepherosa Ziehau 	/* prod points to the next free tx_bd at this point. */
502343c2aeb0SSepherosa Ziehau 	sc->tx_prod = prod;
502443c2aeb0SSepherosa Ziehau 	sc->tx_prod_bseq = prod_bseq;
502543c2aeb0SSepherosa Ziehau back:
502643c2aeb0SSepherosa Ziehau 	if (error) {
502743c2aeb0SSepherosa Ziehau 		m_freem(*m_head);
502843c2aeb0SSepherosa Ziehau 		*m_head = NULL;
502943c2aeb0SSepherosa Ziehau 	}
503043c2aeb0SSepherosa Ziehau 	return error;
503143c2aeb0SSepherosa Ziehau }
503243c2aeb0SSepherosa Ziehau 
503343c2aeb0SSepherosa Ziehau 
503443c2aeb0SSepherosa Ziehau /****************************************************************************/
503543c2aeb0SSepherosa Ziehau /* Main transmit routine when called from another routine with a lock.      */
503643c2aeb0SSepherosa Ziehau /*                                                                          */
503743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
503843c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
503943c2aeb0SSepherosa Ziehau /****************************************************************************/
504043c2aeb0SSepherosa Ziehau static void
504143c2aeb0SSepherosa Ziehau bce_start(struct ifnet *ifp)
504243c2aeb0SSepherosa Ziehau {
504343c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
504443c2aeb0SSepherosa Ziehau 	int count = 0;
504543c2aeb0SSepherosa Ziehau 
504643c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
504743c2aeb0SSepherosa Ziehau 
504843c2aeb0SSepherosa Ziehau 	/* If there's no link or the transmit queue is empty then just exit. */
50499db4b353SSepherosa Ziehau 	if (!sc->bce_link) {
50509db4b353SSepherosa Ziehau 		ifq_purge(&ifp->if_snd);
50519db4b353SSepherosa Ziehau 		return;
50529db4b353SSepherosa Ziehau 	}
50539db4b353SSepherosa Ziehau 
50549db4b353SSepherosa Ziehau 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
505543c2aeb0SSepherosa Ziehau 		return;
505643c2aeb0SSepherosa Ziehau 
505743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_SEND,
5058664f5072SSascha Wildner 		"%s(): Start: tx_prod = 0x%04X, tx_chain_prod = %04zX, "
505943c2aeb0SSepherosa Ziehau 		"tx_prod_bseq = 0x%08X\n",
506043c2aeb0SSepherosa Ziehau 		__func__,
506143c2aeb0SSepherosa Ziehau 		sc->tx_prod, TX_CHAIN_IDX(sc->tx_prod), sc->tx_prod_bseq);
506243c2aeb0SSepherosa Ziehau 
506343c2aeb0SSepherosa Ziehau 	for (;;) {
506443c2aeb0SSepherosa Ziehau 		struct mbuf *m_head;
506543c2aeb0SSepherosa Ziehau 
506643c2aeb0SSepherosa Ziehau 		/*
506743c2aeb0SSepherosa Ziehau 		 * We keep BCE_TX_SPARE_SPACE entries, so bce_encap() is
506843c2aeb0SSepherosa Ziehau 		 * unlikely to fail.
506943c2aeb0SSepherosa Ziehau 		 */
507043c2aeb0SSepherosa Ziehau 		if (sc->max_tx_bd - sc->used_tx_bd < BCE_TX_SPARE_SPACE) {
507143c2aeb0SSepherosa Ziehau 			ifp->if_flags |= IFF_OACTIVE;
507243c2aeb0SSepherosa Ziehau 			break;
507343c2aeb0SSepherosa Ziehau 		}
507443c2aeb0SSepherosa Ziehau 
507543c2aeb0SSepherosa Ziehau 		/* Check for any frames to send. */
507643c2aeb0SSepherosa Ziehau 		m_head = ifq_dequeue(&ifp->if_snd, NULL);
507743c2aeb0SSepherosa Ziehau 		if (m_head == NULL)
507843c2aeb0SSepherosa Ziehau 			break;
507943c2aeb0SSepherosa Ziehau 
508043c2aeb0SSepherosa Ziehau 		/*
508143c2aeb0SSepherosa Ziehau 		 * Pack the data into the transmit ring. If we
508243c2aeb0SSepherosa Ziehau 		 * don't have room, place the mbuf back at the
508343c2aeb0SSepherosa Ziehau 		 * head of the queue and set the OACTIVE flag
508443c2aeb0SSepherosa Ziehau 		 * to wait for the NIC to drain the chain.
508543c2aeb0SSepherosa Ziehau 		 */
508643c2aeb0SSepherosa Ziehau 		if (bce_encap(sc, &m_head)) {
5087ba0809ceSSepherosa Ziehau 			ifp->if_oerrors++;
5088ba0809ceSSepherosa Ziehau 			if (sc->used_tx_bd == 0) {
5089ba0809ceSSepherosa Ziehau 				continue;
5090ba0809ceSSepherosa Ziehau 			} else {
509143c2aeb0SSepherosa Ziehau 				ifp->if_flags |= IFF_OACTIVE;
509243c2aeb0SSepherosa Ziehau 				break;
509343c2aeb0SSepherosa Ziehau 			}
5094ba0809ceSSepherosa Ziehau 		}
509543c2aeb0SSepherosa Ziehau 
509643c2aeb0SSepherosa Ziehau 		count++;
509743c2aeb0SSepherosa Ziehau 
509843c2aeb0SSepherosa Ziehau 		/* Send a copy of the frame to any BPF listeners. */
5099b637f170SSepherosa Ziehau 		ETHER_BPF_MTAP(ifp, m_head);
510043c2aeb0SSepherosa Ziehau 	}
510143c2aeb0SSepherosa Ziehau 
510243c2aeb0SSepherosa Ziehau 	if (count == 0) {
510343c2aeb0SSepherosa Ziehau 		/* no packets were dequeued */
510443c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE_SEND,
510543c2aeb0SSepherosa Ziehau 			"%s(): No packets were dequeued\n", __func__);
510643c2aeb0SSepherosa Ziehau 		return;
510743c2aeb0SSepherosa Ziehau 	}
510843c2aeb0SSepherosa Ziehau 
510943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_SEND,
5110664f5072SSascha Wildner 		"%s(): End: tx_prod = 0x%04X, tx_chain_prod = 0x%04zX, "
511143c2aeb0SSepherosa Ziehau 		"tx_prod_bseq = 0x%08X\n",
511243c2aeb0SSepherosa Ziehau 		__func__,
511343c2aeb0SSepherosa Ziehau 		sc->tx_prod, TX_CHAIN_IDX(sc->tx_prod), sc->tx_prod_bseq);
511443c2aeb0SSepherosa Ziehau 
5115d0092544SSepherosa Ziehau 	REG_WR(sc, BCE_MQ_COMMAND,
5116d0092544SSepherosa Ziehau 	    REG_RD(sc, BCE_MQ_COMMAND) | BCE_MQ_COMMAND_NO_MAP_ERROR);
5117d0092544SSepherosa Ziehau 
511843c2aeb0SSepherosa Ziehau 	/* Start the transmit. */
5119d0092544SSepherosa Ziehau 	REG_WR16(sc, MB_GET_CID_ADDR(TX_CID) + BCE_L2CTX_TX_HOST_BIDX, sc->tx_prod);
5120d0092544SSepherosa Ziehau 	REG_WR(sc, MB_GET_CID_ADDR(TX_CID) + BCE_L2CTX_TX_HOST_BSEQ, sc->tx_prod_bseq);
512143c2aeb0SSepherosa Ziehau 
512243c2aeb0SSepherosa Ziehau 	/* Set the tx timeout. */
512343c2aeb0SSepherosa Ziehau 	ifp->if_timer = BCE_TX_TIMEOUT;
512443c2aeb0SSepherosa Ziehau }
512543c2aeb0SSepherosa Ziehau 
512643c2aeb0SSepherosa Ziehau 
512743c2aeb0SSepherosa Ziehau /****************************************************************************/
512843c2aeb0SSepherosa Ziehau /* Handles any IOCTL calls from the operating system.                       */
512943c2aeb0SSepherosa Ziehau /*                                                                          */
513043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
513143c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
513243c2aeb0SSepherosa Ziehau /****************************************************************************/
513343c2aeb0SSepherosa Ziehau static int
513443c2aeb0SSepherosa Ziehau bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
513543c2aeb0SSepherosa Ziehau {
513643c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
513743c2aeb0SSepherosa Ziehau 	struct ifreq *ifr = (struct ifreq *)data;
513843c2aeb0SSepherosa Ziehau 	struct mii_data *mii;
513943c2aeb0SSepherosa Ziehau 	int mask, error = 0;
514043c2aeb0SSepherosa Ziehau 
514143c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
514243c2aeb0SSepherosa Ziehau 
514343c2aeb0SSepherosa Ziehau 	switch(command) {
514443c2aeb0SSepherosa Ziehau 	case SIOCSIFMTU:
514543c2aeb0SSepherosa Ziehau 		/* Check that the MTU setting is supported. */
514643c2aeb0SSepherosa Ziehau 		if (ifr->ifr_mtu < BCE_MIN_MTU ||
514743c2aeb0SSepherosa Ziehau #ifdef notyet
514843c2aeb0SSepherosa Ziehau 		    ifr->ifr_mtu > BCE_MAX_JUMBO_MTU
514943c2aeb0SSepherosa Ziehau #else
515043c2aeb0SSepherosa Ziehau 		    ifr->ifr_mtu > ETHERMTU
515143c2aeb0SSepherosa Ziehau #endif
515243c2aeb0SSepherosa Ziehau 		   ) {
515343c2aeb0SSepherosa Ziehau 			error = EINVAL;
515443c2aeb0SSepherosa Ziehau 			break;
515543c2aeb0SSepherosa Ziehau 		}
515643c2aeb0SSepherosa Ziehau 
515743c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting new MTU of %d\n", ifr->ifr_mtu);
515843c2aeb0SSepherosa Ziehau 
515943c2aeb0SSepherosa Ziehau 		ifp->if_mtu = ifr->ifr_mtu;
516043c2aeb0SSepherosa Ziehau 		ifp->if_flags &= ~IFF_RUNNING;	/* Force reinitialize */
516143c2aeb0SSepherosa Ziehau 		bce_init(sc);
516243c2aeb0SSepherosa Ziehau 		break;
516343c2aeb0SSepherosa Ziehau 
516443c2aeb0SSepherosa Ziehau 	case SIOCSIFFLAGS:
516543c2aeb0SSepherosa Ziehau 		if (ifp->if_flags & IFF_UP) {
516643c2aeb0SSepherosa Ziehau 			if (ifp->if_flags & IFF_RUNNING) {
516743c2aeb0SSepherosa Ziehau 				mask = ifp->if_flags ^ sc->bce_if_flags;
516843c2aeb0SSepherosa Ziehau 
516943c2aeb0SSepherosa Ziehau 				if (mask & (IFF_PROMISC | IFF_ALLMULTI))
517043c2aeb0SSepherosa Ziehau 					bce_set_rx_mode(sc);
517143c2aeb0SSepherosa Ziehau 			} else {
517243c2aeb0SSepherosa Ziehau 				bce_init(sc);
517343c2aeb0SSepherosa Ziehau 			}
517443c2aeb0SSepherosa Ziehau 		} else if (ifp->if_flags & IFF_RUNNING) {
517543c2aeb0SSepherosa Ziehau 			bce_stop(sc);
5176d0092544SSepherosa Ziehau 
5177d0092544SSepherosa Ziehau 			/* If MFW is running, restart the controller a bit. */
5178d0092544SSepherosa Ziehau 			if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) {
5179d0092544SSepherosa Ziehau 				bce_reset(sc, BCE_DRV_MSG_CODE_RESET);
5180d0092544SSepherosa Ziehau 				bce_chipinit(sc);
5181d0092544SSepherosa Ziehau 				bce_mgmt_init(sc);
5182d0092544SSepherosa Ziehau 			}
518343c2aeb0SSepherosa Ziehau 		}
518443c2aeb0SSepherosa Ziehau 		sc->bce_if_flags = ifp->if_flags;
518543c2aeb0SSepherosa Ziehau 		break;
518643c2aeb0SSepherosa Ziehau 
518743c2aeb0SSepherosa Ziehau 	case SIOCADDMULTI:
518843c2aeb0SSepherosa Ziehau 	case SIOCDELMULTI:
518943c2aeb0SSepherosa Ziehau 		if (ifp->if_flags & IFF_RUNNING)
519043c2aeb0SSepherosa Ziehau 			bce_set_rx_mode(sc);
519143c2aeb0SSepherosa Ziehau 		break;
519243c2aeb0SSepherosa Ziehau 
519343c2aeb0SSepherosa Ziehau 	case SIOCSIFMEDIA:
519443c2aeb0SSepherosa Ziehau 	case SIOCGIFMEDIA:
519543c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE, "bce_phy_flags = 0x%08X\n",
519643c2aeb0SSepherosa Ziehau 			sc->bce_phy_flags);
519743c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE, "Copper media set/get\n");
519843c2aeb0SSepherosa Ziehau 
519943c2aeb0SSepherosa Ziehau 		mii = device_get_softc(sc->bce_miibus);
520043c2aeb0SSepherosa Ziehau 		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
520143c2aeb0SSepherosa Ziehau 		break;
520243c2aeb0SSepherosa Ziehau 
520343c2aeb0SSepherosa Ziehau 	case SIOCSIFCAP:
520443c2aeb0SSepherosa Ziehau 		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
520543c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Received SIOCSIFCAP = 0x%08X\n",
520643c2aeb0SSepherosa Ziehau 			(uint32_t) mask);
520743c2aeb0SSepherosa Ziehau 
520843c2aeb0SSepherosa Ziehau 		if (mask & IFCAP_HWCSUM) {
520971e2c3e7SSepherosa Ziehau 			ifp->if_capenable ^= (mask & IFCAP_HWCSUM);
521043c2aeb0SSepherosa Ziehau 			if (IFCAP_HWCSUM & ifp->if_capenable)
521143c2aeb0SSepherosa Ziehau 				ifp->if_hwassist = BCE_IF_HWASSIST;
521243c2aeb0SSepherosa Ziehau 			else
521343c2aeb0SSepherosa Ziehau 				ifp->if_hwassist = 0;
521443c2aeb0SSepherosa Ziehau 		}
521543c2aeb0SSepherosa Ziehau 		break;
521643c2aeb0SSepherosa Ziehau 
521743c2aeb0SSepherosa Ziehau 	default:
521843c2aeb0SSepherosa Ziehau 		error = ether_ioctl(ifp, command, data);
521943c2aeb0SSepherosa Ziehau 		break;
522043c2aeb0SSepherosa Ziehau 	}
522143c2aeb0SSepherosa Ziehau 	return error;
522243c2aeb0SSepherosa Ziehau }
522343c2aeb0SSepherosa Ziehau 
522443c2aeb0SSepherosa Ziehau 
522543c2aeb0SSepherosa Ziehau /****************************************************************************/
522643c2aeb0SSepherosa Ziehau /* Transmit timeout handler.                                                */
522743c2aeb0SSepherosa Ziehau /*                                                                          */
522843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
522943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
523043c2aeb0SSepherosa Ziehau /****************************************************************************/
523143c2aeb0SSepherosa Ziehau static void
523243c2aeb0SSepherosa Ziehau bce_watchdog(struct ifnet *ifp)
523343c2aeb0SSepherosa Ziehau {
523443c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
523543c2aeb0SSepherosa Ziehau 
523643c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
523743c2aeb0SSepherosa Ziehau 
523843c2aeb0SSepherosa Ziehau 	DBRUN(BCE_VERBOSE_SEND,
523943c2aeb0SSepherosa Ziehau 	      bce_dump_driver_state(sc);
524043c2aeb0SSepherosa Ziehau 	      bce_dump_status_block(sc));
524143c2aeb0SSepherosa Ziehau 
524243c2aeb0SSepherosa Ziehau 	/*
524343c2aeb0SSepherosa Ziehau 	 * If we are in this routine because of pause frames, then
524443c2aeb0SSepherosa Ziehau 	 * don't reset the hardware.
524543c2aeb0SSepherosa Ziehau 	 */
524643c2aeb0SSepherosa Ziehau 	if (REG_RD(sc, BCE_EMAC_TX_STATUS) & BCE_EMAC_TX_STATUS_XOFFED)
524743c2aeb0SSepherosa Ziehau 		return;
524843c2aeb0SSepherosa Ziehau 
524943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "Watchdog timeout occurred, resetting!\n");
525043c2aeb0SSepherosa Ziehau 
525143c2aeb0SSepherosa Ziehau 	/* DBRUN(BCE_FATAL, bce_breakpoint(sc)); */
525243c2aeb0SSepherosa Ziehau 
525343c2aeb0SSepherosa Ziehau 	ifp->if_flags &= ~IFF_RUNNING;	/* Force reinitialize */
525443c2aeb0SSepherosa Ziehau 	bce_init(sc);
525543c2aeb0SSepherosa Ziehau 
525643c2aeb0SSepherosa Ziehau 	ifp->if_oerrors++;
525743c2aeb0SSepherosa Ziehau 
525843c2aeb0SSepherosa Ziehau 	if (!ifq_is_empty(&ifp->if_snd))
52599db4b353SSepherosa Ziehau 		if_devstart(ifp);
526043c2aeb0SSepherosa Ziehau }
526143c2aeb0SSepherosa Ziehau 
526243c2aeb0SSepherosa Ziehau 
526343c2aeb0SSepherosa Ziehau #ifdef DEVICE_POLLING
526443c2aeb0SSepherosa Ziehau 
526543c2aeb0SSepherosa Ziehau static void
526643c2aeb0SSepherosa Ziehau bce_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
526743c2aeb0SSepherosa Ziehau {
526843c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
526943c2aeb0SSepherosa Ziehau 	struct status_block *sblk = sc->status_block;
527024603545SSepherosa Ziehau 	uint16_t hw_tx_cons, hw_rx_cons;
527143c2aeb0SSepherosa Ziehau 
527243c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
527343c2aeb0SSepherosa Ziehau 
527443c2aeb0SSepherosa Ziehau 	switch (cmd) {
527543c2aeb0SSepherosa Ziehau 	case POLL_REGISTER:
527643c2aeb0SSepherosa Ziehau 		bce_disable_intr(sc);
527743c2aeb0SSepherosa Ziehau 
527843c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
527943c2aeb0SSepherosa Ziehau 		       (1 << 16) | sc->bce_rx_quick_cons_trip);
528043c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
528143c2aeb0SSepherosa Ziehau 		       (1 << 16) | sc->bce_tx_quick_cons_trip);
528243c2aeb0SSepherosa Ziehau 		return;
528343c2aeb0SSepherosa Ziehau 	case POLL_DEREGISTER:
5284d0092544SSepherosa Ziehau 		bce_enable_intr(sc, 1);
528543c2aeb0SSepherosa Ziehau 
528643c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
528743c2aeb0SSepherosa Ziehau 		       (sc->bce_tx_quick_cons_trip_int << 16) |
528843c2aeb0SSepherosa Ziehau 		       sc->bce_tx_quick_cons_trip);
528943c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
529043c2aeb0SSepherosa Ziehau 		       (sc->bce_rx_quick_cons_trip_int << 16) |
529143c2aeb0SSepherosa Ziehau 		       sc->bce_rx_quick_cons_trip);
529243c2aeb0SSepherosa Ziehau 		return;
529343c2aeb0SSepherosa Ziehau 	default:
529443c2aeb0SSepherosa Ziehau 		break;
529543c2aeb0SSepherosa Ziehau 	}
529643c2aeb0SSepherosa Ziehau 
529743c2aeb0SSepherosa Ziehau 	if (cmd == POLL_AND_CHECK_STATUS) {
529843c2aeb0SSepherosa Ziehau 		uint32_t status_attn_bits;
529943c2aeb0SSepherosa Ziehau 
530043c2aeb0SSepherosa Ziehau 		status_attn_bits = sblk->status_attn_bits;
530143c2aeb0SSepherosa Ziehau 
530243c2aeb0SSepherosa Ziehau 		DBRUNIF(DB_RANDOMTRUE(bce_debug_unexpected_attention),
530343c2aeb0SSepherosa Ziehau 			if_printf(ifp,
530443c2aeb0SSepherosa Ziehau 			"Simulating unexpected status attention bit set.");
530543c2aeb0SSepherosa Ziehau 			status_attn_bits |= STATUS_ATTN_BITS_PARITY_ERROR);
530643c2aeb0SSepherosa Ziehau 
530743c2aeb0SSepherosa Ziehau 		/* Was it a link change interrupt? */
530843c2aeb0SSepherosa Ziehau 		if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
530943c2aeb0SSepherosa Ziehau 		    (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE))
531043c2aeb0SSepherosa Ziehau 			bce_phy_intr(sc);
531143c2aeb0SSepherosa Ziehau 
5312d0092544SSepherosa Ziehau 		/* Clear any transient status updates during link state change. */
5313d0092544SSepherosa Ziehau 		REG_WR(sc, BCE_HC_COMMAND,
5314d0092544SSepherosa Ziehau 		    sc->hc_command | BCE_HC_COMMAND_COAL_NOW_WO_INT);
5315d0092544SSepherosa Ziehau 		REG_RD(sc, BCE_HC_COMMAND);
5316d0092544SSepherosa Ziehau 
531743c2aeb0SSepherosa Ziehau 		/*
531843c2aeb0SSepherosa Ziehau 		 * If any other attention is asserted then
531943c2aeb0SSepherosa Ziehau 		 * the chip is toast.
532043c2aeb0SSepherosa Ziehau 		 */
532143c2aeb0SSepherosa Ziehau 		if ((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) !=
532243c2aeb0SSepherosa Ziehau 		     (sblk->status_attn_bits_ack &
532343c2aeb0SSepherosa Ziehau 		      ~STATUS_ATTN_BITS_LINK_STATE)) {
532443c2aeb0SSepherosa Ziehau 			DBRUN(1, sc->unexpected_attentions++);
532543c2aeb0SSepherosa Ziehau 
532643c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Fatal attention detected: 0x%08X\n",
532743c2aeb0SSepherosa Ziehau 				  sblk->status_attn_bits);
532843c2aeb0SSepherosa Ziehau 
532943c2aeb0SSepherosa Ziehau 			DBRUN(BCE_FATAL,
533043c2aeb0SSepherosa Ziehau 			if (bce_debug_unexpected_attention == 0)
533143c2aeb0SSepherosa Ziehau 				bce_breakpoint(sc));
533243c2aeb0SSepherosa Ziehau 
533343c2aeb0SSepherosa Ziehau 			bce_init(sc);
533443c2aeb0SSepherosa Ziehau 			return;
533543c2aeb0SSepherosa Ziehau 		}
533643c2aeb0SSepherosa Ziehau 	}
533743c2aeb0SSepherosa Ziehau 
533824603545SSepherosa Ziehau 	hw_rx_cons = bce_get_hw_rx_cons(sc);
533924603545SSepherosa Ziehau 	hw_tx_cons = bce_get_hw_tx_cons(sc);
534024603545SSepherosa Ziehau 
534143c2aeb0SSepherosa Ziehau 	/* Check for any completed RX frames. */
534224603545SSepherosa Ziehau 	if (hw_rx_cons != sc->hw_rx_cons)
534343c2aeb0SSepherosa Ziehau 		bce_rx_intr(sc, count);
534443c2aeb0SSepherosa Ziehau 
534543c2aeb0SSepherosa Ziehau 	/* Check for any completed TX frames. */
534624603545SSepherosa Ziehau 	if (hw_tx_cons != sc->hw_tx_cons)
534743c2aeb0SSepherosa Ziehau 		bce_tx_intr(sc);
534843c2aeb0SSepherosa Ziehau 
534943c2aeb0SSepherosa Ziehau 	/* Check for new frames to transmit. */
535043c2aeb0SSepherosa Ziehau 	if (!ifq_is_empty(&ifp->if_snd))
53519db4b353SSepherosa Ziehau 		if_devstart(ifp);
535243c2aeb0SSepherosa Ziehau }
535343c2aeb0SSepherosa Ziehau 
535443c2aeb0SSepherosa Ziehau #endif	/* DEVICE_POLLING */
535543c2aeb0SSepherosa Ziehau 
535643c2aeb0SSepherosa Ziehau 
535743c2aeb0SSepherosa Ziehau /*
535843c2aeb0SSepherosa Ziehau  * Interrupt handler.
535943c2aeb0SSepherosa Ziehau  */
536043c2aeb0SSepherosa Ziehau /****************************************************************************/
536143c2aeb0SSepherosa Ziehau /* Main interrupt entry point.  Verifies that the controller generated the  */
536243c2aeb0SSepherosa Ziehau /* interrupt and then calls a separate routine for handle the various       */
536343c2aeb0SSepherosa Ziehau /* interrupt causes (PHY, TX, RX).                                          */
536443c2aeb0SSepherosa Ziehau /*                                                                          */
536543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
536643c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
536743c2aeb0SSepherosa Ziehau /****************************************************************************/
536843c2aeb0SSepherosa Ziehau static void
536943c2aeb0SSepherosa Ziehau bce_intr(void *xsc)
537043c2aeb0SSepherosa Ziehau {
537143c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = xsc;
537243c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
537343c2aeb0SSepherosa Ziehau 	struct status_block *sblk;
537424603545SSepherosa Ziehau 	uint16_t hw_rx_cons, hw_tx_cons;
537543c2aeb0SSepherosa Ziehau 
537643c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
537743c2aeb0SSepherosa Ziehau 
537843c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE, "Entering %s()\n", __func__);
537943c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->interrupts_generated++);
538043c2aeb0SSepherosa Ziehau 
538143c2aeb0SSepherosa Ziehau 	sblk = sc->status_block;
538243c2aeb0SSepherosa Ziehau 
538343c2aeb0SSepherosa Ziehau 	/*
538443c2aeb0SSepherosa Ziehau 	 * If the hardware status block index matches the last value
538543c2aeb0SSepherosa Ziehau 	 * read by the driver and we haven't asserted our interrupt
538643c2aeb0SSepherosa Ziehau 	 * then there's nothing to do.
538743c2aeb0SSepherosa Ziehau 	 */
538843c2aeb0SSepherosa Ziehau 	if (sblk->status_idx == sc->last_status_idx &&
538943c2aeb0SSepherosa Ziehau 	    (REG_RD(sc, BCE_PCICFG_MISC_STATUS) &
539043c2aeb0SSepherosa Ziehau 	     BCE_PCICFG_MISC_STATUS_INTA_VALUE))
539143c2aeb0SSepherosa Ziehau 		return;
539243c2aeb0SSepherosa Ziehau 
539343c2aeb0SSepherosa Ziehau 	/* Ack the interrupt and stop others from occuring. */
539443c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
539543c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
539643c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_MASK_INT);
539743c2aeb0SSepherosa Ziehau 
539824603545SSepherosa Ziehau 	/* Check if the hardware has finished any work. */
539924603545SSepherosa Ziehau 	hw_rx_cons = bce_get_hw_rx_cons(sc);
540024603545SSepherosa Ziehau 	hw_tx_cons = bce_get_hw_tx_cons(sc);
540124603545SSepherosa Ziehau 
540243c2aeb0SSepherosa Ziehau 	/* Keep processing data as long as there is work to do. */
540343c2aeb0SSepherosa Ziehau 	for (;;) {
540443c2aeb0SSepherosa Ziehau 		uint32_t status_attn_bits;
540543c2aeb0SSepherosa Ziehau 
540643c2aeb0SSepherosa Ziehau 		status_attn_bits = sblk->status_attn_bits;
540743c2aeb0SSepherosa Ziehau 
540843c2aeb0SSepherosa Ziehau 		DBRUNIF(DB_RANDOMTRUE(bce_debug_unexpected_attention),
540943c2aeb0SSepherosa Ziehau 			if_printf(ifp,
541043c2aeb0SSepherosa Ziehau 			"Simulating unexpected status attention bit set.");
541143c2aeb0SSepherosa Ziehau 			status_attn_bits |= STATUS_ATTN_BITS_PARITY_ERROR);
541243c2aeb0SSepherosa Ziehau 
541343c2aeb0SSepherosa Ziehau 		/* Was it a link change interrupt? */
541443c2aeb0SSepherosa Ziehau 		if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
5415d0092544SSepherosa Ziehau 		    (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE)) {
541643c2aeb0SSepherosa Ziehau 			bce_phy_intr(sc);
541743c2aeb0SSepherosa Ziehau 
541843c2aeb0SSepherosa Ziehau 			/*
5419d0092544SSepherosa Ziehau 			 * Clear any transient status updates during link state
5420d0092544SSepherosa Ziehau 			 * change.
5421d0092544SSepherosa Ziehau 			 */
5422d0092544SSepherosa Ziehau 			REG_WR(sc, BCE_HC_COMMAND,
5423d0092544SSepherosa Ziehau 			    sc->hc_command | BCE_HC_COMMAND_COAL_NOW_WO_INT);
5424d0092544SSepherosa Ziehau 			REG_RD(sc, BCE_HC_COMMAND);
5425d0092544SSepherosa Ziehau 		}
5426d0092544SSepherosa Ziehau 
5427d0092544SSepherosa Ziehau 		/*
542843c2aeb0SSepherosa Ziehau 		 * If any other attention is asserted then
542943c2aeb0SSepherosa Ziehau 		 * the chip is toast.
543043c2aeb0SSepherosa Ziehau 		 */
543143c2aeb0SSepherosa Ziehau 		if ((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) !=
543243c2aeb0SSepherosa Ziehau 		     (sblk->status_attn_bits_ack &
543343c2aeb0SSepherosa Ziehau 		      ~STATUS_ATTN_BITS_LINK_STATE)) {
543443c2aeb0SSepherosa Ziehau 			DBRUN(1, sc->unexpected_attentions++);
543543c2aeb0SSepherosa Ziehau 
543643c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Fatal attention detected: 0x%08X\n",
543743c2aeb0SSepherosa Ziehau 				  sblk->status_attn_bits);
543843c2aeb0SSepherosa Ziehau 
543943c2aeb0SSepherosa Ziehau 			DBRUN(BCE_FATAL,
544043c2aeb0SSepherosa Ziehau 			if (bce_debug_unexpected_attention == 0)
544143c2aeb0SSepherosa Ziehau 				bce_breakpoint(sc));
544243c2aeb0SSepherosa Ziehau 
544343c2aeb0SSepherosa Ziehau 			bce_init(sc);
544443c2aeb0SSepherosa Ziehau 			return;
544543c2aeb0SSepherosa Ziehau 		}
544643c2aeb0SSepherosa Ziehau 
544743c2aeb0SSepherosa Ziehau 		/* Check for any completed RX frames. */
544824603545SSepherosa Ziehau 		if (hw_rx_cons != sc->hw_rx_cons)
544943c2aeb0SSepherosa Ziehau 			bce_rx_intr(sc, -1);
545043c2aeb0SSepherosa Ziehau 
545143c2aeb0SSepherosa Ziehau 		/* Check for any completed TX frames. */
545224603545SSepherosa Ziehau 		if (hw_tx_cons != sc->hw_tx_cons)
545343c2aeb0SSepherosa Ziehau 			bce_tx_intr(sc);
545443c2aeb0SSepherosa Ziehau 
545543c2aeb0SSepherosa Ziehau 		/*
545643c2aeb0SSepherosa Ziehau 		 * Save the status block index value
545743c2aeb0SSepherosa Ziehau 		 * for use during the next interrupt.
545843c2aeb0SSepherosa Ziehau 		 */
545943c2aeb0SSepherosa Ziehau 		sc->last_status_idx = sblk->status_idx;
546043c2aeb0SSepherosa Ziehau 
546143c2aeb0SSepherosa Ziehau 		/*
546243c2aeb0SSepherosa Ziehau 		 * Prevent speculative reads from getting
546343c2aeb0SSepherosa Ziehau 		 * ahead of the status block.
546443c2aeb0SSepherosa Ziehau 		 */
546543c2aeb0SSepherosa Ziehau 		bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
546643c2aeb0SSepherosa Ziehau 				  BUS_SPACE_BARRIER_READ);
546743c2aeb0SSepherosa Ziehau 
546843c2aeb0SSepherosa Ziehau 		/*
546943c2aeb0SSepherosa Ziehau 		 * If there's no work left then exit the
547043c2aeb0SSepherosa Ziehau 		 * interrupt service routine.
547143c2aeb0SSepherosa Ziehau 		 */
547224603545SSepherosa Ziehau 		hw_rx_cons = bce_get_hw_rx_cons(sc);
547324603545SSepherosa Ziehau 		hw_tx_cons = bce_get_hw_tx_cons(sc);
547424603545SSepherosa Ziehau 		if ((hw_rx_cons == sc->hw_rx_cons) && (hw_tx_cons == sc->hw_tx_cons))
547543c2aeb0SSepherosa Ziehau 			break;
547643c2aeb0SSepherosa Ziehau 	}
547743c2aeb0SSepherosa Ziehau 
547843c2aeb0SSepherosa Ziehau 	/* Re-enable interrupts. */
5479d0092544SSepherosa Ziehau 	bce_enable_intr(sc, 0);
548043c2aeb0SSepherosa Ziehau 
5481bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask)
5482bdeb8fffSSepherosa Ziehau 		bce_coal_change(sc);
5483bdeb8fffSSepherosa Ziehau 
548443c2aeb0SSepherosa Ziehau 	/* Handle any frames that arrived while handling the interrupt. */
548543c2aeb0SSepherosa Ziehau 	if (!ifq_is_empty(&ifp->if_snd))
54869db4b353SSepherosa Ziehau 		if_devstart(ifp);
548743c2aeb0SSepherosa Ziehau }
548843c2aeb0SSepherosa Ziehau 
548943c2aeb0SSepherosa Ziehau 
549043c2aeb0SSepherosa Ziehau /****************************************************************************/
549143c2aeb0SSepherosa Ziehau /* Programs the various packet receive modes (broadcast and multicast).     */
549243c2aeb0SSepherosa Ziehau /*                                                                          */
549343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
549443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
549543c2aeb0SSepherosa Ziehau /****************************************************************************/
549643c2aeb0SSepherosa Ziehau static void
549743c2aeb0SSepherosa Ziehau bce_set_rx_mode(struct bce_softc *sc)
549843c2aeb0SSepherosa Ziehau {
549943c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
550043c2aeb0SSepherosa Ziehau 	struct ifmultiaddr *ifma;
550143c2aeb0SSepherosa Ziehau 	uint32_t hashes[NUM_MC_HASH_REGISTERS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
550243c2aeb0SSepherosa Ziehau 	uint32_t rx_mode, sort_mode;
550343c2aeb0SSepherosa Ziehau 	int h, i;
550443c2aeb0SSepherosa Ziehau 
550543c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
550643c2aeb0SSepherosa Ziehau 
550743c2aeb0SSepherosa Ziehau 	/* Initialize receive mode default settings. */
550843c2aeb0SSepherosa Ziehau 	rx_mode = sc->rx_mode &
550943c2aeb0SSepherosa Ziehau 		  ~(BCE_EMAC_RX_MODE_PROMISCUOUS |
551043c2aeb0SSepherosa Ziehau 		    BCE_EMAC_RX_MODE_KEEP_VLAN_TAG);
551143c2aeb0SSepherosa Ziehau 	sort_mode = 1 | BCE_RPM_SORT_USER0_BC_EN;
551243c2aeb0SSepherosa Ziehau 
551343c2aeb0SSepherosa Ziehau 	/*
551443c2aeb0SSepherosa Ziehau 	 * ASF/IPMI/UMP firmware requires that VLAN tag stripping
551543c2aeb0SSepherosa Ziehau 	 * be enbled.
551643c2aeb0SSepherosa Ziehau 	 */
551743c2aeb0SSepherosa Ziehau 	if (!(BCE_IF_CAPABILITIES & IFCAP_VLAN_HWTAGGING) &&
551843c2aeb0SSepherosa Ziehau 	    !(sc->bce_flags & BCE_MFW_ENABLE_FLAG))
551943c2aeb0SSepherosa Ziehau 		rx_mode |= BCE_EMAC_RX_MODE_KEEP_VLAN_TAG;
552043c2aeb0SSepherosa Ziehau 
552143c2aeb0SSepherosa Ziehau 	/*
552243c2aeb0SSepherosa Ziehau 	 * Check for promiscuous, all multicast, or selected
552343c2aeb0SSepherosa Ziehau 	 * multicast address filtering.
552443c2aeb0SSepherosa Ziehau 	 */
552543c2aeb0SSepherosa Ziehau 	if (ifp->if_flags & IFF_PROMISC) {
552643c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Enabling promiscuous mode.\n");
552743c2aeb0SSepherosa Ziehau 
552843c2aeb0SSepherosa Ziehau 		/* Enable promiscuous mode. */
552943c2aeb0SSepherosa Ziehau 		rx_mode |= BCE_EMAC_RX_MODE_PROMISCUOUS;
553043c2aeb0SSepherosa Ziehau 		sort_mode |= BCE_RPM_SORT_USER0_PROM_EN;
553143c2aeb0SSepherosa Ziehau 	} else if (ifp->if_flags & IFF_ALLMULTI) {
553243c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Enabling all multicast mode.\n");
553343c2aeb0SSepherosa Ziehau 
553443c2aeb0SSepherosa Ziehau 		/* Enable all multicast addresses. */
553543c2aeb0SSepherosa Ziehau 		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
553643c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4),
553743c2aeb0SSepherosa Ziehau 			       0xffffffff);
553843c2aeb0SSepherosa Ziehau 		}
553943c2aeb0SSepherosa Ziehau 		sort_mode |= BCE_RPM_SORT_USER0_MC_EN;
554043c2aeb0SSepherosa Ziehau 	} else {
554143c2aeb0SSepherosa Ziehau 		/* Accept one or more multicast(s). */
554243c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Enabling selective multicast mode.\n");
554343c2aeb0SSepherosa Ziehau 
5544441d34b2SSascha Wildner 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
554543c2aeb0SSepherosa Ziehau 			if (ifma->ifma_addr->sa_family != AF_LINK)
554643c2aeb0SSepherosa Ziehau 				continue;
554743c2aeb0SSepherosa Ziehau 			h = ether_crc32_le(
554843c2aeb0SSepherosa Ziehau 			    LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
554943c2aeb0SSepherosa Ziehau 			    ETHER_ADDR_LEN) & 0xFF;
555043c2aeb0SSepherosa Ziehau 			hashes[(h & 0xE0) >> 5] |= 1 << (h & 0x1F);
555143c2aeb0SSepherosa Ziehau 		}
555243c2aeb0SSepherosa Ziehau 
555343c2aeb0SSepherosa Ziehau 		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
555443c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4),
555543c2aeb0SSepherosa Ziehau 			       hashes[i]);
555643c2aeb0SSepherosa Ziehau 		}
555743c2aeb0SSepherosa Ziehau 		sort_mode |= BCE_RPM_SORT_USER0_MC_HSH_EN;
555843c2aeb0SSepherosa Ziehau 	}
555943c2aeb0SSepherosa Ziehau 
556043c2aeb0SSepherosa Ziehau 	/* Only make changes if the recive mode has actually changed. */
556143c2aeb0SSepherosa Ziehau 	if (rx_mode != sc->rx_mode) {
556243c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE, "Enabling new receive mode: 0x%08X\n",
556343c2aeb0SSepherosa Ziehau 			rx_mode);
556443c2aeb0SSepherosa Ziehau 
556543c2aeb0SSepherosa Ziehau 		sc->rx_mode = rx_mode;
556643c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_RX_MODE, rx_mode);
556743c2aeb0SSepherosa Ziehau 	}
556843c2aeb0SSepherosa Ziehau 
556943c2aeb0SSepherosa Ziehau 	/* Disable and clear the exisitng sort before enabling a new sort. */
557043c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_RPM_SORT_USER0, 0x0);
557143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode);
557243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode | BCE_RPM_SORT_USER0_ENA);
557343c2aeb0SSepherosa Ziehau }
557443c2aeb0SSepherosa Ziehau 
557543c2aeb0SSepherosa Ziehau 
557643c2aeb0SSepherosa Ziehau /****************************************************************************/
557743c2aeb0SSepherosa Ziehau /* Called periodically to updates statistics from the controllers           */
557843c2aeb0SSepherosa Ziehau /* statistics block.                                                        */
557943c2aeb0SSepherosa Ziehau /*                                                                          */
558043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
558143c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
558243c2aeb0SSepherosa Ziehau /****************************************************************************/
558343c2aeb0SSepherosa Ziehau static void
558443c2aeb0SSepherosa Ziehau bce_stats_update(struct bce_softc *sc)
558543c2aeb0SSepherosa Ziehau {
558643c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
558743c2aeb0SSepherosa Ziehau 	struct statistics_block *stats = sc->stats_block;
558843c2aeb0SSepherosa Ziehau 
558943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE, "Entering %s()\n", __func__);
559043c2aeb0SSepherosa Ziehau 
559143c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
559243c2aeb0SSepherosa Ziehau 
559343c2aeb0SSepherosa Ziehau 	/*
559443c2aeb0SSepherosa Ziehau 	 * Certain controllers don't report carrier sense errors correctly.
559543c2aeb0SSepherosa Ziehau 	 * See errata E11_5708CA0_1165.
559643c2aeb0SSepherosa Ziehau 	 */
559743c2aeb0SSepherosa Ziehau 	if (!(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) &&
559843c2aeb0SSepherosa Ziehau 	    !(BCE_CHIP_ID(sc) == BCE_CHIP_ID_5708_A0)) {
559943c2aeb0SSepherosa Ziehau 		ifp->if_oerrors +=
560043c2aeb0SSepherosa Ziehau 			(u_long)stats->stat_Dot3StatsCarrierSenseErrors;
560143c2aeb0SSepherosa Ziehau 	}
560243c2aeb0SSepherosa Ziehau 
560343c2aeb0SSepherosa Ziehau 	/*
560443c2aeb0SSepherosa Ziehau 	 * Update the sysctl statistics from the hardware statistics.
560543c2aeb0SSepherosa Ziehau 	 */
560643c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInOctets =
560743c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInOctets_hi << 32) +
560843c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInOctets_lo;
560943c2aeb0SSepherosa Ziehau 
561043c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInBadOctets =
561143c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInBadOctets_hi << 32) +
561243c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInBadOctets_lo;
561343c2aeb0SSepherosa Ziehau 
561443c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutOctets =
561543c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutOctets_hi << 32) +
561643c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutOctets_lo;
561743c2aeb0SSepherosa Ziehau 
561843c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutBadOctets =
561943c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutBadOctets_hi << 32) +
562043c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutBadOctets_lo;
562143c2aeb0SSepherosa Ziehau 
562243c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInUcastPkts =
562343c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInUcastPkts_hi << 32) +
562443c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInUcastPkts_lo;
562543c2aeb0SSepherosa Ziehau 
562643c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInMulticastPkts =
562743c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInMulticastPkts_hi << 32) +
562843c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInMulticastPkts_lo;
562943c2aeb0SSepherosa Ziehau 
563043c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInBroadcastPkts =
563143c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInBroadcastPkts_hi << 32) +
563243c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInBroadcastPkts_lo;
563343c2aeb0SSepherosa Ziehau 
563443c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutUcastPkts =
563543c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutUcastPkts_hi << 32) +
563643c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutUcastPkts_lo;
563743c2aeb0SSepherosa Ziehau 
563843c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutMulticastPkts =
563943c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutMulticastPkts_hi << 32) +
564043c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutMulticastPkts_lo;
564143c2aeb0SSepherosa Ziehau 
564243c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutBroadcastPkts =
564343c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutBroadcastPkts_hi << 32) +
564443c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutBroadcastPkts_lo;
564543c2aeb0SSepherosa Ziehau 
564643c2aeb0SSepherosa Ziehau 	sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors =
564743c2aeb0SSepherosa Ziehau 		stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
564843c2aeb0SSepherosa Ziehau 
564943c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsCarrierSenseErrors =
565043c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsCarrierSenseErrors;
565143c2aeb0SSepherosa Ziehau 
565243c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsFCSErrors =
565343c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsFCSErrors;
565443c2aeb0SSepherosa Ziehau 
565543c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsAlignmentErrors =
565643c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsAlignmentErrors;
565743c2aeb0SSepherosa Ziehau 
565843c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsSingleCollisionFrames =
565943c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsSingleCollisionFrames;
566043c2aeb0SSepherosa Ziehau 
566143c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsMultipleCollisionFrames =
566243c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsMultipleCollisionFrames;
566343c2aeb0SSepherosa Ziehau 
566443c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsDeferredTransmissions =
566543c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsDeferredTransmissions;
566643c2aeb0SSepherosa Ziehau 
566743c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsExcessiveCollisions =
566843c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsExcessiveCollisions;
566943c2aeb0SSepherosa Ziehau 
567043c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsLateCollisions =
567143c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsLateCollisions;
567243c2aeb0SSepherosa Ziehau 
567343c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsCollisions =
567443c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsCollisions;
567543c2aeb0SSepherosa Ziehau 
567643c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsFragments =
567743c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsFragments;
567843c2aeb0SSepherosa Ziehau 
567943c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsJabbers =
568043c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsJabbers;
568143c2aeb0SSepherosa Ziehau 
568243c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsUndersizePkts =
568343c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsUndersizePkts;
568443c2aeb0SSepherosa Ziehau 
568543c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsOverrsizePkts =
568643c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsOverrsizePkts;
568743c2aeb0SSepherosa Ziehau 
568843c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx64Octets =
568943c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx64Octets;
569043c2aeb0SSepherosa Ziehau 
569143c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx65Octetsto127Octets =
569243c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx65Octetsto127Octets;
569343c2aeb0SSepherosa Ziehau 
569443c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx128Octetsto255Octets =
569543c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx128Octetsto255Octets;
569643c2aeb0SSepherosa Ziehau 
569743c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx256Octetsto511Octets =
569843c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx256Octetsto511Octets;
569943c2aeb0SSepherosa Ziehau 
570043c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx512Octetsto1023Octets =
570143c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx512Octetsto1023Octets;
570243c2aeb0SSepherosa Ziehau 
570343c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx1024Octetsto1522Octets =
570443c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx1024Octetsto1522Octets;
570543c2aeb0SSepherosa Ziehau 
570643c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx1523Octetsto9022Octets =
570743c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx1523Octetsto9022Octets;
570843c2aeb0SSepherosa Ziehau 
570943c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx64Octets =
571043c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx64Octets;
571143c2aeb0SSepherosa Ziehau 
571243c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx65Octetsto127Octets =
571343c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx65Octetsto127Octets;
571443c2aeb0SSepherosa Ziehau 
571543c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx128Octetsto255Octets =
571643c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx128Octetsto255Octets;
571743c2aeb0SSepherosa Ziehau 
571843c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx256Octetsto511Octets =
571943c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx256Octetsto511Octets;
572043c2aeb0SSepherosa Ziehau 
572143c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx512Octetsto1023Octets =
572243c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx512Octetsto1023Octets;
572343c2aeb0SSepherosa Ziehau 
572443c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx1024Octetsto1522Octets =
572543c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx1024Octetsto1522Octets;
572643c2aeb0SSepherosa Ziehau 
572743c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx1523Octetsto9022Octets =
572843c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx1523Octetsto9022Octets;
572943c2aeb0SSepherosa Ziehau 
573043c2aeb0SSepherosa Ziehau 	sc->stat_XonPauseFramesReceived =
573143c2aeb0SSepherosa Ziehau 		stats->stat_XonPauseFramesReceived;
573243c2aeb0SSepherosa Ziehau 
573343c2aeb0SSepherosa Ziehau 	sc->stat_XoffPauseFramesReceived =
573443c2aeb0SSepherosa Ziehau 		stats->stat_XoffPauseFramesReceived;
573543c2aeb0SSepherosa Ziehau 
573643c2aeb0SSepherosa Ziehau 	sc->stat_OutXonSent =
573743c2aeb0SSepherosa Ziehau 		stats->stat_OutXonSent;
573843c2aeb0SSepherosa Ziehau 
573943c2aeb0SSepherosa Ziehau 	sc->stat_OutXoffSent =
574043c2aeb0SSepherosa Ziehau 		stats->stat_OutXoffSent;
574143c2aeb0SSepherosa Ziehau 
574243c2aeb0SSepherosa Ziehau 	sc->stat_FlowControlDone =
574343c2aeb0SSepherosa Ziehau 		stats->stat_FlowControlDone;
574443c2aeb0SSepherosa Ziehau 
574543c2aeb0SSepherosa Ziehau 	sc->stat_MacControlFramesReceived =
574643c2aeb0SSepherosa Ziehau 		stats->stat_MacControlFramesReceived;
574743c2aeb0SSepherosa Ziehau 
574843c2aeb0SSepherosa Ziehau 	sc->stat_XoffStateEntered =
574943c2aeb0SSepherosa Ziehau 		stats->stat_XoffStateEntered;
575043c2aeb0SSepherosa Ziehau 
575143c2aeb0SSepherosa Ziehau 	sc->stat_IfInFramesL2FilterDiscards =
575243c2aeb0SSepherosa Ziehau 		stats->stat_IfInFramesL2FilterDiscards;
575343c2aeb0SSepherosa Ziehau 
575443c2aeb0SSepherosa Ziehau 	sc->stat_IfInRuleCheckerDiscards =
575543c2aeb0SSepherosa Ziehau 		stats->stat_IfInRuleCheckerDiscards;
575643c2aeb0SSepherosa Ziehau 
575743c2aeb0SSepherosa Ziehau 	sc->stat_IfInFTQDiscards =
575843c2aeb0SSepherosa Ziehau 		stats->stat_IfInFTQDiscards;
575943c2aeb0SSepherosa Ziehau 
576043c2aeb0SSepherosa Ziehau 	sc->stat_IfInMBUFDiscards =
576143c2aeb0SSepherosa Ziehau 		stats->stat_IfInMBUFDiscards;
576243c2aeb0SSepherosa Ziehau 
576343c2aeb0SSepherosa Ziehau 	sc->stat_IfInRuleCheckerP4Hit =
576443c2aeb0SSepherosa Ziehau 		stats->stat_IfInRuleCheckerP4Hit;
576543c2aeb0SSepherosa Ziehau 
576643c2aeb0SSepherosa Ziehau 	sc->stat_CatchupInRuleCheckerDiscards =
576743c2aeb0SSepherosa Ziehau 		stats->stat_CatchupInRuleCheckerDiscards;
576843c2aeb0SSepherosa Ziehau 
576943c2aeb0SSepherosa Ziehau 	sc->stat_CatchupInFTQDiscards =
577043c2aeb0SSepherosa Ziehau 		stats->stat_CatchupInFTQDiscards;
577143c2aeb0SSepherosa Ziehau 
577243c2aeb0SSepherosa Ziehau 	sc->stat_CatchupInMBUFDiscards =
577343c2aeb0SSepherosa Ziehau 		stats->stat_CatchupInMBUFDiscards;
577443c2aeb0SSepherosa Ziehau 
577543c2aeb0SSepherosa Ziehau 	sc->stat_CatchupInRuleCheckerP4Hit =
577643c2aeb0SSepherosa Ziehau 		stats->stat_CatchupInRuleCheckerP4Hit;
577743c2aeb0SSepherosa Ziehau 
577843c2aeb0SSepherosa Ziehau 	sc->com_no_buffers = REG_RD_IND(sc, 0x120084);
577943c2aeb0SSepherosa Ziehau 
5780d0092544SSepherosa Ziehau 	/*
5781d0092544SSepherosa Ziehau 	 * Update the interface statistics from the
5782d0092544SSepherosa Ziehau 	 * hardware statistics.
5783d0092544SSepherosa Ziehau 	 */
5784d0092544SSepherosa Ziehau 	ifp->if_collisions = (u_long)sc->stat_EtherStatsCollisions;
5785d0092544SSepherosa Ziehau 
5786d0092544SSepherosa Ziehau 	ifp->if_ierrors = (u_long)sc->stat_EtherStatsUndersizePkts +
5787d0092544SSepherosa Ziehau 	    (u_long)sc->stat_EtherStatsOverrsizePkts +
5788d0092544SSepherosa Ziehau 	    (u_long)sc->stat_IfInMBUFDiscards +
5789d0092544SSepherosa Ziehau 	    (u_long)sc->stat_Dot3StatsAlignmentErrors +
5790d0092544SSepherosa Ziehau 	    (u_long)sc->stat_Dot3StatsFCSErrors +
5791d0092544SSepherosa Ziehau 	    (u_long)sc->stat_IfInRuleCheckerDiscards +
5792d0092544SSepherosa Ziehau 	    (u_long)sc->stat_IfInFTQDiscards +
5793d0092544SSepherosa Ziehau 	    (u_long)sc->com_no_buffers;
5794d0092544SSepherosa Ziehau 
5795d0092544SSepherosa Ziehau 	ifp->if_oerrors =
5796d0092544SSepherosa Ziehau 	    (u_long)sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors +
5797d0092544SSepherosa Ziehau 	    (u_long)sc->stat_Dot3StatsExcessiveCollisions +
5798d0092544SSepherosa Ziehau 	    (u_long)sc->stat_Dot3StatsLateCollisions;
5799d0092544SSepherosa Ziehau 
580043c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE, "Exiting %s()\n", __func__);
580143c2aeb0SSepherosa Ziehau }
580243c2aeb0SSepherosa Ziehau 
580343c2aeb0SSepherosa Ziehau 
580443c2aeb0SSepherosa Ziehau /****************************************************************************/
5805d0092544SSepherosa Ziehau /* Periodic function to notify the bootcode that the driver is still        */
5806d0092544SSepherosa Ziehau /* present.                                                                 */
5807d0092544SSepherosa Ziehau /*                                                                          */
5808d0092544SSepherosa Ziehau /* Returns:                                                                 */
5809d0092544SSepherosa Ziehau /*   Nothing.                                                               */
5810d0092544SSepherosa Ziehau /****************************************************************************/
5811d0092544SSepherosa Ziehau static void
5812d0092544SSepherosa Ziehau bce_pulse(void *xsc)
5813d0092544SSepherosa Ziehau {
5814d0092544SSepherosa Ziehau 	struct bce_softc *sc = xsc;
5815d0092544SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
5816d0092544SSepherosa Ziehau 	uint32_t msg;
5817d0092544SSepherosa Ziehau 
5818d0092544SSepherosa Ziehau 	lwkt_serialize_enter(ifp->if_serializer);
5819d0092544SSepherosa Ziehau 
5820d0092544SSepherosa Ziehau 	/* Tell the firmware that the driver is still running. */
5821d0092544SSepherosa Ziehau 	msg = (uint32_t)++sc->bce_fw_drv_pulse_wr_seq;
5822bc30d40dSSepherosa Ziehau 	bce_shmem_wr(sc, BCE_DRV_PULSE_MB, msg);
5823d0092544SSepherosa Ziehau 
5824d0092544SSepherosa Ziehau 	/* Schedule the next pulse. */
5825d0092544SSepherosa Ziehau 	callout_reset(&sc->bce_pulse_callout, hz, bce_pulse, sc);
5826d0092544SSepherosa Ziehau 
5827d0092544SSepherosa Ziehau 	lwkt_serialize_exit(ifp->if_serializer);
5828d0092544SSepherosa Ziehau }
5829d0092544SSepherosa Ziehau 
5830d0092544SSepherosa Ziehau 
5831d0092544SSepherosa Ziehau /****************************************************************************/
583243c2aeb0SSepherosa Ziehau /* Periodic function to perform maintenance tasks.                          */
583343c2aeb0SSepherosa Ziehau /*                                                                          */
583443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
583543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
583643c2aeb0SSepherosa Ziehau /****************************************************************************/
583743c2aeb0SSepherosa Ziehau static void
583843c2aeb0SSepherosa Ziehau bce_tick_serialized(struct bce_softc *sc)
583943c2aeb0SSepherosa Ziehau {
584043c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
584143c2aeb0SSepherosa Ziehau 	struct mii_data *mii;
584243c2aeb0SSepherosa Ziehau 
584343c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
584443c2aeb0SSepherosa Ziehau 
584543c2aeb0SSepherosa Ziehau 	/* Update the statistics from the hardware statistics block. */
584643c2aeb0SSepherosa Ziehau 	bce_stats_update(sc);
584743c2aeb0SSepherosa Ziehau 
584843c2aeb0SSepherosa Ziehau 	/* Schedule the next tick. */
5849d0092544SSepherosa Ziehau 	callout_reset(&sc->bce_tick_callout, hz, bce_tick, sc);
585043c2aeb0SSepherosa Ziehau 
585143c2aeb0SSepherosa Ziehau 	/* If link is up already up then we're done. */
585243c2aeb0SSepherosa Ziehau 	if (sc->bce_link)
585343c2aeb0SSepherosa Ziehau 		return;
585443c2aeb0SSepherosa Ziehau 
585543c2aeb0SSepherosa Ziehau 	mii = device_get_softc(sc->bce_miibus);
585643c2aeb0SSepherosa Ziehau 	mii_tick(mii);
585743c2aeb0SSepherosa Ziehau 
585843c2aeb0SSepherosa Ziehau 	/* Check if the link has come up. */
5859d0092544SSepherosa Ziehau 	if ((mii->mii_media_status & IFM_ACTIVE) &&
586043c2aeb0SSepherosa Ziehau 	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
586143c2aeb0SSepherosa Ziehau 		sc->bce_link++;
586243c2aeb0SSepherosa Ziehau 		/* Now that link is up, handle any outstanding TX traffic. */
586343c2aeb0SSepherosa Ziehau 		if (!ifq_is_empty(&ifp->if_snd))
58649db4b353SSepherosa Ziehau 			if_devstart(ifp);
586543c2aeb0SSepherosa Ziehau 	}
586643c2aeb0SSepherosa Ziehau }
586743c2aeb0SSepherosa Ziehau 
586843c2aeb0SSepherosa Ziehau 
586943c2aeb0SSepherosa Ziehau static void
587043c2aeb0SSepherosa Ziehau bce_tick(void *xsc)
587143c2aeb0SSepherosa Ziehau {
587243c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = xsc;
587343c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
587443c2aeb0SSepherosa Ziehau 
587543c2aeb0SSepherosa Ziehau 	lwkt_serialize_enter(ifp->if_serializer);
587643c2aeb0SSepherosa Ziehau 	bce_tick_serialized(sc);
587743c2aeb0SSepherosa Ziehau 	lwkt_serialize_exit(ifp->if_serializer);
587843c2aeb0SSepherosa Ziehau }
587943c2aeb0SSepherosa Ziehau 
588043c2aeb0SSepherosa Ziehau 
588143c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
588243c2aeb0SSepherosa Ziehau /****************************************************************************/
588343c2aeb0SSepherosa Ziehau /* Allows the driver state to be dumped through the sysctl interface.       */
588443c2aeb0SSepherosa Ziehau /*                                                                          */
588543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
588643c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
588743c2aeb0SSepherosa Ziehau /****************************************************************************/
588843c2aeb0SSepherosa Ziehau static int
588943c2aeb0SSepherosa Ziehau bce_sysctl_driver_state(SYSCTL_HANDLER_ARGS)
589043c2aeb0SSepherosa Ziehau {
589143c2aeb0SSepherosa Ziehau         int error;
589243c2aeb0SSepherosa Ziehau         int result;
589343c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
589443c2aeb0SSepherosa Ziehau 
589543c2aeb0SSepherosa Ziehau         result = -1;
589643c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
589743c2aeb0SSepherosa Ziehau 
589843c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
589943c2aeb0SSepherosa Ziehau                 return (error);
590043c2aeb0SSepherosa Ziehau 
590143c2aeb0SSepherosa Ziehau         if (result == 1) {
590243c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
590343c2aeb0SSepherosa Ziehau                 bce_dump_driver_state(sc);
590443c2aeb0SSepherosa Ziehau         }
590543c2aeb0SSepherosa Ziehau 
590643c2aeb0SSepherosa Ziehau         return error;
590743c2aeb0SSepherosa Ziehau }
590843c2aeb0SSepherosa Ziehau 
590943c2aeb0SSepherosa Ziehau 
591043c2aeb0SSepherosa Ziehau /****************************************************************************/
591143c2aeb0SSepherosa Ziehau /* Allows the hardware state to be dumped through the sysctl interface.     */
591243c2aeb0SSepherosa Ziehau /*                                                                          */
591343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
591443c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
591543c2aeb0SSepherosa Ziehau /****************************************************************************/
591643c2aeb0SSepherosa Ziehau static int
591743c2aeb0SSepherosa Ziehau bce_sysctl_hw_state(SYSCTL_HANDLER_ARGS)
591843c2aeb0SSepherosa Ziehau {
591943c2aeb0SSepherosa Ziehau         int error;
592043c2aeb0SSepherosa Ziehau         int result;
592143c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
592243c2aeb0SSepherosa Ziehau 
592343c2aeb0SSepherosa Ziehau         result = -1;
592443c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
592543c2aeb0SSepherosa Ziehau 
592643c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
592743c2aeb0SSepherosa Ziehau                 return (error);
592843c2aeb0SSepherosa Ziehau 
592943c2aeb0SSepherosa Ziehau         if (result == 1) {
593043c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
593143c2aeb0SSepherosa Ziehau                 bce_dump_hw_state(sc);
593243c2aeb0SSepherosa Ziehau         }
593343c2aeb0SSepherosa Ziehau 
593443c2aeb0SSepherosa Ziehau         return error;
593543c2aeb0SSepherosa Ziehau }
593643c2aeb0SSepherosa Ziehau 
593743c2aeb0SSepherosa Ziehau 
593843c2aeb0SSepherosa Ziehau /****************************************************************************/
593943c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to allows dumping the RX chain.              */
594043c2aeb0SSepherosa Ziehau /*                                                                          */
594143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
594243c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
594343c2aeb0SSepherosa Ziehau /****************************************************************************/
594443c2aeb0SSepherosa Ziehau static int
594543c2aeb0SSepherosa Ziehau bce_sysctl_dump_rx_chain(SYSCTL_HANDLER_ARGS)
594643c2aeb0SSepherosa Ziehau {
594743c2aeb0SSepherosa Ziehau         int error;
594843c2aeb0SSepherosa Ziehau         int result;
594943c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
595043c2aeb0SSepherosa Ziehau 
595143c2aeb0SSepherosa Ziehau         result = -1;
595243c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
595343c2aeb0SSepherosa Ziehau 
595443c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
595543c2aeb0SSepherosa Ziehau                 return (error);
595643c2aeb0SSepherosa Ziehau 
595743c2aeb0SSepherosa Ziehau         if (result == 1) {
595843c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
595943c2aeb0SSepherosa Ziehau                 bce_dump_rx_chain(sc, 0, USABLE_RX_BD);
596043c2aeb0SSepherosa Ziehau         }
596143c2aeb0SSepherosa Ziehau 
596243c2aeb0SSepherosa Ziehau         return error;
596343c2aeb0SSepherosa Ziehau }
596443c2aeb0SSepherosa Ziehau 
596543c2aeb0SSepherosa Ziehau 
596643c2aeb0SSepherosa Ziehau /****************************************************************************/
596743c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to allows dumping the TX chain.              */
596843c2aeb0SSepherosa Ziehau /*                                                                          */
596943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
597043c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
597143c2aeb0SSepherosa Ziehau /****************************************************************************/
597243c2aeb0SSepherosa Ziehau static int
597343c2aeb0SSepherosa Ziehau bce_sysctl_dump_tx_chain(SYSCTL_HANDLER_ARGS)
597443c2aeb0SSepherosa Ziehau {
597543c2aeb0SSepherosa Ziehau         int error;
597643c2aeb0SSepherosa Ziehau         int result;
597743c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
597843c2aeb0SSepherosa Ziehau 
597943c2aeb0SSepherosa Ziehau         result = -1;
598043c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
598143c2aeb0SSepherosa Ziehau 
598243c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
598343c2aeb0SSepherosa Ziehau                 return (error);
598443c2aeb0SSepherosa Ziehau 
598543c2aeb0SSepherosa Ziehau         if (result == 1) {
598643c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
598743c2aeb0SSepherosa Ziehau                 bce_dump_tx_chain(sc, 0, USABLE_TX_BD);
598843c2aeb0SSepherosa Ziehau         }
598943c2aeb0SSepherosa Ziehau 
599043c2aeb0SSepherosa Ziehau         return error;
599143c2aeb0SSepherosa Ziehau }
599243c2aeb0SSepherosa Ziehau 
599343c2aeb0SSepherosa Ziehau 
599443c2aeb0SSepherosa Ziehau /****************************************************************************/
599543c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to allow reading arbitrary registers in the  */
599643c2aeb0SSepherosa Ziehau /* device.  DO NOT ENABLE ON PRODUCTION SYSTEMS!                            */
599743c2aeb0SSepherosa Ziehau /*                                                                          */
599843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
599943c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
600043c2aeb0SSepherosa Ziehau /****************************************************************************/
600143c2aeb0SSepherosa Ziehau static int
600243c2aeb0SSepherosa Ziehau bce_sysctl_reg_read(SYSCTL_HANDLER_ARGS)
600343c2aeb0SSepherosa Ziehau {
600443c2aeb0SSepherosa Ziehau 	struct bce_softc *sc;
600543c2aeb0SSepherosa Ziehau 	int error;
600643c2aeb0SSepherosa Ziehau 	uint32_t val, result;
600743c2aeb0SSepherosa Ziehau 
600843c2aeb0SSepherosa Ziehau 	result = -1;
600943c2aeb0SSepherosa Ziehau 	error = sysctl_handle_int(oidp, &result, 0, req);
601043c2aeb0SSepherosa Ziehau 	if (error || (req->newptr == NULL))
601143c2aeb0SSepherosa Ziehau 		return (error);
601243c2aeb0SSepherosa Ziehau 
601343c2aeb0SSepherosa Ziehau 	/* Make sure the register is accessible. */
601443c2aeb0SSepherosa Ziehau 	if (result < 0x8000) {
601543c2aeb0SSepherosa Ziehau 		sc = (struct bce_softc *)arg1;
601643c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, result);
601743c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "reg 0x%08X = 0x%08X\n",
601843c2aeb0SSepherosa Ziehau 			  result, val);
601943c2aeb0SSepherosa Ziehau 	} else if (result < 0x0280000) {
602043c2aeb0SSepherosa Ziehau 		sc = (struct bce_softc *)arg1;
602143c2aeb0SSepherosa Ziehau 		val = REG_RD_IND(sc, result);
602243c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "reg 0x%08X = 0x%08X\n",
602343c2aeb0SSepherosa Ziehau 			  result, val);
602443c2aeb0SSepherosa Ziehau 	}
602543c2aeb0SSepherosa Ziehau 	return (error);
602643c2aeb0SSepherosa Ziehau }
602743c2aeb0SSepherosa Ziehau 
602843c2aeb0SSepherosa Ziehau 
602943c2aeb0SSepherosa Ziehau /****************************************************************************/
603043c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to allow reading arbitrary PHY registers in  */
603143c2aeb0SSepherosa Ziehau /* the device.  DO NOT ENABLE ON PRODUCTION SYSTEMS!                        */
603243c2aeb0SSepherosa Ziehau /*                                                                          */
603343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
603443c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
603543c2aeb0SSepherosa Ziehau /****************************************************************************/
603643c2aeb0SSepherosa Ziehau static int
603743c2aeb0SSepherosa Ziehau bce_sysctl_phy_read(SYSCTL_HANDLER_ARGS)
603843c2aeb0SSepherosa Ziehau {
603943c2aeb0SSepherosa Ziehau 	struct bce_softc *sc;
604043c2aeb0SSepherosa Ziehau 	device_t dev;
604143c2aeb0SSepherosa Ziehau 	int error, result;
604243c2aeb0SSepherosa Ziehau 	uint16_t val;
604343c2aeb0SSepherosa Ziehau 
604443c2aeb0SSepherosa Ziehau 	result = -1;
604543c2aeb0SSepherosa Ziehau 	error = sysctl_handle_int(oidp, &result, 0, req);
604643c2aeb0SSepherosa Ziehau 	if (error || (req->newptr == NULL))
604743c2aeb0SSepherosa Ziehau 		return (error);
604843c2aeb0SSepherosa Ziehau 
604943c2aeb0SSepherosa Ziehau 	/* Make sure the register is accessible. */
605043c2aeb0SSepherosa Ziehau 	if (result < 0x20) {
605143c2aeb0SSepherosa Ziehau 		sc = (struct bce_softc *)arg1;
605243c2aeb0SSepherosa Ziehau 		dev = sc->bce_dev;
605343c2aeb0SSepherosa Ziehau 		val = bce_miibus_read_reg(dev, sc->bce_phy_addr, result);
605443c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
605543c2aeb0SSepherosa Ziehau 			  "phy 0x%02X = 0x%04X\n", result, val);
605643c2aeb0SSepherosa Ziehau 	}
605743c2aeb0SSepherosa Ziehau 	return (error);
605843c2aeb0SSepherosa Ziehau }
605943c2aeb0SSepherosa Ziehau 
606043c2aeb0SSepherosa Ziehau 
606143c2aeb0SSepherosa Ziehau /****************************************************************************/
606243c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to forcing the driver to dump state and      */
606343c2aeb0SSepherosa Ziehau /* enter the debugger.  DO NOT ENABLE ON PRODUCTION SYSTEMS!                */
606443c2aeb0SSepherosa Ziehau /*                                                                          */
606543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
606643c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
606743c2aeb0SSepherosa Ziehau /****************************************************************************/
606843c2aeb0SSepherosa Ziehau static int
606943c2aeb0SSepherosa Ziehau bce_sysctl_breakpoint(SYSCTL_HANDLER_ARGS)
607043c2aeb0SSepherosa Ziehau {
607143c2aeb0SSepherosa Ziehau         int error;
607243c2aeb0SSepherosa Ziehau         int result;
607343c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
607443c2aeb0SSepherosa Ziehau 
607543c2aeb0SSepherosa Ziehau         result = -1;
607643c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
607743c2aeb0SSepherosa Ziehau 
607843c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
607943c2aeb0SSepherosa Ziehau                 return (error);
608043c2aeb0SSepherosa Ziehau 
608143c2aeb0SSepherosa Ziehau         if (result == 1) {
608243c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
608343c2aeb0SSepherosa Ziehau                 bce_breakpoint(sc);
608443c2aeb0SSepherosa Ziehau         }
608543c2aeb0SSepherosa Ziehau 
608643c2aeb0SSepherosa Ziehau         return error;
608743c2aeb0SSepherosa Ziehau }
608843c2aeb0SSepherosa Ziehau #endif
608943c2aeb0SSepherosa Ziehau 
609043c2aeb0SSepherosa Ziehau 
609143c2aeb0SSepherosa Ziehau /****************************************************************************/
609243c2aeb0SSepherosa Ziehau /* Adds any sysctl parameters for tuning or debugging purposes.             */
609343c2aeb0SSepherosa Ziehau /*                                                                          */
609443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
609543c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
609643c2aeb0SSepherosa Ziehau /****************************************************************************/
609743c2aeb0SSepherosa Ziehau static void
609843c2aeb0SSepherosa Ziehau bce_add_sysctls(struct bce_softc *sc)
609943c2aeb0SSepherosa Ziehau {
610043c2aeb0SSepherosa Ziehau 	struct sysctl_ctx_list *ctx;
610143c2aeb0SSepherosa Ziehau 	struct sysctl_oid_list *children;
610243c2aeb0SSepherosa Ziehau 
610343c2aeb0SSepherosa Ziehau 	sysctl_ctx_init(&sc->bce_sysctl_ctx);
610443c2aeb0SSepherosa Ziehau 	sc->bce_sysctl_tree = SYSCTL_ADD_NODE(&sc->bce_sysctl_ctx,
610543c2aeb0SSepherosa Ziehau 					      SYSCTL_STATIC_CHILDREN(_hw),
610643c2aeb0SSepherosa Ziehau 					      OID_AUTO,
610743c2aeb0SSepherosa Ziehau 					      device_get_nameunit(sc->bce_dev),
610843c2aeb0SSepherosa Ziehau 					      CTLFLAG_RD, 0, "");
610943c2aeb0SSepherosa Ziehau 	if (sc->bce_sysctl_tree == NULL) {
611043c2aeb0SSepherosa Ziehau 		device_printf(sc->bce_dev, "can't add sysctl node\n");
611143c2aeb0SSepherosa Ziehau 		return;
611243c2aeb0SSepherosa Ziehau 	}
611343c2aeb0SSepherosa Ziehau 
611443c2aeb0SSepherosa Ziehau 	ctx = &sc->bce_sysctl_ctx;
611543c2aeb0SSepherosa Ziehau 	children = SYSCTL_CHILDREN(sc->bce_sysctl_tree);
611643c2aeb0SSepherosa Ziehau 
6117bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_bds_int",
6118bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
6119bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_tx_bds_int, "I",
6120bdeb8fffSSepherosa Ziehau 			"Send max coalesced BD count during interrupt");
6121bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_bds",
6122bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
6123bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_tx_bds, "I",
6124bdeb8fffSSepherosa Ziehau 			"Send max coalesced BD count");
6125bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_ticks_int",
6126bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
6127bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_tx_ticks_int, "I",
6128bdeb8fffSSepherosa Ziehau 			"Send coalescing ticks during interrupt");
6129bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_ticks",
6130bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
6131bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_tx_ticks, "I",
6132bdeb8fffSSepherosa Ziehau 			"Send coalescing ticks");
6133bdeb8fffSSepherosa Ziehau 
6134bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_bds_int",
6135bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
6136bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_rx_bds_int, "I",
6137bdeb8fffSSepherosa Ziehau 			"Receive max coalesced BD count during interrupt");
6138bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_bds",
6139bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
6140bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_rx_bds, "I",
6141bdeb8fffSSepherosa Ziehau 			"Receive max coalesced BD count");
6142bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_ticks_int",
6143bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
6144bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_rx_ticks_int, "I",
6145bdeb8fffSSepherosa Ziehau 			"Receive coalescing ticks during interrupt");
6146bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_ticks",
6147bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
6148bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_rx_ticks, "I",
6149bdeb8fffSSepherosa Ziehau 			"Receive coalescing ticks");
6150bdeb8fffSSepherosa Ziehau 
615143c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
615243c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
615343c2aeb0SSepherosa Ziehau 		"rx_low_watermark",
615443c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->rx_low_watermark,
615543c2aeb0SSepherosa Ziehau 		0, "Lowest level of free rx_bd's");
615643c2aeb0SSepherosa Ziehau 
615743c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
615843c2aeb0SSepherosa Ziehau 		"rx_empty_count",
615943c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->rx_empty_count,
616043c2aeb0SSepherosa Ziehau 		0, "Number of times the RX chain was empty");
616143c2aeb0SSepherosa Ziehau 
616243c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
616343c2aeb0SSepherosa Ziehau 		"tx_hi_watermark",
616443c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->tx_hi_watermark,
616543c2aeb0SSepherosa Ziehau 		0, "Highest level of used tx_bd's");
616643c2aeb0SSepherosa Ziehau 
616743c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
616843c2aeb0SSepherosa Ziehau 		"tx_full_count",
616943c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->tx_full_count,
617043c2aeb0SSepherosa Ziehau 		0, "Number of times the TX chain was full");
617143c2aeb0SSepherosa Ziehau 
617243c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
617343c2aeb0SSepherosa Ziehau 		"l2fhdr_status_errors",
617443c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->l2fhdr_status_errors,
617543c2aeb0SSepherosa Ziehau 		0, "l2_fhdr status errors");
617643c2aeb0SSepherosa Ziehau 
617743c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
617843c2aeb0SSepherosa Ziehau 		"unexpected_attentions",
617943c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->unexpected_attentions,
618043c2aeb0SSepherosa Ziehau 		0, "unexpected attentions");
618143c2aeb0SSepherosa Ziehau 
618243c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
618343c2aeb0SSepherosa Ziehau 		"lost_status_block_updates",
618443c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->lost_status_block_updates,
618543c2aeb0SSepherosa Ziehau 		0, "lost status block updates");
618643c2aeb0SSepherosa Ziehau 
618743c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
618843c2aeb0SSepherosa Ziehau 		"mbuf_alloc_failed",
618943c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->mbuf_alloc_failed,
619043c2aeb0SSepherosa Ziehau 		0, "mbuf cluster allocation failures");
619143c2aeb0SSepherosa Ziehau #endif
619243c2aeb0SSepherosa Ziehau 
619343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
619456872d4eSSepherosa Ziehau 		"stat_IfHCInOctets",
619543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInOctets,
619643c2aeb0SSepherosa Ziehau 		"Bytes received");
619743c2aeb0SSepherosa Ziehau 
619843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
619943c2aeb0SSepherosa Ziehau 		"stat_IfHCInBadOctets",
620043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInBadOctets,
620143c2aeb0SSepherosa Ziehau 		"Bad bytes received");
620243c2aeb0SSepherosa Ziehau 
620343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
620443c2aeb0SSepherosa Ziehau 		"stat_IfHCOutOctets",
620543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutOctets,
620643c2aeb0SSepherosa Ziehau 		"Bytes sent");
620743c2aeb0SSepherosa Ziehau 
620843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
620943c2aeb0SSepherosa Ziehau 		"stat_IfHCOutBadOctets",
621043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutBadOctets,
621143c2aeb0SSepherosa Ziehau 		"Bad bytes sent");
621243c2aeb0SSepherosa Ziehau 
621343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
621443c2aeb0SSepherosa Ziehau 		"stat_IfHCInUcastPkts",
621543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInUcastPkts,
621643c2aeb0SSepherosa Ziehau 		"Unicast packets received");
621743c2aeb0SSepherosa Ziehau 
621843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
621943c2aeb0SSepherosa Ziehau 		"stat_IfHCInMulticastPkts",
622043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInMulticastPkts,
622143c2aeb0SSepherosa Ziehau 		"Multicast packets received");
622243c2aeb0SSepherosa Ziehau 
622343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
622443c2aeb0SSepherosa Ziehau 		"stat_IfHCInBroadcastPkts",
622543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInBroadcastPkts,
622643c2aeb0SSepherosa Ziehau 		"Broadcast packets received");
622743c2aeb0SSepherosa Ziehau 
622843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
622943c2aeb0SSepherosa Ziehau 		"stat_IfHCOutUcastPkts",
623043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutUcastPkts,
623143c2aeb0SSepherosa Ziehau 		"Unicast packets sent");
623243c2aeb0SSepherosa Ziehau 
623343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
623443c2aeb0SSepherosa Ziehau 		"stat_IfHCOutMulticastPkts",
623543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutMulticastPkts,
623643c2aeb0SSepherosa Ziehau 		"Multicast packets sent");
623743c2aeb0SSepherosa Ziehau 
623843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
623943c2aeb0SSepherosa Ziehau 		"stat_IfHCOutBroadcastPkts",
624043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutBroadcastPkts,
624143c2aeb0SSepherosa Ziehau 		"Broadcast packets sent");
624243c2aeb0SSepherosa Ziehau 
624343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
624443c2aeb0SSepherosa Ziehau 		"stat_emac_tx_stat_dot3statsinternalmactransmiterrors",
624543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors,
624643c2aeb0SSepherosa Ziehau 		0, "Internal MAC transmit errors");
624743c2aeb0SSepherosa Ziehau 
624843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
624943c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsCarrierSenseErrors",
625043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsCarrierSenseErrors,
625143c2aeb0SSepherosa Ziehau 		0, "Carrier sense errors");
625243c2aeb0SSepherosa Ziehau 
625343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
625443c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsFCSErrors",
625543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsFCSErrors,
625643c2aeb0SSepherosa Ziehau 		0, "Frame check sequence errors");
625743c2aeb0SSepherosa Ziehau 
625843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
625943c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsAlignmentErrors",
626043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsAlignmentErrors,
626143c2aeb0SSepherosa Ziehau 		0, "Alignment errors");
626243c2aeb0SSepherosa Ziehau 
626343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
626443c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsSingleCollisionFrames",
626543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsSingleCollisionFrames,
626643c2aeb0SSepherosa Ziehau 		0, "Single Collision Frames");
626743c2aeb0SSepherosa Ziehau 
626843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
626943c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsMultipleCollisionFrames",
627043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsMultipleCollisionFrames,
627143c2aeb0SSepherosa Ziehau 		0, "Multiple Collision Frames");
627243c2aeb0SSepherosa Ziehau 
627343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
627443c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsDeferredTransmissions",
627543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsDeferredTransmissions,
627643c2aeb0SSepherosa Ziehau 		0, "Deferred Transmissions");
627743c2aeb0SSepherosa Ziehau 
627843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
627943c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsExcessiveCollisions",
628043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsExcessiveCollisions,
628143c2aeb0SSepherosa Ziehau 		0, "Excessive Collisions");
628243c2aeb0SSepherosa Ziehau 
628343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
628443c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsLateCollisions",
628543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsLateCollisions,
628643c2aeb0SSepherosa Ziehau 		0, "Late Collisions");
628743c2aeb0SSepherosa Ziehau 
628843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
628943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsCollisions",
629043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsCollisions,
629143c2aeb0SSepherosa Ziehau 		0, "Collisions");
629243c2aeb0SSepherosa Ziehau 
629343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
629443c2aeb0SSepherosa Ziehau 		"stat_EtherStatsFragments",
629543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsFragments,
629643c2aeb0SSepherosa Ziehau 		0, "Fragments");
629743c2aeb0SSepherosa Ziehau 
629843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
629943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsJabbers",
630043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsJabbers,
630143c2aeb0SSepherosa Ziehau 		0, "Jabbers");
630243c2aeb0SSepherosa Ziehau 
630343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
630443c2aeb0SSepherosa Ziehau 		"stat_EtherStatsUndersizePkts",
630543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsUndersizePkts,
630643c2aeb0SSepherosa Ziehau 		0, "Undersize packets");
630743c2aeb0SSepherosa Ziehau 
630843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
630943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsOverrsizePkts",
631043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsOverrsizePkts,
631143c2aeb0SSepherosa Ziehau 		0, "stat_EtherStatsOverrsizePkts");
631243c2aeb0SSepherosa Ziehau 
631343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
631443c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx64Octets",
631543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx64Octets,
631643c2aeb0SSepherosa Ziehau 		0, "Bytes received in 64 byte packets");
631743c2aeb0SSepherosa Ziehau 
631843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
631943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx65Octetsto127Octets",
632043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx65Octetsto127Octets,
632143c2aeb0SSepherosa Ziehau 		0, "Bytes received in 65 to 127 byte packets");
632243c2aeb0SSepherosa Ziehau 
632343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
632443c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx128Octetsto255Octets",
632543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx128Octetsto255Octets,
632643c2aeb0SSepherosa Ziehau 		0, "Bytes received in 128 to 255 byte packets");
632743c2aeb0SSepherosa Ziehau 
632843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
632943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx256Octetsto511Octets",
633043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx256Octetsto511Octets,
633143c2aeb0SSepherosa Ziehau 		0, "Bytes received in 256 to 511 byte packets");
633243c2aeb0SSepherosa Ziehau 
633343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
633443c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx512Octetsto1023Octets",
633543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx512Octetsto1023Octets,
633643c2aeb0SSepherosa Ziehau 		0, "Bytes received in 512 to 1023 byte packets");
633743c2aeb0SSepherosa Ziehau 
633843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
633943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx1024Octetsto1522Octets",
634043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1024Octetsto1522Octets,
634143c2aeb0SSepherosa Ziehau 		0, "Bytes received in 1024 t0 1522 byte packets");
634243c2aeb0SSepherosa Ziehau 
634343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
634443c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx1523Octetsto9022Octets",
634543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1523Octetsto9022Octets,
634643c2aeb0SSepherosa Ziehau 		0, "Bytes received in 1523 to 9022 byte packets");
634743c2aeb0SSepherosa Ziehau 
634843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
634943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx64Octets",
635043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx64Octets,
635143c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 64 byte packets");
635243c2aeb0SSepherosa Ziehau 
635343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
635443c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx65Octetsto127Octets",
635543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx65Octetsto127Octets,
635643c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 65 to 127 byte packets");
635743c2aeb0SSepherosa Ziehau 
635843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
635943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx128Octetsto255Octets",
636043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx128Octetsto255Octets,
636143c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 128 to 255 byte packets");
636243c2aeb0SSepherosa Ziehau 
636343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
636443c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx256Octetsto511Octets",
636543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx256Octetsto511Octets,
636643c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 256 to 511 byte packets");
636743c2aeb0SSepherosa Ziehau 
636843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
636943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx512Octetsto1023Octets",
637043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx512Octetsto1023Octets,
637143c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 512 to 1023 byte packets");
637243c2aeb0SSepherosa Ziehau 
637343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
637443c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx1024Octetsto1522Octets",
637543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1024Octetsto1522Octets,
637643c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 1024 to 1522 byte packets");
637743c2aeb0SSepherosa Ziehau 
637843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
637943c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx1523Octetsto9022Octets",
638043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1523Octetsto9022Octets,
638143c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 1523 to 9022 byte packets");
638243c2aeb0SSepherosa Ziehau 
638343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
638443c2aeb0SSepherosa Ziehau 		"stat_XonPauseFramesReceived",
638543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_XonPauseFramesReceived,
638643c2aeb0SSepherosa Ziehau 		0, "XON pause frames receved");
638743c2aeb0SSepherosa Ziehau 
638843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
638943c2aeb0SSepherosa Ziehau 		"stat_XoffPauseFramesReceived",
639043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_XoffPauseFramesReceived,
639143c2aeb0SSepherosa Ziehau 		0, "XOFF pause frames received");
639243c2aeb0SSepherosa Ziehau 
639343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
639443c2aeb0SSepherosa Ziehau 		"stat_OutXonSent",
639543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_OutXonSent,
639643c2aeb0SSepherosa Ziehau 		0, "XON pause frames sent");
639743c2aeb0SSepherosa Ziehau 
639843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
639943c2aeb0SSepherosa Ziehau 		"stat_OutXoffSent",
640043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_OutXoffSent,
640143c2aeb0SSepherosa Ziehau 		0, "XOFF pause frames sent");
640243c2aeb0SSepherosa Ziehau 
640343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
640443c2aeb0SSepherosa Ziehau 		"stat_FlowControlDone",
640543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_FlowControlDone,
640643c2aeb0SSepherosa Ziehau 		0, "Flow control done");
640743c2aeb0SSepherosa Ziehau 
640843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
640943c2aeb0SSepherosa Ziehau 		"stat_MacControlFramesReceived",
641043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_MacControlFramesReceived,
641143c2aeb0SSepherosa Ziehau 		0, "MAC control frames received");
641243c2aeb0SSepherosa Ziehau 
641343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
641443c2aeb0SSepherosa Ziehau 		"stat_XoffStateEntered",
641543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_XoffStateEntered,
641643c2aeb0SSepherosa Ziehau 		0, "XOFF state entered");
641743c2aeb0SSepherosa Ziehau 
641843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
641943c2aeb0SSepherosa Ziehau 		"stat_IfInFramesL2FilterDiscards",
642043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInFramesL2FilterDiscards,
642143c2aeb0SSepherosa Ziehau 		0, "Received L2 packets discarded");
642243c2aeb0SSepherosa Ziehau 
642343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
642443c2aeb0SSepherosa Ziehau 		"stat_IfInRuleCheckerDiscards",
642543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInRuleCheckerDiscards,
642643c2aeb0SSepherosa Ziehau 		0, "Received packets discarded by rule");
642743c2aeb0SSepherosa Ziehau 
642843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
642943c2aeb0SSepherosa Ziehau 		"stat_IfInFTQDiscards",
643043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInFTQDiscards,
643143c2aeb0SSepherosa Ziehau 		0, "Received packet FTQ discards");
643243c2aeb0SSepherosa Ziehau 
643343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
643443c2aeb0SSepherosa Ziehau 		"stat_IfInMBUFDiscards",
643543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInMBUFDiscards,
643643c2aeb0SSepherosa Ziehau 		0, "Received packets discarded due to lack of controller buffer memory");
643743c2aeb0SSepherosa Ziehau 
643843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
643943c2aeb0SSepherosa Ziehau 		"stat_IfInRuleCheckerP4Hit",
644043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInRuleCheckerP4Hit,
644143c2aeb0SSepherosa Ziehau 		0, "Received packets rule checker hits");
644243c2aeb0SSepherosa Ziehau 
644343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
644443c2aeb0SSepherosa Ziehau 		"stat_CatchupInRuleCheckerDiscards",
644543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerDiscards,
644643c2aeb0SSepherosa Ziehau 		0, "Received packets discarded in Catchup path");
644743c2aeb0SSepherosa Ziehau 
644843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
644943c2aeb0SSepherosa Ziehau 		"stat_CatchupInFTQDiscards",
645043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_CatchupInFTQDiscards,
645143c2aeb0SSepherosa Ziehau 		0, "Received packets discarded in FTQ in Catchup path");
645243c2aeb0SSepherosa Ziehau 
645343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
645443c2aeb0SSepherosa Ziehau 		"stat_CatchupInMBUFDiscards",
645543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_CatchupInMBUFDiscards,
645643c2aeb0SSepherosa Ziehau 		0, "Received packets discarded in controller buffer memory in Catchup path");
645743c2aeb0SSepherosa Ziehau 
645843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
645943c2aeb0SSepherosa Ziehau 		"stat_CatchupInRuleCheckerP4Hit",
646043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerP4Hit,
646143c2aeb0SSepherosa Ziehau 		0, "Received packets rule checker hits in Catchup path");
646243c2aeb0SSepherosa Ziehau 
646343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
646443c2aeb0SSepherosa Ziehau 		"com_no_buffers",
646543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->com_no_buffers,
646643c2aeb0SSepherosa Ziehau 		0, "Valid packets received but no RX buffers available");
646743c2aeb0SSepherosa Ziehau 
646843c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
646943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
647043c2aeb0SSepherosa Ziehau 		"driver_state", CTLTYPE_INT | CTLFLAG_RW,
647143c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
647243c2aeb0SSepherosa Ziehau 		bce_sysctl_driver_state, "I", "Drive state information");
647343c2aeb0SSepherosa Ziehau 
647443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
647543c2aeb0SSepherosa Ziehau 		"hw_state", CTLTYPE_INT | CTLFLAG_RW,
647643c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
647743c2aeb0SSepherosa Ziehau 		bce_sysctl_hw_state, "I", "Hardware state information");
647843c2aeb0SSepherosa Ziehau 
647943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
648043c2aeb0SSepherosa Ziehau 		"dump_rx_chain", CTLTYPE_INT | CTLFLAG_RW,
648143c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
648243c2aeb0SSepherosa Ziehau 		bce_sysctl_dump_rx_chain, "I", "Dump rx_bd chain");
648343c2aeb0SSepherosa Ziehau 
648443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
648543c2aeb0SSepherosa Ziehau 		"dump_tx_chain", CTLTYPE_INT | CTLFLAG_RW,
648643c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
648743c2aeb0SSepherosa Ziehau 		bce_sysctl_dump_tx_chain, "I", "Dump tx_bd chain");
648843c2aeb0SSepherosa Ziehau 
648943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
649043c2aeb0SSepherosa Ziehau 		"breakpoint", CTLTYPE_INT | CTLFLAG_RW,
649143c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
649243c2aeb0SSepherosa Ziehau 		bce_sysctl_breakpoint, "I", "Driver breakpoint");
649343c2aeb0SSepherosa Ziehau 
649443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
649543c2aeb0SSepherosa Ziehau 		"reg_read", CTLTYPE_INT | CTLFLAG_RW,
649643c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
649743c2aeb0SSepherosa Ziehau 		bce_sysctl_reg_read, "I", "Register read");
649843c2aeb0SSepherosa Ziehau 
649943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
650043c2aeb0SSepherosa Ziehau 		"phy_read", CTLTYPE_INT | CTLFLAG_RW,
650143c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
650243c2aeb0SSepherosa Ziehau 		bce_sysctl_phy_read, "I", "PHY register read");
650343c2aeb0SSepherosa Ziehau 
650443c2aeb0SSepherosa Ziehau #endif
650543c2aeb0SSepherosa Ziehau 
650643c2aeb0SSepherosa Ziehau }
650743c2aeb0SSepherosa Ziehau 
650843c2aeb0SSepherosa Ziehau 
650943c2aeb0SSepherosa Ziehau /****************************************************************************/
651043c2aeb0SSepherosa Ziehau /* BCE Debug Routines                                                       */
651143c2aeb0SSepherosa Ziehau /****************************************************************************/
651243c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
651343c2aeb0SSepherosa Ziehau 
651443c2aeb0SSepherosa Ziehau /****************************************************************************/
651543c2aeb0SSepherosa Ziehau /* Freezes the controller to allow for a cohesive state dump.               */
651643c2aeb0SSepherosa Ziehau /*                                                                          */
651743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
651843c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
651943c2aeb0SSepherosa Ziehau /****************************************************************************/
652043c2aeb0SSepherosa Ziehau static void
652143c2aeb0SSepherosa Ziehau bce_freeze_controller(struct bce_softc *sc)
652243c2aeb0SSepherosa Ziehau {
652343c2aeb0SSepherosa Ziehau 	uint32_t val;
652443c2aeb0SSepherosa Ziehau 
652543c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_COMMAND);
652643c2aeb0SSepherosa Ziehau 	val |= BCE_MISC_COMMAND_DISABLE_ALL;
652743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_COMMAND, val);
652843c2aeb0SSepherosa Ziehau }
652943c2aeb0SSepherosa Ziehau 
653043c2aeb0SSepherosa Ziehau 
653143c2aeb0SSepherosa Ziehau /****************************************************************************/
653243c2aeb0SSepherosa Ziehau /* Unfreezes the controller after a freeze operation.  This may not always  */
653343c2aeb0SSepherosa Ziehau /* work and the controller will require a reset!                            */
653443c2aeb0SSepherosa Ziehau /*                                                                          */
653543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
653643c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
653743c2aeb0SSepherosa Ziehau /****************************************************************************/
653843c2aeb0SSepherosa Ziehau static void
653943c2aeb0SSepherosa Ziehau bce_unfreeze_controller(struct bce_softc *sc)
654043c2aeb0SSepherosa Ziehau {
654143c2aeb0SSepherosa Ziehau 	uint32_t val;
654243c2aeb0SSepherosa Ziehau 
654343c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_COMMAND);
654443c2aeb0SSepherosa Ziehau 	val |= BCE_MISC_COMMAND_ENABLE_ALL;
654543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_COMMAND, val);
654643c2aeb0SSepherosa Ziehau }
654743c2aeb0SSepherosa Ziehau 
654843c2aeb0SSepherosa Ziehau 
654943c2aeb0SSepherosa Ziehau /****************************************************************************/
655043c2aeb0SSepherosa Ziehau /* Prints out information about an mbuf.                                    */
655143c2aeb0SSepherosa Ziehau /*                                                                          */
655243c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
655343c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
655443c2aeb0SSepherosa Ziehau /****************************************************************************/
655543c2aeb0SSepherosa Ziehau static void
655643c2aeb0SSepherosa Ziehau bce_dump_mbuf(struct bce_softc *sc, struct mbuf *m)
655743c2aeb0SSepherosa Ziehau {
655843c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
655943c2aeb0SSepherosa Ziehau 	uint32_t val_hi, val_lo;
656043c2aeb0SSepherosa Ziehau 	struct mbuf *mp = m;
656143c2aeb0SSepherosa Ziehau 
656243c2aeb0SSepherosa Ziehau 	if (m == NULL) {
656343c2aeb0SSepherosa Ziehau 		/* Index out of range. */
656443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "mbuf: null pointer\n");
656543c2aeb0SSepherosa Ziehau 		return;
656643c2aeb0SSepherosa Ziehau 	}
656743c2aeb0SSepherosa Ziehau 
656843c2aeb0SSepherosa Ziehau 	while (mp) {
656943c2aeb0SSepherosa Ziehau 		val_hi = BCE_ADDR_HI(mp);
657043c2aeb0SSepherosa Ziehau 		val_lo = BCE_ADDR_LO(mp);
657143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "mbuf: vaddr = 0x%08X:%08X, m_len = %d, "
657243c2aeb0SSepherosa Ziehau 			  "m_flags = ( ", val_hi, val_lo, mp->m_len);
657343c2aeb0SSepherosa Ziehau 
657443c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_EXT)
657543c2aeb0SSepherosa Ziehau 			kprintf("M_EXT ");
657643c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_PKTHDR)
657743c2aeb0SSepherosa Ziehau 			kprintf("M_PKTHDR ");
657843c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_EOR)
657943c2aeb0SSepherosa Ziehau 			kprintf("M_EOR ");
658043c2aeb0SSepherosa Ziehau #ifdef M_RDONLY
658143c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_RDONLY)
658243c2aeb0SSepherosa Ziehau 			kprintf("M_RDONLY ");
658343c2aeb0SSepherosa Ziehau #endif
658443c2aeb0SSepherosa Ziehau 
658543c2aeb0SSepherosa Ziehau 		val_hi = BCE_ADDR_HI(mp->m_data);
658643c2aeb0SSepherosa Ziehau 		val_lo = BCE_ADDR_LO(mp->m_data);
658743c2aeb0SSepherosa Ziehau 		kprintf(") m_data = 0x%08X:%08X\n", val_hi, val_lo);
658843c2aeb0SSepherosa Ziehau 
658943c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_PKTHDR) {
659043c2aeb0SSepherosa Ziehau 			if_printf(ifp, "- m_pkthdr: flags = ( ");
659143c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_BCAST)
659243c2aeb0SSepherosa Ziehau 				kprintf("M_BCAST ");
659343c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_MCAST)
659443c2aeb0SSepherosa Ziehau 				kprintf("M_MCAST ");
659543c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_FRAG)
659643c2aeb0SSepherosa Ziehau 				kprintf("M_FRAG ");
659743c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_FIRSTFRAG)
659843c2aeb0SSepherosa Ziehau 				kprintf("M_FIRSTFRAG ");
659943c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_LASTFRAG)
660043c2aeb0SSepherosa Ziehau 				kprintf("M_LASTFRAG ");
660143c2aeb0SSepherosa Ziehau #ifdef M_VLANTAG
660243c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_VLANTAG)
660343c2aeb0SSepherosa Ziehau 				kprintf("M_VLANTAG ");
660443c2aeb0SSepherosa Ziehau #endif
660543c2aeb0SSepherosa Ziehau #ifdef M_PROMISC
660643c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_PROMISC)
660743c2aeb0SSepherosa Ziehau 				kprintf("M_PROMISC ");
660843c2aeb0SSepherosa Ziehau #endif
660943c2aeb0SSepherosa Ziehau 			kprintf(") csum_flags = ( ");
661043c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_IP)
661143c2aeb0SSepherosa Ziehau 				kprintf("CSUM_IP ");
661243c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_TCP)
661343c2aeb0SSepherosa Ziehau 				kprintf("CSUM_TCP ");
661443c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_UDP)
661543c2aeb0SSepherosa Ziehau 				kprintf("CSUM_UDP ");
661643c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_IP_FRAGS)
661743c2aeb0SSepherosa Ziehau 				kprintf("CSUM_IP_FRAGS ");
661843c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_FRAGMENT)
661943c2aeb0SSepherosa Ziehau 				kprintf("CSUM_FRAGMENT ");
662043c2aeb0SSepherosa Ziehau #ifdef CSUM_TSO
662143c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_TSO)
662243c2aeb0SSepherosa Ziehau 				kprintf("CSUM_TSO ");
662343c2aeb0SSepherosa Ziehau #endif
662443c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_IP_CHECKED)
662543c2aeb0SSepherosa Ziehau 				kprintf("CSUM_IP_CHECKED ");
662643c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_IP_VALID)
662743c2aeb0SSepherosa Ziehau 				kprintf("CSUM_IP_VALID ");
662843c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_DATA_VALID)
662943c2aeb0SSepherosa Ziehau 				kprintf("CSUM_DATA_VALID ");
663043c2aeb0SSepherosa Ziehau 			kprintf(")\n");
663143c2aeb0SSepherosa Ziehau 		}
663243c2aeb0SSepherosa Ziehau 
663343c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_EXT) {
663443c2aeb0SSepherosa Ziehau 			val_hi = BCE_ADDR_HI(mp->m_ext.ext_buf);
663543c2aeb0SSepherosa Ziehau 			val_lo = BCE_ADDR_LO(mp->m_ext.ext_buf);
663643c2aeb0SSepherosa Ziehau 			if_printf(ifp, "- m_ext: vaddr = 0x%08X:%08X, "
663743c2aeb0SSepherosa Ziehau 				  "ext_size = %d\n",
663843c2aeb0SSepherosa Ziehau 				  val_hi, val_lo, mp->m_ext.ext_size);
663943c2aeb0SSepherosa Ziehau 		}
664043c2aeb0SSepherosa Ziehau 		mp = mp->m_next;
664143c2aeb0SSepherosa Ziehau 	}
664243c2aeb0SSepherosa Ziehau }
664343c2aeb0SSepherosa Ziehau 
664443c2aeb0SSepherosa Ziehau 
664543c2aeb0SSepherosa Ziehau /****************************************************************************/
664643c2aeb0SSepherosa Ziehau /* Prints out the mbufs in the TX mbuf chain.                               */
664743c2aeb0SSepherosa Ziehau /*                                                                          */
664843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
664943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
665043c2aeb0SSepherosa Ziehau /****************************************************************************/
665143c2aeb0SSepherosa Ziehau static void
665243c2aeb0SSepherosa Ziehau bce_dump_tx_mbuf_chain(struct bce_softc *sc, int chain_prod, int count)
665343c2aeb0SSepherosa Ziehau {
665443c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
665543c2aeb0SSepherosa Ziehau 	int i;
665643c2aeb0SSepherosa Ziehau 
665743c2aeb0SSepherosa Ziehau 	if_printf(ifp,
665843c2aeb0SSepherosa Ziehau 	"----------------------------"
665943c2aeb0SSepherosa Ziehau 	"  tx mbuf data  "
666043c2aeb0SSepherosa Ziehau 	"----------------------------\n");
666143c2aeb0SSepherosa Ziehau 
666243c2aeb0SSepherosa Ziehau 	for (i = 0; i < count; i++) {
666343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "txmbuf[%d]\n", chain_prod);
666443c2aeb0SSepherosa Ziehau 		bce_dump_mbuf(sc, sc->tx_mbuf_ptr[chain_prod]);
666543c2aeb0SSepherosa Ziehau 		chain_prod = TX_CHAIN_IDX(NEXT_TX_BD(chain_prod));
666643c2aeb0SSepherosa Ziehau 	}
666743c2aeb0SSepherosa Ziehau 
666843c2aeb0SSepherosa Ziehau 	if_printf(ifp,
666943c2aeb0SSepherosa Ziehau 	"----------------------------"
667043c2aeb0SSepherosa Ziehau 	"----------------"
667143c2aeb0SSepherosa Ziehau 	"----------------------------\n");
667243c2aeb0SSepherosa Ziehau }
667343c2aeb0SSepherosa Ziehau 
667443c2aeb0SSepherosa Ziehau 
667543c2aeb0SSepherosa Ziehau /****************************************************************************/
667643c2aeb0SSepherosa Ziehau /* Prints out the mbufs in the RX mbuf chain.                               */
667743c2aeb0SSepherosa Ziehau /*                                                                          */
667843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
667943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
668043c2aeb0SSepherosa Ziehau /****************************************************************************/
668143c2aeb0SSepherosa Ziehau static void
668243c2aeb0SSepherosa Ziehau bce_dump_rx_mbuf_chain(struct bce_softc *sc, int chain_prod, int count)
668343c2aeb0SSepherosa Ziehau {
668443c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
668543c2aeb0SSepherosa Ziehau 	int i;
668643c2aeb0SSepherosa Ziehau 
668743c2aeb0SSepherosa Ziehau 	if_printf(ifp,
668843c2aeb0SSepherosa Ziehau 	"----------------------------"
668943c2aeb0SSepherosa Ziehau 	"  rx mbuf data  "
669043c2aeb0SSepherosa Ziehau 	"----------------------------\n");
669143c2aeb0SSepherosa Ziehau 
669243c2aeb0SSepherosa Ziehau 	for (i = 0; i < count; i++) {
669343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rxmbuf[0x%04X]\n", chain_prod);
669443c2aeb0SSepherosa Ziehau 		bce_dump_mbuf(sc, sc->rx_mbuf_ptr[chain_prod]);
669543c2aeb0SSepherosa Ziehau 		chain_prod = RX_CHAIN_IDX(NEXT_RX_BD(chain_prod));
669643c2aeb0SSepherosa Ziehau 	}
669743c2aeb0SSepherosa Ziehau 
669843c2aeb0SSepherosa Ziehau 	if_printf(ifp,
669943c2aeb0SSepherosa Ziehau 	"----------------------------"
670043c2aeb0SSepherosa Ziehau 	"----------------"
670143c2aeb0SSepherosa Ziehau 	"----------------------------\n");
670243c2aeb0SSepherosa Ziehau }
670343c2aeb0SSepherosa Ziehau 
670443c2aeb0SSepherosa Ziehau 
670543c2aeb0SSepherosa Ziehau /****************************************************************************/
670643c2aeb0SSepherosa Ziehau /* Prints out a tx_bd structure.                                            */
670743c2aeb0SSepherosa Ziehau /*                                                                          */
670843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
670943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
671043c2aeb0SSepherosa Ziehau /****************************************************************************/
671143c2aeb0SSepherosa Ziehau static void
671243c2aeb0SSepherosa Ziehau bce_dump_txbd(struct bce_softc *sc, int idx, struct tx_bd *txbd)
671343c2aeb0SSepherosa Ziehau {
671443c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
671543c2aeb0SSepherosa Ziehau 
671643c2aeb0SSepherosa Ziehau 	if (idx > MAX_TX_BD) {
671743c2aeb0SSepherosa Ziehau 		/* Index out of range. */
671843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "tx_bd[0x%04X]: Invalid tx_bd index!\n", idx);
671943c2aeb0SSepherosa Ziehau 	} else if ((idx & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE) {
672043c2aeb0SSepherosa Ziehau 		/* TX Chain page pointer. */
672143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, "
672243c2aeb0SSepherosa Ziehau 			  "chain page pointer\n",
672343c2aeb0SSepherosa Ziehau 			  idx, txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo);
672443c2aeb0SSepherosa Ziehau 	} else {
672543c2aeb0SSepherosa Ziehau 		/* Normal tx_bd entry. */
672643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, "
672743c2aeb0SSepherosa Ziehau 			  "nbytes = 0x%08X, "
672843c2aeb0SSepherosa Ziehau 			  "vlan tag= 0x%04X, flags = 0x%04X (",
672943c2aeb0SSepherosa Ziehau 			  idx, txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo,
673043c2aeb0SSepherosa Ziehau 			  txbd->tx_bd_mss_nbytes,
673143c2aeb0SSepherosa Ziehau 			  txbd->tx_bd_vlan_tag, txbd->tx_bd_flags);
673243c2aeb0SSepherosa Ziehau 
673343c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_CONN_FAULT)
673443c2aeb0SSepherosa Ziehau 			kprintf(" CONN_FAULT");
673543c2aeb0SSepherosa Ziehau 
673643c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_TCP_UDP_CKSUM)
673743c2aeb0SSepherosa Ziehau 			kprintf(" TCP_UDP_CKSUM");
673843c2aeb0SSepherosa Ziehau 
673943c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_IP_CKSUM)
674043c2aeb0SSepherosa Ziehau 			kprintf(" IP_CKSUM");
674143c2aeb0SSepherosa Ziehau 
674243c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_VLAN_TAG)
674343c2aeb0SSepherosa Ziehau 			kprintf("  VLAN");
674443c2aeb0SSepherosa Ziehau 
674543c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_COAL_NOW)
674643c2aeb0SSepherosa Ziehau 			kprintf(" COAL_NOW");
674743c2aeb0SSepherosa Ziehau 
674843c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_DONT_GEN_CRC)
674943c2aeb0SSepherosa Ziehau 			kprintf(" DONT_GEN_CRC");
675043c2aeb0SSepherosa Ziehau 
675143c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_START)
675243c2aeb0SSepherosa Ziehau 			kprintf(" START");
675343c2aeb0SSepherosa Ziehau 
675443c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_END)
675543c2aeb0SSepherosa Ziehau 			kprintf(" END");
675643c2aeb0SSepherosa Ziehau 
675743c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_LSO)
675843c2aeb0SSepherosa Ziehau 			kprintf(" LSO");
675943c2aeb0SSepherosa Ziehau 
676043c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_OPTION_WORD)
676143c2aeb0SSepherosa Ziehau 			kprintf(" OPTION_WORD");
676243c2aeb0SSepherosa Ziehau 
676343c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_FLAGS)
676443c2aeb0SSepherosa Ziehau 			kprintf(" FLAGS");
676543c2aeb0SSepherosa Ziehau 
676643c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_SNAP)
676743c2aeb0SSepherosa Ziehau 			kprintf(" SNAP");
676843c2aeb0SSepherosa Ziehau 
676943c2aeb0SSepherosa Ziehau 		kprintf(" )\n");
677043c2aeb0SSepherosa Ziehau 	}
677143c2aeb0SSepherosa Ziehau }
677243c2aeb0SSepherosa Ziehau 
677343c2aeb0SSepherosa Ziehau 
677443c2aeb0SSepherosa Ziehau /****************************************************************************/
677543c2aeb0SSepherosa Ziehau /* Prints out a rx_bd structure.                                            */
677643c2aeb0SSepherosa Ziehau /*                                                                          */
677743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
677843c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
677943c2aeb0SSepherosa Ziehau /****************************************************************************/
678043c2aeb0SSepherosa Ziehau static void
678143c2aeb0SSepherosa Ziehau bce_dump_rxbd(struct bce_softc *sc, int idx, struct rx_bd *rxbd)
678243c2aeb0SSepherosa Ziehau {
678343c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
678443c2aeb0SSepherosa Ziehau 
678543c2aeb0SSepherosa Ziehau 	if (idx > MAX_RX_BD) {
678643c2aeb0SSepherosa Ziehau 		/* Index out of range. */
678743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_bd[0x%04X]: Invalid rx_bd index!\n", idx);
678843c2aeb0SSepherosa Ziehau 	} else if ((idx & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE) {
678943c2aeb0SSepherosa Ziehau 		/* TX Chain page pointer. */
679043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, "
679143c2aeb0SSepherosa Ziehau 			  "chain page pointer\n",
679243c2aeb0SSepherosa Ziehau 			  idx, rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo);
679343c2aeb0SSepherosa Ziehau 	} else {
679443c2aeb0SSepherosa Ziehau 		/* Normal tx_bd entry. */
679543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, "
679643c2aeb0SSepherosa Ziehau 			  "nbytes = 0x%08X, flags = 0x%08X\n",
679743c2aeb0SSepherosa Ziehau 			  idx, rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo,
679843c2aeb0SSepherosa Ziehau 			  rxbd->rx_bd_len, rxbd->rx_bd_flags);
679943c2aeb0SSepherosa Ziehau 	}
680043c2aeb0SSepherosa Ziehau }
680143c2aeb0SSepherosa Ziehau 
680243c2aeb0SSepherosa Ziehau 
680343c2aeb0SSepherosa Ziehau /****************************************************************************/
680443c2aeb0SSepherosa Ziehau /* Prints out a l2_fhdr structure.                                          */
680543c2aeb0SSepherosa Ziehau /*                                                                          */
680643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
680743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
680843c2aeb0SSepherosa Ziehau /****************************************************************************/
680943c2aeb0SSepherosa Ziehau static void
681043c2aeb0SSepherosa Ziehau bce_dump_l2fhdr(struct bce_softc *sc, int idx, struct l2_fhdr *l2fhdr)
681143c2aeb0SSepherosa Ziehau {
681243c2aeb0SSepherosa Ziehau 	if_printf(&sc->arpcom.ac_if, "l2_fhdr[0x%04X]: status = 0x%08X, "
681343c2aeb0SSepherosa Ziehau 		  "pkt_len = 0x%04X, vlan = 0x%04x, "
681443c2aeb0SSepherosa Ziehau 		  "ip_xsum = 0x%04X, tcp_udp_xsum = 0x%04X\n",
681543c2aeb0SSepherosa Ziehau 		  idx, l2fhdr->l2_fhdr_status,
681643c2aeb0SSepherosa Ziehau 		  l2fhdr->l2_fhdr_pkt_len, l2fhdr->l2_fhdr_vlan_tag,
681743c2aeb0SSepherosa Ziehau 		  l2fhdr->l2_fhdr_ip_xsum, l2fhdr->l2_fhdr_tcp_udp_xsum);
681843c2aeb0SSepherosa Ziehau }
681943c2aeb0SSepherosa Ziehau 
682043c2aeb0SSepherosa Ziehau 
682143c2aeb0SSepherosa Ziehau /****************************************************************************/
682243c2aeb0SSepherosa Ziehau /* Prints out the tx chain.                                                 */
682343c2aeb0SSepherosa Ziehau /*                                                                          */
682443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
682543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
682643c2aeb0SSepherosa Ziehau /****************************************************************************/
682743c2aeb0SSepherosa Ziehau static void
682843c2aeb0SSepherosa Ziehau bce_dump_tx_chain(struct bce_softc *sc, int tx_prod, int count)
682943c2aeb0SSepherosa Ziehau {
683043c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
683143c2aeb0SSepherosa Ziehau 	int i;
683243c2aeb0SSepherosa Ziehau 
683343c2aeb0SSepherosa Ziehau 	/* First some info about the tx_bd chain structure. */
683443c2aeb0SSepherosa Ziehau 	if_printf(ifp,
683543c2aeb0SSepherosa Ziehau 	"----------------------------"
683643c2aeb0SSepherosa Ziehau 	"  tx_bd  chain  "
683743c2aeb0SSepherosa Ziehau 	"----------------------------\n");
683843c2aeb0SSepherosa Ziehau 
683943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "page size      = 0x%08X, "
684043c2aeb0SSepherosa Ziehau 		  "tx chain pages        = 0x%08X\n",
684143c2aeb0SSepherosa Ziehau 		  (uint32_t)BCM_PAGE_SIZE, (uint32_t)TX_PAGES);
684243c2aeb0SSepherosa Ziehau 
684343c2aeb0SSepherosa Ziehau 	if_printf(ifp, "tx_bd per page = 0x%08X, "
684443c2aeb0SSepherosa Ziehau 		  "usable tx_bd per page = 0x%08X\n",
684543c2aeb0SSepherosa Ziehau 		  (uint32_t)TOTAL_TX_BD_PER_PAGE,
684643c2aeb0SSepherosa Ziehau 		  (uint32_t)USABLE_TX_BD_PER_PAGE);
684743c2aeb0SSepherosa Ziehau 
684843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "total tx_bd    = 0x%08X\n", (uint32_t)TOTAL_TX_BD);
684943c2aeb0SSepherosa Ziehau 
685043c2aeb0SSepherosa Ziehau 	if_printf(ifp,
685143c2aeb0SSepherosa Ziehau 	"----------------------------"
685243c2aeb0SSepherosa Ziehau 	"  tx_bd data    "
685343c2aeb0SSepherosa Ziehau 	"----------------------------\n");
685443c2aeb0SSepherosa Ziehau 
685543c2aeb0SSepherosa Ziehau 	/* Now print out the tx_bd's themselves. */
685643c2aeb0SSepherosa Ziehau 	for (i = 0; i < count; i++) {
685743c2aeb0SSepherosa Ziehau 		struct tx_bd *txbd;
685843c2aeb0SSepherosa Ziehau 
685943c2aeb0SSepherosa Ziehau 	 	txbd = &sc->tx_bd_chain[TX_PAGE(tx_prod)][TX_IDX(tx_prod)];
686043c2aeb0SSepherosa Ziehau 		bce_dump_txbd(sc, tx_prod, txbd);
686143c2aeb0SSepherosa Ziehau 		tx_prod = TX_CHAIN_IDX(NEXT_TX_BD(tx_prod));
686243c2aeb0SSepherosa Ziehau 	}
686343c2aeb0SSepherosa Ziehau 
686443c2aeb0SSepherosa Ziehau 	if_printf(ifp,
686543c2aeb0SSepherosa Ziehau 	"----------------------------"
686643c2aeb0SSepherosa Ziehau 	"----------------"
686743c2aeb0SSepherosa Ziehau 	"----------------------------\n");
686843c2aeb0SSepherosa Ziehau }
686943c2aeb0SSepherosa Ziehau 
687043c2aeb0SSepherosa Ziehau 
687143c2aeb0SSepherosa Ziehau /****************************************************************************/
687243c2aeb0SSepherosa Ziehau /* Prints out the rx chain.                                                 */
687343c2aeb0SSepherosa Ziehau /*                                                                          */
687443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
687543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
687643c2aeb0SSepherosa Ziehau /****************************************************************************/
687743c2aeb0SSepherosa Ziehau static void
687843c2aeb0SSepherosa Ziehau bce_dump_rx_chain(struct bce_softc *sc, int rx_prod, int count)
687943c2aeb0SSepherosa Ziehau {
688043c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
688143c2aeb0SSepherosa Ziehau 	int i;
688243c2aeb0SSepherosa Ziehau 
688343c2aeb0SSepherosa Ziehau 	/* First some info about the tx_bd chain structure. */
688443c2aeb0SSepherosa Ziehau 	if_printf(ifp,
688543c2aeb0SSepherosa Ziehau 	"----------------------------"
688643c2aeb0SSepherosa Ziehau 	"  rx_bd  chain  "
688743c2aeb0SSepherosa Ziehau 	"----------------------------\n");
688843c2aeb0SSepherosa Ziehau 
688943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "page size      = 0x%08X, "
689043c2aeb0SSepherosa Ziehau 		  "rx chain pages        = 0x%08X\n",
689143c2aeb0SSepherosa Ziehau 		  (uint32_t)BCM_PAGE_SIZE, (uint32_t)RX_PAGES);
689243c2aeb0SSepherosa Ziehau 
689343c2aeb0SSepherosa Ziehau 	if_printf(ifp, "rx_bd per page = 0x%08X, "
689443c2aeb0SSepherosa Ziehau 		  "usable rx_bd per page = 0x%08X\n",
689543c2aeb0SSepherosa Ziehau 		  (uint32_t)TOTAL_RX_BD_PER_PAGE,
689643c2aeb0SSepherosa Ziehau 		  (uint32_t)USABLE_RX_BD_PER_PAGE);
689743c2aeb0SSepherosa Ziehau 
689843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "total rx_bd    = 0x%08X\n", (uint32_t)TOTAL_RX_BD);
689943c2aeb0SSepherosa Ziehau 
690043c2aeb0SSepherosa Ziehau 	if_printf(ifp,
690143c2aeb0SSepherosa Ziehau 	"----------------------------"
690243c2aeb0SSepherosa Ziehau 	"   rx_bd data   "
690343c2aeb0SSepherosa Ziehau 	"----------------------------\n");
690443c2aeb0SSepherosa Ziehau 
690543c2aeb0SSepherosa Ziehau 	/* Now print out the rx_bd's themselves. */
690643c2aeb0SSepherosa Ziehau 	for (i = 0; i < count; i++) {
690743c2aeb0SSepherosa Ziehau 		struct rx_bd *rxbd;
690843c2aeb0SSepherosa Ziehau 
690943c2aeb0SSepherosa Ziehau 		rxbd = &sc->rx_bd_chain[RX_PAGE(rx_prod)][RX_IDX(rx_prod)];
691043c2aeb0SSepherosa Ziehau 		bce_dump_rxbd(sc, rx_prod, rxbd);
691143c2aeb0SSepherosa Ziehau 		rx_prod = RX_CHAIN_IDX(NEXT_RX_BD(rx_prod));
691243c2aeb0SSepherosa Ziehau 	}
691343c2aeb0SSepherosa Ziehau 
691443c2aeb0SSepherosa Ziehau 	if_printf(ifp,
691543c2aeb0SSepherosa Ziehau 	"----------------------------"
691643c2aeb0SSepherosa Ziehau 	"----------------"
691743c2aeb0SSepherosa Ziehau 	"----------------------------\n");
691843c2aeb0SSepherosa Ziehau }
691943c2aeb0SSepherosa Ziehau 
692043c2aeb0SSepherosa Ziehau 
692143c2aeb0SSepherosa Ziehau /****************************************************************************/
692243c2aeb0SSepherosa Ziehau /* Prints out the status block from host memory.                            */
692343c2aeb0SSepherosa Ziehau /*                                                                          */
692443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
692543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
692643c2aeb0SSepherosa Ziehau /****************************************************************************/
692743c2aeb0SSepherosa Ziehau static void
692843c2aeb0SSepherosa Ziehau bce_dump_status_block(struct bce_softc *sc)
692943c2aeb0SSepherosa Ziehau {
693043c2aeb0SSepherosa Ziehau 	struct status_block *sblk = sc->status_block;
693143c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
693243c2aeb0SSepherosa Ziehau 
693343c2aeb0SSepherosa Ziehau 	if_printf(ifp,
693443c2aeb0SSepherosa Ziehau 	"----------------------------"
693543c2aeb0SSepherosa Ziehau 	"  Status Block  "
693643c2aeb0SSepherosa Ziehau 	"----------------------------\n");
693743c2aeb0SSepherosa Ziehau 
693843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "    0x%08X - attn_bits\n", sblk->status_attn_bits);
693943c2aeb0SSepherosa Ziehau 
694043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "    0x%08X - attn_bits_ack\n",
694143c2aeb0SSepherosa Ziehau 		  sblk->status_attn_bits_ack);
694243c2aeb0SSepherosa Ziehau 
694343c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%04X(0x%04X) - rx_cons0\n",
694443c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index0,
694543c2aeb0SSepherosa Ziehau 	    (uint16_t)RX_CHAIN_IDX(sblk->status_rx_quick_consumer_index0));
694643c2aeb0SSepherosa Ziehau 
694743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%04X(0x%04X) - tx_cons0\n",
694843c2aeb0SSepherosa Ziehau 	    sblk->status_tx_quick_consumer_index0,
694943c2aeb0SSepherosa Ziehau 	    (uint16_t)TX_CHAIN_IDX(sblk->status_tx_quick_consumer_index0));
695043c2aeb0SSepherosa Ziehau 
695143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "        0x%04X - status_idx\n", sblk->status_idx);
695243c2aeb0SSepherosa Ziehau 
695343c2aeb0SSepherosa Ziehau 	/* Theses indices are not used for normal L2 drivers. */
695443c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index1) {
695543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - rx_cons1\n",
695643c2aeb0SSepherosa Ziehau 		sblk->status_rx_quick_consumer_index1,
695743c2aeb0SSepherosa Ziehau 		(uint16_t)RX_CHAIN_IDX(sblk->status_rx_quick_consumer_index1));
695843c2aeb0SSepherosa Ziehau 	}
695943c2aeb0SSepherosa Ziehau 
696043c2aeb0SSepherosa Ziehau 	if (sblk->status_tx_quick_consumer_index1) {
696143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - tx_cons1\n",
696243c2aeb0SSepherosa Ziehau 		sblk->status_tx_quick_consumer_index1,
696343c2aeb0SSepherosa Ziehau 		(uint16_t)TX_CHAIN_IDX(sblk->status_tx_quick_consumer_index1));
696443c2aeb0SSepherosa Ziehau 	}
696543c2aeb0SSepherosa Ziehau 
696643c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index2) {
696743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X)- rx_cons2\n",
696843c2aeb0SSepherosa Ziehau 		sblk->status_rx_quick_consumer_index2,
696943c2aeb0SSepherosa Ziehau 		(uint16_t)RX_CHAIN_IDX(sblk->status_rx_quick_consumer_index2));
697043c2aeb0SSepherosa Ziehau 	}
697143c2aeb0SSepherosa Ziehau 
697243c2aeb0SSepherosa Ziehau 	if (sblk->status_tx_quick_consumer_index2) {
697343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - tx_cons2\n",
697443c2aeb0SSepherosa Ziehau 		sblk->status_tx_quick_consumer_index2,
697543c2aeb0SSepherosa Ziehau 		(uint16_t)TX_CHAIN_IDX(sblk->status_tx_quick_consumer_index2));
697643c2aeb0SSepherosa Ziehau 	}
697743c2aeb0SSepherosa Ziehau 
697843c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index3) {
697943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - rx_cons3\n",
698043c2aeb0SSepherosa Ziehau 		sblk->status_rx_quick_consumer_index3,
698143c2aeb0SSepherosa Ziehau 		(uint16_t)RX_CHAIN_IDX(sblk->status_rx_quick_consumer_index3));
698243c2aeb0SSepherosa Ziehau 	}
698343c2aeb0SSepherosa Ziehau 
698443c2aeb0SSepherosa Ziehau 	if (sblk->status_tx_quick_consumer_index3) {
698543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - tx_cons3\n",
698643c2aeb0SSepherosa Ziehau 		sblk->status_tx_quick_consumer_index3,
698743c2aeb0SSepherosa Ziehau 		(uint16_t)TX_CHAIN_IDX(sblk->status_tx_quick_consumer_index3));
698843c2aeb0SSepherosa Ziehau 	}
698943c2aeb0SSepherosa Ziehau 
699043c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index4 ||
699143c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index5) {
699243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons4  = 0x%08X, rx_cons5      = 0x%08X\n",
699343c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index4,
699443c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index5);
699543c2aeb0SSepherosa Ziehau 	}
699643c2aeb0SSepherosa Ziehau 
699743c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index6 ||
699843c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index7) {
699943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons6  = 0x%08X, rx_cons7      = 0x%08X\n",
700043c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index6,
700143c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index7);
700243c2aeb0SSepherosa Ziehau 	}
700343c2aeb0SSepherosa Ziehau 
700443c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index8 ||
700543c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index9) {
700643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons8  = 0x%08X, rx_cons9      = 0x%08X\n",
700743c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index8,
700843c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index9);
700943c2aeb0SSepherosa Ziehau 	}
701043c2aeb0SSepherosa Ziehau 
701143c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index10 ||
701243c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index11) {
701343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons10 = 0x%08X, rx_cons11     = 0x%08X\n",
701443c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index10,
701543c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index11);
701643c2aeb0SSepherosa Ziehau 	}
701743c2aeb0SSepherosa Ziehau 
701843c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index12 ||
701943c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index13) {
702043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons12 = 0x%08X, rx_cons13     = 0x%08X\n",
702143c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index12,
702243c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index13);
702343c2aeb0SSepherosa Ziehau 	}
702443c2aeb0SSepherosa Ziehau 
702543c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index14 ||
702643c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index15) {
702743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons14 = 0x%08X, rx_cons15     = 0x%08X\n",
702843c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index14,
702943c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index15);
703043c2aeb0SSepherosa Ziehau 	}
703143c2aeb0SSepherosa Ziehau 
703243c2aeb0SSepherosa Ziehau 	if (sblk->status_completion_producer_index ||
703343c2aeb0SSepherosa Ziehau 	    sblk->status_cmd_consumer_index) {
703443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "com_prod  = 0x%08X, cmd_cons      = 0x%08X\n",
703543c2aeb0SSepherosa Ziehau 			  sblk->status_completion_producer_index,
703643c2aeb0SSepherosa Ziehau 			  sblk->status_cmd_consumer_index);
703743c2aeb0SSepherosa Ziehau 	}
703843c2aeb0SSepherosa Ziehau 
703943c2aeb0SSepherosa Ziehau 	if_printf(ifp,
704043c2aeb0SSepherosa Ziehau 	"----------------------------"
704143c2aeb0SSepherosa Ziehau 	"----------------"
704243c2aeb0SSepherosa Ziehau 	"----------------------------\n");
704343c2aeb0SSepherosa Ziehau }
704443c2aeb0SSepherosa Ziehau 
704543c2aeb0SSepherosa Ziehau 
704643c2aeb0SSepherosa Ziehau /****************************************************************************/
704743c2aeb0SSepherosa Ziehau /* Prints out the statistics block.                                         */
704843c2aeb0SSepherosa Ziehau /*                                                                          */
704943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
705043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
705143c2aeb0SSepherosa Ziehau /****************************************************************************/
705243c2aeb0SSepherosa Ziehau static void
705343c2aeb0SSepherosa Ziehau bce_dump_stats_block(struct bce_softc *sc)
705443c2aeb0SSepherosa Ziehau {
705543c2aeb0SSepherosa Ziehau 	struct statistics_block *sblk = sc->stats_block;
705643c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
705743c2aeb0SSepherosa Ziehau 
705843c2aeb0SSepherosa Ziehau 	if_printf(ifp,
705943c2aeb0SSepherosa Ziehau 	"---------------"
706043c2aeb0SSepherosa Ziehau 	" Stats Block  (All Stats Not Shown Are 0) "
706143c2aeb0SSepherosa Ziehau 	"---------------\n");
706243c2aeb0SSepherosa Ziehau 
706343c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInOctets_hi || sblk->stat_IfHCInOctets_lo) {
706443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInOctets\n",
706543c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInOctets_hi,
706643c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInOctets_lo);
706743c2aeb0SSepherosa Ziehau 	}
706843c2aeb0SSepherosa Ziehau 
706943c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInBadOctets_hi || sblk->stat_IfHCInBadOctets_lo) {
707043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInBadOctets\n",
707143c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInBadOctets_hi,
707243c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInBadOctets_lo);
707343c2aeb0SSepherosa Ziehau 	}
707443c2aeb0SSepherosa Ziehau 
707543c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutOctets_hi || sblk->stat_IfHCOutOctets_lo) {
707643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutOctets\n",
707743c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutOctets_hi,
707843c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutOctets_lo);
707943c2aeb0SSepherosa Ziehau 	}
708043c2aeb0SSepherosa Ziehau 
708143c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutBadOctets_hi || sblk->stat_IfHCOutBadOctets_lo) {
708243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutBadOctets\n",
708343c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutBadOctets_hi,
708443c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutBadOctets_lo);
708543c2aeb0SSepherosa Ziehau 	}
708643c2aeb0SSepherosa Ziehau 
708743c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInUcastPkts_hi || sblk->stat_IfHCInUcastPkts_lo) {
708843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInUcastPkts\n",
708943c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInUcastPkts_hi,
709043c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInUcastPkts_lo);
709143c2aeb0SSepherosa Ziehau 	}
709243c2aeb0SSepherosa Ziehau 
709343c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInBroadcastPkts_hi ||
709443c2aeb0SSepherosa Ziehau 	    sblk->stat_IfHCInBroadcastPkts_lo) {
709543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInBroadcastPkts\n",
709643c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInBroadcastPkts_hi,
709743c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInBroadcastPkts_lo);
709843c2aeb0SSepherosa Ziehau 	}
709943c2aeb0SSepherosa Ziehau 
710043c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInMulticastPkts_hi ||
710143c2aeb0SSepherosa Ziehau 	    sblk->stat_IfHCInMulticastPkts_lo) {
710243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInMulticastPkts\n",
710343c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInMulticastPkts_hi,
710443c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInMulticastPkts_lo);
710543c2aeb0SSepherosa Ziehau 	}
710643c2aeb0SSepherosa Ziehau 
710743c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutUcastPkts_hi || sblk->stat_IfHCOutUcastPkts_lo) {
710843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutUcastPkts\n",
710943c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutUcastPkts_hi,
711043c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutUcastPkts_lo);
711143c2aeb0SSepherosa Ziehau 	}
711243c2aeb0SSepherosa Ziehau 
711343c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutBroadcastPkts_hi ||
711443c2aeb0SSepherosa Ziehau 	    sblk->stat_IfHCOutBroadcastPkts_lo) {
711543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutBroadcastPkts\n",
711643c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutBroadcastPkts_hi,
711743c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutBroadcastPkts_lo);
711843c2aeb0SSepherosa Ziehau 	}
711943c2aeb0SSepherosa Ziehau 
712043c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutMulticastPkts_hi ||
712143c2aeb0SSepherosa Ziehau 	    sblk->stat_IfHCOutMulticastPkts_lo) {
712243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutMulticastPkts\n",
712343c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutMulticastPkts_hi,
712443c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutMulticastPkts_lo);
712543c2aeb0SSepherosa Ziehau 	}
712643c2aeb0SSepherosa Ziehau 
712743c2aeb0SSepherosa Ziehau 	if (sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors) {
712843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
712943c2aeb0SSepherosa Ziehau 		"emac_tx_stat_dot3statsinternalmactransmiterrors\n",
713043c2aeb0SSepherosa Ziehau 		sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors);
713143c2aeb0SSepherosa Ziehau 	}
713243c2aeb0SSepherosa Ziehau 
713343c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsCarrierSenseErrors) {
713443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
713543c2aeb0SSepherosa Ziehau 			  "Dot3StatsCarrierSenseErrors\n",
713643c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsCarrierSenseErrors);
713743c2aeb0SSepherosa Ziehau 	}
713843c2aeb0SSepherosa Ziehau 
713943c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsFCSErrors) {
714043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : Dot3StatsFCSErrors\n",
714143c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsFCSErrors);
714243c2aeb0SSepherosa Ziehau 	}
714343c2aeb0SSepherosa Ziehau 
714443c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsAlignmentErrors) {
714543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : Dot3StatsAlignmentErrors\n",
714643c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsAlignmentErrors);
714743c2aeb0SSepherosa Ziehau 	}
714843c2aeb0SSepherosa Ziehau 
714943c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsSingleCollisionFrames) {
715043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
715143c2aeb0SSepherosa Ziehau 			  "Dot3StatsSingleCollisionFrames\n",
715243c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsSingleCollisionFrames);
715343c2aeb0SSepherosa Ziehau 	}
715443c2aeb0SSepherosa Ziehau 
715543c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsMultipleCollisionFrames) {
715643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
715743c2aeb0SSepherosa Ziehau 			  "Dot3StatsMultipleCollisionFrames\n",
715843c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsMultipleCollisionFrames);
715943c2aeb0SSepherosa Ziehau 	}
716043c2aeb0SSepherosa Ziehau 
716143c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsDeferredTransmissions) {
716243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
716343c2aeb0SSepherosa Ziehau 			  "Dot3StatsDeferredTransmissions\n",
716443c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsDeferredTransmissions);
716543c2aeb0SSepherosa Ziehau 	}
716643c2aeb0SSepherosa Ziehau 
716743c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsExcessiveCollisions) {
716843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
716943c2aeb0SSepherosa Ziehau 			  "Dot3StatsExcessiveCollisions\n",
717043c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsExcessiveCollisions);
717143c2aeb0SSepherosa Ziehau 	}
717243c2aeb0SSepherosa Ziehau 
717343c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsLateCollisions) {
717443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : Dot3StatsLateCollisions\n",
717543c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsLateCollisions);
717643c2aeb0SSepherosa Ziehau 	}
717743c2aeb0SSepherosa Ziehau 
717843c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsCollisions) {
717943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsCollisions\n",
718043c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsCollisions);
718143c2aeb0SSepherosa Ziehau 	}
718243c2aeb0SSepherosa Ziehau 
718343c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsFragments)  {
718443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsFragments\n",
718543c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsFragments);
718643c2aeb0SSepherosa Ziehau 	}
718743c2aeb0SSepherosa Ziehau 
718843c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsJabbers) {
718943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsJabbers\n",
719043c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsJabbers);
719143c2aeb0SSepherosa Ziehau 	}
719243c2aeb0SSepherosa Ziehau 
719343c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsUndersizePkts) {
719443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsUndersizePkts\n",
719543c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsUndersizePkts);
719643c2aeb0SSepherosa Ziehau 	}
719743c2aeb0SSepherosa Ziehau 
719843c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsOverrsizePkts) {
719943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsOverrsizePkts\n",
720043c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsOverrsizePkts);
720143c2aeb0SSepherosa Ziehau 	}
720243c2aeb0SSepherosa Ziehau 
720343c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx64Octets) {
720443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsPktsRx64Octets\n",
720543c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx64Octets);
720643c2aeb0SSepherosa Ziehau 	}
720743c2aeb0SSepherosa Ziehau 
720843c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx65Octetsto127Octets) {
720943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
721043c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx65Octetsto127Octets\n",
721143c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx65Octetsto127Octets);
721243c2aeb0SSepherosa Ziehau 	}
721343c2aeb0SSepherosa Ziehau 
721443c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx128Octetsto255Octets) {
721543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
721643c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx128Octetsto255Octets\n",
721743c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx128Octetsto255Octets);
721843c2aeb0SSepherosa Ziehau 	}
721943c2aeb0SSepherosa Ziehau 
722043c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx256Octetsto511Octets) {
722143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
722243c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx256Octetsto511Octets\n",
722343c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx256Octetsto511Octets);
722443c2aeb0SSepherosa Ziehau 	}
722543c2aeb0SSepherosa Ziehau 
722643c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx512Octetsto1023Octets) {
722743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
722843c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx512Octetsto1023Octets\n",
722943c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx512Octetsto1023Octets);
723043c2aeb0SSepherosa Ziehau 	}
723143c2aeb0SSepherosa Ziehau 
723243c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets) {
723343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
723443c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx1024Octetsto1522Octets\n",
723543c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets);
723643c2aeb0SSepherosa Ziehau 	}
723743c2aeb0SSepherosa Ziehau 
723843c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets) {
723943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
724043c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx1523Octetsto9022Octets\n",
724143c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets);
724243c2aeb0SSepherosa Ziehau 	}
724343c2aeb0SSepherosa Ziehau 
724443c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx64Octets) {
724543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsPktsTx64Octets\n",
724643c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx64Octets);
724743c2aeb0SSepherosa Ziehau 	}
724843c2aeb0SSepherosa Ziehau 
724943c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx65Octetsto127Octets) {
725043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
725143c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx65Octetsto127Octets\n",
725243c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx65Octetsto127Octets);
725343c2aeb0SSepherosa Ziehau 	}
725443c2aeb0SSepherosa Ziehau 
725543c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx128Octetsto255Octets) {
725643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
725743c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx128Octetsto255Octets\n",
725843c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx128Octetsto255Octets);
725943c2aeb0SSepherosa Ziehau 	}
726043c2aeb0SSepherosa Ziehau 
726143c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx256Octetsto511Octets) {
726243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
726343c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx256Octetsto511Octets\n",
726443c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx256Octetsto511Octets);
726543c2aeb0SSepherosa Ziehau 	}
726643c2aeb0SSepherosa Ziehau 
726743c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx512Octetsto1023Octets) {
726843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
726943c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx512Octetsto1023Octets\n",
727043c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx512Octetsto1023Octets);
727143c2aeb0SSepherosa Ziehau 	}
727243c2aeb0SSepherosa Ziehau 
727343c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets) {
727443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
727543c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx1024Octetsto1522Octets\n",
727643c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets);
727743c2aeb0SSepherosa Ziehau 	}
727843c2aeb0SSepherosa Ziehau 
727943c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets) {
728043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
728143c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx1523Octetsto9022Octets\n",
728243c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets);
728343c2aeb0SSepherosa Ziehau 	}
728443c2aeb0SSepherosa Ziehau 
728543c2aeb0SSepherosa Ziehau 	if (sblk->stat_XonPauseFramesReceived) {
728643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : XonPauseFramesReceived\n",
728743c2aeb0SSepherosa Ziehau 			  sblk->stat_XonPauseFramesReceived);
728843c2aeb0SSepherosa Ziehau 	}
728943c2aeb0SSepherosa Ziehau 
729043c2aeb0SSepherosa Ziehau 	if (sblk->stat_XoffPauseFramesReceived) {
729143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "          0x%08X : XoffPauseFramesReceived\n",
729243c2aeb0SSepherosa Ziehau 			  sblk->stat_XoffPauseFramesReceived);
729343c2aeb0SSepherosa Ziehau 	}
729443c2aeb0SSepherosa Ziehau 
729543c2aeb0SSepherosa Ziehau 	if (sblk->stat_OutXonSent) {
729643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : OutXoffSent\n",
729743c2aeb0SSepherosa Ziehau 			  sblk->stat_OutXonSent);
729843c2aeb0SSepherosa Ziehau 	}
729943c2aeb0SSepherosa Ziehau 
730043c2aeb0SSepherosa Ziehau 	if (sblk->stat_OutXoffSent) {
730143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : OutXoffSent\n",
730243c2aeb0SSepherosa Ziehau 			  sblk->stat_OutXoffSent);
730343c2aeb0SSepherosa Ziehau 	}
730443c2aeb0SSepherosa Ziehau 
730543c2aeb0SSepherosa Ziehau 	if (sblk->stat_FlowControlDone) {
730643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : FlowControlDone\n",
730743c2aeb0SSepherosa Ziehau 			  sblk->stat_FlowControlDone);
730843c2aeb0SSepherosa Ziehau 	}
730943c2aeb0SSepherosa Ziehau 
731043c2aeb0SSepherosa Ziehau 	if (sblk->stat_MacControlFramesReceived) {
731143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : MacControlFramesReceived\n",
731243c2aeb0SSepherosa Ziehau 			  sblk->stat_MacControlFramesReceived);
731343c2aeb0SSepherosa Ziehau 	}
731443c2aeb0SSepherosa Ziehau 
731543c2aeb0SSepherosa Ziehau 	if (sblk->stat_XoffStateEntered) {
731643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : XoffStateEntered\n",
731743c2aeb0SSepherosa Ziehau 			  sblk->stat_XoffStateEntered);
731843c2aeb0SSepherosa Ziehau 	}
731943c2aeb0SSepherosa Ziehau 
732043c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInFramesL2FilterDiscards) {
732143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInFramesL2FilterDiscards\n",			  sblk->stat_IfInFramesL2FilterDiscards);
732243c2aeb0SSepherosa Ziehau 	}
732343c2aeb0SSepherosa Ziehau 
732443c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInRuleCheckerDiscards) {
732543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInRuleCheckerDiscards\n",
732643c2aeb0SSepherosa Ziehau 			  sblk->stat_IfInRuleCheckerDiscards);
732743c2aeb0SSepherosa Ziehau 	}
732843c2aeb0SSepherosa Ziehau 
732943c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInFTQDiscards) {
733043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInFTQDiscards\n",
733143c2aeb0SSepherosa Ziehau 			  sblk->stat_IfInFTQDiscards);
733243c2aeb0SSepherosa Ziehau 	}
733343c2aeb0SSepherosa Ziehau 
733443c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInMBUFDiscards) {
733543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInMBUFDiscards\n",
733643c2aeb0SSepherosa Ziehau 			  sblk->stat_IfInMBUFDiscards);
733743c2aeb0SSepherosa Ziehau 	}
733843c2aeb0SSepherosa Ziehau 
733943c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInRuleCheckerP4Hit) {
734043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInRuleCheckerP4Hit\n",
734143c2aeb0SSepherosa Ziehau 			  sblk->stat_IfInRuleCheckerP4Hit);
734243c2aeb0SSepherosa Ziehau 	}
734343c2aeb0SSepherosa Ziehau 
734443c2aeb0SSepherosa Ziehau 	if (sblk->stat_CatchupInRuleCheckerDiscards) {
734543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
734643c2aeb0SSepherosa Ziehau 			  "CatchupInRuleCheckerDiscards\n",
734743c2aeb0SSepherosa Ziehau 			  sblk->stat_CatchupInRuleCheckerDiscards);
734843c2aeb0SSepherosa Ziehau 	}
734943c2aeb0SSepherosa Ziehau 
735043c2aeb0SSepherosa Ziehau 	if (sblk->stat_CatchupInFTQDiscards) {
735143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : CatchupInFTQDiscards\n",
735243c2aeb0SSepherosa Ziehau 			  sblk->stat_CatchupInFTQDiscards);
735343c2aeb0SSepherosa Ziehau 	}
735443c2aeb0SSepherosa Ziehau 
735543c2aeb0SSepherosa Ziehau 	if (sblk->stat_CatchupInMBUFDiscards) {
735643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : CatchupInMBUFDiscards\n",
735743c2aeb0SSepherosa Ziehau 			  sblk->stat_CatchupInMBUFDiscards);
735843c2aeb0SSepherosa Ziehau 	}
735943c2aeb0SSepherosa Ziehau 
736043c2aeb0SSepherosa Ziehau 	if (sblk->stat_CatchupInRuleCheckerP4Hit) {
736143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : CatchupInRuleCheckerP4Hit\n",
736243c2aeb0SSepherosa Ziehau 			  sblk->stat_CatchupInRuleCheckerP4Hit);
736343c2aeb0SSepherosa Ziehau 	}
736443c2aeb0SSepherosa Ziehau 
736543c2aeb0SSepherosa Ziehau 	if_printf(ifp,
736643c2aeb0SSepherosa Ziehau 	"----------------------------"
736743c2aeb0SSepherosa Ziehau 	"----------------"
736843c2aeb0SSepherosa Ziehau 	"----------------------------\n");
736943c2aeb0SSepherosa Ziehau }
737043c2aeb0SSepherosa Ziehau 
737143c2aeb0SSepherosa Ziehau 
737243c2aeb0SSepherosa Ziehau /****************************************************************************/
737343c2aeb0SSepherosa Ziehau /* Prints out a summary of the driver state.                                */
737443c2aeb0SSepherosa Ziehau /*                                                                          */
737543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
737643c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
737743c2aeb0SSepherosa Ziehau /****************************************************************************/
737843c2aeb0SSepherosa Ziehau static void
737943c2aeb0SSepherosa Ziehau bce_dump_driver_state(struct bce_softc *sc)
738043c2aeb0SSepherosa Ziehau {
738143c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
738243c2aeb0SSepherosa Ziehau 	uint32_t val_hi, val_lo;
738343c2aeb0SSepherosa Ziehau 
738443c2aeb0SSepherosa Ziehau 	if_printf(ifp,
738543c2aeb0SSepherosa Ziehau 	"-----------------------------"
738643c2aeb0SSepherosa Ziehau 	" Driver State "
738743c2aeb0SSepherosa Ziehau 	"-----------------------------\n");
738843c2aeb0SSepherosa Ziehau 
738943c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc);
739043c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc);
739143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc) driver softc structure "
739243c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
739343c2aeb0SSepherosa Ziehau 
739443c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->status_block);
739543c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->status_block);
739643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->status_block) status block "
739743c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
739843c2aeb0SSepherosa Ziehau 
739943c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->stats_block);
740043c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->stats_block);
740143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->stats_block) statistics block "
740243c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
740343c2aeb0SSepherosa Ziehau 
740443c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->tx_bd_chain);
740543c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->tx_bd_chain);
740643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->tx_bd_chain) tx_bd chain "
740743c2aeb0SSepherosa Ziehau 		  "virtual adddress\n", val_hi, val_lo);
740843c2aeb0SSepherosa Ziehau 
740943c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->rx_bd_chain);
741043c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->rx_bd_chain);
741143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->rx_bd_chain) rx_bd chain "
741243c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
741343c2aeb0SSepherosa Ziehau 
741443c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->tx_mbuf_ptr);
741543c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->tx_mbuf_ptr);
741643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->tx_mbuf_ptr) tx mbuf chain "
741743c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
741843c2aeb0SSepherosa Ziehau 
741943c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->rx_mbuf_ptr);
742043c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->rx_mbuf_ptr);
742143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->rx_mbuf_ptr) rx mbuf chain "
742243c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
742343c2aeb0SSepherosa Ziehau 
742443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->interrupts_generated) "
742543c2aeb0SSepherosa Ziehau 		  "h/w intrs\n", sc->interrupts_generated);
742643c2aeb0SSepherosa Ziehau 
742743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->rx_interrupts) "
742843c2aeb0SSepherosa Ziehau 		  "rx interrupts handled\n", sc->rx_interrupts);
742943c2aeb0SSepherosa Ziehau 
743043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->tx_interrupts) "
743143c2aeb0SSepherosa Ziehau 		  "tx interrupts handled\n", sc->tx_interrupts);
743243c2aeb0SSepherosa Ziehau 
743343c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->last_status_idx) "
743443c2aeb0SSepherosa Ziehau 		  "status block index\n", sc->last_status_idx);
743543c2aeb0SSepherosa Ziehau 
743643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "     0x%04X(0x%04X) - (sc->tx_prod) "
743743c2aeb0SSepherosa Ziehau 		  "tx producer index\n",
743843c2aeb0SSepherosa Ziehau 		  sc->tx_prod, (uint16_t)TX_CHAIN_IDX(sc->tx_prod));
743943c2aeb0SSepherosa Ziehau 
744043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "     0x%04X(0x%04X) - (sc->tx_cons) "
744143c2aeb0SSepherosa Ziehau 		  "tx consumer index\n",
744243c2aeb0SSepherosa Ziehau 		  sc->tx_cons, (uint16_t)TX_CHAIN_IDX(sc->tx_cons));
744343c2aeb0SSepherosa Ziehau 
744443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->tx_prod_bseq) "
744543c2aeb0SSepherosa Ziehau 		  "tx producer bseq index\n", sc->tx_prod_bseq);
744643c2aeb0SSepherosa Ziehau 
744743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "     0x%04X(0x%04X) - (sc->rx_prod) "
744843c2aeb0SSepherosa Ziehau 		  "rx producer index\n",
744943c2aeb0SSepherosa Ziehau 		  sc->rx_prod, (uint16_t)RX_CHAIN_IDX(sc->rx_prod));
745043c2aeb0SSepherosa Ziehau 
745143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "     0x%04X(0x%04X) - (sc->rx_cons) "
745243c2aeb0SSepherosa Ziehau 		  "rx consumer index\n",
745343c2aeb0SSepherosa Ziehau 		  sc->rx_cons, (uint16_t)RX_CHAIN_IDX(sc->rx_cons));
745443c2aeb0SSepherosa Ziehau 
745543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->rx_prod_bseq) "
745643c2aeb0SSepherosa Ziehau 		  "rx producer bseq index\n", sc->rx_prod_bseq);
745743c2aeb0SSepherosa Ziehau 
745843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->rx_mbuf_alloc) "
745943c2aeb0SSepherosa Ziehau 		  "rx mbufs allocated\n", sc->rx_mbuf_alloc);
746043c2aeb0SSepherosa Ziehau 
746143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->free_rx_bd) "
746243c2aeb0SSepherosa Ziehau 		  "free rx_bd's\n", sc->free_rx_bd);
746343c2aeb0SSepherosa Ziehau 
746443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X/%08X - (sc->rx_low_watermark) rx "
746543c2aeb0SSepherosa Ziehau 		  "low watermark\n", sc->rx_low_watermark, sc->max_rx_bd);
746643c2aeb0SSepherosa Ziehau 
746743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->txmbuf_alloc) "
746843c2aeb0SSepherosa Ziehau 		  "tx mbufs allocated\n", sc->tx_mbuf_alloc);
746943c2aeb0SSepherosa Ziehau 
747043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->rx_mbuf_alloc) "
747143c2aeb0SSepherosa Ziehau 		  "rx mbufs allocated\n", sc->rx_mbuf_alloc);
747243c2aeb0SSepherosa Ziehau 
747343c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->used_tx_bd) used tx_bd's\n",
747443c2aeb0SSepherosa Ziehau 		  sc->used_tx_bd);
747543c2aeb0SSepherosa Ziehau 
747643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X/%08X - (sc->tx_hi_watermark) tx hi watermark\n",
747743c2aeb0SSepherosa Ziehau 		  sc->tx_hi_watermark, sc->max_tx_bd);
747843c2aeb0SSepherosa Ziehau 
747943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->mbuf_alloc_failed) "
748043c2aeb0SSepherosa Ziehau 		  "failed mbuf alloc\n", sc->mbuf_alloc_failed);
748143c2aeb0SSepherosa Ziehau 
748243c2aeb0SSepherosa Ziehau 	if_printf(ifp,
748343c2aeb0SSepherosa Ziehau 	"----------------------------"
748443c2aeb0SSepherosa Ziehau 	"----------------"
748543c2aeb0SSepherosa Ziehau 	"----------------------------\n");
748643c2aeb0SSepherosa Ziehau }
748743c2aeb0SSepherosa Ziehau 
748843c2aeb0SSepherosa Ziehau 
748943c2aeb0SSepherosa Ziehau /****************************************************************************/
749043c2aeb0SSepherosa Ziehau /* Prints out the hardware state through a summary of important registers,  */
749143c2aeb0SSepherosa Ziehau /* followed by a complete register dump.                                    */
749243c2aeb0SSepherosa Ziehau /*                                                                          */
749343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
749443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
749543c2aeb0SSepherosa Ziehau /****************************************************************************/
749643c2aeb0SSepherosa Ziehau static void
749743c2aeb0SSepherosa Ziehau bce_dump_hw_state(struct bce_softc *sc)
749843c2aeb0SSepherosa Ziehau {
749943c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
750043c2aeb0SSepherosa Ziehau 	uint32_t val1;
750143c2aeb0SSepherosa Ziehau 	int i;
750243c2aeb0SSepherosa Ziehau 
750343c2aeb0SSepherosa Ziehau 	if_printf(ifp,
750443c2aeb0SSepherosa Ziehau 	"----------------------------"
750543c2aeb0SSepherosa Ziehau 	" Hardware State "
750643c2aeb0SSepherosa Ziehau 	"----------------------------\n");
750743c2aeb0SSepherosa Ziehau 
75081d8e1d4aSSascha Wildner 	if_printf(ifp, "0x%08X - bootcode version\n", sc->bce_bc_ver);
750943c2aeb0SSepherosa Ziehau 
751043c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_MISC_ENABLE_STATUS_BITS);
751143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) misc_enable_status_bits\n",
751243c2aeb0SSepherosa Ziehau 		  val1, BCE_MISC_ENABLE_STATUS_BITS);
751343c2aeb0SSepherosa Ziehau 
751443c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_DMA_STATUS);
751543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) dma_status\n", val1, BCE_DMA_STATUS);
751643c2aeb0SSepherosa Ziehau 
751743c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_CTX_STATUS);
751843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) ctx_status\n", val1, BCE_CTX_STATUS);
751943c2aeb0SSepherosa Ziehau 
752043c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_EMAC_STATUS);
752143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) emac_status\n",
752243c2aeb0SSepherosa Ziehau 		  val1, BCE_EMAC_STATUS);
752343c2aeb0SSepherosa Ziehau 
752443c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_RPM_STATUS);
752543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) rpm_status\n", val1, BCE_RPM_STATUS);
752643c2aeb0SSepherosa Ziehau 
752743c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_TBDR_STATUS);
752843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) tbdr_status\n",
752943c2aeb0SSepherosa Ziehau 		  val1, BCE_TBDR_STATUS);
753043c2aeb0SSepherosa Ziehau 
753143c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_TDMA_STATUS);
753243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) tdma_status\n",
753343c2aeb0SSepherosa Ziehau 		  val1, BCE_TDMA_STATUS);
753443c2aeb0SSepherosa Ziehau 
753543c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_HC_STATUS);
753643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) hc_status\n", val1, BCE_HC_STATUS);
753743c2aeb0SSepherosa Ziehau 
753843c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TXP_CPU_STATE);
753943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) txp_cpu_state\n",
754043c2aeb0SSepherosa Ziehau 		  val1, BCE_TXP_CPU_STATE);
754143c2aeb0SSepherosa Ziehau 
754243c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TPAT_CPU_STATE);
754343c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) tpat_cpu_state\n",
754443c2aeb0SSepherosa Ziehau 		  val1, BCE_TPAT_CPU_STATE);
754543c2aeb0SSepherosa Ziehau 
754643c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_RXP_CPU_STATE);
754743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) rxp_cpu_state\n",
754843c2aeb0SSepherosa Ziehau 		  val1, BCE_RXP_CPU_STATE);
754943c2aeb0SSepherosa Ziehau 
755043c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_COM_CPU_STATE);
755143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) com_cpu_state\n",
755243c2aeb0SSepherosa Ziehau 		  val1, BCE_COM_CPU_STATE);
755343c2aeb0SSepherosa Ziehau 
755443c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_MCP_CPU_STATE);
755543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) mcp_cpu_state\n",
755643c2aeb0SSepherosa Ziehau 		  val1, BCE_MCP_CPU_STATE);
755743c2aeb0SSepherosa Ziehau 
755843c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_CP_CPU_STATE);
755943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) cp_cpu_state\n",
756043c2aeb0SSepherosa Ziehau 		  val1, BCE_CP_CPU_STATE);
756143c2aeb0SSepherosa Ziehau 
756243c2aeb0SSepherosa Ziehau 	if_printf(ifp,
756343c2aeb0SSepherosa Ziehau 	"----------------------------"
756443c2aeb0SSepherosa Ziehau 	"----------------"
756543c2aeb0SSepherosa Ziehau 	"----------------------------\n");
756643c2aeb0SSepherosa Ziehau 
756743c2aeb0SSepherosa Ziehau 	if_printf(ifp,
756843c2aeb0SSepherosa Ziehau 	"----------------------------"
756943c2aeb0SSepherosa Ziehau 	" Register  Dump "
757043c2aeb0SSepherosa Ziehau 	"----------------------------\n");
757143c2aeb0SSepherosa Ziehau 
757243c2aeb0SSepherosa Ziehau 	for (i = 0x400; i < 0x8000; i += 0x10) {
757343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X: 0x%08X 0x%08X 0x%08X 0x%08X\n", i,
757443c2aeb0SSepherosa Ziehau 			  REG_RD(sc, i),
757543c2aeb0SSepherosa Ziehau 			  REG_RD(sc, i + 0x4),
757643c2aeb0SSepherosa Ziehau 			  REG_RD(sc, i + 0x8),
757743c2aeb0SSepherosa Ziehau 			  REG_RD(sc, i + 0xc));
757843c2aeb0SSepherosa Ziehau 	}
757943c2aeb0SSepherosa Ziehau 
758043c2aeb0SSepherosa Ziehau 	if_printf(ifp,
758143c2aeb0SSepherosa Ziehau 	"----------------------------"
758243c2aeb0SSepherosa Ziehau 	"----------------"
758343c2aeb0SSepherosa Ziehau 	"----------------------------\n");
758443c2aeb0SSepherosa Ziehau }
758543c2aeb0SSepherosa Ziehau 
758643c2aeb0SSepherosa Ziehau 
758743c2aeb0SSepherosa Ziehau /****************************************************************************/
758843c2aeb0SSepherosa Ziehau /* Prints out the TXP state.                                                */
758943c2aeb0SSepherosa Ziehau /*                                                                          */
759043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
759143c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
759243c2aeb0SSepherosa Ziehau /****************************************************************************/
759343c2aeb0SSepherosa Ziehau static void
759443c2aeb0SSepherosa Ziehau bce_dump_txp_state(struct bce_softc *sc)
759543c2aeb0SSepherosa Ziehau {
759643c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
759743c2aeb0SSepherosa Ziehau 	uint32_t val1;
759843c2aeb0SSepherosa Ziehau 	int i;
759943c2aeb0SSepherosa Ziehau 
760043c2aeb0SSepherosa Ziehau 	if_printf(ifp,
760143c2aeb0SSepherosa Ziehau 	"----------------------------"
760243c2aeb0SSepherosa Ziehau 	"   TXP  State   "
760343c2aeb0SSepherosa Ziehau 	"----------------------------\n");
760443c2aeb0SSepherosa Ziehau 
760543c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TXP_CPU_MODE);
760643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) txp_cpu_mode\n",
760743c2aeb0SSepherosa Ziehau 		  val1, BCE_TXP_CPU_MODE);
760843c2aeb0SSepherosa Ziehau 
760943c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TXP_CPU_STATE);
761043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) txp_cpu_state\n",
761143c2aeb0SSepherosa Ziehau 		  val1, BCE_TXP_CPU_STATE);
761243c2aeb0SSepherosa Ziehau 
761343c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TXP_CPU_EVENT_MASK);
761443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) txp_cpu_event_mask\n",
761543c2aeb0SSepherosa Ziehau 		  val1, BCE_TXP_CPU_EVENT_MASK);
761643c2aeb0SSepherosa Ziehau 
761743c2aeb0SSepherosa Ziehau 	if_printf(ifp,
761843c2aeb0SSepherosa Ziehau 	"----------------------------"
761943c2aeb0SSepherosa Ziehau 	" Register  Dump "
762043c2aeb0SSepherosa Ziehau 	"----------------------------\n");
762143c2aeb0SSepherosa Ziehau 
762243c2aeb0SSepherosa Ziehau 	for (i = BCE_TXP_CPU_MODE; i < 0x68000; i += 0x10) {
762343c2aeb0SSepherosa Ziehau 		/* Skip the big blank spaces */
762443c2aeb0SSepherosa Ziehau 		if (i < 0x454000 && i > 0x5ffff) {
762543c2aeb0SSepherosa Ziehau 			if_printf(ifp, "0x%04X: "
762643c2aeb0SSepherosa Ziehau 				  "0x%08X 0x%08X 0x%08X 0x%08X\n", i,
762743c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i),
762843c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x4),
762943c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x8),
763043c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0xc));
763143c2aeb0SSepherosa Ziehau 		}
763243c2aeb0SSepherosa Ziehau 	}
763343c2aeb0SSepherosa Ziehau 
763443c2aeb0SSepherosa Ziehau 	if_printf(ifp,
763543c2aeb0SSepherosa Ziehau 	"----------------------------"
763643c2aeb0SSepherosa Ziehau 	"----------------"
763743c2aeb0SSepherosa Ziehau 	"----------------------------\n");
763843c2aeb0SSepherosa Ziehau }
763943c2aeb0SSepherosa Ziehau 
764043c2aeb0SSepherosa Ziehau 
764143c2aeb0SSepherosa Ziehau /****************************************************************************/
764243c2aeb0SSepherosa Ziehau /* Prints out the RXP state.                                                */
764343c2aeb0SSepherosa Ziehau /*                                                                          */
764443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
764543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
764643c2aeb0SSepherosa Ziehau /****************************************************************************/
764743c2aeb0SSepherosa Ziehau static void
764843c2aeb0SSepherosa Ziehau bce_dump_rxp_state(struct bce_softc *sc)
764943c2aeb0SSepherosa Ziehau {
765043c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
765143c2aeb0SSepherosa Ziehau 	uint32_t val1;
765243c2aeb0SSepherosa Ziehau 	int i;
765343c2aeb0SSepherosa Ziehau 
765443c2aeb0SSepherosa Ziehau 	if_printf(ifp,
765543c2aeb0SSepherosa Ziehau 	"----------------------------"
765643c2aeb0SSepherosa Ziehau 	"   RXP  State   "
765743c2aeb0SSepherosa Ziehau 	"----------------------------\n");
765843c2aeb0SSepherosa Ziehau 
765943c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_RXP_CPU_MODE);
766043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) rxp_cpu_mode\n",
766143c2aeb0SSepherosa Ziehau 		  val1, BCE_RXP_CPU_MODE);
766243c2aeb0SSepherosa Ziehau 
766343c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_RXP_CPU_STATE);
766443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) rxp_cpu_state\n",
766543c2aeb0SSepherosa Ziehau 		  val1, BCE_RXP_CPU_STATE);
766643c2aeb0SSepherosa Ziehau 
766743c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_RXP_CPU_EVENT_MASK);
766843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) rxp_cpu_event_mask\n",
766943c2aeb0SSepherosa Ziehau 		  val1, BCE_RXP_CPU_EVENT_MASK);
767043c2aeb0SSepherosa Ziehau 
767143c2aeb0SSepherosa Ziehau 	if_printf(ifp,
767243c2aeb0SSepherosa Ziehau 	"----------------------------"
767343c2aeb0SSepherosa Ziehau 	" Register  Dump "
767443c2aeb0SSepherosa Ziehau 	"----------------------------\n");
767543c2aeb0SSepherosa Ziehau 
767643c2aeb0SSepherosa Ziehau 	for (i = BCE_RXP_CPU_MODE; i < 0xe8fff; i += 0x10) {
767743c2aeb0SSepherosa Ziehau 		/* Skip the big blank sapces */
767843c2aeb0SSepherosa Ziehau 		if (i < 0xc5400 && i > 0xdffff) {
767943c2aeb0SSepherosa Ziehau 			if_printf(ifp, "0x%04X: "
768043c2aeb0SSepherosa Ziehau 				  "0x%08X 0x%08X 0x%08X 0x%08X\n", i,
768143c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i),
768243c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x4),
768343c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x8),
768443c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0xc));
768543c2aeb0SSepherosa Ziehau 		}
768643c2aeb0SSepherosa Ziehau 	}
768743c2aeb0SSepherosa Ziehau 
768843c2aeb0SSepherosa Ziehau 	if_printf(ifp,
768943c2aeb0SSepherosa Ziehau 	"----------------------------"
769043c2aeb0SSepherosa Ziehau 	"----------------"
769143c2aeb0SSepherosa Ziehau 	"----------------------------\n");
769243c2aeb0SSepherosa Ziehau }
769343c2aeb0SSepherosa Ziehau 
769443c2aeb0SSepherosa Ziehau 
769543c2aeb0SSepherosa Ziehau /****************************************************************************/
769643c2aeb0SSepherosa Ziehau /* Prints out the TPAT state.                                               */
769743c2aeb0SSepherosa Ziehau /*                                                                          */
769843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
769943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
770043c2aeb0SSepherosa Ziehau /****************************************************************************/
770143c2aeb0SSepherosa Ziehau static void
770243c2aeb0SSepherosa Ziehau bce_dump_tpat_state(struct bce_softc *sc)
770343c2aeb0SSepherosa Ziehau {
770443c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
770543c2aeb0SSepherosa Ziehau 	uint32_t val1;
770643c2aeb0SSepherosa Ziehau 	int i;
770743c2aeb0SSepherosa Ziehau 
770843c2aeb0SSepherosa Ziehau 	if_printf(ifp,
770943c2aeb0SSepherosa Ziehau 	"----------------------------"
771043c2aeb0SSepherosa Ziehau 	"   TPAT State   "
771143c2aeb0SSepherosa Ziehau 	"----------------------------\n");
771243c2aeb0SSepherosa Ziehau 
771343c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TPAT_CPU_MODE);
771443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) tpat_cpu_mode\n",
771543c2aeb0SSepherosa Ziehau 		  val1, BCE_TPAT_CPU_MODE);
771643c2aeb0SSepherosa Ziehau 
771743c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TPAT_CPU_STATE);
771843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) tpat_cpu_state\n",
771943c2aeb0SSepherosa Ziehau 		  val1, BCE_TPAT_CPU_STATE);
772043c2aeb0SSepherosa Ziehau 
772143c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TPAT_CPU_EVENT_MASK);
772243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) tpat_cpu_event_mask\n",
772343c2aeb0SSepherosa Ziehau 		  val1, BCE_TPAT_CPU_EVENT_MASK);
772443c2aeb0SSepherosa Ziehau 
772543c2aeb0SSepherosa Ziehau 	if_printf(ifp,
772643c2aeb0SSepherosa Ziehau 	"----------------------------"
772743c2aeb0SSepherosa Ziehau 	" Register  Dump "
772843c2aeb0SSepherosa Ziehau 	"----------------------------\n");
772943c2aeb0SSepherosa Ziehau 
773043c2aeb0SSepherosa Ziehau 	for (i = BCE_TPAT_CPU_MODE; i < 0xa3fff; i += 0x10) {
773143c2aeb0SSepherosa Ziehau 		/* Skip the big blank spaces */
773243c2aeb0SSepherosa Ziehau 		if (i < 0x854000 && i > 0x9ffff) {
773343c2aeb0SSepherosa Ziehau 			if_printf(ifp, "0x%04X: "
773443c2aeb0SSepherosa Ziehau 				  "0x%08X 0x%08X 0x%08X 0x%08X\n", i,
773543c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i),
773643c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x4),
773743c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x8),
773843c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0xc));
773943c2aeb0SSepherosa Ziehau 		}
774043c2aeb0SSepherosa Ziehau 	}
774143c2aeb0SSepherosa Ziehau 
774243c2aeb0SSepherosa Ziehau 	if_printf(ifp,
774343c2aeb0SSepherosa Ziehau 	"----------------------------"
774443c2aeb0SSepherosa Ziehau 	"----------------"
774543c2aeb0SSepherosa Ziehau 	"----------------------------\n");
774643c2aeb0SSepherosa Ziehau }
774743c2aeb0SSepherosa Ziehau 
774843c2aeb0SSepherosa Ziehau 
774943c2aeb0SSepherosa Ziehau /****************************************************************************/
775043c2aeb0SSepherosa Ziehau /* Prints out the driver state and then enters the debugger.                */
775143c2aeb0SSepherosa Ziehau /*                                                                          */
775243c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
775343c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
775443c2aeb0SSepherosa Ziehau /****************************************************************************/
775543c2aeb0SSepherosa Ziehau static void
775643c2aeb0SSepherosa Ziehau bce_breakpoint(struct bce_softc *sc)
775743c2aeb0SSepherosa Ziehau {
775843c2aeb0SSepherosa Ziehau #if 0
775943c2aeb0SSepherosa Ziehau 	bce_freeze_controller(sc);
776043c2aeb0SSepherosa Ziehau #endif
776143c2aeb0SSepherosa Ziehau 
776243c2aeb0SSepherosa Ziehau 	bce_dump_driver_state(sc);
776343c2aeb0SSepherosa Ziehau 	bce_dump_status_block(sc);
776443c2aeb0SSepherosa Ziehau 	bce_dump_tx_chain(sc, 0, TOTAL_TX_BD);
776543c2aeb0SSepherosa Ziehau 	bce_dump_hw_state(sc);
776643c2aeb0SSepherosa Ziehau 	bce_dump_txp_state(sc);
776743c2aeb0SSepherosa Ziehau 
776843c2aeb0SSepherosa Ziehau #if 0
776943c2aeb0SSepherosa Ziehau 	bce_unfreeze_controller(sc);
777043c2aeb0SSepherosa Ziehau #endif
777143c2aeb0SSepherosa Ziehau 
777243c2aeb0SSepherosa Ziehau 	/* Call the debugger. */
777343c2aeb0SSepherosa Ziehau 	breakpoint();
777443c2aeb0SSepherosa Ziehau }
777543c2aeb0SSepherosa Ziehau 
777643c2aeb0SSepherosa Ziehau #endif	/* BCE_DEBUG */
7777bdeb8fffSSepherosa Ziehau 
7778bdeb8fffSSepherosa Ziehau static int
7779bdeb8fffSSepherosa Ziehau bce_sysctl_tx_bds_int(SYSCTL_HANDLER_ARGS)
7780bdeb8fffSSepherosa Ziehau {
7781bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7782bdeb8fffSSepherosa Ziehau 
7783bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7784bdeb8fffSSepherosa Ziehau 			&sc->bce_tx_quick_cons_trip_int,
7785bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_TX_BDS_INT);
7786bdeb8fffSSepherosa Ziehau }
7787bdeb8fffSSepherosa Ziehau 
7788bdeb8fffSSepherosa Ziehau static int
7789bdeb8fffSSepherosa Ziehau bce_sysctl_tx_bds(SYSCTL_HANDLER_ARGS)
7790bdeb8fffSSepherosa Ziehau {
7791bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7792bdeb8fffSSepherosa Ziehau 
7793bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7794bdeb8fffSSepherosa Ziehau 			&sc->bce_tx_quick_cons_trip,
7795bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_TX_BDS);
7796bdeb8fffSSepherosa Ziehau }
7797bdeb8fffSSepherosa Ziehau 
7798bdeb8fffSSepherosa Ziehau static int
7799bdeb8fffSSepherosa Ziehau bce_sysctl_tx_ticks_int(SYSCTL_HANDLER_ARGS)
7800bdeb8fffSSepherosa Ziehau {
7801bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7802bdeb8fffSSepherosa Ziehau 
7803bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7804bdeb8fffSSepherosa Ziehau 			&sc->bce_tx_ticks_int,
7805bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_TX_TICKS_INT);
7806bdeb8fffSSepherosa Ziehau }
7807bdeb8fffSSepherosa Ziehau 
7808bdeb8fffSSepherosa Ziehau static int
7809bdeb8fffSSepherosa Ziehau bce_sysctl_tx_ticks(SYSCTL_HANDLER_ARGS)
7810bdeb8fffSSepherosa Ziehau {
7811bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7812bdeb8fffSSepherosa Ziehau 
7813bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7814bdeb8fffSSepherosa Ziehau 			&sc->bce_tx_ticks,
7815bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_TX_TICKS);
7816bdeb8fffSSepherosa Ziehau }
7817bdeb8fffSSepherosa Ziehau 
7818bdeb8fffSSepherosa Ziehau static int
7819bdeb8fffSSepherosa Ziehau bce_sysctl_rx_bds_int(SYSCTL_HANDLER_ARGS)
7820bdeb8fffSSepherosa Ziehau {
7821bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7822bdeb8fffSSepherosa Ziehau 
7823bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7824bdeb8fffSSepherosa Ziehau 			&sc->bce_rx_quick_cons_trip_int,
7825bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_RX_BDS_INT);
7826bdeb8fffSSepherosa Ziehau }
7827bdeb8fffSSepherosa Ziehau 
7828bdeb8fffSSepherosa Ziehau static int
7829bdeb8fffSSepherosa Ziehau bce_sysctl_rx_bds(SYSCTL_HANDLER_ARGS)
7830bdeb8fffSSepherosa Ziehau {
7831bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7832bdeb8fffSSepherosa Ziehau 
7833bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7834bdeb8fffSSepherosa Ziehau 			&sc->bce_rx_quick_cons_trip,
7835bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_RX_BDS);
7836bdeb8fffSSepherosa Ziehau }
7837bdeb8fffSSepherosa Ziehau 
7838bdeb8fffSSepherosa Ziehau static int
7839bdeb8fffSSepherosa Ziehau bce_sysctl_rx_ticks_int(SYSCTL_HANDLER_ARGS)
7840bdeb8fffSSepherosa Ziehau {
7841bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7842bdeb8fffSSepherosa Ziehau 
7843bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7844bdeb8fffSSepherosa Ziehau 			&sc->bce_rx_ticks_int,
7845bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_RX_TICKS_INT);
7846bdeb8fffSSepherosa Ziehau }
7847bdeb8fffSSepherosa Ziehau 
7848bdeb8fffSSepherosa Ziehau static int
7849bdeb8fffSSepherosa Ziehau bce_sysctl_rx_ticks(SYSCTL_HANDLER_ARGS)
7850bdeb8fffSSepherosa Ziehau {
7851bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7852bdeb8fffSSepherosa Ziehau 
7853bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7854bdeb8fffSSepherosa Ziehau 			&sc->bce_rx_ticks,
7855bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_RX_TICKS);
7856bdeb8fffSSepherosa Ziehau }
7857bdeb8fffSSepherosa Ziehau 
7858bdeb8fffSSepherosa Ziehau static int
7859bdeb8fffSSepherosa Ziehau bce_sysctl_coal_change(SYSCTL_HANDLER_ARGS, uint32_t *coal,
7860bdeb8fffSSepherosa Ziehau 		       uint32_t coalchg_mask)
7861bdeb8fffSSepherosa Ziehau {
7862bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7863bdeb8fffSSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
7864bdeb8fffSSepherosa Ziehau 	int error = 0, v;
7865bdeb8fffSSepherosa Ziehau 
7866bdeb8fffSSepherosa Ziehau 	lwkt_serialize_enter(ifp->if_serializer);
7867bdeb8fffSSepherosa Ziehau 
7868bdeb8fffSSepherosa Ziehau 	v = *coal;
7869bdeb8fffSSepherosa Ziehau 	error = sysctl_handle_int(oidp, &v, 0, req);
7870bdeb8fffSSepherosa Ziehau 	if (!error && req->newptr != NULL) {
7871bdeb8fffSSepherosa Ziehau 		if (v < 0) {
7872bdeb8fffSSepherosa Ziehau 			error = EINVAL;
7873bdeb8fffSSepherosa Ziehau 		} else {
7874bdeb8fffSSepherosa Ziehau 			*coal = v;
7875bdeb8fffSSepherosa Ziehau 			sc->bce_coalchg_mask |= coalchg_mask;
7876bdeb8fffSSepherosa Ziehau 		}
7877bdeb8fffSSepherosa Ziehau 	}
7878bdeb8fffSSepherosa Ziehau 
7879bdeb8fffSSepherosa Ziehau 	lwkt_serialize_exit(ifp->if_serializer);
7880bdeb8fffSSepherosa Ziehau 	return error;
7881bdeb8fffSSepherosa Ziehau }
7882bdeb8fffSSepherosa Ziehau 
7883bdeb8fffSSepherosa Ziehau static void
7884bdeb8fffSSepherosa Ziehau bce_coal_change(struct bce_softc *sc)
7885bdeb8fffSSepherosa Ziehau {
7886bdeb8fffSSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
7887bdeb8fffSSepherosa Ziehau 
7888bdeb8fffSSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
7889bdeb8fffSSepherosa Ziehau 
7890bdeb8fffSSepherosa Ziehau 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
7891bdeb8fffSSepherosa Ziehau 		sc->bce_coalchg_mask = 0;
7892bdeb8fffSSepherosa Ziehau 		return;
7893bdeb8fffSSepherosa Ziehau 	}
7894bdeb8fffSSepherosa Ziehau 
7895bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask &
7896bdeb8fffSSepherosa Ziehau 	    (BCE_COALMASK_TX_BDS | BCE_COALMASK_TX_BDS_INT)) {
7897bdeb8fffSSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
7898bdeb8fffSSepherosa Ziehau 		       (sc->bce_tx_quick_cons_trip_int << 16) |
7899bdeb8fffSSepherosa Ziehau 		       sc->bce_tx_quick_cons_trip);
7900bdeb8fffSSepherosa Ziehau 		if (bootverbose) {
7901bdeb8fffSSepherosa Ziehau 			if_printf(ifp, "tx_bds %u, tx_bds_int %u\n",
7902bdeb8fffSSepherosa Ziehau 				  sc->bce_tx_quick_cons_trip,
7903bdeb8fffSSepherosa Ziehau 				  sc->bce_tx_quick_cons_trip_int);
7904bdeb8fffSSepherosa Ziehau 		}
7905bdeb8fffSSepherosa Ziehau 	}
7906bdeb8fffSSepherosa Ziehau 
7907bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask &
7908bdeb8fffSSepherosa Ziehau 	    (BCE_COALMASK_TX_TICKS | BCE_COALMASK_TX_TICKS_INT)) {
7909bdeb8fffSSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_TICKS,
7910bdeb8fffSSepherosa Ziehau 		       (sc->bce_tx_ticks_int << 16) | sc->bce_tx_ticks);
7911bdeb8fffSSepherosa Ziehau 		if (bootverbose) {
7912bdeb8fffSSepherosa Ziehau 			if_printf(ifp, "tx_ticks %u, tx_ticks_int %u\n",
7913bdeb8fffSSepherosa Ziehau 				  sc->bce_tx_ticks, sc->bce_tx_ticks_int);
7914bdeb8fffSSepherosa Ziehau 		}
7915bdeb8fffSSepherosa Ziehau 	}
7916bdeb8fffSSepherosa Ziehau 
7917bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask &
7918bdeb8fffSSepherosa Ziehau 	    (BCE_COALMASK_RX_BDS | BCE_COALMASK_RX_BDS_INT)) {
7919bdeb8fffSSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
7920bdeb8fffSSepherosa Ziehau 		       (sc->bce_rx_quick_cons_trip_int << 16) |
7921bdeb8fffSSepherosa Ziehau 		       sc->bce_rx_quick_cons_trip);
7922bdeb8fffSSepherosa Ziehau 		if (bootverbose) {
7923bdeb8fffSSepherosa Ziehau 			if_printf(ifp, "rx_bds %u, rx_bds_int %u\n",
7924bdeb8fffSSepherosa Ziehau 				  sc->bce_rx_quick_cons_trip,
7925bdeb8fffSSepherosa Ziehau 				  sc->bce_rx_quick_cons_trip_int);
7926bdeb8fffSSepherosa Ziehau 		}
7927bdeb8fffSSepherosa Ziehau 	}
7928bdeb8fffSSepherosa Ziehau 
7929bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask &
7930bdeb8fffSSepherosa Ziehau 	    (BCE_COALMASK_RX_TICKS | BCE_COALMASK_RX_TICKS_INT)) {
7931bdeb8fffSSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_TICKS,
7932bdeb8fffSSepherosa Ziehau 		       (sc->bce_rx_ticks_int << 16) | sc->bce_rx_ticks);
7933bdeb8fffSSepherosa Ziehau 		if (bootverbose) {
7934bdeb8fffSSepherosa Ziehau 			if_printf(ifp, "rx_ticks %u, rx_ticks_int %u\n",
7935bdeb8fffSSepherosa Ziehau 				  sc->bce_rx_ticks, sc->bce_rx_ticks_int);
7936bdeb8fffSSepherosa Ziehau 		}
7937bdeb8fffSSepherosa Ziehau 	}
7938bdeb8fffSSepherosa Ziehau 
7939bdeb8fffSSepherosa Ziehau 	sc->bce_coalchg_mask = 0;
7940bdeb8fffSSepherosa Ziehau }
7941