xref: /dflybsd-src/sys/dev/netif/bce/if_bce.c (revision 45010e4d9b74c259eacde8a5241e71ff73e75e72)
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 $
311af951abSSepherosa Ziehau  * $DragonFly: src/sys/dev/netif/bce/if_bce.c,v 1.21 2008/11/19 13:57:49 sephe Exp $
3243c2aeb0SSepherosa Ziehau  */
3343c2aeb0SSepherosa Ziehau 
3443c2aeb0SSepherosa Ziehau /*
3543c2aeb0SSepherosa Ziehau  * The following controllers are supported by this driver:
3643c2aeb0SSepherosa Ziehau  *   BCM5706C A2, A3
3743c2aeb0SSepherosa Ziehau  *   BCM5708C B1, B2
3843c2aeb0SSepherosa Ziehau  *
3943c2aeb0SSepherosa Ziehau  * The following controllers are not supported by this driver:
4043c2aeb0SSepherosa Ziehau  *   BCM5706C A0, A1
4143c2aeb0SSepherosa Ziehau  *   BCM5706S A0, A1, A2, A3
4243c2aeb0SSepherosa Ziehau  *   BCM5708C A0, B0
4343c2aeb0SSepherosa Ziehau  *   BCM5708S A0, B0, B1, B2
4443c2aeb0SSepherosa Ziehau  */
4543c2aeb0SSepherosa Ziehau 
4643c2aeb0SSepherosa Ziehau #include "opt_bce.h"
4743c2aeb0SSepherosa Ziehau #include "opt_polling.h"
4843c2aeb0SSepherosa Ziehau 
4943c2aeb0SSepherosa Ziehau #include <sys/param.h>
5043c2aeb0SSepherosa Ziehau #include <sys/bus.h>
5143c2aeb0SSepherosa Ziehau #include <sys/endian.h>
5243c2aeb0SSepherosa Ziehau #include <sys/kernel.h>
539db4b353SSepherosa Ziehau #include <sys/interrupt.h>
5443c2aeb0SSepherosa Ziehau #include <sys/mbuf.h>
5543c2aeb0SSepherosa Ziehau #include <sys/malloc.h>
5643c2aeb0SSepherosa Ziehau #include <sys/queue.h>
5743c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
5843c2aeb0SSepherosa Ziehau #include <sys/random.h>
5943c2aeb0SSepherosa Ziehau #endif
6043c2aeb0SSepherosa Ziehau #include <sys/rman.h>
6143c2aeb0SSepherosa Ziehau #include <sys/serialize.h>
6243c2aeb0SSepherosa Ziehau #include <sys/socket.h>
6343c2aeb0SSepherosa Ziehau #include <sys/sockio.h>
6443c2aeb0SSepherosa Ziehau #include <sys/sysctl.h>
6543c2aeb0SSepherosa Ziehau 
6643c2aeb0SSepherosa Ziehau #include <net/bpf.h>
6743c2aeb0SSepherosa Ziehau #include <net/ethernet.h>
6843c2aeb0SSepherosa Ziehau #include <net/if.h>
6943c2aeb0SSepherosa Ziehau #include <net/if_arp.h>
7043c2aeb0SSepherosa Ziehau #include <net/if_dl.h>
7143c2aeb0SSepherosa Ziehau #include <net/if_media.h>
7243c2aeb0SSepherosa Ziehau #include <net/if_types.h>
7343c2aeb0SSepherosa Ziehau #include <net/ifq_var.h>
7443c2aeb0SSepherosa Ziehau #include <net/vlan/if_vlan_var.h>
75b637f170SSepherosa Ziehau #include <net/vlan/if_vlan_ether.h>
7643c2aeb0SSepherosa Ziehau 
7743c2aeb0SSepherosa Ziehau #include <dev/netif/mii_layer/mii.h>
7843c2aeb0SSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h>
7943c2aeb0SSepherosa Ziehau 
8043c2aeb0SSepherosa Ziehau #include <bus/pci/pcireg.h>
8143c2aeb0SSepherosa Ziehau #include <bus/pci/pcivar.h>
8243c2aeb0SSepherosa Ziehau 
8343c2aeb0SSepherosa Ziehau #include "miibus_if.h"
8443c2aeb0SSepherosa Ziehau 
859382dc55SSepherosa Ziehau #include <dev/netif/bce/if_bcereg.h>
869382dc55SSepherosa Ziehau #include <dev/netif/bce/if_bcefw.h>
8743c2aeb0SSepherosa Ziehau 
8843c2aeb0SSepherosa Ziehau /****************************************************************************/
8943c2aeb0SSepherosa Ziehau /* BCE Debug Options                                                        */
9043c2aeb0SSepherosa Ziehau /****************************************************************************/
9143c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
9243c2aeb0SSepherosa Ziehau 
9343c2aeb0SSepherosa Ziehau static uint32_t	bce_debug = BCE_WARN;
9443c2aeb0SSepherosa Ziehau 
9543c2aeb0SSepherosa Ziehau /*
9643c2aeb0SSepherosa Ziehau  *          0 = Never
9743c2aeb0SSepherosa Ziehau  *          1 = 1 in 2,147,483,648
9843c2aeb0SSepherosa Ziehau  *        256 = 1 in     8,388,608
9943c2aeb0SSepherosa Ziehau  *       2048 = 1 in     1,048,576
10043c2aeb0SSepherosa Ziehau  *      65536 = 1 in        32,768
10143c2aeb0SSepherosa Ziehau  *    1048576 = 1 in         2,048
10243c2aeb0SSepherosa Ziehau  *  268435456 = 1 in             8
10343c2aeb0SSepherosa Ziehau  *  536870912 = 1 in             4
10443c2aeb0SSepherosa Ziehau  * 1073741824 = 1 in             2
10543c2aeb0SSepherosa Ziehau  *
10643c2aeb0SSepherosa Ziehau  * bce_debug_l2fhdr_status_check:
10743c2aeb0SSepherosa Ziehau  *     How often the l2_fhdr frame error check will fail.
10843c2aeb0SSepherosa Ziehau  *
10943c2aeb0SSepherosa Ziehau  * bce_debug_unexpected_attention:
11043c2aeb0SSepherosa Ziehau  *     How often the unexpected attention check will fail.
11143c2aeb0SSepherosa Ziehau  *
11243c2aeb0SSepherosa Ziehau  * bce_debug_mbuf_allocation_failure:
11343c2aeb0SSepherosa Ziehau  *     How often to simulate an mbuf allocation failure.
11443c2aeb0SSepherosa Ziehau  *
11543c2aeb0SSepherosa Ziehau  * bce_debug_dma_map_addr_failure:
11643c2aeb0SSepherosa Ziehau  *     How often to simulate a DMA mapping failure.
11743c2aeb0SSepherosa Ziehau  *
11843c2aeb0SSepherosa Ziehau  * bce_debug_bootcode_running_failure:
11943c2aeb0SSepherosa Ziehau  *     How often to simulate a bootcode failure.
12043c2aeb0SSepherosa Ziehau  */
12143c2aeb0SSepherosa Ziehau static int	bce_debug_l2fhdr_status_check = 0;
12243c2aeb0SSepherosa Ziehau static int	bce_debug_unexpected_attention = 0;
12343c2aeb0SSepherosa Ziehau static int	bce_debug_mbuf_allocation_failure = 0;
12443c2aeb0SSepherosa Ziehau static int	bce_debug_dma_map_addr_failure = 0;
12543c2aeb0SSepherosa Ziehau static int	bce_debug_bootcode_running_failure = 0;
12643c2aeb0SSepherosa Ziehau 
12743c2aeb0SSepherosa Ziehau #endif	/* BCE_DEBUG */
12843c2aeb0SSepherosa Ziehau 
12943c2aeb0SSepherosa Ziehau 
13043c2aeb0SSepherosa Ziehau /****************************************************************************/
13143c2aeb0SSepherosa Ziehau /* PCI Device ID Table                                                      */
13243c2aeb0SSepherosa Ziehau /*                                                                          */
13343c2aeb0SSepherosa Ziehau /* Used by bce_probe() to identify the devices supported by this driver.    */
13443c2aeb0SSepherosa Ziehau /****************************************************************************/
13543c2aeb0SSepherosa Ziehau #define BCE_DEVDESC_MAX		64
13643c2aeb0SSepherosa Ziehau 
13743c2aeb0SSepherosa Ziehau static struct bce_type bce_devs[] = {
13843c2aeb0SSepherosa Ziehau 	/* BCM5706C Controllers and OEM boards. */
13943c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  HP_VENDORID, 0x3101,
14043c2aeb0SSepherosa Ziehau 		"HP NC370T Multifunction Gigabit Server Adapter" },
14143c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  HP_VENDORID, 0x3106,
14243c2aeb0SSepherosa Ziehau 		"HP NC370i Multifunction Gigabit Server Adapter" },
14343c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  PCI_ANY_ID,  PCI_ANY_ID,
14443c2aeb0SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5706 1000Base-T" },
14543c2aeb0SSepherosa Ziehau 
14643c2aeb0SSepherosa Ziehau 	/* BCM5706S controllers and OEM boards. */
14743c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, HP_VENDORID, 0x3102,
14843c2aeb0SSepherosa Ziehau 		"HP NC370F Multifunction Gigabit Server Adapter" },
14943c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, PCI_ANY_ID,  PCI_ANY_ID,
15043c2aeb0SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5706 1000Base-SX" },
15143c2aeb0SSepherosa Ziehau 
15243c2aeb0SSepherosa Ziehau 	/* BCM5708C controllers and OEM boards. */
15343c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708,  PCI_ANY_ID,  PCI_ANY_ID,
15443c2aeb0SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5708 1000Base-T" },
15543c2aeb0SSepherosa Ziehau 
15643c2aeb0SSepherosa Ziehau 	/* BCM5708S controllers and OEM boards. */
15743c2aeb0SSepherosa Ziehau 	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S,  PCI_ANY_ID,  PCI_ANY_ID,
15843c2aeb0SSepherosa Ziehau 		"Broadcom NetXtreme II BCM5708S 1000Base-T" },
15943c2aeb0SSepherosa Ziehau 	{ 0, 0, 0, 0, NULL }
16043c2aeb0SSepherosa Ziehau };
16143c2aeb0SSepherosa Ziehau 
16243c2aeb0SSepherosa Ziehau 
16343c2aeb0SSepherosa Ziehau /****************************************************************************/
16443c2aeb0SSepherosa Ziehau /* Supported Flash NVRAM device data.                                       */
16543c2aeb0SSepherosa Ziehau /****************************************************************************/
16643c2aeb0SSepherosa Ziehau static const struct flash_spec flash_table[] =
16743c2aeb0SSepherosa Ziehau {
16843c2aeb0SSepherosa Ziehau 	/* Slow EEPROM */
16943c2aeb0SSepherosa Ziehau 	{0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
17043c2aeb0SSepherosa Ziehau 	 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
17143c2aeb0SSepherosa Ziehau 	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
17243c2aeb0SSepherosa Ziehau 	 "EEPROM - slow"},
17343c2aeb0SSepherosa Ziehau 	/* Expansion entry 0001 */
17443c2aeb0SSepherosa Ziehau 	{0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
17543c2aeb0SSepherosa Ziehau 	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
17643c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
17743c2aeb0SSepherosa Ziehau 	 "Entry 0001"},
17843c2aeb0SSepherosa Ziehau 	/* Saifun SA25F010 (non-buffered flash) */
17943c2aeb0SSepherosa Ziehau 	/* strap, cfg1, & write1 need updates */
18043c2aeb0SSepherosa Ziehau 	{0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
18143c2aeb0SSepherosa Ziehau 	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
18243c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
18343c2aeb0SSepherosa Ziehau 	 "Non-buffered flash (128kB)"},
18443c2aeb0SSepherosa Ziehau 	/* Saifun SA25F020 (non-buffered flash) */
18543c2aeb0SSepherosa Ziehau 	/* strap, cfg1, & write1 need updates */
18643c2aeb0SSepherosa Ziehau 	{0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
18743c2aeb0SSepherosa Ziehau 	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
18843c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
18943c2aeb0SSepherosa Ziehau 	 "Non-buffered flash (256kB)"},
19043c2aeb0SSepherosa Ziehau 	/* Expansion entry 0100 */
19143c2aeb0SSepherosa Ziehau 	{0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
19243c2aeb0SSepherosa Ziehau 	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
19343c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
19443c2aeb0SSepherosa Ziehau 	 "Entry 0100"},
19543c2aeb0SSepherosa Ziehau 	/* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
19643c2aeb0SSepherosa Ziehau 	{0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
19743c2aeb0SSepherosa Ziehau 	 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
19843c2aeb0SSepherosa Ziehau 	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
19943c2aeb0SSepherosa Ziehau 	 "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
20043c2aeb0SSepherosa Ziehau 	/* Entry 0110: ST M45PE20 (non-buffered flash)*/
20143c2aeb0SSepherosa Ziehau 	{0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
20243c2aeb0SSepherosa Ziehau 	 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
20343c2aeb0SSepherosa Ziehau 	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
20443c2aeb0SSepherosa Ziehau 	 "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
20543c2aeb0SSepherosa Ziehau 	/* Saifun SA25F005 (non-buffered flash) */
20643c2aeb0SSepherosa Ziehau 	/* strap, cfg1, & write1 need updates */
20743c2aeb0SSepherosa Ziehau 	{0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
20843c2aeb0SSepherosa Ziehau 	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
20943c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
21043c2aeb0SSepherosa Ziehau 	 "Non-buffered flash (64kB)"},
21143c2aeb0SSepherosa Ziehau 	/* Fast EEPROM */
21243c2aeb0SSepherosa Ziehau 	{0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
21343c2aeb0SSepherosa Ziehau 	 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
21443c2aeb0SSepherosa Ziehau 	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
21543c2aeb0SSepherosa Ziehau 	 "EEPROM - fast"},
21643c2aeb0SSepherosa Ziehau 	/* Expansion entry 1001 */
21743c2aeb0SSepherosa Ziehau 	{0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
21843c2aeb0SSepherosa Ziehau 	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
21943c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
22043c2aeb0SSepherosa Ziehau 	 "Entry 1001"},
22143c2aeb0SSepherosa Ziehau 	/* Expansion entry 1010 */
22243c2aeb0SSepherosa Ziehau 	{0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
22343c2aeb0SSepherosa Ziehau 	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
22443c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
22543c2aeb0SSepherosa Ziehau 	 "Entry 1010"},
22643c2aeb0SSepherosa Ziehau 	/* ATMEL AT45DB011B (buffered flash) */
22743c2aeb0SSepherosa Ziehau 	{0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
22843c2aeb0SSepherosa Ziehau 	 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
22943c2aeb0SSepherosa Ziehau 	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
23043c2aeb0SSepherosa Ziehau 	 "Buffered flash (128kB)"},
23143c2aeb0SSepherosa Ziehau 	/* Expansion entry 1100 */
23243c2aeb0SSepherosa Ziehau 	{0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
23343c2aeb0SSepherosa Ziehau 	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
23443c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
23543c2aeb0SSepherosa Ziehau 	 "Entry 1100"},
23643c2aeb0SSepherosa Ziehau 	/* Expansion entry 1101 */
23743c2aeb0SSepherosa Ziehau 	{0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
23843c2aeb0SSepherosa Ziehau 	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
23943c2aeb0SSepherosa Ziehau 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
24043c2aeb0SSepherosa Ziehau 	 "Entry 1101"},
24143c2aeb0SSepherosa Ziehau 	/* Ateml Expansion entry 1110 */
24243c2aeb0SSepherosa Ziehau 	{0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
24343c2aeb0SSepherosa Ziehau 	 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
24443c2aeb0SSepherosa Ziehau 	 BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
24543c2aeb0SSepherosa Ziehau 	 "Entry 1110 (Atmel)"},
24643c2aeb0SSepherosa Ziehau 	/* ATMEL AT45DB021B (buffered flash) */
24743c2aeb0SSepherosa Ziehau 	{0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
24843c2aeb0SSepherosa Ziehau 	 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
24943c2aeb0SSepherosa Ziehau 	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
25043c2aeb0SSepherosa Ziehau 	 "Buffered flash (256kB)"},
25143c2aeb0SSepherosa Ziehau };
25243c2aeb0SSepherosa Ziehau 
25343c2aeb0SSepherosa Ziehau 
25443c2aeb0SSepherosa Ziehau /****************************************************************************/
25543c2aeb0SSepherosa Ziehau /* DragonFly device entry points.                                           */
25643c2aeb0SSepherosa Ziehau /****************************************************************************/
25743c2aeb0SSepherosa Ziehau static int	bce_probe(device_t);
25843c2aeb0SSepherosa Ziehau static int	bce_attach(device_t);
25943c2aeb0SSepherosa Ziehau static int	bce_detach(device_t);
26043c2aeb0SSepherosa Ziehau static void	bce_shutdown(device_t);
26143c2aeb0SSepherosa Ziehau 
26243c2aeb0SSepherosa Ziehau /****************************************************************************/
26343c2aeb0SSepherosa Ziehau /* BCE Debug Data Structure Dump Routines                                   */
26443c2aeb0SSepherosa Ziehau /****************************************************************************/
26543c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
26643c2aeb0SSepherosa Ziehau static void	bce_dump_mbuf(struct bce_softc *, struct mbuf *);
26743c2aeb0SSepherosa Ziehau static void	bce_dump_tx_mbuf_chain(struct bce_softc *, int, int);
26843c2aeb0SSepherosa Ziehau static void	bce_dump_rx_mbuf_chain(struct bce_softc *, int, int);
26943c2aeb0SSepherosa Ziehau static void	bce_dump_txbd(struct bce_softc *, int, struct tx_bd *);
27043c2aeb0SSepherosa Ziehau static void	bce_dump_rxbd(struct bce_softc *, int, struct rx_bd *);
27143c2aeb0SSepherosa Ziehau static void	bce_dump_l2fhdr(struct bce_softc *, int,
27243c2aeb0SSepherosa Ziehau 				struct l2_fhdr *) __unused;
27343c2aeb0SSepherosa Ziehau static void	bce_dump_tx_chain(struct bce_softc *, int, int);
27443c2aeb0SSepherosa Ziehau static void	bce_dump_rx_chain(struct bce_softc *, int, int);
27543c2aeb0SSepherosa Ziehau static void	bce_dump_status_block(struct bce_softc *);
27643c2aeb0SSepherosa Ziehau static void	bce_dump_driver_state(struct bce_softc *);
27743c2aeb0SSepherosa Ziehau static void	bce_dump_stats_block(struct bce_softc *) __unused;
27843c2aeb0SSepherosa Ziehau static void	bce_dump_hw_state(struct bce_softc *);
27943c2aeb0SSepherosa Ziehau static void	bce_dump_txp_state(struct bce_softc *);
28043c2aeb0SSepherosa Ziehau static void	bce_dump_rxp_state(struct bce_softc *) __unused;
28143c2aeb0SSepherosa Ziehau static void	bce_dump_tpat_state(struct bce_softc *) __unused;
28243c2aeb0SSepherosa Ziehau static void	bce_freeze_controller(struct bce_softc *) __unused;
28343c2aeb0SSepherosa Ziehau static void	bce_unfreeze_controller(struct bce_softc *) __unused;
28443c2aeb0SSepherosa Ziehau static void	bce_breakpoint(struct bce_softc *);
28543c2aeb0SSepherosa Ziehau #endif	/* BCE_DEBUG */
28643c2aeb0SSepherosa Ziehau 
28743c2aeb0SSepherosa Ziehau 
28843c2aeb0SSepherosa Ziehau /****************************************************************************/
28943c2aeb0SSepherosa Ziehau /* BCE Register/Memory Access Routines                                      */
29043c2aeb0SSepherosa Ziehau /****************************************************************************/
29143c2aeb0SSepherosa Ziehau static uint32_t	bce_reg_rd_ind(struct bce_softc *, uint32_t);
29243c2aeb0SSepherosa Ziehau static void	bce_reg_wr_ind(struct bce_softc *, uint32_t, uint32_t);
29343c2aeb0SSepherosa Ziehau static void	bce_ctx_wr(struct bce_softc *, uint32_t, uint32_t, uint32_t);
29443c2aeb0SSepherosa Ziehau static int	bce_miibus_read_reg(device_t, int, int);
29543c2aeb0SSepherosa Ziehau static int	bce_miibus_write_reg(device_t, int, int, int);
29643c2aeb0SSepherosa Ziehau static void	bce_miibus_statchg(device_t);
29743c2aeb0SSepherosa Ziehau 
29843c2aeb0SSepherosa Ziehau 
29943c2aeb0SSepherosa Ziehau /****************************************************************************/
30043c2aeb0SSepherosa Ziehau /* BCE NVRAM Access Routines                                                */
30143c2aeb0SSepherosa Ziehau /****************************************************************************/
30243c2aeb0SSepherosa Ziehau static int	bce_acquire_nvram_lock(struct bce_softc *);
30343c2aeb0SSepherosa Ziehau static int	bce_release_nvram_lock(struct bce_softc *);
30443c2aeb0SSepherosa Ziehau static void	bce_enable_nvram_access(struct bce_softc *);
30543c2aeb0SSepherosa Ziehau static void	bce_disable_nvram_access(struct bce_softc *);
30643c2aeb0SSepherosa Ziehau static int	bce_nvram_read_dword(struct bce_softc *, uint32_t, uint8_t *,
30743c2aeb0SSepherosa Ziehau 				     uint32_t);
30843c2aeb0SSepherosa Ziehau static int	bce_init_nvram(struct bce_softc *);
30943c2aeb0SSepherosa Ziehau static int	bce_nvram_read(struct bce_softc *, uint32_t, uint8_t *, int);
31043c2aeb0SSepherosa Ziehau static int	bce_nvram_test(struct bce_softc *);
31143c2aeb0SSepherosa Ziehau #ifdef BCE_NVRAM_WRITE_SUPPORT
31243c2aeb0SSepherosa Ziehau static int	bce_enable_nvram_write(struct bce_softc *);
31343c2aeb0SSepherosa Ziehau static void	bce_disable_nvram_write(struct bce_softc *);
31443c2aeb0SSepherosa Ziehau static int	bce_nvram_erase_page(struct bce_softc *, uint32_t);
31519081c78SSepherosa Ziehau static int	bce_nvram_write_dword(struct bce_softc *, uint32_t, uint8_t *,
31619081c78SSepherosa Ziehau 				      uint32_t);
31743c2aeb0SSepherosa Ziehau static int	bce_nvram_write(struct bce_softc *, uint32_t, uint8_t *,
31843c2aeb0SSepherosa Ziehau 				int) __unused;
31943c2aeb0SSepherosa Ziehau #endif
32043c2aeb0SSepherosa Ziehau 
32143c2aeb0SSepherosa Ziehau /****************************************************************************/
32243c2aeb0SSepherosa Ziehau /* BCE DMA Allocate/Free Routines                                           */
32343c2aeb0SSepherosa Ziehau /****************************************************************************/
32443c2aeb0SSepherosa Ziehau static int	bce_dma_alloc(struct bce_softc *);
32543c2aeb0SSepherosa Ziehau static void	bce_dma_free(struct bce_softc *);
32643c2aeb0SSepherosa Ziehau static void	bce_dma_map_addr(void *, bus_dma_segment_t *, int, int);
32743c2aeb0SSepherosa Ziehau static void	bce_dma_map_mbuf(void *, bus_dma_segment_t *, int,
32843c2aeb0SSepherosa Ziehau 				 bus_size_t, int);
32943c2aeb0SSepherosa Ziehau 
33043c2aeb0SSepherosa Ziehau /****************************************************************************/
33143c2aeb0SSepherosa Ziehau /* BCE Firmware Synchronization and Load                                    */
33243c2aeb0SSepherosa Ziehau /****************************************************************************/
33343c2aeb0SSepherosa Ziehau static int	bce_fw_sync(struct bce_softc *, uint32_t);
33443c2aeb0SSepherosa Ziehau static void	bce_load_rv2p_fw(struct bce_softc *, uint32_t *,
33543c2aeb0SSepherosa Ziehau 				 uint32_t, uint32_t);
33643c2aeb0SSepherosa Ziehau static void	bce_load_cpu_fw(struct bce_softc *, struct cpu_reg *,
33743c2aeb0SSepherosa Ziehau 				struct fw_info *);
33843c2aeb0SSepherosa Ziehau static void	bce_init_cpus(struct bce_softc *);
33943c2aeb0SSepherosa Ziehau 
34043c2aeb0SSepherosa Ziehau static void	bce_stop(struct bce_softc *);
34143c2aeb0SSepherosa Ziehau static int	bce_reset(struct bce_softc *, uint32_t);
34243c2aeb0SSepherosa Ziehau static int	bce_chipinit(struct bce_softc *);
34343c2aeb0SSepherosa Ziehau static int	bce_blockinit(struct bce_softc *);
34443c2aeb0SSepherosa Ziehau static int	bce_newbuf_std(struct bce_softc *, struct mbuf *,
34543c2aeb0SSepherosa Ziehau 			       uint16_t *, uint16_t *, uint32_t *);
34643c2aeb0SSepherosa Ziehau 
34743c2aeb0SSepherosa Ziehau static int	bce_init_tx_chain(struct bce_softc *);
34843c2aeb0SSepherosa Ziehau static int	bce_init_rx_chain(struct bce_softc *);
34943c2aeb0SSepherosa Ziehau static void	bce_free_rx_chain(struct bce_softc *);
35043c2aeb0SSepherosa Ziehau static void	bce_free_tx_chain(struct bce_softc *);
35143c2aeb0SSepherosa Ziehau 
35243c2aeb0SSepherosa Ziehau static int	bce_encap(struct bce_softc *, struct mbuf **);
35343c2aeb0SSepherosa Ziehau static void	bce_start(struct ifnet *);
35443c2aeb0SSepherosa Ziehau static int	bce_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
35543c2aeb0SSepherosa Ziehau static void	bce_watchdog(struct ifnet *);
35643c2aeb0SSepherosa Ziehau static int	bce_ifmedia_upd(struct ifnet *);
35743c2aeb0SSepherosa Ziehau static void	bce_ifmedia_sts(struct ifnet *, struct ifmediareq *);
35843c2aeb0SSepherosa Ziehau static void	bce_init(void *);
35943c2aeb0SSepherosa Ziehau static void	bce_mgmt_init(struct bce_softc *);
36043c2aeb0SSepherosa Ziehau 
3613a41a80bSSepherosa Ziehau static void	bce_init_ctx(struct bce_softc *);
36243c2aeb0SSepherosa Ziehau static void	bce_get_mac_addr(struct bce_softc *);
36343c2aeb0SSepherosa Ziehau static void	bce_set_mac_addr(struct bce_softc *);
36443c2aeb0SSepherosa Ziehau static void	bce_phy_intr(struct bce_softc *);
36543c2aeb0SSepherosa Ziehau static void	bce_rx_intr(struct bce_softc *, int);
36643c2aeb0SSepherosa Ziehau static void	bce_tx_intr(struct bce_softc *);
36743c2aeb0SSepherosa Ziehau static void	bce_disable_intr(struct bce_softc *);
36843c2aeb0SSepherosa Ziehau static void	bce_enable_intr(struct bce_softc *);
36943c2aeb0SSepherosa Ziehau 
37043c2aeb0SSepherosa Ziehau #ifdef DEVICE_POLLING
37143c2aeb0SSepherosa Ziehau static void	bce_poll(struct ifnet *, enum poll_cmd, int);
37243c2aeb0SSepherosa Ziehau #endif
37343c2aeb0SSepherosa Ziehau static void	bce_intr(void *);
37443c2aeb0SSepherosa Ziehau static void	bce_set_rx_mode(struct bce_softc *);
37543c2aeb0SSepherosa Ziehau static void	bce_stats_update(struct bce_softc *);
37643c2aeb0SSepherosa Ziehau static void	bce_tick(void *);
37743c2aeb0SSepherosa Ziehau static void	bce_tick_serialized(struct bce_softc *);
37843c2aeb0SSepherosa Ziehau static void	bce_add_sysctls(struct bce_softc *);
37943c2aeb0SSepherosa Ziehau 
380bdeb8fffSSepherosa Ziehau static void	bce_coal_change(struct bce_softc *);
381bdeb8fffSSepherosa Ziehau static int	bce_sysctl_tx_bds_int(SYSCTL_HANDLER_ARGS);
382bdeb8fffSSepherosa Ziehau static int	bce_sysctl_tx_bds(SYSCTL_HANDLER_ARGS);
383bdeb8fffSSepherosa Ziehau static int	bce_sysctl_tx_ticks_int(SYSCTL_HANDLER_ARGS);
384bdeb8fffSSepherosa Ziehau static int	bce_sysctl_tx_ticks(SYSCTL_HANDLER_ARGS);
385bdeb8fffSSepherosa Ziehau static int	bce_sysctl_rx_bds_int(SYSCTL_HANDLER_ARGS);
386bdeb8fffSSepherosa Ziehau static int	bce_sysctl_rx_bds(SYSCTL_HANDLER_ARGS);
387bdeb8fffSSepherosa Ziehau static int	bce_sysctl_rx_ticks_int(SYSCTL_HANDLER_ARGS);
388bdeb8fffSSepherosa Ziehau static int	bce_sysctl_rx_ticks(SYSCTL_HANDLER_ARGS);
389bdeb8fffSSepherosa Ziehau static int	bce_sysctl_coal_change(SYSCTL_HANDLER_ARGS,
390bdeb8fffSSepherosa Ziehau 				       uint32_t *, uint32_t);
391bdeb8fffSSepherosa Ziehau 
3923fb4bb6cSSepherosa Ziehau /*
3933fb4bb6cSSepherosa Ziehau  * NOTE:
3943fb4bb6cSSepherosa Ziehau  * Don't set bce_tx_ticks_int/bce_tx_ticks to 1023.  Linux's bnx2
3953fb4bb6cSSepherosa Ziehau  * takes 1023 as the TX ticks limit.  However, using 1023 will
3963fb4bb6cSSepherosa Ziehau  * cause 5708(B2) to generate extra interrupts (~2000/s) even when
3973fb4bb6cSSepherosa Ziehau  * there is _no_ network activity on the NIC.
3983fb4bb6cSSepherosa Ziehau  */
3993fb4bb6cSSepherosa Ziehau static uint32_t	bce_tx_bds_int = 255;		/* bcm: 20 */
4003fb4bb6cSSepherosa Ziehau static uint32_t	bce_tx_bds = 255;		/* bcm: 20 */
4013fb4bb6cSSepherosa Ziehau static uint32_t	bce_tx_ticks_int = 1022;	/* bcm: 80 */
4023fb4bb6cSSepherosa Ziehau static uint32_t	bce_tx_ticks = 1022;		/* bcm: 80 */
4031af951abSSepherosa Ziehau static uint32_t	bce_rx_bds_int = 128;		/* bcm: 6 */
4041af951abSSepherosa Ziehau static uint32_t	bce_rx_bds = 128;		/* bcm: 6 */
4051af951abSSepherosa Ziehau static uint32_t	bce_rx_ticks_int = 125;		/* bcm: 18 */
4061af951abSSepherosa Ziehau static uint32_t	bce_rx_ticks = 125;		/* bcm: 18 */
407bdeb8fffSSepherosa Ziehau 
408bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_bds_int", &bce_tx_bds_int);
409bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_bds", &bce_tx_bds);
410bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_ticks_int", &bce_tx_ticks_int);
411bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_ticks", &bce_tx_ticks);
412bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_bds_int", &bce_rx_bds_int);
413bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_bds", &bce_rx_bds);
414bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_ticks_int", &bce_rx_ticks_int);
415bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_ticks", &bce_rx_ticks);
41643c2aeb0SSepherosa Ziehau 
41743c2aeb0SSepherosa Ziehau /****************************************************************************/
41843c2aeb0SSepherosa Ziehau /* DragonFly device dispatch table.                                         */
41943c2aeb0SSepherosa Ziehau /****************************************************************************/
42043c2aeb0SSepherosa Ziehau static device_method_t bce_methods[] = {
42143c2aeb0SSepherosa Ziehau 	/* Device interface */
42243c2aeb0SSepherosa Ziehau 	DEVMETHOD(device_probe,		bce_probe),
42343c2aeb0SSepherosa Ziehau 	DEVMETHOD(device_attach,	bce_attach),
42443c2aeb0SSepherosa Ziehau 	DEVMETHOD(device_detach,	bce_detach),
42543c2aeb0SSepherosa Ziehau 	DEVMETHOD(device_shutdown,	bce_shutdown),
42643c2aeb0SSepherosa Ziehau 
42743c2aeb0SSepherosa Ziehau 	/* bus interface */
42843c2aeb0SSepherosa Ziehau 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
42943c2aeb0SSepherosa Ziehau 	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
43043c2aeb0SSepherosa Ziehau 
43143c2aeb0SSepherosa Ziehau 	/* MII interface */
43243c2aeb0SSepherosa Ziehau 	DEVMETHOD(miibus_readreg,	bce_miibus_read_reg),
43343c2aeb0SSepherosa Ziehau 	DEVMETHOD(miibus_writereg,	bce_miibus_write_reg),
43443c2aeb0SSepherosa Ziehau 	DEVMETHOD(miibus_statchg,	bce_miibus_statchg),
43543c2aeb0SSepherosa Ziehau 
43643c2aeb0SSepherosa Ziehau 	{ 0, 0 }
43743c2aeb0SSepherosa Ziehau };
43843c2aeb0SSepherosa Ziehau 
43943c2aeb0SSepherosa Ziehau static driver_t bce_driver = {
44043c2aeb0SSepherosa Ziehau 	"bce",
44143c2aeb0SSepherosa Ziehau 	bce_methods,
44243c2aeb0SSepherosa Ziehau 	sizeof(struct bce_softc)
44343c2aeb0SSepherosa Ziehau };
44443c2aeb0SSepherosa Ziehau 
44543c2aeb0SSepherosa Ziehau static devclass_t bce_devclass;
44643c2aeb0SSepherosa Ziehau 
44743c2aeb0SSepherosa Ziehau 
4481be78fa8SSepherosa Ziehau DECLARE_DUMMY_MODULE(if_xl);
4491be78fa8SSepherosa Ziehau MODULE_DEPEND(bce, miibus, 1, 1, 1);
4501be78fa8SSepherosa Ziehau DRIVER_MODULE(if_bce, pci, bce_driver, bce_devclass, 0, 0);
45143c2aeb0SSepherosa Ziehau DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, 0, 0);
45243c2aeb0SSepherosa Ziehau 
45343c2aeb0SSepherosa Ziehau 
45443c2aeb0SSepherosa Ziehau /****************************************************************************/
45543c2aeb0SSepherosa Ziehau /* Device probe function.                                                   */
45643c2aeb0SSepherosa Ziehau /*                                                                          */
45743c2aeb0SSepherosa Ziehau /* Compares the device to the driver's list of supported devices and        */
45843c2aeb0SSepherosa Ziehau /* reports back to the OS whether this is the right driver for the device.  */
45943c2aeb0SSepherosa Ziehau /*                                                                          */
46043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
46143c2aeb0SSepherosa Ziehau /*   BUS_PROBE_DEFAULT on success, positive value on failure.               */
46243c2aeb0SSepherosa Ziehau /****************************************************************************/
46343c2aeb0SSepherosa Ziehau static int
46443c2aeb0SSepherosa Ziehau bce_probe(device_t dev)
46543c2aeb0SSepherosa Ziehau {
46643c2aeb0SSepherosa Ziehau 	struct bce_type *t;
46743c2aeb0SSepherosa Ziehau 	uint16_t vid, did, svid, sdid;
46843c2aeb0SSepherosa Ziehau 
46943c2aeb0SSepherosa Ziehau 	/* Get the data for the device to be probed. */
47043c2aeb0SSepherosa Ziehau 	vid  = pci_get_vendor(dev);
47143c2aeb0SSepherosa Ziehau 	did  = pci_get_device(dev);
47243c2aeb0SSepherosa Ziehau 	svid = pci_get_subvendor(dev);
47343c2aeb0SSepherosa Ziehau 	sdid = pci_get_subdevice(dev);
47443c2aeb0SSepherosa Ziehau 
47543c2aeb0SSepherosa Ziehau 	/* Look through the list of known devices for a match. */
47643c2aeb0SSepherosa Ziehau 	for (t = bce_devs; t->bce_name != NULL; ++t) {
47743c2aeb0SSepherosa Ziehau 		if (vid == t->bce_vid && did == t->bce_did &&
47843c2aeb0SSepherosa Ziehau 		    (svid == t->bce_svid || t->bce_svid == PCI_ANY_ID) &&
47943c2aeb0SSepherosa Ziehau 		    (sdid == t->bce_sdid || t->bce_sdid == PCI_ANY_ID)) {
48043c2aeb0SSepherosa Ziehau 		    	uint32_t revid = pci_read_config(dev, PCIR_REVID, 4);
48143c2aeb0SSepherosa Ziehau 			char *descbuf;
48243c2aeb0SSepherosa Ziehau 
48343c2aeb0SSepherosa Ziehau 			descbuf = kmalloc(BCE_DEVDESC_MAX, M_TEMP, M_WAITOK);
48443c2aeb0SSepherosa Ziehau 
48543c2aeb0SSepherosa Ziehau 			/* Print out the device identity. */
48643c2aeb0SSepherosa Ziehau 			ksnprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d)",
48743c2aeb0SSepherosa Ziehau 				  t->bce_name,
48843c2aeb0SSepherosa Ziehau 				  ((revid & 0xf0) >> 4) + 'A', revid & 0xf);
48943c2aeb0SSepherosa Ziehau 
49043c2aeb0SSepherosa Ziehau 			device_set_desc_copy(dev, descbuf);
49143c2aeb0SSepherosa Ziehau 			kfree(descbuf, M_TEMP);
49243c2aeb0SSepherosa Ziehau 			return 0;
49343c2aeb0SSepherosa Ziehau 		}
49443c2aeb0SSepherosa Ziehau 	}
49543c2aeb0SSepherosa Ziehau 	return ENXIO;
49643c2aeb0SSepherosa Ziehau }
49743c2aeb0SSepherosa Ziehau 
49843c2aeb0SSepherosa Ziehau 
49943c2aeb0SSepherosa Ziehau /****************************************************************************/
50043c2aeb0SSepherosa Ziehau /* Device attach function.                                                  */
50143c2aeb0SSepherosa Ziehau /*                                                                          */
50243c2aeb0SSepherosa Ziehau /* Allocates device resources, performs secondary chip identification,      */
50343c2aeb0SSepherosa Ziehau /* resets and initializes the hardware, and initializes driver instance     */
50443c2aeb0SSepherosa Ziehau /* variables.                                                               */
50543c2aeb0SSepherosa Ziehau /*                                                                          */
50643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
50743c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
50843c2aeb0SSepherosa Ziehau /****************************************************************************/
50943c2aeb0SSepherosa Ziehau static int
51043c2aeb0SSepherosa Ziehau bce_attach(device_t dev)
51143c2aeb0SSepherosa Ziehau {
51243c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
51343c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
51443c2aeb0SSepherosa Ziehau 	uint32_t val;
51543c2aeb0SSepherosa Ziehau 	int rid, rc = 0;
51643c2aeb0SSepherosa Ziehau #ifdef notyet
51743c2aeb0SSepherosa Ziehau 	int count;
51843c2aeb0SSepherosa Ziehau #endif
51943c2aeb0SSepherosa Ziehau 
52043c2aeb0SSepherosa Ziehau 	sc->bce_dev = dev;
52143c2aeb0SSepherosa Ziehau 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
52243c2aeb0SSepherosa Ziehau 
52343c2aeb0SSepherosa Ziehau 	pci_enable_busmaster(dev);
52443c2aeb0SSepherosa Ziehau 
52543c2aeb0SSepherosa Ziehau 	/* Allocate PCI memory resources. */
52643c2aeb0SSepherosa Ziehau 	rid = PCIR_BAR(0);
52743c2aeb0SSepherosa Ziehau 	sc->bce_res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
52843c2aeb0SSepherosa Ziehau 						 RF_ACTIVE | PCI_RF_DENSE);
52943c2aeb0SSepherosa Ziehau 	if (sc->bce_res_mem == NULL) {
53043c2aeb0SSepherosa Ziehau 		device_printf(dev, "PCI memory allocation failed\n");
53143c2aeb0SSepherosa Ziehau 		return ENXIO;
53243c2aeb0SSepherosa Ziehau 	}
53343c2aeb0SSepherosa Ziehau 	sc->bce_btag = rman_get_bustag(sc->bce_res_mem);
53443c2aeb0SSepherosa Ziehau 	sc->bce_bhandle = rman_get_bushandle(sc->bce_res_mem);
53543c2aeb0SSepherosa Ziehau 
53643c2aeb0SSepherosa Ziehau 	/* Allocate PCI IRQ resources. */
53743c2aeb0SSepherosa Ziehau #ifdef notyet
53843c2aeb0SSepherosa Ziehau 	count = pci_msi_count(dev);
53943c2aeb0SSepherosa Ziehau 	if (count == 1 && pci_alloc_msi(dev, &count) == 0) {
54043c2aeb0SSepherosa Ziehau 		rid = 1;
54143c2aeb0SSepherosa Ziehau 		sc->bce_flags |= BCE_USING_MSI_FLAG;
54243c2aeb0SSepherosa Ziehau 	} else
54343c2aeb0SSepherosa Ziehau #endif
54443c2aeb0SSepherosa Ziehau 	rid = 0;
54543c2aeb0SSepherosa Ziehau 	sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
54643c2aeb0SSepherosa Ziehau 						 RF_SHAREABLE | RF_ACTIVE);
54743c2aeb0SSepherosa Ziehau 	if (sc->bce_res_irq == NULL) {
54843c2aeb0SSepherosa Ziehau 		device_printf(dev, "PCI map interrupt failed\n");
54943c2aeb0SSepherosa Ziehau 		rc = ENXIO;
55043c2aeb0SSepherosa Ziehau 		goto fail;
55143c2aeb0SSepherosa Ziehau 	}
55243c2aeb0SSepherosa Ziehau 
55343c2aeb0SSepherosa Ziehau 	/*
55443c2aeb0SSepherosa Ziehau 	 * Configure byte swap and enable indirect register access.
55543c2aeb0SSepherosa Ziehau 	 * Rely on CPU to do target byte swapping on big endian systems.
55643c2aeb0SSepherosa Ziehau 	 * Access to registers outside of PCI configurtion space are not
55743c2aeb0SSepherosa Ziehau 	 * valid until this is done.
55843c2aeb0SSepherosa Ziehau 	 */
55943c2aeb0SSepherosa Ziehau 	pci_write_config(dev, BCE_PCICFG_MISC_CONFIG,
56043c2aeb0SSepherosa Ziehau 			 BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
56143c2aeb0SSepherosa Ziehau 			 BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP, 4);
56243c2aeb0SSepherosa Ziehau 
56343c2aeb0SSepherosa Ziehau 	/* Save ASIC revsion info. */
56443c2aeb0SSepherosa Ziehau 	sc->bce_chipid =  REG_RD(sc, BCE_MISC_ID);
56543c2aeb0SSepherosa Ziehau 
56643c2aeb0SSepherosa Ziehau 	/* Weed out any non-production controller revisions. */
56743c2aeb0SSepherosa Ziehau 	switch(BCE_CHIP_ID(sc)) {
56843c2aeb0SSepherosa Ziehau 	case BCE_CHIP_ID_5706_A0:
56943c2aeb0SSepherosa Ziehau 	case BCE_CHIP_ID_5706_A1:
57043c2aeb0SSepherosa Ziehau 	case BCE_CHIP_ID_5708_A0:
57143c2aeb0SSepherosa Ziehau 	case BCE_CHIP_ID_5708_B0:
57243c2aeb0SSepherosa Ziehau 		device_printf(dev, "Unsupported chip id 0x%08x!\n",
57343c2aeb0SSepherosa Ziehau 			      BCE_CHIP_ID(sc));
57443c2aeb0SSepherosa Ziehau 		rc = ENODEV;
57543c2aeb0SSepherosa Ziehau 		goto fail;
57643c2aeb0SSepherosa Ziehau 	}
57743c2aeb0SSepherosa Ziehau 
57843c2aeb0SSepherosa Ziehau 	/*
57943c2aeb0SSepherosa Ziehau 	 * The embedded PCIe to PCI-X bridge (EPB)
58043c2aeb0SSepherosa Ziehau 	 * in the 5708 cannot address memory above
58143c2aeb0SSepherosa Ziehau 	 * 40 bits (E7_5708CB1_23043 & E6_5708SB1_23043).
58243c2aeb0SSepherosa Ziehau 	 */
58343c2aeb0SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708)
58443c2aeb0SSepherosa Ziehau 		sc->max_bus_addr = BCE_BUS_SPACE_MAXADDR;
58543c2aeb0SSepherosa Ziehau 	else
58643c2aeb0SSepherosa Ziehau 		sc->max_bus_addr = BUS_SPACE_MAXADDR;
58743c2aeb0SSepherosa Ziehau 
58843c2aeb0SSepherosa Ziehau 	/*
58943c2aeb0SSepherosa Ziehau 	 * Find the base address for shared memory access.
59043c2aeb0SSepherosa Ziehau 	 * Newer versions of bootcode use a signature and offset
59143c2aeb0SSepherosa Ziehau 	 * while older versions use a fixed address.
59243c2aeb0SSepherosa Ziehau 	 */
59343c2aeb0SSepherosa Ziehau 	val = REG_RD_IND(sc, BCE_SHM_HDR_SIGNATURE);
59443c2aeb0SSepherosa Ziehau 	if ((val & BCE_SHM_HDR_SIGNATURE_SIG_MASK) == BCE_SHM_HDR_SIGNATURE_SIG)
59543c2aeb0SSepherosa Ziehau 		sc->bce_shmem_base = REG_RD_IND(sc, BCE_SHM_HDR_ADDR_0);
59643c2aeb0SSepherosa Ziehau 	else
59743c2aeb0SSepherosa Ziehau 		sc->bce_shmem_base = HOST_VIEW_SHMEM_BASE;
59843c2aeb0SSepherosa Ziehau 
59943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "bce_shmem_base = 0x%08X\n", sc->bce_shmem_base);
60043c2aeb0SSepherosa Ziehau 
60143c2aeb0SSepherosa Ziehau 	/* Get PCI bus information (speed and type). */
60243c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_PCICFG_MISC_STATUS);
60343c2aeb0SSepherosa Ziehau 	if (val & BCE_PCICFG_MISC_STATUS_PCIX_DET) {
60443c2aeb0SSepherosa Ziehau 		uint32_t clkreg;
60543c2aeb0SSepherosa Ziehau 
60643c2aeb0SSepherosa Ziehau 		sc->bce_flags |= BCE_PCIX_FLAG;
60743c2aeb0SSepherosa Ziehau 
60843c2aeb0SSepherosa Ziehau 		clkreg = REG_RD(sc, BCE_PCICFG_PCI_CLOCK_CONTROL_BITS) &
60943c2aeb0SSepherosa Ziehau 			 BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
61043c2aeb0SSepherosa Ziehau 		switch (clkreg) {
61143c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
61243c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 133;
61343c2aeb0SSepherosa Ziehau 			break;
61443c2aeb0SSepherosa Ziehau 
61543c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
61643c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 100;
61743c2aeb0SSepherosa Ziehau 			break;
61843c2aeb0SSepherosa Ziehau 
61943c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
62043c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
62143c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 66;
62243c2aeb0SSepherosa Ziehau 			break;
62343c2aeb0SSepherosa Ziehau 
62443c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
62543c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
62643c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 50;
62743c2aeb0SSepherosa Ziehau 			break;
62843c2aeb0SSepherosa Ziehau 
62943c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
63043c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
63143c2aeb0SSepherosa Ziehau 		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
63243c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 33;
63343c2aeb0SSepherosa Ziehau 			break;
63443c2aeb0SSepherosa Ziehau 		}
63543c2aeb0SSepherosa Ziehau 	} else {
63643c2aeb0SSepherosa Ziehau 		if (val & BCE_PCICFG_MISC_STATUS_M66EN)
63743c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 66;
63843c2aeb0SSepherosa Ziehau 		else
63943c2aeb0SSepherosa Ziehau 			sc->bus_speed_mhz = 33;
64043c2aeb0SSepherosa Ziehau 	}
64143c2aeb0SSepherosa Ziehau 
64243c2aeb0SSepherosa Ziehau 	if (val & BCE_PCICFG_MISC_STATUS_32BIT_DET)
64343c2aeb0SSepherosa Ziehau 		sc->bce_flags |= BCE_PCI_32BIT_FLAG;
64443c2aeb0SSepherosa Ziehau 
64543c2aeb0SSepherosa Ziehau 	device_printf(dev, "ASIC ID 0x%08X; Revision (%c%d); PCI%s %s %dMHz\n",
64643c2aeb0SSepherosa Ziehau 		      sc->bce_chipid,
64743c2aeb0SSepherosa Ziehau 		      ((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A',
64843c2aeb0SSepherosa Ziehau 		      (BCE_CHIP_ID(sc) & 0x0ff0) >> 4,
64943c2aeb0SSepherosa Ziehau 		      (sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : "",
65043c2aeb0SSepherosa Ziehau 		      (sc->bce_flags & BCE_PCI_32BIT_FLAG) ?
65143c2aeb0SSepherosa Ziehau 		      "32-bit" : "64-bit", sc->bus_speed_mhz);
65243c2aeb0SSepherosa Ziehau 
65343c2aeb0SSepherosa Ziehau 	/* Reset the controller. */
65443c2aeb0SSepherosa Ziehau 	rc = bce_reset(sc, BCE_DRV_MSG_CODE_RESET);
65543c2aeb0SSepherosa Ziehau 	if (rc != 0)
65643c2aeb0SSepherosa Ziehau 		goto fail;
65743c2aeb0SSepherosa Ziehau 
65843c2aeb0SSepherosa Ziehau 	/* Initialize the controller. */
65943c2aeb0SSepherosa Ziehau 	rc = bce_chipinit(sc);
66043c2aeb0SSepherosa Ziehau 	if (rc != 0) {
66143c2aeb0SSepherosa Ziehau 		device_printf(dev, "Controller initialization failed!\n");
66243c2aeb0SSepherosa Ziehau 		goto fail;
66343c2aeb0SSepherosa Ziehau 	}
66443c2aeb0SSepherosa Ziehau 
66543c2aeb0SSepherosa Ziehau 	/* Perform NVRAM test. */
66643c2aeb0SSepherosa Ziehau 	rc = bce_nvram_test(sc);
66743c2aeb0SSepherosa Ziehau 	if (rc != 0) {
66843c2aeb0SSepherosa Ziehau 		device_printf(dev, "NVRAM test failed!\n");
66943c2aeb0SSepherosa Ziehau 		goto fail;
67043c2aeb0SSepherosa Ziehau 	}
67143c2aeb0SSepherosa Ziehau 
67243c2aeb0SSepherosa Ziehau 	/* Fetch the permanent Ethernet MAC address. */
67343c2aeb0SSepherosa Ziehau 	bce_get_mac_addr(sc);
67443c2aeb0SSepherosa Ziehau 
67543c2aeb0SSepherosa Ziehau 	/*
67643c2aeb0SSepherosa Ziehau 	 * Trip points control how many BDs
67743c2aeb0SSepherosa Ziehau 	 * should be ready before generating an
67843c2aeb0SSepherosa Ziehau 	 * interrupt while ticks control how long
67943c2aeb0SSepherosa Ziehau 	 * a BD can sit in the chain before
68043c2aeb0SSepherosa Ziehau 	 * generating an interrupt.  Set the default
68143c2aeb0SSepherosa Ziehau 	 * values for the RX and TX rings.
68243c2aeb0SSepherosa Ziehau 	 */
68343c2aeb0SSepherosa Ziehau 
68443c2aeb0SSepherosa Ziehau #ifdef BCE_DRBUG
68543c2aeb0SSepherosa Ziehau 	/* Force more frequent interrupts. */
68643c2aeb0SSepherosa Ziehau 	sc->bce_tx_quick_cons_trip_int = 1;
68743c2aeb0SSepherosa Ziehau 	sc->bce_tx_quick_cons_trip     = 1;
68843c2aeb0SSepherosa Ziehau 	sc->bce_tx_ticks_int           = 0;
68943c2aeb0SSepherosa Ziehau 	sc->bce_tx_ticks               = 0;
69043c2aeb0SSepherosa Ziehau 
69143c2aeb0SSepherosa Ziehau 	sc->bce_rx_quick_cons_trip_int = 1;
69243c2aeb0SSepherosa Ziehau 	sc->bce_rx_quick_cons_trip     = 1;
69343c2aeb0SSepherosa Ziehau 	sc->bce_rx_ticks_int           = 0;
69443c2aeb0SSepherosa Ziehau 	sc->bce_rx_ticks               = 0;
69543c2aeb0SSepherosa Ziehau #else
696bdeb8fffSSepherosa Ziehau 	sc->bce_tx_quick_cons_trip_int = bce_tx_bds_int;
697bdeb8fffSSepherosa Ziehau 	sc->bce_tx_quick_cons_trip     = bce_tx_bds;
698bdeb8fffSSepherosa Ziehau 	sc->bce_tx_ticks_int           = bce_tx_ticks_int;
699bdeb8fffSSepherosa Ziehau 	sc->bce_tx_ticks               = bce_tx_ticks;
70043c2aeb0SSepherosa Ziehau 
701bdeb8fffSSepherosa Ziehau 	sc->bce_rx_quick_cons_trip_int = bce_rx_bds_int;
702bdeb8fffSSepherosa Ziehau 	sc->bce_rx_quick_cons_trip     = bce_rx_bds;
703bdeb8fffSSepherosa Ziehau 	sc->bce_rx_ticks_int           = bce_rx_ticks_int;
704bdeb8fffSSepherosa Ziehau 	sc->bce_rx_ticks               = bce_rx_ticks;
70543c2aeb0SSepherosa Ziehau #endif
70643c2aeb0SSepherosa Ziehau 
70743c2aeb0SSepherosa Ziehau 	/* Update statistics once every second. */
70843c2aeb0SSepherosa Ziehau 	sc->bce_stats_ticks = 1000000 & 0xffff00;
70943c2aeb0SSepherosa Ziehau 
71043c2aeb0SSepherosa Ziehau 	/*
71143c2aeb0SSepherosa Ziehau 	 * The copper based NetXtreme II controllers
71243c2aeb0SSepherosa Ziehau 	 * use an integrated PHY at address 1 while
71343c2aeb0SSepherosa Ziehau 	 * the SerDes controllers use a PHY at
71443c2aeb0SSepherosa Ziehau 	 * address 2.
71543c2aeb0SSepherosa Ziehau 	 */
71643c2aeb0SSepherosa Ziehau 	sc->bce_phy_addr = 1;
71743c2aeb0SSepherosa Ziehau 
71843c2aeb0SSepherosa Ziehau 	if (BCE_CHIP_BOND_ID(sc) & BCE_CHIP_BOND_ID_SERDES_BIT) {
71943c2aeb0SSepherosa Ziehau 		sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG;
72043c2aeb0SSepherosa Ziehau 		sc->bce_flags |= BCE_NO_WOL_FLAG;
72143c2aeb0SSepherosa Ziehau 		if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708) {
72243c2aeb0SSepherosa Ziehau 			sc->bce_phy_addr = 2;
72343c2aeb0SSepherosa Ziehau 			val = REG_RD_IND(sc, sc->bce_shmem_base +
72443c2aeb0SSepherosa Ziehau 					 BCE_SHARED_HW_CFG_CONFIG);
72543c2aeb0SSepherosa Ziehau 			if (val & BCE_SHARED_HW_CFG_PHY_2_5G)
72643c2aeb0SSepherosa Ziehau 				sc->bce_phy_flags |= BCE_PHY_2_5G_CAPABLE_FLAG;
72743c2aeb0SSepherosa Ziehau 		}
72843c2aeb0SSepherosa Ziehau 	}
72943c2aeb0SSepherosa Ziehau 
73043c2aeb0SSepherosa Ziehau 	/* Allocate DMA memory resources. */
73143c2aeb0SSepherosa Ziehau 	rc = bce_dma_alloc(sc);
73243c2aeb0SSepherosa Ziehau 	if (rc != 0) {
73343c2aeb0SSepherosa Ziehau 		device_printf(dev, "DMA resource allocation failed!\n");
73443c2aeb0SSepherosa Ziehau 		goto fail;
73543c2aeb0SSepherosa Ziehau 	}
73643c2aeb0SSepherosa Ziehau 
73743c2aeb0SSepherosa Ziehau 	/* Initialize the ifnet interface. */
73843c2aeb0SSepherosa Ziehau 	ifp->if_softc = sc;
73943c2aeb0SSepherosa Ziehau 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
74043c2aeb0SSepherosa Ziehau 	ifp->if_ioctl = bce_ioctl;
74143c2aeb0SSepherosa Ziehau 	ifp->if_start = bce_start;
74243c2aeb0SSepherosa Ziehau 	ifp->if_init = bce_init;
74343c2aeb0SSepherosa Ziehau 	ifp->if_watchdog = bce_watchdog;
74443c2aeb0SSepherosa Ziehau #ifdef DEVICE_POLLING
74543c2aeb0SSepherosa Ziehau 	ifp->if_poll = bce_poll;
74643c2aeb0SSepherosa Ziehau #endif
74743c2aeb0SSepherosa Ziehau 	ifp->if_mtu = ETHERMTU;
74843c2aeb0SSepherosa Ziehau 	ifp->if_hwassist = BCE_IF_HWASSIST;
74943c2aeb0SSepherosa Ziehau 	ifp->if_capabilities = BCE_IF_CAPABILITIES;
75043c2aeb0SSepherosa Ziehau 	ifp->if_capenable = ifp->if_capabilities;
75143c2aeb0SSepherosa Ziehau 	ifq_set_maxlen(&ifp->if_snd, USABLE_TX_BD);
75243c2aeb0SSepherosa Ziehau 	ifq_set_ready(&ifp->if_snd);
75343c2aeb0SSepherosa Ziehau 
75443c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)
75543c2aeb0SSepherosa Ziehau 		ifp->if_baudrate = IF_Gbps(2.5);
75643c2aeb0SSepherosa Ziehau 	else
75743c2aeb0SSepherosa Ziehau 		ifp->if_baudrate = IF_Gbps(1);
75843c2aeb0SSepherosa Ziehau 
75943c2aeb0SSepherosa Ziehau 	/* Assume a standard 1500 byte MTU size for mbuf allocations. */
76043c2aeb0SSepherosa Ziehau 	sc->mbuf_alloc_size  = MCLBYTES;
76143c2aeb0SSepherosa Ziehau 
76243c2aeb0SSepherosa Ziehau 	/* Look for our PHY. */
76343c2aeb0SSepherosa Ziehau 	rc = mii_phy_probe(dev, &sc->bce_miibus,
76443c2aeb0SSepherosa Ziehau 			   bce_ifmedia_upd, bce_ifmedia_sts);
76543c2aeb0SSepherosa Ziehau 	if (rc != 0) {
76643c2aeb0SSepherosa Ziehau 		device_printf(dev, "PHY probe failed!\n");
76743c2aeb0SSepherosa Ziehau 		goto fail;
76843c2aeb0SSepherosa Ziehau 	}
76943c2aeb0SSepherosa Ziehau 
77043c2aeb0SSepherosa Ziehau 	/* Attach to the Ethernet interface list. */
77143c2aeb0SSepherosa Ziehau 	ether_ifattach(ifp, sc->eaddr, NULL);
77243c2aeb0SSepherosa Ziehau 
77343c2aeb0SSepherosa Ziehau 	callout_init(&sc->bce_stat_ch);
77443c2aeb0SSepherosa Ziehau 
77543c2aeb0SSepherosa Ziehau 	/* Hookup IRQ last. */
77695893fe4SSepherosa Ziehau 	rc = bus_setup_intr(dev, sc->bce_res_irq, INTR_MPSAFE, bce_intr, sc,
77743c2aeb0SSepherosa Ziehau 			    &sc->bce_intrhand, ifp->if_serializer);
77843c2aeb0SSepherosa Ziehau 	if (rc != 0) {
77943c2aeb0SSepherosa Ziehau 		device_printf(dev, "Failed to setup IRQ!\n");
78043c2aeb0SSepherosa Ziehau 		ether_ifdetach(ifp);
78143c2aeb0SSepherosa Ziehau 		goto fail;
78243c2aeb0SSepherosa Ziehau 	}
78343c2aeb0SSepherosa Ziehau 
7849db4b353SSepherosa Ziehau 	ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->bce_res_irq));
7859db4b353SSepherosa Ziehau 	KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus);
7869db4b353SSepherosa Ziehau 
78743c2aeb0SSepherosa Ziehau 	/* Print some important debugging info. */
78843c2aeb0SSepherosa Ziehau 	DBRUN(BCE_INFO, bce_dump_driver_state(sc));
78943c2aeb0SSepherosa Ziehau 
79043c2aeb0SSepherosa Ziehau 	/* Add the supported sysctls to the kernel. */
79143c2aeb0SSepherosa Ziehau 	bce_add_sysctls(sc);
79243c2aeb0SSepherosa Ziehau 
79343c2aeb0SSepherosa Ziehau 	/* Get the firmware running so IPMI still works */
79443c2aeb0SSepherosa Ziehau 	bce_mgmt_init(sc);
79543c2aeb0SSepherosa Ziehau 
79643c2aeb0SSepherosa Ziehau 	return 0;
79743c2aeb0SSepherosa Ziehau fail:
79843c2aeb0SSepherosa Ziehau 	bce_detach(dev);
79943c2aeb0SSepherosa Ziehau 	return(rc);
80043c2aeb0SSepherosa Ziehau }
80143c2aeb0SSepherosa Ziehau 
80243c2aeb0SSepherosa Ziehau 
80343c2aeb0SSepherosa Ziehau /****************************************************************************/
80443c2aeb0SSepherosa Ziehau /* Device detach function.                                                  */
80543c2aeb0SSepherosa Ziehau /*                                                                          */
80643c2aeb0SSepherosa Ziehau /* Stops the controller, resets the controller, and releases resources.     */
80743c2aeb0SSepherosa Ziehau /*                                                                          */
80843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
80943c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
81043c2aeb0SSepherosa Ziehau /****************************************************************************/
81143c2aeb0SSepherosa Ziehau static int
81243c2aeb0SSepherosa Ziehau bce_detach(device_t dev)
81343c2aeb0SSepherosa Ziehau {
81443c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
81543c2aeb0SSepherosa Ziehau 
81643c2aeb0SSepherosa Ziehau 	if (device_is_attached(dev)) {
81743c2aeb0SSepherosa Ziehau 		struct ifnet *ifp = &sc->arpcom.ac_if;
81843c2aeb0SSepherosa Ziehau 
81943c2aeb0SSepherosa Ziehau 		/* Stop and reset the controller. */
82043c2aeb0SSepherosa Ziehau 		lwkt_serialize_enter(ifp->if_serializer);
82143c2aeb0SSepherosa Ziehau 		bce_stop(sc);
82243c2aeb0SSepherosa Ziehau 		bce_reset(sc, BCE_DRV_MSG_CODE_RESET);
82343c2aeb0SSepherosa Ziehau 		bus_teardown_intr(dev, sc->bce_res_irq, sc->bce_intrhand);
82443c2aeb0SSepherosa Ziehau 		lwkt_serialize_exit(ifp->if_serializer);
82543c2aeb0SSepherosa Ziehau 
82643c2aeb0SSepherosa Ziehau 		ether_ifdetach(ifp);
82743c2aeb0SSepherosa Ziehau 	}
82843c2aeb0SSepherosa Ziehau 
82943c2aeb0SSepherosa Ziehau 	/* If we have a child device on the MII bus remove it too. */
83043c2aeb0SSepherosa Ziehau 	if (sc->bce_miibus)
83143c2aeb0SSepherosa Ziehau 		device_delete_child(dev, sc->bce_miibus);
83243c2aeb0SSepherosa Ziehau 	bus_generic_detach(dev);
83343c2aeb0SSepherosa Ziehau 
83443c2aeb0SSepherosa Ziehau 	if (sc->bce_res_irq != NULL) {
83543c2aeb0SSepherosa Ziehau 		bus_release_resource(dev, SYS_RES_IRQ,
83643c2aeb0SSepherosa Ziehau 			sc->bce_flags & BCE_USING_MSI_FLAG ? 1 : 0,
83743c2aeb0SSepherosa Ziehau 			sc->bce_res_irq);
83843c2aeb0SSepherosa Ziehau 	}
83943c2aeb0SSepherosa Ziehau 
84043c2aeb0SSepherosa Ziehau #ifdef notyet
84143c2aeb0SSepherosa Ziehau 	if (sc->bce_flags & BCE_USING_MSI_FLAG)
84243c2aeb0SSepherosa Ziehau 		pci_release_msi(dev);
84343c2aeb0SSepherosa Ziehau #endif
84443c2aeb0SSepherosa Ziehau 
84543c2aeb0SSepherosa Ziehau 	if (sc->bce_res_mem != NULL) {
84643c2aeb0SSepherosa Ziehau 		bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
84743c2aeb0SSepherosa Ziehau 				     sc->bce_res_mem);
84843c2aeb0SSepherosa Ziehau 	}
84943c2aeb0SSepherosa Ziehau 
85043c2aeb0SSepherosa Ziehau 	bce_dma_free(sc);
85143c2aeb0SSepherosa Ziehau 
85243c2aeb0SSepherosa Ziehau 	if (sc->bce_sysctl_tree != NULL)
85343c2aeb0SSepherosa Ziehau 		sysctl_ctx_free(&sc->bce_sysctl_ctx);
85443c2aeb0SSepherosa Ziehau 
85543c2aeb0SSepherosa Ziehau 	return 0;
85643c2aeb0SSepherosa Ziehau }
85743c2aeb0SSepherosa Ziehau 
85843c2aeb0SSepherosa Ziehau 
85943c2aeb0SSepherosa Ziehau /****************************************************************************/
86043c2aeb0SSepherosa Ziehau /* Device shutdown function.                                                */
86143c2aeb0SSepherosa Ziehau /*                                                                          */
86243c2aeb0SSepherosa Ziehau /* Stops and resets the controller.                                         */
86343c2aeb0SSepherosa Ziehau /*                                                                          */
86443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
86543c2aeb0SSepherosa Ziehau /*   Nothing                                                                */
86643c2aeb0SSepherosa Ziehau /****************************************************************************/
86743c2aeb0SSepherosa Ziehau static void
86843c2aeb0SSepherosa Ziehau bce_shutdown(device_t dev)
86943c2aeb0SSepherosa Ziehau {
87043c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
87143c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
87243c2aeb0SSepherosa Ziehau 
87343c2aeb0SSepherosa Ziehau 	lwkt_serialize_enter(ifp->if_serializer);
87443c2aeb0SSepherosa Ziehau 	bce_stop(sc);
87543c2aeb0SSepherosa Ziehau 	bce_reset(sc, BCE_DRV_MSG_CODE_RESET);
87643c2aeb0SSepherosa Ziehau 	lwkt_serialize_exit(ifp->if_serializer);
87743c2aeb0SSepherosa Ziehau }
87843c2aeb0SSepherosa Ziehau 
87943c2aeb0SSepherosa Ziehau 
88043c2aeb0SSepherosa Ziehau /****************************************************************************/
88143c2aeb0SSepherosa Ziehau /* Indirect register read.                                                  */
88243c2aeb0SSepherosa Ziehau /*                                                                          */
88343c2aeb0SSepherosa Ziehau /* Reads NetXtreme II registers using an index/data register pair in PCI    */
88443c2aeb0SSepherosa Ziehau /* configuration space.  Using this mechanism avoids issues with posted     */
88543c2aeb0SSepherosa Ziehau /* reads but is much slower than memory-mapped I/O.                         */
88643c2aeb0SSepherosa Ziehau /*                                                                          */
88743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
88843c2aeb0SSepherosa Ziehau /*   The value of the register.                                             */
88943c2aeb0SSepherosa Ziehau /****************************************************************************/
89043c2aeb0SSepherosa Ziehau static uint32_t
89143c2aeb0SSepherosa Ziehau bce_reg_rd_ind(struct bce_softc *sc, uint32_t offset)
89243c2aeb0SSepherosa Ziehau {
89343c2aeb0SSepherosa Ziehau 	device_t dev = sc->bce_dev;
89443c2aeb0SSepherosa Ziehau 
89543c2aeb0SSepherosa Ziehau 	pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4);
89643c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
89743c2aeb0SSepherosa Ziehau 	{
89843c2aeb0SSepherosa Ziehau 		uint32_t val;
89943c2aeb0SSepherosa Ziehau 		val = pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4);
90043c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_EXCESSIVE,
90143c2aeb0SSepherosa Ziehau 			"%s(); offset = 0x%08X, val = 0x%08X\n",
90243c2aeb0SSepherosa Ziehau 			__func__, offset, val);
90343c2aeb0SSepherosa Ziehau 		return val;
90443c2aeb0SSepherosa Ziehau 	}
90543c2aeb0SSepherosa Ziehau #else
90643c2aeb0SSepherosa Ziehau 	return pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4);
90743c2aeb0SSepherosa Ziehau #endif
90843c2aeb0SSepherosa Ziehau }
90943c2aeb0SSepherosa Ziehau 
91043c2aeb0SSepherosa Ziehau 
91143c2aeb0SSepherosa Ziehau /****************************************************************************/
91243c2aeb0SSepherosa Ziehau /* Indirect register write.                                                 */
91343c2aeb0SSepherosa Ziehau /*                                                                          */
91443c2aeb0SSepherosa Ziehau /* Writes NetXtreme II registers using an index/data register pair in PCI   */
91543c2aeb0SSepherosa Ziehau /* configuration space.  Using this mechanism avoids issues with posted     */
91643c2aeb0SSepherosa Ziehau /* writes but is muchh slower than memory-mapped I/O.                       */
91743c2aeb0SSepherosa Ziehau /*                                                                          */
91843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
91943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
92043c2aeb0SSepherosa Ziehau /****************************************************************************/
92143c2aeb0SSepherosa Ziehau static void
92243c2aeb0SSepherosa Ziehau bce_reg_wr_ind(struct bce_softc *sc, uint32_t offset, uint32_t val)
92343c2aeb0SSepherosa Ziehau {
92443c2aeb0SSepherosa Ziehau 	device_t dev = sc->bce_dev;
92543c2aeb0SSepherosa Ziehau 
92643c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n",
92743c2aeb0SSepherosa Ziehau 		__func__, offset, val);
92843c2aeb0SSepherosa Ziehau 
92943c2aeb0SSepherosa Ziehau 	pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4);
93043c2aeb0SSepherosa Ziehau 	pci_write_config(dev, BCE_PCICFG_REG_WINDOW, val, 4);
93143c2aeb0SSepherosa Ziehau }
93243c2aeb0SSepherosa Ziehau 
93343c2aeb0SSepherosa Ziehau 
93443c2aeb0SSepherosa Ziehau /****************************************************************************/
93543c2aeb0SSepherosa Ziehau /* Context memory write.                                                    */
93643c2aeb0SSepherosa Ziehau /*                                                                          */
93743c2aeb0SSepherosa Ziehau /* The NetXtreme II controller uses context memory to track connection      */
93843c2aeb0SSepherosa Ziehau /* information for L2 and higher network protocols.                         */
93943c2aeb0SSepherosa Ziehau /*                                                                          */
94043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
94143c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
94243c2aeb0SSepherosa Ziehau /****************************************************************************/
94343c2aeb0SSepherosa Ziehau static void
94443c2aeb0SSepherosa Ziehau bce_ctx_wr(struct bce_softc *sc, uint32_t cid_addr, uint32_t offset,
94543c2aeb0SSepherosa Ziehau 	   uint32_t val)
94643c2aeb0SSepherosa Ziehau {
94743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE, "%s(); cid_addr = 0x%08X, offset = 0x%08X, "
94843c2aeb0SSepherosa Ziehau 		"val = 0x%08X\n", __func__, cid_addr, offset, val);
94943c2aeb0SSepherosa Ziehau 
95043c2aeb0SSepherosa Ziehau 	offset += cid_addr;
95143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_CTX_DATA_ADR, offset);
95243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_CTX_DATA, val);
95343c2aeb0SSepherosa Ziehau }
95443c2aeb0SSepherosa Ziehau 
95543c2aeb0SSepherosa Ziehau 
95643c2aeb0SSepherosa Ziehau /****************************************************************************/
95743c2aeb0SSepherosa Ziehau /* PHY register read.                                                       */
95843c2aeb0SSepherosa Ziehau /*                                                                          */
95943c2aeb0SSepherosa Ziehau /* Implements register reads on the MII bus.                                */
96043c2aeb0SSepherosa Ziehau /*                                                                          */
96143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
96243c2aeb0SSepherosa Ziehau /*   The value of the register.                                             */
96343c2aeb0SSepherosa Ziehau /****************************************************************************/
96443c2aeb0SSepherosa Ziehau static int
96543c2aeb0SSepherosa Ziehau bce_miibus_read_reg(device_t dev, int phy, int reg)
96643c2aeb0SSepherosa Ziehau {
96743c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
96843c2aeb0SSepherosa Ziehau 	uint32_t val;
96943c2aeb0SSepherosa Ziehau 	int i;
97043c2aeb0SSepherosa Ziehau 
97143c2aeb0SSepherosa Ziehau 	/* Make sure we are accessing the correct PHY address. */
97243c2aeb0SSepherosa Ziehau 	if (phy != sc->bce_phy_addr) {
97343c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE,
97443c2aeb0SSepherosa Ziehau 			"Invalid PHY address %d for PHY read!\n", phy);
97543c2aeb0SSepherosa Ziehau 		return 0;
97643c2aeb0SSepherosa Ziehau 	}
97743c2aeb0SSepherosa Ziehau 
97843c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
97943c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_EMAC_MDIO_MODE);
98043c2aeb0SSepherosa Ziehau 		val &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL;
98143c2aeb0SSepherosa Ziehau 
98243c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_MDIO_MODE, val);
98343c2aeb0SSepherosa Ziehau 		REG_RD(sc, BCE_EMAC_MDIO_MODE);
98443c2aeb0SSepherosa Ziehau 
98543c2aeb0SSepherosa Ziehau 		DELAY(40);
98643c2aeb0SSepherosa Ziehau 	}
98743c2aeb0SSepherosa Ziehau 
98843c2aeb0SSepherosa Ziehau 	val = BCE_MIPHY(phy) | BCE_MIREG(reg) |
98943c2aeb0SSepherosa Ziehau 	      BCE_EMAC_MDIO_COMM_COMMAND_READ | BCE_EMAC_MDIO_COMM_DISEXT |
99043c2aeb0SSepherosa Ziehau 	      BCE_EMAC_MDIO_COMM_START_BUSY;
99143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_MDIO_COMM, val);
99243c2aeb0SSepherosa Ziehau 
99343c2aeb0SSepherosa Ziehau 	for (i = 0; i < BCE_PHY_TIMEOUT; i++) {
99443c2aeb0SSepherosa Ziehau 		DELAY(10);
99543c2aeb0SSepherosa Ziehau 
99643c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_EMAC_MDIO_COMM);
99743c2aeb0SSepherosa Ziehau 		if (!(val & BCE_EMAC_MDIO_COMM_START_BUSY)) {
99843c2aeb0SSepherosa Ziehau 			DELAY(5);
99943c2aeb0SSepherosa Ziehau 
100043c2aeb0SSepherosa Ziehau 			val = REG_RD(sc, BCE_EMAC_MDIO_COMM);
100143c2aeb0SSepherosa Ziehau 			val &= BCE_EMAC_MDIO_COMM_DATA;
100243c2aeb0SSepherosa Ziehau 			break;
100343c2aeb0SSepherosa Ziehau 		}
100443c2aeb0SSepherosa Ziehau 	}
100543c2aeb0SSepherosa Ziehau 
100643c2aeb0SSepherosa Ziehau 	if (val & BCE_EMAC_MDIO_COMM_START_BUSY) {
100743c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
100843c2aeb0SSepherosa Ziehau 			  "Error: PHY read timeout! phy = %d, reg = 0x%04X\n",
100943c2aeb0SSepherosa Ziehau 			  phy, reg);
101043c2aeb0SSepherosa Ziehau 		val = 0x0;
101143c2aeb0SSepherosa Ziehau 	} else {
101243c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_EMAC_MDIO_COMM);
101343c2aeb0SSepherosa Ziehau 	}
101443c2aeb0SSepherosa Ziehau 
101543c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE,
101643c2aeb0SSepherosa Ziehau 		"%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n",
101743c2aeb0SSepherosa Ziehau 		__func__, phy, (uint16_t)reg & 0xffff, (uint16_t) val & 0xffff);
101843c2aeb0SSepherosa Ziehau 
101943c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
102043c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_EMAC_MDIO_MODE);
102143c2aeb0SSepherosa Ziehau 		val |= BCE_EMAC_MDIO_MODE_AUTO_POLL;
102243c2aeb0SSepherosa Ziehau 
102343c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_MDIO_MODE, val);
102443c2aeb0SSepherosa Ziehau 		REG_RD(sc, BCE_EMAC_MDIO_MODE);
102543c2aeb0SSepherosa Ziehau 
102643c2aeb0SSepherosa Ziehau 		DELAY(40);
102743c2aeb0SSepherosa Ziehau 	}
102843c2aeb0SSepherosa Ziehau 	return (val & 0xffff);
102943c2aeb0SSepherosa Ziehau }
103043c2aeb0SSepherosa Ziehau 
103143c2aeb0SSepherosa Ziehau 
103243c2aeb0SSepherosa Ziehau /****************************************************************************/
103343c2aeb0SSepherosa Ziehau /* PHY register write.                                                      */
103443c2aeb0SSepherosa Ziehau /*                                                                          */
103543c2aeb0SSepherosa Ziehau /* Implements register writes on the MII bus.                               */
103643c2aeb0SSepherosa Ziehau /*                                                                          */
103743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
103843c2aeb0SSepherosa Ziehau /*   The value of the register.                                             */
103943c2aeb0SSepherosa Ziehau /****************************************************************************/
104043c2aeb0SSepherosa Ziehau static int
104143c2aeb0SSepherosa Ziehau bce_miibus_write_reg(device_t dev, int phy, int reg, int val)
104243c2aeb0SSepherosa Ziehau {
104343c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
104443c2aeb0SSepherosa Ziehau 	uint32_t val1;
104543c2aeb0SSepherosa Ziehau 	int i;
104643c2aeb0SSepherosa Ziehau 
104743c2aeb0SSepherosa Ziehau 	/* Make sure we are accessing the correct PHY address. */
104843c2aeb0SSepherosa Ziehau 	if (phy != sc->bce_phy_addr) {
104943c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_WARN,
105043c2aeb0SSepherosa Ziehau 			"Invalid PHY address %d for PHY write!\n", phy);
105143c2aeb0SSepherosa Ziehau 		return(0);
105243c2aeb0SSepherosa Ziehau 	}
105343c2aeb0SSepherosa Ziehau 
105443c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE,
105543c2aeb0SSepherosa Ziehau 		"%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n",
105643c2aeb0SSepherosa Ziehau 		__func__, phy, (uint16_t)(reg & 0xffff),
105743c2aeb0SSepherosa Ziehau 		(uint16_t)(val & 0xffff));
105843c2aeb0SSepherosa Ziehau 
105943c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
106043c2aeb0SSepherosa Ziehau 		val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE);
106143c2aeb0SSepherosa Ziehau 		val1 &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL;
106243c2aeb0SSepherosa Ziehau 
106343c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_MDIO_MODE, val1);
106443c2aeb0SSepherosa Ziehau 		REG_RD(sc, BCE_EMAC_MDIO_MODE);
106543c2aeb0SSepherosa Ziehau 
106643c2aeb0SSepherosa Ziehau 		DELAY(40);
106743c2aeb0SSepherosa Ziehau 	}
106843c2aeb0SSepherosa Ziehau 
106943c2aeb0SSepherosa Ziehau 	val1 = BCE_MIPHY(phy) | BCE_MIREG(reg) | val |
107043c2aeb0SSepherosa Ziehau 		BCE_EMAC_MDIO_COMM_COMMAND_WRITE |
107143c2aeb0SSepherosa Ziehau 		BCE_EMAC_MDIO_COMM_START_BUSY | BCE_EMAC_MDIO_COMM_DISEXT;
107243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_MDIO_COMM, val1);
107343c2aeb0SSepherosa Ziehau 
107443c2aeb0SSepherosa Ziehau 	for (i = 0; i < BCE_PHY_TIMEOUT; i++) {
107543c2aeb0SSepherosa Ziehau 		DELAY(10);
107643c2aeb0SSepherosa Ziehau 
107743c2aeb0SSepherosa Ziehau 		val1 = REG_RD(sc, BCE_EMAC_MDIO_COMM);
107843c2aeb0SSepherosa Ziehau 		if (!(val1 & BCE_EMAC_MDIO_COMM_START_BUSY)) {
107943c2aeb0SSepherosa Ziehau 			DELAY(5);
108043c2aeb0SSepherosa Ziehau 			break;
108143c2aeb0SSepherosa Ziehau 		}
108243c2aeb0SSepherosa Ziehau 	}
108343c2aeb0SSepherosa Ziehau 
108443c2aeb0SSepherosa Ziehau 	if (val1 & BCE_EMAC_MDIO_COMM_START_BUSY)
108543c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "PHY write timeout!\n");
108643c2aeb0SSepherosa Ziehau 
108743c2aeb0SSepherosa Ziehau 	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
108843c2aeb0SSepherosa Ziehau 		val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE);
108943c2aeb0SSepherosa Ziehau 		val1 |= BCE_EMAC_MDIO_MODE_AUTO_POLL;
109043c2aeb0SSepherosa Ziehau 
109143c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_MDIO_MODE, val1);
109243c2aeb0SSepherosa Ziehau 		REG_RD(sc, BCE_EMAC_MDIO_MODE);
109343c2aeb0SSepherosa Ziehau 
109443c2aeb0SSepherosa Ziehau 		DELAY(40);
109543c2aeb0SSepherosa Ziehau 	}
109643c2aeb0SSepherosa Ziehau 	return 0;
109743c2aeb0SSepherosa Ziehau }
109843c2aeb0SSepherosa Ziehau 
109943c2aeb0SSepherosa Ziehau 
110043c2aeb0SSepherosa Ziehau /****************************************************************************/
110143c2aeb0SSepherosa Ziehau /* MII bus status change.                                                   */
110243c2aeb0SSepherosa Ziehau /*                                                                          */
110343c2aeb0SSepherosa Ziehau /* Called by the MII bus driver when the PHY establishes link to set the    */
110443c2aeb0SSepherosa Ziehau /* MAC interface registers.                                                 */
110543c2aeb0SSepherosa Ziehau /*                                                                          */
110643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
110743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
110843c2aeb0SSepherosa Ziehau /****************************************************************************/
110943c2aeb0SSepherosa Ziehau static void
111043c2aeb0SSepherosa Ziehau bce_miibus_statchg(device_t dev)
111143c2aeb0SSepherosa Ziehau {
111243c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = device_get_softc(dev);
111343c2aeb0SSepherosa Ziehau 	struct mii_data *mii = device_get_softc(sc->bce_miibus);
111443c2aeb0SSepherosa Ziehau 
111543c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "mii_media_active = 0x%08X\n",
111643c2aeb0SSepherosa Ziehau 		mii->mii_media_active);
111743c2aeb0SSepherosa Ziehau 
111843c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
111943c2aeb0SSepherosa Ziehau 	/* Decode the interface media flags. */
112043c2aeb0SSepherosa Ziehau 	if_printf(&sc->arpcom.ac_if, "Media: ( ");
112143c2aeb0SSepherosa Ziehau 	switch(IFM_TYPE(mii->mii_media_active)) {
112243c2aeb0SSepherosa Ziehau 	case IFM_ETHER:
112343c2aeb0SSepherosa Ziehau 		kprintf("Ethernet )");
112443c2aeb0SSepherosa Ziehau 		break;
112543c2aeb0SSepherosa Ziehau 	default:
112643c2aeb0SSepherosa Ziehau 		kprintf("Unknown )");
112743c2aeb0SSepherosa Ziehau 		break;
112843c2aeb0SSepherosa Ziehau 	}
112943c2aeb0SSepherosa Ziehau 
113043c2aeb0SSepherosa Ziehau 	kprintf(" Media Options: ( ");
113143c2aeb0SSepherosa Ziehau 	switch(IFM_SUBTYPE(mii->mii_media_active)) {
113243c2aeb0SSepherosa Ziehau 	case IFM_AUTO:
113343c2aeb0SSepherosa Ziehau 		kprintf("Autoselect )");
113443c2aeb0SSepherosa Ziehau 		break;
113543c2aeb0SSepherosa Ziehau 	case IFM_MANUAL:
113643c2aeb0SSepherosa Ziehau 		kprintf("Manual )");
113743c2aeb0SSepherosa Ziehau 		break;
113843c2aeb0SSepherosa Ziehau 	case IFM_NONE:
113943c2aeb0SSepherosa Ziehau 		kprintf("None )");
114043c2aeb0SSepherosa Ziehau 		break;
114143c2aeb0SSepherosa Ziehau 	case IFM_10_T:
114243c2aeb0SSepherosa Ziehau 		kprintf("10Base-T )");
114343c2aeb0SSepherosa Ziehau 		break;
114443c2aeb0SSepherosa Ziehau 	case IFM_100_TX:
114543c2aeb0SSepherosa Ziehau 		kprintf("100Base-TX )");
114643c2aeb0SSepherosa Ziehau 		break;
114743c2aeb0SSepherosa Ziehau 	case IFM_1000_SX:
114843c2aeb0SSepherosa Ziehau 		kprintf("1000Base-SX )");
114943c2aeb0SSepherosa Ziehau 		break;
115043c2aeb0SSepherosa Ziehau 	case IFM_1000_T:
115143c2aeb0SSepherosa Ziehau 		kprintf("1000Base-T )");
115243c2aeb0SSepherosa Ziehau 		break;
115343c2aeb0SSepherosa Ziehau 	default:
115443c2aeb0SSepherosa Ziehau 		kprintf("Other )");
115543c2aeb0SSepherosa Ziehau 		break;
115643c2aeb0SSepherosa Ziehau 	}
115743c2aeb0SSepherosa Ziehau 
115843c2aeb0SSepherosa Ziehau 	kprintf(" Global Options: (");
115943c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_FDX)
116043c2aeb0SSepherosa Ziehau 		kprintf(" FullDuplex");
116143c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_HDX)
116243c2aeb0SSepherosa Ziehau 		kprintf(" HalfDuplex");
116343c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_LOOP)
116443c2aeb0SSepherosa Ziehau 		kprintf(" Loopback");
116543c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_FLAG0)
116643c2aeb0SSepherosa Ziehau 		kprintf(" Flag0");
116743c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_FLAG1)
116843c2aeb0SSepherosa Ziehau 		kprintf(" Flag1");
116943c2aeb0SSepherosa Ziehau 	if (mii->mii_media_active & IFM_FLAG2)
117043c2aeb0SSepherosa Ziehau 		kprintf(" Flag2");
117143c2aeb0SSepherosa Ziehau 	kprintf(" )\n");
117243c2aeb0SSepherosa Ziehau #endif
117343c2aeb0SSepherosa Ziehau 
117443c2aeb0SSepherosa Ziehau 	BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT);
117543c2aeb0SSepherosa Ziehau 
117643c2aeb0SSepherosa Ziehau 	/*
117743c2aeb0SSepherosa Ziehau 	 * Set MII or GMII interface based on the speed negotiated
117843c2aeb0SSepherosa Ziehau 	 * by the PHY.
117943c2aeb0SSepherosa Ziehau 	 */
118043c2aeb0SSepherosa Ziehau 	if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
118143c2aeb0SSepherosa Ziehau 	    IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) {
118243c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting GMII interface.\n");
118343c2aeb0SSepherosa Ziehau 		BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_GMII);
118443c2aeb0SSepherosa Ziehau 	} else {
118543c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting MII interface.\n");
118643c2aeb0SSepherosa Ziehau 		BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_MII);
118743c2aeb0SSepherosa Ziehau 	}
118843c2aeb0SSepherosa Ziehau 
118943c2aeb0SSepherosa Ziehau 	/*
119043c2aeb0SSepherosa Ziehau 	 * Set half or full duplex based on the duplicity negotiated
119143c2aeb0SSepherosa Ziehau 	 * by the PHY.
119243c2aeb0SSepherosa Ziehau 	 */
119343c2aeb0SSepherosa Ziehau 	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
119443c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting Full-Duplex interface.\n");
119543c2aeb0SSepherosa Ziehau 		BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX);
119643c2aeb0SSepherosa Ziehau 	} else {
119743c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting Half-Duplex interface.\n");
119843c2aeb0SSepherosa Ziehau 		BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX);
119943c2aeb0SSepherosa Ziehau 	}
120043c2aeb0SSepherosa Ziehau }
120143c2aeb0SSepherosa Ziehau 
120243c2aeb0SSepherosa Ziehau 
120343c2aeb0SSepherosa Ziehau /****************************************************************************/
120443c2aeb0SSepherosa Ziehau /* Acquire NVRAM lock.                                                      */
120543c2aeb0SSepherosa Ziehau /*                                                                          */
120643c2aeb0SSepherosa Ziehau /* Before the NVRAM can be accessed the caller must acquire an NVRAM lock.  */
120743c2aeb0SSepherosa Ziehau /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is     */
120843c2aeb0SSepherosa Ziehau /* for use by the driver.                                                   */
120943c2aeb0SSepherosa Ziehau /*                                                                          */
121043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
121143c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
121243c2aeb0SSepherosa Ziehau /****************************************************************************/
121343c2aeb0SSepherosa Ziehau static int
121443c2aeb0SSepherosa Ziehau bce_acquire_nvram_lock(struct bce_softc *sc)
121543c2aeb0SSepherosa Ziehau {
121643c2aeb0SSepherosa Ziehau 	uint32_t val;
121743c2aeb0SSepherosa Ziehau 	int j;
121843c2aeb0SSepherosa Ziehau 
121943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Acquiring NVRAM lock.\n");
122043c2aeb0SSepherosa Ziehau 
122143c2aeb0SSepherosa Ziehau 	/* Request access to the flash interface. */
122243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_SET2);
122343c2aeb0SSepherosa Ziehau 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
122443c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_NVM_SW_ARB);
122543c2aeb0SSepherosa Ziehau 		if (val & BCE_NVM_SW_ARB_ARB_ARB2)
122643c2aeb0SSepherosa Ziehau 			break;
122743c2aeb0SSepherosa Ziehau 
122843c2aeb0SSepherosa Ziehau 		DELAY(5);
122943c2aeb0SSepherosa Ziehau 	}
123043c2aeb0SSepherosa Ziehau 
123143c2aeb0SSepherosa Ziehau 	if (j >= NVRAM_TIMEOUT_COUNT) {
123243c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_WARN, "Timeout acquiring NVRAM lock!\n");
123343c2aeb0SSepherosa Ziehau 		return EBUSY;
123443c2aeb0SSepherosa Ziehau 	}
123543c2aeb0SSepherosa Ziehau 	return 0;
123643c2aeb0SSepherosa Ziehau }
123743c2aeb0SSepherosa Ziehau 
123843c2aeb0SSepherosa Ziehau 
123943c2aeb0SSepherosa Ziehau /****************************************************************************/
124043c2aeb0SSepherosa Ziehau /* Release NVRAM lock.                                                      */
124143c2aeb0SSepherosa Ziehau /*                                                                          */
124243c2aeb0SSepherosa Ziehau /* When the caller is finished accessing NVRAM the lock must be released.   */
124343c2aeb0SSepherosa Ziehau /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is     */
124443c2aeb0SSepherosa Ziehau /* for use by the driver.                                                   */
124543c2aeb0SSepherosa Ziehau /*                                                                          */
124643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
124743c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
124843c2aeb0SSepherosa Ziehau /****************************************************************************/
124943c2aeb0SSepherosa Ziehau static int
125043c2aeb0SSepherosa Ziehau bce_release_nvram_lock(struct bce_softc *sc)
125143c2aeb0SSepherosa Ziehau {
125243c2aeb0SSepherosa Ziehau 	int j;
125343c2aeb0SSepherosa Ziehau 	uint32_t val;
125443c2aeb0SSepherosa Ziehau 
125543c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Releasing NVRAM lock.\n");
125643c2aeb0SSepherosa Ziehau 
125743c2aeb0SSepherosa Ziehau 	/*
125843c2aeb0SSepherosa Ziehau 	 * Relinquish nvram interface.
125943c2aeb0SSepherosa Ziehau 	 */
126043c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_CLR2);
126143c2aeb0SSepherosa Ziehau 
126243c2aeb0SSepherosa Ziehau 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
126343c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_NVM_SW_ARB);
126443c2aeb0SSepherosa Ziehau 		if (!(val & BCE_NVM_SW_ARB_ARB_ARB2))
126543c2aeb0SSepherosa Ziehau 			break;
126643c2aeb0SSepherosa Ziehau 
126743c2aeb0SSepherosa Ziehau 		DELAY(5);
126843c2aeb0SSepherosa Ziehau 	}
126943c2aeb0SSepherosa Ziehau 
127043c2aeb0SSepherosa Ziehau 	if (j >= NVRAM_TIMEOUT_COUNT) {
127143c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_WARN, "Timeout reeasing NVRAM lock!\n");
127243c2aeb0SSepherosa Ziehau 		return EBUSY;
127343c2aeb0SSepherosa Ziehau 	}
127443c2aeb0SSepherosa Ziehau 	return 0;
127543c2aeb0SSepherosa Ziehau }
127643c2aeb0SSepherosa Ziehau 
127743c2aeb0SSepherosa Ziehau 
127843c2aeb0SSepherosa Ziehau #ifdef BCE_NVRAM_WRITE_SUPPORT
127943c2aeb0SSepherosa Ziehau /****************************************************************************/
128043c2aeb0SSepherosa Ziehau /* Enable NVRAM write access.                                               */
128143c2aeb0SSepherosa Ziehau /*                                                                          */
128243c2aeb0SSepherosa Ziehau /* Before writing to NVRAM the caller must enable NVRAM writes.             */
128343c2aeb0SSepherosa Ziehau /*                                                                          */
128443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
128543c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
128643c2aeb0SSepherosa Ziehau /****************************************************************************/
128743c2aeb0SSepherosa Ziehau static int
128843c2aeb0SSepherosa Ziehau bce_enable_nvram_write(struct bce_softc *sc)
128943c2aeb0SSepherosa Ziehau {
129043c2aeb0SSepherosa Ziehau 	uint32_t val;
129143c2aeb0SSepherosa Ziehau 
129243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Enabling NVRAM write.\n");
129343c2aeb0SSepherosa Ziehau 
129443c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_CFG);
129543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_CFG, val | BCE_MISC_CFG_NVM_WR_EN_PCI);
129643c2aeb0SSepherosa Ziehau 
129743c2aeb0SSepherosa Ziehau 	if (!sc->bce_flash_info->buffered) {
129843c2aeb0SSepherosa Ziehau 		int j;
129943c2aeb0SSepherosa Ziehau 
130043c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE);
130143c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_NVM_COMMAND,
130243c2aeb0SSepherosa Ziehau 		       BCE_NVM_COMMAND_WREN | BCE_NVM_COMMAND_DOIT);
130343c2aeb0SSepherosa Ziehau 
130443c2aeb0SSepherosa Ziehau 		for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
130543c2aeb0SSepherosa Ziehau 			DELAY(5);
130643c2aeb0SSepherosa Ziehau 
130743c2aeb0SSepherosa Ziehau 			val = REG_RD(sc, BCE_NVM_COMMAND);
130843c2aeb0SSepherosa Ziehau 			if (val & BCE_NVM_COMMAND_DONE)
130943c2aeb0SSepherosa Ziehau 				break;
131043c2aeb0SSepherosa Ziehau 		}
131143c2aeb0SSepherosa Ziehau 
131243c2aeb0SSepherosa Ziehau 		if (j >= NVRAM_TIMEOUT_COUNT) {
131343c2aeb0SSepherosa Ziehau 			DBPRINT(sc, BCE_WARN, "Timeout writing NVRAM!\n");
131443c2aeb0SSepherosa Ziehau 			return EBUSY;
131543c2aeb0SSepherosa Ziehau 		}
131643c2aeb0SSepherosa Ziehau 	}
131743c2aeb0SSepherosa Ziehau 	return 0;
131843c2aeb0SSepherosa Ziehau }
131943c2aeb0SSepherosa Ziehau 
132043c2aeb0SSepherosa Ziehau 
132143c2aeb0SSepherosa Ziehau /****************************************************************************/
132243c2aeb0SSepherosa Ziehau /* Disable NVRAM write access.                                              */
132343c2aeb0SSepherosa Ziehau /*                                                                          */
132443c2aeb0SSepherosa Ziehau /* When the caller is finished writing to NVRAM write access must be        */
132543c2aeb0SSepherosa Ziehau /* disabled.                                                                */
132643c2aeb0SSepherosa Ziehau /*                                                                          */
132743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
132843c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
132943c2aeb0SSepherosa Ziehau /****************************************************************************/
133043c2aeb0SSepherosa Ziehau static void
133143c2aeb0SSepherosa Ziehau bce_disable_nvram_write(struct bce_softc *sc)
133243c2aeb0SSepherosa Ziehau {
133343c2aeb0SSepherosa Ziehau 	uint32_t val;
133443c2aeb0SSepherosa Ziehau 
133543c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Disabling NVRAM write.\n");
133643c2aeb0SSepherosa Ziehau 
133743c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_CFG);
133843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_CFG, val & ~BCE_MISC_CFG_NVM_WR_EN);
133943c2aeb0SSepherosa Ziehau }
134043c2aeb0SSepherosa Ziehau #endif	/* BCE_NVRAM_WRITE_SUPPORT */
134143c2aeb0SSepherosa Ziehau 
134243c2aeb0SSepherosa Ziehau 
134343c2aeb0SSepherosa Ziehau /****************************************************************************/
134443c2aeb0SSepherosa Ziehau /* Enable NVRAM access.                                                     */
134543c2aeb0SSepherosa Ziehau /*                                                                          */
134643c2aeb0SSepherosa Ziehau /* Before accessing NVRAM for read or write operations the caller must      */
134743c2aeb0SSepherosa Ziehau /* enabled NVRAM access.                                                    */
134843c2aeb0SSepherosa Ziehau /*                                                                          */
134943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
135043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
135143c2aeb0SSepherosa Ziehau /****************************************************************************/
135243c2aeb0SSepherosa Ziehau static void
135343c2aeb0SSepherosa Ziehau bce_enable_nvram_access(struct bce_softc *sc)
135443c2aeb0SSepherosa Ziehau {
135543c2aeb0SSepherosa Ziehau 	uint32_t val;
135643c2aeb0SSepherosa Ziehau 
135743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Enabling NVRAM access.\n");
135843c2aeb0SSepherosa Ziehau 
135943c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE);
136043c2aeb0SSepherosa Ziehau 	/* Enable both bits, even on read. */
136143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_ACCESS_ENABLE,
136243c2aeb0SSepherosa Ziehau 	       val | BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN);
136343c2aeb0SSepherosa Ziehau }
136443c2aeb0SSepherosa Ziehau 
136543c2aeb0SSepherosa Ziehau 
136643c2aeb0SSepherosa Ziehau /****************************************************************************/
136743c2aeb0SSepherosa Ziehau /* Disable NVRAM access.                                                    */
136843c2aeb0SSepherosa Ziehau /*                                                                          */
136943c2aeb0SSepherosa Ziehau /* When the caller is finished accessing NVRAM access must be disabled.     */
137043c2aeb0SSepherosa Ziehau /*                                                                          */
137143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
137243c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
137343c2aeb0SSepherosa Ziehau /****************************************************************************/
137443c2aeb0SSepherosa Ziehau static void
137543c2aeb0SSepherosa Ziehau bce_disable_nvram_access(struct bce_softc *sc)
137643c2aeb0SSepherosa Ziehau {
137743c2aeb0SSepherosa Ziehau 	uint32_t val;
137843c2aeb0SSepherosa Ziehau 
137943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Disabling NVRAM access.\n");
138043c2aeb0SSepherosa Ziehau 
138143c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE);
138243c2aeb0SSepherosa Ziehau 
138343c2aeb0SSepherosa Ziehau 	/* Disable both bits, even after read. */
138443c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_ACCESS_ENABLE,
138543c2aeb0SSepherosa Ziehau 	       val & ~(BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN));
138643c2aeb0SSepherosa Ziehau }
138743c2aeb0SSepherosa Ziehau 
138843c2aeb0SSepherosa Ziehau 
138943c2aeb0SSepherosa Ziehau #ifdef BCE_NVRAM_WRITE_SUPPORT
139043c2aeb0SSepherosa Ziehau /****************************************************************************/
139143c2aeb0SSepherosa Ziehau /* Erase NVRAM page before writing.                                         */
139243c2aeb0SSepherosa Ziehau /*                                                                          */
139343c2aeb0SSepherosa Ziehau /* Non-buffered flash parts require that a page be erased before it is      */
139443c2aeb0SSepherosa Ziehau /* written.                                                                 */
139543c2aeb0SSepherosa Ziehau /*                                                                          */
139643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
139743c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
139843c2aeb0SSepherosa Ziehau /****************************************************************************/
139943c2aeb0SSepherosa Ziehau static int
140043c2aeb0SSepherosa Ziehau bce_nvram_erase_page(struct bce_softc *sc, uint32_t offset)
140143c2aeb0SSepherosa Ziehau {
140243c2aeb0SSepherosa Ziehau 	uint32_t cmd;
140343c2aeb0SSepherosa Ziehau 	int j;
140443c2aeb0SSepherosa Ziehau 
140543c2aeb0SSepherosa Ziehau 	/* Buffered flash doesn't require an erase. */
140643c2aeb0SSepherosa Ziehau 	if (sc->bce_flash_info->buffered)
140743c2aeb0SSepherosa Ziehau 		return 0;
140843c2aeb0SSepherosa Ziehau 
140943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE, "Erasing NVRAM page.\n");
141043c2aeb0SSepherosa Ziehau 
141143c2aeb0SSepherosa Ziehau 	/* Build an erase command. */
141243c2aeb0SSepherosa Ziehau 	cmd = BCE_NVM_COMMAND_ERASE | BCE_NVM_COMMAND_WR |
141343c2aeb0SSepherosa Ziehau 	      BCE_NVM_COMMAND_DOIT;
141443c2aeb0SSepherosa Ziehau 
141543c2aeb0SSepherosa Ziehau 	/*
141643c2aeb0SSepherosa Ziehau 	 * Clear the DONE bit separately, set the NVRAM adress to erase,
141743c2aeb0SSepherosa Ziehau 	 * and issue the erase command.
141843c2aeb0SSepherosa Ziehau 	 */
141943c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE);
142043c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE);
142143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_COMMAND, cmd);
142243c2aeb0SSepherosa Ziehau 
142343c2aeb0SSepherosa Ziehau 	/* Wait for completion. */
142443c2aeb0SSepherosa Ziehau 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
142543c2aeb0SSepherosa Ziehau 		uint32_t val;
142643c2aeb0SSepherosa Ziehau 
142743c2aeb0SSepherosa Ziehau 		DELAY(5);
142843c2aeb0SSepherosa Ziehau 
142943c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_NVM_COMMAND);
143043c2aeb0SSepherosa Ziehau 		if (val & BCE_NVM_COMMAND_DONE)
143143c2aeb0SSepherosa Ziehau 			break;
143243c2aeb0SSepherosa Ziehau 	}
143343c2aeb0SSepherosa Ziehau 
143443c2aeb0SSepherosa Ziehau 	if (j >= NVRAM_TIMEOUT_COUNT) {
143543c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_WARN, "Timeout erasing NVRAM.\n");
143643c2aeb0SSepherosa Ziehau 		return EBUSY;
143743c2aeb0SSepherosa Ziehau 	}
143843c2aeb0SSepherosa Ziehau 	return 0;
143943c2aeb0SSepherosa Ziehau }
144043c2aeb0SSepherosa Ziehau #endif /* BCE_NVRAM_WRITE_SUPPORT */
144143c2aeb0SSepherosa Ziehau 
144243c2aeb0SSepherosa Ziehau 
144343c2aeb0SSepherosa Ziehau /****************************************************************************/
144443c2aeb0SSepherosa Ziehau /* Read a dword (32 bits) from NVRAM.                                       */
144543c2aeb0SSepherosa Ziehau /*                                                                          */
144643c2aeb0SSepherosa Ziehau /* Read a 32 bit word from NVRAM.  The caller is assumed to have already    */
144743c2aeb0SSepherosa Ziehau /* obtained the NVRAM lock and enabled the controller for NVRAM access.     */
144843c2aeb0SSepherosa Ziehau /*                                                                          */
144943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
145043c2aeb0SSepherosa Ziehau /*   0 on success and the 32 bit value read, positive value on failure.     */
145143c2aeb0SSepherosa Ziehau /****************************************************************************/
145243c2aeb0SSepherosa Ziehau static int
145343c2aeb0SSepherosa Ziehau bce_nvram_read_dword(struct bce_softc *sc, uint32_t offset, uint8_t *ret_val,
145443c2aeb0SSepherosa Ziehau 		     uint32_t cmd_flags)
145543c2aeb0SSepherosa Ziehau {
145643c2aeb0SSepherosa Ziehau 	uint32_t cmd;
145743c2aeb0SSepherosa Ziehau 	int i, rc = 0;
145843c2aeb0SSepherosa Ziehau 
145943c2aeb0SSepherosa Ziehau 	/* Build the command word. */
146043c2aeb0SSepherosa Ziehau 	cmd = BCE_NVM_COMMAND_DOIT | cmd_flags;
146143c2aeb0SSepherosa Ziehau 
146243c2aeb0SSepherosa Ziehau 	/* Calculate the offset for buffered flash. */
146343c2aeb0SSepherosa Ziehau 	if (sc->bce_flash_info->buffered) {
146443c2aeb0SSepherosa Ziehau 		offset = ((offset / sc->bce_flash_info->page_size) <<
146543c2aeb0SSepherosa Ziehau 			  sc->bce_flash_info->page_bits) +
146643c2aeb0SSepherosa Ziehau 			 (offset % sc->bce_flash_info->page_size);
146743c2aeb0SSepherosa Ziehau 	}
146843c2aeb0SSepherosa Ziehau 
146943c2aeb0SSepherosa Ziehau 	/*
147043c2aeb0SSepherosa Ziehau 	 * Clear the DONE bit separately, set the address to read,
147143c2aeb0SSepherosa Ziehau 	 * and issue the read.
147243c2aeb0SSepherosa Ziehau 	 */
147343c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE);
147443c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE);
147543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_COMMAND, cmd);
147643c2aeb0SSepherosa Ziehau 
147743c2aeb0SSepherosa Ziehau 	/* Wait for completion. */
147843c2aeb0SSepherosa Ziehau 	for (i = 0; i < NVRAM_TIMEOUT_COUNT; i++) {
147943c2aeb0SSepherosa Ziehau 		uint32_t val;
148043c2aeb0SSepherosa Ziehau 
148143c2aeb0SSepherosa Ziehau 		DELAY(5);
148243c2aeb0SSepherosa Ziehau 
148343c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_NVM_COMMAND);
148443c2aeb0SSepherosa Ziehau 		if (val & BCE_NVM_COMMAND_DONE) {
148543c2aeb0SSepherosa Ziehau 			val = REG_RD(sc, BCE_NVM_READ);
148643c2aeb0SSepherosa Ziehau 
148743c2aeb0SSepherosa Ziehau 			val = be32toh(val);
148843c2aeb0SSepherosa Ziehau 			memcpy(ret_val, &val, 4);
148943c2aeb0SSepherosa Ziehau 			break;
149043c2aeb0SSepherosa Ziehau 		}
149143c2aeb0SSepherosa Ziehau 	}
149243c2aeb0SSepherosa Ziehau 
149343c2aeb0SSepherosa Ziehau 	/* Check for errors. */
149443c2aeb0SSepherosa Ziehau 	if (i >= NVRAM_TIMEOUT_COUNT) {
149543c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
149643c2aeb0SSepherosa Ziehau 			  "Timeout error reading NVRAM at offset 0x%08X!\n",
149743c2aeb0SSepherosa Ziehau 			  offset);
149843c2aeb0SSepherosa Ziehau 		rc = EBUSY;
149943c2aeb0SSepherosa Ziehau 	}
150043c2aeb0SSepherosa Ziehau 	return rc;
150143c2aeb0SSepherosa Ziehau }
150243c2aeb0SSepherosa Ziehau 
150343c2aeb0SSepherosa Ziehau 
150443c2aeb0SSepherosa Ziehau #ifdef BCE_NVRAM_WRITE_SUPPORT
150543c2aeb0SSepherosa Ziehau /****************************************************************************/
150643c2aeb0SSepherosa Ziehau /* Write a dword (32 bits) to NVRAM.                                        */
150743c2aeb0SSepherosa Ziehau /*                                                                          */
150843c2aeb0SSepherosa Ziehau /* Write a 32 bit word to NVRAM.  The caller is assumed to have already     */
150943c2aeb0SSepherosa Ziehau /* obtained the NVRAM lock, enabled the controller for NVRAM access, and    */
151043c2aeb0SSepherosa Ziehau /* enabled NVRAM write access.                                              */
151143c2aeb0SSepherosa Ziehau /*                                                                          */
151243c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
151343c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
151443c2aeb0SSepherosa Ziehau /****************************************************************************/
151543c2aeb0SSepherosa Ziehau static int
151643c2aeb0SSepherosa Ziehau bce_nvram_write_dword(struct bce_softc *sc, uint32_t offset, uint8_t *val,
151743c2aeb0SSepherosa Ziehau 		      uint32_t cmd_flags)
151843c2aeb0SSepherosa Ziehau {
151943c2aeb0SSepherosa Ziehau 	uint32_t cmd, val32;
152043c2aeb0SSepherosa Ziehau 	int j;
152143c2aeb0SSepherosa Ziehau 
152243c2aeb0SSepherosa Ziehau 	/* Build the command word. */
152343c2aeb0SSepherosa Ziehau 	cmd = BCE_NVM_COMMAND_DOIT | BCE_NVM_COMMAND_WR | cmd_flags;
152443c2aeb0SSepherosa Ziehau 
152543c2aeb0SSepherosa Ziehau 	/* Calculate the offset for buffered flash. */
152643c2aeb0SSepherosa Ziehau 	if (sc->bce_flash_info->buffered) {
152743c2aeb0SSepherosa Ziehau 		offset = ((offset / sc->bce_flash_info->page_size) <<
152843c2aeb0SSepherosa Ziehau 			  sc->bce_flash_info->page_bits) +
152943c2aeb0SSepherosa Ziehau 			 (offset % sc->bce_flash_info->page_size);
153043c2aeb0SSepherosa Ziehau 	}
153143c2aeb0SSepherosa Ziehau 
153243c2aeb0SSepherosa Ziehau 	/*
153343c2aeb0SSepherosa Ziehau 	 * Clear the DONE bit separately, convert NVRAM data to big-endian,
153443c2aeb0SSepherosa Ziehau 	 * set the NVRAM address to write, and issue the write command
153543c2aeb0SSepherosa Ziehau 	 */
153643c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE);
153743c2aeb0SSepherosa Ziehau 	memcpy(&val32, val, 4);
153843c2aeb0SSepherosa Ziehau 	val32 = htobe32(val32);
153943c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_WRITE, val32);
154043c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE);
154143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_NVM_COMMAND, cmd);
154243c2aeb0SSepherosa Ziehau 
154343c2aeb0SSepherosa Ziehau 	/* Wait for completion. */
154443c2aeb0SSepherosa Ziehau 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
154543c2aeb0SSepherosa Ziehau 		DELAY(5);
154643c2aeb0SSepherosa Ziehau 
154743c2aeb0SSepherosa Ziehau 		if (REG_RD(sc, BCE_NVM_COMMAND) & BCE_NVM_COMMAND_DONE)
154843c2aeb0SSepherosa Ziehau 			break;
154943c2aeb0SSepherosa Ziehau 	}
155043c2aeb0SSepherosa Ziehau 	if (j >= NVRAM_TIMEOUT_COUNT) {
155143c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
155243c2aeb0SSepherosa Ziehau 			  "Timeout error writing NVRAM at offset 0x%08X\n",
155343c2aeb0SSepherosa Ziehau 			  offset);
155443c2aeb0SSepherosa Ziehau 		return EBUSY;
155543c2aeb0SSepherosa Ziehau 	}
155643c2aeb0SSepherosa Ziehau 	return 0;
155743c2aeb0SSepherosa Ziehau }
155843c2aeb0SSepherosa Ziehau #endif /* BCE_NVRAM_WRITE_SUPPORT */
155943c2aeb0SSepherosa Ziehau 
156043c2aeb0SSepherosa Ziehau 
156143c2aeb0SSepherosa Ziehau /****************************************************************************/
156243c2aeb0SSepherosa Ziehau /* Initialize NVRAM access.                                                 */
156343c2aeb0SSepherosa Ziehau /*                                                                          */
156443c2aeb0SSepherosa Ziehau /* Identify the NVRAM device in use and prepare the NVRAM interface to      */
156543c2aeb0SSepherosa Ziehau /* access that device.                                                      */
156643c2aeb0SSepherosa Ziehau /*                                                                          */
156743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
156843c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
156943c2aeb0SSepherosa Ziehau /****************************************************************************/
157043c2aeb0SSepherosa Ziehau static int
157143c2aeb0SSepherosa Ziehau bce_init_nvram(struct bce_softc *sc)
157243c2aeb0SSepherosa Ziehau {
157343c2aeb0SSepherosa Ziehau 	uint32_t val;
157443c2aeb0SSepherosa Ziehau 	int j, entry_count, rc = 0;
157543c2aeb0SSepherosa Ziehau 	const struct flash_spec *flash;
157643c2aeb0SSepherosa Ziehau 
157743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
157843c2aeb0SSepherosa Ziehau 
157943c2aeb0SSepherosa Ziehau 	/* Determine the selected interface. */
158043c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_NVM_CFG1);
158143c2aeb0SSepherosa Ziehau 
158243c2aeb0SSepherosa Ziehau 	entry_count = sizeof(flash_table) / sizeof(struct flash_spec);
158343c2aeb0SSepherosa Ziehau 
158443c2aeb0SSepherosa Ziehau 	/*
158543c2aeb0SSepherosa Ziehau 	 * Flash reconfiguration is required to support additional
158643c2aeb0SSepherosa Ziehau 	 * NVRAM devices not directly supported in hardware.
158743c2aeb0SSepherosa Ziehau 	 * Check if the flash interface was reconfigured
158843c2aeb0SSepherosa Ziehau 	 * by the bootcode.
158943c2aeb0SSepherosa Ziehau 	 */
159043c2aeb0SSepherosa Ziehau 
159143c2aeb0SSepherosa Ziehau 	if (val & 0x40000000) {
159243c2aeb0SSepherosa Ziehau 		/* Flash interface reconfigured by bootcode. */
159343c2aeb0SSepherosa Ziehau 
159443c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO_LOAD,
159543c2aeb0SSepherosa Ziehau 			"%s(): Flash WAS reconfigured.\n", __func__);
159643c2aeb0SSepherosa Ziehau 
159743c2aeb0SSepherosa Ziehau 		for (j = 0, flash = flash_table; j < entry_count;
159843c2aeb0SSepherosa Ziehau 		     j++, flash++) {
159943c2aeb0SSepherosa Ziehau 			if ((val & FLASH_BACKUP_STRAP_MASK) ==
160043c2aeb0SSepherosa Ziehau 			    (flash->config1 & FLASH_BACKUP_STRAP_MASK)) {
160143c2aeb0SSepherosa Ziehau 				sc->bce_flash_info = flash;
160243c2aeb0SSepherosa Ziehau 				break;
160343c2aeb0SSepherosa Ziehau 			}
160443c2aeb0SSepherosa Ziehau 		}
160543c2aeb0SSepherosa Ziehau 	} else {
160643c2aeb0SSepherosa Ziehau 		/* Flash interface not yet reconfigured. */
160743c2aeb0SSepherosa Ziehau 		uint32_t mask;
160843c2aeb0SSepherosa Ziehau 
160943c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO_LOAD,
161043c2aeb0SSepherosa Ziehau 			"%s(): Flash was NOT reconfigured.\n", __func__);
161143c2aeb0SSepherosa Ziehau 
161243c2aeb0SSepherosa Ziehau 		if (val & (1 << 23))
161343c2aeb0SSepherosa Ziehau 			mask = FLASH_BACKUP_STRAP_MASK;
161443c2aeb0SSepherosa Ziehau 		else
161543c2aeb0SSepherosa Ziehau 			mask = FLASH_STRAP_MASK;
161643c2aeb0SSepherosa Ziehau 
161743c2aeb0SSepherosa Ziehau 		/* Look for the matching NVRAM device configuration data. */
161843c2aeb0SSepherosa Ziehau 		for (j = 0, flash = flash_table; j < entry_count;
161943c2aeb0SSepherosa Ziehau 		     j++, flash++) {
162043c2aeb0SSepherosa Ziehau 			/* Check if the device matches any of the known devices. */
162143c2aeb0SSepherosa Ziehau 			if ((val & mask) == (flash->strapping & mask)) {
162243c2aeb0SSepherosa Ziehau 				/* Found a device match. */
162343c2aeb0SSepherosa Ziehau 				sc->bce_flash_info = flash;
162443c2aeb0SSepherosa Ziehau 
162543c2aeb0SSepherosa Ziehau 				/* Request access to the flash interface. */
162643c2aeb0SSepherosa Ziehau 				rc = bce_acquire_nvram_lock(sc);
162743c2aeb0SSepherosa Ziehau 				if (rc != 0)
162843c2aeb0SSepherosa Ziehau 					return rc;
162943c2aeb0SSepherosa Ziehau 
163043c2aeb0SSepherosa Ziehau 				/* Reconfigure the flash interface. */
163143c2aeb0SSepherosa Ziehau 				bce_enable_nvram_access(sc);
163243c2aeb0SSepherosa Ziehau 				REG_WR(sc, BCE_NVM_CFG1, flash->config1);
163343c2aeb0SSepherosa Ziehau 				REG_WR(sc, BCE_NVM_CFG2, flash->config2);
163443c2aeb0SSepherosa Ziehau 				REG_WR(sc, BCE_NVM_CFG3, flash->config3);
163543c2aeb0SSepherosa Ziehau 				REG_WR(sc, BCE_NVM_WRITE1, flash->write1);
163643c2aeb0SSepherosa Ziehau 				bce_disable_nvram_access(sc);
163743c2aeb0SSepherosa Ziehau 				bce_release_nvram_lock(sc);
163843c2aeb0SSepherosa Ziehau 				break;
163943c2aeb0SSepherosa Ziehau 			}
164043c2aeb0SSepherosa Ziehau 		}
164143c2aeb0SSepherosa Ziehau 	}
164243c2aeb0SSepherosa Ziehau 
164343c2aeb0SSepherosa Ziehau 	/* Check if a matching device was found. */
164443c2aeb0SSepherosa Ziehau 	if (j == entry_count) {
164543c2aeb0SSepherosa Ziehau 		sc->bce_flash_info = NULL;
164643c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "Unknown Flash NVRAM found!\n");
164743c2aeb0SSepherosa Ziehau 		rc = ENODEV;
164843c2aeb0SSepherosa Ziehau 	}
164943c2aeb0SSepherosa Ziehau 
165043c2aeb0SSepherosa Ziehau 	/* Write the flash config data to the shared memory interface. */
165143c2aeb0SSepherosa Ziehau 	val = REG_RD_IND(sc, sc->bce_shmem_base + BCE_SHARED_HW_CFG_CONFIG2) &
165243c2aeb0SSepherosa Ziehau 	      BCE_SHARED_HW_CFG2_NVM_SIZE_MASK;
165343c2aeb0SSepherosa Ziehau 	if (val)
165443c2aeb0SSepherosa Ziehau 		sc->bce_flash_size = val;
165543c2aeb0SSepherosa Ziehau 	else
165643c2aeb0SSepherosa Ziehau 		sc->bce_flash_size = sc->bce_flash_info->total_size;
165743c2aeb0SSepherosa Ziehau 
165843c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_LOAD, "%s() flash->total_size = 0x%08X\n",
165943c2aeb0SSepherosa Ziehau 		__func__, sc->bce_flash_info->total_size);
166043c2aeb0SSepherosa Ziehau 
166143c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __func__);
166243c2aeb0SSepherosa Ziehau 
166343c2aeb0SSepherosa Ziehau 	return rc;
166443c2aeb0SSepherosa Ziehau }
166543c2aeb0SSepherosa Ziehau 
166643c2aeb0SSepherosa Ziehau 
166743c2aeb0SSepherosa Ziehau /****************************************************************************/
166843c2aeb0SSepherosa Ziehau /* Read an arbitrary range of data from NVRAM.                              */
166943c2aeb0SSepherosa Ziehau /*                                                                          */
167043c2aeb0SSepherosa Ziehau /* Prepares the NVRAM interface for access and reads the requested data     */
167143c2aeb0SSepherosa Ziehau /* into the supplied buffer.                                                */
167243c2aeb0SSepherosa Ziehau /*                                                                          */
167343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
167443c2aeb0SSepherosa Ziehau /*   0 on success and the data read, positive value on failure.             */
167543c2aeb0SSepherosa Ziehau /****************************************************************************/
167643c2aeb0SSepherosa Ziehau static int
167743c2aeb0SSepherosa Ziehau bce_nvram_read(struct bce_softc *sc, uint32_t offset, uint8_t *ret_buf,
167843c2aeb0SSepherosa Ziehau 	       int buf_size)
167943c2aeb0SSepherosa Ziehau {
168043c2aeb0SSepherosa Ziehau 	uint32_t cmd_flags, offset32, len32, extra;
168143c2aeb0SSepherosa Ziehau 	int rc = 0;
168243c2aeb0SSepherosa Ziehau 
168343c2aeb0SSepherosa Ziehau 	if (buf_size == 0)
168443c2aeb0SSepherosa Ziehau 		return 0;
168543c2aeb0SSepherosa Ziehau 
168643c2aeb0SSepherosa Ziehau 	/* Request access to the flash interface. */
168743c2aeb0SSepherosa Ziehau 	rc = bce_acquire_nvram_lock(sc);
168843c2aeb0SSepherosa Ziehau 	if (rc != 0)
168943c2aeb0SSepherosa Ziehau 		return rc;
169043c2aeb0SSepherosa Ziehau 
169143c2aeb0SSepherosa Ziehau 	/* Enable access to flash interface */
169243c2aeb0SSepherosa Ziehau 	bce_enable_nvram_access(sc);
169343c2aeb0SSepherosa Ziehau 
169443c2aeb0SSepherosa Ziehau 	len32 = buf_size;
169543c2aeb0SSepherosa Ziehau 	offset32 = offset;
169643c2aeb0SSepherosa Ziehau 	extra = 0;
169743c2aeb0SSepherosa Ziehau 
169843c2aeb0SSepherosa Ziehau 	cmd_flags = 0;
169943c2aeb0SSepherosa Ziehau 
170043c2aeb0SSepherosa Ziehau 	/* XXX should we release nvram lock if read_dword() fails? */
170143c2aeb0SSepherosa Ziehau 	if (offset32 & 3) {
170243c2aeb0SSepherosa Ziehau 		uint8_t buf[4];
170343c2aeb0SSepherosa Ziehau 		uint32_t pre_len;
170443c2aeb0SSepherosa Ziehau 
170543c2aeb0SSepherosa Ziehau 		offset32 &= ~3;
170643c2aeb0SSepherosa Ziehau 		pre_len = 4 - (offset & 3);
170743c2aeb0SSepherosa Ziehau 
170843c2aeb0SSepherosa Ziehau 		if (pre_len >= len32) {
170943c2aeb0SSepherosa Ziehau 			pre_len = len32;
171043c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_FIRST | BCE_NVM_COMMAND_LAST;
171143c2aeb0SSepherosa Ziehau 		} else {
171243c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_FIRST;
171343c2aeb0SSepherosa Ziehau 		}
171443c2aeb0SSepherosa Ziehau 
171543c2aeb0SSepherosa Ziehau 		rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags);
171643c2aeb0SSepherosa Ziehau 		if (rc)
171743c2aeb0SSepherosa Ziehau 			return rc;
171843c2aeb0SSepherosa Ziehau 
171943c2aeb0SSepherosa Ziehau 		memcpy(ret_buf, buf + (offset & 3), pre_len);
172043c2aeb0SSepherosa Ziehau 
172143c2aeb0SSepherosa Ziehau 		offset32 += 4;
172243c2aeb0SSepherosa Ziehau 		ret_buf += pre_len;
172343c2aeb0SSepherosa Ziehau 		len32 -= pre_len;
172443c2aeb0SSepherosa Ziehau 	}
172543c2aeb0SSepherosa Ziehau 
172643c2aeb0SSepherosa Ziehau 	if (len32 & 3) {
172743c2aeb0SSepherosa Ziehau 		extra = 4 - (len32 & 3);
172843c2aeb0SSepherosa Ziehau 		len32 = (len32 + 4) & ~3;
172943c2aeb0SSepherosa Ziehau 	}
173043c2aeb0SSepherosa Ziehau 
173143c2aeb0SSepherosa Ziehau 	if (len32 == 4) {
173243c2aeb0SSepherosa Ziehau 		uint8_t buf[4];
173343c2aeb0SSepherosa Ziehau 
173443c2aeb0SSepherosa Ziehau 		if (cmd_flags)
173543c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_LAST;
173643c2aeb0SSepherosa Ziehau 		else
173743c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_FIRST |
173843c2aeb0SSepherosa Ziehau 				    BCE_NVM_COMMAND_LAST;
173943c2aeb0SSepherosa Ziehau 
174043c2aeb0SSepherosa Ziehau 		rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags);
174143c2aeb0SSepherosa Ziehau 
174243c2aeb0SSepherosa Ziehau 		memcpy(ret_buf, buf, 4 - extra);
174343c2aeb0SSepherosa Ziehau 	} else if (len32 > 0) {
174443c2aeb0SSepherosa Ziehau 		uint8_t buf[4];
174543c2aeb0SSepherosa Ziehau 
174643c2aeb0SSepherosa Ziehau 		/* Read the first word. */
174743c2aeb0SSepherosa Ziehau 		if (cmd_flags)
174843c2aeb0SSepherosa Ziehau 			cmd_flags = 0;
174943c2aeb0SSepherosa Ziehau 		else
175043c2aeb0SSepherosa Ziehau 			cmd_flags = BCE_NVM_COMMAND_FIRST;
175143c2aeb0SSepherosa Ziehau 
175243c2aeb0SSepherosa Ziehau 		rc = bce_nvram_read_dword(sc, offset32, ret_buf, cmd_flags);
175343c2aeb0SSepherosa Ziehau 
175443c2aeb0SSepherosa Ziehau 		/* Advance to the next dword. */
175543c2aeb0SSepherosa Ziehau 		offset32 += 4;
175643c2aeb0SSepherosa Ziehau 		ret_buf += 4;
175743c2aeb0SSepherosa Ziehau 		len32 -= 4;
175843c2aeb0SSepherosa Ziehau 
175943c2aeb0SSepherosa Ziehau 		while (len32 > 4 && rc == 0) {
176043c2aeb0SSepherosa Ziehau 			rc = bce_nvram_read_dword(sc, offset32, ret_buf, 0);
176143c2aeb0SSepherosa Ziehau 
176243c2aeb0SSepherosa Ziehau 			/* Advance to the next dword. */
176343c2aeb0SSepherosa Ziehau 			offset32 += 4;
176443c2aeb0SSepherosa Ziehau 			ret_buf += 4;
176543c2aeb0SSepherosa Ziehau 			len32 -= 4;
176643c2aeb0SSepherosa Ziehau 		}
176743c2aeb0SSepherosa Ziehau 
176843c2aeb0SSepherosa Ziehau 		if (rc)
176943c2aeb0SSepherosa Ziehau 			return rc;
177043c2aeb0SSepherosa Ziehau 
177143c2aeb0SSepherosa Ziehau 		cmd_flags = BCE_NVM_COMMAND_LAST;
177243c2aeb0SSepherosa Ziehau 		rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags);
177343c2aeb0SSepherosa Ziehau 
177443c2aeb0SSepherosa Ziehau 		memcpy(ret_buf, buf, 4 - extra);
177543c2aeb0SSepherosa Ziehau 	}
177643c2aeb0SSepherosa Ziehau 
177743c2aeb0SSepherosa Ziehau 	/* Disable access to flash interface and release the lock. */
177843c2aeb0SSepherosa Ziehau 	bce_disable_nvram_access(sc);
177943c2aeb0SSepherosa Ziehau 	bce_release_nvram_lock(sc);
178043c2aeb0SSepherosa Ziehau 
178143c2aeb0SSepherosa Ziehau 	return rc;
178243c2aeb0SSepherosa Ziehau }
178343c2aeb0SSepherosa Ziehau 
178443c2aeb0SSepherosa Ziehau 
178543c2aeb0SSepherosa Ziehau #ifdef BCE_NVRAM_WRITE_SUPPORT
178643c2aeb0SSepherosa Ziehau /****************************************************************************/
178743c2aeb0SSepherosa Ziehau /* Write an arbitrary range of data from NVRAM.                             */
178843c2aeb0SSepherosa Ziehau /*                                                                          */
178943c2aeb0SSepherosa Ziehau /* Prepares the NVRAM interface for write access and writes the requested   */
179043c2aeb0SSepherosa Ziehau /* data from the supplied buffer.  The caller is responsible for            */
179143c2aeb0SSepherosa Ziehau /* calculating any appropriate CRCs.                                        */
179243c2aeb0SSepherosa Ziehau /*                                                                          */
179343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
179443c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
179543c2aeb0SSepherosa Ziehau /****************************************************************************/
179643c2aeb0SSepherosa Ziehau static int
179743c2aeb0SSepherosa Ziehau bce_nvram_write(struct bce_softc *sc, uint32_t offset, uint8_t *data_buf,
179843c2aeb0SSepherosa Ziehau 		int buf_size)
179943c2aeb0SSepherosa Ziehau {
180043c2aeb0SSepherosa Ziehau 	uint32_t written, offset32, len32;
180143c2aeb0SSepherosa Ziehau 	uint8_t *buf, start[4], end[4];
180243c2aeb0SSepherosa Ziehau 	int rc = 0;
180343c2aeb0SSepherosa Ziehau 	int align_start, align_end;
180443c2aeb0SSepherosa Ziehau 
180543c2aeb0SSepherosa Ziehau 	buf = data_buf;
180643c2aeb0SSepherosa Ziehau 	offset32 = offset;
180743c2aeb0SSepherosa Ziehau 	len32 = buf_size;
180843c2aeb0SSepherosa Ziehau 	align_end = 0;
180943c2aeb0SSepherosa Ziehau 	align_start = (offset32 & 3);
181043c2aeb0SSepherosa Ziehau 
181143c2aeb0SSepherosa Ziehau 	if (align_start) {
181243c2aeb0SSepherosa Ziehau 		offset32 &= ~3;
181343c2aeb0SSepherosa Ziehau 		len32 += align_start;
181443c2aeb0SSepherosa Ziehau 		rc = bce_nvram_read(sc, offset32, start, 4);
181543c2aeb0SSepherosa Ziehau 		if (rc)
181643c2aeb0SSepherosa Ziehau 			return rc;
181743c2aeb0SSepherosa Ziehau 	}
181843c2aeb0SSepherosa Ziehau 
181943c2aeb0SSepherosa Ziehau 	if (len32 & 3) {
182043c2aeb0SSepherosa Ziehau 	       	if (len32 > 4 || !align_start) {
182143c2aeb0SSepherosa Ziehau 			align_end = 4 - (len32 & 3);
182243c2aeb0SSepherosa Ziehau 			len32 += align_end;
182343c2aeb0SSepherosa Ziehau 			rc = bce_nvram_read(sc, offset32 + len32 - 4, end, 4);
182443c2aeb0SSepherosa Ziehau 			if (rc)
182543c2aeb0SSepherosa Ziehau 				return rc;
182643c2aeb0SSepherosa Ziehau 		}
182743c2aeb0SSepherosa Ziehau 	}
182843c2aeb0SSepherosa Ziehau 
182943c2aeb0SSepherosa Ziehau 	if (align_start || align_end) {
183043c2aeb0SSepherosa Ziehau 		buf = kmalloc(len32, M_DEVBUF, M_NOWAIT);
183143c2aeb0SSepherosa Ziehau 		if (buf == NULL)
183243c2aeb0SSepherosa Ziehau 			return ENOMEM;
183343c2aeb0SSepherosa Ziehau 		if (align_start)
183443c2aeb0SSepherosa Ziehau 			memcpy(buf, start, 4);
183543c2aeb0SSepherosa Ziehau 		if (align_end)
183643c2aeb0SSepherosa Ziehau 			memcpy(buf + len32 - 4, end, 4);
183743c2aeb0SSepherosa Ziehau 		memcpy(buf + align_start, data_buf, buf_size);
183843c2aeb0SSepherosa Ziehau 	}
183943c2aeb0SSepherosa Ziehau 
184043c2aeb0SSepherosa Ziehau 	written = 0;
184143c2aeb0SSepherosa Ziehau 	while (written < len32 && rc == 0) {
184243c2aeb0SSepherosa Ziehau 		uint32_t page_start, page_end, data_start, data_end;
184343c2aeb0SSepherosa Ziehau 		uint32_t addr, cmd_flags;
184443c2aeb0SSepherosa Ziehau 		int i;
184543c2aeb0SSepherosa Ziehau 		uint8_t flash_buffer[264];
184643c2aeb0SSepherosa Ziehau 
184743c2aeb0SSepherosa Ziehau 		/* Find the page_start addr */
184843c2aeb0SSepherosa Ziehau 		page_start = offset32 + written;
184943c2aeb0SSepherosa Ziehau 		page_start -= (page_start % sc->bce_flash_info->page_size);
185043c2aeb0SSepherosa Ziehau 		/* Find the page_end addr */
185143c2aeb0SSepherosa Ziehau 		page_end = page_start + sc->bce_flash_info->page_size;
185243c2aeb0SSepherosa Ziehau 		/* Find the data_start addr */
185343c2aeb0SSepherosa Ziehau 		data_start = (written == 0) ? offset32 : page_start;
185443c2aeb0SSepherosa Ziehau 		/* Find the data_end addr */
185543c2aeb0SSepherosa Ziehau 		data_end = (page_end > offset32 + len32) ? (offset32 + len32)
185643c2aeb0SSepherosa Ziehau 							 : page_end;
185743c2aeb0SSepherosa Ziehau 
185843c2aeb0SSepherosa Ziehau 		/* Request access to the flash interface. */
185943c2aeb0SSepherosa Ziehau 		rc = bce_acquire_nvram_lock(sc);
186043c2aeb0SSepherosa Ziehau 		if (rc != 0)
186143c2aeb0SSepherosa Ziehau 			goto nvram_write_end;
186243c2aeb0SSepherosa Ziehau 
186343c2aeb0SSepherosa Ziehau 		/* Enable access to flash interface */
186443c2aeb0SSepherosa Ziehau 		bce_enable_nvram_access(sc);
186543c2aeb0SSepherosa Ziehau 
186643c2aeb0SSepherosa Ziehau 		cmd_flags = BCE_NVM_COMMAND_FIRST;
186743c2aeb0SSepherosa Ziehau 		if (sc->bce_flash_info->buffered == 0) {
186843c2aeb0SSepherosa Ziehau 			int j;
186943c2aeb0SSepherosa Ziehau 
187043c2aeb0SSepherosa Ziehau 			/*
187143c2aeb0SSepherosa Ziehau 			 * Read the whole page into the buffer
187243c2aeb0SSepherosa Ziehau 			 * (non-buffer flash only)
187343c2aeb0SSepherosa Ziehau 			 */
187443c2aeb0SSepherosa Ziehau 			for (j = 0; j < sc->bce_flash_info->page_size; j += 4) {
187543c2aeb0SSepherosa Ziehau 				if (j == (sc->bce_flash_info->page_size - 4))
187643c2aeb0SSepherosa Ziehau 					cmd_flags |= BCE_NVM_COMMAND_LAST;
187743c2aeb0SSepherosa Ziehau 
187843c2aeb0SSepherosa Ziehau 				rc = bce_nvram_read_dword(sc, page_start + j,
187943c2aeb0SSepherosa Ziehau 							  &flash_buffer[j],
188043c2aeb0SSepherosa Ziehau 							  cmd_flags);
188143c2aeb0SSepherosa Ziehau 				if (rc)
188243c2aeb0SSepherosa Ziehau 					goto nvram_write_end;
188343c2aeb0SSepherosa Ziehau 
188443c2aeb0SSepherosa Ziehau 				cmd_flags = 0;
188543c2aeb0SSepherosa Ziehau 			}
188643c2aeb0SSepherosa Ziehau 		}
188743c2aeb0SSepherosa Ziehau 
188843c2aeb0SSepherosa Ziehau 		/* Enable writes to flash interface (unlock write-protect) */
188943c2aeb0SSepherosa Ziehau 		rc = bce_enable_nvram_write(sc);
189043c2aeb0SSepherosa Ziehau 		if (rc != 0)
189143c2aeb0SSepherosa Ziehau 			goto nvram_write_end;
189243c2aeb0SSepherosa Ziehau 
189343c2aeb0SSepherosa Ziehau 		/* Erase the page */
189443c2aeb0SSepherosa Ziehau 		rc = bce_nvram_erase_page(sc, page_start);
189543c2aeb0SSepherosa Ziehau 		if (rc != 0)
189643c2aeb0SSepherosa Ziehau 			goto nvram_write_end;
189743c2aeb0SSepherosa Ziehau 
189843c2aeb0SSepherosa Ziehau 		/* Re-enable the write again for the actual write */
189943c2aeb0SSepherosa Ziehau 		bce_enable_nvram_write(sc);
190043c2aeb0SSepherosa Ziehau 
190143c2aeb0SSepherosa Ziehau 		/* Loop to write back the buffer data from page_start to
190243c2aeb0SSepherosa Ziehau 		 * data_start */
190343c2aeb0SSepherosa Ziehau 		i = 0;
190443c2aeb0SSepherosa Ziehau 		if (sc->bce_flash_info->buffered == 0) {
190543c2aeb0SSepherosa Ziehau 			for (addr = page_start; addr < data_start;
190643c2aeb0SSepherosa Ziehau 			     addr += 4, i += 4) {
190743c2aeb0SSepherosa Ziehau 				rc = bce_nvram_write_dword(sc, addr,
190843c2aeb0SSepherosa Ziehau 							   &flash_buffer[i],
190943c2aeb0SSepherosa Ziehau 							   cmd_flags);
191043c2aeb0SSepherosa Ziehau 				if (rc != 0)
191143c2aeb0SSepherosa Ziehau 					goto nvram_write_end;
191243c2aeb0SSepherosa Ziehau 
191343c2aeb0SSepherosa Ziehau 				cmd_flags = 0;
191443c2aeb0SSepherosa Ziehau 			}
191543c2aeb0SSepherosa Ziehau 		}
191643c2aeb0SSepherosa Ziehau 
191743c2aeb0SSepherosa Ziehau 		/* Loop to write the new data from data_start to data_end */
191843c2aeb0SSepherosa Ziehau 		for (addr = data_start; addr < data_end; addr += 4, i++) {
191943c2aeb0SSepherosa Ziehau 			if (addr == page_end - 4 ||
192043c2aeb0SSepherosa Ziehau 			    (sc->bce_flash_info->buffered &&
192143c2aeb0SSepherosa Ziehau 			     addr == data_end - 4))
192243c2aeb0SSepherosa Ziehau 				cmd_flags |= BCE_NVM_COMMAND_LAST;
192343c2aeb0SSepherosa Ziehau 
192443c2aeb0SSepherosa Ziehau 			rc = bce_nvram_write_dword(sc, addr, buf, cmd_flags);
192543c2aeb0SSepherosa Ziehau 			if (rc != 0)
192643c2aeb0SSepherosa Ziehau 				goto nvram_write_end;
192743c2aeb0SSepherosa Ziehau 
192843c2aeb0SSepherosa Ziehau 			cmd_flags = 0;
192943c2aeb0SSepherosa Ziehau 			buf += 4;
193043c2aeb0SSepherosa Ziehau 		}
193143c2aeb0SSepherosa Ziehau 
193243c2aeb0SSepherosa Ziehau 		/* Loop to write back the buffer data from data_end
193343c2aeb0SSepherosa Ziehau 		 * to page_end */
193443c2aeb0SSepherosa Ziehau 		if (sc->bce_flash_info->buffered == 0) {
193543c2aeb0SSepherosa Ziehau 			for (addr = data_end; addr < page_end;
193643c2aeb0SSepherosa Ziehau 			     addr += 4, i += 4) {
193743c2aeb0SSepherosa Ziehau 				if (addr == page_end-4)
193843c2aeb0SSepherosa Ziehau 					cmd_flags = BCE_NVM_COMMAND_LAST;
193943c2aeb0SSepherosa Ziehau 
194043c2aeb0SSepherosa Ziehau 				rc = bce_nvram_write_dword(sc, addr,
194143c2aeb0SSepherosa Ziehau 					&flash_buffer[i], cmd_flags);
194243c2aeb0SSepherosa Ziehau 				if (rc != 0)
194343c2aeb0SSepherosa Ziehau 					goto nvram_write_end;
194443c2aeb0SSepherosa Ziehau 
194543c2aeb0SSepherosa Ziehau 				cmd_flags = 0;
194643c2aeb0SSepherosa Ziehau 			}
194743c2aeb0SSepherosa Ziehau 		}
194843c2aeb0SSepherosa Ziehau 
194943c2aeb0SSepherosa Ziehau 		/* Disable writes to flash interface (lock write-protect) */
195043c2aeb0SSepherosa Ziehau 		bce_disable_nvram_write(sc);
195143c2aeb0SSepherosa Ziehau 
195243c2aeb0SSepherosa Ziehau 		/* Disable access to flash interface */
195343c2aeb0SSepherosa Ziehau 		bce_disable_nvram_access(sc);
195443c2aeb0SSepherosa Ziehau 		bce_release_nvram_lock(sc);
195543c2aeb0SSepherosa Ziehau 
195643c2aeb0SSepherosa Ziehau 		/* Increment written */
195743c2aeb0SSepherosa Ziehau 		written += data_end - data_start;
195843c2aeb0SSepherosa Ziehau 	}
195943c2aeb0SSepherosa Ziehau 
196043c2aeb0SSepherosa Ziehau nvram_write_end:
196143c2aeb0SSepherosa Ziehau 	if (align_start || align_end)
196243c2aeb0SSepherosa Ziehau 		kfree(buf, M_DEVBUF);
196343c2aeb0SSepherosa Ziehau 	return rc;
196443c2aeb0SSepherosa Ziehau }
196543c2aeb0SSepherosa Ziehau #endif /* BCE_NVRAM_WRITE_SUPPORT */
196643c2aeb0SSepherosa Ziehau 
196743c2aeb0SSepherosa Ziehau 
196843c2aeb0SSepherosa Ziehau /****************************************************************************/
196943c2aeb0SSepherosa Ziehau /* Verifies that NVRAM is accessible and contains valid data.               */
197043c2aeb0SSepherosa Ziehau /*                                                                          */
197143c2aeb0SSepherosa Ziehau /* Reads the configuration data from NVRAM and verifies that the CRC is     */
197243c2aeb0SSepherosa Ziehau /* correct.                                                                 */
197343c2aeb0SSepherosa Ziehau /*                                                                          */
197443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
197543c2aeb0SSepherosa Ziehau /*   0 on success, positive value on failure.                               */
197643c2aeb0SSepherosa Ziehau /****************************************************************************/
197743c2aeb0SSepherosa Ziehau static int
197843c2aeb0SSepherosa Ziehau bce_nvram_test(struct bce_softc *sc)
197943c2aeb0SSepherosa Ziehau {
198043c2aeb0SSepherosa Ziehau 	uint32_t buf[BCE_NVRAM_SIZE / 4];
198143c2aeb0SSepherosa Ziehau 	uint32_t magic, csum;
198243c2aeb0SSepherosa Ziehau 	uint8_t *data = (uint8_t *)buf;
198343c2aeb0SSepherosa Ziehau 	int rc = 0;
198443c2aeb0SSepherosa Ziehau 
198543c2aeb0SSepherosa Ziehau 	/*
198643c2aeb0SSepherosa Ziehau 	 * Check that the device NVRAM is valid by reading
198743c2aeb0SSepherosa Ziehau 	 * the magic value at offset 0.
198843c2aeb0SSepherosa Ziehau 	 */
198943c2aeb0SSepherosa Ziehau 	rc = bce_nvram_read(sc, 0, data, 4);
199043c2aeb0SSepherosa Ziehau 	if (rc != 0)
199143c2aeb0SSepherosa Ziehau 		return rc;
199243c2aeb0SSepherosa Ziehau 
199343c2aeb0SSepherosa Ziehau 	magic = be32toh(buf[0]);
199443c2aeb0SSepherosa Ziehau 	if (magic != BCE_NVRAM_MAGIC) {
199543c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
199643c2aeb0SSepherosa Ziehau 			  "Invalid NVRAM magic value! Expected: 0x%08X, "
199743c2aeb0SSepherosa Ziehau 			  "Found: 0x%08X\n", BCE_NVRAM_MAGIC, magic);
199843c2aeb0SSepherosa Ziehau 		return ENODEV;
199943c2aeb0SSepherosa Ziehau 	}
200043c2aeb0SSepherosa Ziehau 
200143c2aeb0SSepherosa Ziehau 	/*
200243c2aeb0SSepherosa Ziehau 	 * Verify that the device NVRAM includes valid
200343c2aeb0SSepherosa Ziehau 	 * configuration data.
200443c2aeb0SSepherosa Ziehau 	 */
200543c2aeb0SSepherosa Ziehau 	rc = bce_nvram_read(sc, 0x100, data, BCE_NVRAM_SIZE);
200643c2aeb0SSepherosa Ziehau 	if (rc != 0)
200743c2aeb0SSepherosa Ziehau 		return rc;
200843c2aeb0SSepherosa Ziehau 
200943c2aeb0SSepherosa Ziehau 	csum = ether_crc32_le(data, 0x100);
201043c2aeb0SSepherosa Ziehau 	if (csum != BCE_CRC32_RESIDUAL) {
201143c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
201243c2aeb0SSepherosa Ziehau 			  "Invalid Manufacturing Information NVRAM CRC! "
201343c2aeb0SSepherosa Ziehau 			  "Expected: 0x%08X, Found: 0x%08X\n",
201443c2aeb0SSepherosa Ziehau 			  BCE_CRC32_RESIDUAL, csum);
201543c2aeb0SSepherosa Ziehau 		return ENODEV;
201643c2aeb0SSepherosa Ziehau 	}
201743c2aeb0SSepherosa Ziehau 
201843c2aeb0SSepherosa Ziehau 	csum = ether_crc32_le(data + 0x100, 0x100);
201943c2aeb0SSepherosa Ziehau 	if (csum != BCE_CRC32_RESIDUAL) {
202043c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
202143c2aeb0SSepherosa Ziehau 			  "Invalid Feature Configuration Information "
202243c2aeb0SSepherosa Ziehau 			  "NVRAM CRC! Expected: 0x%08X, Found: 08%08X\n",
202343c2aeb0SSepherosa Ziehau 			  BCE_CRC32_RESIDUAL, csum);
202443c2aeb0SSepherosa Ziehau 		rc = ENODEV;
202543c2aeb0SSepherosa Ziehau 	}
202643c2aeb0SSepherosa Ziehau 	return rc;
202743c2aeb0SSepherosa Ziehau }
202843c2aeb0SSepherosa Ziehau 
202943c2aeb0SSepherosa Ziehau 
203043c2aeb0SSepherosa Ziehau /****************************************************************************/
203143c2aeb0SSepherosa Ziehau /* Free any DMA memory owned by the driver.                                 */
203243c2aeb0SSepherosa Ziehau /*                                                                          */
203343c2aeb0SSepherosa Ziehau /* Scans through each data structre that requires DMA memory and frees      */
203443c2aeb0SSepherosa Ziehau /* the memory if allocated.                                                 */
203543c2aeb0SSepherosa Ziehau /*                                                                          */
203643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
203743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
203843c2aeb0SSepherosa Ziehau /****************************************************************************/
203943c2aeb0SSepherosa Ziehau static void
204043c2aeb0SSepherosa Ziehau bce_dma_free(struct bce_softc *sc)
204143c2aeb0SSepherosa Ziehau {
204243c2aeb0SSepherosa Ziehau 	int i;
204343c2aeb0SSepherosa Ziehau 
204443c2aeb0SSepherosa Ziehau 	/* Destroy the status block. */
204543c2aeb0SSepherosa Ziehau 	if (sc->status_tag != NULL) {
204643c2aeb0SSepherosa Ziehau 		if (sc->status_block != NULL) {
204743c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->status_tag, sc->status_map);
204843c2aeb0SSepherosa Ziehau 			bus_dmamem_free(sc->status_tag, sc->status_block,
204943c2aeb0SSepherosa Ziehau 					sc->status_map);
205043c2aeb0SSepherosa Ziehau 		}
205143c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->status_tag);
205243c2aeb0SSepherosa Ziehau 	}
205343c2aeb0SSepherosa Ziehau 
205443c2aeb0SSepherosa Ziehau 
205543c2aeb0SSepherosa Ziehau 	/* Destroy the statistics block. */
205643c2aeb0SSepherosa Ziehau 	if (sc->stats_tag != NULL) {
205743c2aeb0SSepherosa Ziehau 		if (sc->stats_block != NULL) {
205843c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->stats_tag, sc->stats_map);
205943c2aeb0SSepherosa Ziehau 			bus_dmamem_free(sc->stats_tag, sc->stats_block,
206043c2aeb0SSepherosa Ziehau 					sc->stats_map);
206143c2aeb0SSepherosa Ziehau 		}
206243c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->stats_tag);
206343c2aeb0SSepherosa Ziehau 	}
206443c2aeb0SSepherosa Ziehau 
206543c2aeb0SSepherosa Ziehau 	/* Destroy the TX buffer descriptor DMA stuffs. */
206643c2aeb0SSepherosa Ziehau 	if (sc->tx_bd_chain_tag != NULL) {
206743c2aeb0SSepherosa Ziehau 		for (i = 0; i < TX_PAGES; i++) {
206843c2aeb0SSepherosa Ziehau 			if (sc->tx_bd_chain[i] != NULL) {
206943c2aeb0SSepherosa Ziehau 				bus_dmamap_unload(sc->tx_bd_chain_tag,
207043c2aeb0SSepherosa Ziehau 						  sc->tx_bd_chain_map[i]);
207143c2aeb0SSepherosa Ziehau 				bus_dmamem_free(sc->tx_bd_chain_tag,
207243c2aeb0SSepherosa Ziehau 						sc->tx_bd_chain[i],
207343c2aeb0SSepherosa Ziehau 						sc->tx_bd_chain_map[i]);
207443c2aeb0SSepherosa Ziehau 			}
207543c2aeb0SSepherosa Ziehau 		}
207643c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->tx_bd_chain_tag);
207743c2aeb0SSepherosa Ziehau 	}
207843c2aeb0SSepherosa Ziehau 
207943c2aeb0SSepherosa Ziehau 	/* Destroy the RX buffer descriptor DMA stuffs. */
208043c2aeb0SSepherosa Ziehau 	if (sc->rx_bd_chain_tag != NULL) {
208143c2aeb0SSepherosa Ziehau 		for (i = 0; i < RX_PAGES; i++) {
208243c2aeb0SSepherosa Ziehau 			if (sc->rx_bd_chain[i] != NULL) {
208343c2aeb0SSepherosa Ziehau 				bus_dmamap_unload(sc->rx_bd_chain_tag,
208443c2aeb0SSepherosa Ziehau 						  sc->rx_bd_chain_map[i]);
208543c2aeb0SSepherosa Ziehau 				bus_dmamem_free(sc->rx_bd_chain_tag,
208643c2aeb0SSepherosa Ziehau 						sc->rx_bd_chain[i],
208743c2aeb0SSepherosa Ziehau 						sc->rx_bd_chain_map[i]);
208843c2aeb0SSepherosa Ziehau 			}
208943c2aeb0SSepherosa Ziehau 		}
209043c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->rx_bd_chain_tag);
209143c2aeb0SSepherosa Ziehau 	}
209243c2aeb0SSepherosa Ziehau 
209343c2aeb0SSepherosa Ziehau 	/* Destroy the TX mbuf DMA stuffs. */
209443c2aeb0SSepherosa Ziehau 	if (sc->tx_mbuf_tag != NULL) {
209543c2aeb0SSepherosa Ziehau 		for (i = 0; i < TOTAL_TX_BD; i++) {
209643c2aeb0SSepherosa Ziehau 			/* Must have been unloaded in bce_stop() */
209743c2aeb0SSepherosa Ziehau 			KKASSERT(sc->tx_mbuf_ptr[i] == NULL);
209843c2aeb0SSepherosa Ziehau 			bus_dmamap_destroy(sc->tx_mbuf_tag,
209943c2aeb0SSepherosa Ziehau 					   sc->tx_mbuf_map[i]);
210043c2aeb0SSepherosa Ziehau 		}
210143c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->tx_mbuf_tag);
210243c2aeb0SSepherosa Ziehau 	}
210343c2aeb0SSepherosa Ziehau 
210443c2aeb0SSepherosa Ziehau 	/* Destroy the RX mbuf DMA stuffs. */
210543c2aeb0SSepherosa Ziehau 	if (sc->rx_mbuf_tag != NULL) {
210643c2aeb0SSepherosa Ziehau 		for (i = 0; i < TOTAL_RX_BD; i++) {
210743c2aeb0SSepherosa Ziehau 			/* Must have been unloaded in bce_stop() */
210843c2aeb0SSepherosa Ziehau 			KKASSERT(sc->rx_mbuf_ptr[i] == NULL);
210943c2aeb0SSepherosa Ziehau 			bus_dmamap_destroy(sc->rx_mbuf_tag,
211043c2aeb0SSepherosa Ziehau 					   sc->rx_mbuf_map[i]);
211143c2aeb0SSepherosa Ziehau 		}
211243c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->rx_mbuf_tag);
211343c2aeb0SSepherosa Ziehau 	}
211443c2aeb0SSepherosa Ziehau 
211543c2aeb0SSepherosa Ziehau 	/* Destroy the parent tag */
211643c2aeb0SSepherosa Ziehau 	if (sc->parent_tag != NULL)
211743c2aeb0SSepherosa Ziehau 		bus_dma_tag_destroy(sc->parent_tag);
211843c2aeb0SSepherosa Ziehau }
211943c2aeb0SSepherosa Ziehau 
212043c2aeb0SSepherosa Ziehau 
212143c2aeb0SSepherosa Ziehau /****************************************************************************/
212243c2aeb0SSepherosa Ziehau /* Get DMA memory from the OS.                                              */
212343c2aeb0SSepherosa Ziehau /*                                                                          */
212443c2aeb0SSepherosa Ziehau /* Validates that the OS has provided DMA buffers in response to a          */
212543c2aeb0SSepherosa Ziehau /* bus_dmamap_load() call and saves the physical address of those buffers.  */
212643c2aeb0SSepherosa Ziehau /* When the callback is used the OS will return 0 for the mapping function  */
212743c2aeb0SSepherosa Ziehau /* (bus_dmamap_load()) so we use the value of map_arg->maxsegs to pass any  */
212843c2aeb0SSepherosa Ziehau /* failures back to the caller.                                             */
212943c2aeb0SSepherosa Ziehau /*                                                                          */
213043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
213143c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
213243c2aeb0SSepherosa Ziehau /****************************************************************************/
213343c2aeb0SSepherosa Ziehau static void
213443c2aeb0SSepherosa Ziehau bce_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
213543c2aeb0SSepherosa Ziehau {
213643c2aeb0SSepherosa Ziehau 	bus_addr_t *busaddr = arg;
213743c2aeb0SSepherosa Ziehau 
213843c2aeb0SSepherosa Ziehau 	/*
213943c2aeb0SSepherosa Ziehau 	 * Simulate a mapping failure.
214043c2aeb0SSepherosa Ziehau 	 * XXX not correct.
214143c2aeb0SSepherosa Ziehau 	 */
214243c2aeb0SSepherosa Ziehau 	DBRUNIF(DB_RANDOMTRUE(bce_debug_dma_map_addr_failure),
214343c2aeb0SSepherosa Ziehau 		kprintf("bce: %s(%d): Simulating DMA mapping error.\n",
214443c2aeb0SSepherosa Ziehau 			__FILE__, __LINE__);
214543c2aeb0SSepherosa Ziehau 		error = ENOMEM);
214643c2aeb0SSepherosa Ziehau 
214743c2aeb0SSepherosa Ziehau 	/* Check for an error and signal the caller that an error occurred. */
214843c2aeb0SSepherosa Ziehau 	if (error)
214943c2aeb0SSepherosa Ziehau 		return;
215043c2aeb0SSepherosa Ziehau 
215143c2aeb0SSepherosa Ziehau 	KASSERT(nseg == 1, ("only one segment is allowed\n"));
215243c2aeb0SSepherosa Ziehau 	*busaddr = segs->ds_addr;
215343c2aeb0SSepherosa Ziehau }
215443c2aeb0SSepherosa Ziehau 
215543c2aeb0SSepherosa Ziehau 
215643c2aeb0SSepherosa Ziehau static void
215743c2aeb0SSepherosa Ziehau bce_dma_map_mbuf(void *arg, bus_dma_segment_t *segs, int nsegs,
215843c2aeb0SSepherosa Ziehau 		 bus_size_t mapsz __unused, int error)
215943c2aeb0SSepherosa Ziehau {
216043c2aeb0SSepherosa Ziehau 	struct bce_dmamap_arg *ctx = arg;
216143c2aeb0SSepherosa Ziehau 	int i;
216243c2aeb0SSepherosa Ziehau 
216343c2aeb0SSepherosa Ziehau 	if (error)
216443c2aeb0SSepherosa Ziehau 		return;
216543c2aeb0SSepherosa Ziehau 
216643c2aeb0SSepherosa Ziehau 	if (nsegs > ctx->bce_maxsegs) {
216743c2aeb0SSepherosa Ziehau 		ctx->bce_maxsegs = 0;
216843c2aeb0SSepherosa Ziehau 		return;
216943c2aeb0SSepherosa Ziehau 	}
217043c2aeb0SSepherosa Ziehau 
217143c2aeb0SSepherosa Ziehau 	ctx->bce_maxsegs = nsegs;
217243c2aeb0SSepherosa Ziehau 	for (i = 0; i < nsegs; ++i)
217343c2aeb0SSepherosa Ziehau 		ctx->bce_segs[i] = segs[i];
217443c2aeb0SSepherosa Ziehau }
217543c2aeb0SSepherosa Ziehau 
217643c2aeb0SSepherosa Ziehau 
217743c2aeb0SSepherosa Ziehau /****************************************************************************/
217843c2aeb0SSepherosa Ziehau /* Allocate any DMA memory needed by the driver.                            */
217943c2aeb0SSepherosa Ziehau /*                                                                          */
218043c2aeb0SSepherosa Ziehau /* Allocates DMA memory needed for the various global structures needed by  */
218143c2aeb0SSepherosa Ziehau /* hardware.                                                                */
218243c2aeb0SSepherosa Ziehau /*                                                                          */
218343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
218443c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
218543c2aeb0SSepherosa Ziehau /****************************************************************************/
218643c2aeb0SSepherosa Ziehau static int
218743c2aeb0SSepherosa Ziehau bce_dma_alloc(struct bce_softc *sc)
218843c2aeb0SSepherosa Ziehau {
218943c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
219043c2aeb0SSepherosa Ziehau 	int i, j, rc = 0;
219143c2aeb0SSepherosa Ziehau 	bus_addr_t busaddr;
219243c2aeb0SSepherosa Ziehau 
219343c2aeb0SSepherosa Ziehau 	/*
219443c2aeb0SSepherosa Ziehau 	 * Allocate the parent bus DMA tag appropriate for PCI.
219543c2aeb0SSepherosa Ziehau 	 */
219643c2aeb0SSepherosa Ziehau 	rc = bus_dma_tag_create(NULL, 1, BCE_DMA_BOUNDARY,
219743c2aeb0SSepherosa Ziehau 				sc->max_bus_addr, BUS_SPACE_MAXADDR,
219843c2aeb0SSepherosa Ziehau 				NULL, NULL,
2199*45010e4dSSepherosa Ziehau 				BUS_SPACE_MAXSIZE_32BIT, 0,
220043c2aeb0SSepherosa Ziehau 				BUS_SPACE_MAXSIZE_32BIT,
220143c2aeb0SSepherosa Ziehau 				0, &sc->parent_tag);
220243c2aeb0SSepherosa Ziehau 	if (rc != 0) {
220343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate parent DMA tag!\n");
220443c2aeb0SSepherosa Ziehau 		return rc;
220543c2aeb0SSepherosa Ziehau 	}
220643c2aeb0SSepherosa Ziehau 
220743c2aeb0SSepherosa Ziehau 	/*
220843c2aeb0SSepherosa Ziehau 	 * Create a DMA tag for the status block, allocate and clear the
220943c2aeb0SSepherosa Ziehau 	 * memory, map the memory into DMA space, and fetch the physical
221043c2aeb0SSepherosa Ziehau 	 * address of the block.
221143c2aeb0SSepherosa Ziehau 	 */
221243c2aeb0SSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag,
221343c2aeb0SSepherosa Ziehau 				BCE_DMA_ALIGN, BCE_DMA_BOUNDARY,
221443c2aeb0SSepherosa Ziehau 				sc->max_bus_addr, BUS_SPACE_MAXADDR,
221543c2aeb0SSepherosa Ziehau 				NULL, NULL,
221643c2aeb0SSepherosa Ziehau 				BCE_STATUS_BLK_SZ, 1, BCE_STATUS_BLK_SZ,
221743c2aeb0SSepherosa Ziehau 				0, &sc->status_tag);
221843c2aeb0SSepherosa Ziehau 	if (rc != 0) {
221943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate status block DMA tag!\n");
222043c2aeb0SSepherosa Ziehau 		return rc;
222143c2aeb0SSepherosa Ziehau 	}
222243c2aeb0SSepherosa Ziehau 
222343c2aeb0SSepherosa Ziehau 	rc = bus_dmamem_alloc(sc->status_tag, (void **)&sc->status_block,
222443c2aeb0SSepherosa Ziehau 			      BUS_DMA_WAITOK | BUS_DMA_ZERO,
222543c2aeb0SSepherosa Ziehau 			      &sc->status_map);
222643c2aeb0SSepherosa Ziehau 	if (rc != 0) {
222743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate status block DMA memory!\n");
222843c2aeb0SSepherosa Ziehau 		return rc;
222943c2aeb0SSepherosa Ziehau 	}
223043c2aeb0SSepherosa Ziehau 
223143c2aeb0SSepherosa Ziehau 	rc = bus_dmamap_load(sc->status_tag, sc->status_map,
223243c2aeb0SSepherosa Ziehau 			     sc->status_block, BCE_STATUS_BLK_SZ,
223343c2aeb0SSepherosa Ziehau 			     bce_dma_map_addr, &busaddr, BUS_DMA_WAITOK);
223443c2aeb0SSepherosa Ziehau 	if (rc != 0) {
223543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not map status block DMA memory!\n");
223643c2aeb0SSepherosa Ziehau 		bus_dmamem_free(sc->status_tag, sc->status_block,
223743c2aeb0SSepherosa Ziehau 				sc->status_map);
223843c2aeb0SSepherosa Ziehau 		sc->status_block = NULL;
223943c2aeb0SSepherosa Ziehau 		return rc;
224043c2aeb0SSepherosa Ziehau 	}
224143c2aeb0SSepherosa Ziehau 
224243c2aeb0SSepherosa Ziehau 	sc->status_block_paddr = busaddr;
224343c2aeb0SSepherosa Ziehau 	/* DRC - Fix for 64 bit addresses. */
224443c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "status_block_paddr = 0x%08X\n",
224543c2aeb0SSepherosa Ziehau 		(uint32_t)sc->status_block_paddr);
224643c2aeb0SSepherosa Ziehau 
224743c2aeb0SSepherosa Ziehau 	/*
224843c2aeb0SSepherosa Ziehau 	 * Create a DMA tag for the statistics block, allocate and clear the
224943c2aeb0SSepherosa Ziehau 	 * memory, map the memory into DMA space, and fetch the physical
225043c2aeb0SSepherosa Ziehau 	 * address of the block.
225143c2aeb0SSepherosa Ziehau 	 */
225243c2aeb0SSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag,
225343c2aeb0SSepherosa Ziehau 				BCE_DMA_ALIGN, BCE_DMA_BOUNDARY,
225443c2aeb0SSepherosa Ziehau 				sc->max_bus_addr, BUS_SPACE_MAXADDR,
225543c2aeb0SSepherosa Ziehau 				NULL, NULL,
225643c2aeb0SSepherosa Ziehau 				BCE_STATS_BLK_SZ, 1, BCE_STATS_BLK_SZ,
225743c2aeb0SSepherosa Ziehau 				0, &sc->stats_tag);
225843c2aeb0SSepherosa Ziehau 	if (rc != 0) {
225943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate "
226043c2aeb0SSepherosa Ziehau 			  "statistics block DMA tag!\n");
226143c2aeb0SSepherosa Ziehau 		return rc;
226243c2aeb0SSepherosa Ziehau 	}
226343c2aeb0SSepherosa Ziehau 
226443c2aeb0SSepherosa Ziehau 	rc = bus_dmamem_alloc(sc->stats_tag, (void **)&sc->stats_block,
226543c2aeb0SSepherosa Ziehau 			      BUS_DMA_WAITOK | BUS_DMA_ZERO,
226643c2aeb0SSepherosa Ziehau 			      &sc->stats_map);
226743c2aeb0SSepherosa Ziehau 	if (rc != 0) {
226843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate "
226943c2aeb0SSepherosa Ziehau 			  "statistics block DMA memory!\n");
227043c2aeb0SSepherosa Ziehau 		return rc;
227143c2aeb0SSepherosa Ziehau 	}
227243c2aeb0SSepherosa Ziehau 
227343c2aeb0SSepherosa Ziehau 	rc = bus_dmamap_load(sc->stats_tag, sc->stats_map,
227443c2aeb0SSepherosa Ziehau 			     sc->stats_block, BCE_STATS_BLK_SZ,
227543c2aeb0SSepherosa Ziehau 			     bce_dma_map_addr, &busaddr, BUS_DMA_WAITOK);
227643c2aeb0SSepherosa Ziehau 	if (rc != 0) {
227743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not map statistics block DMA memory!\n");
227843c2aeb0SSepherosa Ziehau 		bus_dmamem_free(sc->stats_tag, sc->stats_block, sc->stats_map);
227943c2aeb0SSepherosa Ziehau 		sc->stats_block = NULL;
228043c2aeb0SSepherosa Ziehau 		return rc;
228143c2aeb0SSepherosa Ziehau 	}
228243c2aeb0SSepherosa Ziehau 
228343c2aeb0SSepherosa Ziehau 	sc->stats_block_paddr = busaddr;
228443c2aeb0SSepherosa Ziehau 	/* DRC - Fix for 64 bit address. */
228543c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "stats_block_paddr = 0x%08X\n",
228643c2aeb0SSepherosa Ziehau 		(uint32_t)sc->stats_block_paddr);
228743c2aeb0SSepherosa Ziehau 
228843c2aeb0SSepherosa 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 	 */
229343c2aeb0SSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag,
229443c2aeb0SSepherosa Ziehau 				BCM_PAGE_SIZE, BCE_DMA_BOUNDARY,
229543c2aeb0SSepherosa Ziehau 				sc->max_bus_addr, BUS_SPACE_MAXADDR,
229643c2aeb0SSepherosa Ziehau 				NULL, NULL,
229743c2aeb0SSepherosa Ziehau 				BCE_TX_CHAIN_PAGE_SZ, 1, BCE_TX_CHAIN_PAGE_SZ,
229843c2aeb0SSepherosa Ziehau 				0, &sc->tx_bd_chain_tag);
229943c2aeb0SSepherosa Ziehau 	if (rc != 0) {
230043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate "
230143c2aeb0SSepherosa Ziehau 			  "TX descriptor chain DMA tag!\n");
230243c2aeb0SSepherosa Ziehau 		return rc;
230343c2aeb0SSepherosa Ziehau 	}
230443c2aeb0SSepherosa Ziehau 
230543c2aeb0SSepherosa Ziehau 	for (i = 0; i < TX_PAGES; i++) {
230643c2aeb0SSepherosa Ziehau 		rc = bus_dmamem_alloc(sc->tx_bd_chain_tag,
230743c2aeb0SSepherosa Ziehau 				      (void **)&sc->tx_bd_chain[i],
230843c2aeb0SSepherosa Ziehau 				      BUS_DMA_WAITOK, &sc->tx_bd_chain_map[i]);
230943c2aeb0SSepherosa Ziehau 		if (rc != 0) {
231043c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Could not allocate %dth TX descriptor "
231143c2aeb0SSepherosa Ziehau 				  "chain DMA memory!\n", i);
231243c2aeb0SSepherosa Ziehau 			return rc;
231343c2aeb0SSepherosa Ziehau 		}
231443c2aeb0SSepherosa Ziehau 
231543c2aeb0SSepherosa Ziehau 		rc = bus_dmamap_load(sc->tx_bd_chain_tag,
231643c2aeb0SSepherosa Ziehau 				     sc->tx_bd_chain_map[i],
231743c2aeb0SSepherosa Ziehau 				     sc->tx_bd_chain[i], BCE_TX_CHAIN_PAGE_SZ,
231843c2aeb0SSepherosa Ziehau 				     bce_dma_map_addr, &busaddr,
231943c2aeb0SSepherosa Ziehau 				     BUS_DMA_WAITOK);
232043c2aeb0SSepherosa Ziehau 		if (rc != 0) {
232143c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Could not map %dth TX descriptor "
232243c2aeb0SSepherosa Ziehau 				  "chain DMA memory!\n", i);
232343c2aeb0SSepherosa Ziehau 			bus_dmamem_free(sc->tx_bd_chain_tag,
232443c2aeb0SSepherosa Ziehau 					sc->tx_bd_chain[i],
232543c2aeb0SSepherosa Ziehau 					sc->tx_bd_chain_map[i]);
232643c2aeb0SSepherosa Ziehau 			sc->tx_bd_chain[i] = NULL;
232743c2aeb0SSepherosa Ziehau 			return rc;
232843c2aeb0SSepherosa Ziehau 		}
232943c2aeb0SSepherosa Ziehau 
233043c2aeb0SSepherosa Ziehau 		sc->tx_bd_chain_paddr[i] = busaddr;
233143c2aeb0SSepherosa Ziehau 		/* DRC - Fix for 64 bit systems. */
233243c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "tx_bd_chain_paddr[%d] = 0x%08X\n",
233343c2aeb0SSepherosa Ziehau 			i, (uint32_t)sc->tx_bd_chain_paddr[i]);
233443c2aeb0SSepherosa Ziehau 	}
233543c2aeb0SSepherosa Ziehau 
233643c2aeb0SSepherosa Ziehau 	/* Create a DMA tag for TX mbufs. */
2337*45010e4dSSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag, 1, 0,
2338*45010e4dSSepherosa Ziehau 				BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
233943c2aeb0SSepherosa Ziehau 				NULL, NULL,
2340*45010e4dSSepherosa Ziehau 				/* BCE_MAX_JUMBO_ETHER_MTU_VLAN */MCLBYTES,
234143c2aeb0SSepherosa Ziehau 				BCE_MAX_SEGMENTS, MCLBYTES,
2342*45010e4dSSepherosa Ziehau 				BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK |
2343*45010e4dSSepherosa Ziehau 				BUS_DMA_ONEBPAGE,
2344*45010e4dSSepherosa Ziehau 				&sc->tx_mbuf_tag);
234543c2aeb0SSepherosa Ziehau 	if (rc != 0) {
234643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate TX mbuf DMA tag!\n");
234743c2aeb0SSepherosa Ziehau 		return rc;
234843c2aeb0SSepherosa Ziehau 	}
234943c2aeb0SSepherosa Ziehau 
235043c2aeb0SSepherosa Ziehau 	/* Create DMA maps for the TX mbufs clusters. */
235143c2aeb0SSepherosa Ziehau 	for (i = 0; i < TOTAL_TX_BD; i++) {
2352*45010e4dSSepherosa Ziehau 		rc = bus_dmamap_create(sc->tx_mbuf_tag,
2353*45010e4dSSepherosa Ziehau 				       BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE,
235443c2aeb0SSepherosa Ziehau 				       &sc->tx_mbuf_map[i]);
235543c2aeb0SSepherosa Ziehau 		if (rc != 0) {
235643c2aeb0SSepherosa Ziehau 			for (j = 0; j < i; ++j) {
235743c2aeb0SSepherosa Ziehau 				bus_dmamap_destroy(sc->tx_mbuf_tag,
235843c2aeb0SSepherosa Ziehau 						   sc->tx_mbuf_map[i]);
235943c2aeb0SSepherosa Ziehau 			}
236043c2aeb0SSepherosa Ziehau 			bus_dma_tag_destroy(sc->tx_mbuf_tag);
236143c2aeb0SSepherosa Ziehau 			sc->tx_mbuf_tag = NULL;
236243c2aeb0SSepherosa Ziehau 
236343c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Unable to create "
236443c2aeb0SSepherosa Ziehau 				  "%dth TX mbuf DMA map!\n", i);
236543c2aeb0SSepherosa Ziehau 			return rc;
236643c2aeb0SSepherosa Ziehau 		}
236743c2aeb0SSepherosa Ziehau 	}
236843c2aeb0SSepherosa Ziehau 
236943c2aeb0SSepherosa Ziehau 	/*
237043c2aeb0SSepherosa Ziehau 	 * Create a DMA tag for the RX buffer descriptor chain,
237143c2aeb0SSepherosa Ziehau 	 * allocate and clear the  memory, and fetch the physical
237243c2aeb0SSepherosa Ziehau 	 * address of the blocks.
237343c2aeb0SSepherosa Ziehau 	 */
237443c2aeb0SSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag,
237543c2aeb0SSepherosa Ziehau 				BCM_PAGE_SIZE, BCE_DMA_BOUNDARY,
237643c2aeb0SSepherosa Ziehau 				sc->max_bus_addr, BUS_SPACE_MAXADDR,
237743c2aeb0SSepherosa Ziehau 				NULL, NULL,
237843c2aeb0SSepherosa Ziehau 				BCE_RX_CHAIN_PAGE_SZ, 1, BCE_RX_CHAIN_PAGE_SZ,
237943c2aeb0SSepherosa Ziehau 				0, &sc->rx_bd_chain_tag);
238043c2aeb0SSepherosa Ziehau 	if (rc != 0) {
238143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate "
238243c2aeb0SSepherosa Ziehau 			  "RX descriptor chain DMA tag!\n");
238343c2aeb0SSepherosa Ziehau 		return rc;
238443c2aeb0SSepherosa Ziehau 	}
238543c2aeb0SSepherosa Ziehau 
238643c2aeb0SSepherosa Ziehau 	for (i = 0; i < RX_PAGES; i++) {
238743c2aeb0SSepherosa Ziehau 		rc = bus_dmamem_alloc(sc->rx_bd_chain_tag,
238843c2aeb0SSepherosa Ziehau 				      (void **)&sc->rx_bd_chain[i],
238943c2aeb0SSepherosa Ziehau 				      BUS_DMA_WAITOK | BUS_DMA_ZERO,
239043c2aeb0SSepherosa Ziehau 				      &sc->rx_bd_chain_map[i]);
239143c2aeb0SSepherosa Ziehau 		if (rc != 0) {
239243c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Could not allocate %dth RX descriptor "
239343c2aeb0SSepherosa Ziehau 				  "chain DMA memory!\n", i);
239443c2aeb0SSepherosa Ziehau 			return rc;
239543c2aeb0SSepherosa Ziehau 		}
239643c2aeb0SSepherosa Ziehau 
239743c2aeb0SSepherosa Ziehau 		rc = bus_dmamap_load(sc->rx_bd_chain_tag,
239843c2aeb0SSepherosa Ziehau 				     sc->rx_bd_chain_map[i],
239943c2aeb0SSepherosa Ziehau 				     sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ,
240043c2aeb0SSepherosa Ziehau 				     bce_dma_map_addr, &busaddr,
240143c2aeb0SSepherosa Ziehau 				     BUS_DMA_WAITOK);
240243c2aeb0SSepherosa Ziehau 		if (rc != 0) {
240343c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Could not map %dth RX descriptor "
240443c2aeb0SSepherosa Ziehau 				  "chain DMA memory!\n", i);
240543c2aeb0SSepherosa Ziehau 			bus_dmamem_free(sc->rx_bd_chain_tag,
240643c2aeb0SSepherosa Ziehau 					sc->rx_bd_chain[i],
240743c2aeb0SSepherosa Ziehau 					sc->rx_bd_chain_map[i]);
240843c2aeb0SSepherosa Ziehau 			sc->rx_bd_chain[i] = NULL;
240943c2aeb0SSepherosa Ziehau 			return rc;
241043c2aeb0SSepherosa Ziehau 		}
241143c2aeb0SSepherosa Ziehau 
241243c2aeb0SSepherosa Ziehau 		sc->rx_bd_chain_paddr[i] = busaddr;
241343c2aeb0SSepherosa Ziehau 		/* DRC - Fix for 64 bit systems. */
241443c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "rx_bd_chain_paddr[%d] = 0x%08X\n",
241543c2aeb0SSepherosa Ziehau 			i, (uint32_t)sc->rx_bd_chain_paddr[i]);
241643c2aeb0SSepherosa Ziehau 	}
241743c2aeb0SSepherosa Ziehau 
241843c2aeb0SSepherosa Ziehau 	/* Create a DMA tag for RX mbufs. */
2419*45010e4dSSepherosa Ziehau 	rc = bus_dma_tag_create(sc->parent_tag, 1, 0,
2420*45010e4dSSepherosa Ziehau 				BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
242143c2aeb0SSepherosa Ziehau 				NULL, NULL,
2422*45010e4dSSepherosa Ziehau 				MCLBYTES, 1, MCLBYTES,
2423*45010e4dSSepherosa Ziehau 				BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK,
2424*45010e4dSSepherosa Ziehau 				&sc->rx_mbuf_tag);
242543c2aeb0SSepherosa Ziehau 	if (rc != 0) {
242643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Could not allocate RX mbuf DMA tag!\n");
242743c2aeb0SSepherosa Ziehau 		return rc;
242843c2aeb0SSepherosa Ziehau 	}
242943c2aeb0SSepherosa Ziehau 
243043c2aeb0SSepherosa Ziehau 	/* Create DMA maps for the RX mbuf clusters. */
243143c2aeb0SSepherosa Ziehau 	for (i = 0; i < TOTAL_RX_BD; i++) {
243243c2aeb0SSepherosa Ziehau 		rc = bus_dmamap_create(sc->rx_mbuf_tag, BUS_DMA_WAITOK,
243343c2aeb0SSepherosa Ziehau 				       &sc->rx_mbuf_map[i]);
243443c2aeb0SSepherosa Ziehau 		if (rc != 0) {
243543c2aeb0SSepherosa Ziehau 			for (j = 0; j < i; ++j) {
243643c2aeb0SSepherosa Ziehau 				bus_dmamap_destroy(sc->rx_mbuf_tag,
243743c2aeb0SSepherosa Ziehau 						   sc->rx_mbuf_map[j]);
243843c2aeb0SSepherosa Ziehau 			}
243943c2aeb0SSepherosa Ziehau 			bus_dma_tag_destroy(sc->rx_mbuf_tag);
244043c2aeb0SSepherosa Ziehau 			sc->rx_mbuf_tag = NULL;
244143c2aeb0SSepherosa Ziehau 
244243c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Unable to create "
244343c2aeb0SSepherosa Ziehau 				  "%dth RX mbuf DMA map!\n", i);
244443c2aeb0SSepherosa Ziehau 			return rc;
244543c2aeb0SSepherosa Ziehau 		}
244643c2aeb0SSepherosa Ziehau 	}
244743c2aeb0SSepherosa Ziehau 	return 0;
244843c2aeb0SSepherosa Ziehau }
244943c2aeb0SSepherosa Ziehau 
245043c2aeb0SSepherosa Ziehau 
245143c2aeb0SSepherosa Ziehau /****************************************************************************/
245243c2aeb0SSepherosa Ziehau /* Firmware synchronization.                                                */
245343c2aeb0SSepherosa Ziehau /*                                                                          */
245443c2aeb0SSepherosa Ziehau /* Before performing certain events such as a chip reset, synchronize with  */
245543c2aeb0SSepherosa Ziehau /* the firmware first.                                                      */
245643c2aeb0SSepherosa Ziehau /*                                                                          */
245743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
245843c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
245943c2aeb0SSepherosa Ziehau /****************************************************************************/
246043c2aeb0SSepherosa Ziehau static int
246143c2aeb0SSepherosa Ziehau bce_fw_sync(struct bce_softc *sc, uint32_t msg_data)
246243c2aeb0SSepherosa Ziehau {
246343c2aeb0SSepherosa Ziehau 	int i, rc = 0;
246443c2aeb0SSepherosa Ziehau 	uint32_t val;
246543c2aeb0SSepherosa Ziehau 
246643c2aeb0SSepherosa Ziehau 	/* Don't waste any time if we've timed out before. */
246743c2aeb0SSepherosa Ziehau 	if (sc->bce_fw_timed_out)
246843c2aeb0SSepherosa Ziehau 		return EBUSY;
246943c2aeb0SSepherosa Ziehau 
247043c2aeb0SSepherosa Ziehau 	/* Increment the message sequence number. */
247143c2aeb0SSepherosa Ziehau 	sc->bce_fw_wr_seq++;
247243c2aeb0SSepherosa Ziehau 	msg_data |= sc->bce_fw_wr_seq;
247343c2aeb0SSepherosa Ziehau 
247443c2aeb0SSepherosa Ziehau  	DBPRINT(sc, BCE_VERBOSE, "bce_fw_sync(): msg_data = 0x%08X\n", msg_data);
247543c2aeb0SSepherosa Ziehau 
247643c2aeb0SSepherosa Ziehau 	/* Send the message to the bootcode driver mailbox. */
247743c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_MB, msg_data);
247843c2aeb0SSepherosa Ziehau 
247943c2aeb0SSepherosa Ziehau 	/* Wait for the bootcode to acknowledge the message. */
248043c2aeb0SSepherosa Ziehau 	for (i = 0; i < FW_ACK_TIME_OUT_MS; i++) {
248143c2aeb0SSepherosa Ziehau 		/* Check for a response in the bootcode firmware mailbox. */
248243c2aeb0SSepherosa Ziehau 		val = REG_RD_IND(sc, sc->bce_shmem_base + BCE_FW_MB);
248343c2aeb0SSepherosa Ziehau 		if ((val & BCE_FW_MSG_ACK) == (msg_data & BCE_DRV_MSG_SEQ))
248443c2aeb0SSepherosa Ziehau 			break;
248543c2aeb0SSepherosa Ziehau 		DELAY(1000);
248643c2aeb0SSepherosa Ziehau 	}
248743c2aeb0SSepherosa Ziehau 
248843c2aeb0SSepherosa Ziehau 	/* If we've timed out, tell the bootcode that we've stopped waiting. */
248943c2aeb0SSepherosa Ziehau 	if ((val & BCE_FW_MSG_ACK) != (msg_data & BCE_DRV_MSG_SEQ) &&
249043c2aeb0SSepherosa Ziehau 	    (msg_data & BCE_DRV_MSG_DATA) != BCE_DRV_MSG_DATA_WAIT0) {
249143c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
249243c2aeb0SSepherosa Ziehau 			  "Firmware synchronization timeout! "
249343c2aeb0SSepherosa Ziehau 			  "msg_data = 0x%08X\n", msg_data);
249443c2aeb0SSepherosa Ziehau 
249543c2aeb0SSepherosa Ziehau 		msg_data &= ~BCE_DRV_MSG_CODE;
249643c2aeb0SSepherosa Ziehau 		msg_data |= BCE_DRV_MSG_CODE_FW_TIMEOUT;
249743c2aeb0SSepherosa Ziehau 
249843c2aeb0SSepherosa Ziehau 		REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_MB, msg_data);
249943c2aeb0SSepherosa Ziehau 
250043c2aeb0SSepherosa Ziehau 		sc->bce_fw_timed_out = 1;
250143c2aeb0SSepherosa Ziehau 		rc = EBUSY;
250243c2aeb0SSepherosa Ziehau 	}
250343c2aeb0SSepherosa Ziehau 	return rc;
250443c2aeb0SSepherosa Ziehau }
250543c2aeb0SSepherosa Ziehau 
250643c2aeb0SSepherosa Ziehau 
250743c2aeb0SSepherosa Ziehau /****************************************************************************/
250843c2aeb0SSepherosa Ziehau /* Load Receive Virtual 2 Physical (RV2P) processor firmware.               */
250943c2aeb0SSepherosa Ziehau /*                                                                          */
251043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
251143c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
251243c2aeb0SSepherosa Ziehau /****************************************************************************/
251343c2aeb0SSepherosa Ziehau static void
251443c2aeb0SSepherosa Ziehau bce_load_rv2p_fw(struct bce_softc *sc, uint32_t *rv2p_code,
251543c2aeb0SSepherosa Ziehau 		 uint32_t rv2p_code_len, uint32_t rv2p_proc)
251643c2aeb0SSepherosa Ziehau {
251743c2aeb0SSepherosa Ziehau 	int i;
251843c2aeb0SSepherosa Ziehau 	uint32_t val;
251943c2aeb0SSepherosa Ziehau 
252043c2aeb0SSepherosa Ziehau 	for (i = 0; i < rv2p_code_len; i += 8) {
252143c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_RV2P_INSTR_HIGH, *rv2p_code);
252243c2aeb0SSepherosa Ziehau 		rv2p_code++;
252343c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_RV2P_INSTR_LOW, *rv2p_code);
252443c2aeb0SSepherosa Ziehau 		rv2p_code++;
252543c2aeb0SSepherosa Ziehau 
252643c2aeb0SSepherosa Ziehau 		if (rv2p_proc == RV2P_PROC1) {
252743c2aeb0SSepherosa Ziehau 			val = (i / 8) | BCE_RV2P_PROC1_ADDR_CMD_RDWR;
252843c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_RV2P_PROC1_ADDR_CMD, val);
252943c2aeb0SSepherosa Ziehau 		} else {
253043c2aeb0SSepherosa Ziehau 			val = (i / 8) | BCE_RV2P_PROC2_ADDR_CMD_RDWR;
253143c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_RV2P_PROC2_ADDR_CMD, val);
253243c2aeb0SSepherosa Ziehau 		}
253343c2aeb0SSepherosa Ziehau 	}
253443c2aeb0SSepherosa Ziehau 
253543c2aeb0SSepherosa Ziehau 	/* Reset the processor, un-stall is done later. */
253643c2aeb0SSepherosa Ziehau 	if (rv2p_proc == RV2P_PROC1)
253743c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC1_RESET);
253843c2aeb0SSepherosa Ziehau 	else
253943c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC2_RESET);
254043c2aeb0SSepherosa Ziehau }
254143c2aeb0SSepherosa Ziehau 
254243c2aeb0SSepherosa Ziehau 
254343c2aeb0SSepherosa Ziehau /****************************************************************************/
254443c2aeb0SSepherosa Ziehau /* Load RISC processor firmware.                                            */
254543c2aeb0SSepherosa Ziehau /*                                                                          */
254643c2aeb0SSepherosa Ziehau /* Loads firmware from the file if_bcefw.h into the scratchpad memory       */
254743c2aeb0SSepherosa Ziehau /* associated with a particular processor.                                  */
254843c2aeb0SSepherosa Ziehau /*                                                                          */
254943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
255043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
255143c2aeb0SSepherosa Ziehau /****************************************************************************/
255243c2aeb0SSepherosa Ziehau static void
255343c2aeb0SSepherosa Ziehau bce_load_cpu_fw(struct bce_softc *sc, struct cpu_reg *cpu_reg,
255443c2aeb0SSepherosa Ziehau 		struct fw_info *fw)
255543c2aeb0SSepherosa Ziehau {
255643c2aeb0SSepherosa Ziehau 	uint32_t offset, val;
255743c2aeb0SSepherosa Ziehau 	int j;
255843c2aeb0SSepherosa Ziehau 
255943c2aeb0SSepherosa Ziehau 	/* Halt the CPU. */
256043c2aeb0SSepherosa Ziehau 	val = REG_RD_IND(sc, cpu_reg->mode);
256143c2aeb0SSepherosa Ziehau 	val |= cpu_reg->mode_value_halt;
256243c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->mode, val);
256343c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear);
256443c2aeb0SSepherosa Ziehau 
256543c2aeb0SSepherosa Ziehau 	/* Load the Text area. */
256643c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
256743c2aeb0SSepherosa Ziehau 	if (fw->text) {
256843c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->text_len / 4); j++, offset += 4)
256943c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->text[j]);
257043c2aeb0SSepherosa Ziehau 	}
257143c2aeb0SSepherosa Ziehau 
257243c2aeb0SSepherosa Ziehau 	/* Load the Data area. */
257343c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
257443c2aeb0SSepherosa Ziehau 	if (fw->data) {
257543c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->data_len / 4); j++, offset += 4)
257643c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->data[j]);
257743c2aeb0SSepherosa Ziehau 	}
257843c2aeb0SSepherosa Ziehau 
257943c2aeb0SSepherosa Ziehau 	/* Load the SBSS area. */
258043c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
258143c2aeb0SSepherosa Ziehau 	if (fw->sbss) {
258243c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4)
258343c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->sbss[j]);
258443c2aeb0SSepherosa Ziehau 	}
258543c2aeb0SSepherosa Ziehau 
258643c2aeb0SSepherosa Ziehau 	/* Load the BSS area. */
258743c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
258843c2aeb0SSepherosa Ziehau 	if (fw->bss) {
258943c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->bss_len/4); j++, offset += 4)
259043c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->bss[j]);
259143c2aeb0SSepherosa Ziehau 	}
259243c2aeb0SSepherosa Ziehau 
259343c2aeb0SSepherosa Ziehau 	/* Load the Read-Only area. */
259443c2aeb0SSepherosa Ziehau 	offset = cpu_reg->spad_base +
259543c2aeb0SSepherosa Ziehau 		(fw->rodata_addr - cpu_reg->mips_view_base);
259643c2aeb0SSepherosa Ziehau 	if (fw->rodata) {
259743c2aeb0SSepherosa Ziehau 		for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4)
259843c2aeb0SSepherosa Ziehau 			REG_WR_IND(sc, offset, fw->rodata[j]);
259943c2aeb0SSepherosa Ziehau 	}
260043c2aeb0SSepherosa Ziehau 
260143c2aeb0SSepherosa Ziehau 	/* Clear the pre-fetch instruction. */
260243c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->inst, 0);
260343c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->pc, fw->start_addr);
260443c2aeb0SSepherosa Ziehau 
260543c2aeb0SSepherosa Ziehau 	/* Start the CPU. */
260643c2aeb0SSepherosa Ziehau 	val = REG_RD_IND(sc, cpu_reg->mode);
260743c2aeb0SSepherosa Ziehau 	val &= ~cpu_reg->mode_value_halt;
260843c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear);
260943c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, cpu_reg->mode, val);
261043c2aeb0SSepherosa Ziehau }
261143c2aeb0SSepherosa Ziehau 
261243c2aeb0SSepherosa Ziehau 
261343c2aeb0SSepherosa Ziehau /****************************************************************************/
261443c2aeb0SSepherosa Ziehau /* Initialize the RV2P, RX, TX, TPAT, and COM CPUs.                         */
261543c2aeb0SSepherosa Ziehau /*                                                                          */
261643c2aeb0SSepherosa Ziehau /* Loads the firmware for each CPU and starts the CPU.                      */
261743c2aeb0SSepherosa Ziehau /*                                                                          */
261843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
261943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
262043c2aeb0SSepherosa Ziehau /****************************************************************************/
262143c2aeb0SSepherosa Ziehau static void
262243c2aeb0SSepherosa Ziehau bce_init_cpus(struct bce_softc *sc)
262343c2aeb0SSepherosa Ziehau {
262443c2aeb0SSepherosa Ziehau 	struct cpu_reg cpu_reg;
262543c2aeb0SSepherosa Ziehau 	struct fw_info fw;
262643c2aeb0SSepherosa Ziehau 
262743c2aeb0SSepherosa Ziehau 	/* Initialize the RV2P processor. */
262843c2aeb0SSepherosa Ziehau 	bce_load_rv2p_fw(sc, bce_rv2p_proc1, sizeof(bce_rv2p_proc1), RV2P_PROC1);
262943c2aeb0SSepherosa Ziehau 	bce_load_rv2p_fw(sc, bce_rv2p_proc2, sizeof(bce_rv2p_proc2), RV2P_PROC2);
263043c2aeb0SSepherosa Ziehau 
263143c2aeb0SSepherosa Ziehau 	/* Initialize the RX Processor. */
263243c2aeb0SSepherosa Ziehau 	cpu_reg.mode = BCE_RXP_CPU_MODE;
263343c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_RXP_CPU_MODE_SOFT_HALT;
263443c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_RXP_CPU_MODE_STEP_ENA;
263543c2aeb0SSepherosa Ziehau 	cpu_reg.state = BCE_RXP_CPU_STATE;
263643c2aeb0SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
263743c2aeb0SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_RXP_CPU_REG_FILE;
263843c2aeb0SSepherosa Ziehau 	cpu_reg.evmask = BCE_RXP_CPU_EVENT_MASK;
263943c2aeb0SSepherosa Ziehau 	cpu_reg.pc = BCE_RXP_CPU_PROGRAM_COUNTER;
264043c2aeb0SSepherosa Ziehau 	cpu_reg.inst = BCE_RXP_CPU_INSTRUCTION;
264143c2aeb0SSepherosa Ziehau 	cpu_reg.bp = BCE_RXP_CPU_HW_BREAKPOINT;
264243c2aeb0SSepherosa Ziehau 	cpu_reg.spad_base = BCE_RXP_SCRATCH;
264343c2aeb0SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
264443c2aeb0SSepherosa Ziehau 
264543c2aeb0SSepherosa Ziehau 	fw.ver_major = bce_RXP_b06FwReleaseMajor;
264643c2aeb0SSepherosa Ziehau 	fw.ver_minor = bce_RXP_b06FwReleaseMinor;
264743c2aeb0SSepherosa Ziehau 	fw.ver_fix = bce_RXP_b06FwReleaseFix;
264843c2aeb0SSepherosa Ziehau 	fw.start_addr = bce_RXP_b06FwStartAddr;
264943c2aeb0SSepherosa Ziehau 
265043c2aeb0SSepherosa Ziehau 	fw.text_addr = bce_RXP_b06FwTextAddr;
265143c2aeb0SSepherosa Ziehau 	fw.text_len = bce_RXP_b06FwTextLen;
265243c2aeb0SSepherosa Ziehau 	fw.text_index = 0;
265343c2aeb0SSepherosa Ziehau 	fw.text = bce_RXP_b06FwText;
265443c2aeb0SSepherosa Ziehau 
265543c2aeb0SSepherosa Ziehau 	fw.data_addr = bce_RXP_b06FwDataAddr;
265643c2aeb0SSepherosa Ziehau 	fw.data_len = bce_RXP_b06FwDataLen;
265743c2aeb0SSepherosa Ziehau 	fw.data_index = 0;
265843c2aeb0SSepherosa Ziehau 	fw.data = bce_RXP_b06FwData;
265943c2aeb0SSepherosa Ziehau 
266043c2aeb0SSepherosa Ziehau 	fw.sbss_addr = bce_RXP_b06FwSbssAddr;
266143c2aeb0SSepherosa Ziehau 	fw.sbss_len = bce_RXP_b06FwSbssLen;
266243c2aeb0SSepherosa Ziehau 	fw.sbss_index = 0;
266343c2aeb0SSepherosa Ziehau 	fw.sbss = bce_RXP_b06FwSbss;
266443c2aeb0SSepherosa Ziehau 
266543c2aeb0SSepherosa Ziehau 	fw.bss_addr = bce_RXP_b06FwBssAddr;
266643c2aeb0SSepherosa Ziehau 	fw.bss_len = bce_RXP_b06FwBssLen;
266743c2aeb0SSepherosa Ziehau 	fw.bss_index = 0;
266843c2aeb0SSepherosa Ziehau 	fw.bss = bce_RXP_b06FwBss;
266943c2aeb0SSepherosa Ziehau 
267043c2aeb0SSepherosa Ziehau 	fw.rodata_addr = bce_RXP_b06FwRodataAddr;
267143c2aeb0SSepherosa Ziehau 	fw.rodata_len = bce_RXP_b06FwRodataLen;
267243c2aeb0SSepherosa Ziehau 	fw.rodata_index = 0;
267343c2aeb0SSepherosa Ziehau 	fw.rodata = bce_RXP_b06FwRodata;
267443c2aeb0SSepherosa Ziehau 
267543c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RESET, "Loading RX firmware.\n");
267643c2aeb0SSepherosa Ziehau 	bce_load_cpu_fw(sc, &cpu_reg, &fw);
267743c2aeb0SSepherosa Ziehau 
267843c2aeb0SSepherosa Ziehau 	/* Initialize the TX Processor. */
267943c2aeb0SSepherosa Ziehau 	cpu_reg.mode = BCE_TXP_CPU_MODE;
268043c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_TXP_CPU_MODE_SOFT_HALT;
268143c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_TXP_CPU_MODE_STEP_ENA;
268243c2aeb0SSepherosa Ziehau 	cpu_reg.state = BCE_TXP_CPU_STATE;
268343c2aeb0SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
268443c2aeb0SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_TXP_CPU_REG_FILE;
268543c2aeb0SSepherosa Ziehau 	cpu_reg.evmask = BCE_TXP_CPU_EVENT_MASK;
268643c2aeb0SSepherosa Ziehau 	cpu_reg.pc = BCE_TXP_CPU_PROGRAM_COUNTER;
268743c2aeb0SSepherosa Ziehau 	cpu_reg.inst = BCE_TXP_CPU_INSTRUCTION;
268843c2aeb0SSepherosa Ziehau 	cpu_reg.bp = BCE_TXP_CPU_HW_BREAKPOINT;
268943c2aeb0SSepherosa Ziehau 	cpu_reg.spad_base = BCE_TXP_SCRATCH;
269043c2aeb0SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
269143c2aeb0SSepherosa Ziehau 
269243c2aeb0SSepherosa Ziehau 	fw.ver_major = bce_TXP_b06FwReleaseMajor;
269343c2aeb0SSepherosa Ziehau 	fw.ver_minor = bce_TXP_b06FwReleaseMinor;
269443c2aeb0SSepherosa Ziehau 	fw.ver_fix = bce_TXP_b06FwReleaseFix;
269543c2aeb0SSepherosa Ziehau 	fw.start_addr = bce_TXP_b06FwStartAddr;
269643c2aeb0SSepherosa Ziehau 
269743c2aeb0SSepherosa Ziehau 	fw.text_addr = bce_TXP_b06FwTextAddr;
269843c2aeb0SSepherosa Ziehau 	fw.text_len = bce_TXP_b06FwTextLen;
269943c2aeb0SSepherosa Ziehau 	fw.text_index = 0;
270043c2aeb0SSepherosa Ziehau 	fw.text = bce_TXP_b06FwText;
270143c2aeb0SSepherosa Ziehau 
270243c2aeb0SSepherosa Ziehau 	fw.data_addr = bce_TXP_b06FwDataAddr;
270343c2aeb0SSepherosa Ziehau 	fw.data_len = bce_TXP_b06FwDataLen;
270443c2aeb0SSepherosa Ziehau 	fw.data_index = 0;
270543c2aeb0SSepherosa Ziehau 	fw.data = bce_TXP_b06FwData;
270643c2aeb0SSepherosa Ziehau 
270743c2aeb0SSepherosa Ziehau 	fw.sbss_addr = bce_TXP_b06FwSbssAddr;
270843c2aeb0SSepherosa Ziehau 	fw.sbss_len = bce_TXP_b06FwSbssLen;
270943c2aeb0SSepherosa Ziehau 	fw.sbss_index = 0;
271043c2aeb0SSepherosa Ziehau 	fw.sbss = bce_TXP_b06FwSbss;
271143c2aeb0SSepherosa Ziehau 
271243c2aeb0SSepherosa Ziehau 	fw.bss_addr = bce_TXP_b06FwBssAddr;
271343c2aeb0SSepherosa Ziehau 	fw.bss_len = bce_TXP_b06FwBssLen;
271443c2aeb0SSepherosa Ziehau 	fw.bss_index = 0;
271543c2aeb0SSepherosa Ziehau 	fw.bss = bce_TXP_b06FwBss;
271643c2aeb0SSepherosa Ziehau 
271743c2aeb0SSepherosa Ziehau 	fw.rodata_addr = bce_TXP_b06FwRodataAddr;
271843c2aeb0SSepherosa Ziehau 	fw.rodata_len = bce_TXP_b06FwRodataLen;
271943c2aeb0SSepherosa Ziehau 	fw.rodata_index = 0;
272043c2aeb0SSepherosa Ziehau 	fw.rodata = bce_TXP_b06FwRodata;
272143c2aeb0SSepherosa Ziehau 
272243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RESET, "Loading TX firmware.\n");
272343c2aeb0SSepherosa Ziehau 	bce_load_cpu_fw(sc, &cpu_reg, &fw);
272443c2aeb0SSepherosa Ziehau 
272543c2aeb0SSepherosa Ziehau 	/* Initialize the TX Patch-up Processor. */
272643c2aeb0SSepherosa Ziehau 	cpu_reg.mode = BCE_TPAT_CPU_MODE;
272743c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_TPAT_CPU_MODE_SOFT_HALT;
272843c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_TPAT_CPU_MODE_STEP_ENA;
272943c2aeb0SSepherosa Ziehau 	cpu_reg.state = BCE_TPAT_CPU_STATE;
273043c2aeb0SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
273143c2aeb0SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_TPAT_CPU_REG_FILE;
273243c2aeb0SSepherosa Ziehau 	cpu_reg.evmask = BCE_TPAT_CPU_EVENT_MASK;
273343c2aeb0SSepherosa Ziehau 	cpu_reg.pc = BCE_TPAT_CPU_PROGRAM_COUNTER;
273443c2aeb0SSepherosa Ziehau 	cpu_reg.inst = BCE_TPAT_CPU_INSTRUCTION;
273543c2aeb0SSepherosa Ziehau 	cpu_reg.bp = BCE_TPAT_CPU_HW_BREAKPOINT;
273643c2aeb0SSepherosa Ziehau 	cpu_reg.spad_base = BCE_TPAT_SCRATCH;
273743c2aeb0SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
273843c2aeb0SSepherosa Ziehau 
273943c2aeb0SSepherosa Ziehau 	fw.ver_major = bce_TPAT_b06FwReleaseMajor;
274043c2aeb0SSepherosa Ziehau 	fw.ver_minor = bce_TPAT_b06FwReleaseMinor;
274143c2aeb0SSepherosa Ziehau 	fw.ver_fix = bce_TPAT_b06FwReleaseFix;
274243c2aeb0SSepherosa Ziehau 	fw.start_addr = bce_TPAT_b06FwStartAddr;
274343c2aeb0SSepherosa Ziehau 
274443c2aeb0SSepherosa Ziehau 	fw.text_addr = bce_TPAT_b06FwTextAddr;
274543c2aeb0SSepherosa Ziehau 	fw.text_len = bce_TPAT_b06FwTextLen;
274643c2aeb0SSepherosa Ziehau 	fw.text_index = 0;
274743c2aeb0SSepherosa Ziehau 	fw.text = bce_TPAT_b06FwText;
274843c2aeb0SSepherosa Ziehau 
274943c2aeb0SSepherosa Ziehau 	fw.data_addr = bce_TPAT_b06FwDataAddr;
275043c2aeb0SSepherosa Ziehau 	fw.data_len = bce_TPAT_b06FwDataLen;
275143c2aeb0SSepherosa Ziehau 	fw.data_index = 0;
275243c2aeb0SSepherosa Ziehau 	fw.data = bce_TPAT_b06FwData;
275343c2aeb0SSepherosa Ziehau 
275443c2aeb0SSepherosa Ziehau 	fw.sbss_addr = bce_TPAT_b06FwSbssAddr;
275543c2aeb0SSepherosa Ziehau 	fw.sbss_len = bce_TPAT_b06FwSbssLen;
275643c2aeb0SSepherosa Ziehau 	fw.sbss_index = 0;
275743c2aeb0SSepherosa Ziehau 	fw.sbss = bce_TPAT_b06FwSbss;
275843c2aeb0SSepherosa Ziehau 
275943c2aeb0SSepherosa Ziehau 	fw.bss_addr = bce_TPAT_b06FwBssAddr;
276043c2aeb0SSepherosa Ziehau 	fw.bss_len = bce_TPAT_b06FwBssLen;
276143c2aeb0SSepherosa Ziehau 	fw.bss_index = 0;
276243c2aeb0SSepherosa Ziehau 	fw.bss = bce_TPAT_b06FwBss;
276343c2aeb0SSepherosa Ziehau 
276443c2aeb0SSepherosa Ziehau 	fw.rodata_addr = bce_TPAT_b06FwRodataAddr;
276543c2aeb0SSepherosa Ziehau 	fw.rodata_len = bce_TPAT_b06FwRodataLen;
276643c2aeb0SSepherosa Ziehau 	fw.rodata_index = 0;
276743c2aeb0SSepherosa Ziehau 	fw.rodata = bce_TPAT_b06FwRodata;
276843c2aeb0SSepherosa Ziehau 
276943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RESET, "Loading TPAT firmware.\n");
277043c2aeb0SSepherosa Ziehau 	bce_load_cpu_fw(sc, &cpu_reg, &fw);
277143c2aeb0SSepherosa Ziehau 
277243c2aeb0SSepherosa Ziehau 	/* Initialize the Completion Processor. */
277343c2aeb0SSepherosa Ziehau 	cpu_reg.mode = BCE_COM_CPU_MODE;
277443c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_halt = BCE_COM_CPU_MODE_SOFT_HALT;
277543c2aeb0SSepherosa Ziehau 	cpu_reg.mode_value_sstep = BCE_COM_CPU_MODE_STEP_ENA;
277643c2aeb0SSepherosa Ziehau 	cpu_reg.state = BCE_COM_CPU_STATE;
277743c2aeb0SSepherosa Ziehau 	cpu_reg.state_value_clear = 0xffffff;
277843c2aeb0SSepherosa Ziehau 	cpu_reg.gpr0 = BCE_COM_CPU_REG_FILE;
277943c2aeb0SSepherosa Ziehau 	cpu_reg.evmask = BCE_COM_CPU_EVENT_MASK;
278043c2aeb0SSepherosa Ziehau 	cpu_reg.pc = BCE_COM_CPU_PROGRAM_COUNTER;
278143c2aeb0SSepherosa Ziehau 	cpu_reg.inst = BCE_COM_CPU_INSTRUCTION;
278243c2aeb0SSepherosa Ziehau 	cpu_reg.bp = BCE_COM_CPU_HW_BREAKPOINT;
278343c2aeb0SSepherosa Ziehau 	cpu_reg.spad_base = BCE_COM_SCRATCH;
278443c2aeb0SSepherosa Ziehau 	cpu_reg.mips_view_base = 0x8000000;
278543c2aeb0SSepherosa Ziehau 
278643c2aeb0SSepherosa Ziehau 	fw.ver_major = bce_COM_b06FwReleaseMajor;
278743c2aeb0SSepherosa Ziehau 	fw.ver_minor = bce_COM_b06FwReleaseMinor;
278843c2aeb0SSepherosa Ziehau 	fw.ver_fix = bce_COM_b06FwReleaseFix;
278943c2aeb0SSepherosa Ziehau 	fw.start_addr = bce_COM_b06FwStartAddr;
279043c2aeb0SSepherosa Ziehau 
279143c2aeb0SSepherosa Ziehau 	fw.text_addr = bce_COM_b06FwTextAddr;
279243c2aeb0SSepherosa Ziehau 	fw.text_len = bce_COM_b06FwTextLen;
279343c2aeb0SSepherosa Ziehau 	fw.text_index = 0;
279443c2aeb0SSepherosa Ziehau 	fw.text = bce_COM_b06FwText;
279543c2aeb0SSepherosa Ziehau 
279643c2aeb0SSepherosa Ziehau 	fw.data_addr = bce_COM_b06FwDataAddr;
279743c2aeb0SSepherosa Ziehau 	fw.data_len = bce_COM_b06FwDataLen;
279843c2aeb0SSepherosa Ziehau 	fw.data_index = 0;
279943c2aeb0SSepherosa Ziehau 	fw.data = bce_COM_b06FwData;
280043c2aeb0SSepherosa Ziehau 
280143c2aeb0SSepherosa Ziehau 	fw.sbss_addr = bce_COM_b06FwSbssAddr;
280243c2aeb0SSepherosa Ziehau 	fw.sbss_len = bce_COM_b06FwSbssLen;
280343c2aeb0SSepherosa Ziehau 	fw.sbss_index = 0;
280443c2aeb0SSepherosa Ziehau 	fw.sbss = bce_COM_b06FwSbss;
280543c2aeb0SSepherosa Ziehau 
280643c2aeb0SSepherosa Ziehau 	fw.bss_addr = bce_COM_b06FwBssAddr;
280743c2aeb0SSepherosa Ziehau 	fw.bss_len = bce_COM_b06FwBssLen;
280843c2aeb0SSepherosa Ziehau 	fw.bss_index = 0;
280943c2aeb0SSepherosa Ziehau 	fw.bss = bce_COM_b06FwBss;
281043c2aeb0SSepherosa Ziehau 
281143c2aeb0SSepherosa Ziehau 	fw.rodata_addr = bce_COM_b06FwRodataAddr;
281243c2aeb0SSepherosa Ziehau 	fw.rodata_len = bce_COM_b06FwRodataLen;
281343c2aeb0SSepherosa Ziehau 	fw.rodata_index = 0;
281443c2aeb0SSepherosa Ziehau 	fw.rodata = bce_COM_b06FwRodata;
281543c2aeb0SSepherosa Ziehau 
281643c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RESET, "Loading COM firmware.\n");
281743c2aeb0SSepherosa Ziehau 	bce_load_cpu_fw(sc, &cpu_reg, &fw);
281843c2aeb0SSepherosa Ziehau }
281943c2aeb0SSepherosa Ziehau 
282043c2aeb0SSepherosa Ziehau 
282143c2aeb0SSepherosa Ziehau /****************************************************************************/
282243c2aeb0SSepherosa Ziehau /* Initialize context memory.                                               */
282343c2aeb0SSepherosa Ziehau /*                                                                          */
282443c2aeb0SSepherosa Ziehau /* Clears the memory associated with each Context ID (CID).                 */
282543c2aeb0SSepherosa Ziehau /*                                                                          */
282643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
282743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
282843c2aeb0SSepherosa Ziehau /****************************************************************************/
282943c2aeb0SSepherosa Ziehau static void
28303a41a80bSSepherosa Ziehau bce_init_ctx(struct bce_softc *sc)
283143c2aeb0SSepherosa Ziehau {
28323a41a80bSSepherosa Ziehau 	uint32_t vcid = 96;
283343c2aeb0SSepherosa Ziehau 
283443c2aeb0SSepherosa Ziehau 	while (vcid) {
283543c2aeb0SSepherosa Ziehau 		uint32_t vcid_addr, pcid_addr, offset;
28363a41a80bSSepherosa Ziehau 		int i;
283743c2aeb0SSepherosa Ziehau 
283843c2aeb0SSepherosa Ziehau 		vcid--;
283943c2aeb0SSepherosa Ziehau 
284043c2aeb0SSepherosa Ziehau    		vcid_addr = GET_CID_ADDR(vcid);
284143c2aeb0SSepherosa Ziehau 		pcid_addr = vcid_addr;
284243c2aeb0SSepherosa Ziehau 
28433a41a80bSSepherosa Ziehau 		for (i = 0; i < (CTX_SIZE / PHY_CTX_SIZE); i++) {
28443a41a80bSSepherosa Ziehau 			vcid_addr += (i << PHY_CTX_SHIFT);
28453a41a80bSSepherosa Ziehau 			pcid_addr += (i << PHY_CTX_SHIFT);
28463a41a80bSSepherosa Ziehau 
28473a41a80bSSepherosa Ziehau 			REG_WR(sc, BCE_CTX_VIRT_ADDR, vcid_addr);
284843c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_CTX_PAGE_TBL, pcid_addr);
284943c2aeb0SSepherosa Ziehau 
285043c2aeb0SSepherosa Ziehau 			/* Zero out the context. */
285143c2aeb0SSepherosa Ziehau 			for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
28523a41a80bSSepherosa Ziehau 				CTX_WR(sc, vcid_addr, offset, 0);
28533a41a80bSSepherosa Ziehau 		}
285443c2aeb0SSepherosa Ziehau 	}
285543c2aeb0SSepherosa Ziehau }
285643c2aeb0SSepherosa Ziehau 
285743c2aeb0SSepherosa Ziehau 
285843c2aeb0SSepherosa Ziehau /****************************************************************************/
285943c2aeb0SSepherosa Ziehau /* Fetch the permanent MAC address of the controller.                       */
286043c2aeb0SSepherosa Ziehau /*                                                                          */
286143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
286243c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
286343c2aeb0SSepherosa Ziehau /****************************************************************************/
286443c2aeb0SSepherosa Ziehau static void
286543c2aeb0SSepherosa Ziehau bce_get_mac_addr(struct bce_softc *sc)
286643c2aeb0SSepherosa Ziehau {
286743c2aeb0SSepherosa Ziehau 	uint32_t mac_lo = 0, mac_hi = 0;
286843c2aeb0SSepherosa Ziehau 
286943c2aeb0SSepherosa Ziehau 	/*
287043c2aeb0SSepherosa Ziehau 	 * The NetXtreme II bootcode populates various NIC
287143c2aeb0SSepherosa Ziehau 	 * power-on and runtime configuration items in a
287243c2aeb0SSepherosa Ziehau 	 * shared memory area.  The factory configured MAC
287343c2aeb0SSepherosa Ziehau 	 * address is available from both NVRAM and the
287443c2aeb0SSepherosa Ziehau 	 * shared memory area so we'll read the value from
287543c2aeb0SSepherosa Ziehau 	 * shared memory for speed.
287643c2aeb0SSepherosa Ziehau 	 */
287743c2aeb0SSepherosa Ziehau 
287843c2aeb0SSepherosa Ziehau 	mac_hi = REG_RD_IND(sc, sc->bce_shmem_base + BCE_PORT_HW_CFG_MAC_UPPER);
287943c2aeb0SSepherosa Ziehau 	mac_lo = REG_RD_IND(sc, sc->bce_shmem_base + BCE_PORT_HW_CFG_MAC_LOWER);
288043c2aeb0SSepherosa Ziehau 
288143c2aeb0SSepherosa Ziehau 	if (mac_lo == 0 && mac_hi == 0) {
288243c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "Invalid Ethernet address!\n");
288343c2aeb0SSepherosa Ziehau 	} else {
288443c2aeb0SSepherosa Ziehau 		sc->eaddr[0] = (u_char)(mac_hi >> 8);
288543c2aeb0SSepherosa Ziehau 		sc->eaddr[1] = (u_char)(mac_hi >> 0);
288643c2aeb0SSepherosa Ziehau 		sc->eaddr[2] = (u_char)(mac_lo >> 24);
288743c2aeb0SSepherosa Ziehau 		sc->eaddr[3] = (u_char)(mac_lo >> 16);
288843c2aeb0SSepherosa Ziehau 		sc->eaddr[4] = (u_char)(mac_lo >> 8);
288943c2aeb0SSepherosa Ziehau 		sc->eaddr[5] = (u_char)(mac_lo >> 0);
289043c2aeb0SSepherosa Ziehau 	}
289143c2aeb0SSepherosa Ziehau 
289243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "Permanent Ethernet address = %6D\n", sc->eaddr, ":");
289343c2aeb0SSepherosa Ziehau }
289443c2aeb0SSepherosa Ziehau 
289543c2aeb0SSepherosa Ziehau 
289643c2aeb0SSepherosa Ziehau /****************************************************************************/
289743c2aeb0SSepherosa Ziehau /* Program the MAC address.                                                 */
289843c2aeb0SSepherosa Ziehau /*                                                                          */
289943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
290043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
290143c2aeb0SSepherosa Ziehau /****************************************************************************/
290243c2aeb0SSepherosa Ziehau static void
290343c2aeb0SSepherosa Ziehau bce_set_mac_addr(struct bce_softc *sc)
290443c2aeb0SSepherosa Ziehau {
290543c2aeb0SSepherosa Ziehau 	const uint8_t *mac_addr = sc->eaddr;
290643c2aeb0SSepherosa Ziehau 	uint32_t val;
290743c2aeb0SSepherosa Ziehau 
290843c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "Setting Ethernet address = %6D\n",
290943c2aeb0SSepherosa Ziehau 		sc->eaddr, ":");
291043c2aeb0SSepherosa Ziehau 
291143c2aeb0SSepherosa Ziehau 	val = (mac_addr[0] << 8) | mac_addr[1];
291243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_MAC_MATCH0, val);
291343c2aeb0SSepherosa Ziehau 
291443c2aeb0SSepherosa Ziehau 	val = (mac_addr[2] << 24) |
291543c2aeb0SSepherosa Ziehau 	      (mac_addr[3] << 16) |
291643c2aeb0SSepherosa Ziehau 	      (mac_addr[4] << 8) |
291743c2aeb0SSepherosa Ziehau 	      mac_addr[5];
291843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_MAC_MATCH1, val);
291943c2aeb0SSepherosa Ziehau }
292043c2aeb0SSepherosa Ziehau 
292143c2aeb0SSepherosa Ziehau 
292243c2aeb0SSepherosa Ziehau /****************************************************************************/
292343c2aeb0SSepherosa Ziehau /* Stop the controller.                                                     */
292443c2aeb0SSepherosa Ziehau /*                                                                          */
292543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
292643c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
292743c2aeb0SSepherosa Ziehau /****************************************************************************/
292843c2aeb0SSepherosa Ziehau static void
292943c2aeb0SSepherosa Ziehau bce_stop(struct bce_softc *sc)
293043c2aeb0SSepherosa Ziehau {
293143c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
293243c2aeb0SSepherosa Ziehau 	struct mii_data *mii = device_get_softc(sc->bce_miibus);
293343c2aeb0SSepherosa Ziehau 	struct ifmedia_entry *ifm;
293443c2aeb0SSepherosa Ziehau 	int mtmp, itmp;
293543c2aeb0SSepherosa Ziehau 
293643c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
293743c2aeb0SSepherosa Ziehau 
293843c2aeb0SSepherosa Ziehau 	callout_stop(&sc->bce_stat_ch);
293943c2aeb0SSepherosa Ziehau 
294043c2aeb0SSepherosa Ziehau 	/* Disable the transmit/receive blocks. */
294143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS, 0x5ffffff);
294243c2aeb0SSepherosa Ziehau 	REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS);
294343c2aeb0SSepherosa Ziehau 	DELAY(20);
294443c2aeb0SSepherosa Ziehau 
294543c2aeb0SSepherosa Ziehau 	bce_disable_intr(sc);
294643c2aeb0SSepherosa Ziehau 
294743c2aeb0SSepherosa Ziehau 	/* Tell firmware that the driver is going away. */
294843c2aeb0SSepherosa Ziehau 	bce_reset(sc, BCE_DRV_MSG_CODE_SUSPEND_NO_WOL);
294943c2aeb0SSepherosa Ziehau 
295043c2aeb0SSepherosa Ziehau 	/* Free the RX lists. */
295143c2aeb0SSepherosa Ziehau 	bce_free_rx_chain(sc);
295243c2aeb0SSepherosa Ziehau 
295343c2aeb0SSepherosa Ziehau 	/* Free TX buffers. */
295443c2aeb0SSepherosa Ziehau 	bce_free_tx_chain(sc);
295543c2aeb0SSepherosa Ziehau 
295643c2aeb0SSepherosa Ziehau 	/*
295743c2aeb0SSepherosa Ziehau 	 * Isolate/power down the PHY, but leave the media selection
295843c2aeb0SSepherosa Ziehau 	 * unchanged so that things will be put back to normal when
295943c2aeb0SSepherosa Ziehau 	 * we bring the interface back up.
2960db1e7fc4SSepherosa Ziehau 	 *
2961db1e7fc4SSepherosa Ziehau 	 * 'mii' may be NULL if bce_stop() is called by bce_detach().
296243c2aeb0SSepherosa Ziehau 	 */
2963db1e7fc4SSepherosa Ziehau 	if (mii != NULL) {
296443c2aeb0SSepherosa Ziehau 		itmp = ifp->if_flags;
296543c2aeb0SSepherosa Ziehau 		ifp->if_flags |= IFF_UP;
296643c2aeb0SSepherosa Ziehau 		ifm = mii->mii_media.ifm_cur;
296743c2aeb0SSepherosa Ziehau 		mtmp = ifm->ifm_media;
296843c2aeb0SSepherosa Ziehau 		ifm->ifm_media = IFM_ETHER | IFM_NONE;
296943c2aeb0SSepherosa Ziehau 		mii_mediachg(mii);
297043c2aeb0SSepherosa Ziehau 		ifm->ifm_media = mtmp;
297143c2aeb0SSepherosa Ziehau 		ifp->if_flags = itmp;
2972db1e7fc4SSepherosa Ziehau 	}
297343c2aeb0SSepherosa Ziehau 
297443c2aeb0SSepherosa Ziehau 	sc->bce_link = 0;
2975bdeb8fffSSepherosa Ziehau 	sc->bce_coalchg_mask = 0;
297643c2aeb0SSepherosa Ziehau 
297743c2aeb0SSepherosa Ziehau 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
297843c2aeb0SSepherosa Ziehau 	ifp->if_timer = 0;
297943c2aeb0SSepherosa Ziehau 
298043c2aeb0SSepherosa Ziehau 	bce_mgmt_init(sc);
298143c2aeb0SSepherosa Ziehau }
298243c2aeb0SSepherosa Ziehau 
298343c2aeb0SSepherosa Ziehau 
298443c2aeb0SSepherosa Ziehau static int
298543c2aeb0SSepherosa Ziehau bce_reset(struct bce_softc *sc, uint32_t reset_code)
298643c2aeb0SSepherosa Ziehau {
298743c2aeb0SSepherosa Ziehau 	uint32_t val;
298843c2aeb0SSepherosa Ziehau 	int i, rc = 0;
298943c2aeb0SSepherosa Ziehau 
299043c2aeb0SSepherosa Ziehau 	/* Wait for pending PCI transactions to complete. */
299143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS,
299243c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
299343c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
299443c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
299543c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
299643c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS);
299743c2aeb0SSepherosa Ziehau 	DELAY(5);
299843c2aeb0SSepherosa Ziehau 
299943c2aeb0SSepherosa Ziehau 	/* Assume bootcode is running. */
300043c2aeb0SSepherosa Ziehau 	sc->bce_fw_timed_out = 0;
300143c2aeb0SSepherosa Ziehau 
300243c2aeb0SSepherosa Ziehau 	/* Give the firmware a chance to prepare for the reset. */
300343c2aeb0SSepherosa Ziehau 	rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT0 | reset_code);
300443c2aeb0SSepherosa Ziehau 	if (rc) {
300543c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
300643c2aeb0SSepherosa Ziehau 			  "Firmware is not ready for reset\n");
300743c2aeb0SSepherosa Ziehau 		return rc;
300843c2aeb0SSepherosa Ziehau 	}
300943c2aeb0SSepherosa Ziehau 
301043c2aeb0SSepherosa Ziehau 	/* Set a firmware reminder that this is a soft reset. */
301143c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_RESET_SIGNATURE,
301243c2aeb0SSepherosa Ziehau 		   BCE_DRV_RESET_SIGNATURE_MAGIC);
301343c2aeb0SSepherosa Ziehau 
301443c2aeb0SSepherosa Ziehau 	/* Dummy read to force the chip to complete all current transactions. */
301543c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_ID);
301643c2aeb0SSepherosa Ziehau 
301743c2aeb0SSepherosa Ziehau 	/* Chip reset. */
301843c2aeb0SSepherosa Ziehau 	val = BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
301943c2aeb0SSepherosa Ziehau 	      BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
302043c2aeb0SSepherosa Ziehau 	      BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
302143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_MISC_CONFIG, val);
302243c2aeb0SSepherosa Ziehau 
302343c2aeb0SSepherosa Ziehau 	/* Allow up to 30us for reset to complete. */
302443c2aeb0SSepherosa Ziehau 	for (i = 0; i < 10; i++) {
302543c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, BCE_PCICFG_MISC_CONFIG);
302643c2aeb0SSepherosa Ziehau 		if ((val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
302743c2aeb0SSepherosa Ziehau 			    BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) {
302843c2aeb0SSepherosa Ziehau 			break;
302943c2aeb0SSepherosa Ziehau 		}
303043c2aeb0SSepherosa Ziehau 		DELAY(10);
303143c2aeb0SSepherosa Ziehau 	}
303243c2aeb0SSepherosa Ziehau 
303343c2aeb0SSepherosa Ziehau 	/* Check that reset completed successfully. */
303443c2aeb0SSepherosa Ziehau 	if (val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
303543c2aeb0SSepherosa Ziehau 		   BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
303643c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "Reset failed!\n");
303743c2aeb0SSepherosa Ziehau 		return EBUSY;
303843c2aeb0SSepherosa Ziehau 	}
303943c2aeb0SSepherosa Ziehau 
304043c2aeb0SSepherosa Ziehau 	/* Make sure byte swapping is properly configured. */
304143c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_PCI_SWAP_DIAG0);
304243c2aeb0SSepherosa Ziehau 	if (val != 0x01020304) {
304343c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "Byte swap is incorrect!\n");
304443c2aeb0SSepherosa Ziehau 		return ENODEV;
304543c2aeb0SSepherosa Ziehau 	}
304643c2aeb0SSepherosa Ziehau 
304743c2aeb0SSepherosa Ziehau 	/* Just completed a reset, assume that firmware is running again. */
304843c2aeb0SSepherosa Ziehau 	sc->bce_fw_timed_out = 0;
304943c2aeb0SSepherosa Ziehau 
305043c2aeb0SSepherosa Ziehau 	/* Wait for the firmware to finish its initialization. */
305143c2aeb0SSepherosa Ziehau 	rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT1 | reset_code);
305243c2aeb0SSepherosa Ziehau 	if (rc) {
305343c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
305443c2aeb0SSepherosa Ziehau 			  "Firmware did not complete initialization!\n");
305543c2aeb0SSepherosa Ziehau 	}
305643c2aeb0SSepherosa Ziehau 	return rc;
305743c2aeb0SSepherosa Ziehau }
305843c2aeb0SSepherosa Ziehau 
305943c2aeb0SSepherosa Ziehau 
306043c2aeb0SSepherosa Ziehau static int
306143c2aeb0SSepherosa Ziehau bce_chipinit(struct bce_softc *sc)
306243c2aeb0SSepherosa Ziehau {
306343c2aeb0SSepherosa Ziehau 	uint32_t val;
306443c2aeb0SSepherosa Ziehau 	int rc = 0;
306543c2aeb0SSepherosa Ziehau 
306643c2aeb0SSepherosa Ziehau 	/* Make sure the interrupt is not active. */
306743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, BCE_PCICFG_INT_ACK_CMD_MASK_INT);
306843c2aeb0SSepherosa Ziehau 
306943c2aeb0SSepherosa Ziehau 	/*
307043c2aeb0SSepherosa Ziehau 	 * Initialize DMA byte/word swapping, configure the number of DMA
307143c2aeb0SSepherosa Ziehau 	 * channels and PCI clock compensation delay.
307243c2aeb0SSepherosa Ziehau 	 */
307343c2aeb0SSepherosa Ziehau 	val = BCE_DMA_CONFIG_DATA_BYTE_SWAP |
307443c2aeb0SSepherosa Ziehau 	      BCE_DMA_CONFIG_DATA_WORD_SWAP |
307543c2aeb0SSepherosa Ziehau #if BYTE_ORDER == BIG_ENDIAN
307643c2aeb0SSepherosa Ziehau 	      BCE_DMA_CONFIG_CNTL_BYTE_SWAP |
307743c2aeb0SSepherosa Ziehau #endif
307843c2aeb0SSepherosa Ziehau 	      BCE_DMA_CONFIG_CNTL_WORD_SWAP |
307943c2aeb0SSepherosa Ziehau 	      DMA_READ_CHANS << 12 |
308043c2aeb0SSepherosa Ziehau 	      DMA_WRITE_CHANS << 16;
308143c2aeb0SSepherosa Ziehau 
308243c2aeb0SSepherosa Ziehau 	val |= (0x2 << 20) | BCE_DMA_CONFIG_CNTL_PCI_COMP_DLY;
308343c2aeb0SSepherosa Ziehau 
308443c2aeb0SSepherosa Ziehau 	if ((sc->bce_flags & BCE_PCIX_FLAG) && sc->bus_speed_mhz == 133)
308543c2aeb0SSepherosa Ziehau 		val |= BCE_DMA_CONFIG_PCI_FAST_CLK_CMP;
308643c2aeb0SSepherosa Ziehau 
308743c2aeb0SSepherosa Ziehau 	/*
308843c2aeb0SSepherosa Ziehau 	 * This setting resolves a problem observed on certain Intel PCI
308943c2aeb0SSepherosa Ziehau 	 * chipsets that cannot handle multiple outstanding DMA operations.
309043c2aeb0SSepherosa Ziehau 	 * See errata E9_5706A1_65.
309143c2aeb0SSepherosa Ziehau 	 */
309243c2aeb0SSepherosa Ziehau 	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706 &&
309343c2aeb0SSepherosa Ziehau 	    BCE_CHIP_ID(sc) != BCE_CHIP_ID_5706_A0 &&
309443c2aeb0SSepherosa Ziehau 	    !(sc->bce_flags & BCE_PCIX_FLAG))
309543c2aeb0SSepherosa Ziehau 		val |= BCE_DMA_CONFIG_CNTL_PING_PONG_DMA;
309643c2aeb0SSepherosa Ziehau 
309743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_DMA_CONFIG, val);
309843c2aeb0SSepherosa Ziehau 
309943c2aeb0SSepherosa Ziehau 	/* Clear the PCI-X relaxed ordering bit. See errata E3_5708CA0_570. */
310043c2aeb0SSepherosa Ziehau 	if (sc->bce_flags & BCE_PCIX_FLAG) {
310143c2aeb0SSepherosa Ziehau 		uint16_t cmd;
310243c2aeb0SSepherosa Ziehau 
310343c2aeb0SSepherosa Ziehau 		cmd = pci_read_config(sc->bce_dev, BCE_PCI_PCIX_CMD, 2);
310443c2aeb0SSepherosa Ziehau 		pci_write_config(sc->bce_dev, BCE_PCI_PCIX_CMD, cmd & ~0x2, 2);
310543c2aeb0SSepherosa Ziehau 	}
310643c2aeb0SSepherosa Ziehau 
310743c2aeb0SSepherosa Ziehau 	/* Enable the RX_V2P and Context state machines before access. */
310843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
310943c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
311043c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
311143c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
311243c2aeb0SSepherosa Ziehau 
311343c2aeb0SSepherosa Ziehau 	/* Initialize context mapping and zero out the quick contexts. */
31143a41a80bSSepherosa Ziehau 	bce_init_ctx(sc);
311543c2aeb0SSepherosa Ziehau 
311643c2aeb0SSepherosa Ziehau 	/* Initialize the on-boards CPUs */
311743c2aeb0SSepherosa Ziehau 	bce_init_cpus(sc);
311843c2aeb0SSepherosa Ziehau 
311943c2aeb0SSepherosa Ziehau 	/* Prepare NVRAM for access. */
312043c2aeb0SSepherosa Ziehau 	rc = bce_init_nvram(sc);
312143c2aeb0SSepherosa Ziehau 	if (rc != 0)
312243c2aeb0SSepherosa Ziehau 		return rc;
312343c2aeb0SSepherosa Ziehau 
312443c2aeb0SSepherosa Ziehau 	/* Set the kernel bypass block size */
312543c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MQ_CONFIG);
312643c2aeb0SSepherosa Ziehau 	val &= ~BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE;
312743c2aeb0SSepherosa Ziehau 	val |= BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
312843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MQ_CONFIG, val);
312943c2aeb0SSepherosa Ziehau 
313043c2aeb0SSepherosa Ziehau 	val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
313143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MQ_KNL_BYP_WIND_START, val);
313243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MQ_KNL_WIND_END, val);
313343c2aeb0SSepherosa Ziehau 
313443c2aeb0SSepherosa Ziehau 	/* Set the page size and clear the RV2P processor stall bits. */
313543c2aeb0SSepherosa Ziehau 	val = (BCM_PAGE_BITS - 8) << 24;
313643c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_RV2P_CONFIG, val);
313743c2aeb0SSepherosa Ziehau 
313843c2aeb0SSepherosa Ziehau 	/* Configure page size. */
313943c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_TBDR_CONFIG);
314043c2aeb0SSepherosa Ziehau 	val &= ~BCE_TBDR_CONFIG_PAGE_SIZE;
314143c2aeb0SSepherosa Ziehau 	val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
314243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_TBDR_CONFIG, val);
314343c2aeb0SSepherosa Ziehau 
314443c2aeb0SSepherosa Ziehau 	return 0;
314543c2aeb0SSepherosa Ziehau }
314643c2aeb0SSepherosa Ziehau 
314743c2aeb0SSepherosa Ziehau 
314843c2aeb0SSepherosa Ziehau /****************************************************************************/
314943c2aeb0SSepherosa Ziehau /* Initialize the controller in preparation to send/receive traffic.        */
315043c2aeb0SSepherosa Ziehau /*                                                                          */
315143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
315243c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
315343c2aeb0SSepherosa Ziehau /****************************************************************************/
315443c2aeb0SSepherosa Ziehau static int
315543c2aeb0SSepherosa Ziehau bce_blockinit(struct bce_softc *sc)
315643c2aeb0SSepherosa Ziehau {
315743c2aeb0SSepherosa Ziehau 	uint32_t reg, val;
315843c2aeb0SSepherosa Ziehau 	int rc = 0;
315943c2aeb0SSepherosa Ziehau 
316043c2aeb0SSepherosa Ziehau 	/* Load the hardware default MAC address. */
316143c2aeb0SSepherosa Ziehau 	bce_set_mac_addr(sc);
316243c2aeb0SSepherosa Ziehau 
316343c2aeb0SSepherosa Ziehau 	/* Set the Ethernet backoff seed value */
316443c2aeb0SSepherosa Ziehau 	val = sc->eaddr[0] + (sc->eaddr[1] << 8) + (sc->eaddr[2] << 16) +
316543c2aeb0SSepherosa Ziehau 	      sc->eaddr[3] + (sc->eaddr[4] << 8) + (sc->eaddr[5] << 16);
316643c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_BACKOFF_SEED, val);
316743c2aeb0SSepherosa Ziehau 
316843c2aeb0SSepherosa Ziehau 	sc->last_status_idx = 0;
316943c2aeb0SSepherosa Ziehau 	sc->rx_mode = BCE_EMAC_RX_MODE_SORT_MODE;
317043c2aeb0SSepherosa Ziehau 
317143c2aeb0SSepherosa Ziehau 	/* Set up link change interrupt generation. */
317243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_ATTENTION_ENA, BCE_EMAC_ATTENTION_ENA_LINK);
317343c2aeb0SSepherosa Ziehau 
317443c2aeb0SSepherosa Ziehau 	/* Program the physical address of the status block. */
317543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATUS_ADDR_L, BCE_ADDR_LO(sc->status_block_paddr));
317643c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATUS_ADDR_H, BCE_ADDR_HI(sc->status_block_paddr));
317743c2aeb0SSepherosa Ziehau 
317843c2aeb0SSepherosa Ziehau 	/* Program the physical address of the statistics block. */
317943c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATISTICS_ADDR_L,
318043c2aeb0SSepherosa Ziehau 	       BCE_ADDR_LO(sc->stats_block_paddr));
318143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATISTICS_ADDR_H,
318243c2aeb0SSepherosa Ziehau 	       BCE_ADDR_HI(sc->stats_block_paddr));
318343c2aeb0SSepherosa Ziehau 
318443c2aeb0SSepherosa Ziehau 	/* Program various host coalescing parameters. */
318543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
318643c2aeb0SSepherosa Ziehau 	       (sc->bce_tx_quick_cons_trip_int << 16) |
318743c2aeb0SSepherosa Ziehau 	       sc->bce_tx_quick_cons_trip);
318843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
318943c2aeb0SSepherosa Ziehau 	       (sc->bce_rx_quick_cons_trip_int << 16) |
319043c2aeb0SSepherosa Ziehau 	       sc->bce_rx_quick_cons_trip);
319143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_COMP_PROD_TRIP,
319243c2aeb0SSepherosa Ziehau 	       (sc->bce_comp_prod_trip_int << 16) | sc->bce_comp_prod_trip);
319343c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_TX_TICKS,
319443c2aeb0SSepherosa Ziehau 	       (sc->bce_tx_ticks_int << 16) | sc->bce_tx_ticks);
319543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_RX_TICKS,
319643c2aeb0SSepherosa Ziehau 	       (sc->bce_rx_ticks_int << 16) | sc->bce_rx_ticks);
319743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_COM_TICKS,
319843c2aeb0SSepherosa Ziehau 	       (sc->bce_com_ticks_int << 16) | sc->bce_com_ticks);
319943c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_CMD_TICKS,
320043c2aeb0SSepherosa Ziehau 	       (sc->bce_cmd_ticks_int << 16) | sc->bce_cmd_ticks);
320143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STATS_TICKS, (sc->bce_stats_ticks & 0xffff00));
320243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_STAT_COLLECT_TICKS, 0xbb8);	/* 3ms */
320343c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_CONFIG,
320443c2aeb0SSepherosa Ziehau 	       BCE_HC_CONFIG_TX_TMR_MODE |
320543c2aeb0SSepherosa Ziehau 	       BCE_HC_CONFIG_COLLECT_STATS);
320643c2aeb0SSepherosa Ziehau 
320743c2aeb0SSepherosa Ziehau 	/* Clear the internal statistics counters. */
320843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW);
320943c2aeb0SSepherosa Ziehau 
321043c2aeb0SSepherosa Ziehau 	/* Verify that bootcode is running. */
321143c2aeb0SSepherosa Ziehau 	reg = REG_RD_IND(sc, sc->bce_shmem_base + BCE_DEV_INFO_SIGNATURE);
321243c2aeb0SSepherosa Ziehau 
321343c2aeb0SSepherosa Ziehau 	DBRUNIF(DB_RANDOMTRUE(bce_debug_bootcode_running_failure),
321443c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
321543c2aeb0SSepherosa Ziehau 			  "%s(%d): Simulating bootcode failure.\n",
321643c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__);
321743c2aeb0SSepherosa Ziehau 		reg = 0);
321843c2aeb0SSepherosa Ziehau 
321943c2aeb0SSepherosa Ziehau 	if ((reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
322043c2aeb0SSepherosa Ziehau 	    BCE_DEV_INFO_SIGNATURE_MAGIC) {
322143c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
322243c2aeb0SSepherosa Ziehau 			  "Bootcode not running! Found: 0x%08X, "
322343c2aeb0SSepherosa Ziehau 			  "Expected: 08%08X\n",
322443c2aeb0SSepherosa Ziehau 			  reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK,
322543c2aeb0SSepherosa Ziehau 			  BCE_DEV_INFO_SIGNATURE_MAGIC);
322643c2aeb0SSepherosa Ziehau 		return ENODEV;
322743c2aeb0SSepherosa Ziehau 	}
322843c2aeb0SSepherosa Ziehau 
322943c2aeb0SSepherosa Ziehau 	/* Check if any management firmware is running. */
323043c2aeb0SSepherosa Ziehau 	reg = REG_RD_IND(sc, sc->bce_shmem_base + BCE_PORT_FEATURE);
323143c2aeb0SSepherosa Ziehau 	if (reg & (BCE_PORT_FEATURE_ASF_ENABLED |
323243c2aeb0SSepherosa Ziehau 		   BCE_PORT_FEATURE_IMD_ENABLED)) {
323343c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Management F/W Enabled.\n");
323443c2aeb0SSepherosa Ziehau 		sc->bce_flags |= BCE_MFW_ENABLE_FLAG;
323543c2aeb0SSepherosa Ziehau 	}
323643c2aeb0SSepherosa Ziehau 
323743c2aeb0SSepherosa Ziehau 	sc->bce_fw_ver =
323843c2aeb0SSepherosa Ziehau 		REG_RD_IND(sc, sc->bce_shmem_base + BCE_DEV_INFO_BC_REV);
323943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "bootcode rev = 0x%08X\n", sc->bce_fw_ver);
324043c2aeb0SSepherosa Ziehau 
324143c2aeb0SSepherosa Ziehau 	/* Allow bootcode to apply any additional fixes before enabling MAC. */
324243c2aeb0SSepherosa Ziehau 	rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT2 | BCE_DRV_MSG_CODE_RESET);
324343c2aeb0SSepherosa Ziehau 
324443c2aeb0SSepherosa Ziehau 	/* Enable link state change interrupt generation. */
324543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
324643c2aeb0SSepherosa Ziehau 
324743c2aeb0SSepherosa Ziehau 	/* Enable all remaining blocks in the MAC. */
324843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, 0x5ffffff);
324943c2aeb0SSepherosa Ziehau 	REG_RD(sc, BCE_MISC_ENABLE_SET_BITS);
325043c2aeb0SSepherosa Ziehau 	DELAY(20);
325143c2aeb0SSepherosa Ziehau 
325243c2aeb0SSepherosa Ziehau 	return 0;
325343c2aeb0SSepherosa Ziehau }
325443c2aeb0SSepherosa Ziehau 
325543c2aeb0SSepherosa Ziehau 
325643c2aeb0SSepherosa Ziehau /****************************************************************************/
325743c2aeb0SSepherosa Ziehau /* Encapsulate an mbuf cluster into the rx_bd chain.                        */
325843c2aeb0SSepherosa Ziehau /*                                                                          */
325943c2aeb0SSepherosa Ziehau /* The NetXtreme II can support Jumbo frames by using multiple rx_bd's.     */
326043c2aeb0SSepherosa Ziehau /* This routine will map an mbuf cluster into 1 or more rx_bd's as          */
326143c2aeb0SSepherosa Ziehau /* necessary.                                                               */
326243c2aeb0SSepherosa Ziehau /*                                                                          */
326343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
326443c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
326543c2aeb0SSepherosa Ziehau /****************************************************************************/
326643c2aeb0SSepherosa Ziehau static int
326743c2aeb0SSepherosa Ziehau bce_newbuf_std(struct bce_softc *sc, struct mbuf *m,
326843c2aeb0SSepherosa Ziehau 	       uint16_t *prod, uint16_t *chain_prod, uint32_t *prod_bseq)
326943c2aeb0SSepherosa Ziehau {
327043c2aeb0SSepherosa Ziehau 	bus_dmamap_t map;
327143c2aeb0SSepherosa Ziehau 	struct bce_dmamap_arg ctx;
327243c2aeb0SSepherosa Ziehau 	bus_dma_segment_t seg;
327343c2aeb0SSepherosa Ziehau 	struct mbuf *m_new;
327443c2aeb0SSepherosa Ziehau 	struct rx_bd *rxbd;
327543c2aeb0SSepherosa Ziehau 	int error;
327643c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
327743c2aeb0SSepherosa Ziehau 	uint16_t debug_chain_prod = *chain_prod;
327843c2aeb0SSepherosa Ziehau #endif
327943c2aeb0SSepherosa Ziehau 
328043c2aeb0SSepherosa Ziehau 	/* Make sure the inputs are valid. */
328143c2aeb0SSepherosa Ziehau 	DBRUNIF((*chain_prod > MAX_RX_BD),
328243c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "%s(%d): "
328343c2aeb0SSepherosa Ziehau 			  "RX producer out of range: 0x%04X > 0x%04X\n",
328443c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__,
328543c2aeb0SSepherosa Ziehau 			  *chain_prod, (uint16_t)MAX_RX_BD));
328643c2aeb0SSepherosa Ziehau 
328743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RECV, "%s(enter): prod = 0x%04X, chain_prod = 0x%04X, "
328843c2aeb0SSepherosa Ziehau 		"prod_bseq = 0x%08X\n", __func__, *prod, *chain_prod, *prod_bseq);
328943c2aeb0SSepherosa Ziehau 
329043c2aeb0SSepherosa Ziehau 	if (m == NULL) {
329143c2aeb0SSepherosa Ziehau 		DBRUNIF(DB_RANDOMTRUE(bce_debug_mbuf_allocation_failure),
329243c2aeb0SSepherosa Ziehau 			if_printf(&sc->arpcom.ac_if, "%s(%d): "
329343c2aeb0SSepherosa Ziehau 				  "Simulating mbuf allocation failure.\n",
329443c2aeb0SSepherosa Ziehau 				  __FILE__, __LINE__);
329543c2aeb0SSepherosa Ziehau 			sc->mbuf_alloc_failed++;
329643c2aeb0SSepherosa Ziehau 			return ENOBUFS);
329743c2aeb0SSepherosa Ziehau 
329843c2aeb0SSepherosa Ziehau 		/* This is a new mbuf allocation. */
329943c2aeb0SSepherosa Ziehau 		m_new = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
330043c2aeb0SSepherosa Ziehau 		if (m_new == NULL)
330143c2aeb0SSepherosa Ziehau 			return ENOBUFS;
330243c2aeb0SSepherosa Ziehau 		DBRUNIF(1, sc->rx_mbuf_alloc++);
330343c2aeb0SSepherosa Ziehau 	} else {
330443c2aeb0SSepherosa Ziehau 		m_new = m;
330543c2aeb0SSepherosa Ziehau 		m_new->m_data = m_new->m_ext.ext_buf;
330643c2aeb0SSepherosa Ziehau 	}
330743c2aeb0SSepherosa Ziehau 	m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
330843c2aeb0SSepherosa Ziehau 
330943c2aeb0SSepherosa Ziehau 	/* Map the mbuf cluster into device memory. */
331043c2aeb0SSepherosa Ziehau 	map = sc->rx_mbuf_map[*chain_prod];
331143c2aeb0SSepherosa Ziehau 
331243c2aeb0SSepherosa Ziehau 	ctx.bce_maxsegs = 1;
331343c2aeb0SSepherosa Ziehau 	ctx.bce_segs = &seg;
331443c2aeb0SSepherosa Ziehau 	error = bus_dmamap_load_mbuf(sc->rx_mbuf_tag, map, m_new,
331543c2aeb0SSepherosa Ziehau 				     bce_dma_map_mbuf, &ctx, BUS_DMA_NOWAIT);
331643c2aeb0SSepherosa Ziehau 	if (error || ctx.bce_maxsegs == 0) {
331743c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
331843c2aeb0SSepherosa Ziehau 			  "Error mapping mbuf into RX chain!\n");
331943c2aeb0SSepherosa Ziehau 
332043c2aeb0SSepherosa Ziehau 		if (m == NULL)
332143c2aeb0SSepherosa Ziehau 			m_freem(m_new);
332243c2aeb0SSepherosa Ziehau 
332343c2aeb0SSepherosa Ziehau 		DBRUNIF(1, sc->rx_mbuf_alloc--);
332443c2aeb0SSepherosa Ziehau 		return ENOBUFS;
332543c2aeb0SSepherosa Ziehau 	}
332643c2aeb0SSepherosa Ziehau 
332743c2aeb0SSepherosa Ziehau 	/* Watch for overflow. */
332843c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd > USABLE_RX_BD),
332943c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "%s(%d): "
333043c2aeb0SSepherosa Ziehau 			  "Too many free rx_bd (0x%04X > 0x%04X)!\n",
333143c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__, sc->free_rx_bd,
333243c2aeb0SSepherosa Ziehau 			  (uint16_t)USABLE_RX_BD));
333343c2aeb0SSepherosa Ziehau 
333443c2aeb0SSepherosa Ziehau 	/* Update some debug statistic counters */
333543c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
333643c2aeb0SSepherosa Ziehau 		sc->rx_low_watermark = sc->free_rx_bd);
333743c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd == 0), sc->rx_empty_count++);
333843c2aeb0SSepherosa Ziehau 
333943c2aeb0SSepherosa Ziehau 	/* Setup the rx_bd for the first segment. */
334043c2aeb0SSepherosa Ziehau 	rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
334143c2aeb0SSepherosa Ziehau 
334243c2aeb0SSepherosa Ziehau 	rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(seg.ds_addr));
334343c2aeb0SSepherosa Ziehau 	rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(seg.ds_addr));
334443c2aeb0SSepherosa Ziehau 	rxbd->rx_bd_len = htole32(seg.ds_len);
334543c2aeb0SSepherosa Ziehau 	rxbd->rx_bd_flags = htole32(RX_BD_FLAGS_START);
334643c2aeb0SSepherosa Ziehau 	*prod_bseq += seg.ds_len;
334743c2aeb0SSepherosa Ziehau 
334843c2aeb0SSepherosa Ziehau 	rxbd->rx_bd_flags |= htole32(RX_BD_FLAGS_END);
334943c2aeb0SSepherosa Ziehau 
335043c2aeb0SSepherosa Ziehau 	/* Save the mbuf and update our counter. */
335143c2aeb0SSepherosa Ziehau 	sc->rx_mbuf_ptr[*chain_prod] = m_new;
335243c2aeb0SSepherosa Ziehau 	sc->free_rx_bd--;
335343c2aeb0SSepherosa Ziehau 
335443c2aeb0SSepherosa Ziehau 	DBRUN(BCE_VERBOSE_RECV,
335543c2aeb0SSepherosa Ziehau 	      bce_dump_rx_mbuf_chain(sc, debug_chain_prod, 1));
335643c2aeb0SSepherosa Ziehau 
335743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RECV, "%s(exit): prod = 0x%04X, chain_prod = 0x%04X, "
335843c2aeb0SSepherosa Ziehau 		"prod_bseq = 0x%08X\n", __func__, *prod, *chain_prod, *prod_bseq);
335943c2aeb0SSepherosa Ziehau 
336043c2aeb0SSepherosa Ziehau 	return 0;
336143c2aeb0SSepherosa Ziehau }
336243c2aeb0SSepherosa Ziehau 
336343c2aeb0SSepherosa Ziehau 
336443c2aeb0SSepherosa Ziehau /****************************************************************************/
336543c2aeb0SSepherosa Ziehau /* Allocate memory and initialize the TX data structures.                   */
336643c2aeb0SSepherosa Ziehau /*                                                                          */
336743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
336843c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
336943c2aeb0SSepherosa Ziehau /****************************************************************************/
337043c2aeb0SSepherosa Ziehau static int
337143c2aeb0SSepherosa Ziehau bce_init_tx_chain(struct bce_softc *sc)
337243c2aeb0SSepherosa Ziehau {
337343c2aeb0SSepherosa Ziehau 	struct tx_bd *txbd;
337443c2aeb0SSepherosa Ziehau 	uint32_t val;
337543c2aeb0SSepherosa Ziehau 	int i, rc = 0;
337643c2aeb0SSepherosa Ziehau 
337743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
337843c2aeb0SSepherosa Ziehau 
337943c2aeb0SSepherosa Ziehau 	/* Set the initial TX producer/consumer indices. */
338043c2aeb0SSepherosa Ziehau 	sc->tx_prod = 0;
338143c2aeb0SSepherosa Ziehau 	sc->tx_cons = 0;
338243c2aeb0SSepherosa Ziehau 	sc->tx_prod_bseq   = 0;
338343c2aeb0SSepherosa Ziehau 	sc->used_tx_bd = 0;
338443c2aeb0SSepherosa Ziehau 	sc->max_tx_bd = USABLE_TX_BD;
338543c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->tx_hi_watermark = USABLE_TX_BD);
338643c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->tx_full_count = 0);
338743c2aeb0SSepherosa Ziehau 
338843c2aeb0SSepherosa Ziehau 	/*
338943c2aeb0SSepherosa Ziehau 	 * The NetXtreme II supports a linked-list structre called
339043c2aeb0SSepherosa Ziehau 	 * a Buffer Descriptor Chain (or BD chain).  A BD chain
339143c2aeb0SSepherosa Ziehau 	 * consists of a series of 1 or more chain pages, each of which
339243c2aeb0SSepherosa Ziehau 	 * consists of a fixed number of BD entries.
339343c2aeb0SSepherosa Ziehau 	 * The last BD entry on each page is a pointer to the next page
339443c2aeb0SSepherosa Ziehau 	 * in the chain, and the last pointer in the BD chain
339543c2aeb0SSepherosa Ziehau 	 * points back to the beginning of the chain.
339643c2aeb0SSepherosa Ziehau 	 */
339743c2aeb0SSepherosa Ziehau 
339843c2aeb0SSepherosa Ziehau 	/* Set the TX next pointer chain entries. */
339943c2aeb0SSepherosa Ziehau 	for (i = 0; i < TX_PAGES; i++) {
340043c2aeb0SSepherosa Ziehau 		int j;
340143c2aeb0SSepherosa Ziehau 
340243c2aeb0SSepherosa Ziehau 		txbd = &sc->tx_bd_chain[i][USABLE_TX_BD_PER_PAGE];
340343c2aeb0SSepherosa Ziehau 
340443c2aeb0SSepherosa Ziehau 		/* Check if we've reached the last page. */
340543c2aeb0SSepherosa Ziehau 		if (i == (TX_PAGES - 1))
340643c2aeb0SSepherosa Ziehau 			j = 0;
340743c2aeb0SSepherosa Ziehau 		else
340843c2aeb0SSepherosa Ziehau 			j = i + 1;
340943c2aeb0SSepherosa Ziehau 
341043c2aeb0SSepherosa Ziehau 		txbd->tx_bd_haddr_hi =
341143c2aeb0SSepherosa Ziehau 			htole32(BCE_ADDR_HI(sc->tx_bd_chain_paddr[j]));
341243c2aeb0SSepherosa Ziehau 		txbd->tx_bd_haddr_lo =
341343c2aeb0SSepherosa Ziehau 			htole32(BCE_ADDR_LO(sc->tx_bd_chain_paddr[j]));
341443c2aeb0SSepherosa Ziehau 	}
341543c2aeb0SSepherosa Ziehau 
341643c2aeb0SSepherosa Ziehau 	for (i = 0; i < TX_PAGES; ++i) {
341743c2aeb0SSepherosa Ziehau 		bus_dmamap_sync(sc->tx_bd_chain_tag, sc->tx_bd_chain_map[i],
341843c2aeb0SSepherosa Ziehau 				BUS_DMASYNC_PREWRITE);
341943c2aeb0SSepherosa Ziehau 	}
342043c2aeb0SSepherosa Ziehau 
342143c2aeb0SSepherosa Ziehau 	/* Initialize the context ID for an L2 TX chain. */
342243c2aeb0SSepherosa Ziehau 	val = BCE_L2CTX_TYPE_TYPE_L2;
342343c2aeb0SSepherosa Ziehau 	val |= BCE_L2CTX_TYPE_SIZE_L2;
342443c2aeb0SSepherosa Ziehau 	CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TYPE, val);
342543c2aeb0SSepherosa Ziehau 
342643c2aeb0SSepherosa Ziehau 	val = BCE_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
342743c2aeb0SSepherosa Ziehau 	CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_CMD_TYPE, val);
342843c2aeb0SSepherosa Ziehau 
342943c2aeb0SSepherosa Ziehau 	/* Point the hardware to the first page in the chain. */
343043c2aeb0SSepherosa Ziehau 	val = BCE_ADDR_HI(sc->tx_bd_chain_paddr[0]);
343143c2aeb0SSepherosa Ziehau 	CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TBDR_BHADDR_HI, val);
343243c2aeb0SSepherosa Ziehau 	val = BCE_ADDR_LO(sc->tx_bd_chain_paddr[0]);
343343c2aeb0SSepherosa Ziehau 	CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TBDR_BHADDR_LO, val);
343443c2aeb0SSepherosa Ziehau 
343543c2aeb0SSepherosa Ziehau 	DBRUN(BCE_VERBOSE_SEND, bce_dump_tx_chain(sc, 0, TOTAL_TX_BD));
343643c2aeb0SSepherosa Ziehau 
343743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __func__);
343843c2aeb0SSepherosa Ziehau 
343943c2aeb0SSepherosa Ziehau 	return(rc);
344043c2aeb0SSepherosa Ziehau }
344143c2aeb0SSepherosa Ziehau 
344243c2aeb0SSepherosa Ziehau 
344343c2aeb0SSepherosa Ziehau /****************************************************************************/
344443c2aeb0SSepherosa Ziehau /* Free memory and clear the TX data structures.                            */
344543c2aeb0SSepherosa Ziehau /*                                                                          */
344643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
344743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
344843c2aeb0SSepherosa Ziehau /****************************************************************************/
344943c2aeb0SSepherosa Ziehau static void
345043c2aeb0SSepherosa Ziehau bce_free_tx_chain(struct bce_softc *sc)
345143c2aeb0SSepherosa Ziehau {
345243c2aeb0SSepherosa Ziehau 	int i;
345343c2aeb0SSepherosa Ziehau 
345443c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
345543c2aeb0SSepherosa Ziehau 
345643c2aeb0SSepherosa Ziehau 	/* Unmap, unload, and free any mbufs still in the TX mbuf chain. */
345743c2aeb0SSepherosa Ziehau 	for (i = 0; i < TOTAL_TX_BD; i++) {
345843c2aeb0SSepherosa Ziehau 		if (sc->tx_mbuf_ptr[i] != NULL) {
345943c2aeb0SSepherosa Ziehau 			bus_dmamap_sync(sc->tx_mbuf_tag, sc->tx_mbuf_map[i],
346043c2aeb0SSepherosa Ziehau 					BUS_DMASYNC_POSTWRITE);
346143c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->tx_mbuf_tag, sc->tx_mbuf_map[i]);
346243c2aeb0SSepherosa Ziehau 			m_freem(sc->tx_mbuf_ptr[i]);
346343c2aeb0SSepherosa Ziehau 			sc->tx_mbuf_ptr[i] = NULL;
346443c2aeb0SSepherosa Ziehau 			DBRUNIF(1, sc->tx_mbuf_alloc--);
346543c2aeb0SSepherosa Ziehau 		}
346643c2aeb0SSepherosa Ziehau 	}
346743c2aeb0SSepherosa Ziehau 
346843c2aeb0SSepherosa Ziehau 	/* Clear each TX chain page. */
346943c2aeb0SSepherosa Ziehau 	for (i = 0; i < TX_PAGES; i++)
347043c2aeb0SSepherosa Ziehau 		bzero(sc->tx_bd_chain[i], BCE_TX_CHAIN_PAGE_SZ);
347124603545SSepherosa Ziehau 	sc->used_tx_bd = 0;
347243c2aeb0SSepherosa Ziehau 
347343c2aeb0SSepherosa Ziehau 	/* Check if we lost any mbufs in the process. */
347443c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->tx_mbuf_alloc),
347543c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
347643c2aeb0SSepherosa Ziehau 			  "%s(%d): Memory leak! "
347743c2aeb0SSepherosa Ziehau 			  "Lost %d mbufs from tx chain!\n",
347843c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__, sc->tx_mbuf_alloc));
347943c2aeb0SSepherosa Ziehau 
348043c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __func__);
348143c2aeb0SSepherosa Ziehau }
348243c2aeb0SSepherosa Ziehau 
348343c2aeb0SSepherosa Ziehau 
348443c2aeb0SSepherosa Ziehau /****************************************************************************/
348543c2aeb0SSepherosa Ziehau /* Allocate memory and initialize the RX data structures.                   */
348643c2aeb0SSepherosa Ziehau /*                                                                          */
348743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
348843c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
348943c2aeb0SSepherosa Ziehau /****************************************************************************/
349043c2aeb0SSepherosa Ziehau static int
349143c2aeb0SSepherosa Ziehau bce_init_rx_chain(struct bce_softc *sc)
349243c2aeb0SSepherosa Ziehau {
349343c2aeb0SSepherosa Ziehau 	struct rx_bd *rxbd;
349443c2aeb0SSepherosa Ziehau 	int i, rc = 0;
349543c2aeb0SSepherosa Ziehau 	uint16_t prod, chain_prod;
349643c2aeb0SSepherosa Ziehau 	uint32_t prod_bseq, val;
349743c2aeb0SSepherosa Ziehau 
349843c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
349943c2aeb0SSepherosa Ziehau 
350043c2aeb0SSepherosa Ziehau 	/* Initialize the RX producer and consumer indices. */
350143c2aeb0SSepherosa Ziehau 	sc->rx_prod = 0;
350243c2aeb0SSepherosa Ziehau 	sc->rx_cons = 0;
350343c2aeb0SSepherosa Ziehau 	sc->rx_prod_bseq = 0;
350443c2aeb0SSepherosa Ziehau 	sc->free_rx_bd = USABLE_RX_BD;
350543c2aeb0SSepherosa Ziehau 	sc->max_rx_bd = USABLE_RX_BD;
350643c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->rx_low_watermark = USABLE_RX_BD);
350743c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->rx_empty_count = 0);
350843c2aeb0SSepherosa Ziehau 
350943c2aeb0SSepherosa Ziehau 	/* Initialize the RX next pointer chain entries. */
351043c2aeb0SSepherosa Ziehau 	for (i = 0; i < RX_PAGES; i++) {
351143c2aeb0SSepherosa Ziehau 		int j;
351243c2aeb0SSepherosa Ziehau 
351343c2aeb0SSepherosa Ziehau 		rxbd = &sc->rx_bd_chain[i][USABLE_RX_BD_PER_PAGE];
351443c2aeb0SSepherosa Ziehau 
351543c2aeb0SSepherosa Ziehau 		/* Check if we've reached the last page. */
351643c2aeb0SSepherosa Ziehau 		if (i == (RX_PAGES - 1))
351743c2aeb0SSepherosa Ziehau 			j = 0;
351843c2aeb0SSepherosa Ziehau 		else
351943c2aeb0SSepherosa Ziehau 			j = i + 1;
352043c2aeb0SSepherosa Ziehau 
352143c2aeb0SSepherosa Ziehau 		/* Setup the chain page pointers. */
352243c2aeb0SSepherosa Ziehau 		rxbd->rx_bd_haddr_hi =
352343c2aeb0SSepherosa Ziehau 			htole32(BCE_ADDR_HI(sc->rx_bd_chain_paddr[j]));
352443c2aeb0SSepherosa Ziehau 		rxbd->rx_bd_haddr_lo =
352543c2aeb0SSepherosa Ziehau 			htole32(BCE_ADDR_LO(sc->rx_bd_chain_paddr[j]));
352643c2aeb0SSepherosa Ziehau 	}
352743c2aeb0SSepherosa Ziehau 
352843c2aeb0SSepherosa Ziehau 	/* Initialize the context ID for an L2 RX chain. */
352943c2aeb0SSepherosa Ziehau 	val = BCE_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
353043c2aeb0SSepherosa Ziehau 	val |= BCE_L2CTX_CTX_TYPE_SIZE_L2;
353143c2aeb0SSepherosa Ziehau 	val |= 0x02 << 8;
353243c2aeb0SSepherosa Ziehau 	CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_CTX_TYPE, val);
353343c2aeb0SSepherosa Ziehau 
353443c2aeb0SSepherosa Ziehau 	/* Point the hardware to the first page in the chain. */
353543c2aeb0SSepherosa Ziehau 	/* XXX shouldn't this after RX descriptor initialization? */
353643c2aeb0SSepherosa Ziehau 	val = BCE_ADDR_HI(sc->rx_bd_chain_paddr[0]);
353743c2aeb0SSepherosa Ziehau 	CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_NX_BDHADDR_HI, val);
353843c2aeb0SSepherosa Ziehau 	val = BCE_ADDR_LO(sc->rx_bd_chain_paddr[0]);
353943c2aeb0SSepherosa Ziehau 	CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_NX_BDHADDR_LO, val);
354043c2aeb0SSepherosa Ziehau 
354143c2aeb0SSepherosa Ziehau 	/* Allocate mbuf clusters for the rx_bd chain. */
354243c2aeb0SSepherosa Ziehau 	prod = prod_bseq = 0;
354343c2aeb0SSepherosa Ziehau 	while (prod < TOTAL_RX_BD) {
354443c2aeb0SSepherosa Ziehau 		chain_prod = RX_CHAIN_IDX(prod);
354543c2aeb0SSepherosa Ziehau 		if (bce_newbuf_std(sc, NULL, &prod, &chain_prod, &prod_bseq)) {
354643c2aeb0SSepherosa Ziehau 			if_printf(&sc->arpcom.ac_if,
354743c2aeb0SSepherosa Ziehau 				  "Error filling RX chain: rx_bd[0x%04X]!\n",
354843c2aeb0SSepherosa Ziehau 				  chain_prod);
354943c2aeb0SSepherosa Ziehau 			rc = ENOBUFS;
355043c2aeb0SSepherosa Ziehau 			break;
355143c2aeb0SSepherosa Ziehau 		}
355243c2aeb0SSepherosa Ziehau 		prod = NEXT_RX_BD(prod);
355343c2aeb0SSepherosa Ziehau 	}
355443c2aeb0SSepherosa Ziehau 
355543c2aeb0SSepherosa Ziehau 	/* Save the RX chain producer index. */
355643c2aeb0SSepherosa Ziehau 	sc->rx_prod = prod;
355743c2aeb0SSepherosa Ziehau 	sc->rx_prod_bseq = prod_bseq;
355843c2aeb0SSepherosa Ziehau 
355943c2aeb0SSepherosa Ziehau 	for (i = 0; i < RX_PAGES; i++) {
356043c2aeb0SSepherosa Ziehau 		bus_dmamap_sync(sc->rx_bd_chain_tag, sc->rx_bd_chain_map[i],
356143c2aeb0SSepherosa Ziehau 				BUS_DMASYNC_PREWRITE);
356243c2aeb0SSepherosa Ziehau 	}
356343c2aeb0SSepherosa Ziehau 
356443c2aeb0SSepherosa Ziehau 	/* Tell the chip about the waiting rx_bd's. */
356543c2aeb0SSepherosa Ziehau 	REG_WR16(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BDIDX, sc->rx_prod);
356643c2aeb0SSepherosa Ziehau 	REG_WR(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BSEQ, sc->rx_prod_bseq);
356743c2aeb0SSepherosa Ziehau 
356843c2aeb0SSepherosa Ziehau 	DBRUN(BCE_VERBOSE_RECV, bce_dump_rx_chain(sc, 0, TOTAL_RX_BD));
356943c2aeb0SSepherosa Ziehau 
357043c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __func__);
357143c2aeb0SSepherosa Ziehau 
357243c2aeb0SSepherosa Ziehau 	return(rc);
357343c2aeb0SSepherosa Ziehau }
357443c2aeb0SSepherosa Ziehau 
357543c2aeb0SSepherosa Ziehau 
357643c2aeb0SSepherosa Ziehau /****************************************************************************/
357743c2aeb0SSepherosa Ziehau /* Free memory and clear the RX data structures.                            */
357843c2aeb0SSepherosa Ziehau /*                                                                          */
357943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
358043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
358143c2aeb0SSepherosa Ziehau /****************************************************************************/
358243c2aeb0SSepherosa Ziehau static void
358343c2aeb0SSepherosa Ziehau bce_free_rx_chain(struct bce_softc *sc)
358443c2aeb0SSepherosa Ziehau {
358543c2aeb0SSepherosa Ziehau 	int i;
358643c2aeb0SSepherosa Ziehau 
358743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __func__);
358843c2aeb0SSepherosa Ziehau 
358943c2aeb0SSepherosa Ziehau 	/* Free any mbufs still in the RX mbuf chain. */
359043c2aeb0SSepherosa Ziehau 	for (i = 0; i < TOTAL_RX_BD; i++) {
359143c2aeb0SSepherosa Ziehau 		if (sc->rx_mbuf_ptr[i] != NULL) {
359243c2aeb0SSepherosa Ziehau 			bus_dmamap_sync(sc->rx_mbuf_tag, sc->rx_mbuf_map[i],
359343c2aeb0SSepherosa Ziehau 					BUS_DMASYNC_POSTREAD);
359443c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->rx_mbuf_tag, sc->rx_mbuf_map[i]);
359543c2aeb0SSepherosa Ziehau 			m_freem(sc->rx_mbuf_ptr[i]);
359643c2aeb0SSepherosa Ziehau 			sc->rx_mbuf_ptr[i] = NULL;
359743c2aeb0SSepherosa Ziehau 			DBRUNIF(1, sc->rx_mbuf_alloc--);
359843c2aeb0SSepherosa Ziehau 		}
359943c2aeb0SSepherosa Ziehau 	}
360043c2aeb0SSepherosa Ziehau 
360143c2aeb0SSepherosa Ziehau 	/* Clear each RX chain page. */
360243c2aeb0SSepherosa Ziehau 	for (i = 0; i < RX_PAGES; i++)
360343c2aeb0SSepherosa Ziehau 		bzero(sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ);
360443c2aeb0SSepherosa Ziehau 
360543c2aeb0SSepherosa Ziehau 	/* Check if we lost any mbufs in the process. */
360643c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->rx_mbuf_alloc),
360743c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
360843c2aeb0SSepherosa Ziehau 			  "%s(%d): Memory leak! "
360943c2aeb0SSepherosa Ziehau 			  "Lost %d mbufs from rx chain!\n",
361043c2aeb0SSepherosa Ziehau 			  __FILE__, __LINE__, sc->rx_mbuf_alloc));
361143c2aeb0SSepherosa Ziehau 
361243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __func__);
361343c2aeb0SSepherosa Ziehau }
361443c2aeb0SSepherosa Ziehau 
361543c2aeb0SSepherosa Ziehau 
361643c2aeb0SSepherosa Ziehau /****************************************************************************/
361743c2aeb0SSepherosa Ziehau /* Set media options.                                                       */
361843c2aeb0SSepherosa Ziehau /*                                                                          */
361943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
362043c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
362143c2aeb0SSepherosa Ziehau /****************************************************************************/
362243c2aeb0SSepherosa Ziehau static int
362343c2aeb0SSepherosa Ziehau bce_ifmedia_upd(struct ifnet *ifp)
362443c2aeb0SSepherosa Ziehau {
362543c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
362643c2aeb0SSepherosa Ziehau 	struct mii_data *mii = device_get_softc(sc->bce_miibus);
362743c2aeb0SSepherosa Ziehau 
362843c2aeb0SSepherosa Ziehau 	/*
362943c2aeb0SSepherosa Ziehau 	 * 'mii' will be NULL, when this function is called on following
363043c2aeb0SSepherosa Ziehau 	 * code path: bce_attach() -> bce_mgmt_init()
363143c2aeb0SSepherosa Ziehau 	 */
363243c2aeb0SSepherosa Ziehau 	if (mii != NULL) {
363343c2aeb0SSepherosa Ziehau 		/* Make sure the MII bus has been enumerated. */
363443c2aeb0SSepherosa Ziehau 		sc->bce_link = 0;
363543c2aeb0SSepherosa Ziehau 		if (mii->mii_instance) {
363643c2aeb0SSepherosa Ziehau 			struct mii_softc *miisc;
363743c2aeb0SSepherosa Ziehau 
363843c2aeb0SSepherosa Ziehau 			LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
363943c2aeb0SSepherosa Ziehau 				mii_phy_reset(miisc);
364043c2aeb0SSepherosa Ziehau 		}
364143c2aeb0SSepherosa Ziehau 		mii_mediachg(mii);
364243c2aeb0SSepherosa Ziehau 	}
364343c2aeb0SSepherosa Ziehau 	return 0;
364443c2aeb0SSepherosa Ziehau }
364543c2aeb0SSepherosa Ziehau 
364643c2aeb0SSepherosa Ziehau 
364743c2aeb0SSepherosa Ziehau /****************************************************************************/
364843c2aeb0SSepherosa Ziehau /* Reports current media status.                                            */
364943c2aeb0SSepherosa Ziehau /*                                                                          */
365043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
365143c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
365243c2aeb0SSepherosa Ziehau /****************************************************************************/
365343c2aeb0SSepherosa Ziehau static void
365443c2aeb0SSepherosa Ziehau bce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
365543c2aeb0SSepherosa Ziehau {
365643c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
365743c2aeb0SSepherosa Ziehau 	struct mii_data *mii = device_get_softc(sc->bce_miibus);
365843c2aeb0SSepherosa Ziehau 
365943c2aeb0SSepherosa Ziehau 	mii_pollstat(mii);
366043c2aeb0SSepherosa Ziehau 	ifmr->ifm_active = mii->mii_media_active;
366143c2aeb0SSepherosa Ziehau 	ifmr->ifm_status = mii->mii_media_status;
366243c2aeb0SSepherosa Ziehau }
366343c2aeb0SSepherosa Ziehau 
366443c2aeb0SSepherosa Ziehau 
366543c2aeb0SSepherosa Ziehau /****************************************************************************/
366643c2aeb0SSepherosa Ziehau /* Handles PHY generated interrupt events.                                  */
366743c2aeb0SSepherosa Ziehau /*                                                                          */
366843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
366943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
367043c2aeb0SSepherosa Ziehau /****************************************************************************/
367143c2aeb0SSepherosa Ziehau static void
367243c2aeb0SSepherosa Ziehau bce_phy_intr(struct bce_softc *sc)
367343c2aeb0SSepherosa Ziehau {
367443c2aeb0SSepherosa Ziehau 	uint32_t new_link_state, old_link_state;
367543c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
367643c2aeb0SSepherosa Ziehau 
367743c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
367843c2aeb0SSepherosa Ziehau 
367943c2aeb0SSepherosa Ziehau 	new_link_state = sc->status_block->status_attn_bits &
368043c2aeb0SSepherosa Ziehau 			 STATUS_ATTN_BITS_LINK_STATE;
368143c2aeb0SSepherosa Ziehau 	old_link_state = sc->status_block->status_attn_bits_ack &
368243c2aeb0SSepherosa Ziehau 			 STATUS_ATTN_BITS_LINK_STATE;
368343c2aeb0SSepherosa Ziehau 
368443c2aeb0SSepherosa Ziehau 	/* Handle any changes if the link state has changed. */
368543c2aeb0SSepherosa Ziehau 	if (new_link_state != old_link_state) {	/* XXX redundant? */
368643c2aeb0SSepherosa Ziehau 		DBRUN(BCE_VERBOSE_INTR, bce_dump_status_block(sc));
368743c2aeb0SSepherosa Ziehau 
368843c2aeb0SSepherosa Ziehau 		sc->bce_link = 0;
368943c2aeb0SSepherosa Ziehau 		callout_stop(&sc->bce_stat_ch);
369043c2aeb0SSepherosa Ziehau 		bce_tick_serialized(sc);
369143c2aeb0SSepherosa Ziehau 
369243c2aeb0SSepherosa Ziehau 		/* Update the status_attn_bits_ack field in the status block. */
369343c2aeb0SSepherosa Ziehau 		if (new_link_state) {
369443c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_PCICFG_STATUS_BIT_SET_CMD,
369543c2aeb0SSepherosa Ziehau 			       STATUS_ATTN_BITS_LINK_STATE);
369643c2aeb0SSepherosa Ziehau 			if (bootverbose)
369743c2aeb0SSepherosa Ziehau 				if_printf(ifp, "Link is now UP.\n");
369843c2aeb0SSepherosa Ziehau 		} else {
369943c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_PCICFG_STATUS_BIT_CLEAR_CMD,
370043c2aeb0SSepherosa Ziehau 			       STATUS_ATTN_BITS_LINK_STATE);
370143c2aeb0SSepherosa Ziehau 			if (bootverbose)
370243c2aeb0SSepherosa Ziehau 				if_printf(ifp, "Link is now DOWN.\n");
370343c2aeb0SSepherosa Ziehau 		}
370443c2aeb0SSepherosa Ziehau 	}
370543c2aeb0SSepherosa Ziehau 
370643c2aeb0SSepherosa Ziehau 	/* Acknowledge the link change interrupt. */
370743c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_EMAC_STATUS, BCE_EMAC_STATUS_LINK_CHANGE);
370843c2aeb0SSepherosa Ziehau }
370943c2aeb0SSepherosa Ziehau 
371043c2aeb0SSepherosa Ziehau 
371143c2aeb0SSepherosa Ziehau /****************************************************************************/
371224603545SSepherosa Ziehau /* Reads the receive consumer value from the status block (skipping over    */
371324603545SSepherosa Ziehau /* chain page pointer if necessary).                                        */
371424603545SSepherosa Ziehau /*                                                                          */
371524603545SSepherosa Ziehau /* Returns:                                                                 */
371624603545SSepherosa Ziehau /*   hw_cons                                                                */
371724603545SSepherosa Ziehau /****************************************************************************/
371824603545SSepherosa Ziehau static __inline uint16_t
371924603545SSepherosa Ziehau bce_get_hw_rx_cons(struct bce_softc *sc)
372024603545SSepherosa Ziehau {
372124603545SSepherosa Ziehau 	uint16_t hw_cons = sc->status_block->status_rx_quick_consumer_index0;
372224603545SSepherosa Ziehau 
372324603545SSepherosa Ziehau 	if ((hw_cons & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE)
372424603545SSepherosa Ziehau 		hw_cons++;
372524603545SSepherosa Ziehau 	return hw_cons;
372624603545SSepherosa Ziehau }
372724603545SSepherosa Ziehau 
372824603545SSepherosa Ziehau 
372924603545SSepherosa Ziehau /****************************************************************************/
373043c2aeb0SSepherosa Ziehau /* Handles received frame interrupt events.                                 */
373143c2aeb0SSepherosa Ziehau /*                                                                          */
373243c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
373343c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
373443c2aeb0SSepherosa Ziehau /****************************************************************************/
373543c2aeb0SSepherosa Ziehau static void
373643c2aeb0SSepherosa Ziehau bce_rx_intr(struct bce_softc *sc, int count)
373743c2aeb0SSepherosa Ziehau {
373843c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
373943c2aeb0SSepherosa Ziehau 	uint16_t hw_cons, sw_cons, sw_chain_cons, sw_prod, sw_chain_prod;
374043c2aeb0SSepherosa Ziehau 	uint32_t sw_prod_bseq;
374143c2aeb0SSepherosa Ziehau 	int i;
374277a7ee7dSSepherosa Ziehau 	struct mbuf_chain chain[MAXCPU];
374343c2aeb0SSepherosa Ziehau 
374443c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
374543c2aeb0SSepherosa Ziehau 
374677a7ee7dSSepherosa Ziehau 	ether_input_chain_init(chain);
374777a7ee7dSSepherosa Ziehau 
374843c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->rx_interrupts++);
374943c2aeb0SSepherosa Ziehau 
375043c2aeb0SSepherosa Ziehau 	/* Prepare the RX chain pages to be accessed by the host CPU. */
375143c2aeb0SSepherosa Ziehau 	for (i = 0; i < RX_PAGES; i++) {
375243c2aeb0SSepherosa Ziehau 		bus_dmamap_sync(sc->rx_bd_chain_tag,
375343c2aeb0SSepherosa Ziehau 				sc->rx_bd_chain_map[i], BUS_DMASYNC_POSTREAD);
375443c2aeb0SSepherosa Ziehau 	}
375543c2aeb0SSepherosa Ziehau 
375643c2aeb0SSepherosa Ziehau 	/* Get the hardware's view of the RX consumer index. */
375724603545SSepherosa Ziehau 	hw_cons = sc->hw_rx_cons = bce_get_hw_rx_cons(sc);
375843c2aeb0SSepherosa Ziehau 
375943c2aeb0SSepherosa Ziehau 	/* Get working copies of the driver's view of the RX indices. */
376043c2aeb0SSepherosa Ziehau 	sw_cons = sc->rx_cons;
376143c2aeb0SSepherosa Ziehau 	sw_prod = sc->rx_prod;
376243c2aeb0SSepherosa Ziehau 	sw_prod_bseq = sc->rx_prod_bseq;
376343c2aeb0SSepherosa Ziehau 
376443c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RECV, "%s(enter): sw_prod = 0x%04X, "
376543c2aeb0SSepherosa Ziehau 		"sw_cons = 0x%04X, sw_prod_bseq = 0x%08X\n",
376643c2aeb0SSepherosa Ziehau 		__func__, sw_prod, sw_cons, sw_prod_bseq);
376743c2aeb0SSepherosa Ziehau 
376843c2aeb0SSepherosa Ziehau 	/* Prevent speculative reads from getting ahead of the status block. */
376943c2aeb0SSepherosa Ziehau 	bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
377043c2aeb0SSepherosa Ziehau 			  BUS_SPACE_BARRIER_READ);
377143c2aeb0SSepherosa Ziehau 
377243c2aeb0SSepherosa Ziehau 	/* Update some debug statistics counters */
377343c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
377443c2aeb0SSepherosa Ziehau 		sc->rx_low_watermark = sc->free_rx_bd);
377543c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->free_rx_bd == 0), sc->rx_empty_count++);
377643c2aeb0SSepherosa Ziehau 
377743c2aeb0SSepherosa Ziehau 	/* Scan through the receive chain as long as there is work to do. */
377843c2aeb0SSepherosa Ziehau 	while (sw_cons != hw_cons) {
377943c2aeb0SSepherosa Ziehau 		struct mbuf *m = NULL;
378043c2aeb0SSepherosa Ziehau 		struct l2_fhdr *l2fhdr = NULL;
378143c2aeb0SSepherosa Ziehau 		struct rx_bd *rxbd;
378243c2aeb0SSepherosa Ziehau 		unsigned int len;
378343c2aeb0SSepherosa Ziehau 		uint32_t status = 0;
378443c2aeb0SSepherosa Ziehau 
37855205bd03SSepherosa Ziehau #ifdef DEVICE_POLLING
37865205bd03SSepherosa Ziehau 		if (count >= 0 && count-- == 0) {
37875205bd03SSepherosa Ziehau 			sc->hw_rx_cons = sw_cons;
378843c2aeb0SSepherosa Ziehau 			break;
37895205bd03SSepherosa Ziehau 		}
379043c2aeb0SSepherosa Ziehau #endif
379143c2aeb0SSepherosa Ziehau 
379243c2aeb0SSepherosa Ziehau 		/*
379343c2aeb0SSepherosa Ziehau 		 * Convert the producer/consumer indices
379443c2aeb0SSepherosa Ziehau 		 * to an actual rx_bd index.
379543c2aeb0SSepherosa Ziehau 		 */
379643c2aeb0SSepherosa Ziehau 		sw_chain_cons = RX_CHAIN_IDX(sw_cons);
379743c2aeb0SSepherosa Ziehau 		sw_chain_prod = RX_CHAIN_IDX(sw_prod);
379843c2aeb0SSepherosa Ziehau 
379943c2aeb0SSepherosa Ziehau 		/* Get the used rx_bd. */
380043c2aeb0SSepherosa Ziehau 		rxbd = &sc->rx_bd_chain[RX_PAGE(sw_chain_cons)]
380143c2aeb0SSepherosa Ziehau 				       [RX_IDX(sw_chain_cons)];
380243c2aeb0SSepherosa Ziehau 		sc->free_rx_bd++;
380343c2aeb0SSepherosa Ziehau 
380443c2aeb0SSepherosa Ziehau 		DBRUN(BCE_VERBOSE_RECV,
380543c2aeb0SSepherosa Ziehau 		      if_printf(ifp, "%s(): ", __func__);
380643c2aeb0SSepherosa Ziehau 		      bce_dump_rxbd(sc, sw_chain_cons, rxbd));
380743c2aeb0SSepherosa Ziehau 
380843c2aeb0SSepherosa Ziehau 		/* The mbuf is stored with the last rx_bd entry of a packet. */
380943c2aeb0SSepherosa Ziehau 		if (sc->rx_mbuf_ptr[sw_chain_cons] != NULL) {
381043c2aeb0SSepherosa Ziehau 			/* Validate that this is the last rx_bd. */
381143c2aeb0SSepherosa Ziehau 			DBRUNIF((!(rxbd->rx_bd_flags & RX_BD_FLAGS_END)),
381243c2aeb0SSepherosa Ziehau 				if_printf(ifp, "%s(%d): "
381343c2aeb0SSepherosa Ziehau 				"Unexpected mbuf found in rx_bd[0x%04X]!\n",
381443c2aeb0SSepherosa Ziehau 				__FILE__, __LINE__, sw_chain_cons);
381543c2aeb0SSepherosa Ziehau 				bce_breakpoint(sc));
381643c2aeb0SSepherosa Ziehau 
381743c2aeb0SSepherosa Ziehau 			/*
381843c2aeb0SSepherosa Ziehau 			 * ToDo: If the received packet is small enough
381943c2aeb0SSepherosa Ziehau 			 * to fit into a single, non-M_EXT mbuf,
382043c2aeb0SSepherosa Ziehau 			 * allocate a new mbuf here, copy the data to
382143c2aeb0SSepherosa Ziehau 			 * that mbuf, and recycle the mapped jumbo frame.
382243c2aeb0SSepherosa Ziehau 			 */
382343c2aeb0SSepherosa Ziehau 
382443c2aeb0SSepherosa Ziehau 			/* Unmap the mbuf from DMA space. */
382543c2aeb0SSepherosa Ziehau 			bus_dmamap_sync(sc->rx_mbuf_tag,
382643c2aeb0SSepherosa Ziehau 					sc->rx_mbuf_map[sw_chain_cons],
382743c2aeb0SSepherosa Ziehau 					BUS_DMASYNC_POSTREAD);
382843c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->rx_mbuf_tag,
382943c2aeb0SSepherosa Ziehau 					  sc->rx_mbuf_map[sw_chain_cons]);
383043c2aeb0SSepherosa Ziehau 
383143c2aeb0SSepherosa Ziehau 			/* Remove the mbuf from the driver's chain. */
383243c2aeb0SSepherosa Ziehau 			m = sc->rx_mbuf_ptr[sw_chain_cons];
383343c2aeb0SSepherosa Ziehau 			sc->rx_mbuf_ptr[sw_chain_cons] = NULL;
383443c2aeb0SSepherosa Ziehau 
383543c2aeb0SSepherosa Ziehau 			/*
383643c2aeb0SSepherosa Ziehau 			 * Frames received on the NetXteme II are prepended
383743c2aeb0SSepherosa Ziehau 			 * with an l2_fhdr structure which provides status
383843c2aeb0SSepherosa Ziehau 			 * information about the received frame (including
383943c2aeb0SSepherosa Ziehau 			 * VLAN tags and checksum info).  The frames are also
384043c2aeb0SSepherosa Ziehau 			 * automatically adjusted to align the IP header
384143c2aeb0SSepherosa Ziehau 			 * (i.e. two null bytes are inserted before the
384243c2aeb0SSepherosa Ziehau 			 * Ethernet header).
384343c2aeb0SSepherosa Ziehau 			 */
384443c2aeb0SSepherosa Ziehau 			l2fhdr = mtod(m, struct l2_fhdr *);
384543c2aeb0SSepherosa Ziehau 
384643c2aeb0SSepherosa Ziehau 			len = l2fhdr->l2_fhdr_pkt_len;
384743c2aeb0SSepherosa Ziehau 			status = l2fhdr->l2_fhdr_status;
384843c2aeb0SSepherosa Ziehau 
384943c2aeb0SSepherosa Ziehau 			DBRUNIF(DB_RANDOMTRUE(bce_debug_l2fhdr_status_check),
385043c2aeb0SSepherosa Ziehau 				if_printf(ifp,
385143c2aeb0SSepherosa Ziehau 				"Simulating l2_fhdr status error.\n");
385243c2aeb0SSepherosa Ziehau 				status = status | L2_FHDR_ERRORS_PHY_DECODE);
385343c2aeb0SSepherosa Ziehau 
385443c2aeb0SSepherosa Ziehau 			/* Watch for unusual sized frames. */
385543c2aeb0SSepherosa Ziehau 			DBRUNIF((len < BCE_MIN_MTU ||
385643c2aeb0SSepherosa Ziehau 				 len > BCE_MAX_JUMBO_ETHER_MTU_VLAN),
385743c2aeb0SSepherosa Ziehau 				if_printf(ifp,
385843c2aeb0SSepherosa Ziehau 				"%s(%d): Unusual frame size found. "
385943c2aeb0SSepherosa Ziehau 				"Min(%d), Actual(%d), Max(%d)\n",
386043c2aeb0SSepherosa Ziehau 				__FILE__, __LINE__,
386143c2aeb0SSepherosa Ziehau 				(int)BCE_MIN_MTU, len,
386243c2aeb0SSepherosa Ziehau 				(int)BCE_MAX_JUMBO_ETHER_MTU_VLAN);
386343c2aeb0SSepherosa Ziehau 				bce_dump_mbuf(sc, m);
386443c2aeb0SSepherosa Ziehau 		 		bce_breakpoint(sc));
386543c2aeb0SSepherosa Ziehau 
386643c2aeb0SSepherosa Ziehau 			len -= ETHER_CRC_LEN;
386743c2aeb0SSepherosa Ziehau 
386843c2aeb0SSepherosa Ziehau 			/* Check the received frame for errors. */
386943c2aeb0SSepherosa Ziehau 			if (status & (L2_FHDR_ERRORS_BAD_CRC |
387043c2aeb0SSepherosa Ziehau 				      L2_FHDR_ERRORS_PHY_DECODE |
387143c2aeb0SSepherosa Ziehau 				      L2_FHDR_ERRORS_ALIGNMENT |
387243c2aeb0SSepherosa Ziehau 				      L2_FHDR_ERRORS_TOO_SHORT |
387343c2aeb0SSepherosa Ziehau 				      L2_FHDR_ERRORS_GIANT_FRAME)) {
387443c2aeb0SSepherosa Ziehau 				ifp->if_ierrors++;
387543c2aeb0SSepherosa Ziehau 				DBRUNIF(1, sc->l2fhdr_status_errors++);
387643c2aeb0SSepherosa Ziehau 
387743c2aeb0SSepherosa Ziehau 				/* Reuse the mbuf for a new frame. */
387843c2aeb0SSepherosa Ziehau 				if (bce_newbuf_std(sc, m, &sw_prod,
387943c2aeb0SSepherosa Ziehau 						   &sw_chain_prod,
388043c2aeb0SSepherosa Ziehau 						   &sw_prod_bseq)) {
388143c2aeb0SSepherosa Ziehau 					DBRUNIF(1, bce_breakpoint(sc));
388243c2aeb0SSepherosa Ziehau 					/* XXX */
388343c2aeb0SSepherosa Ziehau 					panic("%s: Can't reuse RX mbuf!\n",
388443c2aeb0SSepherosa Ziehau 					      ifp->if_xname);
388543c2aeb0SSepherosa Ziehau 				}
388643c2aeb0SSepherosa Ziehau 				m = NULL;
388743c2aeb0SSepherosa Ziehau 				goto bce_rx_int_next_rx;
388843c2aeb0SSepherosa Ziehau 			}
388943c2aeb0SSepherosa Ziehau 
389043c2aeb0SSepherosa Ziehau 			/*
389143c2aeb0SSepherosa Ziehau 			 * Get a new mbuf for the rx_bd.   If no new
389243c2aeb0SSepherosa Ziehau 			 * mbufs are available then reuse the current mbuf,
389343c2aeb0SSepherosa Ziehau 			 * log an ierror on the interface, and generate
389443c2aeb0SSepherosa Ziehau 			 * an error in the system log.
389543c2aeb0SSepherosa Ziehau 			 */
389643c2aeb0SSepherosa Ziehau 			if (bce_newbuf_std(sc, NULL, &sw_prod, &sw_chain_prod,
389743c2aeb0SSepherosa Ziehau 					   &sw_prod_bseq)) {
389843c2aeb0SSepherosa Ziehau 				DBRUN(BCE_WARN,
389943c2aeb0SSepherosa Ziehau 				      if_printf(ifp,
390043c2aeb0SSepherosa Ziehau 				      "%s(%d): Failed to allocate new mbuf, "
390143c2aeb0SSepherosa Ziehau 				      "incoming frame dropped!\n",
390243c2aeb0SSepherosa Ziehau 				      __FILE__, __LINE__));
390343c2aeb0SSepherosa Ziehau 
390443c2aeb0SSepherosa Ziehau 				ifp->if_ierrors++;
390543c2aeb0SSepherosa Ziehau 
390643c2aeb0SSepherosa Ziehau 				/* Try and reuse the exisitng mbuf. */
390743c2aeb0SSepherosa Ziehau 				if (bce_newbuf_std(sc, m, &sw_prod,
390843c2aeb0SSepherosa Ziehau 						   &sw_chain_prod,
390943c2aeb0SSepherosa Ziehau 						   &sw_prod_bseq)) {
391043c2aeb0SSepherosa Ziehau 					DBRUNIF(1, bce_breakpoint(sc));
391143c2aeb0SSepherosa Ziehau 					/* XXX */
391243c2aeb0SSepherosa Ziehau 					panic("%s: Double mbuf allocation "
391343c2aeb0SSepherosa Ziehau 					      "failure!", ifp->if_xname);
391443c2aeb0SSepherosa Ziehau 				}
391543c2aeb0SSepherosa Ziehau 				m = NULL;
391643c2aeb0SSepherosa Ziehau 				goto bce_rx_int_next_rx;
391743c2aeb0SSepherosa Ziehau 			}
391843c2aeb0SSepherosa Ziehau 
391943c2aeb0SSepherosa Ziehau 			/*
392043c2aeb0SSepherosa Ziehau 			 * Skip over the l2_fhdr when passing
392143c2aeb0SSepherosa Ziehau 			 * the data up the stack.
392243c2aeb0SSepherosa Ziehau 			 */
392343c2aeb0SSepherosa Ziehau 			m_adj(m, sizeof(struct l2_fhdr) + ETHER_ALIGN);
392443c2aeb0SSepherosa Ziehau 
392543c2aeb0SSepherosa Ziehau 			m->m_pkthdr.len = m->m_len = len;
392643c2aeb0SSepherosa Ziehau 			m->m_pkthdr.rcvif = ifp;
392743c2aeb0SSepherosa Ziehau 
392843c2aeb0SSepherosa Ziehau 			DBRUN(BCE_VERBOSE_RECV,
392943c2aeb0SSepherosa Ziehau 			      struct ether_header *eh;
393043c2aeb0SSepherosa Ziehau 			      eh = mtod(m, struct ether_header *);
393143c2aeb0SSepherosa Ziehau 			      if_printf(ifp, "%s(): to: %6D, from: %6D, "
393243c2aeb0SSepherosa Ziehau 			      		"type: 0x%04X\n", __func__,
393343c2aeb0SSepherosa Ziehau 					eh->ether_dhost, ":",
393443c2aeb0SSepherosa Ziehau 					eh->ether_shost, ":",
393543c2aeb0SSepherosa Ziehau 					htons(eh->ether_type)));
393643c2aeb0SSepherosa Ziehau 
393743c2aeb0SSepherosa Ziehau 			/* Validate the checksum if offload enabled. */
393843c2aeb0SSepherosa Ziehau 			if (ifp->if_capenable & IFCAP_RXCSUM) {
393943c2aeb0SSepherosa Ziehau 				/* Check for an IP datagram. */
394043c2aeb0SSepherosa Ziehau 				if (status & L2_FHDR_STATUS_IP_DATAGRAM) {
394143c2aeb0SSepherosa Ziehau 					m->m_pkthdr.csum_flags |=
394243c2aeb0SSepherosa Ziehau 						CSUM_IP_CHECKED;
394343c2aeb0SSepherosa Ziehau 
394443c2aeb0SSepherosa Ziehau 					/* Check if the IP checksum is valid. */
394543c2aeb0SSepherosa Ziehau 					if ((l2fhdr->l2_fhdr_ip_xsum ^
394643c2aeb0SSepherosa Ziehau 					     0xffff) == 0) {
394743c2aeb0SSepherosa Ziehau 						m->m_pkthdr.csum_flags |=
394843c2aeb0SSepherosa Ziehau 							CSUM_IP_VALID;
394943c2aeb0SSepherosa Ziehau 					} else {
395043c2aeb0SSepherosa Ziehau 						DBPRINT(sc, BCE_WARN_RECV,
395143c2aeb0SSepherosa Ziehau 							"%s(): Invalid IP checksum = 0x%04X!\n",
395243c2aeb0SSepherosa Ziehau 							__func__, l2fhdr->l2_fhdr_ip_xsum);
395343c2aeb0SSepherosa Ziehau 					}
395443c2aeb0SSepherosa Ziehau 				}
395543c2aeb0SSepherosa Ziehau 
395643c2aeb0SSepherosa Ziehau 				/* Check for a valid TCP/UDP frame. */
395743c2aeb0SSepherosa Ziehau 				if (status & (L2_FHDR_STATUS_TCP_SEGMENT |
395843c2aeb0SSepherosa Ziehau 					      L2_FHDR_STATUS_UDP_DATAGRAM)) {
395943c2aeb0SSepherosa Ziehau 
396043c2aeb0SSepherosa Ziehau 					/* Check for a good TCP/UDP checksum. */
396143c2aeb0SSepherosa Ziehau 					if ((status &
396243c2aeb0SSepherosa Ziehau 					     (L2_FHDR_ERRORS_TCP_XSUM |
396343c2aeb0SSepherosa Ziehau 					      L2_FHDR_ERRORS_UDP_XSUM)) == 0) {
396443c2aeb0SSepherosa Ziehau 						m->m_pkthdr.csum_data =
396543c2aeb0SSepherosa Ziehau 						l2fhdr->l2_fhdr_tcp_udp_xsum;
396643c2aeb0SSepherosa Ziehau 						m->m_pkthdr.csum_flags |=
396743c2aeb0SSepherosa Ziehau 							CSUM_DATA_VALID |
396843c2aeb0SSepherosa Ziehau 							CSUM_PSEUDO_HDR;
396943c2aeb0SSepherosa Ziehau 					} else {
397043c2aeb0SSepherosa Ziehau 						DBPRINT(sc, BCE_WARN_RECV,
397143c2aeb0SSepherosa Ziehau 							"%s(): Invalid TCP/UDP checksum = 0x%04X!\n",
397243c2aeb0SSepherosa Ziehau 							__func__, l2fhdr->l2_fhdr_tcp_udp_xsum);
397343c2aeb0SSepherosa Ziehau 					}
397443c2aeb0SSepherosa Ziehau 				}
397543c2aeb0SSepherosa Ziehau 			}
397643c2aeb0SSepherosa Ziehau 
397743c2aeb0SSepherosa Ziehau 			ifp->if_ipackets++;
397843c2aeb0SSepherosa Ziehau bce_rx_int_next_rx:
397943c2aeb0SSepherosa Ziehau 			sw_prod = NEXT_RX_BD(sw_prod);
398043c2aeb0SSepherosa Ziehau 		}
398143c2aeb0SSepherosa Ziehau 
398243c2aeb0SSepherosa Ziehau 		sw_cons = NEXT_RX_BD(sw_cons);
398343c2aeb0SSepherosa Ziehau 
398443c2aeb0SSepherosa Ziehau 		/* If we have a packet, pass it up the stack */
398543c2aeb0SSepherosa Ziehau 		if (m) {
398643c2aeb0SSepherosa Ziehau 			DBPRINT(sc, BCE_VERBOSE_RECV,
398743c2aeb0SSepherosa Ziehau 				"%s(): Passing received frame up.\n", __func__);
398843c2aeb0SSepherosa Ziehau 
3989e6b5847cSSepherosa Ziehau 			if (status & L2_FHDR_STATUS_L2_VLAN_TAG) {
3990e6b5847cSSepherosa Ziehau 				m->m_flags |= M_VLANTAG;
3991e6b5847cSSepherosa Ziehau 				m->m_pkthdr.ether_vlantag =
3992e6b5847cSSepherosa Ziehau 					l2fhdr->l2_fhdr_vlan_tag;
3993e6b5847cSSepherosa Ziehau 			}
399450098e2eSSepherosa Ziehau 			ether_input_chain(ifp, m, chain);
399543c2aeb0SSepherosa Ziehau 
399643c2aeb0SSepherosa Ziehau 			DBRUNIF(1, sc->rx_mbuf_alloc--);
399743c2aeb0SSepherosa Ziehau 		}
399843c2aeb0SSepherosa Ziehau 
399943c2aeb0SSepherosa Ziehau 		/*
400043c2aeb0SSepherosa Ziehau 		 * If polling(4) is not enabled, refresh hw_cons to see
400143c2aeb0SSepherosa Ziehau 		 * whether there's new work.
400243c2aeb0SSepherosa Ziehau 		 *
400343c2aeb0SSepherosa Ziehau 		 * If polling(4) is enabled, i.e count >= 0, refreshing
400443c2aeb0SSepherosa Ziehau 		 * should not be performed, so that we would not spend
400543c2aeb0SSepherosa Ziehau 		 * too much time in RX processing.
400643c2aeb0SSepherosa Ziehau 		 */
400724603545SSepherosa Ziehau 		if (count < 0 && sw_cons == hw_cons)
400824603545SSepherosa Ziehau 			hw_cons = sc->hw_rx_cons = bce_get_hw_rx_cons(sc);
400943c2aeb0SSepherosa Ziehau 
401043c2aeb0SSepherosa Ziehau 		/*
401143c2aeb0SSepherosa Ziehau 		 * Prevent speculative reads from getting ahead
401243c2aeb0SSepherosa Ziehau 		 * of the status block.
401343c2aeb0SSepherosa Ziehau 		 */
401443c2aeb0SSepherosa Ziehau 		bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
401543c2aeb0SSepherosa Ziehau 				  BUS_SPACE_BARRIER_READ);
401643c2aeb0SSepherosa Ziehau 	}
401743c2aeb0SSepherosa Ziehau 
401877a7ee7dSSepherosa Ziehau 	ether_input_dispatch(chain);
401977a7ee7dSSepherosa Ziehau 
402043c2aeb0SSepherosa Ziehau 	for (i = 0; i < RX_PAGES; i++) {
402143c2aeb0SSepherosa Ziehau 		bus_dmamap_sync(sc->rx_bd_chain_tag,
402243c2aeb0SSepherosa Ziehau 				sc->rx_bd_chain_map[i], BUS_DMASYNC_PREWRITE);
402343c2aeb0SSepherosa Ziehau 	}
402443c2aeb0SSepherosa Ziehau 
402543c2aeb0SSepherosa Ziehau 	sc->rx_cons = sw_cons;
402643c2aeb0SSepherosa Ziehau 	sc->rx_prod = sw_prod;
402743c2aeb0SSepherosa Ziehau 	sc->rx_prod_bseq = sw_prod_bseq;
402843c2aeb0SSepherosa Ziehau 
402943c2aeb0SSepherosa Ziehau 	REG_WR16(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BDIDX, sc->rx_prod);
403043c2aeb0SSepherosa Ziehau 	REG_WR(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BSEQ, sc->rx_prod_bseq);
403143c2aeb0SSepherosa Ziehau 
403243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_RECV, "%s(exit): rx_prod = 0x%04X, "
403343c2aeb0SSepherosa Ziehau 		"rx_cons = 0x%04X, rx_prod_bseq = 0x%08X\n",
403443c2aeb0SSepherosa Ziehau 		__func__, sc->rx_prod, sc->rx_cons, sc->rx_prod_bseq);
403543c2aeb0SSepherosa Ziehau }
403643c2aeb0SSepherosa Ziehau 
403743c2aeb0SSepherosa Ziehau 
403843c2aeb0SSepherosa Ziehau /****************************************************************************/
403924603545SSepherosa Ziehau /* Reads the transmit consumer value from the status block (skipping over   */
404024603545SSepherosa Ziehau /* chain page pointer if necessary).                                        */
404124603545SSepherosa Ziehau /*                                                                          */
404224603545SSepherosa Ziehau /* Returns:                                                                 */
404324603545SSepherosa Ziehau /*   hw_cons                                                                */
404424603545SSepherosa Ziehau /****************************************************************************/
404524603545SSepherosa Ziehau static __inline uint16_t
404624603545SSepherosa Ziehau bce_get_hw_tx_cons(struct bce_softc *sc)
404724603545SSepherosa Ziehau {
404824603545SSepherosa Ziehau 	uint16_t hw_cons = sc->status_block->status_tx_quick_consumer_index0;
404924603545SSepherosa Ziehau 
405024603545SSepherosa Ziehau 	if ((hw_cons & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE)
405124603545SSepherosa Ziehau 		hw_cons++;
405224603545SSepherosa Ziehau 	return hw_cons;
405324603545SSepherosa Ziehau }
405424603545SSepherosa Ziehau 
405524603545SSepherosa Ziehau 
405624603545SSepherosa Ziehau /****************************************************************************/
405743c2aeb0SSepherosa Ziehau /* Handles transmit completion interrupt events.                            */
405843c2aeb0SSepherosa Ziehau /*                                                                          */
405943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
406043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
406143c2aeb0SSepherosa Ziehau /****************************************************************************/
406243c2aeb0SSepherosa Ziehau static void
406343c2aeb0SSepherosa Ziehau bce_tx_intr(struct bce_softc *sc)
406443c2aeb0SSepherosa Ziehau {
406543c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
406643c2aeb0SSepherosa Ziehau 	uint16_t hw_tx_cons, sw_tx_cons, sw_tx_chain_cons;
406743c2aeb0SSepherosa Ziehau 
406843c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
406943c2aeb0SSepherosa Ziehau 
407043c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->tx_interrupts++);
407143c2aeb0SSepherosa Ziehau 
407243c2aeb0SSepherosa Ziehau 	/* Get the hardware's view of the TX consumer index. */
407324603545SSepherosa Ziehau 	hw_tx_cons = sc->hw_tx_cons = bce_get_hw_tx_cons(sc);
407443c2aeb0SSepherosa Ziehau 	sw_tx_cons = sc->tx_cons;
407543c2aeb0SSepherosa Ziehau 
407643c2aeb0SSepherosa Ziehau 	/* Prevent speculative reads from getting ahead of the status block. */
407743c2aeb0SSepherosa Ziehau 	bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
407843c2aeb0SSepherosa Ziehau 			  BUS_SPACE_BARRIER_READ);
407943c2aeb0SSepherosa Ziehau 
408043c2aeb0SSepherosa Ziehau 	/* Cycle through any completed TX chain page entries. */
408143c2aeb0SSepherosa Ziehau 	while (sw_tx_cons != hw_tx_cons) {
408243c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
408343c2aeb0SSepherosa Ziehau 		struct tx_bd *txbd = NULL;
408443c2aeb0SSepherosa Ziehau #endif
408543c2aeb0SSepherosa Ziehau 		sw_tx_chain_cons = TX_CHAIN_IDX(sw_tx_cons);
408643c2aeb0SSepherosa Ziehau 
408743c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO_SEND,
408843c2aeb0SSepherosa Ziehau 			"%s(): hw_tx_cons = 0x%04X, sw_tx_cons = 0x%04X, "
408943c2aeb0SSepherosa Ziehau 			"sw_tx_chain_cons = 0x%04X\n",
409043c2aeb0SSepherosa Ziehau 			__func__, hw_tx_cons, sw_tx_cons, sw_tx_chain_cons);
409143c2aeb0SSepherosa Ziehau 
409243c2aeb0SSepherosa Ziehau 		DBRUNIF((sw_tx_chain_cons > MAX_TX_BD),
409343c2aeb0SSepherosa Ziehau 			if_printf(ifp, "%s(%d): "
409443c2aeb0SSepherosa Ziehau 				  "TX chain consumer out of range! "
409543c2aeb0SSepherosa Ziehau 				  " 0x%04X > 0x%04X\n",
409643c2aeb0SSepherosa Ziehau 				  __FILE__, __LINE__, sw_tx_chain_cons,
409743c2aeb0SSepherosa Ziehau 				  (int)MAX_TX_BD);
409843c2aeb0SSepherosa Ziehau 			bce_breakpoint(sc));
409943c2aeb0SSepherosa Ziehau 
410043c2aeb0SSepherosa Ziehau 		DBRUNIF(1, txbd = &sc->tx_bd_chain[TX_PAGE(sw_tx_chain_cons)]
410143c2aeb0SSepherosa Ziehau 				[TX_IDX(sw_tx_chain_cons)]);
410243c2aeb0SSepherosa Ziehau 
410343c2aeb0SSepherosa Ziehau 		DBRUNIF((txbd == NULL),
410443c2aeb0SSepherosa Ziehau 			if_printf(ifp, "%s(%d): "
410543c2aeb0SSepherosa Ziehau 				  "Unexpected NULL tx_bd[0x%04X]!\n",
410643c2aeb0SSepherosa Ziehau 				  __FILE__, __LINE__, sw_tx_chain_cons);
410743c2aeb0SSepherosa Ziehau 			bce_breakpoint(sc));
410843c2aeb0SSepherosa Ziehau 
410943c2aeb0SSepherosa Ziehau 		DBRUN(BCE_INFO_SEND,
411043c2aeb0SSepherosa Ziehau 		      if_printf(ifp, "%s(): ", __func__);
411143c2aeb0SSepherosa Ziehau 		      bce_dump_txbd(sc, sw_tx_chain_cons, txbd));
411243c2aeb0SSepherosa Ziehau 
411343c2aeb0SSepherosa Ziehau 		/*
411443c2aeb0SSepherosa Ziehau 		 * Free the associated mbuf. Remember
411543c2aeb0SSepherosa Ziehau 		 * that only the last tx_bd of a packet
411643c2aeb0SSepherosa Ziehau 		 * has an mbuf pointer and DMA map.
411743c2aeb0SSepherosa Ziehau 		 */
411843c2aeb0SSepherosa Ziehau 		if (sc->tx_mbuf_ptr[sw_tx_chain_cons] != NULL) {
411943c2aeb0SSepherosa Ziehau 			/* Validate that this is the last tx_bd. */
412043c2aeb0SSepherosa Ziehau 			DBRUNIF((!(txbd->tx_bd_flags & TX_BD_FLAGS_END)),
412143c2aeb0SSepherosa Ziehau 				if_printf(ifp, "%s(%d): "
412243c2aeb0SSepherosa Ziehau 				"tx_bd END flag not set but "
412343c2aeb0SSepherosa Ziehau 				"txmbuf == NULL!\n", __FILE__, __LINE__);
412443c2aeb0SSepherosa Ziehau 				bce_breakpoint(sc));
412543c2aeb0SSepherosa Ziehau 
412643c2aeb0SSepherosa Ziehau 			DBRUN(BCE_INFO_SEND,
412743c2aeb0SSepherosa Ziehau 			      if_printf(ifp, "%s(): Unloading map/freeing mbuf "
412843c2aeb0SSepherosa Ziehau 			      		"from tx_bd[0x%04X]\n", __func__,
412943c2aeb0SSepherosa Ziehau 					sw_tx_chain_cons));
413043c2aeb0SSepherosa Ziehau 
413143c2aeb0SSepherosa Ziehau 			/* Unmap the mbuf. */
413243c2aeb0SSepherosa Ziehau 			bus_dmamap_unload(sc->tx_mbuf_tag,
413343c2aeb0SSepherosa Ziehau 					  sc->tx_mbuf_map[sw_tx_chain_cons]);
413443c2aeb0SSepherosa Ziehau 
413543c2aeb0SSepherosa Ziehau 			/* Free the mbuf. */
413643c2aeb0SSepherosa Ziehau 			m_freem(sc->tx_mbuf_ptr[sw_tx_chain_cons]);
413743c2aeb0SSepherosa Ziehau 			sc->tx_mbuf_ptr[sw_tx_chain_cons] = NULL;
413843c2aeb0SSepherosa Ziehau 			DBRUNIF(1, sc->tx_mbuf_alloc--);
413943c2aeb0SSepherosa Ziehau 
414043c2aeb0SSepherosa Ziehau 			ifp->if_opackets++;
414143c2aeb0SSepherosa Ziehau 		}
414243c2aeb0SSepherosa Ziehau 
414343c2aeb0SSepherosa Ziehau 		sc->used_tx_bd--;
414443c2aeb0SSepherosa Ziehau 		sw_tx_cons = NEXT_TX_BD(sw_tx_cons);
414543c2aeb0SSepherosa Ziehau 
414643c2aeb0SSepherosa Ziehau 		if (sw_tx_cons == hw_tx_cons) {
414743c2aeb0SSepherosa Ziehau 			/* Refresh hw_cons to see if there's new work. */
414824603545SSepherosa Ziehau 			hw_tx_cons = sc->hw_tx_cons = bce_get_hw_tx_cons(sc);
414943c2aeb0SSepherosa Ziehau 		}
415043c2aeb0SSepherosa Ziehau 
415143c2aeb0SSepherosa Ziehau 		/*
415243c2aeb0SSepherosa Ziehau 		 * Prevent speculative reads from getting
415343c2aeb0SSepherosa Ziehau 		 * ahead of the status block.
415443c2aeb0SSepherosa Ziehau 		 */
415543c2aeb0SSepherosa Ziehau 		bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
415643c2aeb0SSepherosa Ziehau 				  BUS_SPACE_BARRIER_READ);
415743c2aeb0SSepherosa Ziehau 	}
415843c2aeb0SSepherosa Ziehau 
415943c2aeb0SSepherosa Ziehau 	if (sc->used_tx_bd == 0) {
416043c2aeb0SSepherosa Ziehau 		/* Clear the TX timeout timer. */
416143c2aeb0SSepherosa Ziehau 		ifp->if_timer = 0;
416243c2aeb0SSepherosa Ziehau 	}
416343c2aeb0SSepherosa Ziehau 
416443c2aeb0SSepherosa Ziehau 	/* Clear the tx hardware queue full flag. */
416543c2aeb0SSepherosa Ziehau 	if (sc->max_tx_bd - sc->used_tx_bd >= BCE_TX_SPARE_SPACE) {
416643c2aeb0SSepherosa Ziehau 		DBRUNIF((ifp->if_flags & IFF_OACTIVE),
416743c2aeb0SSepherosa Ziehau 			DBPRINT(sc, BCE_WARN_SEND,
416843c2aeb0SSepherosa Ziehau 				"%s(): Open TX chain! %d/%d (used/total)\n",
416943c2aeb0SSepherosa Ziehau 				__func__, sc->used_tx_bd, sc->max_tx_bd));
417043c2aeb0SSepherosa Ziehau 		ifp->if_flags &= ~IFF_OACTIVE;
417143c2aeb0SSepherosa Ziehau 	}
417243c2aeb0SSepherosa Ziehau 	sc->tx_cons = sw_tx_cons;
417343c2aeb0SSepherosa Ziehau }
417443c2aeb0SSepherosa Ziehau 
417543c2aeb0SSepherosa Ziehau 
417643c2aeb0SSepherosa Ziehau /****************************************************************************/
417743c2aeb0SSepherosa Ziehau /* Disables interrupt generation.                                           */
417843c2aeb0SSepherosa Ziehau /*                                                                          */
417943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
418043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
418143c2aeb0SSepherosa Ziehau /****************************************************************************/
418243c2aeb0SSepherosa Ziehau static void
418343c2aeb0SSepherosa Ziehau bce_disable_intr(struct bce_softc *sc)
418443c2aeb0SSepherosa Ziehau {
418543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, BCE_PCICFG_INT_ACK_CMD_MASK_INT);
418643c2aeb0SSepherosa Ziehau 	REG_RD(sc, BCE_PCICFG_INT_ACK_CMD);
418743c2aeb0SSepherosa Ziehau 	lwkt_serialize_handler_disable(sc->arpcom.ac_if.if_serializer);
418843c2aeb0SSepherosa Ziehau }
418943c2aeb0SSepherosa Ziehau 
419043c2aeb0SSepherosa Ziehau 
419143c2aeb0SSepherosa Ziehau /****************************************************************************/
419243c2aeb0SSepherosa Ziehau /* Enables interrupt generation.                                            */
419343c2aeb0SSepherosa Ziehau /*                                                                          */
419443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
419543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
419643c2aeb0SSepherosa Ziehau /****************************************************************************/
419743c2aeb0SSepherosa Ziehau static void
419843c2aeb0SSepherosa Ziehau bce_enable_intr(struct bce_softc *sc)
419943c2aeb0SSepherosa Ziehau {
420043c2aeb0SSepherosa Ziehau 	uint32_t val;
420143c2aeb0SSepherosa Ziehau 
420243c2aeb0SSepherosa Ziehau 	lwkt_serialize_handler_enable(sc->arpcom.ac_if.if_serializer);
420343c2aeb0SSepherosa Ziehau 
420443c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
420543c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID |
420643c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_MASK_INT | sc->last_status_idx);
420743c2aeb0SSepherosa Ziehau 
420843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
420943c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx);
421043c2aeb0SSepherosa Ziehau 
421143c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_HC_COMMAND);
421243c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_HC_COMMAND, val | BCE_HC_COMMAND_COAL_NOW);
421343c2aeb0SSepherosa Ziehau }
421443c2aeb0SSepherosa Ziehau 
421543c2aeb0SSepherosa Ziehau 
421643c2aeb0SSepherosa Ziehau /****************************************************************************/
421743c2aeb0SSepherosa Ziehau /* Handles controller initialization.                                       */
421843c2aeb0SSepherosa Ziehau /*                                                                          */
421943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
422043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
422143c2aeb0SSepherosa Ziehau /****************************************************************************/
422243c2aeb0SSepherosa Ziehau static void
422343c2aeb0SSepherosa Ziehau bce_init(void *xsc)
422443c2aeb0SSepherosa Ziehau {
422543c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = xsc;
422643c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
422743c2aeb0SSepherosa Ziehau 	uint32_t ether_mtu;
422843c2aeb0SSepherosa Ziehau 	int error;
422943c2aeb0SSepherosa Ziehau 
423043c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
423143c2aeb0SSepherosa Ziehau 
423243c2aeb0SSepherosa Ziehau 	/* Check if the driver is still running and bail out if it is. */
423343c2aeb0SSepherosa Ziehau 	if (ifp->if_flags & IFF_RUNNING)
423443c2aeb0SSepherosa Ziehau 		return;
423543c2aeb0SSepherosa Ziehau 
423643c2aeb0SSepherosa Ziehau 	bce_stop(sc);
423743c2aeb0SSepherosa Ziehau 
423843c2aeb0SSepherosa Ziehau 	error = bce_reset(sc, BCE_DRV_MSG_CODE_RESET);
423943c2aeb0SSepherosa Ziehau 	if (error) {
424043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Controller reset failed!\n");
424143c2aeb0SSepherosa Ziehau 		goto back;
424243c2aeb0SSepherosa Ziehau 	}
424343c2aeb0SSepherosa Ziehau 
424443c2aeb0SSepherosa Ziehau 	error = bce_chipinit(sc);
424543c2aeb0SSepherosa Ziehau 	if (error) {
424643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Controller initialization failed!\n");
424743c2aeb0SSepherosa Ziehau 		goto back;
424843c2aeb0SSepherosa Ziehau 	}
424943c2aeb0SSepherosa Ziehau 
425043c2aeb0SSepherosa Ziehau 	error = bce_blockinit(sc);
425143c2aeb0SSepherosa Ziehau 	if (error) {
425243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "Block initialization failed!\n");
425343c2aeb0SSepherosa Ziehau 		goto back;
425443c2aeb0SSepherosa Ziehau 	}
425543c2aeb0SSepherosa Ziehau 
425643c2aeb0SSepherosa Ziehau 	/* Load our MAC address. */
425743c2aeb0SSepherosa Ziehau 	bcopy(IF_LLADDR(ifp), sc->eaddr, ETHER_ADDR_LEN);
425843c2aeb0SSepherosa Ziehau 	bce_set_mac_addr(sc);
425943c2aeb0SSepherosa Ziehau 
426043c2aeb0SSepherosa Ziehau 	/* Calculate and program the Ethernet MTU size. */
426143c2aeb0SSepherosa Ziehau 	ether_mtu = ETHER_HDR_LEN + EVL_ENCAPLEN + ifp->if_mtu + ETHER_CRC_LEN;
426243c2aeb0SSepherosa Ziehau 
426343c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO, "%s(): setting mtu = %d\n", __func__, ether_mtu);
426443c2aeb0SSepherosa Ziehau 
426543c2aeb0SSepherosa Ziehau 	/*
426643c2aeb0SSepherosa Ziehau 	 * Program the mtu, enabling jumbo frame
426743c2aeb0SSepherosa Ziehau 	 * support if necessary.  Also set the mbuf
426843c2aeb0SSepherosa Ziehau 	 * allocation count for RX frames.
426943c2aeb0SSepherosa Ziehau 	 */
427043c2aeb0SSepherosa Ziehau 	if (ether_mtu > ETHER_MAX_LEN + EVL_ENCAPLEN) {
427143c2aeb0SSepherosa Ziehau #ifdef notyet
427243c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_RX_MTU_SIZE,
427343c2aeb0SSepherosa Ziehau 		       min(ether_mtu, BCE_MAX_JUMBO_ETHER_MTU) |
427443c2aeb0SSepherosa Ziehau 		       BCE_EMAC_RX_MTU_SIZE_JUMBO_ENA);
427543c2aeb0SSepherosa Ziehau 		sc->mbuf_alloc_size = MJUM9BYTES;
427643c2aeb0SSepherosa Ziehau #else
427743c2aeb0SSepherosa Ziehau 		panic("jumbo buffer is not supported yet\n");
427843c2aeb0SSepherosa Ziehau #endif
427943c2aeb0SSepherosa Ziehau 	} else {
428043c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, ether_mtu);
428143c2aeb0SSepherosa Ziehau 		sc->mbuf_alloc_size = MCLBYTES;
428243c2aeb0SSepherosa Ziehau 	}
428343c2aeb0SSepherosa Ziehau 
428443c2aeb0SSepherosa Ziehau 	/* Calculate the RX Ethernet frame size for rx_bd's. */
428543c2aeb0SSepherosa Ziehau 	sc->max_frame_size = sizeof(struct l2_fhdr) + 2 + ether_mtu + 8;
428643c2aeb0SSepherosa Ziehau 
428743c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO,
428843c2aeb0SSepherosa Ziehau 		"%s(): mclbytes = %d, mbuf_alloc_size = %d, "
428943c2aeb0SSepherosa Ziehau 		"max_frame_size = %d\n",
429043c2aeb0SSepherosa Ziehau 		__func__, (int)MCLBYTES, sc->mbuf_alloc_size,
429143c2aeb0SSepherosa Ziehau 		sc->max_frame_size);
429243c2aeb0SSepherosa Ziehau 
429343c2aeb0SSepherosa Ziehau 	/* Program appropriate promiscuous/multicast filtering. */
429443c2aeb0SSepherosa Ziehau 	bce_set_rx_mode(sc);
429543c2aeb0SSepherosa Ziehau 
429643c2aeb0SSepherosa Ziehau 	/* Init RX buffer descriptor chain. */
429743c2aeb0SSepherosa Ziehau 	bce_init_rx_chain(sc);	/* XXX return value */
429843c2aeb0SSepherosa Ziehau 
429943c2aeb0SSepherosa Ziehau 	/* Init TX buffer descriptor chain. */
430043c2aeb0SSepherosa Ziehau 	bce_init_tx_chain(sc);	/* XXX return value */
430143c2aeb0SSepherosa Ziehau 
430243c2aeb0SSepherosa Ziehau #ifdef DEVICE_POLLING
430343c2aeb0SSepherosa Ziehau 	/* Disable interrupts if we are polling. */
430443c2aeb0SSepherosa Ziehau 	if (ifp->if_flags & IFF_POLLING) {
430543c2aeb0SSepherosa Ziehau 		bce_disable_intr(sc);
430643c2aeb0SSepherosa Ziehau 
430743c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
430843c2aeb0SSepherosa Ziehau 		       (1 << 16) | sc->bce_rx_quick_cons_trip);
430943c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
431043c2aeb0SSepherosa Ziehau 		       (1 << 16) | sc->bce_tx_quick_cons_trip);
431143c2aeb0SSepherosa Ziehau 	} else
431243c2aeb0SSepherosa Ziehau #endif
431343c2aeb0SSepherosa Ziehau 	/* Enable host interrupts. */
431443c2aeb0SSepherosa Ziehau 	bce_enable_intr(sc);
431543c2aeb0SSepherosa Ziehau 
431643c2aeb0SSepherosa Ziehau 	bce_ifmedia_upd(ifp);
431743c2aeb0SSepherosa Ziehau 
431843c2aeb0SSepherosa Ziehau 	ifp->if_flags |= IFF_RUNNING;
431943c2aeb0SSepherosa Ziehau 	ifp->if_flags &= ~IFF_OACTIVE;
432043c2aeb0SSepherosa Ziehau 
432143c2aeb0SSepherosa Ziehau 	callout_reset(&sc->bce_stat_ch, hz, bce_tick, sc);
432243c2aeb0SSepherosa Ziehau back:
432343c2aeb0SSepherosa Ziehau 	if (error)
432443c2aeb0SSepherosa Ziehau 		bce_stop(sc);
432543c2aeb0SSepherosa Ziehau }
432643c2aeb0SSepherosa Ziehau 
432743c2aeb0SSepherosa Ziehau 
432843c2aeb0SSepherosa Ziehau /****************************************************************************/
432943c2aeb0SSepherosa Ziehau /* Initialize the controller just enough so that any management firmware    */
433043c2aeb0SSepherosa Ziehau /* running on the device will continue to operate corectly.                 */
433143c2aeb0SSepherosa Ziehau /*                                                                          */
433243c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
433343c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
433443c2aeb0SSepherosa Ziehau /****************************************************************************/
433543c2aeb0SSepherosa Ziehau static void
433643c2aeb0SSepherosa Ziehau bce_mgmt_init(struct bce_softc *sc)
433743c2aeb0SSepherosa Ziehau {
433843c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
433943c2aeb0SSepherosa Ziehau 	uint32_t val;
434043c2aeb0SSepherosa Ziehau 
434143c2aeb0SSepherosa Ziehau 	/* Check if the driver is still running and bail out if it is. */
434243c2aeb0SSepherosa Ziehau 	if (ifp->if_flags & IFF_RUNNING)
434343c2aeb0SSepherosa Ziehau 		return;
434443c2aeb0SSepherosa Ziehau 
434543c2aeb0SSepherosa Ziehau 	/* Initialize the on-boards CPUs */
434643c2aeb0SSepherosa Ziehau 	bce_init_cpus(sc);
434743c2aeb0SSepherosa Ziehau 
434843c2aeb0SSepherosa Ziehau 	/* Set the page size and clear the RV2P processor stall bits. */
434943c2aeb0SSepherosa Ziehau 	val = (BCM_PAGE_BITS - 8) << 24;
435043c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_RV2P_CONFIG, val);
435143c2aeb0SSepherosa Ziehau 
435243c2aeb0SSepherosa Ziehau 	/* Enable all critical blocks in the MAC. */
435343c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
435443c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE |
435543c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE |
435643c2aeb0SSepherosa Ziehau 	       BCE_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE);
435743c2aeb0SSepherosa Ziehau 	REG_RD(sc, BCE_MISC_ENABLE_SET_BITS);
435843c2aeb0SSepherosa Ziehau 	DELAY(20);
435943c2aeb0SSepherosa Ziehau 
436043c2aeb0SSepherosa Ziehau 	bce_ifmedia_upd(ifp);
436143c2aeb0SSepherosa Ziehau }
436243c2aeb0SSepherosa Ziehau 
436343c2aeb0SSepherosa Ziehau 
436443c2aeb0SSepherosa Ziehau /****************************************************************************/
436543c2aeb0SSepherosa Ziehau /* Encapsultes an mbuf cluster into the tx_bd chain structure and makes the */
436643c2aeb0SSepherosa Ziehau /* memory visible to the controller.                                        */
436743c2aeb0SSepherosa Ziehau /*                                                                          */
436843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
436943c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
437043c2aeb0SSepherosa Ziehau /****************************************************************************/
437143c2aeb0SSepherosa Ziehau static int
437243c2aeb0SSepherosa Ziehau bce_encap(struct bce_softc *sc, struct mbuf **m_head)
437343c2aeb0SSepherosa Ziehau {
437443c2aeb0SSepherosa Ziehau 	struct bce_dmamap_arg ctx;
437543c2aeb0SSepherosa Ziehau 	bus_dma_segment_t segs[BCE_MAX_SEGMENTS];
437643c2aeb0SSepherosa Ziehau 	bus_dmamap_t map, tmp_map;
437743c2aeb0SSepherosa Ziehau 	struct mbuf *m0 = *m_head;
437843c2aeb0SSepherosa Ziehau 	struct tx_bd *txbd = NULL;
437943c2aeb0SSepherosa Ziehau 	uint16_t vlan_tag = 0, flags = 0;
438043c2aeb0SSepherosa Ziehau 	uint16_t chain_prod, chain_prod_start, prod;
438143c2aeb0SSepherosa Ziehau 	uint32_t prod_bseq;
438243c2aeb0SSepherosa Ziehau 	int i, error, maxsegs;
438343c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
438443c2aeb0SSepherosa Ziehau 	uint16_t debug_prod;
438543c2aeb0SSepherosa Ziehau #endif
438643c2aeb0SSepherosa Ziehau 
438743c2aeb0SSepherosa Ziehau 	/* Transfer any checksum offload flags to the bd. */
438843c2aeb0SSepherosa Ziehau 	if (m0->m_pkthdr.csum_flags) {
438943c2aeb0SSepherosa Ziehau 		if (m0->m_pkthdr.csum_flags & CSUM_IP)
439043c2aeb0SSepherosa Ziehau 			flags |= TX_BD_FLAGS_IP_CKSUM;
439143c2aeb0SSepherosa Ziehau 		if (m0->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))
439243c2aeb0SSepherosa Ziehau 			flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
439343c2aeb0SSepherosa Ziehau 	}
439443c2aeb0SSepherosa Ziehau 
439543c2aeb0SSepherosa Ziehau 	/* Transfer any VLAN tags to the bd. */
439683790f85SSepherosa Ziehau 	if (m0->m_flags & M_VLANTAG) {
439743c2aeb0SSepherosa Ziehau 		flags |= TX_BD_FLAGS_VLAN_TAG;
439883790f85SSepherosa Ziehau 		vlan_tag = m0->m_pkthdr.ether_vlantag;
439943c2aeb0SSepherosa Ziehau 	}
440043c2aeb0SSepherosa Ziehau 
440143c2aeb0SSepherosa Ziehau 	prod = sc->tx_prod;
440243c2aeb0SSepherosa Ziehau 	chain_prod_start = chain_prod = TX_CHAIN_IDX(prod);
440343c2aeb0SSepherosa Ziehau 
440443c2aeb0SSepherosa Ziehau 	/* Map the mbuf into DMAable memory. */
440543c2aeb0SSepherosa Ziehau 	map = sc->tx_mbuf_map[chain_prod_start];
440643c2aeb0SSepherosa Ziehau 
440743c2aeb0SSepherosa Ziehau 	maxsegs = sc->max_tx_bd - sc->used_tx_bd;
440843c2aeb0SSepherosa Ziehau 	KASSERT(maxsegs >= BCE_TX_SPARE_SPACE,
440943c2aeb0SSepherosa Ziehau 		("not enough segements %d\n", maxsegs));
441043c2aeb0SSepherosa Ziehau 	if (maxsegs > BCE_MAX_SEGMENTS)
441143c2aeb0SSepherosa Ziehau 		maxsegs = BCE_MAX_SEGMENTS;
441243c2aeb0SSepherosa Ziehau 
441343c2aeb0SSepherosa Ziehau 	/* Map the mbuf into our DMA address space. */
441443c2aeb0SSepherosa Ziehau 	ctx.bce_maxsegs = maxsegs;
441543c2aeb0SSepherosa Ziehau 	ctx.bce_segs = segs;
441643c2aeb0SSepherosa Ziehau 	error = bus_dmamap_load_mbuf(sc->tx_mbuf_tag, map, m0,
441743c2aeb0SSepherosa Ziehau 				     bce_dma_map_mbuf, &ctx, BUS_DMA_NOWAIT);
441843c2aeb0SSepherosa Ziehau 	if (error == EFBIG || ctx.bce_maxsegs == 0) {
441943c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_WARN, "%s(): fragmented mbuf\n", __func__);
442043c2aeb0SSepherosa Ziehau 		DBRUNIF(1, bce_dump_mbuf(sc, m0););
442143c2aeb0SSepherosa Ziehau 
442243c2aeb0SSepherosa Ziehau 		m0 = m_defrag(*m_head, MB_DONTWAIT);
442343c2aeb0SSepherosa Ziehau 		if (m0 == NULL) {
442443c2aeb0SSepherosa Ziehau 			error = ENOBUFS;
442543c2aeb0SSepherosa Ziehau 			goto back;
442643c2aeb0SSepherosa Ziehau 		}
442743c2aeb0SSepherosa Ziehau 		*m_head = m0;
442843c2aeb0SSepherosa Ziehau 
442943c2aeb0SSepherosa Ziehau 		ctx.bce_maxsegs = maxsegs;
443043c2aeb0SSepherosa Ziehau 		ctx.bce_segs = segs;
443143c2aeb0SSepherosa Ziehau 		error = bus_dmamap_load_mbuf(sc->tx_mbuf_tag, map, m0,
443243c2aeb0SSepherosa Ziehau 					     bce_dma_map_mbuf, &ctx,
443343c2aeb0SSepherosa Ziehau 					     BUS_DMA_NOWAIT);
443443c2aeb0SSepherosa Ziehau 		if (error || ctx.bce_maxsegs == 0) {
443543c2aeb0SSepherosa Ziehau 			if_printf(&sc->arpcom.ac_if,
443643c2aeb0SSepherosa Ziehau 				  "Error mapping mbuf into TX chain\n");
443743c2aeb0SSepherosa Ziehau 			if (error == 0)
443843c2aeb0SSepherosa Ziehau 				error = EFBIG;
443943c2aeb0SSepherosa Ziehau 			goto back;
444043c2aeb0SSepherosa Ziehau 		}
444143c2aeb0SSepherosa Ziehau 	} else if (error) {
444243c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
444343c2aeb0SSepherosa Ziehau 			  "Error mapping mbuf into TX chain\n");
444443c2aeb0SSepherosa Ziehau 		goto back;
444543c2aeb0SSepherosa Ziehau 	}
444643c2aeb0SSepherosa Ziehau 
444743c2aeb0SSepherosa Ziehau 	/* prod points to an empty tx_bd at this point. */
444843c2aeb0SSepherosa Ziehau 	prod_bseq  = sc->tx_prod_bseq;
444943c2aeb0SSepherosa Ziehau 
445043c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
445143c2aeb0SSepherosa Ziehau 	debug_prod = chain_prod;
445243c2aeb0SSepherosa Ziehau #endif
445343c2aeb0SSepherosa Ziehau 
445443c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_SEND,
445543c2aeb0SSepherosa Ziehau 		"%s(): Start: prod = 0x%04X, chain_prod = %04X, "
445643c2aeb0SSepherosa Ziehau 		"prod_bseq = 0x%08X\n",
445743c2aeb0SSepherosa Ziehau 		__func__, prod, chain_prod, prod_bseq);
445843c2aeb0SSepherosa Ziehau 
445943c2aeb0SSepherosa Ziehau 	/*
446043c2aeb0SSepherosa Ziehau 	 * Cycle through each mbuf segment that makes up
446143c2aeb0SSepherosa Ziehau 	 * the outgoing frame, gathering the mapping info
446243c2aeb0SSepherosa Ziehau 	 * for that segment and creating a tx_bd to for
446343c2aeb0SSepherosa Ziehau 	 * the mbuf.
446443c2aeb0SSepherosa Ziehau 	 */
446543c2aeb0SSepherosa Ziehau 	for (i = 0; i < ctx.bce_maxsegs; i++) {
446643c2aeb0SSepherosa Ziehau 		chain_prod = TX_CHAIN_IDX(prod);
446743c2aeb0SSepherosa Ziehau 		txbd= &sc->tx_bd_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)];
446843c2aeb0SSepherosa Ziehau 
446943c2aeb0SSepherosa Ziehau 		txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr));
447043c2aeb0SSepherosa Ziehau 		txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr));
447143c2aeb0SSepherosa Ziehau 		txbd->tx_bd_mss_nbytes = htole16(segs[i].ds_len);
447243c2aeb0SSepherosa Ziehau 		txbd->tx_bd_vlan_tag = htole16(vlan_tag);
447343c2aeb0SSepherosa Ziehau 		txbd->tx_bd_flags = htole16(flags);
447443c2aeb0SSepherosa Ziehau 		prod_bseq += segs[i].ds_len;
447543c2aeb0SSepherosa Ziehau 		if (i == 0)
447643c2aeb0SSepherosa Ziehau 			txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_START);
447743c2aeb0SSepherosa Ziehau 		prod = NEXT_TX_BD(prod);
447843c2aeb0SSepherosa Ziehau 	}
447943c2aeb0SSepherosa Ziehau 
448043c2aeb0SSepherosa Ziehau 	/* Set the END flag on the last TX buffer descriptor. */
448143c2aeb0SSepherosa Ziehau 	txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_END);
448243c2aeb0SSepherosa Ziehau 
448343c2aeb0SSepherosa Ziehau 	DBRUN(BCE_EXCESSIVE_SEND,
448443c2aeb0SSepherosa Ziehau 	      bce_dump_tx_chain(sc, debug_prod, ctx.bce_maxsegs));
448543c2aeb0SSepherosa Ziehau 
448643c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_SEND,
448743c2aeb0SSepherosa Ziehau 		"%s(): End: prod = 0x%04X, chain_prod = %04X, "
448843c2aeb0SSepherosa Ziehau 		"prod_bseq = 0x%08X\n",
448943c2aeb0SSepherosa Ziehau 		__func__, prod, chain_prod, prod_bseq);
449043c2aeb0SSepherosa Ziehau 
449143c2aeb0SSepherosa Ziehau 	bus_dmamap_sync(sc->tx_mbuf_tag, map, BUS_DMASYNC_PREWRITE);
449243c2aeb0SSepherosa Ziehau 
449343c2aeb0SSepherosa Ziehau 	/*
449443c2aeb0SSepherosa Ziehau 	 * Ensure that the mbuf pointer for this transmission
449543c2aeb0SSepherosa Ziehau 	 * is placed at the array index of the last
449643c2aeb0SSepherosa Ziehau 	 * descriptor in this chain.  This is done
449743c2aeb0SSepherosa Ziehau 	 * because a single map is used for all
449843c2aeb0SSepherosa Ziehau 	 * segments of the mbuf and we don't want to
449943c2aeb0SSepherosa Ziehau 	 * unload the map before all of the segments
450043c2aeb0SSepherosa Ziehau 	 * have been freed.
450143c2aeb0SSepherosa Ziehau 	 */
450243c2aeb0SSepherosa Ziehau 	sc->tx_mbuf_ptr[chain_prod] = m0;
450343c2aeb0SSepherosa Ziehau 
450443c2aeb0SSepherosa Ziehau 	tmp_map = sc->tx_mbuf_map[chain_prod];
450543c2aeb0SSepherosa Ziehau 	sc->tx_mbuf_map[chain_prod] = map;
450643c2aeb0SSepherosa Ziehau 	sc->tx_mbuf_map[chain_prod_start] = tmp_map;
450743c2aeb0SSepherosa Ziehau 
450843c2aeb0SSepherosa Ziehau 	sc->used_tx_bd += ctx.bce_maxsegs;
450943c2aeb0SSepherosa Ziehau 
451043c2aeb0SSepherosa Ziehau 	/* Update some debug statistic counters */
451143c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->used_tx_bd > sc->tx_hi_watermark),
451243c2aeb0SSepherosa Ziehau 		sc->tx_hi_watermark = sc->used_tx_bd);
451343c2aeb0SSepherosa Ziehau 	DBRUNIF((sc->used_tx_bd == sc->max_tx_bd), sc->tx_full_count++);
451443c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->tx_mbuf_alloc++);
451543c2aeb0SSepherosa Ziehau 
451643c2aeb0SSepherosa Ziehau 	DBRUN(BCE_VERBOSE_SEND,
451743c2aeb0SSepherosa Ziehau 	      bce_dump_tx_mbuf_chain(sc, chain_prod, ctx.bce_maxsegs));
451843c2aeb0SSepherosa Ziehau 
451943c2aeb0SSepherosa Ziehau 	/* prod points to the next free tx_bd at this point. */
452043c2aeb0SSepherosa Ziehau 	sc->tx_prod = prod;
452143c2aeb0SSepherosa Ziehau 	sc->tx_prod_bseq = prod_bseq;
452243c2aeb0SSepherosa Ziehau back:
452343c2aeb0SSepherosa Ziehau 	if (error) {
452443c2aeb0SSepherosa Ziehau 		m_freem(*m_head);
452543c2aeb0SSepherosa Ziehau 		*m_head = NULL;
452643c2aeb0SSepherosa Ziehau 	}
452743c2aeb0SSepherosa Ziehau 	return error;
452843c2aeb0SSepherosa Ziehau }
452943c2aeb0SSepherosa Ziehau 
453043c2aeb0SSepherosa Ziehau 
453143c2aeb0SSepherosa Ziehau /****************************************************************************/
453243c2aeb0SSepherosa Ziehau /* Main transmit routine when called from another routine with a lock.      */
453343c2aeb0SSepherosa Ziehau /*                                                                          */
453443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
453543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
453643c2aeb0SSepherosa Ziehau /****************************************************************************/
453743c2aeb0SSepherosa Ziehau static void
453843c2aeb0SSepherosa Ziehau bce_start(struct ifnet *ifp)
453943c2aeb0SSepherosa Ziehau {
454043c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
454143c2aeb0SSepherosa Ziehau 	int count = 0;
454243c2aeb0SSepherosa Ziehau 
454343c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
454443c2aeb0SSepherosa Ziehau 
454543c2aeb0SSepherosa Ziehau 	/* If there's no link or the transmit queue is empty then just exit. */
45469db4b353SSepherosa Ziehau 	if (!sc->bce_link) {
45479db4b353SSepherosa Ziehau 		ifq_purge(&ifp->if_snd);
45489db4b353SSepherosa Ziehau 		return;
45499db4b353SSepherosa Ziehau 	}
45509db4b353SSepherosa Ziehau 
45519db4b353SSepherosa Ziehau 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
455243c2aeb0SSepherosa Ziehau 		return;
455343c2aeb0SSepherosa Ziehau 
455443c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_SEND,
455543c2aeb0SSepherosa Ziehau 		"%s(): Start: tx_prod = 0x%04X, tx_chain_prod = %04X, "
455643c2aeb0SSepherosa Ziehau 		"tx_prod_bseq = 0x%08X\n",
455743c2aeb0SSepherosa Ziehau 		__func__,
455843c2aeb0SSepherosa Ziehau 		sc->tx_prod, TX_CHAIN_IDX(sc->tx_prod), sc->tx_prod_bseq);
455943c2aeb0SSepherosa Ziehau 
456043c2aeb0SSepherosa Ziehau 	for (;;) {
456143c2aeb0SSepherosa Ziehau 		struct mbuf *m_head;
456243c2aeb0SSepherosa Ziehau 
456343c2aeb0SSepherosa Ziehau 		/*
456443c2aeb0SSepherosa Ziehau 		 * We keep BCE_TX_SPARE_SPACE entries, so bce_encap() is
456543c2aeb0SSepherosa Ziehau 		 * unlikely to fail.
456643c2aeb0SSepherosa Ziehau 		 */
456743c2aeb0SSepherosa Ziehau 		if (sc->max_tx_bd - sc->used_tx_bd < BCE_TX_SPARE_SPACE) {
456843c2aeb0SSepherosa Ziehau 			ifp->if_flags |= IFF_OACTIVE;
456943c2aeb0SSepherosa Ziehau 			break;
457043c2aeb0SSepherosa Ziehau 		}
457143c2aeb0SSepherosa Ziehau 
457243c2aeb0SSepherosa Ziehau 		/* Check for any frames to send. */
457343c2aeb0SSepherosa Ziehau 		m_head = ifq_dequeue(&ifp->if_snd, NULL);
457443c2aeb0SSepherosa Ziehau 		if (m_head == NULL)
457543c2aeb0SSepherosa Ziehau 			break;
457643c2aeb0SSepherosa Ziehau 
457743c2aeb0SSepherosa Ziehau 		/*
457843c2aeb0SSepherosa Ziehau 		 * Pack the data into the transmit ring. If we
457943c2aeb0SSepherosa Ziehau 		 * don't have room, place the mbuf back at the
458043c2aeb0SSepherosa Ziehau 		 * head of the queue and set the OACTIVE flag
458143c2aeb0SSepherosa Ziehau 		 * to wait for the NIC to drain the chain.
458243c2aeb0SSepherosa Ziehau 		 */
458343c2aeb0SSepherosa Ziehau 		if (bce_encap(sc, &m_head)) {
458443c2aeb0SSepherosa Ziehau 			ifp->if_flags |= IFF_OACTIVE;
458543c2aeb0SSepherosa Ziehau 			DBPRINT(sc, BCE_INFO_SEND,
458643c2aeb0SSepherosa Ziehau 				"TX chain is closed for business! "
458743c2aeb0SSepherosa Ziehau 				"Total tx_bd used = %d\n",
458843c2aeb0SSepherosa Ziehau 				sc->used_tx_bd);
458943c2aeb0SSepherosa Ziehau 			break;
459043c2aeb0SSepherosa Ziehau 		}
459143c2aeb0SSepherosa Ziehau 
459243c2aeb0SSepherosa Ziehau 		count++;
459343c2aeb0SSepherosa Ziehau 
459443c2aeb0SSepherosa Ziehau 		/* Send a copy of the frame to any BPF listeners. */
4595b637f170SSepherosa Ziehau 		ETHER_BPF_MTAP(ifp, m_head);
459643c2aeb0SSepherosa Ziehau 	}
459743c2aeb0SSepherosa Ziehau 
459843c2aeb0SSepherosa Ziehau 	if (count == 0) {
459943c2aeb0SSepherosa Ziehau 		/* no packets were dequeued */
460043c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE_SEND,
460143c2aeb0SSepherosa Ziehau 			"%s(): No packets were dequeued\n", __func__);
460243c2aeb0SSepherosa Ziehau 		return;
460343c2aeb0SSepherosa Ziehau 	}
460443c2aeb0SSepherosa Ziehau 
460543c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_INFO_SEND,
460643c2aeb0SSepherosa Ziehau 		"%s(): End: tx_prod = 0x%04X, tx_chain_prod = 0x%04X, "
460743c2aeb0SSepherosa Ziehau 		"tx_prod_bseq = 0x%08X\n",
460843c2aeb0SSepherosa Ziehau 		__func__,
460943c2aeb0SSepherosa Ziehau 		sc->tx_prod, TX_CHAIN_IDX(sc->tx_prod), sc->tx_prod_bseq);
461043c2aeb0SSepherosa Ziehau 
461143c2aeb0SSepherosa Ziehau 	/* Start the transmit. */
461243c2aeb0SSepherosa Ziehau 	REG_WR16(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BIDX, sc->tx_prod);
461343c2aeb0SSepherosa Ziehau 	REG_WR(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BSEQ, sc->tx_prod_bseq);
461443c2aeb0SSepherosa Ziehau 
461543c2aeb0SSepherosa Ziehau 	/* Set the tx timeout. */
461643c2aeb0SSepherosa Ziehau 	ifp->if_timer = BCE_TX_TIMEOUT;
461743c2aeb0SSepherosa Ziehau }
461843c2aeb0SSepherosa Ziehau 
461943c2aeb0SSepherosa Ziehau 
462043c2aeb0SSepherosa Ziehau /****************************************************************************/
462143c2aeb0SSepherosa Ziehau /* Handles any IOCTL calls from the operating system.                       */
462243c2aeb0SSepherosa Ziehau /*                                                                          */
462343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
462443c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
462543c2aeb0SSepherosa Ziehau /****************************************************************************/
462643c2aeb0SSepherosa Ziehau static int
462743c2aeb0SSepherosa Ziehau bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
462843c2aeb0SSepherosa Ziehau {
462943c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
463043c2aeb0SSepherosa Ziehau 	struct ifreq *ifr = (struct ifreq *)data;
463143c2aeb0SSepherosa Ziehau 	struct mii_data *mii;
463243c2aeb0SSepherosa Ziehau 	int mask, error = 0;
463343c2aeb0SSepherosa Ziehau 
463443c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
463543c2aeb0SSepherosa Ziehau 
463643c2aeb0SSepherosa Ziehau 	switch(command) {
463743c2aeb0SSepherosa Ziehau 	case SIOCSIFMTU:
463843c2aeb0SSepherosa Ziehau 		/* Check that the MTU setting is supported. */
463943c2aeb0SSepherosa Ziehau 		if (ifr->ifr_mtu < BCE_MIN_MTU ||
464043c2aeb0SSepherosa Ziehau #ifdef notyet
464143c2aeb0SSepherosa Ziehau 		    ifr->ifr_mtu > BCE_MAX_JUMBO_MTU
464243c2aeb0SSepherosa Ziehau #else
464343c2aeb0SSepherosa Ziehau 		    ifr->ifr_mtu > ETHERMTU
464443c2aeb0SSepherosa Ziehau #endif
464543c2aeb0SSepherosa Ziehau 		   ) {
464643c2aeb0SSepherosa Ziehau 			error = EINVAL;
464743c2aeb0SSepherosa Ziehau 			break;
464843c2aeb0SSepherosa Ziehau 		}
464943c2aeb0SSepherosa Ziehau 
465043c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Setting new MTU of %d\n", ifr->ifr_mtu);
465143c2aeb0SSepherosa Ziehau 
465243c2aeb0SSepherosa Ziehau 		ifp->if_mtu = ifr->ifr_mtu;
465343c2aeb0SSepherosa Ziehau 		ifp->if_flags &= ~IFF_RUNNING;	/* Force reinitialize */
465443c2aeb0SSepherosa Ziehau 		bce_init(sc);
465543c2aeb0SSepherosa Ziehau 		break;
465643c2aeb0SSepherosa Ziehau 
465743c2aeb0SSepherosa Ziehau 	case SIOCSIFFLAGS:
465843c2aeb0SSepherosa Ziehau 		if (ifp->if_flags & IFF_UP) {
465943c2aeb0SSepherosa Ziehau 			if (ifp->if_flags & IFF_RUNNING) {
466043c2aeb0SSepherosa Ziehau 				mask = ifp->if_flags ^ sc->bce_if_flags;
466143c2aeb0SSepherosa Ziehau 
466243c2aeb0SSepherosa Ziehau 				if (mask & (IFF_PROMISC | IFF_ALLMULTI))
466343c2aeb0SSepherosa Ziehau 					bce_set_rx_mode(sc);
466443c2aeb0SSepherosa Ziehau 			} else {
466543c2aeb0SSepherosa Ziehau 				bce_init(sc);
466643c2aeb0SSepherosa Ziehau 			}
466743c2aeb0SSepherosa Ziehau 		} else if (ifp->if_flags & IFF_RUNNING) {
466843c2aeb0SSepherosa Ziehau 			bce_stop(sc);
466943c2aeb0SSepherosa Ziehau 		}
467043c2aeb0SSepherosa Ziehau 		sc->bce_if_flags = ifp->if_flags;
467143c2aeb0SSepherosa Ziehau 		break;
467243c2aeb0SSepherosa Ziehau 
467343c2aeb0SSepherosa Ziehau 	case SIOCADDMULTI:
467443c2aeb0SSepherosa Ziehau 	case SIOCDELMULTI:
467543c2aeb0SSepherosa Ziehau 		if (ifp->if_flags & IFF_RUNNING)
467643c2aeb0SSepherosa Ziehau 			bce_set_rx_mode(sc);
467743c2aeb0SSepherosa Ziehau 		break;
467843c2aeb0SSepherosa Ziehau 
467943c2aeb0SSepherosa Ziehau 	case SIOCSIFMEDIA:
468043c2aeb0SSepherosa Ziehau 	case SIOCGIFMEDIA:
468143c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE, "bce_phy_flags = 0x%08X\n",
468243c2aeb0SSepherosa Ziehau 			sc->bce_phy_flags);
468343c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE, "Copper media set/get\n");
468443c2aeb0SSepherosa Ziehau 
468543c2aeb0SSepherosa Ziehau 		mii = device_get_softc(sc->bce_miibus);
468643c2aeb0SSepherosa Ziehau 		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
468743c2aeb0SSepherosa Ziehau 		break;
468843c2aeb0SSepherosa Ziehau 
468943c2aeb0SSepherosa Ziehau 	case SIOCSIFCAP:
469043c2aeb0SSepherosa Ziehau 		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
469143c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Received SIOCSIFCAP = 0x%08X\n",
469243c2aeb0SSepherosa Ziehau 			(uint32_t) mask);
469343c2aeb0SSepherosa Ziehau 
469443c2aeb0SSepherosa Ziehau 		if (mask & IFCAP_HWCSUM) {
469543c2aeb0SSepherosa Ziehau 			ifp->if_capenable ^= IFCAP_HWCSUM;
469643c2aeb0SSepherosa Ziehau 			if (IFCAP_HWCSUM & ifp->if_capenable)
469743c2aeb0SSepherosa Ziehau 				ifp->if_hwassist = BCE_IF_HWASSIST;
469843c2aeb0SSepherosa Ziehau 			else
469943c2aeb0SSepherosa Ziehau 				ifp->if_hwassist = 0;
470043c2aeb0SSepherosa Ziehau 		}
470143c2aeb0SSepherosa Ziehau 		break;
470243c2aeb0SSepherosa Ziehau 
470343c2aeb0SSepherosa Ziehau 	default:
470443c2aeb0SSepherosa Ziehau 		error = ether_ioctl(ifp, command, data);
470543c2aeb0SSepherosa Ziehau 		break;
470643c2aeb0SSepherosa Ziehau 	}
470743c2aeb0SSepherosa Ziehau 	return error;
470843c2aeb0SSepherosa Ziehau }
470943c2aeb0SSepherosa Ziehau 
471043c2aeb0SSepherosa Ziehau 
471143c2aeb0SSepherosa Ziehau /****************************************************************************/
471243c2aeb0SSepherosa Ziehau /* Transmit timeout handler.                                                */
471343c2aeb0SSepherosa Ziehau /*                                                                          */
471443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
471543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
471643c2aeb0SSepherosa Ziehau /****************************************************************************/
471743c2aeb0SSepherosa Ziehau static void
471843c2aeb0SSepherosa Ziehau bce_watchdog(struct ifnet *ifp)
471943c2aeb0SSepherosa Ziehau {
472043c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
472143c2aeb0SSepherosa Ziehau 
472243c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
472343c2aeb0SSepherosa Ziehau 
472443c2aeb0SSepherosa Ziehau 	DBRUN(BCE_VERBOSE_SEND,
472543c2aeb0SSepherosa Ziehau 	      bce_dump_driver_state(sc);
472643c2aeb0SSepherosa Ziehau 	      bce_dump_status_block(sc));
472743c2aeb0SSepherosa Ziehau 
472843c2aeb0SSepherosa Ziehau 	/*
472943c2aeb0SSepherosa Ziehau 	 * If we are in this routine because of pause frames, then
473043c2aeb0SSepherosa Ziehau 	 * don't reset the hardware.
473143c2aeb0SSepherosa Ziehau 	 */
473243c2aeb0SSepherosa Ziehau 	if (REG_RD(sc, BCE_EMAC_TX_STATUS) & BCE_EMAC_TX_STATUS_XOFFED)
473343c2aeb0SSepherosa Ziehau 		return;
473443c2aeb0SSepherosa Ziehau 
473543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "Watchdog timeout occurred, resetting!\n");
473643c2aeb0SSepherosa Ziehau 
473743c2aeb0SSepherosa Ziehau 	/* DBRUN(BCE_FATAL, bce_breakpoint(sc)); */
473843c2aeb0SSepherosa Ziehau 
473943c2aeb0SSepherosa Ziehau 	ifp->if_flags &= ~IFF_RUNNING;	/* Force reinitialize */
474043c2aeb0SSepherosa Ziehau 	bce_init(sc);
474143c2aeb0SSepherosa Ziehau 
474243c2aeb0SSepherosa Ziehau 	ifp->if_oerrors++;
474343c2aeb0SSepherosa Ziehau 
474443c2aeb0SSepherosa Ziehau 	if (!ifq_is_empty(&ifp->if_snd))
47459db4b353SSepherosa Ziehau 		if_devstart(ifp);
474643c2aeb0SSepherosa Ziehau }
474743c2aeb0SSepherosa Ziehau 
474843c2aeb0SSepherosa Ziehau 
474943c2aeb0SSepherosa Ziehau #ifdef DEVICE_POLLING
475043c2aeb0SSepherosa Ziehau 
475143c2aeb0SSepherosa Ziehau static void
475243c2aeb0SSepherosa Ziehau bce_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
475343c2aeb0SSepherosa Ziehau {
475443c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = ifp->if_softc;
475543c2aeb0SSepherosa Ziehau 	struct status_block *sblk = sc->status_block;
475624603545SSepherosa Ziehau 	uint16_t hw_tx_cons, hw_rx_cons;
475743c2aeb0SSepherosa Ziehau 
475843c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
475943c2aeb0SSepherosa Ziehau 
476043c2aeb0SSepherosa Ziehau 	switch (cmd) {
476143c2aeb0SSepherosa Ziehau 	case POLL_REGISTER:
476243c2aeb0SSepherosa Ziehau 		bce_disable_intr(sc);
476343c2aeb0SSepherosa Ziehau 
476443c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
476543c2aeb0SSepherosa Ziehau 		       (1 << 16) | sc->bce_rx_quick_cons_trip);
476643c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
476743c2aeb0SSepherosa Ziehau 		       (1 << 16) | sc->bce_tx_quick_cons_trip);
476843c2aeb0SSepherosa Ziehau 		return;
476943c2aeb0SSepherosa Ziehau 	case POLL_DEREGISTER:
477043c2aeb0SSepherosa Ziehau 		bce_enable_intr(sc);
477143c2aeb0SSepherosa Ziehau 
477243c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
477343c2aeb0SSepherosa Ziehau 		       (sc->bce_tx_quick_cons_trip_int << 16) |
477443c2aeb0SSepherosa Ziehau 		       sc->bce_tx_quick_cons_trip);
477543c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
477643c2aeb0SSepherosa Ziehau 		       (sc->bce_rx_quick_cons_trip_int << 16) |
477743c2aeb0SSepherosa Ziehau 		       sc->bce_rx_quick_cons_trip);
477843c2aeb0SSepherosa Ziehau 		return;
477943c2aeb0SSepherosa Ziehau 	default:
478043c2aeb0SSepherosa Ziehau 		break;
478143c2aeb0SSepherosa Ziehau 	}
478243c2aeb0SSepherosa Ziehau 
478343c2aeb0SSepherosa Ziehau 	bus_dmamap_sync(sc->status_tag, sc->status_map, BUS_DMASYNC_POSTREAD);
478443c2aeb0SSepherosa Ziehau 
478543c2aeb0SSepherosa Ziehau 	if (cmd == POLL_AND_CHECK_STATUS) {
478643c2aeb0SSepherosa Ziehau 		uint32_t status_attn_bits;
478743c2aeb0SSepherosa Ziehau 
478843c2aeb0SSepherosa Ziehau 		status_attn_bits = sblk->status_attn_bits;
478943c2aeb0SSepherosa Ziehau 
479043c2aeb0SSepherosa Ziehau 		DBRUNIF(DB_RANDOMTRUE(bce_debug_unexpected_attention),
479143c2aeb0SSepherosa Ziehau 			if_printf(ifp,
479243c2aeb0SSepherosa Ziehau 			"Simulating unexpected status attention bit set.");
479343c2aeb0SSepherosa Ziehau 			status_attn_bits |= STATUS_ATTN_BITS_PARITY_ERROR);
479443c2aeb0SSepherosa Ziehau 
479543c2aeb0SSepherosa Ziehau 		/* Was it a link change interrupt? */
479643c2aeb0SSepherosa Ziehau 		if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
479743c2aeb0SSepherosa Ziehau 		    (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE))
479843c2aeb0SSepherosa Ziehau 			bce_phy_intr(sc);
479943c2aeb0SSepherosa Ziehau 
480043c2aeb0SSepherosa Ziehau 		/*
480143c2aeb0SSepherosa Ziehau 		 * If any other attention is asserted then
480243c2aeb0SSepherosa Ziehau 		 * the chip is toast.
480343c2aeb0SSepherosa Ziehau 		 */
480443c2aeb0SSepherosa Ziehau 		if ((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) !=
480543c2aeb0SSepherosa Ziehau 		     (sblk->status_attn_bits_ack &
480643c2aeb0SSepherosa Ziehau 		      ~STATUS_ATTN_BITS_LINK_STATE)) {
480743c2aeb0SSepherosa Ziehau 			DBRUN(1, sc->unexpected_attentions++);
480843c2aeb0SSepherosa Ziehau 
480943c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Fatal attention detected: 0x%08X\n",
481043c2aeb0SSepherosa Ziehau 				  sblk->status_attn_bits);
481143c2aeb0SSepherosa Ziehau 
481243c2aeb0SSepherosa Ziehau 			DBRUN(BCE_FATAL,
481343c2aeb0SSepherosa Ziehau 			if (bce_debug_unexpected_attention == 0)
481443c2aeb0SSepherosa Ziehau 				bce_breakpoint(sc));
481543c2aeb0SSepherosa Ziehau 
481643c2aeb0SSepherosa Ziehau 			bce_init(sc);
481743c2aeb0SSepherosa Ziehau 			return;
481843c2aeb0SSepherosa Ziehau 		}
481943c2aeb0SSepherosa Ziehau 	}
482043c2aeb0SSepherosa Ziehau 
482124603545SSepherosa Ziehau 	hw_rx_cons = bce_get_hw_rx_cons(sc);
482224603545SSepherosa Ziehau 	hw_tx_cons = bce_get_hw_tx_cons(sc);
482324603545SSepherosa Ziehau 
482443c2aeb0SSepherosa Ziehau 	/* Check for any completed RX frames. */
482524603545SSepherosa Ziehau 	if (hw_rx_cons != sc->hw_rx_cons)
482643c2aeb0SSepherosa Ziehau 		bce_rx_intr(sc, count);
482743c2aeb0SSepherosa Ziehau 
482843c2aeb0SSepherosa Ziehau 	/* Check for any completed TX frames. */
482924603545SSepherosa Ziehau 	if (hw_tx_cons != sc->hw_tx_cons)
483043c2aeb0SSepherosa Ziehau 		bce_tx_intr(sc);
483143c2aeb0SSepherosa Ziehau 
483243c2aeb0SSepherosa Ziehau 	bus_dmamap_sync(sc->status_tag,	sc->status_map, BUS_DMASYNC_PREWRITE);
483343c2aeb0SSepherosa Ziehau 
483443c2aeb0SSepherosa Ziehau 	/* Check for new frames to transmit. */
483543c2aeb0SSepherosa Ziehau 	if (!ifq_is_empty(&ifp->if_snd))
48369db4b353SSepherosa Ziehau 		if_devstart(ifp);
483743c2aeb0SSepherosa Ziehau }
483843c2aeb0SSepherosa Ziehau 
483943c2aeb0SSepherosa Ziehau #endif	/* DEVICE_POLLING */
484043c2aeb0SSepherosa Ziehau 
484143c2aeb0SSepherosa Ziehau 
484243c2aeb0SSepherosa Ziehau /*
484343c2aeb0SSepherosa Ziehau  * Interrupt handler.
484443c2aeb0SSepherosa Ziehau  */
484543c2aeb0SSepherosa Ziehau /****************************************************************************/
484643c2aeb0SSepherosa Ziehau /* Main interrupt entry point.  Verifies that the controller generated the  */
484743c2aeb0SSepherosa Ziehau /* interrupt and then calls a separate routine for handle the various       */
484843c2aeb0SSepherosa Ziehau /* interrupt causes (PHY, TX, RX).                                          */
484943c2aeb0SSepherosa Ziehau /*                                                                          */
485043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
485143c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
485243c2aeb0SSepherosa Ziehau /****************************************************************************/
485343c2aeb0SSepherosa Ziehau static void
485443c2aeb0SSepherosa Ziehau bce_intr(void *xsc)
485543c2aeb0SSepherosa Ziehau {
485643c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = xsc;
485743c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
485843c2aeb0SSepherosa Ziehau 	struct status_block *sblk;
485924603545SSepherosa Ziehau 	uint16_t hw_rx_cons, hw_tx_cons;
486043c2aeb0SSepherosa Ziehau 
486143c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
486243c2aeb0SSepherosa Ziehau 
486343c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE, "Entering %s()\n", __func__);
486443c2aeb0SSepherosa Ziehau 	DBRUNIF(1, sc->interrupts_generated++);
486543c2aeb0SSepherosa Ziehau 
486643c2aeb0SSepherosa Ziehau 	bus_dmamap_sync(sc->status_tag, sc->status_map, BUS_DMASYNC_POSTREAD);
486743c2aeb0SSepherosa Ziehau 	sblk = sc->status_block;
486843c2aeb0SSepherosa Ziehau 
486943c2aeb0SSepherosa Ziehau 	/*
487043c2aeb0SSepherosa Ziehau 	 * If the hardware status block index matches the last value
487143c2aeb0SSepherosa Ziehau 	 * read by the driver and we haven't asserted our interrupt
487243c2aeb0SSepherosa Ziehau 	 * then there's nothing to do.
487343c2aeb0SSepherosa Ziehau 	 */
487443c2aeb0SSepherosa Ziehau 	if (sblk->status_idx == sc->last_status_idx &&
487543c2aeb0SSepherosa Ziehau 	    (REG_RD(sc, BCE_PCICFG_MISC_STATUS) &
487643c2aeb0SSepherosa Ziehau 	     BCE_PCICFG_MISC_STATUS_INTA_VALUE))
487743c2aeb0SSepherosa Ziehau 		return;
487843c2aeb0SSepherosa Ziehau 
487943c2aeb0SSepherosa Ziehau 	/* Ack the interrupt and stop others from occuring. */
488043c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
488143c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
488243c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_MASK_INT);
488343c2aeb0SSepherosa Ziehau 
488424603545SSepherosa Ziehau 	/* Check if the hardware has finished any work. */
488524603545SSepherosa Ziehau 	hw_rx_cons = bce_get_hw_rx_cons(sc);
488624603545SSepherosa Ziehau 	hw_tx_cons = bce_get_hw_tx_cons(sc);
488724603545SSepherosa Ziehau 
488843c2aeb0SSepherosa Ziehau 	/* Keep processing data as long as there is work to do. */
488943c2aeb0SSepherosa Ziehau 	for (;;) {
489043c2aeb0SSepherosa Ziehau 		uint32_t status_attn_bits;
489143c2aeb0SSepherosa Ziehau 
489243c2aeb0SSepherosa Ziehau 		status_attn_bits = sblk->status_attn_bits;
489343c2aeb0SSepherosa Ziehau 
489443c2aeb0SSepherosa Ziehau 		DBRUNIF(DB_RANDOMTRUE(bce_debug_unexpected_attention),
489543c2aeb0SSepherosa Ziehau 			if_printf(ifp,
489643c2aeb0SSepherosa Ziehau 			"Simulating unexpected status attention bit set.");
489743c2aeb0SSepherosa Ziehau 			status_attn_bits |= STATUS_ATTN_BITS_PARITY_ERROR);
489843c2aeb0SSepherosa Ziehau 
489943c2aeb0SSepherosa Ziehau 		/* Was it a link change interrupt? */
490043c2aeb0SSepherosa Ziehau 		if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
490143c2aeb0SSepherosa Ziehau 		    (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE))
490243c2aeb0SSepherosa Ziehau 			bce_phy_intr(sc);
490343c2aeb0SSepherosa Ziehau 
490443c2aeb0SSepherosa Ziehau 		/*
490543c2aeb0SSepherosa Ziehau 		 * If any other attention is asserted then
490643c2aeb0SSepherosa Ziehau 		 * the chip is toast.
490743c2aeb0SSepherosa Ziehau 		 */
490843c2aeb0SSepherosa Ziehau 		if ((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) !=
490943c2aeb0SSepherosa Ziehau 		     (sblk->status_attn_bits_ack &
491043c2aeb0SSepherosa Ziehau 		      ~STATUS_ATTN_BITS_LINK_STATE)) {
491143c2aeb0SSepherosa Ziehau 			DBRUN(1, sc->unexpected_attentions++);
491243c2aeb0SSepherosa Ziehau 
491343c2aeb0SSepherosa Ziehau 			if_printf(ifp, "Fatal attention detected: 0x%08X\n",
491443c2aeb0SSepherosa Ziehau 				  sblk->status_attn_bits);
491543c2aeb0SSepherosa Ziehau 
491643c2aeb0SSepherosa Ziehau 			DBRUN(BCE_FATAL,
491743c2aeb0SSepherosa Ziehau 			if (bce_debug_unexpected_attention == 0)
491843c2aeb0SSepherosa Ziehau 				bce_breakpoint(sc));
491943c2aeb0SSepherosa Ziehau 
492043c2aeb0SSepherosa Ziehau 			bce_init(sc);
492143c2aeb0SSepherosa Ziehau 			return;
492243c2aeb0SSepherosa Ziehau 		}
492343c2aeb0SSepherosa Ziehau 
492443c2aeb0SSepherosa Ziehau 		/* Check for any completed RX frames. */
492524603545SSepherosa Ziehau 		if (hw_rx_cons != sc->hw_rx_cons)
492643c2aeb0SSepherosa Ziehau 			bce_rx_intr(sc, -1);
492743c2aeb0SSepherosa Ziehau 
492843c2aeb0SSepherosa Ziehau 		/* Check for any completed TX frames. */
492924603545SSepherosa Ziehau 		if (hw_tx_cons != sc->hw_tx_cons)
493043c2aeb0SSepherosa Ziehau 			bce_tx_intr(sc);
493143c2aeb0SSepherosa Ziehau 
493243c2aeb0SSepherosa Ziehau 		/*
493343c2aeb0SSepherosa Ziehau 		 * Save the status block index value
493443c2aeb0SSepherosa Ziehau 		 * for use during the next interrupt.
493543c2aeb0SSepherosa Ziehau 		 */
493643c2aeb0SSepherosa Ziehau 		sc->last_status_idx = sblk->status_idx;
493743c2aeb0SSepherosa Ziehau 
493843c2aeb0SSepherosa Ziehau 		/*
493943c2aeb0SSepherosa Ziehau 		 * Prevent speculative reads from getting
494043c2aeb0SSepherosa Ziehau 		 * ahead of the status block.
494143c2aeb0SSepherosa Ziehau 		 */
494243c2aeb0SSepherosa Ziehau 		bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
494343c2aeb0SSepherosa Ziehau 				  BUS_SPACE_BARRIER_READ);
494443c2aeb0SSepherosa Ziehau 
494543c2aeb0SSepherosa Ziehau 		/*
494643c2aeb0SSepherosa Ziehau 		 * If there's no work left then exit the
494743c2aeb0SSepherosa Ziehau 		 * interrupt service routine.
494843c2aeb0SSepherosa Ziehau 		 */
494924603545SSepherosa Ziehau 		hw_rx_cons = bce_get_hw_rx_cons(sc);
495024603545SSepherosa Ziehau 		hw_tx_cons = bce_get_hw_tx_cons(sc);
495124603545SSepherosa Ziehau 		if ((hw_rx_cons == sc->hw_rx_cons) && (hw_tx_cons == sc->hw_tx_cons))
495243c2aeb0SSepherosa Ziehau 			break;
495343c2aeb0SSepherosa Ziehau 	}
495443c2aeb0SSepherosa Ziehau 
495543c2aeb0SSepherosa Ziehau 	bus_dmamap_sync(sc->status_tag,	sc->status_map, BUS_DMASYNC_PREWRITE);
495643c2aeb0SSepherosa Ziehau 
495743c2aeb0SSepherosa Ziehau 	/* Re-enable interrupts. */
495843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
495943c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx |
496043c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_MASK_INT);
496143c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
496243c2aeb0SSepherosa Ziehau 	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx);
496343c2aeb0SSepherosa Ziehau 
4964bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask)
4965bdeb8fffSSepherosa Ziehau 		bce_coal_change(sc);
4966bdeb8fffSSepherosa Ziehau 
496743c2aeb0SSepherosa Ziehau 	/* Handle any frames that arrived while handling the interrupt. */
496843c2aeb0SSepherosa Ziehau 	if (!ifq_is_empty(&ifp->if_snd))
49699db4b353SSepherosa Ziehau 		if_devstart(ifp);
497043c2aeb0SSepherosa Ziehau }
497143c2aeb0SSepherosa Ziehau 
497243c2aeb0SSepherosa Ziehau 
497343c2aeb0SSepherosa Ziehau /****************************************************************************/
497443c2aeb0SSepherosa Ziehau /* Programs the various packet receive modes (broadcast and multicast).     */
497543c2aeb0SSepherosa Ziehau /*                                                                          */
497643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
497743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
497843c2aeb0SSepherosa Ziehau /****************************************************************************/
497943c2aeb0SSepherosa Ziehau static void
498043c2aeb0SSepherosa Ziehau bce_set_rx_mode(struct bce_softc *sc)
498143c2aeb0SSepherosa Ziehau {
498243c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
498343c2aeb0SSepherosa Ziehau 	struct ifmultiaddr *ifma;
498443c2aeb0SSepherosa Ziehau 	uint32_t hashes[NUM_MC_HASH_REGISTERS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
498543c2aeb0SSepherosa Ziehau 	uint32_t rx_mode, sort_mode;
498643c2aeb0SSepherosa Ziehau 	int h, i;
498743c2aeb0SSepherosa Ziehau 
498843c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
498943c2aeb0SSepherosa Ziehau 
499043c2aeb0SSepherosa Ziehau 	/* Initialize receive mode default settings. */
499143c2aeb0SSepherosa Ziehau 	rx_mode = sc->rx_mode &
499243c2aeb0SSepherosa Ziehau 		  ~(BCE_EMAC_RX_MODE_PROMISCUOUS |
499343c2aeb0SSepherosa Ziehau 		    BCE_EMAC_RX_MODE_KEEP_VLAN_TAG);
499443c2aeb0SSepherosa Ziehau 	sort_mode = 1 | BCE_RPM_SORT_USER0_BC_EN;
499543c2aeb0SSepherosa Ziehau 
499643c2aeb0SSepherosa Ziehau 	/*
499743c2aeb0SSepherosa Ziehau 	 * ASF/IPMI/UMP firmware requires that VLAN tag stripping
499843c2aeb0SSepherosa Ziehau 	 * be enbled.
499943c2aeb0SSepherosa Ziehau 	 */
500043c2aeb0SSepherosa Ziehau 	if (!(BCE_IF_CAPABILITIES & IFCAP_VLAN_HWTAGGING) &&
500143c2aeb0SSepherosa Ziehau 	    !(sc->bce_flags & BCE_MFW_ENABLE_FLAG))
500243c2aeb0SSepherosa Ziehau 		rx_mode |= BCE_EMAC_RX_MODE_KEEP_VLAN_TAG;
500343c2aeb0SSepherosa Ziehau 
500443c2aeb0SSepherosa Ziehau 	/*
500543c2aeb0SSepherosa Ziehau 	 * Check for promiscuous, all multicast, or selected
500643c2aeb0SSepherosa Ziehau 	 * multicast address filtering.
500743c2aeb0SSepherosa Ziehau 	 */
500843c2aeb0SSepherosa Ziehau 	if (ifp->if_flags & IFF_PROMISC) {
500943c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Enabling promiscuous mode.\n");
501043c2aeb0SSepherosa Ziehau 
501143c2aeb0SSepherosa Ziehau 		/* Enable promiscuous mode. */
501243c2aeb0SSepherosa Ziehau 		rx_mode |= BCE_EMAC_RX_MODE_PROMISCUOUS;
501343c2aeb0SSepherosa Ziehau 		sort_mode |= BCE_RPM_SORT_USER0_PROM_EN;
501443c2aeb0SSepherosa Ziehau 	} else if (ifp->if_flags & IFF_ALLMULTI) {
501543c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Enabling all multicast mode.\n");
501643c2aeb0SSepherosa Ziehau 
501743c2aeb0SSepherosa Ziehau 		/* Enable all multicast addresses. */
501843c2aeb0SSepherosa Ziehau 		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
501943c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4),
502043c2aeb0SSepherosa Ziehau 			       0xffffffff);
502143c2aeb0SSepherosa Ziehau 		}
502243c2aeb0SSepherosa Ziehau 		sort_mode |= BCE_RPM_SORT_USER0_MC_EN;
502343c2aeb0SSepherosa Ziehau 	} else {
502443c2aeb0SSepherosa Ziehau 		/* Accept one or more multicast(s). */
502543c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_INFO, "Enabling selective multicast mode.\n");
502643c2aeb0SSepherosa Ziehau 
502743c2aeb0SSepherosa Ziehau 		LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
502843c2aeb0SSepherosa Ziehau 			if (ifma->ifma_addr->sa_family != AF_LINK)
502943c2aeb0SSepherosa Ziehau 				continue;
503043c2aeb0SSepherosa Ziehau 			h = ether_crc32_le(
503143c2aeb0SSepherosa Ziehau 			    LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
503243c2aeb0SSepherosa Ziehau 			    ETHER_ADDR_LEN) & 0xFF;
503343c2aeb0SSepherosa Ziehau 			hashes[(h & 0xE0) >> 5] |= 1 << (h & 0x1F);
503443c2aeb0SSepherosa Ziehau 		}
503543c2aeb0SSepherosa Ziehau 
503643c2aeb0SSepherosa Ziehau 		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
503743c2aeb0SSepherosa Ziehau 			REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4),
503843c2aeb0SSepherosa Ziehau 			       hashes[i]);
503943c2aeb0SSepherosa Ziehau 		}
504043c2aeb0SSepherosa Ziehau 		sort_mode |= BCE_RPM_SORT_USER0_MC_HSH_EN;
504143c2aeb0SSepherosa Ziehau 	}
504243c2aeb0SSepherosa Ziehau 
504343c2aeb0SSepherosa Ziehau 	/* Only make changes if the recive mode has actually changed. */
504443c2aeb0SSepherosa Ziehau 	if (rx_mode != sc->rx_mode) {
504543c2aeb0SSepherosa Ziehau 		DBPRINT(sc, BCE_VERBOSE, "Enabling new receive mode: 0x%08X\n",
504643c2aeb0SSepherosa Ziehau 			rx_mode);
504743c2aeb0SSepherosa Ziehau 
504843c2aeb0SSepherosa Ziehau 		sc->rx_mode = rx_mode;
504943c2aeb0SSepherosa Ziehau 		REG_WR(sc, BCE_EMAC_RX_MODE, rx_mode);
505043c2aeb0SSepherosa Ziehau 	}
505143c2aeb0SSepherosa Ziehau 
505243c2aeb0SSepherosa Ziehau 	/* Disable and clear the exisitng sort before enabling a new sort. */
505343c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_RPM_SORT_USER0, 0x0);
505443c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode);
505543c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode | BCE_RPM_SORT_USER0_ENA);
505643c2aeb0SSepherosa Ziehau }
505743c2aeb0SSepherosa Ziehau 
505843c2aeb0SSepherosa Ziehau 
505943c2aeb0SSepherosa Ziehau /****************************************************************************/
506043c2aeb0SSepherosa Ziehau /* Called periodically to updates statistics from the controllers           */
506143c2aeb0SSepherosa Ziehau /* statistics block.                                                        */
506243c2aeb0SSepherosa Ziehau /*                                                                          */
506343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
506443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
506543c2aeb0SSepherosa Ziehau /****************************************************************************/
506643c2aeb0SSepherosa Ziehau static void
506743c2aeb0SSepherosa Ziehau bce_stats_update(struct bce_softc *sc)
506843c2aeb0SSepherosa Ziehau {
506943c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
507043c2aeb0SSepherosa Ziehau 	struct statistics_block *stats = sc->stats_block;
507143c2aeb0SSepherosa Ziehau 
507243c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE, "Entering %s()\n", __func__);
507343c2aeb0SSepherosa Ziehau 
507443c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
507543c2aeb0SSepherosa Ziehau 
507643c2aeb0SSepherosa Ziehau 	/*
507743c2aeb0SSepherosa Ziehau 	 * Update the interface statistics from the hardware statistics.
507843c2aeb0SSepherosa Ziehau 	 */
507943c2aeb0SSepherosa Ziehau 	ifp->if_collisions = (u_long)stats->stat_EtherStatsCollisions;
508043c2aeb0SSepherosa Ziehau 
508143c2aeb0SSepherosa Ziehau 	ifp->if_ierrors = (u_long)stats->stat_EtherStatsUndersizePkts +
508243c2aeb0SSepherosa Ziehau 			  (u_long)stats->stat_EtherStatsOverrsizePkts +
508343c2aeb0SSepherosa Ziehau 			  (u_long)stats->stat_IfInMBUFDiscards +
508443c2aeb0SSepherosa Ziehau 			  (u_long)stats->stat_Dot3StatsAlignmentErrors +
508543c2aeb0SSepherosa Ziehau 			  (u_long)stats->stat_Dot3StatsFCSErrors;
508643c2aeb0SSepherosa Ziehau 
508743c2aeb0SSepherosa Ziehau 	ifp->if_oerrors =
508843c2aeb0SSepherosa Ziehau 	(u_long)stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors +
508943c2aeb0SSepherosa Ziehau 	(u_long)stats->stat_Dot3StatsExcessiveCollisions +
509043c2aeb0SSepherosa Ziehau 	(u_long)stats->stat_Dot3StatsLateCollisions;
509143c2aeb0SSepherosa Ziehau 
509243c2aeb0SSepherosa Ziehau 	/*
509343c2aeb0SSepherosa Ziehau 	 * Certain controllers don't report carrier sense errors correctly.
509443c2aeb0SSepherosa Ziehau 	 * See errata E11_5708CA0_1165.
509543c2aeb0SSepherosa Ziehau 	 */
509643c2aeb0SSepherosa Ziehau 	if (!(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) &&
509743c2aeb0SSepherosa Ziehau 	    !(BCE_CHIP_ID(sc) == BCE_CHIP_ID_5708_A0)) {
509843c2aeb0SSepherosa Ziehau 		ifp->if_oerrors +=
509943c2aeb0SSepherosa Ziehau 			(u_long)stats->stat_Dot3StatsCarrierSenseErrors;
510043c2aeb0SSepherosa Ziehau 	}
510143c2aeb0SSepherosa Ziehau 
510243c2aeb0SSepherosa Ziehau 	/*
510343c2aeb0SSepherosa Ziehau 	 * Update the sysctl statistics from the hardware statistics.
510443c2aeb0SSepherosa Ziehau 	 */
510543c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInOctets =
510643c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInOctets_hi << 32) +
510743c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInOctets_lo;
510843c2aeb0SSepherosa Ziehau 
510943c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInBadOctets =
511043c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInBadOctets_hi << 32) +
511143c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInBadOctets_lo;
511243c2aeb0SSepherosa Ziehau 
511343c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutOctets =
511443c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutOctets_hi << 32) +
511543c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutOctets_lo;
511643c2aeb0SSepherosa Ziehau 
511743c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutBadOctets =
511843c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutBadOctets_hi << 32) +
511943c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutBadOctets_lo;
512043c2aeb0SSepherosa Ziehau 
512143c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInUcastPkts =
512243c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInUcastPkts_hi << 32) +
512343c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInUcastPkts_lo;
512443c2aeb0SSepherosa Ziehau 
512543c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInMulticastPkts =
512643c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInMulticastPkts_hi << 32) +
512743c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInMulticastPkts_lo;
512843c2aeb0SSepherosa Ziehau 
512943c2aeb0SSepherosa Ziehau 	sc->stat_IfHCInBroadcastPkts =
513043c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCInBroadcastPkts_hi << 32) +
513143c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCInBroadcastPkts_lo;
513243c2aeb0SSepherosa Ziehau 
513343c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutUcastPkts =
513443c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutUcastPkts_hi << 32) +
513543c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutUcastPkts_lo;
513643c2aeb0SSepherosa Ziehau 
513743c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutMulticastPkts =
513843c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutMulticastPkts_hi << 32) +
513943c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutMulticastPkts_lo;
514043c2aeb0SSepherosa Ziehau 
514143c2aeb0SSepherosa Ziehau 	sc->stat_IfHCOutBroadcastPkts =
514243c2aeb0SSepherosa Ziehau 		((uint64_t)stats->stat_IfHCOutBroadcastPkts_hi << 32) +
514343c2aeb0SSepherosa Ziehau 		 (uint64_t)stats->stat_IfHCOutBroadcastPkts_lo;
514443c2aeb0SSepherosa Ziehau 
514543c2aeb0SSepherosa Ziehau 	sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors =
514643c2aeb0SSepherosa Ziehau 		stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
514743c2aeb0SSepherosa Ziehau 
514843c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsCarrierSenseErrors =
514943c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsCarrierSenseErrors;
515043c2aeb0SSepherosa Ziehau 
515143c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsFCSErrors =
515243c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsFCSErrors;
515343c2aeb0SSepherosa Ziehau 
515443c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsAlignmentErrors =
515543c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsAlignmentErrors;
515643c2aeb0SSepherosa Ziehau 
515743c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsSingleCollisionFrames =
515843c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsSingleCollisionFrames;
515943c2aeb0SSepherosa Ziehau 
516043c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsMultipleCollisionFrames =
516143c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsMultipleCollisionFrames;
516243c2aeb0SSepherosa Ziehau 
516343c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsDeferredTransmissions =
516443c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsDeferredTransmissions;
516543c2aeb0SSepherosa Ziehau 
516643c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsExcessiveCollisions =
516743c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsExcessiveCollisions;
516843c2aeb0SSepherosa Ziehau 
516943c2aeb0SSepherosa Ziehau 	sc->stat_Dot3StatsLateCollisions =
517043c2aeb0SSepherosa Ziehau 		stats->stat_Dot3StatsLateCollisions;
517143c2aeb0SSepherosa Ziehau 
517243c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsCollisions =
517343c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsCollisions;
517443c2aeb0SSepherosa Ziehau 
517543c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsFragments =
517643c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsFragments;
517743c2aeb0SSepherosa Ziehau 
517843c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsJabbers =
517943c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsJabbers;
518043c2aeb0SSepherosa Ziehau 
518143c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsUndersizePkts =
518243c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsUndersizePkts;
518343c2aeb0SSepherosa Ziehau 
518443c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsOverrsizePkts =
518543c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsOverrsizePkts;
518643c2aeb0SSepherosa Ziehau 
518743c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx64Octets =
518843c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx64Octets;
518943c2aeb0SSepherosa Ziehau 
519043c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx65Octetsto127Octets =
519143c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx65Octetsto127Octets;
519243c2aeb0SSepherosa Ziehau 
519343c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx128Octetsto255Octets =
519443c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx128Octetsto255Octets;
519543c2aeb0SSepherosa Ziehau 
519643c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx256Octetsto511Octets =
519743c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx256Octetsto511Octets;
519843c2aeb0SSepherosa Ziehau 
519943c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx512Octetsto1023Octets =
520043c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx512Octetsto1023Octets;
520143c2aeb0SSepherosa Ziehau 
520243c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx1024Octetsto1522Octets =
520343c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx1024Octetsto1522Octets;
520443c2aeb0SSepherosa Ziehau 
520543c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsRx1523Octetsto9022Octets =
520643c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsRx1523Octetsto9022Octets;
520743c2aeb0SSepherosa Ziehau 
520843c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx64Octets =
520943c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx64Octets;
521043c2aeb0SSepherosa Ziehau 
521143c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx65Octetsto127Octets =
521243c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx65Octetsto127Octets;
521343c2aeb0SSepherosa Ziehau 
521443c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx128Octetsto255Octets =
521543c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx128Octetsto255Octets;
521643c2aeb0SSepherosa Ziehau 
521743c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx256Octetsto511Octets =
521843c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx256Octetsto511Octets;
521943c2aeb0SSepherosa Ziehau 
522043c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx512Octetsto1023Octets =
522143c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx512Octetsto1023Octets;
522243c2aeb0SSepherosa Ziehau 
522343c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx1024Octetsto1522Octets =
522443c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx1024Octetsto1522Octets;
522543c2aeb0SSepherosa Ziehau 
522643c2aeb0SSepherosa Ziehau 	sc->stat_EtherStatsPktsTx1523Octetsto9022Octets =
522743c2aeb0SSepherosa Ziehau 		stats->stat_EtherStatsPktsTx1523Octetsto9022Octets;
522843c2aeb0SSepherosa Ziehau 
522943c2aeb0SSepherosa Ziehau 	sc->stat_XonPauseFramesReceived =
523043c2aeb0SSepherosa Ziehau 		stats->stat_XonPauseFramesReceived;
523143c2aeb0SSepherosa Ziehau 
523243c2aeb0SSepherosa Ziehau 	sc->stat_XoffPauseFramesReceived =
523343c2aeb0SSepherosa Ziehau 		stats->stat_XoffPauseFramesReceived;
523443c2aeb0SSepherosa Ziehau 
523543c2aeb0SSepherosa Ziehau 	sc->stat_OutXonSent =
523643c2aeb0SSepherosa Ziehau 		stats->stat_OutXonSent;
523743c2aeb0SSepherosa Ziehau 
523843c2aeb0SSepherosa Ziehau 	sc->stat_OutXoffSent =
523943c2aeb0SSepherosa Ziehau 		stats->stat_OutXoffSent;
524043c2aeb0SSepherosa Ziehau 
524143c2aeb0SSepherosa Ziehau 	sc->stat_FlowControlDone =
524243c2aeb0SSepherosa Ziehau 		stats->stat_FlowControlDone;
524343c2aeb0SSepherosa Ziehau 
524443c2aeb0SSepherosa Ziehau 	sc->stat_MacControlFramesReceived =
524543c2aeb0SSepherosa Ziehau 		stats->stat_MacControlFramesReceived;
524643c2aeb0SSepherosa Ziehau 
524743c2aeb0SSepherosa Ziehau 	sc->stat_XoffStateEntered =
524843c2aeb0SSepherosa Ziehau 		stats->stat_XoffStateEntered;
524943c2aeb0SSepherosa Ziehau 
525043c2aeb0SSepherosa Ziehau 	sc->stat_IfInFramesL2FilterDiscards =
525143c2aeb0SSepherosa Ziehau 		stats->stat_IfInFramesL2FilterDiscards;
525243c2aeb0SSepherosa Ziehau 
525343c2aeb0SSepherosa Ziehau 	sc->stat_IfInRuleCheckerDiscards =
525443c2aeb0SSepherosa Ziehau 		stats->stat_IfInRuleCheckerDiscards;
525543c2aeb0SSepherosa Ziehau 
525643c2aeb0SSepherosa Ziehau 	sc->stat_IfInFTQDiscards =
525743c2aeb0SSepherosa Ziehau 		stats->stat_IfInFTQDiscards;
525843c2aeb0SSepherosa Ziehau 
525943c2aeb0SSepherosa Ziehau 	sc->stat_IfInMBUFDiscards =
526043c2aeb0SSepherosa Ziehau 		stats->stat_IfInMBUFDiscards;
526143c2aeb0SSepherosa Ziehau 
526243c2aeb0SSepherosa Ziehau 	sc->stat_IfInRuleCheckerP4Hit =
526343c2aeb0SSepherosa Ziehau 		stats->stat_IfInRuleCheckerP4Hit;
526443c2aeb0SSepherosa Ziehau 
526543c2aeb0SSepherosa Ziehau 	sc->stat_CatchupInRuleCheckerDiscards =
526643c2aeb0SSepherosa Ziehau 		stats->stat_CatchupInRuleCheckerDiscards;
526743c2aeb0SSepherosa Ziehau 
526843c2aeb0SSepherosa Ziehau 	sc->stat_CatchupInFTQDiscards =
526943c2aeb0SSepherosa Ziehau 		stats->stat_CatchupInFTQDiscards;
527043c2aeb0SSepherosa Ziehau 
527143c2aeb0SSepherosa Ziehau 	sc->stat_CatchupInMBUFDiscards =
527243c2aeb0SSepherosa Ziehau 		stats->stat_CatchupInMBUFDiscards;
527343c2aeb0SSepherosa Ziehau 
527443c2aeb0SSepherosa Ziehau 	sc->stat_CatchupInRuleCheckerP4Hit =
527543c2aeb0SSepherosa Ziehau 		stats->stat_CatchupInRuleCheckerP4Hit;
527643c2aeb0SSepherosa Ziehau 
527743c2aeb0SSepherosa Ziehau 	sc->com_no_buffers = REG_RD_IND(sc, 0x120084);
527843c2aeb0SSepherosa Ziehau 
527943c2aeb0SSepherosa Ziehau 	DBPRINT(sc, BCE_EXCESSIVE, "Exiting %s()\n", __func__);
528043c2aeb0SSepherosa Ziehau }
528143c2aeb0SSepherosa Ziehau 
528243c2aeb0SSepherosa Ziehau 
528343c2aeb0SSepherosa Ziehau /****************************************************************************/
528443c2aeb0SSepherosa Ziehau /* Periodic function to perform maintenance tasks.                          */
528543c2aeb0SSepherosa Ziehau /*                                                                          */
528643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
528743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
528843c2aeb0SSepherosa Ziehau /****************************************************************************/
528943c2aeb0SSepherosa Ziehau static void
529043c2aeb0SSepherosa Ziehau bce_tick_serialized(struct bce_softc *sc)
529143c2aeb0SSepherosa Ziehau {
529243c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
529343c2aeb0SSepherosa Ziehau 	struct mii_data *mii;
529443c2aeb0SSepherosa Ziehau 	uint32_t msg;
529543c2aeb0SSepherosa Ziehau 
529643c2aeb0SSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
529743c2aeb0SSepherosa Ziehau 
529843c2aeb0SSepherosa Ziehau 	/* Tell the firmware that the driver is still running. */
529943c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
530043c2aeb0SSepherosa Ziehau 	msg = (uint32_t)BCE_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE;
530143c2aeb0SSepherosa Ziehau #else
530243c2aeb0SSepherosa Ziehau 	msg = (uint32_t)++sc->bce_fw_drv_pulse_wr_seq;
530343c2aeb0SSepherosa Ziehau #endif
530443c2aeb0SSepherosa Ziehau 	REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_PULSE_MB, msg);
530543c2aeb0SSepherosa Ziehau 
530643c2aeb0SSepherosa Ziehau 	/* Update the statistics from the hardware statistics block. */
530743c2aeb0SSepherosa Ziehau 	bce_stats_update(sc);
530843c2aeb0SSepherosa Ziehau 
530943c2aeb0SSepherosa Ziehau 	/* Schedule the next tick. */
531043c2aeb0SSepherosa Ziehau 	callout_reset(&sc->bce_stat_ch, hz, bce_tick, sc);
531143c2aeb0SSepherosa Ziehau 
531243c2aeb0SSepherosa Ziehau 	/* If link is up already up then we're done. */
531343c2aeb0SSepherosa Ziehau 	if (sc->bce_link)
531443c2aeb0SSepherosa Ziehau 		return;
531543c2aeb0SSepherosa Ziehau 
531643c2aeb0SSepherosa Ziehau 	mii = device_get_softc(sc->bce_miibus);
531743c2aeb0SSepherosa Ziehau 	mii_tick(mii);
531843c2aeb0SSepherosa Ziehau 
531943c2aeb0SSepherosa Ziehau 	/* Check if the link has come up. */
532043c2aeb0SSepherosa Ziehau 	if (!sc->bce_link && (mii->mii_media_status & IFM_ACTIVE) &&
532143c2aeb0SSepherosa Ziehau 	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
532243c2aeb0SSepherosa Ziehau 		sc->bce_link++;
532343c2aeb0SSepherosa Ziehau 		/* Now that link is up, handle any outstanding TX traffic. */
532443c2aeb0SSepherosa Ziehau 		if (!ifq_is_empty(&ifp->if_snd))
53259db4b353SSepherosa Ziehau 			if_devstart(ifp);
532643c2aeb0SSepherosa Ziehau 	}
532743c2aeb0SSepherosa Ziehau }
532843c2aeb0SSepherosa Ziehau 
532943c2aeb0SSepherosa Ziehau 
533043c2aeb0SSepherosa Ziehau static void
533143c2aeb0SSepherosa Ziehau bce_tick(void *xsc)
533243c2aeb0SSepherosa Ziehau {
533343c2aeb0SSepherosa Ziehau 	struct bce_softc *sc = xsc;
533443c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
533543c2aeb0SSepherosa Ziehau 
533643c2aeb0SSepherosa Ziehau 	lwkt_serialize_enter(ifp->if_serializer);
533743c2aeb0SSepherosa Ziehau 	bce_tick_serialized(sc);
533843c2aeb0SSepherosa Ziehau 	lwkt_serialize_exit(ifp->if_serializer);
533943c2aeb0SSepherosa Ziehau }
534043c2aeb0SSepherosa Ziehau 
534143c2aeb0SSepherosa Ziehau 
534243c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
534343c2aeb0SSepherosa Ziehau /****************************************************************************/
534443c2aeb0SSepherosa Ziehau /* Allows the driver state to be dumped through the sysctl interface.       */
534543c2aeb0SSepherosa Ziehau /*                                                                          */
534643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
534743c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
534843c2aeb0SSepherosa Ziehau /****************************************************************************/
534943c2aeb0SSepherosa Ziehau static int
535043c2aeb0SSepherosa Ziehau bce_sysctl_driver_state(SYSCTL_HANDLER_ARGS)
535143c2aeb0SSepherosa Ziehau {
535243c2aeb0SSepherosa Ziehau         int error;
535343c2aeb0SSepherosa Ziehau         int result;
535443c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
535543c2aeb0SSepherosa Ziehau 
535643c2aeb0SSepherosa Ziehau         result = -1;
535743c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
535843c2aeb0SSepherosa Ziehau 
535943c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
536043c2aeb0SSepherosa Ziehau                 return (error);
536143c2aeb0SSepherosa Ziehau 
536243c2aeb0SSepherosa Ziehau         if (result == 1) {
536343c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
536443c2aeb0SSepherosa Ziehau                 bce_dump_driver_state(sc);
536543c2aeb0SSepherosa Ziehau         }
536643c2aeb0SSepherosa Ziehau 
536743c2aeb0SSepherosa Ziehau         return error;
536843c2aeb0SSepherosa Ziehau }
536943c2aeb0SSepherosa Ziehau 
537043c2aeb0SSepherosa Ziehau 
537143c2aeb0SSepherosa Ziehau /****************************************************************************/
537243c2aeb0SSepherosa Ziehau /* Allows the hardware state to be dumped through the sysctl interface.     */
537343c2aeb0SSepherosa Ziehau /*                                                                          */
537443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
537543c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
537643c2aeb0SSepherosa Ziehau /****************************************************************************/
537743c2aeb0SSepherosa Ziehau static int
537843c2aeb0SSepherosa Ziehau bce_sysctl_hw_state(SYSCTL_HANDLER_ARGS)
537943c2aeb0SSepherosa Ziehau {
538043c2aeb0SSepherosa Ziehau         int error;
538143c2aeb0SSepherosa Ziehau         int result;
538243c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
538343c2aeb0SSepherosa Ziehau 
538443c2aeb0SSepherosa Ziehau         result = -1;
538543c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
538643c2aeb0SSepherosa Ziehau 
538743c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
538843c2aeb0SSepherosa Ziehau                 return (error);
538943c2aeb0SSepherosa Ziehau 
539043c2aeb0SSepherosa Ziehau         if (result == 1) {
539143c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
539243c2aeb0SSepherosa Ziehau                 bce_dump_hw_state(sc);
539343c2aeb0SSepherosa Ziehau         }
539443c2aeb0SSepherosa Ziehau 
539543c2aeb0SSepherosa Ziehau         return error;
539643c2aeb0SSepherosa Ziehau }
539743c2aeb0SSepherosa Ziehau 
539843c2aeb0SSepherosa Ziehau 
539943c2aeb0SSepherosa Ziehau /****************************************************************************/
540043c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to allows dumping the RX chain.              */
540143c2aeb0SSepherosa Ziehau /*                                                                          */
540243c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
540343c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
540443c2aeb0SSepherosa Ziehau /****************************************************************************/
540543c2aeb0SSepherosa Ziehau static int
540643c2aeb0SSepherosa Ziehau bce_sysctl_dump_rx_chain(SYSCTL_HANDLER_ARGS)
540743c2aeb0SSepherosa Ziehau {
540843c2aeb0SSepherosa Ziehau         int error;
540943c2aeb0SSepherosa Ziehau         int result;
541043c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
541143c2aeb0SSepherosa Ziehau 
541243c2aeb0SSepherosa Ziehau         result = -1;
541343c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
541443c2aeb0SSepherosa Ziehau 
541543c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
541643c2aeb0SSepherosa Ziehau                 return (error);
541743c2aeb0SSepherosa Ziehau 
541843c2aeb0SSepherosa Ziehau         if (result == 1) {
541943c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
542043c2aeb0SSepherosa Ziehau                 bce_dump_rx_chain(sc, 0, USABLE_RX_BD);
542143c2aeb0SSepherosa Ziehau         }
542243c2aeb0SSepherosa Ziehau 
542343c2aeb0SSepherosa Ziehau         return error;
542443c2aeb0SSepherosa Ziehau }
542543c2aeb0SSepherosa Ziehau 
542643c2aeb0SSepherosa Ziehau 
542743c2aeb0SSepherosa Ziehau /****************************************************************************/
542843c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to allows dumping the TX chain.              */
542943c2aeb0SSepherosa Ziehau /*                                                                          */
543043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
543143c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
543243c2aeb0SSepherosa Ziehau /****************************************************************************/
543343c2aeb0SSepherosa Ziehau static int
543443c2aeb0SSepherosa Ziehau bce_sysctl_dump_tx_chain(SYSCTL_HANDLER_ARGS)
543543c2aeb0SSepherosa Ziehau {
543643c2aeb0SSepherosa Ziehau         int error;
543743c2aeb0SSepherosa Ziehau         int result;
543843c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
543943c2aeb0SSepherosa Ziehau 
544043c2aeb0SSepherosa Ziehau         result = -1;
544143c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
544243c2aeb0SSepherosa Ziehau 
544343c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
544443c2aeb0SSepherosa Ziehau                 return (error);
544543c2aeb0SSepherosa Ziehau 
544643c2aeb0SSepherosa Ziehau         if (result == 1) {
544743c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
544843c2aeb0SSepherosa Ziehau                 bce_dump_tx_chain(sc, 0, USABLE_TX_BD);
544943c2aeb0SSepherosa Ziehau         }
545043c2aeb0SSepherosa Ziehau 
545143c2aeb0SSepherosa Ziehau         return error;
545243c2aeb0SSepherosa Ziehau }
545343c2aeb0SSepherosa Ziehau 
545443c2aeb0SSepherosa Ziehau 
545543c2aeb0SSepherosa Ziehau /****************************************************************************/
545643c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to allow reading arbitrary registers in the  */
545743c2aeb0SSepherosa Ziehau /* device.  DO NOT ENABLE ON PRODUCTION SYSTEMS!                            */
545843c2aeb0SSepherosa Ziehau /*                                                                          */
545943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
546043c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
546143c2aeb0SSepherosa Ziehau /****************************************************************************/
546243c2aeb0SSepherosa Ziehau static int
546343c2aeb0SSepherosa Ziehau bce_sysctl_reg_read(SYSCTL_HANDLER_ARGS)
546443c2aeb0SSepherosa Ziehau {
546543c2aeb0SSepherosa Ziehau 	struct bce_softc *sc;
546643c2aeb0SSepherosa Ziehau 	int error;
546743c2aeb0SSepherosa Ziehau 	uint32_t val, result;
546843c2aeb0SSepherosa Ziehau 
546943c2aeb0SSepherosa Ziehau 	result = -1;
547043c2aeb0SSepherosa Ziehau 	error = sysctl_handle_int(oidp, &result, 0, req);
547143c2aeb0SSepherosa Ziehau 	if (error || (req->newptr == NULL))
547243c2aeb0SSepherosa Ziehau 		return (error);
547343c2aeb0SSepherosa Ziehau 
547443c2aeb0SSepherosa Ziehau 	/* Make sure the register is accessible. */
547543c2aeb0SSepherosa Ziehau 	if (result < 0x8000) {
547643c2aeb0SSepherosa Ziehau 		sc = (struct bce_softc *)arg1;
547743c2aeb0SSepherosa Ziehau 		val = REG_RD(sc, result);
547843c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "reg 0x%08X = 0x%08X\n",
547943c2aeb0SSepherosa Ziehau 			  result, val);
548043c2aeb0SSepherosa Ziehau 	} else if (result < 0x0280000) {
548143c2aeb0SSepherosa Ziehau 		sc = (struct bce_softc *)arg1;
548243c2aeb0SSepherosa Ziehau 		val = REG_RD_IND(sc, result);
548343c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if, "reg 0x%08X = 0x%08X\n",
548443c2aeb0SSepherosa Ziehau 			  result, val);
548543c2aeb0SSepherosa Ziehau 	}
548643c2aeb0SSepherosa Ziehau 	return (error);
548743c2aeb0SSepherosa Ziehau }
548843c2aeb0SSepherosa Ziehau 
548943c2aeb0SSepherosa Ziehau 
549043c2aeb0SSepherosa Ziehau /****************************************************************************/
549143c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to allow reading arbitrary PHY registers in  */
549243c2aeb0SSepherosa Ziehau /* the device.  DO NOT ENABLE ON PRODUCTION SYSTEMS!                        */
549343c2aeb0SSepherosa Ziehau /*                                                                          */
549443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
549543c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
549643c2aeb0SSepherosa Ziehau /****************************************************************************/
549743c2aeb0SSepherosa Ziehau static int
549843c2aeb0SSepherosa Ziehau bce_sysctl_phy_read(SYSCTL_HANDLER_ARGS)
549943c2aeb0SSepherosa Ziehau {
550043c2aeb0SSepherosa Ziehau 	struct bce_softc *sc;
550143c2aeb0SSepherosa Ziehau 	device_t dev;
550243c2aeb0SSepherosa Ziehau 	int error, result;
550343c2aeb0SSepherosa Ziehau 	uint16_t val;
550443c2aeb0SSepherosa Ziehau 
550543c2aeb0SSepherosa Ziehau 	result = -1;
550643c2aeb0SSepherosa Ziehau 	error = sysctl_handle_int(oidp, &result, 0, req);
550743c2aeb0SSepherosa Ziehau 	if (error || (req->newptr == NULL))
550843c2aeb0SSepherosa Ziehau 		return (error);
550943c2aeb0SSepherosa Ziehau 
551043c2aeb0SSepherosa Ziehau 	/* Make sure the register is accessible. */
551143c2aeb0SSepherosa Ziehau 	if (result < 0x20) {
551243c2aeb0SSepherosa Ziehau 		sc = (struct bce_softc *)arg1;
551343c2aeb0SSepherosa Ziehau 		dev = sc->bce_dev;
551443c2aeb0SSepherosa Ziehau 		val = bce_miibus_read_reg(dev, sc->bce_phy_addr, result);
551543c2aeb0SSepherosa Ziehau 		if_printf(&sc->arpcom.ac_if,
551643c2aeb0SSepherosa Ziehau 			  "phy 0x%02X = 0x%04X\n", result, val);
551743c2aeb0SSepherosa Ziehau 	}
551843c2aeb0SSepherosa Ziehau 	return (error);
551943c2aeb0SSepherosa Ziehau }
552043c2aeb0SSepherosa Ziehau 
552143c2aeb0SSepherosa Ziehau 
552243c2aeb0SSepherosa Ziehau /****************************************************************************/
552343c2aeb0SSepherosa Ziehau /* Provides a sysctl interface to forcing the driver to dump state and      */
552443c2aeb0SSepherosa Ziehau /* enter the debugger.  DO NOT ENABLE ON PRODUCTION SYSTEMS!                */
552543c2aeb0SSepherosa Ziehau /*                                                                          */
552643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
552743c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
552843c2aeb0SSepherosa Ziehau /****************************************************************************/
552943c2aeb0SSepherosa Ziehau static int
553043c2aeb0SSepherosa Ziehau bce_sysctl_breakpoint(SYSCTL_HANDLER_ARGS)
553143c2aeb0SSepherosa Ziehau {
553243c2aeb0SSepherosa Ziehau         int error;
553343c2aeb0SSepherosa Ziehau         int result;
553443c2aeb0SSepherosa Ziehau         struct bce_softc *sc;
553543c2aeb0SSepherosa Ziehau 
553643c2aeb0SSepherosa Ziehau         result = -1;
553743c2aeb0SSepherosa Ziehau         error = sysctl_handle_int(oidp, &result, 0, req);
553843c2aeb0SSepherosa Ziehau 
553943c2aeb0SSepherosa Ziehau         if (error || !req->newptr)
554043c2aeb0SSepherosa Ziehau                 return (error);
554143c2aeb0SSepherosa Ziehau 
554243c2aeb0SSepherosa Ziehau         if (result == 1) {
554343c2aeb0SSepherosa Ziehau                 sc = (struct bce_softc *)arg1;
554443c2aeb0SSepherosa Ziehau                 bce_breakpoint(sc);
554543c2aeb0SSepherosa Ziehau         }
554643c2aeb0SSepherosa Ziehau 
554743c2aeb0SSepherosa Ziehau         return error;
554843c2aeb0SSepherosa Ziehau }
554943c2aeb0SSepherosa Ziehau #endif
555043c2aeb0SSepherosa Ziehau 
555143c2aeb0SSepherosa Ziehau 
555243c2aeb0SSepherosa Ziehau /****************************************************************************/
555343c2aeb0SSepherosa Ziehau /* Adds any sysctl parameters for tuning or debugging purposes.             */
555443c2aeb0SSepherosa Ziehau /*                                                                          */
555543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
555643c2aeb0SSepherosa Ziehau /*   0 for success, positive value for failure.                             */
555743c2aeb0SSepherosa Ziehau /****************************************************************************/
555843c2aeb0SSepherosa Ziehau static void
555943c2aeb0SSepherosa Ziehau bce_add_sysctls(struct bce_softc *sc)
556043c2aeb0SSepherosa Ziehau {
556143c2aeb0SSepherosa Ziehau 	struct sysctl_ctx_list *ctx;
556243c2aeb0SSepherosa Ziehau 	struct sysctl_oid_list *children;
556343c2aeb0SSepherosa Ziehau 
556443c2aeb0SSepherosa Ziehau 	sysctl_ctx_init(&sc->bce_sysctl_ctx);
556543c2aeb0SSepherosa Ziehau 	sc->bce_sysctl_tree = SYSCTL_ADD_NODE(&sc->bce_sysctl_ctx,
556643c2aeb0SSepherosa Ziehau 					      SYSCTL_STATIC_CHILDREN(_hw),
556743c2aeb0SSepherosa Ziehau 					      OID_AUTO,
556843c2aeb0SSepherosa Ziehau 					      device_get_nameunit(sc->bce_dev),
556943c2aeb0SSepherosa Ziehau 					      CTLFLAG_RD, 0, "");
557043c2aeb0SSepherosa Ziehau 	if (sc->bce_sysctl_tree == NULL) {
557143c2aeb0SSepherosa Ziehau 		device_printf(sc->bce_dev, "can't add sysctl node\n");
557243c2aeb0SSepherosa Ziehau 		return;
557343c2aeb0SSepherosa Ziehau 	}
557443c2aeb0SSepherosa Ziehau 
557543c2aeb0SSepherosa Ziehau 	ctx = &sc->bce_sysctl_ctx;
557643c2aeb0SSepherosa Ziehau 	children = SYSCTL_CHILDREN(sc->bce_sysctl_tree);
557743c2aeb0SSepherosa Ziehau 
5578bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_bds_int",
5579bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
5580bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_tx_bds_int, "I",
5581bdeb8fffSSepherosa Ziehau 			"Send max coalesced BD count during interrupt");
5582bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_bds",
5583bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
5584bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_tx_bds, "I",
5585bdeb8fffSSepherosa Ziehau 			"Send max coalesced BD count");
5586bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_ticks_int",
5587bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
5588bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_tx_ticks_int, "I",
5589bdeb8fffSSepherosa Ziehau 			"Send coalescing ticks during interrupt");
5590bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_ticks",
5591bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
5592bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_tx_ticks, "I",
5593bdeb8fffSSepherosa Ziehau 			"Send coalescing ticks");
5594bdeb8fffSSepherosa Ziehau 
5595bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_bds_int",
5596bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
5597bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_rx_bds_int, "I",
5598bdeb8fffSSepherosa Ziehau 			"Receive max coalesced BD count during interrupt");
5599bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_bds",
5600bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
5601bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_rx_bds, "I",
5602bdeb8fffSSepherosa Ziehau 			"Receive max coalesced BD count");
5603bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_ticks_int",
5604bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
5605bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_rx_ticks_int, "I",
5606bdeb8fffSSepherosa Ziehau 			"Receive coalescing ticks during interrupt");
5607bdeb8fffSSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_ticks",
5608bdeb8fffSSepherosa Ziehau 			CTLTYPE_INT | CTLFLAG_RW,
5609bdeb8fffSSepherosa Ziehau 			sc, 0, bce_sysctl_rx_ticks, "I",
5610bdeb8fffSSepherosa Ziehau 			"Receive coalescing ticks");
5611bdeb8fffSSepherosa Ziehau 
561243c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
561343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
561443c2aeb0SSepherosa Ziehau 		"rx_low_watermark",
561543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->rx_low_watermark,
561643c2aeb0SSepherosa Ziehau 		0, "Lowest level of free rx_bd's");
561743c2aeb0SSepherosa Ziehau 
561843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
561943c2aeb0SSepherosa Ziehau 		"rx_empty_count",
562043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->rx_empty_count,
562143c2aeb0SSepherosa Ziehau 		0, "Number of times the RX chain was empty");
562243c2aeb0SSepherosa Ziehau 
562343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
562443c2aeb0SSepherosa Ziehau 		"tx_hi_watermark",
562543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->tx_hi_watermark,
562643c2aeb0SSepherosa Ziehau 		0, "Highest level of used tx_bd's");
562743c2aeb0SSepherosa Ziehau 
562843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
562943c2aeb0SSepherosa Ziehau 		"tx_full_count",
563043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->tx_full_count,
563143c2aeb0SSepherosa Ziehau 		0, "Number of times the TX chain was full");
563243c2aeb0SSepherosa Ziehau 
563343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
563443c2aeb0SSepherosa Ziehau 		"l2fhdr_status_errors",
563543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->l2fhdr_status_errors,
563643c2aeb0SSepherosa Ziehau 		0, "l2_fhdr status errors");
563743c2aeb0SSepherosa Ziehau 
563843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
563943c2aeb0SSepherosa Ziehau 		"unexpected_attentions",
564043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->unexpected_attentions,
564143c2aeb0SSepherosa Ziehau 		0, "unexpected attentions");
564243c2aeb0SSepherosa Ziehau 
564343c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
564443c2aeb0SSepherosa Ziehau 		"lost_status_block_updates",
564543c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->lost_status_block_updates,
564643c2aeb0SSepherosa Ziehau 		0, "lost status block updates");
564743c2aeb0SSepherosa Ziehau 
564843c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
564943c2aeb0SSepherosa Ziehau 		"mbuf_alloc_failed",
565043c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->mbuf_alloc_failed,
565143c2aeb0SSepherosa Ziehau 		0, "mbuf cluster allocation failures");
565243c2aeb0SSepherosa Ziehau #endif
565343c2aeb0SSepherosa Ziehau 
565443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
565556872d4eSSepherosa Ziehau 		"stat_IfHCInOctets",
565643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInOctets,
565743c2aeb0SSepherosa Ziehau 		"Bytes received");
565843c2aeb0SSepherosa Ziehau 
565943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
566043c2aeb0SSepherosa Ziehau 		"stat_IfHCInBadOctets",
566143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInBadOctets,
566243c2aeb0SSepherosa Ziehau 		"Bad bytes received");
566343c2aeb0SSepherosa Ziehau 
566443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
566543c2aeb0SSepherosa Ziehau 		"stat_IfHCOutOctets",
566643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutOctets,
566743c2aeb0SSepherosa Ziehau 		"Bytes sent");
566843c2aeb0SSepherosa Ziehau 
566943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
567043c2aeb0SSepherosa Ziehau 		"stat_IfHCOutBadOctets",
567143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutBadOctets,
567243c2aeb0SSepherosa Ziehau 		"Bad bytes sent");
567343c2aeb0SSepherosa Ziehau 
567443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
567543c2aeb0SSepherosa Ziehau 		"stat_IfHCInUcastPkts",
567643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInUcastPkts,
567743c2aeb0SSepherosa Ziehau 		"Unicast packets received");
567843c2aeb0SSepherosa Ziehau 
567943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
568043c2aeb0SSepherosa Ziehau 		"stat_IfHCInMulticastPkts",
568143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInMulticastPkts,
568243c2aeb0SSepherosa Ziehau 		"Multicast packets received");
568343c2aeb0SSepherosa Ziehau 
568443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
568543c2aeb0SSepherosa Ziehau 		"stat_IfHCInBroadcastPkts",
568643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCInBroadcastPkts,
568743c2aeb0SSepherosa Ziehau 		"Broadcast packets received");
568843c2aeb0SSepherosa Ziehau 
568943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
569043c2aeb0SSepherosa Ziehau 		"stat_IfHCOutUcastPkts",
569143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutUcastPkts,
569243c2aeb0SSepherosa Ziehau 		"Unicast packets sent");
569343c2aeb0SSepherosa Ziehau 
569443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
569543c2aeb0SSepherosa Ziehau 		"stat_IfHCOutMulticastPkts",
569643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutMulticastPkts,
569743c2aeb0SSepherosa Ziehau 		"Multicast packets sent");
569843c2aeb0SSepherosa Ziehau 
569943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
570043c2aeb0SSepherosa Ziehau 		"stat_IfHCOutBroadcastPkts",
570143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfHCOutBroadcastPkts,
570243c2aeb0SSepherosa Ziehau 		"Broadcast packets sent");
570343c2aeb0SSepherosa Ziehau 
570443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
570543c2aeb0SSepherosa Ziehau 		"stat_emac_tx_stat_dot3statsinternalmactransmiterrors",
570643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors,
570743c2aeb0SSepherosa Ziehau 		0, "Internal MAC transmit errors");
570843c2aeb0SSepherosa Ziehau 
570943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
571043c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsCarrierSenseErrors",
571143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsCarrierSenseErrors,
571243c2aeb0SSepherosa Ziehau 		0, "Carrier sense errors");
571343c2aeb0SSepherosa Ziehau 
571443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
571543c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsFCSErrors",
571643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsFCSErrors,
571743c2aeb0SSepherosa Ziehau 		0, "Frame check sequence errors");
571843c2aeb0SSepherosa Ziehau 
571943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
572043c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsAlignmentErrors",
572143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsAlignmentErrors,
572243c2aeb0SSepherosa Ziehau 		0, "Alignment errors");
572343c2aeb0SSepherosa Ziehau 
572443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
572543c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsSingleCollisionFrames",
572643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsSingleCollisionFrames,
572743c2aeb0SSepherosa Ziehau 		0, "Single Collision Frames");
572843c2aeb0SSepherosa Ziehau 
572943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
573043c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsMultipleCollisionFrames",
573143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsMultipleCollisionFrames,
573243c2aeb0SSepherosa Ziehau 		0, "Multiple Collision Frames");
573343c2aeb0SSepherosa Ziehau 
573443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
573543c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsDeferredTransmissions",
573643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsDeferredTransmissions,
573743c2aeb0SSepherosa Ziehau 		0, "Deferred Transmissions");
573843c2aeb0SSepherosa Ziehau 
573943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
574043c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsExcessiveCollisions",
574143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsExcessiveCollisions,
574243c2aeb0SSepherosa Ziehau 		0, "Excessive Collisions");
574343c2aeb0SSepherosa Ziehau 
574443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
574543c2aeb0SSepherosa Ziehau 		"stat_Dot3StatsLateCollisions",
574643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_Dot3StatsLateCollisions,
574743c2aeb0SSepherosa Ziehau 		0, "Late Collisions");
574843c2aeb0SSepherosa Ziehau 
574943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
575043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsCollisions",
575143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsCollisions,
575243c2aeb0SSepherosa Ziehau 		0, "Collisions");
575343c2aeb0SSepherosa Ziehau 
575443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
575543c2aeb0SSepherosa Ziehau 		"stat_EtherStatsFragments",
575643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsFragments,
575743c2aeb0SSepherosa Ziehau 		0, "Fragments");
575843c2aeb0SSepherosa Ziehau 
575943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
576043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsJabbers",
576143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsJabbers,
576243c2aeb0SSepherosa Ziehau 		0, "Jabbers");
576343c2aeb0SSepherosa Ziehau 
576443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
576543c2aeb0SSepherosa Ziehau 		"stat_EtherStatsUndersizePkts",
576643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsUndersizePkts,
576743c2aeb0SSepherosa Ziehau 		0, "Undersize packets");
576843c2aeb0SSepherosa Ziehau 
576943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
577043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsOverrsizePkts",
577143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsOverrsizePkts,
577243c2aeb0SSepherosa Ziehau 		0, "stat_EtherStatsOverrsizePkts");
577343c2aeb0SSepherosa Ziehau 
577443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
577543c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx64Octets",
577643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx64Octets,
577743c2aeb0SSepherosa Ziehau 		0, "Bytes received in 64 byte packets");
577843c2aeb0SSepherosa Ziehau 
577943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
578043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx65Octetsto127Octets",
578143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx65Octetsto127Octets,
578243c2aeb0SSepherosa Ziehau 		0, "Bytes received in 65 to 127 byte packets");
578343c2aeb0SSepherosa Ziehau 
578443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
578543c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx128Octetsto255Octets",
578643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx128Octetsto255Octets,
578743c2aeb0SSepherosa Ziehau 		0, "Bytes received in 128 to 255 byte packets");
578843c2aeb0SSepherosa Ziehau 
578943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
579043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx256Octetsto511Octets",
579143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx256Octetsto511Octets,
579243c2aeb0SSepherosa Ziehau 		0, "Bytes received in 256 to 511 byte packets");
579343c2aeb0SSepherosa Ziehau 
579443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
579543c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx512Octetsto1023Octets",
579643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx512Octetsto1023Octets,
579743c2aeb0SSepherosa Ziehau 		0, "Bytes received in 512 to 1023 byte packets");
579843c2aeb0SSepherosa Ziehau 
579943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
580043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx1024Octetsto1522Octets",
580143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1024Octetsto1522Octets,
580243c2aeb0SSepherosa Ziehau 		0, "Bytes received in 1024 t0 1522 byte packets");
580343c2aeb0SSepherosa Ziehau 
580443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
580543c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsRx1523Octetsto9022Octets",
580643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1523Octetsto9022Octets,
580743c2aeb0SSepherosa Ziehau 		0, "Bytes received in 1523 to 9022 byte packets");
580843c2aeb0SSepherosa Ziehau 
580943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
581043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx64Octets",
581143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx64Octets,
581243c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 64 byte packets");
581343c2aeb0SSepherosa Ziehau 
581443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
581543c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx65Octetsto127Octets",
581643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx65Octetsto127Octets,
581743c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 65 to 127 byte packets");
581843c2aeb0SSepherosa Ziehau 
581943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
582043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx128Octetsto255Octets",
582143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx128Octetsto255Octets,
582243c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 128 to 255 byte packets");
582343c2aeb0SSepherosa Ziehau 
582443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
582543c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx256Octetsto511Octets",
582643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx256Octetsto511Octets,
582743c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 256 to 511 byte packets");
582843c2aeb0SSepherosa Ziehau 
582943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
583043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx512Octetsto1023Octets",
583143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx512Octetsto1023Octets,
583243c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 512 to 1023 byte packets");
583343c2aeb0SSepherosa Ziehau 
583443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
583543c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx1024Octetsto1522Octets",
583643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1024Octetsto1522Octets,
583743c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 1024 to 1522 byte packets");
583843c2aeb0SSepherosa Ziehau 
583943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
584043c2aeb0SSepherosa Ziehau 		"stat_EtherStatsPktsTx1523Octetsto9022Octets",
584143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1523Octetsto9022Octets,
584243c2aeb0SSepherosa Ziehau 		0, "Bytes sent in 1523 to 9022 byte packets");
584343c2aeb0SSepherosa Ziehau 
584443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
584543c2aeb0SSepherosa Ziehau 		"stat_XonPauseFramesReceived",
584643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_XonPauseFramesReceived,
584743c2aeb0SSepherosa Ziehau 		0, "XON pause frames receved");
584843c2aeb0SSepherosa Ziehau 
584943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
585043c2aeb0SSepherosa Ziehau 		"stat_XoffPauseFramesReceived",
585143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_XoffPauseFramesReceived,
585243c2aeb0SSepherosa Ziehau 		0, "XOFF pause frames received");
585343c2aeb0SSepherosa Ziehau 
585443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
585543c2aeb0SSepherosa Ziehau 		"stat_OutXonSent",
585643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_OutXonSent,
585743c2aeb0SSepherosa Ziehau 		0, "XON pause frames sent");
585843c2aeb0SSepherosa Ziehau 
585943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
586043c2aeb0SSepherosa Ziehau 		"stat_OutXoffSent",
586143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_OutXoffSent,
586243c2aeb0SSepherosa Ziehau 		0, "XOFF pause frames sent");
586343c2aeb0SSepherosa Ziehau 
586443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
586543c2aeb0SSepherosa Ziehau 		"stat_FlowControlDone",
586643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_FlowControlDone,
586743c2aeb0SSepherosa Ziehau 		0, "Flow control done");
586843c2aeb0SSepherosa Ziehau 
586943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
587043c2aeb0SSepherosa Ziehau 		"stat_MacControlFramesReceived",
587143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_MacControlFramesReceived,
587243c2aeb0SSepherosa Ziehau 		0, "MAC control frames received");
587343c2aeb0SSepherosa Ziehau 
587443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
587543c2aeb0SSepherosa Ziehau 		"stat_XoffStateEntered",
587643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_XoffStateEntered,
587743c2aeb0SSepherosa Ziehau 		0, "XOFF state entered");
587843c2aeb0SSepherosa Ziehau 
587943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
588043c2aeb0SSepherosa Ziehau 		"stat_IfInFramesL2FilterDiscards",
588143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInFramesL2FilterDiscards,
588243c2aeb0SSepherosa Ziehau 		0, "Received L2 packets discarded");
588343c2aeb0SSepherosa Ziehau 
588443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
588543c2aeb0SSepherosa Ziehau 		"stat_IfInRuleCheckerDiscards",
588643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInRuleCheckerDiscards,
588743c2aeb0SSepherosa Ziehau 		0, "Received packets discarded by rule");
588843c2aeb0SSepherosa Ziehau 
588943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
589043c2aeb0SSepherosa Ziehau 		"stat_IfInFTQDiscards",
589143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInFTQDiscards,
589243c2aeb0SSepherosa Ziehau 		0, "Received packet FTQ discards");
589343c2aeb0SSepherosa Ziehau 
589443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
589543c2aeb0SSepherosa Ziehau 		"stat_IfInMBUFDiscards",
589643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInMBUFDiscards,
589743c2aeb0SSepherosa Ziehau 		0, "Received packets discarded due to lack of controller buffer memory");
589843c2aeb0SSepherosa Ziehau 
589943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
590043c2aeb0SSepherosa Ziehau 		"stat_IfInRuleCheckerP4Hit",
590143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_IfInRuleCheckerP4Hit,
590243c2aeb0SSepherosa Ziehau 		0, "Received packets rule checker hits");
590343c2aeb0SSepherosa Ziehau 
590443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
590543c2aeb0SSepherosa Ziehau 		"stat_CatchupInRuleCheckerDiscards",
590643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerDiscards,
590743c2aeb0SSepherosa Ziehau 		0, "Received packets discarded in Catchup path");
590843c2aeb0SSepherosa Ziehau 
590943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
591043c2aeb0SSepherosa Ziehau 		"stat_CatchupInFTQDiscards",
591143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_CatchupInFTQDiscards,
591243c2aeb0SSepherosa Ziehau 		0, "Received packets discarded in FTQ in Catchup path");
591343c2aeb0SSepherosa Ziehau 
591443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
591543c2aeb0SSepherosa Ziehau 		"stat_CatchupInMBUFDiscards",
591643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_CatchupInMBUFDiscards,
591743c2aeb0SSepherosa Ziehau 		0, "Received packets discarded in controller buffer memory in Catchup path");
591843c2aeb0SSepherosa Ziehau 
591943c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
592043c2aeb0SSepherosa Ziehau 		"stat_CatchupInRuleCheckerP4Hit",
592143c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerP4Hit,
592243c2aeb0SSepherosa Ziehau 		0, "Received packets rule checker hits in Catchup path");
592343c2aeb0SSepherosa Ziehau 
592443c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
592543c2aeb0SSepherosa Ziehau 		"com_no_buffers",
592643c2aeb0SSepherosa Ziehau 		CTLFLAG_RD, &sc->com_no_buffers,
592743c2aeb0SSepherosa Ziehau 		0, "Valid packets received but no RX buffers available");
592843c2aeb0SSepherosa Ziehau 
592943c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
593043c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
593143c2aeb0SSepherosa Ziehau 		"driver_state", CTLTYPE_INT | CTLFLAG_RW,
593243c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
593343c2aeb0SSepherosa Ziehau 		bce_sysctl_driver_state, "I", "Drive state information");
593443c2aeb0SSepherosa Ziehau 
593543c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
593643c2aeb0SSepherosa Ziehau 		"hw_state", CTLTYPE_INT | CTLFLAG_RW,
593743c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
593843c2aeb0SSepherosa Ziehau 		bce_sysctl_hw_state, "I", "Hardware state information");
593943c2aeb0SSepherosa Ziehau 
594043c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
594143c2aeb0SSepherosa Ziehau 		"dump_rx_chain", CTLTYPE_INT | CTLFLAG_RW,
594243c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
594343c2aeb0SSepherosa Ziehau 		bce_sysctl_dump_rx_chain, "I", "Dump rx_bd chain");
594443c2aeb0SSepherosa Ziehau 
594543c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
594643c2aeb0SSepherosa Ziehau 		"dump_tx_chain", CTLTYPE_INT | CTLFLAG_RW,
594743c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
594843c2aeb0SSepherosa Ziehau 		bce_sysctl_dump_tx_chain, "I", "Dump tx_bd chain");
594943c2aeb0SSepherosa Ziehau 
595043c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
595143c2aeb0SSepherosa Ziehau 		"breakpoint", CTLTYPE_INT | CTLFLAG_RW,
595243c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
595343c2aeb0SSepherosa Ziehau 		bce_sysctl_breakpoint, "I", "Driver breakpoint");
595443c2aeb0SSepherosa Ziehau 
595543c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
595643c2aeb0SSepherosa Ziehau 		"reg_read", CTLTYPE_INT | CTLFLAG_RW,
595743c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
595843c2aeb0SSepherosa Ziehau 		bce_sysctl_reg_read, "I", "Register read");
595943c2aeb0SSepherosa Ziehau 
596043c2aeb0SSepherosa Ziehau 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
596143c2aeb0SSepherosa Ziehau 		"phy_read", CTLTYPE_INT | CTLFLAG_RW,
596243c2aeb0SSepherosa Ziehau 		(void *)sc, 0,
596343c2aeb0SSepherosa Ziehau 		bce_sysctl_phy_read, "I", "PHY register read");
596443c2aeb0SSepherosa Ziehau 
596543c2aeb0SSepherosa Ziehau #endif
596643c2aeb0SSepherosa Ziehau 
596743c2aeb0SSepherosa Ziehau }
596843c2aeb0SSepherosa Ziehau 
596943c2aeb0SSepherosa Ziehau 
597043c2aeb0SSepherosa Ziehau /****************************************************************************/
597143c2aeb0SSepherosa Ziehau /* BCE Debug Routines                                                       */
597243c2aeb0SSepherosa Ziehau /****************************************************************************/
597343c2aeb0SSepherosa Ziehau #ifdef BCE_DEBUG
597443c2aeb0SSepherosa Ziehau 
597543c2aeb0SSepherosa Ziehau /****************************************************************************/
597643c2aeb0SSepherosa Ziehau /* Freezes the controller to allow for a cohesive state dump.               */
597743c2aeb0SSepherosa Ziehau /*                                                                          */
597843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
597943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
598043c2aeb0SSepherosa Ziehau /****************************************************************************/
598143c2aeb0SSepherosa Ziehau static void
598243c2aeb0SSepherosa Ziehau bce_freeze_controller(struct bce_softc *sc)
598343c2aeb0SSepherosa Ziehau {
598443c2aeb0SSepherosa Ziehau 	uint32_t val;
598543c2aeb0SSepherosa Ziehau 
598643c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_COMMAND);
598743c2aeb0SSepherosa Ziehau 	val |= BCE_MISC_COMMAND_DISABLE_ALL;
598843c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_COMMAND, val);
598943c2aeb0SSepherosa Ziehau }
599043c2aeb0SSepherosa Ziehau 
599143c2aeb0SSepherosa Ziehau 
599243c2aeb0SSepherosa Ziehau /****************************************************************************/
599343c2aeb0SSepherosa Ziehau /* Unfreezes the controller after a freeze operation.  This may not always  */
599443c2aeb0SSepherosa Ziehau /* work and the controller will require a reset!                            */
599543c2aeb0SSepherosa Ziehau /*                                                                          */
599643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
599743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
599843c2aeb0SSepherosa Ziehau /****************************************************************************/
599943c2aeb0SSepherosa Ziehau static void
600043c2aeb0SSepherosa Ziehau bce_unfreeze_controller(struct bce_softc *sc)
600143c2aeb0SSepherosa Ziehau {
600243c2aeb0SSepherosa Ziehau 	uint32_t val;
600343c2aeb0SSepherosa Ziehau 
600443c2aeb0SSepherosa Ziehau 	val = REG_RD(sc, BCE_MISC_COMMAND);
600543c2aeb0SSepherosa Ziehau 	val |= BCE_MISC_COMMAND_ENABLE_ALL;
600643c2aeb0SSepherosa Ziehau 	REG_WR(sc, BCE_MISC_COMMAND, val);
600743c2aeb0SSepherosa Ziehau }
600843c2aeb0SSepherosa Ziehau 
600943c2aeb0SSepherosa Ziehau 
601043c2aeb0SSepherosa Ziehau /****************************************************************************/
601143c2aeb0SSepherosa Ziehau /* Prints out information about an mbuf.                                    */
601243c2aeb0SSepherosa Ziehau /*                                                                          */
601343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
601443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
601543c2aeb0SSepherosa Ziehau /****************************************************************************/
601643c2aeb0SSepherosa Ziehau static void
601743c2aeb0SSepherosa Ziehau bce_dump_mbuf(struct bce_softc *sc, struct mbuf *m)
601843c2aeb0SSepherosa Ziehau {
601943c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
602043c2aeb0SSepherosa Ziehau 	uint32_t val_hi, val_lo;
602143c2aeb0SSepherosa Ziehau 	struct mbuf *mp = m;
602243c2aeb0SSepherosa Ziehau 
602343c2aeb0SSepherosa Ziehau 	if (m == NULL) {
602443c2aeb0SSepherosa Ziehau 		/* Index out of range. */
602543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "mbuf: null pointer\n");
602643c2aeb0SSepherosa Ziehau 		return;
602743c2aeb0SSepherosa Ziehau 	}
602843c2aeb0SSepherosa Ziehau 
602943c2aeb0SSepherosa Ziehau 	while (mp) {
603043c2aeb0SSepherosa Ziehau 		val_hi = BCE_ADDR_HI(mp);
603143c2aeb0SSepherosa Ziehau 		val_lo = BCE_ADDR_LO(mp);
603243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "mbuf: vaddr = 0x%08X:%08X, m_len = %d, "
603343c2aeb0SSepherosa Ziehau 			  "m_flags = ( ", val_hi, val_lo, mp->m_len);
603443c2aeb0SSepherosa Ziehau 
603543c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_EXT)
603643c2aeb0SSepherosa Ziehau 			kprintf("M_EXT ");
603743c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_PKTHDR)
603843c2aeb0SSepherosa Ziehau 			kprintf("M_PKTHDR ");
603943c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_EOR)
604043c2aeb0SSepherosa Ziehau 			kprintf("M_EOR ");
604143c2aeb0SSepherosa Ziehau #ifdef M_RDONLY
604243c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_RDONLY)
604343c2aeb0SSepherosa Ziehau 			kprintf("M_RDONLY ");
604443c2aeb0SSepherosa Ziehau #endif
604543c2aeb0SSepherosa Ziehau 
604643c2aeb0SSepherosa Ziehau 		val_hi = BCE_ADDR_HI(mp->m_data);
604743c2aeb0SSepherosa Ziehau 		val_lo = BCE_ADDR_LO(mp->m_data);
604843c2aeb0SSepherosa Ziehau 		kprintf(") m_data = 0x%08X:%08X\n", val_hi, val_lo);
604943c2aeb0SSepherosa Ziehau 
605043c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_PKTHDR) {
605143c2aeb0SSepherosa Ziehau 			if_printf(ifp, "- m_pkthdr: flags = ( ");
605243c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_BCAST)
605343c2aeb0SSepherosa Ziehau 				kprintf("M_BCAST ");
605443c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_MCAST)
605543c2aeb0SSepherosa Ziehau 				kprintf("M_MCAST ");
605643c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_FRAG)
605743c2aeb0SSepherosa Ziehau 				kprintf("M_FRAG ");
605843c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_FIRSTFRAG)
605943c2aeb0SSepherosa Ziehau 				kprintf("M_FIRSTFRAG ");
606043c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_LASTFRAG)
606143c2aeb0SSepherosa Ziehau 				kprintf("M_LASTFRAG ");
606243c2aeb0SSepherosa Ziehau #ifdef M_VLANTAG
606343c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_VLANTAG)
606443c2aeb0SSepherosa Ziehau 				kprintf("M_VLANTAG ");
606543c2aeb0SSepherosa Ziehau #endif
606643c2aeb0SSepherosa Ziehau #ifdef M_PROMISC
606743c2aeb0SSepherosa Ziehau 			if (mp->m_flags & M_PROMISC)
606843c2aeb0SSepherosa Ziehau 				kprintf("M_PROMISC ");
606943c2aeb0SSepherosa Ziehau #endif
607043c2aeb0SSepherosa Ziehau 			kprintf(") csum_flags = ( ");
607143c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_IP)
607243c2aeb0SSepherosa Ziehau 				kprintf("CSUM_IP ");
607343c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_TCP)
607443c2aeb0SSepherosa Ziehau 				kprintf("CSUM_TCP ");
607543c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_UDP)
607643c2aeb0SSepherosa Ziehau 				kprintf("CSUM_UDP ");
607743c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_IP_FRAGS)
607843c2aeb0SSepherosa Ziehau 				kprintf("CSUM_IP_FRAGS ");
607943c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_FRAGMENT)
608043c2aeb0SSepherosa Ziehau 				kprintf("CSUM_FRAGMENT ");
608143c2aeb0SSepherosa Ziehau #ifdef CSUM_TSO
608243c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_TSO)
608343c2aeb0SSepherosa Ziehau 				kprintf("CSUM_TSO ");
608443c2aeb0SSepherosa Ziehau #endif
608543c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_IP_CHECKED)
608643c2aeb0SSepherosa Ziehau 				kprintf("CSUM_IP_CHECKED ");
608743c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_IP_VALID)
608843c2aeb0SSepherosa Ziehau 				kprintf("CSUM_IP_VALID ");
608943c2aeb0SSepherosa Ziehau 			if (mp->m_pkthdr.csum_flags & CSUM_DATA_VALID)
609043c2aeb0SSepherosa Ziehau 				kprintf("CSUM_DATA_VALID ");
609143c2aeb0SSepherosa Ziehau 			kprintf(")\n");
609243c2aeb0SSepherosa Ziehau 		}
609343c2aeb0SSepherosa Ziehau 
609443c2aeb0SSepherosa Ziehau 		if (mp->m_flags & M_EXT) {
609543c2aeb0SSepherosa Ziehau 			val_hi = BCE_ADDR_HI(mp->m_ext.ext_buf);
609643c2aeb0SSepherosa Ziehau 			val_lo = BCE_ADDR_LO(mp->m_ext.ext_buf);
609743c2aeb0SSepherosa Ziehau 			if_printf(ifp, "- m_ext: vaddr = 0x%08X:%08X, "
609843c2aeb0SSepherosa Ziehau 				  "ext_size = %d\n",
609943c2aeb0SSepherosa Ziehau 				  val_hi, val_lo, mp->m_ext.ext_size);
610043c2aeb0SSepherosa Ziehau 		}
610143c2aeb0SSepherosa Ziehau 		mp = mp->m_next;
610243c2aeb0SSepherosa Ziehau 	}
610343c2aeb0SSepherosa Ziehau }
610443c2aeb0SSepherosa Ziehau 
610543c2aeb0SSepherosa Ziehau 
610643c2aeb0SSepherosa Ziehau /****************************************************************************/
610743c2aeb0SSepherosa Ziehau /* Prints out the mbufs in the TX mbuf chain.                               */
610843c2aeb0SSepherosa Ziehau /*                                                                          */
610943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
611043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
611143c2aeb0SSepherosa Ziehau /****************************************************************************/
611243c2aeb0SSepherosa Ziehau static void
611343c2aeb0SSepherosa Ziehau bce_dump_tx_mbuf_chain(struct bce_softc *sc, int chain_prod, int count)
611443c2aeb0SSepherosa Ziehau {
611543c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
611643c2aeb0SSepherosa Ziehau 	int i;
611743c2aeb0SSepherosa Ziehau 
611843c2aeb0SSepherosa Ziehau 	if_printf(ifp,
611943c2aeb0SSepherosa Ziehau 	"----------------------------"
612043c2aeb0SSepherosa Ziehau 	"  tx mbuf data  "
612143c2aeb0SSepherosa Ziehau 	"----------------------------\n");
612243c2aeb0SSepherosa Ziehau 
612343c2aeb0SSepherosa Ziehau 	for (i = 0; i < count; i++) {
612443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "txmbuf[%d]\n", chain_prod);
612543c2aeb0SSepherosa Ziehau 		bce_dump_mbuf(sc, sc->tx_mbuf_ptr[chain_prod]);
612643c2aeb0SSepherosa Ziehau 		chain_prod = TX_CHAIN_IDX(NEXT_TX_BD(chain_prod));
612743c2aeb0SSepherosa Ziehau 	}
612843c2aeb0SSepherosa Ziehau 
612943c2aeb0SSepherosa Ziehau 	if_printf(ifp,
613043c2aeb0SSepherosa Ziehau 	"----------------------------"
613143c2aeb0SSepherosa Ziehau 	"----------------"
613243c2aeb0SSepherosa Ziehau 	"----------------------------\n");
613343c2aeb0SSepherosa Ziehau }
613443c2aeb0SSepherosa Ziehau 
613543c2aeb0SSepherosa Ziehau 
613643c2aeb0SSepherosa Ziehau /****************************************************************************/
613743c2aeb0SSepherosa Ziehau /* Prints out the mbufs in the RX mbuf chain.                               */
613843c2aeb0SSepherosa Ziehau /*                                                                          */
613943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
614043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
614143c2aeb0SSepherosa Ziehau /****************************************************************************/
614243c2aeb0SSepherosa Ziehau static void
614343c2aeb0SSepherosa Ziehau bce_dump_rx_mbuf_chain(struct bce_softc *sc, int chain_prod, int count)
614443c2aeb0SSepherosa Ziehau {
614543c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
614643c2aeb0SSepherosa Ziehau 	int i;
614743c2aeb0SSepherosa Ziehau 
614843c2aeb0SSepherosa Ziehau 	if_printf(ifp,
614943c2aeb0SSepherosa Ziehau 	"----------------------------"
615043c2aeb0SSepherosa Ziehau 	"  rx mbuf data  "
615143c2aeb0SSepherosa Ziehau 	"----------------------------\n");
615243c2aeb0SSepherosa Ziehau 
615343c2aeb0SSepherosa Ziehau 	for (i = 0; i < count; i++) {
615443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rxmbuf[0x%04X]\n", chain_prod);
615543c2aeb0SSepherosa Ziehau 		bce_dump_mbuf(sc, sc->rx_mbuf_ptr[chain_prod]);
615643c2aeb0SSepherosa Ziehau 		chain_prod = RX_CHAIN_IDX(NEXT_RX_BD(chain_prod));
615743c2aeb0SSepherosa Ziehau 	}
615843c2aeb0SSepherosa Ziehau 
615943c2aeb0SSepherosa Ziehau 	if_printf(ifp,
616043c2aeb0SSepherosa Ziehau 	"----------------------------"
616143c2aeb0SSepherosa Ziehau 	"----------------"
616243c2aeb0SSepherosa Ziehau 	"----------------------------\n");
616343c2aeb0SSepherosa Ziehau }
616443c2aeb0SSepherosa Ziehau 
616543c2aeb0SSepherosa Ziehau 
616643c2aeb0SSepherosa Ziehau /****************************************************************************/
616743c2aeb0SSepherosa Ziehau /* Prints out a tx_bd structure.                                            */
616843c2aeb0SSepherosa Ziehau /*                                                                          */
616943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
617043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
617143c2aeb0SSepherosa Ziehau /****************************************************************************/
617243c2aeb0SSepherosa Ziehau static void
617343c2aeb0SSepherosa Ziehau bce_dump_txbd(struct bce_softc *sc, int idx, struct tx_bd *txbd)
617443c2aeb0SSepherosa Ziehau {
617543c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
617643c2aeb0SSepherosa Ziehau 
617743c2aeb0SSepherosa Ziehau 	if (idx > MAX_TX_BD) {
617843c2aeb0SSepherosa Ziehau 		/* Index out of range. */
617943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "tx_bd[0x%04X]: Invalid tx_bd index!\n", idx);
618043c2aeb0SSepherosa Ziehau 	} else if ((idx & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE) {
618143c2aeb0SSepherosa Ziehau 		/* TX Chain page pointer. */
618243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, "
618343c2aeb0SSepherosa Ziehau 			  "chain page pointer\n",
618443c2aeb0SSepherosa Ziehau 			  idx, txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo);
618543c2aeb0SSepherosa Ziehau 	} else {
618643c2aeb0SSepherosa Ziehau 		/* Normal tx_bd entry. */
618743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, "
618843c2aeb0SSepherosa Ziehau 			  "nbytes = 0x%08X, "
618943c2aeb0SSepherosa Ziehau 			  "vlan tag= 0x%04X, flags = 0x%04X (",
619043c2aeb0SSepherosa Ziehau 			  idx, txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo,
619143c2aeb0SSepherosa Ziehau 			  txbd->tx_bd_mss_nbytes,
619243c2aeb0SSepherosa Ziehau 			  txbd->tx_bd_vlan_tag, txbd->tx_bd_flags);
619343c2aeb0SSepherosa Ziehau 
619443c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_CONN_FAULT)
619543c2aeb0SSepherosa Ziehau 			kprintf(" CONN_FAULT");
619643c2aeb0SSepherosa Ziehau 
619743c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_TCP_UDP_CKSUM)
619843c2aeb0SSepherosa Ziehau 			kprintf(" TCP_UDP_CKSUM");
619943c2aeb0SSepherosa Ziehau 
620043c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_IP_CKSUM)
620143c2aeb0SSepherosa Ziehau 			kprintf(" IP_CKSUM");
620243c2aeb0SSepherosa Ziehau 
620343c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_VLAN_TAG)
620443c2aeb0SSepherosa Ziehau 			kprintf("  VLAN");
620543c2aeb0SSepherosa Ziehau 
620643c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_COAL_NOW)
620743c2aeb0SSepherosa Ziehau 			kprintf(" COAL_NOW");
620843c2aeb0SSepherosa Ziehau 
620943c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_DONT_GEN_CRC)
621043c2aeb0SSepherosa Ziehau 			kprintf(" DONT_GEN_CRC");
621143c2aeb0SSepherosa Ziehau 
621243c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_START)
621343c2aeb0SSepherosa Ziehau 			kprintf(" START");
621443c2aeb0SSepherosa Ziehau 
621543c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_END)
621643c2aeb0SSepherosa Ziehau 			kprintf(" END");
621743c2aeb0SSepherosa Ziehau 
621843c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_LSO)
621943c2aeb0SSepherosa Ziehau 			kprintf(" LSO");
622043c2aeb0SSepherosa Ziehau 
622143c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_OPTION_WORD)
622243c2aeb0SSepherosa Ziehau 			kprintf(" OPTION_WORD");
622343c2aeb0SSepherosa Ziehau 
622443c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_FLAGS)
622543c2aeb0SSepherosa Ziehau 			kprintf(" FLAGS");
622643c2aeb0SSepherosa Ziehau 
622743c2aeb0SSepherosa Ziehau 		if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_SNAP)
622843c2aeb0SSepherosa Ziehau 			kprintf(" SNAP");
622943c2aeb0SSepherosa Ziehau 
623043c2aeb0SSepherosa Ziehau 		kprintf(" )\n");
623143c2aeb0SSepherosa Ziehau 	}
623243c2aeb0SSepherosa Ziehau }
623343c2aeb0SSepherosa Ziehau 
623443c2aeb0SSepherosa Ziehau 
623543c2aeb0SSepherosa Ziehau /****************************************************************************/
623643c2aeb0SSepherosa Ziehau /* Prints out a rx_bd structure.                                            */
623743c2aeb0SSepherosa Ziehau /*                                                                          */
623843c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
623943c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
624043c2aeb0SSepherosa Ziehau /****************************************************************************/
624143c2aeb0SSepherosa Ziehau static void
624243c2aeb0SSepherosa Ziehau bce_dump_rxbd(struct bce_softc *sc, int idx, struct rx_bd *rxbd)
624343c2aeb0SSepherosa Ziehau {
624443c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
624543c2aeb0SSepherosa Ziehau 
624643c2aeb0SSepherosa Ziehau 	if (idx > MAX_RX_BD) {
624743c2aeb0SSepherosa Ziehau 		/* Index out of range. */
624843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_bd[0x%04X]: Invalid rx_bd index!\n", idx);
624943c2aeb0SSepherosa Ziehau 	} else if ((idx & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE) {
625043c2aeb0SSepherosa Ziehau 		/* TX Chain page pointer. */
625143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, "
625243c2aeb0SSepherosa Ziehau 			  "chain page pointer\n",
625343c2aeb0SSepherosa Ziehau 			  idx, rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo);
625443c2aeb0SSepherosa Ziehau 	} else {
625543c2aeb0SSepherosa Ziehau 		/* Normal tx_bd entry. */
625643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, "
625743c2aeb0SSepherosa Ziehau 			  "nbytes = 0x%08X, flags = 0x%08X\n",
625843c2aeb0SSepherosa Ziehau 			  idx, rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo,
625943c2aeb0SSepherosa Ziehau 			  rxbd->rx_bd_len, rxbd->rx_bd_flags);
626043c2aeb0SSepherosa Ziehau 	}
626143c2aeb0SSepherosa Ziehau }
626243c2aeb0SSepherosa Ziehau 
626343c2aeb0SSepherosa Ziehau 
626443c2aeb0SSepherosa Ziehau /****************************************************************************/
626543c2aeb0SSepherosa Ziehau /* Prints out a l2_fhdr structure.                                          */
626643c2aeb0SSepherosa Ziehau /*                                                                          */
626743c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
626843c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
626943c2aeb0SSepherosa Ziehau /****************************************************************************/
627043c2aeb0SSepherosa Ziehau static void
627143c2aeb0SSepherosa Ziehau bce_dump_l2fhdr(struct bce_softc *sc, int idx, struct l2_fhdr *l2fhdr)
627243c2aeb0SSepherosa Ziehau {
627343c2aeb0SSepherosa Ziehau 	if_printf(&sc->arpcom.ac_if, "l2_fhdr[0x%04X]: status = 0x%08X, "
627443c2aeb0SSepherosa Ziehau 		  "pkt_len = 0x%04X, vlan = 0x%04x, "
627543c2aeb0SSepherosa Ziehau 		  "ip_xsum = 0x%04X, tcp_udp_xsum = 0x%04X\n",
627643c2aeb0SSepherosa Ziehau 		  idx, l2fhdr->l2_fhdr_status,
627743c2aeb0SSepherosa Ziehau 		  l2fhdr->l2_fhdr_pkt_len, l2fhdr->l2_fhdr_vlan_tag,
627843c2aeb0SSepherosa Ziehau 		  l2fhdr->l2_fhdr_ip_xsum, l2fhdr->l2_fhdr_tcp_udp_xsum);
627943c2aeb0SSepherosa Ziehau }
628043c2aeb0SSepherosa Ziehau 
628143c2aeb0SSepherosa Ziehau 
628243c2aeb0SSepherosa Ziehau /****************************************************************************/
628343c2aeb0SSepherosa Ziehau /* Prints out the tx chain.                                                 */
628443c2aeb0SSepherosa Ziehau /*                                                                          */
628543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
628643c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
628743c2aeb0SSepherosa Ziehau /****************************************************************************/
628843c2aeb0SSepherosa Ziehau static void
628943c2aeb0SSepherosa Ziehau bce_dump_tx_chain(struct bce_softc *sc, int tx_prod, int count)
629043c2aeb0SSepherosa Ziehau {
629143c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
629243c2aeb0SSepherosa Ziehau 	int i;
629343c2aeb0SSepherosa Ziehau 
629443c2aeb0SSepherosa Ziehau 	/* First some info about the tx_bd chain structure. */
629543c2aeb0SSepherosa Ziehau 	if_printf(ifp,
629643c2aeb0SSepherosa Ziehau 	"----------------------------"
629743c2aeb0SSepherosa Ziehau 	"  tx_bd  chain  "
629843c2aeb0SSepherosa Ziehau 	"----------------------------\n");
629943c2aeb0SSepherosa Ziehau 
630043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "page size      = 0x%08X, "
630143c2aeb0SSepherosa Ziehau 		  "tx chain pages        = 0x%08X\n",
630243c2aeb0SSepherosa Ziehau 		  (uint32_t)BCM_PAGE_SIZE, (uint32_t)TX_PAGES);
630343c2aeb0SSepherosa Ziehau 
630443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "tx_bd per page = 0x%08X, "
630543c2aeb0SSepherosa Ziehau 		  "usable tx_bd per page = 0x%08X\n",
630643c2aeb0SSepherosa Ziehau 		  (uint32_t)TOTAL_TX_BD_PER_PAGE,
630743c2aeb0SSepherosa Ziehau 		  (uint32_t)USABLE_TX_BD_PER_PAGE);
630843c2aeb0SSepherosa Ziehau 
630943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "total tx_bd    = 0x%08X\n", (uint32_t)TOTAL_TX_BD);
631043c2aeb0SSepherosa Ziehau 
631143c2aeb0SSepherosa Ziehau 	if_printf(ifp,
631243c2aeb0SSepherosa Ziehau 	"----------------------------"
631343c2aeb0SSepherosa Ziehau 	"  tx_bd data    "
631443c2aeb0SSepherosa Ziehau 	"----------------------------\n");
631543c2aeb0SSepherosa Ziehau 
631643c2aeb0SSepherosa Ziehau 	/* Now print out the tx_bd's themselves. */
631743c2aeb0SSepherosa Ziehau 	for (i = 0; i < count; i++) {
631843c2aeb0SSepherosa Ziehau 		struct tx_bd *txbd;
631943c2aeb0SSepherosa Ziehau 
632043c2aeb0SSepherosa Ziehau 	 	txbd = &sc->tx_bd_chain[TX_PAGE(tx_prod)][TX_IDX(tx_prod)];
632143c2aeb0SSepherosa Ziehau 		bce_dump_txbd(sc, tx_prod, txbd);
632243c2aeb0SSepherosa Ziehau 		tx_prod = TX_CHAIN_IDX(NEXT_TX_BD(tx_prod));
632343c2aeb0SSepherosa Ziehau 	}
632443c2aeb0SSepherosa Ziehau 
632543c2aeb0SSepherosa Ziehau 	if_printf(ifp,
632643c2aeb0SSepherosa Ziehau 	"----------------------------"
632743c2aeb0SSepherosa Ziehau 	"----------------"
632843c2aeb0SSepherosa Ziehau 	"----------------------------\n");
632943c2aeb0SSepherosa Ziehau }
633043c2aeb0SSepherosa Ziehau 
633143c2aeb0SSepherosa Ziehau 
633243c2aeb0SSepherosa Ziehau /****************************************************************************/
633343c2aeb0SSepherosa Ziehau /* Prints out the rx chain.                                                 */
633443c2aeb0SSepherosa Ziehau /*                                                                          */
633543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
633643c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
633743c2aeb0SSepherosa Ziehau /****************************************************************************/
633843c2aeb0SSepherosa Ziehau static void
633943c2aeb0SSepherosa Ziehau bce_dump_rx_chain(struct bce_softc *sc, int rx_prod, int count)
634043c2aeb0SSepherosa Ziehau {
634143c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
634243c2aeb0SSepherosa Ziehau 	int i;
634343c2aeb0SSepherosa Ziehau 
634443c2aeb0SSepherosa Ziehau 	/* First some info about the tx_bd chain structure. */
634543c2aeb0SSepherosa Ziehau 	if_printf(ifp,
634643c2aeb0SSepherosa Ziehau 	"----------------------------"
634743c2aeb0SSepherosa Ziehau 	"  rx_bd  chain  "
634843c2aeb0SSepherosa Ziehau 	"----------------------------\n");
634943c2aeb0SSepherosa Ziehau 
635043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "page size      = 0x%08X, "
635143c2aeb0SSepherosa Ziehau 		  "rx chain pages        = 0x%08X\n",
635243c2aeb0SSepherosa Ziehau 		  (uint32_t)BCM_PAGE_SIZE, (uint32_t)RX_PAGES);
635343c2aeb0SSepherosa Ziehau 
635443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "rx_bd per page = 0x%08X, "
635543c2aeb0SSepherosa Ziehau 		  "usable rx_bd per page = 0x%08X\n",
635643c2aeb0SSepherosa Ziehau 		  (uint32_t)TOTAL_RX_BD_PER_PAGE,
635743c2aeb0SSepherosa Ziehau 		  (uint32_t)USABLE_RX_BD_PER_PAGE);
635843c2aeb0SSepherosa Ziehau 
635943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "total rx_bd    = 0x%08X\n", (uint32_t)TOTAL_RX_BD);
636043c2aeb0SSepherosa Ziehau 
636143c2aeb0SSepherosa Ziehau 	if_printf(ifp,
636243c2aeb0SSepherosa Ziehau 	"----------------------------"
636343c2aeb0SSepherosa Ziehau 	"   rx_bd data   "
636443c2aeb0SSepherosa Ziehau 	"----------------------------\n");
636543c2aeb0SSepherosa Ziehau 
636643c2aeb0SSepherosa Ziehau 	/* Now print out the rx_bd's themselves. */
636743c2aeb0SSepherosa Ziehau 	for (i = 0; i < count; i++) {
636843c2aeb0SSepherosa Ziehau 		struct rx_bd *rxbd;
636943c2aeb0SSepherosa Ziehau 
637043c2aeb0SSepherosa Ziehau 		rxbd = &sc->rx_bd_chain[RX_PAGE(rx_prod)][RX_IDX(rx_prod)];
637143c2aeb0SSepherosa Ziehau 		bce_dump_rxbd(sc, rx_prod, rxbd);
637243c2aeb0SSepherosa Ziehau 		rx_prod = RX_CHAIN_IDX(NEXT_RX_BD(rx_prod));
637343c2aeb0SSepherosa Ziehau 	}
637443c2aeb0SSepherosa Ziehau 
637543c2aeb0SSepherosa Ziehau 	if_printf(ifp,
637643c2aeb0SSepherosa Ziehau 	"----------------------------"
637743c2aeb0SSepherosa Ziehau 	"----------------"
637843c2aeb0SSepherosa Ziehau 	"----------------------------\n");
637943c2aeb0SSepherosa Ziehau }
638043c2aeb0SSepherosa Ziehau 
638143c2aeb0SSepherosa Ziehau 
638243c2aeb0SSepherosa Ziehau /****************************************************************************/
638343c2aeb0SSepherosa Ziehau /* Prints out the status block from host memory.                            */
638443c2aeb0SSepherosa Ziehau /*                                                                          */
638543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
638643c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
638743c2aeb0SSepherosa Ziehau /****************************************************************************/
638843c2aeb0SSepherosa Ziehau static void
638943c2aeb0SSepherosa Ziehau bce_dump_status_block(struct bce_softc *sc)
639043c2aeb0SSepherosa Ziehau {
639143c2aeb0SSepherosa Ziehau 	struct status_block *sblk = sc->status_block;
639243c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
639343c2aeb0SSepherosa Ziehau 
639443c2aeb0SSepherosa Ziehau 	if_printf(ifp,
639543c2aeb0SSepherosa Ziehau 	"----------------------------"
639643c2aeb0SSepherosa Ziehau 	"  Status Block  "
639743c2aeb0SSepherosa Ziehau 	"----------------------------\n");
639843c2aeb0SSepherosa Ziehau 
639943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "    0x%08X - attn_bits\n", sblk->status_attn_bits);
640043c2aeb0SSepherosa Ziehau 
640143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "    0x%08X - attn_bits_ack\n",
640243c2aeb0SSepherosa Ziehau 		  sblk->status_attn_bits_ack);
640343c2aeb0SSepherosa Ziehau 
640443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%04X(0x%04X) - rx_cons0\n",
640543c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index0,
640643c2aeb0SSepherosa Ziehau 	    (uint16_t)RX_CHAIN_IDX(sblk->status_rx_quick_consumer_index0));
640743c2aeb0SSepherosa Ziehau 
640843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%04X(0x%04X) - tx_cons0\n",
640943c2aeb0SSepherosa Ziehau 	    sblk->status_tx_quick_consumer_index0,
641043c2aeb0SSepherosa Ziehau 	    (uint16_t)TX_CHAIN_IDX(sblk->status_tx_quick_consumer_index0));
641143c2aeb0SSepherosa Ziehau 
641243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "        0x%04X - status_idx\n", sblk->status_idx);
641343c2aeb0SSepherosa Ziehau 
641443c2aeb0SSepherosa Ziehau 	/* Theses indices are not used for normal L2 drivers. */
641543c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index1) {
641643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - rx_cons1\n",
641743c2aeb0SSepherosa Ziehau 		sblk->status_rx_quick_consumer_index1,
641843c2aeb0SSepherosa Ziehau 		(uint16_t)RX_CHAIN_IDX(sblk->status_rx_quick_consumer_index1));
641943c2aeb0SSepherosa Ziehau 	}
642043c2aeb0SSepherosa Ziehau 
642143c2aeb0SSepherosa Ziehau 	if (sblk->status_tx_quick_consumer_index1) {
642243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - tx_cons1\n",
642343c2aeb0SSepherosa Ziehau 		sblk->status_tx_quick_consumer_index1,
642443c2aeb0SSepherosa Ziehau 		(uint16_t)TX_CHAIN_IDX(sblk->status_tx_quick_consumer_index1));
642543c2aeb0SSepherosa Ziehau 	}
642643c2aeb0SSepherosa Ziehau 
642743c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index2) {
642843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X)- rx_cons2\n",
642943c2aeb0SSepherosa Ziehau 		sblk->status_rx_quick_consumer_index2,
643043c2aeb0SSepherosa Ziehau 		(uint16_t)RX_CHAIN_IDX(sblk->status_rx_quick_consumer_index2));
643143c2aeb0SSepherosa Ziehau 	}
643243c2aeb0SSepherosa Ziehau 
643343c2aeb0SSepherosa Ziehau 	if (sblk->status_tx_quick_consumer_index2) {
643443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - tx_cons2\n",
643543c2aeb0SSepherosa Ziehau 		sblk->status_tx_quick_consumer_index2,
643643c2aeb0SSepherosa Ziehau 		(uint16_t)TX_CHAIN_IDX(sblk->status_tx_quick_consumer_index2));
643743c2aeb0SSepherosa Ziehau 	}
643843c2aeb0SSepherosa Ziehau 
643943c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index3) {
644043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - rx_cons3\n",
644143c2aeb0SSepherosa Ziehau 		sblk->status_rx_quick_consumer_index3,
644243c2aeb0SSepherosa Ziehau 		(uint16_t)RX_CHAIN_IDX(sblk->status_rx_quick_consumer_index3));
644343c2aeb0SSepherosa Ziehau 	}
644443c2aeb0SSepherosa Ziehau 
644543c2aeb0SSepherosa Ziehau 	if (sblk->status_tx_quick_consumer_index3) {
644643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X(0x%04X) - tx_cons3\n",
644743c2aeb0SSepherosa Ziehau 		sblk->status_tx_quick_consumer_index3,
644843c2aeb0SSepherosa Ziehau 		(uint16_t)TX_CHAIN_IDX(sblk->status_tx_quick_consumer_index3));
644943c2aeb0SSepherosa Ziehau 	}
645043c2aeb0SSepherosa Ziehau 
645143c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index4 ||
645243c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index5) {
645343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons4  = 0x%08X, rx_cons5      = 0x%08X\n",
645443c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index4,
645543c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index5);
645643c2aeb0SSepherosa Ziehau 	}
645743c2aeb0SSepherosa Ziehau 
645843c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index6 ||
645943c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index7) {
646043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons6  = 0x%08X, rx_cons7      = 0x%08X\n",
646143c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index6,
646243c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index7);
646343c2aeb0SSepherosa Ziehau 	}
646443c2aeb0SSepherosa Ziehau 
646543c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index8 ||
646643c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index9) {
646743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons8  = 0x%08X, rx_cons9      = 0x%08X\n",
646843c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index8,
646943c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index9);
647043c2aeb0SSepherosa Ziehau 	}
647143c2aeb0SSepherosa Ziehau 
647243c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index10 ||
647343c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index11) {
647443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons10 = 0x%08X, rx_cons11     = 0x%08X\n",
647543c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index10,
647643c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index11);
647743c2aeb0SSepherosa Ziehau 	}
647843c2aeb0SSepherosa Ziehau 
647943c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index12 ||
648043c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index13) {
648143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons12 = 0x%08X, rx_cons13     = 0x%08X\n",
648243c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index12,
648343c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index13);
648443c2aeb0SSepherosa Ziehau 	}
648543c2aeb0SSepherosa Ziehau 
648643c2aeb0SSepherosa Ziehau 	if (sblk->status_rx_quick_consumer_index14 ||
648743c2aeb0SSepherosa Ziehau 	    sblk->status_rx_quick_consumer_index15) {
648843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "rx_cons14 = 0x%08X, rx_cons15     = 0x%08X\n",
648943c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index14,
649043c2aeb0SSepherosa Ziehau 			  sblk->status_rx_quick_consumer_index15);
649143c2aeb0SSepherosa Ziehau 	}
649243c2aeb0SSepherosa Ziehau 
649343c2aeb0SSepherosa Ziehau 	if (sblk->status_completion_producer_index ||
649443c2aeb0SSepherosa Ziehau 	    sblk->status_cmd_consumer_index) {
649543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "com_prod  = 0x%08X, cmd_cons      = 0x%08X\n",
649643c2aeb0SSepherosa Ziehau 			  sblk->status_completion_producer_index,
649743c2aeb0SSepherosa Ziehau 			  sblk->status_cmd_consumer_index);
649843c2aeb0SSepherosa Ziehau 	}
649943c2aeb0SSepherosa Ziehau 
650043c2aeb0SSepherosa Ziehau 	if_printf(ifp,
650143c2aeb0SSepherosa Ziehau 	"----------------------------"
650243c2aeb0SSepherosa Ziehau 	"----------------"
650343c2aeb0SSepherosa Ziehau 	"----------------------------\n");
650443c2aeb0SSepherosa Ziehau }
650543c2aeb0SSepherosa Ziehau 
650643c2aeb0SSepherosa Ziehau 
650743c2aeb0SSepherosa Ziehau /****************************************************************************/
650843c2aeb0SSepherosa Ziehau /* Prints out the statistics block.                                         */
650943c2aeb0SSepherosa Ziehau /*                                                                          */
651043c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
651143c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
651243c2aeb0SSepherosa Ziehau /****************************************************************************/
651343c2aeb0SSepherosa Ziehau static void
651443c2aeb0SSepherosa Ziehau bce_dump_stats_block(struct bce_softc *sc)
651543c2aeb0SSepherosa Ziehau {
651643c2aeb0SSepherosa Ziehau 	struct statistics_block *sblk = sc->stats_block;
651743c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
651843c2aeb0SSepherosa Ziehau 
651943c2aeb0SSepherosa Ziehau 	if_printf(ifp,
652043c2aeb0SSepherosa Ziehau 	"---------------"
652143c2aeb0SSepherosa Ziehau 	" Stats Block  (All Stats Not Shown Are 0) "
652243c2aeb0SSepherosa Ziehau 	"---------------\n");
652343c2aeb0SSepherosa Ziehau 
652443c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInOctets_hi || sblk->stat_IfHCInOctets_lo) {
652543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInOctets\n",
652643c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInOctets_hi,
652743c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInOctets_lo);
652843c2aeb0SSepherosa Ziehau 	}
652943c2aeb0SSepherosa Ziehau 
653043c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInBadOctets_hi || sblk->stat_IfHCInBadOctets_lo) {
653143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInBadOctets\n",
653243c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInBadOctets_hi,
653343c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInBadOctets_lo);
653443c2aeb0SSepherosa Ziehau 	}
653543c2aeb0SSepherosa Ziehau 
653643c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutOctets_hi || sblk->stat_IfHCOutOctets_lo) {
653743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutOctets\n",
653843c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutOctets_hi,
653943c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutOctets_lo);
654043c2aeb0SSepherosa Ziehau 	}
654143c2aeb0SSepherosa Ziehau 
654243c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutBadOctets_hi || sblk->stat_IfHCOutBadOctets_lo) {
654343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutBadOctets\n",
654443c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutBadOctets_hi,
654543c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutBadOctets_lo);
654643c2aeb0SSepherosa Ziehau 	}
654743c2aeb0SSepherosa Ziehau 
654843c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInUcastPkts_hi || sblk->stat_IfHCInUcastPkts_lo) {
654943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInUcastPkts\n",
655043c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInUcastPkts_hi,
655143c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInUcastPkts_lo);
655243c2aeb0SSepherosa Ziehau 	}
655343c2aeb0SSepherosa Ziehau 
655443c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInBroadcastPkts_hi ||
655543c2aeb0SSepherosa Ziehau 	    sblk->stat_IfHCInBroadcastPkts_lo) {
655643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInBroadcastPkts\n",
655743c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInBroadcastPkts_hi,
655843c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInBroadcastPkts_lo);
655943c2aeb0SSepherosa Ziehau 	}
656043c2aeb0SSepherosa Ziehau 
656143c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCInMulticastPkts_hi ||
656243c2aeb0SSepherosa Ziehau 	    sblk->stat_IfHCInMulticastPkts_lo) {
656343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcInMulticastPkts\n",
656443c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInMulticastPkts_hi,
656543c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCInMulticastPkts_lo);
656643c2aeb0SSepherosa Ziehau 	}
656743c2aeb0SSepherosa Ziehau 
656843c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutUcastPkts_hi || sblk->stat_IfHCOutUcastPkts_lo) {
656943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutUcastPkts\n",
657043c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutUcastPkts_hi,
657143c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutUcastPkts_lo);
657243c2aeb0SSepherosa Ziehau 	}
657343c2aeb0SSepherosa Ziehau 
657443c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutBroadcastPkts_hi ||
657543c2aeb0SSepherosa Ziehau 	    sblk->stat_IfHCOutBroadcastPkts_lo) {
657643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutBroadcastPkts\n",
657743c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutBroadcastPkts_hi,
657843c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutBroadcastPkts_lo);
657943c2aeb0SSepherosa Ziehau 	}
658043c2aeb0SSepherosa Ziehau 
658143c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfHCOutMulticastPkts_hi ||
658243c2aeb0SSepherosa Ziehau 	    sblk->stat_IfHCOutMulticastPkts_lo) {
658343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%08X:%08X : IfHcOutMulticastPkts\n",
658443c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutMulticastPkts_hi,
658543c2aeb0SSepherosa Ziehau 			  sblk->stat_IfHCOutMulticastPkts_lo);
658643c2aeb0SSepherosa Ziehau 	}
658743c2aeb0SSepherosa Ziehau 
658843c2aeb0SSepherosa Ziehau 	if (sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors) {
658943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
659043c2aeb0SSepherosa Ziehau 		"emac_tx_stat_dot3statsinternalmactransmiterrors\n",
659143c2aeb0SSepherosa Ziehau 		sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors);
659243c2aeb0SSepherosa Ziehau 	}
659343c2aeb0SSepherosa Ziehau 
659443c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsCarrierSenseErrors) {
659543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
659643c2aeb0SSepherosa Ziehau 			  "Dot3StatsCarrierSenseErrors\n",
659743c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsCarrierSenseErrors);
659843c2aeb0SSepherosa Ziehau 	}
659943c2aeb0SSepherosa Ziehau 
660043c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsFCSErrors) {
660143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : Dot3StatsFCSErrors\n",
660243c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsFCSErrors);
660343c2aeb0SSepherosa Ziehau 	}
660443c2aeb0SSepherosa Ziehau 
660543c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsAlignmentErrors) {
660643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : Dot3StatsAlignmentErrors\n",
660743c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsAlignmentErrors);
660843c2aeb0SSepherosa Ziehau 	}
660943c2aeb0SSepherosa Ziehau 
661043c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsSingleCollisionFrames) {
661143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
661243c2aeb0SSepherosa Ziehau 			  "Dot3StatsSingleCollisionFrames\n",
661343c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsSingleCollisionFrames);
661443c2aeb0SSepherosa Ziehau 	}
661543c2aeb0SSepherosa Ziehau 
661643c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsMultipleCollisionFrames) {
661743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
661843c2aeb0SSepherosa Ziehau 			  "Dot3StatsMultipleCollisionFrames\n",
661943c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsMultipleCollisionFrames);
662043c2aeb0SSepherosa Ziehau 	}
662143c2aeb0SSepherosa Ziehau 
662243c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsDeferredTransmissions) {
662343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
662443c2aeb0SSepherosa Ziehau 			  "Dot3StatsDeferredTransmissions\n",
662543c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsDeferredTransmissions);
662643c2aeb0SSepherosa Ziehau 	}
662743c2aeb0SSepherosa Ziehau 
662843c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsExcessiveCollisions) {
662943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
663043c2aeb0SSepherosa Ziehau 			  "Dot3StatsExcessiveCollisions\n",
663143c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsExcessiveCollisions);
663243c2aeb0SSepherosa Ziehau 	}
663343c2aeb0SSepherosa Ziehau 
663443c2aeb0SSepherosa Ziehau 	if (sblk->stat_Dot3StatsLateCollisions) {
663543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : Dot3StatsLateCollisions\n",
663643c2aeb0SSepherosa Ziehau 			  sblk->stat_Dot3StatsLateCollisions);
663743c2aeb0SSepherosa Ziehau 	}
663843c2aeb0SSepherosa Ziehau 
663943c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsCollisions) {
664043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsCollisions\n",
664143c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsCollisions);
664243c2aeb0SSepherosa Ziehau 	}
664343c2aeb0SSepherosa Ziehau 
664443c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsFragments)  {
664543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsFragments\n",
664643c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsFragments);
664743c2aeb0SSepherosa Ziehau 	}
664843c2aeb0SSepherosa Ziehau 
664943c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsJabbers) {
665043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsJabbers\n",
665143c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsJabbers);
665243c2aeb0SSepherosa Ziehau 	}
665343c2aeb0SSepherosa Ziehau 
665443c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsUndersizePkts) {
665543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsUndersizePkts\n",
665643c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsUndersizePkts);
665743c2aeb0SSepherosa Ziehau 	}
665843c2aeb0SSepherosa Ziehau 
665943c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsOverrsizePkts) {
666043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsOverrsizePkts\n",
666143c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsOverrsizePkts);
666243c2aeb0SSepherosa Ziehau 	}
666343c2aeb0SSepherosa Ziehau 
666443c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx64Octets) {
666543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsPktsRx64Octets\n",
666643c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx64Octets);
666743c2aeb0SSepherosa Ziehau 	}
666843c2aeb0SSepherosa Ziehau 
666943c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx65Octetsto127Octets) {
667043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
667143c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx65Octetsto127Octets\n",
667243c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx65Octetsto127Octets);
667343c2aeb0SSepherosa Ziehau 	}
667443c2aeb0SSepherosa Ziehau 
667543c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx128Octetsto255Octets) {
667643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
667743c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx128Octetsto255Octets\n",
667843c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx128Octetsto255Octets);
667943c2aeb0SSepherosa Ziehau 	}
668043c2aeb0SSepherosa Ziehau 
668143c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx256Octetsto511Octets) {
668243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
668343c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx256Octetsto511Octets\n",
668443c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx256Octetsto511Octets);
668543c2aeb0SSepherosa Ziehau 	}
668643c2aeb0SSepherosa Ziehau 
668743c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx512Octetsto1023Octets) {
668843c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
668943c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx512Octetsto1023Octets\n",
669043c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx512Octetsto1023Octets);
669143c2aeb0SSepherosa Ziehau 	}
669243c2aeb0SSepherosa Ziehau 
669343c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets) {
669443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
669543c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx1024Octetsto1522Octets\n",
669643c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets);
669743c2aeb0SSepherosa Ziehau 	}
669843c2aeb0SSepherosa Ziehau 
669943c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets) {
670043c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
670143c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsRx1523Octetsto9022Octets\n",
670243c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets);
670343c2aeb0SSepherosa Ziehau 	}
670443c2aeb0SSepherosa Ziehau 
670543c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx64Octets) {
670643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : EtherStatsPktsTx64Octets\n",
670743c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx64Octets);
670843c2aeb0SSepherosa Ziehau 	}
670943c2aeb0SSepherosa Ziehau 
671043c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx65Octetsto127Octets) {
671143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
671243c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx65Octetsto127Octets\n",
671343c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx65Octetsto127Octets);
671443c2aeb0SSepherosa Ziehau 	}
671543c2aeb0SSepherosa Ziehau 
671643c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx128Octetsto255Octets) {
671743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
671843c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx128Octetsto255Octets\n",
671943c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx128Octetsto255Octets);
672043c2aeb0SSepherosa Ziehau 	}
672143c2aeb0SSepherosa Ziehau 
672243c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx256Octetsto511Octets) {
672343c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
672443c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx256Octetsto511Octets\n",
672543c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx256Octetsto511Octets);
672643c2aeb0SSepherosa Ziehau 	}
672743c2aeb0SSepherosa Ziehau 
672843c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx512Octetsto1023Octets) {
672943c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
673043c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx512Octetsto1023Octets\n",
673143c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx512Octetsto1023Octets);
673243c2aeb0SSepherosa Ziehau 	}
673343c2aeb0SSepherosa Ziehau 
673443c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets) {
673543c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
673643c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx1024Octetsto1522Octets\n",
673743c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets);
673843c2aeb0SSepherosa Ziehau 	}
673943c2aeb0SSepherosa Ziehau 
674043c2aeb0SSepherosa Ziehau 	if (sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets) {
674143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
674243c2aeb0SSepherosa Ziehau 			  "EtherStatsPktsTx1523Octetsto9022Octets\n",
674343c2aeb0SSepherosa Ziehau 			  sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets);
674443c2aeb0SSepherosa Ziehau 	}
674543c2aeb0SSepherosa Ziehau 
674643c2aeb0SSepherosa Ziehau 	if (sblk->stat_XonPauseFramesReceived) {
674743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : XonPauseFramesReceived\n",
674843c2aeb0SSepherosa Ziehau 			  sblk->stat_XonPauseFramesReceived);
674943c2aeb0SSepherosa Ziehau 	}
675043c2aeb0SSepherosa Ziehau 
675143c2aeb0SSepherosa Ziehau 	if (sblk->stat_XoffPauseFramesReceived) {
675243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "          0x%08X : XoffPauseFramesReceived\n",
675343c2aeb0SSepherosa Ziehau 			  sblk->stat_XoffPauseFramesReceived);
675443c2aeb0SSepherosa Ziehau 	}
675543c2aeb0SSepherosa Ziehau 
675643c2aeb0SSepherosa Ziehau 	if (sblk->stat_OutXonSent) {
675743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : OutXoffSent\n",
675843c2aeb0SSepherosa Ziehau 			  sblk->stat_OutXonSent);
675943c2aeb0SSepherosa Ziehau 	}
676043c2aeb0SSepherosa Ziehau 
676143c2aeb0SSepherosa Ziehau 	if (sblk->stat_OutXoffSent) {
676243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : OutXoffSent\n",
676343c2aeb0SSepherosa Ziehau 			  sblk->stat_OutXoffSent);
676443c2aeb0SSepherosa Ziehau 	}
676543c2aeb0SSepherosa Ziehau 
676643c2aeb0SSepherosa Ziehau 	if (sblk->stat_FlowControlDone) {
676743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : FlowControlDone\n",
676843c2aeb0SSepherosa Ziehau 			  sblk->stat_FlowControlDone);
676943c2aeb0SSepherosa Ziehau 	}
677043c2aeb0SSepherosa Ziehau 
677143c2aeb0SSepherosa Ziehau 	if (sblk->stat_MacControlFramesReceived) {
677243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : MacControlFramesReceived\n",
677343c2aeb0SSepherosa Ziehau 			  sblk->stat_MacControlFramesReceived);
677443c2aeb0SSepherosa Ziehau 	}
677543c2aeb0SSepherosa Ziehau 
677643c2aeb0SSepherosa Ziehau 	if (sblk->stat_XoffStateEntered) {
677743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : XoffStateEntered\n",
677843c2aeb0SSepherosa Ziehau 			  sblk->stat_XoffStateEntered);
677943c2aeb0SSepherosa Ziehau 	}
678043c2aeb0SSepherosa Ziehau 
678143c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInFramesL2FilterDiscards) {
678243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInFramesL2FilterDiscards\n",			  sblk->stat_IfInFramesL2FilterDiscards);
678343c2aeb0SSepherosa Ziehau 	}
678443c2aeb0SSepherosa Ziehau 
678543c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInRuleCheckerDiscards) {
678643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInRuleCheckerDiscards\n",
678743c2aeb0SSepherosa Ziehau 			  sblk->stat_IfInRuleCheckerDiscards);
678843c2aeb0SSepherosa Ziehau 	}
678943c2aeb0SSepherosa Ziehau 
679043c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInFTQDiscards) {
679143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInFTQDiscards\n",
679243c2aeb0SSepherosa Ziehau 			  sblk->stat_IfInFTQDiscards);
679343c2aeb0SSepherosa Ziehau 	}
679443c2aeb0SSepherosa Ziehau 
679543c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInMBUFDiscards) {
679643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInMBUFDiscards\n",
679743c2aeb0SSepherosa Ziehau 			  sblk->stat_IfInMBUFDiscards);
679843c2aeb0SSepherosa Ziehau 	}
679943c2aeb0SSepherosa Ziehau 
680043c2aeb0SSepherosa Ziehau 	if (sblk->stat_IfInRuleCheckerP4Hit) {
680143c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : IfInRuleCheckerP4Hit\n",
680243c2aeb0SSepherosa Ziehau 			  sblk->stat_IfInRuleCheckerP4Hit);
680343c2aeb0SSepherosa Ziehau 	}
680443c2aeb0SSepherosa Ziehau 
680543c2aeb0SSepherosa Ziehau 	if (sblk->stat_CatchupInRuleCheckerDiscards) {
680643c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : "
680743c2aeb0SSepherosa Ziehau 			  "CatchupInRuleCheckerDiscards\n",
680843c2aeb0SSepherosa Ziehau 			  sblk->stat_CatchupInRuleCheckerDiscards);
680943c2aeb0SSepherosa Ziehau 	}
681043c2aeb0SSepherosa Ziehau 
681143c2aeb0SSepherosa Ziehau 	if (sblk->stat_CatchupInFTQDiscards) {
681243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : CatchupInFTQDiscards\n",
681343c2aeb0SSepherosa Ziehau 			  sblk->stat_CatchupInFTQDiscards);
681443c2aeb0SSepherosa Ziehau 	}
681543c2aeb0SSepherosa Ziehau 
681643c2aeb0SSepherosa Ziehau 	if (sblk->stat_CatchupInMBUFDiscards) {
681743c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : CatchupInMBUFDiscards\n",
681843c2aeb0SSepherosa Ziehau 			  sblk->stat_CatchupInMBUFDiscards);
681943c2aeb0SSepherosa Ziehau 	}
682043c2aeb0SSepherosa Ziehau 
682143c2aeb0SSepherosa Ziehau 	if (sblk->stat_CatchupInRuleCheckerP4Hit) {
682243c2aeb0SSepherosa Ziehau 		if_printf(ifp, "         0x%08X : CatchupInRuleCheckerP4Hit\n",
682343c2aeb0SSepherosa Ziehau 			  sblk->stat_CatchupInRuleCheckerP4Hit);
682443c2aeb0SSepherosa Ziehau 	}
682543c2aeb0SSepherosa Ziehau 
682643c2aeb0SSepherosa Ziehau 	if_printf(ifp,
682743c2aeb0SSepherosa Ziehau 	"----------------------------"
682843c2aeb0SSepherosa Ziehau 	"----------------"
682943c2aeb0SSepherosa Ziehau 	"----------------------------\n");
683043c2aeb0SSepherosa Ziehau }
683143c2aeb0SSepherosa Ziehau 
683243c2aeb0SSepherosa Ziehau 
683343c2aeb0SSepherosa Ziehau /****************************************************************************/
683443c2aeb0SSepherosa Ziehau /* Prints out a summary of the driver state.                                */
683543c2aeb0SSepherosa Ziehau /*                                                                          */
683643c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
683743c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
683843c2aeb0SSepherosa Ziehau /****************************************************************************/
683943c2aeb0SSepherosa Ziehau static void
684043c2aeb0SSepherosa Ziehau bce_dump_driver_state(struct bce_softc *sc)
684143c2aeb0SSepherosa Ziehau {
684243c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
684343c2aeb0SSepherosa Ziehau 	uint32_t val_hi, val_lo;
684443c2aeb0SSepherosa Ziehau 
684543c2aeb0SSepherosa Ziehau 	if_printf(ifp,
684643c2aeb0SSepherosa Ziehau 	"-----------------------------"
684743c2aeb0SSepherosa Ziehau 	" Driver State "
684843c2aeb0SSepherosa Ziehau 	"-----------------------------\n");
684943c2aeb0SSepherosa Ziehau 
685043c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc);
685143c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc);
685243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc) driver softc structure "
685343c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
685443c2aeb0SSepherosa Ziehau 
685543c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->status_block);
685643c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->status_block);
685743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->status_block) status block "
685843c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
685943c2aeb0SSepherosa Ziehau 
686043c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->stats_block);
686143c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->stats_block);
686243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->stats_block) statistics block "
686343c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
686443c2aeb0SSepherosa Ziehau 
686543c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->tx_bd_chain);
686643c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->tx_bd_chain);
686743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->tx_bd_chain) tx_bd chain "
686843c2aeb0SSepherosa Ziehau 		  "virtual adddress\n", val_hi, val_lo);
686943c2aeb0SSepherosa Ziehau 
687043c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->rx_bd_chain);
687143c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->rx_bd_chain);
687243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->rx_bd_chain) rx_bd chain "
687343c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
687443c2aeb0SSepherosa Ziehau 
687543c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->tx_mbuf_ptr);
687643c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->tx_mbuf_ptr);
687743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->tx_mbuf_ptr) tx mbuf chain "
687843c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
687943c2aeb0SSepherosa Ziehau 
688043c2aeb0SSepherosa Ziehau 	val_hi = BCE_ADDR_HI(sc->rx_mbuf_ptr);
688143c2aeb0SSepherosa Ziehau 	val_lo = BCE_ADDR_LO(sc->rx_mbuf_ptr);
688243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X:%08X - (sc->rx_mbuf_ptr) rx mbuf chain "
688343c2aeb0SSepherosa Ziehau 		  "virtual address\n", val_hi, val_lo);
688443c2aeb0SSepherosa Ziehau 
688543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->interrupts_generated) "
688643c2aeb0SSepherosa Ziehau 		  "h/w intrs\n", sc->interrupts_generated);
688743c2aeb0SSepherosa Ziehau 
688843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->rx_interrupts) "
688943c2aeb0SSepherosa Ziehau 		  "rx interrupts handled\n", sc->rx_interrupts);
689043c2aeb0SSepherosa Ziehau 
689143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->tx_interrupts) "
689243c2aeb0SSepherosa Ziehau 		  "tx interrupts handled\n", sc->tx_interrupts);
689343c2aeb0SSepherosa Ziehau 
689443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->last_status_idx) "
689543c2aeb0SSepherosa Ziehau 		  "status block index\n", sc->last_status_idx);
689643c2aeb0SSepherosa Ziehau 
689743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "     0x%04X(0x%04X) - (sc->tx_prod) "
689843c2aeb0SSepherosa Ziehau 		  "tx producer index\n",
689943c2aeb0SSepherosa Ziehau 		  sc->tx_prod, (uint16_t)TX_CHAIN_IDX(sc->tx_prod));
690043c2aeb0SSepherosa Ziehau 
690143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "     0x%04X(0x%04X) - (sc->tx_cons) "
690243c2aeb0SSepherosa Ziehau 		  "tx consumer index\n",
690343c2aeb0SSepherosa Ziehau 		  sc->tx_cons, (uint16_t)TX_CHAIN_IDX(sc->tx_cons));
690443c2aeb0SSepherosa Ziehau 
690543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->tx_prod_bseq) "
690643c2aeb0SSepherosa Ziehau 		  "tx producer bseq index\n", sc->tx_prod_bseq);
690743c2aeb0SSepherosa Ziehau 
690843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "     0x%04X(0x%04X) - (sc->rx_prod) "
690943c2aeb0SSepherosa Ziehau 		  "rx producer index\n",
691043c2aeb0SSepherosa Ziehau 		  sc->rx_prod, (uint16_t)RX_CHAIN_IDX(sc->rx_prod));
691143c2aeb0SSepherosa Ziehau 
691243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "     0x%04X(0x%04X) - (sc->rx_cons) "
691343c2aeb0SSepherosa Ziehau 		  "rx consumer index\n",
691443c2aeb0SSepherosa Ziehau 		  sc->rx_cons, (uint16_t)RX_CHAIN_IDX(sc->rx_cons));
691543c2aeb0SSepherosa Ziehau 
691643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->rx_prod_bseq) "
691743c2aeb0SSepherosa Ziehau 		  "rx producer bseq index\n", sc->rx_prod_bseq);
691843c2aeb0SSepherosa Ziehau 
691943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->rx_mbuf_alloc) "
692043c2aeb0SSepherosa Ziehau 		  "rx mbufs allocated\n", sc->rx_mbuf_alloc);
692143c2aeb0SSepherosa Ziehau 
692243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->free_rx_bd) "
692343c2aeb0SSepherosa Ziehau 		  "free rx_bd's\n", sc->free_rx_bd);
692443c2aeb0SSepherosa Ziehau 
692543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X/%08X - (sc->rx_low_watermark) rx "
692643c2aeb0SSepherosa Ziehau 		  "low watermark\n", sc->rx_low_watermark, sc->max_rx_bd);
692743c2aeb0SSepherosa Ziehau 
692843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->txmbuf_alloc) "
692943c2aeb0SSepherosa Ziehau 		  "tx mbufs allocated\n", sc->tx_mbuf_alloc);
693043c2aeb0SSepherosa Ziehau 
693143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->rx_mbuf_alloc) "
693243c2aeb0SSepherosa Ziehau 		  "rx mbufs allocated\n", sc->rx_mbuf_alloc);
693343c2aeb0SSepherosa Ziehau 
693443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->used_tx_bd) used tx_bd's\n",
693543c2aeb0SSepherosa Ziehau 		  sc->used_tx_bd);
693643c2aeb0SSepherosa Ziehau 
693743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X/%08X - (sc->tx_hi_watermark) tx hi watermark\n",
693843c2aeb0SSepherosa Ziehau 		  sc->tx_hi_watermark, sc->max_tx_bd);
693943c2aeb0SSepherosa Ziehau 
694043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "         0x%08X - (sc->mbuf_alloc_failed) "
694143c2aeb0SSepherosa Ziehau 		  "failed mbuf alloc\n", sc->mbuf_alloc_failed);
694243c2aeb0SSepherosa Ziehau 
694343c2aeb0SSepherosa Ziehau 	if_printf(ifp,
694443c2aeb0SSepherosa Ziehau 	"----------------------------"
694543c2aeb0SSepherosa Ziehau 	"----------------"
694643c2aeb0SSepherosa Ziehau 	"----------------------------\n");
694743c2aeb0SSepherosa Ziehau }
694843c2aeb0SSepherosa Ziehau 
694943c2aeb0SSepherosa Ziehau 
695043c2aeb0SSepherosa Ziehau /****************************************************************************/
695143c2aeb0SSepherosa Ziehau /* Prints out the hardware state through a summary of important registers,  */
695243c2aeb0SSepherosa Ziehau /* followed by a complete register dump.                                    */
695343c2aeb0SSepherosa Ziehau /*                                                                          */
695443c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
695543c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
695643c2aeb0SSepherosa Ziehau /****************************************************************************/
695743c2aeb0SSepherosa Ziehau static void
695843c2aeb0SSepherosa Ziehau bce_dump_hw_state(struct bce_softc *sc)
695943c2aeb0SSepherosa Ziehau {
696043c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
696143c2aeb0SSepherosa Ziehau 	uint32_t val1;
696243c2aeb0SSepherosa Ziehau 	int i;
696343c2aeb0SSepherosa Ziehau 
696443c2aeb0SSepherosa Ziehau 	if_printf(ifp,
696543c2aeb0SSepherosa Ziehau 	"----------------------------"
696643c2aeb0SSepherosa Ziehau 	" Hardware State "
696743c2aeb0SSepherosa Ziehau 	"----------------------------\n");
696843c2aeb0SSepherosa Ziehau 
696943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - bootcode version\n", sc->bce_fw_ver);
697043c2aeb0SSepherosa Ziehau 
697143c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_MISC_ENABLE_STATUS_BITS);
697243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) misc_enable_status_bits\n",
697343c2aeb0SSepherosa Ziehau 		  val1, BCE_MISC_ENABLE_STATUS_BITS);
697443c2aeb0SSepherosa Ziehau 
697543c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_DMA_STATUS);
697643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) dma_status\n", val1, BCE_DMA_STATUS);
697743c2aeb0SSepherosa Ziehau 
697843c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_CTX_STATUS);
697943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) ctx_status\n", val1, BCE_CTX_STATUS);
698043c2aeb0SSepherosa Ziehau 
698143c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_EMAC_STATUS);
698243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) emac_status\n",
698343c2aeb0SSepherosa Ziehau 		  val1, BCE_EMAC_STATUS);
698443c2aeb0SSepherosa Ziehau 
698543c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_RPM_STATUS);
698643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) rpm_status\n", val1, BCE_RPM_STATUS);
698743c2aeb0SSepherosa Ziehau 
698843c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_TBDR_STATUS);
698943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) tbdr_status\n",
699043c2aeb0SSepherosa Ziehau 		  val1, BCE_TBDR_STATUS);
699143c2aeb0SSepherosa Ziehau 
699243c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_TDMA_STATUS);
699343c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%04X) tdma_status\n",
699443c2aeb0SSepherosa Ziehau 		  val1, BCE_TDMA_STATUS);
699543c2aeb0SSepherosa Ziehau 
699643c2aeb0SSepherosa Ziehau 	val1 = REG_RD(sc, BCE_HC_STATUS);
699743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) hc_status\n", val1, BCE_HC_STATUS);
699843c2aeb0SSepherosa Ziehau 
699943c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TXP_CPU_STATE);
700043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) txp_cpu_state\n",
700143c2aeb0SSepherosa Ziehau 		  val1, BCE_TXP_CPU_STATE);
700243c2aeb0SSepherosa Ziehau 
700343c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TPAT_CPU_STATE);
700443c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) tpat_cpu_state\n",
700543c2aeb0SSepherosa Ziehau 		  val1, BCE_TPAT_CPU_STATE);
700643c2aeb0SSepherosa Ziehau 
700743c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_RXP_CPU_STATE);
700843c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) rxp_cpu_state\n",
700943c2aeb0SSepherosa Ziehau 		  val1, BCE_RXP_CPU_STATE);
701043c2aeb0SSepherosa Ziehau 
701143c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_COM_CPU_STATE);
701243c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) com_cpu_state\n",
701343c2aeb0SSepherosa Ziehau 		  val1, BCE_COM_CPU_STATE);
701443c2aeb0SSepherosa Ziehau 
701543c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_MCP_CPU_STATE);
701643c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) mcp_cpu_state\n",
701743c2aeb0SSepherosa Ziehau 		  val1, BCE_MCP_CPU_STATE);
701843c2aeb0SSepherosa Ziehau 
701943c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_CP_CPU_STATE);
702043c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) cp_cpu_state\n",
702143c2aeb0SSepherosa Ziehau 		  val1, BCE_CP_CPU_STATE);
702243c2aeb0SSepherosa Ziehau 
702343c2aeb0SSepherosa Ziehau 	if_printf(ifp,
702443c2aeb0SSepherosa Ziehau 	"----------------------------"
702543c2aeb0SSepherosa Ziehau 	"----------------"
702643c2aeb0SSepherosa Ziehau 	"----------------------------\n");
702743c2aeb0SSepherosa Ziehau 
702843c2aeb0SSepherosa Ziehau 	if_printf(ifp,
702943c2aeb0SSepherosa Ziehau 	"----------------------------"
703043c2aeb0SSepherosa Ziehau 	" Register  Dump "
703143c2aeb0SSepherosa Ziehau 	"----------------------------\n");
703243c2aeb0SSepherosa Ziehau 
703343c2aeb0SSepherosa Ziehau 	for (i = 0x400; i < 0x8000; i += 0x10) {
703443c2aeb0SSepherosa Ziehau 		if_printf(ifp, "0x%04X: 0x%08X 0x%08X 0x%08X 0x%08X\n", i,
703543c2aeb0SSepherosa Ziehau 			  REG_RD(sc, i),
703643c2aeb0SSepherosa Ziehau 			  REG_RD(sc, i + 0x4),
703743c2aeb0SSepherosa Ziehau 			  REG_RD(sc, i + 0x8),
703843c2aeb0SSepherosa Ziehau 			  REG_RD(sc, i + 0xc));
703943c2aeb0SSepherosa Ziehau 	}
704043c2aeb0SSepherosa Ziehau 
704143c2aeb0SSepherosa Ziehau 	if_printf(ifp,
704243c2aeb0SSepherosa Ziehau 	"----------------------------"
704343c2aeb0SSepherosa Ziehau 	"----------------"
704443c2aeb0SSepherosa Ziehau 	"----------------------------\n");
704543c2aeb0SSepherosa Ziehau }
704643c2aeb0SSepherosa Ziehau 
704743c2aeb0SSepherosa Ziehau 
704843c2aeb0SSepherosa Ziehau /****************************************************************************/
704943c2aeb0SSepherosa Ziehau /* Prints out the TXP state.                                                */
705043c2aeb0SSepherosa Ziehau /*                                                                          */
705143c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
705243c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
705343c2aeb0SSepherosa Ziehau /****************************************************************************/
705443c2aeb0SSepherosa Ziehau static void
705543c2aeb0SSepherosa Ziehau bce_dump_txp_state(struct bce_softc *sc)
705643c2aeb0SSepherosa Ziehau {
705743c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
705843c2aeb0SSepherosa Ziehau 	uint32_t val1;
705943c2aeb0SSepherosa Ziehau 	int i;
706043c2aeb0SSepherosa Ziehau 
706143c2aeb0SSepherosa Ziehau 	if_printf(ifp,
706243c2aeb0SSepherosa Ziehau 	"----------------------------"
706343c2aeb0SSepherosa Ziehau 	"   TXP  State   "
706443c2aeb0SSepherosa Ziehau 	"----------------------------\n");
706543c2aeb0SSepherosa Ziehau 
706643c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TXP_CPU_MODE);
706743c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) txp_cpu_mode\n",
706843c2aeb0SSepherosa Ziehau 		  val1, BCE_TXP_CPU_MODE);
706943c2aeb0SSepherosa Ziehau 
707043c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TXP_CPU_STATE);
707143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) txp_cpu_state\n",
707243c2aeb0SSepherosa Ziehau 		  val1, BCE_TXP_CPU_STATE);
707343c2aeb0SSepherosa Ziehau 
707443c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TXP_CPU_EVENT_MASK);
707543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) txp_cpu_event_mask\n",
707643c2aeb0SSepherosa Ziehau 		  val1, BCE_TXP_CPU_EVENT_MASK);
707743c2aeb0SSepherosa Ziehau 
707843c2aeb0SSepherosa Ziehau 	if_printf(ifp,
707943c2aeb0SSepherosa Ziehau 	"----------------------------"
708043c2aeb0SSepherosa Ziehau 	" Register  Dump "
708143c2aeb0SSepherosa Ziehau 	"----------------------------\n");
708243c2aeb0SSepherosa Ziehau 
708343c2aeb0SSepherosa Ziehau 	for (i = BCE_TXP_CPU_MODE; i < 0x68000; i += 0x10) {
708443c2aeb0SSepherosa Ziehau 		/* Skip the big blank spaces */
708543c2aeb0SSepherosa Ziehau 		if (i < 0x454000 && i > 0x5ffff) {
708643c2aeb0SSepherosa Ziehau 			if_printf(ifp, "0x%04X: "
708743c2aeb0SSepherosa Ziehau 				  "0x%08X 0x%08X 0x%08X 0x%08X\n", i,
708843c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i),
708943c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x4),
709043c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x8),
709143c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0xc));
709243c2aeb0SSepherosa Ziehau 		}
709343c2aeb0SSepherosa Ziehau 	}
709443c2aeb0SSepherosa Ziehau 
709543c2aeb0SSepherosa Ziehau 	if_printf(ifp,
709643c2aeb0SSepherosa Ziehau 	"----------------------------"
709743c2aeb0SSepherosa Ziehau 	"----------------"
709843c2aeb0SSepherosa Ziehau 	"----------------------------\n");
709943c2aeb0SSepherosa Ziehau }
710043c2aeb0SSepherosa Ziehau 
710143c2aeb0SSepherosa Ziehau 
710243c2aeb0SSepherosa Ziehau /****************************************************************************/
710343c2aeb0SSepherosa Ziehau /* Prints out the RXP state.                                                */
710443c2aeb0SSepherosa Ziehau /*                                                                          */
710543c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
710643c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
710743c2aeb0SSepherosa Ziehau /****************************************************************************/
710843c2aeb0SSepherosa Ziehau static void
710943c2aeb0SSepherosa Ziehau bce_dump_rxp_state(struct bce_softc *sc)
711043c2aeb0SSepherosa Ziehau {
711143c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
711243c2aeb0SSepherosa Ziehau 	uint32_t val1;
711343c2aeb0SSepherosa Ziehau 	int i;
711443c2aeb0SSepherosa Ziehau 
711543c2aeb0SSepherosa Ziehau 	if_printf(ifp,
711643c2aeb0SSepherosa Ziehau 	"----------------------------"
711743c2aeb0SSepherosa Ziehau 	"   RXP  State   "
711843c2aeb0SSepherosa Ziehau 	"----------------------------\n");
711943c2aeb0SSepherosa Ziehau 
712043c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_RXP_CPU_MODE);
712143c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) rxp_cpu_mode\n",
712243c2aeb0SSepherosa Ziehau 		  val1, BCE_RXP_CPU_MODE);
712343c2aeb0SSepherosa Ziehau 
712443c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_RXP_CPU_STATE);
712543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) rxp_cpu_state\n",
712643c2aeb0SSepherosa Ziehau 		  val1, BCE_RXP_CPU_STATE);
712743c2aeb0SSepherosa Ziehau 
712843c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_RXP_CPU_EVENT_MASK);
712943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) rxp_cpu_event_mask\n",
713043c2aeb0SSepherosa Ziehau 		  val1, BCE_RXP_CPU_EVENT_MASK);
713143c2aeb0SSepherosa Ziehau 
713243c2aeb0SSepherosa Ziehau 	if_printf(ifp,
713343c2aeb0SSepherosa Ziehau 	"----------------------------"
713443c2aeb0SSepherosa Ziehau 	" Register  Dump "
713543c2aeb0SSepherosa Ziehau 	"----------------------------\n");
713643c2aeb0SSepherosa Ziehau 
713743c2aeb0SSepherosa Ziehau 	for (i = BCE_RXP_CPU_MODE; i < 0xe8fff; i += 0x10) {
713843c2aeb0SSepherosa Ziehau 		/* Skip the big blank sapces */
713943c2aeb0SSepherosa Ziehau 		if (i < 0xc5400 && i > 0xdffff) {
714043c2aeb0SSepherosa Ziehau 			if_printf(ifp, "0x%04X: "
714143c2aeb0SSepherosa Ziehau 				  "0x%08X 0x%08X 0x%08X 0x%08X\n", i,
714243c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i),
714343c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x4),
714443c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x8),
714543c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0xc));
714643c2aeb0SSepherosa Ziehau 		}
714743c2aeb0SSepherosa Ziehau 	}
714843c2aeb0SSepherosa Ziehau 
714943c2aeb0SSepherosa Ziehau 	if_printf(ifp,
715043c2aeb0SSepherosa Ziehau 	"----------------------------"
715143c2aeb0SSepherosa Ziehau 	"----------------"
715243c2aeb0SSepherosa Ziehau 	"----------------------------\n");
715343c2aeb0SSepherosa Ziehau }
715443c2aeb0SSepherosa Ziehau 
715543c2aeb0SSepherosa Ziehau 
715643c2aeb0SSepherosa Ziehau /****************************************************************************/
715743c2aeb0SSepherosa Ziehau /* Prints out the TPAT state.                                               */
715843c2aeb0SSepherosa Ziehau /*                                                                          */
715943c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
716043c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
716143c2aeb0SSepherosa Ziehau /****************************************************************************/
716243c2aeb0SSepherosa Ziehau static void
716343c2aeb0SSepherosa Ziehau bce_dump_tpat_state(struct bce_softc *sc)
716443c2aeb0SSepherosa Ziehau {
716543c2aeb0SSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
716643c2aeb0SSepherosa Ziehau 	uint32_t val1;
716743c2aeb0SSepherosa Ziehau 	int i;
716843c2aeb0SSepherosa Ziehau 
716943c2aeb0SSepherosa Ziehau 	if_printf(ifp,
717043c2aeb0SSepherosa Ziehau 	"----------------------------"
717143c2aeb0SSepherosa Ziehau 	"   TPAT State   "
717243c2aeb0SSepherosa Ziehau 	"----------------------------\n");
717343c2aeb0SSepherosa Ziehau 
717443c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TPAT_CPU_MODE);
717543c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) tpat_cpu_mode\n",
717643c2aeb0SSepherosa Ziehau 		  val1, BCE_TPAT_CPU_MODE);
717743c2aeb0SSepherosa Ziehau 
717843c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TPAT_CPU_STATE);
717943c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) tpat_cpu_state\n",
718043c2aeb0SSepherosa Ziehau 		  val1, BCE_TPAT_CPU_STATE);
718143c2aeb0SSepherosa Ziehau 
718243c2aeb0SSepherosa Ziehau 	val1 = REG_RD_IND(sc, BCE_TPAT_CPU_EVENT_MASK);
718343c2aeb0SSepherosa Ziehau 	if_printf(ifp, "0x%08X - (0x%06X) tpat_cpu_event_mask\n",
718443c2aeb0SSepherosa Ziehau 		  val1, BCE_TPAT_CPU_EVENT_MASK);
718543c2aeb0SSepherosa Ziehau 
718643c2aeb0SSepherosa Ziehau 	if_printf(ifp,
718743c2aeb0SSepherosa Ziehau 	"----------------------------"
718843c2aeb0SSepherosa Ziehau 	" Register  Dump "
718943c2aeb0SSepherosa Ziehau 	"----------------------------\n");
719043c2aeb0SSepherosa Ziehau 
719143c2aeb0SSepherosa Ziehau 	for (i = BCE_TPAT_CPU_MODE; i < 0xa3fff; i += 0x10) {
719243c2aeb0SSepherosa Ziehau 		/* Skip the big blank spaces */
719343c2aeb0SSepherosa Ziehau 		if (i < 0x854000 && i > 0x9ffff) {
719443c2aeb0SSepherosa Ziehau 			if_printf(ifp, "0x%04X: "
719543c2aeb0SSepherosa Ziehau 				  "0x%08X 0x%08X 0x%08X 0x%08X\n", i,
719643c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i),
719743c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x4),
719843c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0x8),
719943c2aeb0SSepherosa Ziehau 				  REG_RD_IND(sc, i + 0xc));
720043c2aeb0SSepherosa Ziehau 		}
720143c2aeb0SSepherosa Ziehau 	}
720243c2aeb0SSepherosa Ziehau 
720343c2aeb0SSepherosa Ziehau 	if_printf(ifp,
720443c2aeb0SSepherosa Ziehau 	"----------------------------"
720543c2aeb0SSepherosa Ziehau 	"----------------"
720643c2aeb0SSepherosa Ziehau 	"----------------------------\n");
720743c2aeb0SSepherosa Ziehau }
720843c2aeb0SSepherosa Ziehau 
720943c2aeb0SSepherosa Ziehau 
721043c2aeb0SSepherosa Ziehau /****************************************************************************/
721143c2aeb0SSepherosa Ziehau /* Prints out the driver state and then enters the debugger.                */
721243c2aeb0SSepherosa Ziehau /*                                                                          */
721343c2aeb0SSepherosa Ziehau /* Returns:                                                                 */
721443c2aeb0SSepherosa Ziehau /*   Nothing.                                                               */
721543c2aeb0SSepherosa Ziehau /****************************************************************************/
721643c2aeb0SSepherosa Ziehau static void
721743c2aeb0SSepherosa Ziehau bce_breakpoint(struct bce_softc *sc)
721843c2aeb0SSepherosa Ziehau {
721943c2aeb0SSepherosa Ziehau #if 0
722043c2aeb0SSepherosa Ziehau 	bce_freeze_controller(sc);
722143c2aeb0SSepherosa Ziehau #endif
722243c2aeb0SSepherosa Ziehau 
722343c2aeb0SSepherosa Ziehau 	bce_dump_driver_state(sc);
722443c2aeb0SSepherosa Ziehau 	bce_dump_status_block(sc);
722543c2aeb0SSepherosa Ziehau 	bce_dump_tx_chain(sc, 0, TOTAL_TX_BD);
722643c2aeb0SSepherosa Ziehau 	bce_dump_hw_state(sc);
722743c2aeb0SSepherosa Ziehau 	bce_dump_txp_state(sc);
722843c2aeb0SSepherosa Ziehau 
722943c2aeb0SSepherosa Ziehau #if 0
723043c2aeb0SSepherosa Ziehau 	bce_unfreeze_controller(sc);
723143c2aeb0SSepherosa Ziehau #endif
723243c2aeb0SSepherosa Ziehau 
723343c2aeb0SSepherosa Ziehau 	/* Call the debugger. */
723443c2aeb0SSepherosa Ziehau 	breakpoint();
723543c2aeb0SSepherosa Ziehau }
723643c2aeb0SSepherosa Ziehau 
723743c2aeb0SSepherosa Ziehau #endif	/* BCE_DEBUG */
7238bdeb8fffSSepherosa Ziehau 
7239bdeb8fffSSepherosa Ziehau static int
7240bdeb8fffSSepherosa Ziehau bce_sysctl_tx_bds_int(SYSCTL_HANDLER_ARGS)
7241bdeb8fffSSepherosa Ziehau {
7242bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7243bdeb8fffSSepherosa Ziehau 
7244bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7245bdeb8fffSSepherosa Ziehau 			&sc->bce_tx_quick_cons_trip_int,
7246bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_TX_BDS_INT);
7247bdeb8fffSSepherosa Ziehau }
7248bdeb8fffSSepherosa Ziehau 
7249bdeb8fffSSepherosa Ziehau static int
7250bdeb8fffSSepherosa Ziehau bce_sysctl_tx_bds(SYSCTL_HANDLER_ARGS)
7251bdeb8fffSSepherosa Ziehau {
7252bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7253bdeb8fffSSepherosa Ziehau 
7254bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7255bdeb8fffSSepherosa Ziehau 			&sc->bce_tx_quick_cons_trip,
7256bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_TX_BDS);
7257bdeb8fffSSepherosa Ziehau }
7258bdeb8fffSSepherosa Ziehau 
7259bdeb8fffSSepherosa Ziehau static int
7260bdeb8fffSSepherosa Ziehau bce_sysctl_tx_ticks_int(SYSCTL_HANDLER_ARGS)
7261bdeb8fffSSepherosa Ziehau {
7262bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7263bdeb8fffSSepherosa Ziehau 
7264bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7265bdeb8fffSSepherosa Ziehau 			&sc->bce_tx_ticks_int,
7266bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_TX_TICKS_INT);
7267bdeb8fffSSepherosa Ziehau }
7268bdeb8fffSSepherosa Ziehau 
7269bdeb8fffSSepherosa Ziehau static int
7270bdeb8fffSSepherosa Ziehau bce_sysctl_tx_ticks(SYSCTL_HANDLER_ARGS)
7271bdeb8fffSSepherosa Ziehau {
7272bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7273bdeb8fffSSepherosa Ziehau 
7274bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7275bdeb8fffSSepherosa Ziehau 			&sc->bce_tx_ticks,
7276bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_TX_TICKS);
7277bdeb8fffSSepherosa Ziehau }
7278bdeb8fffSSepherosa Ziehau 
7279bdeb8fffSSepherosa Ziehau static int
7280bdeb8fffSSepherosa Ziehau bce_sysctl_rx_bds_int(SYSCTL_HANDLER_ARGS)
7281bdeb8fffSSepherosa Ziehau {
7282bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7283bdeb8fffSSepherosa Ziehau 
7284bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7285bdeb8fffSSepherosa Ziehau 			&sc->bce_rx_quick_cons_trip_int,
7286bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_RX_BDS_INT);
7287bdeb8fffSSepherosa Ziehau }
7288bdeb8fffSSepherosa Ziehau 
7289bdeb8fffSSepherosa Ziehau static int
7290bdeb8fffSSepherosa Ziehau bce_sysctl_rx_bds(SYSCTL_HANDLER_ARGS)
7291bdeb8fffSSepherosa Ziehau {
7292bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7293bdeb8fffSSepherosa Ziehau 
7294bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7295bdeb8fffSSepherosa Ziehau 			&sc->bce_rx_quick_cons_trip,
7296bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_RX_BDS);
7297bdeb8fffSSepherosa Ziehau }
7298bdeb8fffSSepherosa Ziehau 
7299bdeb8fffSSepherosa Ziehau static int
7300bdeb8fffSSepherosa Ziehau bce_sysctl_rx_ticks_int(SYSCTL_HANDLER_ARGS)
7301bdeb8fffSSepherosa Ziehau {
7302bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7303bdeb8fffSSepherosa Ziehau 
7304bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7305bdeb8fffSSepherosa Ziehau 			&sc->bce_rx_ticks_int,
7306bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_RX_TICKS_INT);
7307bdeb8fffSSepherosa Ziehau }
7308bdeb8fffSSepherosa Ziehau 
7309bdeb8fffSSepherosa Ziehau static int
7310bdeb8fffSSepherosa Ziehau bce_sysctl_rx_ticks(SYSCTL_HANDLER_ARGS)
7311bdeb8fffSSepherosa Ziehau {
7312bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7313bdeb8fffSSepherosa Ziehau 
7314bdeb8fffSSepherosa Ziehau 	return bce_sysctl_coal_change(oidp, arg1, arg2, req,
7315bdeb8fffSSepherosa Ziehau 			&sc->bce_rx_ticks,
7316bdeb8fffSSepherosa Ziehau 			BCE_COALMASK_RX_TICKS);
7317bdeb8fffSSepherosa Ziehau }
7318bdeb8fffSSepherosa Ziehau 
7319bdeb8fffSSepherosa Ziehau static int
7320bdeb8fffSSepherosa Ziehau bce_sysctl_coal_change(SYSCTL_HANDLER_ARGS, uint32_t *coal,
7321bdeb8fffSSepherosa Ziehau 		       uint32_t coalchg_mask)
7322bdeb8fffSSepherosa Ziehau {
7323bdeb8fffSSepherosa Ziehau 	struct bce_softc *sc = arg1;
7324bdeb8fffSSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
7325bdeb8fffSSepherosa Ziehau 	int error = 0, v;
7326bdeb8fffSSepherosa Ziehau 
7327bdeb8fffSSepherosa Ziehau 	lwkt_serialize_enter(ifp->if_serializer);
7328bdeb8fffSSepherosa Ziehau 
7329bdeb8fffSSepherosa Ziehau 	v = *coal;
7330bdeb8fffSSepherosa Ziehau 	error = sysctl_handle_int(oidp, &v, 0, req);
7331bdeb8fffSSepherosa Ziehau 	if (!error && req->newptr != NULL) {
7332bdeb8fffSSepherosa Ziehau 		if (v < 0) {
7333bdeb8fffSSepherosa Ziehau 			error = EINVAL;
7334bdeb8fffSSepherosa Ziehau 		} else {
7335bdeb8fffSSepherosa Ziehau 			*coal = v;
7336bdeb8fffSSepherosa Ziehau 			sc->bce_coalchg_mask |= coalchg_mask;
7337bdeb8fffSSepherosa Ziehau 		}
7338bdeb8fffSSepherosa Ziehau 	}
7339bdeb8fffSSepherosa Ziehau 
7340bdeb8fffSSepherosa Ziehau 	lwkt_serialize_exit(ifp->if_serializer);
7341bdeb8fffSSepherosa Ziehau 	return error;
7342bdeb8fffSSepherosa Ziehau }
7343bdeb8fffSSepherosa Ziehau 
7344bdeb8fffSSepherosa Ziehau static void
7345bdeb8fffSSepherosa Ziehau bce_coal_change(struct bce_softc *sc)
7346bdeb8fffSSepherosa Ziehau {
7347bdeb8fffSSepherosa Ziehau 	struct ifnet *ifp = &sc->arpcom.ac_if;
7348bdeb8fffSSepherosa Ziehau 
7349bdeb8fffSSepherosa Ziehau 	ASSERT_SERIALIZED(ifp->if_serializer);
7350bdeb8fffSSepherosa Ziehau 
7351bdeb8fffSSepherosa Ziehau 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
7352bdeb8fffSSepherosa Ziehau 		sc->bce_coalchg_mask = 0;
7353bdeb8fffSSepherosa Ziehau 		return;
7354bdeb8fffSSepherosa Ziehau 	}
7355bdeb8fffSSepherosa Ziehau 
7356bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask &
7357bdeb8fffSSepherosa Ziehau 	    (BCE_COALMASK_TX_BDS | BCE_COALMASK_TX_BDS_INT)) {
7358bdeb8fffSSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
7359bdeb8fffSSepherosa Ziehau 		       (sc->bce_tx_quick_cons_trip_int << 16) |
7360bdeb8fffSSepherosa Ziehau 		       sc->bce_tx_quick_cons_trip);
7361bdeb8fffSSepherosa Ziehau 		if (bootverbose) {
7362bdeb8fffSSepherosa Ziehau 			if_printf(ifp, "tx_bds %u, tx_bds_int %u\n",
7363bdeb8fffSSepherosa Ziehau 				  sc->bce_tx_quick_cons_trip,
7364bdeb8fffSSepherosa Ziehau 				  sc->bce_tx_quick_cons_trip_int);
7365bdeb8fffSSepherosa Ziehau 		}
7366bdeb8fffSSepherosa Ziehau 	}
7367bdeb8fffSSepherosa Ziehau 
7368bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask &
7369bdeb8fffSSepherosa Ziehau 	    (BCE_COALMASK_TX_TICKS | BCE_COALMASK_TX_TICKS_INT)) {
7370bdeb8fffSSepherosa Ziehau 		REG_WR(sc, BCE_HC_TX_TICKS,
7371bdeb8fffSSepherosa Ziehau 		       (sc->bce_tx_ticks_int << 16) | sc->bce_tx_ticks);
7372bdeb8fffSSepherosa Ziehau 		if (bootverbose) {
7373bdeb8fffSSepherosa Ziehau 			if_printf(ifp, "tx_ticks %u, tx_ticks_int %u\n",
7374bdeb8fffSSepherosa Ziehau 				  sc->bce_tx_ticks, sc->bce_tx_ticks_int);
7375bdeb8fffSSepherosa Ziehau 		}
7376bdeb8fffSSepherosa Ziehau 	}
7377bdeb8fffSSepherosa Ziehau 
7378bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask &
7379bdeb8fffSSepherosa Ziehau 	    (BCE_COALMASK_RX_BDS | BCE_COALMASK_RX_BDS_INT)) {
7380bdeb8fffSSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
7381bdeb8fffSSepherosa Ziehau 		       (sc->bce_rx_quick_cons_trip_int << 16) |
7382bdeb8fffSSepherosa Ziehau 		       sc->bce_rx_quick_cons_trip);
7383bdeb8fffSSepherosa Ziehau 		if (bootverbose) {
7384bdeb8fffSSepherosa Ziehau 			if_printf(ifp, "rx_bds %u, rx_bds_int %u\n",
7385bdeb8fffSSepherosa Ziehau 				  sc->bce_rx_quick_cons_trip,
7386bdeb8fffSSepherosa Ziehau 				  sc->bce_rx_quick_cons_trip_int);
7387bdeb8fffSSepherosa Ziehau 		}
7388bdeb8fffSSepherosa Ziehau 	}
7389bdeb8fffSSepherosa Ziehau 
7390bdeb8fffSSepherosa Ziehau 	if (sc->bce_coalchg_mask &
7391bdeb8fffSSepherosa Ziehau 	    (BCE_COALMASK_RX_TICKS | BCE_COALMASK_RX_TICKS_INT)) {
7392bdeb8fffSSepherosa Ziehau 		REG_WR(sc, BCE_HC_RX_TICKS,
7393bdeb8fffSSepherosa Ziehau 		       (sc->bce_rx_ticks_int << 16) | sc->bce_rx_ticks);
7394bdeb8fffSSepherosa Ziehau 		if (bootverbose) {
7395bdeb8fffSSepherosa Ziehau 			if_printf(ifp, "rx_ticks %u, rx_ticks_int %u\n",
7396bdeb8fffSSepherosa Ziehau 				  sc->bce_rx_ticks, sc->bce_rx_ticks_int);
7397bdeb8fffSSepherosa Ziehau 		}
7398bdeb8fffSSepherosa Ziehau 	}
7399bdeb8fffSSepherosa Ziehau 
7400bdeb8fffSSepherosa Ziehau 	sc->bce_coalchg_mask = 0;
7401bdeb8fffSSepherosa Ziehau }
7402