if_bce.c revision 157724
1157642Sps/*- 2157642Sps * Copyright (c) 2006 Broadcom Corporation 3157642Sps * David Christensen <davidch@broadcom.com>. All rights reserved. 4157642Sps * 5157642Sps * Redistribution and use in source and binary forms, with or without 6157642Sps * modification, are permitted provided that the following conditions 7157642Sps * are met: 8157642Sps * 9157642Sps * 1. Redistributions of source code must retain the above copyright 10157642Sps * notice, this list of conditions and the following disclaimer. 11157642Sps * 2. Redistributions in binary form must reproduce the above copyright 12157642Sps * notice, this list of conditions and the following disclaimer in the 13157642Sps * documentation and/or other materials provided with the distribution. 14157642Sps * 3. Neither the name of Broadcom Corporation nor the name of its contributors 15157642Sps * may be used to endorse or promote products derived from this software 16157642Sps * without specific prior written consent. 17157642Sps * 18157642Sps * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' 19157642Sps * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20157642Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21157642Sps * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22157642Sps * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23157642Sps * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24157642Sps * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25157642Sps * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26157642Sps * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27157642Sps * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28157642Sps * THE POSSIBILITY OF SUCH DAMAGE. 29157642Sps */ 30157642Sps 31157642Sps#include <sys/cdefs.h> 32157642Sps__FBSDID("$FreeBSD: head/sys/dev/bce/if_bce.c 157724 2006-04-13 14:12:26Z ru $"); 33157642Sps 34157642Sps/* 35157642Sps * The following controllers are supported by this driver: 36157642Sps * BCM5706C A2, A3 37157642Sps * BCM5708C B1 38157642Sps * 39157642Sps * The following controllers are not supported by this driver: 40157642Sps * (These are not "Production" versions of the controller.) 41157642Sps * 42157642Sps * BCM5706C A0, A1 43157642Sps * BCM5706S A0, A1, A2, A3 44157642Sps * BCM5708C A0, B0 45157642Sps * BCM5708S A0, B0, B1 46157642Sps */ 47157642Sps 48157643Sps#include "opt_bce.h" 49157643Sps 50157642Sps#include <dev/bce/if_bcereg.h> 51157642Sps#include <dev/bce/if_bcefw.h> 52157642Sps 53157642Sps/****************************************************************************/ 54157642Sps/* BCE Driver Version */ 55157642Sps/****************************************************************************/ 56157642Spschar bce_driver_version[] = "v0.9.5"; 57157642Sps 58157642Sps 59157642Sps/****************************************************************************/ 60157642Sps/* BCE Debug Options */ 61157642Sps/****************************************************************************/ 62157642Sps#ifdef BCE_DEBUG 63157642Sps u32 bce_debug = BCE_WARN; 64157642Sps 65157642Sps /* 0 = Never */ 66157642Sps /* 1 = 1 in 2,147,483,648 */ 67157642Sps /* 256 = 1 in 8,388,608 */ 68157642Sps /* 2048 = 1 in 1,048,576 */ 69157642Sps /* 65536 = 1 in 32,768 */ 70157642Sps /* 1048576 = 1 in 2,048 */ 71157642Sps /* 268435456 = 1 in 8 */ 72157642Sps /* 536870912 = 1 in 4 */ 73157642Sps /* 1073741824 = 1 in 2 */ 74157642Sps 75157642Sps /* Controls how often the l2_fhdr frame error check will fail. */ 76157642Sps int bce_debug_l2fhdr_status_check = 0; 77157642Sps 78157642Sps /* Controls how often the unexpected attention check will fail. */ 79157642Sps int bce_debug_unexpected_attention = 0; 80157642Sps 81157642Sps /* Controls how often to simulate an mbuf allocation failure. */ 82157642Sps int bce_debug_mbuf_allocation_failure = 0; 83157642Sps 84157642Sps /* Controls how often to simulate a DMA mapping failure. */ 85157642Sps int bce_debug_dma_map_addr_failure = 0; 86157642Sps 87157642Sps /* Controls how often to simulate a bootcode failure. */ 88157642Sps int bce_debug_bootcode_running_failure = 0; 89157642Sps#endif 90157642Sps 91157642Sps 92157642Sps/****************************************************************************/ 93157642Sps/* PCI Device ID Table */ 94157642Sps/* */ 95157642Sps/* Used by bce_probe() to identify the devices supported by this driver. */ 96157642Sps/****************************************************************************/ 97157642Sps#define BCE_DEVDESC_MAX 64 98157642Sps 99157642Spsstatic struct bce_type bce_devs[] = { 100157642Sps /* BCM5706C Controllers and OEM boards. */ 101157642Sps { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3101, 102157642Sps "HP NC370T Multifunction Gigabit Server Adapter" }, 103157642Sps { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3106, 104157642Sps "HP NC370i Multifunction Gigabit Server Adapter" }, 105157642Sps { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, PCI_ANY_ID, PCI_ANY_ID, 106157642Sps "Broadcom NetXtreme II BCM5706 1000Base-T" }, 107157642Sps 108157642Sps /* BCM5706S controllers and OEM boards. */ 109157642Sps { BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, HP_VENDORID, 0x3102, 110157642Sps "HP NC370F Multifunction Gigabit Server Adapter" }, 111157642Sps { BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, PCI_ANY_ID, PCI_ANY_ID, 112157642Sps "Broadcom NetXtreme II BCM5706 1000Base-SX" }, 113157642Sps 114157642Sps /* BCM5708C controllers and OEM boards. */ 115157642Sps { BRCM_VENDORID, BRCM_DEVICEID_BCM5708, PCI_ANY_ID, PCI_ANY_ID, 116157642Sps "Broadcom NetXtreme II BCM5708 1000Base-T" }, 117157642Sps 118157642Sps /* BCM5708S controllers and OEM boards. */ 119157642Sps { BRCM_VENDORID, BRCM_DEVICEID_BCM5708, PCI_ANY_ID, PCI_ANY_ID, 120157642Sps "Broadcom NetXtreme II BCM5708 1000Base-T" }, 121157642Sps { 0, 0, 0, 0, NULL } 122157642Sps}; 123157642Sps 124157642Sps 125157642Sps/****************************************************************************/ 126157642Sps/* Supported Flash NVRAM device data. */ 127157642Sps/****************************************************************************/ 128157642Spsstatic struct flash_spec flash_table[] = 129157642Sps{ 130157642Sps /* Slow EEPROM */ 131157642Sps {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400, 132157642Sps 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, 133157642Sps SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, 134157642Sps "EEPROM - slow"}, 135157642Sps /* Expansion entry 0001 */ 136157642Sps {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406, 137157642Sps 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 138157642Sps SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 139157642Sps "Entry 0001"}, 140157642Sps /* Saifun SA25F010 (non-buffered flash) */ 141157642Sps /* strap, cfg1, & write1 need updates */ 142157642Sps {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406, 143157642Sps 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 144157642Sps SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2, 145157642Sps "Non-buffered flash (128kB)"}, 146157642Sps /* Saifun SA25F020 (non-buffered flash) */ 147157642Sps /* strap, cfg1, & write1 need updates */ 148157642Sps {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406, 149157642Sps 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 150157642Sps SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4, 151157642Sps "Non-buffered flash (256kB)"}, 152157642Sps /* Expansion entry 0100 */ 153157642Sps {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406, 154157642Sps 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 155157642Sps SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 156157642Sps "Entry 0100"}, 157157642Sps /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */ 158157642Sps {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406, 159157642Sps 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, 160157642Sps ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2, 161157642Sps "Entry 0101: ST M45PE10 (128kB non-bufferred)"}, 162157642Sps /* Entry 0110: ST M45PE20 (non-buffered flash)*/ 163157642Sps {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406, 164157642Sps 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, 165157642Sps ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4, 166157642Sps "Entry 0110: ST M45PE20 (256kB non-bufferred)"}, 167157642Sps /* Saifun SA25F005 (non-buffered flash) */ 168157642Sps /* strap, cfg1, & write1 need updates */ 169157642Sps {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406, 170157642Sps 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 171157642Sps SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE, 172157642Sps "Non-buffered flash (64kB)"}, 173157642Sps /* Fast EEPROM */ 174157642Sps {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400, 175157642Sps 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, 176157642Sps SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, 177157642Sps "EEPROM - fast"}, 178157642Sps /* Expansion entry 1001 */ 179157642Sps {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406, 180157642Sps 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 181157642Sps SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 182157642Sps "Entry 1001"}, 183157642Sps /* Expansion entry 1010 */ 184157642Sps {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406, 185157642Sps 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 186157642Sps SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 187157642Sps "Entry 1010"}, 188157642Sps /* ATMEL AT45DB011B (buffered flash) */ 189157642Sps {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400, 190157642Sps 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, 191157642Sps BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE, 192157642Sps "Buffered flash (128kB)"}, 193157642Sps /* Expansion entry 1100 */ 194157642Sps {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406, 195157642Sps 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 196157642Sps SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 197157642Sps "Entry 1100"}, 198157642Sps /* Expansion entry 1101 */ 199157642Sps {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406, 200157642Sps 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 201157642Sps SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 202157642Sps "Entry 1101"}, 203157642Sps /* Ateml Expansion entry 1110 */ 204157642Sps {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400, 205157642Sps 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, 206157642Sps BUFFERED_FLASH_BYTE_ADDR_MASK, 0, 207157642Sps "Entry 1110 (Atmel)"}, 208157642Sps /* ATMEL AT45DB021B (buffered flash) */ 209157642Sps {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400, 210157642Sps 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, 211157642Sps BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2, 212157642Sps "Buffered flash (256kB)"}, 213157642Sps}; 214157642Sps 215157642Sps 216157642Sps/****************************************************************************/ 217157642Sps/* FreeBSD device entry points. */ 218157642Sps/****************************************************************************/ 219157642Spsstatic int bce_probe (device_t); 220157642Spsstatic int bce_attach (device_t); 221157642Spsstatic int bce_detach (device_t); 222157642Spsstatic void bce_shutdown (device_t); 223157642Sps 224157642Sps 225157642Sps/****************************************************************************/ 226157642Sps/* BCE Debug Data Structure Dump Routines */ 227157642Sps/****************************************************************************/ 228157642Sps#ifdef BCE_DEBUG 229157642Spsstatic void bce_dump_mbuf (struct bce_softc *, struct mbuf *); 230157642Spsstatic void bce_dump_tx_mbuf_chain (struct bce_softc *, int, int); 231157642Spsstatic void bce_dump_rx_mbuf_chain (struct bce_softc *, int, int); 232157642Spsstatic void bce_dump_txbd (struct bce_softc *, int, struct tx_bd *); 233157642Spsstatic void bce_dump_rxbd (struct bce_softc *, int, struct rx_bd *); 234157642Spsstatic void bce_dump_l2fhdr (struct bce_softc *, int, struct l2_fhdr *); 235157642Spsstatic void bce_dump_tx_chain (struct bce_softc *, int, int); 236157642Spsstatic void bce_dump_rx_chain (struct bce_softc *, int, int); 237157642Spsstatic void bce_dump_status_block (struct bce_softc *); 238157642Spsstatic void bce_dump_stats_block (struct bce_softc *); 239157642Spsstatic void bce_dump_driver_state (struct bce_softc *); 240157642Spsstatic void bce_dump_hw_state (struct bce_softc *); 241157642Spsstatic void bce_breakpoint (struct bce_softc *); 242157642Sps#endif 243157642Sps 244157642Sps 245157642Sps/****************************************************************************/ 246157642Sps/* BCE Register/Memory Access Routines */ 247157642Sps/****************************************************************************/ 248157642Spsstatic u32 bce_reg_rd_ind (struct bce_softc *, u32); 249157642Spsstatic void bce_reg_wr_ind (struct bce_softc *, u32, u32); 250157642Spsstatic void bce_ctx_wr (struct bce_softc *, u32, u32, u32); 251157642Spsstatic int bce_miibus_read_reg (device_t, int, int); 252157642Spsstatic int bce_miibus_write_reg (device_t, int, int, int); 253157642Spsstatic void bce_miibus_statchg (device_t); 254157642Sps 255157642Sps 256157642Sps/****************************************************************************/ 257157642Sps/* BCE NVRAM Access Routines */ 258157642Sps/****************************************************************************/ 259157642Spsstatic int bce_acquire_nvram_lock (struct bce_softc *); 260157642Spsstatic int bce_release_nvram_lock (struct bce_softc *); 261157642Spsstatic void bce_enable_nvram_access (struct bce_softc *); 262157642Spsstatic void bce_disable_nvram_access(struct bce_softc *); 263157642Spsstatic int bce_nvram_read_dword (struct bce_softc *, u32, u8 *, u32); 264157642Spsstatic int bce_init_nvram (struct bce_softc *); 265157642Spsstatic int bce_nvram_read (struct bce_softc *, u32, u8 *, int); 266157642Spsstatic int bce_nvram_test (struct bce_softc *); 267157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT 268157642Spsstatic int bce_enable_nvram_write (struct bce_softc *); 269157642Spsstatic void bce_disable_nvram_write (struct bce_softc *); 270157642Spsstatic int bce_nvram_erase_page (struct bce_softc *, u32); 271157642Spsstatic int bce_nvram_write_dword (struct bce_softc *, u32, u8 *, u32); 272157642Spsstatic int bce_nvram_write (struct bce_softc *, u32, u8 *, int); 273157642Sps#endif 274157642Sps 275157642Sps/****************************************************************************/ 276157642Sps/* */ 277157642Sps/****************************************************************************/ 278157642Spsstatic void bce_dma_map_addr (void *, bus_dma_segment_t *, int, int); 279157642Spsstatic void bce_dma_map_tx_desc (void *, bus_dma_segment_t *, int, bus_size_t, int); 280157642Spsstatic int bce_dma_alloc (device_t); 281157642Spsstatic void bce_dma_free (struct bce_softc *); 282157642Spsstatic void bce_release_resources (struct bce_softc *); 283157642Sps 284157642Sps/****************************************************************************/ 285157642Sps/* BCE Firmware Synchronization and Load */ 286157642Sps/****************************************************************************/ 287157642Spsstatic int bce_fw_sync (struct bce_softc *, u32); 288157642Spsstatic void bce_load_rv2p_fw (struct bce_softc *, u32 *, u32, u32); 289157642Spsstatic void bce_load_cpu_fw (struct bce_softc *, struct cpu_reg *, struct fw_info *); 290157642Spsstatic void bce_init_cpus (struct bce_softc *); 291157642Sps 292157642Spsstatic void bce_stop (struct bce_softc *); 293157642Spsstatic int bce_reset (struct bce_softc *, u32); 294157642Spsstatic int bce_chipinit (struct bce_softc *); 295157642Spsstatic int bce_blockinit (struct bce_softc *); 296157642Spsstatic int bce_get_buf (struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *); 297157642Sps 298157642Spsstatic int bce_init_tx_chain (struct bce_softc *); 299157642Spsstatic int bce_init_rx_chain (struct bce_softc *); 300157642Spsstatic void bce_free_rx_chain (struct bce_softc *); 301157642Spsstatic void bce_free_tx_chain (struct bce_softc *); 302157642Sps 303157642Spsstatic int bce_tx_encap (struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *); 304157642Spsstatic void bce_start_locked (struct ifnet *); 305157642Spsstatic void bce_start (struct ifnet *); 306157642Spsstatic int bce_ioctl (struct ifnet *, u_long, caddr_t); 307157642Spsstatic void bce_watchdog (struct ifnet *); 308157642Spsstatic int bce_ifmedia_upd (struct ifnet *); 309157642Spsstatic void bce_ifmedia_sts (struct ifnet *, struct ifmediareq *); 310157642Spsstatic void bce_init_locked (struct bce_softc *); 311157642Spsstatic void bce_init (void *); 312157642Sps 313157642Spsstatic void bce_init_context (struct bce_softc *); 314157642Spsstatic void bce_get_mac_addr (struct bce_softc *); 315157642Spsstatic void bce_set_mac_addr (struct bce_softc *); 316157642Spsstatic void bce_phy_intr (struct bce_softc *); 317157642Spsstatic void bce_rx_intr (struct bce_softc *); 318157642Spsstatic void bce_tx_intr (struct bce_softc *); 319157642Spsstatic void bce_disable_intr (struct bce_softc *); 320157642Spsstatic void bce_enable_intr (struct bce_softc *); 321157642Sps 322157642Sps#ifdef DEVICE_POLLING 323157642Spsstatic void bce_poll_locked (struct ifnet *, enum poll_cmd, int); 324157642Spsstatic void bce_poll (struct ifnet *, enum poll_cmd, int); 325157642Sps#endif 326157642Spsstatic void bce_intr (void *); 327157642Spsstatic void bce_set_rx_mode (struct bce_softc *); 328157642Spsstatic void bce_stats_update (struct bce_softc *); 329157642Spsstatic void bce_tick_locked (struct bce_softc *); 330157642Spsstatic void bce_tick (void *); 331157642Spsstatic void bce_add_sysctls (struct bce_softc *); 332157642Sps 333157642Sps 334157642Sps/****************************************************************************/ 335157642Sps/* FreeBSD device dispatch table. */ 336157642Sps/****************************************************************************/ 337157642Spsstatic device_method_t bce_methods[] = { 338157642Sps /* Device interface */ 339157642Sps DEVMETHOD(device_probe, bce_probe), 340157642Sps DEVMETHOD(device_attach, bce_attach), 341157642Sps DEVMETHOD(device_detach, bce_detach), 342157642Sps DEVMETHOD(device_shutdown, bce_shutdown), 343157642Sps 344157642Sps /* bus interface */ 345157642Sps DEVMETHOD(bus_print_child, bus_generic_print_child), 346157642Sps DEVMETHOD(bus_driver_added, bus_generic_driver_added), 347157642Sps 348157642Sps /* MII interface */ 349157642Sps DEVMETHOD(miibus_readreg, bce_miibus_read_reg), 350157642Sps DEVMETHOD(miibus_writereg, bce_miibus_write_reg), 351157642Sps DEVMETHOD(miibus_statchg, bce_miibus_statchg), 352157642Sps 353157642Sps { 0, 0 } 354157642Sps}; 355157642Sps 356157642Spsstatic driver_t bce_driver = { 357157642Sps "bce", 358157642Sps bce_methods, 359157642Sps sizeof(struct bce_softc) 360157642Sps}; 361157642Sps 362157642Spsstatic devclass_t bce_devclass; 363157642Sps 364157642SpsMODULE_DEPEND(bce, pci, 1, 1, 1); 365157642SpsMODULE_DEPEND(bce, ether, 1, 1, 1); 366157642SpsMODULE_DEPEND(bce, miibus, 1, 1, 1); 367157642Sps 368157642SpsDRIVER_MODULE(bce, pci, bce_driver, bce_devclass, 0, 0); 369157642SpsDRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, 0, 0); 370157642Sps 371157642Sps 372157642Sps/****************************************************************************/ 373157642Sps/* Device probe function. */ 374157642Sps/* */ 375157642Sps/* Compares the device to the driver's list of supported devices and */ 376157642Sps/* reports back to the OS whether this is the right driver for the device. */ 377157642Sps/* */ 378157642Sps/* Returns: */ 379157642Sps/* BUS_PROBE_DEFAULT on success, positive value on failure. */ 380157642Sps/****************************************************************************/ 381157642Spsstatic int 382157642Spsbce_probe(device_t dev) 383157642Sps{ 384157642Sps struct bce_type *t; 385157642Sps struct bce_softc *sc; 386157642Sps char *descbuf; 387157642Sps u16 vid = 0, did = 0, svid = 0, sdid = 0; 388157642Sps 389157642Sps t = bce_devs; 390157642Sps 391157642Sps sc = device_get_softc(dev); 392157642Sps bzero(sc, sizeof(struct bce_softc)); 393157642Sps sc->bce_unit = device_get_unit(dev); 394157642Sps sc->bce_dev = dev; 395157642Sps 396157642Sps /* Get the data for the device to be probed. */ 397157642Sps vid = pci_get_vendor(dev); 398157642Sps did = pci_get_device(dev); 399157642Sps svid = pci_get_subvendor(dev); 400157642Sps sdid = pci_get_subdevice(dev); 401157642Sps 402157642Sps DBPRINT(sc, BCE_VERBOSE_LOAD, 403157642Sps "%s(); VID = 0x%04X, DID = 0x%04X, SVID = 0x%04X, " 404157642Sps "SDID = 0x%04X\n", __FUNCTION__, vid, did, svid, sdid); 405157642Sps 406157642Sps /* Look through the list of known devices for a match. */ 407157642Sps while(t->bce_name != NULL) { 408157642Sps 409157642Sps if ((vid == t->bce_vid) && (did == t->bce_did) && 410157642Sps ((svid == t->bce_svid) || (t->bce_svid == PCI_ANY_ID)) && 411157642Sps ((sdid == t->bce_sdid) || (t->bce_sdid == PCI_ANY_ID))) { 412157642Sps 413157642Sps descbuf = malloc(BCE_DEVDESC_MAX, M_TEMP, M_NOWAIT); 414157642Sps 415157642Sps if (descbuf == NULL) 416157642Sps return(ENOMEM); 417157642Sps 418157642Sps /* Print out the device identity. */ 419157642Sps snprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d), %s", 420157642Sps t->bce_name, 421157642Sps (((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'), 422157642Sps (pci_read_config(dev, PCIR_REVID, 4) & 0xf), 423157642Sps bce_driver_version); 424157642Sps 425157642Sps device_set_desc_copy(dev, descbuf); 426157642Sps free(descbuf, M_TEMP); 427157642Sps return(BUS_PROBE_DEFAULT); 428157642Sps } 429157642Sps t++; 430157642Sps } 431157642Sps 432157642Sps DBPRINT(sc, BCE_VERBOSE_LOAD, "%s(%d): No IOCTL match found!\n", 433157642Sps __FILE__, __LINE__); 434157642Sps 435157642Sps return(ENXIO); 436157642Sps} 437157642Sps 438157642Sps 439157642Sps/****************************************************************************/ 440157642Sps/* Device attach function. */ 441157642Sps/* */ 442157642Sps/* Allocates device resources, performs secondary chip identification, */ 443157642Sps/* resets and initializes the hardware, and initializes driver instance */ 444157642Sps/* variables. */ 445157642Sps/* */ 446157642Sps/* Returns: */ 447157642Sps/* 0 on success, positive value on failure. */ 448157642Sps/****************************************************************************/ 449157642Spsstatic int 450157642Spsbce_attach(device_t dev) 451157642Sps{ 452157642Sps struct bce_softc *sc; 453157642Sps struct ifnet *ifp; 454157642Sps u32 val; 455157642Sps int mbuf, rid, rc = 0; 456157642Sps 457157642Sps sc = device_get_softc(dev); 458157642Sps sc->bce_dev = dev; 459157642Sps 460157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 461157642Sps 462157642Sps mbuf = device_get_unit(dev); 463157642Sps sc->bce_unit = mbuf; 464157642Sps 465157642Sps pci_enable_busmaster(dev); 466157642Sps 467157642Sps /* Allocate PCI memory resources. */ 468157642Sps rid = PCIR_BAR(0); 469157642Sps sc->bce_res = bus_alloc_resource_any( 470157642Sps dev, /* dev */ 471157642Sps SYS_RES_MEMORY, /* type */ 472157642Sps &rid, /* rid */ 473157642Sps RF_ACTIVE | PCI_RF_DENSE); /* flags */ 474157642Sps 475157642Sps if (sc->bce_res == NULL) { 476157642Sps BCE_PRINTF(sc, "%s(%d): PCI memory allocation failed\n", 477157642Sps __FILE__, __LINE__); 478157642Sps rc = ENXIO; 479157642Sps goto bce_attach_fail; 480157642Sps } 481157642Sps 482157642Sps /* Get various resource handles. */ 483157642Sps sc->bce_btag = rman_get_bustag(sc->bce_res); 484157642Sps sc->bce_bhandle = rman_get_bushandle(sc->bce_res); 485157642Sps sc->bce_vhandle = (vm_offset_t) rman_get_virtual(sc->bce_res); 486157642Sps 487157642Sps /* Allocate PCI IRQ resources. */ 488157642Sps rid = 0; 489157642Sps sc->bce_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 490157642Sps RF_SHAREABLE | RF_ACTIVE); 491157642Sps 492157642Sps if (sc->bce_irq == NULL) { 493157642Sps BCE_PRINTF(sc, "%s(%d): PCI map interrupt failed\n", 494157642Sps __FILE__, __LINE__); 495157642Sps rc = ENXIO; 496157642Sps goto bce_attach_fail; 497157642Sps } 498157642Sps 499157642Sps /* Initialize mutex for the current device instance. */ 500157642Sps BCE_LOCK_INIT(sc, device_get_nameunit(dev)); 501157642Sps 502157642Sps /* 503157642Sps * Configure byte swap and enable indirect register access. 504157642Sps * Rely on CPU to do target byte swapping on big endian systems. 505157642Sps * Access to registers outside of PCI configurtion space are not 506157642Sps * valid until this is done. 507157642Sps */ 508157642Sps pci_write_config(dev, BCE_PCICFG_MISC_CONFIG, 509157642Sps BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | 510157642Sps BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP, 4); 511157642Sps 512157642Sps /* Save ASIC revsion info. */ 513157642Sps sc->bce_chipid = REG_RD(sc, BCE_MISC_ID); 514157642Sps 515157642Sps /* Weed out any non-production controller revisions. */ 516157642Sps switch(BCE_CHIP_ID(sc)) { 517157642Sps case BCE_CHIP_ID_5706_A0: 518157642Sps case BCE_CHIP_ID_5706_A1: 519157642Sps case BCE_CHIP_ID_5708_A0: 520157642Sps case BCE_CHIP_ID_5708_B0: 521157642Sps BCE_PRINTF(sc, "%s(%d): Unsupported controller revision (%c%d)!\n", 522157642Sps __FILE__, __LINE__, 523157642Sps (((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'), 524157642Sps (pci_read_config(dev, PCIR_REVID, 4) & 0xf)); 525157642Sps rc = ENODEV; 526157642Sps goto bce_attach_fail; 527157642Sps } 528157642Sps 529157642Sps if (BCE_CHIP_BOND_ID(sc) & BCE_CHIP_BOND_ID_SERDES_BIT) { 530157642Sps BCE_PRINTF(sc, "%s(%d): SerDes controllers are not supported!\n", 531157642Sps __FILE__, __LINE__); 532157642Sps rc = ENODEV; 533157642Sps goto bce_attach_fail; 534157642Sps } 535157642Sps 536157642Sps /* 537157642Sps * The embedded PCIe to PCI-X bridge (EPB) 538157642Sps * in the 5708 cannot address memory above 539157642Sps * 40 bits (E7_5708CB1_23043 & E6_5708SB1_23043). 540157642Sps */ 541157642Sps if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708) 542157642Sps sc->max_bus_addr = BCE_BUS_SPACE_MAXADDR; 543157642Sps else 544157642Sps sc->max_bus_addr = BUS_SPACE_MAXADDR; 545157642Sps 546157642Sps /* 547157642Sps * Find the base address for shared memory access. 548157642Sps * Newer versions of bootcode use a signature and offset 549157642Sps * while older versions use a fixed address. 550157642Sps */ 551157642Sps val = REG_RD_IND(sc, BCE_SHM_HDR_SIGNATURE); 552157642Sps if ((val & BCE_SHM_HDR_SIGNATURE_SIG_MASK) == BCE_SHM_HDR_SIGNATURE_SIG) 553157642Sps sc->bce_shmem_base = REG_RD_IND(sc, BCE_SHM_HDR_ADDR_0); 554157642Sps else 555157642Sps sc->bce_shmem_base = HOST_VIEW_SHMEM_BASE; 556157642Sps 557157642Sps DBPRINT(sc, BCE_INFO, "bce_shmem_base = 0x%08X\n", sc->bce_shmem_base); 558157642Sps 559157642Sps /* Set initial device and PHY flags */ 560157642Sps sc->bce_flags = 0; 561157642Sps sc->bce_phy_flags = 0; 562157642Sps 563157642Sps /* Get PCI bus information (speed and type). */ 564157642Sps val = REG_RD(sc, BCE_PCICFG_MISC_STATUS); 565157642Sps if (val & BCE_PCICFG_MISC_STATUS_PCIX_DET) { 566157642Sps u32 clkreg; 567157642Sps 568157642Sps sc->bce_flags |= BCE_PCIX_FLAG; 569157642Sps 570157642Sps clkreg = REG_RD(sc, BCE_PCICFG_PCI_CLOCK_CONTROL_BITS); 571157642Sps 572157642Sps clkreg &= BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; 573157642Sps switch (clkreg) { 574157642Sps case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ: 575157642Sps sc->bus_speed_mhz = 133; 576157642Sps break; 577157642Sps 578157642Sps case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ: 579157642Sps sc->bus_speed_mhz = 100; 580157642Sps break; 581157642Sps 582157642Sps case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ: 583157642Sps case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ: 584157642Sps sc->bus_speed_mhz = 66; 585157642Sps break; 586157642Sps 587157642Sps case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ: 588157642Sps case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ: 589157642Sps sc->bus_speed_mhz = 50; 590157642Sps break; 591157642Sps 592157642Sps case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW: 593157642Sps case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ: 594157642Sps case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ: 595157642Sps sc->bus_speed_mhz = 33; 596157642Sps break; 597157642Sps } 598157642Sps } else { 599157642Sps if (val & BCE_PCICFG_MISC_STATUS_M66EN) 600157642Sps sc->bus_speed_mhz = 66; 601157642Sps else 602157642Sps sc->bus_speed_mhz = 33; 603157642Sps } 604157642Sps 605157642Sps if (val & BCE_PCICFG_MISC_STATUS_32BIT_DET) 606157642Sps sc->bce_flags |= BCE_PCI_32BIT_FLAG; 607157642Sps 608157642Sps BCE_PRINTF(sc, "ASIC ID 0x%08X; Revision (%c%d); PCI%s %s %dMHz\n", 609157642Sps sc->bce_chipid, 610157642Sps ((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A', 611157642Sps ((BCE_CHIP_ID(sc) & 0x0ff0) >> 4), 612157642Sps ((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""), 613157642Sps ((sc->bce_flags & BCE_PCI_32BIT_FLAG) ? "32-bit" : "64-bit"), 614157642Sps sc->bus_speed_mhz); 615157642Sps 616157642Sps /* Reset the controller. */ 617157642Sps if (bce_reset(sc, BCE_DRV_MSG_CODE_RESET)) { 618157642Sps rc = ENXIO; 619157642Sps goto bce_attach_fail; 620157642Sps } 621157642Sps 622157642Sps /* Initialize the controller. */ 623157642Sps if (bce_chipinit(sc)) { 624157642Sps BCE_PRINTF(sc, "%s(%d): Controller initialization failed!\n", 625157642Sps __FILE__, __LINE__); 626157642Sps rc = ENXIO; 627157642Sps goto bce_attach_fail; 628157642Sps } 629157642Sps 630157642Sps /* Perform NVRAM test. */ 631157642Sps if (bce_nvram_test(sc)) { 632157642Sps BCE_PRINTF(sc, "%s(%d): NVRAM test failed!\n", 633157642Sps __FILE__, __LINE__); 634157642Sps rc = ENXIO; 635157642Sps goto bce_attach_fail; 636157642Sps } 637157642Sps 638157642Sps /* Fetch the permanent Ethernet MAC address. */ 639157642Sps bce_get_mac_addr(sc); 640157642Sps 641157642Sps /* 642157642Sps * Trip points control how many BDs 643157642Sps * should be ready before generating an 644157642Sps * interrupt while ticks control how long 645157642Sps * a BD can sit in the chain before 646157642Sps * generating an interrupt. Set the default 647157642Sps * values for the RX and TX rings. 648157642Sps */ 649157642Sps 650157642Sps#ifdef BCE_DRBUG 651157642Sps /* Force more frequent interrupts. */ 652157642Sps sc->bce_tx_quick_cons_trip_int = 1; 653157642Sps sc->bce_tx_quick_cons_trip = 1; 654157642Sps sc->bce_tx_ticks_int = 0; 655157642Sps sc->bce_tx_ticks = 0; 656157642Sps 657157642Sps sc->bce_rx_quick_cons_trip_int = 1; 658157642Sps sc->bce_rx_quick_cons_trip = 1; 659157642Sps sc->bce_rx_ticks_int = 0; 660157642Sps sc->bce_rx_ticks = 0; 661157642Sps#else 662157642Sps sc->bce_tx_quick_cons_trip_int = 20; 663157642Sps sc->bce_tx_quick_cons_trip = 20; 664157642Sps sc->bce_tx_ticks_int = 80; 665157642Sps sc->bce_tx_ticks = 80; 666157642Sps 667157642Sps sc->bce_rx_quick_cons_trip_int = 6; 668157642Sps sc->bce_rx_quick_cons_trip = 6; 669157642Sps sc->bce_rx_ticks_int = 18; 670157642Sps sc->bce_rx_ticks = 18; 671157642Sps#endif 672157642Sps 673157642Sps /* Update statistics once every second. */ 674157642Sps sc->bce_stats_ticks = 1000000 & 0xffff00; 675157642Sps 676157642Sps /* 677157642Sps * The copper based NetXtreme II controllers 678157642Sps * use an integrated PHY at address 1 while 679157642Sps * the SerDes controllers use a PHY at 680157642Sps * address 2. 681157642Sps */ 682157642Sps sc->bce_phy_addr = 1; 683157642Sps 684157642Sps if (BCE_CHIP_BOND_ID(sc) & BCE_CHIP_BOND_ID_SERDES_BIT) { 685157642Sps sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG; 686157642Sps sc->bce_flags |= BCE_NO_WOL_FLAG; 687157642Sps if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708) { 688157642Sps sc->bce_phy_addr = 2; 689157642Sps val = REG_RD_IND(sc, sc->bce_shmem_base + 690157642Sps BCE_SHARED_HW_CFG_CONFIG); 691157642Sps if (val & BCE_SHARED_HW_CFG_PHY_2_5G) 692157642Sps sc->bce_phy_flags |= BCE_PHY_2_5G_CAPABLE_FLAG; 693157642Sps } 694157642Sps } 695157642Sps 696157642Sps /* Allocate DMA memory resources. */ 697157642Sps if (bce_dma_alloc(dev)) { 698157642Sps BCE_PRINTF(sc, "%s(%d): DMA resource allocation failed!\n", 699157642Sps __FILE__, __LINE__); 700157642Sps rc = ENXIO; 701157642Sps goto bce_attach_fail; 702157642Sps } 703157642Sps 704157642Sps /* Allocate an ifnet structure. */ 705157642Sps ifp = sc->bce_ifp = if_alloc(IFT_ETHER); 706157642Sps if (ifp == NULL) { 707157642Sps BCE_PRINTF(sc, "%s(%d): Interface allocation failed!\n", 708157642Sps __FILE__, __LINE__); 709157642Sps rc = ENXIO; 710157642Sps goto bce_attach_fail; 711157642Sps } 712157642Sps 713157642Sps /* Initialize the ifnet interface. */ 714157642Sps ifp->if_softc = sc; 715157642Sps if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 716157642Sps ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 717157642Sps ifp->if_ioctl = bce_ioctl; 718157642Sps ifp->if_start = bce_start; 719157642Sps ifp->if_timer = 0; 720157642Sps ifp->if_watchdog = bce_watchdog; 721157642Sps ifp->if_init = bce_init; 722157642Sps ifp->if_mtu = ETHERMTU; 723157642Sps ifp->if_hwassist = BCE_IF_HWASSIST; 724157642Sps ifp->if_capabilities = BCE_IF_CAPABILITIES; 725157642Sps ifp->if_capenable = ifp->if_capabilities; 726157642Sps 727157642Sps /* Assume a standard 1500 byte MTU size for mbuf allocations. */ 728157642Sps sc->mbuf_alloc_size = MCLBYTES; 729157642Sps#ifdef DEVICE_POLLING 730157642Sps ifp->if_capabilities |= IFCAP_POLLING; 731157642Sps#endif 732157642Sps 733157642Sps ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD; 734157642Sps if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) 735157642Sps ifp->if_baudrate = IF_Gbps(2.5); 736157642Sps else 737157642Sps ifp->if_baudrate = IF_Gbps(1); 738157642Sps 739157642Sps IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 740157642Sps IFQ_SET_READY(&ifp->if_snd); 741157642Sps 742157642Sps if (sc->bce_phy_flags & BCE_PHY_SERDES_FLAG) { 743157642Sps BCE_PRINTF(sc, "%s(%d): SerDes is not supported by this driver!\n", 744157642Sps __FILE__, __LINE__); 745157642Sps rc = ENODEV; 746157642Sps goto bce_attach_fail; 747157642Sps } else { 748157642Sps /* Look for our PHY. */ 749157642Sps if (mii_phy_probe(dev, &sc->bce_miibus, bce_ifmedia_upd, 750157642Sps bce_ifmedia_sts)) { 751157642Sps BCE_PRINTF(sc, "%s(%d): PHY probe failed!\n", 752157642Sps __FILE__, __LINE__); 753157642Sps rc = ENXIO; 754157642Sps goto bce_attach_fail; 755157642Sps } 756157642Sps } 757157642Sps 758157642Sps /* Attach to the Ethernet interface list. */ 759157642Sps ether_ifattach(ifp, sc->eaddr); 760157642Sps 761157642Sps#if __FreeBSD_version < 500000 762157642Sps callout_init(&sc->bce_stat_ch); 763157642Sps#else 764157642Sps callout_init(&sc->bce_stat_ch, CALLOUT_MPSAFE); 765157642Sps#endif 766157642Sps 767157642Sps /* Hookup IRQ last. */ 768157642Sps rc = bus_setup_intr(dev, sc->bce_irq, INTR_TYPE_NET | INTR_MPSAFE, 769157642Sps bce_intr, sc, &sc->bce_intrhand); 770157642Sps 771157642Sps if (rc) { 772157642Sps BCE_PRINTF(sc, "%s(%d): Failed to setup IRQ!\n", 773157642Sps __FILE__, __LINE__); 774157642Sps bce_detach(dev); 775157642Sps goto bce_attach_exit; 776157642Sps } 777157642Sps 778157642Sps /* Print some important debugging info. */ 779157642Sps DBRUN(BCE_INFO, bce_dump_driver_state(sc)); 780157642Sps 781157642Sps /* Add the supported sysctls to the kernel. */ 782157642Sps bce_add_sysctls(sc); 783157642Sps 784157642Sps goto bce_attach_exit; 785157642Sps 786157642Spsbce_attach_fail: 787157642Sps bce_release_resources(sc); 788157642Sps 789157642Spsbce_attach_exit: 790157642Sps 791157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 792157642Sps 793157642Sps return(rc); 794157642Sps} 795157642Sps 796157642Sps 797157642Sps/****************************************************************************/ 798157642Sps/* Device detach function. */ 799157642Sps/* */ 800157642Sps/* Stops the controller, resets the controller, and releases resources. */ 801157642Sps/* */ 802157642Sps/* Returns: */ 803157642Sps/* 0 on success, positive value on failure. */ 804157642Sps/****************************************************************************/ 805157642Spsstatic int 806157642Spsbce_detach(device_t dev) 807157642Sps{ 808157642Sps struct bce_softc *sc; 809157642Sps struct ifnet *ifp; 810157642Sps 811157642Sps sc = device_get_softc(dev); 812157642Sps 813157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 814157642Sps 815157642Sps ifp = sc->bce_ifp; 816157642Sps 817157642Sps#ifdef DEVICE_POLLING 818157642Sps if (ifp->if_capenable & IFCAP_POLLING) 819157642Sps ether_poll_deregister(ifp); 820157642Sps#endif 821157642Sps 822157642Sps /* Stop and reset the controller. */ 823157642Sps BCE_LOCK(sc); 824157642Sps bce_stop(sc); 825157642Sps bce_reset(sc, BCE_DRV_MSG_CODE_RESET); 826157642Sps BCE_UNLOCK(sc); 827157642Sps 828157642Sps ether_ifdetach(ifp); 829157642Sps 830157642Sps /* If we have a child device on the MII bus remove it too. */ 831157642Sps if (sc->bce_phy_flags & BCE_PHY_SERDES_FLAG) { 832157642Sps ifmedia_removeall(&sc->bce_ifmedia); 833157642Sps } else { 834157642Sps bus_generic_detach(dev); 835157642Sps device_delete_child(dev, sc->bce_miibus); 836157642Sps } 837157642Sps 838157642Sps /* Release all remaining resources. */ 839157642Sps bce_release_resources(sc); 840157642Sps 841157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 842157642Sps 843157642Sps return(0); 844157642Sps} 845157642Sps 846157642Sps 847157642Sps/****************************************************************************/ 848157642Sps/* Device shutdown function. */ 849157642Sps/* */ 850157642Sps/* Stops and resets the controller. */ 851157642Sps/* */ 852157642Sps/* Returns: */ 853157642Sps/* Nothing */ 854157642Sps/****************************************************************************/ 855157642Spsstatic void 856157642Spsbce_shutdown(device_t dev) 857157642Sps{ 858157642Sps struct bce_softc *sc = device_get_softc(dev); 859157642Sps 860157642Sps BCE_LOCK(sc); 861157642Sps bce_stop(sc); 862157642Sps bce_reset(sc, BCE_DRV_MSG_CODE_RESET); 863157642Sps BCE_UNLOCK(sc); 864157642Sps} 865157642Sps 866157642Sps 867157642Sps/****************************************************************************/ 868157642Sps/* Indirect register read. */ 869157642Sps/* */ 870157642Sps/* Reads NetXtreme II registers using an index/data register pair in PCI */ 871157642Sps/* configuration space. Using this mechanism avoids issues with posted */ 872157642Sps/* reads but is much slower than memory-mapped I/O. */ 873157642Sps/* */ 874157642Sps/* Returns: */ 875157642Sps/* The value of the register. */ 876157642Sps/****************************************************************************/ 877157642Spsstatic u32 878157642Spsbce_reg_rd_ind(struct bce_softc *sc, u32 offset) 879157642Sps{ 880157642Sps device_t dev; 881157642Sps dev = sc->bce_dev; 882157642Sps 883157642Sps pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4); 884157642Sps#ifdef BCE_DEBUG 885157642Sps { 886157642Sps u32 val; 887157642Sps val = pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4); 888157642Sps DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n", 889157642Sps __FUNCTION__, offset, val); 890157642Sps return val; 891157642Sps } 892157642Sps#else 893157642Sps return pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4); 894157642Sps#endif 895157642Sps} 896157642Sps 897157642Sps 898157642Sps/****************************************************************************/ 899157642Sps/* Indirect register write. */ 900157642Sps/* */ 901157642Sps/* Writes NetXtreme II registers using an index/data register pair in PCI */ 902157642Sps/* configuration space. Using this mechanism avoids issues with posted */ 903157642Sps/* writes but is muchh slower than memory-mapped I/O. */ 904157642Sps/* */ 905157642Sps/* Returns: */ 906157642Sps/* Nothing. */ 907157642Sps/****************************************************************************/ 908157642Spsstatic void 909157642Spsbce_reg_wr_ind(struct bce_softc *sc, u32 offset, u32 val) 910157642Sps{ 911157642Sps device_t dev; 912157642Sps dev = sc->bce_dev; 913157642Sps 914157642Sps DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n", 915157642Sps __FUNCTION__, offset, val); 916157642Sps 917157642Sps pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4); 918157642Sps pci_write_config(dev, BCE_PCICFG_REG_WINDOW, val, 4); 919157642Sps} 920157642Sps 921157642Sps 922157642Sps/****************************************************************************/ 923157642Sps/* Context memory write. */ 924157642Sps/* */ 925157642Sps/* The NetXtreme II controller uses context memory to track connection */ 926157642Sps/* information for L2 and higher network protocols. */ 927157642Sps/* */ 928157642Sps/* Returns: */ 929157642Sps/* Nothing. */ 930157642Sps/****************************************************************************/ 931157642Spsstatic void 932157642Spsbce_ctx_wr(struct bce_softc *sc, u32 cid_addr, u32 offset, u32 val) 933157642Sps{ 934157642Sps 935157642Sps DBPRINT(sc, BCE_EXCESSIVE, "%s(); cid_addr = 0x%08X, offset = 0x%08X, " 936157642Sps "val = 0x%08X\n", __FUNCTION__, cid_addr, offset, val); 937157642Sps 938157642Sps offset += cid_addr; 939157642Sps REG_WR(sc, BCE_CTX_DATA_ADR, offset); 940157642Sps REG_WR(sc, BCE_CTX_DATA, val); 941157642Sps} 942157642Sps 943157642Sps 944157642Sps/****************************************************************************/ 945157642Sps/* PHY register read. */ 946157642Sps/* */ 947157642Sps/* Implements register reads on the MII bus. */ 948157642Sps/* */ 949157642Sps/* Returns: */ 950157642Sps/* The value of the register. */ 951157642Sps/****************************************************************************/ 952157642Spsstatic int 953157642Spsbce_miibus_read_reg(device_t dev, int phy, int reg) 954157642Sps{ 955157642Sps struct bce_softc *sc; 956157642Sps u32 val; 957157642Sps int i; 958157642Sps 959157642Sps sc = device_get_softc(dev); 960157642Sps 961157642Sps /* Make sure we are accessing the correct PHY address. */ 962157642Sps if (phy != sc->bce_phy_addr) { 963157642Sps DBPRINT(sc, BCE_VERBOSE, "Invalid PHY address %d for PHY read!\n", phy); 964157642Sps return(0); 965157642Sps } 966157642Sps 967157642Sps if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) { 968157642Sps val = REG_RD(sc, BCE_EMAC_MDIO_MODE); 969157642Sps val &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL; 970157642Sps 971157642Sps REG_WR(sc, BCE_EMAC_MDIO_MODE, val); 972157642Sps REG_RD(sc, BCE_EMAC_MDIO_MODE); 973157642Sps 974157642Sps DELAY(40); 975157642Sps } 976157642Sps 977157642Sps val = BCE_MIPHY(phy) | BCE_MIREG(reg) | 978157642Sps BCE_EMAC_MDIO_COMM_COMMAND_READ | BCE_EMAC_MDIO_COMM_DISEXT | 979157642Sps BCE_EMAC_MDIO_COMM_START_BUSY; 980157642Sps REG_WR(sc, BCE_EMAC_MDIO_COMM, val); 981157642Sps 982157642Sps for (i = 0; i < BCE_PHY_TIMEOUT; i++) { 983157642Sps DELAY(10); 984157642Sps 985157642Sps val = REG_RD(sc, BCE_EMAC_MDIO_COMM); 986157642Sps if (!(val & BCE_EMAC_MDIO_COMM_START_BUSY)) { 987157642Sps DELAY(5); 988157642Sps 989157642Sps val = REG_RD(sc, BCE_EMAC_MDIO_COMM); 990157642Sps val &= BCE_EMAC_MDIO_COMM_DATA; 991157642Sps 992157642Sps break; 993157642Sps } 994157642Sps } 995157642Sps 996157642Sps if (val & BCE_EMAC_MDIO_COMM_START_BUSY) { 997157642Sps BCE_PRINTF(sc, "%s(%d): Error: PHY read timeout! phy = %d, reg = 0x%04X\n", 998157642Sps __FILE__, __LINE__, phy, reg); 999157642Sps val = 0x0; 1000157642Sps } else { 1001157642Sps val = REG_RD(sc, BCE_EMAC_MDIO_COMM); 1002157642Sps } 1003157642Sps 1004157642Sps DBPRINT(sc, BCE_EXCESSIVE, "%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n", 1005157642Sps __FUNCTION__, phy, (u16) reg & 0xffff, (u16) val & 0xffff); 1006157642Sps 1007157642Sps if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) { 1008157642Sps val = REG_RD(sc, BCE_EMAC_MDIO_MODE); 1009157642Sps val |= BCE_EMAC_MDIO_MODE_AUTO_POLL; 1010157642Sps 1011157642Sps REG_WR(sc, BCE_EMAC_MDIO_MODE, val); 1012157642Sps REG_RD(sc, BCE_EMAC_MDIO_MODE); 1013157642Sps 1014157642Sps DELAY(40); 1015157642Sps } 1016157642Sps 1017157642Sps return (val & 0xffff); 1018157642Sps 1019157642Sps} 1020157642Sps 1021157642Sps 1022157642Sps/****************************************************************************/ 1023157642Sps/* PHY register write. */ 1024157642Sps/* */ 1025157642Sps/* Implements register writes on the MII bus. */ 1026157642Sps/* */ 1027157642Sps/* Returns: */ 1028157642Sps/* The value of the register. */ 1029157642Sps/****************************************************************************/ 1030157642Spsstatic int 1031157642Spsbce_miibus_write_reg(device_t dev, int phy, int reg, int val) 1032157642Sps{ 1033157642Sps struct bce_softc *sc; 1034157642Sps u32 val1; 1035157642Sps int i; 1036157642Sps 1037157642Sps sc = device_get_softc(dev); 1038157642Sps 1039157642Sps /* Make sure we are accessing the correct PHY address. */ 1040157642Sps if (phy != sc->bce_phy_addr) { 1041157642Sps DBPRINT(sc, BCE_WARN, "Invalid PHY address %d for PHY write!\n", phy); 1042157642Sps return(0); 1043157642Sps } 1044157642Sps 1045157642Sps DBPRINT(sc, BCE_EXCESSIVE, "%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n", 1046157642Sps __FUNCTION__, phy, (u16) reg & 0xffff, (u16) val & 0xffff); 1047157642Sps 1048157642Sps if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) { 1049157642Sps val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE); 1050157642Sps val1 &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL; 1051157642Sps 1052157642Sps REG_WR(sc, BCE_EMAC_MDIO_MODE, val1); 1053157642Sps REG_RD(sc, BCE_EMAC_MDIO_MODE); 1054157642Sps 1055157642Sps DELAY(40); 1056157642Sps } 1057157642Sps 1058157642Sps val1 = BCE_MIPHY(phy) | BCE_MIREG(reg) | val | 1059157642Sps BCE_EMAC_MDIO_COMM_COMMAND_WRITE | 1060157642Sps BCE_EMAC_MDIO_COMM_START_BUSY | BCE_EMAC_MDIO_COMM_DISEXT; 1061157642Sps REG_WR(sc, BCE_EMAC_MDIO_COMM, val1); 1062157642Sps 1063157642Sps for (i = 0; i < BCE_PHY_TIMEOUT; i++) { 1064157642Sps DELAY(10); 1065157642Sps 1066157642Sps val1 = REG_RD(sc, BCE_EMAC_MDIO_COMM); 1067157642Sps if (!(val1 & BCE_EMAC_MDIO_COMM_START_BUSY)) { 1068157642Sps DELAY(5); 1069157642Sps break; 1070157642Sps } 1071157642Sps } 1072157642Sps 1073157642Sps if (val1 & BCE_EMAC_MDIO_COMM_START_BUSY) 1074157642Sps BCE_PRINTF(sc, "%s(%d): PHY write timeout!\n", 1075157642Sps __FILE__, __LINE__); 1076157642Sps 1077157642Sps if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) { 1078157642Sps val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE); 1079157642Sps val1 |= BCE_EMAC_MDIO_MODE_AUTO_POLL; 1080157642Sps 1081157642Sps REG_WR(sc, BCE_EMAC_MDIO_MODE, val1); 1082157642Sps REG_RD(sc, BCE_EMAC_MDIO_MODE); 1083157642Sps 1084157642Sps DELAY(40); 1085157642Sps } 1086157642Sps 1087157642Sps return 0; 1088157642Sps} 1089157642Sps 1090157642Sps 1091157642Sps/****************************************************************************/ 1092157642Sps/* MII bus status change. */ 1093157642Sps/* */ 1094157642Sps/* Called by the MII bus driver when the PHY establishes link to set the */ 1095157642Sps/* MAC interface registers. */ 1096157642Sps/* */ 1097157642Sps/* Returns: */ 1098157642Sps/* Nothing. */ 1099157642Sps/****************************************************************************/ 1100157642Spsstatic void 1101157642Spsbce_miibus_statchg(device_t dev) 1102157642Sps{ 1103157642Sps struct bce_softc *sc; 1104157642Sps struct mii_data *mii; 1105157642Sps 1106157642Sps sc = device_get_softc(dev); 1107157642Sps 1108157642Sps mii = device_get_softc(sc->bce_miibus); 1109157642Sps 1110157642Sps BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT); 1111157642Sps 1112157642Sps /* Set MII or GMII inerface based on the speed negotiated by the PHY. */ 1113157642Sps if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) { 1114157642Sps DBPRINT(sc, BCE_INFO, "Setting GMII interface.\n"); 1115157642Sps BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_GMII); 1116157642Sps } else { 1117157642Sps DBPRINT(sc, BCE_INFO, "Setting MII interface.\n"); 1118157642Sps BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_MII); 1119157642Sps } 1120157642Sps 1121157642Sps /* Set half or full duplex based on the duplicity negotiated by the PHY. */ 1122157642Sps if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { 1123157642Sps DBPRINT(sc, BCE_INFO, "Setting Full-Duplex interface.\n"); 1124157642Sps BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX); 1125157642Sps } else { 1126157642Sps DBPRINT(sc, BCE_INFO, "Setting Half-Duplex interface.\n"); 1127157642Sps BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX); 1128157642Sps } 1129157642Sps} 1130157642Sps 1131157642Sps 1132157642Sps/****************************************************************************/ 1133157642Sps/* Acquire NVRAM lock. */ 1134157642Sps/* */ 1135157642Sps/* Before the NVRAM can be accessed the caller must acquire an NVRAM lock. */ 1136157642Sps/* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */ 1137157642Sps/* for use by the driver. */ 1138157642Sps/* */ 1139157642Sps/* Returns: */ 1140157642Sps/* 0 on success, positive value on failure. */ 1141157642Sps/****************************************************************************/ 1142157642Spsstatic int 1143157642Spsbce_acquire_nvram_lock(struct bce_softc *sc) 1144157642Sps{ 1145157642Sps u32 val; 1146157642Sps int j; 1147157642Sps 1148157642Sps DBPRINT(sc, BCE_VERBOSE, "Acquiring NVRAM lock.\n"); 1149157642Sps 1150157642Sps /* Request access to the flash interface. */ 1151157642Sps REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_SET2); 1152157642Sps for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 1153157642Sps val = REG_RD(sc, BCE_NVM_SW_ARB); 1154157642Sps if (val & BCE_NVM_SW_ARB_ARB_ARB2) 1155157642Sps break; 1156157642Sps 1157157642Sps DELAY(5); 1158157642Sps } 1159157642Sps 1160157642Sps if (j >= NVRAM_TIMEOUT_COUNT) { 1161157642Sps DBPRINT(sc, BCE_WARN, "Timeout acquiring NVRAM lock!\n"); 1162157642Sps return EBUSY; 1163157642Sps } 1164157642Sps 1165157642Sps return 0; 1166157642Sps} 1167157642Sps 1168157642Sps 1169157642Sps/****************************************************************************/ 1170157642Sps/* Release NVRAM lock. */ 1171157642Sps/* */ 1172157642Sps/* When the caller is finished accessing NVRAM the lock must be released. */ 1173157642Sps/* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */ 1174157642Sps/* for use by the driver. */ 1175157642Sps/* */ 1176157642Sps/* Returns: */ 1177157642Sps/* 0 on success, positive value on failure. */ 1178157642Sps/****************************************************************************/ 1179157642Spsstatic int 1180157642Spsbce_release_nvram_lock(struct bce_softc *sc) 1181157642Sps{ 1182157642Sps int j; 1183157642Sps u32 val; 1184157642Sps 1185157642Sps DBPRINT(sc, BCE_VERBOSE, "Releasing NVRAM lock.\n"); 1186157642Sps 1187157642Sps /* 1188157642Sps * Relinquish nvram interface. 1189157642Sps */ 1190157642Sps REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_CLR2); 1191157642Sps 1192157642Sps for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 1193157642Sps val = REG_RD(sc, BCE_NVM_SW_ARB); 1194157642Sps if (!(val & BCE_NVM_SW_ARB_ARB_ARB2)) 1195157642Sps break; 1196157642Sps 1197157642Sps DELAY(5); 1198157642Sps } 1199157642Sps 1200157642Sps if (j >= NVRAM_TIMEOUT_COUNT) { 1201157642Sps DBPRINT(sc, BCE_WARN, "Timeout reeasing NVRAM lock!\n"); 1202157642Sps return EBUSY; 1203157642Sps } 1204157642Sps 1205157642Sps return 0; 1206157642Sps} 1207157642Sps 1208157642Sps 1209157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT 1210157642Sps/****************************************************************************/ 1211157642Sps/* Enable NVRAM write access. */ 1212157642Sps/* */ 1213157642Sps/* Before writing to NVRAM the caller must enable NVRAM writes. */ 1214157642Sps/* */ 1215157642Sps/* Returns: */ 1216157642Sps/* 0 on success, positive value on failure. */ 1217157642Sps/****************************************************************************/ 1218157642Spsstatic int 1219157642Spsbce_enable_nvram_write(struct bce_softc *sc) 1220157642Sps{ 1221157642Sps u32 val; 1222157642Sps 1223157642Sps DBPRINT(sc, BCE_VERBOSE, "Enabling NVRAM write.\n"); 1224157642Sps 1225157642Sps val = REG_RD(sc, BCE_MISC_CFG); 1226157642Sps REG_WR(sc, BCE_MISC_CFG, val | BCE_MISC_CFG_NVM_WR_EN_PCI); 1227157642Sps 1228157642Sps if (!sc->bce_flash_info->buffered) { 1229157642Sps int j; 1230157642Sps 1231157642Sps REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE); 1232157642Sps REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_WREN | BCE_NVM_COMMAND_DOIT); 1233157642Sps 1234157642Sps for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 1235157642Sps DELAY(5); 1236157642Sps 1237157642Sps val = REG_RD(sc, BCE_NVM_COMMAND); 1238157642Sps if (val & BCE_NVM_COMMAND_DONE) 1239157642Sps break; 1240157642Sps } 1241157642Sps 1242157642Sps if (j >= NVRAM_TIMEOUT_COUNT) { 1243157642Sps DBPRINT(sc, BCE_WARN, "Timeout writing NVRAM!\n"); 1244157642Sps return EBUSY; 1245157642Sps } 1246157642Sps } 1247157642Sps return 0; 1248157642Sps} 1249157642Sps 1250157642Sps 1251157642Sps/****************************************************************************/ 1252157642Sps/* Disable NVRAM write access. */ 1253157642Sps/* */ 1254157642Sps/* When the caller is finished writing to NVRAM write access must be */ 1255157642Sps/* disabled. */ 1256157642Sps/* */ 1257157642Sps/* Returns: */ 1258157642Sps/* Nothing. */ 1259157642Sps/****************************************************************************/ 1260157642Spsstatic void 1261157642Spsbce_disable_nvram_write(struct bce_softc *sc) 1262157642Sps{ 1263157642Sps u32 val; 1264157642Sps 1265157642Sps DBPRINT(sc, BCE_VERBOSE, "Disabling NVRAM write.\n"); 1266157642Sps 1267157642Sps val = REG_RD(sc, BCE_MISC_CFG); 1268157642Sps REG_WR(sc, BCE_MISC_CFG, val & ~BCE_MISC_CFG_NVM_WR_EN); 1269157642Sps} 1270157642Sps#endif 1271157642Sps 1272157642Sps 1273157642Sps/****************************************************************************/ 1274157642Sps/* Enable NVRAM access. */ 1275157642Sps/* */ 1276157642Sps/* Before accessing NVRAM for read or write operations the caller must */ 1277157642Sps/* enabled NVRAM access. */ 1278157642Sps/* */ 1279157642Sps/* Returns: */ 1280157642Sps/* Nothing. */ 1281157642Sps/****************************************************************************/ 1282157642Spsstatic void 1283157642Spsbce_enable_nvram_access(struct bce_softc *sc) 1284157642Sps{ 1285157642Sps u32 val; 1286157642Sps 1287157642Sps DBPRINT(sc, BCE_VERBOSE, "Enabling NVRAM access.\n"); 1288157642Sps 1289157642Sps val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE); 1290157642Sps /* Enable both bits, even on read. */ 1291157642Sps REG_WR(sc, BCE_NVM_ACCESS_ENABLE, 1292157642Sps val | BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN); 1293157642Sps} 1294157642Sps 1295157642Sps 1296157642Sps/****************************************************************************/ 1297157642Sps/* Disable NVRAM access. */ 1298157642Sps/* */ 1299157642Sps/* When the caller is finished accessing NVRAM access must be disabled. */ 1300157642Sps/* */ 1301157642Sps/* Returns: */ 1302157642Sps/* Nothing. */ 1303157642Sps/****************************************************************************/ 1304157642Spsstatic void 1305157642Spsbce_disable_nvram_access(struct bce_softc *sc) 1306157642Sps{ 1307157642Sps u32 val; 1308157642Sps 1309157642Sps DBPRINT(sc, BCE_VERBOSE, "Disabling NVRAM access.\n"); 1310157642Sps 1311157642Sps val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE); 1312157642Sps 1313157642Sps /* Disable both bits, even after read. */ 1314157642Sps REG_WR(sc, BCE_NVM_ACCESS_ENABLE, 1315157642Sps val & ~(BCE_NVM_ACCESS_ENABLE_EN | 1316157642Sps BCE_NVM_ACCESS_ENABLE_WR_EN)); 1317157642Sps} 1318157642Sps 1319157642Sps 1320157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT 1321157642Sps/****************************************************************************/ 1322157642Sps/* Erase NVRAM page before writing. */ 1323157642Sps/* */ 1324157642Sps/* Non-buffered flash parts require that a page be erased before it is */ 1325157642Sps/* written. */ 1326157642Sps/* */ 1327157642Sps/* Returns: */ 1328157642Sps/* 0 on success, positive value on failure. */ 1329157642Sps/****************************************************************************/ 1330157642Spsstatic int 1331157642Spsbce_nvram_erase_page(struct bce_softc *sc, u32 offset) 1332157642Sps{ 1333157642Sps u32 cmd; 1334157642Sps int j; 1335157642Sps 1336157642Sps /* Buffered flash doesn't require an erase. */ 1337157642Sps if (sc->bce_flash_info->buffered) 1338157642Sps return 0; 1339157642Sps 1340157642Sps DBPRINT(sc, BCE_VERBOSE, "Erasing NVRAM page.\n"); 1341157642Sps 1342157642Sps /* Build an erase command. */ 1343157642Sps cmd = BCE_NVM_COMMAND_ERASE | BCE_NVM_COMMAND_WR | 1344157642Sps BCE_NVM_COMMAND_DOIT; 1345157642Sps 1346157642Sps /* 1347157642Sps * Clear the DONE bit separately, set the NVRAM adress to erase, 1348157642Sps * and issue the erase command. 1349157642Sps */ 1350157642Sps REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE); 1351157642Sps REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE); 1352157642Sps REG_WR(sc, BCE_NVM_COMMAND, cmd); 1353157642Sps 1354157642Sps /* Wait for completion. */ 1355157642Sps */ 1356157642Sps for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 1357157642Sps u32 val; 1358157642Sps 1359157642Sps DELAY(5); 1360157642Sps 1361157642Sps val = REG_RD(sc, BCE_NVM_COMMAND); 1362157642Sps if (val & BCE_NVM_COMMAND_DONE) 1363157642Sps break; 1364157642Sps } 1365157642Sps 1366157642Sps if (j >= NVRAM_TIMEOUT_COUNT) { 1367157642Sps DBPRINT(sc, BCE_WARN, "Timeout erasing NVRAM.\n"); 1368157642Sps return EBUSY; 1369157642Sps } 1370157642Sps 1371157642Sps return 0; 1372157642Sps} 1373157642Sps#endif /* BCE_NVRAM_WRITE_SUPPORT */ 1374157642Sps 1375157642Sps 1376157642Sps/****************************************************************************/ 1377157642Sps/* Read a dword (32 bits) from NVRAM. */ 1378157642Sps/* */ 1379157642Sps/* Read a 32 bit word from NVRAM. The caller is assumed to have already */ 1380157642Sps/* obtained the NVRAM lock and enabled the controller for NVRAM access. */ 1381157642Sps/* */ 1382157642Sps/* Returns: */ 1383157642Sps/* 0 on success and the 32 bit value read, positive value on failure. */ 1384157642Sps/****************************************************************************/ 1385157642Spsstatic int 1386157642Spsbce_nvram_read_dword(struct bce_softc *sc, u32 offset, u8 *ret_val, 1387157642Sps u32 cmd_flags) 1388157642Sps{ 1389157642Sps u32 cmd; 1390157642Sps int i, rc = 0; 1391157642Sps 1392157642Sps /* Build the command word. */ 1393157642Sps cmd = BCE_NVM_COMMAND_DOIT | cmd_flags; 1394157642Sps 1395157642Sps /* Calculate the offset for buffered flash. */ 1396157642Sps if (sc->bce_flash_info->buffered) { 1397157642Sps offset = ((offset / sc->bce_flash_info->page_size) << 1398157642Sps sc->bce_flash_info->page_bits) + 1399157642Sps (offset % sc->bce_flash_info->page_size); 1400157642Sps } 1401157642Sps 1402157642Sps /* 1403157642Sps * Clear the DONE bit separately, set the address to read, 1404157642Sps * and issue the read. 1405157642Sps */ 1406157642Sps REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE); 1407157642Sps REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE); 1408157642Sps REG_WR(sc, BCE_NVM_COMMAND, cmd); 1409157642Sps 1410157642Sps /* Wait for completion. */ 1411157642Sps for (i = 0; i < NVRAM_TIMEOUT_COUNT; i++) { 1412157642Sps u32 val; 1413157642Sps 1414157642Sps DELAY(5); 1415157642Sps 1416157642Sps val = REG_RD(sc, BCE_NVM_COMMAND); 1417157642Sps if (val & BCE_NVM_COMMAND_DONE) { 1418157642Sps val = REG_RD(sc, BCE_NVM_READ); 1419157642Sps 1420157642Sps val = bce_be32toh(val); 1421157642Sps memcpy(ret_val, &val, 4); 1422157642Sps break; 1423157642Sps } 1424157642Sps } 1425157642Sps 1426157642Sps /* Check for errors. */ 1427157642Sps if (i >= NVRAM_TIMEOUT_COUNT) { 1428157642Sps BCE_PRINTF(sc, "%s(%d): Timeout error reading NVRAM at offset 0x%08X!\n", 1429157642Sps __FILE__, __LINE__, offset); 1430157642Sps rc = EBUSY; 1431157642Sps } 1432157642Sps 1433157642Sps return(rc); 1434157642Sps} 1435157642Sps 1436157642Sps 1437157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT 1438157642Sps/****************************************************************************/ 1439157642Sps/* Write a dword (32 bits) to NVRAM. */ 1440157642Sps/* */ 1441157642Sps/* Write a 32 bit word to NVRAM. The caller is assumed to have already */ 1442157642Sps/* obtained the NVRAM lock, enabled the controller for NVRAM access, and */ 1443157642Sps/* enabled NVRAM write access. */ 1444157642Sps/* */ 1445157642Sps/* Returns: */ 1446157642Sps/* 0 on success, positive value on failure. */ 1447157642Sps/****************************************************************************/ 1448157642Spsstatic int 1449157642Spsbce_nvram_write_dword(struct bce_softc *sc, u32 offset, u8 *val, 1450157642Sps u32 cmd_flags) 1451157642Sps{ 1452157642Sps u32 cmd, val32; 1453157642Sps int j; 1454157642Sps 1455157642Sps /* Build the command word. */ 1456157642Sps cmd = BCE_NVM_COMMAND_DOIT | BCE_NVM_COMMAND_WR | cmd_flags; 1457157642Sps 1458157642Sps /* Calculate the offset for buffered flash. */ 1459157642Sps if (sc->bce_flash_info->buffered) { 1460157642Sps offset = ((offset / sc->bce_flash_info->page_size) << 1461157642Sps sc->bce_flash_info->page_bits) + 1462157642Sps (offset % sc->bce_flash_info->page_size); 1463157642Sps } 1464157642Sps 1465157642Sps /* 1466157642Sps * Clear the DONE bit separately, convert NVRAM data to big-endian, 1467157642Sps * set the NVRAM address to write, and issue the write command 1468157642Sps */ 1469157642Sps REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE); 1470157642Sps memcpy(&val32, val, 4); 1471157642Sps val32 = htobe32(val32); 1472157642Sps REG_WR(sc, BCE_NVM_WRITE, val32); 1473157642Sps REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE); 1474157642Sps REG_WR(sc, BCE_NVM_COMMAND, cmd); 1475157642Sps 1476157642Sps /* Wait for completion. */ 1477157642Sps for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 1478157642Sps DELAY(5); 1479157642Sps 1480157642Sps if (REG_RD(sc, BCE_NVM_COMMAND) & BCE_NVM_COMMAND_DONE) 1481157642Sps break; 1482157642Sps } 1483157642Sps if (j >= NVRAM_TIMEOUT_COUNT) { 1484157642Sps BCE_PRINTF(sc, "%s(%d): Timeout error writing NVRAM at offset 0x%08X\n", 1485157642Sps __FILE__, __LINE__, offset); 1486157642Sps return EBUSY; 1487157642Sps } 1488157642Sps 1489157642Sps return 0; 1490157642Sps} 1491157642Sps#endif /* BCE_NVRAM_WRITE_SUPPORT */ 1492157642Sps 1493157642Sps 1494157642Sps/****************************************************************************/ 1495157642Sps/* Initialize NVRAM access. */ 1496157642Sps/* */ 1497157642Sps/* Identify the NVRAM device in use and prepare the NVRAM interface to */ 1498157642Sps/* access that device. */ 1499157642Sps/* */ 1500157642Sps/* Returns: */ 1501157642Sps/* 0 on success, positive value on failure. */ 1502157642Sps/****************************************************************************/ 1503157642Spsstatic int 1504157642Spsbce_init_nvram(struct bce_softc *sc) 1505157642Sps{ 1506157642Sps u32 val; 1507157642Sps int j, entry_count, rc; 1508157642Sps struct flash_spec *flash; 1509157642Sps 1510157642Sps DBPRINT(sc,BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 1511157642Sps 1512157642Sps /* Determine the selected interface. */ 1513157642Sps val = REG_RD(sc, BCE_NVM_CFG1); 1514157642Sps 1515157642Sps entry_count = sizeof(flash_table) / sizeof(struct flash_spec); 1516157642Sps 1517157642Sps rc = 0; 1518157642Sps 1519157642Sps /* 1520157642Sps * Flash reconfiguration is required to support additional 1521157642Sps * NVRAM devices not directly supported in hardware. 1522157642Sps * Check if the flash interface was reconfigured 1523157642Sps * by the bootcode. 1524157642Sps */ 1525157642Sps 1526157642Sps if (val & 0x40000000) { 1527157642Sps /* Flash interface reconfigured by bootcode. */ 1528157642Sps 1529157642Sps DBPRINT(sc,BCE_INFO_LOAD, 1530157642Sps "bce_init_nvram(): Flash WAS reconfigured.\n"); 1531157642Sps 1532157642Sps for (j = 0, flash = &flash_table[0]; j < entry_count; 1533157642Sps j++, flash++) { 1534157642Sps if ((val & FLASH_BACKUP_STRAP_MASK) == 1535157642Sps (flash->config1 & FLASH_BACKUP_STRAP_MASK)) { 1536157642Sps sc->bce_flash_info = flash; 1537157642Sps break; 1538157642Sps } 1539157642Sps } 1540157642Sps } else { 1541157642Sps /* Flash interface not yet reconfigured. */ 1542157642Sps u32 mask; 1543157642Sps 1544157642Sps DBPRINT(sc,BCE_INFO_LOAD, 1545157642Sps "bce_init_nvram(): Flash was NOT reconfigured.\n"); 1546157642Sps 1547157642Sps if (val & (1 << 23)) 1548157642Sps mask = FLASH_BACKUP_STRAP_MASK; 1549157642Sps else 1550157642Sps mask = FLASH_STRAP_MASK; 1551157642Sps 1552157642Sps /* Look for the matching NVRAM device configuration data. */ 1553157642Sps for (j = 0, flash = &flash_table[0]; j < entry_count; j++, flash++) { 1554157642Sps 1555157642Sps /* Check if the device matches any of the known devices. */ 1556157642Sps if ((val & mask) == (flash->strapping & mask)) { 1557157642Sps /* Found a device match. */ 1558157642Sps sc->bce_flash_info = flash; 1559157642Sps 1560157642Sps /* Request access to the flash interface. */ 1561157642Sps if ((rc = bce_acquire_nvram_lock(sc)) != 0) 1562157642Sps return rc; 1563157642Sps 1564157642Sps /* Reconfigure the flash interface. */ 1565157642Sps bce_enable_nvram_access(sc); 1566157642Sps REG_WR(sc, BCE_NVM_CFG1, flash->config1); 1567157642Sps REG_WR(sc, BCE_NVM_CFG2, flash->config2); 1568157642Sps REG_WR(sc, BCE_NVM_CFG3, flash->config3); 1569157642Sps REG_WR(sc, BCE_NVM_WRITE1, flash->write1); 1570157642Sps bce_disable_nvram_access(sc); 1571157642Sps bce_release_nvram_lock(sc); 1572157642Sps 1573157642Sps break; 1574157642Sps } 1575157642Sps } 1576157642Sps } 1577157642Sps 1578157642Sps /* Check if a matching device was found. */ 1579157642Sps if (j == entry_count) { 1580157642Sps sc->bce_flash_info = NULL; 1581157642Sps BCE_PRINTF(sc, "%s(%d): Unknown Flash NVRAM found!\n", 1582157642Sps __FILE__, __LINE__); 1583157642Sps rc = ENODEV; 1584157642Sps } 1585157642Sps 1586157642Sps /* Write the flash config data to the shared memory interface. */ 1587157642Sps val = REG_RD_IND(sc, sc->bce_shmem_base + BCE_SHARED_HW_CFG_CONFIG2); 1588157642Sps val &= BCE_SHARED_HW_CFG2_NVM_SIZE_MASK; 1589157642Sps if (val) 1590157642Sps sc->bce_flash_size = val; 1591157642Sps else 1592157642Sps sc->bce_flash_size = sc->bce_flash_info->total_size; 1593157642Sps 1594157642Sps DBPRINT(sc, BCE_INFO_LOAD, "bce_init_nvram() flash->total_size = 0x%08X\n", 1595157642Sps sc->bce_flash_info->total_size); 1596157642Sps 1597157642Sps DBPRINT(sc,BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 1598157642Sps 1599157642Sps return rc; 1600157642Sps} 1601157642Sps 1602157642Sps 1603157642Sps/****************************************************************************/ 1604157642Sps/* Read an arbitrary range of data from NVRAM. */ 1605157642Sps/* */ 1606157642Sps/* Prepares the NVRAM interface for access and reads the requested data */ 1607157642Sps/* into the supplied buffer. */ 1608157642Sps/* */ 1609157642Sps/* Returns: */ 1610157642Sps/* 0 on success and the data read, positive value on failure. */ 1611157642Sps/****************************************************************************/ 1612157642Spsstatic int 1613157642Spsbce_nvram_read(struct bce_softc *sc, u32 offset, u8 *ret_buf, 1614157642Sps int buf_size) 1615157642Sps{ 1616157642Sps int rc = 0; 1617157642Sps u32 cmd_flags, offset32, len32, extra; 1618157642Sps 1619157642Sps if (buf_size == 0) 1620157642Sps return 0; 1621157642Sps 1622157642Sps /* Request access to the flash interface. */ 1623157642Sps if ((rc = bce_acquire_nvram_lock(sc)) != 0) 1624157642Sps return rc; 1625157642Sps 1626157642Sps /* Enable access to flash interface */ 1627157642Sps bce_enable_nvram_access(sc); 1628157642Sps 1629157642Sps len32 = buf_size; 1630157642Sps offset32 = offset; 1631157642Sps extra = 0; 1632157642Sps 1633157642Sps cmd_flags = 0; 1634157642Sps 1635157642Sps if (offset32 & 3) { 1636157642Sps u8 buf[4]; 1637157642Sps u32 pre_len; 1638157642Sps 1639157642Sps offset32 &= ~3; 1640157642Sps pre_len = 4 - (offset & 3); 1641157642Sps 1642157642Sps if (pre_len >= len32) { 1643157642Sps pre_len = len32; 1644157642Sps cmd_flags = BCE_NVM_COMMAND_FIRST | BCE_NVM_COMMAND_LAST; 1645157642Sps } 1646157642Sps else { 1647157642Sps cmd_flags = BCE_NVM_COMMAND_FIRST; 1648157642Sps } 1649157642Sps 1650157642Sps rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags); 1651157642Sps 1652157642Sps if (rc) 1653157642Sps return rc; 1654157642Sps 1655157642Sps memcpy(ret_buf, buf + (offset & 3), pre_len); 1656157642Sps 1657157642Sps offset32 += 4; 1658157642Sps ret_buf += pre_len; 1659157642Sps len32 -= pre_len; 1660157642Sps } 1661157642Sps 1662157642Sps if (len32 & 3) { 1663157642Sps extra = 4 - (len32 & 3); 1664157642Sps len32 = (len32 + 4) & ~3; 1665157642Sps } 1666157642Sps 1667157642Sps if (len32 == 4) { 1668157642Sps u8 buf[4]; 1669157642Sps 1670157642Sps if (cmd_flags) 1671157642Sps cmd_flags = BCE_NVM_COMMAND_LAST; 1672157642Sps else 1673157642Sps cmd_flags = BCE_NVM_COMMAND_FIRST | 1674157642Sps BCE_NVM_COMMAND_LAST; 1675157642Sps 1676157642Sps rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags); 1677157642Sps 1678157642Sps memcpy(ret_buf, buf, 4 - extra); 1679157642Sps } 1680157642Sps else if (len32 > 0) { 1681157642Sps u8 buf[4]; 1682157642Sps 1683157642Sps /* Read the first word. */ 1684157642Sps if (cmd_flags) 1685157642Sps cmd_flags = 0; 1686157642Sps else 1687157642Sps cmd_flags = BCE_NVM_COMMAND_FIRST; 1688157642Sps 1689157642Sps rc = bce_nvram_read_dword(sc, offset32, ret_buf, cmd_flags); 1690157642Sps 1691157642Sps /* Advance to the next dword. */ 1692157642Sps offset32 += 4; 1693157642Sps ret_buf += 4; 1694157642Sps len32 -= 4; 1695157642Sps 1696157642Sps while (len32 > 4 && rc == 0) { 1697157642Sps rc = bce_nvram_read_dword(sc, offset32, ret_buf, 0); 1698157642Sps 1699157642Sps /* Advance to the next dword. */ 1700157642Sps offset32 += 4; 1701157642Sps ret_buf += 4; 1702157642Sps len32 -= 4; 1703157642Sps } 1704157642Sps 1705157642Sps if (rc) 1706157642Sps return rc; 1707157642Sps 1708157642Sps cmd_flags = BCE_NVM_COMMAND_LAST; 1709157642Sps rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags); 1710157642Sps 1711157642Sps memcpy(ret_buf, buf, 4 - extra); 1712157642Sps } 1713157642Sps 1714157642Sps /* Disable access to flash interface and release the lock. */ 1715157642Sps bce_disable_nvram_access(sc); 1716157642Sps bce_release_nvram_lock(sc); 1717157642Sps 1718157642Sps return rc; 1719157642Sps} 1720157642Sps 1721157642Sps 1722157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT 1723157642Sps/****************************************************************************/ 1724157642Sps/* Write an arbitrary range of data from NVRAM. */ 1725157642Sps/* */ 1726157642Sps/* Prepares the NVRAM interface for write access and writes the requested */ 1727157642Sps/* data from the supplied buffer. The caller is responsible for */ 1728157642Sps/* calculating any appropriate CRCs. */ 1729157642Sps/* */ 1730157642Sps/* Returns: */ 1731157642Sps/* 0 on success, positive value on failure. */ 1732157642Sps/****************************************************************************/ 1733157642Spsstatic int 1734157642Spsbce_nvram_write(struct bce_softc *sc, u32 offset, u8 *data_buf, 1735157642Sps int buf_size) 1736157642Sps{ 1737157642Sps u32 written, offset32, len32; 1738157642Sps u8 *buf, start[4], end[4]; 1739157642Sps int rc = 0; 1740157642Sps int align_start, align_end; 1741157642Sps 1742157642Sps buf = data_buf; 1743157642Sps offset32 = offset; 1744157642Sps len32 = buf_size; 1745157642Sps align_start = align_end = 0; 1746157642Sps 1747157642Sps if ((align_start = (offset32 & 3))) { 1748157642Sps offset32 &= ~3; 1749157642Sps len32 += align_start; 1750157642Sps if ((rc = bce_nvram_read(sc, offset32, start, 4))) 1751157642Sps return rc; 1752157642Sps } 1753157642Sps 1754157642Sps if (len32 & 3) { 1755157642Sps if ((len32 > 4) || !align_start) { 1756157642Sps align_end = 4 - (len32 & 3); 1757157642Sps len32 += align_end; 1758157642Sps if ((rc = bce_nvram_read(sc, offset32 + len32 - 4, 1759157642Sps end, 4))) { 1760157642Sps return rc; 1761157642Sps } 1762157642Sps } 1763157642Sps } 1764157642Sps 1765157642Sps if (align_start || align_end) { 1766157642Sps buf = malloc(len32, M_DEVBUF, M_NOWAIT); 1767157642Sps if (buf == 0) 1768157642Sps return ENOMEM; 1769157642Sps if (align_start) { 1770157642Sps memcpy(buf, start, 4); 1771157642Sps } 1772157642Sps if (align_end) { 1773157642Sps memcpy(buf + len32 - 4, end, 4); 1774157642Sps } 1775157642Sps memcpy(buf + align_start, data_buf, buf_size); 1776157642Sps } 1777157642Sps 1778157642Sps written = 0; 1779157642Sps while ((written < len32) && (rc == 0)) { 1780157642Sps u32 page_start, page_end, data_start, data_end; 1781157642Sps u32 addr, cmd_flags; 1782157642Sps int i; 1783157642Sps u8 flash_buffer[264]; 1784157642Sps 1785157642Sps /* Find the page_start addr */ 1786157642Sps page_start = offset32 + written; 1787157642Sps page_start -= (page_start % sc->bce_flash_info->page_size); 1788157642Sps /* Find the page_end addr */ 1789157642Sps page_end = page_start + sc->bce_flash_info->page_size; 1790157642Sps /* Find the data_start addr */ 1791157642Sps data_start = (written == 0) ? offset32 : page_start; 1792157642Sps /* Find the data_end addr */ 1793157642Sps data_end = (page_end > offset32 + len32) ? 1794157642Sps (offset32 + len32) : page_end; 1795157642Sps 1796157642Sps /* Request access to the flash interface. */ 1797157642Sps if ((rc = bce_acquire_nvram_lock(sc)) != 0) 1798157642Sps goto nvram_write_end; 1799157642Sps 1800157642Sps /* Enable access to flash interface */ 1801157642Sps bce_enable_nvram_access(sc); 1802157642Sps 1803157642Sps cmd_flags = BCE_NVM_COMMAND_FIRST; 1804157642Sps if (sc->bce_flash_info->buffered == 0) { 1805157642Sps int j; 1806157642Sps 1807157642Sps /* Read the whole page into the buffer 1808157642Sps * (non-buffer flash only) */ 1809157642Sps for (j = 0; j < sc->bce_flash_info->page_size; j += 4) { 1810157642Sps if (j == (sc->bce_flash_info->page_size - 4)) { 1811157642Sps cmd_flags |= BCE_NVM_COMMAND_LAST; 1812157642Sps } 1813157642Sps rc = bce_nvram_read_dword(sc, 1814157642Sps page_start + j, 1815157642Sps &flash_buffer[j], 1816157642Sps cmd_flags); 1817157642Sps 1818157642Sps if (rc) 1819157642Sps goto nvram_write_end; 1820157642Sps 1821157642Sps cmd_flags = 0; 1822157642Sps } 1823157642Sps } 1824157642Sps 1825157642Sps /* Enable writes to flash interface (unlock write-protect) */ 1826157642Sps if ((rc = bce_enable_nvram_write(sc)) != 0) 1827157642Sps goto nvram_write_end; 1828157642Sps 1829157642Sps /* Erase the page */ 1830157642Sps if ((rc = bce_nvram_erase_page(sc, page_start)) != 0) 1831157642Sps goto nvram_write_end; 1832157642Sps 1833157642Sps /* Re-enable the write again for the actual write */ 1834157642Sps bce_enable_nvram_write(sc); 1835157642Sps 1836157642Sps /* Loop to write back the buffer data from page_start to 1837157642Sps * data_start */ 1838157642Sps i = 0; 1839157642Sps if (sc->bce_flash_info->buffered == 0) { 1840157642Sps for (addr = page_start; addr < data_start; 1841157642Sps addr += 4, i += 4) { 1842157642Sps 1843157642Sps rc = bce_nvram_write_dword(sc, addr, 1844157642Sps &flash_buffer[i], cmd_flags); 1845157642Sps 1846157642Sps if (rc != 0) 1847157642Sps goto nvram_write_end; 1848157642Sps 1849157642Sps cmd_flags = 0; 1850157642Sps } 1851157642Sps } 1852157642Sps 1853157642Sps /* Loop to write the new data from data_start to data_end */ 1854157642Sps for (addr = data_start; addr < data_end; addr += 4, i++) { 1855157642Sps if ((addr == page_end - 4) || 1856157642Sps ((sc->bce_flash_info->buffered) && 1857157642Sps (addr == data_end - 4))) { 1858157642Sps 1859157642Sps cmd_flags |= BCE_NVM_COMMAND_LAST; 1860157642Sps } 1861157642Sps rc = bce_nvram_write_dword(sc, addr, buf, 1862157642Sps cmd_flags); 1863157642Sps 1864157642Sps if (rc != 0) 1865157642Sps goto nvram_write_end; 1866157642Sps 1867157642Sps cmd_flags = 0; 1868157642Sps buf += 4; 1869157642Sps } 1870157642Sps 1871157642Sps /* Loop to write back the buffer data from data_end 1872157642Sps * to page_end */ 1873157642Sps if (sc->bce_flash_info->buffered == 0) { 1874157642Sps for (addr = data_end; addr < page_end; 1875157642Sps addr += 4, i += 4) { 1876157642Sps 1877157642Sps if (addr == page_end-4) { 1878157642Sps cmd_flags = BCE_NVM_COMMAND_LAST; 1879157642Sps } 1880157642Sps rc = bce_nvram_write_dword(sc, addr, 1881157642Sps &flash_buffer[i], cmd_flags); 1882157642Sps 1883157642Sps if (rc != 0) 1884157642Sps goto nvram_write_end; 1885157642Sps 1886157642Sps cmd_flags = 0; 1887157642Sps } 1888157642Sps } 1889157642Sps 1890157642Sps /* Disable writes to flash interface (lock write-protect) */ 1891157642Sps bce_disable_nvram_write(sc); 1892157642Sps 1893157642Sps /* Disable access to flash interface */ 1894157642Sps bce_disable_nvram_access(sc); 1895157642Sps bce_release_nvram_lock(sc); 1896157642Sps 1897157642Sps /* Increment written */ 1898157642Sps written += data_end - data_start; 1899157642Sps } 1900157642Sps 1901157642Spsnvram_write_end: 1902157642Sps if (align_start || align_end) 1903157642Sps free(buf, M_DEVBUF); 1904157642Sps 1905157642Sps return rc; 1906157642Sps} 1907157642Sps#endif /* BCE_NVRAM_WRITE_SUPPORT */ 1908157642Sps 1909157642Sps 1910157642Sps/****************************************************************************/ 1911157642Sps/* Verifies that NVRAM is accessible and contains valid data. */ 1912157642Sps/* */ 1913157642Sps/* Reads the configuration data from NVRAM and verifies that the CRC is */ 1914157642Sps/* correct. */ 1915157642Sps/* */ 1916157642Sps/* Returns: */ 1917157642Sps/* 0 on success, positive value on failure. */ 1918157642Sps/****************************************************************************/ 1919157642Spsstatic int 1920157642Spsbce_nvram_test(struct bce_softc *sc) 1921157642Sps{ 1922157642Sps u32 buf[BCE_NVRAM_SIZE / 4]; 1923157642Sps u8 *data = (u8 *) buf; 1924157642Sps int rc = 0; 1925157642Sps u32 magic, csum; 1926157642Sps 1927157642Sps 1928157642Sps /* 1929157642Sps * Check that the device NVRAM is valid by reading 1930157642Sps * the magic value at offset 0. 1931157642Sps */ 1932157642Sps if ((rc = bce_nvram_read(sc, 0, data, 4)) != 0) 1933157642Sps goto bce_nvram_test_done; 1934157642Sps 1935157642Sps 1936157642Sps magic = bce_be32toh(buf[0]); 1937157642Sps if (magic != BCE_NVRAM_MAGIC) { 1938157642Sps rc = ENODEV; 1939157642Sps BCE_PRINTF(sc, "%s(%d): Invalid NVRAM magic value! Expected: 0x%08X, " 1940157642Sps "Found: 0x%08X\n", 1941157642Sps __FILE__, __LINE__, BCE_NVRAM_MAGIC, magic); 1942157642Sps goto bce_nvram_test_done; 1943157642Sps } 1944157642Sps 1945157642Sps /* 1946157642Sps * Verify that the device NVRAM includes valid 1947157642Sps * configuration data. 1948157642Sps */ 1949157642Sps if ((rc = bce_nvram_read(sc, 0x100, data, BCE_NVRAM_SIZE)) != 0) 1950157642Sps goto bce_nvram_test_done; 1951157642Sps 1952157642Sps csum = ether_crc32_le(data, 0x100); 1953157642Sps if (csum != BCE_CRC32_RESIDUAL) { 1954157642Sps rc = ENODEV; 1955157642Sps BCE_PRINTF(sc, "%s(%d): Invalid Manufacturing Information NVRAM CRC! " 1956157642Sps "Expected: 0x%08X, Found: 0x%08X\n", 1957157642Sps __FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum); 1958157642Sps goto bce_nvram_test_done; 1959157642Sps } 1960157642Sps 1961157642Sps csum = ether_crc32_le(data + 0x100, 0x100); 1962157642Sps if (csum != BCE_CRC32_RESIDUAL) { 1963157642Sps BCE_PRINTF(sc, "%s(%d): Invalid Feature Configuration Information " 1964157642Sps "NVRAM CRC! Expected: 0x%08X, Found: 08%08X\n", 1965157642Sps __FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum); 1966157642Sps rc = ENODEV; 1967157642Sps } 1968157642Sps 1969157642Spsbce_nvram_test_done: 1970157642Sps return rc; 1971157642Sps} 1972157642Sps 1973157642Sps 1974157642Sps/****************************************************************************/ 1975157642Sps/* Free any DMA memory owned by the driver. */ 1976157642Sps/* */ 1977157642Sps/* Scans through each data structre that requires DMA memory and frees */ 1978157642Sps/* the memory if allocated. */ 1979157642Sps/* */ 1980157642Sps/* Returns: */ 1981157642Sps/* Nothing. */ 1982157642Sps/****************************************************************************/ 1983157642Spsstatic void 1984157642Spsbce_dma_free(struct bce_softc *sc) 1985157642Sps{ 1986157642Sps int i; 1987157642Sps 1988157642Sps DBPRINT(sc,BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 1989157642Sps 1990157642Sps /* Destroy the status block. */ 1991157642Sps if (sc->status_block != NULL) 1992157642Sps bus_dmamem_free( 1993157642Sps sc->status_tag, 1994157642Sps sc->status_block, 1995157642Sps sc->status_map); 1996157642Sps 1997157642Sps if (sc->status_map != NULL) { 1998157642Sps bus_dmamap_unload( 1999157642Sps sc->status_tag, 2000157642Sps sc->status_map); 2001157642Sps bus_dmamap_destroy(sc->status_tag, 2002157642Sps sc->status_map); 2003157642Sps } 2004157642Sps 2005157642Sps if (sc->status_tag != NULL) 2006157642Sps bus_dma_tag_destroy(sc->status_tag); 2007157642Sps 2008157642Sps 2009157642Sps /* Destroy the statistics block. */ 2010157642Sps if (sc->stats_block != NULL) 2011157642Sps bus_dmamem_free( 2012157642Sps sc->stats_tag, 2013157642Sps sc->stats_block, 2014157642Sps sc->stats_map); 2015157642Sps 2016157642Sps if (sc->stats_map != NULL) { 2017157642Sps bus_dmamap_unload( 2018157642Sps sc->stats_tag, 2019157642Sps sc->stats_map); 2020157642Sps bus_dmamap_destroy(sc->stats_tag, 2021157642Sps sc->stats_map); 2022157642Sps } 2023157642Sps 2024157642Sps if (sc->stats_tag != NULL) 2025157642Sps bus_dma_tag_destroy(sc->stats_tag); 2026157642Sps 2027157642Sps 2028157642Sps /* Free, unmap and destroy all TX buffer descriptor chain pages. */ 2029157642Sps for (i = 0; i < TX_PAGES; i++ ) { 2030157642Sps if (sc->tx_bd_chain[i] != NULL) 2031157642Sps bus_dmamem_free( 2032157642Sps sc->tx_bd_chain_tag, 2033157642Sps sc->tx_bd_chain[i], 2034157642Sps sc->tx_bd_chain_map[i]); 2035157642Sps 2036157642Sps if (sc->tx_bd_chain_map[i] != NULL) { 2037157642Sps bus_dmamap_unload( 2038157642Sps sc->tx_bd_chain_tag, 2039157642Sps sc->tx_bd_chain_map[i]); 2040157642Sps bus_dmamap_destroy( 2041157642Sps sc->tx_bd_chain_tag, 2042157642Sps sc->tx_bd_chain_map[i]); 2043157642Sps } 2044157642Sps 2045157642Sps } 2046157642Sps 2047157642Sps /* Destroy the TX buffer descriptor tag. */ 2048157642Sps if (sc->tx_bd_chain_tag != NULL) 2049157642Sps bus_dma_tag_destroy(sc->tx_bd_chain_tag); 2050157642Sps 2051157642Sps 2052157642Sps /* Free, unmap and destroy all RX buffer descriptor chain pages. */ 2053157642Sps for (i = 0; i < RX_PAGES; i++ ) { 2054157642Sps if (sc->rx_bd_chain[i] != NULL) 2055157642Sps bus_dmamem_free( 2056157642Sps sc->rx_bd_chain_tag, 2057157642Sps sc->rx_bd_chain[i], 2058157642Sps sc->rx_bd_chain_map[i]); 2059157642Sps 2060157642Sps if (sc->rx_bd_chain_map[i] != NULL) { 2061157642Sps bus_dmamap_unload( 2062157642Sps sc->rx_bd_chain_tag, 2063157642Sps sc->rx_bd_chain_map[i]); 2064157642Sps bus_dmamap_destroy( 2065157642Sps sc->rx_bd_chain_tag, 2066157642Sps sc->rx_bd_chain_map[i]); 2067157642Sps } 2068157642Sps } 2069157642Sps 2070157642Sps /* Destroy the RX buffer descriptor tag. */ 2071157642Sps if (sc->rx_bd_chain_tag != NULL) 2072157642Sps bus_dma_tag_destroy(sc->rx_bd_chain_tag); 2073157642Sps 2074157642Sps 2075157642Sps /* Unload and destroy the TX mbuf maps. */ 2076157642Sps for (i = 0; i < TOTAL_TX_BD; i++) { 2077157642Sps if (sc->tx_mbuf_map[i] != NULL) { 2078157642Sps bus_dmamap_unload(sc->tx_mbuf_tag, 2079157642Sps sc->tx_mbuf_map[i]); 2080157642Sps bus_dmamap_destroy(sc->tx_mbuf_tag, 2081157642Sps sc->tx_mbuf_map[i]); 2082157642Sps } 2083157642Sps } 2084157642Sps 2085157642Sps /* Destroy the TX mbuf tag. */ 2086157642Sps if (sc->tx_mbuf_tag != NULL) 2087157642Sps bus_dma_tag_destroy(sc->tx_mbuf_tag); 2088157642Sps 2089157642Sps 2090157642Sps /* Unload and destroy the RX mbuf maps. */ 2091157642Sps for (i = 0; i < TOTAL_RX_BD; i++) { 2092157642Sps if (sc->rx_mbuf_map[i] != NULL) { 2093157642Sps bus_dmamap_unload(sc->rx_mbuf_tag, 2094157642Sps sc->rx_mbuf_map[i]); 2095157642Sps bus_dmamap_destroy(sc->rx_mbuf_tag, 2096157642Sps sc->rx_mbuf_map[i]); 2097157642Sps } 2098157642Sps } 2099157642Sps 2100157642Sps /* Destroy the RX mbuf tag. */ 2101157642Sps if (sc->rx_mbuf_tag != NULL) 2102157642Sps bus_dma_tag_destroy(sc->rx_mbuf_tag); 2103157642Sps 2104157642Sps 2105157642Sps /* Destroy the parent tag */ 2106157642Sps if (sc->parent_tag != NULL) 2107157642Sps bus_dma_tag_destroy(sc->parent_tag); 2108157642Sps 2109157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 2110157642Sps 2111157642Sps} 2112157642Sps 2113157642Sps 2114157642Sps/****************************************************************************/ 2115157642Sps/* Get DMA memory from the OS. */ 2116157642Sps/* */ 2117157642Sps/* Validates that the OS has provided DMA buffers in response to a */ 2118157642Sps/* bus_dmamap_load() call and saves the physical address of those buffers. */ 2119157642Sps/* When the callback is used the OS will return 0 for the mapping function */ 2120157642Sps/* (bus_dmamap_load()) so we use the value of map_arg->maxsegs to pass any */ 2121157642Sps/* failures back to the caller. */ 2122157642Sps/* */ 2123157642Sps/* Returns: */ 2124157642Sps/* Nothing. */ 2125157642Sps/****************************************************************************/ 2126157642Spsstatic void 2127157642Spsbce_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2128157642Sps{ 2129157642Sps struct bce_dmamap_arg *map_arg = arg; 2130157642Sps struct bce_softc *sc = map_arg->sc; 2131157642Sps 2132157642Sps /* Simulate a mapping failure. */ 2133157642Sps DBRUNIF(DB_RANDOMTRUE(bce_debug_dma_map_addr_failure), 2134157642Sps BCE_PRINTF(sc, "%s(%d): Simulating DMA mapping error.\n", 2135157642Sps __FILE__, __LINE__); 2136157642Sps error = ENOMEM); 2137157642Sps 2138157642Sps /* Check for an error and signal the caller that an error occurred. */ 2139157642Sps if (error || (nseg > map_arg->maxsegs)) { 2140157642Sps BCE_PRINTF(sc, "%s(%d): DMA mapping error! error = %d, " 2141157642Sps "nseg = %d, maxsegs = %d\n", 2142157642Sps __FILE__, __LINE__, error, nseg, map_arg->maxsegs); 2143157642Sps map_arg->maxsegs = 0; 2144157642Sps goto bce_dma_map_addr_exit; 2145157642Sps } 2146157642Sps 2147157642Sps map_arg->busaddr = segs->ds_addr; 2148157642Sps 2149157642Spsbce_dma_map_addr_exit: 2150157642Sps return; 2151157642Sps} 2152157642Sps 2153157642Sps 2154157642Sps/****************************************************************************/ 2155157642Sps/* Map TX buffers into TX buffer descriptors. */ 2156157642Sps/* */ 2157157642Sps/* Given a series of DMA memory containting an outgoing frame, map the */ 2158157642Sps/* segments into the tx_bd structure used by the hardware. */ 2159157642Sps/* */ 2160157642Sps/* Returns: */ 2161157642Sps/* Nothing. */ 2162157642Sps/****************************************************************************/ 2163157642Spsstatic void 2164157642Spsbce_dma_map_tx_desc(void *arg, bus_dma_segment_t *segs, 2165157642Sps int nseg, bus_size_t mapsize, int error) 2166157642Sps{ 2167157642Sps struct bce_dmamap_arg *map_arg; 2168157642Sps struct bce_softc *sc; 2169157642Sps struct tx_bd *txbd = NULL; 2170157642Sps int i = 0; 2171157642Sps u16 prod, chain_prod; 2172157642Sps u32 prod_bseq; 2173157642Sps#ifdef BCE_DEBUG 2174157642Sps u16 debug_prod; 2175157642Sps#endif 2176157642Sps 2177157642Sps map_arg = arg; 2178157642Sps sc = map_arg->sc; 2179157642Sps 2180157642Sps if (error) { 2181157642Sps DBPRINT(sc, BCE_WARN, "%s(): Called with error = %d\n", 2182157642Sps __FUNCTION__, error); 2183157642Sps return; 2184157642Sps } 2185157642Sps 2186157642Sps /* Signal error to caller if there's too many segments */ 2187157642Sps if (nseg > map_arg->maxsegs) { 2188157642Sps DBPRINT(sc, BCE_WARN, 2189157642Sps "%s(): Mapped TX descriptors: max segs = %d, " 2190157642Sps "actual segs = %d\n", 2191157642Sps __FUNCTION__, map_arg->maxsegs, nseg); 2192157642Sps 2193157642Sps map_arg->maxsegs = 0; 2194157642Sps return; 2195157642Sps } 2196157642Sps 2197157642Sps /* prod points to an empty tx_bd at this point. */ 2198157642Sps prod = map_arg->prod; 2199157642Sps chain_prod = map_arg->chain_prod; 2200157642Sps prod_bseq = map_arg->prod_bseq; 2201157642Sps 2202157642Sps#ifdef BCE_DEBUG 2203157642Sps debug_prod = chain_prod; 2204157642Sps#endif 2205157642Sps 2206157642Sps DBPRINT(sc, BCE_INFO_SEND, 2207157642Sps "%s(): Start: prod = 0x%04X, chain_prod = %04X, " 2208157642Sps "prod_bseq = 0x%08X\n", 2209157642Sps __FUNCTION__, prod, chain_prod, prod_bseq); 2210157642Sps 2211157642Sps /* 2212157642Sps * Cycle through each mbuf segment that makes up 2213157642Sps * the outgoing frame, gathering the mapping info 2214157642Sps * for that segment and creating a tx_bd to for 2215157642Sps * the mbuf. 2216157642Sps */ 2217157642Sps 2218157642Sps txbd = &map_arg->tx_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)]; 2219157642Sps 2220157642Sps /* Setup the first tx_bd for the first segment. */ 2221157642Sps txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr)); 2222157642Sps txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr)); 2223157642Sps txbd->tx_bd_mss_nbytes = htole16(segs[i].ds_len); 2224157642Sps txbd->tx_bd_vlan_tag_flags = htole16(map_arg->tx_flags | 2225157642Sps TX_BD_FLAGS_START); 2226157642Sps prod_bseq += segs[i].ds_len; 2227157642Sps 2228157642Sps /* Setup any remaing segments. */ 2229157642Sps for (i = 1; i < nseg; i++) { 2230157642Sps prod = NEXT_TX_BD(prod); 2231157642Sps chain_prod = TX_CHAIN_IDX(prod); 2232157642Sps 2233157642Sps txbd = &map_arg->tx_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)]; 2234157642Sps 2235157642Sps txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr)); 2236157642Sps txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr)); 2237157642Sps txbd->tx_bd_mss_nbytes = htole16(segs[i].ds_len); 2238157642Sps txbd->tx_bd_vlan_tag_flags = htole16(map_arg->tx_flags); 2239157642Sps 2240157642Sps prod_bseq += segs[i].ds_len; 2241157642Sps } 2242157642Sps 2243157642Sps /* Set the END flag on the last TX buffer descriptor. */ 2244157642Sps txbd->tx_bd_vlan_tag_flags |= htole16(TX_BD_FLAGS_END); 2245157642Sps 2246157642Sps DBRUN(BCE_INFO_SEND, bce_dump_tx_chain(sc, debug_prod, nseg)); 2247157642Sps 2248157642Sps DBPRINT(sc, BCE_INFO_SEND, 2249157642Sps "%s(): End: prod = 0x%04X, chain_prod = %04X, " 2250157642Sps "prod_bseq = 0x%08X\n", 2251157642Sps __FUNCTION__, prod, chain_prod, prod_bseq); 2252157642Sps 2253157642Sps /* prod points to the last tx_bd at this point. */ 2254157642Sps map_arg->maxsegs = nseg; 2255157642Sps map_arg->prod = prod; 2256157642Sps map_arg->chain_prod = chain_prod; 2257157642Sps map_arg->prod_bseq = prod_bseq; 2258157642Sps} 2259157642Sps 2260157642Sps 2261157642Sps/****************************************************************************/ 2262157642Sps/* Allocate any DMA memory needed by the driver. */ 2263157642Sps/* */ 2264157642Sps/* Allocates DMA memory needed for the various global structures needed by */ 2265157642Sps/* hardware. */ 2266157642Sps/* */ 2267157642Sps/* Returns: */ 2268157642Sps/* 0 for success, positive value for failure. */ 2269157642Sps/****************************************************************************/ 2270157642Spsstatic int 2271157642Spsbce_dma_alloc(device_t dev) 2272157642Sps{ 2273157642Sps struct bce_softc *sc; 2274157642Sps int i, error, rc = 0; 2275157642Sps struct bce_dmamap_arg map_arg; 2276157642Sps 2277157642Sps sc = device_get_softc(dev); 2278157642Sps 2279157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 2280157642Sps 2281157642Sps /* 2282157642Sps * Allocate the parent bus DMA tag appropriate for PCI. 2283157642Sps */ 2284157642Sps if (bus_dma_tag_create(NULL, /* parent */ 2285157642Sps BCE_DMA_ALIGN, /* alignment */ 2286157642Sps BCE_DMA_BOUNDARY, /* boundary */ 2287157642Sps sc->max_bus_addr, /* lowaddr */ 2288157642Sps BUS_SPACE_MAXADDR, /* highaddr */ 2289157642Sps NULL, /* filterfunc */ 2290157642Sps NULL, /* filterarg */ 2291157642Sps MAXBSIZE, /* maxsize */ 2292157642Sps BUS_SPACE_UNRESTRICTED, /* nsegments */ 2293157642Sps BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 2294157642Sps 0, /* flags */ 2295157642Sps NULL, /* locfunc */ 2296157642Sps NULL, /* lockarg */ 2297157642Sps &sc->parent_tag)) { 2298157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate parent DMA tag!\n", 2299157642Sps __FILE__, __LINE__); 2300157642Sps rc = ENOMEM; 2301157642Sps goto bce_dma_alloc_exit; 2302157642Sps } 2303157642Sps 2304157642Sps /* 2305157642Sps * Create a DMA tag for the status block, allocate and clear the 2306157642Sps * memory, map the memory into DMA space, and fetch the physical 2307157642Sps * address of the block. 2308157642Sps */ 2309157642Sps if (bus_dma_tag_create( 2310157642Sps sc->parent_tag, /* parent */ 2311157642Sps BCE_DMA_ALIGN, /* alignment */ 2312157642Sps BCE_DMA_BOUNDARY, /* boundary */ 2313157642Sps sc->max_bus_addr, /* lowaddr */ 2314157642Sps BUS_SPACE_MAXADDR, /* highaddr */ 2315157642Sps NULL, /* filterfunc */ 2316157642Sps NULL, /* filterarg */ 2317157642Sps BCE_STATUS_BLK_SZ, /* maxsize */ 2318157642Sps 1, /* nsegments */ 2319157642Sps BCE_STATUS_BLK_SZ, /* maxsegsize */ 2320157642Sps 0, /* flags */ 2321157642Sps NULL, /* lockfunc */ 2322157642Sps NULL, /* lockarg */ 2323157642Sps &sc->status_tag)) { 2324157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate status block DMA tag!\n", 2325157642Sps __FILE__, __LINE__); 2326157642Sps rc = ENOMEM; 2327157642Sps goto bce_dma_alloc_exit; 2328157642Sps } 2329157642Sps 2330157642Sps if(bus_dmamem_alloc( 2331157642Sps sc->status_tag, /* dmat */ 2332157642Sps (void **)&sc->status_block, /* vaddr */ 2333157642Sps BUS_DMA_NOWAIT, /* flags */ 2334157642Sps &sc->status_map)) { 2335157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate status block DMA memory!\n", 2336157642Sps __FILE__, __LINE__); 2337157642Sps rc = ENOMEM; 2338157642Sps goto bce_dma_alloc_exit; 2339157642Sps } 2340157642Sps 2341157642Sps bzero((char *)sc->status_block, BCE_STATUS_BLK_SZ); 2342157642Sps 2343157642Sps map_arg.sc = sc; 2344157642Sps map_arg.maxsegs = 1; 2345157642Sps 2346157642Sps error = bus_dmamap_load( 2347157642Sps sc->status_tag, /* dmat */ 2348157642Sps sc->status_map, /* map */ 2349157642Sps sc->status_block, /* buf */ 2350157642Sps BCE_STATUS_BLK_SZ, /* buflen */ 2351157642Sps bce_dma_map_addr, /* callback */ 2352157642Sps &map_arg, /* callbackarg */ 2353157642Sps BUS_DMA_NOWAIT); /* flags */ 2354157642Sps 2355157642Sps if(error || (map_arg.maxsegs == 0)) { 2356157642Sps BCE_PRINTF(sc, "%s(%d): Could not map status block DMA memory!\n", 2357157642Sps __FILE__, __LINE__); 2358157642Sps rc = ENOMEM; 2359157642Sps goto bce_dma_alloc_exit; 2360157642Sps } 2361157642Sps 2362157642Sps sc->status_block_paddr = map_arg.busaddr; 2363157642Sps /* DRC - Fix for 64 bit addresses. */ 2364157642Sps DBPRINT(sc, BCE_INFO, "status_block_paddr = 0x%08X\n", 2365157642Sps (u32) sc->status_block_paddr); 2366157642Sps 2367157642Sps /* 2368157642Sps * Create a DMA tag for the statistics block, allocate and clear the 2369157642Sps * memory, map the memory into DMA space, and fetch the physical 2370157642Sps * address of the block. 2371157642Sps */ 2372157642Sps if (bus_dma_tag_create( 2373157642Sps sc->parent_tag, /* parent */ 2374157642Sps BCE_DMA_ALIGN, /* alignment */ 2375157642Sps BCE_DMA_BOUNDARY, /* boundary */ 2376157642Sps sc->max_bus_addr, /* lowaddr */ 2377157642Sps BUS_SPACE_MAXADDR, /* highaddr */ 2378157642Sps NULL, /* filterfunc */ 2379157642Sps NULL, /* filterarg */ 2380157642Sps BCE_STATS_BLK_SZ, /* maxsize */ 2381157642Sps 1, /* nsegments */ 2382157642Sps BCE_STATS_BLK_SZ, /* maxsegsize */ 2383157642Sps 0, /* flags */ 2384157642Sps NULL, /* lockfunc */ 2385157642Sps NULL, /* lockarg */ 2386157642Sps &sc->stats_tag)) { 2387157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate statistics block DMA tag!\n", 2388157642Sps __FILE__, __LINE__); 2389157642Sps rc = ENOMEM; 2390157642Sps goto bce_dma_alloc_exit; 2391157642Sps } 2392157642Sps 2393157642Sps if (bus_dmamem_alloc( 2394157642Sps sc->stats_tag, /* dmat */ 2395157642Sps (void **)&sc->stats_block, /* vaddr */ 2396157642Sps BUS_DMA_NOWAIT, /* flags */ 2397157642Sps &sc->stats_map)) { 2398157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate statistics block DMA memory!\n", 2399157642Sps __FILE__, __LINE__); 2400157642Sps rc = ENOMEM; 2401157642Sps goto bce_dma_alloc_exit; 2402157642Sps } 2403157642Sps 2404157642Sps bzero((char *)sc->stats_block, BCE_STATS_BLK_SZ); 2405157642Sps 2406157642Sps map_arg.sc = sc; 2407157642Sps map_arg.maxsegs = 1; 2408157642Sps 2409157642Sps error = bus_dmamap_load( 2410157642Sps sc->stats_tag, /* dmat */ 2411157642Sps sc->stats_map, /* map */ 2412157642Sps sc->stats_block, /* buf */ 2413157642Sps BCE_STATS_BLK_SZ, /* buflen */ 2414157642Sps bce_dma_map_addr, /* callback */ 2415157642Sps &map_arg, /* callbackarg */ 2416157642Sps BUS_DMA_NOWAIT); /* flags */ 2417157642Sps 2418157642Sps if(error || (map_arg.maxsegs == 0)) { 2419157642Sps BCE_PRINTF(sc, "%s(%d): Could not map statistics block DMA memory!\n", 2420157642Sps __FILE__, __LINE__); 2421157642Sps rc = ENOMEM; 2422157642Sps goto bce_dma_alloc_exit; 2423157642Sps } 2424157642Sps 2425157642Sps sc->stats_block_paddr = map_arg.busaddr; 2426157642Sps /* DRC - Fix for 64 bit address. */ 2427157642Sps DBPRINT(sc,BCE_INFO, "stats_block_paddr = 0x%08X\n", 2428157642Sps (u32) sc->stats_block_paddr); 2429157642Sps 2430157642Sps /* 2431157642Sps * Create a DMA tag for the TX buffer descriptor chain, 2432157642Sps * allocate and clear the memory, and fetch the 2433157642Sps * physical address of the block. 2434157642Sps */ 2435157642Sps if(bus_dma_tag_create( 2436157642Sps sc->parent_tag, /* parent */ 2437157642Sps BCM_PAGE_SIZE, /* alignment */ 2438157642Sps BCE_DMA_BOUNDARY, /* boundary */ 2439157642Sps sc->max_bus_addr, /* lowaddr */ 2440157642Sps BUS_SPACE_MAXADDR, /* highaddr */ 2441157642Sps NULL, /* filterfunc */ 2442157642Sps NULL, /* filterarg */ 2443157642Sps BCE_TX_CHAIN_PAGE_SZ, /* maxsize */ 2444157642Sps 1, /* nsegments */ 2445157642Sps BCE_TX_CHAIN_PAGE_SZ, /* maxsegsize */ 2446157642Sps 0, /* flags */ 2447157642Sps NULL, /* lockfunc */ 2448157642Sps NULL, /* lockarg */ 2449157642Sps &sc->tx_bd_chain_tag)) { 2450157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate TX descriptor chain DMA tag!\n", 2451157642Sps __FILE__, __LINE__); 2452157642Sps rc = ENOMEM; 2453157642Sps goto bce_dma_alloc_exit; 2454157642Sps } 2455157642Sps 2456157642Sps for (i = 0; i < TX_PAGES; i++) { 2457157642Sps 2458157642Sps if(bus_dmamem_alloc( 2459157642Sps sc->tx_bd_chain_tag, /* tag */ 2460157642Sps (void **)&sc->tx_bd_chain[i], /* vaddr */ 2461157642Sps BUS_DMA_NOWAIT, /* flags */ 2462157642Sps &sc->tx_bd_chain_map[i])) { 2463157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate TX descriptor " 2464157642Sps "chain DMA memory!\n", __FILE__, __LINE__); 2465157642Sps rc = ENOMEM; 2466157642Sps goto bce_dma_alloc_exit; 2467157642Sps } 2468157642Sps 2469157642Sps map_arg.maxsegs = 1; 2470157642Sps map_arg.sc = sc; 2471157642Sps 2472157642Sps error = bus_dmamap_load( 2473157642Sps sc->tx_bd_chain_tag, /* dmat */ 2474157642Sps sc->tx_bd_chain_map[i], /* map */ 2475157642Sps sc->tx_bd_chain[i], /* buf */ 2476157642Sps BCE_TX_CHAIN_PAGE_SZ, /* buflen */ 2477157642Sps bce_dma_map_addr, /* callback */ 2478157642Sps &map_arg, /* callbackarg */ 2479157642Sps BUS_DMA_NOWAIT); /* flags */ 2480157642Sps 2481157642Sps if(error || (map_arg.maxsegs == 0)) { 2482157642Sps BCE_PRINTF(sc, "%s(%d): Could not map TX descriptor chain DMA memory!\n", 2483157642Sps __FILE__, __LINE__); 2484157642Sps rc = ENOMEM; 2485157642Sps goto bce_dma_alloc_exit; 2486157642Sps } 2487157642Sps 2488157642Sps sc->tx_bd_chain_paddr[i] = map_arg.busaddr; 2489157642Sps /* DRC - Fix for 64 bit systems. */ 2490157642Sps DBPRINT(sc, BCE_INFO, "tx_bd_chain_paddr[%d] = 0x%08X\n", 2491157642Sps i, (u32) sc->tx_bd_chain_paddr[i]); 2492157642Sps } 2493157642Sps 2494157642Sps /* Create a DMA tag for TX mbufs. */ 2495157642Sps if (bus_dma_tag_create( 2496157642Sps sc->parent_tag, /* parent */ 2497157642Sps BCE_DMA_ALIGN, /* alignment */ 2498157642Sps BCE_DMA_BOUNDARY, /* boundary */ 2499157642Sps sc->max_bus_addr, /* lowaddr */ 2500157642Sps BUS_SPACE_MAXADDR, /* highaddr */ 2501157642Sps NULL, /* filterfunc */ 2502157642Sps NULL, /* filterarg */ 2503157642Sps MCLBYTES * BCE_MAX_SEGMENTS, /* maxsize */ 2504157642Sps BCE_MAX_SEGMENTS, /* nsegments */ 2505157642Sps MCLBYTES, /* maxsegsize */ 2506157642Sps 0, /* flags */ 2507157642Sps NULL, /* lockfunc */ 2508157642Sps NULL, /* lockarg */ 2509157642Sps &sc->tx_mbuf_tag)) { 2510157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate TX mbuf DMA tag!\n", 2511157642Sps __FILE__, __LINE__); 2512157642Sps rc = ENOMEM; 2513157642Sps goto bce_dma_alloc_exit; 2514157642Sps } 2515157642Sps 2516157642Sps /* Create DMA maps for the TX mbufs clusters. */ 2517157642Sps for (i = 0; i < TOTAL_TX_BD; i++) { 2518157642Sps if (bus_dmamap_create(sc->tx_mbuf_tag, BUS_DMA_NOWAIT, 2519157642Sps &sc->tx_mbuf_map[i])) { 2520157642Sps BCE_PRINTF(sc, "%s(%d): Unable to create TX mbuf DMA map!\n", 2521157642Sps __FILE__, __LINE__); 2522157642Sps rc = ENOMEM; 2523157642Sps goto bce_dma_alloc_exit; 2524157642Sps } 2525157642Sps } 2526157642Sps 2527157642Sps /* 2528157642Sps * Create a DMA tag for the RX buffer descriptor chain, 2529157642Sps * allocate and clear the memory, and fetch the physical 2530157642Sps * address of the blocks. 2531157642Sps */ 2532157642Sps if (bus_dma_tag_create( 2533157642Sps sc->parent_tag, /* parent */ 2534157642Sps BCM_PAGE_SIZE, /* alignment */ 2535157642Sps BCE_DMA_BOUNDARY, /* boundary */ 2536157642Sps BUS_SPACE_MAXADDR, /* lowaddr */ 2537157642Sps sc->max_bus_addr, /* lowaddr */ 2538157642Sps NULL, /* filter */ 2539157642Sps NULL, /* filterarg */ 2540157642Sps BCE_RX_CHAIN_PAGE_SZ, /* maxsize */ 2541157642Sps 1, /* nsegments */ 2542157642Sps BCE_RX_CHAIN_PAGE_SZ, /* maxsegsize */ 2543157642Sps 0, /* flags */ 2544157642Sps NULL, /* lockfunc */ 2545157642Sps NULL, /* lockarg */ 2546157642Sps &sc->rx_bd_chain_tag)) { 2547157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate RX descriptor chain DMA tag!\n", 2548157642Sps __FILE__, __LINE__); 2549157642Sps rc = ENOMEM; 2550157642Sps goto bce_dma_alloc_exit; 2551157642Sps } 2552157642Sps 2553157642Sps for (i = 0; i < RX_PAGES; i++) { 2554157642Sps 2555157642Sps if (bus_dmamem_alloc( 2556157642Sps sc->rx_bd_chain_tag, /* tag */ 2557157642Sps (void **)&sc->rx_bd_chain[i], /* vaddr */ 2558157642Sps BUS_DMA_NOWAIT, /* flags */ 2559157642Sps &sc->rx_bd_chain_map[i])) { 2560157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate RX descriptor chain " 2561157642Sps "DMA memory!\n", __FILE__, __LINE__); 2562157642Sps rc = ENOMEM; 2563157642Sps goto bce_dma_alloc_exit; 2564157642Sps } 2565157642Sps 2566157642Sps bzero((char *)sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ); 2567157642Sps 2568157642Sps map_arg.maxsegs = 1; 2569157642Sps map_arg.sc = sc; 2570157642Sps 2571157642Sps error = bus_dmamap_load( 2572157642Sps sc->rx_bd_chain_tag, /* dmat */ 2573157642Sps sc->rx_bd_chain_map[i], /* map */ 2574157642Sps sc->rx_bd_chain[i], /* buf */ 2575157642Sps BCE_RX_CHAIN_PAGE_SZ, /* buflen */ 2576157642Sps bce_dma_map_addr, /* callback */ 2577157642Sps &map_arg, /* callbackarg */ 2578157642Sps BUS_DMA_NOWAIT); /* flags */ 2579157642Sps 2580157642Sps if(error || (map_arg.maxsegs == 0)) { 2581157642Sps BCE_PRINTF(sc, "%s(%d): Could not map RX descriptor chain DMA memory!\n", 2582157642Sps __FILE__, __LINE__); 2583157642Sps rc = ENOMEM; 2584157642Sps goto bce_dma_alloc_exit; 2585157642Sps } 2586157642Sps 2587157642Sps sc->rx_bd_chain_paddr[i] = map_arg.busaddr; 2588157642Sps /* DRC - Fix for 64 bit systems. */ 2589157642Sps DBPRINT(sc, BCE_INFO, "rx_bd_chain_paddr[%d] = 0x%08X\n", 2590157642Sps i, (u32) sc->rx_bd_chain_paddr[i]); 2591157642Sps } 2592157642Sps 2593157642Sps /* 2594157642Sps * Create a DMA tag for RX mbufs. 2595157642Sps */ 2596157642Sps if (bus_dma_tag_create( 2597157642Sps sc->parent_tag, /* parent */ 2598157642Sps BCE_DMA_ALIGN, /* alignment */ 2599157642Sps BCE_DMA_BOUNDARY, /* boundary */ 2600157642Sps sc->max_bus_addr, /* lowaddr */ 2601157642Sps BUS_SPACE_MAXADDR, /* highaddr */ 2602157642Sps NULL, /* filterfunc */ 2603157642Sps NULL, /* filterarg */ 2604157642Sps MJUM9BYTES, /* maxsize */ 2605157642Sps BCE_MAX_SEGMENTS, /* nsegments */ 2606157642Sps MJUM9BYTES, /* maxsegsize */ 2607157642Sps 0, /* flags */ 2608157642Sps NULL, /* lockfunc */ 2609157642Sps NULL, /* lockarg */ 2610157642Sps &sc->rx_mbuf_tag)) { 2611157642Sps BCE_PRINTF(sc, "%s(%d): Could not allocate RX mbuf DMA tag!\n", 2612157642Sps __FILE__, __LINE__); 2613157642Sps rc = ENOMEM; 2614157642Sps goto bce_dma_alloc_exit; 2615157642Sps } 2616157642Sps 2617157642Sps /* Create DMA maps for the RX mbuf clusters. */ 2618157642Sps for (i = 0; i < TOTAL_RX_BD; i++) { 2619157642Sps if (bus_dmamap_create(sc->rx_mbuf_tag, BUS_DMA_NOWAIT, 2620157642Sps &sc->rx_mbuf_map[i])) { 2621157642Sps BCE_PRINTF(sc, "%s(%d): Unable to create RX mbuf DMA map!\n", 2622157642Sps __FILE__, __LINE__); 2623157642Sps rc = ENOMEM; 2624157642Sps goto bce_dma_alloc_exit; 2625157642Sps } 2626157642Sps } 2627157642Sps 2628157642Spsbce_dma_alloc_exit: 2629157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 2630157642Sps 2631157642Sps return(rc); 2632157642Sps} 2633157642Sps 2634157642Sps 2635157642Sps/****************************************************************************/ 2636157642Sps/* Release all resources used by the driver. */ 2637157642Sps/* */ 2638157642Sps/* Releases all resources acquired by the driver including interrupts, */ 2639157642Sps/* interrupt handler, interfaces, mutexes, and DMA memory. */ 2640157642Sps/* */ 2641157642Sps/* Returns: */ 2642157642Sps/* Nothing. */ 2643157642Sps/****************************************************************************/ 2644157642Spsstatic void 2645157642Spsbce_release_resources(struct bce_softc *sc) 2646157642Sps{ 2647157642Sps device_t dev; 2648157642Sps 2649157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 2650157642Sps 2651157642Sps dev = sc->bce_dev; 2652157642Sps 2653157642Sps bce_dma_free(sc); 2654157642Sps 2655157642Sps if (sc->bce_intrhand != NULL) 2656157642Sps bus_teardown_intr(dev, sc->bce_irq, sc->bce_intrhand); 2657157642Sps 2658157642Sps if (sc->bce_irq != NULL) 2659157642Sps bus_release_resource(dev, 2660157642Sps SYS_RES_IRQ, 2661157642Sps 0, 2662157642Sps sc->bce_irq); 2663157642Sps 2664157642Sps if (sc->bce_res != NULL) 2665157642Sps bus_release_resource(dev, 2666157642Sps SYS_RES_MEMORY, 2667157642Sps PCIR_BAR(0), 2668157642Sps sc->bce_res); 2669157642Sps 2670157642Sps if (sc->bce_ifp != NULL) 2671157642Sps if_free(sc->bce_ifp); 2672157642Sps 2673157642Sps 2674157642Sps if (mtx_initialized(&sc->bce_mtx)) 2675157642Sps BCE_LOCK_DESTROY(sc); 2676157642Sps 2677157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 2678157642Sps 2679157642Sps} 2680157642Sps 2681157642Sps 2682157642Sps/****************************************************************************/ 2683157642Sps/* Firmware synchronization. */ 2684157642Sps/* */ 2685157642Sps/* Before performing certain events such as a chip reset, synchronize with */ 2686157642Sps/* the firmware first. */ 2687157642Sps/* */ 2688157642Sps/* Returns: */ 2689157642Sps/* 0 for success, positive value for failure. */ 2690157642Sps/****************************************************************************/ 2691157642Spsstatic int 2692157642Spsbce_fw_sync(struct bce_softc *sc, u32 msg_data) 2693157642Sps{ 2694157642Sps int i, rc = 0; 2695157642Sps u32 val; 2696157642Sps 2697157642Sps /* Don't waste any time if we've timed out before. */ 2698157642Sps if (sc->bce_fw_timed_out) { 2699157642Sps rc = EBUSY; 2700157642Sps goto bce_fw_sync_exit; 2701157642Sps } 2702157642Sps 2703157642Sps /* Increment the message sequence number. */ 2704157642Sps sc->bce_fw_wr_seq++; 2705157642Sps msg_data |= sc->bce_fw_wr_seq; 2706157642Sps 2707157642Sps DBPRINT(sc, BCE_VERBOSE, "bce_fw_sync(): msg_data = 0x%08X\n", msg_data); 2708157642Sps 2709157642Sps /* Send the message to the bootcode driver mailbox. */ 2710157642Sps REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_MB, msg_data); 2711157642Sps 2712157642Sps /* Wait for the bootcode to acknowledge the message. */ 2713157642Sps for (i = 0; i < FW_ACK_TIME_OUT_MS; i++) { 2714157642Sps /* Check for a response in the bootcode firmware mailbox. */ 2715157642Sps val = REG_RD_IND(sc, sc->bce_shmem_base + BCE_FW_MB); 2716157642Sps if ((val & BCE_FW_MSG_ACK) == (msg_data & BCE_DRV_MSG_SEQ)) 2717157642Sps break; 2718157642Sps DELAY(1000); 2719157642Sps } 2720157642Sps 2721157642Sps /* If we've timed out, tell the bootcode that we've stopped waiting. */ 2722157642Sps if (((val & BCE_FW_MSG_ACK) != (msg_data & BCE_DRV_MSG_SEQ)) && 2723157642Sps ((msg_data & BCE_DRV_MSG_DATA) != BCE_DRV_MSG_DATA_WAIT0)) { 2724157642Sps 2725157642Sps BCE_PRINTF(sc, "%s(%d): Firmware synchronization timeout! " 2726157642Sps "msg_data = 0x%08X\n", 2727157642Sps __FILE__, __LINE__, msg_data); 2728157642Sps 2729157642Sps msg_data &= ~BCE_DRV_MSG_CODE; 2730157642Sps msg_data |= BCE_DRV_MSG_CODE_FW_TIMEOUT; 2731157642Sps 2732157642Sps REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_MB, msg_data); 2733157642Sps 2734157642Sps sc->bce_fw_timed_out = 1; 2735157642Sps rc = EBUSY; 2736157642Sps } 2737157642Sps 2738157642Spsbce_fw_sync_exit: 2739157642Sps return (rc); 2740157642Sps} 2741157642Sps 2742157642Sps 2743157642Sps/****************************************************************************/ 2744157642Sps/* Load Receive Virtual 2 Physical (RV2P) processor firmware. */ 2745157642Sps/* */ 2746157642Sps/* Returns: */ 2747157642Sps/* Nothing. */ 2748157642Sps/****************************************************************************/ 2749157642Spsstatic void 2750157642Spsbce_load_rv2p_fw(struct bce_softc *sc, u32 *rv2p_code, 2751157642Sps u32 rv2p_code_len, u32 rv2p_proc) 2752157642Sps{ 2753157642Sps int i; 2754157642Sps u32 val; 2755157642Sps 2756157642Sps for (i = 0; i < rv2p_code_len; i += 8) { 2757157642Sps REG_WR(sc, BCE_RV2P_INSTR_HIGH, *rv2p_code); 2758157642Sps rv2p_code++; 2759157642Sps REG_WR(sc, BCE_RV2P_INSTR_LOW, *rv2p_code); 2760157642Sps rv2p_code++; 2761157642Sps 2762157642Sps if (rv2p_proc == RV2P_PROC1) { 2763157642Sps val = (i / 8) | BCE_RV2P_PROC1_ADDR_CMD_RDWR; 2764157642Sps REG_WR(sc, BCE_RV2P_PROC1_ADDR_CMD, val); 2765157642Sps } 2766157642Sps else { 2767157642Sps val = (i / 8) | BCE_RV2P_PROC2_ADDR_CMD_RDWR; 2768157642Sps REG_WR(sc, BCE_RV2P_PROC2_ADDR_CMD, val); 2769157642Sps } 2770157642Sps } 2771157642Sps 2772157642Sps /* Reset the processor, un-stall is done later. */ 2773157642Sps if (rv2p_proc == RV2P_PROC1) { 2774157642Sps REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC1_RESET); 2775157642Sps } 2776157642Sps else { 2777157642Sps REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC2_RESET); 2778157642Sps } 2779157642Sps} 2780157642Sps 2781157642Sps 2782157642Sps/****************************************************************************/ 2783157642Sps/* Load RISC processor firmware. */ 2784157642Sps/* */ 2785157642Sps/* Loads firmware from the file if_bcefw.h into the scratchpad memory */ 2786157642Sps/* associated with a particular processor. */ 2787157642Sps/* */ 2788157642Sps/* Returns: */ 2789157642Sps/* Nothing. */ 2790157642Sps/****************************************************************************/ 2791157642Spsstatic void 2792157642Spsbce_load_cpu_fw(struct bce_softc *sc, struct cpu_reg *cpu_reg, 2793157642Sps struct fw_info *fw) 2794157642Sps{ 2795157642Sps u32 offset; 2796157642Sps u32 val; 2797157642Sps 2798157642Sps /* Halt the CPU. */ 2799157642Sps val = REG_RD_IND(sc, cpu_reg->mode); 2800157642Sps val |= cpu_reg->mode_value_halt; 2801157642Sps REG_WR_IND(sc, cpu_reg->mode, val); 2802157642Sps REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear); 2803157642Sps 2804157642Sps /* Load the Text area. */ 2805157642Sps offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base); 2806157642Sps if (fw->text) { 2807157642Sps int j; 2808157642Sps 2809157642Sps for (j = 0; j < (fw->text_len / 4); j++, offset += 4) { 2810157642Sps REG_WR_IND(sc, offset, fw->text[j]); 2811157642Sps } 2812157642Sps } 2813157642Sps 2814157642Sps /* Load the Data area. */ 2815157642Sps offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base); 2816157642Sps if (fw->data) { 2817157642Sps int j; 2818157642Sps 2819157642Sps for (j = 0; j < (fw->data_len / 4); j++, offset += 4) { 2820157642Sps REG_WR_IND(sc, offset, fw->data[j]); 2821157642Sps } 2822157642Sps } 2823157642Sps 2824157642Sps /* Load the SBSS area. */ 2825157642Sps offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base); 2826157642Sps if (fw->sbss) { 2827157642Sps int j; 2828157642Sps 2829157642Sps for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) { 2830157642Sps REG_WR_IND(sc, offset, fw->sbss[j]); 2831157642Sps } 2832157642Sps } 2833157642Sps 2834157642Sps /* Load the BSS area. */ 2835157642Sps offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base); 2836157642Sps if (fw->bss) { 2837157642Sps int j; 2838157642Sps 2839157642Sps for (j = 0; j < (fw->bss_len/4); j++, offset += 4) { 2840157642Sps REG_WR_IND(sc, offset, fw->bss[j]); 2841157642Sps } 2842157642Sps } 2843157642Sps 2844157642Sps /* Load the Read-Only area. */ 2845157642Sps offset = cpu_reg->spad_base + 2846157642Sps (fw->rodata_addr - cpu_reg->mips_view_base); 2847157642Sps if (fw->rodata) { 2848157642Sps int j; 2849157642Sps 2850157642Sps for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) { 2851157642Sps REG_WR_IND(sc, offset, fw->rodata[j]); 2852157642Sps } 2853157642Sps } 2854157642Sps 2855157642Sps /* Clear the pre-fetch instruction. */ 2856157642Sps REG_WR_IND(sc, cpu_reg->inst, 0); 2857157642Sps REG_WR_IND(sc, cpu_reg->pc, fw->start_addr); 2858157642Sps 2859157642Sps /* Start the CPU. */ 2860157642Sps val = REG_RD_IND(sc, cpu_reg->mode); 2861157642Sps val &= ~cpu_reg->mode_value_halt; 2862157642Sps REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear); 2863157642Sps REG_WR_IND(sc, cpu_reg->mode, val); 2864157642Sps} 2865157642Sps 2866157642Sps 2867157642Sps/****************************************************************************/ 2868157642Sps/* Initialize the RV2P, RX, TX, TPAT, and COM CPUs. */ 2869157642Sps/* */ 2870157642Sps/* Loads the firmware for each CPU and starts the CPU. */ 2871157642Sps/* */ 2872157642Sps/* Returns: */ 2873157642Sps/* Nothing. */ 2874157642Sps/****************************************************************************/ 2875157642Spsstatic void 2876157642Spsbce_init_cpus(struct bce_softc *sc) 2877157642Sps{ 2878157642Sps struct cpu_reg cpu_reg; 2879157642Sps struct fw_info fw; 2880157642Sps 2881157642Sps /* Initialize the RV2P processor. */ 2882157642Sps bce_load_rv2p_fw(sc, bce_rv2p_proc1, sizeof(bce_rv2p_proc1), RV2P_PROC1); 2883157642Sps bce_load_rv2p_fw(sc, bce_rv2p_proc2, sizeof(bce_rv2p_proc2), RV2P_PROC2); 2884157642Sps 2885157642Sps /* Initialize the RX Processor. */ 2886157642Sps cpu_reg.mode = BCE_RXP_CPU_MODE; 2887157642Sps cpu_reg.mode_value_halt = BCE_RXP_CPU_MODE_SOFT_HALT; 2888157642Sps cpu_reg.mode_value_sstep = BCE_RXP_CPU_MODE_STEP_ENA; 2889157642Sps cpu_reg.state = BCE_RXP_CPU_STATE; 2890157642Sps cpu_reg.state_value_clear = 0xffffff; 2891157642Sps cpu_reg.gpr0 = BCE_RXP_CPU_REG_FILE; 2892157642Sps cpu_reg.evmask = BCE_RXP_CPU_EVENT_MASK; 2893157642Sps cpu_reg.pc = BCE_RXP_CPU_PROGRAM_COUNTER; 2894157642Sps cpu_reg.inst = BCE_RXP_CPU_INSTRUCTION; 2895157642Sps cpu_reg.bp = BCE_RXP_CPU_HW_BREAKPOINT; 2896157642Sps cpu_reg.spad_base = BCE_RXP_SCRATCH; 2897157642Sps cpu_reg.mips_view_base = 0x8000000; 2898157642Sps 2899157642Sps fw.ver_major = bce_RXP_b06FwReleaseMajor; 2900157642Sps fw.ver_minor = bce_RXP_b06FwReleaseMinor; 2901157642Sps fw.ver_fix = bce_RXP_b06FwReleaseFix; 2902157642Sps fw.start_addr = bce_RXP_b06FwStartAddr; 2903157642Sps 2904157642Sps fw.text_addr = bce_RXP_b06FwTextAddr; 2905157642Sps fw.text_len = bce_RXP_b06FwTextLen; 2906157642Sps fw.text_index = 0; 2907157642Sps fw.text = bce_RXP_b06FwText; 2908157642Sps 2909157642Sps fw.data_addr = bce_RXP_b06FwDataAddr; 2910157642Sps fw.data_len = bce_RXP_b06FwDataLen; 2911157642Sps fw.data_index = 0; 2912157642Sps fw.data = bce_RXP_b06FwData; 2913157642Sps 2914157642Sps fw.sbss_addr = bce_RXP_b06FwSbssAddr; 2915157642Sps fw.sbss_len = bce_RXP_b06FwSbssLen; 2916157642Sps fw.sbss_index = 0; 2917157642Sps fw.sbss = bce_RXP_b06FwSbss; 2918157642Sps 2919157642Sps fw.bss_addr = bce_RXP_b06FwBssAddr; 2920157642Sps fw.bss_len = bce_RXP_b06FwBssLen; 2921157642Sps fw.bss_index = 0; 2922157642Sps fw.bss = bce_RXP_b06FwBss; 2923157642Sps 2924157642Sps fw.rodata_addr = bce_RXP_b06FwRodataAddr; 2925157642Sps fw.rodata_len = bce_RXP_b06FwRodataLen; 2926157642Sps fw.rodata_index = 0; 2927157642Sps fw.rodata = bce_RXP_b06FwRodata; 2928157642Sps 2929157642Sps DBPRINT(sc, BCE_INFO_RESET, "Loading RX firmware.\n"); 2930157642Sps bce_load_cpu_fw(sc, &cpu_reg, &fw); 2931157642Sps 2932157642Sps /* Initialize the TX Processor. */ 2933157642Sps cpu_reg.mode = BCE_TXP_CPU_MODE; 2934157642Sps cpu_reg.mode_value_halt = BCE_TXP_CPU_MODE_SOFT_HALT; 2935157642Sps cpu_reg.mode_value_sstep = BCE_TXP_CPU_MODE_STEP_ENA; 2936157642Sps cpu_reg.state = BCE_TXP_CPU_STATE; 2937157642Sps cpu_reg.state_value_clear = 0xffffff; 2938157642Sps cpu_reg.gpr0 = BCE_TXP_CPU_REG_FILE; 2939157642Sps cpu_reg.evmask = BCE_TXP_CPU_EVENT_MASK; 2940157642Sps cpu_reg.pc = BCE_TXP_CPU_PROGRAM_COUNTER; 2941157642Sps cpu_reg.inst = BCE_TXP_CPU_INSTRUCTION; 2942157642Sps cpu_reg.bp = BCE_TXP_CPU_HW_BREAKPOINT; 2943157642Sps cpu_reg.spad_base = BCE_TXP_SCRATCH; 2944157642Sps cpu_reg.mips_view_base = 0x8000000; 2945157642Sps 2946157642Sps fw.ver_major = bce_TXP_b06FwReleaseMajor; 2947157642Sps fw.ver_minor = bce_TXP_b06FwReleaseMinor; 2948157642Sps fw.ver_fix = bce_TXP_b06FwReleaseFix; 2949157642Sps fw.start_addr = bce_TXP_b06FwStartAddr; 2950157642Sps 2951157642Sps fw.text_addr = bce_TXP_b06FwTextAddr; 2952157642Sps fw.text_len = bce_TXP_b06FwTextLen; 2953157642Sps fw.text_index = 0; 2954157642Sps fw.text = bce_TXP_b06FwText; 2955157642Sps 2956157642Sps fw.data_addr = bce_TXP_b06FwDataAddr; 2957157642Sps fw.data_len = bce_TXP_b06FwDataLen; 2958157642Sps fw.data_index = 0; 2959157642Sps fw.data = bce_TXP_b06FwData; 2960157642Sps 2961157642Sps fw.sbss_addr = bce_TXP_b06FwSbssAddr; 2962157642Sps fw.sbss_len = bce_TXP_b06FwSbssLen; 2963157642Sps fw.sbss_index = 0; 2964157642Sps fw.sbss = bce_TXP_b06FwSbss; 2965157642Sps 2966157642Sps fw.bss_addr = bce_TXP_b06FwBssAddr; 2967157642Sps fw.bss_len = bce_TXP_b06FwBssLen; 2968157642Sps fw.bss_index = 0; 2969157642Sps fw.bss = bce_TXP_b06FwBss; 2970157642Sps 2971157642Sps fw.rodata_addr = bce_TXP_b06FwRodataAddr; 2972157642Sps fw.rodata_len = bce_TXP_b06FwRodataLen; 2973157642Sps fw.rodata_index = 0; 2974157642Sps fw.rodata = bce_TXP_b06FwRodata; 2975157642Sps 2976157642Sps DBPRINT(sc, BCE_INFO_RESET, "Loading TX firmware.\n"); 2977157642Sps bce_load_cpu_fw(sc, &cpu_reg, &fw); 2978157642Sps 2979157642Sps /* Initialize the TX Patch-up Processor. */ 2980157642Sps cpu_reg.mode = BCE_TPAT_CPU_MODE; 2981157642Sps cpu_reg.mode_value_halt = BCE_TPAT_CPU_MODE_SOFT_HALT; 2982157642Sps cpu_reg.mode_value_sstep = BCE_TPAT_CPU_MODE_STEP_ENA; 2983157642Sps cpu_reg.state = BCE_TPAT_CPU_STATE; 2984157642Sps cpu_reg.state_value_clear = 0xffffff; 2985157642Sps cpu_reg.gpr0 = BCE_TPAT_CPU_REG_FILE; 2986157642Sps cpu_reg.evmask = BCE_TPAT_CPU_EVENT_MASK; 2987157642Sps cpu_reg.pc = BCE_TPAT_CPU_PROGRAM_COUNTER; 2988157642Sps cpu_reg.inst = BCE_TPAT_CPU_INSTRUCTION; 2989157642Sps cpu_reg.bp = BCE_TPAT_CPU_HW_BREAKPOINT; 2990157642Sps cpu_reg.spad_base = BCE_TPAT_SCRATCH; 2991157642Sps cpu_reg.mips_view_base = 0x8000000; 2992157642Sps 2993157642Sps fw.ver_major = bce_TPAT_b06FwReleaseMajor; 2994157642Sps fw.ver_minor = bce_TPAT_b06FwReleaseMinor; 2995157642Sps fw.ver_fix = bce_TPAT_b06FwReleaseFix; 2996157642Sps fw.start_addr = bce_TPAT_b06FwStartAddr; 2997157642Sps 2998157642Sps fw.text_addr = bce_TPAT_b06FwTextAddr; 2999157642Sps fw.text_len = bce_TPAT_b06FwTextLen; 3000157642Sps fw.text_index = 0; 3001157642Sps fw.text = bce_TPAT_b06FwText; 3002157642Sps 3003157642Sps fw.data_addr = bce_TPAT_b06FwDataAddr; 3004157642Sps fw.data_len = bce_TPAT_b06FwDataLen; 3005157642Sps fw.data_index = 0; 3006157642Sps fw.data = bce_TPAT_b06FwData; 3007157642Sps 3008157642Sps fw.sbss_addr = bce_TPAT_b06FwSbssAddr; 3009157642Sps fw.sbss_len = bce_TPAT_b06FwSbssLen; 3010157642Sps fw.sbss_index = 0; 3011157642Sps fw.sbss = bce_TPAT_b06FwSbss; 3012157642Sps 3013157642Sps fw.bss_addr = bce_TPAT_b06FwBssAddr; 3014157642Sps fw.bss_len = bce_TPAT_b06FwBssLen; 3015157642Sps fw.bss_index = 0; 3016157642Sps fw.bss = bce_TPAT_b06FwBss; 3017157642Sps 3018157642Sps fw.rodata_addr = bce_TPAT_b06FwRodataAddr; 3019157642Sps fw.rodata_len = bce_TPAT_b06FwRodataLen; 3020157642Sps fw.rodata_index = 0; 3021157642Sps fw.rodata = bce_TPAT_b06FwRodata; 3022157642Sps 3023157642Sps DBPRINT(sc, BCE_INFO_RESET, "Loading TPAT firmware.\n"); 3024157642Sps bce_load_cpu_fw(sc, &cpu_reg, &fw); 3025157642Sps 3026157642Sps /* Initialize the Completion Processor. */ 3027157642Sps cpu_reg.mode = BCE_COM_CPU_MODE; 3028157642Sps cpu_reg.mode_value_halt = BCE_COM_CPU_MODE_SOFT_HALT; 3029157642Sps cpu_reg.mode_value_sstep = BCE_COM_CPU_MODE_STEP_ENA; 3030157642Sps cpu_reg.state = BCE_COM_CPU_STATE; 3031157642Sps cpu_reg.state_value_clear = 0xffffff; 3032157642Sps cpu_reg.gpr0 = BCE_COM_CPU_REG_FILE; 3033157642Sps cpu_reg.evmask = BCE_COM_CPU_EVENT_MASK; 3034157642Sps cpu_reg.pc = BCE_COM_CPU_PROGRAM_COUNTER; 3035157642Sps cpu_reg.inst = BCE_COM_CPU_INSTRUCTION; 3036157642Sps cpu_reg.bp = BCE_COM_CPU_HW_BREAKPOINT; 3037157642Sps cpu_reg.spad_base = BCE_COM_SCRATCH; 3038157642Sps cpu_reg.mips_view_base = 0x8000000; 3039157642Sps 3040157642Sps fw.ver_major = bce_COM_b06FwReleaseMajor; 3041157642Sps fw.ver_minor = bce_COM_b06FwReleaseMinor; 3042157642Sps fw.ver_fix = bce_COM_b06FwReleaseFix; 3043157642Sps fw.start_addr = bce_COM_b06FwStartAddr; 3044157642Sps 3045157642Sps fw.text_addr = bce_COM_b06FwTextAddr; 3046157642Sps fw.text_len = bce_COM_b06FwTextLen; 3047157642Sps fw.text_index = 0; 3048157642Sps fw.text = bce_COM_b06FwText; 3049157642Sps 3050157642Sps fw.data_addr = bce_COM_b06FwDataAddr; 3051157642Sps fw.data_len = bce_COM_b06FwDataLen; 3052157642Sps fw.data_index = 0; 3053157642Sps fw.data = bce_COM_b06FwData; 3054157642Sps 3055157642Sps fw.sbss_addr = bce_COM_b06FwSbssAddr; 3056157642Sps fw.sbss_len = bce_COM_b06FwSbssLen; 3057157642Sps fw.sbss_index = 0; 3058157642Sps fw.sbss = bce_COM_b06FwSbss; 3059157642Sps 3060157642Sps fw.bss_addr = bce_COM_b06FwBssAddr; 3061157642Sps fw.bss_len = bce_COM_b06FwBssLen; 3062157642Sps fw.bss_index = 0; 3063157642Sps fw.bss = bce_COM_b06FwBss; 3064157642Sps 3065157642Sps fw.rodata_addr = bce_COM_b06FwRodataAddr; 3066157642Sps fw.rodata_len = bce_COM_b06FwRodataLen; 3067157642Sps fw.rodata_index = 0; 3068157642Sps fw.rodata = bce_COM_b06FwRodata; 3069157642Sps 3070157642Sps DBPRINT(sc, BCE_INFO_RESET, "Loading COM firmware.\n"); 3071157642Sps bce_load_cpu_fw(sc, &cpu_reg, &fw); 3072157642Sps} 3073157642Sps 3074157642Sps 3075157642Sps/****************************************************************************/ 3076157642Sps/* Initialize context memory. */ 3077157642Sps/* */ 3078157642Sps/* Clears the memory associated with each Context ID (CID). */ 3079157642Sps/* */ 3080157642Sps/* Returns: */ 3081157642Sps/* Nothing. */ 3082157642Sps/****************************************************************************/ 3083157642Spsstatic void 3084157642Spsbce_init_context(struct bce_softc *sc) 3085157642Sps{ 3086157642Sps u32 vcid; 3087157642Sps 3088157642Sps vcid = 96; 3089157642Sps while (vcid) { 3090157642Sps u32 vcid_addr, pcid_addr, offset; 3091157642Sps 3092157642Sps vcid--; 3093157642Sps 3094157642Sps vcid_addr = GET_CID_ADDR(vcid); 3095157642Sps pcid_addr = vcid_addr; 3096157642Sps 3097157642Sps REG_WR(sc, BCE_CTX_VIRT_ADDR, 0x00); 3098157642Sps REG_WR(sc, BCE_CTX_PAGE_TBL, pcid_addr); 3099157642Sps 3100157642Sps /* Zero out the context. */ 3101157642Sps for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) { 3102157642Sps CTX_WR(sc, 0x00, offset, 0); 3103157642Sps } 3104157642Sps 3105157642Sps REG_WR(sc, BCE_CTX_VIRT_ADDR, vcid_addr); 3106157642Sps REG_WR(sc, BCE_CTX_PAGE_TBL, pcid_addr); 3107157642Sps } 3108157642Sps} 3109157642Sps 3110157642Sps 3111157642Sps/****************************************************************************/ 3112157642Sps/* Fetch the permanent MAC address of the controller. */ 3113157642Sps/* */ 3114157642Sps/* Returns: */ 3115157642Sps/* Nothing. */ 3116157642Sps/****************************************************************************/ 3117157642Spsstatic void 3118157642Spsbce_get_mac_addr(struct bce_softc *sc) 3119157642Sps{ 3120157642Sps u32 mac_lo = 0, mac_hi = 0; 3121157642Sps 3122157642Sps /* 3123157642Sps * The NetXtreme II bootcode populates various NIC 3124157642Sps * power-on and runtime configuration items in a 3125157642Sps * shared memory area. The factory configured MAC 3126157642Sps * address is available from both NVRAM and the 3127157642Sps * shared memory area so we'll read the value from 3128157642Sps * shared memory for speed. 3129157642Sps */ 3130157642Sps 3131157642Sps mac_hi = REG_RD_IND(sc, sc->bce_shmem_base + 3132157642Sps BCE_PORT_HW_CFG_MAC_UPPER); 3133157642Sps mac_lo = REG_RD_IND(sc, sc->bce_shmem_base + 3134157642Sps BCE_PORT_HW_CFG_MAC_LOWER); 3135157642Sps 3136157642Sps if ((mac_lo == 0) && (mac_hi == 0)) { 3137157642Sps BCE_PRINTF(sc, "%s(%d): Invalid Ethernet address!\n", 3138157642Sps __FILE__, __LINE__); 3139157642Sps } else { 3140157642Sps sc->eaddr[0] = (u_char)(mac_hi >> 8); 3141157642Sps sc->eaddr[1] = (u_char)(mac_hi >> 0); 3142157642Sps sc->eaddr[2] = (u_char)(mac_lo >> 24); 3143157642Sps sc->eaddr[3] = (u_char)(mac_lo >> 16); 3144157642Sps sc->eaddr[4] = (u_char)(mac_lo >> 8); 3145157642Sps sc->eaddr[5] = (u_char)(mac_lo >> 0); 3146157642Sps } 3147157642Sps 3148157642Sps DBPRINT(sc, BCE_INFO, "Permanent Ethernet address = %6D\n", sc->eaddr, ":"); 3149157642Sps} 3150157642Sps 3151157642Sps 3152157642Sps/****************************************************************************/ 3153157642Sps/* Program the MAC address. */ 3154157642Sps/* */ 3155157642Sps/* Returns: */ 3156157642Sps/* Nothing. */ 3157157642Sps/****************************************************************************/ 3158157642Spsstatic void 3159157642Spsbce_set_mac_addr(struct bce_softc *sc) 3160157642Sps{ 3161157642Sps u32 val; 3162157642Sps u8 *mac_addr = sc->eaddr; 3163157642Sps 3164157642Sps DBPRINT(sc, BCE_INFO, "Setting Ethernet address = %6D\n", sc->eaddr, ":"); 3165157642Sps 3166157642Sps val = (mac_addr[0] << 8) | mac_addr[1]; 3167157642Sps 3168157642Sps REG_WR(sc, BCE_EMAC_MAC_MATCH0, val); 3169157642Sps 3170157642Sps val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | 3171157642Sps (mac_addr[4] << 8) | mac_addr[5]; 3172157642Sps 3173157642Sps REG_WR(sc, BCE_EMAC_MAC_MATCH1, val); 3174157642Sps} 3175157642Sps 3176157642Sps 3177157642Sps/****************************************************************************/ 3178157642Sps/* Stop the controller. */ 3179157642Sps/* */ 3180157642Sps/* Returns: */ 3181157642Sps/* Nothing. */ 3182157642Sps/****************************************************************************/ 3183157642Spsstatic void 3184157642Spsbce_stop(struct bce_softc *sc) 3185157642Sps{ 3186157642Sps struct ifnet *ifp; 3187157642Sps struct ifmedia_entry *ifm; 3188157642Sps struct mii_data *mii = NULL; 3189157642Sps int mtmp, itmp; 3190157642Sps 3191157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 3192157642Sps 3193157642Sps BCE_LOCK_ASSERT(sc); 3194157642Sps 3195157642Sps ifp = sc->bce_ifp; 3196157642Sps 3197157642Sps mii = device_get_softc(sc->bce_miibus); 3198157642Sps 3199157642Sps callout_stop(&sc->bce_stat_ch); 3200157642Sps 3201157642Sps /* Disable the transmit/receive blocks. */ 3202157642Sps REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS, 0x5ffffff); 3203157642Sps REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS); 3204157642Sps DELAY(20); 3205157642Sps 3206157642Sps bce_disable_intr(sc); 3207157642Sps 3208157642Sps /* Tell firmware that the driver is going away. */ 3209157642Sps bce_reset(sc, BCE_DRV_MSG_CODE_SUSPEND_NO_WOL); 3210157642Sps 3211157642Sps /* Free the RX lists. */ 3212157642Sps bce_free_rx_chain(sc); 3213157642Sps 3214157642Sps /* Free TX buffers. */ 3215157642Sps bce_free_tx_chain(sc); 3216157642Sps 3217157642Sps /* 3218157642Sps * Isolate/power down the PHY, but leave the media selection 3219157642Sps * unchanged so that things will be put back to normal when 3220157642Sps * we bring the interface back up. 3221157642Sps */ 3222157642Sps 3223157642Sps itmp = ifp->if_flags; 3224157642Sps ifp->if_flags |= IFF_UP; 3225157642Sps /* 3226157642Sps * If we are called from bce_detach(), mii is already NULL. 3227157642Sps */ 3228157642Sps if (mii != NULL) { 3229157642Sps ifm = mii->mii_media.ifm_cur; 3230157642Sps mtmp = ifm->ifm_media; 3231157642Sps ifm->ifm_media = IFM_ETHER | IFM_NONE; 3232157642Sps mii_mediachg(mii); 3233157642Sps ifm->ifm_media = mtmp; 3234157642Sps } 3235157642Sps 3236157642Sps ifp->if_flags = itmp; 3237157642Sps ifp->if_timer = 0; 3238157642Sps 3239157642Sps sc->bce_link = 0; 3240157642Sps 3241157642Sps ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 3242157642Sps 3243157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 3244157642Sps 3245157642Sps} 3246157642Sps 3247157642Sps 3248157642Spsstatic int 3249157642Spsbce_reset(struct bce_softc *sc, u32 reset_code) 3250157642Sps{ 3251157642Sps u32 val; 3252157642Sps int i, rc = 0; 3253157642Sps 3254157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 3255157642Sps 3256157642Sps /* Wait for pending PCI transactions to complete. */ 3257157642Sps REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS, 3258157642Sps BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | 3259157642Sps BCE_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | 3260157642Sps BCE_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | 3261157642Sps BCE_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); 3262157642Sps val = REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS); 3263157642Sps DELAY(5); 3264157642Sps 3265157642Sps /* Assume bootcode is running. */ 3266157642Sps sc->bce_fw_timed_out = 0; 3267157642Sps 3268157642Sps /* Give the firmware a chance to prepare for the reset. */ 3269157642Sps rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT0 | reset_code); 3270157642Sps if (rc) 3271157642Sps goto bce_reset_exit; 3272157642Sps 3273157642Sps /* Set a firmware reminder that this is a soft reset. */ 3274157642Sps REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_RESET_SIGNATURE, 3275157642Sps BCE_DRV_RESET_SIGNATURE_MAGIC); 3276157642Sps 3277157642Sps /* Dummy read to force the chip to complete all current transactions. */ 3278157642Sps val = REG_RD(sc, BCE_MISC_ID); 3279157642Sps 3280157642Sps /* Chip reset. */ 3281157642Sps val = BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ | 3282157642Sps BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | 3283157642Sps BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; 3284157642Sps REG_WR(sc, BCE_PCICFG_MISC_CONFIG, val); 3285157642Sps 3286157642Sps /* Allow up to 30us for reset to complete. */ 3287157642Sps for (i = 0; i < 10; i++) { 3288157642Sps val = REG_RD(sc, BCE_PCICFG_MISC_CONFIG); 3289157642Sps if ((val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ | 3290157642Sps BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) { 3291157642Sps break; 3292157642Sps } 3293157642Sps DELAY(10); 3294157642Sps } 3295157642Sps 3296157642Sps /* Check that reset completed successfully. */ 3297157642Sps if (val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ | 3298157642Sps BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) { 3299157642Sps BCE_PRINTF(sc, "%s(%d): Reset failed!\n", 3300157642Sps __FILE__, __LINE__); 3301157642Sps rc = EBUSY; 3302157642Sps goto bce_reset_exit; 3303157642Sps } 3304157642Sps 3305157642Sps /* Make sure byte swapping is properly configured. */ 3306157642Sps val = REG_RD(sc, BCE_PCI_SWAP_DIAG0); 3307157642Sps if (val != 0x01020304) { 3308157642Sps BCE_PRINTF(sc, "%s(%d): Byte swap is incorrect!\n", 3309157642Sps __FILE__, __LINE__); 3310157642Sps rc = ENODEV; 3311157642Sps goto bce_reset_exit; 3312157642Sps } 3313157642Sps 3314157642Sps /* Just completed a reset, assume that firmware is running again. */ 3315157642Sps sc->bce_fw_timed_out = 0; 3316157642Sps 3317157642Sps /* Wait for the firmware to finish its initialization. */ 3318157642Sps rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT1 | reset_code); 3319157642Sps if (rc) 3320157642Sps BCE_PRINTF(sc, "%s(%d): Firmware did not complete initialization!\n", 3321157642Sps __FILE__, __LINE__); 3322157642Sps 3323157642Spsbce_reset_exit: 3324157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 3325157642Sps 3326157642Sps return (rc); 3327157642Sps} 3328157642Sps 3329157642Sps 3330157642Spsstatic int 3331157642Spsbce_chipinit(struct bce_softc *sc) 3332157642Sps{ 3333157642Sps u32 val; 3334157642Sps int rc = 0; 3335157642Sps 3336157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 3337157642Sps 3338157642Sps /* Make sure the interrupt is not active. */ 3339157642Sps REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, BCE_PCICFG_INT_ACK_CMD_MASK_INT); 3340157642Sps 3341157642Sps /* Initialize DMA byte/word swapping, configure the number of DMA */ 3342157642Sps /* channels and PCI clock compensation delay. */ 3343157642Sps val = BCE_DMA_CONFIG_DATA_BYTE_SWAP | 3344157642Sps BCE_DMA_CONFIG_DATA_WORD_SWAP | 3345157642Sps#if BYTE_ORDER == BIG_ENDIAN 3346157642Sps BCE_DMA_CONFIG_CNTL_BYTE_SWAP | 3347157642Sps#endif 3348157642Sps BCE_DMA_CONFIG_CNTL_WORD_SWAP | 3349157642Sps DMA_READ_CHANS << 12 | 3350157642Sps DMA_WRITE_CHANS << 16; 3351157642Sps 3352157642Sps val |= (0x2 << 20) | BCE_DMA_CONFIG_CNTL_PCI_COMP_DLY; 3353157642Sps 3354157642Sps if ((sc->bce_flags & BCE_PCIX_FLAG) && (sc->bus_speed_mhz == 133)) 3355157642Sps val |= BCE_DMA_CONFIG_PCI_FAST_CLK_CMP; 3356157642Sps 3357157642Sps /* 3358157642Sps * This setting resolves a problem observed on certain Intel PCI 3359157642Sps * chipsets that cannot handle multiple outstanding DMA operations. 3360157642Sps * See errata E9_5706A1_65. 3361157642Sps */ 3362157642Sps if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) && 3363157642Sps (BCE_CHIP_ID(sc) != BCE_CHIP_ID_5706_A0) && 3364157642Sps !(sc->bce_flags & BCE_PCIX_FLAG)) 3365157642Sps val |= BCE_DMA_CONFIG_CNTL_PING_PONG_DMA; 3366157642Sps 3367157642Sps REG_WR(sc, BCE_DMA_CONFIG, val); 3368157642Sps 3369157642Sps /* Clear the PCI-X relaxed ordering bit. See errata E3_5708CA0_570. */ 3370157642Sps if (sc->bce_flags & BCE_PCIX_FLAG) { 3371157642Sps u16 val; 3372157642Sps 3373157642Sps val = pci_read_config(sc->bce_dev, BCE_PCI_PCIX_CMD, 2); 3374157642Sps pci_write_config(sc->bce_dev, BCE_PCI_PCIX_CMD, val & ~0x2, 2); 3375157642Sps } 3376157642Sps 3377157642Sps /* Enable the RX_V2P and Context state machines before access. */ 3378157642Sps REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, 3379157642Sps BCE_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE | 3380157642Sps BCE_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE | 3381157642Sps BCE_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE); 3382157642Sps 3383157642Sps /* Initialize context mapping and zero out the quick contexts. */ 3384157642Sps bce_init_context(sc); 3385157642Sps 3386157642Sps /* Initialize the on-boards CPUs */ 3387157642Sps bce_init_cpus(sc); 3388157642Sps 3389157642Sps /* Prepare NVRAM for access. */ 3390157642Sps if (bce_init_nvram(sc)) { 3391157642Sps rc = ENODEV; 3392157642Sps goto bce_chipinit_exit; 3393157642Sps } 3394157642Sps 3395157642Sps /* Set the kernel bypass block size */ 3396157642Sps val = REG_RD(sc, BCE_MQ_CONFIG); 3397157642Sps val &= ~BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE; 3398157642Sps val |= BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE_256; 3399157642Sps REG_WR(sc, BCE_MQ_CONFIG, val); 3400157642Sps 3401157642Sps val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE); 3402157642Sps REG_WR(sc, BCE_MQ_KNL_BYP_WIND_START, val); 3403157642Sps REG_WR(sc, BCE_MQ_KNL_WIND_END, val); 3404157642Sps 3405157642Sps val = (BCM_PAGE_BITS - 8) << 24; 3406157642Sps REG_WR(sc, BCE_RV2P_CONFIG, val); 3407157642Sps 3408157642Sps /* Configure page size. */ 3409157642Sps val = REG_RD(sc, BCE_TBDR_CONFIG); 3410157642Sps val &= ~BCE_TBDR_CONFIG_PAGE_SIZE; 3411157642Sps val |= (BCM_PAGE_BITS - 8) << 24 | 0x40; 3412157642Sps REG_WR(sc, BCE_TBDR_CONFIG, val); 3413157642Sps 3414157642Spsbce_chipinit_exit: 3415157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 3416157642Sps 3417157642Sps return(rc); 3418157642Sps} 3419157642Sps 3420157642Sps 3421157642Sps/****************************************************************************/ 3422157642Sps/* Initialize the controller in preparation to send/receive traffic. */ 3423157642Sps/* */ 3424157642Sps/* Returns: */ 3425157642Sps/* 0 for success, positive value for failure. */ 3426157642Sps/****************************************************************************/ 3427157642Spsstatic int 3428157642Spsbce_blockinit(struct bce_softc *sc) 3429157642Sps{ 3430157642Sps u32 reg, val; 3431157642Sps int rc = 0; 3432157642Sps 3433157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 3434157642Sps 3435157642Sps /* Load the hardware default MAC address. */ 3436157642Sps bce_set_mac_addr(sc); 3437157642Sps 3438157642Sps /* Set the Ethernet backoff seed value */ 3439157642Sps val = sc->eaddr[0] + (sc->eaddr[1] << 8) + 3440157642Sps (sc->eaddr[2] << 16) + (sc->eaddr[3] ) + 3441157642Sps (sc->eaddr[4] << 8) + (sc->eaddr[5] << 16); 3442157642Sps REG_WR(sc, BCE_EMAC_BACKOFF_SEED, val); 3443157642Sps 3444157642Sps sc->last_status_idx = 0; 3445157642Sps sc->rx_mode = BCE_EMAC_RX_MODE_SORT_MODE; 3446157642Sps 3447157642Sps /* Set up link change interrupt generation. */ 3448157642Sps REG_WR(sc, BCE_EMAC_ATTENTION_ENA, BCE_EMAC_ATTENTION_ENA_LINK); 3449157642Sps 3450157642Sps /* Program the physical address of the status block. */ 3451157642Sps REG_WR(sc, BCE_HC_STATUS_ADDR_L, 3452157642Sps BCE_ADDR_LO(sc->status_block_paddr)); 3453157642Sps REG_WR(sc, BCE_HC_STATUS_ADDR_H, 3454157642Sps BCE_ADDR_HI(sc->status_block_paddr)); 3455157642Sps 3456157642Sps /* Program the physical address of the statistics block. */ 3457157642Sps REG_WR(sc, BCE_HC_STATISTICS_ADDR_L, 3458157642Sps BCE_ADDR_LO(sc->stats_block_paddr)); 3459157642Sps REG_WR(sc, BCE_HC_STATISTICS_ADDR_H, 3460157642Sps BCE_ADDR_HI(sc->stats_block_paddr)); 3461157642Sps 3462157642Sps /* Program various host coalescing parameters. */ 3463157642Sps REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, 3464157642Sps (sc->bce_tx_quick_cons_trip_int << 16) | sc->bce_tx_quick_cons_trip); 3465157642Sps REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, 3466157642Sps (sc->bce_rx_quick_cons_trip_int << 16) | sc->bce_rx_quick_cons_trip); 3467157642Sps REG_WR(sc, BCE_HC_COMP_PROD_TRIP, 3468157642Sps (sc->bce_comp_prod_trip_int << 16) | sc->bce_comp_prod_trip); 3469157642Sps REG_WR(sc, BCE_HC_TX_TICKS, 3470157642Sps (sc->bce_tx_ticks_int << 16) | sc->bce_tx_ticks); 3471157642Sps REG_WR(sc, BCE_HC_RX_TICKS, 3472157642Sps (sc->bce_rx_ticks_int << 16) | sc->bce_rx_ticks); 3473157642Sps REG_WR(sc, BCE_HC_COM_TICKS, 3474157642Sps (sc->bce_com_ticks_int << 16) | sc->bce_com_ticks); 3475157642Sps REG_WR(sc, BCE_HC_CMD_TICKS, 3476157642Sps (sc->bce_cmd_ticks_int << 16) | sc->bce_cmd_ticks); 3477157642Sps REG_WR(sc, BCE_HC_STATS_TICKS, 3478157642Sps (sc->bce_stats_ticks & 0xffff00)); 3479157642Sps REG_WR(sc, BCE_HC_STAT_COLLECT_TICKS, 3480157642Sps 0xbb8); /* 3ms */ 3481157642Sps REG_WR(sc, BCE_HC_CONFIG, 3482157642Sps (BCE_HC_CONFIG_RX_TMR_MODE | BCE_HC_CONFIG_TX_TMR_MODE | 3483157642Sps BCE_HC_CONFIG_COLLECT_STATS)); 3484157642Sps 3485157642Sps /* Clear the internal statistics counters. */ 3486157642Sps REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW); 3487157642Sps 3488157642Sps /* Verify that bootcode is running. */ 3489157642Sps reg = REG_RD_IND(sc, sc->bce_shmem_base + BCE_DEV_INFO_SIGNATURE); 3490157642Sps 3491157642Sps DBRUNIF(DB_RANDOMTRUE(bce_debug_bootcode_running_failure), 3492157642Sps BCE_PRINTF(sc, "%s(%d): Simulating bootcode failure.\n", 3493157642Sps __FILE__, __LINE__); 3494157642Sps reg = 0); 3495157642Sps 3496157642Sps if ((reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK) != 3497157642Sps BCE_DEV_INFO_SIGNATURE_MAGIC) { 3498157642Sps BCE_PRINTF(sc, "%s(%d): Bootcode not running! Found: 0x%08X, " 3499157642Sps "Expected: 08%08X\n", __FILE__, __LINE__, 3500157642Sps (reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK), 3501157642Sps BCE_DEV_INFO_SIGNATURE_MAGIC); 3502157642Sps rc = ENODEV; 3503157642Sps goto bce_blockinit_exit; 3504157642Sps } 3505157642Sps 3506157642Sps /* Check if any management firmware is running. */ 3507157642Sps reg = REG_RD_IND(sc, sc->bce_shmem_base + BCE_PORT_FEATURE); 3508157642Sps if (reg & (BCE_PORT_FEATURE_ASF_ENABLED | BCE_PORT_FEATURE_IMD_ENABLED)) { 3509157642Sps DBPRINT(sc, BCE_INFO, "Management F/W Enabled.\n"); 3510157642Sps sc->bce_flags |= BCE_MFW_ENABLE_FLAG; 3511157642Sps } 3512157642Sps 3513157642Sps sc->bce_fw_ver = REG_RD_IND(sc, sc->bce_shmem_base + BCE_DEV_INFO_BC_REV); 3514157642Sps DBPRINT(sc, BCE_INFO, "bootcode rev = 0x%08X\n", sc->bce_fw_ver); 3515157642Sps 3516157642Sps /* Allow bootcode to apply any additional fixes before enabling MAC. */ 3517157642Sps rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT2 | BCE_DRV_MSG_CODE_RESET); 3518157642Sps 3519157642Sps /* Enable link state change interrupt generation. */ 3520157642Sps REG_WR(sc, BCE_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE); 3521157642Sps 3522157642Sps /* Enable all remaining blocks in the MAC. */ 3523157642Sps REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, 0x5ffffff); 3524157642Sps REG_RD(sc, BCE_MISC_ENABLE_SET_BITS); 3525157642Sps DELAY(20); 3526157642Sps 3527157642Spsbce_blockinit_exit: 3528157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 3529157642Sps 3530157642Sps return (rc); 3531157642Sps} 3532157642Sps 3533157642Sps 3534157642Sps/****************************************************************************/ 3535157642Sps/* Encapsulate an mbuf cluster into the rx_bd chain. */ 3536157642Sps/* */ 3537157642Sps/* The NetXtreme II can support Jumbo frames by using multiple rx_bd's. */ 3538157642Sps/* This routine will map an mbuf cluster into 1 or more rx_bd's as */ 3539157642Sps/* necessary. */ 3540157642Sps/* */ 3541157642Sps/* Returns: */ 3542157642Sps/* 0 for success, positive value for failure. */ 3543157642Sps/****************************************************************************/ 3544157642Spsstatic int 3545157642Spsbce_get_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, u16 *chain_prod, 3546157642Sps u32 *prod_bseq) 3547157642Sps{ 3548157642Sps bus_dmamap_t map; 3549157642Sps bus_dma_segment_t segs[4]; 3550157642Sps struct mbuf *m_new = NULL; 3551157642Sps struct rx_bd *rxbd; 3552157642Sps int i, nsegs, error, rc = 0; 3553157642Sps#ifdef BCE_DEBUG 3554157642Sps u16 debug_chain_prod = *chain_prod; 3555157642Sps#endif 3556157642Sps 3557157642Sps DBPRINT(sc, (BCE_VERBOSE_RESET | BCE_VERBOSE_RECV), "Entering %s()\n", 3558157642Sps __FUNCTION__); 3559157642Sps 3560157642Sps /* Make sure the inputs are valid. */ 3561157642Sps DBRUNIF((*chain_prod > MAX_RX_BD), 3562157642Sps BCE_PRINTF(sc, "%s(%d): RX producer out of range: 0x%04X > 0x%04X\n", 3563157642Sps __FILE__, __LINE__, *chain_prod, (u16) MAX_RX_BD)); 3564157642Sps 3565157642Sps DBPRINT(sc, BCE_VERBOSE_RECV, "%s(enter): prod = 0x%04X, chain_prod = 0x%04X, " 3566157642Sps "prod_bseq = 0x%08X\n", __FUNCTION__, *prod, *chain_prod, *prod_bseq); 3567157642Sps 3568157642Sps if (m == NULL) { 3569157642Sps 3570157642Sps DBRUNIF(DB_RANDOMTRUE(bce_debug_mbuf_allocation_failure), 3571157642Sps BCE_PRINTF(sc, "%s(%d): Simulating mbuf allocation failure.\n", 3572157642Sps __FILE__, __LINE__); 3573157642Sps sc->mbuf_alloc_failed++; 3574157642Sps rc = ENOBUFS; 3575157642Sps goto bce_get_buf_exit); 3576157642Sps 3577157642Sps /* This is a new mbuf allocation. */ 3578157642Sps MGETHDR(m_new, M_DONTWAIT, MT_DATA); 3579157642Sps if (m_new == NULL) { 3580157642Sps 3581157642Sps DBPRINT(sc, BCE_WARN, "%s(%d): RX mbuf header allocation failed!\n", 3582157642Sps __FILE__, __LINE__); 3583157642Sps 3584157642Sps DBRUNIF(1, sc->mbuf_alloc_failed++); 3585157642Sps 3586157642Sps rc = ENOBUFS; 3587157642Sps goto bce_get_buf_exit; 3588157642Sps } 3589157642Sps 3590157642Sps DBRUNIF(1, sc->rx_mbuf_alloc++); 3591157642Sps m_cljget(m_new, M_DONTWAIT, sc->mbuf_alloc_size); 3592157642Sps if (!(m_new->m_flags & M_EXT)) { 3593157642Sps 3594157642Sps DBPRINT(sc, BCE_WARN, "%s(%d): RX mbuf chain allocation failed!\n", 3595157642Sps __FILE__, __LINE__); 3596157642Sps 3597157642Sps m_freem(m_new); 3598157642Sps 3599157642Sps DBRUNIF(1, sc->rx_mbuf_alloc--); 3600157642Sps DBRUNIF(1, sc->mbuf_alloc_failed++); 3601157642Sps 3602157642Sps rc = ENOBUFS; 3603157642Sps goto bce_get_buf_exit; 3604157642Sps } 3605157642Sps 3606157642Sps m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size; 3607157642Sps } else { 3608157642Sps m_new = m; 3609157642Sps m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size; 3610157642Sps m_new->m_data = m_new->m_ext.ext_buf; 3611157642Sps } 3612157642Sps 3613157642Sps /* Map the mbuf cluster into device memory. */ 3614157642Sps map = sc->rx_mbuf_map[*chain_prod]; 3615157642Sps error = bus_dmamap_load_mbuf_sg(sc->rx_mbuf_tag, map, m_new, 3616157642Sps segs, &nsegs, BUS_DMA_NOWAIT); 3617157642Sps 3618157642Sps if (error) { 3619157642Sps BCE_PRINTF(sc, "%s(%d): Error mapping mbuf into RX chain!\n", 3620157642Sps __FILE__, __LINE__); 3621157642Sps 3622157642Sps m_freem(m_new); 3623157642Sps 3624157642Sps DBRUNIF(1, sc->rx_mbuf_alloc--); 3625157642Sps 3626157642Sps rc = ENOBUFS; 3627157642Sps goto bce_get_buf_exit; 3628157642Sps } 3629157642Sps 3630157642Sps /* Watch for overflow. */ 3631157642Sps DBRUNIF((sc->free_rx_bd > USABLE_RX_BD), 3632157642Sps BCE_PRINTF(sc, "%s(%d): Too many free rx_bd (0x%04X > 0x%04X)!\n", 3633157642Sps __FILE__, __LINE__, sc->free_rx_bd, (u16) USABLE_RX_BD)); 3634157642Sps 3635157642Sps DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark), 3636157642Sps sc->rx_low_watermark = sc->free_rx_bd); 3637157642Sps 3638157642Sps /* Setup the rx_bd for the first segment. */ 3639157642Sps rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)]; 3640157642Sps 3641157642Sps rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[0].ds_addr)); 3642157642Sps rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[0].ds_addr)); 3643157642Sps rxbd->rx_bd_len = htole32(segs[0].ds_len); 3644157642Sps rxbd->rx_bd_flags = htole32(RX_BD_FLAGS_START); 3645157642Sps *prod_bseq += segs[0].ds_len; 3646157642Sps 3647157642Sps for (i = 1; i < nsegs; i++) { 3648157642Sps 3649157642Sps *prod = NEXT_RX_BD(*prod); 3650157642Sps *chain_prod = RX_CHAIN_IDX(*prod); 3651157642Sps 3652157642Sps rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)]; 3653157642Sps 3654157642Sps rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr)); 3655157642Sps rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr)); 3656157642Sps rxbd->rx_bd_len = htole32(segs[i].ds_len); 3657157642Sps rxbd->rx_bd_flags = 0; 3658157642Sps *prod_bseq += segs[i].ds_len; 3659157642Sps } 3660157642Sps 3661157642Sps rxbd->rx_bd_flags |= htole32(RX_BD_FLAGS_END); 3662157642Sps 3663157642Sps /* Save the mbuf and update our counter. */ 3664157642Sps sc->rx_mbuf_ptr[*chain_prod] = m_new; 3665157642Sps sc->free_rx_bd -= nsegs; 3666157642Sps 3667157642Sps DBRUN(BCE_VERBOSE_RECV, bce_dump_rx_mbuf_chain(sc, debug_chain_prod, 3668157642Sps nsegs)); 3669157642Sps 3670157642Sps DBPRINT(sc, BCE_VERBOSE_RECV, "%s(exit): prod = 0x%04X, chain_prod = 0x%04X, " 3671157642Sps "prod_bseq = 0x%08X\n", __FUNCTION__, *prod, *chain_prod, *prod_bseq); 3672157642Sps 3673157642Spsbce_get_buf_exit: 3674157642Sps DBPRINT(sc, (BCE_VERBOSE_RESET | BCE_VERBOSE_RECV), "Exiting %s()\n", 3675157642Sps __FUNCTION__); 3676157642Sps 3677157642Sps return(rc); 3678157642Sps} 3679157642Sps 3680157642Sps 3681157642Sps/****************************************************************************/ 3682157642Sps/* Allocate memory and initialize the TX data structures. */ 3683157642Sps/* */ 3684157642Sps/* Returns: */ 3685157642Sps/* 0 for success, positive value for failure. */ 3686157642Sps/****************************************************************************/ 3687157642Spsstatic int 3688157642Spsbce_init_tx_chain(struct bce_softc *sc) 3689157642Sps{ 3690157642Sps struct tx_bd *txbd; 3691157642Sps u32 val; 3692157642Sps int i, rc = 0; 3693157642Sps 3694157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 3695157642Sps 3696157642Sps /* Set the initial TX producer/consumer indices. */ 3697157642Sps sc->tx_prod = 0; 3698157642Sps sc->tx_cons = 0; 3699157642Sps sc->tx_prod_bseq = 0; 3700157642Sps sc->used_tx_bd = 0; 3701157642Sps DBRUNIF(1, sc->tx_hi_watermark = USABLE_TX_BD); 3702157642Sps 3703157642Sps /* 3704157642Sps * The NetXtreme II supports a linked-list structre called 3705157642Sps * a Buffer Descriptor Chain (or BD chain). A BD chain 3706157642Sps * consists of a series of 1 or more chain pages, each of which 3707157642Sps * consists of a fixed number of BD entries. 3708157642Sps * The last BD entry on each page is a pointer to the next page 3709157642Sps * in the chain, and the last pointer in the BD chain 3710157642Sps * points back to the beginning of the chain. 3711157642Sps */ 3712157642Sps 3713157642Sps /* Set the TX next pointer chain entries. */ 3714157642Sps for (i = 0; i < TX_PAGES; i++) { 3715157642Sps int j; 3716157642Sps 3717157642Sps txbd = &sc->tx_bd_chain[i][USABLE_TX_BD_PER_PAGE]; 3718157642Sps 3719157642Sps /* Check if we've reached the last page. */ 3720157642Sps if (i == (TX_PAGES - 1)) 3721157642Sps j = 0; 3722157642Sps else 3723157642Sps j = i + 1; 3724157642Sps 3725157642Sps txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(sc->tx_bd_chain_paddr[j])); 3726157642Sps txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(sc->tx_bd_chain_paddr[j])); 3727157642Sps } 3728157642Sps 3729157642Sps /* 3730157642Sps * Initialize the context ID for an L2 TX chain. 3731157642Sps */ 3732157642Sps val = BCE_L2CTX_TYPE_TYPE_L2; 3733157642Sps val |= BCE_L2CTX_TYPE_SIZE_L2; 3734157642Sps CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TYPE, val); 3735157642Sps 3736157642Sps val = BCE_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16); 3737157642Sps CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_CMD_TYPE, val); 3738157642Sps 3739157642Sps /* Point the hardware to the first page in the chain. */ 3740157642Sps val = BCE_ADDR_HI(sc->tx_bd_chain_paddr[0]); 3741157642Sps CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TBDR_BHADDR_HI, val); 3742157642Sps val = BCE_ADDR_LO(sc->tx_bd_chain_paddr[0]); 3743157642Sps CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TBDR_BHADDR_LO, val); 3744157642Sps 3745157642Sps DBRUN(BCE_VERBOSE_SEND, bce_dump_tx_chain(sc, 0, TOTAL_TX_BD)); 3746157642Sps 3747157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 3748157642Sps 3749157642Sps return(rc); 3750157642Sps} 3751157642Sps 3752157642Sps 3753157642Sps/****************************************************************************/ 3754157642Sps/* Free memory and clear the TX data structures. */ 3755157642Sps/* */ 3756157642Sps/* Returns: */ 3757157642Sps/* Nothing. */ 3758157642Sps/****************************************************************************/ 3759157642Spsstatic void 3760157642Spsbce_free_tx_chain(struct bce_softc *sc) 3761157642Sps{ 3762157642Sps int i; 3763157642Sps 3764157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 3765157642Sps 3766157642Sps /* Unmap, unload, and free any mbufs still in the TX mbuf chain. */ 3767157642Sps for (i = 0; i < TOTAL_TX_BD; i++) { 3768157642Sps if (sc->tx_mbuf_ptr[i] != NULL) { 3769157642Sps if (sc->tx_mbuf_map != NULL) 3770157642Sps bus_dmamap_sync(sc->tx_mbuf_tag, sc->tx_mbuf_map[i], 3771157642Sps BUS_DMASYNC_POSTWRITE); 3772157642Sps m_freem(sc->tx_mbuf_ptr[i]); 3773157642Sps sc->tx_mbuf_ptr[i] = NULL; 3774157642Sps DBRUNIF(1, sc->tx_mbuf_alloc--); 3775157642Sps } 3776157642Sps } 3777157642Sps 3778157642Sps /* Clear each TX chain page. */ 3779157642Sps for (i = 0; i < TX_PAGES; i++) 3780157642Sps bzero((char *)sc->tx_bd_chain[i], BCE_TX_CHAIN_PAGE_SZ); 3781157642Sps 3782157642Sps /* Check if we lost any mbufs in the process. */ 3783157642Sps DBRUNIF((sc->tx_mbuf_alloc), 3784157642Sps BCE_PRINTF(sc, "%s(%d): Memory leak! Lost %d mbufs " 3785157642Sps "from tx chain!\n", 3786157642Sps __FILE__, __LINE__, sc->tx_mbuf_alloc)); 3787157642Sps 3788157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 3789157642Sps} 3790157642Sps 3791157642Sps 3792157642Sps/****************************************************************************/ 3793157642Sps/* Allocate memory and initialize the RX data structures. */ 3794157642Sps/* */ 3795157642Sps/* Returns: */ 3796157642Sps/* 0 for success, positive value for failure. */ 3797157642Sps/****************************************************************************/ 3798157642Spsstatic int 3799157642Spsbce_init_rx_chain(struct bce_softc *sc) 3800157642Sps{ 3801157642Sps struct rx_bd *rxbd; 3802157642Sps int i, rc = 0; 3803157642Sps u16 prod, chain_prod; 3804157642Sps u32 prod_bseq, val; 3805157642Sps 3806157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 3807157642Sps 3808157642Sps /* Initialize the RX producer and consumer indices. */ 3809157642Sps sc->rx_prod = 0; 3810157642Sps sc->rx_cons = 0; 3811157642Sps sc->rx_prod_bseq = 0; 3812157642Sps sc->free_rx_bd = BCE_RX_SLACK_SPACE; 3813157642Sps DBRUNIF(1, sc->rx_low_watermark = USABLE_RX_BD); 3814157642Sps 3815157642Sps /* Initialize the RX next pointer chain entries. */ 3816157642Sps for (i = 0; i < RX_PAGES; i++) { 3817157642Sps int j; 3818157642Sps 3819157642Sps rxbd = &sc->rx_bd_chain[i][USABLE_RX_BD_PER_PAGE]; 3820157642Sps 3821157642Sps /* Check if we've reached the last page. */ 3822157642Sps if (i == (RX_PAGES - 1)) 3823157642Sps j = 0; 3824157642Sps else 3825157642Sps j = i + 1; 3826157642Sps 3827157642Sps /* Setup the chain page pointers. */ 3828157642Sps rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(sc->rx_bd_chain_paddr[j])); 3829157642Sps rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(sc->rx_bd_chain_paddr[j])); 3830157642Sps } 3831157642Sps 3832157642Sps /* Initialize the context ID for an L2 RX chain. */ 3833157642Sps val = BCE_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; 3834157642Sps val |= BCE_L2CTX_CTX_TYPE_SIZE_L2; 3835157642Sps val |= 0x02 << 8; 3836157642Sps CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_CTX_TYPE, val); 3837157642Sps 3838157642Sps /* Point the hardware to the first page in the chain. */ 3839157642Sps val = BCE_ADDR_HI(sc->rx_bd_chain_paddr[0]); 3840157642Sps CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_NX_BDHADDR_HI, val); 3841157642Sps val = BCE_ADDR_LO(sc->rx_bd_chain_paddr[0]); 3842157642Sps CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_NX_BDHADDR_LO, val); 3843157642Sps 3844157642Sps /* Allocate mbuf clusters for the rx_bd chain. */ 3845157642Sps prod = prod_bseq = 0; 3846157642Sps while (prod < BCE_RX_SLACK_SPACE) { 3847157642Sps chain_prod = RX_CHAIN_IDX(prod); 3848157642Sps if (bce_get_buf(sc, NULL, &prod, &chain_prod, &prod_bseq)) { 3849157642Sps BCE_PRINTF(sc, "%s(%d): Error filling RX chain: rx_bd[0x%04X]!\n", 3850157642Sps __FILE__, __LINE__, chain_prod); 3851157642Sps rc = ENOBUFS; 3852157642Sps break; 3853157642Sps } 3854157642Sps prod = NEXT_RX_BD(prod); 3855157642Sps } 3856157642Sps 3857157642Sps /* Save the RX chain producer index. */ 3858157642Sps sc->rx_prod = prod; 3859157642Sps sc->rx_prod_bseq = prod_bseq; 3860157642Sps 3861157642Sps for (i = 0; i < RX_PAGES; i++) { 3862157642Sps bus_dmamap_sync( 3863157642Sps sc->rx_bd_chain_tag, 3864157642Sps sc->rx_bd_chain_map[i], 3865157642Sps BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3866157642Sps } 3867157642Sps 3868157642Sps /* Tell the chip about the waiting rx_bd's. */ 3869157642Sps REG_WR16(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BDIDX, sc->rx_prod); 3870157642Sps REG_WR(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BSEQ, sc->rx_prod_bseq); 3871157642Sps 3872157642Sps DBRUN(BCE_VERBOSE_RECV, bce_dump_rx_chain(sc, 0, TOTAL_RX_BD)); 3873157642Sps 3874157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 3875157642Sps 3876157642Sps return(rc); 3877157642Sps} 3878157642Sps 3879157642Sps 3880157642Sps/****************************************************************************/ 3881157642Sps/* Free memory and clear the RX data structures. */ 3882157642Sps/* */ 3883157642Sps/* Returns: */ 3884157642Sps/* Nothing. */ 3885157642Sps/****************************************************************************/ 3886157642Spsstatic void 3887157642Spsbce_free_rx_chain(struct bce_softc *sc) 3888157642Sps{ 3889157642Sps int i; 3890157642Sps 3891157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 3892157642Sps 3893157642Sps /* Free any mbufs still in the RX mbuf chain. */ 3894157642Sps for (i = 0; i < TOTAL_RX_BD; i++) { 3895157642Sps if (sc->rx_mbuf_ptr[i] != NULL) { 3896157642Sps if (sc->rx_mbuf_map[i] != NULL) 3897157642Sps bus_dmamap_sync(sc->rx_mbuf_tag, sc->rx_mbuf_map[i], 3898157642Sps BUS_DMASYNC_POSTREAD); 3899157642Sps m_freem(sc->rx_mbuf_ptr[i]); 3900157642Sps sc->rx_mbuf_ptr[i] = NULL; 3901157642Sps DBRUNIF(1, sc->rx_mbuf_alloc--); 3902157642Sps } 3903157642Sps } 3904157642Sps 3905157642Sps /* Clear each RX chain page. */ 3906157642Sps for (i = 0; i < RX_PAGES; i++) 3907157642Sps bzero((char *)sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ); 3908157642Sps 3909157642Sps /* Check if we lost any mbufs in the process. */ 3910157642Sps DBRUNIF((sc->rx_mbuf_alloc), 3911157642Sps BCE_PRINTF(sc, "%s(%d): Memory leak! Lost %d mbufs from rx chain!\n", 3912157642Sps __FILE__, __LINE__, sc->rx_mbuf_alloc)); 3913157642Sps 3914157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 3915157642Sps} 3916157642Sps 3917157642Sps 3918157642Sps/****************************************************************************/ 3919157642Sps/* Set media options. */ 3920157642Sps/* */ 3921157642Sps/* Returns: */ 3922157642Sps/* 0 for success, positive value for failure. */ 3923157642Sps/****************************************************************************/ 3924157642Spsstatic int 3925157642Spsbce_ifmedia_upd(struct ifnet *ifp) 3926157642Sps{ 3927157642Sps struct bce_softc *sc; 3928157642Sps struct mii_data *mii; 3929157642Sps struct ifmedia *ifm; 3930157642Sps int rc = 0; 3931157642Sps 3932157642Sps sc = ifp->if_softc; 3933157642Sps ifm = &sc->bce_ifmedia; 3934157642Sps 3935157642Sps /* DRC - ToDo: Add SerDes support. */ 3936157642Sps 3937157642Sps mii = device_get_softc(sc->bce_miibus); 3938157642Sps sc->bce_link = 0; 3939157642Sps if (mii->mii_instance) { 3940157642Sps struct mii_softc *miisc; 3941157642Sps for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL; 3942157642Sps miisc = LIST_NEXT(miisc, mii_list)) 3943157642Sps mii_phy_reset(miisc); 3944157642Sps } 3945157642Sps mii_mediachg(mii); 3946157642Sps 3947157642Sps return(rc); 3948157642Sps} 3949157642Sps 3950157642Sps 3951157642Sps/****************************************************************************/ 3952157642Sps/* Reports current media status. */ 3953157642Sps/* */ 3954157642Sps/* Returns: */ 3955157642Sps/* Nothing. */ 3956157642Sps/****************************************************************************/ 3957157642Spsstatic void 3958157642Spsbce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 3959157642Sps{ 3960157642Sps struct bce_softc *sc; 3961157642Sps struct mii_data *mii; 3962157642Sps 3963157642Sps sc = ifp->if_softc; 3964157642Sps 3965157642Sps BCE_LOCK(sc); 3966157642Sps 3967157642Sps mii = device_get_softc(sc->bce_miibus); 3968157642Sps 3969157642Sps /* DRC - ToDo: Add SerDes support. */ 3970157642Sps 3971157642Sps mii_pollstat(mii); 3972157642Sps ifmr->ifm_active = mii->mii_media_active; 3973157642Sps ifmr->ifm_status = mii->mii_media_status; 3974157642Sps 3975157642Sps BCE_UNLOCK(sc); 3976157642Sps} 3977157642Sps 3978157642Sps 3979157642Sps/****************************************************************************/ 3980157642Sps/* Handles PHY generated interrupt events. */ 3981157642Sps/* */ 3982157642Sps/* Returns: */ 3983157642Sps/* Nothing. */ 3984157642Sps/****************************************************************************/ 3985157642Spsstatic void 3986157642Spsbce_phy_intr(struct bce_softc *sc) 3987157642Sps{ 3988157642Sps u32 new_link_state, old_link_state; 3989157642Sps 3990157642Sps new_link_state = sc->status_block->status_attn_bits & 3991157642Sps STATUS_ATTN_BITS_LINK_STATE; 3992157642Sps old_link_state = sc->status_block->status_attn_bits_ack & 3993157642Sps STATUS_ATTN_BITS_LINK_STATE; 3994157642Sps 3995157642Sps /* Handle any changes if the link state has changed. */ 3996157642Sps if (new_link_state != old_link_state) { 3997157642Sps 3998157642Sps DBRUN(BCE_VERBOSE_INTR, bce_dump_status_block(sc)); 3999157642Sps 4000157642Sps sc->bce_link = 0; 4001157642Sps callout_stop(&sc->bce_stat_ch); 4002157642Sps bce_tick_locked(sc); 4003157642Sps 4004157642Sps /* Update the status_attn_bits_ack field in the status block. */ 4005157642Sps if (new_link_state) { 4006157642Sps REG_WR(sc, BCE_PCICFG_STATUS_BIT_SET_CMD, 4007157642Sps STATUS_ATTN_BITS_LINK_STATE); 4008157642Sps DBPRINT(sc, BCE_INFO, "Link is now UP.\n"); 4009157642Sps } 4010157642Sps else { 4011157642Sps REG_WR(sc, BCE_PCICFG_STATUS_BIT_CLEAR_CMD, 4012157642Sps STATUS_ATTN_BITS_LINK_STATE); 4013157642Sps DBPRINT(sc, BCE_INFO, "Link is now DOWN.\n"); 4014157642Sps } 4015157642Sps 4016157642Sps } 4017157642Sps 4018157642Sps /* Acknowledge the link change interrupt. */ 4019157642Sps REG_WR(sc, BCE_EMAC_STATUS, BCE_EMAC_STATUS_LINK_CHANGE); 4020157642Sps} 4021157642Sps 4022157642Sps 4023157642Sps/****************************************************************************/ 4024157642Sps/* Handles received frame interrupt events. */ 4025157642Sps/* */ 4026157642Sps/* Returns: */ 4027157642Sps/* Nothing. */ 4028157642Sps/****************************************************************************/ 4029157642Spsstatic void 4030157642Spsbce_rx_intr(struct bce_softc *sc) 4031157642Sps{ 4032157642Sps struct status_block *sblk = sc->status_block; 4033157642Sps struct ifnet *ifp = sc->bce_ifp; 4034157642Sps u16 hw_cons, sw_cons, sw_chain_cons, sw_prod, sw_chain_prod; 4035157642Sps u32 sw_prod_bseq; 4036157642Sps struct l2_fhdr *l2fhdr; 4037157642Sps 4038157642Sps DBRUNIF(1, sc->rx_interrupts++); 4039157642Sps 4040157642Sps /* Prepare the RX chain pages to be accessed by the host CPU. */ 4041157642Sps for (int i = 0; i < RX_PAGES; i++) 4042157642Sps bus_dmamap_sync(sc->rx_bd_chain_tag, 4043157642Sps sc->rx_bd_chain_map[i], BUS_DMASYNC_POSTWRITE); 4044157642Sps 4045157642Sps /* Get the hardware's view of the RX consumer index. */ 4046157642Sps hw_cons = sc->hw_rx_cons = sblk->status_rx_quick_consumer_index0; 4047157642Sps if ((hw_cons & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE) 4048157642Sps hw_cons++; 4049157642Sps 4050157642Sps /* Get working copies of the driver's view of the RX indices. */ 4051157642Sps sw_cons = sc->rx_cons; 4052157642Sps sw_prod = sc->rx_prod; 4053157642Sps sw_prod_bseq = sc->rx_prod_bseq; 4054157642Sps 4055157642Sps DBPRINT(sc, BCE_INFO_RECV, "%s(enter): sw_prod = 0x%04X, " 4056157642Sps "sw_cons = 0x%04X, sw_prod_bseq = 0x%08X\n", 4057157642Sps __FUNCTION__, sw_prod, sw_cons, 4058157642Sps sw_prod_bseq); 4059157642Sps 4060157642Sps /* Prevent speculative reads from getting ahead of the status block. */ 4061157642Sps bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0, 4062157642Sps BUS_SPACE_BARRIER_READ); 4063157642Sps 4064157642Sps DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark), 4065157642Sps sc->rx_low_watermark = sc->free_rx_bd); 4066157642Sps 4067157642Sps /* 4068157642Sps * Scan through the receive chain as long 4069157642Sps * as there is work to do. 4070157642Sps */ 4071157642Sps while (sw_cons != hw_cons) { 4072157642Sps struct mbuf *m; 4073157642Sps struct rx_bd *rxbd; 4074157642Sps unsigned int len; 4075157642Sps u32 status; 4076157642Sps 4077157642Sps /* Convert the producer/consumer indices to an actual rx_bd index. */ 4078157642Sps sw_chain_cons = RX_CHAIN_IDX(sw_cons); 4079157642Sps sw_chain_prod = RX_CHAIN_IDX(sw_prod); 4080157642Sps 4081157642Sps /* Get the used rx_bd. */ 4082157642Sps rxbd = &sc->rx_bd_chain[RX_PAGE(sw_chain_cons)][RX_IDX(sw_chain_cons)]; 4083157642Sps sc->free_rx_bd++; 4084157642Sps 4085157642Sps DBRUN(BCE_VERBOSE_RECV, 4086157642Sps BCE_PRINTF(sc, "%s(): ", __FUNCTION__); 4087157642Sps bce_dump_rxbd(sc, sw_chain_cons, rxbd)); 4088157642Sps 4089157642Sps#ifdef DEVICE_POLLING 4090157642Sps if (ifp->if_capenable & IFCAP_POLLING) { 4091157642Sps if (sc->bce_rxcycles <= 0) 4092157642Sps break; 4093157724Sru sc->bce_rxcycles--; 4094157642Sps } 4095157642Sps#endif 4096157642Sps 4097157642Sps /* The mbuf is stored with the last rx_bd entry of a packet. */ 4098157642Sps if (sc->rx_mbuf_ptr[sw_chain_cons] != NULL) { 4099157642Sps 4100157642Sps /* Validate that this is the last rx_bd. */ 4101157642Sps DBRUNIF((!(rxbd->rx_bd_flags & RX_BD_FLAGS_END)), 4102157642Sps BCE_PRINTF(sc, "%s(%d): Unexpected mbuf found in rx_bd[0x%04X]!\n", 4103157642Sps __FILE__, __LINE__, sw_chain_cons); 4104157642Sps bce_breakpoint(sc)); 4105157642Sps 4106157642Sps /* DRC - ToDo: If the received packet is small, say less */ 4107157642Sps /* than 128 bytes, allocate a new mbuf here, */ 4108157642Sps /* copy the data to that mbuf, and recycle */ 4109157642Sps /* the mapped jumbo frame. */ 4110157642Sps 4111157642Sps /* Unmap the mbuf from DMA space. */ 4112157642Sps bus_dmamap_sync(sc->rx_mbuf_tag, 4113157642Sps sc->rx_mbuf_map[sw_chain_cons], 4114157642Sps BUS_DMASYNC_POSTREAD); 4115157642Sps bus_dmamap_unload(sc->rx_mbuf_tag, 4116157642Sps sc->rx_mbuf_map[sw_chain_cons]); 4117157642Sps 4118157642Sps /* Remove the mbuf from the driver's chain. */ 4119157642Sps m = sc->rx_mbuf_ptr[sw_chain_cons]; 4120157642Sps sc->rx_mbuf_ptr[sw_chain_cons] = NULL; 4121157642Sps 4122157642Sps /* 4123157642Sps * Frames received on the NetXteme II are prepended 4124157642Sps * with the l2_fhdr structure which provides status 4125157642Sps * information about the received frame (including 4126157642Sps * VLAN tags and checksum info) and are also 4127157642Sps * automatically adjusted to align the IP header 4128157642Sps * (i.e. two null bytes are inserted before the 4129157642Sps * Ethernet header). 4130157642Sps */ 4131157642Sps l2fhdr = mtod(m, struct l2_fhdr *); 4132157642Sps 4133157642Sps len = l2fhdr->l2_fhdr_pkt_len; 4134157642Sps status = l2fhdr->l2_fhdr_status; 4135157642Sps 4136157642Sps DBRUNIF(DB_RANDOMTRUE(bce_debug_l2fhdr_status_check), 4137157642Sps BCE_PRINTF(sc, "Simulating l2_fhdr status error.\n"); 4138157642Sps status = status | L2_FHDR_ERRORS_PHY_DECODE); 4139157642Sps 4140157642Sps /* Watch for unusual sized frames. */ 4141157642Sps DBRUNIF(((len < BCE_MIN_MTU) || (len > BCE_MAX_JUMBO_ETHER_MTU_VLAN)), 4142157642Sps BCE_PRINTF(sc, "%s(%d): Unusual frame size found. " 4143157642Sps "Min(%d), Actual(%d), Max(%d)\n", 4144157642Sps __FILE__, __LINE__, (int) BCE_MIN_MTU, 4145157642Sps len, (int) BCE_MAX_JUMBO_ETHER_MTU_VLAN); 4146157642Sps bce_dump_mbuf(sc, m); 4147157642Sps bce_breakpoint(sc)); 4148157642Sps 4149157642Sps len -= ETHER_CRC_LEN; 4150157642Sps 4151157642Sps /* Check the received frame for errors. */ 4152157642Sps if (status & (L2_FHDR_ERRORS_BAD_CRC | 4153157642Sps L2_FHDR_ERRORS_PHY_DECODE | L2_FHDR_ERRORS_ALIGNMENT | 4154157642Sps L2_FHDR_ERRORS_TOO_SHORT | L2_FHDR_ERRORS_GIANT_FRAME)) { 4155157642Sps 4156157642Sps ifp->if_ierrors++; 4157157642Sps DBRUNIF(1, sc->l2fhdr_status_errors++); 4158157642Sps 4159157642Sps /* Reuse the mbuf for a new frame. */ 4160157642Sps if (bce_get_buf(sc, m, &sw_prod, &sw_chain_prod, &sw_prod_bseq)) { 4161157642Sps 4162157642Sps DBRUNIF(1, bce_breakpoint(sc)); 4163157642Sps panic("bce%d: Can't reuse RX mbuf!\n", sc->bce_unit); 4164157642Sps 4165157642Sps } 4166157642Sps goto bce_rx_int_next_rx; 4167157642Sps } 4168157642Sps 4169157642Sps /* 4170157642Sps * Get a new mbuf for the rx_bd. If no new 4171157642Sps * mbufs are available then reuse the current mbuf, 4172157642Sps * log an ierror on the interface, and generate 4173157642Sps * an error in the system log. 4174157642Sps */ 4175157642Sps if (bce_get_buf(sc, NULL, &sw_prod, &sw_chain_prod, &sw_prod_bseq)) { 4176157642Sps 4177157642Sps DBRUN(BCE_WARN, 4178157642Sps BCE_PRINTF(sc, "%s(%d): Failed to allocate " 4179157642Sps "new mbuf, incoming frame dropped!\n", 4180157642Sps __FILE__, __LINE__)); 4181157642Sps 4182157642Sps ifp->if_ierrors++; 4183157642Sps 4184157642Sps /* Try and reuse the exisitng mbuf. */ 4185157642Sps if (bce_get_buf(sc, m, &sw_prod, &sw_chain_prod, &sw_prod_bseq)) { 4186157642Sps 4187157642Sps DBRUNIF(1, bce_breakpoint(sc)); 4188157642Sps panic("bce%d: Double mbuf allocation failure!", sc->bce_unit); 4189157642Sps 4190157642Sps } 4191157642Sps goto bce_rx_int_next_rx; 4192157642Sps } 4193157642Sps 4194157642Sps /* Skip over the l2_fhdr when passing the data up the stack. */ 4195157642Sps m_adj(m, sizeof(struct l2_fhdr) + ETHER_ALIGN); 4196157642Sps 4197157642Sps /* Adjust the packet length to match the received data. */ 4198157642Sps m->m_pkthdr.len = m->m_len = len; 4199157642Sps 4200157642Sps /* Send the packet to the appropriate interface. */ 4201157642Sps m->m_pkthdr.rcvif = ifp; 4202157642Sps 4203157642Sps DBRUN(BCE_VERBOSE_RECV, 4204157642Sps struct ether_header *eh; 4205157642Sps eh = mtod(m, struct ether_header *); 4206157642Sps BCE_PRINTF(sc, "%s(): to: %6D, from: %6D, type: 0x%04X\n", 4207157642Sps __FUNCTION__, eh->ether_dhost, ":", 4208157642Sps eh->ether_shost, ":", htons(eh->ether_type))); 4209157642Sps 4210157642Sps /* Validate the checksum if offload enabled. */ 4211157642Sps if (ifp->if_capenable & IFCAP_RXCSUM) { 4212157642Sps 4213157642Sps /* Check for an IP datagram. */ 4214157642Sps if (status & L2_FHDR_STATUS_IP_DATAGRAM) { 4215157642Sps m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 4216157642Sps 4217157642Sps /* Check if the IP checksum is valid. */ 4218157642Sps if ((l2fhdr->l2_fhdr_ip_xsum ^ 0xffff) == 0) 4219157642Sps m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 4220157642Sps else 4221157642Sps DBPRINT(sc, BCE_WARN_SEND, 4222157642Sps "%s(): Invalid IP checksum = 0x%04X!\n", 4223157642Sps __FUNCTION__, l2fhdr->l2_fhdr_ip_xsum); 4224157642Sps } 4225157642Sps 4226157642Sps /* Check for a valid TCP/UDP frame. */ 4227157642Sps if (status & (L2_FHDR_STATUS_TCP_SEGMENT | 4228157642Sps L2_FHDR_STATUS_UDP_DATAGRAM)) { 4229157642Sps 4230157642Sps /* Check for a good TCP/UDP checksum. */ 4231157642Sps if ((status & (L2_FHDR_ERRORS_TCP_XSUM | 4232157642Sps L2_FHDR_ERRORS_UDP_XSUM)) == 0) { 4233157642Sps m->m_pkthdr.csum_data = 4234157642Sps l2fhdr->l2_fhdr_tcp_udp_xsum; 4235157642Sps m->m_pkthdr.csum_flags |= (CSUM_DATA_VALID 4236157642Sps | CSUM_PSEUDO_HDR); 4237157642Sps } else 4238157642Sps DBPRINT(sc, BCE_WARN_SEND, 4239157642Sps "%s(): Invalid TCP/UDP checksum = 0x%04X!\n", 4240157642Sps __FUNCTION__, l2fhdr->l2_fhdr_tcp_udp_xsum); 4241157642Sps } 4242157642Sps } 4243157642Sps 4244157642Sps 4245157642Sps /* 4246157642Sps * If we received a packet with a vlan tag, 4247157642Sps * attach that information to the packet. 4248157642Sps */ 4249157642Sps if (status & L2_FHDR_STATUS_L2_VLAN_TAG) { 4250157642Sps DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): VLAN tag = 0x%04X\n", 4251157642Sps __FUNCTION__, l2fhdr->l2_fhdr_vlan_tag); 4252157642Sps#if __FreeBSD_version < 700000 4253157642Sps VLAN_INPUT_TAG(ifp, m, l2fhdr->l2_fhdr_vlan_tag, continue); 4254157642Sps#else 4255157642Sps VLAN_INPUT_TAG(ifp, m, l2fhdr->l2_fhdr_vlan_tag); 4256157642Sps if (m == NULL) 4257157642Sps continue; 4258157642Sps#endif 4259157642Sps } 4260157642Sps 4261157642Sps /* Pass the mbuf off to the upper layers. */ 4262157642Sps ifp->if_ipackets++; 4263157642Sps DBPRINT(sc, BCE_VERBOSE_RECV, "%s(): Passing received frame up.\n", 4264157642Sps __FUNCTION__); 4265157642Sps BCE_UNLOCK(sc); 4266157642Sps (*ifp->if_input)(ifp, m); 4267157642Sps DBRUNIF(1, sc->rx_mbuf_alloc--); 4268157642Sps BCE_LOCK(sc); 4269157642Sps 4270157642Spsbce_rx_int_next_rx: 4271157642Sps sw_prod = NEXT_RX_BD(sw_prod); 4272157642Sps } 4273157642Sps 4274157642Sps sw_cons = NEXT_RX_BD(sw_cons); 4275157642Sps 4276157642Sps /* Refresh hw_cons to see if there's new work */ 4277157642Sps if (sw_cons == hw_cons) { 4278157642Sps hw_cons = sc->hw_rx_cons = sblk->status_rx_quick_consumer_index0; 4279157642Sps if ((hw_cons & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE) 4280157642Sps hw_cons++; 4281157642Sps } 4282157642Sps 4283157642Sps /* Prevent speculative reads from getting ahead of the status block. */ 4284157642Sps bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0, 4285157642Sps BUS_SPACE_BARRIER_READ); 4286157642Sps } 4287157642Sps 4288157642Sps for (int i = 0; i < RX_PAGES; i++) 4289157642Sps bus_dmamap_sync(sc->rx_bd_chain_tag, 4290157642Sps sc->rx_bd_chain_map[i], BUS_DMASYNC_PREWRITE); 4291157642Sps 4292157642Sps sc->rx_cons = sw_cons; 4293157642Sps sc->rx_prod = sw_prod; 4294157642Sps sc->rx_prod_bseq = sw_prod_bseq; 4295157642Sps 4296157642Sps REG_WR16(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BDIDX, sc->rx_prod); 4297157642Sps REG_WR(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BSEQ, sc->rx_prod_bseq); 4298157642Sps 4299157642Sps DBPRINT(sc, BCE_INFO_RECV, "%s(exit): rx_prod = 0x%04X, " 4300157642Sps "rx_cons = 0x%04X, rx_prod_bseq = 0x%08X\n", 4301157642Sps __FUNCTION__, sc->rx_prod, sc->rx_cons, sc->rx_prod_bseq); 4302157642Sps} 4303157642Sps 4304157642Sps 4305157642Sps/****************************************************************************/ 4306157642Sps/* Handles transmit completion interrupt events. */ 4307157642Sps/* */ 4308157642Sps/* Returns: */ 4309157642Sps/* Nothing. */ 4310157642Sps/****************************************************************************/ 4311157642Spsstatic void 4312157642Spsbce_tx_intr(struct bce_softc *sc) 4313157642Sps{ 4314157642Sps struct status_block *sblk = sc->status_block; 4315157642Sps struct ifnet *ifp = sc->bce_ifp; 4316157642Sps u16 hw_tx_cons, sw_tx_cons, sw_tx_chain_cons; 4317157642Sps 4318157642Sps BCE_LOCK_ASSERT(sc); 4319157642Sps 4320157642Sps DBRUNIF(1, sc->tx_interrupts++); 4321157642Sps 4322157642Sps /* Get the hardware's view of the TX consumer index. */ 4323157642Sps hw_tx_cons = sc->hw_tx_cons = sblk->status_tx_quick_consumer_index0; 4324157642Sps 4325157642Sps /* Skip to the next entry if this is a chain page pointer. */ 4326157642Sps if ((hw_tx_cons & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE) 4327157642Sps hw_tx_cons++; 4328157642Sps 4329157642Sps sw_tx_cons = sc->tx_cons; 4330157642Sps 4331157642Sps /* Prevent speculative reads from getting ahead of the status block. */ 4332157642Sps bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0, 4333157642Sps BUS_SPACE_BARRIER_READ); 4334157642Sps 4335157642Sps /* Cycle through any completed TX chain page entries. */ 4336157642Sps while (sw_tx_cons != hw_tx_cons) { 4337157642Sps#ifdef BCE_DEBUG 4338157642Sps struct tx_bd *txbd = NULL; 4339157642Sps#endif 4340157642Sps sw_tx_chain_cons = TX_CHAIN_IDX(sw_tx_cons); 4341157642Sps 4342157642Sps DBPRINT(sc, BCE_INFO_SEND, 4343157642Sps "%s(): hw_tx_cons = 0x%04X, sw_tx_cons = 0x%04X, " 4344157642Sps "sw_tx_chain_cons = 0x%04X\n", 4345157642Sps __FUNCTION__, hw_tx_cons, sw_tx_cons, sw_tx_chain_cons); 4346157642Sps 4347157642Sps DBRUNIF((sw_tx_chain_cons > MAX_TX_BD), 4348157642Sps BCE_PRINTF(sc, "%s(%d): TX chain consumer out of range! " 4349157642Sps " 0x%04X > 0x%04X\n", 4350157642Sps __FILE__, __LINE__, sw_tx_chain_cons, 4351157642Sps (int) MAX_TX_BD); 4352157642Sps bce_breakpoint(sc)); 4353157642Sps 4354157642Sps DBRUNIF(1, 4355157642Sps txbd = &sc->tx_bd_chain[TX_PAGE(sw_tx_chain_cons)] 4356157642Sps [TX_IDX(sw_tx_chain_cons)]); 4357157642Sps 4358157642Sps DBRUNIF((txbd == NULL), 4359157642Sps BCE_PRINTF(sc, "%s(%d): Unexpected NULL tx_bd[0x%04X]!\n", 4360157642Sps __FILE__, __LINE__, sw_tx_chain_cons); 4361157642Sps bce_breakpoint(sc)); 4362157642Sps 4363157642Sps DBRUN(BCE_INFO_SEND, 4364157642Sps BCE_PRINTF(sc, "%s(): ", __FUNCTION__); 4365157642Sps bce_dump_txbd(sc, sw_tx_chain_cons, txbd)); 4366157642Sps 4367157642Sps /* 4368157642Sps * Free the associated mbuf. Remember 4369157642Sps * that only the last tx_bd of a packet 4370157642Sps * has an mbuf pointer and DMA map. 4371157642Sps */ 4372157642Sps if (sc->tx_mbuf_ptr[sw_tx_chain_cons] != NULL) { 4373157642Sps 4374157642Sps /* Validate that this is the last tx_bd. */ 4375157642Sps DBRUNIF((!(txbd->tx_bd_vlan_tag_flags & TX_BD_FLAGS_END)), 4376157642Sps BCE_PRINTF(sc, "%s(%d): tx_bd END flag not set but " 4377157642Sps "txmbuf == NULL!\n", __FILE__, __LINE__); 4378157642Sps bce_breakpoint(sc)); 4379157642Sps 4380157642Sps DBRUN(BCE_INFO_SEND, 4381157642Sps BCE_PRINTF(sc, "%s(): Unloading map/freeing mbuf " 4382157642Sps "from tx_bd[0x%04X]\n", __FUNCTION__, sw_tx_chain_cons)); 4383157642Sps 4384157642Sps /* Unmap the mbuf. */ 4385157642Sps bus_dmamap_unload(sc->tx_mbuf_tag, 4386157642Sps sc->tx_mbuf_map[sw_tx_chain_cons]); 4387157642Sps 4388157642Sps /* Free the mbuf. */ 4389157642Sps m_freem(sc->tx_mbuf_ptr[sw_tx_chain_cons]); 4390157642Sps sc->tx_mbuf_ptr[sw_tx_chain_cons] = NULL; 4391157642Sps DBRUNIF(1, sc->tx_mbuf_alloc--); 4392157642Sps 4393157642Sps ifp->if_opackets++; 4394157642Sps } 4395157642Sps 4396157642Sps sc->used_tx_bd--; 4397157642Sps sw_tx_cons = NEXT_TX_BD(sw_tx_cons); 4398157642Sps 4399157642Sps /* Refresh hw_cons to see if there's new work. */ 4400157642Sps hw_tx_cons = sc->hw_tx_cons = sblk->status_tx_quick_consumer_index0; 4401157642Sps if ((hw_tx_cons & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE) 4402157642Sps hw_tx_cons++; 4403157642Sps 4404157642Sps /* Prevent speculative reads from getting ahead of the status block. */ 4405157642Sps bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0, 4406157642Sps BUS_SPACE_BARRIER_READ); 4407157642Sps } 4408157642Sps 4409157642Sps /* Clear the TX timeout timer. */ 4410157642Sps ifp->if_timer = 0; 4411157642Sps 4412157642Sps /* Clear the tx hardware queue full flag. */ 4413157642Sps if ((sc->used_tx_bd + BCE_TX_SLACK_SPACE) < USABLE_TX_BD) { 4414157642Sps DBRUNIF((ifp->if_drv_flags & IFF_DRV_OACTIVE), 4415157642Sps BCE_PRINTF(sc, "%s(): TX chain is open for business! Used tx_bd = %d\n", 4416157642Sps __FUNCTION__, sc->used_tx_bd)); 4417157642Sps ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 4418157642Sps } 4419157642Sps 4420157642Sps sc->tx_cons = sw_tx_cons; 4421157642Sps} 4422157642Sps 4423157642Sps 4424157642Sps/****************************************************************************/ 4425157642Sps/* Disables interrupt generation. */ 4426157642Sps/* */ 4427157642Sps/* Returns: */ 4428157642Sps/* Nothing. */ 4429157642Sps/****************************************************************************/ 4430157642Spsstatic void 4431157642Spsbce_disable_intr(struct bce_softc *sc) 4432157642Sps{ 4433157642Sps REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 4434157642Sps BCE_PCICFG_INT_ACK_CMD_MASK_INT); 4435157642Sps REG_RD(sc, BCE_PCICFG_INT_ACK_CMD); 4436157642Sps} 4437157642Sps 4438157642Sps 4439157642Sps/****************************************************************************/ 4440157642Sps/* Enables interrupt generation. */ 4441157642Sps/* */ 4442157642Sps/* Returns: */ 4443157642Sps/* Nothing. */ 4444157642Sps/****************************************************************************/ 4445157642Spsstatic void 4446157642Spsbce_enable_intr(struct bce_softc *sc) 4447157642Sps{ 4448157642Sps u32 val; 4449157642Sps 4450157642Sps REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 4451157642Sps BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | 4452157642Sps BCE_PCICFG_INT_ACK_CMD_MASK_INT | sc->last_status_idx); 4453157642Sps 4454157642Sps REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 4455157642Sps BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx); 4456157642Sps 4457157642Sps val = REG_RD(sc, BCE_HC_COMMAND); 4458157642Sps REG_WR(sc, BCE_HC_COMMAND, val | BCE_HC_COMMAND_COAL_NOW); 4459157642Sps} 4460157642Sps 4461157642Sps 4462157642Sps/****************************************************************************/ 4463157642Sps/* Handles controller initialization. */ 4464157642Sps/* */ 4465157642Sps/* Must be called from a locked routine. */ 4466157642Sps/* */ 4467157642Sps/* Returns: */ 4468157642Sps/* Nothing. */ 4469157642Sps/****************************************************************************/ 4470157642Spsstatic void 4471157642Spsbce_init_locked(struct bce_softc *sc) 4472157642Sps{ 4473157642Sps struct ifnet *ifp; 4474157642Sps u32 ether_mtu; 4475157642Sps 4476157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 4477157642Sps 4478157642Sps BCE_LOCK_ASSERT(sc); 4479157642Sps 4480157642Sps ifp = sc->bce_ifp; 4481157642Sps 4482157642Sps /* Check if the driver is still running and bail out if it is. */ 4483157642Sps if (ifp->if_drv_flags & IFF_DRV_RUNNING) 4484157642Sps goto bce_init_locked_exit; 4485157642Sps 4486157642Sps bce_stop(sc); 4487157642Sps 4488157642Sps if (bce_reset(sc, BCE_DRV_MSG_CODE_RESET)) { 4489157642Sps BCE_PRINTF(sc, "%s(%d): Controller reset failed!\n", 4490157642Sps __FILE__, __LINE__); 4491157642Sps goto bce_init_locked_exit; 4492157642Sps } 4493157642Sps 4494157642Sps if (bce_chipinit(sc)) { 4495157642Sps BCE_PRINTF(sc, "%s(%d): Controller initialization failed!\n", 4496157642Sps __FILE__, __LINE__); 4497157642Sps goto bce_init_locked_exit; 4498157642Sps } 4499157642Sps 4500157642Sps if (bce_blockinit(sc)) { 4501157642Sps BCE_PRINTF(sc, "%s(%d): Block initialization failed!\n", 4502157642Sps __FILE__, __LINE__); 4503157642Sps goto bce_init_locked_exit; 4504157642Sps } 4505157642Sps 4506157642Sps /* Load our MAC address. */ 4507157642Sps bcopy(IF_LLADDR(sc->bce_ifp), sc->eaddr, ETHER_ADDR_LEN); 4508157642Sps bce_set_mac_addr(sc); 4509157642Sps 4510157642Sps /* Calculate and program the Ethernet MTU size. */ 4511157642Sps ether_mtu = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ifp->if_mtu + 4512157642Sps ETHER_CRC_LEN; 4513157642Sps 4514157642Sps DBPRINT(sc, BCE_INFO, "%s(): setting mtu = %d\n",__FUNCTION__, ether_mtu); 4515157642Sps 4516157642Sps /* 4517157642Sps * Program the mtu, enabling jumbo frame 4518157642Sps * support if necessary. Also set the mbuf 4519157642Sps * allocation count for RX frames. 4520157642Sps */ 4521157642Sps if (ether_mtu > ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) { 4522157642Sps REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, ether_mtu | 4523157642Sps BCE_EMAC_RX_MTU_SIZE_JUMBO_ENA); 4524157642Sps sc->mbuf_alloc_size = MJUM9BYTES; 4525157642Sps } else { 4526157642Sps REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, ether_mtu); 4527157642Sps sc->mbuf_alloc_size = MCLBYTES; 4528157642Sps } 4529157642Sps 4530157642Sps /* Calculate the RX Ethernet frame size for rx_bd's. */ 4531157642Sps sc->max_frame_size = sizeof(struct l2_fhdr) + 2 + ether_mtu + 8; 4532157642Sps 4533157642Sps DBPRINT(sc, BCE_INFO, 4534157642Sps "%s(): mclbytes = %d, mbuf_alloc_size = %d, " 4535157642Sps "max_frame_size = %d\n", 4536157642Sps __FUNCTION__, (int) MCLBYTES, sc->mbuf_alloc_size, sc->max_frame_size); 4537157642Sps 4538157642Sps /* Program appropriate promiscuous/multicast filtering. */ 4539157642Sps bce_set_rx_mode(sc); 4540157642Sps 4541157642Sps /* Init RX buffer descriptor chain. */ 4542157642Sps bce_init_rx_chain(sc); 4543157642Sps 4544157642Sps /* Init TX buffer descriptor chain. */ 4545157642Sps bce_init_tx_chain(sc); 4546157642Sps 4547157642Sps#ifdef DEVICE_POLLING 4548157642Sps /* Disable interrupts if we are polling. */ 4549157642Sps if (ifp->if_capenable & IFCAP_POLLING) { 4550157642Sps bce_disable_intr(sc); 4551157642Sps 4552157642Sps REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, 4553157642Sps (1 << 16) | sc->bce_rx_quick_cons_trip); 4554157642Sps REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, 4555157642Sps (1 << 16) | sc->bce_tx_quick_cons_trip); 4556157642Sps } else 4557157642Sps#endif 4558157642Sps /* Enable host interrupts. */ 4559157642Sps bce_enable_intr(sc); 4560157642Sps 4561157642Sps bce_ifmedia_upd(ifp); 4562157642Sps 4563157642Sps ifp->if_drv_flags |= IFF_DRV_RUNNING; 4564157642Sps ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 4565157642Sps 4566157642Sps callout_reset(&sc->bce_stat_ch, hz, bce_tick, sc); 4567157642Sps 4568157642Spsbce_init_locked_exit: 4569157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 4570157642Sps 4571157642Sps return; 4572157642Sps} 4573157642Sps 4574157642Sps 4575157642Sps/****************************************************************************/ 4576157642Sps/* Handles controller initialization when called from an unlocked routine. */ 4577157642Sps/* */ 4578157642Sps/* Returns: */ 4579157642Sps/* Nothing. */ 4580157642Sps/****************************************************************************/ 4581157642Spsstatic void 4582157642Spsbce_init(void *xsc) 4583157642Sps{ 4584157642Sps struct bce_softc *sc = xsc; 4585157642Sps 4586157642Sps BCE_LOCK(sc); 4587157642Sps bce_init_locked(sc); 4588157642Sps BCE_UNLOCK(sc); 4589157642Sps} 4590157642Sps 4591157642Sps 4592157642Sps/****************************************************************************/ 4593157642Sps/* Encapsultes an mbuf cluster into the tx_bd chain structure and makes the */ 4594157642Sps/* memory visible to the controller. */ 4595157642Sps/* */ 4596157642Sps/* Returns: */ 4597157642Sps/* 0 for success, positive value for failure. */ 4598157642Sps/****************************************************************************/ 4599157642Spsstatic int 4600157642Spsbce_tx_encap(struct bce_softc *sc, struct mbuf *m_head, u16 *prod, 4601157642Sps u16 *chain_prod, u32 *prod_bseq) 4602157642Sps{ 4603157642Sps u32 vlan_tag_flags = 0; 4604157642Sps struct m_tag *mtag; 4605157642Sps struct bce_dmamap_arg map_arg; 4606157642Sps bus_dmamap_t map; 4607157642Sps int i, error, rc = 0; 4608157642Sps 4609157642Sps /* Transfer any checksum offload flags to the bd. */ 4610157642Sps if (m_head->m_pkthdr.csum_flags) { 4611157642Sps if (m_head->m_pkthdr.csum_flags & CSUM_IP) 4612157642Sps vlan_tag_flags |= TX_BD_FLAGS_IP_CKSUM; 4613157642Sps if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 4614157642Sps vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; 4615157642Sps } 4616157642Sps 4617157642Sps /* Transfer any VLAN tags to the bd. */ 4618157642Sps mtag = VLAN_OUTPUT_TAG(sc->bce_ifp, m_head); 4619157642Sps if (mtag != NULL) 4620157642Sps vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG | 4621157642Sps (VLAN_TAG_VALUE(mtag) << 16)); 4622157642Sps 4623157642Sps /* Map the mbuf into DMAable memory. */ 4624157642Sps map = sc->tx_mbuf_map[*chain_prod]; 4625157642Sps map_arg.sc = sc; 4626157642Sps map_arg.prod = *prod; 4627157642Sps map_arg.chain_prod = *chain_prod; 4628157642Sps map_arg.prod_bseq = *prod_bseq; 4629157642Sps map_arg.tx_flags = vlan_tag_flags; 4630157642Sps map_arg.maxsegs = USABLE_TX_BD - sc->used_tx_bd - 4631157642Sps BCE_TX_SLACK_SPACE; 4632157642Sps 4633157642Sps KASSERT(map_arg.maxsegs > 0, ("Invalid TX maxsegs value!")); 4634157642Sps 4635157642Sps for (i = 0; i < TX_PAGES; i++) 4636157642Sps map_arg.tx_chain[i] = sc->tx_bd_chain[i]; 4637157642Sps 4638157642Sps /* Map the mbuf into our DMA address space. */ 4639157642Sps error = bus_dmamap_load_mbuf(sc->tx_mbuf_tag, map, m_head, 4640157642Sps bce_dma_map_tx_desc, &map_arg, BUS_DMA_NOWAIT); 4641157642Sps 4642157642Sps if (error || map_arg.maxsegs == 0) { 4643157642Sps BCE_PRINTF(sc, "%s(%d): Error mapping mbuf into TX chain!\n", 4644157642Sps __FILE__, __LINE__); 4645157642Sps rc = ENOBUFS; 4646157642Sps goto bce_tx_encap_exit; 4647157642Sps } 4648157642Sps 4649157642Sps /* 4650157642Sps * Ensure that the map for this transmission 4651157642Sps * is placed at the array index of the last 4652157642Sps * descriptor in this chain. This is done 4653157642Sps * because a single map is used for all 4654157642Sps * segments of the mbuf and we don't want to 4655157642Sps * delete the map before all of the segments 4656157642Sps * have been freed. 4657157642Sps */ 4658157642Sps sc->tx_mbuf_map[*chain_prod] = 4659157642Sps sc->tx_mbuf_map[map_arg.chain_prod]; 4660157642Sps sc->tx_mbuf_map[map_arg.chain_prod] = map; 4661157642Sps sc->tx_mbuf_ptr[map_arg.chain_prod] = m_head; 4662157642Sps sc->used_tx_bd += map_arg.maxsegs; 4663157642Sps 4664157642Sps DBRUNIF((sc->used_tx_bd > sc->tx_hi_watermark), 4665157642Sps sc->tx_hi_watermark = sc->used_tx_bd); 4666157642Sps 4667157642Sps DBRUNIF(1, sc->tx_mbuf_alloc++); 4668157642Sps 4669157642Sps DBRUN(BCE_VERBOSE_SEND, bce_dump_tx_mbuf_chain(sc, *chain_prod, 4670157642Sps map_arg.maxsegs)); 4671157642Sps 4672157642Sps /* prod still points the last used tx_bd at this point. */ 4673157642Sps *prod = map_arg.prod; 4674157642Sps *chain_prod = map_arg.chain_prod; 4675157642Sps *prod_bseq = map_arg.prod_bseq; 4676157642Sps 4677157642Spsbce_tx_encap_exit: 4678157642Sps 4679157642Sps return(rc); 4680157642Sps} 4681157642Sps 4682157642Sps 4683157642Sps/****************************************************************************/ 4684157642Sps/* Main transmit routine when called from another routine with a lock. */ 4685157642Sps/* */ 4686157642Sps/* Returns: */ 4687157642Sps/* Nothing. */ 4688157642Sps/****************************************************************************/ 4689157642Spsstatic void 4690157642Spsbce_start_locked(struct ifnet *ifp) 4691157642Sps{ 4692157642Sps struct bce_softc *sc = ifp->if_softc; 4693157642Sps struct mbuf *m_head = NULL; 4694157642Sps int count = 0; 4695157642Sps u16 tx_prod, tx_chain_prod; 4696157642Sps u32 tx_prod_bseq; 4697157642Sps 4698157642Sps /* If there's no link or the transmit queue is empty then just exit. */ 4699157642Sps if (!sc->bce_link || IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 4700157642Sps DBPRINT(sc, BCE_INFO_SEND, "%s(): No link or transmit queue empty.\n", 4701157642Sps __FUNCTION__); 4702157642Sps goto bce_start_locked_exit; 4703157642Sps } 4704157642Sps 4705157642Sps /* prod points to the next free tx_bd. */ 4706157642Sps tx_prod = sc->tx_prod; 4707157642Sps tx_chain_prod = TX_CHAIN_IDX(tx_prod); 4708157642Sps tx_prod_bseq = sc->tx_prod_bseq; 4709157642Sps 4710157642Sps DBPRINT(sc, BCE_INFO_SEND, 4711157642Sps "%s(): Start: tx_prod = 0x%04X, tx_chain_prod = %04X, " 4712157642Sps "tx_prod_bseq = 0x%08X\n", 4713157642Sps __FUNCTION__, tx_prod, tx_chain_prod, tx_prod_bseq); 4714157642Sps 4715157642Sps /* Keep adding entries while there is space in the ring. */ 4716157642Sps while(sc->tx_mbuf_ptr[tx_chain_prod] == NULL) { 4717157642Sps 4718157642Sps /* Check for any frames to send. */ 4719157642Sps IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 4720157642Sps if (m_head == NULL) 4721157642Sps break; 4722157642Sps 4723157642Sps /* 4724157642Sps * Pack the data into the transmit ring. If we 4725157642Sps * don't have room, place the mbuf back at the 4726157642Sps * head of the queue and set the OACTIVE flag 4727157642Sps * to wait for the NIC to drain the chain. 4728157642Sps */ 4729157642Sps if (bce_tx_encap(sc, m_head, &tx_prod, &tx_chain_prod, &tx_prod_bseq)) { 4730157642Sps IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 4731157642Sps ifp->if_drv_flags |= IFF_DRV_OACTIVE; 4732157642Sps DBPRINT(sc, BCE_INFO_SEND, 4733157642Sps "TX chain is closed for business! Total tx_bd used = %d\n", 4734157642Sps sc->used_tx_bd); 4735157642Sps break; 4736157642Sps } 4737157642Sps 4738157642Sps count++; 4739157642Sps 4740157642Sps /* Send a copy of the frame to any BPF listeners. */ 4741157642Sps BPF_MTAP(ifp, m_head); 4742157642Sps 4743157642Sps tx_prod = NEXT_TX_BD(tx_prod); 4744157642Sps tx_chain_prod = TX_CHAIN_IDX(tx_prod); 4745157642Sps } 4746157642Sps 4747157642Sps if (count == 0) { 4748157642Sps /* no packets were dequeued */ 4749157642Sps DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): No packets were dequeued\n", 4750157642Sps __FUNCTION__); 4751157642Sps goto bce_start_locked_exit; 4752157642Sps } 4753157642Sps 4754157642Sps /* Update the driver's counters. */ 4755157642Sps sc->tx_prod = tx_prod; 4756157642Sps sc->tx_prod_bseq = tx_prod_bseq; 4757157642Sps 4758157642Sps DBPRINT(sc, BCE_INFO_SEND, 4759157642Sps "%s(): End: tx_prod = 0x%04X, tx_chain_prod = 0x%04X, " 4760157642Sps "tx_prod_bseq = 0x%08X\n", 4761157642Sps __FUNCTION__, tx_prod, tx_chain_prod, tx_prod_bseq); 4762157642Sps 4763157642Sps /* Start the transmit. */ 4764157642Sps REG_WR16(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BIDX, sc->tx_prod); 4765157642Sps REG_WR(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BSEQ, sc->tx_prod_bseq); 4766157642Sps 4767157642Sps /* Set the tx timeout. */ 4768157642Sps ifp->if_timer = BCE_TX_TIMEOUT; 4769157642Sps 4770157642Spsbce_start_locked_exit: 4771157642Sps return; 4772157642Sps} 4773157642Sps 4774157642Sps 4775157642Sps/****************************************************************************/ 4776157642Sps/* Main transmit routine when called from another routine without a lock. */ 4777157642Sps/* */ 4778157642Sps/* Returns: */ 4779157642Sps/* Nothing. */ 4780157642Sps/****************************************************************************/ 4781157642Spsstatic void 4782157642Spsbce_start(struct ifnet *ifp) 4783157642Sps{ 4784157642Sps struct bce_softc *sc = ifp->if_softc; 4785157642Sps 4786157642Sps BCE_LOCK(sc); 4787157642Sps bce_start_locked(ifp); 4788157642Sps BCE_UNLOCK(sc); 4789157642Sps} 4790157642Sps 4791157642Sps 4792157642Sps/****************************************************************************/ 4793157642Sps/* Handles any IOCTL calls from the operating system. */ 4794157642Sps/* */ 4795157642Sps/* Returns: */ 4796157642Sps/* 0 for success, positive value for failure. */ 4797157642Sps/****************************************************************************/ 4798157642Spsstatic int 4799157642Spsbce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 4800157642Sps{ 4801157642Sps struct bce_softc *sc = ifp->if_softc; 4802157642Sps struct ifreq *ifr = (struct ifreq *) data; 4803157642Sps struct mii_data *mii; 4804157642Sps int mask, error = 0; 4805157642Sps 4806157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); 4807157642Sps 4808157642Sps switch(command) { 4809157642Sps 4810157642Sps /* Set the MTU. */ 4811157642Sps case SIOCSIFMTU: 4812157642Sps /* Check that the MTU setting is supported. */ 4813157642Sps if ((ifr->ifr_mtu < BCE_MIN_MTU) || 4814157642Sps (ifr->ifr_mtu > BCE_MAX_JUMBO_MTU)) { 4815157642Sps error = EINVAL; 4816157642Sps break; 4817157642Sps } 4818157642Sps 4819157642Sps DBPRINT(sc, BCE_INFO, "Setting new MTU of %d\n", ifr->ifr_mtu); 4820157642Sps 4821157642Sps ifp->if_mtu = ifr->ifr_mtu; 4822157642Sps ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 4823157642Sps bce_init(sc); 4824157642Sps break; 4825157642Sps 4826157642Sps /* Set interface. */ 4827157642Sps case SIOCSIFFLAGS: 4828157642Sps DBPRINT(sc, BCE_VERBOSE, "Received SIOCSIFFLAGS\n"); 4829157642Sps 4830157642Sps BCE_LOCK(sc); 4831157642Sps 4832157642Sps /* Check if the interface is up. */ 4833157642Sps if (ifp->if_flags & IFF_UP) { 4834157642Sps /* Change the promiscuous/multicast flags as necessary. */ 4835157642Sps bce_set_rx_mode(sc); 4836157642Sps } else { 4837157642Sps /* The interface is down. Check if the driver is running. */ 4838157642Sps if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 4839157642Sps bce_stop(sc); 4840157642Sps } 4841157642Sps } 4842157642Sps 4843157642Sps BCE_UNLOCK(sc); 4844157642Sps error = 0; 4845157642Sps 4846157642Sps break; 4847157642Sps 4848157642Sps /* Add/Delete multicast address */ 4849157642Sps case SIOCADDMULTI: 4850157642Sps case SIOCDELMULTI: 4851157642Sps DBPRINT(sc, BCE_VERBOSE, "Received SIOCADDMULTI/SIOCDELMULTI\n"); 4852157642Sps 4853157642Sps if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 4854157642Sps BCE_LOCK(sc); 4855157642Sps bce_set_rx_mode(sc); 4856157642Sps BCE_UNLOCK(sc); 4857157642Sps error = 0; 4858157642Sps } 4859157642Sps 4860157642Sps break; 4861157642Sps 4862157642Sps /* Set/Get Interface media */ 4863157642Sps case SIOCSIFMEDIA: 4864157642Sps case SIOCGIFMEDIA: 4865157642Sps DBPRINT(sc, BCE_VERBOSE, "Received SIOCSIFMEDIA/SIOCGIFMEDIA\n"); 4866157642Sps 4867157642Sps DBPRINT(sc, BCE_VERBOSE, "bce_phy_flags = 0x%08X\n", 4868157642Sps sc->bce_phy_flags); 4869157642Sps 4870157642Sps if (sc->bce_phy_flags & BCE_PHY_SERDES_FLAG) { 4871157642Sps DBPRINT(sc, BCE_VERBOSE, "SerDes media set/get\n"); 4872157642Sps 4873157642Sps error = ifmedia_ioctl(ifp, ifr, 4874157642Sps &sc->bce_ifmedia, command); 4875157642Sps } else { 4876157642Sps DBPRINT(sc, BCE_VERBOSE, "Copper media set/get\n"); 4877157642Sps mii = device_get_softc(sc->bce_miibus); 4878157642Sps error = ifmedia_ioctl(ifp, ifr, 4879157642Sps &mii->mii_media, command); 4880157642Sps } 4881157642Sps break; 4882157642Sps 4883157642Sps /* Set interface capability */ 4884157642Sps case SIOCSIFCAP: 4885157642Sps mask = ifr->ifr_reqcap ^ ifp->if_capenable; 4886157642Sps DBPRINT(sc, BCE_INFO, "Received SIOCSIFCAP = 0x%08X\n", (u32) mask); 4887157642Sps 4888157642Sps#ifdef DEVICE_POLLING 4889157642Sps if (mask & IFCAP_POLLING) { 4890157642Sps if (ifr->ifr_reqcap & IFCAP_POLLING) { 4891157642Sps 4892157642Sps /* Setup the poll routine to call. */ 4893157642Sps error = ether_poll_register(bce_poll, ifp); 4894157642Sps if (error) { 4895157642Sps BCE_PRINTF(sc, "%s(%d): Error registering poll function!\n", 4896157642Sps __FILE__, __LINE__); 4897157642Sps goto bce_ioctl_exit; 4898157642Sps } 4899157642Sps 4900157642Sps /* Clear the interrupt. */ 4901157642Sps BCE_LOCK(sc); 4902157642Sps bce_disable_intr(sc); 4903157642Sps 4904157642Sps REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, 4905157642Sps (1 << 16) | sc->bce_rx_quick_cons_trip); 4906157642Sps REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, 4907157642Sps (1 << 16) | sc->bce_tx_quick_cons_trip); 4908157642Sps 4909157642Sps ifp->if_capenable |= IFCAP_POLLING; 4910157642Sps BCE_UNLOCK(sc); 4911157642Sps } else { 4912157642Sps /* Clear the poll routine. */ 4913157642Sps error = ether_poll_deregister(ifp); 4914157642Sps 4915157642Sps /* Enable interrupt even in error case */ 4916157642Sps BCE_LOCK(sc); 4917157642Sps bce_enable_intr(sc); 4918157642Sps 4919157642Sps REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, 4920157642Sps (sc->bce_tx_quick_cons_trip_int << 16) | 4921157642Sps sc->bce_tx_quick_cons_trip); 4922157642Sps REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, 4923157642Sps (sc->bce_rx_quick_cons_trip_int << 16) | 4924157642Sps sc->bce_rx_quick_cons_trip); 4925157642Sps 4926157642Sps ifp->if_capenable &= ~IFCAP_POLLING; 4927157642Sps BCE_UNLOCK(sc); 4928157642Sps } 4929157642Sps } 4930157642Sps#endif /*DEVICE_POLLING */ 4931157642Sps 4932157642Sps /* Toggle the TX checksum capabilites enable flag. */ 4933157642Sps if (mask & IFCAP_TXCSUM) { 4934157642Sps ifp->if_capenable ^= IFCAP_TXCSUM; 4935157642Sps if (IFCAP_TXCSUM & ifp->if_capenable) 4936157642Sps ifp->if_hwassist = BCE_IF_HWASSIST; 4937157642Sps else 4938157642Sps ifp->if_hwassist = 0; 4939157642Sps } 4940157642Sps 4941157642Sps /* Toggle the RX checksum capabilities enable flag. */ 4942157642Sps if (mask & IFCAP_RXCSUM) { 4943157642Sps ifp->if_capenable ^= IFCAP_RXCSUM; 4944157642Sps if (IFCAP_RXCSUM & ifp->if_capenable) 4945157642Sps ifp->if_hwassist = BCE_IF_HWASSIST; 4946157642Sps else 4947157642Sps ifp->if_hwassist = 0; 4948157642Sps } 4949157642Sps 4950157642Sps /* Toggle VLAN_MTU capabilities enable flag. */ 4951157642Sps if (mask & IFCAP_VLAN_MTU) { 4952157642Sps BCE_PRINTF(sc, "%s(%d): Changing VLAN_MTU not supported.\n", 4953157642Sps __FILE__, __LINE__); 4954157642Sps } 4955157642Sps 4956157642Sps /* Toggle VLANHWTAG capabilities enabled flag. */ 4957157642Sps if (mask & IFCAP_VLAN_HWTAGGING) { 4958157642Sps if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) 4959157642Sps BCE_PRINTF(sc, "%s(%d): Cannot change VLAN_HWTAGGING while " 4960157642Sps "management firmware (ASF/IPMI/UMP) is running!\n", 4961157642Sps __FILE__, __LINE__); 4962157642Sps else 4963157642Sps BCE_PRINTF(sc, "%s(%d): Changing VLAN_HWTAGGING not supported!\n", 4964157642Sps __FILE__, __LINE__); 4965157642Sps } 4966157642Sps 4967157642Sps break; 4968157642Sps default: 4969157642Sps DBPRINT(sc, BCE_INFO, "Received unsupported IOCTL: 0x%08X\n", 4970157642Sps (u32) command); 4971157642Sps 4972157642Sps /* We don't know how to handle the IOCTL, pass it on. */ 4973157642Sps error = ether_ioctl(ifp, command, data); 4974157642Sps break; 4975157642Sps } 4976157642Sps 4977157724Sru#ifdef DEVICE_POLLING 4978157724Srubce_ioctl_exit: 4979157724Sru#endif 4980157724Sru 4981157642Sps DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); 4982157642Sps 4983157642Sps return(error); 4984157642Sps} 4985157642Sps 4986157642Sps 4987157642Sps/****************************************************************************/ 4988157642Sps/* Transmit timeout handler. */ 4989157642Sps/* */ 4990157642Sps/* Returns: */ 4991157642Sps/* Nothing. */ 4992157642Sps/****************************************************************************/ 4993157642Spsstatic void 4994157642Spsbce_watchdog(struct ifnet *ifp) 4995157642Sps{ 4996157642Sps struct bce_softc *sc = ifp->if_softc; 4997157642Sps 4998157642Sps DBRUN(BCE_WARN_SEND, 4999157642Sps bce_dump_driver_state(sc); 5000157642Sps bce_dump_status_block(sc)); 5001157642Sps 5002157642Sps BCE_PRINTF(sc, "%s(%d): Watchdog timeout occurred, resetting!\n", 5003157642Sps __FILE__, __LINE__); 5004157642Sps 5005157642Sps /* DBRUN(BCE_FATAL, bce_breakpoint(sc)); */ 5006157642Sps 5007157642Sps ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 5008157642Sps 5009157642Sps bce_init(sc); 5010157642Sps ifp->if_oerrors++; 5011157642Sps 5012157642Sps} 5013157642Sps 5014157642Sps 5015157642Sps#ifdef DEVICE_POLLING 5016157642Spsstatic void 5017157642Spsbce_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) 5018157642Sps{ 5019157642Sps struct bce_softc *sc = ifp->if_softc; 5020157642Sps 5021157642Sps BCE_LOCK_ASSERT(sc); 5022157642Sps 5023157642Sps sc->bce_rxcycles = count; 5024157642Sps 5025157642Sps bus_dmamap_sync(sc->status_tag, sc->status_map, 5026157642Sps BUS_DMASYNC_POSTWRITE); 5027157642Sps 5028157642Sps /* Check for any completed RX frames. */ 5029157642Sps if (sc->status_block->status_rx_quick_consumer_index0 != 5030157642Sps sc->hw_rx_cons) 5031157642Sps bce_rx_intr(sc); 5032157642Sps 5033157642Sps /* Check for any completed TX frames. */ 5034157642Sps if (sc->status_block->status_tx_quick_consumer_index0 != 5035157642Sps sc->hw_tx_cons) 5036157642Sps bce_tx_intr(sc); 5037157642Sps 5038157642Sps /* Check for new frames to transmit. */ 5039157642Sps if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 5040157642Sps bce_start_locked(ifp); 5041157642Sps 5042157642Sps} 5043157642Sps 5044157642Sps 5045157642Spsstatic void 5046157642Spsbce_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 5047157642Sps{ 5048157642Sps struct bce_softc *sc = ifp->if_softc; 5049157642Sps 5050157642Sps BCE_LOCK(sc); 5051157642Sps if (ifp->if_drv_flags & IFF_DRV_RUNNING) 5052157642Sps bce_poll_locked(ifp, cmd, count); 5053157642Sps BCE_UNLOCK(sc); 5054157642Sps} 5055157642Sps#endif /* DEVICE_POLLING */ 5056157642Sps 5057157642Sps 5058157642Sps#if 0 5059157642Spsstatic inline int 5060157642Spsbce_has_work(struct bce_softc *sc) 5061157642Sps{ 5062157642Sps struct status_block *stat = sc->status_block; 5063157642Sps 5064157642Sps if ((stat->status_rx_quick_consumer_index0 != sc->hw_rx_cons) || 5065157642Sps (stat->status_tx_quick_consumer_index0 != sc->hw_tx_cons)) 5066157642Sps return 1; 5067157642Sps 5068157642Sps if (((stat->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 0) != 5069157642Sps bp->link_up) 5070157642Sps return 1; 5071157642Sps 5072157642Sps return 0; 5073157642Sps} 5074157642Sps#endif 5075157642Sps 5076157642Sps 5077157642Sps/* 5078157642Sps * Interrupt handler. 5079157642Sps */ 5080157642Sps/****************************************************************************/ 5081157642Sps/* Main interrupt entry point. Verifies that the controller generated the */ 5082157642Sps/* interrupt and then calls a separate routine for handle the various */ 5083157642Sps/* interrupt causes (PHY, TX, RX). */ 5084157642Sps/* */ 5085157642Sps/* Returns: */ 5086157642Sps/* 0 for success, positive value for failure. */ 5087157642Sps/****************************************************************************/ 5088157642Spsstatic void 5089157642Spsbce_intr(void *xsc) 5090157642Sps{ 5091157642Sps struct bce_softc *sc; 5092157642Sps struct ifnet *ifp; 5093157642Sps u32 status_attn_bits; 5094157642Sps 5095157642Sps sc = xsc; 5096157642Sps ifp = sc->bce_ifp; 5097157642Sps 5098157642Sps BCE_LOCK(sc); 5099157642Sps 5100157642Sps DBRUNIF(1, sc->interrupts_generated++); 5101157642Sps 5102157642Sps#ifdef DEVICE_POLLING 5103157642Sps if (ifp->if_capenable & IFCAP_POLLING) { 5104157642Sps DBPRINT(sc, BCE_INFO, "Polling enabled!\n"); 5105157642Sps goto bce_intr_exit; 5106157642Sps } 5107157642Sps#endif 5108157642Sps 5109157642Sps bus_dmamap_sync(sc->status_tag, sc->status_map, 5110157642Sps BUS_DMASYNC_POSTWRITE); 5111157642Sps 5112157642Sps /* 5113157642Sps * If the hardware status block index 5114157642Sps * matches the last value read by the 5115157642Sps * driver and we haven't asserted our 5116157642Sps * interrupt then there's nothing to do. 5117157642Sps */ 5118157642Sps if ((sc->status_block->status_idx == sc->last_status_idx) && 5119157642Sps (REG_RD(sc, BCE_PCICFG_MISC_STATUS) & BCE_PCICFG_MISC_STATUS_INTA_VALUE)) 5120157642Sps goto bce_intr_exit; 5121157642Sps 5122157642Sps /* Ack the interrupt and stop others from occuring. */ 5123157642Sps REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 5124157642Sps BCE_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | 5125157642Sps BCE_PCICFG_INT_ACK_CMD_MASK_INT); 5126157642Sps 5127157642Sps /* Keep processing data as long as there is work to do. */ 5128157642Sps for (;;) { 5129157642Sps 5130157642Sps status_attn_bits = sc->status_block->status_attn_bits; 5131157642Sps 5132157642Sps DBRUNIF(DB_RANDOMTRUE(bce_debug_unexpected_attention), 5133157642Sps BCE_PRINTF(sc, "Simulating unexpected status attention bit set."); 5134157642Sps status_attn_bits = status_attn_bits | STATUS_ATTN_BITS_PARITY_ERROR); 5135157642Sps 5136157642Sps /* Was it a link change interrupt? */ 5137157642Sps if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 5138157642Sps (sc->status_block->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE)) 5139157642Sps bce_phy_intr(sc); 5140157642Sps 5141157642Sps /* If any other attention is asserted then the chip is toast. */ 5142157642Sps if (((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) != 5143157642Sps (sc->status_block->status_attn_bits_ack & 5144157642Sps ~STATUS_ATTN_BITS_LINK_STATE))) { 5145157642Sps 5146157642Sps DBRUN(1, sc->unexpected_attentions++); 5147157642Sps 5148157642Sps BCE_PRINTF(sc, "%s(%d): Fatal attention detected: 0x%08X\n", 5149157642Sps __FILE__, __LINE__, sc->status_block->status_attn_bits); 5150157642Sps 5151157642Sps DBRUN(BCE_FATAL, 5152157642Sps if (bce_debug_unexpected_attention == 0) 5153157642Sps bce_breakpoint(sc)); 5154157642Sps 5155157642Sps bce_init_locked(sc); 5156157642Sps goto bce_intr_exit; 5157157642Sps } 5158157642Sps 5159157642Sps /* Check for any completed RX frames. */ 5160157642Sps if (sc->status_block->status_rx_quick_consumer_index0 != sc->hw_rx_cons) 5161157642Sps bce_rx_intr(sc); 5162157642Sps 5163157642Sps /* Check for any completed TX frames. */ 5164157642Sps if (sc->status_block->status_tx_quick_consumer_index0 != sc->hw_tx_cons) 5165157642Sps bce_tx_intr(sc); 5166157642Sps 5167157642Sps /* Save the status block index value for use during the next interrupt. */ 5168157642Sps sc->last_status_idx = sc->status_block->status_idx; 5169157642Sps 5170157642Sps /* Prevent speculative reads from getting ahead of the status block. */ 5171157642Sps bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0, 5172157642Sps BUS_SPACE_BARRIER_READ); 5173157642Sps 5174157642Sps /* If there's no work left then exit the interrupt service routine. */ 5175157642Sps if ((sc->status_block->status_rx_quick_consumer_index0 == sc->hw_rx_cons) && 5176157642Sps (sc->status_block->status_tx_quick_consumer_index0 == sc->hw_tx_cons)) 5177157642Sps break; 5178157642Sps 5179157642Sps } 5180157642Sps 5181157642Sps bus_dmamap_sync(sc->status_tag, sc->status_map, 5182157642Sps BUS_DMASYNC_PREWRITE); 5183157642Sps 5184157642Sps /* Re-enable interrupts. */ 5185157642Sps REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 5186157642Sps BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx | 5187157642Sps BCE_PCICFG_INT_ACK_CMD_MASK_INT); 5188157642Sps REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 5189157642Sps BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx); 5190157642Sps 5191157642Sps /* Handle any frames that arrived while handling the interrupt. */ 5192157642Sps if (ifp->if_drv_flags & IFF_DRV_RUNNING && !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 5193157642Sps bce_start_locked(ifp); 5194157642Sps 5195157642Spsbce_intr_exit: 5196157642Sps BCE_UNLOCK(sc); 5197157642Sps} 5198157642Sps 5199157642Sps 5200157642Sps/****************************************************************************/ 5201157642Sps/* Programs the various packet receive modes (broadcast and multicast). */ 5202157642Sps/* */ 5203157642Sps/* Returns: */ 5204157642Sps/* Nothing. */ 5205157642Sps/****************************************************************************/ 5206157642Spsstatic void 5207157642Spsbce_set_rx_mode(struct bce_softc *sc) 5208157642Sps{ 5209157642Sps struct ifnet *ifp; 5210157642Sps struct ifmultiaddr *ifma; 5211157642Sps u32 hashes[4] = { 0, 0, 0, 0 }; 5212157642Sps u32 rx_mode, sort_mode; 5213157642Sps int h, i; 5214157642Sps 5215157642Sps BCE_LOCK_ASSERT(sc); 5216157642Sps 5217157642Sps ifp = sc->bce_ifp; 5218157642Sps 5219157642Sps /* Initialize receive mode default settings. */ 5220157642Sps rx_mode = sc->rx_mode & ~(BCE_EMAC_RX_MODE_PROMISCUOUS | 5221157642Sps BCE_EMAC_RX_MODE_KEEP_VLAN_TAG); 5222157642Sps sort_mode = 1 | BCE_RPM_SORT_USER0_BC_EN; 5223157642Sps 5224157642Sps /* 5225157642Sps * ASF/IPMI/UMP firmware requires that VLAN tag stripping 5226157642Sps * be enbled. 5227157642Sps */ 5228157642Sps if (!(BCE_IF_CAPABILITIES & IFCAP_VLAN_HWTAGGING) && 5229157642Sps (!(sc->bce_flags & BCE_MFW_ENABLE_FLAG))) 5230157642Sps rx_mode |= BCE_EMAC_RX_MODE_KEEP_VLAN_TAG; 5231157642Sps 5232157642Sps /* 5233157642Sps * Check for promiscuous, all multicast, or selected 5234157642Sps * multicast address filtering. 5235157642Sps */ 5236157642Sps if (ifp->if_flags & IFF_PROMISC) { 5237157642Sps DBPRINT(sc, BCE_INFO, "Enabling promiscuous mode.\n"); 5238157642Sps 5239157642Sps /* Enable promiscuous mode. */ 5240157642Sps rx_mode |= BCE_EMAC_RX_MODE_PROMISCUOUS; 5241157642Sps sort_mode |= BCE_RPM_SORT_USER0_PROM_EN; 5242157642Sps } else if (ifp->if_flags & IFF_ALLMULTI) { 5243157642Sps DBPRINT(sc, BCE_INFO, "Enabling all multicast mode.\n"); 5244157642Sps 5245157642Sps /* Enable all multicast addresses. */ 5246157642Sps for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { 5247157642Sps REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4), 0xffffffff); 5248157642Sps } 5249157642Sps sort_mode |= BCE_RPM_SORT_USER0_MC_EN; 5250157642Sps } else { 5251157642Sps /* Accept one or more multicast(s). */ 5252157642Sps DBPRINT(sc, BCE_INFO, "Enabling selective multicast mode.\n"); 5253157642Sps 5254157642Sps IF_ADDR_LOCK(ifp); 5255157642Sps TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 5256157642Sps if (ifma->ifma_addr->sa_family != AF_LINK) 5257157642Sps continue; 5258157642Sps h = ether_crc32_le(LLADDR((struct sockaddr_dl *) 5259157642Sps ifma->ifma_addr), ETHER_ADDR_LEN) & 0x7F; 5260157642Sps hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F); 5261157642Sps } 5262157642Sps IF_ADDR_UNLOCK(ifp); 5263157642Sps 5264157642Sps for (i = 0; i < 4; i++) 5265157642Sps REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4), hashes[i]); 5266157642Sps 5267157642Sps sort_mode |= BCE_RPM_SORT_USER0_MC_HSH_EN; 5268157642Sps } 5269157642Sps 5270157642Sps /* Only make changes if the recive mode has actually changed. */ 5271157642Sps if (rx_mode != sc->rx_mode) { 5272157642Sps DBPRINT(sc, BCE_VERBOSE, "Enabling new receive mode: 0x%08X\n", 5273157642Sps rx_mode); 5274157642Sps 5275157642Sps sc->rx_mode = rx_mode; 5276157642Sps REG_WR(sc, BCE_EMAC_RX_MODE, rx_mode); 5277157642Sps } 5278157642Sps 5279157642Sps /* Disable and clear the exisitng sort before enabling a new sort. */ 5280157642Sps REG_WR(sc, BCE_RPM_SORT_USER0, 0x0); 5281157642Sps REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode); 5282157642Sps REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode | BCE_RPM_SORT_USER0_ENA); 5283157642Sps} 5284157642Sps 5285157642Sps 5286157642Sps/****************************************************************************/ 5287157642Sps/* Called periodically to updates statistics from the controllers */ 5288157642Sps/* statistics block. */ 5289157642Sps/* */ 5290157642Sps/* Returns: */ 5291157642Sps/* Nothing. */ 5292157642Sps/****************************************************************************/ 5293157642Spsstatic void 5294157642Spsbce_stats_update(struct bce_softc *sc) 5295157642Sps{ 5296157642Sps struct ifnet *ifp; 5297157642Sps struct statistics_block *stats; 5298157642Sps 5299157642Sps DBPRINT(sc, BCE_EXCESSIVE, "Entering %s()\n", __FUNCTION__); 5300157642Sps 5301157642Sps ifp = sc->bce_ifp; 5302157642Sps 5303157642Sps stats = (struct statistics_block *) sc->stats_block; 5304157642Sps 5305157642Sps /* 5306157642Sps * Update the interface statistics from the 5307157642Sps * hardware statistics. 5308157642Sps */ 5309157642Sps ifp->if_collisions = (u_long) stats->stat_EtherStatsCollisions; 5310157642Sps 5311157642Sps ifp->if_ibytes = BCE_STATS(IfHCInOctets); 5312157642Sps 5313157642Sps ifp->if_obytes = BCE_STATS(IfHCOutOctets); 5314157642Sps 5315157642Sps ifp->if_imcasts = BCE_STATS(IfHCInMulticastPkts); 5316157642Sps 5317157642Sps ifp->if_omcasts = BCE_STATS(IfHCOutMulticastPkts); 5318157642Sps 5319157642Sps ifp->if_ierrors = (u_long) stats->stat_EtherStatsUndersizePkts + 5320157642Sps (u_long) stats->stat_EtherStatsOverrsizePkts + 5321157642Sps (u_long) stats->stat_IfInMBUFDiscards + 5322157642Sps (u_long) stats->stat_Dot3StatsAlignmentErrors + 5323157642Sps (u_long) stats->stat_Dot3StatsFCSErrors; 5324157642Sps 5325157642Sps ifp->if_oerrors = (u_long) stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors + 5326157642Sps (u_long) stats->stat_Dot3StatsExcessiveCollisions + 5327157642Sps (u_long) stats->stat_Dot3StatsLateCollisions; 5328157642Sps 5329157642Sps /* 5330157642Sps * Certain controllers don't report 5331157642Sps * carrier sense errors correctly. 5332157642Sps * See errata E11_5708CA0_1165. 5333157642Sps */ 5334157642Sps if (!(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) && 5335157642Sps !(BCE_CHIP_ID(sc) == BCE_CHIP_ID_5708_A0)) 5336157642Sps ifp->if_oerrors += (u_long) stats->stat_Dot3StatsCarrierSenseErrors; 5337157642Sps 5338157642Sps /* 5339157642Sps * Update the sysctl statistics from the 5340157642Sps * hardware statistics. 5341157642Sps */ 5342157642Sps sc->stat_IfHCInOctets = 5343157642Sps ((u64) stats->stat_IfHCInOctets_hi << 32) + 5344157642Sps (u64) stats->stat_IfHCInOctets_lo; 5345157642Sps 5346157642Sps sc->stat_IfHCInBadOctets = 5347157642Sps ((u64) stats->stat_IfHCInBadOctets_hi << 32) + 5348157642Sps (u64) stats->stat_IfHCInBadOctets_lo; 5349157642Sps 5350157642Sps sc->stat_IfHCOutOctets = 5351157642Sps ((u64) stats->stat_IfHCOutOctets_hi << 32) + 5352157642Sps (u64) stats->stat_IfHCOutOctets_lo; 5353157642Sps 5354157642Sps sc->stat_IfHCOutBadOctets = 5355157642Sps ((u64) stats->stat_IfHCOutBadOctets_hi << 32) + 5356157642Sps (u64) stats->stat_IfHCOutBadOctets_lo; 5357157642Sps 5358157642Sps sc->stat_IfHCInUcastPkts = 5359157642Sps ((u64) stats->stat_IfHCInUcastPkts_hi << 32) + 5360157642Sps (u64) stats->stat_IfHCInUcastPkts_lo; 5361157642Sps 5362157642Sps sc->stat_IfHCInMulticastPkts = 5363157642Sps ((u64) stats->stat_IfHCInMulticastPkts_hi << 32) + 5364157642Sps (u64) stats->stat_IfHCInMulticastPkts_lo; 5365157642Sps 5366157642Sps sc->stat_IfHCInBroadcastPkts = 5367157642Sps ((u64) stats->stat_IfHCInBroadcastPkts_hi << 32) + 5368157642Sps (u64) stats->stat_IfHCInBroadcastPkts_lo; 5369157642Sps 5370157642Sps sc->stat_IfHCOutUcastPkts = 5371157642Sps ((u64) stats->stat_IfHCOutUcastPkts_hi << 32) + 5372157642Sps (u64) stats->stat_IfHCOutUcastPkts_lo; 5373157642Sps 5374157642Sps sc->stat_IfHCOutMulticastPkts = 5375157642Sps ((u64) stats->stat_IfHCOutMulticastPkts_hi << 32) + 5376157642Sps (u64) stats->stat_IfHCOutMulticastPkts_lo; 5377157642Sps 5378157642Sps sc->stat_IfHCOutBroadcastPkts = 5379157642Sps ((u64) stats->stat_IfHCOutBroadcastPkts_hi << 32) + 5380157642Sps (u64) stats->stat_IfHCOutBroadcastPkts_lo; 5381157642Sps 5382157642Sps sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors = 5383157642Sps stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors; 5384157642Sps 5385157642Sps sc->stat_Dot3StatsCarrierSenseErrors = 5386157642Sps stats->stat_Dot3StatsCarrierSenseErrors; 5387157642Sps 5388157642Sps sc->stat_Dot3StatsFCSErrors = 5389157642Sps stats->stat_Dot3StatsFCSErrors; 5390157642Sps 5391157642Sps sc->stat_Dot3StatsAlignmentErrors = 5392157642Sps stats->stat_Dot3StatsAlignmentErrors; 5393157642Sps 5394157642Sps sc->stat_Dot3StatsSingleCollisionFrames = 5395157642Sps stats->stat_Dot3StatsSingleCollisionFrames; 5396157642Sps 5397157642Sps sc->stat_Dot3StatsMultipleCollisionFrames = 5398157642Sps stats->stat_Dot3StatsMultipleCollisionFrames; 5399157642Sps 5400157642Sps sc->stat_Dot3StatsDeferredTransmissions = 5401157642Sps stats->stat_Dot3StatsDeferredTransmissions; 5402157642Sps 5403157642Sps sc->stat_Dot3StatsExcessiveCollisions = 5404157642Sps stats->stat_Dot3StatsExcessiveCollisions; 5405157642Sps 5406157642Sps sc->stat_Dot3StatsLateCollisions = 5407157642Sps stats->stat_Dot3StatsLateCollisions; 5408157642Sps 5409157642Sps sc->stat_EtherStatsCollisions = 5410157642Sps stats->stat_EtherStatsCollisions; 5411157642Sps 5412157642Sps sc->stat_EtherStatsFragments = 5413157642Sps stats->stat_EtherStatsFragments; 5414157642Sps 5415157642Sps sc->stat_EtherStatsJabbers = 5416157642Sps stats->stat_EtherStatsJabbers; 5417157642Sps 5418157642Sps sc->stat_EtherStatsUndersizePkts = 5419157642Sps stats->stat_EtherStatsUndersizePkts; 5420157642Sps 5421157642Sps sc->stat_EtherStatsOverrsizePkts = 5422157642Sps stats->stat_EtherStatsOverrsizePkts; 5423157642Sps 5424157642Sps sc->stat_EtherStatsPktsRx64Octets = 5425157642Sps stats->stat_EtherStatsPktsRx64Octets; 5426157642Sps 5427157642Sps sc->stat_EtherStatsPktsRx65Octetsto127Octets = 5428157642Sps stats->stat_EtherStatsPktsRx65Octetsto127Octets; 5429157642Sps 5430157642Sps sc->stat_EtherStatsPktsRx128Octetsto255Octets = 5431157642Sps stats->stat_EtherStatsPktsRx128Octetsto255Octets; 5432157642Sps 5433157642Sps sc->stat_EtherStatsPktsRx256Octetsto511Octets = 5434157642Sps stats->stat_EtherStatsPktsRx256Octetsto511Octets; 5435157642Sps 5436157642Sps sc->stat_EtherStatsPktsRx512Octetsto1023Octets = 5437157642Sps stats->stat_EtherStatsPktsRx512Octetsto1023Octets; 5438157642Sps 5439157642Sps sc->stat_EtherStatsPktsRx1024Octetsto1522Octets = 5440157642Sps stats->stat_EtherStatsPktsRx1024Octetsto1522Octets; 5441157642Sps 5442157642Sps sc->stat_EtherStatsPktsRx1523Octetsto9022Octets = 5443157642Sps stats->stat_EtherStatsPktsRx1523Octetsto9022Octets; 5444157642Sps 5445157642Sps sc->stat_EtherStatsPktsTx64Octets = 5446157642Sps stats->stat_EtherStatsPktsTx64Octets; 5447157642Sps 5448157642Sps sc->stat_EtherStatsPktsTx65Octetsto127Octets = 5449157642Sps stats->stat_EtherStatsPktsTx65Octetsto127Octets; 5450157642Sps 5451157642Sps sc->stat_EtherStatsPktsTx128Octetsto255Octets = 5452157642Sps stats->stat_EtherStatsPktsTx128Octetsto255Octets; 5453157642Sps 5454157642Sps sc->stat_EtherStatsPktsTx256Octetsto511Octets = 5455157642Sps stats->stat_EtherStatsPktsTx256Octetsto511Octets; 5456157642Sps 5457157642Sps sc->stat_EtherStatsPktsTx512Octetsto1023Octets = 5458157642Sps stats->stat_EtherStatsPktsTx512Octetsto1023Octets; 5459157642Sps 5460157642Sps sc->stat_EtherStatsPktsTx1024Octetsto1522Octets = 5461157642Sps stats->stat_EtherStatsPktsTx1024Octetsto1522Octets; 5462157642Sps 5463157642Sps sc->stat_EtherStatsPktsTx1523Octetsto9022Octets = 5464157642Sps stats->stat_EtherStatsPktsTx1523Octetsto9022Octets; 5465157642Sps 5466157642Sps sc->stat_XonPauseFramesReceived = 5467157642Sps stats->stat_XonPauseFramesReceived; 5468157642Sps 5469157642Sps sc->stat_XoffPauseFramesReceived = 5470157642Sps stats->stat_XoffPauseFramesReceived; 5471157642Sps 5472157642Sps sc->stat_OutXonSent = 5473157642Sps stats->stat_OutXonSent; 5474157642Sps 5475157642Sps sc->stat_OutXoffSent = 5476157642Sps stats->stat_OutXoffSent; 5477157642Sps 5478157642Sps sc->stat_FlowControlDone = 5479157642Sps stats->stat_FlowControlDone; 5480157642Sps 5481157642Sps sc->stat_MacControlFramesReceived = 5482157642Sps stats->stat_MacControlFramesReceived; 5483157642Sps 5484157642Sps sc->stat_XoffStateEntered = 5485157642Sps stats->stat_XoffStateEntered; 5486157642Sps 5487157642Sps sc->stat_IfInFramesL2FilterDiscards = 5488157642Sps stats->stat_IfInFramesL2FilterDiscards; 5489157642Sps 5490157642Sps sc->stat_IfInRuleCheckerDiscards = 5491157642Sps stats->stat_IfInRuleCheckerDiscards; 5492157642Sps 5493157642Sps sc->stat_IfInFTQDiscards = 5494157642Sps stats->stat_IfInFTQDiscards; 5495157642Sps 5496157642Sps sc->stat_IfInMBUFDiscards = 5497157642Sps stats->stat_IfInMBUFDiscards; 5498157642Sps 5499157642Sps sc->stat_IfInRuleCheckerP4Hit = 5500157642Sps stats->stat_IfInRuleCheckerP4Hit; 5501157642Sps 5502157642Sps sc->stat_CatchupInRuleCheckerDiscards = 5503157642Sps stats->stat_CatchupInRuleCheckerDiscards; 5504157642Sps 5505157642Sps sc->stat_CatchupInFTQDiscards = 5506157642Sps stats->stat_CatchupInFTQDiscards; 5507157642Sps 5508157642Sps sc->stat_CatchupInMBUFDiscards = 5509157642Sps stats->stat_CatchupInMBUFDiscards; 5510157642Sps 5511157642Sps sc->stat_CatchupInRuleCheckerP4Hit = 5512157642Sps stats->stat_CatchupInRuleCheckerP4Hit; 5513157642Sps 5514157642Sps DBPRINT(sc, BCE_EXCESSIVE, "Exiting %s()\n", __FUNCTION__); 5515157642Sps} 5516157642Sps 5517157642Sps 5518157642Spsstatic void 5519157642Spsbce_tick_locked(struct bce_softc *sc) 5520157642Sps{ 5521157642Sps struct mii_data *mii = NULL; 5522157642Sps struct ifnet *ifp; 5523157642Sps u32 msg; 5524157642Sps 5525157642Sps ifp = sc->bce_ifp; 5526157642Sps 5527157642Sps BCE_LOCK_ASSERT(sc); 5528157642Sps 5529157642Sps /* Tell the firmware that the driver is still running. */ 5530157642Sps#ifdef BCE_DEBUG 5531157642Sps msg = (u32) BCE_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE; 5532157642Sps#else 5533157642Sps msg = (u32) ++sc->bce_fw_drv_pulse_wr_seq; 5534157642Sps#endif 5535157642Sps REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_PULSE_MB, msg); 5536157642Sps 5537157642Sps /* Update the statistics from the hardware statistics block. */ 5538157642Sps bce_stats_update(sc); 5539157642Sps 5540157642Sps /* Schedule the next tick. */ 5541157642Sps callout_reset( 5542157642Sps &sc->bce_stat_ch, /* callout */ 5543157642Sps hz, /* ticks */ 5544157642Sps bce_tick, /* function */ 5545157642Sps sc); /* function argument */ 5546157642Sps 5547157642Sps /* If link is up already up then we're done. */ 5548157642Sps if (sc->bce_link) 5549157642Sps goto bce_tick_locked_exit; 5550157642Sps 5551157642Sps /* DRC - ToDo: Add SerDes support and check SerDes link here. */ 5552157642Sps 5553157642Sps mii = device_get_softc(sc->bce_miibus); 5554157642Sps mii_tick(mii); 5555157642Sps 5556157642Sps /* Check if the link has come up. */ 5557157642Sps if (!sc->bce_link && mii->mii_media_status & IFM_ACTIVE && 5558157642Sps IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 5559157642Sps sc->bce_link++; 5560157642Sps if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || 5561157642Sps IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) && 5562157642Sps bootverbose) 5563157642Sps BCE_PRINTF(sc, "Gigabit link up\n"); 5564157642Sps /* Now that link is up, handle any outstanding TX traffic. */ 5565157642Sps if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 5566157642Sps bce_start_locked(ifp); 5567157642Sps } 5568157642Sps 5569157642Spsbce_tick_locked_exit: 5570157642Sps return; 5571157642Sps} 5572157642Sps 5573157642Sps 5574157642Spsstatic void 5575157642Spsbce_tick(void *xsc) 5576157642Sps{ 5577157642Sps struct bce_softc *sc; 5578157642Sps 5579157642Sps sc = xsc; 5580157642Sps 5581157642Sps BCE_LOCK(sc); 5582157642Sps bce_tick_locked(sc); 5583157642Sps BCE_UNLOCK(sc); 5584157642Sps} 5585157642Sps 5586157642Sps 5587157642Sps#ifdef BCE_DEBUG 5588157642Sps/****************************************************************************/ 5589157642Sps/* Allows the driver state to be dumped through the sysctl interface. */ 5590157642Sps/* */ 5591157642Sps/* Returns: */ 5592157642Sps/* 0 for success, positive value for failure. */ 5593157642Sps/****************************************************************************/ 5594157642Spsstatic int 5595157642Spsbce_sysctl_driver_state(SYSCTL_HANDLER_ARGS) 5596157642Sps{ 5597157642Sps int error; 5598157642Sps int result; 5599157642Sps struct bce_softc *sc; 5600157642Sps 5601157642Sps result = -1; 5602157642Sps error = sysctl_handle_int(oidp, &result, 0, req); 5603157642Sps 5604157642Sps if (error || !req->newptr) 5605157642Sps return (error); 5606157642Sps 5607157642Sps if (result == 1) { 5608157642Sps sc = (struct bce_softc *)arg1; 5609157642Sps bce_dump_driver_state(sc); 5610157642Sps } 5611157642Sps 5612157642Sps return error; 5613157642Sps} 5614157642Sps 5615157642Sps 5616157642Sps/****************************************************************************/ 5617157642Sps/* Allows the hardware state to be dumped through the sysctl interface. */ 5618157642Sps/* */ 5619157642Sps/* Returns: */ 5620157642Sps/* 0 for success, positive value for failure. */ 5621157642Sps/****************************************************************************/ 5622157642Spsstatic int 5623157642Spsbce_sysctl_hw_state(SYSCTL_HANDLER_ARGS) 5624157642Sps{ 5625157642Sps int error; 5626157642Sps int result; 5627157642Sps struct bce_softc *sc; 5628157642Sps 5629157642Sps result = -1; 5630157642Sps error = sysctl_handle_int(oidp, &result, 0, req); 5631157642Sps 5632157642Sps if (error || !req->newptr) 5633157642Sps return (error); 5634157642Sps 5635157642Sps if (result == 1) { 5636157642Sps sc = (struct bce_softc *)arg1; 5637157642Sps bce_dump_hw_state(sc); 5638157642Sps } 5639157642Sps 5640157642Sps return error; 5641157642Sps} 5642157642Sps 5643157642Sps 5644157642Sps/****************************************************************************/ 5645157642Sps/* */ 5646157642Sps/* */ 5647157642Sps/* Returns: */ 5648157642Sps/* 0 for success, positive value for failure. */ 5649157642Sps/****************************************************************************/ 5650157642Spsstatic int 5651157642Spsbce_sysctl_dump_rx_chain(SYSCTL_HANDLER_ARGS) 5652157642Sps{ 5653157642Sps int error; 5654157642Sps int result; 5655157642Sps struct bce_softc *sc; 5656157642Sps 5657157642Sps result = -1; 5658157642Sps error = sysctl_handle_int(oidp, &result, 0, req); 5659157642Sps 5660157642Sps if (error || !req->newptr) 5661157642Sps return (error); 5662157642Sps 5663157642Sps if (result == 1) { 5664157642Sps sc = (struct bce_softc *)arg1; 5665157642Sps bce_dump_rx_chain(sc, 0, USABLE_RX_BD); 5666157642Sps } 5667157642Sps 5668157642Sps return error; 5669157642Sps} 5670157642Sps 5671157642Sps 5672157642Sps/****************************************************************************/ 5673157642Sps/* */ 5674157642Sps/* */ 5675157642Sps/* Returns: */ 5676157642Sps/* 0 for success, positive value for failure. */ 5677157642Sps/****************************************************************************/ 5678157642Spsstatic int 5679157642Spsbce_sysctl_breakpoint(SYSCTL_HANDLER_ARGS) 5680157642Sps{ 5681157642Sps int error; 5682157642Sps int result; 5683157642Sps struct bce_softc *sc; 5684157642Sps 5685157642Sps result = -1; 5686157642Sps error = sysctl_handle_int(oidp, &result, 0, req); 5687157642Sps 5688157642Sps if (error || !req->newptr) 5689157642Sps return (error); 5690157642Sps 5691157642Sps if (result == 1) { 5692157642Sps sc = (struct bce_softc *)arg1; 5693157642Sps bce_breakpoint(sc); 5694157642Sps } 5695157642Sps 5696157642Sps return error; 5697157642Sps} 5698157642Sps#endif 5699157642Sps 5700157642Sps 5701157642Sps/****************************************************************************/ 5702157642Sps/* Adds any sysctl parameters for tuning or debugging purposes. */ 5703157642Sps/* */ 5704157642Sps/* Returns: */ 5705157642Sps/* 0 for success, positive value for failure. */ 5706157642Sps/****************************************************************************/ 5707157642Spsstatic void 5708157642Spsbce_add_sysctls(struct bce_softc *sc) 5709157642Sps{ 5710157642Sps struct sysctl_ctx_list *ctx; 5711157642Sps struct sysctl_oid_list *children; 5712157642Sps 5713157642Sps ctx = device_get_sysctl_ctx(sc->bce_dev); 5714157642Sps children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->bce_dev)); 5715157642Sps 5716157642Sps SYSCTL_ADD_STRING(ctx, children, OID_AUTO, 5717157642Sps "driver_version", 5718157642Sps CTLFLAG_RD, &bce_driver_version, 5719157642Sps 0, "bce driver version"); 5720157642Sps 5721157642Sps#ifdef BCE_DEBUG 5722157642Sps SYSCTL_ADD_INT(ctx, children, OID_AUTO, 5723157642Sps "rx_low_watermark", 5724157642Sps CTLFLAG_RD, &sc->rx_low_watermark, 5725157642Sps 0, "Lowest level of free rx_bd's"); 5726157642Sps 5727157642Sps SYSCTL_ADD_INT(ctx, children, OID_AUTO, 5728157642Sps "tx_hi_watermark", 5729157642Sps CTLFLAG_RD, &sc->tx_hi_watermark, 5730157642Sps 0, "Highest level of used tx_bd's"); 5731157642Sps 5732157642Sps SYSCTL_ADD_INT(ctx, children, OID_AUTO, 5733157642Sps "l2fhdr_status_errors", 5734157642Sps CTLFLAG_RD, &sc->l2fhdr_status_errors, 5735157642Sps 0, "l2_fhdr status errors"); 5736157642Sps 5737157642Sps SYSCTL_ADD_INT(ctx, children, OID_AUTO, 5738157642Sps "unexpected_attentions", 5739157642Sps CTLFLAG_RD, &sc->unexpected_attentions, 5740157642Sps 0, "unexpected attentions"); 5741157642Sps 5742157642Sps SYSCTL_ADD_INT(ctx, children, OID_AUTO, 5743157642Sps "lost_status_block_updates", 5744157642Sps CTLFLAG_RD, &sc->lost_status_block_updates, 5745157642Sps 0, "lost status block updates"); 5746157642Sps 5747157642Sps SYSCTL_ADD_INT(ctx, children, OID_AUTO, 5748157642Sps "mbuf_alloc_failed", 5749157642Sps CTLFLAG_RD, &sc->mbuf_alloc_failed, 5750157642Sps 0, "mbuf cluster allocation failures"); 5751157642Sps#endif 5752157642Sps 5753157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5754157642Sps "stat_IfHcInOctets", 5755157642Sps CTLFLAG_RD, &sc->stat_IfHCInOctets, 5756157642Sps "Bytes received"); 5757157642Sps 5758157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5759157642Sps "stat_IfHCInBadOctets", 5760157642Sps CTLFLAG_RD, &sc->stat_IfHCInBadOctets, 5761157642Sps "Bad bytes received"); 5762157642Sps 5763157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5764157642Sps "stat_IfHCOutOctets", 5765157642Sps CTLFLAG_RD, &sc->stat_IfHCOutOctets, 5766157642Sps "Bytes sent"); 5767157642Sps 5768157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5769157642Sps "stat_IfHCOutBadOctets", 5770157642Sps CTLFLAG_RD, &sc->stat_IfHCOutBadOctets, 5771157642Sps "Bad bytes sent"); 5772157642Sps 5773157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5774157642Sps "stat_IfHCInUcastPkts", 5775157642Sps CTLFLAG_RD, &sc->stat_IfHCInUcastPkts, 5776157642Sps "Unicast packets received"); 5777157642Sps 5778157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5779157642Sps "stat_IfHCInMulticastPkts", 5780157642Sps CTLFLAG_RD, &sc->stat_IfHCInMulticastPkts, 5781157642Sps "Multicast packets received"); 5782157642Sps 5783157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5784157642Sps "stat_IfHCInBroadcastPkts", 5785157642Sps CTLFLAG_RD, &sc->stat_IfHCInBroadcastPkts, 5786157642Sps "Broadcast packets received"); 5787157642Sps 5788157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5789157642Sps "stat_IfHCOutUcastPkts", 5790157642Sps CTLFLAG_RD, &sc->stat_IfHCOutUcastPkts, 5791157642Sps "Unicast packets sent"); 5792157642Sps 5793157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5794157642Sps "stat_IfHCOutMulticastPkts", 5795157642Sps CTLFLAG_RD, &sc->stat_IfHCOutMulticastPkts, 5796157642Sps "Multicast packets sent"); 5797157642Sps 5798157642Sps SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 5799157642Sps "stat_IfHCOutBroadcastPkts", 5800157642Sps CTLFLAG_RD, &sc->stat_IfHCOutBroadcastPkts, 5801157642Sps "Broadcast packets sent"); 5802157642Sps 5803157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5804157642Sps "stat_emac_tx_stat_dot3statsinternalmactransmiterrors", 5805157642Sps CTLFLAG_RD, &sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors, 5806157642Sps 0, "Internal MAC transmit errors"); 5807157642Sps 5808157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5809157642Sps "stat_Dot3StatsCarrierSenseErrors", 5810157642Sps CTLFLAG_RD, &sc->stat_Dot3StatsCarrierSenseErrors, 5811157642Sps 0, "Carrier sense errors"); 5812157642Sps 5813157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5814157642Sps "stat_Dot3StatsFCSErrors", 5815157642Sps CTLFLAG_RD, &sc->stat_Dot3StatsFCSErrors, 5816157642Sps 0, "Frame check sequence errors"); 5817157642Sps 5818157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5819157642Sps "stat_Dot3StatsAlignmentErrors", 5820157642Sps CTLFLAG_RD, &sc->stat_Dot3StatsAlignmentErrors, 5821157642Sps 0, "Alignment errors"); 5822157642Sps 5823157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5824157642Sps "stat_Dot3StatsSingleCollisionFrames", 5825157642Sps CTLFLAG_RD, &sc->stat_Dot3StatsSingleCollisionFrames, 5826157642Sps 0, "Single Collision Frames"); 5827157642Sps 5828157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5829157642Sps "stat_Dot3StatsMultipleCollisionFrames", 5830157642Sps CTLFLAG_RD, &sc->stat_Dot3StatsMultipleCollisionFrames, 5831157642Sps 0, "Multiple Collision Frames"); 5832157642Sps 5833157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5834157642Sps "stat_Dot3StatsDeferredTransmissions", 5835157642Sps CTLFLAG_RD, &sc->stat_Dot3StatsDeferredTransmissions, 5836157642Sps 0, "Deferred Transmissions"); 5837157642Sps 5838157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5839157642Sps "stat_Dot3StatsExcessiveCollisions", 5840157642Sps CTLFLAG_RD, &sc->stat_Dot3StatsExcessiveCollisions, 5841157642Sps 0, "Excessive Collisions"); 5842157642Sps 5843157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5844157642Sps "stat_Dot3StatsLateCollisions", 5845157642Sps CTLFLAG_RD, &sc->stat_Dot3StatsLateCollisions, 5846157642Sps 0, "Late Collisions"); 5847157642Sps 5848157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5849157642Sps "stat_EtherStatsCollisions", 5850157642Sps CTLFLAG_RD, &sc->stat_EtherStatsCollisions, 5851157642Sps 0, "Collisions"); 5852157642Sps 5853157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5854157642Sps "stat_EtherStatsFragments", 5855157642Sps CTLFLAG_RD, &sc->stat_EtherStatsFragments, 5856157642Sps 0, "Fragments"); 5857157642Sps 5858157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5859157642Sps "stat_EtherStatsJabbers", 5860157642Sps CTLFLAG_RD, &sc->stat_EtherStatsJabbers, 5861157642Sps 0, "Jabbers"); 5862157642Sps 5863157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5864157642Sps "stat_EtherStatsUndersizePkts", 5865157642Sps CTLFLAG_RD, &sc->stat_EtherStatsUndersizePkts, 5866157642Sps 0, "Undersize packets"); 5867157642Sps 5868157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5869157642Sps "stat_EtherStatsOverrsizePkts", 5870157642Sps CTLFLAG_RD, &sc->stat_EtherStatsOverrsizePkts, 5871157642Sps 0, "stat_EtherStatsOverrsizePkts"); 5872157642Sps 5873157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5874157642Sps "stat_EtherStatsPktsRx64Octets", 5875157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsRx64Octets, 5876157642Sps 0, "Bytes received in 64 byte packets"); 5877157642Sps 5878157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5879157642Sps "stat_EtherStatsPktsRx65Octetsto127Octets", 5880157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsRx65Octetsto127Octets, 5881157642Sps 0, "Bytes received in 65 to 127 byte packets"); 5882157642Sps 5883157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5884157642Sps "stat_EtherStatsPktsRx128Octetsto255Octets", 5885157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsRx128Octetsto255Octets, 5886157642Sps 0, "Bytes received in 128 to 255 byte packets"); 5887157642Sps 5888157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5889157642Sps "stat_EtherStatsPktsRx256Octetsto511Octets", 5890157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsRx256Octetsto511Octets, 5891157642Sps 0, "Bytes received in 256 to 511 byte packets"); 5892157642Sps 5893157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5894157642Sps "stat_EtherStatsPktsRx512Octetsto1023Octets", 5895157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsRx512Octetsto1023Octets, 5896157642Sps 0, "Bytes received in 512 to 1023 byte packets"); 5897157642Sps 5898157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5899157642Sps "stat_EtherStatsPktsRx1024Octetsto1522Octets", 5900157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1024Octetsto1522Octets, 5901157642Sps 0, "Bytes received in 1024 t0 1522 byte packets"); 5902157642Sps 5903157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5904157642Sps "stat_EtherStatsPktsRx1523Octetsto9022Octets", 5905157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1523Octetsto9022Octets, 5906157642Sps 0, "Bytes received in 1523 to 9022 byte packets"); 5907157642Sps 5908157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5909157642Sps "stat_EtherStatsPktsTx64Octets", 5910157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsTx64Octets, 5911157642Sps 0, "Bytes sent in 64 byte packets"); 5912157642Sps 5913157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5914157642Sps "stat_EtherStatsPktsTx65Octetsto127Octets", 5915157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsTx65Octetsto127Octets, 5916157642Sps 0, "Bytes sent in 65 to 127 byte packets"); 5917157642Sps 5918157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5919157642Sps "stat_EtherStatsPktsTx128Octetsto255Octets", 5920157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsTx128Octetsto255Octets, 5921157642Sps 0, "Bytes sent in 128 to 255 byte packets"); 5922157642Sps 5923157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5924157642Sps "stat_EtherStatsPktsTx256Octetsto511Octets", 5925157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsTx256Octetsto511Octets, 5926157642Sps 0, "Bytes sent in 256 to 511 byte packets"); 5927157642Sps 5928157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5929157642Sps "stat_EtherStatsPktsTx512Octetsto1023Octets", 5930157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsTx512Octetsto1023Octets, 5931157642Sps 0, "Bytes sent in 512 to 1023 byte packets"); 5932157642Sps 5933157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5934157642Sps "stat_EtherStatsPktsTx1024Octetsto1522Octets", 5935157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1024Octetsto1522Octets, 5936157642Sps 0, "Bytes sent in 1024 to 1522 byte packets"); 5937157642Sps 5938157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5939157642Sps "stat_EtherStatsPktsTx1523Octetsto9022Octets", 5940157642Sps CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1523Octetsto9022Octets, 5941157642Sps 0, "Bytes sent in 1523 to 9022 byte packets"); 5942157642Sps 5943157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5944157642Sps "stat_XonPauseFramesReceived", 5945157642Sps CTLFLAG_RD, &sc->stat_XonPauseFramesReceived, 5946157642Sps 0, "XON pause frames receved"); 5947157642Sps 5948157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5949157642Sps "stat_XoffPauseFramesReceived", 5950157642Sps CTLFLAG_RD, &sc->stat_XoffPauseFramesReceived, 5951157642Sps 0, "XOFF pause frames received"); 5952157642Sps 5953157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5954157642Sps "stat_OutXonSent", 5955157642Sps CTLFLAG_RD, &sc->stat_OutXonSent, 5956157642Sps 0, "XON pause frames sent"); 5957157642Sps 5958157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5959157642Sps "stat_OutXoffSent", 5960157642Sps CTLFLAG_RD, &sc->stat_OutXoffSent, 5961157642Sps 0, "XOFF pause frames sent"); 5962157642Sps 5963157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5964157642Sps "stat_FlowControlDone", 5965157642Sps CTLFLAG_RD, &sc->stat_FlowControlDone, 5966157642Sps 0, "Flow control done"); 5967157642Sps 5968157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5969157642Sps "stat_MacControlFramesReceived", 5970157642Sps CTLFLAG_RD, &sc->stat_MacControlFramesReceived, 5971157642Sps 0, "MAC control frames received"); 5972157642Sps 5973157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5974157642Sps "stat_XoffStateEntered", 5975157642Sps CTLFLAG_RD, &sc->stat_XoffStateEntered, 5976157642Sps 0, "XOFF state entered"); 5977157642Sps 5978157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5979157642Sps "stat_IfInFramesL2FilterDiscards", 5980157642Sps CTLFLAG_RD, &sc->stat_IfInFramesL2FilterDiscards, 5981157642Sps 0, "Received L2 packets discarded"); 5982157642Sps 5983157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5984157642Sps "stat_IfInRuleCheckerDiscards", 5985157642Sps CTLFLAG_RD, &sc->stat_IfInRuleCheckerDiscards, 5986157642Sps 0, "Received packets discarded by rule"); 5987157642Sps 5988157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5989157642Sps "stat_IfInFTQDiscards", 5990157642Sps CTLFLAG_RD, &sc->stat_IfInFTQDiscards, 5991157642Sps 0, "Received packet FTQ discards"); 5992157642Sps 5993157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5994157642Sps "stat_IfInMBUFDiscards", 5995157642Sps CTLFLAG_RD, &sc->stat_IfInMBUFDiscards, 5996157642Sps 0, "Received packets discarded due to lack of controller buffer memory"); 5997157642Sps 5998157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 5999157642Sps "stat_IfInRuleCheckerP4Hit", 6000157642Sps CTLFLAG_RD, &sc->stat_IfInRuleCheckerP4Hit, 6001157642Sps 0, "Received packets rule checker hits"); 6002157642Sps 6003157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 6004157642Sps "stat_CatchupInRuleCheckerDiscards", 6005157642Sps CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerDiscards, 6006157642Sps 0, "Received packets discarded in Catchup path"); 6007157642Sps 6008157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 6009157642Sps "stat_CatchupInFTQDiscards", 6010157642Sps CTLFLAG_RD, &sc->stat_CatchupInFTQDiscards, 6011157642Sps 0, "Received packets discarded in FTQ in Catchup path"); 6012157642Sps 6013157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 6014157642Sps "stat_CatchupInMBUFDiscards", 6015157642Sps CTLFLAG_RD, &sc->stat_CatchupInMBUFDiscards, 6016157642Sps 0, "Received packets discarded in controller buffer memory in Catchup path"); 6017157642Sps 6018157642Sps SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 6019157642Sps "stat_CatchupInRuleCheckerP4Hit", 6020157642Sps CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerP4Hit, 6021157642Sps 0, "Received packets rule checker hits in Catchup path"); 6022157642Sps 6023157642Sps#ifdef BCE_DEBUG 6024157642Sps SYSCTL_ADD_PROC(ctx, children, OID_AUTO, 6025157642Sps "driver_state", CTLTYPE_INT | CTLFLAG_RW, 6026157642Sps (void *)sc, 0, 6027157642Sps bce_sysctl_driver_state, "I", "Drive state information"); 6028157642Sps 6029157642Sps SYSCTL_ADD_PROC(ctx, children, OID_AUTO, 6030157642Sps "hw_state", CTLTYPE_INT | CTLFLAG_RW, 6031157642Sps (void *)sc, 0, 6032157642Sps bce_sysctl_hw_state, "I", "Hardware state information"); 6033157642Sps 6034157642Sps SYSCTL_ADD_PROC(ctx, children, OID_AUTO, 6035157642Sps "dump_rx_chain", CTLTYPE_INT | CTLFLAG_RW, 6036157642Sps (void *)sc, 0, 6037157642Sps bce_sysctl_dump_rx_chain, "I", "Dump rx_bd chain"); 6038157642Sps 6039157642Sps SYSCTL_ADD_PROC(ctx, children, OID_AUTO, 6040157642Sps "breakpoint", CTLTYPE_INT | CTLFLAG_RW, 6041157642Sps (void *)sc, 0, 6042157642Sps bce_sysctl_breakpoint, "I", "Driver breakpoint"); 6043157642Sps#endif 6044157642Sps 6045157642Sps} 6046157642Sps 6047157642Sps 6048157642Sps/****************************************************************************/ 6049157642Sps/* BCE Debug Routines */ 6050157642Sps/****************************************************************************/ 6051157642Sps#ifdef BCE_DEBUG 6052157642Sps 6053157642Sps/****************************************************************************/ 6054157642Sps/* Prints out information about an mbuf. */ 6055157642Sps/* */ 6056157642Sps/* Returns: */ 6057157642Sps/* Nothing. */ 6058157642Sps/****************************************************************************/ 6059157642Spsstatic void 6060157642Spsbce_dump_mbuf(struct bce_softc *sc, struct mbuf *m) 6061157642Sps{ 6062157642Sps u32 val_hi, val_lo; 6063157642Sps struct mbuf *mp = m; 6064157642Sps 6065157642Sps if (m == NULL) { 6066157642Sps /* Index out of range. */ 6067157642Sps printf("mbuf ptr is null!\n"); 6068157642Sps return; 6069157642Sps } 6070157642Sps 6071157642Sps while (mp) { 6072157642Sps val_hi = BCE_ADDR_HI(mp); 6073157642Sps val_lo = BCE_ADDR_LO(mp); 6074157642Sps BCE_PRINTF(sc, "mbuf: vaddr = 0x%08X:%08X, m_len = %d, m_flags = ", 6075157642Sps val_hi, val_lo, mp->m_len); 6076157642Sps 6077157642Sps if (mp->m_flags & M_EXT) 6078157642Sps printf("M_EXT "); 6079157642Sps if (mp->m_flags & M_PKTHDR) 6080157642Sps printf("M_PKTHDR "); 6081157642Sps printf("\n"); 6082157642Sps 6083157642Sps if (mp->m_flags & M_EXT) { 6084157642Sps val_hi = BCE_ADDR_HI(mp->m_ext.ext_buf); 6085157642Sps val_lo = BCE_ADDR_LO(mp->m_ext.ext_buf); 6086157642Sps BCE_PRINTF(sc, "- m_ext: vaddr = 0x%08X:%08X, ext_size = 0x%04X\n", 6087157642Sps val_hi, val_lo, mp->m_ext.ext_size); 6088157642Sps } 6089157642Sps 6090157642Sps mp = mp->m_next; 6091157642Sps } 6092157642Sps 6093157642Sps 6094157642Sps} 6095157642Sps 6096157642Sps 6097157642Sps/****************************************************************************/ 6098157642Sps/* Prints out the mbufs in the TX mbuf chain. */ 6099157642Sps/* */ 6100157642Sps/* Returns: */ 6101157642Sps/* Nothing. */ 6102157642Sps/****************************************************************************/ 6103157642Spsstatic void 6104157642Spsbce_dump_tx_mbuf_chain(struct bce_softc *sc, int chain_prod, int count) 6105157642Sps{ 6106157642Sps struct mbuf *m; 6107157642Sps 6108157642Sps BCE_PRINTF(sc, 6109157642Sps "----------------------------" 6110157642Sps " tx mbuf data " 6111157642Sps "----------------------------\n"); 6112157642Sps 6113157642Sps for (int i = 0; i < count; i++) { 6114157642Sps m = sc->tx_mbuf_ptr[chain_prod]; 6115157642Sps BCE_PRINTF(sc, "txmbuf[%d]\n", chain_prod); 6116157642Sps bce_dump_mbuf(sc, m); 6117157642Sps chain_prod = TX_CHAIN_IDX(NEXT_TX_BD(chain_prod)); 6118157642Sps } 6119157642Sps 6120157642Sps BCE_PRINTF(sc, 6121157642Sps "----------------------------" 6122157642Sps "----------------" 6123157642Sps "----------------------------\n"); 6124157642Sps} 6125157642Sps 6126157642Sps 6127157642Sps/* 6128157642Sps * This routine prints the RX mbuf chain. 6129157642Sps */ 6130157642Spsstatic void 6131157642Spsbce_dump_rx_mbuf_chain(struct bce_softc *sc, int chain_prod, int count) 6132157642Sps{ 6133157642Sps struct mbuf *m; 6134157642Sps 6135157642Sps BCE_PRINTF(sc, 6136157642Sps "----------------------------" 6137157642Sps " rx mbuf data " 6138157642Sps "----------------------------\n"); 6139157642Sps 6140157642Sps for (int i = 0; i < count; i++) { 6141157642Sps m = sc->rx_mbuf_ptr[chain_prod]; 6142157642Sps BCE_PRINTF(sc, "rxmbuf[0x%04X]\n", chain_prod); 6143157642Sps bce_dump_mbuf(sc, m); 6144157642Sps chain_prod = RX_CHAIN_IDX(NEXT_RX_BD(chain_prod)); 6145157642Sps } 6146157642Sps 6147157642Sps 6148157642Sps BCE_PRINTF(sc, 6149157642Sps "----------------------------" 6150157642Sps "----------------" 6151157642Sps "----------------------------\n"); 6152157642Sps} 6153157642Sps 6154157642Sps 6155157642Spsstatic void 6156157642Spsbce_dump_txbd(struct bce_softc *sc, int idx, struct tx_bd *txbd) 6157157642Sps{ 6158157642Sps if (idx > MAX_TX_BD) 6159157642Sps /* Index out of range. */ 6160157642Sps BCE_PRINTF(sc, "tx_bd[0x%04X]: Invalid tx_bd index!\n", idx); 6161157642Sps else if ((idx & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE) 6162157642Sps /* TX Chain page pointer. */ 6163157642Sps BCE_PRINTF(sc, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, chain page pointer\n", 6164157642Sps idx, txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo); 6165157642Sps else 6166157642Sps /* Normal tx_bd entry. */ 6167157642Sps BCE_PRINTF(sc, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, nbytes = 0x%08X, " 6168157642Sps "flags = 0x%08X\n", idx, 6169157642Sps txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo, 6170157642Sps txbd->tx_bd_mss_nbytes, txbd->tx_bd_vlan_tag_flags); 6171157642Sps} 6172157642Sps 6173157642Sps 6174157642Spsstatic void 6175157642Spsbce_dump_rxbd(struct bce_softc *sc, int idx, struct rx_bd *rxbd) 6176157642Sps{ 6177157642Sps if (idx > MAX_RX_BD) 6178157642Sps /* Index out of range. */ 6179157642Sps BCE_PRINTF(sc, "rx_bd[0x%04X]: Invalid rx_bd index!\n", idx); 6180157642Sps else if ((idx & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE) 6181157642Sps /* TX Chain page pointer. */ 6182157642Sps BCE_PRINTF(sc, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, chain page pointer\n", 6183157642Sps idx, rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo); 6184157642Sps else 6185157642Sps /* Normal tx_bd entry. */ 6186157642Sps BCE_PRINTF(sc, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, nbytes = 0x%08X, " 6187157642Sps "flags = 0x%08X\n", idx, 6188157642Sps rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo, 6189157642Sps rxbd->rx_bd_len, rxbd->rx_bd_flags); 6190157642Sps} 6191157642Sps 6192157642Sps 6193157642Spsstatic void 6194157642Spsbce_dump_l2fhdr(struct bce_softc *sc, int idx, struct l2_fhdr *l2fhdr) 6195157642Sps{ 6196157642Sps BCE_PRINTF(sc, "l2_fhdr[0x%04X]: status = 0x%08X, " 6197157642Sps "pkt_len = 0x%04X, vlan = 0x%04x, ip_xsum = 0x%04X, " 6198157642Sps "tcp_udp_xsum = 0x%04X\n", idx, 6199157642Sps l2fhdr->l2_fhdr_status, l2fhdr->l2_fhdr_pkt_len, 6200157642Sps l2fhdr->l2_fhdr_vlan_tag, l2fhdr->l2_fhdr_ip_xsum, 6201157642Sps l2fhdr->l2_fhdr_tcp_udp_xsum); 6202157642Sps} 6203157642Sps 6204157642Sps 6205157642Sps/* 6206157642Sps * This routine prints the TX chain. 6207157642Sps */ 6208157642Spsstatic void 6209157642Spsbce_dump_tx_chain(struct bce_softc *sc, int tx_prod, int count) 6210157642Sps{ 6211157642Sps struct tx_bd *txbd; 6212157642Sps 6213157642Sps /* First some info about the tx_bd chain structure. */ 6214157642Sps BCE_PRINTF(sc, 6215157642Sps "----------------------------" 6216157642Sps " tx_bd chain " 6217157642Sps "----------------------------\n"); 6218157642Sps 6219157642Sps BCE_PRINTF(sc, "page size = 0x%08X, tx chain pages = 0x%08X\n", 6220157642Sps (u32) BCM_PAGE_SIZE, (u32) TX_PAGES); 6221157642Sps 6222157642Sps BCE_PRINTF(sc, "tx_bd per page = 0x%08X, usable tx_bd per page = 0x%08X\n", 6223157642Sps (u32) TOTAL_TX_BD_PER_PAGE, (u32) USABLE_TX_BD_PER_PAGE); 6224157642Sps 6225157642Sps BCE_PRINTF(sc, "total tx_bd = 0x%08X\n", (u32) TOTAL_TX_BD); 6226157642Sps 6227157642Sps BCE_PRINTF(sc, "" 6228157642Sps "-----------------------------" 6229157642Sps " tx_bd data " 6230157642Sps "-----------------------------\n"); 6231157642Sps 6232157642Sps /* Now print out the tx_bd's themselves. */ 6233157642Sps for (int i = 0; i < count; i++) { 6234157642Sps txbd = &sc->tx_bd_chain[TX_PAGE(tx_prod)][TX_IDX(tx_prod)]; 6235157642Sps bce_dump_txbd(sc, tx_prod, txbd); 6236157642Sps tx_prod = TX_CHAIN_IDX(NEXT_TX_BD(tx_prod)); 6237157642Sps } 6238157642Sps 6239157642Sps BCE_PRINTF(sc, 6240157642Sps "-----------------------------" 6241157642Sps "--------------" 6242157642Sps "-----------------------------\n"); 6243157642Sps} 6244157642Sps 6245157642Sps 6246157642Sps/* 6247157642Sps * This routine prints the RX chain. 6248157642Sps */ 6249157642Spsstatic void 6250157642Spsbce_dump_rx_chain(struct bce_softc *sc, int rx_prod, int count) 6251157642Sps{ 6252157642Sps struct rx_bd *rxbd; 6253157642Sps 6254157642Sps /* First some info about the tx_bd chain structure. */ 6255157642Sps BCE_PRINTF(sc, 6256157642Sps "----------------------------" 6257157642Sps " rx_bd chain " 6258157642Sps "----------------------------\n"); 6259157642Sps 6260157642Sps BCE_PRINTF(sc, "----- RX_BD Chain -----\n"); 6261157642Sps 6262157642Sps BCE_PRINTF(sc, "page size = 0x%08X, rx chain pages = 0x%08X\n", 6263157642Sps (u32) BCM_PAGE_SIZE, (u32) RX_PAGES); 6264157642Sps 6265157642Sps BCE_PRINTF(sc, "rx_bd per page = 0x%08X, usable rx_bd per page = 0x%08X\n", 6266157642Sps (u32) TOTAL_RX_BD_PER_PAGE, (u32) USABLE_RX_BD_PER_PAGE); 6267157642Sps 6268157642Sps BCE_PRINTF(sc, "total rx_bd = 0x%08X\n", (u32) TOTAL_RX_BD); 6269157642Sps 6270157642Sps BCE_PRINTF(sc, 6271157642Sps "----------------------------" 6272157642Sps " rx_bd data " 6273157642Sps "----------------------------\n"); 6274157642Sps 6275157642Sps /* Now print out the rx_bd's themselves. */ 6276157642Sps for (int i = 0; i < count; i++) { 6277157642Sps rxbd = &sc->rx_bd_chain[RX_PAGE(rx_prod)][RX_IDX(rx_prod)]; 6278157642Sps bce_dump_rxbd(sc, rx_prod, rxbd); 6279157642Sps rx_prod = RX_CHAIN_IDX(NEXT_RX_BD(rx_prod)); 6280157642Sps } 6281157642Sps 6282157642Sps BCE_PRINTF(sc, 6283157642Sps "----------------------------" 6284157642Sps "--------------" 6285157642Sps "----------------------------\n"); 6286157642Sps} 6287157642Sps 6288157642Sps 6289157642Sps/* 6290157642Sps * This routine prints the status block. 6291157642Sps */ 6292157642Spsstatic void 6293157642Spsbce_dump_status_block(struct bce_softc *sc) 6294157642Sps{ 6295157642Sps struct status_block *sblk; 6296157642Sps 6297157642Sps sblk = sc->status_block; 6298157642Sps 6299157642Sps BCE_PRINTF(sc, "----------------------------- Status Block " 6300157642Sps "-----------------------------\n"); 6301157642Sps 6302157642Sps BCE_PRINTF(sc, "attn_bits = 0x%08X, attn_bits_ack = 0x%08X, index = 0x%04X\n", 6303157642Sps sblk->status_attn_bits, sblk->status_attn_bits_ack, 6304157642Sps sblk->status_idx); 6305157642Sps 6306157642Sps BCE_PRINTF(sc, "rx_cons0 = 0x%08X, tx_cons0 = 0x%08X\n", 6307157642Sps sblk->status_rx_quick_consumer_index0, 6308157642Sps sblk->status_tx_quick_consumer_index0); 6309157642Sps 6310157642Sps BCE_PRINTF(sc, "status_idx = 0x%04X\n", sblk->status_idx); 6311157642Sps 6312157642Sps /* Theses indices are not used for normal L2 drivers. */ 6313157642Sps if (sblk->status_rx_quick_consumer_index1 || 6314157642Sps sblk->status_tx_quick_consumer_index1) 6315157642Sps BCE_PRINTF(sc, "rx_cons1 = 0x%08X, tx_cons1 = 0x%08X\n", 6316157642Sps sblk->status_rx_quick_consumer_index1, 6317157642Sps sblk->status_tx_quick_consumer_index1); 6318157642Sps 6319157642Sps if (sblk->status_rx_quick_consumer_index2 || 6320157642Sps sblk->status_tx_quick_consumer_index2) 6321157642Sps BCE_PRINTF(sc, "rx_cons2 = 0x%08X, tx_cons2 = 0x%08X\n", 6322157642Sps sblk->status_rx_quick_consumer_index2, 6323157642Sps sblk->status_tx_quick_consumer_index2); 6324157642Sps 6325157642Sps if (sblk->status_rx_quick_consumer_index3 || 6326157642Sps sblk->status_tx_quick_consumer_index3) 6327157642Sps BCE_PRINTF(sc, "rx_cons3 = 0x%08X, tx_cons3 = 0x%08X\n", 6328157642Sps sblk->status_rx_quick_consumer_index3, 6329157642Sps sblk->status_tx_quick_consumer_index3); 6330157642Sps 6331157642Sps if (sblk->status_rx_quick_consumer_index4 || 6332157642Sps sblk->status_rx_quick_consumer_index5) 6333157642Sps BCE_PRINTF(sc, "rx_cons4 = 0x%08X, rx_cons5 = 0x%08X\n", 6334157642Sps sblk->status_rx_quick_consumer_index4, 6335157642Sps sblk->status_rx_quick_consumer_index5); 6336157642Sps 6337157642Sps if (sblk->status_rx_quick_consumer_index6 || 6338157642Sps sblk->status_rx_quick_consumer_index7) 6339157642Sps BCE_PRINTF(sc, "rx_cons6 = 0x%08X, rx_cons7 = 0x%08X\n", 6340157642Sps sblk->status_rx_quick_consumer_index6, 6341157642Sps sblk->status_rx_quick_consumer_index7); 6342157642Sps 6343157642Sps if (sblk->status_rx_quick_consumer_index8 || 6344157642Sps sblk->status_rx_quick_consumer_index9) 6345157642Sps BCE_PRINTF(sc, "rx_cons8 = 0x%08X, rx_cons9 = 0x%08X\n", 6346157642Sps sblk->status_rx_quick_consumer_index8, 6347157642Sps sblk->status_rx_quick_consumer_index9); 6348157642Sps 6349157642Sps if (sblk->status_rx_quick_consumer_index10 || 6350157642Sps sblk->status_rx_quick_consumer_index11) 6351157642Sps BCE_PRINTF(sc, "rx_cons10 = 0x%08X, rx_cons11 = 0x%08X\n", 6352157642Sps sblk->status_rx_quick_consumer_index10, 6353157642Sps sblk->status_rx_quick_consumer_index11); 6354157642Sps 6355157642Sps if (sblk->status_rx_quick_consumer_index12 || 6356157642Sps sblk->status_rx_quick_consumer_index13) 6357157642Sps BCE_PRINTF(sc, "rx_cons12 = 0x%08X, rx_cons13 = 0x%08X\n", 6358157642Sps sblk->status_rx_quick_consumer_index12, 6359157642Sps sblk->status_rx_quick_consumer_index13); 6360157642Sps 6361157642Sps if (sblk->status_rx_quick_consumer_index14 || 6362157642Sps sblk->status_rx_quick_consumer_index15) 6363157642Sps BCE_PRINTF(sc, "rx_cons14 = 0x%08X, rx_cons15 = 0x%08X\n", 6364157642Sps sblk->status_rx_quick_consumer_index14, 6365157642Sps sblk->status_rx_quick_consumer_index15); 6366157642Sps 6367157642Sps if (sblk->status_completion_producer_index || 6368157642Sps sblk->status_cmd_consumer_index) 6369157642Sps BCE_PRINTF(sc, "com_prod = 0x%08X, cmd_cons = 0x%08X\n", 6370157642Sps sblk->status_completion_producer_index, 6371157642Sps sblk->status_cmd_consumer_index); 6372157642Sps 6373157642Sps BCE_PRINTF(sc, "-------------------------------------------" 6374157642Sps "-----------------------------\n"); 6375157642Sps} 6376157642Sps 6377157642Sps 6378157642Sps/* 6379157642Sps * This routine prints the statistics block. 6380157642Sps */ 6381157642Spsstatic void 6382157642Spsbce_dump_stats_block(struct bce_softc *sc) 6383157642Sps{ 6384157642Sps struct statistics_block *sblk; 6385157642Sps 6386157642Sps sblk = sc->stats_block; 6387157642Sps 6388157642Sps BCE_PRINTF(sc, "" 6389157642Sps "-----------------------------" 6390157642Sps " Stats Block " 6391157642Sps "-----------------------------\n"); 6392157642Sps 6393157642Sps BCE_PRINTF(sc, "IfHcInOctets = 0x%08X:%08X, " 6394157642Sps "IfHcInBadOctets = 0x%08X:%08X\n", 6395157642Sps sblk->stat_IfHCInOctets_hi, sblk->stat_IfHCInOctets_lo, 6396157642Sps sblk->stat_IfHCInBadOctets_hi, sblk->stat_IfHCInBadOctets_lo); 6397157642Sps 6398157642Sps BCE_PRINTF(sc, "IfHcOutOctets = 0x%08X:%08X, " 6399157642Sps "IfHcOutBadOctets = 0x%08X:%08X\n", 6400157642Sps sblk->stat_IfHCOutOctets_hi, sblk->stat_IfHCOutOctets_lo, 6401157642Sps sblk->stat_IfHCOutBadOctets_hi, sblk->stat_IfHCOutBadOctets_lo); 6402157642Sps 6403157642Sps BCE_PRINTF(sc, "IfHcInUcastPkts = 0x%08X:%08X, " 6404157642Sps "IfHcInMulticastPkts = 0x%08X:%08X\n", 6405157642Sps sblk->stat_IfHCInUcastPkts_hi, sblk->stat_IfHCInUcastPkts_lo, 6406157642Sps sblk->stat_IfHCInMulticastPkts_hi, sblk->stat_IfHCInMulticastPkts_lo); 6407157642Sps 6408157642Sps BCE_PRINTF(sc, "IfHcInBroadcastPkts = 0x%08X:%08X, " 6409157642Sps "IfHcOutUcastPkts = 0x%08X:%08X\n", 6410157642Sps sblk->stat_IfHCInBroadcastPkts_hi, sblk->stat_IfHCInBroadcastPkts_lo, 6411157642Sps sblk->stat_IfHCOutUcastPkts_hi, sblk->stat_IfHCOutUcastPkts_lo); 6412157642Sps 6413157642Sps BCE_PRINTF(sc, "IfHcOutMulticastPkts = 0x%08X:%08X, IfHcOutBroadcastPkts = 0x%08X:%08X\n", 6414157642Sps sblk->stat_IfHCOutMulticastPkts_hi, sblk->stat_IfHCOutMulticastPkts_lo, 6415157642Sps sblk->stat_IfHCOutBroadcastPkts_hi, sblk->stat_IfHCOutBroadcastPkts_lo); 6416157642Sps 6417157642Sps if (sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors) 6418157642Sps BCE_PRINTF(sc, "0x%08X : " 6419157642Sps "emac_tx_stat_dot3statsinternalmactransmiterrors\n", 6420157642Sps sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors); 6421157642Sps 6422157642Sps if (sblk->stat_Dot3StatsCarrierSenseErrors) 6423157642Sps BCE_PRINTF(sc, "0x%08X : Dot3StatsCarrierSenseErrors\n", 6424157642Sps sblk->stat_Dot3StatsCarrierSenseErrors); 6425157642Sps 6426157642Sps if (sblk->stat_Dot3StatsFCSErrors) 6427157642Sps BCE_PRINTF(sc, "0x%08X : Dot3StatsFCSErrors\n", 6428157642Sps sblk->stat_Dot3StatsFCSErrors); 6429157642Sps 6430157642Sps if (sblk->stat_Dot3StatsAlignmentErrors) 6431157642Sps BCE_PRINTF(sc, "0x%08X : Dot3StatsAlignmentErrors\n", 6432157642Sps sblk->stat_Dot3StatsAlignmentErrors); 6433157642Sps 6434157642Sps if (sblk->stat_Dot3StatsSingleCollisionFrames) 6435157642Sps BCE_PRINTF(sc, "0x%08X : Dot3StatsSingleCollisionFrames\n", 6436157642Sps sblk->stat_Dot3StatsSingleCollisionFrames); 6437157642Sps 6438157642Sps if (sblk->stat_Dot3StatsMultipleCollisionFrames) 6439157642Sps BCE_PRINTF(sc, "0x%08X : Dot3StatsMultipleCollisionFrames\n", 6440157642Sps sblk->stat_Dot3StatsMultipleCollisionFrames); 6441157642Sps 6442157642Sps if (sblk->stat_Dot3StatsDeferredTransmissions) 6443157642Sps BCE_PRINTF(sc, "0x%08X : Dot3StatsDeferredTransmissions\n", 6444157642Sps sblk->stat_Dot3StatsDeferredTransmissions); 6445157642Sps 6446157642Sps if (sblk->stat_Dot3StatsExcessiveCollisions) 6447157642Sps BCE_PRINTF(sc, "0x%08X : Dot3StatsExcessiveCollisions\n", 6448157642Sps sblk->stat_Dot3StatsExcessiveCollisions); 6449157642Sps 6450157642Sps if (sblk->stat_Dot3StatsLateCollisions) 6451157642Sps BCE_PRINTF(sc, "0x%08X : Dot3StatsLateCollisions\n", 6452157642Sps sblk->stat_Dot3StatsLateCollisions); 6453157642Sps 6454157642Sps if (sblk->stat_EtherStatsCollisions) 6455157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsCollisions\n", 6456157642Sps sblk->stat_EtherStatsCollisions); 6457157642Sps 6458157642Sps if (sblk->stat_EtherStatsFragments) 6459157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsFragments\n", 6460157642Sps sblk->stat_EtherStatsFragments); 6461157642Sps 6462157642Sps if (sblk->stat_EtherStatsJabbers) 6463157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsJabbers\n", 6464157642Sps sblk->stat_EtherStatsJabbers); 6465157642Sps 6466157642Sps if (sblk->stat_EtherStatsUndersizePkts) 6467157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsUndersizePkts\n", 6468157642Sps sblk->stat_EtherStatsUndersizePkts); 6469157642Sps 6470157642Sps if (sblk->stat_EtherStatsOverrsizePkts) 6471157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsOverrsizePkts\n", 6472157642Sps sblk->stat_EtherStatsOverrsizePkts); 6473157642Sps 6474157642Sps if (sblk->stat_EtherStatsPktsRx64Octets) 6475157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx64Octets\n", 6476157642Sps sblk->stat_EtherStatsPktsRx64Octets); 6477157642Sps 6478157642Sps if (sblk->stat_EtherStatsPktsRx65Octetsto127Octets) 6479157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx65Octetsto127Octets\n", 6480157642Sps sblk->stat_EtherStatsPktsRx65Octetsto127Octets); 6481157642Sps 6482157642Sps if (sblk->stat_EtherStatsPktsRx128Octetsto255Octets) 6483157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx128Octetsto255Octets\n", 6484157642Sps sblk->stat_EtherStatsPktsRx128Octetsto255Octets); 6485157642Sps 6486157642Sps if (sblk->stat_EtherStatsPktsRx256Octetsto511Octets) 6487157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx256Octetsto511Octets\n", 6488157642Sps sblk->stat_EtherStatsPktsRx256Octetsto511Octets); 6489157642Sps 6490157642Sps if (sblk->stat_EtherStatsPktsRx512Octetsto1023Octets) 6491157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx512Octetsto1023Octets\n", 6492157642Sps sblk->stat_EtherStatsPktsRx512Octetsto1023Octets); 6493157642Sps 6494157642Sps if (sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets) 6495157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx1024Octetsto1522Octets\n", 6496157642Sps sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets); 6497157642Sps 6498157642Sps if (sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets) 6499157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx1523Octetsto9022Octets\n", 6500157642Sps sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets); 6501157642Sps 6502157642Sps if (sblk->stat_EtherStatsPktsTx64Octets) 6503157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx64Octets\n", 6504157642Sps sblk->stat_EtherStatsPktsTx64Octets); 6505157642Sps 6506157642Sps if (sblk->stat_EtherStatsPktsTx65Octetsto127Octets) 6507157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx65Octetsto127Octets\n", 6508157642Sps sblk->stat_EtherStatsPktsTx65Octetsto127Octets); 6509157642Sps 6510157642Sps if (sblk->stat_EtherStatsPktsTx128Octetsto255Octets) 6511157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx128Octetsto255Octets\n", 6512157642Sps sblk->stat_EtherStatsPktsTx128Octetsto255Octets); 6513157642Sps 6514157642Sps if (sblk->stat_EtherStatsPktsTx256Octetsto511Octets) 6515157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx256Octetsto511Octets\n", 6516157642Sps sblk->stat_EtherStatsPktsTx256Octetsto511Octets); 6517157642Sps 6518157642Sps if (sblk->stat_EtherStatsPktsTx512Octetsto1023Octets) 6519157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx512Octetsto1023Octets\n", 6520157642Sps sblk->stat_EtherStatsPktsTx512Octetsto1023Octets); 6521157642Sps 6522157642Sps if (sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets) 6523157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx1024Octetsto1522Octets\n", 6524157642Sps sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets); 6525157642Sps 6526157642Sps if (sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets) 6527157642Sps BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx1523Octetsto9022Octets\n", 6528157642Sps sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets); 6529157642Sps 6530157642Sps if (sblk->stat_XonPauseFramesReceived) 6531157642Sps BCE_PRINTF(sc, "0x%08X : XonPauseFramesReceived\n", 6532157642Sps sblk->stat_XonPauseFramesReceived); 6533157642Sps 6534157642Sps if (sblk->stat_XoffPauseFramesReceived) 6535157642Sps BCE_PRINTF(sc, "0x%08X : XoffPauseFramesReceived\n", 6536157642Sps sblk->stat_XoffPauseFramesReceived); 6537157642Sps 6538157642Sps if (sblk->stat_OutXonSent) 6539157642Sps BCE_PRINTF(sc, "0x%08X : OutXonSent\n", 6540157642Sps sblk->stat_OutXonSent); 6541157642Sps 6542157642Sps if (sblk->stat_OutXoffSent) 6543157642Sps BCE_PRINTF(sc, "0x%08X : OutXoffSent\n", 6544157642Sps sblk->stat_OutXoffSent); 6545157642Sps 6546157642Sps if (sblk->stat_FlowControlDone) 6547157642Sps BCE_PRINTF(sc, "0x%08X : FlowControlDone\n", 6548157642Sps sblk->stat_FlowControlDone); 6549157642Sps 6550157642Sps if (sblk->stat_MacControlFramesReceived) 6551157642Sps BCE_PRINTF(sc, "0x%08X : MacControlFramesReceived\n", 6552157642Sps sblk->stat_MacControlFramesReceived); 6553157642Sps 6554157642Sps if (sblk->stat_XoffStateEntered) 6555157642Sps BCE_PRINTF(sc, "0x%08X : XoffStateEntered\n", 6556157642Sps sblk->stat_XoffStateEntered); 6557157642Sps 6558157642Sps if (sblk->stat_IfInFramesL2FilterDiscards) 6559157642Sps BCE_PRINTF(sc, "0x%08X : IfInFramesL2FilterDiscards\n", 6560157642Sps sblk->stat_IfInFramesL2FilterDiscards); 6561157642Sps 6562157642Sps if (sblk->stat_IfInRuleCheckerDiscards) 6563157642Sps BCE_PRINTF(sc, "0x%08X : IfInRuleCheckerDiscards\n", 6564157642Sps sblk->stat_IfInRuleCheckerDiscards); 6565157642Sps 6566157642Sps if (sblk->stat_IfInFTQDiscards) 6567157642Sps BCE_PRINTF(sc, "0x%08X : IfInFTQDiscards\n", 6568157642Sps sblk->stat_IfInFTQDiscards); 6569157642Sps 6570157642Sps if (sblk->stat_IfInMBUFDiscards) 6571157642Sps BCE_PRINTF(sc, "0x%08X : IfInMBUFDiscards\n", 6572157642Sps sblk->stat_IfInMBUFDiscards); 6573157642Sps 6574157642Sps if (sblk->stat_IfInRuleCheckerP4Hit) 6575157642Sps BCE_PRINTF(sc, "0x%08X : IfInRuleCheckerP4Hit\n", 6576157642Sps sblk->stat_IfInRuleCheckerP4Hit); 6577157642Sps 6578157642Sps if (sblk->stat_CatchupInRuleCheckerDiscards) 6579157642Sps BCE_PRINTF(sc, "0x%08X : CatchupInRuleCheckerDiscards\n", 6580157642Sps sblk->stat_CatchupInRuleCheckerDiscards); 6581157642Sps 6582157642Sps if (sblk->stat_CatchupInFTQDiscards) 6583157642Sps BCE_PRINTF(sc, "0x%08X : CatchupInFTQDiscards\n", 6584157642Sps sblk->stat_CatchupInFTQDiscards); 6585157642Sps 6586157642Sps if (sblk->stat_CatchupInMBUFDiscards) 6587157642Sps BCE_PRINTF(sc, "0x%08X : CatchupInMBUFDiscards\n", 6588157642Sps sblk->stat_CatchupInMBUFDiscards); 6589157642Sps 6590157642Sps if (sblk->stat_CatchupInRuleCheckerP4Hit) 6591157642Sps BCE_PRINTF(sc, "0x%08X : CatchupInRuleCheckerP4Hit\n", 6592157642Sps sblk->stat_CatchupInRuleCheckerP4Hit); 6593157642Sps 6594157642Sps BCE_PRINTF(sc, 6595157642Sps "-----------------------------" 6596157642Sps "--------------" 6597157642Sps "-----------------------------\n"); 6598157642Sps} 6599157642Sps 6600157642Sps 6601157642Spsstatic void 6602157642Spsbce_dump_driver_state(struct bce_softc *sc) 6603157642Sps{ 6604157642Sps u32 val_hi, val_lo; 6605157642Sps 6606157642Sps BCE_PRINTF(sc, 6607157642Sps "-----------------------------" 6608157642Sps " Driver State " 6609157642Sps "-----------------------------\n"); 6610157642Sps 6611157642Sps val_hi = BCE_ADDR_HI(sc); 6612157642Sps val_lo = BCE_ADDR_LO(sc); 6613157642Sps BCE_PRINTF(sc, "0x%08X:%08X - (sc) driver softc structure virtual address\n", 6614157642Sps val_hi, val_lo); 6615157642Sps 6616157642Sps val_hi = BCE_ADDR_HI(sc->bce_vhandle); 6617157642Sps val_lo = BCE_ADDR_LO(sc->bce_vhandle); 6618157642Sps BCE_PRINTF(sc, "0x%08X:%08X - (sc->bce_vhandle) PCI BAR virtual address\n", 6619157642Sps val_hi, val_lo); 6620157642Sps 6621157642Sps val_hi = BCE_ADDR_HI(sc->status_block); 6622157642Sps val_lo = BCE_ADDR_LO(sc->status_block); 6623157642Sps BCE_PRINTF(sc, "0x%08X:%08X - (sc->status_block) status block virtual address\n", 6624157642Sps val_hi, val_lo); 6625157642Sps 6626157642Sps val_hi = BCE_ADDR_HI(sc->stats_block); 6627157642Sps val_lo = BCE_ADDR_LO(sc->stats_block); 6628157642Sps BCE_PRINTF(sc, "0x%08X:%08X - (sc->stats_block) statistics block virtual address\n", 6629157642Sps val_hi, val_lo); 6630157642Sps 6631157642Sps val_hi = BCE_ADDR_HI(sc->tx_bd_chain); 6632157642Sps val_lo = BCE_ADDR_LO(sc->tx_bd_chain); 6633157642Sps BCE_PRINTF(sc, 6634157642Sps "0x%08X:%08X - (sc->tx_bd_chain) tx_bd chain virtual adddress\n", 6635157642Sps val_hi, val_lo); 6636157642Sps 6637157642Sps val_hi = BCE_ADDR_HI(sc->rx_bd_chain); 6638157642Sps val_lo = BCE_ADDR_LO(sc->rx_bd_chain); 6639157642Sps BCE_PRINTF(sc, 6640157642Sps "0x%08X:%08X - (sc->rx_bd_chain) rx_bd chain virtual address\n", 6641157642Sps val_hi, val_lo); 6642157642Sps 6643157642Sps val_hi = BCE_ADDR_HI(sc->tx_mbuf_ptr); 6644157642Sps val_lo = BCE_ADDR_LO(sc->tx_mbuf_ptr); 6645157642Sps BCE_PRINTF(sc, 6646157642Sps "0x%08X:%08X - (sc->tx_mbuf_ptr) tx mbuf chain virtual address\n", 6647157642Sps val_hi, val_lo); 6648157642Sps 6649157642Sps val_hi = BCE_ADDR_HI(sc->rx_mbuf_ptr); 6650157642Sps val_lo = BCE_ADDR_LO(sc->rx_mbuf_ptr); 6651157642Sps BCE_PRINTF(sc, 6652157642Sps "0x%08X:%08X - (sc->rx_mbuf_ptr) rx mbuf chain virtual address\n", 6653157642Sps val_hi, val_lo); 6654157642Sps 6655157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->interrupts_generated) h/w intrs\n", 6656157642Sps sc->interrupts_generated); 6657157642Sps 6658157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->rx_interrupts) rx interrupts handled\n", 6659157642Sps sc->rx_interrupts); 6660157642Sps 6661157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->tx_interrupts) tx interrupts handled\n", 6662157642Sps sc->tx_interrupts); 6663157642Sps 6664157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->last_status_idx) status block index\n", 6665157642Sps sc->last_status_idx); 6666157642Sps 6667157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->tx_prod) tx producer index\n", 6668157642Sps sc->tx_prod); 6669157642Sps 6670157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->tx_cons) tx consumer index\n", 6671157642Sps sc->tx_cons); 6672157642Sps 6673157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->tx_prod_bseq) tx producer bseq index\n", 6674157642Sps sc->tx_prod_bseq); 6675157642Sps 6676157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->rx_prod) rx producer index\n", 6677157642Sps sc->rx_prod); 6678157642Sps 6679157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->rx_cons) rx consumer index\n", 6680157642Sps sc->rx_cons); 6681157642Sps 6682157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->rx_prod_bseq) rx producer bseq index\n", 6683157642Sps sc->rx_prod_bseq); 6684157642Sps 6685157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->rx_mbuf_alloc) rx mbufs allocated\n", 6686157642Sps sc->rx_mbuf_alloc); 6687157642Sps 6688157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->free_rx_bd) free rx_bd's\n", 6689157642Sps sc->free_rx_bd); 6690157642Sps 6691157642Sps BCE_PRINTF(sc, "0x%08X/%08X - (sc->rx_low_watermark) rx low watermark\n", 6692157642Sps sc->rx_low_watermark, (u32) USABLE_RX_BD); 6693157642Sps 6694157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->txmbuf_alloc) tx mbufs allocated\n", 6695157642Sps sc->tx_mbuf_alloc); 6696157642Sps 6697157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->rx_mbuf_alloc) rx mbufs allocated\n", 6698157642Sps sc->rx_mbuf_alloc); 6699157642Sps 6700157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->used_tx_bd) used tx_bd's\n", 6701157642Sps sc->used_tx_bd); 6702157642Sps 6703157642Sps BCE_PRINTF(sc, "0x%08X/%08X - (sc->tx_hi_watermark) tx hi watermark\n", 6704157642Sps sc->tx_hi_watermark, (u32) USABLE_TX_BD); 6705157642Sps 6706157642Sps BCE_PRINTF(sc, " 0x%08X - (sc->mbuf_alloc_failed) failed mbuf alloc\n", 6707157642Sps sc->mbuf_alloc_failed); 6708157642Sps 6709157642Sps BCE_PRINTF(sc, 6710157642Sps "-----------------------------" 6711157642Sps "--------------" 6712157642Sps "-----------------------------\n"); 6713157642Sps} 6714157642Sps 6715157642Sps 6716157642Spsstatic void 6717157642Spsbce_dump_hw_state(struct bce_softc *sc) 6718157642Sps{ 6719157642Sps u32 val1; 6720157642Sps 6721157642Sps BCE_PRINTF(sc, 6722157642Sps "----------------------------" 6723157642Sps " Hardware State " 6724157642Sps "----------------------------\n"); 6725157642Sps 6726157642Sps BCE_PRINTF(sc, "0x%08X : bootcode version\n", sc->bce_fw_ver); 6727157642Sps 6728157642Sps val1 = REG_RD(sc, BCE_MISC_ENABLE_STATUS_BITS); 6729157642Sps BCE_PRINTF(sc, "0x%08X : (0x%04X) misc_enable_status_bits\n", 6730157642Sps val1, BCE_MISC_ENABLE_STATUS_BITS); 6731157642Sps 6732157642Sps val1 = REG_RD(sc, BCE_DMA_STATUS); 6733157642Sps BCE_PRINTF(sc, "0x%08X : (0x%04X) dma_status\n", val1, BCE_DMA_STATUS); 6734157642Sps 6735157642Sps val1 = REG_RD(sc, BCE_CTX_STATUS); 6736157642Sps BCE_PRINTF(sc, "0x%08X : (0x%04X) ctx_status\n", val1, BCE_CTX_STATUS); 6737157642Sps 6738157642Sps val1 = REG_RD(sc, BCE_EMAC_STATUS); 6739157642Sps BCE_PRINTF(sc, "0x%08X : (0x%04X) emac_status\n", val1, BCE_EMAC_STATUS); 6740157642Sps 6741157642Sps val1 = REG_RD(sc, BCE_RPM_STATUS); 6742157642Sps BCE_PRINTF(sc, "0x%08X : (0x%04X) rpm_status\n", val1, BCE_RPM_STATUS); 6743157642Sps 6744157642Sps val1 = REG_RD(sc, BCE_TBDR_STATUS); 6745157642Sps BCE_PRINTF(sc, "0x%08X : (0x%04X) tbdr_status\n", val1, BCE_TBDR_STATUS); 6746157642Sps 6747157642Sps val1 = REG_RD(sc, BCE_TDMA_STATUS); 6748157642Sps BCE_PRINTF(sc, "0x%08X : (0x%04X) tdma_status\n", val1, BCE_TDMA_STATUS); 6749157642Sps 6750157642Sps val1 = REG_RD(sc, BCE_HC_STATUS); 6751157642Sps BCE_PRINTF(sc, "0x%08X : (0x%04X) hc_status\n", val1, BCE_HC_STATUS); 6752157642Sps 6753157642Sps BCE_PRINTF(sc, 6754157642Sps "----------------------------" 6755157642Sps "----------------" 6756157642Sps "----------------------------\n"); 6757157642Sps 6758157642Sps BCE_PRINTF(sc, 6759157642Sps "----------------------------" 6760157642Sps " Register Dump " 6761157642Sps "----------------------------\n"); 6762157642Sps 6763157642Sps for (int i = 0x400; i < 0x8000; i += 0x10) 6764157642Sps BCE_PRINTF(sc, "0x%04X: 0x%08X 0x%08X 0x%08X 0x%08X\n", 6765157642Sps i, REG_RD(sc, i), REG_RD(sc, i + 0x4), 6766157642Sps REG_RD(sc, i + 0x8), REG_RD(sc, i + 0xC)); 6767157642Sps 6768157642Sps BCE_PRINTF(sc, 6769157642Sps "----------------------------" 6770157642Sps "----------------" 6771157642Sps "----------------------------\n"); 6772157642Sps} 6773157642Sps 6774157642Sps 6775157642Spsstatic void 6776157642Spsbce_breakpoint(struct bce_softc *sc) 6777157642Sps{ 6778157642Sps 6779157642Sps /* Unreachable code to shut the compiler up about unused functions. */ 6780157642Sps if (0) { 6781157642Sps bce_dump_txbd(sc, 0, NULL); 6782157642Sps bce_dump_rxbd(sc, 0, NULL); 6783157642Sps bce_dump_tx_mbuf_chain(sc, 0, USABLE_TX_BD); 6784157642Sps bce_dump_rx_mbuf_chain(sc, 0, USABLE_RX_BD); 6785157642Sps bce_dump_l2fhdr(sc, 0, NULL); 6786157642Sps bce_dump_tx_chain(sc, 0, USABLE_TX_BD); 6787157642Sps bce_dump_rx_chain(sc, 0, USABLE_RX_BD); 6788157642Sps bce_dump_status_block(sc); 6789157642Sps bce_dump_stats_block(sc); 6790157642Sps bce_dump_driver_state(sc); 6791157642Sps bce_dump_hw_state(sc); 6792157642Sps } 6793157642Sps 6794157642Sps bce_dump_driver_state(sc); 6795157642Sps /* Print the important status block fields. */ 6796157642Sps bce_dump_status_block(sc); 6797157642Sps 6798157642Sps /* Call the debugger. */ 6799157642Sps breakpoint(); 6800157642Sps 6801157642Sps return; 6802157642Sps} 6803157642Sps#endif 6804