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