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