143c2aeb0SSepherosa Ziehau /*- 243c2aeb0SSepherosa Ziehau * Copyright (c) 2006-2007 Broadcom Corporation 343c2aeb0SSepherosa Ziehau * David Christensen <davidch@broadcom.com>. All rights reserved. 443c2aeb0SSepherosa Ziehau * 543c2aeb0SSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 643c2aeb0SSepherosa Ziehau * modification, are permitted provided that the following conditions 743c2aeb0SSepherosa Ziehau * are met: 843c2aeb0SSepherosa Ziehau * 943c2aeb0SSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 1043c2aeb0SSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 1143c2aeb0SSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 1243c2aeb0SSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the 1343c2aeb0SSepherosa Ziehau * documentation and/or other materials provided with the distribution. 1443c2aeb0SSepherosa Ziehau * 3. Neither the name of Broadcom Corporation nor the name of its contributors 1543c2aeb0SSepherosa Ziehau * may be used to endorse or promote products derived from this software 1643c2aeb0SSepherosa Ziehau * without specific prior written consent. 1743c2aeb0SSepherosa Ziehau * 1843c2aeb0SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' 1943c2aeb0SSepherosa Ziehau * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2043c2aeb0SSepherosa Ziehau * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2143c2aeb0SSepherosa Ziehau * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 2243c2aeb0SSepherosa Ziehau * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2343c2aeb0SSepherosa Ziehau * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2443c2aeb0SSepherosa Ziehau * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2543c2aeb0SSepherosa Ziehau * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2643c2aeb0SSepherosa Ziehau * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2743c2aeb0SSepherosa Ziehau * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 2843c2aeb0SSepherosa Ziehau * THE POSSIBILITY OF SUCH DAMAGE. 2943c2aeb0SSepherosa Ziehau * 3043c2aeb0SSepherosa Ziehau * $FreeBSD: src/sys/dev/bce/if_bce.c,v 1.31 2007/05/16 23:34:11 davidch Exp $ 3143c2aeb0SSepherosa Ziehau */ 3243c2aeb0SSepherosa Ziehau 3343c2aeb0SSepherosa Ziehau /* 3443c2aeb0SSepherosa Ziehau * The following controllers are supported by this driver: 3543c2aeb0SSepherosa Ziehau * BCM5706C A2, A3 36d0092544SSepherosa Ziehau * BCM5706S A2, A3 3743c2aeb0SSepherosa Ziehau * BCM5708C B1, B2 38d0092544SSepherosa Ziehau * BCM5708S B1, B2 39f358071bSSepherosa Ziehau * BCM5709C A1, B2, C0 40d0092544SSepherosa Ziehau * BCM5716 C0 4143c2aeb0SSepherosa Ziehau * 4243c2aeb0SSepherosa Ziehau * The following controllers are not supported by this driver: 4343c2aeb0SSepherosa Ziehau * BCM5706C A0, A1 44d0092544SSepherosa Ziehau * BCM5706S A0, A1 4543c2aeb0SSepherosa Ziehau * BCM5708C A0, B0 46d0092544SSepherosa Ziehau * BCM5708S A0, B0 47d0092544SSepherosa Ziehau * BCM5709C A0, B0, B1 48d0092544SSepherosa Ziehau * BCM5709S A0, A1, B0, B1, B2, C0 4943c2aeb0SSepherosa Ziehau */ 5043c2aeb0SSepherosa Ziehau 5143c2aeb0SSepherosa Ziehau #include "opt_bce.h" 524a331bf7SSepherosa Ziehau #include "opt_ifpoll.h" 5343c2aeb0SSepherosa Ziehau 5443c2aeb0SSepherosa Ziehau #include <sys/param.h> 5543c2aeb0SSepherosa Ziehau #include <sys/bus.h> 5643c2aeb0SSepherosa Ziehau #include <sys/endian.h> 5743c2aeb0SSepherosa Ziehau #include <sys/kernel.h> 589db4b353SSepherosa Ziehau #include <sys/interrupt.h> 5943c2aeb0SSepherosa Ziehau #include <sys/mbuf.h> 6043c2aeb0SSepherosa Ziehau #include <sys/malloc.h> 6143c2aeb0SSepherosa Ziehau #include <sys/queue.h> 6243c2aeb0SSepherosa Ziehau #include <sys/rman.h> 6343c2aeb0SSepherosa Ziehau #include <sys/serialize.h> 6443c2aeb0SSepherosa Ziehau #include <sys/socket.h> 6543c2aeb0SSepherosa Ziehau #include <sys/sockio.h> 6643c2aeb0SSepherosa Ziehau #include <sys/sysctl.h> 6743c2aeb0SSepherosa Ziehau 68eefd160dSSepherosa Ziehau #include <netinet/ip.h> 69eefd160dSSepherosa Ziehau #include <netinet/tcp.h> 70eefd160dSSepherosa Ziehau 7143c2aeb0SSepherosa Ziehau #include <net/bpf.h> 7243c2aeb0SSepherosa Ziehau #include <net/ethernet.h> 7343c2aeb0SSepherosa Ziehau #include <net/if.h> 7443c2aeb0SSepherosa Ziehau #include <net/if_arp.h> 7543c2aeb0SSepherosa Ziehau #include <net/if_dl.h> 7643c2aeb0SSepherosa Ziehau #include <net/if_media.h> 774a331bf7SSepherosa Ziehau #include <net/if_poll.h> 7843c2aeb0SSepherosa Ziehau #include <net/if_types.h> 7943c2aeb0SSepherosa Ziehau #include <net/ifq_var.h> 8043c2aeb0SSepherosa Ziehau #include <net/vlan/if_vlan_var.h> 81b637f170SSepherosa Ziehau #include <net/vlan/if_vlan_ether.h> 8243c2aeb0SSepherosa Ziehau 8343c2aeb0SSepherosa Ziehau #include <dev/netif/mii_layer/mii.h> 8443c2aeb0SSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h> 85f31c6e4dSSepherosa Ziehau #include <dev/netif/mii_layer/brgphyreg.h> 8643c2aeb0SSepherosa Ziehau 8743c2aeb0SSepherosa Ziehau #include <bus/pci/pcireg.h> 8843c2aeb0SSepherosa Ziehau #include <bus/pci/pcivar.h> 8943c2aeb0SSepherosa Ziehau 9043c2aeb0SSepherosa Ziehau #include "miibus_if.h" 9143c2aeb0SSepherosa Ziehau 929382dc55SSepherosa Ziehau #include <dev/netif/bce/if_bcereg.h> 939382dc55SSepherosa Ziehau #include <dev/netif/bce/if_bcefw.h> 9443c2aeb0SSepherosa Ziehau 9528ef7645SSepherosa Ziehau #define BCE_MSI_CKINTVL ((10 * hz) / 1000) /* 10ms */ 9628ef7645SSepherosa Ziehau 9743c2aeb0SSepherosa Ziehau /****************************************************************************/ 9843c2aeb0SSepherosa Ziehau /* PCI Device ID Table */ 9943c2aeb0SSepherosa Ziehau /* */ 10043c2aeb0SSepherosa Ziehau /* Used by bce_probe() to identify the devices supported by this driver. */ 10143c2aeb0SSepherosa Ziehau /****************************************************************************/ 10243c2aeb0SSepherosa Ziehau #define BCE_DEVDESC_MAX 64 10343c2aeb0SSepherosa Ziehau 10443c2aeb0SSepherosa Ziehau static struct bce_type bce_devs[] = { 10543c2aeb0SSepherosa Ziehau /* BCM5706C Controllers and OEM boards. */ 10643c2aeb0SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3101, 10743c2aeb0SSepherosa Ziehau "HP NC370T Multifunction Gigabit Server Adapter" }, 10843c2aeb0SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3106, 10943c2aeb0SSepherosa Ziehau "HP NC370i Multifunction Gigabit Server Adapter" }, 1103482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3070, 1113482f06cSSepherosa Ziehau "HP NC380T PCIe DP Multifunc Gig Server Adapter" }, 1123482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x1709, 1133482f06cSSepherosa Ziehau "HP NC371i Multifunction Gigabit Server Adapter" }, 11443c2aeb0SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, PCI_ANY_ID, PCI_ANY_ID, 11543c2aeb0SSepherosa Ziehau "Broadcom NetXtreme II BCM5706 1000Base-T" }, 11643c2aeb0SSepherosa Ziehau 11743c2aeb0SSepherosa Ziehau /* BCM5706S controllers and OEM boards. */ 11843c2aeb0SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, HP_VENDORID, 0x3102, 11943c2aeb0SSepherosa Ziehau "HP NC370F Multifunction Gigabit Server Adapter" }, 12043c2aeb0SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, PCI_ANY_ID, PCI_ANY_ID, 12143c2aeb0SSepherosa Ziehau "Broadcom NetXtreme II BCM5706 1000Base-SX" }, 12243c2aeb0SSepherosa Ziehau 12343c2aeb0SSepherosa Ziehau /* BCM5708C controllers and OEM boards. */ 1243482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5708, HP_VENDORID, 0x7037, 1253482f06cSSepherosa Ziehau "HP NC373T PCIe Multifunction Gig Server Adapter" }, 1263482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5708, HP_VENDORID, 0x7038, 1273482f06cSSepherosa Ziehau "HP NC373i Multifunction Gigabit Server Adapter" }, 1283482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5708, HP_VENDORID, 0x7045, 1293482f06cSSepherosa Ziehau "HP NC374m PCIe Multifunction Adapter" }, 13043c2aeb0SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5708, PCI_ANY_ID, PCI_ANY_ID, 13143c2aeb0SSepherosa Ziehau "Broadcom NetXtreme II BCM5708 1000Base-T" }, 13243c2aeb0SSepherosa Ziehau 13343c2aeb0SSepherosa Ziehau /* BCM5708S controllers and OEM boards. */ 1343482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, HP_VENDORID, 0x1706, 1353482f06cSSepherosa Ziehau "HP NC373m Multifunction Gigabit Server Adapter" }, 1363482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, HP_VENDORID, 0x703b, 1373482f06cSSepherosa Ziehau "HP NC373i Multifunction Gigabit Server Adapter" }, 1383482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, HP_VENDORID, 0x703d, 1393482f06cSSepherosa Ziehau "HP NC373F PCIe Multifunc Giga Server Adapter" }, 14043c2aeb0SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, PCI_ANY_ID, PCI_ANY_ID, 14143c2aeb0SSepherosa Ziehau "Broadcom NetXtreme II BCM5708S 1000Base-T" }, 142d0092544SSepherosa Ziehau 143d0092544SSepherosa Ziehau /* BCM5709C controllers and OEM boards. */ 1443482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5709, HP_VENDORID, 0x7055, 1453482f06cSSepherosa Ziehau "HP NC382i DP Multifunction Gigabit Server Adapter" }, 1463482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5709, HP_VENDORID, 0x7059, 1473482f06cSSepherosa Ziehau "HP NC382T PCIe DP Multifunction Gigabit Server Adapter" }, 148d0092544SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5709, PCI_ANY_ID, PCI_ANY_ID, 149d0092544SSepherosa Ziehau "Broadcom NetXtreme II BCM5709 1000Base-T" }, 150d0092544SSepherosa Ziehau 151d0092544SSepherosa Ziehau /* BCM5709S controllers and OEM boards. */ 1523482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5709S, HP_VENDORID, 0x171d, 1533482f06cSSepherosa Ziehau "HP NC382m DP 1GbE Multifunction BL-c Adapter" }, 1543482f06cSSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5709S, HP_VENDORID, 0x7056, 1553482f06cSSepherosa Ziehau "HP NC382i DP Multifunction Gigabit Server Adapter" }, 156d0092544SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5709S, PCI_ANY_ID, PCI_ANY_ID, 157d0092544SSepherosa Ziehau "Broadcom NetXtreme II BCM5709 1000Base-SX" }, 158d0092544SSepherosa Ziehau 159d0092544SSepherosa Ziehau /* BCM5716 controllers and OEM boards. */ 160d0092544SSepherosa Ziehau { BRCM_VENDORID, BRCM_DEVICEID_BCM5716, PCI_ANY_ID, PCI_ANY_ID, 161d0092544SSepherosa Ziehau "Broadcom NetXtreme II BCM5716 1000Base-T" }, 162d0092544SSepherosa Ziehau 16343c2aeb0SSepherosa Ziehau { 0, 0, 0, 0, NULL } 16443c2aeb0SSepherosa Ziehau }; 16543c2aeb0SSepherosa Ziehau 16643c2aeb0SSepherosa Ziehau 16743c2aeb0SSepherosa Ziehau /****************************************************************************/ 16843c2aeb0SSepherosa Ziehau /* Supported Flash NVRAM device data. */ 16943c2aeb0SSepherosa Ziehau /****************************************************************************/ 17043c2aeb0SSepherosa Ziehau static const struct flash_spec flash_table[] = 17143c2aeb0SSepherosa Ziehau { 172d0092544SSepherosa Ziehau #define BUFFERED_FLAGS (BCE_NV_BUFFERED | BCE_NV_TRANSLATE) 173d0092544SSepherosa Ziehau #define NONBUFFERED_FLAGS (BCE_NV_WREN) 174d0092544SSepherosa Ziehau 17543c2aeb0SSepherosa Ziehau /* Slow EEPROM */ 17643c2aeb0SSepherosa Ziehau {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400, 177d0092544SSepherosa Ziehau BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, 17843c2aeb0SSepherosa Ziehau SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, 17943c2aeb0SSepherosa Ziehau "EEPROM - slow"}, 18043c2aeb0SSepherosa Ziehau /* Expansion entry 0001 */ 18143c2aeb0SSepherosa Ziehau {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406, 182d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 18343c2aeb0SSepherosa Ziehau SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 18443c2aeb0SSepherosa Ziehau "Entry 0001"}, 18543c2aeb0SSepherosa Ziehau /* Saifun SA25F010 (non-buffered flash) */ 18643c2aeb0SSepherosa Ziehau /* strap, cfg1, & write1 need updates */ 18743c2aeb0SSepherosa Ziehau {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406, 188d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 18943c2aeb0SSepherosa Ziehau SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2, 19043c2aeb0SSepherosa Ziehau "Non-buffered flash (128kB)"}, 19143c2aeb0SSepherosa Ziehau /* Saifun SA25F020 (non-buffered flash) */ 19243c2aeb0SSepherosa Ziehau /* strap, cfg1, & write1 need updates */ 19343c2aeb0SSepherosa Ziehau {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406, 194d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 19543c2aeb0SSepherosa Ziehau SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4, 19643c2aeb0SSepherosa Ziehau "Non-buffered flash (256kB)"}, 19743c2aeb0SSepherosa Ziehau /* Expansion entry 0100 */ 19843c2aeb0SSepherosa Ziehau {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406, 199d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 20043c2aeb0SSepherosa Ziehau SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 20143c2aeb0SSepherosa Ziehau "Entry 0100"}, 20243c2aeb0SSepherosa Ziehau /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */ 20343c2aeb0SSepherosa Ziehau {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406, 204d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, 20543c2aeb0SSepherosa Ziehau ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2, 20643c2aeb0SSepherosa Ziehau "Entry 0101: ST M45PE10 (128kB non-bufferred)"}, 20743c2aeb0SSepherosa Ziehau /* Entry 0110: ST M45PE20 (non-buffered flash)*/ 20843c2aeb0SSepherosa Ziehau {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406, 209d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, 21043c2aeb0SSepherosa Ziehau ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4, 21143c2aeb0SSepherosa Ziehau "Entry 0110: ST M45PE20 (256kB non-bufferred)"}, 21243c2aeb0SSepherosa Ziehau /* Saifun SA25F005 (non-buffered flash) */ 21343c2aeb0SSepherosa Ziehau /* strap, cfg1, & write1 need updates */ 21443c2aeb0SSepherosa Ziehau {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406, 215d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 21643c2aeb0SSepherosa Ziehau SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE, 21743c2aeb0SSepherosa Ziehau "Non-buffered flash (64kB)"}, 21843c2aeb0SSepherosa Ziehau /* Fast EEPROM */ 21943c2aeb0SSepherosa Ziehau {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400, 220d0092544SSepherosa Ziehau BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, 22143c2aeb0SSepherosa Ziehau SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, 22243c2aeb0SSepherosa Ziehau "EEPROM - fast"}, 22343c2aeb0SSepherosa Ziehau /* Expansion entry 1001 */ 22443c2aeb0SSepherosa Ziehau {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406, 225d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 22643c2aeb0SSepherosa Ziehau SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 22743c2aeb0SSepherosa Ziehau "Entry 1001"}, 22843c2aeb0SSepherosa Ziehau /* Expansion entry 1010 */ 22943c2aeb0SSepherosa Ziehau {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406, 230d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 23143c2aeb0SSepherosa Ziehau SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 23243c2aeb0SSepherosa Ziehau "Entry 1010"}, 23343c2aeb0SSepherosa Ziehau /* ATMEL AT45DB011B (buffered flash) */ 23443c2aeb0SSepherosa Ziehau {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400, 235d0092544SSepherosa Ziehau BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, 23643c2aeb0SSepherosa Ziehau BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE, 23743c2aeb0SSepherosa Ziehau "Buffered flash (128kB)"}, 23843c2aeb0SSepherosa Ziehau /* Expansion entry 1100 */ 23943c2aeb0SSepherosa Ziehau {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406, 240d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 24143c2aeb0SSepherosa Ziehau SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 24243c2aeb0SSepherosa Ziehau "Entry 1100"}, 24343c2aeb0SSepherosa Ziehau /* Expansion entry 1101 */ 24443c2aeb0SSepherosa Ziehau {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406, 245d0092544SSepherosa Ziehau NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 24643c2aeb0SSepherosa Ziehau SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 24743c2aeb0SSepherosa Ziehau "Entry 1101"}, 24843c2aeb0SSepherosa Ziehau /* Ateml Expansion entry 1110 */ 24943c2aeb0SSepherosa Ziehau {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400, 250d0092544SSepherosa Ziehau BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, 25143c2aeb0SSepherosa Ziehau BUFFERED_FLASH_BYTE_ADDR_MASK, 0, 25243c2aeb0SSepherosa Ziehau "Entry 1110 (Atmel)"}, 25343c2aeb0SSepherosa Ziehau /* ATMEL AT45DB021B (buffered flash) */ 25443c2aeb0SSepherosa Ziehau {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400, 255d0092544SSepherosa Ziehau BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, 25643c2aeb0SSepherosa Ziehau BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2, 25743c2aeb0SSepherosa Ziehau "Buffered flash (256kB)"}, 25843c2aeb0SSepherosa Ziehau }; 25943c2aeb0SSepherosa Ziehau 260d0092544SSepherosa Ziehau /* 261d0092544SSepherosa Ziehau * The BCM5709 controllers transparently handle the 262d0092544SSepherosa Ziehau * differences between Atmel 264 byte pages and all 263d0092544SSepherosa Ziehau * flash devices which use 256 byte pages, so no 264d0092544SSepherosa Ziehau * logical-to-physical mapping is required in the 265d0092544SSepherosa Ziehau * driver. 266d0092544SSepherosa Ziehau */ 267d0092544SSepherosa Ziehau static struct flash_spec flash_5709 = { 268d0092544SSepherosa Ziehau .flags = BCE_NV_BUFFERED, 269d0092544SSepherosa Ziehau .page_bits = BCM5709_FLASH_PAGE_BITS, 270d0092544SSepherosa Ziehau .page_size = BCM5709_FLASH_PAGE_SIZE, 271d0092544SSepherosa Ziehau .addr_mask = BCM5709_FLASH_BYTE_ADDR_MASK, 272d0092544SSepherosa Ziehau .total_size = BUFFERED_FLASH_TOTAL_SIZE * 2, 273d0092544SSepherosa Ziehau .name = "5709/5716 buffered flash (256kB)", 274d0092544SSepherosa Ziehau }; 275d0092544SSepherosa Ziehau 27643c2aeb0SSepherosa Ziehau 27743c2aeb0SSepherosa Ziehau /****************************************************************************/ 27843c2aeb0SSepherosa Ziehau /* DragonFly device entry points. */ 27943c2aeb0SSepherosa Ziehau /****************************************************************************/ 28043c2aeb0SSepherosa Ziehau static int bce_probe(device_t); 28143c2aeb0SSepherosa Ziehau static int bce_attach(device_t); 28243c2aeb0SSepherosa Ziehau static int bce_detach(device_t); 28343c2aeb0SSepherosa Ziehau static void bce_shutdown(device_t); 2848aca6ad9SSepherosa Ziehau static int bce_miibus_read_reg(device_t, int, int); 2858aca6ad9SSepherosa Ziehau static int bce_miibus_write_reg(device_t, int, int, int); 2868aca6ad9SSepherosa Ziehau static void bce_miibus_statchg(device_t); 28743c2aeb0SSepherosa Ziehau 28843c2aeb0SSepherosa Ziehau /****************************************************************************/ 28943c2aeb0SSepherosa Ziehau /* BCE Register/Memory Access Routines */ 29043c2aeb0SSepherosa Ziehau /****************************************************************************/ 29143c2aeb0SSepherosa Ziehau static uint32_t bce_reg_rd_ind(struct bce_softc *, uint32_t); 29243c2aeb0SSepherosa Ziehau static void bce_reg_wr_ind(struct bce_softc *, uint32_t, uint32_t); 293bc30d40dSSepherosa Ziehau static void bce_shmem_wr(struct bce_softc *, uint32_t, uint32_t); 294bc30d40dSSepherosa Ziehau static uint32_t bce_shmem_rd(struct bce_softc *, u32); 29543c2aeb0SSepherosa Ziehau static void bce_ctx_wr(struct bce_softc *, uint32_t, uint32_t, uint32_t); 29643c2aeb0SSepherosa Ziehau 29743c2aeb0SSepherosa Ziehau /****************************************************************************/ 29843c2aeb0SSepherosa Ziehau /* BCE NVRAM Access Routines */ 29943c2aeb0SSepherosa Ziehau /****************************************************************************/ 30043c2aeb0SSepherosa Ziehau static int bce_acquire_nvram_lock(struct bce_softc *); 30143c2aeb0SSepherosa Ziehau static int bce_release_nvram_lock(struct bce_softc *); 30243c2aeb0SSepherosa Ziehau static void bce_enable_nvram_access(struct bce_softc *); 30343c2aeb0SSepherosa Ziehau static void bce_disable_nvram_access(struct bce_softc *); 30443c2aeb0SSepherosa Ziehau static int bce_nvram_read_dword(struct bce_softc *, uint32_t, uint8_t *, 30543c2aeb0SSepherosa Ziehau uint32_t); 30643c2aeb0SSepherosa Ziehau static int bce_init_nvram(struct bce_softc *); 30743c2aeb0SSepherosa Ziehau static int bce_nvram_read(struct bce_softc *, uint32_t, uint8_t *, int); 30843c2aeb0SSepherosa Ziehau static int bce_nvram_test(struct bce_softc *); 30943c2aeb0SSepherosa Ziehau 31043c2aeb0SSepherosa Ziehau /****************************************************************************/ 31143c2aeb0SSepherosa Ziehau /* BCE DMA Allocate/Free Routines */ 31243c2aeb0SSepherosa Ziehau /****************************************************************************/ 31343c2aeb0SSepherosa Ziehau static int bce_dma_alloc(struct bce_softc *); 31443c2aeb0SSepherosa Ziehau static void bce_dma_free(struct bce_softc *); 31543c2aeb0SSepherosa Ziehau static void bce_dma_map_addr(void *, bus_dma_segment_t *, int, int); 31643c2aeb0SSepherosa Ziehau 31743c2aeb0SSepherosa Ziehau /****************************************************************************/ 31843c2aeb0SSepherosa Ziehau /* BCE Firmware Synchronization and Load */ 31943c2aeb0SSepherosa Ziehau /****************************************************************************/ 32043c2aeb0SSepherosa Ziehau static int bce_fw_sync(struct bce_softc *, uint32_t); 32143c2aeb0SSepherosa Ziehau static void bce_load_rv2p_fw(struct bce_softc *, uint32_t *, 32243c2aeb0SSepherosa Ziehau uint32_t, uint32_t); 32343c2aeb0SSepherosa Ziehau static void bce_load_cpu_fw(struct bce_softc *, struct cpu_reg *, 32443c2aeb0SSepherosa Ziehau struct fw_info *); 3255d05a208SSepherosa Ziehau static void bce_start_cpu(struct bce_softc *, struct cpu_reg *); 3265d05a208SSepherosa Ziehau static void bce_halt_cpu(struct bce_softc *, struct cpu_reg *); 3275d05a208SSepherosa Ziehau static void bce_start_rxp_cpu(struct bce_softc *); 328d0092544SSepherosa Ziehau static void bce_init_rxp_cpu(struct bce_softc *); 329d0092544SSepherosa Ziehau static void bce_init_txp_cpu(struct bce_softc *); 330d0092544SSepherosa Ziehau static void bce_init_tpat_cpu(struct bce_softc *); 331d0092544SSepherosa Ziehau static void bce_init_cp_cpu(struct bce_softc *); 332d0092544SSepherosa Ziehau static void bce_init_com_cpu(struct bce_softc *); 33343c2aeb0SSepherosa Ziehau static void bce_init_cpus(struct bce_softc *); 33443c2aeb0SSepherosa Ziehau 33543c2aeb0SSepherosa Ziehau static void bce_stop(struct bce_softc *); 33643c2aeb0SSepherosa Ziehau static int bce_reset(struct bce_softc *, uint32_t); 33743c2aeb0SSepherosa Ziehau static int bce_chipinit(struct bce_softc *); 33843c2aeb0SSepherosa Ziehau static int bce_blockinit(struct bce_softc *); 339d0092544SSepherosa Ziehau static void bce_probe_pci_caps(struct bce_softc *); 340d0092544SSepherosa Ziehau static void bce_print_adapter_info(struct bce_softc *); 341d0092544SSepherosa Ziehau static void bce_get_media(struct bce_softc *); 3428aca6ad9SSepherosa Ziehau static void bce_mgmt_init(struct bce_softc *); 3438aca6ad9SSepherosa Ziehau static int bce_init_ctx(struct bce_softc *); 3448aca6ad9SSepherosa Ziehau static void bce_get_mac_addr(struct bce_softc *); 3458aca6ad9SSepherosa Ziehau static void bce_set_mac_addr(struct bce_softc *); 3468aca6ad9SSepherosa Ziehau static void bce_set_rx_mode(struct bce_softc *); 3478aca6ad9SSepherosa Ziehau static void bce_coal_change(struct bce_softc *); 34884464af5SSepherosa Ziehau static void bce_setup_serialize(struct bce_softc *); 34984464af5SSepherosa Ziehau static void bce_serialize_skipmain(struct bce_softc *); 35084464af5SSepherosa Ziehau static void bce_deserialize_skipmain(struct bce_softc *); 35143c2aeb0SSepherosa Ziehau 35210bcbdabSSepherosa Ziehau static int bce_create_tx_ring(struct bce_tx_ring *); 35310bcbdabSSepherosa Ziehau static void bce_destroy_tx_ring(struct bce_tx_ring *); 35410bcbdabSSepherosa Ziehau static void bce_init_tx_context(struct bce_tx_ring *); 35510bcbdabSSepherosa Ziehau static int bce_init_tx_chain(struct bce_tx_ring *); 35610bcbdabSSepherosa Ziehau static void bce_free_tx_chain(struct bce_tx_ring *); 3578aca6ad9SSepherosa Ziehau static void bce_xmit(struct bce_tx_ring *); 3588aca6ad9SSepherosa Ziehau static int bce_encap(struct bce_tx_ring *, struct mbuf **, int *); 3598aca6ad9SSepherosa Ziehau static int bce_tso_setup(struct bce_tx_ring *, struct mbuf **, 3608aca6ad9SSepherosa Ziehau uint16_t *, uint16_t *); 3618aca6ad9SSepherosa Ziehau 36208b64767SSepherosa Ziehau static int bce_create_rx_ring(struct bce_rx_ring *); 36308b64767SSepherosa Ziehau static void bce_destroy_rx_ring(struct bce_rx_ring *); 36408b64767SSepherosa Ziehau static void bce_init_rx_context(struct bce_rx_ring *); 36508b64767SSepherosa Ziehau static int bce_init_rx_chain(struct bce_rx_ring *); 36608b64767SSepherosa Ziehau static void bce_free_rx_chain(struct bce_rx_ring *); 3678aca6ad9SSepherosa Ziehau static int bce_newbuf_std(struct bce_rx_ring *, uint16_t *, uint16_t *, 3688aca6ad9SSepherosa Ziehau uint32_t *, int); 3698aca6ad9SSepherosa Ziehau static void bce_setup_rxdesc_std(struct bce_rx_ring *, uint16_t, 3708aca6ad9SSepherosa Ziehau uint32_t *); 37143c2aeb0SSepherosa Ziehau 372f0a26983SSepherosa Ziehau static void bce_start(struct ifnet *, struct ifaltq_subque *); 37343c2aeb0SSepherosa Ziehau static int bce_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 37443c2aeb0SSepherosa Ziehau static void bce_watchdog(struct ifnet *); 37543c2aeb0SSepherosa Ziehau static int bce_ifmedia_upd(struct ifnet *); 37643c2aeb0SSepherosa Ziehau static void bce_ifmedia_sts(struct ifnet *, struct ifmediareq *); 37743c2aeb0SSepherosa Ziehau static void bce_init(void *); 3784a331bf7SSepherosa Ziehau #ifdef IFPOLL_ENABLE 3794a331bf7SSepherosa Ziehau static void bce_npoll(struct ifnet *, struct ifpoll_info *); 38057b3ecd9SSepherosa Ziehau static void bce_npoll_rx(struct ifnet *, void *, int); 38157b3ecd9SSepherosa Ziehau static void bce_npoll_tx(struct ifnet *, void *, int); 38257b3ecd9SSepherosa Ziehau static void bce_npoll_status(struct ifnet *); 38343c2aeb0SSepherosa Ziehau #endif 38484464af5SSepherosa Ziehau static void bce_serialize(struct ifnet *, enum ifnet_serialize); 38584464af5SSepherosa Ziehau static void bce_deserialize(struct ifnet *, enum ifnet_serialize); 38684464af5SSepherosa Ziehau static int bce_tryserialize(struct ifnet *, enum ifnet_serialize); 38784464af5SSepherosa Ziehau #ifdef INVARIANTS 38884464af5SSepherosa Ziehau static void bce_serialize_assert(struct ifnet *, enum ifnet_serialize, 38984464af5SSepherosa Ziehau boolean_t); 39084464af5SSepherosa Ziehau #endif 3918aca6ad9SSepherosa Ziehau 392eac57ffbSSepherosa Ziehau static void bce_intr(struct bce_softc *); 393eac57ffbSSepherosa Ziehau static void bce_intr_legacy(void *); 394eac57ffbSSepherosa Ziehau static void bce_intr_msi(void *); 395eac57ffbSSepherosa Ziehau static void bce_intr_msi_oneshot(void *); 3968aca6ad9SSepherosa Ziehau static void bce_tx_intr(struct bce_tx_ring *, uint16_t); 3978aca6ad9SSepherosa Ziehau static void bce_rx_intr(struct bce_rx_ring *, int, uint16_t); 3988aca6ad9SSepherosa Ziehau static void bce_phy_intr(struct bce_softc *); 3998aca6ad9SSepherosa Ziehau static void bce_disable_intr(struct bce_softc *); 4008aca6ad9SSepherosa Ziehau static void bce_enable_intr(struct bce_softc *); 4018aca6ad9SSepherosa Ziehau static void bce_reenable_intr(struct bce_softc *); 4028aca6ad9SSepherosa Ziehau static void bce_check_msi(void *); 4038aca6ad9SSepherosa Ziehau 40443c2aeb0SSepherosa Ziehau static void bce_stats_update(struct bce_softc *); 40543c2aeb0SSepherosa Ziehau static void bce_tick(void *); 40643c2aeb0SSepherosa Ziehau static void bce_tick_serialized(struct bce_softc *); 407d0092544SSepherosa Ziehau static void bce_pulse(void *); 40843c2aeb0SSepherosa Ziehau 4098aca6ad9SSepherosa Ziehau static void bce_add_sysctls(struct bce_softc *); 410bdeb8fffSSepherosa Ziehau static int bce_sysctl_tx_bds_int(SYSCTL_HANDLER_ARGS); 411bdeb8fffSSepherosa Ziehau static int bce_sysctl_tx_bds(SYSCTL_HANDLER_ARGS); 412bdeb8fffSSepherosa Ziehau static int bce_sysctl_tx_ticks_int(SYSCTL_HANDLER_ARGS); 413bdeb8fffSSepherosa Ziehau static int bce_sysctl_tx_ticks(SYSCTL_HANDLER_ARGS); 414bdeb8fffSSepherosa Ziehau static int bce_sysctl_rx_bds_int(SYSCTL_HANDLER_ARGS); 415bdeb8fffSSepherosa Ziehau static int bce_sysctl_rx_bds(SYSCTL_HANDLER_ARGS); 416bdeb8fffSSepherosa Ziehau static int bce_sysctl_rx_ticks_int(SYSCTL_HANDLER_ARGS); 417bdeb8fffSSepherosa Ziehau static int bce_sysctl_rx_ticks(SYSCTL_HANDLER_ARGS); 41857b3ecd9SSepherosa Ziehau #ifdef IFPOLL_ENABLE 41957b3ecd9SSepherosa Ziehau static int bce_sysctl_npoll_offset(SYSCTL_HANDLER_ARGS); 42057b3ecd9SSepherosa Ziehau #endif 421bdeb8fffSSepherosa Ziehau static int bce_sysctl_coal_change(SYSCTL_HANDLER_ARGS, 422bdeb8fffSSepherosa Ziehau uint32_t *, uint32_t); 423bdeb8fffSSepherosa Ziehau 4243fb4bb6cSSepherosa Ziehau /* 4253fb4bb6cSSepherosa Ziehau * NOTE: 4263fb4bb6cSSepherosa Ziehau * Don't set bce_tx_ticks_int/bce_tx_ticks to 1023. Linux's bnx2 4273fb4bb6cSSepherosa Ziehau * takes 1023 as the TX ticks limit. However, using 1023 will 4283fb4bb6cSSepherosa Ziehau * cause 5708(B2) to generate extra interrupts (~2000/s) even when 4293fb4bb6cSSepherosa Ziehau * there is _no_ network activity on the NIC. 4303fb4bb6cSSepherosa Ziehau */ 4313fb4bb6cSSepherosa Ziehau static uint32_t bce_tx_bds_int = 255; /* bcm: 20 */ 4323fb4bb6cSSepherosa Ziehau static uint32_t bce_tx_bds = 255; /* bcm: 20 */ 4333fb4bb6cSSepherosa Ziehau static uint32_t bce_tx_ticks_int = 1022; /* bcm: 80 */ 4343fb4bb6cSSepherosa Ziehau static uint32_t bce_tx_ticks = 1022; /* bcm: 80 */ 4351af951abSSepherosa Ziehau static uint32_t bce_rx_bds_int = 128; /* bcm: 6 */ 43647388162SSepherosa Ziehau static uint32_t bce_rx_bds = 0; /* bcm: 6 */ 4372b3bab8aSSepherosa Ziehau static uint32_t bce_rx_ticks_int = 150; /* bcm: 18 */ 4382b3bab8aSSepherosa Ziehau static uint32_t bce_rx_ticks = 150; /* bcm: 18 */ 439bdeb8fffSSepherosa Ziehau 440c19b6815SSepherosa Ziehau static int bce_tx_wreg = 8; 441c19b6815SSepherosa Ziehau 44283ce3dceSSepherosa Ziehau static int bce_msi_enable = 1; 44383ce3dceSSepherosa Ziehau 4444b166d4eSSepherosa Ziehau static int bce_rx_pages = RX_PAGES_DEFAULT; 4454b166d4eSSepherosa Ziehau static int bce_tx_pages = TX_PAGES_DEFAULT; 4464b166d4eSSepherosa Ziehau 447bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_bds_int", &bce_tx_bds_int); 448bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_bds", &bce_tx_bds); 449bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_ticks_int", &bce_tx_ticks_int); 450bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_ticks", &bce_tx_ticks); 451bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_bds_int", &bce_rx_bds_int); 452bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_bds", &bce_rx_bds); 453bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_ticks_int", &bce_rx_ticks_int); 454bdeb8fffSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_ticks", &bce_rx_ticks); 45583ce3dceSSepherosa Ziehau TUNABLE_INT("hw.bce.msi.enable", &bce_msi_enable); 4564b166d4eSSepherosa Ziehau TUNABLE_INT("hw.bce.rx_pages", &bce_rx_pages); 4574b166d4eSSepherosa Ziehau TUNABLE_INT("hw.bce.tx_pages", &bce_tx_pages); 458c19b6815SSepherosa Ziehau TUNABLE_INT("hw.bce.tx_wreg", &bce_tx_wreg); 45943c2aeb0SSepherosa Ziehau 46043c2aeb0SSepherosa Ziehau /****************************************************************************/ 46143c2aeb0SSepherosa Ziehau /* DragonFly device dispatch table. */ 46243c2aeb0SSepherosa Ziehau /****************************************************************************/ 46343c2aeb0SSepherosa Ziehau static device_method_t bce_methods[] = { 46443c2aeb0SSepherosa Ziehau /* Device interface */ 46543c2aeb0SSepherosa Ziehau DEVMETHOD(device_probe, bce_probe), 46643c2aeb0SSepherosa Ziehau DEVMETHOD(device_attach, bce_attach), 46743c2aeb0SSepherosa Ziehau DEVMETHOD(device_detach, bce_detach), 46843c2aeb0SSepherosa Ziehau DEVMETHOD(device_shutdown, bce_shutdown), 46943c2aeb0SSepherosa Ziehau 47043c2aeb0SSepherosa Ziehau /* bus interface */ 47143c2aeb0SSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 47243c2aeb0SSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 47343c2aeb0SSepherosa Ziehau 47443c2aeb0SSepherosa Ziehau /* MII interface */ 47543c2aeb0SSepherosa Ziehau DEVMETHOD(miibus_readreg, bce_miibus_read_reg), 47643c2aeb0SSepherosa Ziehau DEVMETHOD(miibus_writereg, bce_miibus_write_reg), 47743c2aeb0SSepherosa Ziehau DEVMETHOD(miibus_statchg, bce_miibus_statchg), 47843c2aeb0SSepherosa Ziehau 479*d3c9c58eSSascha Wildner DEVMETHOD_END 48043c2aeb0SSepherosa Ziehau }; 48143c2aeb0SSepherosa Ziehau 48243c2aeb0SSepherosa Ziehau static driver_t bce_driver = { 48343c2aeb0SSepherosa Ziehau "bce", 48443c2aeb0SSepherosa Ziehau bce_methods, 48543c2aeb0SSepherosa Ziehau sizeof(struct bce_softc) 48643c2aeb0SSepherosa Ziehau }; 48743c2aeb0SSepherosa Ziehau 48843c2aeb0SSepherosa Ziehau static devclass_t bce_devclass; 48943c2aeb0SSepherosa Ziehau 49043c2aeb0SSepherosa Ziehau 491d0092544SSepherosa Ziehau DECLARE_DUMMY_MODULE(if_bce); 4921be78fa8SSepherosa Ziehau MODULE_DEPEND(bce, miibus, 1, 1, 1); 493aa2b9d05SSascha Wildner DRIVER_MODULE(if_bce, pci, bce_driver, bce_devclass, NULL, NULL); 494aa2b9d05SSascha Wildner DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, NULL, NULL); 49543c2aeb0SSepherosa Ziehau 49643c2aeb0SSepherosa Ziehau 49743c2aeb0SSepherosa Ziehau /****************************************************************************/ 49843c2aeb0SSepherosa Ziehau /* Device probe function. */ 49943c2aeb0SSepherosa Ziehau /* */ 50043c2aeb0SSepherosa Ziehau /* Compares the device to the driver's list of supported devices and */ 50143c2aeb0SSepherosa Ziehau /* reports back to the OS whether this is the right driver for the device. */ 50243c2aeb0SSepherosa Ziehau /* */ 50343c2aeb0SSepherosa Ziehau /* Returns: */ 50443c2aeb0SSepherosa Ziehau /* BUS_PROBE_DEFAULT on success, positive value on failure. */ 50543c2aeb0SSepherosa Ziehau /****************************************************************************/ 50643c2aeb0SSepherosa Ziehau static int 50743c2aeb0SSepherosa Ziehau bce_probe(device_t dev) 50843c2aeb0SSepherosa Ziehau { 50943c2aeb0SSepherosa Ziehau struct bce_type *t; 51043c2aeb0SSepherosa Ziehau uint16_t vid, did, svid, sdid; 51143c2aeb0SSepherosa Ziehau 51243c2aeb0SSepherosa Ziehau /* Get the data for the device to be probed. */ 51343c2aeb0SSepherosa Ziehau vid = pci_get_vendor(dev); 51443c2aeb0SSepherosa Ziehau did = pci_get_device(dev); 51543c2aeb0SSepherosa Ziehau svid = pci_get_subvendor(dev); 51643c2aeb0SSepherosa Ziehau sdid = pci_get_subdevice(dev); 51743c2aeb0SSepherosa Ziehau 51843c2aeb0SSepherosa Ziehau /* Look through the list of known devices for a match. */ 51943c2aeb0SSepherosa Ziehau for (t = bce_devs; t->bce_name != NULL; ++t) { 52043c2aeb0SSepherosa Ziehau if (vid == t->bce_vid && did == t->bce_did && 52143c2aeb0SSepherosa Ziehau (svid == t->bce_svid || t->bce_svid == PCI_ANY_ID) && 52243c2aeb0SSepherosa Ziehau (sdid == t->bce_sdid || t->bce_sdid == PCI_ANY_ID)) { 52343c2aeb0SSepherosa Ziehau uint32_t revid = pci_read_config(dev, PCIR_REVID, 4); 52443c2aeb0SSepherosa Ziehau char *descbuf; 52543c2aeb0SSepherosa Ziehau 52643c2aeb0SSepherosa Ziehau descbuf = kmalloc(BCE_DEVDESC_MAX, M_TEMP, M_WAITOK); 52743c2aeb0SSepherosa Ziehau 52843c2aeb0SSepherosa Ziehau /* Print out the device identity. */ 52943c2aeb0SSepherosa Ziehau ksnprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d)", 53043c2aeb0SSepherosa Ziehau t->bce_name, 53143c2aeb0SSepherosa Ziehau ((revid & 0xf0) >> 4) + 'A', revid & 0xf); 53243c2aeb0SSepherosa Ziehau 53343c2aeb0SSepherosa Ziehau device_set_desc_copy(dev, descbuf); 53443c2aeb0SSepherosa Ziehau kfree(descbuf, M_TEMP); 53543c2aeb0SSepherosa Ziehau return 0; 53643c2aeb0SSepherosa Ziehau } 53743c2aeb0SSepherosa Ziehau } 53843c2aeb0SSepherosa Ziehau return ENXIO; 53943c2aeb0SSepherosa Ziehau } 54043c2aeb0SSepherosa Ziehau 54143c2aeb0SSepherosa Ziehau 54243c2aeb0SSepherosa Ziehau /****************************************************************************/ 543d0092544SSepherosa Ziehau /* PCI Capabilities Probe Function. */ 544d0092544SSepherosa Ziehau /* */ 545d0092544SSepherosa Ziehau /* Walks the PCI capabiites list for the device to find what features are */ 546d0092544SSepherosa Ziehau /* supported. */ 547d0092544SSepherosa Ziehau /* */ 548d0092544SSepherosa Ziehau /* Returns: */ 549d0092544SSepherosa Ziehau /* None. */ 550d0092544SSepherosa Ziehau /****************************************************************************/ 551d0092544SSepherosa Ziehau static void 552d0092544SSepherosa Ziehau bce_print_adapter_info(struct bce_softc *sc) 553d0092544SSepherosa Ziehau { 554d0092544SSepherosa Ziehau device_printf(sc->bce_dev, "ASIC (0x%08X); ", sc->bce_chipid); 555d0092544SSepherosa Ziehau 556d0092544SSepherosa Ziehau kprintf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A', 557d0092544SSepherosa Ziehau ((BCE_CHIP_ID(sc) & 0x0ff0) >> 4)); 558d0092544SSepherosa Ziehau 559d0092544SSepherosa Ziehau /* Bus info. */ 560d0092544SSepherosa Ziehau if (sc->bce_flags & BCE_PCIE_FLAG) { 561d0092544SSepherosa Ziehau kprintf("Bus (PCIe x%d, ", sc->link_width); 562d0092544SSepherosa Ziehau switch (sc->link_speed) { 563d0092544SSepherosa Ziehau case 1: 564d0092544SSepherosa Ziehau kprintf("2.5Gbps); "); 565d0092544SSepherosa Ziehau break; 566d0092544SSepherosa Ziehau case 2: 567d0092544SSepherosa Ziehau kprintf("5Gbps); "); 568d0092544SSepherosa Ziehau break; 569d0092544SSepherosa Ziehau default: 570d0092544SSepherosa Ziehau kprintf("Unknown link speed); "); 571d0092544SSepherosa Ziehau break; 572d0092544SSepherosa Ziehau } 573d0092544SSepherosa Ziehau } else { 574d0092544SSepherosa Ziehau kprintf("Bus (PCI%s, %s, %dMHz); ", 575d0092544SSepherosa Ziehau ((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""), 576d0092544SSepherosa Ziehau ((sc->bce_flags & BCE_PCI_32BIT_FLAG) ? "32-bit" : "64-bit"), 577d0092544SSepherosa Ziehau sc->bus_speed_mhz); 578d0092544SSepherosa Ziehau } 579d0092544SSepherosa Ziehau 580d0092544SSepherosa Ziehau /* Firmware version and device features. */ 581bc30d40dSSepherosa Ziehau kprintf("B/C (%s)", sc->bce_bc_ver); 582d0092544SSepherosa Ziehau 583cff16e71SSepherosa Ziehau if ((sc->bce_flags & BCE_MFW_ENABLE_FLAG) || 584cff16e71SSepherosa Ziehau (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)) { 585cff16e71SSepherosa Ziehau kprintf("; Flags("); 586d0092544SSepherosa Ziehau if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) 587bc30d40dSSepherosa Ziehau kprintf("MFW[%s]", sc->bce_mfw_ver); 588d0092544SSepherosa Ziehau if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) 589d0092544SSepherosa Ziehau kprintf(" 2.5G"); 590cff16e71SSepherosa Ziehau kprintf(")"); 591cff16e71SSepherosa Ziehau } 592cff16e71SSepherosa Ziehau kprintf("\n"); 593d0092544SSepherosa Ziehau } 594d0092544SSepherosa Ziehau 595d0092544SSepherosa Ziehau 596d0092544SSepherosa Ziehau /****************************************************************************/ 597d0092544SSepherosa Ziehau /* PCI Capabilities Probe Function. */ 598d0092544SSepherosa Ziehau /* */ 599d0092544SSepherosa Ziehau /* Walks the PCI capabiites list for the device to find what features are */ 600d0092544SSepherosa Ziehau /* supported. */ 601d0092544SSepherosa Ziehau /* */ 602d0092544SSepherosa Ziehau /* Returns: */ 603d0092544SSepherosa Ziehau /* None. */ 604d0092544SSepherosa Ziehau /****************************************************************************/ 605d0092544SSepherosa Ziehau static void 606d0092544SSepherosa Ziehau bce_probe_pci_caps(struct bce_softc *sc) 607d0092544SSepherosa Ziehau { 608d0092544SSepherosa Ziehau device_t dev = sc->bce_dev; 609d0092544SSepherosa Ziehau uint8_t ptr; 610d0092544SSepherosa Ziehau 611d0092544SSepherosa Ziehau if (pci_is_pcix(dev)) 612d0092544SSepherosa Ziehau sc->bce_cap_flags |= BCE_PCIX_CAPABLE_FLAG; 613d0092544SSepherosa Ziehau 614d0092544SSepherosa Ziehau ptr = pci_get_pciecap_ptr(dev); 615d0092544SSepherosa Ziehau if (ptr) { 616d0092544SSepherosa Ziehau uint16_t link_status = pci_read_config(dev, ptr + 0x12, 2); 617d0092544SSepherosa Ziehau 618d0092544SSepherosa Ziehau sc->link_speed = link_status & 0xf; 619d0092544SSepherosa Ziehau sc->link_width = (link_status >> 4) & 0x3f; 620d0092544SSepherosa Ziehau sc->bce_cap_flags |= BCE_PCIE_CAPABLE_FLAG; 621d0092544SSepherosa Ziehau sc->bce_flags |= BCE_PCIE_FLAG; 622d0092544SSepherosa Ziehau } 623d0092544SSepherosa Ziehau } 624d0092544SSepherosa Ziehau 625d0092544SSepherosa Ziehau 626d0092544SSepherosa Ziehau /****************************************************************************/ 62743c2aeb0SSepherosa Ziehau /* Device attach function. */ 62843c2aeb0SSepherosa Ziehau /* */ 62943c2aeb0SSepherosa Ziehau /* Allocates device resources, performs secondary chip identification, */ 63043c2aeb0SSepherosa Ziehau /* resets and initializes the hardware, and initializes driver instance */ 63143c2aeb0SSepherosa Ziehau /* variables. */ 63243c2aeb0SSepherosa Ziehau /* */ 63343c2aeb0SSepherosa Ziehau /* Returns: */ 63443c2aeb0SSepherosa Ziehau /* 0 on success, positive value on failure. */ 63543c2aeb0SSepherosa Ziehau /****************************************************************************/ 63643c2aeb0SSepherosa Ziehau static int 63743c2aeb0SSepherosa Ziehau bce_attach(device_t dev) 63843c2aeb0SSepherosa Ziehau { 63943c2aeb0SSepherosa Ziehau struct bce_softc *sc = device_get_softc(dev); 64043c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 64143c2aeb0SSepherosa Ziehau uint32_t val; 64283ce3dceSSepherosa Ziehau u_int irq_flags; 643eac57ffbSSepherosa Ziehau void (*irq_handle)(void *); 6447fb43956SSepherosa Ziehau int rid, rc = 0; 645bc30d40dSSepherosa Ziehau int i, j; 646f31c6e4dSSepherosa Ziehau struct mii_probe_args mii_args; 647f31c6e4dSSepherosa Ziehau uintptr_t mii_priv = 0; 64857b3ecd9SSepherosa Ziehau #ifdef IFPOLL_ENABLE 64957b3ecd9SSepherosa Ziehau int offset, offset_def; 65057b3ecd9SSepherosa Ziehau #endif 65143c2aeb0SSepherosa Ziehau 65243c2aeb0SSepherosa Ziehau sc->bce_dev = dev; 65343c2aeb0SSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 65443c2aeb0SSepherosa Ziehau 65584464af5SSepherosa Ziehau lwkt_serialize_init(&sc->main_serialize); 65684464af5SSepherosa Ziehau 65743c2aeb0SSepherosa Ziehau pci_enable_busmaster(dev); 65843c2aeb0SSepherosa Ziehau 659d0092544SSepherosa Ziehau bce_probe_pci_caps(sc); 660d0092544SSepherosa Ziehau 66143c2aeb0SSepherosa Ziehau /* Allocate PCI memory resources. */ 66243c2aeb0SSepherosa Ziehau rid = PCIR_BAR(0); 66343c2aeb0SSepherosa Ziehau sc->bce_res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 66443c2aeb0SSepherosa Ziehau RF_ACTIVE | PCI_RF_DENSE); 66543c2aeb0SSepherosa Ziehau if (sc->bce_res_mem == NULL) { 66643c2aeb0SSepherosa Ziehau device_printf(dev, "PCI memory allocation failed\n"); 66743c2aeb0SSepherosa Ziehau return ENXIO; 66843c2aeb0SSepherosa Ziehau } 66943c2aeb0SSepherosa Ziehau sc->bce_btag = rman_get_bustag(sc->bce_res_mem); 67043c2aeb0SSepherosa Ziehau sc->bce_bhandle = rman_get_bushandle(sc->bce_res_mem); 67143c2aeb0SSepherosa Ziehau 67243c2aeb0SSepherosa Ziehau /* 67343c2aeb0SSepherosa Ziehau * Configure byte swap and enable indirect register access. 67443c2aeb0SSepherosa Ziehau * Rely on CPU to do target byte swapping on big endian systems. 67543c2aeb0SSepherosa Ziehau * Access to registers outside of PCI configurtion space are not 67643c2aeb0SSepherosa Ziehau * valid until this is done. 67743c2aeb0SSepherosa Ziehau */ 67843c2aeb0SSepherosa Ziehau pci_write_config(dev, BCE_PCICFG_MISC_CONFIG, 67943c2aeb0SSepherosa Ziehau BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | 68043c2aeb0SSepherosa Ziehau BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP, 4); 68143c2aeb0SSepherosa Ziehau 68243c2aeb0SSepherosa Ziehau /* Save ASIC revsion info. */ 68343c2aeb0SSepherosa Ziehau sc->bce_chipid = REG_RD(sc, BCE_MISC_ID); 68443c2aeb0SSepherosa Ziehau 68543c2aeb0SSepherosa Ziehau /* Weed out any non-production controller revisions. */ 68643c2aeb0SSepherosa Ziehau switch (BCE_CHIP_ID(sc)) { 68743c2aeb0SSepherosa Ziehau case BCE_CHIP_ID_5706_A0: 68843c2aeb0SSepherosa Ziehau case BCE_CHIP_ID_5706_A1: 68943c2aeb0SSepherosa Ziehau case BCE_CHIP_ID_5708_A0: 69043c2aeb0SSepherosa Ziehau case BCE_CHIP_ID_5708_B0: 691d0092544SSepherosa Ziehau case BCE_CHIP_ID_5709_A0: 692d0092544SSepherosa Ziehau case BCE_CHIP_ID_5709_B0: 693d0092544SSepherosa Ziehau case BCE_CHIP_ID_5709_B1: 694d0092544SSepherosa Ziehau #ifdef foo 695d0092544SSepherosa Ziehau /* 5709C B2 seems to work fine */ 696d0092544SSepherosa Ziehau case BCE_CHIP_ID_5709_B2: 697d0092544SSepherosa Ziehau #endif 69843c2aeb0SSepherosa Ziehau device_printf(dev, "Unsupported chip id 0x%08x!\n", 69943c2aeb0SSepherosa Ziehau BCE_CHIP_ID(sc)); 70043c2aeb0SSepherosa Ziehau rc = ENODEV; 70143c2aeb0SSepherosa Ziehau goto fail; 70243c2aeb0SSepherosa Ziehau } 70343c2aeb0SSepherosa Ziehau 704f31c6e4dSSepherosa Ziehau mii_priv |= BRGPHY_FLAG_WIRESPEED; 705f31c6e4dSSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) { 706f31c6e4dSSepherosa Ziehau if (BCE_CHIP_REV(sc) == BCE_CHIP_REV_Ax || 707f31c6e4dSSepherosa Ziehau BCE_CHIP_REV(sc) == BCE_CHIP_REV_Bx) 708f31c6e4dSSepherosa Ziehau mii_priv |= BRGPHY_FLAG_NO_EARLYDAC; 709f31c6e4dSSepherosa Ziehau } else { 710f31c6e4dSSepherosa Ziehau mii_priv |= BRGPHY_FLAG_BER_BUG; 711f31c6e4dSSepherosa Ziehau } 712f31c6e4dSSepherosa Ziehau 71343c2aeb0SSepherosa Ziehau /* 71443c2aeb0SSepherosa Ziehau * Find the base address for shared memory access. 71543c2aeb0SSepherosa Ziehau * Newer versions of bootcode use a signature and offset 71643c2aeb0SSepherosa Ziehau * while older versions use a fixed address. 71743c2aeb0SSepherosa Ziehau */ 71843c2aeb0SSepherosa Ziehau val = REG_RD_IND(sc, BCE_SHM_HDR_SIGNATURE); 719d0092544SSepherosa Ziehau if ((val & BCE_SHM_HDR_SIGNATURE_SIG_MASK) == 720d0092544SSepherosa Ziehau BCE_SHM_HDR_SIGNATURE_SIG) { 721d0092544SSepherosa Ziehau /* Multi-port devices use different offsets in shared memory. */ 722d0092544SSepherosa Ziehau sc->bce_shmem_base = REG_RD_IND(sc, 723d0092544SSepherosa Ziehau BCE_SHM_HDR_ADDR_0 + (pci_get_function(sc->bce_dev) << 2)); 724d0092544SSepherosa Ziehau } else { 72543c2aeb0SSepherosa Ziehau sc->bce_shmem_base = HOST_VIEW_SHMEM_BASE; 726d0092544SSepherosa Ziehau } 72743c2aeb0SSepherosa Ziehau 728d0092544SSepherosa Ziehau /* Fetch the bootcode revision. */ 729bc30d40dSSepherosa Ziehau val = bce_shmem_rd(sc, BCE_DEV_INFO_BC_REV); 730bc30d40dSSepherosa Ziehau for (i = 0, j = 0; i < 3; i++) { 731bc30d40dSSepherosa Ziehau uint8_t num; 732bc30d40dSSepherosa Ziehau int k, skip0; 733d0092544SSepherosa Ziehau 734bc30d40dSSepherosa Ziehau num = (uint8_t)(val >> (24 - (i * 8))); 735bc30d40dSSepherosa Ziehau for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) { 736bc30d40dSSepherosa Ziehau if (num >= k || !skip0 || k == 1) { 737bc30d40dSSepherosa Ziehau sc->bce_bc_ver[j++] = (num / k) + '0'; 738bc30d40dSSepherosa Ziehau skip0 = 0; 739bc30d40dSSepherosa Ziehau } 740bc30d40dSSepherosa Ziehau } 741bc30d40dSSepherosa Ziehau if (i != 2) 742bc30d40dSSepherosa Ziehau sc->bce_bc_ver[j++] = '.'; 743bc30d40dSSepherosa Ziehau } 744bc30d40dSSepherosa Ziehau 745bc30d40dSSepherosa Ziehau /* Check if any management firwmare is running. */ 746bc30d40dSSepherosa Ziehau val = bce_shmem_rd(sc, BCE_PORT_FEATURE); 747bc30d40dSSepherosa Ziehau if (val & BCE_PORT_FEATURE_ASF_ENABLED) { 748d0092544SSepherosa Ziehau sc->bce_flags |= BCE_MFW_ENABLE_FLAG; 749d0092544SSepherosa Ziehau 750bc30d40dSSepherosa Ziehau /* Allow time for firmware to enter the running state. */ 751bc30d40dSSepherosa Ziehau for (i = 0; i < 30; i++) { 752bc30d40dSSepherosa Ziehau val = bce_shmem_rd(sc, BCE_BC_STATE_CONDITION); 753bc30d40dSSepherosa Ziehau if (val & BCE_CONDITION_MFW_RUN_MASK) 754bc30d40dSSepherosa Ziehau break; 755bc30d40dSSepherosa Ziehau DELAY(10000); 756bc30d40dSSepherosa Ziehau } 757bc30d40dSSepherosa Ziehau } 758bc30d40dSSepherosa Ziehau 759bc30d40dSSepherosa Ziehau /* Check the current bootcode state. */ 760bc30d40dSSepherosa Ziehau val = bce_shmem_rd(sc, BCE_BC_STATE_CONDITION) & 761bc30d40dSSepherosa Ziehau BCE_CONDITION_MFW_RUN_MASK; 762bc30d40dSSepherosa Ziehau if (val != BCE_CONDITION_MFW_RUN_UNKNOWN && 763bc30d40dSSepherosa Ziehau val != BCE_CONDITION_MFW_RUN_NONE) { 764bc30d40dSSepherosa Ziehau uint32_t addr = bce_shmem_rd(sc, BCE_MFW_VER_PTR); 765bc30d40dSSepherosa Ziehau 766bc30d40dSSepherosa Ziehau for (i = 0, j = 0; j < 3; j++) { 767bc30d40dSSepherosa Ziehau val = bce_reg_rd_ind(sc, addr + j * 4); 768bc30d40dSSepherosa Ziehau val = bswap32(val); 769bc30d40dSSepherosa Ziehau memcpy(&sc->bce_mfw_ver[i], &val, 4); 770bc30d40dSSepherosa Ziehau i += 4; 771bc30d40dSSepherosa Ziehau } 772bc30d40dSSepherosa Ziehau } 773bc30d40dSSepherosa Ziehau 77443c2aeb0SSepherosa Ziehau /* Get PCI bus information (speed and type). */ 77543c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_PCICFG_MISC_STATUS); 77643c2aeb0SSepherosa Ziehau if (val & BCE_PCICFG_MISC_STATUS_PCIX_DET) { 77743c2aeb0SSepherosa Ziehau uint32_t clkreg; 77843c2aeb0SSepherosa Ziehau 77943c2aeb0SSepherosa Ziehau sc->bce_flags |= BCE_PCIX_FLAG; 78043c2aeb0SSepherosa Ziehau 78143c2aeb0SSepherosa Ziehau clkreg = REG_RD(sc, BCE_PCICFG_PCI_CLOCK_CONTROL_BITS) & 78243c2aeb0SSepherosa Ziehau BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; 78343c2aeb0SSepherosa Ziehau switch (clkreg) { 78443c2aeb0SSepherosa Ziehau case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ: 78543c2aeb0SSepherosa Ziehau sc->bus_speed_mhz = 133; 78643c2aeb0SSepherosa Ziehau break; 78743c2aeb0SSepherosa Ziehau 78843c2aeb0SSepherosa Ziehau case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ: 78943c2aeb0SSepherosa Ziehau sc->bus_speed_mhz = 100; 79043c2aeb0SSepherosa Ziehau break; 79143c2aeb0SSepherosa Ziehau 79243c2aeb0SSepherosa Ziehau case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ: 79343c2aeb0SSepherosa Ziehau case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ: 79443c2aeb0SSepherosa Ziehau sc->bus_speed_mhz = 66; 79543c2aeb0SSepherosa Ziehau break; 79643c2aeb0SSepherosa Ziehau 79743c2aeb0SSepherosa Ziehau case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ: 79843c2aeb0SSepherosa Ziehau case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ: 79943c2aeb0SSepherosa Ziehau sc->bus_speed_mhz = 50; 80043c2aeb0SSepherosa Ziehau break; 80143c2aeb0SSepherosa Ziehau 80243c2aeb0SSepherosa Ziehau case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW: 80343c2aeb0SSepherosa Ziehau case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ: 80443c2aeb0SSepherosa Ziehau case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ: 80543c2aeb0SSepherosa Ziehau sc->bus_speed_mhz = 33; 80643c2aeb0SSepherosa Ziehau break; 80743c2aeb0SSepherosa Ziehau } 80843c2aeb0SSepherosa Ziehau } else { 80943c2aeb0SSepherosa Ziehau if (val & BCE_PCICFG_MISC_STATUS_M66EN) 81043c2aeb0SSepherosa Ziehau sc->bus_speed_mhz = 66; 81143c2aeb0SSepherosa Ziehau else 81243c2aeb0SSepherosa Ziehau sc->bus_speed_mhz = 33; 81343c2aeb0SSepherosa Ziehau } 81443c2aeb0SSepherosa Ziehau 81543c2aeb0SSepherosa Ziehau if (val & BCE_PCICFG_MISC_STATUS_32BIT_DET) 81643c2aeb0SSepherosa Ziehau sc->bce_flags |= BCE_PCI_32BIT_FLAG; 81743c2aeb0SSepherosa Ziehau 81843c2aeb0SSepherosa Ziehau /* Reset the controller. */ 81943c2aeb0SSepherosa Ziehau rc = bce_reset(sc, BCE_DRV_MSG_CODE_RESET); 82043c2aeb0SSepherosa Ziehau if (rc != 0) 82143c2aeb0SSepherosa Ziehau goto fail; 82243c2aeb0SSepherosa Ziehau 82343c2aeb0SSepherosa Ziehau /* Initialize the controller. */ 82443c2aeb0SSepherosa Ziehau rc = bce_chipinit(sc); 82543c2aeb0SSepherosa Ziehau if (rc != 0) { 82643c2aeb0SSepherosa Ziehau device_printf(dev, "Controller initialization failed!\n"); 82743c2aeb0SSepherosa Ziehau goto fail; 82843c2aeb0SSepherosa Ziehau } 82943c2aeb0SSepherosa Ziehau 83043c2aeb0SSepherosa Ziehau /* Perform NVRAM test. */ 83143c2aeb0SSepherosa Ziehau rc = bce_nvram_test(sc); 83243c2aeb0SSepherosa Ziehau if (rc != 0) { 83343c2aeb0SSepherosa Ziehau device_printf(dev, "NVRAM test failed!\n"); 83443c2aeb0SSepherosa Ziehau goto fail; 83543c2aeb0SSepherosa Ziehau } 83643c2aeb0SSepherosa Ziehau 83743c2aeb0SSepherosa Ziehau /* Fetch the permanent Ethernet MAC address. */ 83843c2aeb0SSepherosa Ziehau bce_get_mac_addr(sc); 83943c2aeb0SSepherosa Ziehau 84043c2aeb0SSepherosa Ziehau /* 84143c2aeb0SSepherosa Ziehau * Trip points control how many BDs 84243c2aeb0SSepherosa Ziehau * should be ready before generating an 84343c2aeb0SSepherosa Ziehau * interrupt while ticks control how long 84443c2aeb0SSepherosa Ziehau * a BD can sit in the chain before 84543c2aeb0SSepherosa Ziehau * generating an interrupt. Set the default 84643c2aeb0SSepherosa Ziehau * values for the RX and TX rings. 84743c2aeb0SSepherosa Ziehau */ 84843c2aeb0SSepherosa Ziehau 84943c2aeb0SSepherosa Ziehau #ifdef BCE_DRBUG 85043c2aeb0SSepherosa Ziehau /* Force more frequent interrupts. */ 85143c2aeb0SSepherosa Ziehau sc->bce_tx_quick_cons_trip_int = 1; 85243c2aeb0SSepherosa Ziehau sc->bce_tx_quick_cons_trip = 1; 85343c2aeb0SSepherosa Ziehau sc->bce_tx_ticks_int = 0; 85443c2aeb0SSepherosa Ziehau sc->bce_tx_ticks = 0; 85543c2aeb0SSepherosa Ziehau 85643c2aeb0SSepherosa Ziehau sc->bce_rx_quick_cons_trip_int = 1; 85743c2aeb0SSepherosa Ziehau sc->bce_rx_quick_cons_trip = 1; 85843c2aeb0SSepherosa Ziehau sc->bce_rx_ticks_int = 0; 85943c2aeb0SSepherosa Ziehau sc->bce_rx_ticks = 0; 86043c2aeb0SSepherosa Ziehau #else 861bdeb8fffSSepherosa Ziehau sc->bce_tx_quick_cons_trip_int = bce_tx_bds_int; 862bdeb8fffSSepherosa Ziehau sc->bce_tx_quick_cons_trip = bce_tx_bds; 863bdeb8fffSSepherosa Ziehau sc->bce_tx_ticks_int = bce_tx_ticks_int; 864bdeb8fffSSepherosa Ziehau sc->bce_tx_ticks = bce_tx_ticks; 86543c2aeb0SSepherosa Ziehau 866bdeb8fffSSepherosa Ziehau sc->bce_rx_quick_cons_trip_int = bce_rx_bds_int; 867bdeb8fffSSepherosa Ziehau sc->bce_rx_quick_cons_trip = bce_rx_bds; 868bdeb8fffSSepherosa Ziehau sc->bce_rx_ticks_int = bce_rx_ticks_int; 869bdeb8fffSSepherosa Ziehau sc->bce_rx_ticks = bce_rx_ticks; 87043c2aeb0SSepherosa Ziehau #endif 87143c2aeb0SSepherosa Ziehau 87243c2aeb0SSepherosa Ziehau /* Update statistics once every second. */ 87343c2aeb0SSepherosa Ziehau sc->bce_stats_ticks = 1000000 & 0xffff00; 87443c2aeb0SSepherosa Ziehau 875d0092544SSepherosa Ziehau /* Find the media type for the adapter. */ 876d0092544SSepherosa Ziehau bce_get_media(sc); 87743c2aeb0SSepherosa Ziehau 87810bcbdabSSepherosa Ziehau /* Find out RX/TX ring count */ 87910bcbdabSSepherosa Ziehau sc->ring_cnt = 1; /* XXX */ 88010bcbdabSSepherosa Ziehau 88143c2aeb0SSepherosa Ziehau /* Allocate DMA memory resources. */ 88243c2aeb0SSepherosa Ziehau rc = bce_dma_alloc(sc); 88343c2aeb0SSepherosa Ziehau if (rc != 0) { 88443c2aeb0SSepherosa Ziehau device_printf(dev, "DMA resource allocation failed!\n"); 88543c2aeb0SSepherosa Ziehau goto fail; 88643c2aeb0SSepherosa Ziehau } 88743c2aeb0SSepherosa Ziehau 88857b3ecd9SSepherosa Ziehau #ifdef IFPOLL_ENABLE 88957b3ecd9SSepherosa Ziehau /* 89057b3ecd9SSepherosa Ziehau * NPOLLING RX/TX CPU offset 89157b3ecd9SSepherosa Ziehau */ 89257b3ecd9SSepherosa Ziehau if (sc->ring_cnt == ncpus2) { 89357b3ecd9SSepherosa Ziehau offset = 0; 89457b3ecd9SSepherosa Ziehau } else { 89557b3ecd9SSepherosa Ziehau offset_def = (sc->ring_cnt * device_get_unit(dev)) % ncpus2; 89657b3ecd9SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.offset", offset_def); 89757b3ecd9SSepherosa Ziehau if (offset >= ncpus2 || 89857b3ecd9SSepherosa Ziehau offset % sc->ring_cnt != 0) { 89957b3ecd9SSepherosa Ziehau device_printf(dev, "invalid npoll.offset %d, use %d\n", 90057b3ecd9SSepherosa Ziehau offset, offset_def); 90157b3ecd9SSepherosa Ziehau offset = offset_def; 90257b3ecd9SSepherosa Ziehau } 90357b3ecd9SSepherosa Ziehau } 90457b3ecd9SSepherosa Ziehau sc->npoll_ofs = offset; 90557b3ecd9SSepherosa Ziehau #endif 90657b3ecd9SSepherosa Ziehau 907ff36bdc4SSepherosa Ziehau /* Allocate PCI IRQ resources. */ 908ff36bdc4SSepherosa Ziehau sc->bce_irq_type = pci_alloc_1intr(dev, bce_msi_enable, 909ff36bdc4SSepherosa Ziehau &sc->bce_irq_rid, &irq_flags); 910ff36bdc4SSepherosa Ziehau 911ff36bdc4SSepherosa Ziehau sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 912ff36bdc4SSepherosa Ziehau &sc->bce_irq_rid, irq_flags); 913ff36bdc4SSepherosa Ziehau if (sc->bce_res_irq == NULL) { 914ff36bdc4SSepherosa Ziehau device_printf(dev, "PCI map interrupt failed\n"); 915ff36bdc4SSepherosa Ziehau rc = ENXIO; 916ff36bdc4SSepherosa Ziehau goto fail; 917ff36bdc4SSepherosa Ziehau } 918ff36bdc4SSepherosa Ziehau 919ff36bdc4SSepherosa Ziehau if (sc->bce_irq_type == PCI_INTR_TYPE_LEGACY) { 920ff36bdc4SSepherosa Ziehau irq_handle = bce_intr_legacy; 921ff36bdc4SSepherosa Ziehau } else if (sc->bce_irq_type == PCI_INTR_TYPE_MSI) { 922ff36bdc4SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) { 923ff36bdc4SSepherosa Ziehau irq_handle = bce_intr_msi_oneshot; 924ff36bdc4SSepherosa Ziehau sc->bce_flags |= BCE_ONESHOT_MSI_FLAG; 925ff36bdc4SSepherosa Ziehau } else { 926ff36bdc4SSepherosa Ziehau irq_handle = bce_intr_msi; 927ff36bdc4SSepherosa Ziehau sc->bce_flags |= BCE_CHECK_MSI_FLAG; 928ff36bdc4SSepherosa Ziehau } 929ff36bdc4SSepherosa Ziehau } else { 930ff36bdc4SSepherosa Ziehau panic("%s: unsupported intr type %d", 931ff36bdc4SSepherosa Ziehau device_get_nameunit(dev), sc->bce_irq_type); 932ff36bdc4SSepherosa Ziehau } 933ff36bdc4SSepherosa Ziehau 93484464af5SSepherosa Ziehau /* Setup serializer */ 93584464af5SSepherosa Ziehau bce_setup_serialize(sc); 93684464af5SSepherosa Ziehau 93743c2aeb0SSepherosa Ziehau /* Initialize the ifnet interface. */ 93843c2aeb0SSepherosa Ziehau ifp->if_softc = sc; 93943c2aeb0SSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 94043c2aeb0SSepherosa Ziehau ifp->if_ioctl = bce_ioctl; 94143c2aeb0SSepherosa Ziehau ifp->if_start = bce_start; 94243c2aeb0SSepherosa Ziehau ifp->if_init = bce_init; 94343c2aeb0SSepherosa Ziehau ifp->if_watchdog = bce_watchdog; 94484464af5SSepherosa Ziehau ifp->if_serialize = bce_serialize; 94584464af5SSepherosa Ziehau ifp->if_deserialize = bce_deserialize; 94684464af5SSepherosa Ziehau ifp->if_tryserialize = bce_tryserialize; 94784464af5SSepherosa Ziehau #ifdef INVARIANTS 94884464af5SSepherosa Ziehau ifp->if_serialize_assert = bce_serialize_assert; 94984464af5SSepherosa Ziehau #endif 9504a331bf7SSepherosa Ziehau #ifdef IFPOLL_ENABLE 9514a331bf7SSepherosa Ziehau ifp->if_npoll = bce_npoll; 95243c2aeb0SSepherosa Ziehau #endif 95384464af5SSepherosa Ziehau 95443c2aeb0SSepherosa Ziehau ifp->if_mtu = ETHERMTU; 955eefd160dSSepherosa Ziehau ifp->if_hwassist = BCE_CSUM_FEATURES | CSUM_TSO; 95643c2aeb0SSepherosa Ziehau ifp->if_capabilities = BCE_IF_CAPABILITIES; 95743c2aeb0SSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 95843c2aeb0SSepherosa Ziehau 95943c2aeb0SSepherosa Ziehau if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) 96043c2aeb0SSepherosa Ziehau ifp->if_baudrate = IF_Gbps(2.5); 96143c2aeb0SSepherosa Ziehau else 96243c2aeb0SSepherosa Ziehau ifp->if_baudrate = IF_Gbps(1); 96343c2aeb0SSepherosa Ziehau 96484464af5SSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, USABLE_TX_BD(&sc->tx_rings[0])); 96584464af5SSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 96684464af5SSepherosa Ziehau 967f31c6e4dSSepherosa Ziehau /* 968f31c6e4dSSepherosa Ziehau * Look for our PHY. 969f31c6e4dSSepherosa Ziehau */ 970f31c6e4dSSepherosa Ziehau mii_probe_args_init(&mii_args, bce_ifmedia_upd, bce_ifmedia_sts); 971f31c6e4dSSepherosa Ziehau mii_args.mii_probemask = 1 << sc->bce_phy_addr; 972f31c6e4dSSepherosa Ziehau mii_args.mii_privtag = MII_PRIVTAG_BRGPHY; 973f31c6e4dSSepherosa Ziehau mii_args.mii_priv = mii_priv; 974f31c6e4dSSepherosa Ziehau 975f31c6e4dSSepherosa Ziehau rc = mii_probe(dev, &sc->bce_miibus, &mii_args); 97643c2aeb0SSepherosa Ziehau if (rc != 0) { 97743c2aeb0SSepherosa Ziehau device_printf(dev, "PHY probe failed!\n"); 97843c2aeb0SSepherosa Ziehau goto fail; 97943c2aeb0SSepherosa Ziehau } 98043c2aeb0SSepherosa Ziehau 98143c2aeb0SSepherosa Ziehau /* Attach to the Ethernet interface list. */ 98243c2aeb0SSepherosa Ziehau ether_ifattach(ifp, sc->eaddr, NULL); 98343c2aeb0SSepherosa Ziehau 9846ac77363SSepherosa Ziehau callout_init_mp(&sc->bce_tick_callout); 9856ac77363SSepherosa Ziehau callout_init_mp(&sc->bce_pulse_callout); 98628ef7645SSepherosa Ziehau callout_init_mp(&sc->bce_ckmsi_callout); 98743c2aeb0SSepherosa Ziehau 98843c2aeb0SSepherosa Ziehau /* Hookup IRQ last. */ 989eac57ffbSSepherosa Ziehau rc = bus_setup_intr(dev, sc->bce_res_irq, INTR_MPSAFE, irq_handle, sc, 99084464af5SSepherosa Ziehau &sc->bce_intrhand, &sc->main_serialize); 99143c2aeb0SSepherosa Ziehau if (rc != 0) { 99243c2aeb0SSepherosa Ziehau device_printf(dev, "Failed to setup IRQ!\n"); 99343c2aeb0SSepherosa Ziehau ether_ifdetach(ifp); 99443c2aeb0SSepherosa Ziehau goto fail; 99543c2aeb0SSepherosa Ziehau } 99643c2aeb0SSepherosa Ziehau 997dfd3b18bSSepherosa Ziehau sc->bce_intr_cpuid = rman_get_cpuid(sc->bce_res_irq); 998dfd3b18bSSepherosa Ziehau ifq_set_cpuid(&ifp->if_snd, sc->bce_intr_cpuid); 9999db4b353SSepherosa Ziehau 100043c2aeb0SSepherosa Ziehau /* Add the supported sysctls to the kernel. */ 100143c2aeb0SSepherosa Ziehau bce_add_sysctls(sc); 100243c2aeb0SSepherosa Ziehau 1003d0092544SSepherosa Ziehau /* 1004d0092544SSepherosa Ziehau * The chip reset earlier notified the bootcode that 1005d0092544SSepherosa Ziehau * a driver is present. We now need to start our pulse 1006d0092544SSepherosa Ziehau * routine so that the bootcode is reminded that we're 1007d0092544SSepherosa Ziehau * still running. 1008d0092544SSepherosa Ziehau */ 1009d0092544SSepherosa Ziehau bce_pulse(sc); 1010d0092544SSepherosa Ziehau 101143c2aeb0SSepherosa Ziehau /* Get the firmware running so IPMI still works */ 101243c2aeb0SSepherosa Ziehau bce_mgmt_init(sc); 101343c2aeb0SSepherosa Ziehau 1014b51a4d98SSepherosa Ziehau if (bootverbose) 1015d0092544SSepherosa Ziehau bce_print_adapter_info(sc); 1016d0092544SSepherosa Ziehau 101743c2aeb0SSepherosa Ziehau return 0; 101843c2aeb0SSepherosa Ziehau fail: 101943c2aeb0SSepherosa Ziehau bce_detach(dev); 102043c2aeb0SSepherosa Ziehau return(rc); 102143c2aeb0SSepherosa Ziehau } 102243c2aeb0SSepherosa Ziehau 102343c2aeb0SSepherosa Ziehau 102443c2aeb0SSepherosa Ziehau /****************************************************************************/ 102543c2aeb0SSepherosa Ziehau /* Device detach function. */ 102643c2aeb0SSepherosa Ziehau /* */ 102743c2aeb0SSepherosa Ziehau /* Stops the controller, resets the controller, and releases resources. */ 102843c2aeb0SSepherosa Ziehau /* */ 102943c2aeb0SSepherosa Ziehau /* Returns: */ 103043c2aeb0SSepherosa Ziehau /* 0 on success, positive value on failure. */ 103143c2aeb0SSepherosa Ziehau /****************************************************************************/ 103243c2aeb0SSepherosa Ziehau static int 103343c2aeb0SSepherosa Ziehau bce_detach(device_t dev) 103443c2aeb0SSepherosa Ziehau { 103543c2aeb0SSepherosa Ziehau struct bce_softc *sc = device_get_softc(dev); 103643c2aeb0SSepherosa Ziehau 103743c2aeb0SSepherosa Ziehau if (device_is_attached(dev)) { 103843c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1039d0092544SSepherosa Ziehau uint32_t msg; 104043c2aeb0SSepherosa Ziehau 104184464af5SSepherosa Ziehau ifnet_serialize_all(ifp); 104284464af5SSepherosa Ziehau 104343c2aeb0SSepherosa Ziehau /* Stop and reset the controller. */ 1044d0092544SSepherosa Ziehau callout_stop(&sc->bce_pulse_callout); 104543c2aeb0SSepherosa Ziehau bce_stop(sc); 1046d0092544SSepherosa Ziehau if (sc->bce_flags & BCE_NO_WOL_FLAG) 1047d0092544SSepherosa Ziehau msg = BCE_DRV_MSG_CODE_UNLOAD_LNK_DN; 1048d0092544SSepherosa Ziehau else 1049d0092544SSepherosa Ziehau msg = BCE_DRV_MSG_CODE_UNLOAD; 1050d0092544SSepherosa Ziehau bce_reset(sc, msg); 105143c2aeb0SSepherosa Ziehau bus_teardown_intr(dev, sc->bce_res_irq, sc->bce_intrhand); 105284464af5SSepherosa Ziehau 105384464af5SSepherosa Ziehau ifnet_deserialize_all(ifp); 105443c2aeb0SSepherosa Ziehau 105543c2aeb0SSepherosa Ziehau ether_ifdetach(ifp); 105643c2aeb0SSepherosa Ziehau } 105743c2aeb0SSepherosa Ziehau 105843c2aeb0SSepherosa Ziehau /* If we have a child device on the MII bus remove it too. */ 105943c2aeb0SSepherosa Ziehau if (sc->bce_miibus) 106043c2aeb0SSepherosa Ziehau device_delete_child(dev, sc->bce_miibus); 106143c2aeb0SSepherosa Ziehau bus_generic_detach(dev); 106243c2aeb0SSepherosa Ziehau 106343c2aeb0SSepherosa Ziehau if (sc->bce_res_irq != NULL) { 106483ce3dceSSepherosa Ziehau bus_release_resource(dev, SYS_RES_IRQ, sc->bce_irq_rid, 106543c2aeb0SSepherosa Ziehau sc->bce_res_irq); 106643c2aeb0SSepherosa Ziehau } 106743c2aeb0SSepherosa Ziehau 10687fb43956SSepherosa Ziehau if (sc->bce_irq_type == PCI_INTR_TYPE_MSI) 106943c2aeb0SSepherosa Ziehau pci_release_msi(dev); 107043c2aeb0SSepherosa Ziehau 107143c2aeb0SSepherosa Ziehau if (sc->bce_res_mem != NULL) { 107243c2aeb0SSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), 107343c2aeb0SSepherosa Ziehau sc->bce_res_mem); 107443c2aeb0SSepherosa Ziehau } 107543c2aeb0SSepherosa Ziehau 107643c2aeb0SSepherosa Ziehau bce_dma_free(sc); 107743c2aeb0SSepherosa Ziehau 107843c2aeb0SSepherosa Ziehau if (sc->bce_sysctl_tree != NULL) 107943c2aeb0SSepherosa Ziehau sysctl_ctx_free(&sc->bce_sysctl_ctx); 108043c2aeb0SSepherosa Ziehau 108143c2aeb0SSepherosa Ziehau return 0; 108243c2aeb0SSepherosa Ziehau } 108343c2aeb0SSepherosa Ziehau 108443c2aeb0SSepherosa Ziehau 108543c2aeb0SSepherosa Ziehau /****************************************************************************/ 108643c2aeb0SSepherosa Ziehau /* Device shutdown function. */ 108743c2aeb0SSepherosa Ziehau /* */ 108843c2aeb0SSepherosa Ziehau /* Stops and resets the controller. */ 108943c2aeb0SSepherosa Ziehau /* */ 109043c2aeb0SSepherosa Ziehau /* Returns: */ 109143c2aeb0SSepherosa Ziehau /* Nothing */ 109243c2aeb0SSepherosa Ziehau /****************************************************************************/ 109343c2aeb0SSepherosa Ziehau static void 109443c2aeb0SSepherosa Ziehau bce_shutdown(device_t dev) 109543c2aeb0SSepherosa Ziehau { 109643c2aeb0SSepherosa Ziehau struct bce_softc *sc = device_get_softc(dev); 109743c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1098d0092544SSepherosa Ziehau uint32_t msg; 109943c2aeb0SSepherosa Ziehau 110084464af5SSepherosa Ziehau ifnet_serialize_all(ifp); 110184464af5SSepherosa Ziehau 110243c2aeb0SSepherosa Ziehau bce_stop(sc); 1103d0092544SSepherosa Ziehau if (sc->bce_flags & BCE_NO_WOL_FLAG) 1104d0092544SSepherosa Ziehau msg = BCE_DRV_MSG_CODE_UNLOAD_LNK_DN; 1105d0092544SSepherosa Ziehau else 1106d0092544SSepherosa Ziehau msg = BCE_DRV_MSG_CODE_UNLOAD; 1107d0092544SSepherosa Ziehau bce_reset(sc, msg); 110884464af5SSepherosa Ziehau 110984464af5SSepherosa Ziehau ifnet_deserialize_all(ifp); 111043c2aeb0SSepherosa Ziehau } 111143c2aeb0SSepherosa Ziehau 111243c2aeb0SSepherosa Ziehau 111343c2aeb0SSepherosa Ziehau /****************************************************************************/ 111443c2aeb0SSepherosa Ziehau /* Indirect register read. */ 111543c2aeb0SSepherosa Ziehau /* */ 111643c2aeb0SSepherosa Ziehau /* Reads NetXtreme II registers using an index/data register pair in PCI */ 111743c2aeb0SSepherosa Ziehau /* configuration space. Using this mechanism avoids issues with posted */ 111843c2aeb0SSepherosa Ziehau /* reads but is much slower than memory-mapped I/O. */ 111943c2aeb0SSepherosa Ziehau /* */ 112043c2aeb0SSepherosa Ziehau /* Returns: */ 112143c2aeb0SSepherosa Ziehau /* The value of the register. */ 112243c2aeb0SSepherosa Ziehau /****************************************************************************/ 112343c2aeb0SSepherosa Ziehau static uint32_t 112443c2aeb0SSepherosa Ziehau bce_reg_rd_ind(struct bce_softc *sc, uint32_t offset) 112543c2aeb0SSepherosa Ziehau { 112643c2aeb0SSepherosa Ziehau device_t dev = sc->bce_dev; 112743c2aeb0SSepherosa Ziehau 112843c2aeb0SSepherosa Ziehau pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4); 112943c2aeb0SSepherosa Ziehau return pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4); 113043c2aeb0SSepherosa Ziehau } 113143c2aeb0SSepherosa Ziehau 113243c2aeb0SSepherosa Ziehau 113343c2aeb0SSepherosa Ziehau /****************************************************************************/ 113443c2aeb0SSepherosa Ziehau /* Indirect register write. */ 113543c2aeb0SSepherosa Ziehau /* */ 113643c2aeb0SSepherosa Ziehau /* Writes NetXtreme II registers using an index/data register pair in PCI */ 113743c2aeb0SSepherosa Ziehau /* configuration space. Using this mechanism avoids issues with posted */ 113843c2aeb0SSepherosa Ziehau /* writes but is muchh slower than memory-mapped I/O. */ 113943c2aeb0SSepherosa Ziehau /* */ 114043c2aeb0SSepherosa Ziehau /* Returns: */ 114143c2aeb0SSepherosa Ziehau /* Nothing. */ 114243c2aeb0SSepherosa Ziehau /****************************************************************************/ 114343c2aeb0SSepherosa Ziehau static void 114443c2aeb0SSepherosa Ziehau bce_reg_wr_ind(struct bce_softc *sc, uint32_t offset, uint32_t val) 114543c2aeb0SSepherosa Ziehau { 114643c2aeb0SSepherosa Ziehau device_t dev = sc->bce_dev; 114743c2aeb0SSepherosa Ziehau 114843c2aeb0SSepherosa Ziehau pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4); 114943c2aeb0SSepherosa Ziehau pci_write_config(dev, BCE_PCICFG_REG_WINDOW, val, 4); 115043c2aeb0SSepherosa Ziehau } 115143c2aeb0SSepherosa Ziehau 115243c2aeb0SSepherosa Ziehau 115343c2aeb0SSepherosa Ziehau /****************************************************************************/ 1154bc30d40dSSepherosa Ziehau /* Shared memory write. */ 1155bc30d40dSSepherosa Ziehau /* */ 1156bc30d40dSSepherosa Ziehau /* Writes NetXtreme II shared memory region. */ 1157bc30d40dSSepherosa Ziehau /* */ 1158bc30d40dSSepherosa Ziehau /* Returns: */ 1159bc30d40dSSepherosa Ziehau /* Nothing. */ 1160bc30d40dSSepherosa Ziehau /****************************************************************************/ 1161bc30d40dSSepherosa Ziehau static void 1162bc30d40dSSepherosa Ziehau bce_shmem_wr(struct bce_softc *sc, uint32_t offset, uint32_t val) 1163bc30d40dSSepherosa Ziehau { 1164bc30d40dSSepherosa Ziehau bce_reg_wr_ind(sc, sc->bce_shmem_base + offset, val); 1165bc30d40dSSepherosa Ziehau } 1166bc30d40dSSepherosa Ziehau 1167bc30d40dSSepherosa Ziehau 1168bc30d40dSSepherosa Ziehau /****************************************************************************/ 1169bc30d40dSSepherosa Ziehau /* Shared memory read. */ 1170bc30d40dSSepherosa Ziehau /* */ 1171bc30d40dSSepherosa Ziehau /* Reads NetXtreme II shared memory region. */ 1172bc30d40dSSepherosa Ziehau /* */ 1173bc30d40dSSepherosa Ziehau /* Returns: */ 1174bc30d40dSSepherosa Ziehau /* The 32 bit value read. */ 1175bc30d40dSSepherosa Ziehau /****************************************************************************/ 1176bc30d40dSSepherosa Ziehau static u32 1177bc30d40dSSepherosa Ziehau bce_shmem_rd(struct bce_softc *sc, uint32_t offset) 1178bc30d40dSSepherosa Ziehau { 1179bc30d40dSSepherosa Ziehau return bce_reg_rd_ind(sc, sc->bce_shmem_base + offset); 1180bc30d40dSSepherosa Ziehau } 1181bc30d40dSSepherosa Ziehau 1182bc30d40dSSepherosa Ziehau 1183bc30d40dSSepherosa Ziehau /****************************************************************************/ 118443c2aeb0SSepherosa Ziehau /* Context memory write. */ 118543c2aeb0SSepherosa Ziehau /* */ 118643c2aeb0SSepherosa Ziehau /* The NetXtreme II controller uses context memory to track connection */ 118743c2aeb0SSepherosa Ziehau /* information for L2 and higher network protocols. */ 118843c2aeb0SSepherosa Ziehau /* */ 118943c2aeb0SSepherosa Ziehau /* Returns: */ 119043c2aeb0SSepherosa Ziehau /* Nothing. */ 119143c2aeb0SSepherosa Ziehau /****************************************************************************/ 119243c2aeb0SSepherosa Ziehau static void 1193d0092544SSepherosa Ziehau bce_ctx_wr(struct bce_softc *sc, uint32_t cid_addr, uint32_t ctx_offset, 1194d0092544SSepherosa Ziehau uint32_t ctx_val) 119543c2aeb0SSepherosa Ziehau { 1196d0092544SSepherosa Ziehau uint32_t idx, offset = ctx_offset + cid_addr; 1197d0092544SSepherosa Ziehau uint32_t val, retry_cnt = 5; 119843c2aeb0SSepherosa Ziehau 1199d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 1200d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 1201d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_CTX_DATA, ctx_val); 1202d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_CTX_CTRL, (offset | BCE_CTX_CTX_CTRL_WRITE_REQ)); 1203d0092544SSepherosa Ziehau 1204d0092544SSepherosa Ziehau for (idx = 0; idx < retry_cnt; idx++) { 1205d0092544SSepherosa Ziehau val = REG_RD(sc, BCE_CTX_CTX_CTRL); 1206d0092544SSepherosa Ziehau if ((val & BCE_CTX_CTX_CTRL_WRITE_REQ) == 0) 1207d0092544SSepherosa Ziehau break; 1208d0092544SSepherosa Ziehau DELAY(5); 1209d0092544SSepherosa Ziehau } 1210d0092544SSepherosa Ziehau 1211d0092544SSepherosa Ziehau if (val & BCE_CTX_CTX_CTRL_WRITE_REQ) { 1212d0092544SSepherosa Ziehau device_printf(sc->bce_dev, 1213d0092544SSepherosa Ziehau "Unable to write CTX memory: " 1214d0092544SSepherosa Ziehau "cid_addr = 0x%08X, offset = 0x%08X!\n", 1215d0092544SSepherosa Ziehau cid_addr, ctx_offset); 1216d0092544SSepherosa Ziehau } 1217d0092544SSepherosa Ziehau } else { 121843c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_CTX_DATA_ADR, offset); 1219d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_DATA, ctx_val); 1220d0092544SSepherosa Ziehau } 122143c2aeb0SSepherosa Ziehau } 122243c2aeb0SSepherosa Ziehau 122343c2aeb0SSepherosa Ziehau 122443c2aeb0SSepherosa Ziehau /****************************************************************************/ 122543c2aeb0SSepherosa Ziehau /* PHY register read. */ 122643c2aeb0SSepherosa Ziehau /* */ 122743c2aeb0SSepherosa Ziehau /* Implements register reads on the MII bus. */ 122843c2aeb0SSepherosa Ziehau /* */ 122943c2aeb0SSepherosa Ziehau /* Returns: */ 123043c2aeb0SSepherosa Ziehau /* The value of the register. */ 123143c2aeb0SSepherosa Ziehau /****************************************************************************/ 123243c2aeb0SSepherosa Ziehau static int 123343c2aeb0SSepherosa Ziehau bce_miibus_read_reg(device_t dev, int phy, int reg) 123443c2aeb0SSepherosa Ziehau { 123543c2aeb0SSepherosa Ziehau struct bce_softc *sc = device_get_softc(dev); 123643c2aeb0SSepherosa Ziehau uint32_t val; 123743c2aeb0SSepherosa Ziehau int i; 123843c2aeb0SSepherosa Ziehau 123943c2aeb0SSepherosa Ziehau /* Make sure we are accessing the correct PHY address. */ 1240f31c6e4dSSepherosa Ziehau KASSERT(phy == sc->bce_phy_addr, 1241f31c6e4dSSepherosa Ziehau ("invalid phyno %d, should be %d\n", phy, sc->bce_phy_addr)); 124243c2aeb0SSepherosa Ziehau 124343c2aeb0SSepherosa Ziehau if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) { 124443c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_EMAC_MDIO_MODE); 124543c2aeb0SSepherosa Ziehau val &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL; 124643c2aeb0SSepherosa Ziehau 124743c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MDIO_MODE, val); 124843c2aeb0SSepherosa Ziehau REG_RD(sc, BCE_EMAC_MDIO_MODE); 124943c2aeb0SSepherosa Ziehau 125043c2aeb0SSepherosa Ziehau DELAY(40); 125143c2aeb0SSepherosa Ziehau } 125243c2aeb0SSepherosa Ziehau 125343c2aeb0SSepherosa Ziehau val = BCE_MIPHY(phy) | BCE_MIREG(reg) | 125443c2aeb0SSepherosa Ziehau BCE_EMAC_MDIO_COMM_COMMAND_READ | BCE_EMAC_MDIO_COMM_DISEXT | 125543c2aeb0SSepherosa Ziehau BCE_EMAC_MDIO_COMM_START_BUSY; 125643c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MDIO_COMM, val); 125743c2aeb0SSepherosa Ziehau 125843c2aeb0SSepherosa Ziehau for (i = 0; i < BCE_PHY_TIMEOUT; i++) { 125943c2aeb0SSepherosa Ziehau DELAY(10); 126043c2aeb0SSepherosa Ziehau 126143c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_EMAC_MDIO_COMM); 126243c2aeb0SSepherosa Ziehau if (!(val & BCE_EMAC_MDIO_COMM_START_BUSY)) { 126343c2aeb0SSepherosa Ziehau DELAY(5); 126443c2aeb0SSepherosa Ziehau 126543c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_EMAC_MDIO_COMM); 126643c2aeb0SSepherosa Ziehau val &= BCE_EMAC_MDIO_COMM_DATA; 126743c2aeb0SSepherosa Ziehau break; 126843c2aeb0SSepherosa Ziehau } 126943c2aeb0SSepherosa Ziehau } 127043c2aeb0SSepherosa Ziehau 127143c2aeb0SSepherosa Ziehau if (val & BCE_EMAC_MDIO_COMM_START_BUSY) { 127243c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 127343c2aeb0SSepherosa Ziehau "Error: PHY read timeout! phy = %d, reg = 0x%04X\n", 127443c2aeb0SSepherosa Ziehau phy, reg); 127543c2aeb0SSepherosa Ziehau val = 0x0; 127643c2aeb0SSepherosa Ziehau } else { 127743c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_EMAC_MDIO_COMM); 127843c2aeb0SSepherosa Ziehau } 127943c2aeb0SSepherosa Ziehau 128043c2aeb0SSepherosa Ziehau if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) { 128143c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_EMAC_MDIO_MODE); 128243c2aeb0SSepherosa Ziehau val |= BCE_EMAC_MDIO_MODE_AUTO_POLL; 128343c2aeb0SSepherosa Ziehau 128443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MDIO_MODE, val); 128543c2aeb0SSepherosa Ziehau REG_RD(sc, BCE_EMAC_MDIO_MODE); 128643c2aeb0SSepherosa Ziehau 128743c2aeb0SSepherosa Ziehau DELAY(40); 128843c2aeb0SSepherosa Ziehau } 128943c2aeb0SSepherosa Ziehau return (val & 0xffff); 129043c2aeb0SSepherosa Ziehau } 129143c2aeb0SSepherosa Ziehau 129243c2aeb0SSepherosa Ziehau 129343c2aeb0SSepherosa Ziehau /****************************************************************************/ 129443c2aeb0SSepherosa Ziehau /* PHY register write. */ 129543c2aeb0SSepherosa Ziehau /* */ 129643c2aeb0SSepherosa Ziehau /* Implements register writes on the MII bus. */ 129743c2aeb0SSepherosa Ziehau /* */ 129843c2aeb0SSepherosa Ziehau /* Returns: */ 129943c2aeb0SSepherosa Ziehau /* The value of the register. */ 130043c2aeb0SSepherosa Ziehau /****************************************************************************/ 130143c2aeb0SSepherosa Ziehau static int 130243c2aeb0SSepherosa Ziehau bce_miibus_write_reg(device_t dev, int phy, int reg, int val) 130343c2aeb0SSepherosa Ziehau { 130443c2aeb0SSepherosa Ziehau struct bce_softc *sc = device_get_softc(dev); 130543c2aeb0SSepherosa Ziehau uint32_t val1; 130643c2aeb0SSepherosa Ziehau int i; 130743c2aeb0SSepherosa Ziehau 130843c2aeb0SSepherosa Ziehau /* Make sure we are accessing the correct PHY address. */ 1309f31c6e4dSSepherosa Ziehau KASSERT(phy == sc->bce_phy_addr, 1310f31c6e4dSSepherosa Ziehau ("invalid phyno %d, should be %d\n", phy, sc->bce_phy_addr)); 131143c2aeb0SSepherosa Ziehau 131243c2aeb0SSepherosa Ziehau if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) { 131343c2aeb0SSepherosa Ziehau val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE); 131443c2aeb0SSepherosa Ziehau val1 &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL; 131543c2aeb0SSepherosa Ziehau 131643c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MDIO_MODE, val1); 131743c2aeb0SSepherosa Ziehau REG_RD(sc, BCE_EMAC_MDIO_MODE); 131843c2aeb0SSepherosa Ziehau 131943c2aeb0SSepherosa Ziehau DELAY(40); 132043c2aeb0SSepherosa Ziehau } 132143c2aeb0SSepherosa Ziehau 132243c2aeb0SSepherosa Ziehau val1 = BCE_MIPHY(phy) | BCE_MIREG(reg) | val | 132343c2aeb0SSepherosa Ziehau BCE_EMAC_MDIO_COMM_COMMAND_WRITE | 132443c2aeb0SSepherosa Ziehau BCE_EMAC_MDIO_COMM_START_BUSY | BCE_EMAC_MDIO_COMM_DISEXT; 132543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MDIO_COMM, val1); 132643c2aeb0SSepherosa Ziehau 132743c2aeb0SSepherosa Ziehau for (i = 0; i < BCE_PHY_TIMEOUT; i++) { 132843c2aeb0SSepherosa Ziehau DELAY(10); 132943c2aeb0SSepherosa Ziehau 133043c2aeb0SSepherosa Ziehau val1 = REG_RD(sc, BCE_EMAC_MDIO_COMM); 133143c2aeb0SSepherosa Ziehau if (!(val1 & BCE_EMAC_MDIO_COMM_START_BUSY)) { 133243c2aeb0SSepherosa Ziehau DELAY(5); 133343c2aeb0SSepherosa Ziehau break; 133443c2aeb0SSepherosa Ziehau } 133543c2aeb0SSepherosa Ziehau } 133643c2aeb0SSepherosa Ziehau 133743c2aeb0SSepherosa Ziehau if (val1 & BCE_EMAC_MDIO_COMM_START_BUSY) 133843c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "PHY write timeout!\n"); 133943c2aeb0SSepherosa Ziehau 134043c2aeb0SSepherosa Ziehau if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) { 134143c2aeb0SSepherosa Ziehau val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE); 134243c2aeb0SSepherosa Ziehau val1 |= BCE_EMAC_MDIO_MODE_AUTO_POLL; 134343c2aeb0SSepherosa Ziehau 134443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MDIO_MODE, val1); 134543c2aeb0SSepherosa Ziehau REG_RD(sc, BCE_EMAC_MDIO_MODE); 134643c2aeb0SSepherosa Ziehau 134743c2aeb0SSepherosa Ziehau DELAY(40); 134843c2aeb0SSepherosa Ziehau } 134943c2aeb0SSepherosa Ziehau return 0; 135043c2aeb0SSepherosa Ziehau } 135143c2aeb0SSepherosa Ziehau 135243c2aeb0SSepherosa Ziehau 135343c2aeb0SSepherosa Ziehau /****************************************************************************/ 135443c2aeb0SSepherosa Ziehau /* MII bus status change. */ 135543c2aeb0SSepherosa Ziehau /* */ 135643c2aeb0SSepherosa Ziehau /* Called by the MII bus driver when the PHY establishes link to set the */ 135743c2aeb0SSepherosa Ziehau /* MAC interface registers. */ 135843c2aeb0SSepherosa Ziehau /* */ 135943c2aeb0SSepherosa Ziehau /* Returns: */ 136043c2aeb0SSepherosa Ziehau /* Nothing. */ 136143c2aeb0SSepherosa Ziehau /****************************************************************************/ 136243c2aeb0SSepherosa Ziehau static void 136343c2aeb0SSepherosa Ziehau bce_miibus_statchg(device_t dev) 136443c2aeb0SSepherosa Ziehau { 136543c2aeb0SSepherosa Ziehau struct bce_softc *sc = device_get_softc(dev); 136643c2aeb0SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bce_miibus); 136743c2aeb0SSepherosa Ziehau 136843c2aeb0SSepherosa Ziehau BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT); 136943c2aeb0SSepherosa Ziehau 137043c2aeb0SSepherosa Ziehau /* 137143c2aeb0SSepherosa Ziehau * Set MII or GMII interface based on the speed negotiated 137243c2aeb0SSepherosa Ziehau * by the PHY. 137343c2aeb0SSepherosa Ziehau */ 137443c2aeb0SSepherosa Ziehau if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || 137543c2aeb0SSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) { 137643c2aeb0SSepherosa Ziehau BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_GMII); 137743c2aeb0SSepherosa Ziehau } else { 137843c2aeb0SSepherosa Ziehau BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_MII); 137943c2aeb0SSepherosa Ziehau } 138043c2aeb0SSepherosa Ziehau 138143c2aeb0SSepherosa Ziehau /* 138243c2aeb0SSepherosa Ziehau * Set half or full duplex based on the duplicity negotiated 138343c2aeb0SSepherosa Ziehau * by the PHY. 138443c2aeb0SSepherosa Ziehau */ 138543c2aeb0SSepherosa Ziehau if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { 138643c2aeb0SSepherosa Ziehau BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX); 138743c2aeb0SSepherosa Ziehau } else { 138843c2aeb0SSepherosa Ziehau BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX); 138943c2aeb0SSepherosa Ziehau } 139043c2aeb0SSepherosa Ziehau } 139143c2aeb0SSepherosa Ziehau 139243c2aeb0SSepherosa Ziehau 139343c2aeb0SSepherosa Ziehau /****************************************************************************/ 139443c2aeb0SSepherosa Ziehau /* Acquire NVRAM lock. */ 139543c2aeb0SSepherosa Ziehau /* */ 139643c2aeb0SSepherosa Ziehau /* Before the NVRAM can be accessed the caller must acquire an NVRAM lock. */ 139743c2aeb0SSepherosa Ziehau /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */ 139843c2aeb0SSepherosa Ziehau /* for use by the driver. */ 139943c2aeb0SSepherosa Ziehau /* */ 140043c2aeb0SSepherosa Ziehau /* Returns: */ 140143c2aeb0SSepherosa Ziehau /* 0 on success, positive value on failure. */ 140243c2aeb0SSepherosa Ziehau /****************************************************************************/ 140343c2aeb0SSepherosa Ziehau static int 140443c2aeb0SSepherosa Ziehau bce_acquire_nvram_lock(struct bce_softc *sc) 140543c2aeb0SSepherosa Ziehau { 140643c2aeb0SSepherosa Ziehau uint32_t val; 140743c2aeb0SSepherosa Ziehau int j; 140843c2aeb0SSepherosa Ziehau 140943c2aeb0SSepherosa Ziehau /* Request access to the flash interface. */ 141043c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_SET2); 141143c2aeb0SSepherosa Ziehau for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 141243c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_NVM_SW_ARB); 141343c2aeb0SSepherosa Ziehau if (val & BCE_NVM_SW_ARB_ARB_ARB2) 141443c2aeb0SSepherosa Ziehau break; 141543c2aeb0SSepherosa Ziehau 141643c2aeb0SSepherosa Ziehau DELAY(5); 141743c2aeb0SSepherosa Ziehau } 141843c2aeb0SSepherosa Ziehau 141943c2aeb0SSepherosa Ziehau if (j >= NVRAM_TIMEOUT_COUNT) { 142043c2aeb0SSepherosa Ziehau return EBUSY; 142143c2aeb0SSepherosa Ziehau } 142243c2aeb0SSepherosa Ziehau return 0; 142343c2aeb0SSepherosa Ziehau } 142443c2aeb0SSepherosa Ziehau 142543c2aeb0SSepherosa Ziehau 142643c2aeb0SSepherosa Ziehau /****************************************************************************/ 142743c2aeb0SSepherosa Ziehau /* Release NVRAM lock. */ 142843c2aeb0SSepherosa Ziehau /* */ 142943c2aeb0SSepherosa Ziehau /* When the caller is finished accessing NVRAM the lock must be released. */ 143043c2aeb0SSepherosa Ziehau /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */ 143143c2aeb0SSepherosa Ziehau /* for use by the driver. */ 143243c2aeb0SSepherosa Ziehau /* */ 143343c2aeb0SSepherosa Ziehau /* Returns: */ 143443c2aeb0SSepherosa Ziehau /* 0 on success, positive value on failure. */ 143543c2aeb0SSepherosa Ziehau /****************************************************************************/ 143643c2aeb0SSepherosa Ziehau static int 143743c2aeb0SSepherosa Ziehau bce_release_nvram_lock(struct bce_softc *sc) 143843c2aeb0SSepherosa Ziehau { 143943c2aeb0SSepherosa Ziehau int j; 144043c2aeb0SSepherosa Ziehau uint32_t val; 144143c2aeb0SSepherosa Ziehau 144243c2aeb0SSepherosa Ziehau /* 144343c2aeb0SSepherosa Ziehau * Relinquish nvram interface. 144443c2aeb0SSepherosa Ziehau */ 144543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_CLR2); 144643c2aeb0SSepherosa Ziehau 144743c2aeb0SSepherosa Ziehau for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 144843c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_NVM_SW_ARB); 144943c2aeb0SSepherosa Ziehau if (!(val & BCE_NVM_SW_ARB_ARB_ARB2)) 145043c2aeb0SSepherosa Ziehau break; 145143c2aeb0SSepherosa Ziehau 145243c2aeb0SSepherosa Ziehau DELAY(5); 145343c2aeb0SSepherosa Ziehau } 145443c2aeb0SSepherosa Ziehau 145543c2aeb0SSepherosa Ziehau if (j >= NVRAM_TIMEOUT_COUNT) { 145643c2aeb0SSepherosa Ziehau return EBUSY; 145743c2aeb0SSepherosa Ziehau } 145843c2aeb0SSepherosa Ziehau return 0; 145943c2aeb0SSepherosa Ziehau } 146043c2aeb0SSepherosa Ziehau 146143c2aeb0SSepherosa Ziehau 146243c2aeb0SSepherosa Ziehau /****************************************************************************/ 146343c2aeb0SSepherosa Ziehau /* Enable NVRAM access. */ 146443c2aeb0SSepherosa Ziehau /* */ 146543c2aeb0SSepherosa Ziehau /* Before accessing NVRAM for read or write operations the caller must */ 146643c2aeb0SSepherosa Ziehau /* enabled NVRAM access. */ 146743c2aeb0SSepherosa Ziehau /* */ 146843c2aeb0SSepherosa Ziehau /* Returns: */ 146943c2aeb0SSepherosa Ziehau /* Nothing. */ 147043c2aeb0SSepherosa Ziehau /****************************************************************************/ 147143c2aeb0SSepherosa Ziehau static void 147243c2aeb0SSepherosa Ziehau bce_enable_nvram_access(struct bce_softc *sc) 147343c2aeb0SSepherosa Ziehau { 147443c2aeb0SSepherosa Ziehau uint32_t val; 147543c2aeb0SSepherosa Ziehau 147643c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE); 147743c2aeb0SSepherosa Ziehau /* Enable both bits, even on read. */ 147843c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_ACCESS_ENABLE, 147943c2aeb0SSepherosa Ziehau val | BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN); 148043c2aeb0SSepherosa Ziehau } 148143c2aeb0SSepherosa Ziehau 148243c2aeb0SSepherosa Ziehau 148343c2aeb0SSepherosa Ziehau /****************************************************************************/ 148443c2aeb0SSepherosa Ziehau /* Disable NVRAM access. */ 148543c2aeb0SSepherosa Ziehau /* */ 148643c2aeb0SSepherosa Ziehau /* When the caller is finished accessing NVRAM access must be disabled. */ 148743c2aeb0SSepherosa Ziehau /* */ 148843c2aeb0SSepherosa Ziehau /* Returns: */ 148943c2aeb0SSepherosa Ziehau /* Nothing. */ 149043c2aeb0SSepherosa Ziehau /****************************************************************************/ 149143c2aeb0SSepherosa Ziehau static void 149243c2aeb0SSepherosa Ziehau bce_disable_nvram_access(struct bce_softc *sc) 149343c2aeb0SSepherosa Ziehau { 149443c2aeb0SSepherosa Ziehau uint32_t val; 149543c2aeb0SSepherosa Ziehau 149643c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE); 149743c2aeb0SSepherosa Ziehau 149843c2aeb0SSepherosa Ziehau /* Disable both bits, even after read. */ 149943c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_ACCESS_ENABLE, 150043c2aeb0SSepherosa Ziehau val & ~(BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN)); 150143c2aeb0SSepherosa Ziehau } 150243c2aeb0SSepherosa Ziehau 150343c2aeb0SSepherosa Ziehau 150443c2aeb0SSepherosa Ziehau /****************************************************************************/ 150543c2aeb0SSepherosa Ziehau /* Read a dword (32 bits) from NVRAM. */ 150643c2aeb0SSepherosa Ziehau /* */ 150743c2aeb0SSepherosa Ziehau /* Read a 32 bit word from NVRAM. The caller is assumed to have already */ 150843c2aeb0SSepherosa Ziehau /* obtained the NVRAM lock and enabled the controller for NVRAM access. */ 150943c2aeb0SSepherosa Ziehau /* */ 151043c2aeb0SSepherosa Ziehau /* Returns: */ 151143c2aeb0SSepherosa Ziehau /* 0 on success and the 32 bit value read, positive value on failure. */ 151243c2aeb0SSepherosa Ziehau /****************************************************************************/ 151343c2aeb0SSepherosa Ziehau static int 151443c2aeb0SSepherosa Ziehau bce_nvram_read_dword(struct bce_softc *sc, uint32_t offset, uint8_t *ret_val, 151543c2aeb0SSepherosa Ziehau uint32_t cmd_flags) 151643c2aeb0SSepherosa Ziehau { 151743c2aeb0SSepherosa Ziehau uint32_t cmd; 151843c2aeb0SSepherosa Ziehau int i, rc = 0; 151943c2aeb0SSepherosa Ziehau 152043c2aeb0SSepherosa Ziehau /* Build the command word. */ 152143c2aeb0SSepherosa Ziehau cmd = BCE_NVM_COMMAND_DOIT | cmd_flags; 152243c2aeb0SSepherosa Ziehau 152343c2aeb0SSepherosa Ziehau /* Calculate the offset for buffered flash. */ 1524d0092544SSepherosa Ziehau if (sc->bce_flash_info->flags & BCE_NV_TRANSLATE) { 152543c2aeb0SSepherosa Ziehau offset = ((offset / sc->bce_flash_info->page_size) << 152643c2aeb0SSepherosa Ziehau sc->bce_flash_info->page_bits) + 152743c2aeb0SSepherosa Ziehau (offset % sc->bce_flash_info->page_size); 152843c2aeb0SSepherosa Ziehau } 152943c2aeb0SSepherosa Ziehau 153043c2aeb0SSepherosa Ziehau /* 153143c2aeb0SSepherosa Ziehau * Clear the DONE bit separately, set the address to read, 153243c2aeb0SSepherosa Ziehau * and issue the read. 153343c2aeb0SSepherosa Ziehau */ 153443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE); 153543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE); 153643c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_COMMAND, cmd); 153743c2aeb0SSepherosa Ziehau 153843c2aeb0SSepherosa Ziehau /* Wait for completion. */ 153943c2aeb0SSepherosa Ziehau for (i = 0; i < NVRAM_TIMEOUT_COUNT; i++) { 154043c2aeb0SSepherosa Ziehau uint32_t val; 154143c2aeb0SSepherosa Ziehau 154243c2aeb0SSepherosa Ziehau DELAY(5); 154343c2aeb0SSepherosa Ziehau 154443c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_NVM_COMMAND); 154543c2aeb0SSepherosa Ziehau if (val & BCE_NVM_COMMAND_DONE) { 154643c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_NVM_READ); 154743c2aeb0SSepherosa Ziehau 154843c2aeb0SSepherosa Ziehau val = be32toh(val); 154943c2aeb0SSepherosa Ziehau memcpy(ret_val, &val, 4); 155043c2aeb0SSepherosa Ziehau break; 155143c2aeb0SSepherosa Ziehau } 155243c2aeb0SSepherosa Ziehau } 155343c2aeb0SSepherosa Ziehau 155443c2aeb0SSepherosa Ziehau /* Check for errors. */ 155543c2aeb0SSepherosa Ziehau if (i >= NVRAM_TIMEOUT_COUNT) { 155643c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 155743c2aeb0SSepherosa Ziehau "Timeout error reading NVRAM at offset 0x%08X!\n", 155843c2aeb0SSepherosa Ziehau offset); 155943c2aeb0SSepherosa Ziehau rc = EBUSY; 156043c2aeb0SSepherosa Ziehau } 156143c2aeb0SSepherosa Ziehau return rc; 156243c2aeb0SSepherosa Ziehau } 156343c2aeb0SSepherosa Ziehau 156443c2aeb0SSepherosa Ziehau 156543c2aeb0SSepherosa Ziehau /****************************************************************************/ 156643c2aeb0SSepherosa Ziehau /* Initialize NVRAM access. */ 156743c2aeb0SSepherosa Ziehau /* */ 156843c2aeb0SSepherosa Ziehau /* Identify the NVRAM device in use and prepare the NVRAM interface to */ 156943c2aeb0SSepherosa Ziehau /* access that device. */ 157043c2aeb0SSepherosa Ziehau /* */ 157143c2aeb0SSepherosa Ziehau /* Returns: */ 157243c2aeb0SSepherosa Ziehau /* 0 on success, positive value on failure. */ 157343c2aeb0SSepherosa Ziehau /****************************************************************************/ 157443c2aeb0SSepherosa Ziehau static int 157543c2aeb0SSepherosa Ziehau bce_init_nvram(struct bce_softc *sc) 157643c2aeb0SSepherosa Ziehau { 157743c2aeb0SSepherosa Ziehau uint32_t val; 157843c2aeb0SSepherosa Ziehau int j, entry_count, rc = 0; 157943c2aeb0SSepherosa Ziehau const struct flash_spec *flash; 158043c2aeb0SSepherosa Ziehau 1581d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 1582d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 1583d0092544SSepherosa Ziehau sc->bce_flash_info = &flash_5709; 1584d0092544SSepherosa Ziehau goto bce_init_nvram_get_flash_size; 1585d0092544SSepherosa Ziehau } 1586d0092544SSepherosa Ziehau 158743c2aeb0SSepherosa Ziehau /* Determine the selected interface. */ 158843c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_NVM_CFG1); 158943c2aeb0SSepherosa Ziehau 159043c2aeb0SSepherosa Ziehau entry_count = sizeof(flash_table) / sizeof(struct flash_spec); 159143c2aeb0SSepherosa Ziehau 159243c2aeb0SSepherosa Ziehau /* 159343c2aeb0SSepherosa Ziehau * Flash reconfiguration is required to support additional 159443c2aeb0SSepherosa Ziehau * NVRAM devices not directly supported in hardware. 159543c2aeb0SSepherosa Ziehau * Check if the flash interface was reconfigured 159643c2aeb0SSepherosa Ziehau * by the bootcode. 159743c2aeb0SSepherosa Ziehau */ 159843c2aeb0SSepherosa Ziehau 159943c2aeb0SSepherosa Ziehau if (val & 0x40000000) { 160043c2aeb0SSepherosa Ziehau /* Flash interface reconfigured by bootcode. */ 160143c2aeb0SSepherosa Ziehau for (j = 0, flash = flash_table; j < entry_count; 160243c2aeb0SSepherosa Ziehau j++, flash++) { 160343c2aeb0SSepherosa Ziehau if ((val & FLASH_BACKUP_STRAP_MASK) == 160443c2aeb0SSepherosa Ziehau (flash->config1 & FLASH_BACKUP_STRAP_MASK)) { 160543c2aeb0SSepherosa Ziehau sc->bce_flash_info = flash; 160643c2aeb0SSepherosa Ziehau break; 160743c2aeb0SSepherosa Ziehau } 160843c2aeb0SSepherosa Ziehau } 160943c2aeb0SSepherosa Ziehau } else { 161043c2aeb0SSepherosa Ziehau /* Flash interface not yet reconfigured. */ 161143c2aeb0SSepherosa Ziehau uint32_t mask; 161243c2aeb0SSepherosa Ziehau 161343c2aeb0SSepherosa Ziehau if (val & (1 << 23)) 161443c2aeb0SSepherosa Ziehau mask = FLASH_BACKUP_STRAP_MASK; 161543c2aeb0SSepherosa Ziehau else 161643c2aeb0SSepherosa Ziehau mask = FLASH_STRAP_MASK; 161743c2aeb0SSepherosa Ziehau 161843c2aeb0SSepherosa Ziehau /* Look for the matching NVRAM device configuration data. */ 161943c2aeb0SSepherosa Ziehau for (j = 0, flash = flash_table; j < entry_count; 162043c2aeb0SSepherosa Ziehau j++, flash++) { 162143c2aeb0SSepherosa Ziehau /* Check if the device matches any of the known devices. */ 162243c2aeb0SSepherosa Ziehau if ((val & mask) == (flash->strapping & mask)) { 162343c2aeb0SSepherosa Ziehau /* Found a device match. */ 162443c2aeb0SSepherosa Ziehau sc->bce_flash_info = flash; 162543c2aeb0SSepherosa Ziehau 162643c2aeb0SSepherosa Ziehau /* Request access to the flash interface. */ 162743c2aeb0SSepherosa Ziehau rc = bce_acquire_nvram_lock(sc); 162843c2aeb0SSepherosa Ziehau if (rc != 0) 162943c2aeb0SSepherosa Ziehau return rc; 163043c2aeb0SSepherosa Ziehau 163143c2aeb0SSepherosa Ziehau /* Reconfigure the flash interface. */ 163243c2aeb0SSepherosa Ziehau bce_enable_nvram_access(sc); 163343c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_CFG1, flash->config1); 163443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_CFG2, flash->config2); 163543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_CFG3, flash->config3); 163643c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_NVM_WRITE1, flash->write1); 163743c2aeb0SSepherosa Ziehau bce_disable_nvram_access(sc); 163843c2aeb0SSepherosa Ziehau bce_release_nvram_lock(sc); 163943c2aeb0SSepherosa Ziehau break; 164043c2aeb0SSepherosa Ziehau } 164143c2aeb0SSepherosa Ziehau } 164243c2aeb0SSepherosa Ziehau } 164343c2aeb0SSepherosa Ziehau 164443c2aeb0SSepherosa Ziehau /* Check if a matching device was found. */ 164543c2aeb0SSepherosa Ziehau if (j == entry_count) { 164643c2aeb0SSepherosa Ziehau sc->bce_flash_info = NULL; 164743c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Unknown Flash NVRAM found!\n"); 1648d819a615SSepherosa Ziehau return ENODEV; 164943c2aeb0SSepherosa Ziehau } 165043c2aeb0SSepherosa Ziehau 1651d0092544SSepherosa Ziehau bce_init_nvram_get_flash_size: 165243c2aeb0SSepherosa Ziehau /* Write the flash config data to the shared memory interface. */ 1653bc30d40dSSepherosa Ziehau val = bce_shmem_rd(sc, BCE_SHARED_HW_CFG_CONFIG2) & 165443c2aeb0SSepherosa Ziehau BCE_SHARED_HW_CFG2_NVM_SIZE_MASK; 165543c2aeb0SSepherosa Ziehau if (val) 165643c2aeb0SSepherosa Ziehau sc->bce_flash_size = val; 165743c2aeb0SSepherosa Ziehau else 165843c2aeb0SSepherosa Ziehau sc->bce_flash_size = sc->bce_flash_info->total_size; 165943c2aeb0SSepherosa Ziehau 166043c2aeb0SSepherosa Ziehau return rc; 166143c2aeb0SSepherosa Ziehau } 166243c2aeb0SSepherosa Ziehau 166343c2aeb0SSepherosa Ziehau 166443c2aeb0SSepherosa Ziehau /****************************************************************************/ 166543c2aeb0SSepherosa Ziehau /* Read an arbitrary range of data from NVRAM. */ 166643c2aeb0SSepherosa Ziehau /* */ 166743c2aeb0SSepherosa Ziehau /* Prepares the NVRAM interface for access and reads the requested data */ 166843c2aeb0SSepherosa Ziehau /* into the supplied buffer. */ 166943c2aeb0SSepherosa Ziehau /* */ 167043c2aeb0SSepherosa Ziehau /* Returns: */ 167143c2aeb0SSepherosa Ziehau /* 0 on success and the data read, positive value on failure. */ 167243c2aeb0SSepherosa Ziehau /****************************************************************************/ 167343c2aeb0SSepherosa Ziehau static int 167443c2aeb0SSepherosa Ziehau bce_nvram_read(struct bce_softc *sc, uint32_t offset, uint8_t *ret_buf, 167543c2aeb0SSepherosa Ziehau int buf_size) 167643c2aeb0SSepherosa Ziehau { 167743c2aeb0SSepherosa Ziehau uint32_t cmd_flags, offset32, len32, extra; 167843c2aeb0SSepherosa Ziehau int rc = 0; 167943c2aeb0SSepherosa Ziehau 168043c2aeb0SSepherosa Ziehau if (buf_size == 0) 168143c2aeb0SSepherosa Ziehau return 0; 168243c2aeb0SSepherosa Ziehau 168343c2aeb0SSepherosa Ziehau /* Request access to the flash interface. */ 168443c2aeb0SSepherosa Ziehau rc = bce_acquire_nvram_lock(sc); 168543c2aeb0SSepherosa Ziehau if (rc != 0) 168643c2aeb0SSepherosa Ziehau return rc; 168743c2aeb0SSepherosa Ziehau 168843c2aeb0SSepherosa Ziehau /* Enable access to flash interface */ 168943c2aeb0SSepherosa Ziehau bce_enable_nvram_access(sc); 169043c2aeb0SSepherosa Ziehau 169143c2aeb0SSepherosa Ziehau len32 = buf_size; 169243c2aeb0SSepherosa Ziehau offset32 = offset; 169343c2aeb0SSepherosa Ziehau extra = 0; 169443c2aeb0SSepherosa Ziehau 169543c2aeb0SSepherosa Ziehau cmd_flags = 0; 169643c2aeb0SSepherosa Ziehau 169743c2aeb0SSepherosa Ziehau /* XXX should we release nvram lock if read_dword() fails? */ 169843c2aeb0SSepherosa Ziehau if (offset32 & 3) { 169943c2aeb0SSepherosa Ziehau uint8_t buf[4]; 170043c2aeb0SSepherosa Ziehau uint32_t pre_len; 170143c2aeb0SSepherosa Ziehau 170243c2aeb0SSepherosa Ziehau offset32 &= ~3; 170343c2aeb0SSepherosa Ziehau pre_len = 4 - (offset & 3); 170443c2aeb0SSepherosa Ziehau 170543c2aeb0SSepherosa Ziehau if (pre_len >= len32) { 170643c2aeb0SSepherosa Ziehau pre_len = len32; 170743c2aeb0SSepherosa Ziehau cmd_flags = BCE_NVM_COMMAND_FIRST | BCE_NVM_COMMAND_LAST; 170843c2aeb0SSepherosa Ziehau } else { 170943c2aeb0SSepherosa Ziehau cmd_flags = BCE_NVM_COMMAND_FIRST; 171043c2aeb0SSepherosa Ziehau } 171143c2aeb0SSepherosa Ziehau 171243c2aeb0SSepherosa Ziehau rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags); 171343c2aeb0SSepherosa Ziehau if (rc) 171443c2aeb0SSepherosa Ziehau return rc; 171543c2aeb0SSepherosa Ziehau 171643c2aeb0SSepherosa Ziehau memcpy(ret_buf, buf + (offset & 3), pre_len); 171743c2aeb0SSepherosa Ziehau 171843c2aeb0SSepherosa Ziehau offset32 += 4; 171943c2aeb0SSepherosa Ziehau ret_buf += pre_len; 172043c2aeb0SSepherosa Ziehau len32 -= pre_len; 172143c2aeb0SSepherosa Ziehau } 172243c2aeb0SSepherosa Ziehau 172343c2aeb0SSepherosa Ziehau if (len32 & 3) { 172443c2aeb0SSepherosa Ziehau extra = 4 - (len32 & 3); 172543c2aeb0SSepherosa Ziehau len32 = (len32 + 4) & ~3; 172643c2aeb0SSepherosa Ziehau } 172743c2aeb0SSepherosa Ziehau 172843c2aeb0SSepherosa Ziehau if (len32 == 4) { 172943c2aeb0SSepherosa Ziehau uint8_t buf[4]; 173043c2aeb0SSepherosa Ziehau 173143c2aeb0SSepherosa Ziehau if (cmd_flags) 173243c2aeb0SSepherosa Ziehau cmd_flags = BCE_NVM_COMMAND_LAST; 173343c2aeb0SSepherosa Ziehau else 173443c2aeb0SSepherosa Ziehau cmd_flags = BCE_NVM_COMMAND_FIRST | 173543c2aeb0SSepherosa Ziehau BCE_NVM_COMMAND_LAST; 173643c2aeb0SSepherosa Ziehau 173743c2aeb0SSepherosa Ziehau rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags); 173843c2aeb0SSepherosa Ziehau 173943c2aeb0SSepherosa Ziehau memcpy(ret_buf, buf, 4 - extra); 174043c2aeb0SSepherosa Ziehau } else if (len32 > 0) { 174143c2aeb0SSepherosa Ziehau uint8_t buf[4]; 174243c2aeb0SSepherosa Ziehau 174343c2aeb0SSepherosa Ziehau /* Read the first word. */ 174443c2aeb0SSepherosa Ziehau if (cmd_flags) 174543c2aeb0SSepherosa Ziehau cmd_flags = 0; 174643c2aeb0SSepherosa Ziehau else 174743c2aeb0SSepherosa Ziehau cmd_flags = BCE_NVM_COMMAND_FIRST; 174843c2aeb0SSepherosa Ziehau 174943c2aeb0SSepherosa Ziehau rc = bce_nvram_read_dword(sc, offset32, ret_buf, cmd_flags); 175043c2aeb0SSepherosa Ziehau 175143c2aeb0SSepherosa Ziehau /* Advance to the next dword. */ 175243c2aeb0SSepherosa Ziehau offset32 += 4; 175343c2aeb0SSepherosa Ziehau ret_buf += 4; 175443c2aeb0SSepherosa Ziehau len32 -= 4; 175543c2aeb0SSepherosa Ziehau 175643c2aeb0SSepherosa Ziehau while (len32 > 4 && rc == 0) { 175743c2aeb0SSepherosa Ziehau rc = bce_nvram_read_dword(sc, offset32, ret_buf, 0); 175843c2aeb0SSepherosa Ziehau 175943c2aeb0SSepherosa Ziehau /* Advance to the next dword. */ 176043c2aeb0SSepherosa Ziehau offset32 += 4; 176143c2aeb0SSepherosa Ziehau ret_buf += 4; 176243c2aeb0SSepherosa Ziehau len32 -= 4; 176343c2aeb0SSepherosa Ziehau } 176443c2aeb0SSepherosa Ziehau 176543c2aeb0SSepherosa Ziehau if (rc) 1766d0092544SSepherosa Ziehau goto bce_nvram_read_locked_exit; 176743c2aeb0SSepherosa Ziehau 176843c2aeb0SSepherosa Ziehau cmd_flags = BCE_NVM_COMMAND_LAST; 176943c2aeb0SSepherosa Ziehau rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags); 177043c2aeb0SSepherosa Ziehau 177143c2aeb0SSepherosa Ziehau memcpy(ret_buf, buf, 4 - extra); 177243c2aeb0SSepherosa Ziehau } 177343c2aeb0SSepherosa Ziehau 1774d0092544SSepherosa Ziehau bce_nvram_read_locked_exit: 177543c2aeb0SSepherosa Ziehau /* Disable access to flash interface and release the lock. */ 177643c2aeb0SSepherosa Ziehau bce_disable_nvram_access(sc); 177743c2aeb0SSepherosa Ziehau bce_release_nvram_lock(sc); 177843c2aeb0SSepherosa Ziehau 177943c2aeb0SSepherosa Ziehau return rc; 178043c2aeb0SSepherosa Ziehau } 178143c2aeb0SSepherosa Ziehau 178243c2aeb0SSepherosa Ziehau 178343c2aeb0SSepherosa Ziehau /****************************************************************************/ 178443c2aeb0SSepherosa Ziehau /* Verifies that NVRAM is accessible and contains valid data. */ 178543c2aeb0SSepherosa Ziehau /* */ 178643c2aeb0SSepherosa Ziehau /* Reads the configuration data from NVRAM and verifies that the CRC is */ 178743c2aeb0SSepherosa Ziehau /* correct. */ 178843c2aeb0SSepherosa Ziehau /* */ 178943c2aeb0SSepherosa Ziehau /* Returns: */ 179043c2aeb0SSepherosa Ziehau /* 0 on success, positive value on failure. */ 179143c2aeb0SSepherosa Ziehau /****************************************************************************/ 179243c2aeb0SSepherosa Ziehau static int 179343c2aeb0SSepherosa Ziehau bce_nvram_test(struct bce_softc *sc) 179443c2aeb0SSepherosa Ziehau { 179543c2aeb0SSepherosa Ziehau uint32_t buf[BCE_NVRAM_SIZE / 4]; 179643c2aeb0SSepherosa Ziehau uint32_t magic, csum; 179743c2aeb0SSepherosa Ziehau uint8_t *data = (uint8_t *)buf; 179843c2aeb0SSepherosa Ziehau int rc = 0; 179943c2aeb0SSepherosa Ziehau 180043c2aeb0SSepherosa Ziehau /* 180143c2aeb0SSepherosa Ziehau * Check that the device NVRAM is valid by reading 180243c2aeb0SSepherosa Ziehau * the magic value at offset 0. 180343c2aeb0SSepherosa Ziehau */ 180443c2aeb0SSepherosa Ziehau rc = bce_nvram_read(sc, 0, data, 4); 180543c2aeb0SSepherosa Ziehau if (rc != 0) 180643c2aeb0SSepherosa Ziehau return rc; 180743c2aeb0SSepherosa Ziehau 180843c2aeb0SSepherosa Ziehau magic = be32toh(buf[0]); 180943c2aeb0SSepherosa Ziehau if (magic != BCE_NVRAM_MAGIC) { 181043c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 181143c2aeb0SSepherosa Ziehau "Invalid NVRAM magic value! Expected: 0x%08X, " 181243c2aeb0SSepherosa Ziehau "Found: 0x%08X\n", BCE_NVRAM_MAGIC, magic); 181343c2aeb0SSepherosa Ziehau return ENODEV; 181443c2aeb0SSepherosa Ziehau } 181543c2aeb0SSepherosa Ziehau 181643c2aeb0SSepherosa Ziehau /* 181743c2aeb0SSepherosa Ziehau * Verify that the device NVRAM includes valid 181843c2aeb0SSepherosa Ziehau * configuration data. 181943c2aeb0SSepherosa Ziehau */ 182043c2aeb0SSepherosa Ziehau rc = bce_nvram_read(sc, 0x100, data, BCE_NVRAM_SIZE); 182143c2aeb0SSepherosa Ziehau if (rc != 0) 182243c2aeb0SSepherosa Ziehau return rc; 182343c2aeb0SSepherosa Ziehau 182443c2aeb0SSepherosa Ziehau csum = ether_crc32_le(data, 0x100); 182543c2aeb0SSepherosa Ziehau if (csum != BCE_CRC32_RESIDUAL) { 182643c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 182743c2aeb0SSepherosa Ziehau "Invalid Manufacturing Information NVRAM CRC! " 182843c2aeb0SSepherosa Ziehau "Expected: 0x%08X, Found: 0x%08X\n", 182943c2aeb0SSepherosa Ziehau BCE_CRC32_RESIDUAL, csum); 183043c2aeb0SSepherosa Ziehau return ENODEV; 183143c2aeb0SSepherosa Ziehau } 183243c2aeb0SSepherosa Ziehau 183343c2aeb0SSepherosa Ziehau csum = ether_crc32_le(data + 0x100, 0x100); 183443c2aeb0SSepherosa Ziehau if (csum != BCE_CRC32_RESIDUAL) { 183543c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 183643c2aeb0SSepherosa Ziehau "Invalid Feature Configuration Information " 183743c2aeb0SSepherosa Ziehau "NVRAM CRC! Expected: 0x%08X, Found: 08%08X\n", 183843c2aeb0SSepherosa Ziehau BCE_CRC32_RESIDUAL, csum); 183943c2aeb0SSepherosa Ziehau rc = ENODEV; 184043c2aeb0SSepherosa Ziehau } 184143c2aeb0SSepherosa Ziehau return rc; 184243c2aeb0SSepherosa Ziehau } 184343c2aeb0SSepherosa Ziehau 184443c2aeb0SSepherosa Ziehau 184543c2aeb0SSepherosa Ziehau /****************************************************************************/ 1846d0092544SSepherosa Ziehau /* Identifies the current media type of the controller and sets the PHY */ 1847d0092544SSepherosa Ziehau /* address. */ 1848d0092544SSepherosa Ziehau /* */ 1849d0092544SSepherosa Ziehau /* Returns: */ 1850d0092544SSepherosa Ziehau /* Nothing. */ 1851d0092544SSepherosa Ziehau /****************************************************************************/ 1852d0092544SSepherosa Ziehau static void 1853d0092544SSepherosa Ziehau bce_get_media(struct bce_softc *sc) 1854d0092544SSepherosa Ziehau { 1855d0092544SSepherosa Ziehau uint32_t val; 1856d0092544SSepherosa Ziehau 1857d0092544SSepherosa Ziehau sc->bce_phy_addr = 1; 1858d0092544SSepherosa Ziehau 1859d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 1860d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 1861d0092544SSepherosa Ziehau uint32_t val = REG_RD(sc, BCE_MISC_DUAL_MEDIA_CTRL); 1862d0092544SSepherosa Ziehau uint32_t bond_id = val & BCE_MISC_DUAL_MEDIA_CTRL_BOND_ID; 1863d0092544SSepherosa Ziehau uint32_t strap; 1864d0092544SSepherosa Ziehau 1865d0092544SSepherosa Ziehau /* 1866d0092544SSepherosa Ziehau * The BCM5709S is software configurable 1867d0092544SSepherosa Ziehau * for Copper or SerDes operation. 1868d0092544SSepherosa Ziehau */ 1869d0092544SSepherosa Ziehau if (bond_id == BCE_MISC_DUAL_MEDIA_CTRL_BOND_ID_C) { 1870d0092544SSepherosa Ziehau return; 1871d0092544SSepherosa Ziehau } else if (bond_id == BCE_MISC_DUAL_MEDIA_CTRL_BOND_ID_S) { 1872d0092544SSepherosa Ziehau sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG; 1873d0092544SSepherosa Ziehau return; 1874d0092544SSepherosa Ziehau } 1875d0092544SSepherosa Ziehau 1876d0092544SSepherosa Ziehau if (val & BCE_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE) { 1877d0092544SSepherosa Ziehau strap = (val & BCE_MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21; 1878d0092544SSepherosa Ziehau } else { 1879d0092544SSepherosa Ziehau strap = 1880d0092544SSepherosa Ziehau (val & BCE_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8; 1881d0092544SSepherosa Ziehau } 1882d0092544SSepherosa Ziehau 1883d0092544SSepherosa Ziehau if (pci_get_function(sc->bce_dev) == 0) { 1884d0092544SSepherosa Ziehau switch (strap) { 1885d0092544SSepherosa Ziehau case 0x4: 1886d0092544SSepherosa Ziehau case 0x5: 1887d0092544SSepherosa Ziehau case 0x6: 1888d0092544SSepherosa Ziehau sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG; 1889d0092544SSepherosa Ziehau break; 1890d0092544SSepherosa Ziehau } 1891d0092544SSepherosa Ziehau } else { 1892d0092544SSepherosa Ziehau switch (strap) { 1893d0092544SSepherosa Ziehau case 0x1: 1894d0092544SSepherosa Ziehau case 0x2: 1895d0092544SSepherosa Ziehau case 0x4: 1896d0092544SSepherosa Ziehau sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG; 1897d0092544SSepherosa Ziehau break; 1898d0092544SSepherosa Ziehau } 1899d0092544SSepherosa Ziehau } 1900d0092544SSepherosa Ziehau } else if (BCE_CHIP_BOND_ID(sc) & BCE_CHIP_BOND_ID_SERDES_BIT) { 1901d0092544SSepherosa Ziehau sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG; 1902d0092544SSepherosa Ziehau } 1903d0092544SSepherosa Ziehau 1904d0092544SSepherosa Ziehau if (sc->bce_phy_flags & BCE_PHY_SERDES_FLAG) { 1905d0092544SSepherosa Ziehau sc->bce_flags |= BCE_NO_WOL_FLAG; 1906d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) != BCE_CHIP_NUM_5706) { 1907d0092544SSepherosa Ziehau sc->bce_phy_addr = 2; 1908bc30d40dSSepherosa Ziehau val = bce_shmem_rd(sc, BCE_SHARED_HW_CFG_CONFIG); 1909d0092544SSepherosa Ziehau if (val & BCE_SHARED_HW_CFG_PHY_2_5G) 1910d0092544SSepherosa Ziehau sc->bce_phy_flags |= BCE_PHY_2_5G_CAPABLE_FLAG; 1911d0092544SSepherosa Ziehau } 1912d0092544SSepherosa Ziehau } else if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) || 1913d0092544SSepherosa Ziehau (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708)) { 1914d0092544SSepherosa Ziehau sc->bce_phy_flags |= BCE_PHY_CRC_FIX_FLAG; 1915d0092544SSepherosa Ziehau } 1916d0092544SSepherosa Ziehau } 1917d0092544SSepherosa Ziehau 1918d0092544SSepherosa Ziehau 191910bcbdabSSepherosa Ziehau static void 192010bcbdabSSepherosa Ziehau bce_destroy_tx_ring(struct bce_tx_ring *txr) 192110bcbdabSSepherosa Ziehau { 192210bcbdabSSepherosa Ziehau int i; 192310bcbdabSSepherosa Ziehau 192410bcbdabSSepherosa Ziehau /* Destroy the TX buffer descriptor DMA stuffs. */ 192510bcbdabSSepherosa Ziehau if (txr->tx_bd_chain_tag != NULL) { 192610bcbdabSSepherosa Ziehau for (i = 0; i < txr->tx_pages; i++) { 192710bcbdabSSepherosa Ziehau if (txr->tx_bd_chain[i] != NULL) { 192810bcbdabSSepherosa Ziehau bus_dmamap_unload(txr->tx_bd_chain_tag, 192910bcbdabSSepherosa Ziehau txr->tx_bd_chain_map[i]); 193010bcbdabSSepherosa Ziehau bus_dmamem_free(txr->tx_bd_chain_tag, 193110bcbdabSSepherosa Ziehau txr->tx_bd_chain[i], 193210bcbdabSSepherosa Ziehau txr->tx_bd_chain_map[i]); 193310bcbdabSSepherosa Ziehau } 193410bcbdabSSepherosa Ziehau } 193510bcbdabSSepherosa Ziehau bus_dma_tag_destroy(txr->tx_bd_chain_tag); 193610bcbdabSSepherosa Ziehau } 193710bcbdabSSepherosa Ziehau 193810bcbdabSSepherosa Ziehau /* Destroy the TX mbuf DMA stuffs. */ 193910bcbdabSSepherosa Ziehau if (txr->tx_mbuf_tag != NULL) { 194010bcbdabSSepherosa Ziehau for (i = 0; i < TOTAL_TX_BD(txr); i++) { 194110bcbdabSSepherosa Ziehau /* Must have been unloaded in bce_stop() */ 194210bcbdabSSepherosa Ziehau KKASSERT(txr->tx_mbuf_ptr[i] == NULL); 194310bcbdabSSepherosa Ziehau bus_dmamap_destroy(txr->tx_mbuf_tag, 194410bcbdabSSepherosa Ziehau txr->tx_mbuf_map[i]); 194510bcbdabSSepherosa Ziehau } 194610bcbdabSSepherosa Ziehau bus_dma_tag_destroy(txr->tx_mbuf_tag); 194710bcbdabSSepherosa Ziehau } 194810bcbdabSSepherosa Ziehau 194910bcbdabSSepherosa Ziehau if (txr->tx_bd_chain_map != NULL) 195010bcbdabSSepherosa Ziehau kfree(txr->tx_bd_chain_map, M_DEVBUF); 195110bcbdabSSepherosa Ziehau if (txr->tx_bd_chain != NULL) 195210bcbdabSSepherosa Ziehau kfree(txr->tx_bd_chain, M_DEVBUF); 195310bcbdabSSepherosa Ziehau if (txr->tx_bd_chain_paddr != NULL) 195410bcbdabSSepherosa Ziehau kfree(txr->tx_bd_chain_paddr, M_DEVBUF); 195510bcbdabSSepherosa Ziehau 195610bcbdabSSepherosa Ziehau if (txr->tx_mbuf_map != NULL) 195710bcbdabSSepherosa Ziehau kfree(txr->tx_mbuf_map, M_DEVBUF); 195810bcbdabSSepherosa Ziehau if (txr->tx_mbuf_ptr != NULL) 195910bcbdabSSepherosa Ziehau kfree(txr->tx_mbuf_ptr, M_DEVBUF); 196010bcbdabSSepherosa Ziehau } 196110bcbdabSSepherosa Ziehau 196210bcbdabSSepherosa Ziehau 196308b64767SSepherosa Ziehau static void 196408b64767SSepherosa Ziehau bce_destroy_rx_ring(struct bce_rx_ring *rxr) 196508b64767SSepherosa Ziehau { 196608b64767SSepherosa Ziehau int i; 196708b64767SSepherosa Ziehau 196808b64767SSepherosa Ziehau /* Destroy the RX buffer descriptor DMA stuffs. */ 196908b64767SSepherosa Ziehau if (rxr->rx_bd_chain_tag != NULL) { 197008b64767SSepherosa Ziehau for (i = 0; i < rxr->rx_pages; i++) { 197108b64767SSepherosa Ziehau if (rxr->rx_bd_chain[i] != NULL) { 197208b64767SSepherosa Ziehau bus_dmamap_unload(rxr->rx_bd_chain_tag, 197308b64767SSepherosa Ziehau rxr->rx_bd_chain_map[i]); 197408b64767SSepherosa Ziehau bus_dmamem_free(rxr->rx_bd_chain_tag, 197508b64767SSepherosa Ziehau rxr->rx_bd_chain[i], 197608b64767SSepherosa Ziehau rxr->rx_bd_chain_map[i]); 197708b64767SSepherosa Ziehau } 197808b64767SSepherosa Ziehau } 197908b64767SSepherosa Ziehau bus_dma_tag_destroy(rxr->rx_bd_chain_tag); 198008b64767SSepherosa Ziehau } 198108b64767SSepherosa Ziehau 198208b64767SSepherosa Ziehau /* Destroy the RX mbuf DMA stuffs. */ 198308b64767SSepherosa Ziehau if (rxr->rx_mbuf_tag != NULL) { 198408b64767SSepherosa Ziehau for (i = 0; i < TOTAL_RX_BD(rxr); i++) { 198508b64767SSepherosa Ziehau /* Must have been unloaded in bce_stop() */ 198608b64767SSepherosa Ziehau KKASSERT(rxr->rx_mbuf_ptr[i] == NULL); 198708b64767SSepherosa Ziehau bus_dmamap_destroy(rxr->rx_mbuf_tag, 198808b64767SSepherosa Ziehau rxr->rx_mbuf_map[i]); 198908b64767SSepherosa Ziehau } 199008b64767SSepherosa Ziehau bus_dmamap_destroy(rxr->rx_mbuf_tag, rxr->rx_mbuf_tmpmap); 199108b64767SSepherosa Ziehau bus_dma_tag_destroy(rxr->rx_mbuf_tag); 199208b64767SSepherosa Ziehau } 199308b64767SSepherosa Ziehau 199408b64767SSepherosa Ziehau if (rxr->rx_bd_chain_map != NULL) 199508b64767SSepherosa Ziehau kfree(rxr->rx_bd_chain_map, M_DEVBUF); 199608b64767SSepherosa Ziehau if (rxr->rx_bd_chain != NULL) 199708b64767SSepherosa Ziehau kfree(rxr->rx_bd_chain, M_DEVBUF); 199808b64767SSepherosa Ziehau if (rxr->rx_bd_chain_paddr != NULL) 199908b64767SSepherosa Ziehau kfree(rxr->rx_bd_chain_paddr, M_DEVBUF); 200008b64767SSepherosa Ziehau 200108b64767SSepherosa Ziehau if (rxr->rx_mbuf_map != NULL) 200208b64767SSepherosa Ziehau kfree(rxr->rx_mbuf_map, M_DEVBUF); 200308b64767SSepherosa Ziehau if (rxr->rx_mbuf_ptr != NULL) 200408b64767SSepherosa Ziehau kfree(rxr->rx_mbuf_ptr, M_DEVBUF); 200508b64767SSepherosa Ziehau if (rxr->rx_mbuf_paddr != NULL) 200608b64767SSepherosa Ziehau kfree(rxr->rx_mbuf_paddr, M_DEVBUF); 200708b64767SSepherosa Ziehau } 200808b64767SSepherosa Ziehau 200908b64767SSepherosa Ziehau 2010d0092544SSepherosa Ziehau /****************************************************************************/ 201143c2aeb0SSepherosa Ziehau /* Free any DMA memory owned by the driver. */ 201243c2aeb0SSepherosa Ziehau /* */ 201343c2aeb0SSepherosa Ziehau /* Scans through each data structre that requires DMA memory and frees */ 201443c2aeb0SSepherosa Ziehau /* the memory if allocated. */ 201543c2aeb0SSepherosa Ziehau /* */ 201643c2aeb0SSepherosa Ziehau /* Returns: */ 201743c2aeb0SSepherosa Ziehau /* Nothing. */ 201843c2aeb0SSepherosa Ziehau /****************************************************************************/ 201943c2aeb0SSepherosa Ziehau static void 202043c2aeb0SSepherosa Ziehau bce_dma_free(struct bce_softc *sc) 202143c2aeb0SSepherosa Ziehau { 202243c2aeb0SSepherosa Ziehau int i; 202343c2aeb0SSepherosa Ziehau 202443c2aeb0SSepherosa Ziehau /* Destroy the status block. */ 202543c2aeb0SSepherosa Ziehau if (sc->status_tag != NULL) { 202643c2aeb0SSepherosa Ziehau if (sc->status_block != NULL) { 202743c2aeb0SSepherosa Ziehau bus_dmamap_unload(sc->status_tag, sc->status_map); 202843c2aeb0SSepherosa Ziehau bus_dmamem_free(sc->status_tag, sc->status_block, 202943c2aeb0SSepherosa Ziehau sc->status_map); 203043c2aeb0SSepherosa Ziehau } 203143c2aeb0SSepherosa Ziehau bus_dma_tag_destroy(sc->status_tag); 203243c2aeb0SSepherosa Ziehau } 203343c2aeb0SSepherosa Ziehau 203443c2aeb0SSepherosa Ziehau /* Destroy the statistics block. */ 203543c2aeb0SSepherosa Ziehau if (sc->stats_tag != NULL) { 203643c2aeb0SSepherosa Ziehau if (sc->stats_block != NULL) { 203743c2aeb0SSepherosa Ziehau bus_dmamap_unload(sc->stats_tag, sc->stats_map); 203843c2aeb0SSepherosa Ziehau bus_dmamem_free(sc->stats_tag, sc->stats_block, 203943c2aeb0SSepherosa Ziehau sc->stats_map); 204043c2aeb0SSepherosa Ziehau } 204143c2aeb0SSepherosa Ziehau bus_dma_tag_destroy(sc->stats_tag); 204243c2aeb0SSepherosa Ziehau } 204343c2aeb0SSepherosa Ziehau 2044d0092544SSepherosa Ziehau /* Destroy the CTX DMA stuffs. */ 2045d0092544SSepherosa Ziehau if (sc->ctx_tag != NULL) { 2046d0092544SSepherosa Ziehau for (i = 0; i < sc->ctx_pages; i++) { 2047d0092544SSepherosa Ziehau if (sc->ctx_block[i] != NULL) { 2048d0092544SSepherosa Ziehau bus_dmamap_unload(sc->ctx_tag, sc->ctx_map[i]); 2049d0092544SSepherosa Ziehau bus_dmamem_free(sc->ctx_tag, sc->ctx_block[i], 2050d0092544SSepherosa Ziehau sc->ctx_map[i]); 2051d0092544SSepherosa Ziehau } 2052d0092544SSepherosa Ziehau } 2053d0092544SSepherosa Ziehau bus_dma_tag_destroy(sc->ctx_tag); 2054d0092544SSepherosa Ziehau } 2055d0092544SSepherosa Ziehau 205610bcbdabSSepherosa Ziehau /* Free TX rings */ 205710bcbdabSSepherosa Ziehau if (sc->tx_rings != NULL) { 205810bcbdabSSepherosa Ziehau for (i = 0; i < sc->ring_cnt; ++i) 205910bcbdabSSepherosa Ziehau bce_destroy_tx_ring(&sc->tx_rings[i]); 206010bcbdabSSepherosa Ziehau kfree(sc->tx_rings, M_DEVBUF); 206143c2aeb0SSepherosa Ziehau } 206243c2aeb0SSepherosa Ziehau 206308b64767SSepherosa Ziehau /* Free RX rings */ 206408b64767SSepherosa Ziehau if (sc->rx_rings != NULL) { 206508b64767SSepherosa Ziehau for (i = 0; i < sc->ring_cnt; ++i) 206608b64767SSepherosa Ziehau bce_destroy_rx_ring(&sc->rx_rings[i]); 206708b64767SSepherosa Ziehau kfree(sc->rx_rings, M_DEVBUF); 206843c2aeb0SSepherosa Ziehau } 206943c2aeb0SSepherosa Ziehau 207043c2aeb0SSepherosa Ziehau /* Destroy the parent tag */ 207143c2aeb0SSepherosa Ziehau if (sc->parent_tag != NULL) 207243c2aeb0SSepherosa Ziehau bus_dma_tag_destroy(sc->parent_tag); 207343c2aeb0SSepherosa Ziehau } 207443c2aeb0SSepherosa Ziehau 207543c2aeb0SSepherosa Ziehau 207643c2aeb0SSepherosa Ziehau /****************************************************************************/ 207743c2aeb0SSepherosa Ziehau /* Get DMA memory from the OS. */ 207843c2aeb0SSepherosa Ziehau /* */ 207943c2aeb0SSepherosa Ziehau /* Validates that the OS has provided DMA buffers in response to a */ 208043c2aeb0SSepherosa Ziehau /* bus_dmamap_load() call and saves the physical address of those buffers. */ 208143c2aeb0SSepherosa Ziehau /* When the callback is used the OS will return 0 for the mapping function */ 208243c2aeb0SSepherosa Ziehau /* (bus_dmamap_load()) so we use the value of map_arg->maxsegs to pass any */ 208343c2aeb0SSepherosa Ziehau /* failures back to the caller. */ 208443c2aeb0SSepherosa Ziehau /* */ 208543c2aeb0SSepherosa Ziehau /* Returns: */ 208643c2aeb0SSepherosa Ziehau /* Nothing. */ 208743c2aeb0SSepherosa Ziehau /****************************************************************************/ 208843c2aeb0SSepherosa Ziehau static void 208943c2aeb0SSepherosa Ziehau bce_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 209043c2aeb0SSepherosa Ziehau { 209143c2aeb0SSepherosa Ziehau bus_addr_t *busaddr = arg; 209243c2aeb0SSepherosa Ziehau 209343c2aeb0SSepherosa Ziehau /* Check for an error and signal the caller that an error occurred. */ 209443c2aeb0SSepherosa Ziehau if (error) 209543c2aeb0SSepherosa Ziehau return; 209643c2aeb0SSepherosa Ziehau 2097ed20d0e3SSascha Wildner KASSERT(nseg == 1, ("only one segment is allowed")); 209843c2aeb0SSepherosa Ziehau *busaddr = segs->ds_addr; 209943c2aeb0SSepherosa Ziehau } 210043c2aeb0SSepherosa Ziehau 210143c2aeb0SSepherosa Ziehau 210210bcbdabSSepherosa Ziehau static int 210310bcbdabSSepherosa Ziehau bce_create_tx_ring(struct bce_tx_ring *txr) 210410bcbdabSSepherosa Ziehau { 210510bcbdabSSepherosa Ziehau int pages, rc, i; 210610bcbdabSSepherosa Ziehau 210784464af5SSepherosa Ziehau lwkt_serialize_init(&txr->tx_serialize); 210810bcbdabSSepherosa Ziehau txr->tx_wreg = bce_tx_wreg; 210910bcbdabSSepherosa Ziehau 211010bcbdabSSepherosa Ziehau pages = device_getenv_int(txr->sc->bce_dev, "tx_pages", bce_tx_pages); 211110bcbdabSSepherosa Ziehau if (pages <= 0 || pages > TX_PAGES_MAX || !powerof2(pages)) { 211210bcbdabSSepherosa Ziehau device_printf(txr->sc->bce_dev, "invalid # of TX pages\n"); 211310bcbdabSSepherosa Ziehau pages = TX_PAGES_DEFAULT; 211410bcbdabSSepherosa Ziehau } 211510bcbdabSSepherosa Ziehau txr->tx_pages = pages; 211610bcbdabSSepherosa Ziehau 211710bcbdabSSepherosa Ziehau txr->tx_bd_chain_map = kmalloc(sizeof(bus_dmamap_t) * txr->tx_pages, 211810bcbdabSSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 211910bcbdabSSepherosa Ziehau txr->tx_bd_chain = kmalloc(sizeof(struct tx_bd *) * txr->tx_pages, 212010bcbdabSSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 212110bcbdabSSepherosa Ziehau txr->tx_bd_chain_paddr = kmalloc(sizeof(bus_addr_t) * txr->tx_pages, 212210bcbdabSSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 212310bcbdabSSepherosa Ziehau 212410bcbdabSSepherosa Ziehau txr->tx_mbuf_map = kmalloc(sizeof(bus_dmamap_t) * TOTAL_TX_BD(txr), 212510bcbdabSSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 212610bcbdabSSepherosa Ziehau txr->tx_mbuf_ptr = kmalloc(sizeof(struct mbuf *) * TOTAL_TX_BD(txr), 212710bcbdabSSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 212810bcbdabSSepherosa Ziehau 212910bcbdabSSepherosa Ziehau /* 213010bcbdabSSepherosa Ziehau * Create a DMA tag for the TX buffer descriptor chain, 213110bcbdabSSepherosa Ziehau * allocate and clear the memory, and fetch the 213210bcbdabSSepherosa Ziehau * physical address of the block. 213310bcbdabSSepherosa Ziehau */ 213410bcbdabSSepherosa Ziehau rc = bus_dma_tag_create(txr->sc->parent_tag, BCM_PAGE_SIZE, 0, 213510bcbdabSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 213610bcbdabSSepherosa Ziehau BCE_TX_CHAIN_PAGE_SZ, 1, BCE_TX_CHAIN_PAGE_SZ, 213710bcbdabSSepherosa Ziehau 0, &txr->tx_bd_chain_tag); 213810bcbdabSSepherosa Ziehau if (rc != 0) { 213910bcbdabSSepherosa Ziehau device_printf(txr->sc->bce_dev, "Could not allocate " 214010bcbdabSSepherosa Ziehau "TX descriptor chain DMA tag!\n"); 214110bcbdabSSepherosa Ziehau return rc; 214210bcbdabSSepherosa Ziehau } 214310bcbdabSSepherosa Ziehau 214410bcbdabSSepherosa Ziehau for (i = 0; i < txr->tx_pages; i++) { 214510bcbdabSSepherosa Ziehau bus_addr_t busaddr; 214610bcbdabSSepherosa Ziehau 214710bcbdabSSepherosa Ziehau rc = bus_dmamem_alloc(txr->tx_bd_chain_tag, 214810bcbdabSSepherosa Ziehau (void **)&txr->tx_bd_chain[i], 214910bcbdabSSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_COHERENT, 215010bcbdabSSepherosa Ziehau &txr->tx_bd_chain_map[i]); 215110bcbdabSSepherosa Ziehau if (rc != 0) { 215210bcbdabSSepherosa Ziehau device_printf(txr->sc->bce_dev, 215310bcbdabSSepherosa Ziehau "Could not allocate %dth TX descriptor " 215410bcbdabSSepherosa Ziehau "chain DMA memory!\n", i); 215510bcbdabSSepherosa Ziehau return rc; 215610bcbdabSSepherosa Ziehau } 215710bcbdabSSepherosa Ziehau 215810bcbdabSSepherosa Ziehau rc = bus_dmamap_load(txr->tx_bd_chain_tag, 215910bcbdabSSepherosa Ziehau txr->tx_bd_chain_map[i], 216010bcbdabSSepherosa Ziehau txr->tx_bd_chain[i], 216110bcbdabSSepherosa Ziehau BCE_TX_CHAIN_PAGE_SZ, 216210bcbdabSSepherosa Ziehau bce_dma_map_addr, &busaddr, 216310bcbdabSSepherosa Ziehau BUS_DMA_WAITOK); 216410bcbdabSSepherosa Ziehau if (rc != 0) { 216510bcbdabSSepherosa Ziehau if (rc == EINPROGRESS) { 216610bcbdabSSepherosa Ziehau panic("%s coherent memory loading " 216710bcbdabSSepherosa Ziehau "is still in progress!", 216810bcbdabSSepherosa Ziehau txr->sc->arpcom.ac_if.if_xname); 216910bcbdabSSepherosa Ziehau } 217010bcbdabSSepherosa Ziehau device_printf(txr->sc->bce_dev, "Could not map %dth " 217110bcbdabSSepherosa Ziehau "TX descriptor chain DMA memory!\n", i); 217210bcbdabSSepherosa Ziehau bus_dmamem_free(txr->tx_bd_chain_tag, 217310bcbdabSSepherosa Ziehau txr->tx_bd_chain[i], 217410bcbdabSSepherosa Ziehau txr->tx_bd_chain_map[i]); 217510bcbdabSSepherosa Ziehau txr->tx_bd_chain[i] = NULL; 217610bcbdabSSepherosa Ziehau return rc; 217710bcbdabSSepherosa Ziehau } 217810bcbdabSSepherosa Ziehau 217910bcbdabSSepherosa Ziehau txr->tx_bd_chain_paddr[i] = busaddr; 218010bcbdabSSepherosa Ziehau } 218110bcbdabSSepherosa Ziehau 218210bcbdabSSepherosa Ziehau /* Create a DMA tag for TX mbufs. */ 218310bcbdabSSepherosa Ziehau rc = bus_dma_tag_create(txr->sc->parent_tag, 1, 0, 218410bcbdabSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 218510bcbdabSSepherosa Ziehau IP_MAXPACKET + sizeof(struct ether_vlan_header), 218610bcbdabSSepherosa Ziehau BCE_MAX_SEGMENTS, PAGE_SIZE, 218710bcbdabSSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 218810bcbdabSSepherosa Ziehau &txr->tx_mbuf_tag); 218910bcbdabSSepherosa Ziehau if (rc != 0) { 219010bcbdabSSepherosa Ziehau device_printf(txr->sc->bce_dev, 219110bcbdabSSepherosa Ziehau "Could not allocate TX mbuf DMA tag!\n"); 219210bcbdabSSepherosa Ziehau return rc; 219310bcbdabSSepherosa Ziehau } 219410bcbdabSSepherosa Ziehau 219510bcbdabSSepherosa Ziehau /* Create DMA maps for the TX mbufs clusters. */ 219610bcbdabSSepherosa Ziehau for (i = 0; i < TOTAL_TX_BD(txr); i++) { 219710bcbdabSSepherosa Ziehau rc = bus_dmamap_create(txr->tx_mbuf_tag, 219810bcbdabSSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 219910bcbdabSSepherosa Ziehau &txr->tx_mbuf_map[i]); 220010bcbdabSSepherosa Ziehau if (rc != 0) { 220110bcbdabSSepherosa Ziehau int j; 220210bcbdabSSepherosa Ziehau 220310bcbdabSSepherosa Ziehau for (j = 0; j < i; ++j) { 220410bcbdabSSepherosa Ziehau bus_dmamap_destroy(txr->tx_mbuf_tag, 220510bcbdabSSepherosa Ziehau txr->tx_mbuf_map[i]); 220610bcbdabSSepherosa Ziehau } 220710bcbdabSSepherosa Ziehau bus_dma_tag_destroy(txr->tx_mbuf_tag); 220810bcbdabSSepherosa Ziehau txr->tx_mbuf_tag = NULL; 220910bcbdabSSepherosa Ziehau 221010bcbdabSSepherosa Ziehau device_printf(txr->sc->bce_dev, "Unable to create " 221110bcbdabSSepherosa Ziehau "%dth TX mbuf DMA map!\n", i); 221210bcbdabSSepherosa Ziehau return rc; 221310bcbdabSSepherosa Ziehau } 221410bcbdabSSepherosa Ziehau } 221510bcbdabSSepherosa Ziehau return 0; 221610bcbdabSSepherosa Ziehau } 221710bcbdabSSepherosa Ziehau 221810bcbdabSSepherosa Ziehau 221908b64767SSepherosa Ziehau static int 222008b64767SSepherosa Ziehau bce_create_rx_ring(struct bce_rx_ring *rxr) 222108b64767SSepherosa Ziehau { 222208b64767SSepherosa Ziehau int pages, rc, i; 222308b64767SSepherosa Ziehau 222484464af5SSepherosa Ziehau lwkt_serialize_init(&rxr->rx_serialize); 222584464af5SSepherosa Ziehau 222608b64767SSepherosa Ziehau pages = device_getenv_int(rxr->sc->bce_dev, "rx_pages", bce_rx_pages); 222708b64767SSepherosa Ziehau if (pages <= 0 || pages > RX_PAGES_MAX || !powerof2(pages)) { 222808b64767SSepherosa Ziehau device_printf(rxr->sc->bce_dev, "invalid # of RX pages\n"); 222908b64767SSepherosa Ziehau pages = RX_PAGES_DEFAULT; 223008b64767SSepherosa Ziehau } 223108b64767SSepherosa Ziehau rxr->rx_pages = pages; 223208b64767SSepherosa Ziehau 223308b64767SSepherosa Ziehau rxr->rx_bd_chain_map = kmalloc(sizeof(bus_dmamap_t) * rxr->rx_pages, 223408b64767SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 223508b64767SSepherosa Ziehau rxr->rx_bd_chain = kmalloc(sizeof(struct rx_bd *) * rxr->rx_pages, 223608b64767SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 223708b64767SSepherosa Ziehau rxr->rx_bd_chain_paddr = kmalloc(sizeof(bus_addr_t) * rxr->rx_pages, 223808b64767SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 223908b64767SSepherosa Ziehau 224008b64767SSepherosa Ziehau rxr->rx_mbuf_map = kmalloc(sizeof(bus_dmamap_t) * TOTAL_RX_BD(rxr), 224108b64767SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 224208b64767SSepherosa Ziehau rxr->rx_mbuf_ptr = kmalloc(sizeof(struct mbuf *) * TOTAL_RX_BD(rxr), 224308b64767SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 224408b64767SSepherosa Ziehau rxr->rx_mbuf_paddr = kmalloc(sizeof(bus_addr_t) * TOTAL_RX_BD(rxr), 224508b64767SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 224608b64767SSepherosa Ziehau 224708b64767SSepherosa Ziehau /* 224808b64767SSepherosa Ziehau * Create a DMA tag for the RX buffer descriptor chain, 224908b64767SSepherosa Ziehau * allocate and clear the memory, and fetch the physical 225008b64767SSepherosa Ziehau * address of the blocks. 225108b64767SSepherosa Ziehau */ 225208b64767SSepherosa Ziehau rc = bus_dma_tag_create(rxr->sc->parent_tag, BCM_PAGE_SIZE, 0, 225308b64767SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 225408b64767SSepherosa Ziehau BCE_RX_CHAIN_PAGE_SZ, 1, BCE_RX_CHAIN_PAGE_SZ, 225508b64767SSepherosa Ziehau 0, &rxr->rx_bd_chain_tag); 225608b64767SSepherosa Ziehau if (rc != 0) { 225708b64767SSepherosa Ziehau device_printf(rxr->sc->bce_dev, "Could not allocate " 225808b64767SSepherosa Ziehau "RX descriptor chain DMA tag!\n"); 225908b64767SSepherosa Ziehau return rc; 226008b64767SSepherosa Ziehau } 226108b64767SSepherosa Ziehau 226208b64767SSepherosa Ziehau for (i = 0; i < rxr->rx_pages; i++) { 226308b64767SSepherosa Ziehau bus_addr_t busaddr; 226408b64767SSepherosa Ziehau 226508b64767SSepherosa Ziehau rc = bus_dmamem_alloc(rxr->rx_bd_chain_tag, 226608b64767SSepherosa Ziehau (void **)&rxr->rx_bd_chain[i], 226708b64767SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_COHERENT, 226808b64767SSepherosa Ziehau &rxr->rx_bd_chain_map[i]); 226908b64767SSepherosa Ziehau if (rc != 0) { 227008b64767SSepherosa Ziehau device_printf(rxr->sc->bce_dev, 227108b64767SSepherosa Ziehau "Could not allocate %dth RX descriptor " 227208b64767SSepherosa Ziehau "chain DMA memory!\n", i); 227308b64767SSepherosa Ziehau return rc; 227408b64767SSepherosa Ziehau } 227508b64767SSepherosa Ziehau 227608b64767SSepherosa Ziehau rc = bus_dmamap_load(rxr->rx_bd_chain_tag, 227708b64767SSepherosa Ziehau rxr->rx_bd_chain_map[i], 227808b64767SSepherosa Ziehau rxr->rx_bd_chain[i], 227908b64767SSepherosa Ziehau BCE_RX_CHAIN_PAGE_SZ, 228008b64767SSepherosa Ziehau bce_dma_map_addr, &busaddr, 228108b64767SSepherosa Ziehau BUS_DMA_WAITOK); 228208b64767SSepherosa Ziehau if (rc != 0) { 228308b64767SSepherosa Ziehau if (rc == EINPROGRESS) { 228408b64767SSepherosa Ziehau panic("%s coherent memory loading " 228508b64767SSepherosa Ziehau "is still in progress!", 228608b64767SSepherosa Ziehau rxr->sc->arpcom.ac_if.if_xname); 228708b64767SSepherosa Ziehau } 228808b64767SSepherosa Ziehau device_printf(rxr->sc->bce_dev, 228908b64767SSepherosa Ziehau "Could not map %dth RX descriptor " 229008b64767SSepherosa Ziehau "chain DMA memory!\n", i); 229108b64767SSepherosa Ziehau bus_dmamem_free(rxr->rx_bd_chain_tag, 229208b64767SSepherosa Ziehau rxr->rx_bd_chain[i], 229308b64767SSepherosa Ziehau rxr->rx_bd_chain_map[i]); 229408b64767SSepherosa Ziehau rxr->rx_bd_chain[i] = NULL; 229508b64767SSepherosa Ziehau return rc; 229608b64767SSepherosa Ziehau } 229708b64767SSepherosa Ziehau 229808b64767SSepherosa Ziehau rxr->rx_bd_chain_paddr[i] = busaddr; 229908b64767SSepherosa Ziehau } 230008b64767SSepherosa Ziehau 230108b64767SSepherosa Ziehau /* Create a DMA tag for RX mbufs. */ 230208b64767SSepherosa Ziehau rc = bus_dma_tag_create(rxr->sc->parent_tag, BCE_DMA_RX_ALIGN, 0, 230308b64767SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 230408b64767SSepherosa Ziehau MCLBYTES, 1, MCLBYTES, 230508b64767SSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_ALIGNED | BUS_DMA_WAITOK, 230608b64767SSepherosa Ziehau &rxr->rx_mbuf_tag); 230708b64767SSepherosa Ziehau if (rc != 0) { 230808b64767SSepherosa Ziehau device_printf(rxr->sc->bce_dev, 230908b64767SSepherosa Ziehau "Could not allocate RX mbuf DMA tag!\n"); 231008b64767SSepherosa Ziehau return rc; 231108b64767SSepherosa Ziehau } 231208b64767SSepherosa Ziehau 231308b64767SSepherosa Ziehau /* Create tmp DMA map for RX mbuf clusters. */ 231408b64767SSepherosa Ziehau rc = bus_dmamap_create(rxr->rx_mbuf_tag, BUS_DMA_WAITOK, 231508b64767SSepherosa Ziehau &rxr->rx_mbuf_tmpmap); 231608b64767SSepherosa Ziehau if (rc != 0) { 231708b64767SSepherosa Ziehau bus_dma_tag_destroy(rxr->rx_mbuf_tag); 231808b64767SSepherosa Ziehau rxr->rx_mbuf_tag = NULL; 231908b64767SSepherosa Ziehau 232008b64767SSepherosa Ziehau device_printf(rxr->sc->bce_dev, 232108b64767SSepherosa Ziehau "Could not create RX mbuf tmp DMA map!\n"); 232208b64767SSepherosa Ziehau return rc; 232308b64767SSepherosa Ziehau } 232408b64767SSepherosa Ziehau 232508b64767SSepherosa Ziehau /* Create DMA maps for the RX mbuf clusters. */ 232608b64767SSepherosa Ziehau for (i = 0; i < TOTAL_RX_BD(rxr); i++) { 232708b64767SSepherosa Ziehau rc = bus_dmamap_create(rxr->rx_mbuf_tag, BUS_DMA_WAITOK, 232808b64767SSepherosa Ziehau &rxr->rx_mbuf_map[i]); 232908b64767SSepherosa Ziehau if (rc != 0) { 233008b64767SSepherosa Ziehau int j; 233108b64767SSepherosa Ziehau 233208b64767SSepherosa Ziehau for (j = 0; j < i; ++j) { 233308b64767SSepherosa Ziehau bus_dmamap_destroy(rxr->rx_mbuf_tag, 233408b64767SSepherosa Ziehau rxr->rx_mbuf_map[j]); 233508b64767SSepherosa Ziehau } 233608b64767SSepherosa Ziehau bus_dma_tag_destroy(rxr->rx_mbuf_tag); 233708b64767SSepherosa Ziehau rxr->rx_mbuf_tag = NULL; 233808b64767SSepherosa Ziehau 233908b64767SSepherosa Ziehau device_printf(rxr->sc->bce_dev, "Unable to create " 234008b64767SSepherosa Ziehau "%dth RX mbuf DMA map!\n", i); 234108b64767SSepherosa Ziehau return rc; 234208b64767SSepherosa Ziehau } 234308b64767SSepherosa Ziehau } 234408b64767SSepherosa Ziehau return 0; 234508b64767SSepherosa Ziehau } 234608b64767SSepherosa Ziehau 234708b64767SSepherosa Ziehau 234843c2aeb0SSepherosa Ziehau /****************************************************************************/ 234943c2aeb0SSepherosa Ziehau /* Allocate any DMA memory needed by the driver. */ 235043c2aeb0SSepherosa Ziehau /* */ 235143c2aeb0SSepherosa Ziehau /* Allocates DMA memory needed for the various global structures needed by */ 235243c2aeb0SSepherosa Ziehau /* hardware. */ 235343c2aeb0SSepherosa Ziehau /* */ 2354cffea833SSepherosa Ziehau /* Memory alignment requirements: */ 2355d0092544SSepherosa Ziehau /* -----------------+----------+----------+----------+----------+ */ 2356d0092544SSepherosa Ziehau /* Data Structure | 5706 | 5708 | 5709 | 5716 | */ 2357d0092544SSepherosa Ziehau /* -----------------+----------+----------+----------+----------+ */ 2358d0092544SSepherosa Ziehau /* Status Block | 8 bytes | 8 bytes | 16 bytes | 16 bytes | */ 2359d0092544SSepherosa Ziehau /* Statistics Block | 8 bytes | 8 bytes | 16 bytes | 16 bytes | */ 2360d0092544SSepherosa Ziehau /* RX Buffers | 16 bytes | 16 bytes | 16 bytes | 16 bytes | */ 2361d0092544SSepherosa Ziehau /* PG Buffers | none | none | none | none | */ 2362d0092544SSepherosa Ziehau /* TX Buffers | none | none | none | none | */ 2363d0092544SSepherosa Ziehau /* Chain Pages(1) | 4KiB | 4KiB | 4KiB | 4KiB | */ 2364d0092544SSepherosa Ziehau /* Context Pages(1) | N/A | N/A | 4KiB | 4KiB | */ 2365d0092544SSepherosa Ziehau /* -----------------+----------+----------+----------+----------+ */ 2366cffea833SSepherosa Ziehau /* */ 2367cffea833SSepherosa Ziehau /* (1) Must align with CPU page size (BCM_PAGE_SZIE). */ 2368cffea833SSepherosa Ziehau /* */ 236943c2aeb0SSepherosa Ziehau /* Returns: */ 237043c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 237143c2aeb0SSepherosa Ziehau /****************************************************************************/ 237243c2aeb0SSepherosa Ziehau static int 237343c2aeb0SSepherosa Ziehau bce_dma_alloc(struct bce_softc *sc) 237443c2aeb0SSepherosa Ziehau { 237543c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 237608b64767SSepherosa Ziehau int i, rc = 0; 2377d0092544SSepherosa Ziehau bus_addr_t busaddr, max_busaddr; 2378d0092544SSepherosa Ziehau bus_size_t status_align, stats_align; 2379d0092544SSepherosa Ziehau 2380d0092544SSepherosa Ziehau /* 2381d0092544SSepherosa Ziehau * The embedded PCIe to PCI-X bridge (EPB) 2382d0092544SSepherosa Ziehau * in the 5708 cannot address memory above 2383d0092544SSepherosa Ziehau * 40 bits (E7_5708CB1_23043 & E6_5708SB1_23043). 2384d0092544SSepherosa Ziehau */ 2385d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708) 2386d0092544SSepherosa Ziehau max_busaddr = BCE_BUS_SPACE_MAXADDR; 2387d0092544SSepherosa Ziehau else 2388d0092544SSepherosa Ziehau max_busaddr = BUS_SPACE_MAXADDR; 2389d0092544SSepherosa Ziehau 2390d0092544SSepherosa Ziehau /* 2391d0092544SSepherosa Ziehau * BCM5709 and BCM5716 uses host memory as cache for context memory. 2392d0092544SSepherosa Ziehau */ 2393d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 2394d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 2395d0092544SSepherosa Ziehau sc->ctx_pages = BCE_CTX_BLK_SZ / BCM_PAGE_SIZE; 2396d0092544SSepherosa Ziehau if (sc->ctx_pages == 0) 2397d0092544SSepherosa Ziehau sc->ctx_pages = 1; 2398d0092544SSepherosa Ziehau if (sc->ctx_pages > BCE_CTX_PAGES) { 2399d0092544SSepherosa Ziehau device_printf(sc->bce_dev, "excessive ctx pages %d\n", 2400d0092544SSepherosa Ziehau sc->ctx_pages); 2401d0092544SSepherosa Ziehau return ENOMEM; 2402d0092544SSepherosa Ziehau } 2403d0092544SSepherosa Ziehau status_align = 16; 2404d0092544SSepherosa Ziehau stats_align = 16; 2405d0092544SSepherosa Ziehau } else { 2406d0092544SSepherosa Ziehau status_align = 8; 2407d0092544SSepherosa Ziehau stats_align = 8; 2408d0092544SSepherosa Ziehau } 240943c2aeb0SSepherosa Ziehau 241043c2aeb0SSepherosa Ziehau /* 241143c2aeb0SSepherosa Ziehau * Allocate the parent bus DMA tag appropriate for PCI. 241243c2aeb0SSepherosa Ziehau */ 241343c2aeb0SSepherosa Ziehau rc = bus_dma_tag_create(NULL, 1, BCE_DMA_BOUNDARY, 2414d0092544SSepherosa Ziehau max_busaddr, BUS_SPACE_MAXADDR, 241543c2aeb0SSepherosa Ziehau NULL, NULL, 241645010e4dSSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 0, 241743c2aeb0SSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 241843c2aeb0SSepherosa Ziehau 0, &sc->parent_tag); 241943c2aeb0SSepherosa Ziehau if (rc != 0) { 242043c2aeb0SSepherosa Ziehau if_printf(ifp, "Could not allocate parent DMA tag!\n"); 242143c2aeb0SSepherosa Ziehau return rc; 242243c2aeb0SSepherosa Ziehau } 242343c2aeb0SSepherosa Ziehau 242443c2aeb0SSepherosa Ziehau /* 24254a458e9dSSepherosa Ziehau * Allocate status block. 242643c2aeb0SSepherosa Ziehau */ 24274a458e9dSSepherosa Ziehau sc->status_block = bus_dmamem_coherent_any(sc->parent_tag, 2428d0092544SSepherosa Ziehau status_align, BCE_STATUS_BLK_SZ, 242943c2aeb0SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO, 24304a458e9dSSepherosa Ziehau &sc->status_tag, &sc->status_map, 24314a458e9dSSepherosa Ziehau &sc->status_block_paddr); 24324a458e9dSSepherosa Ziehau if (sc->status_block == NULL) { 24334a458e9dSSepherosa Ziehau if_printf(ifp, "Could not allocate status block!\n"); 24344a458e9dSSepherosa Ziehau return ENOMEM; 243543c2aeb0SSepherosa Ziehau } 243643c2aeb0SSepherosa Ziehau 243743c2aeb0SSepherosa Ziehau /* 24384a458e9dSSepherosa Ziehau * Allocate statistics block. 243943c2aeb0SSepherosa Ziehau */ 24404a458e9dSSepherosa Ziehau sc->stats_block = bus_dmamem_coherent_any(sc->parent_tag, 2441d0092544SSepherosa Ziehau stats_align, BCE_STATS_BLK_SZ, 244243c2aeb0SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO, 24434a458e9dSSepherosa Ziehau &sc->stats_tag, &sc->stats_map, 24444a458e9dSSepherosa Ziehau &sc->stats_block_paddr); 24454a458e9dSSepherosa Ziehau if (sc->stats_block == NULL) { 24464a458e9dSSepherosa Ziehau if_printf(ifp, "Could not allocate statistics block!\n"); 24474a458e9dSSepherosa Ziehau return ENOMEM; 244843c2aeb0SSepherosa Ziehau } 244943c2aeb0SSepherosa Ziehau 245043c2aeb0SSepherosa Ziehau /* 2451d0092544SSepherosa Ziehau * Allocate context block, if needed 2452d0092544SSepherosa Ziehau */ 2453d0092544SSepherosa Ziehau if (sc->ctx_pages != 0) { 2454d0092544SSepherosa Ziehau rc = bus_dma_tag_create(sc->parent_tag, BCM_PAGE_SIZE, 0, 2455d0092544SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 2456d0092544SSepherosa Ziehau NULL, NULL, 2457d0092544SSepherosa Ziehau BCM_PAGE_SIZE, 1, BCM_PAGE_SIZE, 2458d0092544SSepherosa Ziehau 0, &sc->ctx_tag); 2459d0092544SSepherosa Ziehau if (rc != 0) { 2460d0092544SSepherosa Ziehau if_printf(ifp, "Could not allocate " 2461d0092544SSepherosa Ziehau "context block DMA tag!\n"); 2462d0092544SSepherosa Ziehau return rc; 2463d0092544SSepherosa Ziehau } 2464d0092544SSepherosa Ziehau 2465d0092544SSepherosa Ziehau for (i = 0; i < sc->ctx_pages; i++) { 2466d0092544SSepherosa Ziehau rc = bus_dmamem_alloc(sc->ctx_tag, 2467d0092544SSepherosa Ziehau (void **)&sc->ctx_block[i], 2468d0092544SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO | 2469d0092544SSepherosa Ziehau BUS_DMA_COHERENT, 2470d0092544SSepherosa Ziehau &sc->ctx_map[i]); 2471d0092544SSepherosa Ziehau if (rc != 0) { 2472d0092544SSepherosa Ziehau if_printf(ifp, "Could not allocate %dth context " 2473d0092544SSepherosa Ziehau "DMA memory!\n", i); 2474d0092544SSepherosa Ziehau return rc; 2475d0092544SSepherosa Ziehau } 2476d0092544SSepherosa Ziehau 2477d0092544SSepherosa Ziehau rc = bus_dmamap_load(sc->ctx_tag, sc->ctx_map[i], 2478d0092544SSepherosa Ziehau sc->ctx_block[i], BCM_PAGE_SIZE, 2479d0092544SSepherosa Ziehau bce_dma_map_addr, &busaddr, 2480d0092544SSepherosa Ziehau BUS_DMA_WAITOK); 2481d0092544SSepherosa Ziehau if (rc != 0) { 2482d0092544SSepherosa Ziehau if (rc == EINPROGRESS) { 2483d0092544SSepherosa Ziehau panic("%s coherent memory loading " 2484d0092544SSepherosa Ziehau "is still in progress!", ifp->if_xname); 2485d0092544SSepherosa Ziehau } 2486d0092544SSepherosa Ziehau if_printf(ifp, "Could not map %dth context " 2487d0092544SSepherosa Ziehau "DMA memory!\n", i); 2488d0092544SSepherosa Ziehau bus_dmamem_free(sc->ctx_tag, sc->ctx_block[i], 2489d0092544SSepherosa Ziehau sc->ctx_map[i]); 2490d0092544SSepherosa Ziehau sc->ctx_block[i] = NULL; 2491d0092544SSepherosa Ziehau return rc; 2492d0092544SSepherosa Ziehau } 2493d0092544SSepherosa Ziehau sc->ctx_paddr[i] = busaddr; 2494d0092544SSepherosa Ziehau } 2495d0092544SSepherosa Ziehau } 2496d0092544SSepherosa Ziehau 249710bcbdabSSepherosa Ziehau sc->tx_rings = kmalloc_cachealign( 249810bcbdabSSepherosa Ziehau sizeof(struct bce_tx_ring) * sc->ring_cnt, M_DEVBUF, 249910bcbdabSSepherosa Ziehau M_WAITOK | M_ZERO); 250010bcbdabSSepherosa Ziehau for (i = 0; i < sc->ring_cnt; ++i) { 250110bcbdabSSepherosa Ziehau sc->tx_rings[i].sc = sc; 250210bcbdabSSepherosa Ziehau 250310bcbdabSSepherosa Ziehau rc = bce_create_tx_ring(&sc->tx_rings[i]); 250443c2aeb0SSepherosa Ziehau if (rc != 0) { 250510bcbdabSSepherosa Ziehau device_printf(sc->bce_dev, 250610bcbdabSSepherosa Ziehau "can't create %dth tx ring\n", i); 250743c2aeb0SSepherosa Ziehau return rc; 250843c2aeb0SSepherosa Ziehau } 250943c2aeb0SSepherosa Ziehau } 251043c2aeb0SSepherosa Ziehau 251108b64767SSepherosa Ziehau sc->rx_rings = kmalloc_cachealign( 251208b64767SSepherosa Ziehau sizeof(struct bce_rx_ring) * sc->ring_cnt, M_DEVBUF, 251308b64767SSepherosa Ziehau M_WAITOK | M_ZERO); 251408b64767SSepherosa Ziehau for (i = 0; i < sc->ring_cnt; ++i) { 251508b64767SSepherosa Ziehau sc->rx_rings[i].sc = sc; 251610bcbdabSSepherosa Ziehau 251708b64767SSepherosa Ziehau rc = bce_create_rx_ring(&sc->rx_rings[i]); 251843c2aeb0SSepherosa Ziehau if (rc != 0) { 251908b64767SSepherosa Ziehau device_printf(sc->bce_dev, 252008b64767SSepherosa Ziehau "can't create %dth rx ring\n", i); 252143c2aeb0SSepherosa Ziehau return rc; 252243c2aeb0SSepherosa Ziehau } 252343c2aeb0SSepherosa Ziehau } 252408b64767SSepherosa Ziehau 252543c2aeb0SSepherosa Ziehau return 0; 252643c2aeb0SSepherosa Ziehau } 252743c2aeb0SSepherosa Ziehau 252843c2aeb0SSepherosa Ziehau 252943c2aeb0SSepherosa Ziehau /****************************************************************************/ 253043c2aeb0SSepherosa Ziehau /* Firmware synchronization. */ 253143c2aeb0SSepherosa Ziehau /* */ 253243c2aeb0SSepherosa Ziehau /* Before performing certain events such as a chip reset, synchronize with */ 253343c2aeb0SSepherosa Ziehau /* the firmware first. */ 253443c2aeb0SSepherosa Ziehau /* */ 253543c2aeb0SSepherosa Ziehau /* Returns: */ 253643c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 253743c2aeb0SSepherosa Ziehau /****************************************************************************/ 253843c2aeb0SSepherosa Ziehau static int 253943c2aeb0SSepherosa Ziehau bce_fw_sync(struct bce_softc *sc, uint32_t msg_data) 254043c2aeb0SSepherosa Ziehau { 254143c2aeb0SSepherosa Ziehau int i, rc = 0; 254243c2aeb0SSepherosa Ziehau uint32_t val; 254343c2aeb0SSepherosa Ziehau 254443c2aeb0SSepherosa Ziehau /* Don't waste any time if we've timed out before. */ 254543c2aeb0SSepherosa Ziehau if (sc->bce_fw_timed_out) 254643c2aeb0SSepherosa Ziehau return EBUSY; 254743c2aeb0SSepherosa Ziehau 254843c2aeb0SSepherosa Ziehau /* Increment the message sequence number. */ 254943c2aeb0SSepherosa Ziehau sc->bce_fw_wr_seq++; 255043c2aeb0SSepherosa Ziehau msg_data |= sc->bce_fw_wr_seq; 255143c2aeb0SSepherosa Ziehau 255243c2aeb0SSepherosa Ziehau /* Send the message to the bootcode driver mailbox. */ 2553bc30d40dSSepherosa Ziehau bce_shmem_wr(sc, BCE_DRV_MB, msg_data); 255443c2aeb0SSepherosa Ziehau 255543c2aeb0SSepherosa Ziehau /* Wait for the bootcode to acknowledge the message. */ 255643c2aeb0SSepherosa Ziehau for (i = 0; i < FW_ACK_TIME_OUT_MS; i++) { 255743c2aeb0SSepherosa Ziehau /* Check for a response in the bootcode firmware mailbox. */ 2558bc30d40dSSepherosa Ziehau val = bce_shmem_rd(sc, BCE_FW_MB); 255943c2aeb0SSepherosa Ziehau if ((val & BCE_FW_MSG_ACK) == (msg_data & BCE_DRV_MSG_SEQ)) 256043c2aeb0SSepherosa Ziehau break; 256143c2aeb0SSepherosa Ziehau DELAY(1000); 256243c2aeb0SSepherosa Ziehau } 256343c2aeb0SSepherosa Ziehau 256443c2aeb0SSepherosa Ziehau /* If we've timed out, tell the bootcode that we've stopped waiting. */ 256543c2aeb0SSepherosa Ziehau if ((val & BCE_FW_MSG_ACK) != (msg_data & BCE_DRV_MSG_SEQ) && 256643c2aeb0SSepherosa Ziehau (msg_data & BCE_DRV_MSG_DATA) != BCE_DRV_MSG_DATA_WAIT0) { 256743c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 256843c2aeb0SSepherosa Ziehau "Firmware synchronization timeout! " 256943c2aeb0SSepherosa Ziehau "msg_data = 0x%08X\n", msg_data); 257043c2aeb0SSepherosa Ziehau 257143c2aeb0SSepherosa Ziehau msg_data &= ~BCE_DRV_MSG_CODE; 257243c2aeb0SSepherosa Ziehau msg_data |= BCE_DRV_MSG_CODE_FW_TIMEOUT; 257343c2aeb0SSepherosa Ziehau 2574bc30d40dSSepherosa Ziehau bce_shmem_wr(sc, BCE_DRV_MB, msg_data); 257543c2aeb0SSepherosa Ziehau 257643c2aeb0SSepherosa Ziehau sc->bce_fw_timed_out = 1; 257743c2aeb0SSepherosa Ziehau rc = EBUSY; 257843c2aeb0SSepherosa Ziehau } 257943c2aeb0SSepherosa Ziehau return rc; 258043c2aeb0SSepherosa Ziehau } 258143c2aeb0SSepherosa Ziehau 258243c2aeb0SSepherosa Ziehau 258343c2aeb0SSepherosa Ziehau /****************************************************************************/ 258443c2aeb0SSepherosa Ziehau /* Load Receive Virtual 2 Physical (RV2P) processor firmware. */ 258543c2aeb0SSepherosa Ziehau /* */ 258643c2aeb0SSepherosa Ziehau /* Returns: */ 258743c2aeb0SSepherosa Ziehau /* Nothing. */ 258843c2aeb0SSepherosa Ziehau /****************************************************************************/ 258943c2aeb0SSepherosa Ziehau static void 259043c2aeb0SSepherosa Ziehau bce_load_rv2p_fw(struct bce_softc *sc, uint32_t *rv2p_code, 259143c2aeb0SSepherosa Ziehau uint32_t rv2p_code_len, uint32_t rv2p_proc) 259243c2aeb0SSepherosa Ziehau { 259343c2aeb0SSepherosa Ziehau int i; 259443c2aeb0SSepherosa Ziehau uint32_t val; 259543c2aeb0SSepherosa Ziehau 259643c2aeb0SSepherosa Ziehau for (i = 0; i < rv2p_code_len; i += 8) { 259743c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RV2P_INSTR_HIGH, *rv2p_code); 259843c2aeb0SSepherosa Ziehau rv2p_code++; 259943c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RV2P_INSTR_LOW, *rv2p_code); 260043c2aeb0SSepherosa Ziehau rv2p_code++; 260143c2aeb0SSepherosa Ziehau 260243c2aeb0SSepherosa Ziehau if (rv2p_proc == RV2P_PROC1) { 260343c2aeb0SSepherosa Ziehau val = (i / 8) | BCE_RV2P_PROC1_ADDR_CMD_RDWR; 260443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RV2P_PROC1_ADDR_CMD, val); 260543c2aeb0SSepherosa Ziehau } else { 260643c2aeb0SSepherosa Ziehau val = (i / 8) | BCE_RV2P_PROC2_ADDR_CMD_RDWR; 260743c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RV2P_PROC2_ADDR_CMD, val); 260843c2aeb0SSepherosa Ziehau } 260943c2aeb0SSepherosa Ziehau } 261043c2aeb0SSepherosa Ziehau 261143c2aeb0SSepherosa Ziehau /* Reset the processor, un-stall is done later. */ 261243c2aeb0SSepherosa Ziehau if (rv2p_proc == RV2P_PROC1) 261343c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC1_RESET); 261443c2aeb0SSepherosa Ziehau else 261543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC2_RESET); 261643c2aeb0SSepherosa Ziehau } 261743c2aeb0SSepherosa Ziehau 261843c2aeb0SSepherosa Ziehau 261943c2aeb0SSepherosa Ziehau /****************************************************************************/ 262043c2aeb0SSepherosa Ziehau /* Load RISC processor firmware. */ 262143c2aeb0SSepherosa Ziehau /* */ 262243c2aeb0SSepherosa Ziehau /* Loads firmware from the file if_bcefw.h into the scratchpad memory */ 262343c2aeb0SSepherosa Ziehau /* associated with a particular processor. */ 262443c2aeb0SSepherosa Ziehau /* */ 262543c2aeb0SSepherosa Ziehau /* Returns: */ 262643c2aeb0SSepherosa Ziehau /* Nothing. */ 262743c2aeb0SSepherosa Ziehau /****************************************************************************/ 262843c2aeb0SSepherosa Ziehau static void 262943c2aeb0SSepherosa Ziehau bce_load_cpu_fw(struct bce_softc *sc, struct cpu_reg *cpu_reg, 263043c2aeb0SSepherosa Ziehau struct fw_info *fw) 263143c2aeb0SSepherosa Ziehau { 26325d05a208SSepherosa Ziehau uint32_t offset; 263343c2aeb0SSepherosa Ziehau int j; 263443c2aeb0SSepherosa Ziehau 26355d05a208SSepherosa Ziehau bce_halt_cpu(sc, cpu_reg); 263643c2aeb0SSepherosa Ziehau 263743c2aeb0SSepherosa Ziehau /* Load the Text area. */ 263843c2aeb0SSepherosa Ziehau offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base); 263943c2aeb0SSepherosa Ziehau if (fw->text) { 264043c2aeb0SSepherosa Ziehau for (j = 0; j < (fw->text_len / 4); j++, offset += 4) 264143c2aeb0SSepherosa Ziehau REG_WR_IND(sc, offset, fw->text[j]); 264243c2aeb0SSepherosa Ziehau } 264343c2aeb0SSepherosa Ziehau 264443c2aeb0SSepherosa Ziehau /* Load the Data area. */ 264543c2aeb0SSepherosa Ziehau offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base); 264643c2aeb0SSepherosa Ziehau if (fw->data) { 264743c2aeb0SSepherosa Ziehau for (j = 0; j < (fw->data_len / 4); j++, offset += 4) 264843c2aeb0SSepherosa Ziehau REG_WR_IND(sc, offset, fw->data[j]); 264943c2aeb0SSepherosa Ziehau } 265043c2aeb0SSepherosa Ziehau 265143c2aeb0SSepherosa Ziehau /* Load the SBSS area. */ 265243c2aeb0SSepherosa Ziehau offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base); 265343c2aeb0SSepherosa Ziehau if (fw->sbss) { 265443c2aeb0SSepherosa Ziehau for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) 265543c2aeb0SSepherosa Ziehau REG_WR_IND(sc, offset, fw->sbss[j]); 265643c2aeb0SSepherosa Ziehau } 265743c2aeb0SSepherosa Ziehau 265843c2aeb0SSepherosa Ziehau /* Load the BSS area. */ 265943c2aeb0SSepherosa Ziehau offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base); 266043c2aeb0SSepherosa Ziehau if (fw->bss) { 266143c2aeb0SSepherosa Ziehau for (j = 0; j < (fw->bss_len/4); j++, offset += 4) 266243c2aeb0SSepherosa Ziehau REG_WR_IND(sc, offset, fw->bss[j]); 266343c2aeb0SSepherosa Ziehau } 266443c2aeb0SSepherosa Ziehau 266543c2aeb0SSepherosa Ziehau /* Load the Read-Only area. */ 266643c2aeb0SSepherosa Ziehau offset = cpu_reg->spad_base + 266743c2aeb0SSepherosa Ziehau (fw->rodata_addr - cpu_reg->mips_view_base); 266843c2aeb0SSepherosa Ziehau if (fw->rodata) { 266943c2aeb0SSepherosa Ziehau for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) 267043c2aeb0SSepherosa Ziehau REG_WR_IND(sc, offset, fw->rodata[j]); 267143c2aeb0SSepherosa Ziehau } 267243c2aeb0SSepherosa Ziehau 26735d05a208SSepherosa Ziehau /* Clear the pre-fetch instruction and set the FW start address. */ 267443c2aeb0SSepherosa Ziehau REG_WR_IND(sc, cpu_reg->inst, 0); 267543c2aeb0SSepherosa Ziehau REG_WR_IND(sc, cpu_reg->pc, fw->start_addr); 26765d05a208SSepherosa Ziehau } 26775d05a208SSepherosa Ziehau 26785d05a208SSepherosa Ziehau 26795d05a208SSepherosa Ziehau /****************************************************************************/ 26805d05a208SSepherosa Ziehau /* Starts the RISC processor. */ 26815d05a208SSepherosa Ziehau /* */ 26825d05a208SSepherosa Ziehau /* Assumes the CPU starting address has already been set. */ 26835d05a208SSepherosa Ziehau /* */ 26845d05a208SSepherosa Ziehau /* Returns: */ 26855d05a208SSepherosa Ziehau /* Nothing. */ 26865d05a208SSepherosa Ziehau /****************************************************************************/ 26875d05a208SSepherosa Ziehau static void 26885d05a208SSepherosa Ziehau bce_start_cpu(struct bce_softc *sc, struct cpu_reg *cpu_reg) 26895d05a208SSepherosa Ziehau { 26905d05a208SSepherosa Ziehau uint32_t val; 269143c2aeb0SSepherosa Ziehau 269243c2aeb0SSepherosa Ziehau /* Start the CPU. */ 269343c2aeb0SSepherosa Ziehau val = REG_RD_IND(sc, cpu_reg->mode); 269443c2aeb0SSepherosa Ziehau val &= ~cpu_reg->mode_value_halt; 269543c2aeb0SSepherosa Ziehau REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear); 269643c2aeb0SSepherosa Ziehau REG_WR_IND(sc, cpu_reg->mode, val); 269743c2aeb0SSepherosa Ziehau } 269843c2aeb0SSepherosa Ziehau 269943c2aeb0SSepherosa Ziehau 270043c2aeb0SSepherosa Ziehau /****************************************************************************/ 27015d05a208SSepherosa Ziehau /* Halts the RISC processor. */ 27025d05a208SSepherosa Ziehau /* */ 27035d05a208SSepherosa Ziehau /* Returns: */ 27045d05a208SSepherosa Ziehau /* Nothing. */ 27055d05a208SSepherosa Ziehau /****************************************************************************/ 27065d05a208SSepherosa Ziehau static void 27075d05a208SSepherosa Ziehau bce_halt_cpu(struct bce_softc *sc, struct cpu_reg *cpu_reg) 27085d05a208SSepherosa Ziehau { 27095d05a208SSepherosa Ziehau uint32_t val; 27105d05a208SSepherosa Ziehau 27115d05a208SSepherosa Ziehau /* Halt the CPU. */ 27125d05a208SSepherosa Ziehau val = REG_RD_IND(sc, cpu_reg->mode); 27135d05a208SSepherosa Ziehau val |= cpu_reg->mode_value_halt; 27145d05a208SSepherosa Ziehau REG_WR_IND(sc, cpu_reg->mode, val); 27155d05a208SSepherosa Ziehau REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear); 27165d05a208SSepherosa Ziehau } 27175d05a208SSepherosa Ziehau 27185d05a208SSepherosa Ziehau 27195d05a208SSepherosa Ziehau /****************************************************************************/ 27205d05a208SSepherosa Ziehau /* Start the RX CPU. */ 27215d05a208SSepherosa Ziehau /* */ 27225d05a208SSepherosa Ziehau /* Returns: */ 27235d05a208SSepherosa Ziehau /* Nothing. */ 27245d05a208SSepherosa Ziehau /****************************************************************************/ 27255d05a208SSepherosa Ziehau static void 27265d05a208SSepherosa Ziehau bce_start_rxp_cpu(struct bce_softc *sc) 27275d05a208SSepherosa Ziehau { 27285d05a208SSepherosa Ziehau struct cpu_reg cpu_reg; 27295d05a208SSepherosa Ziehau 27305d05a208SSepherosa Ziehau cpu_reg.mode = BCE_RXP_CPU_MODE; 27315d05a208SSepherosa Ziehau cpu_reg.mode_value_halt = BCE_RXP_CPU_MODE_SOFT_HALT; 27325d05a208SSepherosa Ziehau cpu_reg.mode_value_sstep = BCE_RXP_CPU_MODE_STEP_ENA; 27335d05a208SSepherosa Ziehau cpu_reg.state = BCE_RXP_CPU_STATE; 27345d05a208SSepherosa Ziehau cpu_reg.state_value_clear = 0xffffff; 27355d05a208SSepherosa Ziehau cpu_reg.gpr0 = BCE_RXP_CPU_REG_FILE; 27365d05a208SSepherosa Ziehau cpu_reg.evmask = BCE_RXP_CPU_EVENT_MASK; 27375d05a208SSepherosa Ziehau cpu_reg.pc = BCE_RXP_CPU_PROGRAM_COUNTER; 27385d05a208SSepherosa Ziehau cpu_reg.inst = BCE_RXP_CPU_INSTRUCTION; 27395d05a208SSepherosa Ziehau cpu_reg.bp = BCE_RXP_CPU_HW_BREAKPOINT; 27405d05a208SSepherosa Ziehau cpu_reg.spad_base = BCE_RXP_SCRATCH; 27415d05a208SSepherosa Ziehau cpu_reg.mips_view_base = 0x8000000; 27425d05a208SSepherosa Ziehau 27435d05a208SSepherosa Ziehau bce_start_cpu(sc, &cpu_reg); 27445d05a208SSepherosa Ziehau } 27455d05a208SSepherosa Ziehau 27465d05a208SSepherosa Ziehau 27475d05a208SSepherosa Ziehau /****************************************************************************/ 2748d0092544SSepherosa Ziehau /* Initialize the RX CPU. */ 274943c2aeb0SSepherosa Ziehau /* */ 275043c2aeb0SSepherosa Ziehau /* Returns: */ 275143c2aeb0SSepherosa Ziehau /* Nothing. */ 275243c2aeb0SSepherosa Ziehau /****************************************************************************/ 275343c2aeb0SSepherosa Ziehau static void 2754d0092544SSepherosa Ziehau bce_init_rxp_cpu(struct bce_softc *sc) 275543c2aeb0SSepherosa Ziehau { 275643c2aeb0SSepherosa Ziehau struct cpu_reg cpu_reg; 275743c2aeb0SSepherosa Ziehau struct fw_info fw; 275843c2aeb0SSepherosa Ziehau 275943c2aeb0SSepherosa Ziehau cpu_reg.mode = BCE_RXP_CPU_MODE; 276043c2aeb0SSepherosa Ziehau cpu_reg.mode_value_halt = BCE_RXP_CPU_MODE_SOFT_HALT; 276143c2aeb0SSepherosa Ziehau cpu_reg.mode_value_sstep = BCE_RXP_CPU_MODE_STEP_ENA; 276243c2aeb0SSepherosa Ziehau cpu_reg.state = BCE_RXP_CPU_STATE; 276343c2aeb0SSepherosa Ziehau cpu_reg.state_value_clear = 0xffffff; 276443c2aeb0SSepherosa Ziehau cpu_reg.gpr0 = BCE_RXP_CPU_REG_FILE; 276543c2aeb0SSepherosa Ziehau cpu_reg.evmask = BCE_RXP_CPU_EVENT_MASK; 276643c2aeb0SSepherosa Ziehau cpu_reg.pc = BCE_RXP_CPU_PROGRAM_COUNTER; 276743c2aeb0SSepherosa Ziehau cpu_reg.inst = BCE_RXP_CPU_INSTRUCTION; 276843c2aeb0SSepherosa Ziehau cpu_reg.bp = BCE_RXP_CPU_HW_BREAKPOINT; 276943c2aeb0SSepherosa Ziehau cpu_reg.spad_base = BCE_RXP_SCRATCH; 277043c2aeb0SSepherosa Ziehau cpu_reg.mips_view_base = 0x8000000; 277143c2aeb0SSepherosa Ziehau 2772d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 2773d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 2774d0092544SSepherosa Ziehau fw.ver_major = bce_RXP_b09FwReleaseMajor; 2775d0092544SSepherosa Ziehau fw.ver_minor = bce_RXP_b09FwReleaseMinor; 2776d0092544SSepherosa Ziehau fw.ver_fix = bce_RXP_b09FwReleaseFix; 2777d0092544SSepherosa Ziehau fw.start_addr = bce_RXP_b09FwStartAddr; 2778d0092544SSepherosa Ziehau 2779d0092544SSepherosa Ziehau fw.text_addr = bce_RXP_b09FwTextAddr; 2780d0092544SSepherosa Ziehau fw.text_len = bce_RXP_b09FwTextLen; 2781d0092544SSepherosa Ziehau fw.text_index = 0; 2782d0092544SSepherosa Ziehau fw.text = bce_RXP_b09FwText; 2783d0092544SSepherosa Ziehau 2784d0092544SSepherosa Ziehau fw.data_addr = bce_RXP_b09FwDataAddr; 2785d0092544SSepherosa Ziehau fw.data_len = bce_RXP_b09FwDataLen; 2786d0092544SSepherosa Ziehau fw.data_index = 0; 2787d0092544SSepherosa Ziehau fw.data = bce_RXP_b09FwData; 2788d0092544SSepherosa Ziehau 2789d0092544SSepherosa Ziehau fw.sbss_addr = bce_RXP_b09FwSbssAddr; 2790d0092544SSepherosa Ziehau fw.sbss_len = bce_RXP_b09FwSbssLen; 2791d0092544SSepherosa Ziehau fw.sbss_index = 0; 2792d0092544SSepherosa Ziehau fw.sbss = bce_RXP_b09FwSbss; 2793d0092544SSepherosa Ziehau 2794d0092544SSepherosa Ziehau fw.bss_addr = bce_RXP_b09FwBssAddr; 2795d0092544SSepherosa Ziehau fw.bss_len = bce_RXP_b09FwBssLen; 2796d0092544SSepherosa Ziehau fw.bss_index = 0; 2797d0092544SSepherosa Ziehau fw.bss = bce_RXP_b09FwBss; 2798d0092544SSepherosa Ziehau 2799d0092544SSepherosa Ziehau fw.rodata_addr = bce_RXP_b09FwRodataAddr; 2800d0092544SSepherosa Ziehau fw.rodata_len = bce_RXP_b09FwRodataLen; 2801d0092544SSepherosa Ziehau fw.rodata_index = 0; 2802d0092544SSepherosa Ziehau fw.rodata = bce_RXP_b09FwRodata; 2803d0092544SSepherosa Ziehau } else { 280443c2aeb0SSepherosa Ziehau fw.ver_major = bce_RXP_b06FwReleaseMajor; 280543c2aeb0SSepherosa Ziehau fw.ver_minor = bce_RXP_b06FwReleaseMinor; 280643c2aeb0SSepherosa Ziehau fw.ver_fix = bce_RXP_b06FwReleaseFix; 280743c2aeb0SSepherosa Ziehau fw.start_addr = bce_RXP_b06FwStartAddr; 280843c2aeb0SSepherosa Ziehau 280943c2aeb0SSepherosa Ziehau fw.text_addr = bce_RXP_b06FwTextAddr; 281043c2aeb0SSepherosa Ziehau fw.text_len = bce_RXP_b06FwTextLen; 281143c2aeb0SSepherosa Ziehau fw.text_index = 0; 281243c2aeb0SSepherosa Ziehau fw.text = bce_RXP_b06FwText; 281343c2aeb0SSepherosa Ziehau 281443c2aeb0SSepherosa Ziehau fw.data_addr = bce_RXP_b06FwDataAddr; 281543c2aeb0SSepherosa Ziehau fw.data_len = bce_RXP_b06FwDataLen; 281643c2aeb0SSepherosa Ziehau fw.data_index = 0; 281743c2aeb0SSepherosa Ziehau fw.data = bce_RXP_b06FwData; 281843c2aeb0SSepherosa Ziehau 281943c2aeb0SSepherosa Ziehau fw.sbss_addr = bce_RXP_b06FwSbssAddr; 282043c2aeb0SSepherosa Ziehau fw.sbss_len = bce_RXP_b06FwSbssLen; 282143c2aeb0SSepherosa Ziehau fw.sbss_index = 0; 282243c2aeb0SSepherosa Ziehau fw.sbss = bce_RXP_b06FwSbss; 282343c2aeb0SSepherosa Ziehau 282443c2aeb0SSepherosa Ziehau fw.bss_addr = bce_RXP_b06FwBssAddr; 282543c2aeb0SSepherosa Ziehau fw.bss_len = bce_RXP_b06FwBssLen; 282643c2aeb0SSepherosa Ziehau fw.bss_index = 0; 282743c2aeb0SSepherosa Ziehau fw.bss = bce_RXP_b06FwBss; 282843c2aeb0SSepherosa Ziehau 282943c2aeb0SSepherosa Ziehau fw.rodata_addr = bce_RXP_b06FwRodataAddr; 283043c2aeb0SSepherosa Ziehau fw.rodata_len = bce_RXP_b06FwRodataLen; 283143c2aeb0SSepherosa Ziehau fw.rodata_index = 0; 283243c2aeb0SSepherosa Ziehau fw.rodata = bce_RXP_b06FwRodata; 2833d0092544SSepherosa Ziehau } 283443c2aeb0SSepherosa Ziehau 283543c2aeb0SSepherosa Ziehau bce_load_cpu_fw(sc, &cpu_reg, &fw); 28365d05a208SSepherosa Ziehau /* Delay RXP start until initialization is complete. */ 2837d0092544SSepherosa Ziehau } 283843c2aeb0SSepherosa Ziehau 2839d0092544SSepherosa Ziehau 2840d0092544SSepherosa Ziehau /****************************************************************************/ 2841d0092544SSepherosa Ziehau /* Initialize the TX CPU. */ 2842d0092544SSepherosa Ziehau /* */ 2843d0092544SSepherosa Ziehau /* Returns: */ 2844d0092544SSepherosa Ziehau /* Nothing. */ 2845d0092544SSepherosa Ziehau /****************************************************************************/ 2846d0092544SSepherosa Ziehau static void 2847d0092544SSepherosa Ziehau bce_init_txp_cpu(struct bce_softc *sc) 2848d0092544SSepherosa Ziehau { 2849d0092544SSepherosa Ziehau struct cpu_reg cpu_reg; 2850d0092544SSepherosa Ziehau struct fw_info fw; 2851d0092544SSepherosa Ziehau 285243c2aeb0SSepherosa Ziehau cpu_reg.mode = BCE_TXP_CPU_MODE; 285343c2aeb0SSepherosa Ziehau cpu_reg.mode_value_halt = BCE_TXP_CPU_MODE_SOFT_HALT; 285443c2aeb0SSepherosa Ziehau cpu_reg.mode_value_sstep = BCE_TXP_CPU_MODE_STEP_ENA; 285543c2aeb0SSepherosa Ziehau cpu_reg.state = BCE_TXP_CPU_STATE; 285643c2aeb0SSepherosa Ziehau cpu_reg.state_value_clear = 0xffffff; 285743c2aeb0SSepherosa Ziehau cpu_reg.gpr0 = BCE_TXP_CPU_REG_FILE; 285843c2aeb0SSepherosa Ziehau cpu_reg.evmask = BCE_TXP_CPU_EVENT_MASK; 285943c2aeb0SSepherosa Ziehau cpu_reg.pc = BCE_TXP_CPU_PROGRAM_COUNTER; 286043c2aeb0SSepherosa Ziehau cpu_reg.inst = BCE_TXP_CPU_INSTRUCTION; 286143c2aeb0SSepherosa Ziehau cpu_reg.bp = BCE_TXP_CPU_HW_BREAKPOINT; 286243c2aeb0SSepherosa Ziehau cpu_reg.spad_base = BCE_TXP_SCRATCH; 286343c2aeb0SSepherosa Ziehau cpu_reg.mips_view_base = 0x8000000; 286443c2aeb0SSepherosa Ziehau 2865d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 2866d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 2867d0092544SSepherosa Ziehau fw.ver_major = bce_TXP_b09FwReleaseMajor; 2868d0092544SSepherosa Ziehau fw.ver_minor = bce_TXP_b09FwReleaseMinor; 2869d0092544SSepherosa Ziehau fw.ver_fix = bce_TXP_b09FwReleaseFix; 2870d0092544SSepherosa Ziehau fw.start_addr = bce_TXP_b09FwStartAddr; 2871d0092544SSepherosa Ziehau 2872d0092544SSepherosa Ziehau fw.text_addr = bce_TXP_b09FwTextAddr; 2873d0092544SSepherosa Ziehau fw.text_len = bce_TXP_b09FwTextLen; 2874d0092544SSepherosa Ziehau fw.text_index = 0; 2875d0092544SSepherosa Ziehau fw.text = bce_TXP_b09FwText; 2876d0092544SSepherosa Ziehau 2877d0092544SSepherosa Ziehau fw.data_addr = bce_TXP_b09FwDataAddr; 2878d0092544SSepherosa Ziehau fw.data_len = bce_TXP_b09FwDataLen; 2879d0092544SSepherosa Ziehau fw.data_index = 0; 2880d0092544SSepherosa Ziehau fw.data = bce_TXP_b09FwData; 2881d0092544SSepherosa Ziehau 2882d0092544SSepherosa Ziehau fw.sbss_addr = bce_TXP_b09FwSbssAddr; 2883d0092544SSepherosa Ziehau fw.sbss_len = bce_TXP_b09FwSbssLen; 2884d0092544SSepherosa Ziehau fw.sbss_index = 0; 2885d0092544SSepherosa Ziehau fw.sbss = bce_TXP_b09FwSbss; 2886d0092544SSepherosa Ziehau 2887d0092544SSepherosa Ziehau fw.bss_addr = bce_TXP_b09FwBssAddr; 2888d0092544SSepherosa Ziehau fw.bss_len = bce_TXP_b09FwBssLen; 2889d0092544SSepherosa Ziehau fw.bss_index = 0; 2890d0092544SSepherosa Ziehau fw.bss = bce_TXP_b09FwBss; 2891d0092544SSepherosa Ziehau 2892d0092544SSepherosa Ziehau fw.rodata_addr = bce_TXP_b09FwRodataAddr; 2893d0092544SSepherosa Ziehau fw.rodata_len = bce_TXP_b09FwRodataLen; 2894d0092544SSepherosa Ziehau fw.rodata_index = 0; 2895d0092544SSepherosa Ziehau fw.rodata = bce_TXP_b09FwRodata; 2896d0092544SSepherosa Ziehau } else { 289743c2aeb0SSepherosa Ziehau fw.ver_major = bce_TXP_b06FwReleaseMajor; 289843c2aeb0SSepherosa Ziehau fw.ver_minor = bce_TXP_b06FwReleaseMinor; 289943c2aeb0SSepherosa Ziehau fw.ver_fix = bce_TXP_b06FwReleaseFix; 290043c2aeb0SSepherosa Ziehau fw.start_addr = bce_TXP_b06FwStartAddr; 290143c2aeb0SSepherosa Ziehau 290243c2aeb0SSepherosa Ziehau fw.text_addr = bce_TXP_b06FwTextAddr; 290343c2aeb0SSepherosa Ziehau fw.text_len = bce_TXP_b06FwTextLen; 290443c2aeb0SSepherosa Ziehau fw.text_index = 0; 290543c2aeb0SSepherosa Ziehau fw.text = bce_TXP_b06FwText; 290643c2aeb0SSepherosa Ziehau 290743c2aeb0SSepherosa Ziehau fw.data_addr = bce_TXP_b06FwDataAddr; 290843c2aeb0SSepherosa Ziehau fw.data_len = bce_TXP_b06FwDataLen; 290943c2aeb0SSepherosa Ziehau fw.data_index = 0; 291043c2aeb0SSepherosa Ziehau fw.data = bce_TXP_b06FwData; 291143c2aeb0SSepherosa Ziehau 291243c2aeb0SSepherosa Ziehau fw.sbss_addr = bce_TXP_b06FwSbssAddr; 291343c2aeb0SSepherosa Ziehau fw.sbss_len = bce_TXP_b06FwSbssLen; 291443c2aeb0SSepherosa Ziehau fw.sbss_index = 0; 291543c2aeb0SSepherosa Ziehau fw.sbss = bce_TXP_b06FwSbss; 291643c2aeb0SSepherosa Ziehau 291743c2aeb0SSepherosa Ziehau fw.bss_addr = bce_TXP_b06FwBssAddr; 291843c2aeb0SSepherosa Ziehau fw.bss_len = bce_TXP_b06FwBssLen; 291943c2aeb0SSepherosa Ziehau fw.bss_index = 0; 292043c2aeb0SSepherosa Ziehau fw.bss = bce_TXP_b06FwBss; 292143c2aeb0SSepherosa Ziehau 292243c2aeb0SSepherosa Ziehau fw.rodata_addr = bce_TXP_b06FwRodataAddr; 292343c2aeb0SSepherosa Ziehau fw.rodata_len = bce_TXP_b06FwRodataLen; 292443c2aeb0SSepherosa Ziehau fw.rodata_index = 0; 292543c2aeb0SSepherosa Ziehau fw.rodata = bce_TXP_b06FwRodata; 2926d0092544SSepherosa Ziehau } 292743c2aeb0SSepherosa Ziehau 292843c2aeb0SSepherosa Ziehau bce_load_cpu_fw(sc, &cpu_reg, &fw); 29295d05a208SSepherosa Ziehau bce_start_cpu(sc, &cpu_reg); 2930d0092544SSepherosa Ziehau } 293143c2aeb0SSepherosa Ziehau 2932d0092544SSepherosa Ziehau 2933d0092544SSepherosa Ziehau /****************************************************************************/ 2934d0092544SSepherosa Ziehau /* Initialize the TPAT CPU. */ 2935d0092544SSepherosa Ziehau /* */ 2936d0092544SSepherosa Ziehau /* Returns: */ 2937d0092544SSepherosa Ziehau /* Nothing. */ 2938d0092544SSepherosa Ziehau /****************************************************************************/ 2939d0092544SSepherosa Ziehau static void 2940d0092544SSepherosa Ziehau bce_init_tpat_cpu(struct bce_softc *sc) 2941d0092544SSepherosa Ziehau { 2942d0092544SSepherosa Ziehau struct cpu_reg cpu_reg; 2943d0092544SSepherosa Ziehau struct fw_info fw; 2944d0092544SSepherosa Ziehau 294543c2aeb0SSepherosa Ziehau cpu_reg.mode = BCE_TPAT_CPU_MODE; 294643c2aeb0SSepherosa Ziehau cpu_reg.mode_value_halt = BCE_TPAT_CPU_MODE_SOFT_HALT; 294743c2aeb0SSepherosa Ziehau cpu_reg.mode_value_sstep = BCE_TPAT_CPU_MODE_STEP_ENA; 294843c2aeb0SSepherosa Ziehau cpu_reg.state = BCE_TPAT_CPU_STATE; 294943c2aeb0SSepherosa Ziehau cpu_reg.state_value_clear = 0xffffff; 295043c2aeb0SSepherosa Ziehau cpu_reg.gpr0 = BCE_TPAT_CPU_REG_FILE; 295143c2aeb0SSepherosa Ziehau cpu_reg.evmask = BCE_TPAT_CPU_EVENT_MASK; 295243c2aeb0SSepherosa Ziehau cpu_reg.pc = BCE_TPAT_CPU_PROGRAM_COUNTER; 295343c2aeb0SSepherosa Ziehau cpu_reg.inst = BCE_TPAT_CPU_INSTRUCTION; 295443c2aeb0SSepherosa Ziehau cpu_reg.bp = BCE_TPAT_CPU_HW_BREAKPOINT; 295543c2aeb0SSepherosa Ziehau cpu_reg.spad_base = BCE_TPAT_SCRATCH; 295643c2aeb0SSepherosa Ziehau cpu_reg.mips_view_base = 0x8000000; 295743c2aeb0SSepherosa Ziehau 2958d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 2959d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 2960d0092544SSepherosa Ziehau fw.ver_major = bce_TPAT_b09FwReleaseMajor; 2961d0092544SSepherosa Ziehau fw.ver_minor = bce_TPAT_b09FwReleaseMinor; 2962d0092544SSepherosa Ziehau fw.ver_fix = bce_TPAT_b09FwReleaseFix; 2963d0092544SSepherosa Ziehau fw.start_addr = bce_TPAT_b09FwStartAddr; 2964d0092544SSepherosa Ziehau 2965d0092544SSepherosa Ziehau fw.text_addr = bce_TPAT_b09FwTextAddr; 2966d0092544SSepherosa Ziehau fw.text_len = bce_TPAT_b09FwTextLen; 2967d0092544SSepherosa Ziehau fw.text_index = 0; 2968d0092544SSepherosa Ziehau fw.text = bce_TPAT_b09FwText; 2969d0092544SSepherosa Ziehau 2970d0092544SSepherosa Ziehau fw.data_addr = bce_TPAT_b09FwDataAddr; 2971d0092544SSepherosa Ziehau fw.data_len = bce_TPAT_b09FwDataLen; 2972d0092544SSepherosa Ziehau fw.data_index = 0; 2973d0092544SSepherosa Ziehau fw.data = bce_TPAT_b09FwData; 2974d0092544SSepherosa Ziehau 2975d0092544SSepherosa Ziehau fw.sbss_addr = bce_TPAT_b09FwSbssAddr; 2976d0092544SSepherosa Ziehau fw.sbss_len = bce_TPAT_b09FwSbssLen; 2977d0092544SSepherosa Ziehau fw.sbss_index = 0; 2978d0092544SSepherosa Ziehau fw.sbss = bce_TPAT_b09FwSbss; 2979d0092544SSepherosa Ziehau 2980d0092544SSepherosa Ziehau fw.bss_addr = bce_TPAT_b09FwBssAddr; 2981d0092544SSepherosa Ziehau fw.bss_len = bce_TPAT_b09FwBssLen; 2982d0092544SSepherosa Ziehau fw.bss_index = 0; 2983d0092544SSepherosa Ziehau fw.bss = bce_TPAT_b09FwBss; 2984d0092544SSepherosa Ziehau 2985d0092544SSepherosa Ziehau fw.rodata_addr = bce_TPAT_b09FwRodataAddr; 2986d0092544SSepherosa Ziehau fw.rodata_len = bce_TPAT_b09FwRodataLen; 2987d0092544SSepherosa Ziehau fw.rodata_index = 0; 2988d0092544SSepherosa Ziehau fw.rodata = bce_TPAT_b09FwRodata; 2989d0092544SSepherosa Ziehau } else { 299043c2aeb0SSepherosa Ziehau fw.ver_major = bce_TPAT_b06FwReleaseMajor; 299143c2aeb0SSepherosa Ziehau fw.ver_minor = bce_TPAT_b06FwReleaseMinor; 299243c2aeb0SSepherosa Ziehau fw.ver_fix = bce_TPAT_b06FwReleaseFix; 299343c2aeb0SSepherosa Ziehau fw.start_addr = bce_TPAT_b06FwStartAddr; 299443c2aeb0SSepherosa Ziehau 299543c2aeb0SSepherosa Ziehau fw.text_addr = bce_TPAT_b06FwTextAddr; 299643c2aeb0SSepherosa Ziehau fw.text_len = bce_TPAT_b06FwTextLen; 299743c2aeb0SSepherosa Ziehau fw.text_index = 0; 299843c2aeb0SSepherosa Ziehau fw.text = bce_TPAT_b06FwText; 299943c2aeb0SSepherosa Ziehau 300043c2aeb0SSepherosa Ziehau fw.data_addr = bce_TPAT_b06FwDataAddr; 300143c2aeb0SSepherosa Ziehau fw.data_len = bce_TPAT_b06FwDataLen; 300243c2aeb0SSepherosa Ziehau fw.data_index = 0; 300343c2aeb0SSepherosa Ziehau fw.data = bce_TPAT_b06FwData; 300443c2aeb0SSepherosa Ziehau 300543c2aeb0SSepherosa Ziehau fw.sbss_addr = bce_TPAT_b06FwSbssAddr; 300643c2aeb0SSepherosa Ziehau fw.sbss_len = bce_TPAT_b06FwSbssLen; 300743c2aeb0SSepherosa Ziehau fw.sbss_index = 0; 300843c2aeb0SSepherosa Ziehau fw.sbss = bce_TPAT_b06FwSbss; 300943c2aeb0SSepherosa Ziehau 301043c2aeb0SSepherosa Ziehau fw.bss_addr = bce_TPAT_b06FwBssAddr; 301143c2aeb0SSepherosa Ziehau fw.bss_len = bce_TPAT_b06FwBssLen; 301243c2aeb0SSepherosa Ziehau fw.bss_index = 0; 301343c2aeb0SSepherosa Ziehau fw.bss = bce_TPAT_b06FwBss; 301443c2aeb0SSepherosa Ziehau 301543c2aeb0SSepherosa Ziehau fw.rodata_addr = bce_TPAT_b06FwRodataAddr; 301643c2aeb0SSepherosa Ziehau fw.rodata_len = bce_TPAT_b06FwRodataLen; 301743c2aeb0SSepherosa Ziehau fw.rodata_index = 0; 301843c2aeb0SSepherosa Ziehau fw.rodata = bce_TPAT_b06FwRodata; 3019d0092544SSepherosa Ziehau } 302043c2aeb0SSepherosa Ziehau 302143c2aeb0SSepherosa Ziehau bce_load_cpu_fw(sc, &cpu_reg, &fw); 30225d05a208SSepherosa Ziehau bce_start_cpu(sc, &cpu_reg); 3023d0092544SSepherosa Ziehau } 302443c2aeb0SSepherosa Ziehau 3025d0092544SSepherosa Ziehau 3026d0092544SSepherosa Ziehau /****************************************************************************/ 3027d0092544SSepherosa Ziehau /* Initialize the CP CPU. */ 3028d0092544SSepherosa Ziehau /* */ 3029d0092544SSepherosa Ziehau /* Returns: */ 3030d0092544SSepherosa Ziehau /* Nothing. */ 3031d0092544SSepherosa Ziehau /****************************************************************************/ 3032d0092544SSepherosa Ziehau static void 3033d0092544SSepherosa Ziehau bce_init_cp_cpu(struct bce_softc *sc) 3034d0092544SSepherosa Ziehau { 3035d0092544SSepherosa Ziehau struct cpu_reg cpu_reg; 3036d0092544SSepherosa Ziehau struct fw_info fw; 3037d0092544SSepherosa Ziehau 3038d0092544SSepherosa Ziehau cpu_reg.mode = BCE_CP_CPU_MODE; 3039d0092544SSepherosa Ziehau cpu_reg.mode_value_halt = BCE_CP_CPU_MODE_SOFT_HALT; 3040d0092544SSepherosa Ziehau cpu_reg.mode_value_sstep = BCE_CP_CPU_MODE_STEP_ENA; 3041d0092544SSepherosa Ziehau cpu_reg.state = BCE_CP_CPU_STATE; 3042d0092544SSepherosa Ziehau cpu_reg.state_value_clear = 0xffffff; 3043d0092544SSepherosa Ziehau cpu_reg.gpr0 = BCE_CP_CPU_REG_FILE; 3044d0092544SSepherosa Ziehau cpu_reg.evmask = BCE_CP_CPU_EVENT_MASK; 3045d0092544SSepherosa Ziehau cpu_reg.pc = BCE_CP_CPU_PROGRAM_COUNTER; 3046d0092544SSepherosa Ziehau cpu_reg.inst = BCE_CP_CPU_INSTRUCTION; 3047d0092544SSepherosa Ziehau cpu_reg.bp = BCE_CP_CPU_HW_BREAKPOINT; 3048d0092544SSepherosa Ziehau cpu_reg.spad_base = BCE_CP_SCRATCH; 3049d0092544SSepherosa Ziehau cpu_reg.mips_view_base = 0x8000000; 3050d0092544SSepherosa Ziehau 3051d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 3052d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 3053d0092544SSepherosa Ziehau fw.ver_major = bce_CP_b09FwReleaseMajor; 3054d0092544SSepherosa Ziehau fw.ver_minor = bce_CP_b09FwReleaseMinor; 3055d0092544SSepherosa Ziehau fw.ver_fix = bce_CP_b09FwReleaseFix; 3056d0092544SSepherosa Ziehau fw.start_addr = bce_CP_b09FwStartAddr; 3057d0092544SSepherosa Ziehau 3058d0092544SSepherosa Ziehau fw.text_addr = bce_CP_b09FwTextAddr; 3059d0092544SSepherosa Ziehau fw.text_len = bce_CP_b09FwTextLen; 3060d0092544SSepherosa Ziehau fw.text_index = 0; 3061d0092544SSepherosa Ziehau fw.text = bce_CP_b09FwText; 3062d0092544SSepherosa Ziehau 3063d0092544SSepherosa Ziehau fw.data_addr = bce_CP_b09FwDataAddr; 3064d0092544SSepherosa Ziehau fw.data_len = bce_CP_b09FwDataLen; 3065d0092544SSepherosa Ziehau fw.data_index = 0; 3066d0092544SSepherosa Ziehau fw.data = bce_CP_b09FwData; 3067d0092544SSepherosa Ziehau 3068d0092544SSepherosa Ziehau fw.sbss_addr = bce_CP_b09FwSbssAddr; 3069d0092544SSepherosa Ziehau fw.sbss_len = bce_CP_b09FwSbssLen; 3070d0092544SSepherosa Ziehau fw.sbss_index = 0; 3071d0092544SSepherosa Ziehau fw.sbss = bce_CP_b09FwSbss; 3072d0092544SSepherosa Ziehau 3073d0092544SSepherosa Ziehau fw.bss_addr = bce_CP_b09FwBssAddr; 3074d0092544SSepherosa Ziehau fw.bss_len = bce_CP_b09FwBssLen; 3075d0092544SSepherosa Ziehau fw.bss_index = 0; 3076d0092544SSepherosa Ziehau fw.bss = bce_CP_b09FwBss; 3077d0092544SSepherosa Ziehau 3078d0092544SSepherosa Ziehau fw.rodata_addr = bce_CP_b09FwRodataAddr; 3079d0092544SSepherosa Ziehau fw.rodata_len = bce_CP_b09FwRodataLen; 3080d0092544SSepherosa Ziehau fw.rodata_index = 0; 3081d0092544SSepherosa Ziehau fw.rodata = bce_CP_b09FwRodata; 3082d0092544SSepherosa Ziehau } else { 3083d0092544SSepherosa Ziehau fw.ver_major = bce_CP_b06FwReleaseMajor; 3084d0092544SSepherosa Ziehau fw.ver_minor = bce_CP_b06FwReleaseMinor; 3085d0092544SSepherosa Ziehau fw.ver_fix = bce_CP_b06FwReleaseFix; 3086d0092544SSepherosa Ziehau fw.start_addr = bce_CP_b06FwStartAddr; 3087d0092544SSepherosa Ziehau 3088d0092544SSepherosa Ziehau fw.text_addr = bce_CP_b06FwTextAddr; 3089d0092544SSepherosa Ziehau fw.text_len = bce_CP_b06FwTextLen; 3090d0092544SSepherosa Ziehau fw.text_index = 0; 3091d0092544SSepherosa Ziehau fw.text = bce_CP_b06FwText; 3092d0092544SSepherosa Ziehau 3093d0092544SSepherosa Ziehau fw.data_addr = bce_CP_b06FwDataAddr; 3094d0092544SSepherosa Ziehau fw.data_len = bce_CP_b06FwDataLen; 3095d0092544SSepherosa Ziehau fw.data_index = 0; 3096d0092544SSepherosa Ziehau fw.data = bce_CP_b06FwData; 3097d0092544SSepherosa Ziehau 3098d0092544SSepherosa Ziehau fw.sbss_addr = bce_CP_b06FwSbssAddr; 3099d0092544SSepherosa Ziehau fw.sbss_len = bce_CP_b06FwSbssLen; 3100d0092544SSepherosa Ziehau fw.sbss_index = 0; 3101d0092544SSepherosa Ziehau fw.sbss = bce_CP_b06FwSbss; 3102d0092544SSepherosa Ziehau 3103d0092544SSepherosa Ziehau fw.bss_addr = bce_CP_b06FwBssAddr; 3104d0092544SSepherosa Ziehau fw.bss_len = bce_CP_b06FwBssLen; 3105d0092544SSepherosa Ziehau fw.bss_index = 0; 3106d0092544SSepherosa Ziehau fw.bss = bce_CP_b06FwBss; 3107d0092544SSepherosa Ziehau 3108d0092544SSepherosa Ziehau fw.rodata_addr = bce_CP_b06FwRodataAddr; 3109d0092544SSepherosa Ziehau fw.rodata_len = bce_CP_b06FwRodataLen; 3110d0092544SSepherosa Ziehau fw.rodata_index = 0; 3111d0092544SSepherosa Ziehau fw.rodata = bce_CP_b06FwRodata; 3112d0092544SSepherosa Ziehau } 3113d0092544SSepherosa Ziehau 3114d0092544SSepherosa Ziehau bce_load_cpu_fw(sc, &cpu_reg, &fw); 31155d05a208SSepherosa Ziehau bce_start_cpu(sc, &cpu_reg); 3116d0092544SSepherosa Ziehau } 3117d0092544SSepherosa Ziehau 3118d0092544SSepherosa Ziehau 3119d0092544SSepherosa Ziehau /****************************************************************************/ 3120d0092544SSepherosa Ziehau /* Initialize the COM CPU. */ 3121d0092544SSepherosa Ziehau /* */ 3122d0092544SSepherosa Ziehau /* Returns: */ 3123d0092544SSepherosa Ziehau /* Nothing. */ 3124d0092544SSepherosa Ziehau /****************************************************************************/ 3125d0092544SSepherosa Ziehau static void 3126d0092544SSepherosa Ziehau bce_init_com_cpu(struct bce_softc *sc) 3127d0092544SSepherosa Ziehau { 3128d0092544SSepherosa Ziehau struct cpu_reg cpu_reg; 3129d0092544SSepherosa Ziehau struct fw_info fw; 3130d0092544SSepherosa Ziehau 313143c2aeb0SSepherosa Ziehau cpu_reg.mode = BCE_COM_CPU_MODE; 313243c2aeb0SSepherosa Ziehau cpu_reg.mode_value_halt = BCE_COM_CPU_MODE_SOFT_HALT; 313343c2aeb0SSepherosa Ziehau cpu_reg.mode_value_sstep = BCE_COM_CPU_MODE_STEP_ENA; 313443c2aeb0SSepherosa Ziehau cpu_reg.state = BCE_COM_CPU_STATE; 313543c2aeb0SSepherosa Ziehau cpu_reg.state_value_clear = 0xffffff; 313643c2aeb0SSepherosa Ziehau cpu_reg.gpr0 = BCE_COM_CPU_REG_FILE; 313743c2aeb0SSepherosa Ziehau cpu_reg.evmask = BCE_COM_CPU_EVENT_MASK; 313843c2aeb0SSepherosa Ziehau cpu_reg.pc = BCE_COM_CPU_PROGRAM_COUNTER; 313943c2aeb0SSepherosa Ziehau cpu_reg.inst = BCE_COM_CPU_INSTRUCTION; 314043c2aeb0SSepherosa Ziehau cpu_reg.bp = BCE_COM_CPU_HW_BREAKPOINT; 314143c2aeb0SSepherosa Ziehau cpu_reg.spad_base = BCE_COM_SCRATCH; 314243c2aeb0SSepherosa Ziehau cpu_reg.mips_view_base = 0x8000000; 314343c2aeb0SSepherosa Ziehau 3144d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 3145d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 3146d0092544SSepherosa Ziehau fw.ver_major = bce_COM_b09FwReleaseMajor; 3147d0092544SSepherosa Ziehau fw.ver_minor = bce_COM_b09FwReleaseMinor; 3148d0092544SSepherosa Ziehau fw.ver_fix = bce_COM_b09FwReleaseFix; 3149d0092544SSepherosa Ziehau fw.start_addr = bce_COM_b09FwStartAddr; 3150d0092544SSepherosa Ziehau 3151d0092544SSepherosa Ziehau fw.text_addr = bce_COM_b09FwTextAddr; 3152d0092544SSepherosa Ziehau fw.text_len = bce_COM_b09FwTextLen; 3153d0092544SSepherosa Ziehau fw.text_index = 0; 3154d0092544SSepherosa Ziehau fw.text = bce_COM_b09FwText; 3155d0092544SSepherosa Ziehau 3156d0092544SSepherosa Ziehau fw.data_addr = bce_COM_b09FwDataAddr; 3157d0092544SSepherosa Ziehau fw.data_len = bce_COM_b09FwDataLen; 3158d0092544SSepherosa Ziehau fw.data_index = 0; 3159d0092544SSepherosa Ziehau fw.data = bce_COM_b09FwData; 3160d0092544SSepherosa Ziehau 3161d0092544SSepherosa Ziehau fw.sbss_addr = bce_COM_b09FwSbssAddr; 3162d0092544SSepherosa Ziehau fw.sbss_len = bce_COM_b09FwSbssLen; 3163d0092544SSepherosa Ziehau fw.sbss_index = 0; 3164d0092544SSepherosa Ziehau fw.sbss = bce_COM_b09FwSbss; 3165d0092544SSepherosa Ziehau 3166d0092544SSepherosa Ziehau fw.bss_addr = bce_COM_b09FwBssAddr; 3167d0092544SSepherosa Ziehau fw.bss_len = bce_COM_b09FwBssLen; 3168d0092544SSepherosa Ziehau fw.bss_index = 0; 3169d0092544SSepherosa Ziehau fw.bss = bce_COM_b09FwBss; 3170d0092544SSepherosa Ziehau 3171d0092544SSepherosa Ziehau fw.rodata_addr = bce_COM_b09FwRodataAddr; 3172d0092544SSepherosa Ziehau fw.rodata_len = bce_COM_b09FwRodataLen; 3173d0092544SSepherosa Ziehau fw.rodata_index = 0; 3174d0092544SSepherosa Ziehau fw.rodata = bce_COM_b09FwRodata; 3175d0092544SSepherosa Ziehau } else { 317643c2aeb0SSepherosa Ziehau fw.ver_major = bce_COM_b06FwReleaseMajor; 317743c2aeb0SSepherosa Ziehau fw.ver_minor = bce_COM_b06FwReleaseMinor; 317843c2aeb0SSepherosa Ziehau fw.ver_fix = bce_COM_b06FwReleaseFix; 317943c2aeb0SSepherosa Ziehau fw.start_addr = bce_COM_b06FwStartAddr; 318043c2aeb0SSepherosa Ziehau 318143c2aeb0SSepherosa Ziehau fw.text_addr = bce_COM_b06FwTextAddr; 318243c2aeb0SSepherosa Ziehau fw.text_len = bce_COM_b06FwTextLen; 318343c2aeb0SSepherosa Ziehau fw.text_index = 0; 318443c2aeb0SSepherosa Ziehau fw.text = bce_COM_b06FwText; 318543c2aeb0SSepherosa Ziehau 318643c2aeb0SSepherosa Ziehau fw.data_addr = bce_COM_b06FwDataAddr; 318743c2aeb0SSepherosa Ziehau fw.data_len = bce_COM_b06FwDataLen; 318843c2aeb0SSepherosa Ziehau fw.data_index = 0; 318943c2aeb0SSepherosa Ziehau fw.data = bce_COM_b06FwData; 319043c2aeb0SSepherosa Ziehau 319143c2aeb0SSepherosa Ziehau fw.sbss_addr = bce_COM_b06FwSbssAddr; 319243c2aeb0SSepherosa Ziehau fw.sbss_len = bce_COM_b06FwSbssLen; 319343c2aeb0SSepherosa Ziehau fw.sbss_index = 0; 319443c2aeb0SSepherosa Ziehau fw.sbss = bce_COM_b06FwSbss; 319543c2aeb0SSepherosa Ziehau 319643c2aeb0SSepherosa Ziehau fw.bss_addr = bce_COM_b06FwBssAddr; 319743c2aeb0SSepherosa Ziehau fw.bss_len = bce_COM_b06FwBssLen; 319843c2aeb0SSepherosa Ziehau fw.bss_index = 0; 319943c2aeb0SSepherosa Ziehau fw.bss = bce_COM_b06FwBss; 320043c2aeb0SSepherosa Ziehau 320143c2aeb0SSepherosa Ziehau fw.rodata_addr = bce_COM_b06FwRodataAddr; 320243c2aeb0SSepherosa Ziehau fw.rodata_len = bce_COM_b06FwRodataLen; 320343c2aeb0SSepherosa Ziehau fw.rodata_index = 0; 320443c2aeb0SSepherosa Ziehau fw.rodata = bce_COM_b06FwRodata; 3205d0092544SSepherosa Ziehau } 320643c2aeb0SSepherosa Ziehau 320743c2aeb0SSepherosa Ziehau bce_load_cpu_fw(sc, &cpu_reg, &fw); 32085d05a208SSepherosa Ziehau bce_start_cpu(sc, &cpu_reg); 320943c2aeb0SSepherosa Ziehau } 321043c2aeb0SSepherosa Ziehau 321143c2aeb0SSepherosa Ziehau 321243c2aeb0SSepherosa Ziehau /****************************************************************************/ 3213d0092544SSepherosa Ziehau /* Initialize the RV2P, RX, TX, TPAT, COM, and CP CPUs. */ 3214d0092544SSepherosa Ziehau /* */ 3215d0092544SSepherosa Ziehau /* Loads the firmware for each CPU and starts the CPU. */ 3216d0092544SSepherosa Ziehau /* */ 3217d0092544SSepherosa Ziehau /* Returns: */ 3218d0092544SSepherosa Ziehau /* Nothing. */ 3219d0092544SSepherosa Ziehau /****************************************************************************/ 3220d0092544SSepherosa Ziehau static void 3221d0092544SSepherosa Ziehau bce_init_cpus(struct bce_softc *sc) 3222d0092544SSepherosa Ziehau { 3223d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 3224d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 3225cff16e71SSepherosa Ziehau if (BCE_CHIP_REV(sc) == BCE_CHIP_REV_Ax) { 3226cff16e71SSepherosa Ziehau bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc1, 3227cff16e71SSepherosa Ziehau sizeof(bce_xi90_rv2p_proc1), RV2P_PROC1); 3228cff16e71SSepherosa Ziehau bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc2, 3229cff16e71SSepherosa Ziehau sizeof(bce_xi90_rv2p_proc2), RV2P_PROC2); 3230d0092544SSepherosa Ziehau } else { 3231cff16e71SSepherosa Ziehau bce_load_rv2p_fw(sc, bce_xi_rv2p_proc1, 3232cff16e71SSepherosa Ziehau sizeof(bce_xi_rv2p_proc1), RV2P_PROC1); 3233cff16e71SSepherosa Ziehau bce_load_rv2p_fw(sc, bce_xi_rv2p_proc2, 3234cff16e71SSepherosa Ziehau sizeof(bce_xi_rv2p_proc2), RV2P_PROC2); 3235cff16e71SSepherosa Ziehau } 3236cff16e71SSepherosa Ziehau } else { 3237cff16e71SSepherosa Ziehau bce_load_rv2p_fw(sc, bce_rv2p_proc1, 3238cff16e71SSepherosa Ziehau sizeof(bce_rv2p_proc1), RV2P_PROC1); 3239cff16e71SSepherosa Ziehau bce_load_rv2p_fw(sc, bce_rv2p_proc2, 3240cff16e71SSepherosa Ziehau sizeof(bce_rv2p_proc2), RV2P_PROC2); 3241d0092544SSepherosa Ziehau } 3242d0092544SSepherosa Ziehau 3243d0092544SSepherosa Ziehau bce_init_rxp_cpu(sc); 3244d0092544SSepherosa Ziehau bce_init_txp_cpu(sc); 3245d0092544SSepherosa Ziehau bce_init_tpat_cpu(sc); 3246d0092544SSepherosa Ziehau bce_init_com_cpu(sc); 3247d0092544SSepherosa Ziehau bce_init_cp_cpu(sc); 3248d0092544SSepherosa Ziehau } 3249d0092544SSepherosa Ziehau 3250d0092544SSepherosa Ziehau 3251d0092544SSepherosa Ziehau /****************************************************************************/ 325243c2aeb0SSepherosa Ziehau /* Initialize context memory. */ 325343c2aeb0SSepherosa Ziehau /* */ 325443c2aeb0SSepherosa Ziehau /* Clears the memory associated with each Context ID (CID). */ 325543c2aeb0SSepherosa Ziehau /* */ 325643c2aeb0SSepherosa Ziehau /* Returns: */ 325743c2aeb0SSepherosa Ziehau /* Nothing. */ 325843c2aeb0SSepherosa Ziehau /****************************************************************************/ 32595b609aa3SSepherosa Ziehau static int 32603a41a80bSSepherosa Ziehau bce_init_ctx(struct bce_softc *sc) 326143c2aeb0SSepherosa Ziehau { 3262d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 3263d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 3264d0092544SSepherosa Ziehau /* DRC: Replace this constant value with a #define. */ 3265d0092544SSepherosa Ziehau int i, retry_cnt = 10; 3266d0092544SSepherosa Ziehau uint32_t val; 326743c2aeb0SSepherosa Ziehau 3268d0092544SSepherosa Ziehau /* 3269d0092544SSepherosa Ziehau * BCM5709 context memory may be cached 3270d0092544SSepherosa Ziehau * in host memory so prepare the host memory 3271d0092544SSepherosa Ziehau * for access. 3272d0092544SSepherosa Ziehau */ 3273d0092544SSepherosa Ziehau val = BCE_CTX_COMMAND_ENABLED | BCE_CTX_COMMAND_MEM_INIT | 3274d0092544SSepherosa Ziehau (1 << 12); 3275d0092544SSepherosa Ziehau val |= (BCM_PAGE_BITS - 8) << 16; 3276d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_COMMAND, val); 327743c2aeb0SSepherosa Ziehau 3278d0092544SSepherosa Ziehau /* Wait for mem init command to complete. */ 3279d0092544SSepherosa Ziehau for (i = 0; i < retry_cnt; i++) { 3280d0092544SSepherosa Ziehau val = REG_RD(sc, BCE_CTX_COMMAND); 3281d0092544SSepherosa Ziehau if (!(val & BCE_CTX_COMMAND_MEM_INIT)) 3282d0092544SSepherosa Ziehau break; 3283d0092544SSepherosa Ziehau DELAY(2); 3284d0092544SSepherosa Ziehau } 32855b609aa3SSepherosa Ziehau if (i == retry_cnt) { 32865b609aa3SSepherosa Ziehau device_printf(sc->bce_dev, 32875b609aa3SSepherosa Ziehau "Context memory initialization failed!\n"); 32885b609aa3SSepherosa Ziehau return ETIMEDOUT; 32895b609aa3SSepherosa Ziehau } 329043c2aeb0SSepherosa Ziehau 3291d0092544SSepherosa Ziehau for (i = 0; i < sc->ctx_pages; i++) { 3292d0092544SSepherosa Ziehau int j; 329343c2aeb0SSepherosa Ziehau 3294d0092544SSepherosa Ziehau /* 3295d0092544SSepherosa Ziehau * Set the physical address of the context 3296d0092544SSepherosa Ziehau * memory cache. 3297d0092544SSepherosa Ziehau */ 3298d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_HOST_PAGE_TBL_DATA0, 3299d0092544SSepherosa Ziehau BCE_ADDR_LO(sc->ctx_paddr[i] & 0xfffffff0) | 3300d0092544SSepherosa Ziehau BCE_CTX_HOST_PAGE_TBL_DATA0_VALID); 3301d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_HOST_PAGE_TBL_DATA1, 3302d0092544SSepherosa Ziehau BCE_ADDR_HI(sc->ctx_paddr[i])); 3303d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_HOST_PAGE_TBL_CTRL, 3304d0092544SSepherosa Ziehau i | BCE_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ); 3305d0092544SSepherosa Ziehau 3306d0092544SSepherosa Ziehau /* 3307d0092544SSepherosa Ziehau * Verify that the context memory write was successful. 3308d0092544SSepherosa Ziehau */ 3309d0092544SSepherosa Ziehau for (j = 0; j < retry_cnt; j++) { 3310d0092544SSepherosa Ziehau val = REG_RD(sc, BCE_CTX_HOST_PAGE_TBL_CTRL); 3311d0092544SSepherosa Ziehau if ((val & 3312d0092544SSepherosa Ziehau BCE_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) == 0) 3313d0092544SSepherosa Ziehau break; 3314d0092544SSepherosa Ziehau DELAY(5); 3315d0092544SSepherosa Ziehau } 33165b609aa3SSepherosa Ziehau if (j == retry_cnt) { 33175b609aa3SSepherosa Ziehau device_printf(sc->bce_dev, 33185b609aa3SSepherosa Ziehau "Failed to initialize context page!\n"); 33195b609aa3SSepherosa Ziehau return ETIMEDOUT; 33205b609aa3SSepherosa Ziehau } 3321d0092544SSepherosa Ziehau } 3322d0092544SSepherosa Ziehau } else { 3323d0092544SSepherosa Ziehau uint32_t vcid_addr, offset; 3324d0092544SSepherosa Ziehau 3325d0092544SSepherosa Ziehau /* 3326d0092544SSepherosa Ziehau * For the 5706/5708, context memory is local to 3327d0092544SSepherosa Ziehau * the controller, so initialize the controller 3328d0092544SSepherosa Ziehau * context memory. 3329d0092544SSepherosa Ziehau */ 3330d0092544SSepherosa Ziehau 3331d0092544SSepherosa Ziehau vcid_addr = GET_CID_ADDR(96); 3332d0092544SSepherosa Ziehau while (vcid_addr) { 3333d0092544SSepherosa Ziehau vcid_addr -= PHY_CTX_SIZE; 3334d0092544SSepherosa Ziehau 3335d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_VIRT_ADDR, 0); 3336d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_PAGE_TBL, vcid_addr); 3337d0092544SSepherosa Ziehau 3338d0092544SSepherosa Ziehau for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) 3339d0092544SSepherosa Ziehau CTX_WR(sc, 0x00, offset, 0); 33403a41a80bSSepherosa Ziehau 33413a41a80bSSepherosa Ziehau REG_WR(sc, BCE_CTX_VIRT_ADDR, vcid_addr); 3342d0092544SSepherosa Ziehau REG_WR(sc, BCE_CTX_PAGE_TBL, vcid_addr); 33433a41a80bSSepherosa Ziehau } 334443c2aeb0SSepherosa Ziehau } 33455b609aa3SSepherosa Ziehau return 0; 334643c2aeb0SSepherosa Ziehau } 334743c2aeb0SSepherosa Ziehau 334843c2aeb0SSepherosa Ziehau 334943c2aeb0SSepherosa Ziehau /****************************************************************************/ 335043c2aeb0SSepherosa Ziehau /* Fetch the permanent MAC address of the controller. */ 335143c2aeb0SSepherosa Ziehau /* */ 335243c2aeb0SSepherosa Ziehau /* Returns: */ 335343c2aeb0SSepherosa Ziehau /* Nothing. */ 335443c2aeb0SSepherosa Ziehau /****************************************************************************/ 335543c2aeb0SSepherosa Ziehau static void 335643c2aeb0SSepherosa Ziehau bce_get_mac_addr(struct bce_softc *sc) 335743c2aeb0SSepherosa Ziehau { 335843c2aeb0SSepherosa Ziehau uint32_t mac_lo = 0, mac_hi = 0; 33593970c114SSepherosa Ziehau 336043c2aeb0SSepherosa Ziehau /* 336143c2aeb0SSepherosa Ziehau * The NetXtreme II bootcode populates various NIC 336243c2aeb0SSepherosa Ziehau * power-on and runtime configuration items in a 336343c2aeb0SSepherosa Ziehau * shared memory area. The factory configured MAC 336443c2aeb0SSepherosa Ziehau * address is available from both NVRAM and the 336543c2aeb0SSepherosa Ziehau * shared memory area so we'll read the value from 336643c2aeb0SSepherosa Ziehau * shared memory for speed. 336743c2aeb0SSepherosa Ziehau */ 336843c2aeb0SSepherosa Ziehau 3369bc30d40dSSepherosa Ziehau mac_hi = bce_shmem_rd(sc, BCE_PORT_HW_CFG_MAC_UPPER); 3370bc30d40dSSepherosa Ziehau mac_lo = bce_shmem_rd(sc, BCE_PORT_HW_CFG_MAC_LOWER); 337143c2aeb0SSepherosa Ziehau 337243c2aeb0SSepherosa Ziehau if (mac_lo == 0 && mac_hi == 0) { 337343c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Invalid Ethernet address!\n"); 337443c2aeb0SSepherosa Ziehau } else { 337543c2aeb0SSepherosa Ziehau sc->eaddr[0] = (u_char)(mac_hi >> 8); 337643c2aeb0SSepherosa Ziehau sc->eaddr[1] = (u_char)(mac_hi >> 0); 337743c2aeb0SSepherosa Ziehau sc->eaddr[2] = (u_char)(mac_lo >> 24); 337843c2aeb0SSepherosa Ziehau sc->eaddr[3] = (u_char)(mac_lo >> 16); 337943c2aeb0SSepherosa Ziehau sc->eaddr[4] = (u_char)(mac_lo >> 8); 338043c2aeb0SSepherosa Ziehau sc->eaddr[5] = (u_char)(mac_lo >> 0); 338143c2aeb0SSepherosa Ziehau } 338243c2aeb0SSepherosa Ziehau } 338343c2aeb0SSepherosa Ziehau 338443c2aeb0SSepherosa Ziehau 338543c2aeb0SSepherosa Ziehau /****************************************************************************/ 338643c2aeb0SSepherosa Ziehau /* Program the MAC address. */ 338743c2aeb0SSepherosa Ziehau /* */ 338843c2aeb0SSepherosa Ziehau /* Returns: */ 338943c2aeb0SSepherosa Ziehau /* Nothing. */ 339043c2aeb0SSepherosa Ziehau /****************************************************************************/ 339143c2aeb0SSepherosa Ziehau static void 339243c2aeb0SSepherosa Ziehau bce_set_mac_addr(struct bce_softc *sc) 339343c2aeb0SSepherosa Ziehau { 339443c2aeb0SSepherosa Ziehau const uint8_t *mac_addr = sc->eaddr; 339543c2aeb0SSepherosa Ziehau uint32_t val; 339643c2aeb0SSepherosa Ziehau 339743c2aeb0SSepherosa Ziehau val = (mac_addr[0] << 8) | mac_addr[1]; 339843c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MAC_MATCH0, val); 339943c2aeb0SSepherosa Ziehau 340043c2aeb0SSepherosa Ziehau val = (mac_addr[2] << 24) | 340143c2aeb0SSepherosa Ziehau (mac_addr[3] << 16) | 340243c2aeb0SSepherosa Ziehau (mac_addr[4] << 8) | 340343c2aeb0SSepherosa Ziehau mac_addr[5]; 340443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MAC_MATCH1, val); 340543c2aeb0SSepherosa Ziehau } 340643c2aeb0SSepherosa Ziehau 340743c2aeb0SSepherosa Ziehau 340843c2aeb0SSepherosa Ziehau /****************************************************************************/ 340943c2aeb0SSepherosa Ziehau /* Stop the controller. */ 341043c2aeb0SSepherosa Ziehau /* */ 341143c2aeb0SSepherosa Ziehau /* Returns: */ 341243c2aeb0SSepherosa Ziehau /* Nothing. */ 341343c2aeb0SSepherosa Ziehau /****************************************************************************/ 341443c2aeb0SSepherosa Ziehau static void 341543c2aeb0SSepherosa Ziehau bce_stop(struct bce_softc *sc) 341643c2aeb0SSepherosa Ziehau { 341743c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 341810bcbdabSSepherosa Ziehau int i; 341943c2aeb0SSepherosa Ziehau 342084464af5SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 342143c2aeb0SSepherosa Ziehau 3422d0092544SSepherosa Ziehau callout_stop(&sc->bce_tick_callout); 342343c2aeb0SSepherosa Ziehau 342443c2aeb0SSepherosa Ziehau /* Disable the transmit/receive blocks. */ 3425d0092544SSepherosa Ziehau REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS, BCE_MISC_ENABLE_CLR_DEFAULT); 342643c2aeb0SSepherosa Ziehau REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS); 342743c2aeb0SSepherosa Ziehau DELAY(20); 342843c2aeb0SSepherosa Ziehau 342943c2aeb0SSepherosa Ziehau bce_disable_intr(sc); 343043c2aeb0SSepherosa Ziehau 343143c2aeb0SSepherosa Ziehau /* Free the RX lists. */ 343208b64767SSepherosa Ziehau for (i = 0; i < sc->ring_cnt; ++i) 343308b64767SSepherosa Ziehau bce_free_rx_chain(&sc->rx_rings[i]); 343443c2aeb0SSepherosa Ziehau 343543c2aeb0SSepherosa Ziehau /* Free TX buffers. */ 343610bcbdabSSepherosa Ziehau for (i = 0; i < sc->ring_cnt; ++i) 343710bcbdabSSepherosa Ziehau bce_free_tx_chain(&sc->tx_rings[i]); 343843c2aeb0SSepherosa Ziehau 343943c2aeb0SSepherosa Ziehau sc->bce_link = 0; 3440bdeb8fffSSepherosa Ziehau sc->bce_coalchg_mask = 0; 344143c2aeb0SSepherosa Ziehau 34429ed293e0SSepherosa Ziehau ifp->if_flags &= ~IFF_RUNNING; 34439ed293e0SSepherosa Ziehau ifq_clr_oactive(&ifp->if_snd); 344443c2aeb0SSepherosa Ziehau ifp->if_timer = 0; 344543c2aeb0SSepherosa Ziehau } 344643c2aeb0SSepherosa Ziehau 344743c2aeb0SSepherosa Ziehau 344843c2aeb0SSepherosa Ziehau static int 344943c2aeb0SSepherosa Ziehau bce_reset(struct bce_softc *sc, uint32_t reset_code) 345043c2aeb0SSepherosa Ziehau { 345143c2aeb0SSepherosa Ziehau uint32_t val; 345243c2aeb0SSepherosa Ziehau int i, rc = 0; 345343c2aeb0SSepherosa Ziehau 345443c2aeb0SSepherosa Ziehau /* Wait for pending PCI transactions to complete. */ 345543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS, 345643c2aeb0SSepherosa Ziehau BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | 345743c2aeb0SSepherosa Ziehau BCE_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | 345843c2aeb0SSepherosa Ziehau BCE_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | 345943c2aeb0SSepherosa Ziehau BCE_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); 346043c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS); 346143c2aeb0SSepherosa Ziehau DELAY(5); 346243c2aeb0SSepherosa Ziehau 3463d0092544SSepherosa Ziehau /* Disable DMA */ 3464d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 3465d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 3466d0092544SSepherosa Ziehau val = REG_RD(sc, BCE_MISC_NEW_CORE_CTL); 3467d0092544SSepherosa Ziehau val &= ~BCE_MISC_NEW_CORE_CTL_DMA_ENABLE; 3468d0092544SSepherosa Ziehau REG_WR(sc, BCE_MISC_NEW_CORE_CTL, val); 3469d0092544SSepherosa Ziehau } 3470d0092544SSepherosa Ziehau 347143c2aeb0SSepherosa Ziehau /* Assume bootcode is running. */ 347243c2aeb0SSepherosa Ziehau sc->bce_fw_timed_out = 0; 3473d8870c52SSepherosa Ziehau sc->bce_drv_cardiac_arrest = 0; 347443c2aeb0SSepherosa Ziehau 347543c2aeb0SSepherosa Ziehau /* Give the firmware a chance to prepare for the reset. */ 347643c2aeb0SSepherosa Ziehau rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT0 | reset_code); 347743c2aeb0SSepherosa Ziehau if (rc) { 347843c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 347943c2aeb0SSepherosa Ziehau "Firmware is not ready for reset\n"); 348043c2aeb0SSepherosa Ziehau return rc; 348143c2aeb0SSepherosa Ziehau } 348243c2aeb0SSepherosa Ziehau 348343c2aeb0SSepherosa Ziehau /* Set a firmware reminder that this is a soft reset. */ 3484bc30d40dSSepherosa Ziehau bce_shmem_wr(sc, BCE_DRV_RESET_SIGNATURE, 348543c2aeb0SSepherosa Ziehau BCE_DRV_RESET_SIGNATURE_MAGIC); 348643c2aeb0SSepherosa Ziehau 348743c2aeb0SSepherosa Ziehau /* Dummy read to force the chip to complete all current transactions. */ 348843c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_MISC_ID); 348943c2aeb0SSepherosa Ziehau 349043c2aeb0SSepherosa Ziehau /* Chip reset. */ 3491d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 3492d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 3493d0092544SSepherosa Ziehau REG_WR(sc, BCE_MISC_COMMAND, BCE_MISC_COMMAND_SW_RESET); 3494d0092544SSepherosa Ziehau REG_RD(sc, BCE_MISC_COMMAND); 3495d0092544SSepherosa Ziehau DELAY(5); 3496d0092544SSepherosa Ziehau 3497d0092544SSepherosa Ziehau val = BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | 3498d0092544SSepherosa Ziehau BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; 3499d0092544SSepherosa Ziehau 3500d0092544SSepherosa Ziehau pci_write_config(sc->bce_dev, BCE_PCICFG_MISC_CONFIG, val, 4); 3501d0092544SSepherosa Ziehau } else { 350243c2aeb0SSepherosa Ziehau val = BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ | 350343c2aeb0SSepherosa Ziehau BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | 350443c2aeb0SSepherosa Ziehau BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; 350543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_PCICFG_MISC_CONFIG, val); 350643c2aeb0SSepherosa Ziehau 350743c2aeb0SSepherosa Ziehau /* Allow up to 30us for reset to complete. */ 350843c2aeb0SSepherosa Ziehau for (i = 0; i < 10; i++) { 350943c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_PCICFG_MISC_CONFIG); 351043c2aeb0SSepherosa Ziehau if ((val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ | 3511d0092544SSepherosa Ziehau BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) 351243c2aeb0SSepherosa Ziehau break; 351343c2aeb0SSepherosa Ziehau DELAY(10); 351443c2aeb0SSepherosa Ziehau } 351543c2aeb0SSepherosa Ziehau 351643c2aeb0SSepherosa Ziehau /* Check that reset completed successfully. */ 351743c2aeb0SSepherosa Ziehau if (val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ | 351843c2aeb0SSepherosa Ziehau BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) { 351943c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Reset failed!\n"); 352043c2aeb0SSepherosa Ziehau return EBUSY; 352143c2aeb0SSepherosa Ziehau } 3522d0092544SSepherosa Ziehau } 352343c2aeb0SSepherosa Ziehau 352443c2aeb0SSepherosa Ziehau /* Make sure byte swapping is properly configured. */ 352543c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_PCI_SWAP_DIAG0); 352643c2aeb0SSepherosa Ziehau if (val != 0x01020304) { 352743c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Byte swap is incorrect!\n"); 352843c2aeb0SSepherosa Ziehau return ENODEV; 352943c2aeb0SSepherosa Ziehau } 353043c2aeb0SSepherosa Ziehau 353143c2aeb0SSepherosa Ziehau /* Just completed a reset, assume that firmware is running again. */ 353243c2aeb0SSepherosa Ziehau sc->bce_fw_timed_out = 0; 3533d8870c52SSepherosa Ziehau sc->bce_drv_cardiac_arrest = 0; 353443c2aeb0SSepherosa Ziehau 353543c2aeb0SSepherosa Ziehau /* Wait for the firmware to finish its initialization. */ 353643c2aeb0SSepherosa Ziehau rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT1 | reset_code); 353743c2aeb0SSepherosa Ziehau if (rc) { 353843c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 353943c2aeb0SSepherosa Ziehau "Firmware did not complete initialization!\n"); 354043c2aeb0SSepherosa Ziehau } 354143c2aeb0SSepherosa Ziehau return rc; 354243c2aeb0SSepherosa Ziehau } 354343c2aeb0SSepherosa Ziehau 354443c2aeb0SSepherosa Ziehau 354543c2aeb0SSepherosa Ziehau static int 354643c2aeb0SSepherosa Ziehau bce_chipinit(struct bce_softc *sc) 354743c2aeb0SSepherosa Ziehau { 354843c2aeb0SSepherosa Ziehau uint32_t val; 354943c2aeb0SSepherosa Ziehau int rc = 0; 355043c2aeb0SSepherosa Ziehau 355143c2aeb0SSepherosa Ziehau /* Make sure the interrupt is not active. */ 355243c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, BCE_PCICFG_INT_ACK_CMD_MASK_INT); 3553d0092544SSepherosa Ziehau REG_RD(sc, BCE_PCICFG_INT_ACK_CMD); 355443c2aeb0SSepherosa Ziehau 355543c2aeb0SSepherosa Ziehau /* 355643c2aeb0SSepherosa Ziehau * Initialize DMA byte/word swapping, configure the number of DMA 355743c2aeb0SSepherosa Ziehau * channels and PCI clock compensation delay. 355843c2aeb0SSepherosa Ziehau */ 355943c2aeb0SSepherosa Ziehau val = BCE_DMA_CONFIG_DATA_BYTE_SWAP | 356043c2aeb0SSepherosa Ziehau BCE_DMA_CONFIG_DATA_WORD_SWAP | 356143c2aeb0SSepherosa Ziehau #if BYTE_ORDER == BIG_ENDIAN 356243c2aeb0SSepherosa Ziehau BCE_DMA_CONFIG_CNTL_BYTE_SWAP | 356343c2aeb0SSepherosa Ziehau #endif 356443c2aeb0SSepherosa Ziehau BCE_DMA_CONFIG_CNTL_WORD_SWAP | 356543c2aeb0SSepherosa Ziehau DMA_READ_CHANS << 12 | 356643c2aeb0SSepherosa Ziehau DMA_WRITE_CHANS << 16; 356743c2aeb0SSepherosa Ziehau 356843c2aeb0SSepherosa Ziehau val |= (0x2 << 20) | BCE_DMA_CONFIG_CNTL_PCI_COMP_DLY; 356943c2aeb0SSepherosa Ziehau 357043c2aeb0SSepherosa Ziehau if ((sc->bce_flags & BCE_PCIX_FLAG) && sc->bus_speed_mhz == 133) 357143c2aeb0SSepherosa Ziehau val |= BCE_DMA_CONFIG_PCI_FAST_CLK_CMP; 357243c2aeb0SSepherosa Ziehau 357343c2aeb0SSepherosa Ziehau /* 357443c2aeb0SSepherosa Ziehau * This setting resolves a problem observed on certain Intel PCI 357543c2aeb0SSepherosa Ziehau * chipsets that cannot handle multiple outstanding DMA operations. 357643c2aeb0SSepherosa Ziehau * See errata E9_5706A1_65. 357743c2aeb0SSepherosa Ziehau */ 357843c2aeb0SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706 && 357943c2aeb0SSepherosa Ziehau BCE_CHIP_ID(sc) != BCE_CHIP_ID_5706_A0 && 358043c2aeb0SSepherosa Ziehau !(sc->bce_flags & BCE_PCIX_FLAG)) 358143c2aeb0SSepherosa Ziehau val |= BCE_DMA_CONFIG_CNTL_PING_PONG_DMA; 358243c2aeb0SSepherosa Ziehau 358343c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_DMA_CONFIG, val); 358443c2aeb0SSepherosa Ziehau 358543c2aeb0SSepherosa Ziehau /* Enable the RX_V2P and Context state machines before access. */ 358643c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, 358743c2aeb0SSepherosa Ziehau BCE_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE | 358843c2aeb0SSepherosa Ziehau BCE_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE | 358943c2aeb0SSepherosa Ziehau BCE_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE); 359043c2aeb0SSepherosa Ziehau 359143c2aeb0SSepherosa Ziehau /* Initialize context mapping and zero out the quick contexts. */ 35925b609aa3SSepherosa Ziehau rc = bce_init_ctx(sc); 35935b609aa3SSepherosa Ziehau if (rc != 0) 35945b609aa3SSepherosa Ziehau return rc; 359543c2aeb0SSepherosa Ziehau 359643c2aeb0SSepherosa Ziehau /* Initialize the on-boards CPUs */ 359743c2aeb0SSepherosa Ziehau bce_init_cpus(sc); 359843c2aeb0SSepherosa Ziehau 35995d05a208SSepherosa Ziehau /* Enable management frames (NC-SI) to flow to the MCP. */ 36005d05a208SSepherosa Ziehau if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) { 36015d05a208SSepherosa Ziehau val = REG_RD(sc, BCE_RPM_MGMT_PKT_CTRL) | 36025d05a208SSepherosa Ziehau BCE_RPM_MGMT_PKT_CTRL_MGMT_EN; 36035d05a208SSepherosa Ziehau REG_WR(sc, BCE_RPM_MGMT_PKT_CTRL, val); 36045d05a208SSepherosa Ziehau } 36055d05a208SSepherosa Ziehau 360643c2aeb0SSepherosa Ziehau /* Prepare NVRAM for access. */ 360743c2aeb0SSepherosa Ziehau rc = bce_init_nvram(sc); 360843c2aeb0SSepherosa Ziehau if (rc != 0) 360943c2aeb0SSepherosa Ziehau return rc; 361043c2aeb0SSepherosa Ziehau 361143c2aeb0SSepherosa Ziehau /* Set the kernel bypass block size */ 361243c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_MQ_CONFIG); 361343c2aeb0SSepherosa Ziehau val &= ~BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE; 361443c2aeb0SSepherosa Ziehau val |= BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE_256; 3615d0092544SSepherosa Ziehau 3616d0092544SSepherosa Ziehau /* Enable bins used on the 5709/5716. */ 3617d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 3618d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 3619d0092544SSepherosa Ziehau val |= BCE_MQ_CONFIG_BIN_MQ_MODE; 3620d0092544SSepherosa Ziehau if (BCE_CHIP_ID(sc) == BCE_CHIP_ID_5709_A1) 3621d0092544SSepherosa Ziehau val |= BCE_MQ_CONFIG_HALT_DIS; 3622d0092544SSepherosa Ziehau } 3623d0092544SSepherosa Ziehau 362443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_MQ_CONFIG, val); 362543c2aeb0SSepherosa Ziehau 362643c2aeb0SSepherosa Ziehau val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE); 362743c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_MQ_KNL_BYP_WIND_START, val); 362843c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_MQ_KNL_WIND_END, val); 362943c2aeb0SSepherosa Ziehau 363043c2aeb0SSepherosa Ziehau /* Set the page size and clear the RV2P processor stall bits. */ 363143c2aeb0SSepherosa Ziehau val = (BCM_PAGE_BITS - 8) << 24; 363243c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RV2P_CONFIG, val); 363343c2aeb0SSepherosa Ziehau 363443c2aeb0SSepherosa Ziehau /* Configure page size. */ 363543c2aeb0SSepherosa Ziehau val = REG_RD(sc, BCE_TBDR_CONFIG); 363643c2aeb0SSepherosa Ziehau val &= ~BCE_TBDR_CONFIG_PAGE_SIZE; 363743c2aeb0SSepherosa Ziehau val |= (BCM_PAGE_BITS - 8) << 24 | 0x40; 363843c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_TBDR_CONFIG, val); 363943c2aeb0SSepherosa Ziehau 3640d0092544SSepherosa Ziehau /* Set the perfect match control register to default. */ 3641d0092544SSepherosa Ziehau REG_WR_IND(sc, BCE_RXP_PM_CTRL, 0); 3642d0092544SSepherosa Ziehau 364343c2aeb0SSepherosa Ziehau return 0; 364443c2aeb0SSepherosa Ziehau } 364543c2aeb0SSepherosa Ziehau 364643c2aeb0SSepherosa Ziehau 364743c2aeb0SSepherosa Ziehau /****************************************************************************/ 364843c2aeb0SSepherosa Ziehau /* Initialize the controller in preparation to send/receive traffic. */ 364943c2aeb0SSepherosa Ziehau /* */ 365043c2aeb0SSepherosa Ziehau /* Returns: */ 365143c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 365243c2aeb0SSepherosa Ziehau /****************************************************************************/ 365343c2aeb0SSepherosa Ziehau static int 365443c2aeb0SSepherosa Ziehau bce_blockinit(struct bce_softc *sc) 365543c2aeb0SSepherosa Ziehau { 365643c2aeb0SSepherosa Ziehau uint32_t reg, val; 365743c2aeb0SSepherosa Ziehau 365843c2aeb0SSepherosa Ziehau /* Load the hardware default MAC address. */ 365943c2aeb0SSepherosa Ziehau bce_set_mac_addr(sc); 366043c2aeb0SSepherosa Ziehau 366143c2aeb0SSepherosa Ziehau /* Set the Ethernet backoff seed value */ 366243c2aeb0SSepherosa Ziehau val = sc->eaddr[0] + (sc->eaddr[1] << 8) + (sc->eaddr[2] << 16) + 366343c2aeb0SSepherosa Ziehau sc->eaddr[3] + (sc->eaddr[4] << 8) + (sc->eaddr[5] << 16); 366443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_BACKOFF_SEED, val); 366543c2aeb0SSepherosa Ziehau 366643c2aeb0SSepherosa Ziehau sc->last_status_idx = 0; 366743c2aeb0SSepherosa Ziehau sc->rx_mode = BCE_EMAC_RX_MODE_SORT_MODE; 366843c2aeb0SSepherosa Ziehau 366943c2aeb0SSepherosa Ziehau /* Set up link change interrupt generation. */ 367043c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_ATTENTION_ENA, BCE_EMAC_ATTENTION_ENA_LINK); 367143c2aeb0SSepherosa Ziehau 367243c2aeb0SSepherosa Ziehau /* Program the physical address of the status block. */ 367343c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_STATUS_ADDR_L, BCE_ADDR_LO(sc->status_block_paddr)); 367443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_STATUS_ADDR_H, BCE_ADDR_HI(sc->status_block_paddr)); 367543c2aeb0SSepherosa Ziehau 367643c2aeb0SSepherosa Ziehau /* Program the physical address of the statistics block. */ 367743c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_STATISTICS_ADDR_L, 367843c2aeb0SSepherosa Ziehau BCE_ADDR_LO(sc->stats_block_paddr)); 367943c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_STATISTICS_ADDR_H, 368043c2aeb0SSepherosa Ziehau BCE_ADDR_HI(sc->stats_block_paddr)); 368143c2aeb0SSepherosa Ziehau 368243c2aeb0SSepherosa Ziehau /* Program various host coalescing parameters. */ 368343c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, 368443c2aeb0SSepherosa Ziehau (sc->bce_tx_quick_cons_trip_int << 16) | 368543c2aeb0SSepherosa Ziehau sc->bce_tx_quick_cons_trip); 368643c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, 368743c2aeb0SSepherosa Ziehau (sc->bce_rx_quick_cons_trip_int << 16) | 368843c2aeb0SSepherosa Ziehau sc->bce_rx_quick_cons_trip); 368943c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_COMP_PROD_TRIP, 369043c2aeb0SSepherosa Ziehau (sc->bce_comp_prod_trip_int << 16) | sc->bce_comp_prod_trip); 369143c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_TX_TICKS, 369243c2aeb0SSepherosa Ziehau (sc->bce_tx_ticks_int << 16) | sc->bce_tx_ticks); 369343c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_RX_TICKS, 369443c2aeb0SSepherosa Ziehau (sc->bce_rx_ticks_int << 16) | sc->bce_rx_ticks); 369543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_COM_TICKS, 369643c2aeb0SSepherosa Ziehau (sc->bce_com_ticks_int << 16) | sc->bce_com_ticks); 369743c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_CMD_TICKS, 369843c2aeb0SSepherosa Ziehau (sc->bce_cmd_ticks_int << 16) | sc->bce_cmd_ticks); 369943c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_STATS_TICKS, (sc->bce_stats_ticks & 0xffff00)); 370043c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ 3701eac57ffbSSepherosa Ziehau 3702eac57ffbSSepherosa Ziehau val = BCE_HC_CONFIG_TX_TMR_MODE | BCE_HC_CONFIG_COLLECT_STATS; 3703eac57ffbSSepherosa Ziehau if (sc->bce_flags & BCE_ONESHOT_MSI_FLAG) { 3704eac57ffbSSepherosa Ziehau if (bootverbose) 3705eac57ffbSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "oneshot MSI\n"); 3706eac57ffbSSepherosa Ziehau val |= BCE_HC_CONFIG_ONE_SHOT | BCE_HC_CONFIG_USE_INT_PARAM; 3707eac57ffbSSepherosa Ziehau } 3708eac57ffbSSepherosa Ziehau REG_WR(sc, BCE_HC_CONFIG, val); 370943c2aeb0SSepherosa Ziehau 371043c2aeb0SSepherosa Ziehau /* Clear the internal statistics counters. */ 371143c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW); 371243c2aeb0SSepherosa Ziehau 371343c2aeb0SSepherosa Ziehau /* Verify that bootcode is running. */ 3714bc30d40dSSepherosa Ziehau reg = bce_shmem_rd(sc, BCE_DEV_INFO_SIGNATURE); 371543c2aeb0SSepherosa Ziehau 371643c2aeb0SSepherosa Ziehau if ((reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK) != 371743c2aeb0SSepherosa Ziehau BCE_DEV_INFO_SIGNATURE_MAGIC) { 371843c2aeb0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 371943c2aeb0SSepherosa Ziehau "Bootcode not running! Found: 0x%08X, " 372043c2aeb0SSepherosa Ziehau "Expected: 08%08X\n", 372143c2aeb0SSepherosa Ziehau reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK, 372243c2aeb0SSepherosa Ziehau BCE_DEV_INFO_SIGNATURE_MAGIC); 372343c2aeb0SSepherosa Ziehau return ENODEV; 372443c2aeb0SSepherosa Ziehau } 372543c2aeb0SSepherosa Ziehau 3726d0092544SSepherosa Ziehau /* Enable DMA */ 3727d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 3728d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 3729d0092544SSepherosa Ziehau val = REG_RD(sc, BCE_MISC_NEW_CORE_CTL); 3730d0092544SSepherosa Ziehau val |= BCE_MISC_NEW_CORE_CTL_DMA_ENABLE; 3731d0092544SSepherosa Ziehau REG_WR(sc, BCE_MISC_NEW_CORE_CTL, val); 373243c2aeb0SSepherosa Ziehau } 373343c2aeb0SSepherosa Ziehau 373443c2aeb0SSepherosa Ziehau /* Allow bootcode to apply any additional fixes before enabling MAC. */ 3735805eb96fSSepherosa Ziehau bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT2 | BCE_DRV_MSG_CODE_RESET); 373643c2aeb0SSepherosa Ziehau 373743c2aeb0SSepherosa Ziehau /* Enable link state change interrupt generation. */ 373843c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE); 373943c2aeb0SSepherosa Ziehau 37405d05a208SSepherosa Ziehau /* Enable the RXP. */ 37415d05a208SSepherosa Ziehau bce_start_rxp_cpu(sc); 37425d05a208SSepherosa Ziehau 37435d05a208SSepherosa Ziehau /* Disable management frames (NC-SI) from flowing to the MCP. */ 37445d05a208SSepherosa Ziehau if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) { 37455d05a208SSepherosa Ziehau val = REG_RD(sc, BCE_RPM_MGMT_PKT_CTRL) & 37465d05a208SSepherosa Ziehau ~BCE_RPM_MGMT_PKT_CTRL_MGMT_EN; 37475d05a208SSepherosa Ziehau REG_WR(sc, BCE_RPM_MGMT_PKT_CTRL, val); 37485d05a208SSepherosa Ziehau } 37495d05a208SSepherosa Ziehau 375043c2aeb0SSepherosa Ziehau /* Enable all remaining blocks in the MAC. */ 3751d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 3752d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 3753d0092544SSepherosa Ziehau REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, 3754d0092544SSepherosa Ziehau BCE_MISC_ENABLE_DEFAULT_XI); 3755d0092544SSepherosa Ziehau } else { 3756d0092544SSepherosa Ziehau REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, BCE_MISC_ENABLE_DEFAULT); 3757d0092544SSepherosa Ziehau } 375843c2aeb0SSepherosa Ziehau REG_RD(sc, BCE_MISC_ENABLE_SET_BITS); 375943c2aeb0SSepherosa Ziehau DELAY(20); 376043c2aeb0SSepherosa Ziehau 3761d0092544SSepherosa Ziehau /* Save the current host coalescing block settings. */ 3762d0092544SSepherosa Ziehau sc->hc_command = REG_RD(sc, BCE_HC_COMMAND); 3763d0092544SSepherosa Ziehau 376443c2aeb0SSepherosa Ziehau return 0; 376543c2aeb0SSepherosa Ziehau } 376643c2aeb0SSepherosa Ziehau 376743c2aeb0SSepherosa Ziehau 376843c2aeb0SSepherosa Ziehau /****************************************************************************/ 376943c2aeb0SSepherosa Ziehau /* Encapsulate an mbuf cluster into the rx_bd chain. */ 377043c2aeb0SSepherosa Ziehau /* */ 377143c2aeb0SSepherosa Ziehau /* The NetXtreme II can support Jumbo frames by using multiple rx_bd's. */ 377243c2aeb0SSepherosa Ziehau /* This routine will map an mbuf cluster into 1 or more rx_bd's as */ 377343c2aeb0SSepherosa Ziehau /* necessary. */ 377443c2aeb0SSepherosa Ziehau /* */ 377543c2aeb0SSepherosa Ziehau /* Returns: */ 377643c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 377743c2aeb0SSepherosa Ziehau /****************************************************************************/ 377843c2aeb0SSepherosa Ziehau static int 377908b64767SSepherosa Ziehau bce_newbuf_std(struct bce_rx_ring *rxr, uint16_t *prod, uint16_t *chain_prod, 3780c36fd9eeSSepherosa Ziehau uint32_t *prod_bseq, int init) 378143c2aeb0SSepherosa Ziehau { 378243c2aeb0SSepherosa Ziehau bus_dmamap_t map; 378343c2aeb0SSepherosa Ziehau bus_dma_segment_t seg; 378443c2aeb0SSepherosa Ziehau struct mbuf *m_new; 3785c36fd9eeSSepherosa Ziehau int error, nseg; 378643c2aeb0SSepherosa Ziehau 378743c2aeb0SSepherosa Ziehau /* This is a new mbuf allocation. */ 3788c36fd9eeSSepherosa Ziehau m_new = m_getcl(init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR); 378943c2aeb0SSepherosa Ziehau if (m_new == NULL) 379043c2aeb0SSepherosa Ziehau return ENOBUFS; 3791c36fd9eeSSepherosa Ziehau 379243c2aeb0SSepherosa Ziehau m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 379343c2aeb0SSepherosa Ziehau 379443c2aeb0SSepherosa Ziehau /* Map the mbuf cluster into device memory. */ 379508b64767SSepherosa Ziehau error = bus_dmamap_load_mbuf_segment(rxr->rx_mbuf_tag, 379608b64767SSepherosa Ziehau rxr->rx_mbuf_tmpmap, m_new, &seg, 1, &nseg, BUS_DMA_NOWAIT); 3797c36fd9eeSSepherosa Ziehau if (error) { 3798c36fd9eeSSepherosa Ziehau m_freem(m_new); 3799c36fd9eeSSepherosa Ziehau if (init) { 380008b64767SSepherosa Ziehau if_printf(&rxr->sc->arpcom.ac_if, 380143c2aeb0SSepherosa Ziehau "Error mapping mbuf into RX chain!\n"); 380243c2aeb0SSepherosa Ziehau } 3803c36fd9eeSSepherosa Ziehau return error; 3804c36fd9eeSSepherosa Ziehau } 3805c36fd9eeSSepherosa Ziehau 380608b64767SSepherosa Ziehau if (rxr->rx_mbuf_ptr[*chain_prod] != NULL) { 380708b64767SSepherosa Ziehau bus_dmamap_unload(rxr->rx_mbuf_tag, 380808b64767SSepherosa Ziehau rxr->rx_mbuf_map[*chain_prod]); 3809c36fd9eeSSepherosa Ziehau } 3810c36fd9eeSSepherosa Ziehau 381108b64767SSepherosa Ziehau map = rxr->rx_mbuf_map[*chain_prod]; 381208b64767SSepherosa Ziehau rxr->rx_mbuf_map[*chain_prod] = rxr->rx_mbuf_tmpmap; 381308b64767SSepherosa Ziehau rxr->rx_mbuf_tmpmap = map; 381443c2aeb0SSepherosa Ziehau 381543c2aeb0SSepherosa Ziehau /* Save the mbuf and update our counter. */ 381608b64767SSepherosa Ziehau rxr->rx_mbuf_ptr[*chain_prod] = m_new; 381708b64767SSepherosa Ziehau rxr->rx_mbuf_paddr[*chain_prod] = seg.ds_addr; 381808b64767SSepherosa Ziehau rxr->free_rx_bd--; 381943c2aeb0SSepherosa Ziehau 382008b64767SSepherosa Ziehau bce_setup_rxdesc_std(rxr, *chain_prod, prod_bseq); 3821314a2fccSSepherosa Ziehau 382243c2aeb0SSepherosa Ziehau return 0; 382343c2aeb0SSepherosa Ziehau } 382443c2aeb0SSepherosa Ziehau 382543c2aeb0SSepherosa Ziehau 3826314a2fccSSepherosa Ziehau static void 382708b64767SSepherosa Ziehau bce_setup_rxdesc_std(struct bce_rx_ring *rxr, uint16_t chain_prod, 382808b64767SSepherosa Ziehau uint32_t *prod_bseq) 3829314a2fccSSepherosa Ziehau { 3830314a2fccSSepherosa Ziehau struct rx_bd *rxbd; 3831314a2fccSSepherosa Ziehau bus_addr_t paddr; 3832314a2fccSSepherosa Ziehau int len; 3833314a2fccSSepherosa Ziehau 383408b64767SSepherosa Ziehau paddr = rxr->rx_mbuf_paddr[chain_prod]; 383508b64767SSepherosa Ziehau len = rxr->rx_mbuf_ptr[chain_prod]->m_len; 3836314a2fccSSepherosa Ziehau 3837314a2fccSSepherosa Ziehau /* Setup the rx_bd for the first segment. */ 383808b64767SSepherosa Ziehau rxbd = &rxr->rx_bd_chain[RX_PAGE(chain_prod)][RX_IDX(chain_prod)]; 3839314a2fccSSepherosa Ziehau 3840314a2fccSSepherosa Ziehau rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(paddr)); 3841314a2fccSSepherosa Ziehau rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(paddr)); 3842314a2fccSSepherosa Ziehau rxbd->rx_bd_len = htole32(len); 3843314a2fccSSepherosa Ziehau rxbd->rx_bd_flags = htole32(RX_BD_FLAGS_START); 3844314a2fccSSepherosa Ziehau *prod_bseq += len; 3845314a2fccSSepherosa Ziehau 3846314a2fccSSepherosa Ziehau rxbd->rx_bd_flags |= htole32(RX_BD_FLAGS_END); 3847314a2fccSSepherosa Ziehau } 3848314a2fccSSepherosa Ziehau 3849314a2fccSSepherosa Ziehau 385043c2aeb0SSepherosa Ziehau /****************************************************************************/ 3851d0092544SSepherosa Ziehau /* Initialize the TX context memory. */ 3852d0092544SSepherosa Ziehau /* */ 3853d0092544SSepherosa Ziehau /* Returns: */ 3854d0092544SSepherosa Ziehau /* Nothing */ 3855d0092544SSepherosa Ziehau /****************************************************************************/ 3856d0092544SSepherosa Ziehau static void 385710bcbdabSSepherosa Ziehau bce_init_tx_context(struct bce_tx_ring *txr) 3858d0092544SSepherosa Ziehau { 3859d0092544SSepherosa Ziehau uint32_t val; 3860d0092544SSepherosa Ziehau 3861d0092544SSepherosa Ziehau /* Initialize the context ID for an L2 TX chain. */ 386210bcbdabSSepherosa Ziehau if (BCE_CHIP_NUM(txr->sc) == BCE_CHIP_NUM_5709 || 386310bcbdabSSepherosa Ziehau BCE_CHIP_NUM(txr->sc) == BCE_CHIP_NUM_5716) { 3864d0092544SSepherosa Ziehau /* Set the CID type to support an L2 connection. */ 3865d0092544SSepherosa Ziehau val = BCE_L2CTX_TX_TYPE_TYPE_L2 | BCE_L2CTX_TX_TYPE_SIZE_L2; 386610bcbdabSSepherosa Ziehau CTX_WR(txr->sc, GET_CID_ADDR(TX_CID), 386710bcbdabSSepherosa Ziehau BCE_L2CTX_TX_TYPE_XI, val); 3868d0092544SSepherosa Ziehau val = BCE_L2CTX_TX_CMD_TYPE_TYPE_L2 | (8 << 16); 386910bcbdabSSepherosa Ziehau CTX_WR(txr->sc, GET_CID_ADDR(TX_CID), 387010bcbdabSSepherosa Ziehau BCE_L2CTX_TX_CMD_TYPE_XI, val); 3871d0092544SSepherosa Ziehau 3872d0092544SSepherosa Ziehau /* Point the hardware to the first page in the chain. */ 387310bcbdabSSepherosa Ziehau val = BCE_ADDR_HI(txr->tx_bd_chain_paddr[0]); 387410bcbdabSSepherosa Ziehau CTX_WR(txr->sc, GET_CID_ADDR(TX_CID), 3875d0092544SSepherosa Ziehau BCE_L2CTX_TX_TBDR_BHADDR_HI_XI, val); 387610bcbdabSSepherosa Ziehau val = BCE_ADDR_LO(txr->tx_bd_chain_paddr[0]); 387710bcbdabSSepherosa Ziehau CTX_WR(txr->sc, GET_CID_ADDR(TX_CID), 3878d0092544SSepherosa Ziehau BCE_L2CTX_TX_TBDR_BHADDR_LO_XI, val); 3879d0092544SSepherosa Ziehau } else { 3880d0092544SSepherosa Ziehau /* Set the CID type to support an L2 connection. */ 3881d0092544SSepherosa Ziehau val = BCE_L2CTX_TX_TYPE_TYPE_L2 | BCE_L2CTX_TX_TYPE_SIZE_L2; 388210bcbdabSSepherosa Ziehau CTX_WR(txr->sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_TYPE, val); 3883d0092544SSepherosa Ziehau val = BCE_L2CTX_TX_CMD_TYPE_TYPE_L2 | (8 << 16); 388410bcbdabSSepherosa Ziehau CTX_WR(txr->sc, GET_CID_ADDR(TX_CID), 388510bcbdabSSepherosa Ziehau BCE_L2CTX_TX_CMD_TYPE, val); 3886d0092544SSepherosa Ziehau 3887d0092544SSepherosa Ziehau /* Point the hardware to the first page in the chain. */ 388810bcbdabSSepherosa Ziehau val = BCE_ADDR_HI(txr->tx_bd_chain_paddr[0]); 388910bcbdabSSepherosa Ziehau CTX_WR(txr->sc, GET_CID_ADDR(TX_CID), 3890d0092544SSepherosa Ziehau BCE_L2CTX_TX_TBDR_BHADDR_HI, val); 389110bcbdabSSepherosa Ziehau val = BCE_ADDR_LO(txr->tx_bd_chain_paddr[0]); 389210bcbdabSSepherosa Ziehau CTX_WR(txr->sc, GET_CID_ADDR(TX_CID), 3893d0092544SSepherosa Ziehau BCE_L2CTX_TX_TBDR_BHADDR_LO, val); 3894d0092544SSepherosa Ziehau } 3895d0092544SSepherosa Ziehau } 3896d0092544SSepherosa Ziehau 3897d0092544SSepherosa Ziehau 3898d0092544SSepherosa Ziehau /****************************************************************************/ 389943c2aeb0SSepherosa Ziehau /* Allocate memory and initialize the TX data structures. */ 390043c2aeb0SSepherosa Ziehau /* */ 390143c2aeb0SSepherosa Ziehau /* Returns: */ 390243c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 390343c2aeb0SSepherosa Ziehau /****************************************************************************/ 390443c2aeb0SSepherosa Ziehau static int 390510bcbdabSSepherosa Ziehau bce_init_tx_chain(struct bce_tx_ring *txr) 390643c2aeb0SSepherosa Ziehau { 390743c2aeb0SSepherosa Ziehau struct tx_bd *txbd; 390843c2aeb0SSepherosa Ziehau int i, rc = 0; 390943c2aeb0SSepherosa Ziehau 391043c2aeb0SSepherosa Ziehau /* Set the initial TX producer/consumer indices. */ 391110bcbdabSSepherosa Ziehau txr->tx_prod = 0; 391210bcbdabSSepherosa Ziehau txr->tx_cons = 0; 391310bcbdabSSepherosa Ziehau txr->tx_prod_bseq = 0; 391410bcbdabSSepherosa Ziehau txr->used_tx_bd = 0; 391510bcbdabSSepherosa Ziehau txr->max_tx_bd = USABLE_TX_BD(txr); 391643c2aeb0SSepherosa Ziehau 391743c2aeb0SSepherosa Ziehau /* 391843c2aeb0SSepherosa Ziehau * The NetXtreme II supports a linked-list structre called 391943c2aeb0SSepherosa Ziehau * a Buffer Descriptor Chain (or BD chain). A BD chain 392043c2aeb0SSepherosa Ziehau * consists of a series of 1 or more chain pages, each of which 392143c2aeb0SSepherosa Ziehau * consists of a fixed number of BD entries. 392243c2aeb0SSepherosa Ziehau * The last BD entry on each page is a pointer to the next page 392343c2aeb0SSepherosa Ziehau * in the chain, and the last pointer in the BD chain 392443c2aeb0SSepherosa Ziehau * points back to the beginning of the chain. 392543c2aeb0SSepherosa Ziehau */ 392643c2aeb0SSepherosa Ziehau 392743c2aeb0SSepherosa Ziehau /* Set the TX next pointer chain entries. */ 392810bcbdabSSepherosa Ziehau for (i = 0; i < txr->tx_pages; i++) { 392943c2aeb0SSepherosa Ziehau int j; 393043c2aeb0SSepherosa Ziehau 393110bcbdabSSepherosa Ziehau txbd = &txr->tx_bd_chain[i][USABLE_TX_BD_PER_PAGE]; 393243c2aeb0SSepherosa Ziehau 393343c2aeb0SSepherosa Ziehau /* Check if we've reached the last page. */ 393410bcbdabSSepherosa Ziehau if (i == (txr->tx_pages - 1)) 393543c2aeb0SSepherosa Ziehau j = 0; 393643c2aeb0SSepherosa Ziehau else 393743c2aeb0SSepherosa Ziehau j = i + 1; 393843c2aeb0SSepherosa Ziehau 393943c2aeb0SSepherosa Ziehau txbd->tx_bd_haddr_hi = 394010bcbdabSSepherosa Ziehau htole32(BCE_ADDR_HI(txr->tx_bd_chain_paddr[j])); 394143c2aeb0SSepherosa Ziehau txbd->tx_bd_haddr_lo = 394210bcbdabSSepherosa Ziehau htole32(BCE_ADDR_LO(txr->tx_bd_chain_paddr[j])); 394343c2aeb0SSepherosa Ziehau } 394410bcbdabSSepherosa Ziehau bce_init_tx_context(txr); 394543c2aeb0SSepherosa Ziehau 394643c2aeb0SSepherosa Ziehau return(rc); 394743c2aeb0SSepherosa Ziehau } 394843c2aeb0SSepherosa Ziehau 394943c2aeb0SSepherosa Ziehau 395043c2aeb0SSepherosa Ziehau /****************************************************************************/ 395143c2aeb0SSepherosa Ziehau /* Free memory and clear the TX data structures. */ 395243c2aeb0SSepherosa Ziehau /* */ 395343c2aeb0SSepherosa Ziehau /* Returns: */ 395443c2aeb0SSepherosa Ziehau /* Nothing. */ 395543c2aeb0SSepherosa Ziehau /****************************************************************************/ 395643c2aeb0SSepherosa Ziehau static void 395710bcbdabSSepherosa Ziehau bce_free_tx_chain(struct bce_tx_ring *txr) 395843c2aeb0SSepherosa Ziehau { 395943c2aeb0SSepherosa Ziehau int i; 396043c2aeb0SSepherosa Ziehau 396143c2aeb0SSepherosa Ziehau /* Unmap, unload, and free any mbufs still in the TX mbuf chain. */ 396210bcbdabSSepherosa Ziehau for (i = 0; i < TOTAL_TX_BD(txr); i++) { 396310bcbdabSSepherosa Ziehau if (txr->tx_mbuf_ptr[i] != NULL) { 396410bcbdabSSepherosa Ziehau bus_dmamap_unload(txr->tx_mbuf_tag, 396510bcbdabSSepherosa Ziehau txr->tx_mbuf_map[i]); 396610bcbdabSSepherosa Ziehau m_freem(txr->tx_mbuf_ptr[i]); 396710bcbdabSSepherosa Ziehau txr->tx_mbuf_ptr[i] = NULL; 396843c2aeb0SSepherosa Ziehau } 396943c2aeb0SSepherosa Ziehau } 397043c2aeb0SSepherosa Ziehau 397143c2aeb0SSepherosa Ziehau /* Clear each TX chain page. */ 397210bcbdabSSepherosa Ziehau for (i = 0; i < txr->tx_pages; i++) 397310bcbdabSSepherosa Ziehau bzero(txr->tx_bd_chain[i], BCE_TX_CHAIN_PAGE_SZ); 397410bcbdabSSepherosa Ziehau txr->used_tx_bd = 0; 397543c2aeb0SSepherosa Ziehau } 397643c2aeb0SSepherosa Ziehau 397743c2aeb0SSepherosa Ziehau 397843c2aeb0SSepherosa Ziehau /****************************************************************************/ 3979d0092544SSepherosa Ziehau /* Initialize the RX context memory. */ 3980d0092544SSepherosa Ziehau /* */ 3981d0092544SSepherosa Ziehau /* Returns: */ 3982d0092544SSepherosa Ziehau /* Nothing */ 3983d0092544SSepherosa Ziehau /****************************************************************************/ 3984d0092544SSepherosa Ziehau static void 398508b64767SSepherosa Ziehau bce_init_rx_context(struct bce_rx_ring *rxr) 3986d0092544SSepherosa Ziehau { 3987d0092544SSepherosa Ziehau uint32_t val; 3988d0092544SSepherosa Ziehau 3989d0092544SSepherosa Ziehau /* Initialize the context ID for an L2 RX chain. */ 3990d0092544SSepherosa Ziehau val = BCE_L2CTX_RX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE | 3991d0092544SSepherosa Ziehau BCE_L2CTX_RX_CTX_TYPE_SIZE_L2 | (0x02 << 8); 3992d0092544SSepherosa Ziehau 3993d0092544SSepherosa Ziehau /* 3994d0092544SSepherosa Ziehau * Set the level for generating pause frames 3995d0092544SSepherosa Ziehau * when the number of available rx_bd's gets 3996d0092544SSepherosa Ziehau * too low (the low watermark) and the level 3997d0092544SSepherosa Ziehau * when pause frames can be stopped (the high 3998d0092544SSepherosa Ziehau * watermark). 3999d0092544SSepherosa Ziehau */ 400008b64767SSepherosa Ziehau if (BCE_CHIP_NUM(rxr->sc) == BCE_CHIP_NUM_5709 || 400108b64767SSepherosa Ziehau BCE_CHIP_NUM(rxr->sc) == BCE_CHIP_NUM_5716) { 4002d0092544SSepherosa Ziehau uint32_t lo_water, hi_water; 4003d0092544SSepherosa Ziehau 4004d0092544SSepherosa Ziehau lo_water = BCE_L2CTX_RX_LO_WATER_MARK_DEFAULT; 400508b64767SSepherosa Ziehau hi_water = USABLE_RX_BD(rxr) / 4; 4006d0092544SSepherosa Ziehau 4007d0092544SSepherosa Ziehau lo_water /= BCE_L2CTX_RX_LO_WATER_MARK_SCALE; 4008d0092544SSepherosa Ziehau hi_water /= BCE_L2CTX_RX_HI_WATER_MARK_SCALE; 4009d0092544SSepherosa Ziehau 4010d0092544SSepherosa Ziehau if (hi_water > 0xf) 4011d0092544SSepherosa Ziehau hi_water = 0xf; 4012d0092544SSepherosa Ziehau else if (hi_water == 0) 4013d0092544SSepherosa Ziehau lo_water = 0; 4014d0092544SSepherosa Ziehau val |= lo_water | 4015d0092544SSepherosa Ziehau (hi_water << BCE_L2CTX_RX_HI_WATER_MARK_SHIFT); 4016d0092544SSepherosa Ziehau } 4017d0092544SSepherosa Ziehau 401808b64767SSepherosa Ziehau CTX_WR(rxr->sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_CTX_TYPE, val); 4019d0092544SSepherosa Ziehau 4020d0092544SSepherosa Ziehau /* Setup the MQ BIN mapping for l2_ctx_host_bseq. */ 402108b64767SSepherosa Ziehau if (BCE_CHIP_NUM(rxr->sc) == BCE_CHIP_NUM_5709 || 402208b64767SSepherosa Ziehau BCE_CHIP_NUM(rxr->sc) == BCE_CHIP_NUM_5716) { 402308b64767SSepherosa Ziehau val = REG_RD(rxr->sc, BCE_MQ_MAP_L2_5); 402408b64767SSepherosa Ziehau REG_WR(rxr->sc, BCE_MQ_MAP_L2_5, val | BCE_MQ_MAP_L2_5_ARM); 4025d0092544SSepherosa Ziehau } 4026d0092544SSepherosa Ziehau 4027d0092544SSepherosa Ziehau /* Point the hardware to the first page in the chain. */ 402808b64767SSepherosa Ziehau val = BCE_ADDR_HI(rxr->rx_bd_chain_paddr[0]); 402908b64767SSepherosa Ziehau CTX_WR(rxr->sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_NX_BDHADDR_HI, val); 403008b64767SSepherosa Ziehau val = BCE_ADDR_LO(rxr->rx_bd_chain_paddr[0]); 403108b64767SSepherosa Ziehau CTX_WR(rxr->sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_NX_BDHADDR_LO, val); 4032d0092544SSepherosa Ziehau } 4033d0092544SSepherosa Ziehau 4034d0092544SSepherosa Ziehau 4035d0092544SSepherosa Ziehau /****************************************************************************/ 403643c2aeb0SSepherosa Ziehau /* Allocate memory and initialize the RX data structures. */ 403743c2aeb0SSepherosa Ziehau /* */ 403843c2aeb0SSepherosa Ziehau /* Returns: */ 403943c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 404043c2aeb0SSepherosa Ziehau /****************************************************************************/ 404143c2aeb0SSepherosa Ziehau static int 404208b64767SSepherosa Ziehau bce_init_rx_chain(struct bce_rx_ring *rxr) 404343c2aeb0SSepherosa Ziehau { 404443c2aeb0SSepherosa Ziehau struct rx_bd *rxbd; 404543c2aeb0SSepherosa Ziehau int i, rc = 0; 404643c2aeb0SSepherosa Ziehau uint16_t prod, chain_prod; 4047d0092544SSepherosa Ziehau uint32_t prod_bseq; 404843c2aeb0SSepherosa Ziehau 404943c2aeb0SSepherosa Ziehau /* Initialize the RX producer and consumer indices. */ 405008b64767SSepherosa Ziehau rxr->rx_prod = 0; 405108b64767SSepherosa Ziehau rxr->rx_cons = 0; 405208b64767SSepherosa Ziehau rxr->rx_prod_bseq = 0; 405308b64767SSepherosa Ziehau rxr->free_rx_bd = USABLE_RX_BD(rxr); 405408b64767SSepherosa Ziehau rxr->max_rx_bd = USABLE_RX_BD(rxr); 405543c2aeb0SSepherosa Ziehau 405643c2aeb0SSepherosa Ziehau /* Initialize the RX next pointer chain entries. */ 405708b64767SSepherosa Ziehau for (i = 0; i < rxr->rx_pages; i++) { 405843c2aeb0SSepherosa Ziehau int j; 405943c2aeb0SSepherosa Ziehau 406008b64767SSepherosa Ziehau rxbd = &rxr->rx_bd_chain[i][USABLE_RX_BD_PER_PAGE]; 406143c2aeb0SSepherosa Ziehau 406243c2aeb0SSepherosa Ziehau /* Check if we've reached the last page. */ 406308b64767SSepherosa Ziehau if (i == (rxr->rx_pages - 1)) 406443c2aeb0SSepherosa Ziehau j = 0; 406543c2aeb0SSepherosa Ziehau else 406643c2aeb0SSepherosa Ziehau j = i + 1; 406743c2aeb0SSepherosa Ziehau 406843c2aeb0SSepherosa Ziehau /* Setup the chain page pointers. */ 406943c2aeb0SSepherosa Ziehau rxbd->rx_bd_haddr_hi = 407008b64767SSepherosa Ziehau htole32(BCE_ADDR_HI(rxr->rx_bd_chain_paddr[j])); 407143c2aeb0SSepherosa Ziehau rxbd->rx_bd_haddr_lo = 407208b64767SSepherosa Ziehau htole32(BCE_ADDR_LO(rxr->rx_bd_chain_paddr[j])); 407343c2aeb0SSepherosa Ziehau } 407443c2aeb0SSepherosa Ziehau 407543c2aeb0SSepherosa Ziehau /* Allocate mbuf clusters for the rx_bd chain. */ 407643c2aeb0SSepherosa Ziehau prod = prod_bseq = 0; 407708b64767SSepherosa Ziehau while (prod < TOTAL_RX_BD(rxr)) { 407808b64767SSepherosa Ziehau chain_prod = RX_CHAIN_IDX(rxr, prod); 407908b64767SSepherosa Ziehau if (bce_newbuf_std(rxr, &prod, &chain_prod, &prod_bseq, 1)) { 408008b64767SSepherosa Ziehau if_printf(&rxr->sc->arpcom.ac_if, 408143c2aeb0SSepherosa Ziehau "Error filling RX chain: rx_bd[0x%04X]!\n", 408243c2aeb0SSepherosa Ziehau chain_prod); 408343c2aeb0SSepherosa Ziehau rc = ENOBUFS; 408443c2aeb0SSepherosa Ziehau break; 408543c2aeb0SSepherosa Ziehau } 408643c2aeb0SSepherosa Ziehau prod = NEXT_RX_BD(prod); 408743c2aeb0SSepherosa Ziehau } 408843c2aeb0SSepherosa Ziehau 408943c2aeb0SSepherosa Ziehau /* Save the RX chain producer index. */ 409008b64767SSepherosa Ziehau rxr->rx_prod = prod; 409108b64767SSepherosa Ziehau rxr->rx_prod_bseq = prod_bseq; 409243c2aeb0SSepherosa Ziehau 409343c2aeb0SSepherosa Ziehau /* Tell the chip about the waiting rx_bd's. */ 409408b64767SSepherosa Ziehau REG_WR16(rxr->sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BDIDX, 409508b64767SSepherosa Ziehau rxr->rx_prod); 409608b64767SSepherosa Ziehau REG_WR(rxr->sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BSEQ, 409708b64767SSepherosa Ziehau rxr->rx_prod_bseq); 409843c2aeb0SSepherosa Ziehau 409908b64767SSepherosa Ziehau bce_init_rx_context(rxr); 410043c2aeb0SSepherosa Ziehau 410143c2aeb0SSepherosa Ziehau return(rc); 410243c2aeb0SSepherosa Ziehau } 410343c2aeb0SSepherosa Ziehau 410443c2aeb0SSepherosa Ziehau 410543c2aeb0SSepherosa Ziehau /****************************************************************************/ 410643c2aeb0SSepherosa Ziehau /* Free memory and clear the RX data structures. */ 410743c2aeb0SSepherosa Ziehau /* */ 410843c2aeb0SSepherosa Ziehau /* Returns: */ 410943c2aeb0SSepherosa Ziehau /* Nothing. */ 411043c2aeb0SSepherosa Ziehau /****************************************************************************/ 411143c2aeb0SSepherosa Ziehau static void 411208b64767SSepherosa Ziehau bce_free_rx_chain(struct bce_rx_ring *rxr) 411343c2aeb0SSepherosa Ziehau { 411443c2aeb0SSepherosa Ziehau int i; 411543c2aeb0SSepherosa Ziehau 411643c2aeb0SSepherosa Ziehau /* Free any mbufs still in the RX mbuf chain. */ 411708b64767SSepherosa Ziehau for (i = 0; i < TOTAL_RX_BD(rxr); i++) { 411808b64767SSepherosa Ziehau if (rxr->rx_mbuf_ptr[i] != NULL) { 411908b64767SSepherosa Ziehau bus_dmamap_unload(rxr->rx_mbuf_tag, 412008b64767SSepherosa Ziehau rxr->rx_mbuf_map[i]); 412108b64767SSepherosa Ziehau m_freem(rxr->rx_mbuf_ptr[i]); 412208b64767SSepherosa Ziehau rxr->rx_mbuf_ptr[i] = NULL; 412343c2aeb0SSepherosa Ziehau } 412443c2aeb0SSepherosa Ziehau } 412543c2aeb0SSepherosa Ziehau 412643c2aeb0SSepherosa Ziehau /* Clear each RX chain page. */ 412708b64767SSepherosa Ziehau for (i = 0; i < rxr->rx_pages; i++) 412808b64767SSepherosa Ziehau bzero(rxr->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ); 412943c2aeb0SSepherosa Ziehau } 413043c2aeb0SSepherosa Ziehau 413143c2aeb0SSepherosa Ziehau 413243c2aeb0SSepherosa Ziehau /****************************************************************************/ 413343c2aeb0SSepherosa Ziehau /* Set media options. */ 413443c2aeb0SSepherosa Ziehau /* */ 413543c2aeb0SSepherosa Ziehau /* Returns: */ 413643c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 413743c2aeb0SSepherosa Ziehau /****************************************************************************/ 413843c2aeb0SSepherosa Ziehau static int 413943c2aeb0SSepherosa Ziehau bce_ifmedia_upd(struct ifnet *ifp) 414043c2aeb0SSepherosa Ziehau { 414143c2aeb0SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 414243c2aeb0SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bce_miibus); 414339f10431SSepherosa Ziehau int error = 0; 414443c2aeb0SSepherosa Ziehau 414543c2aeb0SSepherosa Ziehau /* 414643c2aeb0SSepherosa Ziehau * 'mii' will be NULL, when this function is called on following 414743c2aeb0SSepherosa Ziehau * code path: bce_attach() -> bce_mgmt_init() 414843c2aeb0SSepherosa Ziehau */ 414943c2aeb0SSepherosa Ziehau if (mii != NULL) { 415043c2aeb0SSepherosa Ziehau /* Make sure the MII bus has been enumerated. */ 415143c2aeb0SSepherosa Ziehau sc->bce_link = 0; 415243c2aeb0SSepherosa Ziehau if (mii->mii_instance) { 415343c2aeb0SSepherosa Ziehau struct mii_softc *miisc; 415443c2aeb0SSepherosa Ziehau 415543c2aeb0SSepherosa Ziehau LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 415643c2aeb0SSepherosa Ziehau mii_phy_reset(miisc); 415743c2aeb0SSepherosa Ziehau } 415839f10431SSepherosa Ziehau error = mii_mediachg(mii); 415943c2aeb0SSepherosa Ziehau } 416039f10431SSepherosa Ziehau return error; 416143c2aeb0SSepherosa Ziehau } 416243c2aeb0SSepherosa Ziehau 416343c2aeb0SSepherosa Ziehau 416443c2aeb0SSepherosa Ziehau /****************************************************************************/ 416543c2aeb0SSepherosa Ziehau /* Reports current media status. */ 416643c2aeb0SSepherosa Ziehau /* */ 416743c2aeb0SSepherosa Ziehau /* Returns: */ 416843c2aeb0SSepherosa Ziehau /* Nothing. */ 416943c2aeb0SSepherosa Ziehau /****************************************************************************/ 417043c2aeb0SSepherosa Ziehau static void 417143c2aeb0SSepherosa Ziehau bce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 417243c2aeb0SSepherosa Ziehau { 417343c2aeb0SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 417443c2aeb0SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bce_miibus); 417543c2aeb0SSepherosa Ziehau 417643c2aeb0SSepherosa Ziehau mii_pollstat(mii); 417743c2aeb0SSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 417843c2aeb0SSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 417943c2aeb0SSepherosa Ziehau } 418043c2aeb0SSepherosa Ziehau 418143c2aeb0SSepherosa Ziehau 418243c2aeb0SSepherosa Ziehau /****************************************************************************/ 418343c2aeb0SSepherosa Ziehau /* Handles PHY generated interrupt events. */ 418443c2aeb0SSepherosa Ziehau /* */ 418543c2aeb0SSepherosa Ziehau /* Returns: */ 418643c2aeb0SSepherosa Ziehau /* Nothing. */ 418743c2aeb0SSepherosa Ziehau /****************************************************************************/ 418843c2aeb0SSepherosa Ziehau static void 418943c2aeb0SSepherosa Ziehau bce_phy_intr(struct bce_softc *sc) 419043c2aeb0SSepherosa Ziehau { 419143c2aeb0SSepherosa Ziehau uint32_t new_link_state, old_link_state; 419243c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 419343c2aeb0SSepherosa Ziehau 419484464af5SSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize); 419543c2aeb0SSepherosa Ziehau 419643c2aeb0SSepherosa Ziehau new_link_state = sc->status_block->status_attn_bits & 419743c2aeb0SSepherosa Ziehau STATUS_ATTN_BITS_LINK_STATE; 419843c2aeb0SSepherosa Ziehau old_link_state = sc->status_block->status_attn_bits_ack & 419943c2aeb0SSepherosa Ziehau STATUS_ATTN_BITS_LINK_STATE; 420043c2aeb0SSepherosa Ziehau 420143c2aeb0SSepherosa Ziehau /* Handle any changes if the link state has changed. */ 420243c2aeb0SSepherosa Ziehau if (new_link_state != old_link_state) { /* XXX redundant? */ 420343c2aeb0SSepherosa Ziehau /* Update the status_attn_bits_ack field in the status block. */ 420443c2aeb0SSepherosa Ziehau if (new_link_state) { 420543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_PCICFG_STATUS_BIT_SET_CMD, 420643c2aeb0SSepherosa Ziehau STATUS_ATTN_BITS_LINK_STATE); 420743c2aeb0SSepherosa Ziehau if (bootverbose) 420843c2aeb0SSepherosa Ziehau if_printf(ifp, "Link is now UP.\n"); 420943c2aeb0SSepherosa Ziehau } else { 421043c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_PCICFG_STATUS_BIT_CLEAR_CMD, 421143c2aeb0SSepherosa Ziehau STATUS_ATTN_BITS_LINK_STATE); 421243c2aeb0SSepherosa Ziehau if (bootverbose) 421343c2aeb0SSepherosa Ziehau if_printf(ifp, "Link is now DOWN.\n"); 421443c2aeb0SSepherosa Ziehau } 4215d0092544SSepherosa Ziehau 4216d0092544SSepherosa Ziehau /* 4217d0092544SSepherosa Ziehau * Assume link is down and allow tick routine to 4218d0092544SSepherosa Ziehau * update the state based on the actual media state. 4219d0092544SSepherosa Ziehau */ 4220d0092544SSepherosa Ziehau sc->bce_link = 0; 4221d0092544SSepherosa Ziehau callout_stop(&sc->bce_tick_callout); 4222d0092544SSepherosa Ziehau bce_tick_serialized(sc); 422343c2aeb0SSepherosa Ziehau } 422443c2aeb0SSepherosa Ziehau 422543c2aeb0SSepherosa Ziehau /* Acknowledge the link change interrupt. */ 422643c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_STATUS, BCE_EMAC_STATUS_LINK_CHANGE); 422743c2aeb0SSepherosa Ziehau } 422843c2aeb0SSepherosa Ziehau 422943c2aeb0SSepherosa Ziehau 423043c2aeb0SSepherosa Ziehau /****************************************************************************/ 423124603545SSepherosa Ziehau /* Reads the receive consumer value from the status block (skipping over */ 423224603545SSepherosa Ziehau /* chain page pointer if necessary). */ 423324603545SSepherosa Ziehau /* */ 423424603545SSepherosa Ziehau /* Returns: */ 423524603545SSepherosa Ziehau /* hw_cons */ 423624603545SSepherosa Ziehau /****************************************************************************/ 423724603545SSepherosa Ziehau static __inline uint16_t 423824603545SSepherosa Ziehau bce_get_hw_rx_cons(struct bce_softc *sc) 423924603545SSepherosa Ziehau { 424024603545SSepherosa Ziehau uint16_t hw_cons = sc->status_block->status_rx_quick_consumer_index0; 424124603545SSepherosa Ziehau 424224603545SSepherosa Ziehau if ((hw_cons & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE) 424324603545SSepherosa Ziehau hw_cons++; 424424603545SSepherosa Ziehau return hw_cons; 424524603545SSepherosa Ziehau } 424624603545SSepherosa Ziehau 424724603545SSepherosa Ziehau 424824603545SSepherosa Ziehau /****************************************************************************/ 424943c2aeb0SSepherosa Ziehau /* Handles received frame interrupt events. */ 425043c2aeb0SSepherosa Ziehau /* */ 425143c2aeb0SSepherosa Ziehau /* Returns: */ 425243c2aeb0SSepherosa Ziehau /* Nothing. */ 425343c2aeb0SSepherosa Ziehau /****************************************************************************/ 425443c2aeb0SSepherosa Ziehau static void 425508b64767SSepherosa Ziehau bce_rx_intr(struct bce_rx_ring *rxr, int count, uint16_t hw_cons) 425643c2aeb0SSepherosa Ziehau { 425708b64767SSepherosa Ziehau struct ifnet *ifp = &rxr->sc->arpcom.ac_if; 4258a5eaa4bfSSepherosa Ziehau uint16_t sw_cons, sw_chain_cons, sw_prod, sw_chain_prod; 425943c2aeb0SSepherosa Ziehau uint32_t sw_prod_bseq; 426043c2aeb0SSepherosa Ziehau 426184464af5SSepherosa Ziehau ASSERT_SERIALIZED(&rxr->rx_serialize); 426243c2aeb0SSepherosa Ziehau 426343c2aeb0SSepherosa Ziehau /* Get working copies of the driver's view of the RX indices. */ 426408b64767SSepherosa Ziehau sw_cons = rxr->rx_cons; 426508b64767SSepherosa Ziehau sw_prod = rxr->rx_prod; 426608b64767SSepherosa Ziehau sw_prod_bseq = rxr->rx_prod_bseq; 426743c2aeb0SSepherosa Ziehau 426843c2aeb0SSepherosa Ziehau /* Scan through the receive chain as long as there is work to do. */ 426943c2aeb0SSepherosa Ziehau while (sw_cons != hw_cons) { 427043c2aeb0SSepherosa Ziehau struct mbuf *m = NULL; 427143c2aeb0SSepherosa Ziehau struct l2_fhdr *l2fhdr = NULL; 427243c2aeb0SSepherosa Ziehau unsigned int len; 427343c2aeb0SSepherosa Ziehau uint32_t status = 0; 427443c2aeb0SSepherosa Ziehau 42754a331bf7SSepherosa Ziehau #ifdef IFPOLL_ENABLE 4276a5eaa4bfSSepherosa Ziehau if (count >= 0 && count-- == 0) 427743c2aeb0SSepherosa Ziehau break; 427843c2aeb0SSepherosa Ziehau #endif 427943c2aeb0SSepherosa Ziehau 428043c2aeb0SSepherosa Ziehau /* 428143c2aeb0SSepherosa Ziehau * Convert the producer/consumer indices 428243c2aeb0SSepherosa Ziehau * to an actual rx_bd index. 428343c2aeb0SSepherosa Ziehau */ 428408b64767SSepherosa Ziehau sw_chain_cons = RX_CHAIN_IDX(rxr, sw_cons); 428508b64767SSepherosa Ziehau sw_chain_prod = RX_CHAIN_IDX(rxr, sw_prod); 428643c2aeb0SSepherosa Ziehau 428708b64767SSepherosa Ziehau rxr->free_rx_bd++; 428843c2aeb0SSepherosa Ziehau 428943c2aeb0SSepherosa Ziehau /* The mbuf is stored with the last rx_bd entry of a packet. */ 429008b64767SSepherosa Ziehau if (rxr->rx_mbuf_ptr[sw_chain_cons] != NULL) { 4291c36fd9eeSSepherosa Ziehau if (sw_chain_cons != sw_chain_prod) { 4292c36fd9eeSSepherosa Ziehau if_printf(ifp, "RX cons(%d) != prod(%d), " 429308b64767SSepherosa Ziehau "drop!\n", sw_chain_cons, sw_chain_prod); 4294d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ierrors, 1); 4295c36fd9eeSSepherosa Ziehau 429608b64767SSepherosa Ziehau bce_setup_rxdesc_std(rxr, sw_chain_cons, 4297c36fd9eeSSepherosa Ziehau &sw_prod_bseq); 4298c36fd9eeSSepherosa Ziehau m = NULL; 4299c36fd9eeSSepherosa Ziehau goto bce_rx_int_next_rx; 4300c36fd9eeSSepherosa Ziehau } 430143c2aeb0SSepherosa Ziehau 430243c2aeb0SSepherosa Ziehau /* Unmap the mbuf from DMA space. */ 430308b64767SSepherosa Ziehau bus_dmamap_sync(rxr->rx_mbuf_tag, 430408b64767SSepherosa Ziehau rxr->rx_mbuf_map[sw_chain_cons], 430543c2aeb0SSepherosa Ziehau BUS_DMASYNC_POSTREAD); 430643c2aeb0SSepherosa Ziehau 4307c36fd9eeSSepherosa Ziehau /* Save the mbuf from the driver's chain. */ 430808b64767SSepherosa Ziehau m = rxr->rx_mbuf_ptr[sw_chain_cons]; 430943c2aeb0SSepherosa Ziehau 431043c2aeb0SSepherosa Ziehau /* 431143c2aeb0SSepherosa Ziehau * Frames received on the NetXteme II are prepended 431243c2aeb0SSepherosa Ziehau * with an l2_fhdr structure which provides status 431343c2aeb0SSepherosa Ziehau * information about the received frame (including 431443c2aeb0SSepherosa Ziehau * VLAN tags and checksum info). The frames are also 431543c2aeb0SSepherosa Ziehau * automatically adjusted to align the IP header 431643c2aeb0SSepherosa Ziehau * (i.e. two null bytes are inserted before the 4317cff16e71SSepherosa Ziehau * Ethernet header). As a result the data DMA'd by 4318cff16e71SSepherosa Ziehau * the controller into the mbuf is as follows: 4319cff16e71SSepherosa Ziehau * 4320cff16e71SSepherosa Ziehau * +---------+-----+---------------------+-----+ 4321cff16e71SSepherosa Ziehau * | l2_fhdr | pad | packet data | FCS | 4322cff16e71SSepherosa Ziehau * +---------+-----+---------------------+-----+ 4323cff16e71SSepherosa Ziehau * 4324cff16e71SSepherosa Ziehau * The l2_fhdr needs to be checked and skipped and the 4325cff16e71SSepherosa Ziehau * FCS needs to be stripped before sending the packet 4326cff16e71SSepherosa Ziehau * up the stack. 432743c2aeb0SSepherosa Ziehau */ 432843c2aeb0SSepherosa Ziehau l2fhdr = mtod(m, struct l2_fhdr *); 432943c2aeb0SSepherosa Ziehau 433043c2aeb0SSepherosa Ziehau len = l2fhdr->l2_fhdr_pkt_len; 433143c2aeb0SSepherosa Ziehau status = l2fhdr->l2_fhdr_status; 433243c2aeb0SSepherosa Ziehau 433343c2aeb0SSepherosa Ziehau len -= ETHER_CRC_LEN; 433443c2aeb0SSepherosa Ziehau 433543c2aeb0SSepherosa Ziehau /* Check the received frame for errors. */ 433643c2aeb0SSepherosa Ziehau if (status & (L2_FHDR_ERRORS_BAD_CRC | 433743c2aeb0SSepherosa Ziehau L2_FHDR_ERRORS_PHY_DECODE | 433843c2aeb0SSepherosa Ziehau L2_FHDR_ERRORS_ALIGNMENT | 433943c2aeb0SSepherosa Ziehau L2_FHDR_ERRORS_TOO_SHORT | 434043c2aeb0SSepherosa Ziehau L2_FHDR_ERRORS_GIANT_FRAME)) { 4341d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ierrors, 1); 434243c2aeb0SSepherosa Ziehau 434343c2aeb0SSepherosa Ziehau /* Reuse the mbuf for a new frame. */ 434408b64767SSepherosa Ziehau bce_setup_rxdesc_std(rxr, sw_chain_prod, 4345c36fd9eeSSepherosa Ziehau &sw_prod_bseq); 434643c2aeb0SSepherosa Ziehau m = NULL; 434743c2aeb0SSepherosa Ziehau goto bce_rx_int_next_rx; 434843c2aeb0SSepherosa Ziehau } 434943c2aeb0SSepherosa Ziehau 435043c2aeb0SSepherosa Ziehau /* 435143c2aeb0SSepherosa Ziehau * Get a new mbuf for the rx_bd. If no new 435243c2aeb0SSepherosa Ziehau * mbufs are available then reuse the current mbuf, 435343c2aeb0SSepherosa Ziehau * log an ierror on the interface, and generate 435443c2aeb0SSepherosa Ziehau * an error in the system log. 435543c2aeb0SSepherosa Ziehau */ 435608b64767SSepherosa Ziehau if (bce_newbuf_std(rxr, &sw_prod, &sw_chain_prod, 4357c36fd9eeSSepherosa Ziehau &sw_prod_bseq, 0)) { 4358d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ierrors, 1); 435943c2aeb0SSepherosa Ziehau 436043c2aeb0SSepherosa Ziehau /* Try and reuse the exisitng mbuf. */ 436108b64767SSepherosa Ziehau bce_setup_rxdesc_std(rxr, sw_chain_prod, 4362c36fd9eeSSepherosa Ziehau &sw_prod_bseq); 436343c2aeb0SSepherosa Ziehau m = NULL; 436443c2aeb0SSepherosa Ziehau goto bce_rx_int_next_rx; 436543c2aeb0SSepherosa Ziehau } 436643c2aeb0SSepherosa Ziehau 436743c2aeb0SSepherosa Ziehau /* 436843c2aeb0SSepherosa Ziehau * Skip over the l2_fhdr when passing 436943c2aeb0SSepherosa Ziehau * the data up the stack. 437043c2aeb0SSepherosa Ziehau */ 437143c2aeb0SSepherosa Ziehau m_adj(m, sizeof(struct l2_fhdr) + ETHER_ALIGN); 437243c2aeb0SSepherosa Ziehau 437343c2aeb0SSepherosa Ziehau m->m_pkthdr.len = m->m_len = len; 437443c2aeb0SSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 437543c2aeb0SSepherosa Ziehau 437643c2aeb0SSepherosa Ziehau /* Validate the checksum if offload enabled. */ 437743c2aeb0SSepherosa Ziehau if (ifp->if_capenable & IFCAP_RXCSUM) { 437843c2aeb0SSepherosa Ziehau /* Check for an IP datagram. */ 437943c2aeb0SSepherosa Ziehau if (status & L2_FHDR_STATUS_IP_DATAGRAM) { 438043c2aeb0SSepherosa Ziehau m->m_pkthdr.csum_flags |= 438143c2aeb0SSepherosa Ziehau CSUM_IP_CHECKED; 438243c2aeb0SSepherosa Ziehau 438343c2aeb0SSepherosa Ziehau /* Check if the IP checksum is valid. */ 438443c2aeb0SSepherosa Ziehau if ((l2fhdr->l2_fhdr_ip_xsum ^ 438543c2aeb0SSepherosa Ziehau 0xffff) == 0) { 438643c2aeb0SSepherosa Ziehau m->m_pkthdr.csum_flags |= 438743c2aeb0SSepherosa Ziehau CSUM_IP_VALID; 438843c2aeb0SSepherosa Ziehau } 438943c2aeb0SSepherosa Ziehau } 439043c2aeb0SSepherosa Ziehau 439143c2aeb0SSepherosa Ziehau /* Check for a valid TCP/UDP frame. */ 439243c2aeb0SSepherosa Ziehau if (status & (L2_FHDR_STATUS_TCP_SEGMENT | 439343c2aeb0SSepherosa Ziehau L2_FHDR_STATUS_UDP_DATAGRAM)) { 439443c2aeb0SSepherosa Ziehau 439543c2aeb0SSepherosa Ziehau /* Check for a good TCP/UDP checksum. */ 439643c2aeb0SSepherosa Ziehau if ((status & 439743c2aeb0SSepherosa Ziehau (L2_FHDR_ERRORS_TCP_XSUM | 439843c2aeb0SSepherosa Ziehau L2_FHDR_ERRORS_UDP_XSUM)) == 0) { 439943c2aeb0SSepherosa Ziehau m->m_pkthdr.csum_data = 440043c2aeb0SSepherosa Ziehau l2fhdr->l2_fhdr_tcp_udp_xsum; 440143c2aeb0SSepherosa Ziehau m->m_pkthdr.csum_flags |= 440243c2aeb0SSepherosa Ziehau CSUM_DATA_VALID | 440343c2aeb0SSepherosa Ziehau CSUM_PSEUDO_HDR; 440443c2aeb0SSepherosa Ziehau } 440543c2aeb0SSepherosa Ziehau } 440643c2aeb0SSepherosa Ziehau } 440743c2aeb0SSepherosa Ziehau 4408d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ipackets, 1); 440943c2aeb0SSepherosa Ziehau bce_rx_int_next_rx: 441043c2aeb0SSepherosa Ziehau sw_prod = NEXT_RX_BD(sw_prod); 441143c2aeb0SSepherosa Ziehau } 441243c2aeb0SSepherosa Ziehau 441343c2aeb0SSepherosa Ziehau sw_cons = NEXT_RX_BD(sw_cons); 441443c2aeb0SSepherosa Ziehau 441543c2aeb0SSepherosa Ziehau /* If we have a packet, pass it up the stack */ 441643c2aeb0SSepherosa Ziehau if (m) { 4417e6b5847cSSepherosa Ziehau if (status & L2_FHDR_STATUS_L2_VLAN_TAG) { 4418e6b5847cSSepherosa Ziehau m->m_flags |= M_VLANTAG; 4419e6b5847cSSepherosa Ziehau m->m_pkthdr.ether_vlantag = 4420e6b5847cSSepherosa Ziehau l2fhdr->l2_fhdr_vlan_tag; 4421e6b5847cSSepherosa Ziehau } 4422eda7db08SSepherosa Ziehau ifp->if_input(ifp, m); 442343c2aeb0SSepherosa Ziehau } 442443c2aeb0SSepherosa Ziehau } 442543c2aeb0SSepherosa Ziehau 442608b64767SSepherosa Ziehau rxr->rx_cons = sw_cons; 442708b64767SSepherosa Ziehau rxr->rx_prod = sw_prod; 442808b64767SSepherosa Ziehau rxr->rx_prod_bseq = sw_prod_bseq; 442943c2aeb0SSepherosa Ziehau 443008b64767SSepherosa Ziehau REG_WR16(rxr->sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BDIDX, 443108b64767SSepherosa Ziehau rxr->rx_prod); 443208b64767SSepherosa Ziehau REG_WR(rxr->sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BSEQ, 443308b64767SSepherosa Ziehau rxr->rx_prod_bseq); 443443c2aeb0SSepherosa Ziehau } 443543c2aeb0SSepherosa Ziehau 443643c2aeb0SSepherosa Ziehau 443743c2aeb0SSepherosa Ziehau /****************************************************************************/ 443824603545SSepherosa Ziehau /* Reads the transmit consumer value from the status block (skipping over */ 443924603545SSepherosa Ziehau /* chain page pointer if necessary). */ 444024603545SSepherosa Ziehau /* */ 444124603545SSepherosa Ziehau /* Returns: */ 444224603545SSepherosa Ziehau /* hw_cons */ 444324603545SSepherosa Ziehau /****************************************************************************/ 444424603545SSepherosa Ziehau static __inline uint16_t 444524603545SSepherosa Ziehau bce_get_hw_tx_cons(struct bce_softc *sc) 444624603545SSepherosa Ziehau { 444724603545SSepherosa Ziehau uint16_t hw_cons = sc->status_block->status_tx_quick_consumer_index0; 444824603545SSepherosa Ziehau 444924603545SSepherosa Ziehau if ((hw_cons & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE) 445024603545SSepherosa Ziehau hw_cons++; 445124603545SSepherosa Ziehau return hw_cons; 445224603545SSepherosa Ziehau } 445324603545SSepherosa Ziehau 445424603545SSepherosa Ziehau 445524603545SSepherosa Ziehau /****************************************************************************/ 445643c2aeb0SSepherosa Ziehau /* Handles transmit completion interrupt events. */ 445743c2aeb0SSepherosa Ziehau /* */ 445843c2aeb0SSepherosa Ziehau /* Returns: */ 445943c2aeb0SSepherosa Ziehau /* Nothing. */ 446043c2aeb0SSepherosa Ziehau /****************************************************************************/ 446143c2aeb0SSepherosa Ziehau static void 446210bcbdabSSepherosa Ziehau bce_tx_intr(struct bce_tx_ring *txr, uint16_t hw_tx_cons) 446343c2aeb0SSepherosa Ziehau { 446410bcbdabSSepherosa Ziehau struct ifnet *ifp = &txr->sc->arpcom.ac_if; 4465a5eaa4bfSSepherosa Ziehau uint16_t sw_tx_cons, sw_tx_chain_cons; 446643c2aeb0SSepherosa Ziehau 446784464af5SSepherosa Ziehau ASSERT_SERIALIZED(&txr->tx_serialize); 446843c2aeb0SSepherosa Ziehau 446943c2aeb0SSepherosa Ziehau /* Get the hardware's view of the TX consumer index. */ 447010bcbdabSSepherosa Ziehau sw_tx_cons = txr->tx_cons; 447143c2aeb0SSepherosa Ziehau 447243c2aeb0SSepherosa Ziehau /* Cycle through any completed TX chain page entries. */ 447343c2aeb0SSepherosa Ziehau while (sw_tx_cons != hw_tx_cons) { 447410bcbdabSSepherosa Ziehau sw_tx_chain_cons = TX_CHAIN_IDX(txr, sw_tx_cons); 447543c2aeb0SSepherosa Ziehau 447643c2aeb0SSepherosa Ziehau /* 447743c2aeb0SSepherosa Ziehau * Free the associated mbuf. Remember 447843c2aeb0SSepherosa Ziehau * that only the last tx_bd of a packet 447943c2aeb0SSepherosa Ziehau * has an mbuf pointer and DMA map. 448043c2aeb0SSepherosa Ziehau */ 448110bcbdabSSepherosa Ziehau if (txr->tx_mbuf_ptr[sw_tx_chain_cons] != NULL) { 448243c2aeb0SSepherosa Ziehau /* Unmap the mbuf. */ 448310bcbdabSSepherosa Ziehau bus_dmamap_unload(txr->tx_mbuf_tag, 448410bcbdabSSepherosa Ziehau txr->tx_mbuf_map[sw_tx_chain_cons]); 448543c2aeb0SSepherosa Ziehau 448643c2aeb0SSepherosa Ziehau /* Free the mbuf. */ 448710bcbdabSSepherosa Ziehau m_freem(txr->tx_mbuf_ptr[sw_tx_chain_cons]); 448810bcbdabSSepherosa Ziehau txr->tx_mbuf_ptr[sw_tx_chain_cons] = NULL; 448943c2aeb0SSepherosa Ziehau 4490d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, opackets, 1); 449143c2aeb0SSepherosa Ziehau } 449243c2aeb0SSepherosa Ziehau 449310bcbdabSSepherosa Ziehau txr->used_tx_bd--; 449443c2aeb0SSepherosa Ziehau sw_tx_cons = NEXT_TX_BD(sw_tx_cons); 449543c2aeb0SSepherosa Ziehau } 449643c2aeb0SSepherosa Ziehau 449710bcbdabSSepherosa Ziehau if (txr->used_tx_bd == 0) { 449843c2aeb0SSepherosa Ziehau /* Clear the TX timeout timer. */ 449943c2aeb0SSepherosa Ziehau ifp->if_timer = 0; 450043c2aeb0SSepherosa Ziehau } 450143c2aeb0SSepherosa Ziehau 450243c2aeb0SSepherosa Ziehau /* Clear the tx hardware queue full flag. */ 450310bcbdabSSepherosa Ziehau if (txr->max_tx_bd - txr->used_tx_bd >= BCE_TX_SPARE_SPACE) 45049ed293e0SSepherosa Ziehau ifq_clr_oactive(&ifp->if_snd); 450510bcbdabSSepherosa Ziehau txr->tx_cons = sw_tx_cons; 450643c2aeb0SSepherosa Ziehau } 450743c2aeb0SSepherosa Ziehau 450843c2aeb0SSepherosa Ziehau 450943c2aeb0SSepherosa Ziehau /****************************************************************************/ 451043c2aeb0SSepherosa Ziehau /* Disables interrupt generation. */ 451143c2aeb0SSepherosa Ziehau /* */ 451243c2aeb0SSepherosa Ziehau /* Returns: */ 451343c2aeb0SSepherosa Ziehau /* Nothing. */ 451443c2aeb0SSepherosa Ziehau /****************************************************************************/ 451543c2aeb0SSepherosa Ziehau static void 451643c2aeb0SSepherosa Ziehau bce_disable_intr(struct bce_softc *sc) 451743c2aeb0SSepherosa Ziehau { 451843c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, BCE_PCICFG_INT_ACK_CMD_MASK_INT); 451943c2aeb0SSepherosa Ziehau REG_RD(sc, BCE_PCICFG_INT_ACK_CMD); 452028ef7645SSepherosa Ziehau 452128ef7645SSepherosa Ziehau callout_stop(&sc->bce_ckmsi_callout); 452228ef7645SSepherosa Ziehau sc->bce_msi_maylose = FALSE; 452328ef7645SSepherosa Ziehau sc->bce_check_rx_cons = 0; 452428ef7645SSepherosa Ziehau sc->bce_check_tx_cons = 0; 452528ef7645SSepherosa Ziehau sc->bce_check_status_idx = 0xffff; 452628ef7645SSepherosa Ziehau 452784464af5SSepherosa Ziehau lwkt_serialize_handler_disable(&sc->main_serialize); 452843c2aeb0SSepherosa Ziehau } 452943c2aeb0SSepherosa Ziehau 453043c2aeb0SSepherosa Ziehau 453143c2aeb0SSepherosa Ziehau /****************************************************************************/ 453243c2aeb0SSepherosa Ziehau /* Enables interrupt generation. */ 453343c2aeb0SSepherosa Ziehau /* */ 453443c2aeb0SSepherosa Ziehau /* Returns: */ 453543c2aeb0SSepherosa Ziehau /* Nothing. */ 453643c2aeb0SSepherosa Ziehau /****************************************************************************/ 453743c2aeb0SSepherosa Ziehau static void 4538d4274f6bSSepherosa Ziehau bce_enable_intr(struct bce_softc *sc) 453943c2aeb0SSepherosa Ziehau { 454084464af5SSepherosa Ziehau lwkt_serialize_handler_enable(&sc->main_serialize); 454143c2aeb0SSepherosa Ziehau 454243c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 454343c2aeb0SSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | 454443c2aeb0SSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_MASK_INT | sc->last_status_idx); 454543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 454643c2aeb0SSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx); 454743c2aeb0SSepherosa Ziehau 4548d4274f6bSSepherosa Ziehau REG_WR(sc, BCE_HC_COMMAND, sc->hc_command | BCE_HC_COMMAND_COAL_NOW); 454928ef7645SSepherosa Ziehau 455028ef7645SSepherosa Ziehau if (sc->bce_flags & BCE_CHECK_MSI_FLAG) { 455128ef7645SSepherosa Ziehau sc->bce_msi_maylose = FALSE; 455228ef7645SSepherosa Ziehau sc->bce_check_rx_cons = 0; 455328ef7645SSepherosa Ziehau sc->bce_check_tx_cons = 0; 455428ef7645SSepherosa Ziehau sc->bce_check_status_idx = 0xffff; 455528ef7645SSepherosa Ziehau 455628ef7645SSepherosa Ziehau if (bootverbose) 455728ef7645SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "check msi\n"); 455828ef7645SSepherosa Ziehau 455928ef7645SSepherosa Ziehau callout_reset_bycpu(&sc->bce_ckmsi_callout, BCE_MSI_CKINTVL, 456028ef7645SSepherosa Ziehau bce_check_msi, sc, sc->bce_intr_cpuid); 456128ef7645SSepherosa Ziehau } 456243c2aeb0SSepherosa Ziehau } 456343c2aeb0SSepherosa Ziehau 456443c2aeb0SSepherosa Ziehau 456543c2aeb0SSepherosa Ziehau /****************************************************************************/ 4566d4274f6bSSepherosa Ziehau /* Reenables interrupt generation during interrupt handling. */ 4567d4274f6bSSepherosa Ziehau /* */ 4568d4274f6bSSepherosa Ziehau /* Returns: */ 4569d4274f6bSSepherosa Ziehau /* Nothing. */ 4570d4274f6bSSepherosa Ziehau /****************************************************************************/ 4571d4274f6bSSepherosa Ziehau static void 4572d4274f6bSSepherosa Ziehau bce_reenable_intr(struct bce_softc *sc) 4573d4274f6bSSepherosa Ziehau { 4574d4274f6bSSepherosa Ziehau if (sc->bce_irq_type == PCI_INTR_TYPE_LEGACY) { 4575d4274f6bSSepherosa Ziehau REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 4576d4274f6bSSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | 4577d4274f6bSSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_MASK_INT | sc->last_status_idx); 4578d4274f6bSSepherosa Ziehau } 4579d4274f6bSSepherosa Ziehau REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 4580d4274f6bSSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx); 4581d4274f6bSSepherosa Ziehau } 4582d4274f6bSSepherosa Ziehau 458328ef7645SSepherosa Ziehau 4584d4274f6bSSepherosa Ziehau /****************************************************************************/ 458543c2aeb0SSepherosa Ziehau /* Handles controller initialization. */ 458643c2aeb0SSepherosa Ziehau /* */ 458743c2aeb0SSepherosa Ziehau /* Returns: */ 458843c2aeb0SSepherosa Ziehau /* Nothing. */ 458943c2aeb0SSepherosa Ziehau /****************************************************************************/ 459043c2aeb0SSepherosa Ziehau static void 459143c2aeb0SSepherosa Ziehau bce_init(void *xsc) 459243c2aeb0SSepherosa Ziehau { 459343c2aeb0SSepherosa Ziehau struct bce_softc *sc = xsc; 459443c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 459543c2aeb0SSepherosa Ziehau uint32_t ether_mtu; 459610bcbdabSSepherosa Ziehau int error, i; 459743c2aeb0SSepherosa Ziehau 459884464af5SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 459943c2aeb0SSepherosa Ziehau 460043c2aeb0SSepherosa Ziehau /* Check if the driver is still running and bail out if it is. */ 460143c2aeb0SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 460243c2aeb0SSepherosa Ziehau return; 460343c2aeb0SSepherosa Ziehau 460443c2aeb0SSepherosa Ziehau bce_stop(sc); 460543c2aeb0SSepherosa Ziehau 460643c2aeb0SSepherosa Ziehau error = bce_reset(sc, BCE_DRV_MSG_CODE_RESET); 460743c2aeb0SSepherosa Ziehau if (error) { 460843c2aeb0SSepherosa Ziehau if_printf(ifp, "Controller reset failed!\n"); 460943c2aeb0SSepherosa Ziehau goto back; 461043c2aeb0SSepherosa Ziehau } 461143c2aeb0SSepherosa Ziehau 461243c2aeb0SSepherosa Ziehau error = bce_chipinit(sc); 461343c2aeb0SSepherosa Ziehau if (error) { 461443c2aeb0SSepherosa Ziehau if_printf(ifp, "Controller initialization failed!\n"); 461543c2aeb0SSepherosa Ziehau goto back; 461643c2aeb0SSepherosa Ziehau } 461743c2aeb0SSepherosa Ziehau 461843c2aeb0SSepherosa Ziehau error = bce_blockinit(sc); 461943c2aeb0SSepherosa Ziehau if (error) { 462043c2aeb0SSepherosa Ziehau if_printf(ifp, "Block initialization failed!\n"); 462143c2aeb0SSepherosa Ziehau goto back; 462243c2aeb0SSepherosa Ziehau } 462343c2aeb0SSepherosa Ziehau 462443c2aeb0SSepherosa Ziehau /* Load our MAC address. */ 462543c2aeb0SSepherosa Ziehau bcopy(IF_LLADDR(ifp), sc->eaddr, ETHER_ADDR_LEN); 462643c2aeb0SSepherosa Ziehau bce_set_mac_addr(sc); 462743c2aeb0SSepherosa Ziehau 462843c2aeb0SSepherosa Ziehau /* Calculate and program the Ethernet MTU size. */ 462943c2aeb0SSepherosa Ziehau ether_mtu = ETHER_HDR_LEN + EVL_ENCAPLEN + ifp->if_mtu + ETHER_CRC_LEN; 463043c2aeb0SSepherosa Ziehau 463143c2aeb0SSepherosa Ziehau /* 463243c2aeb0SSepherosa Ziehau * Program the mtu, enabling jumbo frame 463343c2aeb0SSepherosa Ziehau * support if necessary. Also set the mbuf 463443c2aeb0SSepherosa Ziehau * allocation count for RX frames. 463543c2aeb0SSepherosa Ziehau */ 463643c2aeb0SSepherosa Ziehau if (ether_mtu > ETHER_MAX_LEN + EVL_ENCAPLEN) { 463743c2aeb0SSepherosa Ziehau #ifdef notyet 463843c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, 463943c2aeb0SSepherosa Ziehau min(ether_mtu, BCE_MAX_JUMBO_ETHER_MTU) | 464043c2aeb0SSepherosa Ziehau BCE_EMAC_RX_MTU_SIZE_JUMBO_ENA); 464143c2aeb0SSepherosa Ziehau #else 4642ed20d0e3SSascha Wildner panic("jumbo buffer is not supported yet"); 464343c2aeb0SSepherosa Ziehau #endif 464443c2aeb0SSepherosa Ziehau } else { 464543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, ether_mtu); 464643c2aeb0SSepherosa Ziehau } 464743c2aeb0SSepherosa Ziehau 464843c2aeb0SSepherosa Ziehau /* Program appropriate promiscuous/multicast filtering. */ 464943c2aeb0SSepherosa Ziehau bce_set_rx_mode(sc); 465043c2aeb0SSepherosa Ziehau 465143c2aeb0SSepherosa Ziehau /* Init RX buffer descriptor chain. */ 465208b64767SSepherosa Ziehau for (i = 0; i < sc->ring_cnt; ++i) 465308b64767SSepherosa Ziehau bce_init_rx_chain(&sc->rx_rings[i]); /* XXX return value */ 465443c2aeb0SSepherosa Ziehau 465543c2aeb0SSepherosa Ziehau /* Init TX buffer descriptor chain. */ 465610bcbdabSSepherosa Ziehau for (i = 0; i < sc->ring_cnt; ++i) 465710bcbdabSSepherosa Ziehau bce_init_tx_chain(&sc->tx_rings[i]); 465843c2aeb0SSepherosa Ziehau 46594a331bf7SSepherosa Ziehau #ifdef IFPOLL_ENABLE 466043c2aeb0SSepherosa Ziehau /* Disable interrupts if we are polling. */ 46614a331bf7SSepherosa Ziehau if (ifp->if_flags & IFF_NPOLLING) { 466243c2aeb0SSepherosa Ziehau bce_disable_intr(sc); 466343c2aeb0SSepherosa Ziehau 466443c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, 466543c2aeb0SSepherosa Ziehau (1 << 16) | sc->bce_rx_quick_cons_trip); 466643c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, 466743c2aeb0SSepherosa Ziehau (1 << 16) | sc->bce_tx_quick_cons_trip); 466843c2aeb0SSepherosa Ziehau } else 466943c2aeb0SSepherosa Ziehau #endif 467043c2aeb0SSepherosa Ziehau /* Enable host interrupts. */ 4671d4274f6bSSepherosa Ziehau bce_enable_intr(sc); 467243c2aeb0SSepherosa Ziehau 467343c2aeb0SSepherosa Ziehau bce_ifmedia_upd(ifp); 467443c2aeb0SSepherosa Ziehau 467543c2aeb0SSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 46769ed293e0SSepherosa Ziehau ifq_clr_oactive(&ifp->if_snd); 467743c2aeb0SSepherosa Ziehau 4678a131f6c2SSepherosa Ziehau callout_reset_bycpu(&sc->bce_tick_callout, hz, bce_tick, sc, 4679a131f6c2SSepherosa Ziehau sc->bce_intr_cpuid); 468043c2aeb0SSepherosa Ziehau back: 468143c2aeb0SSepherosa Ziehau if (error) 468243c2aeb0SSepherosa Ziehau bce_stop(sc); 468343c2aeb0SSepherosa Ziehau } 468443c2aeb0SSepherosa Ziehau 468543c2aeb0SSepherosa Ziehau 468643c2aeb0SSepherosa Ziehau /****************************************************************************/ 468743c2aeb0SSepherosa Ziehau /* Initialize the controller just enough so that any management firmware */ 468843c2aeb0SSepherosa Ziehau /* running on the device will continue to operate corectly. */ 468943c2aeb0SSepherosa Ziehau /* */ 469043c2aeb0SSepherosa Ziehau /* Returns: */ 469143c2aeb0SSepherosa Ziehau /* Nothing. */ 469243c2aeb0SSepherosa Ziehau /****************************************************************************/ 469343c2aeb0SSepherosa Ziehau static void 469443c2aeb0SSepherosa Ziehau bce_mgmt_init(struct bce_softc *sc) 469543c2aeb0SSepherosa Ziehau { 469643c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 469743c2aeb0SSepherosa Ziehau 4698d0092544SSepherosa Ziehau /* Bail out if management firmware is not running. */ 4699d0092544SSepherosa Ziehau if (!(sc->bce_flags & BCE_MFW_ENABLE_FLAG)) 470043c2aeb0SSepherosa Ziehau return; 470143c2aeb0SSepherosa Ziehau 470243c2aeb0SSepherosa Ziehau /* Enable all critical blocks in the MAC. */ 4703d0092544SSepherosa Ziehau if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709 || 4704d0092544SSepherosa Ziehau BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716) { 470543c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, 4706d0092544SSepherosa Ziehau BCE_MISC_ENABLE_DEFAULT_XI); 4707d0092544SSepherosa Ziehau } else { 4708d0092544SSepherosa Ziehau REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, BCE_MISC_ENABLE_DEFAULT); 4709d0092544SSepherosa Ziehau } 471043c2aeb0SSepherosa Ziehau REG_RD(sc, BCE_MISC_ENABLE_SET_BITS); 471143c2aeb0SSepherosa Ziehau DELAY(20); 471243c2aeb0SSepherosa Ziehau 471343c2aeb0SSepherosa Ziehau bce_ifmedia_upd(ifp); 471443c2aeb0SSepherosa Ziehau } 471543c2aeb0SSepherosa Ziehau 471643c2aeb0SSepherosa Ziehau 471743c2aeb0SSepherosa Ziehau /****************************************************************************/ 471843c2aeb0SSepherosa Ziehau /* Encapsultes an mbuf cluster into the tx_bd chain structure and makes the */ 471943c2aeb0SSepherosa Ziehau /* memory visible to the controller. */ 472043c2aeb0SSepherosa Ziehau /* */ 472143c2aeb0SSepherosa Ziehau /* Returns: */ 472243c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 472343c2aeb0SSepherosa Ziehau /****************************************************************************/ 472443c2aeb0SSepherosa Ziehau static int 472510bcbdabSSepherosa Ziehau bce_encap(struct bce_tx_ring *txr, struct mbuf **m_head, int *nsegs_used) 472643c2aeb0SSepherosa Ziehau { 472743c2aeb0SSepherosa Ziehau bus_dma_segment_t segs[BCE_MAX_SEGMENTS]; 472843c2aeb0SSepherosa Ziehau bus_dmamap_t map, tmp_map; 472943c2aeb0SSepherosa Ziehau struct mbuf *m0 = *m_head; 473043c2aeb0SSepherosa Ziehau struct tx_bd *txbd = NULL; 4731eefd160dSSepherosa Ziehau uint16_t vlan_tag = 0, flags = 0, mss = 0; 473243c2aeb0SSepherosa Ziehau uint16_t chain_prod, chain_prod_start, prod; 473343c2aeb0SSepherosa Ziehau uint32_t prod_bseq; 4734ba0809ceSSepherosa Ziehau int i, error, maxsegs, nsegs; 473543c2aeb0SSepherosa Ziehau 473643c2aeb0SSepherosa Ziehau /* Transfer any checksum offload flags to the bd. */ 4737eefd160dSSepherosa Ziehau if (m0->m_pkthdr.csum_flags & CSUM_TSO) { 473810bcbdabSSepherosa Ziehau error = bce_tso_setup(txr, m_head, &flags, &mss); 4739eefd160dSSepherosa Ziehau if (error) 4740eefd160dSSepherosa Ziehau return ENOBUFS; 4741eefd160dSSepherosa Ziehau m0 = *m_head; 4742eefd160dSSepherosa Ziehau } else if (m0->m_pkthdr.csum_flags & BCE_CSUM_FEATURES) { 474343c2aeb0SSepherosa Ziehau if (m0->m_pkthdr.csum_flags & CSUM_IP) 474443c2aeb0SSepherosa Ziehau flags |= TX_BD_FLAGS_IP_CKSUM; 474543c2aeb0SSepherosa Ziehau if (m0->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 474643c2aeb0SSepherosa Ziehau flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; 474743c2aeb0SSepherosa Ziehau } 474843c2aeb0SSepherosa Ziehau 474943c2aeb0SSepherosa Ziehau /* Transfer any VLAN tags to the bd. */ 475083790f85SSepherosa Ziehau if (m0->m_flags & M_VLANTAG) { 475143c2aeb0SSepherosa Ziehau flags |= TX_BD_FLAGS_VLAN_TAG; 475283790f85SSepherosa Ziehau vlan_tag = m0->m_pkthdr.ether_vlantag; 475343c2aeb0SSepherosa Ziehau } 475443c2aeb0SSepherosa Ziehau 475510bcbdabSSepherosa Ziehau prod = txr->tx_prod; 475610bcbdabSSepherosa Ziehau chain_prod_start = chain_prod = TX_CHAIN_IDX(txr, prod); 475743c2aeb0SSepherosa Ziehau 475843c2aeb0SSepherosa Ziehau /* Map the mbuf into DMAable memory. */ 475910bcbdabSSepherosa Ziehau map = txr->tx_mbuf_map[chain_prod_start]; 476043c2aeb0SSepherosa Ziehau 476110bcbdabSSepherosa Ziehau maxsegs = txr->max_tx_bd - txr->used_tx_bd; 476243c2aeb0SSepherosa Ziehau KASSERT(maxsegs >= BCE_TX_SPARE_SPACE, 4763ed20d0e3SSascha Wildner ("not enough segments %d", maxsegs)); 476443c2aeb0SSepherosa Ziehau if (maxsegs > BCE_MAX_SEGMENTS) 476543c2aeb0SSepherosa Ziehau maxsegs = BCE_MAX_SEGMENTS; 476643c2aeb0SSepherosa Ziehau 476743c2aeb0SSepherosa Ziehau /* Map the mbuf into our DMA address space. */ 476810bcbdabSSepherosa Ziehau error = bus_dmamap_load_mbuf_defrag(txr->tx_mbuf_tag, map, m_head, 4769ba0809ceSSepherosa Ziehau segs, maxsegs, &nsegs, BUS_DMA_NOWAIT); 4770ba0809ceSSepherosa Ziehau if (error) 4771ba0809ceSSepherosa Ziehau goto back; 477210bcbdabSSepherosa Ziehau bus_dmamap_sync(txr->tx_mbuf_tag, map, BUS_DMASYNC_PREWRITE); 477343c2aeb0SSepherosa Ziehau 4774f52858a0SSepherosa Ziehau *nsegs_used += nsegs; 4775f52858a0SSepherosa Ziehau 4776ba0809ceSSepherosa Ziehau /* Reset m0 */ 4777ba0809ceSSepherosa Ziehau m0 = *m_head; 477843c2aeb0SSepherosa Ziehau 477943c2aeb0SSepherosa Ziehau /* prod points to an empty tx_bd at this point. */ 478010bcbdabSSepherosa Ziehau prod_bseq = txr->tx_prod_bseq; 478143c2aeb0SSepherosa Ziehau 478243c2aeb0SSepherosa Ziehau /* 478343c2aeb0SSepherosa Ziehau * Cycle through each mbuf segment that makes up 478443c2aeb0SSepherosa Ziehau * the outgoing frame, gathering the mapping info 478543c2aeb0SSepherosa Ziehau * for that segment and creating a tx_bd to for 478643c2aeb0SSepherosa Ziehau * the mbuf. 478743c2aeb0SSepherosa Ziehau */ 4788ba0809ceSSepherosa Ziehau for (i = 0; i < nsegs; i++) { 478910bcbdabSSepherosa Ziehau chain_prod = TX_CHAIN_IDX(txr, prod); 479010bcbdabSSepherosa Ziehau txbd = 479110bcbdabSSepherosa Ziehau &txr->tx_bd_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)]; 479243c2aeb0SSepherosa Ziehau 479343c2aeb0SSepherosa Ziehau txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr)); 479443c2aeb0SSepherosa Ziehau txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr)); 4795eefd160dSSepherosa Ziehau txbd->tx_bd_mss_nbytes = htole32(mss << 16) | 4796eefd160dSSepherosa Ziehau htole16(segs[i].ds_len); 479743c2aeb0SSepherosa Ziehau txbd->tx_bd_vlan_tag = htole16(vlan_tag); 479843c2aeb0SSepherosa Ziehau txbd->tx_bd_flags = htole16(flags); 4799eefd160dSSepherosa Ziehau 480043c2aeb0SSepherosa Ziehau prod_bseq += segs[i].ds_len; 480143c2aeb0SSepherosa Ziehau if (i == 0) 480243c2aeb0SSepherosa Ziehau txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_START); 480343c2aeb0SSepherosa Ziehau prod = NEXT_TX_BD(prod); 480443c2aeb0SSepherosa Ziehau } 480543c2aeb0SSepherosa Ziehau 480643c2aeb0SSepherosa Ziehau /* Set the END flag on the last TX buffer descriptor. */ 480743c2aeb0SSepherosa Ziehau txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_END); 480843c2aeb0SSepherosa Ziehau 480943c2aeb0SSepherosa Ziehau /* 481043c2aeb0SSepherosa Ziehau * Ensure that the mbuf pointer for this transmission 481143c2aeb0SSepherosa Ziehau * is placed at the array index of the last 481243c2aeb0SSepherosa Ziehau * descriptor in this chain. This is done 481343c2aeb0SSepherosa Ziehau * because a single map is used for all 481443c2aeb0SSepherosa Ziehau * segments of the mbuf and we don't want to 481543c2aeb0SSepherosa Ziehau * unload the map before all of the segments 481643c2aeb0SSepherosa Ziehau * have been freed. 481743c2aeb0SSepherosa Ziehau */ 481810bcbdabSSepherosa Ziehau txr->tx_mbuf_ptr[chain_prod] = m0; 481943c2aeb0SSepherosa Ziehau 482010bcbdabSSepherosa Ziehau tmp_map = txr->tx_mbuf_map[chain_prod]; 482110bcbdabSSepherosa Ziehau txr->tx_mbuf_map[chain_prod] = map; 482210bcbdabSSepherosa Ziehau txr->tx_mbuf_map[chain_prod_start] = tmp_map; 482343c2aeb0SSepherosa Ziehau 482410bcbdabSSepherosa Ziehau txr->used_tx_bd += nsegs; 482543c2aeb0SSepherosa Ziehau 482643c2aeb0SSepherosa Ziehau /* prod points to the next free tx_bd at this point. */ 482710bcbdabSSepherosa Ziehau txr->tx_prod = prod; 482810bcbdabSSepherosa Ziehau txr->tx_prod_bseq = prod_bseq; 482943c2aeb0SSepherosa Ziehau back: 483043c2aeb0SSepherosa Ziehau if (error) { 483143c2aeb0SSepherosa Ziehau m_freem(*m_head); 483243c2aeb0SSepherosa Ziehau *m_head = NULL; 483343c2aeb0SSepherosa Ziehau } 483443c2aeb0SSepherosa Ziehau return error; 483543c2aeb0SSepherosa Ziehau } 483643c2aeb0SSepherosa Ziehau 483743c2aeb0SSepherosa Ziehau 483834483efcSSepherosa Ziehau static void 483910bcbdabSSepherosa Ziehau bce_xmit(struct bce_tx_ring *txr) 484034483efcSSepherosa Ziehau { 484134483efcSSepherosa Ziehau /* Start the transmit. */ 484210bcbdabSSepherosa Ziehau REG_WR16(txr->sc, MB_GET_CID_ADDR(TX_CID) + BCE_L2CTX_TX_HOST_BIDX, 484310bcbdabSSepherosa Ziehau txr->tx_prod); 484410bcbdabSSepherosa Ziehau REG_WR(txr->sc, MB_GET_CID_ADDR(TX_CID) + BCE_L2CTX_TX_HOST_BSEQ, 484510bcbdabSSepherosa Ziehau txr->tx_prod_bseq); 484634483efcSSepherosa Ziehau } 484734483efcSSepherosa Ziehau 484834483efcSSepherosa Ziehau 484943c2aeb0SSepherosa Ziehau /****************************************************************************/ 485043c2aeb0SSepherosa Ziehau /* Main transmit routine when called from another routine with a lock. */ 485143c2aeb0SSepherosa Ziehau /* */ 485243c2aeb0SSepherosa Ziehau /* Returns: */ 485343c2aeb0SSepherosa Ziehau /* Nothing. */ 485443c2aeb0SSepherosa Ziehau /****************************************************************************/ 485543c2aeb0SSepherosa Ziehau static void 4856f0a26983SSepherosa Ziehau bce_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) 485743c2aeb0SSepherosa Ziehau { 485843c2aeb0SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 485910bcbdabSSepherosa Ziehau struct bce_tx_ring *txr = &sc->tx_rings[0]; 486043c2aeb0SSepherosa Ziehau int count = 0; 486143c2aeb0SSepherosa Ziehau 4862f0a26983SSepherosa Ziehau ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); 486384464af5SSepherosa Ziehau ASSERT_SERIALIZED(&txr->tx_serialize); 486443c2aeb0SSepherosa Ziehau 486543c2aeb0SSepherosa Ziehau /* If there's no link or the transmit queue is empty then just exit. */ 48669db4b353SSepherosa Ziehau if (!sc->bce_link) { 48679db4b353SSepherosa Ziehau ifq_purge(&ifp->if_snd); 48689db4b353SSepherosa Ziehau return; 48699db4b353SSepherosa Ziehau } 48709db4b353SSepherosa Ziehau 48719ed293e0SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) == 0 || ifq_is_oactive(&ifp->if_snd)) 487243c2aeb0SSepherosa Ziehau return; 487343c2aeb0SSepherosa Ziehau 487443c2aeb0SSepherosa Ziehau for (;;) { 487543c2aeb0SSepherosa Ziehau struct mbuf *m_head; 487643c2aeb0SSepherosa Ziehau 487743c2aeb0SSepherosa Ziehau /* 487843c2aeb0SSepherosa Ziehau * We keep BCE_TX_SPARE_SPACE entries, so bce_encap() is 487943c2aeb0SSepherosa Ziehau * unlikely to fail. 488043c2aeb0SSepherosa Ziehau */ 488110bcbdabSSepherosa Ziehau if (txr->max_tx_bd - txr->used_tx_bd < BCE_TX_SPARE_SPACE) { 48829ed293e0SSepherosa Ziehau ifq_set_oactive(&ifp->if_snd); 488343c2aeb0SSepherosa Ziehau break; 488443c2aeb0SSepherosa Ziehau } 488543c2aeb0SSepherosa Ziehau 488643c2aeb0SSepherosa Ziehau /* Check for any frames to send. */ 488743c2aeb0SSepherosa Ziehau m_head = ifq_dequeue(&ifp->if_snd, NULL); 488843c2aeb0SSepherosa Ziehau if (m_head == NULL) 488943c2aeb0SSepherosa Ziehau break; 489043c2aeb0SSepherosa Ziehau 489143c2aeb0SSepherosa Ziehau /* 489243c2aeb0SSepherosa Ziehau * Pack the data into the transmit ring. If we 489343c2aeb0SSepherosa Ziehau * don't have room, place the mbuf back at the 489443c2aeb0SSepherosa Ziehau * head of the queue and set the OACTIVE flag 489543c2aeb0SSepherosa Ziehau * to wait for the NIC to drain the chain. 489643c2aeb0SSepherosa Ziehau */ 489710bcbdabSSepherosa Ziehau if (bce_encap(txr, &m_head, &count)) { 4898d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 1); 489910bcbdabSSepherosa Ziehau if (txr->used_tx_bd == 0) { 4900ba0809ceSSepherosa Ziehau continue; 4901ba0809ceSSepherosa Ziehau } else { 49029ed293e0SSepherosa Ziehau ifq_set_oactive(&ifp->if_snd); 490343c2aeb0SSepherosa Ziehau break; 490443c2aeb0SSepherosa Ziehau } 4905ba0809ceSSepherosa Ziehau } 490643c2aeb0SSepherosa Ziehau 490710bcbdabSSepherosa Ziehau if (count >= txr->tx_wreg) { 490810bcbdabSSepherosa Ziehau bce_xmit(txr); 4909f52858a0SSepherosa Ziehau count = 0; 4910f52858a0SSepherosa Ziehau } 491143c2aeb0SSepherosa Ziehau 491243c2aeb0SSepherosa Ziehau /* Send a copy of the frame to any BPF listeners. */ 4913b637f170SSepherosa Ziehau ETHER_BPF_MTAP(ifp, m_head); 4914f52858a0SSepherosa Ziehau 4915f52858a0SSepherosa Ziehau /* Set the tx timeout. */ 4916f52858a0SSepherosa Ziehau ifp->if_timer = BCE_TX_TIMEOUT; 491743c2aeb0SSepherosa Ziehau } 491834483efcSSepherosa Ziehau if (count > 0) 491910bcbdabSSepherosa Ziehau bce_xmit(txr); 492043c2aeb0SSepherosa Ziehau } 492143c2aeb0SSepherosa Ziehau 492243c2aeb0SSepherosa Ziehau 492343c2aeb0SSepherosa Ziehau /****************************************************************************/ 492443c2aeb0SSepherosa Ziehau /* Handles any IOCTL calls from the operating system. */ 492543c2aeb0SSepherosa Ziehau /* */ 492643c2aeb0SSepherosa Ziehau /* Returns: */ 492743c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 492843c2aeb0SSepherosa Ziehau /****************************************************************************/ 492943c2aeb0SSepherosa Ziehau static int 493043c2aeb0SSepherosa Ziehau bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) 493143c2aeb0SSepherosa Ziehau { 493243c2aeb0SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 493343c2aeb0SSepherosa Ziehau struct ifreq *ifr = (struct ifreq *)data; 493443c2aeb0SSepherosa Ziehau struct mii_data *mii; 493543c2aeb0SSepherosa Ziehau int mask, error = 0; 493643c2aeb0SSepherosa Ziehau 493784464af5SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 493843c2aeb0SSepherosa Ziehau 493943c2aeb0SSepherosa Ziehau switch(command) { 494043c2aeb0SSepherosa Ziehau case SIOCSIFMTU: 494143c2aeb0SSepherosa Ziehau /* Check that the MTU setting is supported. */ 494243c2aeb0SSepherosa Ziehau if (ifr->ifr_mtu < BCE_MIN_MTU || 494343c2aeb0SSepherosa Ziehau #ifdef notyet 494443c2aeb0SSepherosa Ziehau ifr->ifr_mtu > BCE_MAX_JUMBO_MTU 494543c2aeb0SSepherosa Ziehau #else 494643c2aeb0SSepherosa Ziehau ifr->ifr_mtu > ETHERMTU 494743c2aeb0SSepherosa Ziehau #endif 494843c2aeb0SSepherosa Ziehau ) { 494943c2aeb0SSepherosa Ziehau error = EINVAL; 495043c2aeb0SSepherosa Ziehau break; 495143c2aeb0SSepherosa Ziehau } 495243c2aeb0SSepherosa Ziehau 495343c2aeb0SSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 495443c2aeb0SSepherosa Ziehau ifp->if_flags &= ~IFF_RUNNING; /* Force reinitialize */ 495543c2aeb0SSepherosa Ziehau bce_init(sc); 495643c2aeb0SSepherosa Ziehau break; 495743c2aeb0SSepherosa Ziehau 495843c2aeb0SSepherosa Ziehau case SIOCSIFFLAGS: 495943c2aeb0SSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 496043c2aeb0SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 496143c2aeb0SSepherosa Ziehau mask = ifp->if_flags ^ sc->bce_if_flags; 496243c2aeb0SSepherosa Ziehau 496343c2aeb0SSepherosa Ziehau if (mask & (IFF_PROMISC | IFF_ALLMULTI)) 496443c2aeb0SSepherosa Ziehau bce_set_rx_mode(sc); 496543c2aeb0SSepherosa Ziehau } else { 496643c2aeb0SSepherosa Ziehau bce_init(sc); 496743c2aeb0SSepherosa Ziehau } 496843c2aeb0SSepherosa Ziehau } else if (ifp->if_flags & IFF_RUNNING) { 496943c2aeb0SSepherosa Ziehau bce_stop(sc); 4970d0092544SSepherosa Ziehau 4971d0092544SSepherosa Ziehau /* If MFW is running, restart the controller a bit. */ 4972d0092544SSepherosa Ziehau if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) { 4973d0092544SSepherosa Ziehau bce_reset(sc, BCE_DRV_MSG_CODE_RESET); 4974d0092544SSepherosa Ziehau bce_chipinit(sc); 4975d0092544SSepherosa Ziehau bce_mgmt_init(sc); 4976d0092544SSepherosa Ziehau } 497743c2aeb0SSepherosa Ziehau } 497843c2aeb0SSepherosa Ziehau sc->bce_if_flags = ifp->if_flags; 497943c2aeb0SSepherosa Ziehau break; 498043c2aeb0SSepherosa Ziehau 498143c2aeb0SSepherosa Ziehau case SIOCADDMULTI: 498243c2aeb0SSepherosa Ziehau case SIOCDELMULTI: 498343c2aeb0SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 498443c2aeb0SSepherosa Ziehau bce_set_rx_mode(sc); 498543c2aeb0SSepherosa Ziehau break; 498643c2aeb0SSepherosa Ziehau 498743c2aeb0SSepherosa Ziehau case SIOCSIFMEDIA: 498843c2aeb0SSepherosa Ziehau case SIOCGIFMEDIA: 498943c2aeb0SSepherosa Ziehau mii = device_get_softc(sc->bce_miibus); 499043c2aeb0SSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 499143c2aeb0SSepherosa Ziehau break; 499243c2aeb0SSepherosa Ziehau 499343c2aeb0SSepherosa Ziehau case SIOCSIFCAP: 499443c2aeb0SSepherosa Ziehau mask = ifr->ifr_reqcap ^ ifp->if_capenable; 499543c2aeb0SSepherosa Ziehau if (mask & IFCAP_HWCSUM) { 499671e2c3e7SSepherosa Ziehau ifp->if_capenable ^= (mask & IFCAP_HWCSUM); 4997eefd160dSSepherosa Ziehau if (ifp->if_capenable & IFCAP_TXCSUM) 4998eefd160dSSepherosa Ziehau ifp->if_hwassist |= BCE_CSUM_FEATURES; 499943c2aeb0SSepherosa Ziehau else 5000eefd160dSSepherosa Ziehau ifp->if_hwassist &= ~BCE_CSUM_FEATURES; 5001eefd160dSSepherosa Ziehau } 5002eefd160dSSepherosa Ziehau if (mask & IFCAP_TSO) { 5003eefd160dSSepherosa Ziehau ifp->if_capenable ^= IFCAP_TSO; 5004eefd160dSSepherosa Ziehau if (ifp->if_capenable & IFCAP_TSO) 5005eefd160dSSepherosa Ziehau ifp->if_hwassist |= CSUM_TSO; 5006eefd160dSSepherosa Ziehau else 5007eefd160dSSepherosa Ziehau ifp->if_hwassist &= ~CSUM_TSO; 500843c2aeb0SSepherosa Ziehau } 500943c2aeb0SSepherosa Ziehau break; 501043c2aeb0SSepherosa Ziehau 501143c2aeb0SSepherosa Ziehau default: 501243c2aeb0SSepherosa Ziehau error = ether_ioctl(ifp, command, data); 501343c2aeb0SSepherosa Ziehau break; 501443c2aeb0SSepherosa Ziehau } 501543c2aeb0SSepherosa Ziehau return error; 501643c2aeb0SSepherosa Ziehau } 501743c2aeb0SSepherosa Ziehau 501843c2aeb0SSepherosa Ziehau 501943c2aeb0SSepherosa Ziehau /****************************************************************************/ 502043c2aeb0SSepherosa Ziehau /* Transmit timeout handler. */ 502143c2aeb0SSepherosa Ziehau /* */ 502243c2aeb0SSepherosa Ziehau /* Returns: */ 502343c2aeb0SSepherosa Ziehau /* Nothing. */ 502443c2aeb0SSepherosa Ziehau /****************************************************************************/ 502543c2aeb0SSepherosa Ziehau static void 502643c2aeb0SSepherosa Ziehau bce_watchdog(struct ifnet *ifp) 502743c2aeb0SSepherosa Ziehau { 502843c2aeb0SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 502943c2aeb0SSepherosa Ziehau 503084464af5SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 503143c2aeb0SSepherosa Ziehau 503243c2aeb0SSepherosa Ziehau /* 503343c2aeb0SSepherosa Ziehau * If we are in this routine because of pause frames, then 503443c2aeb0SSepherosa Ziehau * don't reset the hardware. 503543c2aeb0SSepherosa Ziehau */ 503643c2aeb0SSepherosa Ziehau if (REG_RD(sc, BCE_EMAC_TX_STATUS) & BCE_EMAC_TX_STATUS_XOFFED) 503743c2aeb0SSepherosa Ziehau return; 503843c2aeb0SSepherosa Ziehau 503943c2aeb0SSepherosa Ziehau if_printf(ifp, "Watchdog timeout occurred, resetting!\n"); 504043c2aeb0SSepherosa Ziehau 504143c2aeb0SSepherosa Ziehau ifp->if_flags &= ~IFF_RUNNING; /* Force reinitialize */ 504243c2aeb0SSepherosa Ziehau bce_init(sc); 504343c2aeb0SSepherosa Ziehau 5044d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 1); 504543c2aeb0SSepherosa Ziehau 504643c2aeb0SSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 50479db4b353SSepherosa Ziehau if_devstart(ifp); 504843c2aeb0SSepherosa Ziehau } 504943c2aeb0SSepherosa Ziehau 505043c2aeb0SSepherosa Ziehau 50514a331bf7SSepherosa Ziehau #ifdef IFPOLL_ENABLE 505243c2aeb0SSepherosa Ziehau 505343c2aeb0SSepherosa Ziehau static void 505457b3ecd9SSepherosa Ziehau bce_npoll_status(struct ifnet *ifp) 505543c2aeb0SSepherosa Ziehau { 505643c2aeb0SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 505743c2aeb0SSepherosa Ziehau struct status_block *sblk = sc->status_block; 505843c2aeb0SSepherosa Ziehau uint32_t status_attn_bits; 505943c2aeb0SSepherosa Ziehau 506057b3ecd9SSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize); 50614a331bf7SSepherosa Ziehau 506243c2aeb0SSepherosa Ziehau status_attn_bits = sblk->status_attn_bits; 506343c2aeb0SSepherosa Ziehau 506443c2aeb0SSepherosa Ziehau /* Was it a link change interrupt? */ 506543c2aeb0SSepherosa Ziehau if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 506657b3ecd9SSepherosa Ziehau (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE)) { 506743c2aeb0SSepherosa Ziehau bce_phy_intr(sc); 506843c2aeb0SSepherosa Ziehau 50696a8549eaSSepherosa Ziehau /* 50706a8549eaSSepherosa Ziehau * Clear any transient status updates during link state change. 50716a8549eaSSepherosa Ziehau */ 5072d0092544SSepherosa Ziehau REG_WR(sc, BCE_HC_COMMAND, 5073d0092544SSepherosa Ziehau sc->hc_command | BCE_HC_COMMAND_COAL_NOW_WO_INT); 5074d0092544SSepherosa Ziehau REG_RD(sc, BCE_HC_COMMAND); 507557b3ecd9SSepherosa Ziehau } 5076d0092544SSepherosa Ziehau 507743c2aeb0SSepherosa Ziehau /* 50786a8549eaSSepherosa Ziehau * If any other attention is asserted then the chip is toast. 507943c2aeb0SSepherosa Ziehau */ 508043c2aeb0SSepherosa Ziehau if ((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) != 508157b3ecd9SSepherosa Ziehau (sblk->status_attn_bits_ack & ~STATUS_ATTN_BITS_LINK_STATE)) { 508243c2aeb0SSepherosa Ziehau if_printf(ifp, "Fatal attention detected: 0x%08X\n", 508343c2aeb0SSepherosa Ziehau sblk->status_attn_bits); 508484464af5SSepherosa Ziehau bce_serialize_skipmain(sc); 508543c2aeb0SSepherosa Ziehau bce_init(sc); 508684464af5SSepherosa Ziehau bce_deserialize_skipmain(sc); 508743c2aeb0SSepherosa Ziehau } 508843c2aeb0SSepherosa Ziehau } 508943c2aeb0SSepherosa Ziehau 509057b3ecd9SSepherosa Ziehau static void 509157b3ecd9SSepherosa Ziehau bce_npoll_rx(struct ifnet *ifp, void *arg, int count) 509257b3ecd9SSepherosa Ziehau { 509357b3ecd9SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 509457b3ecd9SSepherosa Ziehau struct bce_rx_ring *rxr = arg; 509557b3ecd9SSepherosa Ziehau struct status_block *sblk = sc->status_block; 509657b3ecd9SSepherosa Ziehau uint16_t hw_rx_cons; 509757b3ecd9SSepherosa Ziehau 509857b3ecd9SSepherosa Ziehau ASSERT_SERIALIZED(&rxr->rx_serialize); 509957b3ecd9SSepherosa Ziehau 510057b3ecd9SSepherosa Ziehau /* 510157b3ecd9SSepherosa Ziehau * Save the status block index value for use when enabling 510257b3ecd9SSepherosa Ziehau * the interrupt. 510357b3ecd9SSepherosa Ziehau */ 510457b3ecd9SSepherosa Ziehau sc->last_status_idx = sblk->status_idx; 510557b3ecd9SSepherosa Ziehau 510657b3ecd9SSepherosa Ziehau /* Make sure status index is extracted before RX/TX cons */ 510757b3ecd9SSepherosa Ziehau cpu_lfence(); 510857b3ecd9SSepherosa Ziehau 510924603545SSepherosa Ziehau hw_rx_cons = bce_get_hw_rx_cons(sc); 511024603545SSepherosa Ziehau 511143c2aeb0SSepherosa Ziehau /* Check for any completed RX frames. */ 511208b64767SSepherosa Ziehau if (hw_rx_cons != rxr->rx_cons) 511308b64767SSepherosa Ziehau bce_rx_intr(rxr, count, hw_rx_cons); 511457b3ecd9SSepherosa Ziehau } 511557b3ecd9SSepherosa Ziehau 511657b3ecd9SSepherosa Ziehau static void 511757b3ecd9SSepherosa Ziehau bce_npoll_tx(struct ifnet *ifp, void *arg, int count __unused) 511857b3ecd9SSepherosa Ziehau { 511957b3ecd9SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 512057b3ecd9SSepherosa Ziehau struct bce_tx_ring *txr = arg; 512157b3ecd9SSepherosa Ziehau uint16_t hw_tx_cons; 512257b3ecd9SSepherosa Ziehau 512357b3ecd9SSepherosa Ziehau ASSERT_SERIALIZED(&txr->tx_serialize); 512457b3ecd9SSepherosa Ziehau 512557b3ecd9SSepherosa Ziehau hw_tx_cons = bce_get_hw_tx_cons(sc); 512643c2aeb0SSepherosa Ziehau 512743c2aeb0SSepherosa Ziehau /* Check for any completed TX frames. */ 512884464af5SSepherosa Ziehau if (hw_tx_cons != txr->tx_cons) { 512910bcbdabSSepherosa Ziehau bce_tx_intr(txr, hw_tx_cons); 513084464af5SSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 513184464af5SSepherosa Ziehau if_devstart(ifp); 513284464af5SSepherosa Ziehau } 513343c2aeb0SSepherosa Ziehau } 513443c2aeb0SSepherosa Ziehau 51354a331bf7SSepherosa Ziehau static void 51364a331bf7SSepherosa Ziehau bce_npoll(struct ifnet *ifp, struct ifpoll_info *info) 51374a331bf7SSepherosa Ziehau { 51384a331bf7SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 513957b3ecd9SSepherosa Ziehau int i; 51404a331bf7SSepherosa Ziehau 514184464af5SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 51424a331bf7SSepherosa Ziehau 51434a331bf7SSepherosa Ziehau if (info != NULL) { 514457b3ecd9SSepherosa Ziehau info->ifpi_status.status_func = bce_npoll_status; 514557b3ecd9SSepherosa Ziehau info->ifpi_status.serializer = &sc->main_serialize; 51464a331bf7SSepherosa Ziehau 514757b3ecd9SSepherosa Ziehau for (i = 0; i < sc->ring_cnt; ++i) { 514857b3ecd9SSepherosa Ziehau struct bce_tx_ring *txr = &sc->tx_rings[i]; 514957b3ecd9SSepherosa Ziehau struct bce_rx_ring *rxr = &sc->rx_rings[i]; 515057b3ecd9SSepherosa Ziehau int idx = i + sc->npoll_ofs; 515157b3ecd9SSepherosa Ziehau 515257b3ecd9SSepherosa Ziehau KKASSERT(idx < ncpus2); 515357b3ecd9SSepherosa Ziehau 515457b3ecd9SSepherosa Ziehau info->ifpi_tx[idx].poll_func = bce_npoll_tx; 515557b3ecd9SSepherosa Ziehau info->ifpi_tx[idx].arg = txr; 515657b3ecd9SSepherosa Ziehau info->ifpi_tx[idx].serializer = &txr->tx_serialize; 515757b3ecd9SSepherosa Ziehau 515857b3ecd9SSepherosa Ziehau info->ifpi_rx[idx].poll_func = bce_npoll_rx; 515957b3ecd9SSepherosa Ziehau info->ifpi_rx[idx].arg = rxr; 516057b3ecd9SSepherosa Ziehau info->ifpi_rx[idx].serializer = &rxr->rx_serialize; 516157b3ecd9SSepherosa Ziehau } 51624a331bf7SSepherosa Ziehau 51634a331bf7SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 51644a331bf7SSepherosa Ziehau bce_disable_intr(sc); 51654a331bf7SSepherosa Ziehau 51664a331bf7SSepherosa Ziehau REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, 51674a331bf7SSepherosa Ziehau (1 << 16) | sc->bce_rx_quick_cons_trip); 51684a331bf7SSepherosa Ziehau REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, 51694a331bf7SSepherosa Ziehau (1 << 16) | sc->bce_tx_quick_cons_trip); 51704a331bf7SSepherosa Ziehau } 517157b3ecd9SSepherosa Ziehau ifq_set_cpuid(&ifp->if_snd, sc->npoll_ofs); /* XXX */ 51724a331bf7SSepherosa Ziehau } else { 517357b3ecd9SSepherosa Ziehau ifq_set_cpuid(&ifp->if_snd, sc->bce_intr_cpuid); 517457b3ecd9SSepherosa Ziehau 51754a331bf7SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 51764a331bf7SSepherosa Ziehau bce_enable_intr(sc); 51774a331bf7SSepherosa Ziehau 51784a331bf7SSepherosa Ziehau REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, 51794a331bf7SSepherosa Ziehau (sc->bce_tx_quick_cons_trip_int << 16) | 51804a331bf7SSepherosa Ziehau sc->bce_tx_quick_cons_trip); 51814a331bf7SSepherosa Ziehau REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, 51824a331bf7SSepherosa Ziehau (sc->bce_rx_quick_cons_trip_int << 16) | 51834a331bf7SSepherosa Ziehau sc->bce_rx_quick_cons_trip); 51844a331bf7SSepherosa Ziehau } 51854a331bf7SSepherosa Ziehau } 51864a331bf7SSepherosa Ziehau } 51874a331bf7SSepherosa Ziehau 51884a331bf7SSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 518943c2aeb0SSepherosa Ziehau 519043c2aeb0SSepherosa Ziehau 519143c2aeb0SSepherosa Ziehau /* 519243c2aeb0SSepherosa Ziehau * Interrupt handler. 519343c2aeb0SSepherosa Ziehau */ 519443c2aeb0SSepherosa Ziehau /****************************************************************************/ 519543c2aeb0SSepherosa Ziehau /* Main interrupt entry point. Verifies that the controller generated the */ 519643c2aeb0SSepherosa Ziehau /* interrupt and then calls a separate routine for handle the various */ 519743c2aeb0SSepherosa Ziehau /* interrupt causes (PHY, TX, RX). */ 519843c2aeb0SSepherosa Ziehau /* */ 519943c2aeb0SSepherosa Ziehau /* Returns: */ 520043c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 520143c2aeb0SSepherosa Ziehau /****************************************************************************/ 520243c2aeb0SSepherosa Ziehau static void 5203eac57ffbSSepherosa Ziehau bce_intr(struct bce_softc *sc) 520443c2aeb0SSepherosa Ziehau { 520543c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 520643c2aeb0SSepherosa Ziehau struct status_block *sblk; 520724603545SSepherosa Ziehau uint16_t hw_rx_cons, hw_tx_cons; 5208a5eaa4bfSSepherosa Ziehau uint32_t status_attn_bits; 520910bcbdabSSepherosa Ziehau struct bce_tx_ring *txr = &sc->tx_rings[0]; 521008b64767SSepherosa Ziehau struct bce_rx_ring *rxr = &sc->rx_rings[0]; 521143c2aeb0SSepherosa Ziehau 521284464af5SSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize); 521343c2aeb0SSepherosa Ziehau 521443c2aeb0SSepherosa Ziehau sblk = sc->status_block; 521543c2aeb0SSepherosa Ziehau 5216a5eaa4bfSSepherosa Ziehau /* 5217a5eaa4bfSSepherosa Ziehau * Save the status block index value for use during 5218a5eaa4bfSSepherosa Ziehau * the next interrupt. 5219a5eaa4bfSSepherosa Ziehau */ 5220a5eaa4bfSSepherosa Ziehau sc->last_status_idx = sblk->status_idx; 5221a5eaa4bfSSepherosa Ziehau 5222a5eaa4bfSSepherosa Ziehau /* Make sure status index is extracted before rx/tx cons */ 5223a5eaa4bfSSepherosa Ziehau cpu_lfence(); 5224a5eaa4bfSSepherosa Ziehau 522524603545SSepherosa Ziehau /* Check if the hardware has finished any work. */ 522624603545SSepherosa Ziehau hw_rx_cons = bce_get_hw_rx_cons(sc); 522724603545SSepherosa Ziehau hw_tx_cons = bce_get_hw_tx_cons(sc); 522824603545SSepherosa Ziehau 522943c2aeb0SSepherosa Ziehau status_attn_bits = sblk->status_attn_bits; 523043c2aeb0SSepherosa Ziehau 523143c2aeb0SSepherosa Ziehau /* Was it a link change interrupt? */ 523243c2aeb0SSepherosa Ziehau if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 5233d0092544SSepherosa Ziehau (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE)) { 523443c2aeb0SSepherosa Ziehau bce_phy_intr(sc); 523543c2aeb0SSepherosa Ziehau 523643c2aeb0SSepherosa Ziehau /* 5237d0092544SSepherosa Ziehau * Clear any transient status updates during link state 5238d0092544SSepherosa Ziehau * change. 5239d0092544SSepherosa Ziehau */ 5240d0092544SSepherosa Ziehau REG_WR(sc, BCE_HC_COMMAND, 5241d0092544SSepherosa Ziehau sc->hc_command | BCE_HC_COMMAND_COAL_NOW_WO_INT); 5242d0092544SSepherosa Ziehau REG_RD(sc, BCE_HC_COMMAND); 5243d0092544SSepherosa Ziehau } 5244d0092544SSepherosa Ziehau 5245d0092544SSepherosa Ziehau /* 524643c2aeb0SSepherosa Ziehau * If any other attention is asserted then 524743c2aeb0SSepherosa Ziehau * the chip is toast. 524843c2aeb0SSepherosa Ziehau */ 524943c2aeb0SSepherosa Ziehau if ((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) != 5250a5eaa4bfSSepherosa Ziehau (sblk->status_attn_bits_ack & ~STATUS_ATTN_BITS_LINK_STATE)) { 525143c2aeb0SSepherosa Ziehau if_printf(ifp, "Fatal attention detected: 0x%08X\n", 525243c2aeb0SSepherosa Ziehau sblk->status_attn_bits); 525384464af5SSepherosa Ziehau bce_serialize_skipmain(sc); 525443c2aeb0SSepherosa Ziehau bce_init(sc); 525584464af5SSepherosa Ziehau bce_deserialize_skipmain(sc); 525643c2aeb0SSepherosa Ziehau return; 525743c2aeb0SSepherosa Ziehau } 525843c2aeb0SSepherosa Ziehau 525943c2aeb0SSepherosa Ziehau /* Check for any completed RX frames. */ 526084464af5SSepherosa Ziehau lwkt_serialize_enter(&rxr->rx_serialize); 526108b64767SSepherosa Ziehau if (hw_rx_cons != rxr->rx_cons) 526208b64767SSepherosa Ziehau bce_rx_intr(rxr, -1, hw_rx_cons); 526384464af5SSepherosa Ziehau lwkt_serialize_exit(&rxr->rx_serialize); 526443c2aeb0SSepherosa Ziehau 526543c2aeb0SSepherosa Ziehau /* Check for any completed TX frames. */ 526684464af5SSepherosa Ziehau lwkt_serialize_enter(&txr->tx_serialize); 526784464af5SSepherosa Ziehau if (hw_tx_cons != txr->tx_cons) { 526810bcbdabSSepherosa Ziehau bce_tx_intr(txr, hw_tx_cons); 526984464af5SSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 527084464af5SSepherosa Ziehau if_devstart(ifp); 527184464af5SSepherosa Ziehau } 527284464af5SSepherosa Ziehau lwkt_serialize_exit(&txr->tx_serialize); 527343c2aeb0SSepherosa Ziehau 527443c2aeb0SSepherosa Ziehau /* Re-enable interrupts. */ 5275d4274f6bSSepherosa Ziehau bce_reenable_intr(sc); 527643c2aeb0SSepherosa Ziehau } 527743c2aeb0SSepherosa Ziehau 5278eac57ffbSSepherosa Ziehau static void 5279eac57ffbSSepherosa Ziehau bce_intr_legacy(void *xsc) 5280eac57ffbSSepherosa Ziehau { 5281eac57ffbSSepherosa Ziehau struct bce_softc *sc = xsc; 5282eac57ffbSSepherosa Ziehau struct status_block *sblk; 5283eac57ffbSSepherosa Ziehau 5284eac57ffbSSepherosa Ziehau sblk = sc->status_block; 5285eac57ffbSSepherosa Ziehau 5286eac57ffbSSepherosa Ziehau /* 5287eac57ffbSSepherosa Ziehau * If the hardware status block index matches the last value 5288eac57ffbSSepherosa Ziehau * read by the driver and we haven't asserted our interrupt 5289eac57ffbSSepherosa Ziehau * then there's nothing to do. 5290eac57ffbSSepherosa Ziehau */ 5291eac57ffbSSepherosa Ziehau if (sblk->status_idx == sc->last_status_idx && 5292eac57ffbSSepherosa Ziehau (REG_RD(sc, BCE_PCICFG_MISC_STATUS) & 5293eac57ffbSSepherosa Ziehau BCE_PCICFG_MISC_STATUS_INTA_VALUE)) 5294eac57ffbSSepherosa Ziehau return; 5295eac57ffbSSepherosa Ziehau 5296eac57ffbSSepherosa Ziehau /* Ack the interrupt and stop others from occuring. */ 5297eac57ffbSSepherosa Ziehau REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 5298eac57ffbSSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | 5299eac57ffbSSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_MASK_INT); 5300eac57ffbSSepherosa Ziehau 5301eac57ffbSSepherosa Ziehau /* 5302eac57ffbSSepherosa Ziehau * Read back to deassert IRQ immediately to avoid too 5303eac57ffbSSepherosa Ziehau * many spurious interrupts. 5304eac57ffbSSepherosa Ziehau */ 5305eac57ffbSSepherosa Ziehau REG_RD(sc, BCE_PCICFG_INT_ACK_CMD); 5306eac57ffbSSepherosa Ziehau 5307eac57ffbSSepherosa Ziehau bce_intr(sc); 5308eac57ffbSSepherosa Ziehau } 5309eac57ffbSSepherosa Ziehau 5310eac57ffbSSepherosa Ziehau static void 5311eac57ffbSSepherosa Ziehau bce_intr_msi(void *xsc) 5312eac57ffbSSepherosa Ziehau { 5313eac57ffbSSepherosa Ziehau struct bce_softc *sc = xsc; 5314eac57ffbSSepherosa Ziehau 5315eac57ffbSSepherosa Ziehau /* Ack the interrupt and stop others from occuring. */ 5316eac57ffbSSepherosa Ziehau REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, 5317eac57ffbSSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | 5318eac57ffbSSepherosa Ziehau BCE_PCICFG_INT_ACK_CMD_MASK_INT); 5319eac57ffbSSepherosa Ziehau 5320eac57ffbSSepherosa Ziehau bce_intr(sc); 5321eac57ffbSSepherosa Ziehau } 5322eac57ffbSSepherosa Ziehau 5323eac57ffbSSepherosa Ziehau static void 5324eac57ffbSSepherosa Ziehau bce_intr_msi_oneshot(void *xsc) 5325eac57ffbSSepherosa Ziehau { 5326eac57ffbSSepherosa Ziehau bce_intr(xsc); 5327eac57ffbSSepherosa Ziehau } 5328eac57ffbSSepherosa Ziehau 532943c2aeb0SSepherosa Ziehau 533043c2aeb0SSepherosa Ziehau /****************************************************************************/ 533143c2aeb0SSepherosa Ziehau /* Programs the various packet receive modes (broadcast and multicast). */ 533243c2aeb0SSepherosa Ziehau /* */ 533343c2aeb0SSepherosa Ziehau /* Returns: */ 533443c2aeb0SSepherosa Ziehau /* Nothing. */ 533543c2aeb0SSepherosa Ziehau /****************************************************************************/ 533643c2aeb0SSepherosa Ziehau static void 533743c2aeb0SSepherosa Ziehau bce_set_rx_mode(struct bce_softc *sc) 533843c2aeb0SSepherosa Ziehau { 533943c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 534043c2aeb0SSepherosa Ziehau struct ifmultiaddr *ifma; 534143c2aeb0SSepherosa Ziehau uint32_t hashes[NUM_MC_HASH_REGISTERS] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 534243c2aeb0SSepherosa Ziehau uint32_t rx_mode, sort_mode; 534343c2aeb0SSepherosa Ziehau int h, i; 534443c2aeb0SSepherosa Ziehau 534584464af5SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 534643c2aeb0SSepherosa Ziehau 534743c2aeb0SSepherosa Ziehau /* Initialize receive mode default settings. */ 534843c2aeb0SSepherosa Ziehau rx_mode = sc->rx_mode & 534943c2aeb0SSepherosa Ziehau ~(BCE_EMAC_RX_MODE_PROMISCUOUS | 535043c2aeb0SSepherosa Ziehau BCE_EMAC_RX_MODE_KEEP_VLAN_TAG); 535143c2aeb0SSepherosa Ziehau sort_mode = 1 | BCE_RPM_SORT_USER0_BC_EN; 535243c2aeb0SSepherosa Ziehau 535343c2aeb0SSepherosa Ziehau /* 535443c2aeb0SSepherosa Ziehau * ASF/IPMI/UMP firmware requires that VLAN tag stripping 535543c2aeb0SSepherosa Ziehau * be enbled. 535643c2aeb0SSepherosa Ziehau */ 535743c2aeb0SSepherosa Ziehau if (!(BCE_IF_CAPABILITIES & IFCAP_VLAN_HWTAGGING) && 535843c2aeb0SSepherosa Ziehau !(sc->bce_flags & BCE_MFW_ENABLE_FLAG)) 535943c2aeb0SSepherosa Ziehau rx_mode |= BCE_EMAC_RX_MODE_KEEP_VLAN_TAG; 536043c2aeb0SSepherosa Ziehau 536143c2aeb0SSepherosa Ziehau /* 536243c2aeb0SSepherosa Ziehau * Check for promiscuous, all multicast, or selected 536343c2aeb0SSepherosa Ziehau * multicast address filtering. 536443c2aeb0SSepherosa Ziehau */ 536543c2aeb0SSepherosa Ziehau if (ifp->if_flags & IFF_PROMISC) { 536643c2aeb0SSepherosa Ziehau /* Enable promiscuous mode. */ 536743c2aeb0SSepherosa Ziehau rx_mode |= BCE_EMAC_RX_MODE_PROMISCUOUS; 536843c2aeb0SSepherosa Ziehau sort_mode |= BCE_RPM_SORT_USER0_PROM_EN; 536943c2aeb0SSepherosa Ziehau } else if (ifp->if_flags & IFF_ALLMULTI) { 537043c2aeb0SSepherosa Ziehau /* Enable all multicast addresses. */ 537143c2aeb0SSepherosa Ziehau for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { 537243c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4), 537343c2aeb0SSepherosa Ziehau 0xffffffff); 537443c2aeb0SSepherosa Ziehau } 537543c2aeb0SSepherosa Ziehau sort_mode |= BCE_RPM_SORT_USER0_MC_EN; 537643c2aeb0SSepherosa Ziehau } else { 537743c2aeb0SSepherosa Ziehau /* Accept one or more multicast(s). */ 5378441d34b2SSascha Wildner TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 537943c2aeb0SSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 538043c2aeb0SSepherosa Ziehau continue; 538143c2aeb0SSepherosa Ziehau h = ether_crc32_le( 538243c2aeb0SSepherosa Ziehau LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 538343c2aeb0SSepherosa Ziehau ETHER_ADDR_LEN) & 0xFF; 538443c2aeb0SSepherosa Ziehau hashes[(h & 0xE0) >> 5] |= 1 << (h & 0x1F); 538543c2aeb0SSepherosa Ziehau } 538643c2aeb0SSepherosa Ziehau 538743c2aeb0SSepherosa Ziehau for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { 538843c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4), 538943c2aeb0SSepherosa Ziehau hashes[i]); 539043c2aeb0SSepherosa Ziehau } 539143c2aeb0SSepherosa Ziehau sort_mode |= BCE_RPM_SORT_USER0_MC_HSH_EN; 539243c2aeb0SSepherosa Ziehau } 539343c2aeb0SSepherosa Ziehau 539443c2aeb0SSepherosa Ziehau /* Only make changes if the recive mode has actually changed. */ 539543c2aeb0SSepherosa Ziehau if (rx_mode != sc->rx_mode) { 539643c2aeb0SSepherosa Ziehau sc->rx_mode = rx_mode; 539743c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_EMAC_RX_MODE, rx_mode); 539843c2aeb0SSepherosa Ziehau } 539943c2aeb0SSepherosa Ziehau 540043c2aeb0SSepherosa Ziehau /* Disable and clear the exisitng sort before enabling a new sort. */ 540143c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RPM_SORT_USER0, 0x0); 540243c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode); 540343c2aeb0SSepherosa Ziehau REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode | BCE_RPM_SORT_USER0_ENA); 540443c2aeb0SSepherosa Ziehau } 540543c2aeb0SSepherosa Ziehau 540643c2aeb0SSepherosa Ziehau 540743c2aeb0SSepherosa Ziehau /****************************************************************************/ 540843c2aeb0SSepherosa Ziehau /* Called periodically to updates statistics from the controllers */ 540943c2aeb0SSepherosa Ziehau /* statistics block. */ 541043c2aeb0SSepherosa Ziehau /* */ 541143c2aeb0SSepherosa Ziehau /* Returns: */ 541243c2aeb0SSepherosa Ziehau /* Nothing. */ 541343c2aeb0SSepherosa Ziehau /****************************************************************************/ 541443c2aeb0SSepherosa Ziehau static void 541543c2aeb0SSepherosa Ziehau bce_stats_update(struct bce_softc *sc) 541643c2aeb0SSepherosa Ziehau { 541743c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 541843c2aeb0SSepherosa Ziehau struct statistics_block *stats = sc->stats_block; 541943c2aeb0SSepherosa Ziehau 542084464af5SSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize); 542143c2aeb0SSepherosa Ziehau 542243c2aeb0SSepherosa Ziehau /* 542343c2aeb0SSepherosa Ziehau * Certain controllers don't report carrier sense errors correctly. 542443c2aeb0SSepherosa Ziehau * See errata E11_5708CA0_1165. 542543c2aeb0SSepherosa Ziehau */ 542643c2aeb0SSepherosa Ziehau if (!(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) && 542743c2aeb0SSepherosa Ziehau !(BCE_CHIP_ID(sc) == BCE_CHIP_ID_5708_A0)) { 5428d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 5429d40991efSSepherosa Ziehau (u_long)stats->stat_Dot3StatsCarrierSenseErrors); 543043c2aeb0SSepherosa Ziehau } 543143c2aeb0SSepherosa Ziehau 543243c2aeb0SSepherosa Ziehau /* 543343c2aeb0SSepherosa Ziehau * Update the sysctl statistics from the hardware statistics. 543443c2aeb0SSepherosa Ziehau */ 543543c2aeb0SSepherosa Ziehau sc->stat_IfHCInOctets = 543643c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCInOctets_hi << 32) + 543743c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCInOctets_lo; 543843c2aeb0SSepherosa Ziehau 543943c2aeb0SSepherosa Ziehau sc->stat_IfHCInBadOctets = 544043c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCInBadOctets_hi << 32) + 544143c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCInBadOctets_lo; 544243c2aeb0SSepherosa Ziehau 544343c2aeb0SSepherosa Ziehau sc->stat_IfHCOutOctets = 544443c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCOutOctets_hi << 32) + 544543c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCOutOctets_lo; 544643c2aeb0SSepherosa Ziehau 544743c2aeb0SSepherosa Ziehau sc->stat_IfHCOutBadOctets = 544843c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCOutBadOctets_hi << 32) + 544943c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCOutBadOctets_lo; 545043c2aeb0SSepherosa Ziehau 545143c2aeb0SSepherosa Ziehau sc->stat_IfHCInUcastPkts = 545243c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCInUcastPkts_hi << 32) + 545343c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCInUcastPkts_lo; 545443c2aeb0SSepherosa Ziehau 545543c2aeb0SSepherosa Ziehau sc->stat_IfHCInMulticastPkts = 545643c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCInMulticastPkts_hi << 32) + 545743c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCInMulticastPkts_lo; 545843c2aeb0SSepherosa Ziehau 545943c2aeb0SSepherosa Ziehau sc->stat_IfHCInBroadcastPkts = 546043c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCInBroadcastPkts_hi << 32) + 546143c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCInBroadcastPkts_lo; 546243c2aeb0SSepherosa Ziehau 546343c2aeb0SSepherosa Ziehau sc->stat_IfHCOutUcastPkts = 546443c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCOutUcastPkts_hi << 32) + 546543c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCOutUcastPkts_lo; 546643c2aeb0SSepherosa Ziehau 546743c2aeb0SSepherosa Ziehau sc->stat_IfHCOutMulticastPkts = 546843c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCOutMulticastPkts_hi << 32) + 546943c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCOutMulticastPkts_lo; 547043c2aeb0SSepherosa Ziehau 547143c2aeb0SSepherosa Ziehau sc->stat_IfHCOutBroadcastPkts = 547243c2aeb0SSepherosa Ziehau ((uint64_t)stats->stat_IfHCOutBroadcastPkts_hi << 32) + 547343c2aeb0SSepherosa Ziehau (uint64_t)stats->stat_IfHCOutBroadcastPkts_lo; 547443c2aeb0SSepherosa Ziehau 547543c2aeb0SSepherosa Ziehau sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors = 547643c2aeb0SSepherosa Ziehau stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors; 547743c2aeb0SSepherosa Ziehau 547843c2aeb0SSepherosa Ziehau sc->stat_Dot3StatsCarrierSenseErrors = 547943c2aeb0SSepherosa Ziehau stats->stat_Dot3StatsCarrierSenseErrors; 548043c2aeb0SSepherosa Ziehau 548143c2aeb0SSepherosa Ziehau sc->stat_Dot3StatsFCSErrors = 548243c2aeb0SSepherosa Ziehau stats->stat_Dot3StatsFCSErrors; 548343c2aeb0SSepherosa Ziehau 548443c2aeb0SSepherosa Ziehau sc->stat_Dot3StatsAlignmentErrors = 548543c2aeb0SSepherosa Ziehau stats->stat_Dot3StatsAlignmentErrors; 548643c2aeb0SSepherosa Ziehau 548743c2aeb0SSepherosa Ziehau sc->stat_Dot3StatsSingleCollisionFrames = 548843c2aeb0SSepherosa Ziehau stats->stat_Dot3StatsSingleCollisionFrames; 548943c2aeb0SSepherosa Ziehau 549043c2aeb0SSepherosa Ziehau sc->stat_Dot3StatsMultipleCollisionFrames = 549143c2aeb0SSepherosa Ziehau stats->stat_Dot3StatsMultipleCollisionFrames; 549243c2aeb0SSepherosa Ziehau 549343c2aeb0SSepherosa Ziehau sc->stat_Dot3StatsDeferredTransmissions = 549443c2aeb0SSepherosa Ziehau stats->stat_Dot3StatsDeferredTransmissions; 549543c2aeb0SSepherosa Ziehau 549643c2aeb0SSepherosa Ziehau sc->stat_Dot3StatsExcessiveCollisions = 549743c2aeb0SSepherosa Ziehau stats->stat_Dot3StatsExcessiveCollisions; 549843c2aeb0SSepherosa Ziehau 549943c2aeb0SSepherosa Ziehau sc->stat_Dot3StatsLateCollisions = 550043c2aeb0SSepherosa Ziehau stats->stat_Dot3StatsLateCollisions; 550143c2aeb0SSepherosa Ziehau 550243c2aeb0SSepherosa Ziehau sc->stat_EtherStatsCollisions = 550343c2aeb0SSepherosa Ziehau stats->stat_EtherStatsCollisions; 550443c2aeb0SSepherosa Ziehau 550543c2aeb0SSepherosa Ziehau sc->stat_EtherStatsFragments = 550643c2aeb0SSepherosa Ziehau stats->stat_EtherStatsFragments; 550743c2aeb0SSepherosa Ziehau 550843c2aeb0SSepherosa Ziehau sc->stat_EtherStatsJabbers = 550943c2aeb0SSepherosa Ziehau stats->stat_EtherStatsJabbers; 551043c2aeb0SSepherosa Ziehau 551143c2aeb0SSepherosa Ziehau sc->stat_EtherStatsUndersizePkts = 551243c2aeb0SSepherosa Ziehau stats->stat_EtherStatsUndersizePkts; 551343c2aeb0SSepherosa Ziehau 551443c2aeb0SSepherosa Ziehau sc->stat_EtherStatsOverrsizePkts = 551543c2aeb0SSepherosa Ziehau stats->stat_EtherStatsOverrsizePkts; 551643c2aeb0SSepherosa Ziehau 551743c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsRx64Octets = 551843c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsRx64Octets; 551943c2aeb0SSepherosa Ziehau 552043c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsRx65Octetsto127Octets = 552143c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsRx65Octetsto127Octets; 552243c2aeb0SSepherosa Ziehau 552343c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsRx128Octetsto255Octets = 552443c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsRx128Octetsto255Octets; 552543c2aeb0SSepherosa Ziehau 552643c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsRx256Octetsto511Octets = 552743c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsRx256Octetsto511Octets; 552843c2aeb0SSepherosa Ziehau 552943c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsRx512Octetsto1023Octets = 553043c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsRx512Octetsto1023Octets; 553143c2aeb0SSepherosa Ziehau 553243c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsRx1024Octetsto1522Octets = 553343c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsRx1024Octetsto1522Octets; 553443c2aeb0SSepherosa Ziehau 553543c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsRx1523Octetsto9022Octets = 553643c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsRx1523Octetsto9022Octets; 553743c2aeb0SSepherosa Ziehau 553843c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsTx64Octets = 553943c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsTx64Octets; 554043c2aeb0SSepherosa Ziehau 554143c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsTx65Octetsto127Octets = 554243c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsTx65Octetsto127Octets; 554343c2aeb0SSepherosa Ziehau 554443c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsTx128Octetsto255Octets = 554543c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsTx128Octetsto255Octets; 554643c2aeb0SSepherosa Ziehau 554743c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsTx256Octetsto511Octets = 554843c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsTx256Octetsto511Octets; 554943c2aeb0SSepherosa Ziehau 555043c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsTx512Octetsto1023Octets = 555143c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsTx512Octetsto1023Octets; 555243c2aeb0SSepherosa Ziehau 555343c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsTx1024Octetsto1522Octets = 555443c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsTx1024Octetsto1522Octets; 555543c2aeb0SSepherosa Ziehau 555643c2aeb0SSepherosa Ziehau sc->stat_EtherStatsPktsTx1523Octetsto9022Octets = 555743c2aeb0SSepherosa Ziehau stats->stat_EtherStatsPktsTx1523Octetsto9022Octets; 555843c2aeb0SSepherosa Ziehau 555943c2aeb0SSepherosa Ziehau sc->stat_XonPauseFramesReceived = 556043c2aeb0SSepherosa Ziehau stats->stat_XonPauseFramesReceived; 556143c2aeb0SSepherosa Ziehau 556243c2aeb0SSepherosa Ziehau sc->stat_XoffPauseFramesReceived = 556343c2aeb0SSepherosa Ziehau stats->stat_XoffPauseFramesReceived; 556443c2aeb0SSepherosa Ziehau 556543c2aeb0SSepherosa Ziehau sc->stat_OutXonSent = 556643c2aeb0SSepherosa Ziehau stats->stat_OutXonSent; 556743c2aeb0SSepherosa Ziehau 556843c2aeb0SSepherosa Ziehau sc->stat_OutXoffSent = 556943c2aeb0SSepherosa Ziehau stats->stat_OutXoffSent; 557043c2aeb0SSepherosa Ziehau 557143c2aeb0SSepherosa Ziehau sc->stat_FlowControlDone = 557243c2aeb0SSepherosa Ziehau stats->stat_FlowControlDone; 557343c2aeb0SSepherosa Ziehau 557443c2aeb0SSepherosa Ziehau sc->stat_MacControlFramesReceived = 557543c2aeb0SSepherosa Ziehau stats->stat_MacControlFramesReceived; 557643c2aeb0SSepherosa Ziehau 557743c2aeb0SSepherosa Ziehau sc->stat_XoffStateEntered = 557843c2aeb0SSepherosa Ziehau stats->stat_XoffStateEntered; 557943c2aeb0SSepherosa Ziehau 558043c2aeb0SSepherosa Ziehau sc->stat_IfInFramesL2FilterDiscards = 558143c2aeb0SSepherosa Ziehau stats->stat_IfInFramesL2FilterDiscards; 558243c2aeb0SSepherosa Ziehau 558343c2aeb0SSepherosa Ziehau sc->stat_IfInRuleCheckerDiscards = 558443c2aeb0SSepherosa Ziehau stats->stat_IfInRuleCheckerDiscards; 558543c2aeb0SSepherosa Ziehau 558643c2aeb0SSepherosa Ziehau sc->stat_IfInFTQDiscards = 558743c2aeb0SSepherosa Ziehau stats->stat_IfInFTQDiscards; 558843c2aeb0SSepherosa Ziehau 558943c2aeb0SSepherosa Ziehau sc->stat_IfInMBUFDiscards = 559043c2aeb0SSepherosa Ziehau stats->stat_IfInMBUFDiscards; 559143c2aeb0SSepherosa Ziehau 559243c2aeb0SSepherosa Ziehau sc->stat_IfInRuleCheckerP4Hit = 559343c2aeb0SSepherosa Ziehau stats->stat_IfInRuleCheckerP4Hit; 559443c2aeb0SSepherosa Ziehau 559543c2aeb0SSepherosa Ziehau sc->stat_CatchupInRuleCheckerDiscards = 559643c2aeb0SSepherosa Ziehau stats->stat_CatchupInRuleCheckerDiscards; 559743c2aeb0SSepherosa Ziehau 559843c2aeb0SSepherosa Ziehau sc->stat_CatchupInFTQDiscards = 559943c2aeb0SSepherosa Ziehau stats->stat_CatchupInFTQDiscards; 560043c2aeb0SSepherosa Ziehau 560143c2aeb0SSepherosa Ziehau sc->stat_CatchupInMBUFDiscards = 560243c2aeb0SSepherosa Ziehau stats->stat_CatchupInMBUFDiscards; 560343c2aeb0SSepherosa Ziehau 560443c2aeb0SSepherosa Ziehau sc->stat_CatchupInRuleCheckerP4Hit = 560543c2aeb0SSepherosa Ziehau stats->stat_CatchupInRuleCheckerP4Hit; 560643c2aeb0SSepherosa Ziehau 560743c2aeb0SSepherosa Ziehau sc->com_no_buffers = REG_RD_IND(sc, 0x120084); 560843c2aeb0SSepherosa Ziehau 5609d0092544SSepherosa Ziehau /* 5610d0092544SSepherosa Ziehau * Update the interface statistics from the 5611d0092544SSepherosa Ziehau * hardware statistics. 5612d0092544SSepherosa Ziehau */ 5613d40991efSSepherosa Ziehau IFNET_STAT_SET(ifp, collisions, (u_long)sc->stat_EtherStatsCollisions); 5614d0092544SSepherosa Ziehau 5615d40991efSSepherosa Ziehau IFNET_STAT_SET(ifp, ierrors, (u_long)sc->stat_EtherStatsUndersizePkts + 5616d0092544SSepherosa Ziehau (u_long)sc->stat_EtherStatsOverrsizePkts + 5617d0092544SSepherosa Ziehau (u_long)sc->stat_IfInMBUFDiscards + 5618d0092544SSepherosa Ziehau (u_long)sc->stat_Dot3StatsAlignmentErrors + 5619d0092544SSepherosa Ziehau (u_long)sc->stat_Dot3StatsFCSErrors + 5620d0092544SSepherosa Ziehau (u_long)sc->stat_IfInRuleCheckerDiscards + 5621d0092544SSepherosa Ziehau (u_long)sc->stat_IfInFTQDiscards + 5622d40991efSSepherosa Ziehau (u_long)sc->com_no_buffers); 5623d0092544SSepherosa Ziehau 5624d40991efSSepherosa Ziehau IFNET_STAT_SET(ifp, oerrors, 5625d0092544SSepherosa Ziehau (u_long)sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors + 5626d0092544SSepherosa Ziehau (u_long)sc->stat_Dot3StatsExcessiveCollisions + 5627d40991efSSepherosa Ziehau (u_long)sc->stat_Dot3StatsLateCollisions); 562843c2aeb0SSepherosa Ziehau } 562943c2aeb0SSepherosa Ziehau 563043c2aeb0SSepherosa Ziehau 563143c2aeb0SSepherosa Ziehau /****************************************************************************/ 5632d0092544SSepherosa Ziehau /* Periodic function to notify the bootcode that the driver is still */ 5633d0092544SSepherosa Ziehau /* present. */ 5634d0092544SSepherosa Ziehau /* */ 5635d0092544SSepherosa Ziehau /* Returns: */ 5636d0092544SSepherosa Ziehau /* Nothing. */ 5637d0092544SSepherosa Ziehau /****************************************************************************/ 5638d0092544SSepherosa Ziehau static void 5639d0092544SSepherosa Ziehau bce_pulse(void *xsc) 5640d0092544SSepherosa Ziehau { 5641d0092544SSepherosa Ziehau struct bce_softc *sc = xsc; 5642d0092544SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5643d0092544SSepherosa Ziehau uint32_t msg; 5644d0092544SSepherosa Ziehau 564584464af5SSepherosa Ziehau lwkt_serialize_enter(&sc->main_serialize); 5646d0092544SSepherosa Ziehau 5647d0092544SSepherosa Ziehau /* Tell the firmware that the driver is still running. */ 5648d0092544SSepherosa Ziehau msg = (uint32_t)++sc->bce_fw_drv_pulse_wr_seq; 5649bc30d40dSSepherosa Ziehau bce_shmem_wr(sc, BCE_DRV_PULSE_MB, msg); 5650d0092544SSepherosa Ziehau 5651d8870c52SSepherosa Ziehau /* Update the bootcode condition. */ 5652d8870c52SSepherosa Ziehau sc->bc_state = bce_shmem_rd(sc, BCE_BC_STATE_CONDITION); 5653d8870c52SSepherosa Ziehau 5654d8870c52SSepherosa Ziehau /* Report whether the bootcode still knows the driver is running. */ 5655d8870c52SSepherosa Ziehau if (!sc->bce_drv_cardiac_arrest) { 5656d8870c52SSepherosa Ziehau if (!(sc->bc_state & BCE_CONDITION_DRV_PRESENT)) { 5657d8870c52SSepherosa Ziehau sc->bce_drv_cardiac_arrest = 1; 5658d8870c52SSepherosa Ziehau if_printf(ifp, "Bootcode lost the driver pulse! " 5659d8870c52SSepherosa Ziehau "(bc_state = 0x%08X)\n", sc->bc_state); 5660d8870c52SSepherosa Ziehau } 5661d8870c52SSepherosa Ziehau } else { 5662d8870c52SSepherosa Ziehau /* 5663d8870c52SSepherosa Ziehau * Not supported by all bootcode versions. 5664d8870c52SSepherosa Ziehau * (v5.0.11+ and v5.2.1+) Older bootcode 5665d8870c52SSepherosa Ziehau * will require the driver to reset the 5666d8870c52SSepherosa Ziehau * controller to clear this condition. 5667d8870c52SSepherosa Ziehau */ 5668d8870c52SSepherosa Ziehau if (sc->bc_state & BCE_CONDITION_DRV_PRESENT) { 5669d8870c52SSepherosa Ziehau sc->bce_drv_cardiac_arrest = 0; 5670d8870c52SSepherosa Ziehau if_printf(ifp, "Bootcode found the driver pulse! " 5671d8870c52SSepherosa Ziehau "(bc_state = 0x%08X)\n", sc->bc_state); 5672d8870c52SSepherosa Ziehau } 5673d8870c52SSepherosa Ziehau } 5674d8870c52SSepherosa Ziehau 5675d0092544SSepherosa Ziehau /* Schedule the next pulse. */ 5676a131f6c2SSepherosa Ziehau callout_reset_bycpu(&sc->bce_pulse_callout, hz, bce_pulse, sc, 5677a131f6c2SSepherosa Ziehau sc->bce_intr_cpuid); 5678d0092544SSepherosa Ziehau 567984464af5SSepherosa Ziehau lwkt_serialize_exit(&sc->main_serialize); 5680d0092544SSepherosa Ziehau } 5681d0092544SSepherosa Ziehau 5682733403d6SSepherosa Ziehau 568328ef7645SSepherosa Ziehau /****************************************************************************/ 568428ef7645SSepherosa Ziehau /* Periodic function to check whether MSI is lost */ 568528ef7645SSepherosa Ziehau /* */ 568628ef7645SSepherosa Ziehau /* Returns: */ 568728ef7645SSepherosa Ziehau /* Nothing. */ 568828ef7645SSepherosa Ziehau /****************************************************************************/ 568928ef7645SSepherosa Ziehau static void 569028ef7645SSepherosa Ziehau bce_check_msi(void *xsc) 569128ef7645SSepherosa Ziehau { 569228ef7645SSepherosa Ziehau struct bce_softc *sc = xsc; 569328ef7645SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5694733403d6SSepherosa Ziehau struct status_block *sblk = sc->status_block; 569510bcbdabSSepherosa Ziehau struct bce_tx_ring *txr = &sc->tx_rings[0]; 569608b64767SSepherosa Ziehau struct bce_rx_ring *rxr = &sc->rx_rings[0]; 5697733403d6SSepherosa Ziehau 569884464af5SSepherosa Ziehau lwkt_serialize_enter(&sc->main_serialize); 569928ef7645SSepherosa Ziehau 570028ef7645SSepherosa Ziehau KKASSERT(mycpuid == sc->bce_intr_cpuid); 570128ef7645SSepherosa Ziehau 57024a331bf7SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_NPOLLING)) != IFF_RUNNING) { 570384464af5SSepherosa Ziehau lwkt_serialize_exit(&sc->main_serialize); 570428ef7645SSepherosa Ziehau return; 5705733403d6SSepherosa Ziehau } 5706733403d6SSepherosa Ziehau 570708b64767SSepherosa Ziehau if (bce_get_hw_rx_cons(sc) != rxr->rx_cons || 570810bcbdabSSepherosa Ziehau bce_get_hw_tx_cons(sc) != txr->tx_cons || 570928ef7645SSepherosa Ziehau (sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 571028ef7645SSepherosa Ziehau (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE)) { 571108b64767SSepherosa Ziehau if (sc->bce_check_rx_cons == rxr->rx_cons && 571210bcbdabSSepherosa Ziehau sc->bce_check_tx_cons == txr->tx_cons && 571328ef7645SSepherosa Ziehau sc->bce_check_status_idx == sc->last_status_idx) { 5714733403d6SSepherosa Ziehau uint32_t msi_ctrl; 5715733403d6SSepherosa Ziehau 571628ef7645SSepherosa Ziehau if (!sc->bce_msi_maylose) { 571728ef7645SSepherosa Ziehau sc->bce_msi_maylose = TRUE; 571828ef7645SSepherosa Ziehau goto done; 571928ef7645SSepherosa Ziehau } 5720733403d6SSepherosa Ziehau 572128ef7645SSepherosa Ziehau msi_ctrl = REG_RD(sc, BCE_PCICFG_MSI_CONTROL); 572228ef7645SSepherosa Ziehau if (msi_ctrl & BCE_PCICFG_MSI_CONTROL_ENABLE) { 572328ef7645SSepherosa Ziehau if (bootverbose) 572428ef7645SSepherosa Ziehau if_printf(ifp, "lost MSI\n"); 5725733403d6SSepherosa Ziehau 5726733403d6SSepherosa Ziehau REG_WR(sc, BCE_PCICFG_MSI_CONTROL, 5727733403d6SSepherosa Ziehau msi_ctrl & ~BCE_PCICFG_MSI_CONTROL_ENABLE); 5728733403d6SSepherosa Ziehau REG_WR(sc, BCE_PCICFG_MSI_CONTROL, msi_ctrl); 5729733403d6SSepherosa Ziehau 5730733403d6SSepherosa Ziehau bce_intr_msi(sc); 573128ef7645SSepherosa Ziehau } else if (bootverbose) { 573228ef7645SSepherosa Ziehau if_printf(ifp, "MSI may be lost\n"); 5733733403d6SSepherosa Ziehau } 5734733403d6SSepherosa Ziehau } 5735733403d6SSepherosa Ziehau } 573628ef7645SSepherosa Ziehau sc->bce_msi_maylose = FALSE; 573708b64767SSepherosa Ziehau sc->bce_check_rx_cons = rxr->rx_cons; 573810bcbdabSSepherosa Ziehau sc->bce_check_tx_cons = txr->tx_cons; 573928ef7645SSepherosa Ziehau sc->bce_check_status_idx = sc->last_status_idx; 574028ef7645SSepherosa Ziehau 574128ef7645SSepherosa Ziehau done: 574228ef7645SSepherosa Ziehau callout_reset(&sc->bce_ckmsi_callout, BCE_MSI_CKINTVL, 574328ef7645SSepherosa Ziehau bce_check_msi, sc); 574484464af5SSepherosa Ziehau lwkt_serialize_exit(&sc->main_serialize); 574528ef7645SSepherosa Ziehau } 574628ef7645SSepherosa Ziehau 5747d0092544SSepherosa Ziehau 5748d0092544SSepherosa Ziehau /****************************************************************************/ 574943c2aeb0SSepherosa Ziehau /* Periodic function to perform maintenance tasks. */ 575043c2aeb0SSepherosa Ziehau /* */ 575143c2aeb0SSepherosa Ziehau /* Returns: */ 575243c2aeb0SSepherosa Ziehau /* Nothing. */ 575343c2aeb0SSepherosa Ziehau /****************************************************************************/ 575443c2aeb0SSepherosa Ziehau static void 575543c2aeb0SSepherosa Ziehau bce_tick_serialized(struct bce_softc *sc) 575643c2aeb0SSepherosa Ziehau { 575743c2aeb0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 575843c2aeb0SSepherosa Ziehau struct mii_data *mii; 575943c2aeb0SSepherosa Ziehau 576084464af5SSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize); 576143c2aeb0SSepherosa Ziehau 576243c2aeb0SSepherosa Ziehau /* Update the statistics from the hardware statistics block. */ 576343c2aeb0SSepherosa Ziehau bce_stats_update(sc); 576443c2aeb0SSepherosa Ziehau 576543c2aeb0SSepherosa Ziehau /* Schedule the next tick. */ 5766a131f6c2SSepherosa Ziehau callout_reset_bycpu(&sc->bce_tick_callout, hz, bce_tick, sc, 5767a131f6c2SSepherosa Ziehau sc->bce_intr_cpuid); 576843c2aeb0SSepherosa Ziehau 576943c2aeb0SSepherosa Ziehau /* If link is up already up then we're done. */ 577043c2aeb0SSepherosa Ziehau if (sc->bce_link) 577143c2aeb0SSepherosa Ziehau return; 577243c2aeb0SSepherosa Ziehau 577343c2aeb0SSepherosa Ziehau mii = device_get_softc(sc->bce_miibus); 577443c2aeb0SSepherosa Ziehau mii_tick(mii); 577543c2aeb0SSepherosa Ziehau 577643c2aeb0SSepherosa Ziehau /* Check if the link has come up. */ 5777d0092544SSepherosa Ziehau if ((mii->mii_media_status & IFM_ACTIVE) && 577843c2aeb0SSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 577943c2aeb0SSepherosa Ziehau sc->bce_link++; 578043c2aeb0SSepherosa Ziehau /* Now that link is up, handle any outstanding TX traffic. */ 578184464af5SSepherosa Ziehau if_devstart_sched(ifp); 578243c2aeb0SSepherosa Ziehau } 578343c2aeb0SSepherosa Ziehau } 578443c2aeb0SSepherosa Ziehau 578543c2aeb0SSepherosa Ziehau 578643c2aeb0SSepherosa Ziehau static void 578743c2aeb0SSepherosa Ziehau bce_tick(void *xsc) 578843c2aeb0SSepherosa Ziehau { 578943c2aeb0SSepherosa Ziehau struct bce_softc *sc = xsc; 579043c2aeb0SSepherosa Ziehau 579184464af5SSepherosa Ziehau lwkt_serialize_enter(&sc->main_serialize); 579243c2aeb0SSepherosa Ziehau bce_tick_serialized(sc); 579384464af5SSepherosa Ziehau lwkt_serialize_exit(&sc->main_serialize); 579443c2aeb0SSepherosa Ziehau } 579543c2aeb0SSepherosa Ziehau 579643c2aeb0SSepherosa Ziehau 579743c2aeb0SSepherosa Ziehau /****************************************************************************/ 579843c2aeb0SSepherosa Ziehau /* Adds any sysctl parameters for tuning or debugging purposes. */ 579943c2aeb0SSepherosa Ziehau /* */ 580043c2aeb0SSepherosa Ziehau /* Returns: */ 580143c2aeb0SSepherosa Ziehau /* 0 for success, positive value for failure. */ 580243c2aeb0SSepherosa Ziehau /****************************************************************************/ 580343c2aeb0SSepherosa Ziehau static void 580443c2aeb0SSepherosa Ziehau bce_add_sysctls(struct bce_softc *sc) 580543c2aeb0SSepherosa Ziehau { 580643c2aeb0SSepherosa Ziehau struct sysctl_ctx_list *ctx; 580743c2aeb0SSepherosa Ziehau struct sysctl_oid_list *children; 580843c2aeb0SSepherosa Ziehau 580943c2aeb0SSepherosa Ziehau sysctl_ctx_init(&sc->bce_sysctl_ctx); 581043c2aeb0SSepherosa Ziehau sc->bce_sysctl_tree = SYSCTL_ADD_NODE(&sc->bce_sysctl_ctx, 581143c2aeb0SSepherosa Ziehau SYSCTL_STATIC_CHILDREN(_hw), 581243c2aeb0SSepherosa Ziehau OID_AUTO, 581343c2aeb0SSepherosa Ziehau device_get_nameunit(sc->bce_dev), 581443c2aeb0SSepherosa Ziehau CTLFLAG_RD, 0, ""); 581543c2aeb0SSepherosa Ziehau if (sc->bce_sysctl_tree == NULL) { 581643c2aeb0SSepherosa Ziehau device_printf(sc->bce_dev, "can't add sysctl node\n"); 581743c2aeb0SSepherosa Ziehau return; 581843c2aeb0SSepherosa Ziehau } 581943c2aeb0SSepherosa Ziehau 582043c2aeb0SSepherosa Ziehau ctx = &sc->bce_sysctl_ctx; 582143c2aeb0SSepherosa Ziehau children = SYSCTL_CHILDREN(sc->bce_sysctl_tree); 582243c2aeb0SSepherosa Ziehau 5823bdeb8fffSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_bds_int", 5824bdeb8fffSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 5825bdeb8fffSSepherosa Ziehau sc, 0, bce_sysctl_tx_bds_int, "I", 5826bdeb8fffSSepherosa Ziehau "Send max coalesced BD count during interrupt"); 5827bdeb8fffSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_bds", 5828bdeb8fffSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 5829bdeb8fffSSepherosa Ziehau sc, 0, bce_sysctl_tx_bds, "I", 5830bdeb8fffSSepherosa Ziehau "Send max coalesced BD count"); 5831bdeb8fffSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_ticks_int", 5832bdeb8fffSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 5833bdeb8fffSSepherosa Ziehau sc, 0, bce_sysctl_tx_ticks_int, "I", 5834bdeb8fffSSepherosa Ziehau "Send coalescing ticks during interrupt"); 5835bdeb8fffSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_ticks", 5836bdeb8fffSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 5837bdeb8fffSSepherosa Ziehau sc, 0, bce_sysctl_tx_ticks, "I", 5838bdeb8fffSSepherosa Ziehau "Send coalescing ticks"); 5839bdeb8fffSSepherosa Ziehau 5840bdeb8fffSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_bds_int", 5841bdeb8fffSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 5842bdeb8fffSSepherosa Ziehau sc, 0, bce_sysctl_rx_bds_int, "I", 5843bdeb8fffSSepherosa Ziehau "Receive max coalesced BD count during interrupt"); 5844bdeb8fffSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_bds", 5845bdeb8fffSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 5846bdeb8fffSSepherosa Ziehau sc, 0, bce_sysctl_rx_bds, "I", 5847bdeb8fffSSepherosa Ziehau "Receive max coalesced BD count"); 5848bdeb8fffSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_ticks_int", 5849bdeb8fffSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 5850bdeb8fffSSepherosa Ziehau sc, 0, bce_sysctl_rx_ticks_int, "I", 5851bdeb8fffSSepherosa Ziehau "Receive coalescing ticks during interrupt"); 5852bdeb8fffSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_ticks", 5853bdeb8fffSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 5854bdeb8fffSSepherosa Ziehau sc, 0, bce_sysctl_rx_ticks, "I", 5855bdeb8fffSSepherosa Ziehau "Receive coalescing ticks"); 5856bdeb8fffSSepherosa Ziehau 58574b166d4eSSepherosa Ziehau SYSCTL_ADD_INT(ctx, children, OID_AUTO, "rx_pages", 585808b64767SSepherosa Ziehau CTLFLAG_RD, &sc->rx_rings[0].rx_pages, 0, "# of RX pages"); 58594b166d4eSSepherosa Ziehau SYSCTL_ADD_INT(ctx, children, OID_AUTO, "tx_pages", 586010bcbdabSSepherosa Ziehau CTLFLAG_RD, &sc->tx_rings[0].tx_pages, 0, "# of TX pages"); 58614b166d4eSSepherosa Ziehau 5862f52858a0SSepherosa Ziehau SYSCTL_ADD_INT(ctx, children, OID_AUTO, "tx_wreg", 586310bcbdabSSepherosa Ziehau CTLFLAG_RW, &sc->tx_rings[0].tx_wreg, 0, 5864f52858a0SSepherosa Ziehau "# segments before write to hardware registers"); 5865f52858a0SSepherosa Ziehau 586657b3ecd9SSepherosa Ziehau #ifdef IFPOLL_ENABLE 586757b3ecd9SSepherosa Ziehau SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "npoll_offset", 586857b3ecd9SSepherosa Ziehau CTLTYPE_INT|CTLFLAG_RW, sc, 0, bce_sysctl_npoll_offset, 586957b3ecd9SSepherosa Ziehau "I", "NPOLLING cpu offset"); 587057b3ecd9SSepherosa Ziehau #endif 587157b3ecd9SSepherosa Ziehau 587243c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 587356872d4eSSepherosa Ziehau "stat_IfHCInOctets", 587443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCInOctets, 587543c2aeb0SSepherosa Ziehau "Bytes received"); 587643c2aeb0SSepherosa Ziehau 587743c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 587843c2aeb0SSepherosa Ziehau "stat_IfHCInBadOctets", 587943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCInBadOctets, 588043c2aeb0SSepherosa Ziehau "Bad bytes received"); 588143c2aeb0SSepherosa Ziehau 588243c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 588343c2aeb0SSepherosa Ziehau "stat_IfHCOutOctets", 588443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCOutOctets, 588543c2aeb0SSepherosa Ziehau "Bytes sent"); 588643c2aeb0SSepherosa Ziehau 588743c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 588843c2aeb0SSepherosa Ziehau "stat_IfHCOutBadOctets", 588943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCOutBadOctets, 589043c2aeb0SSepherosa Ziehau "Bad bytes sent"); 589143c2aeb0SSepherosa Ziehau 589243c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 589343c2aeb0SSepherosa Ziehau "stat_IfHCInUcastPkts", 589443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCInUcastPkts, 589543c2aeb0SSepherosa Ziehau "Unicast packets received"); 589643c2aeb0SSepherosa Ziehau 589743c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 589843c2aeb0SSepherosa Ziehau "stat_IfHCInMulticastPkts", 589943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCInMulticastPkts, 590043c2aeb0SSepherosa Ziehau "Multicast packets received"); 590143c2aeb0SSepherosa Ziehau 590243c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 590343c2aeb0SSepherosa Ziehau "stat_IfHCInBroadcastPkts", 590443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCInBroadcastPkts, 590543c2aeb0SSepherosa Ziehau "Broadcast packets received"); 590643c2aeb0SSepherosa Ziehau 590743c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 590843c2aeb0SSepherosa Ziehau "stat_IfHCOutUcastPkts", 590943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCOutUcastPkts, 591043c2aeb0SSepherosa Ziehau "Unicast packets sent"); 591143c2aeb0SSepherosa Ziehau 591243c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 591343c2aeb0SSepherosa Ziehau "stat_IfHCOutMulticastPkts", 591443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCOutMulticastPkts, 591543c2aeb0SSepherosa Ziehau "Multicast packets sent"); 591643c2aeb0SSepherosa Ziehau 591743c2aeb0SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, 591843c2aeb0SSepherosa Ziehau "stat_IfHCOutBroadcastPkts", 591943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfHCOutBroadcastPkts, 592043c2aeb0SSepherosa Ziehau "Broadcast packets sent"); 592143c2aeb0SSepherosa Ziehau 592243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 592343c2aeb0SSepherosa Ziehau "stat_emac_tx_stat_dot3statsinternalmactransmiterrors", 592443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors, 592543c2aeb0SSepherosa Ziehau 0, "Internal MAC transmit errors"); 592643c2aeb0SSepherosa Ziehau 592743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 592843c2aeb0SSepherosa Ziehau "stat_Dot3StatsCarrierSenseErrors", 592943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_Dot3StatsCarrierSenseErrors, 593043c2aeb0SSepherosa Ziehau 0, "Carrier sense errors"); 593143c2aeb0SSepherosa Ziehau 593243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 593343c2aeb0SSepherosa Ziehau "stat_Dot3StatsFCSErrors", 593443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_Dot3StatsFCSErrors, 593543c2aeb0SSepherosa Ziehau 0, "Frame check sequence errors"); 593643c2aeb0SSepherosa Ziehau 593743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 593843c2aeb0SSepherosa Ziehau "stat_Dot3StatsAlignmentErrors", 593943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_Dot3StatsAlignmentErrors, 594043c2aeb0SSepherosa Ziehau 0, "Alignment errors"); 594143c2aeb0SSepherosa Ziehau 594243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 594343c2aeb0SSepherosa Ziehau "stat_Dot3StatsSingleCollisionFrames", 594443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_Dot3StatsSingleCollisionFrames, 594543c2aeb0SSepherosa Ziehau 0, "Single Collision Frames"); 594643c2aeb0SSepherosa Ziehau 594743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 594843c2aeb0SSepherosa Ziehau "stat_Dot3StatsMultipleCollisionFrames", 594943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_Dot3StatsMultipleCollisionFrames, 595043c2aeb0SSepherosa Ziehau 0, "Multiple Collision Frames"); 595143c2aeb0SSepherosa Ziehau 595243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 595343c2aeb0SSepherosa Ziehau "stat_Dot3StatsDeferredTransmissions", 595443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_Dot3StatsDeferredTransmissions, 595543c2aeb0SSepherosa Ziehau 0, "Deferred Transmissions"); 595643c2aeb0SSepherosa Ziehau 595743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 595843c2aeb0SSepherosa Ziehau "stat_Dot3StatsExcessiveCollisions", 595943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_Dot3StatsExcessiveCollisions, 596043c2aeb0SSepherosa Ziehau 0, "Excessive Collisions"); 596143c2aeb0SSepherosa Ziehau 596243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 596343c2aeb0SSepherosa Ziehau "stat_Dot3StatsLateCollisions", 596443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_Dot3StatsLateCollisions, 596543c2aeb0SSepherosa Ziehau 0, "Late Collisions"); 596643c2aeb0SSepherosa Ziehau 596743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 596843c2aeb0SSepherosa Ziehau "stat_EtherStatsCollisions", 596943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsCollisions, 597043c2aeb0SSepherosa Ziehau 0, "Collisions"); 597143c2aeb0SSepherosa Ziehau 597243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 597343c2aeb0SSepherosa Ziehau "stat_EtherStatsFragments", 597443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsFragments, 597543c2aeb0SSepherosa Ziehau 0, "Fragments"); 597643c2aeb0SSepherosa Ziehau 597743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 597843c2aeb0SSepherosa Ziehau "stat_EtherStatsJabbers", 597943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsJabbers, 598043c2aeb0SSepherosa Ziehau 0, "Jabbers"); 598143c2aeb0SSepherosa Ziehau 598243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 598343c2aeb0SSepherosa Ziehau "stat_EtherStatsUndersizePkts", 598443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsUndersizePkts, 598543c2aeb0SSepherosa Ziehau 0, "Undersize packets"); 598643c2aeb0SSepherosa Ziehau 598743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 598843c2aeb0SSepherosa Ziehau "stat_EtherStatsOverrsizePkts", 598943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsOverrsizePkts, 599043c2aeb0SSepherosa Ziehau 0, "stat_EtherStatsOverrsizePkts"); 599143c2aeb0SSepherosa Ziehau 599243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 599343c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsRx64Octets", 599443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsRx64Octets, 599543c2aeb0SSepherosa Ziehau 0, "Bytes received in 64 byte packets"); 599643c2aeb0SSepherosa Ziehau 599743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 599843c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsRx65Octetsto127Octets", 599943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsRx65Octetsto127Octets, 600043c2aeb0SSepherosa Ziehau 0, "Bytes received in 65 to 127 byte packets"); 600143c2aeb0SSepherosa Ziehau 600243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 600343c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsRx128Octetsto255Octets", 600443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsRx128Octetsto255Octets, 600543c2aeb0SSepherosa Ziehau 0, "Bytes received in 128 to 255 byte packets"); 600643c2aeb0SSepherosa Ziehau 600743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 600843c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsRx256Octetsto511Octets", 600943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsRx256Octetsto511Octets, 601043c2aeb0SSepherosa Ziehau 0, "Bytes received in 256 to 511 byte packets"); 601143c2aeb0SSepherosa Ziehau 601243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 601343c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsRx512Octetsto1023Octets", 601443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsRx512Octetsto1023Octets, 601543c2aeb0SSepherosa Ziehau 0, "Bytes received in 512 to 1023 byte packets"); 601643c2aeb0SSepherosa Ziehau 601743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 601843c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsRx1024Octetsto1522Octets", 601943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1024Octetsto1522Octets, 602043c2aeb0SSepherosa Ziehau 0, "Bytes received in 1024 t0 1522 byte packets"); 602143c2aeb0SSepherosa Ziehau 602243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 602343c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsRx1523Octetsto9022Octets", 602443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1523Octetsto9022Octets, 602543c2aeb0SSepherosa Ziehau 0, "Bytes received in 1523 to 9022 byte packets"); 602643c2aeb0SSepherosa Ziehau 602743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 602843c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsTx64Octets", 602943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsTx64Octets, 603043c2aeb0SSepherosa Ziehau 0, "Bytes sent in 64 byte packets"); 603143c2aeb0SSepherosa Ziehau 603243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 603343c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsTx65Octetsto127Octets", 603443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsTx65Octetsto127Octets, 603543c2aeb0SSepherosa Ziehau 0, "Bytes sent in 65 to 127 byte packets"); 603643c2aeb0SSepherosa Ziehau 603743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 603843c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsTx128Octetsto255Octets", 603943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsTx128Octetsto255Octets, 604043c2aeb0SSepherosa Ziehau 0, "Bytes sent in 128 to 255 byte packets"); 604143c2aeb0SSepherosa Ziehau 604243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 604343c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsTx256Octetsto511Octets", 604443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsTx256Octetsto511Octets, 604543c2aeb0SSepherosa Ziehau 0, "Bytes sent in 256 to 511 byte packets"); 604643c2aeb0SSepherosa Ziehau 604743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 604843c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsTx512Octetsto1023Octets", 604943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsTx512Octetsto1023Octets, 605043c2aeb0SSepherosa Ziehau 0, "Bytes sent in 512 to 1023 byte packets"); 605143c2aeb0SSepherosa Ziehau 605243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 605343c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsTx1024Octetsto1522Octets", 605443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1024Octetsto1522Octets, 605543c2aeb0SSepherosa Ziehau 0, "Bytes sent in 1024 to 1522 byte packets"); 605643c2aeb0SSepherosa Ziehau 605743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 605843c2aeb0SSepherosa Ziehau "stat_EtherStatsPktsTx1523Octetsto9022Octets", 605943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1523Octetsto9022Octets, 606043c2aeb0SSepherosa Ziehau 0, "Bytes sent in 1523 to 9022 byte packets"); 606143c2aeb0SSepherosa Ziehau 606243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 606343c2aeb0SSepherosa Ziehau "stat_XonPauseFramesReceived", 606443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_XonPauseFramesReceived, 606543c2aeb0SSepherosa Ziehau 0, "XON pause frames receved"); 606643c2aeb0SSepherosa Ziehau 606743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 606843c2aeb0SSepherosa Ziehau "stat_XoffPauseFramesReceived", 606943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_XoffPauseFramesReceived, 607043c2aeb0SSepherosa Ziehau 0, "XOFF pause frames received"); 607143c2aeb0SSepherosa Ziehau 607243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 607343c2aeb0SSepherosa Ziehau "stat_OutXonSent", 607443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_OutXonSent, 607543c2aeb0SSepherosa Ziehau 0, "XON pause frames sent"); 607643c2aeb0SSepherosa Ziehau 607743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 607843c2aeb0SSepherosa Ziehau "stat_OutXoffSent", 607943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_OutXoffSent, 608043c2aeb0SSepherosa Ziehau 0, "XOFF pause frames sent"); 608143c2aeb0SSepherosa Ziehau 608243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 608343c2aeb0SSepherosa Ziehau "stat_FlowControlDone", 608443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_FlowControlDone, 608543c2aeb0SSepherosa Ziehau 0, "Flow control done"); 608643c2aeb0SSepherosa Ziehau 608743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 608843c2aeb0SSepherosa Ziehau "stat_MacControlFramesReceived", 608943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_MacControlFramesReceived, 609043c2aeb0SSepherosa Ziehau 0, "MAC control frames received"); 609143c2aeb0SSepherosa Ziehau 609243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 609343c2aeb0SSepherosa Ziehau "stat_XoffStateEntered", 609443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_XoffStateEntered, 609543c2aeb0SSepherosa Ziehau 0, "XOFF state entered"); 609643c2aeb0SSepherosa Ziehau 609743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 609843c2aeb0SSepherosa Ziehau "stat_IfInFramesL2FilterDiscards", 609943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfInFramesL2FilterDiscards, 610043c2aeb0SSepherosa Ziehau 0, "Received L2 packets discarded"); 610143c2aeb0SSepherosa Ziehau 610243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 610343c2aeb0SSepherosa Ziehau "stat_IfInRuleCheckerDiscards", 610443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfInRuleCheckerDiscards, 610543c2aeb0SSepherosa Ziehau 0, "Received packets discarded by rule"); 610643c2aeb0SSepherosa Ziehau 610743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 610843c2aeb0SSepherosa Ziehau "stat_IfInFTQDiscards", 610943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfInFTQDiscards, 611043c2aeb0SSepherosa Ziehau 0, "Received packet FTQ discards"); 611143c2aeb0SSepherosa Ziehau 611243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 611343c2aeb0SSepherosa Ziehau "stat_IfInMBUFDiscards", 611443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfInMBUFDiscards, 611543c2aeb0SSepherosa Ziehau 0, "Received packets discarded due to lack of controller buffer memory"); 611643c2aeb0SSepherosa Ziehau 611743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 611843c2aeb0SSepherosa Ziehau "stat_IfInRuleCheckerP4Hit", 611943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_IfInRuleCheckerP4Hit, 612043c2aeb0SSepherosa Ziehau 0, "Received packets rule checker hits"); 612143c2aeb0SSepherosa Ziehau 612243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 612343c2aeb0SSepherosa Ziehau "stat_CatchupInRuleCheckerDiscards", 612443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerDiscards, 612543c2aeb0SSepherosa Ziehau 0, "Received packets discarded in Catchup path"); 612643c2aeb0SSepherosa Ziehau 612743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 612843c2aeb0SSepherosa Ziehau "stat_CatchupInFTQDiscards", 612943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_CatchupInFTQDiscards, 613043c2aeb0SSepherosa Ziehau 0, "Received packets discarded in FTQ in Catchup path"); 613143c2aeb0SSepherosa Ziehau 613243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 613343c2aeb0SSepherosa Ziehau "stat_CatchupInMBUFDiscards", 613443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_CatchupInMBUFDiscards, 613543c2aeb0SSepherosa Ziehau 0, "Received packets discarded in controller buffer memory in Catchup path"); 613643c2aeb0SSepherosa Ziehau 613743c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 613843c2aeb0SSepherosa Ziehau "stat_CatchupInRuleCheckerP4Hit", 613943c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerP4Hit, 614043c2aeb0SSepherosa Ziehau 0, "Received packets rule checker hits in Catchup path"); 614143c2aeb0SSepherosa Ziehau 614243c2aeb0SSepherosa Ziehau SYSCTL_ADD_UINT(ctx, children, OID_AUTO, 614343c2aeb0SSepherosa Ziehau "com_no_buffers", 614443c2aeb0SSepherosa Ziehau CTLFLAG_RD, &sc->com_no_buffers, 614543c2aeb0SSepherosa Ziehau 0, "Valid packets received but no RX buffers available"); 614643c2aeb0SSepherosa Ziehau } 614743c2aeb0SSepherosa Ziehau 6148bdeb8fffSSepherosa Ziehau static int 6149bdeb8fffSSepherosa Ziehau bce_sysctl_tx_bds_int(SYSCTL_HANDLER_ARGS) 6150bdeb8fffSSepherosa Ziehau { 6151bdeb8fffSSepherosa Ziehau struct bce_softc *sc = arg1; 6152bdeb8fffSSepherosa Ziehau 6153bdeb8fffSSepherosa Ziehau return bce_sysctl_coal_change(oidp, arg1, arg2, req, 6154bdeb8fffSSepherosa Ziehau &sc->bce_tx_quick_cons_trip_int, 6155bdeb8fffSSepherosa Ziehau BCE_COALMASK_TX_BDS_INT); 6156bdeb8fffSSepherosa Ziehau } 6157bdeb8fffSSepherosa Ziehau 6158bdeb8fffSSepherosa Ziehau static int 6159bdeb8fffSSepherosa Ziehau bce_sysctl_tx_bds(SYSCTL_HANDLER_ARGS) 6160bdeb8fffSSepherosa Ziehau { 6161bdeb8fffSSepherosa Ziehau struct bce_softc *sc = arg1; 6162bdeb8fffSSepherosa Ziehau 6163bdeb8fffSSepherosa Ziehau return bce_sysctl_coal_change(oidp, arg1, arg2, req, 6164bdeb8fffSSepherosa Ziehau &sc->bce_tx_quick_cons_trip, 6165bdeb8fffSSepherosa Ziehau BCE_COALMASK_TX_BDS); 6166bdeb8fffSSepherosa Ziehau } 6167bdeb8fffSSepherosa Ziehau 6168bdeb8fffSSepherosa Ziehau static int 6169bdeb8fffSSepherosa Ziehau bce_sysctl_tx_ticks_int(SYSCTL_HANDLER_ARGS) 6170bdeb8fffSSepherosa Ziehau { 6171bdeb8fffSSepherosa Ziehau struct bce_softc *sc = arg1; 6172bdeb8fffSSepherosa Ziehau 6173bdeb8fffSSepherosa Ziehau return bce_sysctl_coal_change(oidp, arg1, arg2, req, 6174bdeb8fffSSepherosa Ziehau &sc->bce_tx_ticks_int, 6175bdeb8fffSSepherosa Ziehau BCE_COALMASK_TX_TICKS_INT); 6176bdeb8fffSSepherosa Ziehau } 6177bdeb8fffSSepherosa Ziehau 6178bdeb8fffSSepherosa Ziehau static int 6179bdeb8fffSSepherosa Ziehau bce_sysctl_tx_ticks(SYSCTL_HANDLER_ARGS) 6180bdeb8fffSSepherosa Ziehau { 6181bdeb8fffSSepherosa Ziehau struct bce_softc *sc = arg1; 6182bdeb8fffSSepherosa Ziehau 6183bdeb8fffSSepherosa Ziehau return bce_sysctl_coal_change(oidp, arg1, arg2, req, 6184bdeb8fffSSepherosa Ziehau &sc->bce_tx_ticks, 6185bdeb8fffSSepherosa Ziehau BCE_COALMASK_TX_TICKS); 6186bdeb8fffSSepherosa Ziehau } 6187bdeb8fffSSepherosa Ziehau 6188bdeb8fffSSepherosa Ziehau static int 6189bdeb8fffSSepherosa Ziehau bce_sysctl_rx_bds_int(SYSCTL_HANDLER_ARGS) 6190bdeb8fffSSepherosa Ziehau { 6191bdeb8fffSSepherosa Ziehau struct bce_softc *sc = arg1; 6192bdeb8fffSSepherosa Ziehau 6193bdeb8fffSSepherosa Ziehau return bce_sysctl_coal_change(oidp, arg1, arg2, req, 6194bdeb8fffSSepherosa Ziehau &sc->bce_rx_quick_cons_trip_int, 6195bdeb8fffSSepherosa Ziehau BCE_COALMASK_RX_BDS_INT); 6196bdeb8fffSSepherosa Ziehau } 6197bdeb8fffSSepherosa Ziehau 6198bdeb8fffSSepherosa Ziehau static int 6199bdeb8fffSSepherosa Ziehau bce_sysctl_rx_bds(SYSCTL_HANDLER_ARGS) 6200bdeb8fffSSepherosa Ziehau { 6201bdeb8fffSSepherosa Ziehau struct bce_softc *sc = arg1; 6202bdeb8fffSSepherosa Ziehau 6203bdeb8fffSSepherosa Ziehau return bce_sysctl_coal_change(oidp, arg1, arg2, req, 6204bdeb8fffSSepherosa Ziehau &sc->bce_rx_quick_cons_trip, 6205bdeb8fffSSepherosa Ziehau BCE_COALMASK_RX_BDS); 6206bdeb8fffSSepherosa Ziehau } 6207bdeb8fffSSepherosa Ziehau 6208bdeb8fffSSepherosa Ziehau static int 6209bdeb8fffSSepherosa Ziehau bce_sysctl_rx_ticks_int(SYSCTL_HANDLER_ARGS) 6210bdeb8fffSSepherosa Ziehau { 6211bdeb8fffSSepherosa Ziehau struct bce_softc *sc = arg1; 6212bdeb8fffSSepherosa Ziehau 6213bdeb8fffSSepherosa Ziehau return bce_sysctl_coal_change(oidp, arg1, arg2, req, 6214bdeb8fffSSepherosa Ziehau &sc->bce_rx_ticks_int, 6215bdeb8fffSSepherosa Ziehau BCE_COALMASK_RX_TICKS_INT); 6216bdeb8fffSSepherosa Ziehau } 6217bdeb8fffSSepherosa Ziehau 6218bdeb8fffSSepherosa Ziehau static int 6219bdeb8fffSSepherosa Ziehau bce_sysctl_rx_ticks(SYSCTL_HANDLER_ARGS) 6220bdeb8fffSSepherosa Ziehau { 6221bdeb8fffSSepherosa Ziehau struct bce_softc *sc = arg1; 6222bdeb8fffSSepherosa Ziehau 6223bdeb8fffSSepherosa Ziehau return bce_sysctl_coal_change(oidp, arg1, arg2, req, 6224bdeb8fffSSepherosa Ziehau &sc->bce_rx_ticks, 6225bdeb8fffSSepherosa Ziehau BCE_COALMASK_RX_TICKS); 6226bdeb8fffSSepherosa Ziehau } 6227bdeb8fffSSepherosa Ziehau 6228bdeb8fffSSepherosa Ziehau static int 6229bdeb8fffSSepherosa Ziehau bce_sysctl_coal_change(SYSCTL_HANDLER_ARGS, uint32_t *coal, 6230bdeb8fffSSepherosa Ziehau uint32_t coalchg_mask) 6231bdeb8fffSSepherosa Ziehau { 6232bdeb8fffSSepherosa Ziehau struct bce_softc *sc = arg1; 6233bdeb8fffSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 6234bdeb8fffSSepherosa Ziehau int error = 0, v; 6235bdeb8fffSSepherosa Ziehau 623684464af5SSepherosa Ziehau ifnet_serialize_all(ifp); 6237bdeb8fffSSepherosa Ziehau 6238bdeb8fffSSepherosa Ziehau v = *coal; 6239bdeb8fffSSepherosa Ziehau error = sysctl_handle_int(oidp, &v, 0, req); 6240bdeb8fffSSepherosa Ziehau if (!error && req->newptr != NULL) { 6241bdeb8fffSSepherosa Ziehau if (v < 0) { 6242bdeb8fffSSepherosa Ziehau error = EINVAL; 6243bdeb8fffSSepherosa Ziehau } else { 6244bdeb8fffSSepherosa Ziehau *coal = v; 6245bdeb8fffSSepherosa Ziehau sc->bce_coalchg_mask |= coalchg_mask; 624657b3ecd9SSepherosa Ziehau 624757b3ecd9SSepherosa Ziehau /* Commit changes */ 624857b3ecd9SSepherosa Ziehau bce_coal_change(sc); 6249bdeb8fffSSepherosa Ziehau } 6250bdeb8fffSSepherosa Ziehau } 6251bdeb8fffSSepherosa Ziehau 625284464af5SSepherosa Ziehau ifnet_deserialize_all(ifp); 6253bdeb8fffSSepherosa Ziehau return error; 6254bdeb8fffSSepherosa Ziehau } 6255bdeb8fffSSepherosa Ziehau 6256bdeb8fffSSepherosa Ziehau static void 6257bdeb8fffSSepherosa Ziehau bce_coal_change(struct bce_softc *sc) 6258bdeb8fffSSepherosa Ziehau { 6259bdeb8fffSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 6260bdeb8fffSSepherosa Ziehau 626184464af5SSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize); 6262bdeb8fffSSepherosa Ziehau 6263bdeb8fffSSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) == 0) { 6264bdeb8fffSSepherosa Ziehau sc->bce_coalchg_mask = 0; 6265bdeb8fffSSepherosa Ziehau return; 6266bdeb8fffSSepherosa Ziehau } 6267bdeb8fffSSepherosa Ziehau 6268bdeb8fffSSepherosa Ziehau if (sc->bce_coalchg_mask & 6269bdeb8fffSSepherosa Ziehau (BCE_COALMASK_TX_BDS | BCE_COALMASK_TX_BDS_INT)) { 6270bdeb8fffSSepherosa Ziehau REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, 6271bdeb8fffSSepherosa Ziehau (sc->bce_tx_quick_cons_trip_int << 16) | 6272bdeb8fffSSepherosa Ziehau sc->bce_tx_quick_cons_trip); 6273bdeb8fffSSepherosa Ziehau if (bootverbose) { 6274bdeb8fffSSepherosa Ziehau if_printf(ifp, "tx_bds %u, tx_bds_int %u\n", 6275bdeb8fffSSepherosa Ziehau sc->bce_tx_quick_cons_trip, 6276bdeb8fffSSepherosa Ziehau sc->bce_tx_quick_cons_trip_int); 6277bdeb8fffSSepherosa Ziehau } 6278bdeb8fffSSepherosa Ziehau } 6279bdeb8fffSSepherosa Ziehau 6280bdeb8fffSSepherosa Ziehau if (sc->bce_coalchg_mask & 6281bdeb8fffSSepherosa Ziehau (BCE_COALMASK_TX_TICKS | BCE_COALMASK_TX_TICKS_INT)) { 6282bdeb8fffSSepherosa Ziehau REG_WR(sc, BCE_HC_TX_TICKS, 6283bdeb8fffSSepherosa Ziehau (sc->bce_tx_ticks_int << 16) | sc->bce_tx_ticks); 6284bdeb8fffSSepherosa Ziehau if (bootverbose) { 6285bdeb8fffSSepherosa Ziehau if_printf(ifp, "tx_ticks %u, tx_ticks_int %u\n", 6286bdeb8fffSSepherosa Ziehau sc->bce_tx_ticks, sc->bce_tx_ticks_int); 6287bdeb8fffSSepherosa Ziehau } 6288bdeb8fffSSepherosa Ziehau } 6289bdeb8fffSSepherosa Ziehau 6290bdeb8fffSSepherosa Ziehau if (sc->bce_coalchg_mask & 6291bdeb8fffSSepherosa Ziehau (BCE_COALMASK_RX_BDS | BCE_COALMASK_RX_BDS_INT)) { 6292bdeb8fffSSepherosa Ziehau REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, 6293bdeb8fffSSepherosa Ziehau (sc->bce_rx_quick_cons_trip_int << 16) | 6294bdeb8fffSSepherosa Ziehau sc->bce_rx_quick_cons_trip); 6295bdeb8fffSSepherosa Ziehau if (bootverbose) { 6296bdeb8fffSSepherosa Ziehau if_printf(ifp, "rx_bds %u, rx_bds_int %u\n", 6297bdeb8fffSSepherosa Ziehau sc->bce_rx_quick_cons_trip, 6298bdeb8fffSSepherosa Ziehau sc->bce_rx_quick_cons_trip_int); 6299bdeb8fffSSepherosa Ziehau } 6300bdeb8fffSSepherosa Ziehau } 6301bdeb8fffSSepherosa Ziehau 6302bdeb8fffSSepherosa Ziehau if (sc->bce_coalchg_mask & 6303bdeb8fffSSepherosa Ziehau (BCE_COALMASK_RX_TICKS | BCE_COALMASK_RX_TICKS_INT)) { 6304bdeb8fffSSepherosa Ziehau REG_WR(sc, BCE_HC_RX_TICKS, 6305bdeb8fffSSepherosa Ziehau (sc->bce_rx_ticks_int << 16) | sc->bce_rx_ticks); 6306bdeb8fffSSepherosa Ziehau if (bootverbose) { 6307bdeb8fffSSepherosa Ziehau if_printf(ifp, "rx_ticks %u, rx_ticks_int %u\n", 6308bdeb8fffSSepherosa Ziehau sc->bce_rx_ticks, sc->bce_rx_ticks_int); 6309bdeb8fffSSepherosa Ziehau } 6310bdeb8fffSSepherosa Ziehau } 6311bdeb8fffSSepherosa Ziehau 6312bdeb8fffSSepherosa Ziehau sc->bce_coalchg_mask = 0; 6313bdeb8fffSSepherosa Ziehau } 6314eefd160dSSepherosa Ziehau 6315eefd160dSSepherosa Ziehau static int 631610bcbdabSSepherosa Ziehau bce_tso_setup(struct bce_tx_ring *txr, struct mbuf **mp, 6317eefd160dSSepherosa Ziehau uint16_t *flags0, uint16_t *mss0) 6318eefd160dSSepherosa Ziehau { 6319eefd160dSSepherosa Ziehau struct mbuf *m; 6320eefd160dSSepherosa Ziehau uint16_t flags; 6321eefd160dSSepherosa Ziehau int thoff, iphlen, hoff; 6322eefd160dSSepherosa Ziehau 6323eefd160dSSepherosa Ziehau m = *mp; 6324eefd160dSSepherosa Ziehau KASSERT(M_WRITABLE(m), ("TSO mbuf not writable")); 6325eefd160dSSepherosa Ziehau 6326eefd160dSSepherosa Ziehau hoff = m->m_pkthdr.csum_lhlen; 6327eefd160dSSepherosa Ziehau iphlen = m->m_pkthdr.csum_iphlen; 6328eefd160dSSepherosa Ziehau thoff = m->m_pkthdr.csum_thlen; 6329eefd160dSSepherosa Ziehau 6330eefd160dSSepherosa Ziehau KASSERT(hoff >= sizeof(struct ether_header), 6331eefd160dSSepherosa Ziehau ("invalid ether header len %d", hoff)); 6332eefd160dSSepherosa Ziehau KASSERT(iphlen >= sizeof(struct ip), 6333eefd160dSSepherosa Ziehau ("invalid ip header len %d", iphlen)); 6334eefd160dSSepherosa Ziehau KASSERT(thoff >= sizeof(struct tcphdr), 6335eefd160dSSepherosa Ziehau ("invalid tcp header len %d", thoff)); 6336eefd160dSSepherosa Ziehau 6337eefd160dSSepherosa Ziehau if (__predict_false(m->m_len < hoff + iphlen + thoff)) { 6338eefd160dSSepherosa Ziehau m = m_pullup(m, hoff + iphlen + thoff); 6339eefd160dSSepherosa Ziehau if (m == NULL) { 6340eefd160dSSepherosa Ziehau *mp = NULL; 6341eefd160dSSepherosa Ziehau return ENOBUFS; 6342eefd160dSSepherosa Ziehau } 6343eefd160dSSepherosa Ziehau *mp = m; 6344eefd160dSSepherosa Ziehau } 6345eefd160dSSepherosa Ziehau 6346eefd160dSSepherosa Ziehau /* Set the LSO flag in the TX BD */ 6347eefd160dSSepherosa Ziehau flags = TX_BD_FLAGS_SW_LSO; 6348eefd160dSSepherosa Ziehau 6349eefd160dSSepherosa Ziehau /* Set the length of IP + TCP options (in 32 bit words) */ 6350eefd160dSSepherosa Ziehau flags |= (((iphlen + thoff - 6351eefd160dSSepherosa Ziehau sizeof(struct ip) - sizeof(struct tcphdr)) >> 2) << 8); 6352eefd160dSSepherosa Ziehau 6353eefd160dSSepherosa Ziehau *mss0 = htole16(m->m_pkthdr.tso_segsz); 6354eefd160dSSepherosa Ziehau *flags0 = flags; 6355eefd160dSSepherosa Ziehau 6356eefd160dSSepherosa Ziehau return 0; 6357eefd160dSSepherosa Ziehau } 635884464af5SSepherosa Ziehau 635984464af5SSepherosa Ziehau static void 636084464af5SSepherosa Ziehau bce_setup_serialize(struct bce_softc *sc) 636184464af5SSepherosa Ziehau { 636284464af5SSepherosa Ziehau int i, j; 636384464af5SSepherosa Ziehau 636484464af5SSepherosa Ziehau /* 636584464af5SSepherosa Ziehau * Allocate serializer array 636684464af5SSepherosa Ziehau */ 636784464af5SSepherosa Ziehau 636884464af5SSepherosa Ziehau /* Main + TX + RX */ 636984464af5SSepherosa Ziehau sc->serialize_cnt = 1 + sc->ring_cnt + sc->ring_cnt; 637084464af5SSepherosa Ziehau 637184464af5SSepherosa Ziehau sc->serializes = 637284464af5SSepherosa Ziehau kmalloc(sc->serialize_cnt * sizeof(struct lwkt_serialize *), 637384464af5SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 637484464af5SSepherosa Ziehau 637584464af5SSepherosa Ziehau /* 637684464af5SSepherosa Ziehau * Setup serializers 637784464af5SSepherosa Ziehau * 637884464af5SSepherosa Ziehau * NOTE: Order is critical 637984464af5SSepherosa Ziehau */ 638084464af5SSepherosa Ziehau 638184464af5SSepherosa Ziehau i = 0; 638284464af5SSepherosa Ziehau KKASSERT(i < sc->serialize_cnt); 638384464af5SSepherosa Ziehau sc->serializes[i++] = &sc->main_serialize; 638484464af5SSepherosa Ziehau 638584464af5SSepherosa Ziehau sc->tx_serialize = i; 638684464af5SSepherosa Ziehau for (j = 0; j < sc->ring_cnt; ++j) { 638784464af5SSepherosa Ziehau KKASSERT(i < sc->serialize_cnt); 638884464af5SSepherosa Ziehau sc->serializes[i++] = &sc->tx_rings[j].tx_serialize; 638984464af5SSepherosa Ziehau } 639084464af5SSepherosa Ziehau 639184464af5SSepherosa Ziehau sc->rx_serialize = i; 639284464af5SSepherosa Ziehau for (j = 0; j < sc->ring_cnt; ++j) { 639384464af5SSepherosa Ziehau KKASSERT(i < sc->serialize_cnt); 639484464af5SSepherosa Ziehau sc->serializes[i++] = &sc->rx_rings[j].rx_serialize; 639584464af5SSepherosa Ziehau } 639684464af5SSepherosa Ziehau 639784464af5SSepherosa Ziehau KKASSERT(i == sc->serialize_cnt); 639884464af5SSepherosa Ziehau } 639984464af5SSepherosa Ziehau 640084464af5SSepherosa Ziehau static void 640184464af5SSepherosa Ziehau bce_serialize(struct ifnet *ifp, enum ifnet_serialize slz) 640284464af5SSepherosa Ziehau { 640384464af5SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 640484464af5SSepherosa Ziehau 640584464af5SSepherosa Ziehau ifnet_serialize_array_enter(sc->serializes, sc->serialize_cnt, 640684464af5SSepherosa Ziehau sc->tx_serialize, sc->rx_serialize, slz); 640784464af5SSepherosa Ziehau } 640884464af5SSepherosa Ziehau 640984464af5SSepherosa Ziehau static void 641084464af5SSepherosa Ziehau bce_deserialize(struct ifnet *ifp, enum ifnet_serialize slz) 641184464af5SSepherosa Ziehau { 641284464af5SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 641384464af5SSepherosa Ziehau 641484464af5SSepherosa Ziehau ifnet_serialize_array_exit(sc->serializes, sc->serialize_cnt, 641584464af5SSepherosa Ziehau sc->tx_serialize, sc->rx_serialize, slz); 641684464af5SSepherosa Ziehau } 641784464af5SSepherosa Ziehau 641884464af5SSepherosa Ziehau static int 641984464af5SSepherosa Ziehau bce_tryserialize(struct ifnet *ifp, enum ifnet_serialize slz) 642084464af5SSepherosa Ziehau { 642184464af5SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 642284464af5SSepherosa Ziehau 642384464af5SSepherosa Ziehau return ifnet_serialize_array_try(sc->serializes, sc->serialize_cnt, 642484464af5SSepherosa Ziehau sc->tx_serialize, sc->rx_serialize, slz); 642584464af5SSepherosa Ziehau } 642684464af5SSepherosa Ziehau 642784464af5SSepherosa Ziehau #ifdef INVARIANTS 642884464af5SSepherosa Ziehau 642984464af5SSepherosa Ziehau static void 643084464af5SSepherosa Ziehau bce_serialize_assert(struct ifnet *ifp, enum ifnet_serialize slz, 643184464af5SSepherosa Ziehau boolean_t serialized) 643284464af5SSepherosa Ziehau { 643384464af5SSepherosa Ziehau struct bce_softc *sc = ifp->if_softc; 643484464af5SSepherosa Ziehau 643584464af5SSepherosa Ziehau ifnet_serialize_array_assert(sc->serializes, sc->serialize_cnt, 643684464af5SSepherosa Ziehau sc->tx_serialize, sc->rx_serialize, slz, serialized); 643784464af5SSepherosa Ziehau } 643884464af5SSepherosa Ziehau 643984464af5SSepherosa Ziehau #endif /* INVARIANTS */ 644084464af5SSepherosa Ziehau 644184464af5SSepherosa Ziehau static void 644284464af5SSepherosa Ziehau bce_serialize_skipmain(struct bce_softc *sc) 644384464af5SSepherosa Ziehau { 644484464af5SSepherosa Ziehau lwkt_serialize_array_enter(sc->serializes, sc->serialize_cnt, 1); 644584464af5SSepherosa Ziehau } 644684464af5SSepherosa Ziehau 644784464af5SSepherosa Ziehau static void 644884464af5SSepherosa Ziehau bce_deserialize_skipmain(struct bce_softc *sc) 644984464af5SSepherosa Ziehau { 645084464af5SSepherosa Ziehau lwkt_serialize_array_exit(sc->serializes, sc->serialize_cnt, 1); 645184464af5SSepherosa Ziehau } 645257b3ecd9SSepherosa Ziehau 645357b3ecd9SSepherosa Ziehau #ifdef IFPOLL_ENABLE 645457b3ecd9SSepherosa Ziehau 645557b3ecd9SSepherosa Ziehau static int 645657b3ecd9SSepherosa Ziehau bce_sysctl_npoll_offset(SYSCTL_HANDLER_ARGS) 645757b3ecd9SSepherosa Ziehau { 645857b3ecd9SSepherosa Ziehau struct bce_softc *sc = (void *)arg1; 645957b3ecd9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 646057b3ecd9SSepherosa Ziehau int error, off; 646157b3ecd9SSepherosa Ziehau 646257b3ecd9SSepherosa Ziehau off = sc->npoll_ofs; 646357b3ecd9SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 646457b3ecd9SSepherosa Ziehau if (error || req->newptr == NULL) 646557b3ecd9SSepherosa Ziehau return error; 646657b3ecd9SSepherosa Ziehau if (off < 0) 646757b3ecd9SSepherosa Ziehau return EINVAL; 646857b3ecd9SSepherosa Ziehau 646957b3ecd9SSepherosa Ziehau ifnet_serialize_all(ifp); 647057b3ecd9SSepherosa Ziehau if (off >= ncpus2 || off % sc->ring_cnt != 0) { 647157b3ecd9SSepherosa Ziehau error = EINVAL; 647257b3ecd9SSepherosa Ziehau } else { 647357b3ecd9SSepherosa Ziehau error = 0; 647457b3ecd9SSepherosa Ziehau sc->npoll_ofs = off; 647557b3ecd9SSepherosa Ziehau } 647657b3ecd9SSepherosa Ziehau ifnet_deserialize_all(ifp); 647757b3ecd9SSepherosa Ziehau 647857b3ecd9SSepherosa Ziehau return error; 647957b3ecd9SSepherosa Ziehau } 648057b3ecd9SSepherosa Ziehau 648157b3ecd9SSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 6482