16c8d8eccSSepherosa Ziehau /* 26c8d8eccSSepherosa Ziehau * Copyright (c) 2001 Wind River Systems 36c8d8eccSSepherosa Ziehau * Copyright (c) 1997, 1998, 1999, 2001 46c8d8eccSSepherosa Ziehau * Bill Paul <wpaul@windriver.com>. All rights reserved. 56c8d8eccSSepherosa Ziehau * 66c8d8eccSSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 76c8d8eccSSepherosa Ziehau * modification, are permitted provided that the following conditions 86c8d8eccSSepherosa Ziehau * are met: 96c8d8eccSSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 106c8d8eccSSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 116c8d8eccSSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 126c8d8eccSSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the 136c8d8eccSSepherosa Ziehau * documentation and/or other materials provided with the distribution. 146c8d8eccSSepherosa Ziehau * 3. All advertising materials mentioning features or use of this software 156c8d8eccSSepherosa Ziehau * must display the following acknowledgement: 166c8d8eccSSepherosa Ziehau * This product includes software developed by Bill Paul. 176c8d8eccSSepherosa Ziehau * 4. Neither the name of the author nor the names of any co-contributors 186c8d8eccSSepherosa Ziehau * may be used to endorse or promote products derived from this software 196c8d8eccSSepherosa Ziehau * without specific prior written permission. 206c8d8eccSSepherosa Ziehau * 216c8d8eccSSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 226c8d8eccSSepherosa Ziehau * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 236c8d8eccSSepherosa Ziehau * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 246c8d8eccSSepherosa Ziehau * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 256c8d8eccSSepherosa Ziehau * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 266c8d8eccSSepherosa Ziehau * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 276c8d8eccSSepherosa Ziehau * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 286c8d8eccSSepherosa Ziehau * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 296c8d8eccSSepherosa Ziehau * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 306c8d8eccSSepherosa Ziehau * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 316c8d8eccSSepherosa Ziehau * THE POSSIBILITY OF SUCH DAMAGE. 326c8d8eccSSepherosa Ziehau * 336c8d8eccSSepherosa Ziehau * $FreeBSD: src/sys/dev/bge/if_bge.c,v 1.3.2.39 2005/07/03 03:41:18 silby Exp $ 346c8d8eccSSepherosa Ziehau */ 356c8d8eccSSepherosa Ziehau 366c8d8eccSSepherosa Ziehau 376c8d8eccSSepherosa Ziehau #include "opt_polling.h" 386c8d8eccSSepherosa Ziehau 396c8d8eccSSepherosa Ziehau #include <sys/param.h> 406c8d8eccSSepherosa Ziehau #include <sys/bus.h> 416c8d8eccSSepherosa Ziehau #include <sys/endian.h> 426c8d8eccSSepherosa Ziehau #include <sys/kernel.h> 436c8d8eccSSepherosa Ziehau #include <sys/interrupt.h> 446c8d8eccSSepherosa Ziehau #include <sys/mbuf.h> 456c8d8eccSSepherosa Ziehau #include <sys/malloc.h> 466c8d8eccSSepherosa Ziehau #include <sys/queue.h> 476c8d8eccSSepherosa Ziehau #include <sys/rman.h> 486c8d8eccSSepherosa Ziehau #include <sys/serialize.h> 496c8d8eccSSepherosa Ziehau #include <sys/socket.h> 506c8d8eccSSepherosa Ziehau #include <sys/sockio.h> 516c8d8eccSSepherosa Ziehau #include <sys/sysctl.h> 526c8d8eccSSepherosa Ziehau 536c8d8eccSSepherosa Ziehau #include <net/bpf.h> 546c8d8eccSSepherosa Ziehau #include <net/ethernet.h> 556c8d8eccSSepherosa Ziehau #include <net/if.h> 566c8d8eccSSepherosa Ziehau #include <net/if_arp.h> 576c8d8eccSSepherosa Ziehau #include <net/if_dl.h> 586c8d8eccSSepherosa Ziehau #include <net/if_media.h> 596c8d8eccSSepherosa Ziehau #include <net/if_types.h> 606c8d8eccSSepherosa Ziehau #include <net/ifq_var.h> 616c8d8eccSSepherosa Ziehau #include <net/vlan/if_vlan_var.h> 626c8d8eccSSepherosa Ziehau #include <net/vlan/if_vlan_ether.h> 636c8d8eccSSepherosa Ziehau 646c8d8eccSSepherosa Ziehau #include <dev/netif/mii_layer/mii.h> 656c8d8eccSSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h> 666c8d8eccSSepherosa Ziehau #include <dev/netif/mii_layer/brgphyreg.h> 676c8d8eccSSepherosa Ziehau 686c8d8eccSSepherosa Ziehau #include <bus/pci/pcidevs.h> 696c8d8eccSSepherosa Ziehau #include <bus/pci/pcireg.h> 706c8d8eccSSepherosa Ziehau #include <bus/pci/pcivar.h> 716c8d8eccSSepherosa Ziehau 726c8d8eccSSepherosa Ziehau #include <dev/netif/bge/if_bgereg.h> 736c8d8eccSSepherosa Ziehau #include <dev/netif/bnx/if_bnxvar.h> 746c8d8eccSSepherosa Ziehau 756c8d8eccSSepherosa Ziehau /* "device miibus" required. See GENERIC if you get errors here. */ 766c8d8eccSSepherosa Ziehau #include "miibus_if.h" 776c8d8eccSSepherosa Ziehau 783b18363fSSepherosa Ziehau #define BNX_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 796c8d8eccSSepherosa Ziehau 80*df9ccc98SSepherosa Ziehau #define BNX_INTR_CKINTVL ((10 * hz) / 1000) /* 10ms */ 81*df9ccc98SSepherosa Ziehau 826c8d8eccSSepherosa Ziehau static const struct bnx_type { 836c8d8eccSSepherosa Ziehau uint16_t bnx_vid; 846c8d8eccSSepherosa Ziehau uint16_t bnx_did; 856c8d8eccSSepherosa Ziehau char *bnx_name; 866c8d8eccSSepherosa Ziehau } bnx_devs[] = { 876c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5717, 886c8d8eccSSepherosa Ziehau "Broadcom BCM5717 Gigabit Ethernet" }, 896c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5718, 906c8d8eccSSepherosa Ziehau "Broadcom BCM5718 Gigabit Ethernet" }, 916c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5719, 926c8d8eccSSepherosa Ziehau "Broadcom BCM5719 Gigabit Ethernet" }, 936c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5720_ALT, 946c8d8eccSSepherosa Ziehau "Broadcom BCM5720 Gigabit Ethernet" }, 956c8d8eccSSepherosa Ziehau 966c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57761, 976c8d8eccSSepherosa Ziehau "Broadcom BCM57761 Gigabit Ethernet" }, 9832ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57762, 9932ff3c80SSepherosa Ziehau "Broadcom BCM57762 Gigabit Ethernet" }, 1006c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57765, 1016c8d8eccSSepherosa Ziehau "Broadcom BCM57765 Gigabit Ethernet" }, 10232ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57766, 10332ff3c80SSepherosa Ziehau "Broadcom BCM57766 Gigabit Ethernet" }, 10432ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57781, 10532ff3c80SSepherosa Ziehau "Broadcom BCM57781 Gigabit Ethernet" }, 10632ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57782, 10732ff3c80SSepherosa Ziehau "Broadcom BCM57782 Gigabit Ethernet" }, 1086c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57785, 1096c8d8eccSSepherosa Ziehau "Broadcom BCM57785 Gigabit Ethernet" }, 11032ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57786, 11132ff3c80SSepherosa Ziehau "Broadcom BCM57786 Gigabit Ethernet" }, 11232ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57791, 11332ff3c80SSepherosa Ziehau "Broadcom BCM57791 Fast Ethernet" }, 1146c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57795, 1156c8d8eccSSepherosa Ziehau "Broadcom BCM57795 Fast Ethernet" }, 1166c8d8eccSSepherosa Ziehau 1176c8d8eccSSepherosa Ziehau { 0, 0, NULL } 1186c8d8eccSSepherosa Ziehau }; 1196c8d8eccSSepherosa Ziehau 1206c8d8eccSSepherosa Ziehau #define BNX_IS_JUMBO_CAPABLE(sc) ((sc)->bnx_flags & BNX_FLAG_JUMBO) 1216c8d8eccSSepherosa Ziehau #define BNX_IS_5717_PLUS(sc) ((sc)->bnx_flags & BNX_FLAG_5717_PLUS) 122f368d0d9SSepherosa Ziehau #define BNX_IS_57765_PLUS(sc) ((sc)->bnx_flags & BNX_FLAG_57765_PLUS) 123f368d0d9SSepherosa Ziehau #define BNX_IS_57765_FAMILY(sc) \ 124f368d0d9SSepherosa Ziehau ((sc)->bnx_flags & BNX_FLAG_57765_FAMILY) 1256c8d8eccSSepherosa Ziehau 1266c8d8eccSSepherosa Ziehau typedef int (*bnx_eaddr_fcn_t)(struct bnx_softc *, uint8_t[]); 1276c8d8eccSSepherosa Ziehau 1286c8d8eccSSepherosa Ziehau static int bnx_probe(device_t); 1296c8d8eccSSepherosa Ziehau static int bnx_attach(device_t); 1306c8d8eccSSepherosa Ziehau static int bnx_detach(device_t); 1316c8d8eccSSepherosa Ziehau static void bnx_shutdown(device_t); 1326c8d8eccSSepherosa Ziehau static int bnx_suspend(device_t); 1336c8d8eccSSepherosa Ziehau static int bnx_resume(device_t); 1346c8d8eccSSepherosa Ziehau static int bnx_miibus_readreg(device_t, int, int); 1356c8d8eccSSepherosa Ziehau static int bnx_miibus_writereg(device_t, int, int, int); 1366c8d8eccSSepherosa Ziehau static void bnx_miibus_statchg(device_t); 1376c8d8eccSSepherosa Ziehau 1386c8d8eccSSepherosa Ziehau #ifdef DEVICE_POLLING 1396c8d8eccSSepherosa Ziehau static void bnx_poll(struct ifnet *ifp, enum poll_cmd cmd, int count); 1406c8d8eccSSepherosa Ziehau #endif 1416c8d8eccSSepherosa Ziehau static void bnx_intr_legacy(void *); 1426c8d8eccSSepherosa Ziehau static void bnx_msi(void *); 1436c8d8eccSSepherosa Ziehau static void bnx_msi_oneshot(void *); 1446c8d8eccSSepherosa Ziehau static void bnx_intr(struct bnx_softc *); 1456c8d8eccSSepherosa Ziehau static void bnx_enable_intr(struct bnx_softc *); 1466c8d8eccSSepherosa Ziehau static void bnx_disable_intr(struct bnx_softc *); 1476c8d8eccSSepherosa Ziehau static void bnx_txeof(struct bnx_softc *, uint16_t); 1486c8d8eccSSepherosa Ziehau static void bnx_rxeof(struct bnx_softc *, uint16_t); 1496c8d8eccSSepherosa Ziehau 1506c8d8eccSSepherosa Ziehau static void bnx_start(struct ifnet *); 1516c8d8eccSSepherosa Ziehau static int bnx_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 1526c8d8eccSSepherosa Ziehau static void bnx_init(void *); 1536c8d8eccSSepherosa Ziehau static void bnx_stop(struct bnx_softc *); 1546c8d8eccSSepherosa Ziehau static void bnx_watchdog(struct ifnet *); 1556c8d8eccSSepherosa Ziehau static int bnx_ifmedia_upd(struct ifnet *); 1566c8d8eccSSepherosa Ziehau static void bnx_ifmedia_sts(struct ifnet *, struct ifmediareq *); 1576c8d8eccSSepherosa Ziehau static void bnx_tick(void *); 1586c8d8eccSSepherosa Ziehau 1596c8d8eccSSepherosa Ziehau static int bnx_alloc_jumbo_mem(struct bnx_softc *); 1606c8d8eccSSepherosa Ziehau static void bnx_free_jumbo_mem(struct bnx_softc *); 1616c8d8eccSSepherosa Ziehau static struct bnx_jslot 1626c8d8eccSSepherosa Ziehau *bnx_jalloc(struct bnx_softc *); 1636c8d8eccSSepherosa Ziehau static void bnx_jfree(void *); 1646c8d8eccSSepherosa Ziehau static void bnx_jref(void *); 1656c8d8eccSSepherosa Ziehau static int bnx_newbuf_std(struct bnx_softc *, int, int); 1666c8d8eccSSepherosa Ziehau static int bnx_newbuf_jumbo(struct bnx_softc *, int, int); 1676c8d8eccSSepherosa Ziehau static void bnx_setup_rxdesc_std(struct bnx_softc *, int); 1686c8d8eccSSepherosa Ziehau static void bnx_setup_rxdesc_jumbo(struct bnx_softc *, int); 1696c8d8eccSSepherosa Ziehau static int bnx_init_rx_ring_std(struct bnx_softc *); 1706c8d8eccSSepherosa Ziehau static void bnx_free_rx_ring_std(struct bnx_softc *); 1716c8d8eccSSepherosa Ziehau static int bnx_init_rx_ring_jumbo(struct bnx_softc *); 1726c8d8eccSSepherosa Ziehau static void bnx_free_rx_ring_jumbo(struct bnx_softc *); 1736c8d8eccSSepherosa Ziehau static void bnx_free_tx_ring(struct bnx_softc *); 1746c8d8eccSSepherosa Ziehau static int bnx_init_tx_ring(struct bnx_softc *); 1756c8d8eccSSepherosa Ziehau static int bnx_dma_alloc(struct bnx_softc *); 1766c8d8eccSSepherosa Ziehau static void bnx_dma_free(struct bnx_softc *); 1776c8d8eccSSepherosa Ziehau static int bnx_dma_block_alloc(struct bnx_softc *, bus_size_t, 1786c8d8eccSSepherosa Ziehau bus_dma_tag_t *, bus_dmamap_t *, void **, bus_addr_t *); 1796c8d8eccSSepherosa Ziehau static void bnx_dma_block_free(bus_dma_tag_t, bus_dmamap_t, void *); 1806c8d8eccSSepherosa Ziehau static struct mbuf * 1816c8d8eccSSepherosa Ziehau bnx_defrag_shortdma(struct mbuf *); 1826c8d8eccSSepherosa Ziehau static int bnx_encap(struct bnx_softc *, struct mbuf **, uint32_t *); 1836c8d8eccSSepherosa Ziehau 1846c8d8eccSSepherosa Ziehau static void bnx_reset(struct bnx_softc *); 1856c8d8eccSSepherosa Ziehau static int bnx_chipinit(struct bnx_softc *); 1866c8d8eccSSepherosa Ziehau static int bnx_blockinit(struct bnx_softc *); 1876c8d8eccSSepherosa Ziehau static void bnx_stop_block(struct bnx_softc *, bus_size_t, uint32_t); 1886c8d8eccSSepherosa Ziehau static void bnx_enable_msi(struct bnx_softc *sc); 1896c8d8eccSSepherosa Ziehau static void bnx_setmulti(struct bnx_softc *); 1906c8d8eccSSepherosa Ziehau static void bnx_setpromisc(struct bnx_softc *); 1916c8d8eccSSepherosa Ziehau static void bnx_stats_update_regs(struct bnx_softc *); 1926c8d8eccSSepherosa Ziehau static uint32_t bnx_dma_swap_options(struct bnx_softc *); 1936c8d8eccSSepherosa Ziehau 1946c8d8eccSSepherosa Ziehau static uint32_t bnx_readmem_ind(struct bnx_softc *, uint32_t); 1956c8d8eccSSepherosa Ziehau static void bnx_writemem_ind(struct bnx_softc *, uint32_t, uint32_t); 1966c8d8eccSSepherosa Ziehau #ifdef notdef 1976c8d8eccSSepherosa Ziehau static uint32_t bnx_readreg_ind(struct bnx_softc *, uint32_t); 1986c8d8eccSSepherosa Ziehau #endif 1996c8d8eccSSepherosa Ziehau static void bnx_writereg_ind(struct bnx_softc *, uint32_t, uint32_t); 2006c8d8eccSSepherosa Ziehau static void bnx_writemem_direct(struct bnx_softc *, uint32_t, uint32_t); 2016c8d8eccSSepherosa Ziehau static void bnx_writembx(struct bnx_softc *, int, int); 2026c8d8eccSSepherosa Ziehau static uint8_t bnx_nvram_getbyte(struct bnx_softc *, int, uint8_t *); 2036c8d8eccSSepherosa Ziehau static int bnx_read_nvram(struct bnx_softc *, caddr_t, int, int); 2046c8d8eccSSepherosa Ziehau static uint8_t bnx_eeprom_getbyte(struct bnx_softc *, uint32_t, uint8_t *); 2056c8d8eccSSepherosa Ziehau static int bnx_read_eeprom(struct bnx_softc *, caddr_t, uint32_t, size_t); 2066c8d8eccSSepherosa Ziehau 2076c8d8eccSSepherosa Ziehau static void bnx_tbi_link_upd(struct bnx_softc *, uint32_t); 2086c8d8eccSSepherosa Ziehau static void bnx_copper_link_upd(struct bnx_softc *, uint32_t); 2096c8d8eccSSepherosa Ziehau static void bnx_autopoll_link_upd(struct bnx_softc *, uint32_t); 2106c8d8eccSSepherosa Ziehau static void bnx_link_poll(struct bnx_softc *); 2116c8d8eccSSepherosa Ziehau 2126c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_mem(struct bnx_softc *, uint8_t[]); 2136c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_nvram(struct bnx_softc *, uint8_t[]); 2146c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_eeprom(struct bnx_softc *, uint8_t[]); 2156c8d8eccSSepherosa Ziehau static int bnx_get_eaddr(struct bnx_softc *, uint8_t[]); 2166c8d8eccSSepherosa Ziehau 2176c8d8eccSSepherosa Ziehau static void bnx_coal_change(struct bnx_softc *); 2186c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_ticks(SYSCTL_HANDLER_ARGS); 2196c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_ticks(SYSCTL_HANDLER_ARGS); 2206c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_bds(SYSCTL_HANDLER_ARGS); 2216c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_bds(SYSCTL_HANDLER_ARGS); 2226c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_bds_int(SYSCTL_HANDLER_ARGS); 2236c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_bds_int(SYSCTL_HANDLER_ARGS); 2246c8d8eccSSepherosa Ziehau static int bnx_sysctl_coal_chg(SYSCTL_HANDLER_ARGS, uint32_t *, 2256c8d8eccSSepherosa Ziehau int, int, uint32_t); 2266c8d8eccSSepherosa Ziehau 2276c8d8eccSSepherosa Ziehau static int bnx_msi_enable = 1; 2286c8d8eccSSepherosa Ziehau TUNABLE_INT("hw.bnx.msi.enable", &bnx_msi_enable); 2296c8d8eccSSepherosa Ziehau 2306c8d8eccSSepherosa Ziehau static device_method_t bnx_methods[] = { 2316c8d8eccSSepherosa Ziehau /* Device interface */ 2326c8d8eccSSepherosa Ziehau DEVMETHOD(device_probe, bnx_probe), 2336c8d8eccSSepherosa Ziehau DEVMETHOD(device_attach, bnx_attach), 2346c8d8eccSSepherosa Ziehau DEVMETHOD(device_detach, bnx_detach), 2356c8d8eccSSepherosa Ziehau DEVMETHOD(device_shutdown, bnx_shutdown), 2366c8d8eccSSepherosa Ziehau DEVMETHOD(device_suspend, bnx_suspend), 2376c8d8eccSSepherosa Ziehau DEVMETHOD(device_resume, bnx_resume), 2386c8d8eccSSepherosa Ziehau 2396c8d8eccSSepherosa Ziehau /* bus interface */ 2406c8d8eccSSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 2416c8d8eccSSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 2426c8d8eccSSepherosa Ziehau 2436c8d8eccSSepherosa Ziehau /* MII interface */ 2446c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_readreg, bnx_miibus_readreg), 2456c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_writereg, bnx_miibus_writereg), 2466c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_statchg, bnx_miibus_statchg), 2476c8d8eccSSepherosa Ziehau 2486c8d8eccSSepherosa Ziehau { 0, 0 } 2496c8d8eccSSepherosa Ziehau }; 2506c8d8eccSSepherosa Ziehau 2516c8d8eccSSepherosa Ziehau static DEFINE_CLASS_0(bnx, bnx_driver, bnx_methods, sizeof(struct bnx_softc)); 2526c8d8eccSSepherosa Ziehau static devclass_t bnx_devclass; 2536c8d8eccSSepherosa Ziehau 2546c8d8eccSSepherosa Ziehau DECLARE_DUMMY_MODULE(if_bnx); 2556c8d8eccSSepherosa Ziehau DRIVER_MODULE(if_bnx, pci, bnx_driver, bnx_devclass, NULL, NULL); 2566c8d8eccSSepherosa Ziehau DRIVER_MODULE(miibus, bnx, miibus_driver, miibus_devclass, NULL, NULL); 2576c8d8eccSSepherosa Ziehau 2586c8d8eccSSepherosa Ziehau static uint32_t 2596c8d8eccSSepherosa Ziehau bnx_readmem_ind(struct bnx_softc *sc, uint32_t off) 2606c8d8eccSSepherosa Ziehau { 2616c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 2626c8d8eccSSepherosa Ziehau uint32_t val; 2636c8d8eccSSepherosa Ziehau 2646c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5906 && 2656c8d8eccSSepherosa Ziehau off >= BGE_STATS_BLOCK && off < BGE_SEND_RING_1_TO_4) 2666c8d8eccSSepherosa Ziehau return 0; 2676c8d8eccSSepherosa Ziehau 2686c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); 2696c8d8eccSSepherosa Ziehau val = pci_read_config(dev, BGE_PCI_MEMWIN_DATA, 4); 2706c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); 2716c8d8eccSSepherosa Ziehau return (val); 2726c8d8eccSSepherosa Ziehau } 2736c8d8eccSSepherosa Ziehau 2746c8d8eccSSepherosa Ziehau static void 2756c8d8eccSSepherosa Ziehau bnx_writemem_ind(struct bnx_softc *sc, uint32_t off, uint32_t val) 2766c8d8eccSSepherosa Ziehau { 2776c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 2786c8d8eccSSepherosa Ziehau 2796c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5906 && 2806c8d8eccSSepherosa Ziehau off >= BGE_STATS_BLOCK && off < BGE_SEND_RING_1_TO_4) 2816c8d8eccSSepherosa Ziehau return; 2826c8d8eccSSepherosa Ziehau 2836c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); 2846c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_DATA, val, 4); 2856c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); 2866c8d8eccSSepherosa Ziehau } 2876c8d8eccSSepherosa Ziehau 2886c8d8eccSSepherosa Ziehau #ifdef notdef 2896c8d8eccSSepherosa Ziehau static uint32_t 2906c8d8eccSSepherosa Ziehau bnx_readreg_ind(struct bnx_softc *sc, uin32_t off) 2916c8d8eccSSepherosa Ziehau { 2926c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 2936c8d8eccSSepherosa Ziehau 2946c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_REG_BASEADDR, off, 4); 2956c8d8eccSSepherosa Ziehau return(pci_read_config(dev, BGE_PCI_REG_DATA, 4)); 2966c8d8eccSSepherosa Ziehau } 2976c8d8eccSSepherosa Ziehau #endif 2986c8d8eccSSepherosa Ziehau 2996c8d8eccSSepherosa Ziehau static void 3006c8d8eccSSepherosa Ziehau bnx_writereg_ind(struct bnx_softc *sc, uint32_t off, uint32_t val) 3016c8d8eccSSepherosa Ziehau { 3026c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 3036c8d8eccSSepherosa Ziehau 3046c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_REG_BASEADDR, off, 4); 3056c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_REG_DATA, val, 4); 3066c8d8eccSSepherosa Ziehau } 3076c8d8eccSSepherosa Ziehau 3086c8d8eccSSepherosa Ziehau static void 3096c8d8eccSSepherosa Ziehau bnx_writemem_direct(struct bnx_softc *sc, uint32_t off, uint32_t val) 3106c8d8eccSSepherosa Ziehau { 3116c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, off, val); 3126c8d8eccSSepherosa Ziehau } 3136c8d8eccSSepherosa Ziehau 3146c8d8eccSSepherosa Ziehau static void 3156c8d8eccSSepherosa Ziehau bnx_writembx(struct bnx_softc *sc, int off, int val) 3166c8d8eccSSepherosa Ziehau { 3176c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5906) 3186c8d8eccSSepherosa Ziehau off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI; 3196c8d8eccSSepherosa Ziehau 3206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, off, val); 3216c8d8eccSSepherosa Ziehau } 3226c8d8eccSSepherosa Ziehau 3236c8d8eccSSepherosa Ziehau static uint8_t 3246c8d8eccSSepherosa Ziehau bnx_nvram_getbyte(struct bnx_softc *sc, int addr, uint8_t *dest) 3256c8d8eccSSepherosa Ziehau { 3266c8d8eccSSepherosa Ziehau uint32_t access, byte = 0; 3276c8d8eccSSepherosa Ziehau int i; 3286c8d8eccSSepherosa Ziehau 3296c8d8eccSSepherosa Ziehau /* Lock. */ 3306c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1); 3316c8d8eccSSepherosa Ziehau for (i = 0; i < 8000; i++) { 3326c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_NVRAM_SWARB) & BGE_NVRAMSWARB_GNT1) 3336c8d8eccSSepherosa Ziehau break; 3346c8d8eccSSepherosa Ziehau DELAY(20); 3356c8d8eccSSepherosa Ziehau } 3366c8d8eccSSepherosa Ziehau if (i == 8000) 3376c8d8eccSSepherosa Ziehau return (1); 3386c8d8eccSSepherosa Ziehau 3396c8d8eccSSepherosa Ziehau /* Enable access. */ 3406c8d8eccSSepherosa Ziehau access = CSR_READ_4(sc, BGE_NVRAM_ACCESS); 3416c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access | BGE_NVRAMACC_ENABLE); 3426c8d8eccSSepherosa Ziehau 3436c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_NVRAM_ADDR, addr & 0xfffffffc); 3446c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_NVRAM_CMD, BGE_NVRAM_READCMD); 3456c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT * 10; i++) { 3466c8d8eccSSepherosa Ziehau DELAY(10); 3476c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_NVRAM_CMD) & BGE_NVRAMCMD_DONE) { 3486c8d8eccSSepherosa Ziehau DELAY(10); 3496c8d8eccSSepherosa Ziehau break; 3506c8d8eccSSepherosa Ziehau } 3516c8d8eccSSepherosa Ziehau } 3526c8d8eccSSepherosa Ziehau 3536c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT * 10) { 3546c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "nvram read timed out\n"); 3556c8d8eccSSepherosa Ziehau return (1); 3566c8d8eccSSepherosa Ziehau } 3576c8d8eccSSepherosa Ziehau 3586c8d8eccSSepherosa Ziehau /* Get result. */ 3596c8d8eccSSepherosa Ziehau byte = CSR_READ_4(sc, BGE_NVRAM_RDDATA); 3606c8d8eccSSepherosa Ziehau 3616c8d8eccSSepherosa Ziehau *dest = (bswap32(byte) >> ((addr % 4) * 8)) & 0xFF; 3626c8d8eccSSepherosa Ziehau 3636c8d8eccSSepherosa Ziehau /* Disable access. */ 3646c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access); 3656c8d8eccSSepherosa Ziehau 3666c8d8eccSSepherosa Ziehau /* Unlock. */ 3676c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1); 3686c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_NVRAM_SWARB); 3696c8d8eccSSepherosa Ziehau 3706c8d8eccSSepherosa Ziehau return (0); 3716c8d8eccSSepherosa Ziehau } 3726c8d8eccSSepherosa Ziehau 3736c8d8eccSSepherosa Ziehau /* 3746c8d8eccSSepherosa Ziehau * Read a sequence of bytes from NVRAM. 3756c8d8eccSSepherosa Ziehau */ 3766c8d8eccSSepherosa Ziehau static int 3776c8d8eccSSepherosa Ziehau bnx_read_nvram(struct bnx_softc *sc, caddr_t dest, int off, int cnt) 3786c8d8eccSSepherosa Ziehau { 3796c8d8eccSSepherosa Ziehau int err = 0, i; 3806c8d8eccSSepherosa Ziehau uint8_t byte = 0; 3816c8d8eccSSepherosa Ziehau 3826c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev != BGE_ASICREV_BCM5906) 3836c8d8eccSSepherosa Ziehau return (1); 3846c8d8eccSSepherosa Ziehau 3856c8d8eccSSepherosa Ziehau for (i = 0; i < cnt; i++) { 3866c8d8eccSSepherosa Ziehau err = bnx_nvram_getbyte(sc, off + i, &byte); 3876c8d8eccSSepherosa Ziehau if (err) 3886c8d8eccSSepherosa Ziehau break; 3896c8d8eccSSepherosa Ziehau *(dest + i) = byte; 3906c8d8eccSSepherosa Ziehau } 3916c8d8eccSSepherosa Ziehau 3926c8d8eccSSepherosa Ziehau return (err ? 1 : 0); 3936c8d8eccSSepherosa Ziehau } 3946c8d8eccSSepherosa Ziehau 3956c8d8eccSSepherosa Ziehau /* 3966c8d8eccSSepherosa Ziehau * Read a byte of data stored in the EEPROM at address 'addr.' The 3976c8d8eccSSepherosa Ziehau * BCM570x supports both the traditional bitbang interface and an 3986c8d8eccSSepherosa Ziehau * auto access interface for reading the EEPROM. We use the auto 3996c8d8eccSSepherosa Ziehau * access method. 4006c8d8eccSSepherosa Ziehau */ 4016c8d8eccSSepherosa Ziehau static uint8_t 4026c8d8eccSSepherosa Ziehau bnx_eeprom_getbyte(struct bnx_softc *sc, uint32_t addr, uint8_t *dest) 4036c8d8eccSSepherosa Ziehau { 4046c8d8eccSSepherosa Ziehau int i; 4056c8d8eccSSepherosa Ziehau uint32_t byte = 0; 4066c8d8eccSSepherosa Ziehau 4076c8d8eccSSepherosa Ziehau /* 4086c8d8eccSSepherosa Ziehau * Enable use of auto EEPROM access so we can avoid 4096c8d8eccSSepherosa Ziehau * having to use the bitbang method. 4106c8d8eccSSepherosa Ziehau */ 4116c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_AUTO_EEPROM); 4126c8d8eccSSepherosa Ziehau 4136c8d8eccSSepherosa Ziehau /* Reset the EEPROM, load the clock period. */ 4146c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_EE_ADDR, 4156c8d8eccSSepherosa Ziehau BGE_EEADDR_RESET|BGE_EEHALFCLK(BGE_HALFCLK_384SCL)); 4166c8d8eccSSepherosa Ziehau DELAY(20); 4176c8d8eccSSepherosa Ziehau 4186c8d8eccSSepherosa Ziehau /* Issue the read EEPROM command. */ 4196c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_EE_ADDR, BGE_EE_READCMD | addr); 4206c8d8eccSSepherosa Ziehau 4216c8d8eccSSepherosa Ziehau /* Wait for completion */ 4226c8d8eccSSepherosa Ziehau for(i = 0; i < BNX_TIMEOUT * 10; i++) { 4236c8d8eccSSepherosa Ziehau DELAY(10); 4246c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_EE_ADDR) & BGE_EEADDR_DONE) 4256c8d8eccSSepherosa Ziehau break; 4266c8d8eccSSepherosa Ziehau } 4276c8d8eccSSepherosa Ziehau 4286c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 4296c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "eeprom read timed out\n"); 4306c8d8eccSSepherosa Ziehau return(1); 4316c8d8eccSSepherosa Ziehau } 4326c8d8eccSSepherosa Ziehau 4336c8d8eccSSepherosa Ziehau /* Get result. */ 4346c8d8eccSSepherosa Ziehau byte = CSR_READ_4(sc, BGE_EE_DATA); 4356c8d8eccSSepherosa Ziehau 4366c8d8eccSSepherosa Ziehau *dest = (byte >> ((addr % 4) * 8)) & 0xFF; 4376c8d8eccSSepherosa Ziehau 4386c8d8eccSSepherosa Ziehau return(0); 4396c8d8eccSSepherosa Ziehau } 4406c8d8eccSSepherosa Ziehau 4416c8d8eccSSepherosa Ziehau /* 4426c8d8eccSSepherosa Ziehau * Read a sequence of bytes from the EEPROM. 4436c8d8eccSSepherosa Ziehau */ 4446c8d8eccSSepherosa Ziehau static int 4456c8d8eccSSepherosa Ziehau bnx_read_eeprom(struct bnx_softc *sc, caddr_t dest, uint32_t off, size_t len) 4466c8d8eccSSepherosa Ziehau { 4476c8d8eccSSepherosa Ziehau size_t i; 4486c8d8eccSSepherosa Ziehau int err; 4496c8d8eccSSepherosa Ziehau uint8_t byte; 4506c8d8eccSSepherosa Ziehau 4516c8d8eccSSepherosa Ziehau for (byte = 0, err = 0, i = 0; i < len; i++) { 4526c8d8eccSSepherosa Ziehau err = bnx_eeprom_getbyte(sc, off + i, &byte); 4536c8d8eccSSepherosa Ziehau if (err) 4546c8d8eccSSepherosa Ziehau break; 4556c8d8eccSSepherosa Ziehau *(dest + i) = byte; 4566c8d8eccSSepherosa Ziehau } 4576c8d8eccSSepherosa Ziehau 4586c8d8eccSSepherosa Ziehau return(err ? 1 : 0); 4596c8d8eccSSepherosa Ziehau } 4606c8d8eccSSepherosa Ziehau 4616c8d8eccSSepherosa Ziehau static int 4626c8d8eccSSepherosa Ziehau bnx_miibus_readreg(device_t dev, int phy, int reg) 4636c8d8eccSSepherosa Ziehau { 4646c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 4656c8d8eccSSepherosa Ziehau uint32_t val; 4666c8d8eccSSepherosa Ziehau int i; 4676c8d8eccSSepherosa Ziehau 4686c8d8eccSSepherosa Ziehau KASSERT(phy == sc->bnx_phyno, 4696c8d8eccSSepherosa Ziehau ("invalid phyno %d, should be %d", phy, sc->bnx_phyno)); 4706c8d8eccSSepherosa Ziehau 4716c8d8eccSSepherosa Ziehau /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ 4726c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 4736c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 4746c8d8eccSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 4756c8d8eccSSepherosa Ziehau DELAY(80); 4766c8d8eccSSepherosa Ziehau } 4776c8d8eccSSepherosa Ziehau 4786c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ | BGE_MICOMM_BUSY | 4796c8d8eccSSepherosa Ziehau BGE_MIPHY(phy) | BGE_MIREG(reg)); 4806c8d8eccSSepherosa Ziehau 4816c8d8eccSSepherosa Ziehau /* Poll for the PHY register access to complete. */ 4826c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 4836c8d8eccSSepherosa Ziehau DELAY(10); 4846c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_MI_COMM); 4856c8d8eccSSepherosa Ziehau if ((val & BGE_MICOMM_BUSY) == 0) { 4866c8d8eccSSepherosa Ziehau DELAY(5); 4876c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_MI_COMM); 4886c8d8eccSSepherosa Ziehau break; 4896c8d8eccSSepherosa Ziehau } 4906c8d8eccSSepherosa Ziehau } 4916c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 4926c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "PHY read timed out " 4936c8d8eccSSepherosa Ziehau "(phy %d, reg %d, val 0x%08x)\n", phy, reg, val); 4946c8d8eccSSepherosa Ziehau val = 0; 4956c8d8eccSSepherosa Ziehau } 4966c8d8eccSSepherosa Ziehau 4976c8d8eccSSepherosa Ziehau /* Restore the autopoll bit if necessary. */ 4986c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 4996c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 5006c8d8eccSSepherosa Ziehau DELAY(80); 5016c8d8eccSSepherosa Ziehau } 5026c8d8eccSSepherosa Ziehau 5036c8d8eccSSepherosa Ziehau if (val & BGE_MICOMM_READFAIL) 5046c8d8eccSSepherosa Ziehau return 0; 5056c8d8eccSSepherosa Ziehau 5066c8d8eccSSepherosa Ziehau return (val & 0xFFFF); 5076c8d8eccSSepherosa Ziehau } 5086c8d8eccSSepherosa Ziehau 5096c8d8eccSSepherosa Ziehau static int 5106c8d8eccSSepherosa Ziehau bnx_miibus_writereg(device_t dev, int phy, int reg, int val) 5116c8d8eccSSepherosa Ziehau { 5126c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 5136c8d8eccSSepherosa Ziehau int i; 5146c8d8eccSSepherosa Ziehau 5156c8d8eccSSepherosa Ziehau KASSERT(phy == sc->bnx_phyno, 5166c8d8eccSSepherosa Ziehau ("invalid phyno %d, should be %d", phy, sc->bnx_phyno)); 5176c8d8eccSSepherosa Ziehau 5186c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5906 && 5196c8d8eccSSepherosa Ziehau (reg == BRGPHY_MII_1000CTL || reg == BRGPHY_MII_AUXCTL)) 5206c8d8eccSSepherosa Ziehau return 0; 5216c8d8eccSSepherosa Ziehau 5226c8d8eccSSepherosa Ziehau /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ 5236c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 5246c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 5256c8d8eccSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 5266c8d8eccSSepherosa Ziehau DELAY(80); 5276c8d8eccSSepherosa Ziehau } 5286c8d8eccSSepherosa Ziehau 5296c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY | 5306c8d8eccSSepherosa Ziehau BGE_MIPHY(phy) | BGE_MIREG(reg) | val); 5316c8d8eccSSepherosa Ziehau 5326c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 5336c8d8eccSSepherosa Ziehau DELAY(10); 5346c8d8eccSSepherosa Ziehau if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) { 5356c8d8eccSSepherosa Ziehau DELAY(5); 5366c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_MI_COMM); /* dummy read */ 5376c8d8eccSSepherosa Ziehau break; 5386c8d8eccSSepherosa Ziehau } 5396c8d8eccSSepherosa Ziehau } 5406c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 5416c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "PHY write timed out " 5426c8d8eccSSepherosa Ziehau "(phy %d, reg %d, val %d)\n", phy, reg, val); 5436c8d8eccSSepherosa Ziehau } 5446c8d8eccSSepherosa Ziehau 5456c8d8eccSSepherosa Ziehau /* Restore the autopoll bit if necessary. */ 5466c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 5476c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 5486c8d8eccSSepherosa Ziehau DELAY(80); 5496c8d8eccSSepherosa Ziehau } 5506c8d8eccSSepherosa Ziehau 5516c8d8eccSSepherosa Ziehau return 0; 5526c8d8eccSSepherosa Ziehau } 5536c8d8eccSSepherosa Ziehau 5546c8d8eccSSepherosa Ziehau static void 5556c8d8eccSSepherosa Ziehau bnx_miibus_statchg(device_t dev) 5566c8d8eccSSepherosa Ziehau { 5576c8d8eccSSepherosa Ziehau struct bnx_softc *sc; 5586c8d8eccSSepherosa Ziehau struct mii_data *mii; 5596c8d8eccSSepherosa Ziehau 5606c8d8eccSSepherosa Ziehau sc = device_get_softc(dev); 5616c8d8eccSSepherosa Ziehau mii = device_get_softc(sc->bnx_miibus); 5626c8d8eccSSepherosa Ziehau 5636c8d8eccSSepherosa Ziehau if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 5646c8d8eccSSepherosa Ziehau (IFM_ACTIVE | IFM_AVALID)) { 5656c8d8eccSSepherosa Ziehau switch (IFM_SUBTYPE(mii->mii_media_active)) { 5666c8d8eccSSepherosa Ziehau case IFM_10_T: 5676c8d8eccSSepherosa Ziehau case IFM_100_TX: 5686c8d8eccSSepherosa Ziehau sc->bnx_link = 1; 5696c8d8eccSSepherosa Ziehau break; 5706c8d8eccSSepherosa Ziehau case IFM_1000_T: 5716c8d8eccSSepherosa Ziehau case IFM_1000_SX: 5726c8d8eccSSepherosa Ziehau case IFM_2500_SX: 5736c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev != BGE_ASICREV_BCM5906) 5746c8d8eccSSepherosa Ziehau sc->bnx_link = 1; 5756c8d8eccSSepherosa Ziehau else 5766c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 5776c8d8eccSSepherosa Ziehau break; 5786c8d8eccSSepherosa Ziehau default: 5796c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 5806c8d8eccSSepherosa Ziehau break; 5816c8d8eccSSepherosa Ziehau } 5826c8d8eccSSepherosa Ziehau } else { 5836c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 5846c8d8eccSSepherosa Ziehau } 5856c8d8eccSSepherosa Ziehau if (sc->bnx_link == 0) 5866c8d8eccSSepherosa Ziehau return; 5876c8d8eccSSepherosa Ziehau 5886c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_PORTMODE); 5896c8d8eccSSepherosa Ziehau if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || 5906c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) { 5916c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_GMII); 5926c8d8eccSSepherosa Ziehau } else { 5936c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_MII); 5946c8d8eccSSepherosa Ziehau } 5956c8d8eccSSepherosa Ziehau 5966c8d8eccSSepherosa Ziehau if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { 5976c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX); 5986c8d8eccSSepherosa Ziehau } else { 5996c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX); 6006c8d8eccSSepherosa Ziehau } 6016c8d8eccSSepherosa Ziehau } 6026c8d8eccSSepherosa Ziehau 6036c8d8eccSSepherosa Ziehau /* 6046c8d8eccSSepherosa Ziehau * Memory management for jumbo frames. 6056c8d8eccSSepherosa Ziehau */ 6066c8d8eccSSepherosa Ziehau static int 6076c8d8eccSSepherosa Ziehau bnx_alloc_jumbo_mem(struct bnx_softc *sc) 6086c8d8eccSSepherosa Ziehau { 6096c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 6106c8d8eccSSepherosa Ziehau struct bnx_jslot *entry; 6116c8d8eccSSepherosa Ziehau uint8_t *ptr; 6126c8d8eccSSepherosa Ziehau bus_addr_t paddr; 6136c8d8eccSSepherosa Ziehau int i, error; 6146c8d8eccSSepherosa Ziehau 6156c8d8eccSSepherosa Ziehau /* 6166c8d8eccSSepherosa Ziehau * Create tag for jumbo mbufs. 6176c8d8eccSSepherosa Ziehau * This is really a bit of a kludge. We allocate a special 6186c8d8eccSSepherosa Ziehau * jumbo buffer pool which (thanks to the way our DMA 6196c8d8eccSSepherosa Ziehau * memory allocation works) will consist of contiguous 6206c8d8eccSSepherosa Ziehau * pages. This means that even though a jumbo buffer might 6216c8d8eccSSepherosa Ziehau * be larger than a page size, we don't really need to 6226c8d8eccSSepherosa Ziehau * map it into more than one DMA segment. However, the 6236c8d8eccSSepherosa Ziehau * default mbuf tag will result in multi-segment mappings, 6246c8d8eccSSepherosa Ziehau * so we have to create a special jumbo mbuf tag that 6256c8d8eccSSepherosa Ziehau * lets us get away with mapping the jumbo buffers as 6266c8d8eccSSepherosa Ziehau * a single segment. I think eventually the driver should 6276c8d8eccSSepherosa Ziehau * be changed so that it uses ordinary mbufs and cluster 6286c8d8eccSSepherosa Ziehau * buffers, i.e. jumbo frames can span multiple DMA 6296c8d8eccSSepherosa Ziehau * descriptors. But that's a project for another day. 6306c8d8eccSSepherosa Ziehau */ 6316c8d8eccSSepherosa Ziehau 6326c8d8eccSSepherosa Ziehau /* 6336c8d8eccSSepherosa Ziehau * Create DMA stuffs for jumbo RX ring. 6346c8d8eccSSepherosa Ziehau */ 6356c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_JUMBO_RX_RING_SZ, 6366c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_jumbo_ring_tag, 6376c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_jumbo_ring_map, 6386c8d8eccSSepherosa Ziehau (void *)&sc->bnx_ldata.bnx_rx_jumbo_ring, 6396c8d8eccSSepherosa Ziehau &sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 6406c8d8eccSSepherosa Ziehau if (error) { 6416c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create jumbo RX ring\n"); 6426c8d8eccSSepherosa Ziehau return error; 6436c8d8eccSSepherosa Ziehau } 6446c8d8eccSSepherosa Ziehau 6456c8d8eccSSepherosa Ziehau /* 6466c8d8eccSSepherosa Ziehau * Create DMA stuffs for jumbo buffer block. 6476c8d8eccSSepherosa Ziehau */ 6486c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BNX_JMEM, 6496c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_jumbo_tag, 6506c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_jumbo_map, 6516c8d8eccSSepherosa Ziehau (void **)&sc->bnx_ldata.bnx_jumbo_buf, 6526c8d8eccSSepherosa Ziehau &paddr); 6536c8d8eccSSepherosa Ziehau if (error) { 6546c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create jumbo buffer\n"); 6556c8d8eccSSepherosa Ziehau return error; 6566c8d8eccSSepherosa Ziehau } 6576c8d8eccSSepherosa Ziehau 6586c8d8eccSSepherosa Ziehau SLIST_INIT(&sc->bnx_jfree_listhead); 6596c8d8eccSSepherosa Ziehau 6606c8d8eccSSepherosa Ziehau /* 6616c8d8eccSSepherosa Ziehau * Now divide it up into 9K pieces and save the addresses 6626c8d8eccSSepherosa Ziehau * in an array. Note that we play an evil trick here by using 6636c8d8eccSSepherosa Ziehau * the first few bytes in the buffer to hold the the address 6646c8d8eccSSepherosa Ziehau * of the softc structure for this interface. This is because 6656c8d8eccSSepherosa Ziehau * bnx_jfree() needs it, but it is called by the mbuf management 6666c8d8eccSSepherosa Ziehau * code which will not pass it to us explicitly. 6676c8d8eccSSepherosa Ziehau */ 6686c8d8eccSSepherosa Ziehau for (i = 0, ptr = sc->bnx_ldata.bnx_jumbo_buf; i < BNX_JSLOTS; i++) { 6696c8d8eccSSepherosa Ziehau entry = &sc->bnx_cdata.bnx_jslots[i]; 6706c8d8eccSSepherosa Ziehau entry->bnx_sc = sc; 6716c8d8eccSSepherosa Ziehau entry->bnx_buf = ptr; 6726c8d8eccSSepherosa Ziehau entry->bnx_paddr = paddr; 6736c8d8eccSSepherosa Ziehau entry->bnx_inuse = 0; 6746c8d8eccSSepherosa Ziehau entry->bnx_slot = i; 6756c8d8eccSSepherosa Ziehau SLIST_INSERT_HEAD(&sc->bnx_jfree_listhead, entry, jslot_link); 6766c8d8eccSSepherosa Ziehau 6776c8d8eccSSepherosa Ziehau ptr += BNX_JLEN; 6786c8d8eccSSepherosa Ziehau paddr += BNX_JLEN; 6796c8d8eccSSepherosa Ziehau } 6806c8d8eccSSepherosa Ziehau return 0; 6816c8d8eccSSepherosa Ziehau } 6826c8d8eccSSepherosa Ziehau 6836c8d8eccSSepherosa Ziehau static void 6846c8d8eccSSepherosa Ziehau bnx_free_jumbo_mem(struct bnx_softc *sc) 6856c8d8eccSSepherosa Ziehau { 6866c8d8eccSSepherosa Ziehau /* Destroy jumbo RX ring. */ 6876c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_rx_jumbo_ring_tag, 6886c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_ring_map, 6896c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_rx_jumbo_ring); 6906c8d8eccSSepherosa Ziehau 6916c8d8eccSSepherosa Ziehau /* Destroy jumbo buffer block. */ 6926c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_jumbo_tag, 6936c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_jumbo_map, 6946c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_jumbo_buf); 6956c8d8eccSSepherosa Ziehau } 6966c8d8eccSSepherosa Ziehau 6976c8d8eccSSepherosa Ziehau /* 6986c8d8eccSSepherosa Ziehau * Allocate a jumbo buffer. 6996c8d8eccSSepherosa Ziehau */ 7006c8d8eccSSepherosa Ziehau static struct bnx_jslot * 7016c8d8eccSSepherosa Ziehau bnx_jalloc(struct bnx_softc *sc) 7026c8d8eccSSepherosa Ziehau { 7036c8d8eccSSepherosa Ziehau struct bnx_jslot *entry; 7046c8d8eccSSepherosa Ziehau 7056c8d8eccSSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_jslot_serializer); 7066c8d8eccSSepherosa Ziehau entry = SLIST_FIRST(&sc->bnx_jfree_listhead); 7076c8d8eccSSepherosa Ziehau if (entry) { 7086c8d8eccSSepherosa Ziehau SLIST_REMOVE_HEAD(&sc->bnx_jfree_listhead, jslot_link); 7096c8d8eccSSepherosa Ziehau entry->bnx_inuse = 1; 7106c8d8eccSSepherosa Ziehau } else { 7116c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "no free jumbo buffers\n"); 7126c8d8eccSSepherosa Ziehau } 7136c8d8eccSSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_jslot_serializer); 7146c8d8eccSSepherosa Ziehau return(entry); 7156c8d8eccSSepherosa Ziehau } 7166c8d8eccSSepherosa Ziehau 7176c8d8eccSSepherosa Ziehau /* 7186c8d8eccSSepherosa Ziehau * Adjust usage count on a jumbo buffer. 7196c8d8eccSSepherosa Ziehau */ 7206c8d8eccSSepherosa Ziehau static void 7216c8d8eccSSepherosa Ziehau bnx_jref(void *arg) 7226c8d8eccSSepherosa Ziehau { 7236c8d8eccSSepherosa Ziehau struct bnx_jslot *entry = (struct bnx_jslot *)arg; 7246c8d8eccSSepherosa Ziehau struct bnx_softc *sc = entry->bnx_sc; 7256c8d8eccSSepherosa Ziehau 7266c8d8eccSSepherosa Ziehau if (sc == NULL) 7276c8d8eccSSepherosa Ziehau panic("bnx_jref: can't find softc pointer!"); 7286c8d8eccSSepherosa Ziehau 7296c8d8eccSSepherosa Ziehau if (&sc->bnx_cdata.bnx_jslots[entry->bnx_slot] != entry) { 7306c8d8eccSSepherosa Ziehau panic("bnx_jref: asked to reference buffer " 7316c8d8eccSSepherosa Ziehau "that we don't manage!"); 7326c8d8eccSSepherosa Ziehau } else if (entry->bnx_inuse == 0) { 7336c8d8eccSSepherosa Ziehau panic("bnx_jref: buffer already free!"); 7346c8d8eccSSepherosa Ziehau } else { 7356c8d8eccSSepherosa Ziehau atomic_add_int(&entry->bnx_inuse, 1); 7366c8d8eccSSepherosa Ziehau } 7376c8d8eccSSepherosa Ziehau } 7386c8d8eccSSepherosa Ziehau 7396c8d8eccSSepherosa Ziehau /* 7406c8d8eccSSepherosa Ziehau * Release a jumbo buffer. 7416c8d8eccSSepherosa Ziehau */ 7426c8d8eccSSepherosa Ziehau static void 7436c8d8eccSSepherosa Ziehau bnx_jfree(void *arg) 7446c8d8eccSSepherosa Ziehau { 7456c8d8eccSSepherosa Ziehau struct bnx_jslot *entry = (struct bnx_jslot *)arg; 7466c8d8eccSSepherosa Ziehau struct bnx_softc *sc = entry->bnx_sc; 7476c8d8eccSSepherosa Ziehau 7486c8d8eccSSepherosa Ziehau if (sc == NULL) 7496c8d8eccSSepherosa Ziehau panic("bnx_jfree: can't find softc pointer!"); 7506c8d8eccSSepherosa Ziehau 7516c8d8eccSSepherosa Ziehau if (&sc->bnx_cdata.bnx_jslots[entry->bnx_slot] != entry) { 7526c8d8eccSSepherosa Ziehau panic("bnx_jfree: asked to free buffer that we don't manage!"); 7536c8d8eccSSepherosa Ziehau } else if (entry->bnx_inuse == 0) { 7546c8d8eccSSepherosa Ziehau panic("bnx_jfree: buffer already free!"); 7556c8d8eccSSepherosa Ziehau } else { 7566c8d8eccSSepherosa Ziehau /* 7576c8d8eccSSepherosa Ziehau * Possible MP race to 0, use the serializer. The atomic insn 7586c8d8eccSSepherosa Ziehau * is still needed for races against bnx_jref(). 7596c8d8eccSSepherosa Ziehau */ 7606c8d8eccSSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_jslot_serializer); 7616c8d8eccSSepherosa Ziehau atomic_subtract_int(&entry->bnx_inuse, 1); 7626c8d8eccSSepherosa Ziehau if (entry->bnx_inuse == 0) { 7636c8d8eccSSepherosa Ziehau SLIST_INSERT_HEAD(&sc->bnx_jfree_listhead, 7646c8d8eccSSepherosa Ziehau entry, jslot_link); 7656c8d8eccSSepherosa Ziehau } 7666c8d8eccSSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_jslot_serializer); 7676c8d8eccSSepherosa Ziehau } 7686c8d8eccSSepherosa Ziehau } 7696c8d8eccSSepherosa Ziehau 7706c8d8eccSSepherosa Ziehau 7716c8d8eccSSepherosa Ziehau /* 7726c8d8eccSSepherosa Ziehau * Intialize a standard receive ring descriptor. 7736c8d8eccSSepherosa Ziehau */ 7746c8d8eccSSepherosa Ziehau static int 7756c8d8eccSSepherosa Ziehau bnx_newbuf_std(struct bnx_softc *sc, int i, int init) 7766c8d8eccSSepherosa Ziehau { 7776c8d8eccSSepherosa Ziehau struct mbuf *m_new = NULL; 7786c8d8eccSSepherosa Ziehau bus_dma_segment_t seg; 7796c8d8eccSSepherosa Ziehau bus_dmamap_t map; 7806c8d8eccSSepherosa Ziehau int error, nsegs; 7816c8d8eccSSepherosa Ziehau 7826c8d8eccSSepherosa Ziehau m_new = m_getcl(init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR); 7836c8d8eccSSepherosa Ziehau if (m_new == NULL) 7846c8d8eccSSepherosa Ziehau return ENOBUFS; 7856c8d8eccSSepherosa Ziehau m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 7866c8d8eccSSepherosa Ziehau m_adj(m_new, ETHER_ALIGN); 7876c8d8eccSSepherosa Ziehau 7886c8d8eccSSepherosa Ziehau error = bus_dmamap_load_mbuf_segment(sc->bnx_cdata.bnx_rx_mtag, 7896c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_tmpmap, m_new, 7906c8d8eccSSepherosa Ziehau &seg, 1, &nsegs, BUS_DMA_NOWAIT); 7916c8d8eccSSepherosa Ziehau if (error) { 7926c8d8eccSSepherosa Ziehau m_freem(m_new); 7936c8d8eccSSepherosa Ziehau return error; 7946c8d8eccSSepherosa Ziehau } 7956c8d8eccSSepherosa Ziehau 7966c8d8eccSSepherosa Ziehau if (!init) { 7976c8d8eccSSepherosa Ziehau bus_dmamap_sync(sc->bnx_cdata.bnx_rx_mtag, 7986c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_std_dmamap[i], 7996c8d8eccSSepherosa Ziehau BUS_DMASYNC_POSTREAD); 8006c8d8eccSSepherosa Ziehau bus_dmamap_unload(sc->bnx_cdata.bnx_rx_mtag, 8016c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_std_dmamap[i]); 8026c8d8eccSSepherosa Ziehau } 8036c8d8eccSSepherosa Ziehau 8046c8d8eccSSepherosa Ziehau map = sc->bnx_cdata.bnx_rx_tmpmap; 8056c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_tmpmap = sc->bnx_cdata.bnx_rx_std_dmamap[i]; 8066c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_std_dmamap[i] = map; 8076c8d8eccSSepherosa Ziehau 8086c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_std_chain[i].bnx_mbuf = m_new; 8096c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_std_chain[i].bnx_paddr = seg.ds_addr; 8106c8d8eccSSepherosa Ziehau 8116c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_std(sc, i); 8126c8d8eccSSepherosa Ziehau return 0; 8136c8d8eccSSepherosa Ziehau } 8146c8d8eccSSepherosa Ziehau 8156c8d8eccSSepherosa Ziehau static void 8166c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_std(struct bnx_softc *sc, int i) 8176c8d8eccSSepherosa Ziehau { 8186c8d8eccSSepherosa Ziehau struct bnx_rxchain *rc; 8196c8d8eccSSepherosa Ziehau struct bge_rx_bd *r; 8206c8d8eccSSepherosa Ziehau 8216c8d8eccSSepherosa Ziehau rc = &sc->bnx_cdata.bnx_rx_std_chain[i]; 8226c8d8eccSSepherosa Ziehau r = &sc->bnx_ldata.bnx_rx_std_ring[i]; 8236c8d8eccSSepherosa Ziehau 8246c8d8eccSSepherosa Ziehau r->bge_addr.bge_addr_lo = BGE_ADDR_LO(rc->bnx_paddr); 8256c8d8eccSSepherosa Ziehau r->bge_addr.bge_addr_hi = BGE_ADDR_HI(rc->bnx_paddr); 8266c8d8eccSSepherosa Ziehau r->bge_len = rc->bnx_mbuf->m_len; 8276c8d8eccSSepherosa Ziehau r->bge_idx = i; 8286c8d8eccSSepherosa Ziehau r->bge_flags = BGE_RXBDFLAG_END; 8296c8d8eccSSepherosa Ziehau } 8306c8d8eccSSepherosa Ziehau 8316c8d8eccSSepherosa Ziehau /* 8326c8d8eccSSepherosa Ziehau * Initialize a jumbo receive ring descriptor. This allocates 8336c8d8eccSSepherosa Ziehau * a jumbo buffer from the pool managed internally by the driver. 8346c8d8eccSSepherosa Ziehau */ 8356c8d8eccSSepherosa Ziehau static int 8366c8d8eccSSepherosa Ziehau bnx_newbuf_jumbo(struct bnx_softc *sc, int i, int init) 8376c8d8eccSSepherosa Ziehau { 8386c8d8eccSSepherosa Ziehau struct mbuf *m_new = NULL; 8396c8d8eccSSepherosa Ziehau struct bnx_jslot *buf; 8406c8d8eccSSepherosa Ziehau bus_addr_t paddr; 8416c8d8eccSSepherosa Ziehau 8426c8d8eccSSepherosa Ziehau /* Allocate the mbuf. */ 8436c8d8eccSSepherosa Ziehau MGETHDR(m_new, init ? MB_WAIT : MB_DONTWAIT, MT_DATA); 8446c8d8eccSSepherosa Ziehau if (m_new == NULL) 8456c8d8eccSSepherosa Ziehau return ENOBUFS; 8466c8d8eccSSepherosa Ziehau 8476c8d8eccSSepherosa Ziehau /* Allocate the jumbo buffer */ 8486c8d8eccSSepherosa Ziehau buf = bnx_jalloc(sc); 8496c8d8eccSSepherosa Ziehau if (buf == NULL) { 8506c8d8eccSSepherosa Ziehau m_freem(m_new); 8516c8d8eccSSepherosa Ziehau return ENOBUFS; 8526c8d8eccSSepherosa Ziehau } 8536c8d8eccSSepherosa Ziehau 8546c8d8eccSSepherosa Ziehau /* Attach the buffer to the mbuf. */ 8556c8d8eccSSepherosa Ziehau m_new->m_ext.ext_arg = buf; 8566c8d8eccSSepherosa Ziehau m_new->m_ext.ext_buf = buf->bnx_buf; 8576c8d8eccSSepherosa Ziehau m_new->m_ext.ext_free = bnx_jfree; 8586c8d8eccSSepherosa Ziehau m_new->m_ext.ext_ref = bnx_jref; 8596c8d8eccSSepherosa Ziehau m_new->m_ext.ext_size = BNX_JUMBO_FRAMELEN; 8606c8d8eccSSepherosa Ziehau 8616c8d8eccSSepherosa Ziehau m_new->m_flags |= M_EXT; 8626c8d8eccSSepherosa Ziehau 8636c8d8eccSSepherosa Ziehau m_new->m_data = m_new->m_ext.ext_buf; 8646c8d8eccSSepherosa Ziehau m_new->m_len = m_new->m_pkthdr.len = m_new->m_ext.ext_size; 8656c8d8eccSSepherosa Ziehau 8666c8d8eccSSepherosa Ziehau paddr = buf->bnx_paddr; 8676c8d8eccSSepherosa Ziehau m_adj(m_new, ETHER_ALIGN); 8686c8d8eccSSepherosa Ziehau paddr += ETHER_ALIGN; 8696c8d8eccSSepherosa Ziehau 8706c8d8eccSSepherosa Ziehau /* Save necessary information */ 8716c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_chain[i].bnx_mbuf = m_new; 8726c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_chain[i].bnx_paddr = paddr; 8736c8d8eccSSepherosa Ziehau 8746c8d8eccSSepherosa Ziehau /* Set up the descriptor. */ 8756c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(sc, i); 8766c8d8eccSSepherosa Ziehau return 0; 8776c8d8eccSSepherosa Ziehau } 8786c8d8eccSSepherosa Ziehau 8796c8d8eccSSepherosa Ziehau static void 8806c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(struct bnx_softc *sc, int i) 8816c8d8eccSSepherosa Ziehau { 8826c8d8eccSSepherosa Ziehau struct bge_rx_bd *r; 8836c8d8eccSSepherosa Ziehau struct bnx_rxchain *rc; 8846c8d8eccSSepherosa Ziehau 8856c8d8eccSSepherosa Ziehau r = &sc->bnx_ldata.bnx_rx_jumbo_ring[i]; 8866c8d8eccSSepherosa Ziehau rc = &sc->bnx_cdata.bnx_rx_jumbo_chain[i]; 8876c8d8eccSSepherosa Ziehau 8886c8d8eccSSepherosa Ziehau r->bge_addr.bge_addr_lo = BGE_ADDR_LO(rc->bnx_paddr); 8896c8d8eccSSepherosa Ziehau r->bge_addr.bge_addr_hi = BGE_ADDR_HI(rc->bnx_paddr); 8906c8d8eccSSepherosa Ziehau r->bge_len = rc->bnx_mbuf->m_len; 8916c8d8eccSSepherosa Ziehau r->bge_idx = i; 8926c8d8eccSSepherosa Ziehau r->bge_flags = BGE_RXBDFLAG_END|BGE_RXBDFLAG_JUMBO_RING; 8936c8d8eccSSepherosa Ziehau } 8946c8d8eccSSepherosa Ziehau 8956c8d8eccSSepherosa Ziehau static int 8966c8d8eccSSepherosa Ziehau bnx_init_rx_ring_std(struct bnx_softc *sc) 8976c8d8eccSSepherosa Ziehau { 8986c8d8eccSSepherosa Ziehau int i, error; 8996c8d8eccSSepherosa Ziehau 9006c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 9016c8d8eccSSepherosa Ziehau error = bnx_newbuf_std(sc, i, 1); 9026c8d8eccSSepherosa Ziehau if (error) 9036c8d8eccSSepherosa Ziehau return error; 9046c8d8eccSSepherosa Ziehau }; 9056c8d8eccSSepherosa Ziehau 9066c8d8eccSSepherosa Ziehau sc->bnx_std = BGE_STD_RX_RING_CNT - 1; 9076c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bnx_std); 9086c8d8eccSSepherosa Ziehau 9096c8d8eccSSepherosa Ziehau return(0); 9106c8d8eccSSepherosa Ziehau } 9116c8d8eccSSepherosa Ziehau 9126c8d8eccSSepherosa Ziehau static void 9136c8d8eccSSepherosa Ziehau bnx_free_rx_ring_std(struct bnx_softc *sc) 9146c8d8eccSSepherosa Ziehau { 9156c8d8eccSSepherosa Ziehau int i; 9166c8d8eccSSepherosa Ziehau 9176c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 9186c8d8eccSSepherosa Ziehau struct bnx_rxchain *rc = &sc->bnx_cdata.bnx_rx_std_chain[i]; 9196c8d8eccSSepherosa Ziehau 9206c8d8eccSSepherosa Ziehau if (rc->bnx_mbuf != NULL) { 9216c8d8eccSSepherosa Ziehau bus_dmamap_unload(sc->bnx_cdata.bnx_rx_mtag, 9226c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_std_dmamap[i]); 9236c8d8eccSSepherosa Ziehau m_freem(rc->bnx_mbuf); 9246c8d8eccSSepherosa Ziehau rc->bnx_mbuf = NULL; 9256c8d8eccSSepherosa Ziehau } 9266c8d8eccSSepherosa Ziehau bzero(&sc->bnx_ldata.bnx_rx_std_ring[i], 9276c8d8eccSSepherosa Ziehau sizeof(struct bge_rx_bd)); 9286c8d8eccSSepherosa Ziehau } 9296c8d8eccSSepherosa Ziehau } 9306c8d8eccSSepherosa Ziehau 9316c8d8eccSSepherosa Ziehau static int 9326c8d8eccSSepherosa Ziehau bnx_init_rx_ring_jumbo(struct bnx_softc *sc) 9336c8d8eccSSepherosa Ziehau { 9346c8d8eccSSepherosa Ziehau struct bge_rcb *rcb; 9356c8d8eccSSepherosa Ziehau int i, error; 9366c8d8eccSSepherosa Ziehau 9376c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) { 9386c8d8eccSSepherosa Ziehau error = bnx_newbuf_jumbo(sc, i, 1); 9396c8d8eccSSepherosa Ziehau if (error) 9406c8d8eccSSepherosa Ziehau return error; 9416c8d8eccSSepherosa Ziehau }; 9426c8d8eccSSepherosa Ziehau 9436c8d8eccSSepherosa Ziehau sc->bnx_jumbo = BGE_JUMBO_RX_RING_CNT - 1; 9446c8d8eccSSepherosa Ziehau 9456c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_jumbo_rx_rcb; 9466c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(0, 0); 9476c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); 9486c8d8eccSSepherosa Ziehau 9496c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bnx_jumbo); 9506c8d8eccSSepherosa Ziehau 9516c8d8eccSSepherosa Ziehau return(0); 9526c8d8eccSSepherosa Ziehau } 9536c8d8eccSSepherosa Ziehau 9546c8d8eccSSepherosa Ziehau static void 9556c8d8eccSSepherosa Ziehau bnx_free_rx_ring_jumbo(struct bnx_softc *sc) 9566c8d8eccSSepherosa Ziehau { 9576c8d8eccSSepherosa Ziehau int i; 9586c8d8eccSSepherosa Ziehau 9596c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) { 9606c8d8eccSSepherosa Ziehau struct bnx_rxchain *rc = &sc->bnx_cdata.bnx_rx_jumbo_chain[i]; 9616c8d8eccSSepherosa Ziehau 9626c8d8eccSSepherosa Ziehau if (rc->bnx_mbuf != NULL) { 9636c8d8eccSSepherosa Ziehau m_freem(rc->bnx_mbuf); 9646c8d8eccSSepherosa Ziehau rc->bnx_mbuf = NULL; 9656c8d8eccSSepherosa Ziehau } 9666c8d8eccSSepherosa Ziehau bzero(&sc->bnx_ldata.bnx_rx_jumbo_ring[i], 9676c8d8eccSSepherosa Ziehau sizeof(struct bge_rx_bd)); 9686c8d8eccSSepherosa Ziehau } 9696c8d8eccSSepherosa Ziehau } 9706c8d8eccSSepherosa Ziehau 9716c8d8eccSSepherosa Ziehau static void 9726c8d8eccSSepherosa Ziehau bnx_free_tx_ring(struct bnx_softc *sc) 9736c8d8eccSSepherosa Ziehau { 9746c8d8eccSSepherosa Ziehau int i; 9756c8d8eccSSepherosa Ziehau 9766c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 9776c8d8eccSSepherosa Ziehau if (sc->bnx_cdata.bnx_tx_chain[i] != NULL) { 9786c8d8eccSSepherosa Ziehau bus_dmamap_unload(sc->bnx_cdata.bnx_tx_mtag, 9796c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_dmamap[i]); 9806c8d8eccSSepherosa Ziehau m_freem(sc->bnx_cdata.bnx_tx_chain[i]); 9816c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_chain[i] = NULL; 9826c8d8eccSSepherosa Ziehau } 9836c8d8eccSSepherosa Ziehau bzero(&sc->bnx_ldata.bnx_tx_ring[i], 9846c8d8eccSSepherosa Ziehau sizeof(struct bge_tx_bd)); 9856c8d8eccSSepherosa Ziehau } 9866c8d8eccSSepherosa Ziehau } 9876c8d8eccSSepherosa Ziehau 9886c8d8eccSSepherosa Ziehau static int 9896c8d8eccSSepherosa Ziehau bnx_init_tx_ring(struct bnx_softc *sc) 9906c8d8eccSSepherosa Ziehau { 9916c8d8eccSSepherosa Ziehau sc->bnx_txcnt = 0; 9926c8d8eccSSepherosa Ziehau sc->bnx_tx_saved_considx = 0; 9936c8d8eccSSepherosa Ziehau sc->bnx_tx_prodidx = 0; 9946c8d8eccSSepherosa Ziehau 9956c8d8eccSSepherosa Ziehau /* Initialize transmit producer index for host-memory send ring. */ 9966c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bnx_tx_prodidx); 9976c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); 9986c8d8eccSSepherosa Ziehau 9996c8d8eccSSepherosa Ziehau return(0); 10006c8d8eccSSepherosa Ziehau } 10016c8d8eccSSepherosa Ziehau 10026c8d8eccSSepherosa Ziehau static void 10036c8d8eccSSepherosa Ziehau bnx_setmulti(struct bnx_softc *sc) 10046c8d8eccSSepherosa Ziehau { 10056c8d8eccSSepherosa Ziehau struct ifnet *ifp; 10066c8d8eccSSepherosa Ziehau struct ifmultiaddr *ifma; 10076c8d8eccSSepherosa Ziehau uint32_t hashes[4] = { 0, 0, 0, 0 }; 10086c8d8eccSSepherosa Ziehau int h, i; 10096c8d8eccSSepherosa Ziehau 10106c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 10116c8d8eccSSepherosa Ziehau 10126c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 10136c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 10146c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0xFFFFFFFF); 10156c8d8eccSSepherosa Ziehau return; 10166c8d8eccSSepherosa Ziehau } 10176c8d8eccSSepherosa Ziehau 10186c8d8eccSSepherosa Ziehau /* First, zot all the existing filters. */ 10196c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 10206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0); 10216c8d8eccSSepherosa Ziehau 10226c8d8eccSSepherosa Ziehau /* Now program new ones. */ 10236c8d8eccSSepherosa Ziehau TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 10246c8d8eccSSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 10256c8d8eccSSepherosa Ziehau continue; 10266c8d8eccSSepherosa Ziehau h = ether_crc32_le( 10276c8d8eccSSepherosa Ziehau LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 10286c8d8eccSSepherosa Ziehau ETHER_ADDR_LEN) & 0x7f; 10296c8d8eccSSepherosa Ziehau hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F); 10306c8d8eccSSepherosa Ziehau } 10316c8d8eccSSepherosa Ziehau 10326c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 10336c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]); 10346c8d8eccSSepherosa Ziehau } 10356c8d8eccSSepherosa Ziehau 10366c8d8eccSSepherosa Ziehau /* 10376c8d8eccSSepherosa Ziehau * Do endian, PCI and DMA initialization. Also check the on-board ROM 10386c8d8eccSSepherosa Ziehau * self-test results. 10396c8d8eccSSepherosa Ziehau */ 10406c8d8eccSSepherosa Ziehau static int 10416c8d8eccSSepherosa Ziehau bnx_chipinit(struct bnx_softc *sc) 10426c8d8eccSSepherosa Ziehau { 10436c8d8eccSSepherosa Ziehau uint32_t dma_rw_ctl, mode_ctl; 10446c8d8eccSSepherosa Ziehau int i; 10456c8d8eccSSepherosa Ziehau 10466c8d8eccSSepherosa Ziehau /* Set endian type before we access any non-PCI registers. */ 10476c8d8eccSSepherosa Ziehau pci_write_config(sc->bnx_dev, BGE_PCI_MISC_CTL, 10486c8d8eccSSepherosa Ziehau BGE_INIT | BGE_PCIMISCCTL_TAGGED_STATUS, 4); 10496c8d8eccSSepherosa Ziehau 10506c8d8eccSSepherosa Ziehau /* Clear the MAC control register */ 10516c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, 0); 10526c8d8eccSSepherosa Ziehau 10536c8d8eccSSepherosa Ziehau /* 10546c8d8eccSSepherosa Ziehau * Clear the MAC statistics block in the NIC's 10556c8d8eccSSepherosa Ziehau * internal memory. 10566c8d8eccSSepherosa Ziehau */ 10576c8d8eccSSepherosa Ziehau for (i = BGE_STATS_BLOCK; 10586c8d8eccSSepherosa Ziehau i < BGE_STATS_BLOCK_END + 1; i += sizeof(uint32_t)) 10596c8d8eccSSepherosa Ziehau BNX_MEMWIN_WRITE(sc, i, 0); 10606c8d8eccSSepherosa Ziehau 10616c8d8eccSSepherosa Ziehau for (i = BGE_STATUS_BLOCK; 10626c8d8eccSSepherosa Ziehau i < BGE_STATUS_BLOCK_END + 1; i += sizeof(uint32_t)) 10636c8d8eccSSepherosa Ziehau BNX_MEMWIN_WRITE(sc, i, 0); 10646c8d8eccSSepherosa Ziehau 1065d7872545SSepherosa Ziehau if (BNX_IS_57765_FAMILY(sc)) { 1066d7872545SSepherosa Ziehau uint32_t val; 1067d7872545SSepherosa Ziehau 1068d7872545SSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) { 1069d7872545SSepherosa Ziehau mode_ctl = CSR_READ_4(sc, BGE_MODE_CTL); 1070d7872545SSepherosa Ziehau val = mode_ctl & ~BGE_MODECTL_PCIE_PORTS; 1071d7872545SSepherosa Ziehau 1072d7872545SSepherosa Ziehau /* Access the lower 1K of PL PCI-E block registers. */ 1073d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, 1074d7872545SSepherosa Ziehau val | BGE_MODECTL_PCIE_PL_SEL); 1075d7872545SSepherosa Ziehau 1076d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_PCIE_PL_LO_PHYCTL5); 1077d7872545SSepherosa Ziehau val |= BGE_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ; 1078d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_PL_LO_PHYCTL5, val); 1079d7872545SSepherosa Ziehau 1080d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 1081d7872545SSepherosa Ziehau } 1082d7872545SSepherosa Ziehau if (sc->bnx_chiprev != BGE_CHIPREV_57765_AX) { 1083d7872545SSepherosa Ziehau mode_ctl = CSR_READ_4(sc, BGE_MODE_CTL); 1084d7872545SSepherosa Ziehau val = mode_ctl & ~BGE_MODECTL_PCIE_PORTS; 1085d7872545SSepherosa Ziehau 1086d7872545SSepherosa Ziehau /* Access the lower 1K of DL PCI-E block registers. */ 1087d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, 1088d7872545SSepherosa Ziehau val | BGE_MODECTL_PCIE_DL_SEL); 1089d7872545SSepherosa Ziehau 1090d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_PCIE_DL_LO_FTSMAX); 1091d7872545SSepherosa Ziehau val &= ~BGE_PCIE_DL_LO_FTSMAX_MASK; 1092d7872545SSepherosa Ziehau val |= BGE_PCIE_DL_LO_FTSMAX_VAL; 1093d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_DL_LO_FTSMAX, val); 1094d7872545SSepherosa Ziehau 1095d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 1096d7872545SSepherosa Ziehau } 1097d7872545SSepherosa Ziehau 1098d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_CPMU_LSPD_10MB_CLK); 1099d7872545SSepherosa Ziehau val &= ~BGE_CPMU_LSPD_10MB_MACCLK_MASK; 1100d7872545SSepherosa Ziehau val |= BGE_CPMU_LSPD_10MB_MACCLK_6_25; 1101d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_CPMU_LSPD_10MB_CLK, val); 1102d7872545SSepherosa Ziehau } 1103d7872545SSepherosa Ziehau 11042890cca3SSepherosa Ziehau /* 11052890cca3SSepherosa Ziehau * Set up the PCI DMA control register. 11062890cca3SSepherosa Ziehau */ 11072890cca3SSepherosa Ziehau dma_rw_ctl = pci_read_config(sc->bnx_dev, BGE_PCI_DMA_RW_CTL, 4); 11082890cca3SSepherosa Ziehau /* 11092890cca3SSepherosa Ziehau * Disable 32bytes cache alignment for DMA write to host memory 11102890cca3SSepherosa Ziehau * 11112890cca3SSepherosa Ziehau * NOTE: 11122890cca3SSepherosa Ziehau * 64bytes cache alignment for DMA write to host memory is still 11132890cca3SSepherosa Ziehau * enabled. 11142890cca3SSepherosa Ziehau */ 11152890cca3SSepherosa Ziehau dma_rw_ctl |= BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT; 11166c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) 11176c8d8eccSSepherosa Ziehau dma_rw_ctl &= ~BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK; 11186c8d8eccSSepherosa Ziehau /* 11196c8d8eccSSepherosa Ziehau * Enable HW workaround for controllers that misinterpret 11206c8d8eccSSepherosa Ziehau * a status tag update and leave interrupts permanently 11216c8d8eccSSepherosa Ziehau * disabled. 11226c8d8eccSSepherosa Ziehau */ 11236c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev != BGE_ASICREV_BCM5717 && 11242890cca3SSepherosa Ziehau !BNX_IS_57765_FAMILY(sc)) 11256c8d8eccSSepherosa Ziehau dma_rw_ctl |= BGE_PCIDMARWCTL_TAGGED_STATUS_WA; 11262890cca3SSepherosa Ziehau if (bootverbose) { 11272890cca3SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "DMA read/write %#x\n", 11282890cca3SSepherosa Ziehau dma_rw_ctl); 11296c8d8eccSSepherosa Ziehau } 11306c8d8eccSSepherosa Ziehau pci_write_config(sc->bnx_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4); 11316c8d8eccSSepherosa Ziehau 11326c8d8eccSSepherosa Ziehau /* 11336c8d8eccSSepherosa Ziehau * Set up general mode register. 11346c8d8eccSSepherosa Ziehau */ 11356c8d8eccSSepherosa Ziehau mode_ctl = bnx_dma_swap_options(sc) | BGE_MODECTL_MAC_ATTN_INTR | 11366c8d8eccSSepherosa Ziehau BGE_MODECTL_HOST_SEND_BDS | BGE_MODECTL_TX_NO_PHDR_CSUM; 11376c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 11386c8d8eccSSepherosa Ziehau 11396c8d8eccSSepherosa Ziehau /* 11406c8d8eccSSepherosa Ziehau * Disable memory write invalidate. Apparently it is not supported 11416c8d8eccSSepherosa Ziehau * properly by these devices. Also ensure that INTx isn't disabled, 11426c8d8eccSSepherosa Ziehau * as these chips need it even when using MSI. 11436c8d8eccSSepherosa Ziehau */ 11446c8d8eccSSepherosa Ziehau PCI_CLRBIT(sc->bnx_dev, BGE_PCI_CMD, 11456c8d8eccSSepherosa Ziehau (PCIM_CMD_MWRICEN | PCIM_CMD_INTxDIS), 4); 11466c8d8eccSSepherosa Ziehau 11476c8d8eccSSepherosa Ziehau /* Set the timer prescaler (always 66Mhz) */ 11486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_CFG, 65 << 1/*BGE_32BITTIME_66MHZ*/); 11496c8d8eccSSepherosa Ziehau 11506c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5906) { 11516c8d8eccSSepherosa Ziehau DELAY(40); /* XXX */ 11526c8d8eccSSepherosa Ziehau 11536c8d8eccSSepherosa Ziehau /* Put PHY into ready state */ 11546c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MISC_CFG, BGE_MISCCFG_EPHY_IDDQ); 11556c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_MISC_CFG); /* Flush */ 11566c8d8eccSSepherosa Ziehau DELAY(40); 11576c8d8eccSSepherosa Ziehau } 11586c8d8eccSSepherosa Ziehau 11596c8d8eccSSepherosa Ziehau return(0); 11606c8d8eccSSepherosa Ziehau } 11616c8d8eccSSepherosa Ziehau 11626c8d8eccSSepherosa Ziehau static int 11636c8d8eccSSepherosa Ziehau bnx_blockinit(struct bnx_softc *sc) 11646c8d8eccSSepherosa Ziehau { 11656c8d8eccSSepherosa Ziehau struct bge_rcb *rcb; 11666c8d8eccSSepherosa Ziehau bus_size_t vrcb; 11676c8d8eccSSepherosa Ziehau bge_hostaddr taddr; 11686c8d8eccSSepherosa Ziehau uint32_t val; 11696c8d8eccSSepherosa Ziehau int i, limit; 11706c8d8eccSSepherosa Ziehau 11716c8d8eccSSepherosa Ziehau /* 11726c8d8eccSSepherosa Ziehau * Initialize the memory window pointer register so that 11736c8d8eccSSepherosa Ziehau * we can access the first 32K of internal NIC RAM. This will 11746c8d8eccSSepherosa Ziehau * allow us to set up the TX send ring RCBs and the RX return 11756c8d8eccSSepherosa Ziehau * ring RCBs, plus other things which live in NIC memory. 11766c8d8eccSSepherosa Ziehau */ 11776c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCI_MEMWIN_BASEADDR, 0); 11786c8d8eccSSepherosa Ziehau 11796c8d8eccSSepherosa Ziehau /* Configure mbuf pool watermarks */ 1180f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 11816c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); 11826c8d8eccSSepherosa Ziehau if (sc->arpcom.ac_if.if_mtu > ETHERMTU) { 11836c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x7e); 11846c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xea); 11856c8d8eccSSepherosa Ziehau } else { 11866c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x2a); 11876c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xa0); 11886c8d8eccSSepherosa Ziehau } 11896c8d8eccSSepherosa Ziehau } else if (sc->bnx_asicrev == BGE_ASICREV_BCM5906) { 11906c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); 11916c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x04); 11926c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x10); 11936c8d8eccSSepherosa Ziehau } else { 11946c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); 11956c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10); 11966c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); 11976c8d8eccSSepherosa Ziehau } 11986c8d8eccSSepherosa Ziehau 11996c8d8eccSSepherosa Ziehau /* Configure DMA resource watermarks */ 12006c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LOWAT, 5); 12016c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10); 12026c8d8eccSSepherosa Ziehau 12036c8d8eccSSepherosa Ziehau /* Enable buffer manager */ 12046c8d8eccSSepherosa Ziehau val = BGE_BMANMODE_ENABLE | BGE_BMANMODE_LOMBUF_ATTN; 12056c8d8eccSSepherosa Ziehau /* 12066c8d8eccSSepherosa Ziehau * Change the arbitration algorithm of TXMBUF read request to 12076c8d8eccSSepherosa Ziehau * round-robin instead of priority based for BCM5719. When 12086c8d8eccSSepherosa Ziehau * TXFIFO is almost empty, RDMA will hold its request until 12096c8d8eccSSepherosa Ziehau * TXFIFO is not almost empty. 12106c8d8eccSSepherosa Ziehau */ 12116c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719) 12126c8d8eccSSepherosa Ziehau val |= BGE_BMANMODE_NO_TX_UNDERRUN; 1213e5eebe34SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 1214e5eebe34SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5719_A0 || 1215e5eebe34SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5720_A0) 1216e5eebe34SSepherosa Ziehau val |= BGE_BMANMODE_LOMBUF_ATTN; 12176c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MODE, val); 12186c8d8eccSSepherosa Ziehau 12196c8d8eccSSepherosa Ziehau /* Poll for buffer manager start indication */ 12206c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 12216c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE) 12226c8d8eccSSepherosa Ziehau break; 12236c8d8eccSSepherosa Ziehau DELAY(10); 12246c8d8eccSSepherosa Ziehau } 12256c8d8eccSSepherosa Ziehau 12266c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 12276c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 12286c8d8eccSSepherosa Ziehau "buffer manager failed to start\n"); 12296c8d8eccSSepherosa Ziehau return(ENXIO); 12306c8d8eccSSepherosa Ziehau } 12316c8d8eccSSepherosa Ziehau 12326c8d8eccSSepherosa Ziehau /* Enable flow-through queues */ 12336c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); 12346c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); 12356c8d8eccSSepherosa Ziehau 12366c8d8eccSSepherosa Ziehau /* Wait until queue initialization is complete */ 12376c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 12386c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_FTQ_RESET) == 0) 12396c8d8eccSSepherosa Ziehau break; 12406c8d8eccSSepherosa Ziehau DELAY(10); 12416c8d8eccSSepherosa Ziehau } 12426c8d8eccSSepherosa Ziehau 12436c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 12446c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 12456c8d8eccSSepherosa Ziehau "flow-through queue init failed\n"); 12466c8d8eccSSepherosa Ziehau return(ENXIO); 12476c8d8eccSSepherosa Ziehau } 12486c8d8eccSSepherosa Ziehau 12496c8d8eccSSepherosa Ziehau /* 12506c8d8eccSSepherosa Ziehau * Summary of rings supported by the controller: 12516c8d8eccSSepherosa Ziehau * 12526c8d8eccSSepherosa Ziehau * Standard Receive Producer Ring 12536c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for "standard" 12546c8d8eccSSepherosa Ziehau * sized frames (typically 1536 bytes) to the controller. 12556c8d8eccSSepherosa Ziehau * 12566c8d8eccSSepherosa Ziehau * Jumbo Receive Producer Ring 12576c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for jumbo sized 12586c8d8eccSSepherosa Ziehau * frames (i.e. anything bigger than the "standard" frames) 12596c8d8eccSSepherosa Ziehau * to the controller. 12606c8d8eccSSepherosa Ziehau * 12616c8d8eccSSepherosa Ziehau * Mini Receive Producer Ring 12626c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for "mini" 12636c8d8eccSSepherosa Ziehau * sized frames to the controller. 12646c8d8eccSSepherosa Ziehau * - This feature required external memory for the controller 12656c8d8eccSSepherosa Ziehau * but was never used in a production system. Should always 12666c8d8eccSSepherosa Ziehau * be disabled. 12676c8d8eccSSepherosa Ziehau * 12686c8d8eccSSepherosa Ziehau * Receive Return Ring 12696c8d8eccSSepherosa Ziehau * - After the controller has placed an incoming frame into a 12706c8d8eccSSepherosa Ziehau * receive buffer that buffer is moved into a receive return 12716c8d8eccSSepherosa Ziehau * ring. The driver is then responsible to passing the 12726c8d8eccSSepherosa Ziehau * buffer up to the stack. Many versions of the controller 12736c8d8eccSSepherosa Ziehau * support multiple RR rings. 12746c8d8eccSSepherosa Ziehau * 12756c8d8eccSSepherosa Ziehau * Send Ring 12766c8d8eccSSepherosa Ziehau * - This ring is used for outgoing frames. Many versions of 12776c8d8eccSSepherosa Ziehau * the controller support multiple send rings. 12786c8d8eccSSepherosa Ziehau */ 12796c8d8eccSSepherosa Ziehau 12806c8d8eccSSepherosa Ziehau /* Initialize the standard receive producer ring control block. */ 12816c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_std_rx_rcb; 12826c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo = 12836c8d8eccSSepherosa Ziehau BGE_ADDR_LO(sc->bnx_ldata.bnx_rx_std_ring_paddr); 12846c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi = 12856c8d8eccSSepherosa Ziehau BGE_ADDR_HI(sc->bnx_ldata.bnx_rx_std_ring_paddr); 1286f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 12876c8d8eccSSepherosa Ziehau /* 12886c8d8eccSSepherosa Ziehau * Bits 31-16: Programmable ring size (2048, 1024, 512, .., 32) 12896c8d8eccSSepherosa Ziehau * Bits 15-2 : Maximum RX frame size 12906c8d8eccSSepherosa Ziehau * Bit 1 : 1 = Ring Disabled, 0 = Ring ENabled 12916c8d8eccSSepherosa Ziehau * Bit 0 : Reserved 12926c8d8eccSSepherosa Ziehau */ 12936c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = 12946c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(512, BNX_MAX_FRAMELEN << 2); 12956c8d8eccSSepherosa Ziehau } else { 12966c8d8eccSSepherosa Ziehau /* 12976c8d8eccSSepherosa Ziehau * Bits 31-16: Programmable ring size (512, 256, 128, 64, 32) 12986c8d8eccSSepherosa Ziehau * Bits 15-2 : Reserved (should be 0) 12996c8d8eccSSepherosa Ziehau * Bit 1 : 1 = Ring Disabled, 0 = Ring Enabled 13006c8d8eccSSepherosa Ziehau * Bit 0 : Reserved 13016c8d8eccSSepherosa Ziehau */ 13026c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(512, 0); 13036c8d8eccSSepherosa Ziehau } 13046c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 13056c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 13066c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) 13076c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_STD_RX_RINGS_5717; 13086c8d8eccSSepherosa Ziehau else 13096c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_STD_RX_RINGS; 13106c8d8eccSSepherosa Ziehau /* Write the standard receive producer ring control block. */ 13116c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi); 13126c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_LO, rcb->bge_hostaddr.bge_addr_lo); 13136c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); 13146c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_NICADDR, rcb->bge_nicaddr); 13156c8d8eccSSepherosa Ziehau /* Reset the standard receive producer ring producer index. */ 13166c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0); 13176c8d8eccSSepherosa Ziehau 13186c8d8eccSSepherosa Ziehau /* 13196c8d8eccSSepherosa Ziehau * Initialize the jumbo RX producer ring control 13206c8d8eccSSepherosa Ziehau * block. We set the 'ring disabled' bit in the 13216c8d8eccSSepherosa Ziehau * flags field until we're actually ready to start 13226c8d8eccSSepherosa Ziehau * using this ring (i.e. once we set the MTU 13236c8d8eccSSepherosa Ziehau * high enough to require it). 13246c8d8eccSSepherosa Ziehau */ 13256c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 13266c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_jumbo_rx_rcb; 13276c8d8eccSSepherosa Ziehau /* Get the jumbo receive producer ring RCB parameters. */ 13286c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo = 13296c8d8eccSSepherosa Ziehau BGE_ADDR_LO(sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 13306c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi = 13316c8d8eccSSepherosa Ziehau BGE_ADDR_HI(sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 13326c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = 13336c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BNX_MAX_FRAMELEN, 13346c8d8eccSSepherosa Ziehau BGE_RCB_FLAG_RING_DISABLED); 13356c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 13366c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 13376c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) 13386c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS_5717; 13396c8d8eccSSepherosa Ziehau else 13406c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; 13416c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI, 13426c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi); 13436c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_LO, 13446c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo); 13456c8d8eccSSepherosa Ziehau /* Program the jumbo receive producer ring RCB parameters. */ 13466c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, 13476c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags); 13486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_NICADDR, rcb->bge_nicaddr); 13496c8d8eccSSepherosa Ziehau /* Reset the jumbo receive producer ring producer index. */ 13506c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0); 13516c8d8eccSSepherosa Ziehau } 13526c8d8eccSSepherosa Ziehau 13536c8d8eccSSepherosa Ziehau /* Choose de-pipeline mode for BCM5906 A0, A1 and A2. */ 13546c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5906 && 13556c8d8eccSSepherosa Ziehau (sc->bnx_chipid == BGE_CHIPID_BCM5906_A0 || 13566c8d8eccSSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5906_A1 || 13576c8d8eccSSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5906_A2)) { 13586c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_ISO_PKT_TX, 13596c8d8eccSSepherosa Ziehau (CSR_READ_4(sc, BGE_ISO_PKT_TX) & ~3) | 2); 13606c8d8eccSSepherosa Ziehau } 13616c8d8eccSSepherosa Ziehau 13626c8d8eccSSepherosa Ziehau /* 13636c8d8eccSSepherosa Ziehau * The BD ring replenish thresholds control how often the 13646c8d8eccSSepherosa Ziehau * hardware fetches new BD's from the producer rings in host 13656c8d8eccSSepherosa Ziehau * memory. Setting the value too low on a busy system can 13666c8d8eccSSepherosa Ziehau * starve the hardware and recue the throughpout. 13676c8d8eccSSepherosa Ziehau * 13686c8d8eccSSepherosa Ziehau * Set the BD ring replentish thresholds. The recommended 13696c8d8eccSSepherosa Ziehau * values are 1/8th the number of descriptors allocated to 13706c8d8eccSSepherosa Ziehau * each ring. 13716c8d8eccSSepherosa Ziehau */ 13726c8d8eccSSepherosa Ziehau val = 8; 13736c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, val); 13746c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 13756c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_JUMBO_REPL_THRESH, 13766c8d8eccSSepherosa Ziehau BGE_JUMBO_RX_RING_CNT/8); 13776c8d8eccSSepherosa Ziehau } 1378f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 13796c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_STD_REPLENISH_LWM, 32); 13806c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_JMB_REPLENISH_LWM, 16); 13816c8d8eccSSepherosa Ziehau } 13826c8d8eccSSepherosa Ziehau 13836c8d8eccSSepherosa Ziehau /* 13846c8d8eccSSepherosa Ziehau * Disable all send rings by setting the 'ring disabled' bit 13856c8d8eccSSepherosa Ziehau * in the flags field of all the TX send ring control blocks, 13866c8d8eccSSepherosa Ziehau * located in NIC memory. 13876c8d8eccSSepherosa Ziehau */ 138880969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 138980969639SSepherosa Ziehau limit = 4; 13904f23029eSSepherosa Ziehau else if (BNX_IS_57765_FAMILY(sc)) 13914f23029eSSepherosa Ziehau limit = 2; 139280969639SSepherosa Ziehau else 13936c8d8eccSSepherosa Ziehau limit = 1; 13946c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB; 13956c8d8eccSSepherosa Ziehau for (i = 0; i < limit; i++) { 13966c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 13976c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_RING_DISABLED)); 13986c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0); 13996c8d8eccSSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 14006c8d8eccSSepherosa Ziehau } 14016c8d8eccSSepherosa Ziehau 14026c8d8eccSSepherosa Ziehau /* Configure send ring RCB 0 (we use only the first ring) */ 14036c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB; 14046c8d8eccSSepherosa Ziehau BGE_HOSTADDR(taddr, sc->bnx_ldata.bnx_tx_ring_paddr); 14056c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, taddr.bge_addr_hi); 14066c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo); 14076c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 14086c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 14096c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 14106c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, BGE_SEND_RING_5717); 14116c8d8eccSSepherosa Ziehau } else { 14126c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, 14136c8d8eccSSepherosa Ziehau BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT)); 14146c8d8eccSSepherosa Ziehau } 14156c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 14166c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0)); 14176c8d8eccSSepherosa Ziehau 14186c8d8eccSSepherosa Ziehau /* 14196c8d8eccSSepherosa Ziehau * Disable all receive return rings by setting the 14206c8d8eccSSepherosa Ziehau * 'ring disabled' bit in the flags field of all the receive 14216c8d8eccSSepherosa Ziehau * return ring control blocks, located in NIC memory. 14226c8d8eccSSepherosa Ziehau */ 142380969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 14246c8d8eccSSepherosa Ziehau /* Should be 17, use 16 until we get an SRAM map. */ 14256c8d8eccSSepherosa Ziehau limit = 16; 14264f23029eSSepherosa Ziehau } else if (BNX_IS_57765_FAMILY(sc)) { 14276c8d8eccSSepherosa Ziehau limit = 4; 14286c8d8eccSSepherosa Ziehau } else { 14296c8d8eccSSepherosa Ziehau limit = 1; 14306c8d8eccSSepherosa Ziehau } 14316c8d8eccSSepherosa Ziehau /* Disable all receive return rings. */ 14326c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB; 14336c8d8eccSSepherosa Ziehau for (i = 0; i < limit; i++) { 14346c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, 0); 14356c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, 0); 14366c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 14376c8d8eccSSepherosa Ziehau BGE_RCB_FLAG_RING_DISABLED); 14386c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0); 14396c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_CONS0_LO + 14406c8d8eccSSepherosa Ziehau (i * (sizeof(uint64_t))), 0); 14416c8d8eccSSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 14426c8d8eccSSepherosa Ziehau } 14436c8d8eccSSepherosa Ziehau 14446c8d8eccSSepherosa Ziehau /* 14456c8d8eccSSepherosa Ziehau * Set up receive return ring 0. Note that the NIC address 14466c8d8eccSSepherosa Ziehau * for RX return rings is 0x0. The return rings live entirely 14476c8d8eccSSepherosa Ziehau * within the host, so the nicaddr field in the RCB isn't used. 14486c8d8eccSSepherosa Ziehau */ 14496c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB; 14506c8d8eccSSepherosa Ziehau BGE_HOSTADDR(taddr, sc->bnx_ldata.bnx_rx_return_ring_paddr); 14516c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, taddr.bge_addr_hi); 14526c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo); 14536c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0); 14546c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 14556c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(sc->bnx_return_ring_cnt, 0)); 14566c8d8eccSSepherosa Ziehau 14576c8d8eccSSepherosa Ziehau /* Set random backoff seed for TX */ 14586c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_RANDOM_BACKOFF, 14596c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[0] + sc->arpcom.ac_enaddr[1] + 14606c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[2] + sc->arpcom.ac_enaddr[3] + 14616c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[4] + sc->arpcom.ac_enaddr[5] + 14626c8d8eccSSepherosa Ziehau BGE_TX_BACKOFF_SEED_MASK); 14636c8d8eccSSepherosa Ziehau 14646c8d8eccSSepherosa Ziehau /* Set inter-packet gap */ 14656c8d8eccSSepherosa Ziehau val = 0x2620; 14666c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 14676c8d8eccSSepherosa Ziehau val |= CSR_READ_4(sc, BGE_TX_LENGTHS) & 14686c8d8eccSSepherosa Ziehau (BGE_TXLEN_JMB_FRM_LEN_MSK | BGE_TXLEN_CNT_DN_VAL_MSK); 14696c8d8eccSSepherosa Ziehau } 14706c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_LENGTHS, val); 14716c8d8eccSSepherosa Ziehau 14726c8d8eccSSepherosa Ziehau /* 14736c8d8eccSSepherosa Ziehau * Specify which ring to use for packets that don't match 14746c8d8eccSSepherosa Ziehau * any RX rules. 14756c8d8eccSSepherosa Ziehau */ 14766c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_RULES_CFG, 0x08); 14776c8d8eccSSepherosa Ziehau 14786c8d8eccSSepherosa Ziehau /* 14796c8d8eccSSepherosa Ziehau * Configure number of RX lists. One interrupt distribution 14806c8d8eccSSepherosa Ziehau * list, sixteen active lists, one bad frames class. 14816c8d8eccSSepherosa Ziehau */ 14826c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_CFG, 0x181); 14836c8d8eccSSepherosa Ziehau 14846c8d8eccSSepherosa Ziehau /* Inialize RX list placement stats mask. */ 14856c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_STATS_ENABLE_MASK, 0x007FFFFF); 14866c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_STATS_CTL, 0x1); 14876c8d8eccSSepherosa Ziehau 14886c8d8eccSSepherosa Ziehau /* Disable host coalescing until we get it set up */ 14896c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_MODE, 0x00000000); 14906c8d8eccSSepherosa Ziehau 14916c8d8eccSSepherosa Ziehau /* Poll to make sure it's shut down. */ 14926c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 14936c8d8eccSSepherosa Ziehau if (!(CSR_READ_4(sc, BGE_HCC_MODE) & BGE_HCCMODE_ENABLE)) 14946c8d8eccSSepherosa Ziehau break; 14956c8d8eccSSepherosa Ziehau DELAY(10); 14966c8d8eccSSepherosa Ziehau } 14976c8d8eccSSepherosa Ziehau 14986c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 14996c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 15006c8d8eccSSepherosa Ziehau "host coalescing engine failed to idle\n"); 15016c8d8eccSSepherosa Ziehau return(ENXIO); 15026c8d8eccSSepherosa Ziehau } 15036c8d8eccSSepherosa Ziehau 15046c8d8eccSSepherosa Ziehau /* Set up host coalescing defaults */ 15056c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS, sc->bnx_rx_coal_ticks); 15066c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, sc->bnx_tx_coal_ticks); 15076c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, sc->bnx_rx_coal_bds); 15086c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, sc->bnx_tx_coal_bds); 15096c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, sc->bnx_rx_coal_bds_int); 15106c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, sc->bnx_tx_coal_bds_int); 15116c8d8eccSSepherosa Ziehau 15126c8d8eccSSepherosa Ziehau /* Set up address of status block */ 15136c8d8eccSSepherosa Ziehau bzero(sc->bnx_ldata.bnx_status_block, BGE_STATUS_BLK_SZ); 15146c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_HI, 15156c8d8eccSSepherosa Ziehau BGE_ADDR_HI(sc->bnx_ldata.bnx_status_block_paddr)); 15166c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_LO, 15176c8d8eccSSepherosa Ziehau BGE_ADDR_LO(sc->bnx_ldata.bnx_status_block_paddr)); 15186c8d8eccSSepherosa Ziehau 15196c8d8eccSSepherosa Ziehau /* Set up status block partail update size. */ 15206c8d8eccSSepherosa Ziehau val = BGE_STATBLKSZ_32BYTE; 15216c8d8eccSSepherosa Ziehau #if 0 15226c8d8eccSSepherosa Ziehau /* 15236c8d8eccSSepherosa Ziehau * Does not seem to have visible effect in both 15246c8d8eccSSepherosa Ziehau * bulk data (1472B UDP datagram) and tiny data 15256c8d8eccSSepherosa Ziehau * (18B UDP datagram) TX tests. 15266c8d8eccSSepherosa Ziehau */ 15276c8d8eccSSepherosa Ziehau val |= BGE_HCCMODE_CLRTICK_TX; 15286c8d8eccSSepherosa Ziehau #endif 15296c8d8eccSSepherosa Ziehau /* Turn on host coalescing state machine */ 15306c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_MODE, val | BGE_HCCMODE_ENABLE); 15316c8d8eccSSepherosa Ziehau 15326c8d8eccSSepherosa Ziehau /* Turn on RX BD completion state machine and enable attentions */ 15336c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDC_MODE, 15346c8d8eccSSepherosa Ziehau BGE_RBDCMODE_ENABLE|BGE_RBDCMODE_ATTN); 15356c8d8eccSSepherosa Ziehau 15366c8d8eccSSepherosa Ziehau /* Turn on RX list placement state machine */ 15376c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); 15386c8d8eccSSepherosa Ziehau 15396c8d8eccSSepherosa Ziehau val = BGE_MACMODE_TXDMA_ENB | BGE_MACMODE_RXDMA_ENB | 15406c8d8eccSSepherosa Ziehau BGE_MACMODE_RX_STATS_CLEAR | BGE_MACMODE_TX_STATS_CLEAR | 15416c8d8eccSSepherosa Ziehau BGE_MACMODE_RX_STATS_ENB | BGE_MACMODE_TX_STATS_ENB | 15426c8d8eccSSepherosa Ziehau BGE_MACMODE_FRMHDR_DMA_ENB; 15436c8d8eccSSepherosa Ziehau 15446c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) 15456c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_TBI; 15466c8d8eccSSepherosa Ziehau else if (sc->bnx_flags & BNX_FLAG_MII_SERDES) 15476c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_GMII; 15486c8d8eccSSepherosa Ziehau else 15496c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_MII; 15506c8d8eccSSepherosa Ziehau 15516c8d8eccSSepherosa Ziehau /* Turn on DMA, clear stats */ 15526c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, val); 15536c8d8eccSSepherosa Ziehau 15546c8d8eccSSepherosa Ziehau /* Set misc. local control, enable interrupts on attentions */ 15556c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN); 15566c8d8eccSSepherosa Ziehau 15576c8d8eccSSepherosa Ziehau #ifdef notdef 15586c8d8eccSSepherosa Ziehau /* Assert GPIO pins for PHY reset */ 15596c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUT0| 15606c8d8eccSSepherosa Ziehau BGE_MLC_MISCIO_OUT1|BGE_MLC_MISCIO_OUT2); 15616c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUTEN0| 15626c8d8eccSSepherosa Ziehau BGE_MLC_MISCIO_OUTEN1|BGE_MLC_MISCIO_OUTEN2); 15636c8d8eccSSepherosa Ziehau #endif 15646c8d8eccSSepherosa Ziehau 15656c8d8eccSSepherosa Ziehau /* Turn on write DMA state machine */ 15666c8d8eccSSepherosa Ziehau val = BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS; 15676c8d8eccSSepherosa Ziehau /* Enable host coalescing bug fix. */ 15686c8d8eccSSepherosa Ziehau val |= BGE_WDMAMODE_STATUS_TAG_FIX; 15696c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5785) { 15706c8d8eccSSepherosa Ziehau /* Request larger DMA burst size to get better performance. */ 15716c8d8eccSSepherosa Ziehau val |= BGE_WDMAMODE_BURST_ALL_DATA; 15726c8d8eccSSepherosa Ziehau } 15736c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_WDMA_MODE, val); 15746c8d8eccSSepherosa Ziehau DELAY(40); 15756c8d8eccSSepherosa Ziehau 15763730a14dSSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 15776c8d8eccSSepherosa Ziehau uint32_t dmactl; 15786c8d8eccSSepherosa Ziehau 15796c8d8eccSSepherosa Ziehau dmactl = CSR_READ_4(sc, BGE_RDMA_RSRVCTRL); 15806c8d8eccSSepherosa Ziehau /* 15816c8d8eccSSepherosa Ziehau * Adjust tx margin to prevent TX data corruption and 15826c8d8eccSSepherosa Ziehau * fix internal FIFO overflow. 15836c8d8eccSSepherosa Ziehau */ 15846c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 15856c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 15866c8d8eccSSepherosa Ziehau dmactl &= ~(BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK | 15876c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK | 15886c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_TXMRGN_MASK); 15896c8d8eccSSepherosa Ziehau dmactl |= BGE_RDMA_RSRVCTRL_FIFO_LWM_1_5K | 15906c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_FIFO_HWM_1_5K | 15916c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_TXMRGN_320B; 15926c8d8eccSSepherosa Ziehau } 15936c8d8eccSSepherosa Ziehau /* 15946c8d8eccSSepherosa Ziehau * Enable fix for read DMA FIFO overruns. 15956c8d8eccSSepherosa Ziehau * The fix is to limit the number of RX BDs 15966c8d8eccSSepherosa Ziehau * the hardware would fetch at a fime. 15976c8d8eccSSepherosa Ziehau */ 15986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_RSRVCTRL, 15996c8d8eccSSepherosa Ziehau dmactl | BGE_RDMA_RSRVCTRL_FIFO_OFLW_FIX); 16006c8d8eccSSepherosa Ziehau } 16016c8d8eccSSepherosa Ziehau 16026c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719) { 16036c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, 16046c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) | 16056c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K | 16066c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K); 16076c8d8eccSSepherosa Ziehau } else if (sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 16086c8d8eccSSepherosa Ziehau /* 16096c8d8eccSSepherosa Ziehau * Allow 4KB burst length reads for non-LSO frames. 16106c8d8eccSSepherosa Ziehau * Enable 512B burst length reads for buffer descriptors. 16116c8d8eccSSepherosa Ziehau */ 16126c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, 16136c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) | 16146c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 | 16156c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K); 16166c8d8eccSSepherosa Ziehau } 16176c8d8eccSSepherosa Ziehau 16186c8d8eccSSepherosa Ziehau /* Turn on read DMA state machine */ 16196c8d8eccSSepherosa Ziehau val = BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS; 16206c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717) 16216c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_MULT_DMA_RD_DIS; 16226c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5784 || 16236c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5785 || 16246c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM57780) { 16256c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_BD_SBD_CRPT_ATTN | 16266c8d8eccSSepherosa Ziehau BGE_RDMAMODE_MBUF_RBD_CRPT_ATTN | 16276c8d8eccSSepherosa Ziehau BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN; 16286c8d8eccSSepherosa Ziehau } 16296c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 16306c8d8eccSSepherosa Ziehau val |= CSR_READ_4(sc, BGE_RDMA_MODE) & 16316c8d8eccSSepherosa Ziehau BGE_RDMAMODE_H2BNC_VLAN_DET; 16326c8d8eccSSepherosa Ziehau /* 16336c8d8eccSSepherosa Ziehau * Allow multiple outstanding read requests from 16346c8d8eccSSepherosa Ziehau * non-LSO read DMA engine. 16356c8d8eccSSepherosa Ziehau */ 16366c8d8eccSSepherosa Ziehau val &= ~BGE_RDMAMODE_MULT_DMA_RD_DIS; 16376c8d8eccSSepherosa Ziehau } 16386c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_FIFO_LONG_BURST; 16396c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_MODE, val); 16406c8d8eccSSepherosa Ziehau DELAY(40); 16416c8d8eccSSepherosa Ziehau 16426c8d8eccSSepherosa Ziehau /* Turn on RX data completion state machine */ 16436c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); 16446c8d8eccSSepherosa Ziehau 16456c8d8eccSSepherosa Ziehau /* Turn on RX BD initiator state machine */ 16466c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); 16476c8d8eccSSepherosa Ziehau 16486c8d8eccSSepherosa Ziehau /* Turn on RX data and RX BD initiator state machine */ 16496c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDBDI_MODE, BGE_RDBDIMODE_ENABLE); 16506c8d8eccSSepherosa Ziehau 16516c8d8eccSSepherosa Ziehau /* Turn on send BD completion state machine */ 16526c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); 16536c8d8eccSSepherosa Ziehau 16546c8d8eccSSepherosa Ziehau /* Turn on send data completion state machine */ 16556c8d8eccSSepherosa Ziehau val = BGE_SDCMODE_ENABLE; 16566c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5761) 16576c8d8eccSSepherosa Ziehau val |= BGE_SDCMODE_CDELAY; 16586c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDC_MODE, val); 16596c8d8eccSSepherosa Ziehau 16606c8d8eccSSepherosa Ziehau /* Turn on send data initiator state machine */ 16616c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); 16626c8d8eccSSepherosa Ziehau 16636c8d8eccSSepherosa Ziehau /* Turn on send BD initiator state machine */ 16646c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); 16656c8d8eccSSepherosa Ziehau 16666c8d8eccSSepherosa Ziehau /* Turn on send BD selector state machine */ 16676c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); 16686c8d8eccSSepherosa Ziehau 16696c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_STATS_ENABLE_MASK, 0x007FFFFF); 16706c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_STATS_CTL, 16716c8d8eccSSepherosa Ziehau BGE_SDISTATSCTL_ENABLE|BGE_SDISTATSCTL_FASTER); 16726c8d8eccSSepherosa Ziehau 16736c8d8eccSSepherosa Ziehau /* ack/clear link change events */ 16746c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| 16756c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| 16766c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 16776c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_STS, 0); 16786c8d8eccSSepherosa Ziehau 16796c8d8eccSSepherosa Ziehau /* 16806c8d8eccSSepherosa Ziehau * Enable attention when the link has changed state for 16816c8d8eccSSepherosa Ziehau * devices that use auto polling. 16826c8d8eccSSepherosa Ziehau */ 16836c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 16846c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK); 16856c8d8eccSSepherosa Ziehau } else { 16866c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 16876c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 16886c8d8eccSSepherosa Ziehau DELAY(80); 16896c8d8eccSSepherosa Ziehau } 16906c8d8eccSSepherosa Ziehau } 16916c8d8eccSSepherosa Ziehau 16926c8d8eccSSepherosa Ziehau /* 16936c8d8eccSSepherosa Ziehau * Clear any pending link state attention. 16946c8d8eccSSepherosa Ziehau * Otherwise some link state change events may be lost until attention 16956c8d8eccSSepherosa Ziehau * is cleared by bnx_intr() -> bnx_softc.bnx_link_upd() sequence. 16966c8d8eccSSepherosa Ziehau * It's not necessary on newer BCM chips - perhaps enabling link 16976c8d8eccSSepherosa Ziehau * state change attentions implies clearing pending attention. 16986c8d8eccSSepherosa Ziehau */ 16996c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| 17006c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| 17016c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 17026c8d8eccSSepherosa Ziehau 17036c8d8eccSSepherosa Ziehau /* Enable link state change attentions. */ 17046c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_EVT_ENB, BGE_EVTENB_LINK_CHANGED); 17056c8d8eccSSepherosa Ziehau 17066c8d8eccSSepherosa Ziehau return(0); 17076c8d8eccSSepherosa Ziehau } 17086c8d8eccSSepherosa Ziehau 17096c8d8eccSSepherosa Ziehau /* 17106c8d8eccSSepherosa Ziehau * Probe for a Broadcom chip. Check the PCI vendor and device IDs 17116c8d8eccSSepherosa Ziehau * against our list and return its name if we find a match. Note 17126c8d8eccSSepherosa Ziehau * that since the Broadcom controller contains VPD support, we 17136c8d8eccSSepherosa Ziehau * can get the device name string from the controller itself instead 17146c8d8eccSSepherosa Ziehau * of the compiled-in string. This is a little slow, but it guarantees 17156c8d8eccSSepherosa Ziehau * we'll always announce the right product name. 17166c8d8eccSSepherosa Ziehau */ 17176c8d8eccSSepherosa Ziehau static int 17186c8d8eccSSepherosa Ziehau bnx_probe(device_t dev) 17196c8d8eccSSepherosa Ziehau { 17206c8d8eccSSepherosa Ziehau const struct bnx_type *t; 17216c8d8eccSSepherosa Ziehau uint16_t product, vendor; 17226c8d8eccSSepherosa Ziehau 17236c8d8eccSSepherosa Ziehau if (!pci_is_pcie(dev)) 17246c8d8eccSSepherosa Ziehau return ENXIO; 17256c8d8eccSSepherosa Ziehau 17266c8d8eccSSepherosa Ziehau product = pci_get_device(dev); 17276c8d8eccSSepherosa Ziehau vendor = pci_get_vendor(dev); 17286c8d8eccSSepherosa Ziehau 17296c8d8eccSSepherosa Ziehau for (t = bnx_devs; t->bnx_name != NULL; t++) { 17306c8d8eccSSepherosa Ziehau if (vendor == t->bnx_vid && product == t->bnx_did) 17316c8d8eccSSepherosa Ziehau break; 17326c8d8eccSSepherosa Ziehau } 17336c8d8eccSSepherosa Ziehau if (t->bnx_name == NULL) 17346c8d8eccSSepherosa Ziehau return ENXIO; 17356c8d8eccSSepherosa Ziehau 17366c8d8eccSSepherosa Ziehau device_set_desc(dev, t->bnx_name); 17376c8d8eccSSepherosa Ziehau return 0; 17386c8d8eccSSepherosa Ziehau } 17396c8d8eccSSepherosa Ziehau 17406c8d8eccSSepherosa Ziehau static int 17416c8d8eccSSepherosa Ziehau bnx_attach(device_t dev) 17426c8d8eccSSepherosa Ziehau { 17436c8d8eccSSepherosa Ziehau struct ifnet *ifp; 17446c8d8eccSSepherosa Ziehau struct bnx_softc *sc; 17456c8d8eccSSepherosa Ziehau uint32_t hwcfg = 0, misccfg; 17466c8d8eccSSepherosa Ziehau int error = 0, rid, capmask; 17476c8d8eccSSepherosa Ziehau uint8_t ether_addr[ETHER_ADDR_LEN]; 17486c8d8eccSSepherosa Ziehau uint16_t product, vendor; 17496c8d8eccSSepherosa Ziehau driver_intr_t *intr_func; 17506c8d8eccSSepherosa Ziehau uintptr_t mii_priv = 0; 17516c8d8eccSSepherosa Ziehau u_int intr_flags; 17526c8d8eccSSepherosa Ziehau 17536c8d8eccSSepherosa Ziehau sc = device_get_softc(dev); 17546c8d8eccSSepherosa Ziehau sc->bnx_dev = dev; 175550668ed5SSepherosa Ziehau callout_init_mp(&sc->bnx_stat_timer); 1756*df9ccc98SSepherosa Ziehau callout_init_mp(&sc->bnx_intr_timer); 17576c8d8eccSSepherosa Ziehau lwkt_serialize_init(&sc->bnx_jslot_serializer); 17586c8d8eccSSepherosa Ziehau 17596c8d8eccSSepherosa Ziehau product = pci_get_device(dev); 17606c8d8eccSSepherosa Ziehau vendor = pci_get_vendor(dev); 17616c8d8eccSSepherosa Ziehau 17626c8d8eccSSepherosa Ziehau #ifndef BURN_BRIDGES 17636c8d8eccSSepherosa Ziehau if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 17646c8d8eccSSepherosa Ziehau uint32_t irq, mem; 17656c8d8eccSSepherosa Ziehau 17666c8d8eccSSepherosa Ziehau irq = pci_read_config(dev, PCIR_INTLINE, 4); 17676c8d8eccSSepherosa Ziehau mem = pci_read_config(dev, BGE_PCI_BAR0, 4); 17686c8d8eccSSepherosa Ziehau 17696c8d8eccSSepherosa Ziehau device_printf(dev, "chip is in D%d power mode " 17706c8d8eccSSepherosa Ziehau "-- setting to D0\n", pci_get_powerstate(dev)); 17716c8d8eccSSepherosa Ziehau 17726c8d8eccSSepherosa Ziehau pci_set_powerstate(dev, PCI_POWERSTATE_D0); 17736c8d8eccSSepherosa Ziehau 17746c8d8eccSSepherosa Ziehau pci_write_config(dev, PCIR_INTLINE, irq, 4); 17756c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_BAR0, mem, 4); 17766c8d8eccSSepherosa Ziehau } 17776c8d8eccSSepherosa Ziehau #endif /* !BURN_BRIDGE */ 17786c8d8eccSSepherosa Ziehau 17796c8d8eccSSepherosa Ziehau /* 17806c8d8eccSSepherosa Ziehau * Map control/status registers. 17816c8d8eccSSepherosa Ziehau */ 17826c8d8eccSSepherosa Ziehau pci_enable_busmaster(dev); 17836c8d8eccSSepherosa Ziehau 17846c8d8eccSSepherosa Ziehau rid = BGE_PCI_BAR0; 17856c8d8eccSSepherosa Ziehau sc->bnx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 17866c8d8eccSSepherosa Ziehau RF_ACTIVE); 17876c8d8eccSSepherosa Ziehau 17886c8d8eccSSepherosa Ziehau if (sc->bnx_res == NULL) { 17896c8d8eccSSepherosa Ziehau device_printf(dev, "couldn't map memory\n"); 17906c8d8eccSSepherosa Ziehau return ENXIO; 17916c8d8eccSSepherosa Ziehau } 17926c8d8eccSSepherosa Ziehau 17936c8d8eccSSepherosa Ziehau sc->bnx_btag = rman_get_bustag(sc->bnx_res); 17946c8d8eccSSepherosa Ziehau sc->bnx_bhandle = rman_get_bushandle(sc->bnx_res); 17956c8d8eccSSepherosa Ziehau 17966c8d8eccSSepherosa Ziehau /* Save various chip information */ 17976c8d8eccSSepherosa Ziehau sc->bnx_chipid = 17986c8d8eccSSepherosa Ziehau pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> 17996c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_ASICREV_SHIFT; 18006c8d8eccSSepherosa Ziehau if (BGE_ASICREV(sc->bnx_chipid) == BGE_ASICREV_USE_PRODID_REG) { 18016c8d8eccSSepherosa Ziehau /* All chips having dedicated ASICREV register have CPMU */ 18026c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_CPMU; 18036c8d8eccSSepherosa Ziehau 18046c8d8eccSSepherosa Ziehau switch (product) { 18056c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5717: 18066c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5718: 18076c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5719: 18086c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5720_ALT: 18096c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 18106c8d8eccSSepherosa Ziehau BGE_PCI_GEN2_PRODID_ASICREV, 4); 18116c8d8eccSSepherosa Ziehau break; 18126c8d8eccSSepherosa Ziehau 18136c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57761: 181432ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57762: 18156c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57765: 181632ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57766: 18176c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57781: 181832ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57782: 18196c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57785: 182032ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57786: 18216c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57791: 18226c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57795: 18236c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 18246c8d8eccSSepherosa Ziehau BGE_PCI_GEN15_PRODID_ASICREV, 4); 18256c8d8eccSSepherosa Ziehau break; 18266c8d8eccSSepherosa Ziehau 18276c8d8eccSSepherosa Ziehau default: 18286c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 18296c8d8eccSSepherosa Ziehau BGE_PCI_PRODID_ASICREV, 4); 18306c8d8eccSSepherosa Ziehau break; 18316c8d8eccSSepherosa Ziehau } 18326c8d8eccSSepherosa Ziehau } 18336c8d8eccSSepherosa Ziehau sc->bnx_asicrev = BGE_ASICREV(sc->bnx_chipid); 18346c8d8eccSSepherosa Ziehau sc->bnx_chiprev = BGE_CHIPREV(sc->bnx_chipid); 18356c8d8eccSSepherosa Ziehau 18366c8d8eccSSepherosa Ziehau switch (sc->bnx_asicrev) { 18376c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5717: 18386c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5719: 18396c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5720: 1840f368d0d9SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_5717_PLUS | BNX_FLAG_57765_PLUS; 1841f368d0d9SSepherosa Ziehau break; 1842f368d0d9SSepherosa Ziehau 18436c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM57765: 184432ff3c80SSepherosa Ziehau case BGE_ASICREV_BCM57766: 1845f368d0d9SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_57765_FAMILY | BNX_FLAG_57765_PLUS; 18466c8d8eccSSepherosa Ziehau break; 18476c8d8eccSSepherosa Ziehau } 18486c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_SHORTDMA; 18496c8d8eccSSepherosa Ziehau 1850*df9ccc98SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 1851*df9ccc98SSepherosa Ziehau BNX_IS_57765_FAMILY(sc)) { 1852*df9ccc98SSepherosa Ziehau /* 1853*df9ccc98SSepherosa Ziehau * All BCM57785 and BCM5718 families chips have a bug that 1854*df9ccc98SSepherosa Ziehau * under certain situation interrupt will not be enabled 1855*df9ccc98SSepherosa Ziehau * even if status tag is written to BGE_MBX_IRQ0_LO mailbox. 1856*df9ccc98SSepherosa Ziehau * 1857*df9ccc98SSepherosa Ziehau * While BCM5719 and BCM5720 have a hardware workaround 1858*df9ccc98SSepherosa Ziehau * which could fix the above bug. 1859*df9ccc98SSepherosa Ziehau * See the comment near BGE_PCIDMARWCTL_TAGGED_STATUS_WA in 1860*df9ccc98SSepherosa Ziehau * bnx_chipinit(). 1861*df9ccc98SSepherosa Ziehau * 1862*df9ccc98SSepherosa Ziehau * For the rest of the chips in these two families, we will 1863*df9ccc98SSepherosa Ziehau * have to poll the status block at high rate (10ms currently) 1864*df9ccc98SSepherosa Ziehau * to check whether the interrupt is hosed or not. 1865*df9ccc98SSepherosa Ziehau * See bnx_intr_check() for details. 1866*df9ccc98SSepherosa Ziehau */ 1867*df9ccc98SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_STATUSTAG_BUG; 1868*df9ccc98SSepherosa Ziehau } 1869*df9ccc98SSepherosa Ziehau 18706c8d8eccSSepherosa Ziehau misccfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID_MASK; 18716c8d8eccSSepherosa Ziehau 18726c8d8eccSSepherosa Ziehau sc->bnx_pciecap = pci_get_pciecap_ptr(sc->bnx_dev); 18736c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 18746c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) 18756c8d8eccSSepherosa Ziehau pcie_set_max_readrq(dev, PCIEM_DEVCTL_MAX_READRQ_2048); 18766c8d8eccSSepherosa Ziehau else 18776c8d8eccSSepherosa Ziehau pcie_set_max_readrq(dev, PCIEM_DEVCTL_MAX_READRQ_4096); 18786c8d8eccSSepherosa Ziehau device_printf(dev, "CHIP ID 0x%08x; " 18796c8d8eccSSepherosa Ziehau "ASIC REV 0x%02x; CHIP REV 0x%02x\n", 18806c8d8eccSSepherosa Ziehau sc->bnx_chipid, sc->bnx_asicrev, sc->bnx_chiprev); 18816c8d8eccSSepherosa Ziehau 18826c8d8eccSSepherosa Ziehau /* 18836c8d8eccSSepherosa Ziehau * Set various PHY quirk flags. 18846c8d8eccSSepherosa Ziehau */ 18856c8d8eccSSepherosa Ziehau 18866c8d8eccSSepherosa Ziehau capmask = MII_CAPMASK_DEFAULT; 188746283a40SSepherosa Ziehau if (product == PCI_PRODUCT_BROADCOM_BCM57791 || 188846283a40SSepherosa Ziehau product == PCI_PRODUCT_BROADCOM_BCM57795) { 18896c8d8eccSSepherosa Ziehau /* 10/100 only */ 18906c8d8eccSSepherosa Ziehau capmask &= ~BMSR_EXTSTAT; 18916c8d8eccSSepherosa Ziehau } 18926c8d8eccSSepherosa Ziehau 18936c8d8eccSSepherosa Ziehau mii_priv |= BRGPHY_FLAG_WIRESPEED; 18946c8d8eccSSepherosa Ziehau 18956c8d8eccSSepherosa Ziehau /* 18966c8d8eccSSepherosa Ziehau * Allocate interrupt 18976c8d8eccSSepherosa Ziehau */ 18986c8d8eccSSepherosa Ziehau sc->bnx_irq_type = pci_alloc_1intr(dev, bnx_msi_enable, &sc->bnx_irq_rid, 18996c8d8eccSSepherosa Ziehau &intr_flags); 19006c8d8eccSSepherosa Ziehau 19016c8d8eccSSepherosa Ziehau sc->bnx_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->bnx_irq_rid, 19026c8d8eccSSepherosa Ziehau intr_flags); 19036c8d8eccSSepherosa Ziehau if (sc->bnx_irq == NULL) { 19046c8d8eccSSepherosa Ziehau device_printf(dev, "couldn't map interrupt\n"); 19056c8d8eccSSepherosa Ziehau error = ENXIO; 19066c8d8eccSSepherosa Ziehau goto fail; 19076c8d8eccSSepherosa Ziehau } 19086c8d8eccSSepherosa Ziehau 19096c8d8eccSSepherosa Ziehau if (sc->bnx_irq_type == PCI_INTR_TYPE_MSI) { 19106c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_ONESHOT_MSI; 19116c8d8eccSSepherosa Ziehau bnx_enable_msi(sc); 19126c8d8eccSSepherosa Ziehau } 19136c8d8eccSSepherosa Ziehau 19146c8d8eccSSepherosa Ziehau /* Initialize if_name earlier, so if_printf could be used */ 19156c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 19166c8d8eccSSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 19176c8d8eccSSepherosa Ziehau 19186c8d8eccSSepherosa Ziehau /* Try to reset the chip. */ 19196c8d8eccSSepherosa Ziehau bnx_reset(sc); 19206c8d8eccSSepherosa Ziehau 19216c8d8eccSSepherosa Ziehau if (bnx_chipinit(sc)) { 19226c8d8eccSSepherosa Ziehau device_printf(dev, "chip initialization failed\n"); 19236c8d8eccSSepherosa Ziehau error = ENXIO; 19246c8d8eccSSepherosa Ziehau goto fail; 19256c8d8eccSSepherosa Ziehau } 19266c8d8eccSSepherosa Ziehau 19276c8d8eccSSepherosa Ziehau /* 19286c8d8eccSSepherosa Ziehau * Get station address 19296c8d8eccSSepherosa Ziehau */ 19306c8d8eccSSepherosa Ziehau error = bnx_get_eaddr(sc, ether_addr); 19316c8d8eccSSepherosa Ziehau if (error) { 19326c8d8eccSSepherosa Ziehau device_printf(dev, "failed to read station address\n"); 19336c8d8eccSSepherosa Ziehau goto fail; 19346c8d8eccSSepherosa Ziehau } 19356c8d8eccSSepherosa Ziehau 1936f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 19376c8d8eccSSepherosa Ziehau sc->bnx_return_ring_cnt = BGE_RETURN_RING_CNT; 19386c8d8eccSSepherosa Ziehau } else { 19396c8d8eccSSepherosa Ziehau /* 5705/5750 limits RX return ring to 512 entries. */ 19406c8d8eccSSepherosa Ziehau sc->bnx_return_ring_cnt = BGE_RETURN_RING_CNT_5705; 19416c8d8eccSSepherosa Ziehau } 19426c8d8eccSSepherosa Ziehau 19436c8d8eccSSepherosa Ziehau error = bnx_dma_alloc(sc); 19446c8d8eccSSepherosa Ziehau if (error) 19456c8d8eccSSepherosa Ziehau goto fail; 19466c8d8eccSSepherosa Ziehau 19476c8d8eccSSepherosa Ziehau /* Set default tuneable values. */ 19486c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks = BNX_RX_COAL_TICKS_DEF; 19496c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks = BNX_TX_COAL_TICKS_DEF; 19506c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds = BNX_RX_COAL_BDS_DEF; 19516c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds = BNX_TX_COAL_BDS_DEF; 19526c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds_int = BNX_RX_COAL_BDS_DEF; 19536c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds_int = BNX_TX_COAL_BDS_DEF; 19546c8d8eccSSepherosa Ziehau 19556c8d8eccSSepherosa Ziehau /* Set up ifnet structure */ 19566c8d8eccSSepherosa Ziehau ifp->if_softc = sc; 19576c8d8eccSSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 19586c8d8eccSSepherosa Ziehau ifp->if_ioctl = bnx_ioctl; 19596c8d8eccSSepherosa Ziehau ifp->if_start = bnx_start; 19606c8d8eccSSepherosa Ziehau #ifdef DEVICE_POLLING 19616c8d8eccSSepherosa Ziehau ifp->if_poll = bnx_poll; 19626c8d8eccSSepherosa Ziehau #endif 19636c8d8eccSSepherosa Ziehau ifp->if_watchdog = bnx_watchdog; 19646c8d8eccSSepherosa Ziehau ifp->if_init = bnx_init; 19656c8d8eccSSepherosa Ziehau ifp->if_mtu = ETHERMTU; 19666c8d8eccSSepherosa Ziehau ifp->if_capabilities = IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 19676c8d8eccSSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, BGE_TX_RING_CNT - 1); 19686c8d8eccSSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 19696c8d8eccSSepherosa Ziehau 19706c8d8eccSSepherosa Ziehau ifp->if_capabilities |= IFCAP_HWCSUM; 19716c8d8eccSSepherosa Ziehau ifp->if_hwassist = BNX_CSUM_FEATURES; 19726c8d8eccSSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 19736c8d8eccSSepherosa Ziehau 19746c8d8eccSSepherosa Ziehau /* 19756c8d8eccSSepherosa Ziehau * Figure out what sort of media we have by checking the 19766c8d8eccSSepherosa Ziehau * hardware config word in the first 32k of NIC internal memory, 19776c8d8eccSSepherosa Ziehau * or fall back to examining the EEPROM if necessary. 19786c8d8eccSSepherosa Ziehau * Note: on some BCM5700 cards, this value appears to be unset. 19796c8d8eccSSepherosa Ziehau * If that's the case, we have to rely on identifying the NIC 19806c8d8eccSSepherosa Ziehau * by its PCI subsystem ID, as we do below for the SysKonnect 19816c8d8eccSSepherosa Ziehau * SK-9D41. 19826c8d8eccSSepherosa Ziehau */ 19836c8d8eccSSepherosa Ziehau if (bnx_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_SIG) == BGE_MAGIC_NUMBER) { 19846c8d8eccSSepherosa Ziehau hwcfg = bnx_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_NICCFG); 19856c8d8eccSSepherosa Ziehau } else { 19866c8d8eccSSepherosa Ziehau if (bnx_read_eeprom(sc, (caddr_t)&hwcfg, BGE_EE_HWCFG_OFFSET, 19876c8d8eccSSepherosa Ziehau sizeof(hwcfg))) { 19886c8d8eccSSepherosa Ziehau device_printf(dev, "failed to read EEPROM\n"); 19896c8d8eccSSepherosa Ziehau error = ENXIO; 19906c8d8eccSSepherosa Ziehau goto fail; 19916c8d8eccSSepherosa Ziehau } 19926c8d8eccSSepherosa Ziehau hwcfg = ntohl(hwcfg); 19936c8d8eccSSepherosa Ziehau } 19946c8d8eccSSepherosa Ziehau 19956c8d8eccSSepherosa Ziehau /* The SysKonnect SK-9D41 is a 1000baseSX card. */ 19966c8d8eccSSepherosa Ziehau if (pci_get_subvendor(dev) == PCI_PRODUCT_SCHNEIDERKOCH_SK_9D41 || 19976c8d8eccSSepherosa Ziehau (hwcfg & BGE_HWCFG_MEDIA) == BGE_MEDIA_FIBER) 19986c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_TBI; 19996c8d8eccSSepherosa Ziehau 20006c8d8eccSSepherosa Ziehau /* Setup MI MODE */ 20016c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_CPMU) 20026c8d8eccSSepherosa Ziehau sc->bnx_mi_mode = BGE_MIMODE_500KHZ_CONST; 20036c8d8eccSSepherosa Ziehau else 20046c8d8eccSSepherosa Ziehau sc->bnx_mi_mode = BGE_MIMODE_BASE; 20056c8d8eccSSepherosa Ziehau 20066c8d8eccSSepherosa Ziehau /* Setup link status update stuffs */ 20076c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 20086c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_tbi_link_upd; 20096c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 20106c8d8eccSSepherosa Ziehau } else if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 20116c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_autopoll_link_upd; 20126c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 20136c8d8eccSSepherosa Ziehau } else { 20146c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_copper_link_upd; 20156c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 20166c8d8eccSSepherosa Ziehau } 20176c8d8eccSSepherosa Ziehau 20186c8d8eccSSepherosa Ziehau /* Set default PHY address */ 20196c8d8eccSSepherosa Ziehau sc->bnx_phyno = 1; 20206c8d8eccSSepherosa Ziehau 20216c8d8eccSSepherosa Ziehau /* 20226c8d8eccSSepherosa Ziehau * PHY address mapping for various devices. 20236c8d8eccSSepherosa Ziehau * 20246c8d8eccSSepherosa Ziehau * | F0 Cu | F0 Sr | F1 Cu | F1 Sr | 20256c8d8eccSSepherosa Ziehau * ---------+-------+-------+-------+-------+ 20266c8d8eccSSepherosa Ziehau * BCM57XX | 1 | X | X | X | 20276c8d8eccSSepherosa Ziehau * BCM5704 | 1 | X | 1 | X | 20286c8d8eccSSepherosa Ziehau * BCM5717 | 1 | 8 | 2 | 9 | 20296c8d8eccSSepherosa Ziehau * BCM5719 | 1 | 8 | 2 | 9 | 20306c8d8eccSSepherosa Ziehau * BCM5720 | 1 | 8 | 2 | 9 | 20316c8d8eccSSepherosa Ziehau * 20326c8d8eccSSepherosa Ziehau * Other addresses may respond but they are not 20336c8d8eccSSepherosa Ziehau * IEEE compliant PHYs and should be ignored. 20346c8d8eccSSepherosa Ziehau */ 203580969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 20366c8d8eccSSepherosa Ziehau int f; 20376c8d8eccSSepherosa Ziehau 20386c8d8eccSSepherosa Ziehau f = pci_get_function(dev); 20396c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5717_A0) { 20406c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_SGDIG_STS) & 20416c8d8eccSSepherosa Ziehau BGE_SGDIGSTS_IS_SERDES) 20426c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 8; 20436c8d8eccSSepherosa Ziehau else 20446c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 1; 20456c8d8eccSSepherosa Ziehau } else { 20466c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_CPMU_PHY_STRAP) & 20476c8d8eccSSepherosa Ziehau BGE_CPMU_PHY_STRAP_IS_SERDES) 20486c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 8; 20496c8d8eccSSepherosa Ziehau else 20506c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 1; 20516c8d8eccSSepherosa Ziehau } 20526c8d8eccSSepherosa Ziehau } 20536c8d8eccSSepherosa Ziehau 20546c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 20556c8d8eccSSepherosa Ziehau ifmedia_init(&sc->bnx_ifmedia, IFM_IMASK, 20566c8d8eccSSepherosa Ziehau bnx_ifmedia_upd, bnx_ifmedia_sts); 20576c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL); 20586c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, 20596c8d8eccSSepherosa Ziehau IFM_ETHER|IFM_1000_SX|IFM_FDX, 0, NULL); 20606c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 20616c8d8eccSSepherosa Ziehau ifmedia_set(&sc->bnx_ifmedia, IFM_ETHER|IFM_AUTO); 20626c8d8eccSSepherosa Ziehau sc->bnx_ifmedia.ifm_media = sc->bnx_ifmedia.ifm_cur->ifm_media; 20636c8d8eccSSepherosa Ziehau } else { 20646c8d8eccSSepherosa Ziehau struct mii_probe_args mii_args; 20656c8d8eccSSepherosa Ziehau 20666c8d8eccSSepherosa Ziehau mii_probe_args_init(&mii_args, bnx_ifmedia_upd, bnx_ifmedia_sts); 20676c8d8eccSSepherosa Ziehau mii_args.mii_probemask = 1 << sc->bnx_phyno; 20686c8d8eccSSepherosa Ziehau mii_args.mii_capmask = capmask; 20696c8d8eccSSepherosa Ziehau mii_args.mii_privtag = MII_PRIVTAG_BRGPHY; 20706c8d8eccSSepherosa Ziehau mii_args.mii_priv = mii_priv; 20716c8d8eccSSepherosa Ziehau 20726c8d8eccSSepherosa Ziehau error = mii_probe(dev, &sc->bnx_miibus, &mii_args); 20736c8d8eccSSepherosa Ziehau if (error) { 20746c8d8eccSSepherosa Ziehau device_printf(dev, "MII without any PHY!\n"); 20756c8d8eccSSepherosa Ziehau goto fail; 20766c8d8eccSSepherosa Ziehau } 20776c8d8eccSSepherosa Ziehau } 20786c8d8eccSSepherosa Ziehau 20796c8d8eccSSepherosa Ziehau /* 20806c8d8eccSSepherosa Ziehau * Create sysctl nodes. 20816c8d8eccSSepherosa Ziehau */ 20826c8d8eccSSepherosa Ziehau sysctl_ctx_init(&sc->bnx_sysctl_ctx); 20836c8d8eccSSepherosa Ziehau sc->bnx_sysctl_tree = SYSCTL_ADD_NODE(&sc->bnx_sysctl_ctx, 20846c8d8eccSSepherosa Ziehau SYSCTL_STATIC_CHILDREN(_hw), 20856c8d8eccSSepherosa Ziehau OID_AUTO, 20866c8d8eccSSepherosa Ziehau device_get_nameunit(dev), 20876c8d8eccSSepherosa Ziehau CTLFLAG_RD, 0, ""); 20886c8d8eccSSepherosa Ziehau if (sc->bnx_sysctl_tree == NULL) { 20896c8d8eccSSepherosa Ziehau device_printf(dev, "can't add sysctl node\n"); 20906c8d8eccSSepherosa Ziehau error = ENXIO; 20916c8d8eccSSepherosa Ziehau goto fail; 20926c8d8eccSSepherosa Ziehau } 20936c8d8eccSSepherosa Ziehau 20946c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 20956c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 20966c8d8eccSSepherosa Ziehau OID_AUTO, "rx_coal_ticks", 20976c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 20986c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_ticks, "I", 20996c8d8eccSSepherosa Ziehau "Receive coalescing ticks (usec)."); 21006c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 21016c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 21026c8d8eccSSepherosa Ziehau OID_AUTO, "tx_coal_ticks", 21036c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 21046c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_ticks, "I", 21056c8d8eccSSepherosa Ziehau "Transmit coalescing ticks (usec)."); 21066c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 21076c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 21086c8d8eccSSepherosa Ziehau OID_AUTO, "rx_coal_bds", 21096c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 21106c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_bds, "I", 21116c8d8eccSSepherosa Ziehau "Receive max coalesced BD count."); 21126c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 21136c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 21146c8d8eccSSepherosa Ziehau OID_AUTO, "tx_coal_bds", 21156c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 21166c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_bds, "I", 21176c8d8eccSSepherosa Ziehau "Transmit max coalesced BD count."); 21186c8d8eccSSepherosa Ziehau /* 21196c8d8eccSSepherosa Ziehau * A common design characteristic for many Broadcom 21206c8d8eccSSepherosa Ziehau * client controllers is that they only support a 21216c8d8eccSSepherosa Ziehau * single outstanding DMA read operation on the PCIe 21226c8d8eccSSepherosa Ziehau * bus. This means that it will take twice as long to 21236c8d8eccSSepherosa Ziehau * fetch a TX frame that is split into header and 21246c8d8eccSSepherosa Ziehau * payload buffers as it does to fetch a single, 21256c8d8eccSSepherosa Ziehau * contiguous TX frame (2 reads vs. 1 read). For these 21266c8d8eccSSepherosa Ziehau * controllers, coalescing buffers to reduce the number 21276c8d8eccSSepherosa Ziehau * of memory reads is effective way to get maximum 21286c8d8eccSSepherosa Ziehau * performance(about 940Mbps). Without collapsing TX 21296c8d8eccSSepherosa Ziehau * buffers the maximum TCP bulk transfer performance 21306c8d8eccSSepherosa Ziehau * is about 850Mbps. However forcing coalescing mbufs 21316c8d8eccSSepherosa Ziehau * consumes a lot of CPU cycles, so leave it off by 21326c8d8eccSSepherosa Ziehau * default. 21336c8d8eccSSepherosa Ziehau */ 21346c8d8eccSSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 21356c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 21366c8d8eccSSepherosa Ziehau "force_defrag", CTLFLAG_RW, &sc->bnx_force_defrag, 0, 21376c8d8eccSSepherosa Ziehau "Force defragment on TX path"); 21386c8d8eccSSepherosa Ziehau 21396c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 21406c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 21416c8d8eccSSepherosa Ziehau "rx_coal_bds_int", CTLTYPE_INT | CTLFLAG_RW, 21426c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_bds_int, "I", 21436c8d8eccSSepherosa Ziehau "Receive max coalesced BD count during interrupt."); 21446c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 21456c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 21466c8d8eccSSepherosa Ziehau "tx_coal_bds_int", CTLTYPE_INT | CTLFLAG_RW, 21476c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_bds_int, "I", 21486c8d8eccSSepherosa Ziehau "Transmit max coalesced BD count during interrupt."); 21496c8d8eccSSepherosa Ziehau 21506c8d8eccSSepherosa Ziehau /* 21516c8d8eccSSepherosa Ziehau * Call MI attach routine. 21526c8d8eccSSepherosa Ziehau */ 21536c8d8eccSSepherosa Ziehau ether_ifattach(ifp, ether_addr, NULL); 21546c8d8eccSSepherosa Ziehau 21556c8d8eccSSepherosa Ziehau if (sc->bnx_irq_type == PCI_INTR_TYPE_MSI) { 21566c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_ONESHOT_MSI) { 21576c8d8eccSSepherosa Ziehau intr_func = bnx_msi_oneshot; 21586c8d8eccSSepherosa Ziehau if (bootverbose) 21596c8d8eccSSepherosa Ziehau device_printf(dev, "oneshot MSI\n"); 21606c8d8eccSSepherosa Ziehau } else { 21616c8d8eccSSepherosa Ziehau intr_func = bnx_msi; 21626c8d8eccSSepherosa Ziehau } 21636c8d8eccSSepherosa Ziehau } else { 21646c8d8eccSSepherosa Ziehau intr_func = bnx_intr_legacy; 21656c8d8eccSSepherosa Ziehau } 21666c8d8eccSSepherosa Ziehau error = bus_setup_intr(dev, sc->bnx_irq, INTR_MPSAFE, intr_func, sc, 21676c8d8eccSSepherosa Ziehau &sc->bnx_intrhand, ifp->if_serializer); 21686c8d8eccSSepherosa Ziehau if (error) { 21696c8d8eccSSepherosa Ziehau ether_ifdetach(ifp); 21706c8d8eccSSepherosa Ziehau device_printf(dev, "couldn't set up irq\n"); 21716c8d8eccSSepherosa Ziehau goto fail; 21726c8d8eccSSepherosa Ziehau } 21736c8d8eccSSepherosa Ziehau 21746c8d8eccSSepherosa Ziehau ifp->if_cpuid = rman_get_cpuid(sc->bnx_irq); 21756c8d8eccSSepherosa Ziehau KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus); 21766c8d8eccSSepherosa Ziehau 21778ca0f604SSepherosa Ziehau sc->bnx_stat_cpuid = ifp->if_cpuid; 2178*df9ccc98SSepherosa Ziehau sc->bnx_intr_cpuid = ifp->if_cpuid; 21798ca0f604SSepherosa Ziehau 21806c8d8eccSSepherosa Ziehau return(0); 21816c8d8eccSSepherosa Ziehau fail: 21826c8d8eccSSepherosa Ziehau bnx_detach(dev); 21836c8d8eccSSepherosa Ziehau return(error); 21846c8d8eccSSepherosa Ziehau } 21856c8d8eccSSepherosa Ziehau 21866c8d8eccSSepherosa Ziehau static int 21876c8d8eccSSepherosa Ziehau bnx_detach(device_t dev) 21886c8d8eccSSepherosa Ziehau { 21896c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 21906c8d8eccSSepherosa Ziehau 21916c8d8eccSSepherosa Ziehau if (device_is_attached(dev)) { 21926c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 21936c8d8eccSSepherosa Ziehau 21946c8d8eccSSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 21956c8d8eccSSepherosa Ziehau bnx_stop(sc); 21966c8d8eccSSepherosa Ziehau bnx_reset(sc); 21976c8d8eccSSepherosa Ziehau bus_teardown_intr(dev, sc->bnx_irq, sc->bnx_intrhand); 21986c8d8eccSSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 21996c8d8eccSSepherosa Ziehau 22006c8d8eccSSepherosa Ziehau ether_ifdetach(ifp); 22016c8d8eccSSepherosa Ziehau } 22026c8d8eccSSepherosa Ziehau 22036c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) 22046c8d8eccSSepherosa Ziehau ifmedia_removeall(&sc->bnx_ifmedia); 22056c8d8eccSSepherosa Ziehau if (sc->bnx_miibus) 22066c8d8eccSSepherosa Ziehau device_delete_child(dev, sc->bnx_miibus); 22076c8d8eccSSepherosa Ziehau bus_generic_detach(dev); 22086c8d8eccSSepherosa Ziehau 22096c8d8eccSSepherosa Ziehau if (sc->bnx_irq != NULL) { 22106c8d8eccSSepherosa Ziehau bus_release_resource(dev, SYS_RES_IRQ, sc->bnx_irq_rid, 22116c8d8eccSSepherosa Ziehau sc->bnx_irq); 22126c8d8eccSSepherosa Ziehau } 22136c8d8eccSSepherosa Ziehau if (sc->bnx_irq_type == PCI_INTR_TYPE_MSI) 22146c8d8eccSSepherosa Ziehau pci_release_msi(dev); 22156c8d8eccSSepherosa Ziehau 22166c8d8eccSSepherosa Ziehau if (sc->bnx_res != NULL) { 22176c8d8eccSSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, 22186c8d8eccSSepherosa Ziehau BGE_PCI_BAR0, sc->bnx_res); 22196c8d8eccSSepherosa Ziehau } 22206c8d8eccSSepherosa Ziehau 22216c8d8eccSSepherosa Ziehau if (sc->bnx_sysctl_tree != NULL) 22226c8d8eccSSepherosa Ziehau sysctl_ctx_free(&sc->bnx_sysctl_ctx); 22236c8d8eccSSepherosa Ziehau 22246c8d8eccSSepherosa Ziehau bnx_dma_free(sc); 22256c8d8eccSSepherosa Ziehau 22266c8d8eccSSepherosa Ziehau return 0; 22276c8d8eccSSepherosa Ziehau } 22286c8d8eccSSepherosa Ziehau 22296c8d8eccSSepherosa Ziehau static void 22306c8d8eccSSepherosa Ziehau bnx_reset(struct bnx_softc *sc) 22316c8d8eccSSepherosa Ziehau { 22326c8d8eccSSepherosa Ziehau device_t dev; 22336c8d8eccSSepherosa Ziehau uint32_t cachesize, command, pcistate, reset; 22346c8d8eccSSepherosa Ziehau void (*write_op)(struct bnx_softc *, uint32_t, uint32_t); 22356c8d8eccSSepherosa Ziehau int i, val = 0; 22366c8d8eccSSepherosa Ziehau uint16_t devctl; 22376c8d8eccSSepherosa Ziehau 22386c8d8eccSSepherosa Ziehau dev = sc->bnx_dev; 22396c8d8eccSSepherosa Ziehau 22406c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev != BGE_ASICREV_BCM5906) 22416c8d8eccSSepherosa Ziehau write_op = bnx_writemem_direct; 22426c8d8eccSSepherosa Ziehau else 22436c8d8eccSSepherosa Ziehau write_op = bnx_writereg_ind; 22446c8d8eccSSepherosa Ziehau 22456c8d8eccSSepherosa Ziehau /* Save some important PCI state. */ 22466c8d8eccSSepherosa Ziehau cachesize = pci_read_config(dev, BGE_PCI_CACHESZ, 4); 22476c8d8eccSSepherosa Ziehau command = pci_read_config(dev, BGE_PCI_CMD, 4); 22486c8d8eccSSepherosa Ziehau pcistate = pci_read_config(dev, BGE_PCI_PCISTATE, 4); 22496c8d8eccSSepherosa Ziehau 22506c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MISC_CTL, 22516c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| 22526c8d8eccSSepherosa Ziehau BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW| 22536c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_TAGGED_STATUS, 4); 22546c8d8eccSSepherosa Ziehau 22556c8d8eccSSepherosa Ziehau /* Disable fastboot on controllers that support it. */ 22566c8d8eccSSepherosa Ziehau if (bootverbose) 22576c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Disabling fastboot\n"); 22586c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FASTBOOT_PC, 0x0); 22596c8d8eccSSepherosa Ziehau 22606c8d8eccSSepherosa Ziehau /* 22616c8d8eccSSepherosa Ziehau * Write the magic number to SRAM at offset 0xB50. 22626c8d8eccSSepherosa Ziehau * When firmware finishes its initialization it will 22636c8d8eccSSepherosa Ziehau * write ~BGE_MAGIC_NUMBER to the same location. 22646c8d8eccSSepherosa Ziehau */ 22656c8d8eccSSepherosa Ziehau bnx_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); 22666c8d8eccSSepherosa Ziehau 22676c8d8eccSSepherosa Ziehau reset = BGE_MISCCFG_RESET_CORE_CLOCKS|(65<<1); 22686c8d8eccSSepherosa Ziehau 22696c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 22706c8d8eccSSepherosa Ziehau /* Force PCI-E 1.0a mode */ 22713730a14dSSepherosa Ziehau if (!BNX_IS_57765_PLUS(sc) && 22726c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_PCIE_PHY_TSTCTL) == 22736c8d8eccSSepherosa Ziehau (BGE_PCIE_PHY_TSTCTL_PSCRAM | 22746c8d8eccSSepherosa Ziehau BGE_PCIE_PHY_TSTCTL_PCIE10)) { 22756c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_PHY_TSTCTL, 22766c8d8eccSSepherosa Ziehau BGE_PCIE_PHY_TSTCTL_PSCRAM); 22776c8d8eccSSepherosa Ziehau } 22786c8d8eccSSepherosa Ziehau if (sc->bnx_chipid != BGE_CHIPID_BCM5750_A0) { 22796c8d8eccSSepherosa Ziehau /* Prevent PCIE link training during global reset */ 22806c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_CFG, (1<<29)); 22816c8d8eccSSepherosa Ziehau reset |= (1<<29); 22826c8d8eccSSepherosa Ziehau } 22836c8d8eccSSepherosa Ziehau 22846c8d8eccSSepherosa Ziehau /* 22856c8d8eccSSepherosa Ziehau * Set GPHY Power Down Override to leave GPHY 22866c8d8eccSSepherosa Ziehau * powered up in D0 uninitialized. 22876c8d8eccSSepherosa Ziehau */ 22886c8d8eccSSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_CPMU) == 0) 22896c8d8eccSSepherosa Ziehau reset |= BGE_MISCCFG_GPHY_PD_OVERRIDE; 22906c8d8eccSSepherosa Ziehau 22916c8d8eccSSepherosa Ziehau /* Issue global reset */ 22926c8d8eccSSepherosa Ziehau write_op(sc, BGE_MISC_CFG, reset); 22936c8d8eccSSepherosa Ziehau 22946c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5906) { 22956c8d8eccSSepherosa Ziehau uint32_t status, ctrl; 22966c8d8eccSSepherosa Ziehau 22976c8d8eccSSepherosa Ziehau status = CSR_READ_4(sc, BGE_VCPU_STATUS); 22986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_VCPU_STATUS, 22996c8d8eccSSepherosa Ziehau status | BGE_VCPU_STATUS_DRV_RESET); 23006c8d8eccSSepherosa Ziehau ctrl = CSR_READ_4(sc, BGE_VCPU_EXT_CTRL); 23016c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_VCPU_EXT_CTRL, 23026c8d8eccSSepherosa Ziehau ctrl & ~BGE_VCPU_EXT_CTRL_HALT_CPU); 23036c8d8eccSSepherosa Ziehau } 23046c8d8eccSSepherosa Ziehau 23056c8d8eccSSepherosa Ziehau DELAY(1000); 23066c8d8eccSSepherosa Ziehau 23076c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 23086c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5750_A0) { 23096c8d8eccSSepherosa Ziehau uint32_t v; 23106c8d8eccSSepherosa Ziehau 23116c8d8eccSSepherosa Ziehau DELAY(500000); /* wait for link training to complete */ 23126c8d8eccSSepherosa Ziehau v = pci_read_config(dev, 0xc4, 4); 23136c8d8eccSSepherosa Ziehau pci_write_config(dev, 0xc4, v | (1<<15), 4); 23146c8d8eccSSepherosa Ziehau } 23156c8d8eccSSepherosa Ziehau 23166c8d8eccSSepherosa Ziehau devctl = pci_read_config(dev, sc->bnx_pciecap + PCIER_DEVCTRL, 2); 23176c8d8eccSSepherosa Ziehau 23186c8d8eccSSepherosa Ziehau /* Disable no snoop and disable relaxed ordering. */ 23196c8d8eccSSepherosa Ziehau devctl &= ~(PCIEM_DEVCTL_RELAX_ORDER | PCIEM_DEVCTL_NOSNOOP); 23206c8d8eccSSepherosa Ziehau 23216c8d8eccSSepherosa Ziehau /* Old PCI-E chips only support 128 bytes Max PayLoad Size. */ 23226c8d8eccSSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_CPMU) == 0) { 23236c8d8eccSSepherosa Ziehau devctl &= ~PCIEM_DEVCTL_MAX_PAYLOAD_MASK; 23246c8d8eccSSepherosa Ziehau devctl |= PCIEM_DEVCTL_MAX_PAYLOAD_128; 23256c8d8eccSSepherosa Ziehau } 23266c8d8eccSSepherosa Ziehau 23276c8d8eccSSepherosa Ziehau pci_write_config(dev, sc->bnx_pciecap + PCIER_DEVCTRL, 23286c8d8eccSSepherosa Ziehau devctl, 2); 23296c8d8eccSSepherosa Ziehau 23306c8d8eccSSepherosa Ziehau /* Clear error status. */ 23316c8d8eccSSepherosa Ziehau pci_write_config(dev, sc->bnx_pciecap + PCIER_DEVSTS, 23326c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_CORR_ERR | 23336c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_NFATAL_ERR | 23346c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_FATAL_ERR | 23356c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_UNSUPP_REQ, 2); 23366c8d8eccSSepherosa Ziehau 23376c8d8eccSSepherosa Ziehau /* Reset some of the PCI state that got zapped by reset */ 23386c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MISC_CTL, 23396c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| 23406c8d8eccSSepherosa Ziehau BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW| 23416c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_TAGGED_STATUS, 4); 23426c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_CACHESZ, cachesize, 4); 23436c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_CMD, command, 4); 23446c8d8eccSSepherosa Ziehau write_op(sc, BGE_MISC_CFG, (65 << 1)); 23456c8d8eccSSepherosa Ziehau 23466c8d8eccSSepherosa Ziehau /* Enable memory arbiter */ 23476c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); 23486c8d8eccSSepherosa Ziehau 23496c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5906) { 23506c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 23516c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_VCPU_STATUS); 23526c8d8eccSSepherosa Ziehau if (val & BGE_VCPU_STATUS_INIT_DONE) 23536c8d8eccSSepherosa Ziehau break; 23546c8d8eccSSepherosa Ziehau DELAY(100); 23556c8d8eccSSepherosa Ziehau } 23566c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 23576c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "reset timed out\n"); 23586c8d8eccSSepherosa Ziehau return; 23596c8d8eccSSepherosa Ziehau } 23606c8d8eccSSepherosa Ziehau } else { 23616c8d8eccSSepherosa Ziehau /* 23626c8d8eccSSepherosa Ziehau * Poll until we see the 1's complement of the magic number. 23636c8d8eccSSepherosa Ziehau * This indicates that the firmware initialization 23646c8d8eccSSepherosa Ziehau * is complete. 23656c8d8eccSSepherosa Ziehau */ 23666c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_FIRMWARE_TIMEOUT; i++) { 23676c8d8eccSSepherosa Ziehau val = bnx_readmem_ind(sc, BGE_SOFTWARE_GENCOMM); 23686c8d8eccSSepherosa Ziehau if (val == ~BGE_MAGIC_NUMBER) 23696c8d8eccSSepherosa Ziehau break; 23706c8d8eccSSepherosa Ziehau DELAY(10); 23716c8d8eccSSepherosa Ziehau } 23726c8d8eccSSepherosa Ziehau if (i == BNX_FIRMWARE_TIMEOUT) { 23736c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "firmware handshake " 23746c8d8eccSSepherosa Ziehau "timed out, found 0x%08x\n", val); 23756c8d8eccSSepherosa Ziehau } 23766c8d8eccSSepherosa Ziehau 23776c8d8eccSSepherosa Ziehau /* BCM57765 A0 needs additional time before accessing. */ 23786c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) 23796c8d8eccSSepherosa Ziehau DELAY(10 * 1000); 23806c8d8eccSSepherosa Ziehau } 23816c8d8eccSSepherosa Ziehau 23826c8d8eccSSepherosa Ziehau /* 23836c8d8eccSSepherosa Ziehau * XXX Wait for the value of the PCISTATE register to 23846c8d8eccSSepherosa Ziehau * return to its original pre-reset state. This is a 23856c8d8eccSSepherosa Ziehau * fairly good indicator of reset completion. If we don't 23866c8d8eccSSepherosa Ziehau * wait for the reset to fully complete, trying to read 23876c8d8eccSSepherosa Ziehau * from the device's non-PCI registers may yield garbage 23886c8d8eccSSepherosa Ziehau * results. 23896c8d8eccSSepherosa Ziehau */ 23906c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 23916c8d8eccSSepherosa Ziehau if (pci_read_config(dev, BGE_PCI_PCISTATE, 4) == pcistate) 23926c8d8eccSSepherosa Ziehau break; 23936c8d8eccSSepherosa Ziehau DELAY(10); 23946c8d8eccSSepherosa Ziehau } 23956c8d8eccSSepherosa Ziehau 23966c8d8eccSSepherosa Ziehau /* Fix up byte swapping */ 23976c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, bnx_dma_swap_options(sc)); 23986c8d8eccSSepherosa Ziehau 23996c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, 0); 24006c8d8eccSSepherosa Ziehau 24016c8d8eccSSepherosa Ziehau /* 24026c8d8eccSSepherosa Ziehau * The 5704 in TBI mode apparently needs some special 24036c8d8eccSSepherosa Ziehau * adjustment to insure the SERDES drive level is set 24046c8d8eccSSepherosa Ziehau * to 1.2V. 24056c8d8eccSSepherosa Ziehau */ 24066c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5704 && 24076c8d8eccSSepherosa Ziehau (sc->bnx_flags & BNX_FLAG_TBI)) { 24086c8d8eccSSepherosa Ziehau uint32_t serdescfg; 24096c8d8eccSSepherosa Ziehau 24106c8d8eccSSepherosa Ziehau serdescfg = CSR_READ_4(sc, BGE_SERDES_CFG); 24116c8d8eccSSepherosa Ziehau serdescfg = (serdescfg & ~0xFFF) | 0x880; 24126c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SERDES_CFG, serdescfg); 24136c8d8eccSSepherosa Ziehau } 24146c8d8eccSSepherosa Ziehau 24156c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 24163730a14dSSepherosa Ziehau if (!BNX_IS_57765_PLUS(sc)) { 24176c8d8eccSSepherosa Ziehau uint32_t v; 24186c8d8eccSSepherosa Ziehau 24196c8d8eccSSepherosa Ziehau /* Enable Data FIFO protection. */ 2420f1f34fc4SSepherosa Ziehau v = CSR_READ_4(sc, BGE_PCIE_TLDLPL_PORT); 2421f1f34fc4SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_TLDLPL_PORT, v | (1 << 25)); 24226c8d8eccSSepherosa Ziehau } 24236c8d8eccSSepherosa Ziehau 24246c8d8eccSSepherosa Ziehau DELAY(10000); 24256c8d8eccSSepherosa Ziehau 24266c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 24276c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_CPMU_CLCK_ORIDE, 24286c8d8eccSSepherosa Ziehau CPMU_CLCK_ORIDE_MAC_ORIDE_EN); 24296c8d8eccSSepherosa Ziehau } 24306c8d8eccSSepherosa Ziehau } 24316c8d8eccSSepherosa Ziehau 24326c8d8eccSSepherosa Ziehau /* 24336c8d8eccSSepherosa Ziehau * Frame reception handling. This is called if there's a frame 24346c8d8eccSSepherosa Ziehau * on the receive return list. 24356c8d8eccSSepherosa Ziehau * 24366c8d8eccSSepherosa Ziehau * Note: we have to be able to handle two possibilities here: 24376c8d8eccSSepherosa Ziehau * 1) the frame is from the jumbo recieve ring 24386c8d8eccSSepherosa Ziehau * 2) the frame is from the standard receive ring 24396c8d8eccSSepherosa Ziehau */ 24406c8d8eccSSepherosa Ziehau 24416c8d8eccSSepherosa Ziehau static void 24426c8d8eccSSepherosa Ziehau bnx_rxeof(struct bnx_softc *sc, uint16_t rx_prod) 24436c8d8eccSSepherosa Ziehau { 24446c8d8eccSSepherosa Ziehau struct ifnet *ifp; 24456c8d8eccSSepherosa Ziehau int stdcnt = 0, jumbocnt = 0; 24466c8d8eccSSepherosa Ziehau 24476c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 24486c8d8eccSSepherosa Ziehau 24496c8d8eccSSepherosa Ziehau while (sc->bnx_rx_saved_considx != rx_prod) { 24506c8d8eccSSepherosa Ziehau struct bge_rx_bd *cur_rx; 24516c8d8eccSSepherosa Ziehau uint32_t rxidx; 24526c8d8eccSSepherosa Ziehau struct mbuf *m = NULL; 24536c8d8eccSSepherosa Ziehau uint16_t vlan_tag = 0; 24546c8d8eccSSepherosa Ziehau int have_tag = 0; 24556c8d8eccSSepherosa Ziehau 24566c8d8eccSSepherosa Ziehau cur_rx = 24576c8d8eccSSepherosa Ziehau &sc->bnx_ldata.bnx_rx_return_ring[sc->bnx_rx_saved_considx]; 24586c8d8eccSSepherosa Ziehau 24596c8d8eccSSepherosa Ziehau rxidx = cur_rx->bge_idx; 24606c8d8eccSSepherosa Ziehau BNX_INC(sc->bnx_rx_saved_considx, sc->bnx_return_ring_cnt); 24616c8d8eccSSepherosa Ziehau 24626c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_VLAN_TAG) { 24636c8d8eccSSepherosa Ziehau have_tag = 1; 24646c8d8eccSSepherosa Ziehau vlan_tag = cur_rx->bge_vlan_tag; 24656c8d8eccSSepherosa Ziehau } 24666c8d8eccSSepherosa Ziehau 24676c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_JUMBO_RING) { 24686c8d8eccSSepherosa Ziehau BNX_INC(sc->bnx_jumbo, BGE_JUMBO_RX_RING_CNT); 24696c8d8eccSSepherosa Ziehau jumbocnt++; 24706c8d8eccSSepherosa Ziehau 24716c8d8eccSSepherosa Ziehau if (rxidx != sc->bnx_jumbo) { 24726c8d8eccSSepherosa Ziehau ifp->if_ierrors++; 24736c8d8eccSSepherosa Ziehau if_printf(ifp, "sw jumbo index(%d) " 24746c8d8eccSSepherosa Ziehau "and hw jumbo index(%d) mismatch, drop!\n", 24756c8d8eccSSepherosa Ziehau sc->bnx_jumbo, rxidx); 24766c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(sc, rxidx); 24776c8d8eccSSepherosa Ziehau continue; 24786c8d8eccSSepherosa Ziehau } 24796c8d8eccSSepherosa Ziehau 24806c8d8eccSSepherosa Ziehau m = sc->bnx_cdata.bnx_rx_jumbo_chain[rxidx].bnx_mbuf; 24816c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_ERROR) { 24826c8d8eccSSepherosa Ziehau ifp->if_ierrors++; 24836c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(sc, sc->bnx_jumbo); 24846c8d8eccSSepherosa Ziehau continue; 24856c8d8eccSSepherosa Ziehau } 24866c8d8eccSSepherosa Ziehau if (bnx_newbuf_jumbo(sc, sc->bnx_jumbo, 0)) { 24876c8d8eccSSepherosa Ziehau ifp->if_ierrors++; 24886c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(sc, sc->bnx_jumbo); 24896c8d8eccSSepherosa Ziehau continue; 24906c8d8eccSSepherosa Ziehau } 24916c8d8eccSSepherosa Ziehau } else { 24926c8d8eccSSepherosa Ziehau BNX_INC(sc->bnx_std, BGE_STD_RX_RING_CNT); 24936c8d8eccSSepherosa Ziehau stdcnt++; 24946c8d8eccSSepherosa Ziehau 24956c8d8eccSSepherosa Ziehau if (rxidx != sc->bnx_std) { 24966c8d8eccSSepherosa Ziehau ifp->if_ierrors++; 24976c8d8eccSSepherosa Ziehau if_printf(ifp, "sw std index(%d) " 24986c8d8eccSSepherosa Ziehau "and hw std index(%d) mismatch, drop!\n", 24996c8d8eccSSepherosa Ziehau sc->bnx_std, rxidx); 25006c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_std(sc, rxidx); 25016c8d8eccSSepherosa Ziehau continue; 25026c8d8eccSSepherosa Ziehau } 25036c8d8eccSSepherosa Ziehau 25046c8d8eccSSepherosa Ziehau m = sc->bnx_cdata.bnx_rx_std_chain[rxidx].bnx_mbuf; 25056c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_ERROR) { 25066c8d8eccSSepherosa Ziehau ifp->if_ierrors++; 25076c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_std(sc, sc->bnx_std); 25086c8d8eccSSepherosa Ziehau continue; 25096c8d8eccSSepherosa Ziehau } 25106c8d8eccSSepherosa Ziehau if (bnx_newbuf_std(sc, sc->bnx_std, 0)) { 25116c8d8eccSSepherosa Ziehau ifp->if_ierrors++; 25126c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_std(sc, sc->bnx_std); 25136c8d8eccSSepherosa Ziehau continue; 25146c8d8eccSSepherosa Ziehau } 25156c8d8eccSSepherosa Ziehau } 25166c8d8eccSSepherosa Ziehau 25176c8d8eccSSepherosa Ziehau ifp->if_ipackets++; 25186c8d8eccSSepherosa Ziehau m->m_pkthdr.len = m->m_len = cur_rx->bge_len - ETHER_CRC_LEN; 25196c8d8eccSSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 25206c8d8eccSSepherosa Ziehau 25216c8d8eccSSepherosa Ziehau if ((ifp->if_capenable & IFCAP_RXCSUM) && 25226c8d8eccSSepherosa Ziehau (cur_rx->bge_flags & BGE_RXBDFLAG_IPV6) == 0) { 25236c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { 25246c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 25256c8d8eccSSepherosa Ziehau if ((cur_rx->bge_error_flag & 25266c8d8eccSSepherosa Ziehau BGE_RXERRFLAG_IP_CSUM_NOK) == 0) 25276c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 25286c8d8eccSSepherosa Ziehau } 25296c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM) { 25306c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_data = 25316c8d8eccSSepherosa Ziehau cur_rx->bge_tcp_udp_csum; 25326c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | 25336c8d8eccSSepherosa Ziehau CSUM_PSEUDO_HDR; 25346c8d8eccSSepherosa Ziehau } 25356c8d8eccSSepherosa Ziehau } 25366c8d8eccSSepherosa Ziehau 25376c8d8eccSSepherosa Ziehau /* 25386c8d8eccSSepherosa Ziehau * If we received a packet with a vlan tag, pass it 25396c8d8eccSSepherosa Ziehau * to vlan_input() instead of ether_input(). 25406c8d8eccSSepherosa Ziehau */ 25416c8d8eccSSepherosa Ziehau if (have_tag) { 25426c8d8eccSSepherosa Ziehau m->m_flags |= M_VLANTAG; 25436c8d8eccSSepherosa Ziehau m->m_pkthdr.ether_vlantag = vlan_tag; 25446c8d8eccSSepherosa Ziehau have_tag = vlan_tag = 0; 25456c8d8eccSSepherosa Ziehau } 25466c8d8eccSSepherosa Ziehau ifp->if_input(ifp, m); 25476c8d8eccSSepherosa Ziehau } 25486c8d8eccSSepherosa Ziehau 25496c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_CONS0_LO, sc->bnx_rx_saved_considx); 25506c8d8eccSSepherosa Ziehau if (stdcnt) 25516c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bnx_std); 25526c8d8eccSSepherosa Ziehau if (jumbocnt) 25536c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bnx_jumbo); 25546c8d8eccSSepherosa Ziehau } 25556c8d8eccSSepherosa Ziehau 25566c8d8eccSSepherosa Ziehau static void 25576c8d8eccSSepherosa Ziehau bnx_txeof(struct bnx_softc *sc, uint16_t tx_cons) 25586c8d8eccSSepherosa Ziehau { 25596c8d8eccSSepherosa Ziehau struct bge_tx_bd *cur_tx = NULL; 25606c8d8eccSSepherosa Ziehau struct ifnet *ifp; 25616c8d8eccSSepherosa Ziehau 25626c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 25636c8d8eccSSepherosa Ziehau 25646c8d8eccSSepherosa Ziehau /* 25656c8d8eccSSepherosa Ziehau * Go through our tx ring and free mbufs for those 25666c8d8eccSSepherosa Ziehau * frames that have been sent. 25676c8d8eccSSepherosa Ziehau */ 25686c8d8eccSSepherosa Ziehau while (sc->bnx_tx_saved_considx != tx_cons) { 25696c8d8eccSSepherosa Ziehau uint32_t idx = 0; 25706c8d8eccSSepherosa Ziehau 25716c8d8eccSSepherosa Ziehau idx = sc->bnx_tx_saved_considx; 25726c8d8eccSSepherosa Ziehau cur_tx = &sc->bnx_ldata.bnx_tx_ring[idx]; 25736c8d8eccSSepherosa Ziehau if (cur_tx->bge_flags & BGE_TXBDFLAG_END) 25746c8d8eccSSepherosa Ziehau ifp->if_opackets++; 25756c8d8eccSSepherosa Ziehau if (sc->bnx_cdata.bnx_tx_chain[idx] != NULL) { 25766c8d8eccSSepherosa Ziehau bus_dmamap_unload(sc->bnx_cdata.bnx_tx_mtag, 25776c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_dmamap[idx]); 25786c8d8eccSSepherosa Ziehau m_freem(sc->bnx_cdata.bnx_tx_chain[idx]); 25796c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_chain[idx] = NULL; 25806c8d8eccSSepherosa Ziehau } 25816c8d8eccSSepherosa Ziehau sc->bnx_txcnt--; 25826c8d8eccSSepherosa Ziehau BNX_INC(sc->bnx_tx_saved_considx, BGE_TX_RING_CNT); 25836c8d8eccSSepherosa Ziehau } 25846c8d8eccSSepherosa Ziehau 25856c8d8eccSSepherosa Ziehau if (cur_tx != NULL && 25866c8d8eccSSepherosa Ziehau (BGE_TX_RING_CNT - sc->bnx_txcnt) >= 25876c8d8eccSSepherosa Ziehau (BNX_NSEG_RSVD + BNX_NSEG_SPARE)) 25886c8d8eccSSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 25896c8d8eccSSepherosa Ziehau 25906c8d8eccSSepherosa Ziehau if (sc->bnx_txcnt == 0) 25916c8d8eccSSepherosa Ziehau ifp->if_timer = 0; 25926c8d8eccSSepherosa Ziehau 25936c8d8eccSSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 25946c8d8eccSSepherosa Ziehau if_devstart(ifp); 25956c8d8eccSSepherosa Ziehau } 25966c8d8eccSSepherosa Ziehau 25976c8d8eccSSepherosa Ziehau #ifdef DEVICE_POLLING 25986c8d8eccSSepherosa Ziehau 25996c8d8eccSSepherosa Ziehau static void 26006c8d8eccSSepherosa Ziehau bnx_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 26016c8d8eccSSepherosa Ziehau { 26026c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 26036c8d8eccSSepherosa Ziehau struct bge_status_block *sblk = sc->bnx_ldata.bnx_status_block; 26046c8d8eccSSepherosa Ziehau uint16_t rx_prod, tx_cons; 26056c8d8eccSSepherosa Ziehau 26066c8d8eccSSepherosa Ziehau switch(cmd) { 26076c8d8eccSSepherosa Ziehau case POLL_REGISTER: 26086c8d8eccSSepherosa Ziehau bnx_disable_intr(sc); 26096c8d8eccSSepherosa Ziehau break; 26106c8d8eccSSepherosa Ziehau case POLL_DEREGISTER: 26116c8d8eccSSepherosa Ziehau bnx_enable_intr(sc); 26126c8d8eccSSepherosa Ziehau break; 26136c8d8eccSSepherosa Ziehau case POLL_AND_CHECK_STATUS: 26146c8d8eccSSepherosa Ziehau /* 26156c8d8eccSSepherosa Ziehau * Process link state changes. 26166c8d8eccSSepherosa Ziehau */ 26176c8d8eccSSepherosa Ziehau bnx_link_poll(sc); 26186c8d8eccSSepherosa Ziehau /* Fall through */ 26196c8d8eccSSepherosa Ziehau case POLL_ONLY: 26206c8d8eccSSepherosa Ziehau sc->bnx_status_tag = sblk->bge_status_tag; 26216c8d8eccSSepherosa Ziehau /* 26226c8d8eccSSepherosa Ziehau * Use a load fence to ensure that status_tag 26236c8d8eccSSepherosa Ziehau * is saved before rx_prod and tx_cons. 26246c8d8eccSSepherosa Ziehau */ 26256c8d8eccSSepherosa Ziehau cpu_lfence(); 26266c8d8eccSSepherosa Ziehau 26276c8d8eccSSepherosa Ziehau rx_prod = sblk->bge_idx[0].bge_rx_prod_idx; 26286c8d8eccSSepherosa Ziehau tx_cons = sblk->bge_idx[0].bge_tx_cons_idx; 26296c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 26306c8d8eccSSepherosa Ziehau rx_prod = sblk->bge_idx[0].bge_rx_prod_idx; 26316c8d8eccSSepherosa Ziehau if (sc->bnx_rx_saved_considx != rx_prod) 26326c8d8eccSSepherosa Ziehau bnx_rxeof(sc, rx_prod); 26336c8d8eccSSepherosa Ziehau 26346c8d8eccSSepherosa Ziehau tx_cons = sblk->bge_idx[0].bge_tx_cons_idx; 26356c8d8eccSSepherosa Ziehau if (sc->bnx_tx_saved_considx != tx_cons) 26366c8d8eccSSepherosa Ziehau bnx_txeof(sc, tx_cons); 26376c8d8eccSSepherosa Ziehau } 26386c8d8eccSSepherosa Ziehau break; 26396c8d8eccSSepherosa Ziehau } 26406c8d8eccSSepherosa Ziehau } 26416c8d8eccSSepherosa Ziehau 26426c8d8eccSSepherosa Ziehau #endif 26436c8d8eccSSepherosa Ziehau 26446c8d8eccSSepherosa Ziehau static void 26456c8d8eccSSepherosa Ziehau bnx_intr_legacy(void *xsc) 26466c8d8eccSSepherosa Ziehau { 26476c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 26486c8d8eccSSepherosa Ziehau struct bge_status_block *sblk = sc->bnx_ldata.bnx_status_block; 26496c8d8eccSSepherosa Ziehau 26506c8d8eccSSepherosa Ziehau if (sc->bnx_status_tag == sblk->bge_status_tag) { 26516c8d8eccSSepherosa Ziehau uint32_t val; 26526c8d8eccSSepherosa Ziehau 26536c8d8eccSSepherosa Ziehau val = pci_read_config(sc->bnx_dev, BGE_PCI_PCISTATE, 4); 26546c8d8eccSSepherosa Ziehau if (val & BGE_PCISTAT_INTR_NOTACT) 26556c8d8eccSSepherosa Ziehau return; 26566c8d8eccSSepherosa Ziehau } 26576c8d8eccSSepherosa Ziehau 26586c8d8eccSSepherosa Ziehau /* 26596c8d8eccSSepherosa Ziehau * NOTE: 26606c8d8eccSSepherosa Ziehau * Interrupt will have to be disabled if tagged status 26616c8d8eccSSepherosa Ziehau * is used, else interrupt will always be asserted on 26626c8d8eccSSepherosa Ziehau * certain chips (at least on BCM5750 AX/BX). 26636c8d8eccSSepherosa Ziehau */ 26646c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, 1); 26656c8d8eccSSepherosa Ziehau 26666c8d8eccSSepherosa Ziehau bnx_intr(sc); 26676c8d8eccSSepherosa Ziehau } 26686c8d8eccSSepherosa Ziehau 26696c8d8eccSSepherosa Ziehau static void 26706c8d8eccSSepherosa Ziehau bnx_msi(void *xsc) 26716c8d8eccSSepherosa Ziehau { 26726c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 26736c8d8eccSSepherosa Ziehau 26746c8d8eccSSepherosa Ziehau /* Disable interrupt first */ 26756c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, 1); 26766c8d8eccSSepherosa Ziehau bnx_intr(sc); 26776c8d8eccSSepherosa Ziehau } 26786c8d8eccSSepherosa Ziehau 26796c8d8eccSSepherosa Ziehau static void 26806c8d8eccSSepherosa Ziehau bnx_msi_oneshot(void *xsc) 26816c8d8eccSSepherosa Ziehau { 26826c8d8eccSSepherosa Ziehau bnx_intr(xsc); 26836c8d8eccSSepherosa Ziehau } 26846c8d8eccSSepherosa Ziehau 26856c8d8eccSSepherosa Ziehau static void 26866c8d8eccSSepherosa Ziehau bnx_intr(struct bnx_softc *sc) 26876c8d8eccSSepherosa Ziehau { 26886c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 26896c8d8eccSSepherosa Ziehau struct bge_status_block *sblk = sc->bnx_ldata.bnx_status_block; 26906c8d8eccSSepherosa Ziehau uint16_t rx_prod, tx_cons; 26916c8d8eccSSepherosa Ziehau uint32_t status; 26926c8d8eccSSepherosa Ziehau 26936c8d8eccSSepherosa Ziehau sc->bnx_status_tag = sblk->bge_status_tag; 26946c8d8eccSSepherosa Ziehau /* 26956c8d8eccSSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 26966c8d8eccSSepherosa Ziehau * before rx_prod, tx_cons and status. 26976c8d8eccSSepherosa Ziehau */ 26986c8d8eccSSepherosa Ziehau cpu_lfence(); 26996c8d8eccSSepherosa Ziehau 27006c8d8eccSSepherosa Ziehau rx_prod = sblk->bge_idx[0].bge_rx_prod_idx; 27016c8d8eccSSepherosa Ziehau tx_cons = sblk->bge_idx[0].bge_tx_cons_idx; 27026c8d8eccSSepherosa Ziehau status = sblk->bge_status; 27036c8d8eccSSepherosa Ziehau 27046c8d8eccSSepherosa Ziehau if ((status & BGE_STATFLAG_LINKSTATE_CHANGED) || sc->bnx_link_evt) 27056c8d8eccSSepherosa Ziehau bnx_link_poll(sc); 27066c8d8eccSSepherosa Ziehau 27076c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 27086c8d8eccSSepherosa Ziehau if (sc->bnx_rx_saved_considx != rx_prod) 27096c8d8eccSSepherosa Ziehau bnx_rxeof(sc, rx_prod); 27106c8d8eccSSepherosa Ziehau 27116c8d8eccSSepherosa Ziehau if (sc->bnx_tx_saved_considx != tx_cons) 27126c8d8eccSSepherosa Ziehau bnx_txeof(sc, tx_cons); 27136c8d8eccSSepherosa Ziehau } 27146c8d8eccSSepherosa Ziehau 27156c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, sc->bnx_status_tag << 24); 27166c8d8eccSSepherosa Ziehau 27176c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg) 27186c8d8eccSSepherosa Ziehau bnx_coal_change(sc); 27196c8d8eccSSepherosa Ziehau } 27206c8d8eccSSepherosa Ziehau 27216c8d8eccSSepherosa Ziehau static void 27226c8d8eccSSepherosa Ziehau bnx_tick(void *xsc) 27236c8d8eccSSepherosa Ziehau { 27246c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 27256c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 27266c8d8eccSSepherosa Ziehau 27276c8d8eccSSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 27286c8d8eccSSepherosa Ziehau 27298ca0f604SSepherosa Ziehau KKASSERT(mycpuid == sc->bnx_stat_cpuid); 27308ca0f604SSepherosa Ziehau 27316c8d8eccSSepherosa Ziehau bnx_stats_update_regs(sc); 27326c8d8eccSSepherosa Ziehau 27336c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 27346c8d8eccSSepherosa Ziehau /* 27356c8d8eccSSepherosa Ziehau * Since in TBI mode auto-polling can't be used we should poll 27366c8d8eccSSepherosa Ziehau * link status manually. Here we register pending link event 27376c8d8eccSSepherosa Ziehau * and trigger interrupt. 27386c8d8eccSSepherosa Ziehau */ 27396c8d8eccSSepherosa Ziehau sc->bnx_link_evt++; 27406c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_COAL_NOW); 27416c8d8eccSSepherosa Ziehau } else if (!sc->bnx_link) { 27426c8d8eccSSepherosa Ziehau mii_tick(device_get_softc(sc->bnx_miibus)); 27436c8d8eccSSepherosa Ziehau } 27446c8d8eccSSepherosa Ziehau 27456c8d8eccSSepherosa Ziehau callout_reset(&sc->bnx_stat_timer, hz, bnx_tick, sc); 27466c8d8eccSSepherosa Ziehau 27476c8d8eccSSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 27486c8d8eccSSepherosa Ziehau } 27496c8d8eccSSepherosa Ziehau 27506c8d8eccSSepherosa Ziehau static void 27516c8d8eccSSepherosa Ziehau bnx_stats_update_regs(struct bnx_softc *sc) 27526c8d8eccSSepherosa Ziehau { 27536c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 27546c8d8eccSSepherosa Ziehau struct bge_mac_stats_regs stats; 27556c8d8eccSSepherosa Ziehau uint32_t *s; 27566c8d8eccSSepherosa Ziehau int i; 27576c8d8eccSSepherosa Ziehau 27586c8d8eccSSepherosa Ziehau s = (uint32_t *)&stats; 27596c8d8eccSSepherosa Ziehau for (i = 0; i < sizeof(struct bge_mac_stats_regs); i += 4) { 27606c8d8eccSSepherosa Ziehau *s = CSR_READ_4(sc, BGE_RX_STATS + i); 27616c8d8eccSSepherosa Ziehau s++; 27626c8d8eccSSepherosa Ziehau } 27636c8d8eccSSepherosa Ziehau 27646c8d8eccSSepherosa Ziehau ifp->if_collisions += 27656c8d8eccSSepherosa Ziehau (stats.dot3StatsSingleCollisionFrames + 27666c8d8eccSSepherosa Ziehau stats.dot3StatsMultipleCollisionFrames + 27676c8d8eccSSepherosa Ziehau stats.dot3StatsExcessiveCollisions + 27686c8d8eccSSepherosa Ziehau stats.dot3StatsLateCollisions) - 27696c8d8eccSSepherosa Ziehau ifp->if_collisions; 27706c8d8eccSSepherosa Ziehau } 27716c8d8eccSSepherosa Ziehau 27726c8d8eccSSepherosa Ziehau /* 27736c8d8eccSSepherosa Ziehau * Encapsulate an mbuf chain in the tx ring by coupling the mbuf data 27746c8d8eccSSepherosa Ziehau * pointers to descriptors. 27756c8d8eccSSepherosa Ziehau */ 27766c8d8eccSSepherosa Ziehau static int 27776c8d8eccSSepherosa Ziehau bnx_encap(struct bnx_softc *sc, struct mbuf **m_head0, uint32_t *txidx) 27786c8d8eccSSepherosa Ziehau { 27796c8d8eccSSepherosa Ziehau struct bge_tx_bd *d = NULL; 27806c8d8eccSSepherosa Ziehau uint16_t csum_flags = 0; 27816c8d8eccSSepherosa Ziehau bus_dma_segment_t segs[BNX_NSEG_NEW]; 27826c8d8eccSSepherosa Ziehau bus_dmamap_t map; 27836c8d8eccSSepherosa Ziehau int error, maxsegs, nsegs, idx, i; 27846c8d8eccSSepherosa Ziehau struct mbuf *m_head = *m_head0, *m_new; 27856c8d8eccSSepherosa Ziehau 27866c8d8eccSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags) { 27876c8d8eccSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & CSUM_IP) 27886c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_CSUM; 27896c8d8eccSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 27906c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_TCP_UDP_CSUM; 27916c8d8eccSSepherosa Ziehau if (m_head->m_flags & M_LASTFRAG) 27926c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_FRAG_END; 27936c8d8eccSSepherosa Ziehau else if (m_head->m_flags & M_FRAG) 27946c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_FRAG; 27956c8d8eccSSepherosa Ziehau } 27966c8d8eccSSepherosa Ziehau 27976c8d8eccSSepherosa Ziehau idx = *txidx; 27986c8d8eccSSepherosa Ziehau map = sc->bnx_cdata.bnx_tx_dmamap[idx]; 27996c8d8eccSSepherosa Ziehau 28006c8d8eccSSepherosa Ziehau maxsegs = (BGE_TX_RING_CNT - sc->bnx_txcnt) - BNX_NSEG_RSVD; 28016c8d8eccSSepherosa Ziehau KASSERT(maxsegs >= BNX_NSEG_SPARE, 28026c8d8eccSSepherosa Ziehau ("not enough segments %d", maxsegs)); 28036c8d8eccSSepherosa Ziehau 28046c8d8eccSSepherosa Ziehau if (maxsegs > BNX_NSEG_NEW) 28056c8d8eccSSepherosa Ziehau maxsegs = BNX_NSEG_NEW; 28066c8d8eccSSepherosa Ziehau 28076c8d8eccSSepherosa Ziehau /* 28086c8d8eccSSepherosa Ziehau * Pad outbound frame to BGE_MIN_FRAMELEN for an unusual reason. 28096c8d8eccSSepherosa Ziehau * The bge hardware will pad out Tx runts to BGE_MIN_FRAMELEN, 28106c8d8eccSSepherosa Ziehau * but when such padded frames employ the bge IP/TCP checksum 28116c8d8eccSSepherosa Ziehau * offload, the hardware checksum assist gives incorrect results 28126c8d8eccSSepherosa Ziehau * (possibly from incorporating its own padding into the UDP/TCP 28136c8d8eccSSepherosa Ziehau * checksum; who knows). If we pad such runts with zeros, the 28146c8d8eccSSepherosa Ziehau * onboard checksum comes out correct. 28156c8d8eccSSepherosa Ziehau */ 28166c8d8eccSSepherosa Ziehau if ((csum_flags & BGE_TXBDFLAG_TCP_UDP_CSUM) && 28176c8d8eccSSepherosa Ziehau m_head->m_pkthdr.len < BNX_MIN_FRAMELEN) { 28186c8d8eccSSepherosa Ziehau error = m_devpad(m_head, BNX_MIN_FRAMELEN); 28196c8d8eccSSepherosa Ziehau if (error) 28206c8d8eccSSepherosa Ziehau goto back; 28216c8d8eccSSepherosa Ziehau } 28226c8d8eccSSepherosa Ziehau 28236c8d8eccSSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_SHORTDMA) && m_head->m_next != NULL) { 28246c8d8eccSSepherosa Ziehau m_new = bnx_defrag_shortdma(m_head); 28256c8d8eccSSepherosa Ziehau if (m_new == NULL) { 28266c8d8eccSSepherosa Ziehau error = ENOBUFS; 28276c8d8eccSSepherosa Ziehau goto back; 28286c8d8eccSSepherosa Ziehau } 28296c8d8eccSSepherosa Ziehau *m_head0 = m_head = m_new; 28306c8d8eccSSepherosa Ziehau } 28316c8d8eccSSepherosa Ziehau if (sc->bnx_force_defrag && m_head->m_next != NULL) { 28326c8d8eccSSepherosa Ziehau /* 28336c8d8eccSSepherosa Ziehau * Forcefully defragment mbuf chain to overcome hardware 28346c8d8eccSSepherosa Ziehau * limitation which only support a single outstanding 28356c8d8eccSSepherosa Ziehau * DMA read operation. If it fails, keep moving on using 28366c8d8eccSSepherosa Ziehau * the original mbuf chain. 28376c8d8eccSSepherosa Ziehau */ 28386c8d8eccSSepherosa Ziehau m_new = m_defrag(m_head, MB_DONTWAIT); 28396c8d8eccSSepherosa Ziehau if (m_new != NULL) 28406c8d8eccSSepherosa Ziehau *m_head0 = m_head = m_new; 28416c8d8eccSSepherosa Ziehau } 28426c8d8eccSSepherosa Ziehau 28436c8d8eccSSepherosa Ziehau error = bus_dmamap_load_mbuf_defrag(sc->bnx_cdata.bnx_tx_mtag, map, 28446c8d8eccSSepherosa Ziehau m_head0, segs, maxsegs, &nsegs, BUS_DMA_NOWAIT); 28456c8d8eccSSepherosa Ziehau if (error) 28466c8d8eccSSepherosa Ziehau goto back; 28476c8d8eccSSepherosa Ziehau 28486c8d8eccSSepherosa Ziehau m_head = *m_head0; 28496c8d8eccSSepherosa Ziehau bus_dmamap_sync(sc->bnx_cdata.bnx_tx_mtag, map, BUS_DMASYNC_PREWRITE); 28506c8d8eccSSepherosa Ziehau 28516c8d8eccSSepherosa Ziehau for (i = 0; ; i++) { 28526c8d8eccSSepherosa Ziehau d = &sc->bnx_ldata.bnx_tx_ring[idx]; 28536c8d8eccSSepherosa Ziehau 28546c8d8eccSSepherosa Ziehau d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr); 28556c8d8eccSSepherosa Ziehau d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr); 28566c8d8eccSSepherosa Ziehau d->bge_len = segs[i].ds_len; 28576c8d8eccSSepherosa Ziehau d->bge_flags = csum_flags; 28586c8d8eccSSepherosa Ziehau 28596c8d8eccSSepherosa Ziehau if (i == nsegs - 1) 28606c8d8eccSSepherosa Ziehau break; 28616c8d8eccSSepherosa Ziehau BNX_INC(idx, BGE_TX_RING_CNT); 28626c8d8eccSSepherosa Ziehau } 28636c8d8eccSSepherosa Ziehau /* Mark the last segment as end of packet... */ 28646c8d8eccSSepherosa Ziehau d->bge_flags |= BGE_TXBDFLAG_END; 28656c8d8eccSSepherosa Ziehau 28666c8d8eccSSepherosa Ziehau /* Set vlan tag to the first segment of the packet. */ 28676c8d8eccSSepherosa Ziehau d = &sc->bnx_ldata.bnx_tx_ring[*txidx]; 28686c8d8eccSSepherosa Ziehau if (m_head->m_flags & M_VLANTAG) { 28696c8d8eccSSepherosa Ziehau d->bge_flags |= BGE_TXBDFLAG_VLAN_TAG; 28706c8d8eccSSepherosa Ziehau d->bge_vlan_tag = m_head->m_pkthdr.ether_vlantag; 28716c8d8eccSSepherosa Ziehau } else { 28726c8d8eccSSepherosa Ziehau d->bge_vlan_tag = 0; 28736c8d8eccSSepherosa Ziehau } 28746c8d8eccSSepherosa Ziehau 28756c8d8eccSSepherosa Ziehau /* 28766c8d8eccSSepherosa Ziehau * Insure that the map for this transmission is placed at 28776c8d8eccSSepherosa Ziehau * the array index of the last descriptor in this chain. 28786c8d8eccSSepherosa Ziehau */ 28796c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_dmamap[*txidx] = sc->bnx_cdata.bnx_tx_dmamap[idx]; 28806c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_dmamap[idx] = map; 28816c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_chain[idx] = m_head; 28826c8d8eccSSepherosa Ziehau sc->bnx_txcnt += nsegs; 28836c8d8eccSSepherosa Ziehau 28846c8d8eccSSepherosa Ziehau BNX_INC(idx, BGE_TX_RING_CNT); 28856c8d8eccSSepherosa Ziehau *txidx = idx; 28866c8d8eccSSepherosa Ziehau back: 28876c8d8eccSSepherosa Ziehau if (error) { 28886c8d8eccSSepherosa Ziehau m_freem(*m_head0); 28896c8d8eccSSepherosa Ziehau *m_head0 = NULL; 28906c8d8eccSSepherosa Ziehau } 28916c8d8eccSSepherosa Ziehau return error; 28926c8d8eccSSepherosa Ziehau } 28936c8d8eccSSepherosa Ziehau 28946c8d8eccSSepherosa Ziehau /* 28956c8d8eccSSepherosa Ziehau * Main transmit routine. To avoid having to do mbuf copies, we put pointers 28966c8d8eccSSepherosa Ziehau * to the mbuf data regions directly in the transmit descriptors. 28976c8d8eccSSepherosa Ziehau */ 28986c8d8eccSSepherosa Ziehau static void 28996c8d8eccSSepherosa Ziehau bnx_start(struct ifnet *ifp) 29006c8d8eccSSepherosa Ziehau { 29016c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 29026c8d8eccSSepherosa Ziehau struct mbuf *m_head = NULL; 29036c8d8eccSSepherosa Ziehau uint32_t prodidx; 29046c8d8eccSSepherosa Ziehau int need_trans; 29056c8d8eccSSepherosa Ziehau 29066c8d8eccSSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 29076c8d8eccSSepherosa Ziehau return; 29086c8d8eccSSepherosa Ziehau 29096c8d8eccSSepherosa Ziehau prodidx = sc->bnx_tx_prodidx; 29106c8d8eccSSepherosa Ziehau 29116c8d8eccSSepherosa Ziehau need_trans = 0; 29126c8d8eccSSepherosa Ziehau while (sc->bnx_cdata.bnx_tx_chain[prodidx] == NULL) { 29136c8d8eccSSepherosa Ziehau m_head = ifq_dequeue(&ifp->if_snd, NULL); 29146c8d8eccSSepherosa Ziehau if (m_head == NULL) 29156c8d8eccSSepherosa Ziehau break; 29166c8d8eccSSepherosa Ziehau 29176c8d8eccSSepherosa Ziehau /* 29186c8d8eccSSepherosa Ziehau * XXX 29196c8d8eccSSepherosa Ziehau * The code inside the if() block is never reached since we 29206c8d8eccSSepherosa Ziehau * must mark CSUM_IP_FRAGS in our if_hwassist to start getting 29216c8d8eccSSepherosa Ziehau * requests to checksum TCP/UDP in a fragmented packet. 29226c8d8eccSSepherosa Ziehau * 29236c8d8eccSSepherosa Ziehau * XXX 29246c8d8eccSSepherosa Ziehau * safety overkill. If this is a fragmented packet chain 29256c8d8eccSSepherosa Ziehau * with delayed TCP/UDP checksums, then only encapsulate 29266c8d8eccSSepherosa Ziehau * it if we have enough descriptors to handle the entire 29276c8d8eccSSepherosa Ziehau * chain at once. 29286c8d8eccSSepherosa Ziehau * (paranoia -- may not actually be needed) 29296c8d8eccSSepherosa Ziehau */ 29306c8d8eccSSepherosa Ziehau if ((m_head->m_flags & M_FIRSTFRAG) && 29316c8d8eccSSepherosa Ziehau (m_head->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) { 29326c8d8eccSSepherosa Ziehau if ((BGE_TX_RING_CNT - sc->bnx_txcnt) < 29336c8d8eccSSepherosa Ziehau m_head->m_pkthdr.csum_data + BNX_NSEG_RSVD) { 29346c8d8eccSSepherosa Ziehau ifp->if_flags |= IFF_OACTIVE; 29356c8d8eccSSepherosa Ziehau ifq_prepend(&ifp->if_snd, m_head); 29366c8d8eccSSepherosa Ziehau break; 29376c8d8eccSSepherosa Ziehau } 29386c8d8eccSSepherosa Ziehau } 29396c8d8eccSSepherosa Ziehau 29406c8d8eccSSepherosa Ziehau /* 29416c8d8eccSSepherosa Ziehau * Sanity check: avoid coming within BGE_NSEG_RSVD 29426c8d8eccSSepherosa Ziehau * descriptors of the end of the ring. Also make 29436c8d8eccSSepherosa Ziehau * sure there are BGE_NSEG_SPARE descriptors for 29446c8d8eccSSepherosa Ziehau * jumbo buffers' defragmentation. 29456c8d8eccSSepherosa Ziehau */ 29466c8d8eccSSepherosa Ziehau if ((BGE_TX_RING_CNT - sc->bnx_txcnt) < 29476c8d8eccSSepherosa Ziehau (BNX_NSEG_RSVD + BNX_NSEG_SPARE)) { 29486c8d8eccSSepherosa Ziehau ifp->if_flags |= IFF_OACTIVE; 29496c8d8eccSSepherosa Ziehau ifq_prepend(&ifp->if_snd, m_head); 29506c8d8eccSSepherosa Ziehau break; 29516c8d8eccSSepherosa Ziehau } 29526c8d8eccSSepherosa Ziehau 29536c8d8eccSSepherosa Ziehau /* 29546c8d8eccSSepherosa Ziehau * Pack the data into the transmit ring. If we 29556c8d8eccSSepherosa Ziehau * don't have room, set the OACTIVE flag and wait 29566c8d8eccSSepherosa Ziehau * for the NIC to drain the ring. 29576c8d8eccSSepherosa Ziehau */ 29586c8d8eccSSepherosa Ziehau if (bnx_encap(sc, &m_head, &prodidx)) { 29596c8d8eccSSepherosa Ziehau ifp->if_flags |= IFF_OACTIVE; 29606c8d8eccSSepherosa Ziehau ifp->if_oerrors++; 29616c8d8eccSSepherosa Ziehau break; 29626c8d8eccSSepherosa Ziehau } 29636c8d8eccSSepherosa Ziehau need_trans = 1; 29646c8d8eccSSepherosa Ziehau 29656c8d8eccSSepherosa Ziehau ETHER_BPF_MTAP(ifp, m_head); 29666c8d8eccSSepherosa Ziehau } 29676c8d8eccSSepherosa Ziehau 29686c8d8eccSSepherosa Ziehau if (!need_trans) 29696c8d8eccSSepherosa Ziehau return; 29706c8d8eccSSepherosa Ziehau 29716c8d8eccSSepherosa Ziehau /* Transmit */ 29726c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); 29736c8d8eccSSepherosa Ziehau 29746c8d8eccSSepherosa Ziehau sc->bnx_tx_prodidx = prodidx; 29756c8d8eccSSepherosa Ziehau 29766c8d8eccSSepherosa Ziehau /* 29776c8d8eccSSepherosa Ziehau * Set a timeout in case the chip goes out to lunch. 29786c8d8eccSSepherosa Ziehau */ 29796c8d8eccSSepherosa Ziehau ifp->if_timer = 5; 29806c8d8eccSSepherosa Ziehau } 29816c8d8eccSSepherosa Ziehau 29826c8d8eccSSepherosa Ziehau static void 29836c8d8eccSSepherosa Ziehau bnx_init(void *xsc) 29846c8d8eccSSepherosa Ziehau { 29856c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 29866c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 29876c8d8eccSSepherosa Ziehau uint16_t *m; 29886c8d8eccSSepherosa Ziehau uint32_t mode; 29896c8d8eccSSepherosa Ziehau 29906c8d8eccSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 29916c8d8eccSSepherosa Ziehau 29926c8d8eccSSepherosa Ziehau /* Cancel pending I/O and flush buffers. */ 29936c8d8eccSSepherosa Ziehau bnx_stop(sc); 29946c8d8eccSSepherosa Ziehau bnx_reset(sc); 29956c8d8eccSSepherosa Ziehau bnx_chipinit(sc); 29966c8d8eccSSepherosa Ziehau 29976c8d8eccSSepherosa Ziehau /* 29986c8d8eccSSepherosa Ziehau * Init the various state machines, ring 29996c8d8eccSSepherosa Ziehau * control blocks and firmware. 30006c8d8eccSSepherosa Ziehau */ 30016c8d8eccSSepherosa Ziehau if (bnx_blockinit(sc)) { 30026c8d8eccSSepherosa Ziehau if_printf(ifp, "initialization failure\n"); 30036c8d8eccSSepherosa Ziehau bnx_stop(sc); 30046c8d8eccSSepherosa Ziehau return; 30056c8d8eccSSepherosa Ziehau } 30066c8d8eccSSepherosa Ziehau 30076c8d8eccSSepherosa Ziehau /* Specify MTU. */ 30086c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_MTU, ifp->if_mtu + 30096c8d8eccSSepherosa Ziehau ETHER_HDR_LEN + ETHER_CRC_LEN + EVL_ENCAPLEN); 30106c8d8eccSSepherosa Ziehau 30116c8d8eccSSepherosa Ziehau /* Load our MAC address. */ 30126c8d8eccSSepherosa Ziehau m = (uint16_t *)&sc->arpcom.ac_enaddr[0]; 30136c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_ADDR1_LO, htons(m[0])); 30146c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_ADDR1_HI, (htons(m[1]) << 16) | htons(m[2])); 30156c8d8eccSSepherosa Ziehau 30166c8d8eccSSepherosa Ziehau /* Enable or disable promiscuous mode as needed. */ 30176c8d8eccSSepherosa Ziehau bnx_setpromisc(sc); 30186c8d8eccSSepherosa Ziehau 30196c8d8eccSSepherosa Ziehau /* Program multicast filter. */ 30206c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 30216c8d8eccSSepherosa Ziehau 30226c8d8eccSSepherosa Ziehau /* Init RX ring. */ 30236c8d8eccSSepherosa Ziehau if (bnx_init_rx_ring_std(sc)) { 30246c8d8eccSSepherosa Ziehau if_printf(ifp, "RX ring initialization failed\n"); 30256c8d8eccSSepherosa Ziehau bnx_stop(sc); 30266c8d8eccSSepherosa Ziehau return; 30276c8d8eccSSepherosa Ziehau } 30286c8d8eccSSepherosa Ziehau 30296c8d8eccSSepherosa Ziehau /* Init jumbo RX ring. */ 30306c8d8eccSSepherosa Ziehau if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN)) { 30316c8d8eccSSepherosa Ziehau if (bnx_init_rx_ring_jumbo(sc)) { 30326c8d8eccSSepherosa Ziehau if_printf(ifp, "Jumbo RX ring initialization failed\n"); 30336c8d8eccSSepherosa Ziehau bnx_stop(sc); 30346c8d8eccSSepherosa Ziehau return; 30356c8d8eccSSepherosa Ziehau } 30366c8d8eccSSepherosa Ziehau } 30376c8d8eccSSepherosa Ziehau 30386c8d8eccSSepherosa Ziehau /* Init our RX return ring index */ 30396c8d8eccSSepherosa Ziehau sc->bnx_rx_saved_considx = 0; 30406c8d8eccSSepherosa Ziehau 30416c8d8eccSSepherosa Ziehau /* Init TX ring. */ 30426c8d8eccSSepherosa Ziehau bnx_init_tx_ring(sc); 30436c8d8eccSSepherosa Ziehau 30446c8d8eccSSepherosa Ziehau /* Enable TX MAC state machine lockup fix. */ 30456c8d8eccSSepherosa Ziehau mode = CSR_READ_4(sc, BGE_TX_MODE); 30466c8d8eccSSepherosa Ziehau mode |= BGE_TXMODE_MBUF_LOCKUP_FIX; 30476c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 30486c8d8eccSSepherosa Ziehau mode &= ~(BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE); 30496c8d8eccSSepherosa Ziehau mode |= CSR_READ_4(sc, BGE_TX_MODE) & 30506c8d8eccSSepherosa Ziehau (BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE); 30516c8d8eccSSepherosa Ziehau } 30526c8d8eccSSepherosa Ziehau /* Turn on transmitter */ 30536c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_MODE, mode | BGE_TXMODE_ENABLE); 30546c8d8eccSSepherosa Ziehau 30556c8d8eccSSepherosa Ziehau /* Turn on receiver */ 30566c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); 30576c8d8eccSSepherosa Ziehau 30586c8d8eccSSepherosa Ziehau /* 30596c8d8eccSSepherosa Ziehau * Set the number of good frames to receive after RX MBUF 30606c8d8eccSSepherosa Ziehau * Low Watermark has been reached. After the RX MAC receives 30616c8d8eccSSepherosa Ziehau * this number of frames, it will drop subsequent incoming 30626c8d8eccSSepherosa Ziehau * frames until the MBUF High Watermark is reached. 30636c8d8eccSSepherosa Ziehau */ 3064bcb29629SSepherosa Ziehau if (BNX_IS_57765_FAMILY(sc)) 30656c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1); 30666c8d8eccSSepherosa Ziehau else 30676c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2); 30686c8d8eccSSepherosa Ziehau 30696c8d8eccSSepherosa Ziehau if (sc->bnx_irq_type == PCI_INTR_TYPE_MSI) { 30706c8d8eccSSepherosa Ziehau if (bootverbose) { 30716c8d8eccSSepherosa Ziehau if_printf(ifp, "MSI_MODE: %#x\n", 30726c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_MSI_MODE)); 30736c8d8eccSSepherosa Ziehau } 30746c8d8eccSSepherosa Ziehau } 30756c8d8eccSSepherosa Ziehau 30766c8d8eccSSepherosa Ziehau /* Tell firmware we're alive. */ 30776c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); 30786c8d8eccSSepherosa Ziehau 30796c8d8eccSSepherosa Ziehau /* Enable host interrupts if polling(4) is not enabled. */ 30806c8d8eccSSepherosa Ziehau PCI_SETBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA, 4); 30816c8d8eccSSepherosa Ziehau #ifdef DEVICE_POLLING 30826c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_POLLING) 30836c8d8eccSSepherosa Ziehau bnx_disable_intr(sc); 30846c8d8eccSSepherosa Ziehau else 30856c8d8eccSSepherosa Ziehau #endif 30866c8d8eccSSepherosa Ziehau bnx_enable_intr(sc); 30876c8d8eccSSepherosa Ziehau 30886c8d8eccSSepherosa Ziehau bnx_ifmedia_upd(ifp); 30896c8d8eccSSepherosa Ziehau 30906c8d8eccSSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 30916c8d8eccSSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 30926c8d8eccSSepherosa Ziehau 30938ca0f604SSepherosa Ziehau callout_reset_bycpu(&sc->bnx_stat_timer, hz, bnx_tick, sc, 30948ca0f604SSepherosa Ziehau sc->bnx_stat_cpuid); 30956c8d8eccSSepherosa Ziehau } 30966c8d8eccSSepherosa Ziehau 30976c8d8eccSSepherosa Ziehau /* 30986c8d8eccSSepherosa Ziehau * Set media options. 30996c8d8eccSSepherosa Ziehau */ 31006c8d8eccSSepherosa Ziehau static int 31016c8d8eccSSepherosa Ziehau bnx_ifmedia_upd(struct ifnet *ifp) 31026c8d8eccSSepherosa Ziehau { 31036c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 31046c8d8eccSSepherosa Ziehau 31056c8d8eccSSepherosa Ziehau /* If this is a 1000baseX NIC, enable the TBI port. */ 31066c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 31076c8d8eccSSepherosa Ziehau struct ifmedia *ifm = &sc->bnx_ifmedia; 31086c8d8eccSSepherosa Ziehau 31096c8d8eccSSepherosa Ziehau if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 31106c8d8eccSSepherosa Ziehau return(EINVAL); 31116c8d8eccSSepherosa Ziehau 31126c8d8eccSSepherosa Ziehau switch(IFM_SUBTYPE(ifm->ifm_media)) { 31136c8d8eccSSepherosa Ziehau case IFM_AUTO: 31146c8d8eccSSepherosa Ziehau break; 31156c8d8eccSSepherosa Ziehau 31166c8d8eccSSepherosa Ziehau case IFM_1000_SX: 31176c8d8eccSSepherosa Ziehau if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) { 31186c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, 31196c8d8eccSSepherosa Ziehau BGE_MACMODE_HALF_DUPLEX); 31206c8d8eccSSepherosa Ziehau } else { 31216c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, 31226c8d8eccSSepherosa Ziehau BGE_MACMODE_HALF_DUPLEX); 31236c8d8eccSSepherosa Ziehau } 31246c8d8eccSSepherosa Ziehau break; 31256c8d8eccSSepherosa Ziehau default: 31266c8d8eccSSepherosa Ziehau return(EINVAL); 31276c8d8eccSSepherosa Ziehau } 31286c8d8eccSSepherosa Ziehau } else { 31296c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 31306c8d8eccSSepherosa Ziehau 31316c8d8eccSSepherosa Ziehau sc->bnx_link_evt++; 31326c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 31336c8d8eccSSepherosa Ziehau if (mii->mii_instance) { 31346c8d8eccSSepherosa Ziehau struct mii_softc *miisc; 31356c8d8eccSSepherosa Ziehau 31366c8d8eccSSepherosa Ziehau LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 31376c8d8eccSSepherosa Ziehau mii_phy_reset(miisc); 31386c8d8eccSSepherosa Ziehau } 31396c8d8eccSSepherosa Ziehau mii_mediachg(mii); 31406c8d8eccSSepherosa Ziehau 31416c8d8eccSSepherosa Ziehau /* 31426c8d8eccSSepherosa Ziehau * Force an interrupt so that we will call bnx_link_upd 31436c8d8eccSSepherosa Ziehau * if needed and clear any pending link state attention. 31446c8d8eccSSepherosa Ziehau * Without this we are not getting any further interrupts 31456c8d8eccSSepherosa Ziehau * for link state changes and thus will not UP the link and 31466c8d8eccSSepherosa Ziehau * not be able to send in bnx_start. The only way to get 31476c8d8eccSSepherosa Ziehau * things working was to receive a packet and get an RX 31486c8d8eccSSepherosa Ziehau * intr. 31496c8d8eccSSepherosa Ziehau * 31506c8d8eccSSepherosa Ziehau * bnx_tick should help for fiber cards and we might not 31516c8d8eccSSepherosa Ziehau * need to do this here if BNX_FLAG_TBI is set but as 31526c8d8eccSSepherosa Ziehau * we poll for fiber anyway it should not harm. 31536c8d8eccSSepherosa Ziehau */ 31546c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_COAL_NOW); 31556c8d8eccSSepherosa Ziehau } 31566c8d8eccSSepherosa Ziehau return(0); 31576c8d8eccSSepherosa Ziehau } 31586c8d8eccSSepherosa Ziehau 31596c8d8eccSSepherosa Ziehau /* 31606c8d8eccSSepherosa Ziehau * Report current media status. 31616c8d8eccSSepherosa Ziehau */ 31626c8d8eccSSepherosa Ziehau static void 31636c8d8eccSSepherosa Ziehau bnx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 31646c8d8eccSSepherosa Ziehau { 31656c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 31666c8d8eccSSepherosa Ziehau 31676c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 31686c8d8eccSSepherosa Ziehau ifmr->ifm_status = IFM_AVALID; 31696c8d8eccSSepherosa Ziehau ifmr->ifm_active = IFM_ETHER; 31706c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_MAC_STS) & 31716c8d8eccSSepherosa Ziehau BGE_MACSTAT_TBI_PCS_SYNCHED) { 31726c8d8eccSSepherosa Ziehau ifmr->ifm_status |= IFM_ACTIVE; 31736c8d8eccSSepherosa Ziehau } else { 31746c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_NONE; 31756c8d8eccSSepherosa Ziehau return; 31766c8d8eccSSepherosa Ziehau } 31776c8d8eccSSepherosa Ziehau 31786c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_SX; 31796c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_MAC_MODE) & BGE_MACMODE_HALF_DUPLEX) 31806c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_HDX; 31816c8d8eccSSepherosa Ziehau else 31826c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_FDX; 31836c8d8eccSSepherosa Ziehau } else { 31846c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 31856c8d8eccSSepherosa Ziehau 31866c8d8eccSSepherosa Ziehau mii_pollstat(mii); 31876c8d8eccSSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 31886c8d8eccSSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 31896c8d8eccSSepherosa Ziehau } 31906c8d8eccSSepherosa Ziehau } 31916c8d8eccSSepherosa Ziehau 31926c8d8eccSSepherosa Ziehau static int 31936c8d8eccSSepherosa Ziehau bnx_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) 31946c8d8eccSSepherosa Ziehau { 31956c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 31966c8d8eccSSepherosa Ziehau struct ifreq *ifr = (struct ifreq *)data; 31976c8d8eccSSepherosa Ziehau int mask, error = 0; 31986c8d8eccSSepherosa Ziehau 31996c8d8eccSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 32006c8d8eccSSepherosa Ziehau 32016c8d8eccSSepherosa Ziehau switch (command) { 32026c8d8eccSSepherosa Ziehau case SIOCSIFMTU: 32036c8d8eccSSepherosa Ziehau if ((!BNX_IS_JUMBO_CAPABLE(sc) && ifr->ifr_mtu > ETHERMTU) || 32046c8d8eccSSepherosa Ziehau (BNX_IS_JUMBO_CAPABLE(sc) && 32056c8d8eccSSepherosa Ziehau ifr->ifr_mtu > BNX_JUMBO_MTU)) { 32066c8d8eccSSepherosa Ziehau error = EINVAL; 32076c8d8eccSSepherosa Ziehau } else if (ifp->if_mtu != ifr->ifr_mtu) { 32086c8d8eccSSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 32096c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 32106c8d8eccSSepherosa Ziehau bnx_init(sc); 32116c8d8eccSSepherosa Ziehau } 32126c8d8eccSSepherosa Ziehau break; 32136c8d8eccSSepherosa Ziehau case SIOCSIFFLAGS: 32146c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 32156c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 32166c8d8eccSSepherosa Ziehau mask = ifp->if_flags ^ sc->bnx_if_flags; 32176c8d8eccSSepherosa Ziehau 32186c8d8eccSSepherosa Ziehau /* 32196c8d8eccSSepherosa Ziehau * If only the state of the PROMISC flag 32206c8d8eccSSepherosa Ziehau * changed, then just use the 'set promisc 32216c8d8eccSSepherosa Ziehau * mode' command instead of reinitializing 32226c8d8eccSSepherosa Ziehau * the entire NIC. Doing a full re-init 32236c8d8eccSSepherosa Ziehau * means reloading the firmware and waiting 32246c8d8eccSSepherosa Ziehau * for it to start up, which may take a 32256c8d8eccSSepherosa Ziehau * second or two. Similarly for ALLMULTI. 32266c8d8eccSSepherosa Ziehau */ 32276c8d8eccSSepherosa Ziehau if (mask & IFF_PROMISC) 32286c8d8eccSSepherosa Ziehau bnx_setpromisc(sc); 32296c8d8eccSSepherosa Ziehau if (mask & IFF_ALLMULTI) 32306c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 32316c8d8eccSSepherosa Ziehau } else { 32326c8d8eccSSepherosa Ziehau bnx_init(sc); 32336c8d8eccSSepherosa Ziehau } 32346c8d8eccSSepherosa Ziehau } else if (ifp->if_flags & IFF_RUNNING) { 32356c8d8eccSSepherosa Ziehau bnx_stop(sc); 32366c8d8eccSSepherosa Ziehau } 32376c8d8eccSSepherosa Ziehau sc->bnx_if_flags = ifp->if_flags; 32386c8d8eccSSepherosa Ziehau break; 32396c8d8eccSSepherosa Ziehau case SIOCADDMULTI: 32406c8d8eccSSepherosa Ziehau case SIOCDELMULTI: 32416c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 32426c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 32436c8d8eccSSepherosa Ziehau break; 32446c8d8eccSSepherosa Ziehau case SIOCSIFMEDIA: 32456c8d8eccSSepherosa Ziehau case SIOCGIFMEDIA: 32466c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 32476c8d8eccSSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, 32486c8d8eccSSepherosa Ziehau &sc->bnx_ifmedia, command); 32496c8d8eccSSepherosa Ziehau } else { 32506c8d8eccSSepherosa Ziehau struct mii_data *mii; 32516c8d8eccSSepherosa Ziehau 32526c8d8eccSSepherosa Ziehau mii = device_get_softc(sc->bnx_miibus); 32536c8d8eccSSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, 32546c8d8eccSSepherosa Ziehau &mii->mii_media, command); 32556c8d8eccSSepherosa Ziehau } 32566c8d8eccSSepherosa Ziehau break; 32576c8d8eccSSepherosa Ziehau case SIOCSIFCAP: 32586c8d8eccSSepherosa Ziehau mask = ifr->ifr_reqcap ^ ifp->if_capenable; 32596c8d8eccSSepherosa Ziehau if (mask & IFCAP_HWCSUM) { 32606c8d8eccSSepherosa Ziehau ifp->if_capenable ^= (mask & IFCAP_HWCSUM); 32616c8d8eccSSepherosa Ziehau if (IFCAP_HWCSUM & ifp->if_capenable) 32626c8d8eccSSepherosa Ziehau ifp->if_hwassist = BNX_CSUM_FEATURES; 32636c8d8eccSSepherosa Ziehau else 32646c8d8eccSSepherosa Ziehau ifp->if_hwassist = 0; 32656c8d8eccSSepherosa Ziehau } 32666c8d8eccSSepherosa Ziehau break; 32676c8d8eccSSepherosa Ziehau default: 32686c8d8eccSSepherosa Ziehau error = ether_ioctl(ifp, command, data); 32696c8d8eccSSepherosa Ziehau break; 32706c8d8eccSSepherosa Ziehau } 32716c8d8eccSSepherosa Ziehau return error; 32726c8d8eccSSepherosa Ziehau } 32736c8d8eccSSepherosa Ziehau 32746c8d8eccSSepherosa Ziehau static void 32756c8d8eccSSepherosa Ziehau bnx_watchdog(struct ifnet *ifp) 32766c8d8eccSSepherosa Ziehau { 32776c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 32786c8d8eccSSepherosa Ziehau 32796c8d8eccSSepherosa Ziehau if_printf(ifp, "watchdog timeout -- resetting\n"); 32806c8d8eccSSepherosa Ziehau 32816c8d8eccSSepherosa Ziehau bnx_init(sc); 32826c8d8eccSSepherosa Ziehau 32836c8d8eccSSepherosa Ziehau ifp->if_oerrors++; 32846c8d8eccSSepherosa Ziehau 32856c8d8eccSSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 32866c8d8eccSSepherosa Ziehau if_devstart(ifp); 32876c8d8eccSSepherosa Ziehau } 32886c8d8eccSSepherosa Ziehau 32896c8d8eccSSepherosa Ziehau /* 32906c8d8eccSSepherosa Ziehau * Stop the adapter and free any mbufs allocated to the 32916c8d8eccSSepherosa Ziehau * RX and TX lists. 32926c8d8eccSSepherosa Ziehau */ 32936c8d8eccSSepherosa Ziehau static void 32946c8d8eccSSepherosa Ziehau bnx_stop(struct bnx_softc *sc) 32956c8d8eccSSepherosa Ziehau { 32966c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 32976c8d8eccSSepherosa Ziehau 32986c8d8eccSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 32996c8d8eccSSepherosa Ziehau 33006c8d8eccSSepherosa Ziehau callout_stop(&sc->bnx_stat_timer); 33016c8d8eccSSepherosa Ziehau 33026c8d8eccSSepherosa Ziehau /* 33036c8d8eccSSepherosa Ziehau * Disable all of the receiver blocks 33046c8d8eccSSepherosa Ziehau */ 33056c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); 33066c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); 33076c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); 33086c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); 33096c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); 33106c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); 33116c8d8eccSSepherosa Ziehau 33126c8d8eccSSepherosa Ziehau /* 33136c8d8eccSSepherosa Ziehau * Disable all of the transmit blocks 33146c8d8eccSSepherosa Ziehau */ 33156c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); 33166c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); 33176c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); 33186c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); 33196c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); 33206c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); 33216c8d8eccSSepherosa Ziehau 33226c8d8eccSSepherosa Ziehau /* 33236c8d8eccSSepherosa Ziehau * Shut down all of the memory managers and related 33246c8d8eccSSepherosa Ziehau * state machines. 33256c8d8eccSSepherosa Ziehau */ 33266c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); 33276c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); 33286c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); 33296c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); 33306c8d8eccSSepherosa Ziehau 33316c8d8eccSSepherosa Ziehau /* Disable host interrupts. */ 33326c8d8eccSSepherosa Ziehau bnx_disable_intr(sc); 33336c8d8eccSSepherosa Ziehau 33346c8d8eccSSepherosa Ziehau /* 33356c8d8eccSSepherosa Ziehau * Tell firmware we're shutting down. 33366c8d8eccSSepherosa Ziehau */ 33376c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); 33386c8d8eccSSepherosa Ziehau 33396c8d8eccSSepherosa Ziehau /* Free the RX lists. */ 33406c8d8eccSSepherosa Ziehau bnx_free_rx_ring_std(sc); 33416c8d8eccSSepherosa Ziehau 33426c8d8eccSSepherosa Ziehau /* Free jumbo RX list. */ 33436c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) 33446c8d8eccSSepherosa Ziehau bnx_free_rx_ring_jumbo(sc); 33456c8d8eccSSepherosa Ziehau 33466c8d8eccSSepherosa Ziehau /* Free TX buffers. */ 33476c8d8eccSSepherosa Ziehau bnx_free_tx_ring(sc); 33486c8d8eccSSepherosa Ziehau 33496c8d8eccSSepherosa Ziehau sc->bnx_status_tag = 0; 33506c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 33516c8d8eccSSepherosa Ziehau sc->bnx_coal_chg = 0; 33526c8d8eccSSepherosa Ziehau 33536c8d8eccSSepherosa Ziehau sc->bnx_tx_saved_considx = BNX_TXCONS_UNSET; 33546c8d8eccSSepherosa Ziehau 33556c8d8eccSSepherosa Ziehau ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 33566c8d8eccSSepherosa Ziehau ifp->if_timer = 0; 33576c8d8eccSSepherosa Ziehau } 33586c8d8eccSSepherosa Ziehau 33596c8d8eccSSepherosa Ziehau /* 33606c8d8eccSSepherosa Ziehau * Stop all chip I/O so that the kernel's probe routines don't 33616c8d8eccSSepherosa Ziehau * get confused by errant DMAs when rebooting. 33626c8d8eccSSepherosa Ziehau */ 33636c8d8eccSSepherosa Ziehau static void 33646c8d8eccSSepherosa Ziehau bnx_shutdown(device_t dev) 33656c8d8eccSSepherosa Ziehau { 33666c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 33676c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 33686c8d8eccSSepherosa Ziehau 33696c8d8eccSSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 33706c8d8eccSSepherosa Ziehau bnx_stop(sc); 33716c8d8eccSSepherosa Ziehau bnx_reset(sc); 33726c8d8eccSSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 33736c8d8eccSSepherosa Ziehau } 33746c8d8eccSSepherosa Ziehau 33756c8d8eccSSepherosa Ziehau static int 33766c8d8eccSSepherosa Ziehau bnx_suspend(device_t dev) 33776c8d8eccSSepherosa Ziehau { 33786c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 33796c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 33806c8d8eccSSepherosa Ziehau 33816c8d8eccSSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 33826c8d8eccSSepherosa Ziehau bnx_stop(sc); 33836c8d8eccSSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 33846c8d8eccSSepherosa Ziehau 33856c8d8eccSSepherosa Ziehau return 0; 33866c8d8eccSSepherosa Ziehau } 33876c8d8eccSSepherosa Ziehau 33886c8d8eccSSepherosa Ziehau static int 33896c8d8eccSSepherosa Ziehau bnx_resume(device_t dev) 33906c8d8eccSSepherosa Ziehau { 33916c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 33926c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 33936c8d8eccSSepherosa Ziehau 33946c8d8eccSSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 33956c8d8eccSSepherosa Ziehau 33966c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 33976c8d8eccSSepherosa Ziehau bnx_init(sc); 33986c8d8eccSSepherosa Ziehau 33996c8d8eccSSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 34006c8d8eccSSepherosa Ziehau if_devstart(ifp); 34016c8d8eccSSepherosa Ziehau } 34026c8d8eccSSepherosa Ziehau 34036c8d8eccSSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 34046c8d8eccSSepherosa Ziehau 34056c8d8eccSSepherosa Ziehau return 0; 34066c8d8eccSSepherosa Ziehau } 34076c8d8eccSSepherosa Ziehau 34086c8d8eccSSepherosa Ziehau static void 34096c8d8eccSSepherosa Ziehau bnx_setpromisc(struct bnx_softc *sc) 34106c8d8eccSSepherosa Ziehau { 34116c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 34126c8d8eccSSepherosa Ziehau 34136c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_PROMISC) 34146c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); 34156c8d8eccSSepherosa Ziehau else 34166c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); 34176c8d8eccSSepherosa Ziehau } 34186c8d8eccSSepherosa Ziehau 34196c8d8eccSSepherosa Ziehau static void 34206c8d8eccSSepherosa Ziehau bnx_dma_free(struct bnx_softc *sc) 34216c8d8eccSSepherosa Ziehau { 34226c8d8eccSSepherosa Ziehau int i; 34236c8d8eccSSepherosa Ziehau 34246c8d8eccSSepherosa Ziehau /* Destroy RX mbuf DMA stuffs. */ 34256c8d8eccSSepherosa Ziehau if (sc->bnx_cdata.bnx_rx_mtag != NULL) { 34266c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 34276c8d8eccSSepherosa Ziehau bus_dmamap_destroy(sc->bnx_cdata.bnx_rx_mtag, 34286c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_std_dmamap[i]); 34296c8d8eccSSepherosa Ziehau } 34306c8d8eccSSepherosa Ziehau bus_dmamap_destroy(sc->bnx_cdata.bnx_rx_mtag, 34316c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_tmpmap); 34326c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(sc->bnx_cdata.bnx_rx_mtag); 34336c8d8eccSSepherosa Ziehau } 34346c8d8eccSSepherosa Ziehau 34356c8d8eccSSepherosa Ziehau /* Destroy TX mbuf DMA stuffs. */ 34366c8d8eccSSepherosa Ziehau if (sc->bnx_cdata.bnx_tx_mtag != NULL) { 34376c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 34386c8d8eccSSepherosa Ziehau bus_dmamap_destroy(sc->bnx_cdata.bnx_tx_mtag, 34396c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_dmamap[i]); 34406c8d8eccSSepherosa Ziehau } 34416c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(sc->bnx_cdata.bnx_tx_mtag); 34426c8d8eccSSepherosa Ziehau } 34436c8d8eccSSepherosa Ziehau 34446c8d8eccSSepherosa Ziehau /* Destroy standard RX ring */ 34456c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_rx_std_ring_tag, 34466c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_std_ring_map, 34476c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_rx_std_ring); 34486c8d8eccSSepherosa Ziehau 34496c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) 34506c8d8eccSSepherosa Ziehau bnx_free_jumbo_mem(sc); 34516c8d8eccSSepherosa Ziehau 34526c8d8eccSSepherosa Ziehau /* Destroy RX return ring */ 34536c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_rx_return_ring_tag, 34546c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_return_ring_map, 34556c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_rx_return_ring); 34566c8d8eccSSepherosa Ziehau 34576c8d8eccSSepherosa Ziehau /* Destroy TX ring */ 34586c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_tx_ring_tag, 34596c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_ring_map, 34606c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_tx_ring); 34616c8d8eccSSepherosa Ziehau 34626c8d8eccSSepherosa Ziehau /* Destroy status block */ 34636c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_status_tag, 34646c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_status_map, 34656c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_status_block); 34666c8d8eccSSepherosa Ziehau 34676c8d8eccSSepherosa Ziehau /* Destroy the parent tag */ 34686c8d8eccSSepherosa Ziehau if (sc->bnx_cdata.bnx_parent_tag != NULL) 34696c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(sc->bnx_cdata.bnx_parent_tag); 34706c8d8eccSSepherosa Ziehau } 34716c8d8eccSSepherosa Ziehau 34726c8d8eccSSepherosa Ziehau static int 34736c8d8eccSSepherosa Ziehau bnx_dma_alloc(struct bnx_softc *sc) 34746c8d8eccSSepherosa Ziehau { 34756c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 34766c8d8eccSSepherosa Ziehau int i, error; 34776c8d8eccSSepherosa Ziehau 34786c8d8eccSSepherosa Ziehau /* 34796c8d8eccSSepherosa Ziehau * Allocate the parent bus DMA tag appropriate for PCI. 34806c8d8eccSSepherosa Ziehau * 34816c8d8eccSSepherosa Ziehau * All of the NetExtreme/NetLink controllers have 4GB boundary 34826c8d8eccSSepherosa Ziehau * DMA bug. 34836c8d8eccSSepherosa Ziehau * Whenever an address crosses a multiple of the 4GB boundary 34846c8d8eccSSepherosa Ziehau * (including 4GB, 8Gb, 12Gb, etc.) and makes the transition 34856c8d8eccSSepherosa Ziehau * from 0xX_FFFF_FFFF to 0x(X+1)_0000_0000 an internal DMA 34866c8d8eccSSepherosa Ziehau * state machine will lockup and cause the device to hang. 34876c8d8eccSSepherosa Ziehau */ 34886c8d8eccSSepherosa Ziehau error = bus_dma_tag_create(NULL, 1, BGE_DMA_BOUNDARY_4G, 34896c8d8eccSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 34906c8d8eccSSepherosa Ziehau NULL, NULL, 34916c8d8eccSSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 0, 34926c8d8eccSSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 34936c8d8eccSSepherosa Ziehau 0, &sc->bnx_cdata.bnx_parent_tag); 34946c8d8eccSSepherosa Ziehau if (error) { 34956c8d8eccSSepherosa Ziehau if_printf(ifp, "could not allocate parent dma tag\n"); 34966c8d8eccSSepherosa Ziehau return error; 34976c8d8eccSSepherosa Ziehau } 34986c8d8eccSSepherosa Ziehau 34996c8d8eccSSepherosa Ziehau /* 35006c8d8eccSSepherosa Ziehau * Create DMA tag and maps for RX mbufs. 35016c8d8eccSSepherosa Ziehau */ 35026c8d8eccSSepherosa Ziehau error = bus_dma_tag_create(sc->bnx_cdata.bnx_parent_tag, 1, 0, 35036c8d8eccSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 35046c8d8eccSSepherosa Ziehau NULL, NULL, MCLBYTES, 1, MCLBYTES, 35056c8d8eccSSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK, 35066c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_mtag); 35076c8d8eccSSepherosa Ziehau if (error) { 35086c8d8eccSSepherosa Ziehau if_printf(ifp, "could not allocate RX mbuf dma tag\n"); 35096c8d8eccSSepherosa Ziehau return error; 35106c8d8eccSSepherosa Ziehau } 35116c8d8eccSSepherosa Ziehau 35126c8d8eccSSepherosa Ziehau error = bus_dmamap_create(sc->bnx_cdata.bnx_rx_mtag, 35136c8d8eccSSepherosa Ziehau BUS_DMA_WAITOK, &sc->bnx_cdata.bnx_rx_tmpmap); 35146c8d8eccSSepherosa Ziehau if (error) { 35156c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(sc->bnx_cdata.bnx_rx_mtag); 35166c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_mtag = NULL; 35176c8d8eccSSepherosa Ziehau return error; 35186c8d8eccSSepherosa Ziehau } 35196c8d8eccSSepherosa Ziehau 35206c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 35216c8d8eccSSepherosa Ziehau error = bus_dmamap_create(sc->bnx_cdata.bnx_rx_mtag, 35226c8d8eccSSepherosa Ziehau BUS_DMA_WAITOK, 35236c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_std_dmamap[i]); 35246c8d8eccSSepherosa Ziehau if (error) { 35256c8d8eccSSepherosa Ziehau int j; 35266c8d8eccSSepherosa Ziehau 35276c8d8eccSSepherosa Ziehau for (j = 0; j < i; ++j) { 35286c8d8eccSSepherosa Ziehau bus_dmamap_destroy(sc->bnx_cdata.bnx_rx_mtag, 35296c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_std_dmamap[j]); 35306c8d8eccSSepherosa Ziehau } 35316c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(sc->bnx_cdata.bnx_rx_mtag); 35326c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_mtag = NULL; 35336c8d8eccSSepherosa Ziehau 35346c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create DMA map for RX\n"); 35356c8d8eccSSepherosa Ziehau return error; 35366c8d8eccSSepherosa Ziehau } 35376c8d8eccSSepherosa Ziehau } 35386c8d8eccSSepherosa Ziehau 35396c8d8eccSSepherosa Ziehau /* 35406c8d8eccSSepherosa Ziehau * Create DMA tag and maps for TX mbufs. 35416c8d8eccSSepherosa Ziehau */ 35426c8d8eccSSepherosa Ziehau error = bus_dma_tag_create(sc->bnx_cdata.bnx_parent_tag, 1, 0, 35436c8d8eccSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 35446c8d8eccSSepherosa Ziehau NULL, NULL, 35456c8d8eccSSepherosa Ziehau BNX_JUMBO_FRAMELEN, BNX_NSEG_NEW, MCLBYTES, 35466c8d8eccSSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK | 35476c8d8eccSSepherosa Ziehau BUS_DMA_ONEBPAGE, 35486c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_tx_mtag); 35496c8d8eccSSepherosa Ziehau if (error) { 35506c8d8eccSSepherosa Ziehau if_printf(ifp, "could not allocate TX mbuf dma tag\n"); 35516c8d8eccSSepherosa Ziehau return error; 35526c8d8eccSSepherosa Ziehau } 35536c8d8eccSSepherosa Ziehau 35546c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 35556c8d8eccSSepherosa Ziehau error = bus_dmamap_create(sc->bnx_cdata.bnx_tx_mtag, 35566c8d8eccSSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 35576c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_tx_dmamap[i]); 35586c8d8eccSSepherosa Ziehau if (error) { 35596c8d8eccSSepherosa Ziehau int j; 35606c8d8eccSSepherosa Ziehau 35616c8d8eccSSepherosa Ziehau for (j = 0; j < i; ++j) { 35626c8d8eccSSepherosa Ziehau bus_dmamap_destroy(sc->bnx_cdata.bnx_tx_mtag, 35636c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_dmamap[j]); 35646c8d8eccSSepherosa Ziehau } 35656c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(sc->bnx_cdata.bnx_tx_mtag); 35666c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_tx_mtag = NULL; 35676c8d8eccSSepherosa Ziehau 35686c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create DMA map for TX\n"); 35696c8d8eccSSepherosa Ziehau return error; 35706c8d8eccSSepherosa Ziehau } 35716c8d8eccSSepherosa Ziehau } 35726c8d8eccSSepherosa Ziehau 35736c8d8eccSSepherosa Ziehau /* 35746c8d8eccSSepherosa Ziehau * Create DMA stuffs for standard RX ring. 35756c8d8eccSSepherosa Ziehau */ 35766c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_STD_RX_RING_SZ, 35776c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_std_ring_tag, 35786c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_std_ring_map, 35796c8d8eccSSepherosa Ziehau (void *)&sc->bnx_ldata.bnx_rx_std_ring, 35806c8d8eccSSepherosa Ziehau &sc->bnx_ldata.bnx_rx_std_ring_paddr); 35816c8d8eccSSepherosa Ziehau if (error) { 35826c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create std RX ring\n"); 35836c8d8eccSSepherosa Ziehau return error; 35846c8d8eccSSepherosa Ziehau } 35856c8d8eccSSepherosa Ziehau 35866c8d8eccSSepherosa Ziehau /* 35876c8d8eccSSepherosa Ziehau * Create jumbo buffer pool. 35886c8d8eccSSepherosa Ziehau */ 35896c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 35906c8d8eccSSepherosa Ziehau error = bnx_alloc_jumbo_mem(sc); 35916c8d8eccSSepherosa Ziehau if (error) { 35926c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create jumbo buffer pool\n"); 35936c8d8eccSSepherosa Ziehau return error; 35946c8d8eccSSepherosa Ziehau } 35956c8d8eccSSepherosa Ziehau } 35966c8d8eccSSepherosa Ziehau 35976c8d8eccSSepherosa Ziehau /* 35986c8d8eccSSepherosa Ziehau * Create DMA stuffs for RX return ring. 35996c8d8eccSSepherosa Ziehau */ 36006c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, 36016c8d8eccSSepherosa Ziehau BGE_RX_RTN_RING_SZ(sc->bnx_return_ring_cnt), 36026c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_return_ring_tag, 36036c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_return_ring_map, 36046c8d8eccSSepherosa Ziehau (void *)&sc->bnx_ldata.bnx_rx_return_ring, 36056c8d8eccSSepherosa Ziehau &sc->bnx_ldata.bnx_rx_return_ring_paddr); 36066c8d8eccSSepherosa Ziehau if (error) { 36076c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create RX ret ring\n"); 36086c8d8eccSSepherosa Ziehau return error; 36096c8d8eccSSepherosa Ziehau } 36106c8d8eccSSepherosa Ziehau 36116c8d8eccSSepherosa Ziehau /* 36126c8d8eccSSepherosa Ziehau * Create DMA stuffs for TX ring. 36136c8d8eccSSepherosa Ziehau */ 36146c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_TX_RING_SZ, 36156c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_tx_ring_tag, 36166c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_tx_ring_map, 36176c8d8eccSSepherosa Ziehau (void *)&sc->bnx_ldata.bnx_tx_ring, 36186c8d8eccSSepherosa Ziehau &sc->bnx_ldata.bnx_tx_ring_paddr); 36196c8d8eccSSepherosa Ziehau if (error) { 36206c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create TX ring\n"); 36216c8d8eccSSepherosa Ziehau return error; 36226c8d8eccSSepherosa Ziehau } 36236c8d8eccSSepherosa Ziehau 36246c8d8eccSSepherosa Ziehau /* 36256c8d8eccSSepherosa Ziehau * Create DMA stuffs for status block. 36266c8d8eccSSepherosa Ziehau */ 36276c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_STATUS_BLK_SZ, 36286c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_status_tag, 36296c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_status_map, 36306c8d8eccSSepherosa Ziehau (void *)&sc->bnx_ldata.bnx_status_block, 36316c8d8eccSSepherosa Ziehau &sc->bnx_ldata.bnx_status_block_paddr); 36326c8d8eccSSepherosa Ziehau if (error) { 36336c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create status block\n"); 36346c8d8eccSSepherosa Ziehau return error; 36356c8d8eccSSepherosa Ziehau } 36366c8d8eccSSepherosa Ziehau 36376c8d8eccSSepherosa Ziehau return 0; 36386c8d8eccSSepherosa Ziehau } 36396c8d8eccSSepherosa Ziehau 36406c8d8eccSSepherosa Ziehau static int 36416c8d8eccSSepherosa Ziehau bnx_dma_block_alloc(struct bnx_softc *sc, bus_size_t size, bus_dma_tag_t *tag, 36426c8d8eccSSepherosa Ziehau bus_dmamap_t *map, void **addr, bus_addr_t *paddr) 36436c8d8eccSSepherosa Ziehau { 36446c8d8eccSSepherosa Ziehau bus_dmamem_t dmem; 36456c8d8eccSSepherosa Ziehau int error; 36466c8d8eccSSepherosa Ziehau 36476c8d8eccSSepherosa Ziehau error = bus_dmamem_coherent(sc->bnx_cdata.bnx_parent_tag, PAGE_SIZE, 0, 36486c8d8eccSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 36496c8d8eccSSepherosa Ziehau size, BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmem); 36506c8d8eccSSepherosa Ziehau if (error) 36516c8d8eccSSepherosa Ziehau return error; 36526c8d8eccSSepherosa Ziehau 36536c8d8eccSSepherosa Ziehau *tag = dmem.dmem_tag; 36546c8d8eccSSepherosa Ziehau *map = dmem.dmem_map; 36556c8d8eccSSepherosa Ziehau *addr = dmem.dmem_addr; 36566c8d8eccSSepherosa Ziehau *paddr = dmem.dmem_busaddr; 36576c8d8eccSSepherosa Ziehau 36586c8d8eccSSepherosa Ziehau return 0; 36596c8d8eccSSepherosa Ziehau } 36606c8d8eccSSepherosa Ziehau 36616c8d8eccSSepherosa Ziehau static void 36626c8d8eccSSepherosa Ziehau bnx_dma_block_free(bus_dma_tag_t tag, bus_dmamap_t map, void *addr) 36636c8d8eccSSepherosa Ziehau { 36646c8d8eccSSepherosa Ziehau if (tag != NULL) { 36656c8d8eccSSepherosa Ziehau bus_dmamap_unload(tag, map); 36666c8d8eccSSepherosa Ziehau bus_dmamem_free(tag, addr, map); 36676c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(tag); 36686c8d8eccSSepherosa Ziehau } 36696c8d8eccSSepherosa Ziehau } 36706c8d8eccSSepherosa Ziehau 36716c8d8eccSSepherosa Ziehau static void 36726c8d8eccSSepherosa Ziehau bnx_tbi_link_upd(struct bnx_softc *sc, uint32_t status) 36736c8d8eccSSepherosa Ziehau { 36746c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 36756c8d8eccSSepherosa Ziehau 36766c8d8eccSSepherosa Ziehau #define PCS_ENCODE_ERR (BGE_MACSTAT_PORT_DECODE_ERROR|BGE_MACSTAT_MI_COMPLETE) 36776c8d8eccSSepherosa Ziehau 36786c8d8eccSSepherosa Ziehau /* 36796c8d8eccSSepherosa Ziehau * Sometimes PCS encoding errors are detected in 36806c8d8eccSSepherosa Ziehau * TBI mode (on fiber NICs), and for some reason 36816c8d8eccSSepherosa Ziehau * the chip will signal them as link changes. 36826c8d8eccSSepherosa Ziehau * If we get a link change event, but the 'PCS 36836c8d8eccSSepherosa Ziehau * encoding error' bit in the MAC status register 36846c8d8eccSSepherosa Ziehau * is set, don't bother doing a link check. 36856c8d8eccSSepherosa Ziehau * This avoids spurious "gigabit link up" messages 36866c8d8eccSSepherosa Ziehau * that sometimes appear on fiber NICs during 36876c8d8eccSSepherosa Ziehau * periods of heavy traffic. 36886c8d8eccSSepherosa Ziehau */ 36896c8d8eccSSepherosa Ziehau if (status & BGE_MACSTAT_TBI_PCS_SYNCHED) { 36906c8d8eccSSepherosa Ziehau if (!sc->bnx_link) { 36916c8d8eccSSepherosa Ziehau sc->bnx_link++; 36926c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5704) { 36936c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, 36946c8d8eccSSepherosa Ziehau BGE_MACMODE_TBI_SEND_CFGS); 36956c8d8eccSSepherosa Ziehau } 36966c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, 0xFFFFFFFF); 36976c8d8eccSSepherosa Ziehau 36986c8d8eccSSepherosa Ziehau if (bootverbose) 36996c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 37006c8d8eccSSepherosa Ziehau 37016c8d8eccSSepherosa Ziehau ifp->if_link_state = LINK_STATE_UP; 37026c8d8eccSSepherosa Ziehau if_link_state_change(ifp); 37036c8d8eccSSepherosa Ziehau } 37046c8d8eccSSepherosa Ziehau } else if ((status & PCS_ENCODE_ERR) != PCS_ENCODE_ERR) { 37056c8d8eccSSepherosa Ziehau if (sc->bnx_link) { 37066c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 37076c8d8eccSSepherosa Ziehau 37086c8d8eccSSepherosa Ziehau if (bootverbose) 37096c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 37106c8d8eccSSepherosa Ziehau 37116c8d8eccSSepherosa Ziehau ifp->if_link_state = LINK_STATE_DOWN; 37126c8d8eccSSepherosa Ziehau if_link_state_change(ifp); 37136c8d8eccSSepherosa Ziehau } 37146c8d8eccSSepherosa Ziehau } 37156c8d8eccSSepherosa Ziehau 37166c8d8eccSSepherosa Ziehau #undef PCS_ENCODE_ERR 37176c8d8eccSSepherosa Ziehau 37186c8d8eccSSepherosa Ziehau /* Clear the attention. */ 37196c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 37206c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 37216c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 37226c8d8eccSSepherosa Ziehau } 37236c8d8eccSSepherosa Ziehau 37246c8d8eccSSepherosa Ziehau static void 37256c8d8eccSSepherosa Ziehau bnx_copper_link_upd(struct bnx_softc *sc, uint32_t status __unused) 37266c8d8eccSSepherosa Ziehau { 37276c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 37286c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 37296c8d8eccSSepherosa Ziehau 37306c8d8eccSSepherosa Ziehau mii_pollstat(mii); 37316c8d8eccSSepherosa Ziehau bnx_miibus_statchg(sc->bnx_dev); 37326c8d8eccSSepherosa Ziehau 37336c8d8eccSSepherosa Ziehau if (bootverbose) { 37346c8d8eccSSepherosa Ziehau if (sc->bnx_link) 37356c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 37366c8d8eccSSepherosa Ziehau else 37376c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 37386c8d8eccSSepherosa Ziehau } 37396c8d8eccSSepherosa Ziehau 37406c8d8eccSSepherosa Ziehau /* Clear the attention. */ 37416c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 37426c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 37436c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 37446c8d8eccSSepherosa Ziehau } 37456c8d8eccSSepherosa Ziehau 37466c8d8eccSSepherosa Ziehau static void 37476c8d8eccSSepherosa Ziehau bnx_autopoll_link_upd(struct bnx_softc *sc, uint32_t status __unused) 37486c8d8eccSSepherosa Ziehau { 37496c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 37506c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 37516c8d8eccSSepherosa Ziehau 37526c8d8eccSSepherosa Ziehau mii_pollstat(mii); 37536c8d8eccSSepherosa Ziehau 37546c8d8eccSSepherosa Ziehau if (!sc->bnx_link && 37556c8d8eccSSepherosa Ziehau (mii->mii_media_status & IFM_ACTIVE) && 37566c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 37576c8d8eccSSepherosa Ziehau sc->bnx_link++; 37586c8d8eccSSepherosa Ziehau if (bootverbose) 37596c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 37606c8d8eccSSepherosa Ziehau } else if (sc->bnx_link && 37616c8d8eccSSepherosa Ziehau (!(mii->mii_media_status & IFM_ACTIVE) || 37626c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_NONE)) { 37636c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 37646c8d8eccSSepherosa Ziehau if (bootverbose) 37656c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 37666c8d8eccSSepherosa Ziehau } 37676c8d8eccSSepherosa Ziehau 37686c8d8eccSSepherosa Ziehau /* Clear the attention. */ 37696c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 37706c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 37716c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 37726c8d8eccSSepherosa Ziehau } 37736c8d8eccSSepherosa Ziehau 37746c8d8eccSSepherosa Ziehau static int 37756c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_ticks(SYSCTL_HANDLER_ARGS) 37766c8d8eccSSepherosa Ziehau { 37776c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 37786c8d8eccSSepherosa Ziehau 37796c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 37806c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_ticks, 37816c8d8eccSSepherosa Ziehau BNX_RX_COAL_TICKS_MIN, BNX_RX_COAL_TICKS_MAX, 37826c8d8eccSSepherosa Ziehau BNX_RX_COAL_TICKS_CHG); 37836c8d8eccSSepherosa Ziehau } 37846c8d8eccSSepherosa Ziehau 37856c8d8eccSSepherosa Ziehau static int 37866c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_ticks(SYSCTL_HANDLER_ARGS) 37876c8d8eccSSepherosa Ziehau { 37886c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 37896c8d8eccSSepherosa Ziehau 37906c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 37916c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_ticks, 37926c8d8eccSSepherosa Ziehau BNX_TX_COAL_TICKS_MIN, BNX_TX_COAL_TICKS_MAX, 37936c8d8eccSSepherosa Ziehau BNX_TX_COAL_TICKS_CHG); 37946c8d8eccSSepherosa Ziehau } 37956c8d8eccSSepherosa Ziehau 37966c8d8eccSSepherosa Ziehau static int 37976c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_bds(SYSCTL_HANDLER_ARGS) 37986c8d8eccSSepherosa Ziehau { 37996c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 38006c8d8eccSSepherosa Ziehau 38016c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 38026c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_bds, 38036c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_MIN, BNX_RX_COAL_BDS_MAX, 38046c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_CHG); 38056c8d8eccSSepherosa Ziehau } 38066c8d8eccSSepherosa Ziehau 38076c8d8eccSSepherosa Ziehau static int 38086c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_bds(SYSCTL_HANDLER_ARGS) 38096c8d8eccSSepherosa Ziehau { 38106c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 38116c8d8eccSSepherosa Ziehau 38126c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 38136c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_bds, 38146c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_MIN, BNX_TX_COAL_BDS_MAX, 38156c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_CHG); 38166c8d8eccSSepherosa Ziehau } 38176c8d8eccSSepherosa Ziehau 38186c8d8eccSSepherosa Ziehau static int 38196c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_bds_int(SYSCTL_HANDLER_ARGS) 38206c8d8eccSSepherosa Ziehau { 38216c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 38226c8d8eccSSepherosa Ziehau 38236c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 38246c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_bds_int, 38256c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_MIN, BNX_RX_COAL_BDS_MAX, 38266c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_INT_CHG); 38276c8d8eccSSepherosa Ziehau } 38286c8d8eccSSepherosa Ziehau 38296c8d8eccSSepherosa Ziehau static int 38306c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_bds_int(SYSCTL_HANDLER_ARGS) 38316c8d8eccSSepherosa Ziehau { 38326c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 38336c8d8eccSSepherosa Ziehau 38346c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 38356c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_bds_int, 38366c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_MIN, BNX_TX_COAL_BDS_MAX, 38376c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_INT_CHG); 38386c8d8eccSSepherosa Ziehau } 38396c8d8eccSSepherosa Ziehau 38406c8d8eccSSepherosa Ziehau static int 38416c8d8eccSSepherosa Ziehau bnx_sysctl_coal_chg(SYSCTL_HANDLER_ARGS, uint32_t *coal, 38426c8d8eccSSepherosa Ziehau int coal_min, int coal_max, uint32_t coal_chg_mask) 38436c8d8eccSSepherosa Ziehau { 38446c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 38456c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 38466c8d8eccSSepherosa Ziehau int error = 0, v; 38476c8d8eccSSepherosa Ziehau 38486c8d8eccSSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 38496c8d8eccSSepherosa Ziehau 38506c8d8eccSSepherosa Ziehau v = *coal; 38516c8d8eccSSepherosa Ziehau error = sysctl_handle_int(oidp, &v, 0, req); 38526c8d8eccSSepherosa Ziehau if (!error && req->newptr != NULL) { 38536c8d8eccSSepherosa Ziehau if (v < coal_min || v > coal_max) { 38546c8d8eccSSepherosa Ziehau error = EINVAL; 38556c8d8eccSSepherosa Ziehau } else { 38566c8d8eccSSepherosa Ziehau *coal = v; 38576c8d8eccSSepherosa Ziehau sc->bnx_coal_chg |= coal_chg_mask; 38586c8d8eccSSepherosa Ziehau } 38596c8d8eccSSepherosa Ziehau } 38606c8d8eccSSepherosa Ziehau 38616c8d8eccSSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 38626c8d8eccSSepherosa Ziehau return error; 38636c8d8eccSSepherosa Ziehau } 38646c8d8eccSSepherosa Ziehau 38656c8d8eccSSepherosa Ziehau static void 38666c8d8eccSSepherosa Ziehau bnx_coal_change(struct bnx_softc *sc) 38676c8d8eccSSepherosa Ziehau { 38686c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 38696c8d8eccSSepherosa Ziehau uint32_t val; 38706c8d8eccSSepherosa Ziehau 38716c8d8eccSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 38726c8d8eccSSepherosa Ziehau 38736c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_TICKS_CHG) { 38746c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS, 38756c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks); 38766c8d8eccSSepherosa Ziehau DELAY(10); 38776c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_HCC_RX_COAL_TICKS); 38786c8d8eccSSepherosa Ziehau 38796c8d8eccSSepherosa Ziehau if (bootverbose) { 38806c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_ticks -> %u\n", 38816c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks); 38826c8d8eccSSepherosa Ziehau } 38836c8d8eccSSepherosa Ziehau } 38846c8d8eccSSepherosa Ziehau 38856c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_TICKS_CHG) { 38866c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, 38876c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks); 38886c8d8eccSSepherosa Ziehau DELAY(10); 38896c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_HCC_TX_COAL_TICKS); 38906c8d8eccSSepherosa Ziehau 38916c8d8eccSSepherosa Ziehau if (bootverbose) { 38926c8d8eccSSepherosa Ziehau if_printf(ifp, "tx_coal_ticks -> %u\n", 38936c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks); 38946c8d8eccSSepherosa Ziehau } 38956c8d8eccSSepherosa Ziehau } 38966c8d8eccSSepherosa Ziehau 38976c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_BDS_CHG) { 38986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, 38996c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds); 39006c8d8eccSSepherosa Ziehau DELAY(10); 39016c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_HCC_RX_MAX_COAL_BDS); 39026c8d8eccSSepherosa Ziehau 39036c8d8eccSSepherosa Ziehau if (bootverbose) { 39046c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_bds -> %u\n", 39056c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds); 39066c8d8eccSSepherosa Ziehau } 39076c8d8eccSSepherosa Ziehau } 39086c8d8eccSSepherosa Ziehau 39096c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_BDS_CHG) { 39106c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, 39116c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds); 39126c8d8eccSSepherosa Ziehau DELAY(10); 39136c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_HCC_TX_MAX_COAL_BDS); 39146c8d8eccSSepherosa Ziehau 39156c8d8eccSSepherosa Ziehau if (bootverbose) { 39166c8d8eccSSepherosa Ziehau if_printf(ifp, "tx_max_coal_bds -> %u\n", 39176c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds); 39186c8d8eccSSepherosa Ziehau } 39196c8d8eccSSepherosa Ziehau } 39206c8d8eccSSepherosa Ziehau 39216c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_BDS_INT_CHG) { 39226c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 39236c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds_int); 39246c8d8eccSSepherosa Ziehau DELAY(10); 39256c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT); 39266c8d8eccSSepherosa Ziehau 39276c8d8eccSSepherosa Ziehau if (bootverbose) { 39286c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_bds_int -> %u\n", 39296c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds_int); 39306c8d8eccSSepherosa Ziehau } 39316c8d8eccSSepherosa Ziehau } 39326c8d8eccSSepherosa Ziehau 39336c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_BDS_INT_CHG) { 39346c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 39356c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds_int); 39366c8d8eccSSepherosa Ziehau DELAY(10); 39376c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT); 39386c8d8eccSSepherosa Ziehau 39396c8d8eccSSepherosa Ziehau if (bootverbose) { 39406c8d8eccSSepherosa Ziehau if_printf(ifp, "tx_coal_bds_int -> %u\n", 39416c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds_int); 39426c8d8eccSSepherosa Ziehau } 39436c8d8eccSSepherosa Ziehau } 39446c8d8eccSSepherosa Ziehau 39456c8d8eccSSepherosa Ziehau sc->bnx_coal_chg = 0; 39466c8d8eccSSepherosa Ziehau } 39476c8d8eccSSepherosa Ziehau 39486c8d8eccSSepherosa Ziehau static void 3949*df9ccc98SSepherosa Ziehau bnx_intr_check(void *xsc) 3950*df9ccc98SSepherosa Ziehau { 3951*df9ccc98SSepherosa Ziehau struct bnx_softc *sc = xsc; 3952*df9ccc98SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 3953*df9ccc98SSepherosa Ziehau struct bge_status_block *sblk = sc->bnx_ldata.bnx_status_block; 3954*df9ccc98SSepherosa Ziehau 3955*df9ccc98SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 3956*df9ccc98SSepherosa Ziehau 3957*df9ccc98SSepherosa Ziehau KKASSERT(mycpuid == sc->bnx_intr_cpuid); 3958*df9ccc98SSepherosa Ziehau 3959*df9ccc98SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_POLLING)) != IFF_RUNNING) { 3960*df9ccc98SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 3961*df9ccc98SSepherosa Ziehau return; 3962*df9ccc98SSepherosa Ziehau } 3963*df9ccc98SSepherosa Ziehau 3964*df9ccc98SSepherosa Ziehau if (sblk->bge_idx[0].bge_rx_prod_idx != sc->bnx_rx_saved_considx || 3965*df9ccc98SSepherosa Ziehau sblk->bge_idx[0].bge_tx_cons_idx != sc->bnx_tx_saved_considx) { 3966*df9ccc98SSepherosa Ziehau if (sc->bnx_rx_check_considx == sc->bnx_rx_saved_considx && 3967*df9ccc98SSepherosa Ziehau sc->bnx_tx_check_considx == sc->bnx_tx_saved_considx) { 3968*df9ccc98SSepherosa Ziehau if (!sc->bnx_intr_maylose) { 3969*df9ccc98SSepherosa Ziehau sc->bnx_intr_maylose = TRUE; 3970*df9ccc98SSepherosa Ziehau goto done; 3971*df9ccc98SSepherosa Ziehau } 3972*df9ccc98SSepherosa Ziehau if (bootverbose) 3973*df9ccc98SSepherosa Ziehau if_printf(ifp, "lost interrupt\n"); 3974*df9ccc98SSepherosa Ziehau bnx_msi(sc); 3975*df9ccc98SSepherosa Ziehau } 3976*df9ccc98SSepherosa Ziehau } 3977*df9ccc98SSepherosa Ziehau sc->bnx_intr_maylose = FALSE; 3978*df9ccc98SSepherosa Ziehau sc->bnx_rx_check_considx = sc->bnx_rx_saved_considx; 3979*df9ccc98SSepherosa Ziehau sc->bnx_tx_check_considx = sc->bnx_tx_saved_considx; 3980*df9ccc98SSepherosa Ziehau 3981*df9ccc98SSepherosa Ziehau done: 3982*df9ccc98SSepherosa Ziehau callout_reset(&sc->bnx_intr_timer, BNX_INTR_CKINTVL, 3983*df9ccc98SSepherosa Ziehau bnx_intr_check, sc); 3984*df9ccc98SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 3985*df9ccc98SSepherosa Ziehau } 3986*df9ccc98SSepherosa Ziehau 3987*df9ccc98SSepherosa Ziehau static void 39886c8d8eccSSepherosa Ziehau bnx_enable_intr(struct bnx_softc *sc) 39896c8d8eccSSepherosa Ziehau { 39906c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 39916c8d8eccSSepherosa Ziehau 39926c8d8eccSSepherosa Ziehau lwkt_serialize_handler_enable(ifp->if_serializer); 39936c8d8eccSSepherosa Ziehau 39946c8d8eccSSepherosa Ziehau /* 39956c8d8eccSSepherosa Ziehau * Enable interrupt. 39966c8d8eccSSepherosa Ziehau */ 39976c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, sc->bnx_status_tag << 24); 39986c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_ONESHOT_MSI) { 39996c8d8eccSSepherosa Ziehau /* XXX Linux driver */ 40006c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, sc->bnx_status_tag << 24); 40016c8d8eccSSepherosa Ziehau } 40026c8d8eccSSepherosa Ziehau 40036c8d8eccSSepherosa Ziehau /* 40046c8d8eccSSepherosa Ziehau * Unmask the interrupt when we stop polling. 40056c8d8eccSSepherosa Ziehau */ 40066c8d8eccSSepherosa Ziehau PCI_CLRBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, 40076c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_MASK_PCI_INTR, 4); 40086c8d8eccSSepherosa Ziehau 40096c8d8eccSSepherosa Ziehau /* 40106c8d8eccSSepherosa Ziehau * Trigger another interrupt, since above writing 40116c8d8eccSSepherosa Ziehau * to interrupt mailbox0 may acknowledge pending 40126c8d8eccSSepherosa Ziehau * interrupt. 40136c8d8eccSSepherosa Ziehau */ 40146c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_SET); 4015*df9ccc98SSepherosa Ziehau 4016*df9ccc98SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STATUSTAG_BUG) { 4017*df9ccc98SSepherosa Ziehau sc->bnx_intr_maylose = FALSE; 4018*df9ccc98SSepherosa Ziehau sc->bnx_rx_check_considx = 0; 4019*df9ccc98SSepherosa Ziehau sc->bnx_tx_check_considx = 0; 4020*df9ccc98SSepherosa Ziehau 4021*df9ccc98SSepherosa Ziehau if (bootverbose) 4022*df9ccc98SSepherosa Ziehau if_printf(ifp, "status tag bug workaround\n"); 4023*df9ccc98SSepherosa Ziehau 4024*df9ccc98SSepherosa Ziehau /* 10ms check interval */ 4025*df9ccc98SSepherosa Ziehau callout_reset_bycpu(&sc->bnx_intr_timer, BNX_INTR_CKINTVL, 4026*df9ccc98SSepherosa Ziehau bnx_intr_check, sc, sc->bnx_intr_cpuid); 4027*df9ccc98SSepherosa Ziehau } 40286c8d8eccSSepherosa Ziehau } 40296c8d8eccSSepherosa Ziehau 40306c8d8eccSSepherosa Ziehau static void 40316c8d8eccSSepherosa Ziehau bnx_disable_intr(struct bnx_softc *sc) 40326c8d8eccSSepherosa Ziehau { 40336c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 40346c8d8eccSSepherosa Ziehau 40356c8d8eccSSepherosa Ziehau /* 40366c8d8eccSSepherosa Ziehau * Mask the interrupt when we start polling. 40376c8d8eccSSepherosa Ziehau */ 40386c8d8eccSSepherosa Ziehau PCI_SETBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, 40396c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_MASK_PCI_INTR, 4); 40406c8d8eccSSepherosa Ziehau 40416c8d8eccSSepherosa Ziehau /* 40426c8d8eccSSepherosa Ziehau * Acknowledge possible asserted interrupt. 40436c8d8eccSSepherosa Ziehau */ 40446c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, 1); 40456c8d8eccSSepherosa Ziehau 4046*df9ccc98SSepherosa Ziehau callout_stop(&sc->bnx_intr_timer); 4047*df9ccc98SSepherosa Ziehau sc->bnx_intr_maylose = FALSE; 4048*df9ccc98SSepherosa Ziehau sc->bnx_rx_check_considx = 0; 4049*df9ccc98SSepherosa Ziehau sc->bnx_tx_check_considx = 0; 4050*df9ccc98SSepherosa Ziehau 40516c8d8eccSSepherosa Ziehau lwkt_serialize_handler_disable(ifp->if_serializer); 40526c8d8eccSSepherosa Ziehau } 40536c8d8eccSSepherosa Ziehau 40546c8d8eccSSepherosa Ziehau static int 40556c8d8eccSSepherosa Ziehau bnx_get_eaddr_mem(struct bnx_softc *sc, uint8_t ether_addr[]) 40566c8d8eccSSepherosa Ziehau { 40576c8d8eccSSepherosa Ziehau uint32_t mac_addr; 40586c8d8eccSSepherosa Ziehau int ret = 1; 40596c8d8eccSSepherosa Ziehau 40606c8d8eccSSepherosa Ziehau mac_addr = bnx_readmem_ind(sc, 0x0c14); 40616c8d8eccSSepherosa Ziehau if ((mac_addr >> 16) == 0x484b) { 40626c8d8eccSSepherosa Ziehau ether_addr[0] = (uint8_t)(mac_addr >> 8); 40636c8d8eccSSepherosa Ziehau ether_addr[1] = (uint8_t)mac_addr; 40646c8d8eccSSepherosa Ziehau mac_addr = bnx_readmem_ind(sc, 0x0c18); 40656c8d8eccSSepherosa Ziehau ether_addr[2] = (uint8_t)(mac_addr >> 24); 40666c8d8eccSSepherosa Ziehau ether_addr[3] = (uint8_t)(mac_addr >> 16); 40676c8d8eccSSepherosa Ziehau ether_addr[4] = (uint8_t)(mac_addr >> 8); 40686c8d8eccSSepherosa Ziehau ether_addr[5] = (uint8_t)mac_addr; 40696c8d8eccSSepherosa Ziehau ret = 0; 40706c8d8eccSSepherosa Ziehau } 40716c8d8eccSSepherosa Ziehau return ret; 40726c8d8eccSSepherosa Ziehau } 40736c8d8eccSSepherosa Ziehau 40746c8d8eccSSepherosa Ziehau static int 40756c8d8eccSSepherosa Ziehau bnx_get_eaddr_nvram(struct bnx_softc *sc, uint8_t ether_addr[]) 40766c8d8eccSSepherosa Ziehau { 40776c8d8eccSSepherosa Ziehau int mac_offset = BGE_EE_MAC_OFFSET; 40786c8d8eccSSepherosa Ziehau 407980969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 408080969639SSepherosa Ziehau int f; 408180969639SSepherosa Ziehau 408280969639SSepherosa Ziehau f = pci_get_function(sc->bnx_dev); 408380969639SSepherosa Ziehau if (f & 1) 408480969639SSepherosa Ziehau mac_offset = BGE_EE_MAC_OFFSET_5717; 408580969639SSepherosa Ziehau if (f > 1) 408680969639SSepherosa Ziehau mac_offset += BGE_EE_MAC_OFFSET_5717_OFF; 408780969639SSepherosa Ziehau } else if (sc->bnx_asicrev == BGE_ASICREV_BCM5906) { 40886c8d8eccSSepherosa Ziehau mac_offset = BGE_EE_MAC_OFFSET_5906; 408980969639SSepherosa Ziehau } 40906c8d8eccSSepherosa Ziehau 40916c8d8eccSSepherosa Ziehau return bnx_read_nvram(sc, ether_addr, mac_offset + 2, ETHER_ADDR_LEN); 40926c8d8eccSSepherosa Ziehau } 40936c8d8eccSSepherosa Ziehau 40946c8d8eccSSepherosa Ziehau static int 40956c8d8eccSSepherosa Ziehau bnx_get_eaddr_eeprom(struct bnx_softc *sc, uint8_t ether_addr[]) 40966c8d8eccSSepherosa Ziehau { 40976c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_NO_EEPROM) 40986c8d8eccSSepherosa Ziehau return 1; 40996c8d8eccSSepherosa Ziehau 41006c8d8eccSSepherosa Ziehau return bnx_read_eeprom(sc, ether_addr, BGE_EE_MAC_OFFSET + 2, 41016c8d8eccSSepherosa Ziehau ETHER_ADDR_LEN); 41026c8d8eccSSepherosa Ziehau } 41036c8d8eccSSepherosa Ziehau 41046c8d8eccSSepherosa Ziehau static int 41056c8d8eccSSepherosa Ziehau bnx_get_eaddr(struct bnx_softc *sc, uint8_t eaddr[]) 41066c8d8eccSSepherosa Ziehau { 41076c8d8eccSSepherosa Ziehau static const bnx_eaddr_fcn_t bnx_eaddr_funcs[] = { 41086c8d8eccSSepherosa Ziehau /* NOTE: Order is critical */ 41096c8d8eccSSepherosa Ziehau bnx_get_eaddr_mem, 41106c8d8eccSSepherosa Ziehau bnx_get_eaddr_nvram, 41116c8d8eccSSepherosa Ziehau bnx_get_eaddr_eeprom, 41126c8d8eccSSepherosa Ziehau NULL 41136c8d8eccSSepherosa Ziehau }; 41146c8d8eccSSepherosa Ziehau const bnx_eaddr_fcn_t *func; 41156c8d8eccSSepherosa Ziehau 41166c8d8eccSSepherosa Ziehau for (func = bnx_eaddr_funcs; *func != NULL; ++func) { 41176c8d8eccSSepherosa Ziehau if ((*func)(sc, eaddr) == 0) 41186c8d8eccSSepherosa Ziehau break; 41196c8d8eccSSepherosa Ziehau } 41206c8d8eccSSepherosa Ziehau return (*func == NULL ? ENXIO : 0); 41216c8d8eccSSepherosa Ziehau } 41226c8d8eccSSepherosa Ziehau 41236c8d8eccSSepherosa Ziehau /* 41246c8d8eccSSepherosa Ziehau * NOTE: 'm' is not freed upon failure 41256c8d8eccSSepherosa Ziehau */ 41266c8d8eccSSepherosa Ziehau struct mbuf * 41276c8d8eccSSepherosa Ziehau bnx_defrag_shortdma(struct mbuf *m) 41286c8d8eccSSepherosa Ziehau { 41296c8d8eccSSepherosa Ziehau struct mbuf *n; 41306c8d8eccSSepherosa Ziehau int found; 41316c8d8eccSSepherosa Ziehau 41326c8d8eccSSepherosa Ziehau /* 41336c8d8eccSSepherosa Ziehau * If device receive two back-to-back send BDs with less than 41346c8d8eccSSepherosa Ziehau * or equal to 8 total bytes then the device may hang. The two 41356c8d8eccSSepherosa Ziehau * back-to-back send BDs must in the same frame for this failure 41366c8d8eccSSepherosa Ziehau * to occur. Scan mbuf chains and see whether two back-to-back 41376c8d8eccSSepherosa Ziehau * send BDs are there. If this is the case, allocate new mbuf 41386c8d8eccSSepherosa Ziehau * and copy the frame to workaround the silicon bug. 41396c8d8eccSSepherosa Ziehau */ 41406c8d8eccSSepherosa Ziehau for (n = m, found = 0; n != NULL; n = n->m_next) { 41416c8d8eccSSepherosa Ziehau if (n->m_len < 8) { 41426c8d8eccSSepherosa Ziehau found++; 41436c8d8eccSSepherosa Ziehau if (found > 1) 41446c8d8eccSSepherosa Ziehau break; 41456c8d8eccSSepherosa Ziehau continue; 41466c8d8eccSSepherosa Ziehau } 41476c8d8eccSSepherosa Ziehau found = 0; 41486c8d8eccSSepherosa Ziehau } 41496c8d8eccSSepherosa Ziehau 41506c8d8eccSSepherosa Ziehau if (found > 1) 41516c8d8eccSSepherosa Ziehau n = m_defrag(m, MB_DONTWAIT); 41526c8d8eccSSepherosa Ziehau else 41536c8d8eccSSepherosa Ziehau n = m; 41546c8d8eccSSepherosa Ziehau return n; 41556c8d8eccSSepherosa Ziehau } 41566c8d8eccSSepherosa Ziehau 41576c8d8eccSSepherosa Ziehau static void 41586c8d8eccSSepherosa Ziehau bnx_stop_block(struct bnx_softc *sc, bus_size_t reg, uint32_t bit) 41596c8d8eccSSepherosa Ziehau { 41606c8d8eccSSepherosa Ziehau int i; 41616c8d8eccSSepherosa Ziehau 41626c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, reg, bit); 41636c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 41646c8d8eccSSepherosa Ziehau if ((CSR_READ_4(sc, reg) & bit) == 0) 41656c8d8eccSSepherosa Ziehau return; 41666c8d8eccSSepherosa Ziehau DELAY(100); 41676c8d8eccSSepherosa Ziehau } 41686c8d8eccSSepherosa Ziehau } 41696c8d8eccSSepherosa Ziehau 41706c8d8eccSSepherosa Ziehau static void 41716c8d8eccSSepherosa Ziehau bnx_link_poll(struct bnx_softc *sc) 41726c8d8eccSSepherosa Ziehau { 41736c8d8eccSSepherosa Ziehau uint32_t status; 41746c8d8eccSSepherosa Ziehau 41756c8d8eccSSepherosa Ziehau status = CSR_READ_4(sc, BGE_MAC_STS); 41766c8d8eccSSepherosa Ziehau if ((status & sc->bnx_link_chg) || sc->bnx_link_evt) { 41776c8d8eccSSepherosa Ziehau sc->bnx_link_evt = 0; 41786c8d8eccSSepherosa Ziehau sc->bnx_link_upd(sc, status); 41796c8d8eccSSepherosa Ziehau } 41806c8d8eccSSepherosa Ziehau } 41816c8d8eccSSepherosa Ziehau 41826c8d8eccSSepherosa Ziehau static void 41836c8d8eccSSepherosa Ziehau bnx_enable_msi(struct bnx_softc *sc) 41846c8d8eccSSepherosa Ziehau { 41856c8d8eccSSepherosa Ziehau uint32_t msi_mode; 41866c8d8eccSSepherosa Ziehau 41876c8d8eccSSepherosa Ziehau msi_mode = CSR_READ_4(sc, BGE_MSI_MODE); 41886c8d8eccSSepherosa Ziehau msi_mode |= BGE_MSIMODE_ENABLE; 41896c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_ONESHOT_MSI) { 41906c8d8eccSSepherosa Ziehau /* 41916c8d8eccSSepherosa Ziehau * NOTE: 41926c8d8eccSSepherosa Ziehau * 5718-PG105-R says that "one shot" mode 41936c8d8eccSSepherosa Ziehau * does not work if MSI is used, however, 41946c8d8eccSSepherosa Ziehau * it obviously works. 41956c8d8eccSSepherosa Ziehau */ 41966c8d8eccSSepherosa Ziehau msi_mode &= ~BGE_MSIMODE_ONESHOT_DISABLE; 41976c8d8eccSSepherosa Ziehau } 41986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MSI_MODE, msi_mode); 41996c8d8eccSSepherosa Ziehau } 42006c8d8eccSSepherosa Ziehau 42016c8d8eccSSepherosa Ziehau static uint32_t 42026c8d8eccSSepherosa Ziehau bnx_dma_swap_options(struct bnx_softc *sc) 42036c8d8eccSSepherosa Ziehau { 42046c8d8eccSSepherosa Ziehau uint32_t dma_options; 42056c8d8eccSSepherosa Ziehau 42066c8d8eccSSepherosa Ziehau dma_options = BGE_MODECTL_WORDSWAP_NONFRAME | 42076c8d8eccSSepherosa Ziehau BGE_MODECTL_BYTESWAP_DATA | BGE_MODECTL_WORDSWAP_DATA; 42086c8d8eccSSepherosa Ziehau #if BYTE_ORDER == BIG_ENDIAN 42096c8d8eccSSepherosa Ziehau dma_options |= BGE_MODECTL_BYTESWAP_NONFRAME; 42106c8d8eccSSepherosa Ziehau #endif 42116c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 42126c8d8eccSSepherosa Ziehau dma_options |= BGE_MODECTL_BYTESWAP_B2HRX_DATA | 42136c8d8eccSSepherosa Ziehau BGE_MODECTL_WORDSWAP_B2HRX_DATA | BGE_MODECTL_B2HRX_ENABLE | 42146c8d8eccSSepherosa Ziehau BGE_MODECTL_HTX2B_ENABLE; 42156c8d8eccSSepherosa Ziehau } 42166c8d8eccSSepherosa Ziehau return dma_options; 42176c8d8eccSSepherosa Ziehau } 4218