1*175a7a0dSjmatthew /* $OpenBSD: if_aq_pci.c,v 1.29 2025/01/26 23:09:48 jmatthew Exp $ */ 2bccaee56Smlarkin /* $NetBSD: if_aq.c,v 1.27 2021/06/16 00:21:18 riastradh Exp $ */ 3bccaee56Smlarkin 4bccaee56Smlarkin /* 5bccaee56Smlarkin * Copyright (c) 2021 Jonathan Matthew <jonathan@d14n.org> 6bccaee56Smlarkin * Copyright (c) 2021 Mike Larkin <mlarkin@openbsd.org> 7bccaee56Smlarkin * 8bccaee56Smlarkin * Permission to use, copy, modify, and distribute this software for any 9bccaee56Smlarkin * purpose with or without fee is hereby granted, provided that the above 10bccaee56Smlarkin * copyright notice and this permission notice appear in all copies. 11bccaee56Smlarkin * 12bccaee56Smlarkin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13bccaee56Smlarkin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14bccaee56Smlarkin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15bccaee56Smlarkin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16bccaee56Smlarkin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17bccaee56Smlarkin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18bccaee56Smlarkin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19bccaee56Smlarkin */ 20bccaee56Smlarkin 21bccaee56Smlarkin /** 22bccaee56Smlarkin * aQuantia Corporation Network Driver 23bccaee56Smlarkin * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved 24bccaee56Smlarkin * 25bccaee56Smlarkin * Redistribution and use in source and binary forms, with or without 26bccaee56Smlarkin * modification, are permitted provided that the following conditions 27bccaee56Smlarkin * are met: 28bccaee56Smlarkin * 29bccaee56Smlarkin * (1) Redistributions of source code must retain the above 30bccaee56Smlarkin * copyright notice, this list of conditions and the following 31bccaee56Smlarkin * disclaimer. 32bccaee56Smlarkin * 33bccaee56Smlarkin * (2) Redistributions in binary form must reproduce the above 34bccaee56Smlarkin * copyright notice, this list of conditions and the following 35bccaee56Smlarkin * disclaimer in the documentation and/or other materials provided 36bccaee56Smlarkin * with the distribution. 37bccaee56Smlarkin * 38bccaee56Smlarkin * (3) The name of the author may not be used to endorse or promote 39bccaee56Smlarkin * products derived from this software without specific prior 40bccaee56Smlarkin * written permission. 41bccaee56Smlarkin * 42bccaee56Smlarkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 43bccaee56Smlarkin * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 44bccaee56Smlarkin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45bccaee56Smlarkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 46bccaee56Smlarkin * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47bccaee56Smlarkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 48bccaee56Smlarkin * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 49bccaee56Smlarkin * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 50bccaee56Smlarkin * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 51bccaee56Smlarkin * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 52bccaee56Smlarkin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53bccaee56Smlarkin * 54bccaee56Smlarkin */ 55bccaee56Smlarkin 56bccaee56Smlarkin /*- 57bccaee56Smlarkin * Copyright (c) 2020 Ryo Shimizu <ryo@nerv.org> 58bccaee56Smlarkin * All rights reserved. 59bccaee56Smlarkin * 60bccaee56Smlarkin * Redistribution and use in source and binary forms, with or without 61bccaee56Smlarkin * modification, are permitted provided that the following conditions 62bccaee56Smlarkin * are met: 63bccaee56Smlarkin * 1. Redistributions of source code must retain the above copyright 64bccaee56Smlarkin * notice, this list of conditions and the following disclaimer. 65bccaee56Smlarkin * 2. Redistributions in binary form must reproduce the above copyright 66bccaee56Smlarkin * notice, this list of conditions and the following disclaimer in the 67bccaee56Smlarkin * documentation and/or other materials provided with the distribution. 68bccaee56Smlarkin * 69bccaee56Smlarkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 70bccaee56Smlarkin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 71bccaee56Smlarkin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 72bccaee56Smlarkin * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 73bccaee56Smlarkin * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 74bccaee56Smlarkin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 75bccaee56Smlarkin * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 76bccaee56Smlarkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 77bccaee56Smlarkin * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 78bccaee56Smlarkin * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 79bccaee56Smlarkin * POSSIBILITY OF SUCH DAMAGE. 80bccaee56Smlarkin */ 8166048eb6Sjmatthew #include "bpfilter.h" 8231f14b89Sjmatthew #include "vlan.h" 8366048eb6Sjmatthew 84bccaee56Smlarkin #include <sys/types.h> 85bccaee56Smlarkin #include <sys/device.h> 86bccaee56Smlarkin #include <sys/param.h> 87bccaee56Smlarkin #include <sys/sockio.h> 88bccaee56Smlarkin #include <sys/systm.h> 891d7ac227Sjmatthew #include <sys/intrmap.h> 90bccaee56Smlarkin 91bccaee56Smlarkin #include <net/if.h> 92bccaee56Smlarkin #include <net/if_media.h> 93190bcc8eSjmatthew #include <net/toeplitz.h> 94bccaee56Smlarkin 95bccaee56Smlarkin #include <netinet/in.h> 96bccaee56Smlarkin #include <netinet/if_ether.h> 97bccaee56Smlarkin 98d685096fSkettenis #ifdef __HAVE_FDT 99d685096fSkettenis #include <dev/ofw/openfirm.h> 100d685096fSkettenis #endif 101d685096fSkettenis 102bccaee56Smlarkin #include <dev/pci/pcireg.h> 103bccaee56Smlarkin #include <dev/pci/pcivar.h> 104bccaee56Smlarkin #include <dev/pci/pcidevs.h> 105bccaee56Smlarkin 10666048eb6Sjmatthew #if NBPFILTER > 0 10766048eb6Sjmatthew #include <net/bpf.h> 10866048eb6Sjmatthew #endif 10966048eb6Sjmatthew 110bccaee56Smlarkin /* #define AQ_DEBUG 1 */ 111bccaee56Smlarkin #ifdef AQ_DEBUG 112bccaee56Smlarkin #define DPRINTF(x) printf x 113bccaee56Smlarkin #else 114bccaee56Smlarkin #define DPRINTF(x) 115bccaee56Smlarkin #endif /* AQ_DEBUG */ 116bccaee56Smlarkin 117bccaee56Smlarkin #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) 118bccaee56Smlarkin 119bccaee56Smlarkin #define AQ_BAR0 0x10 120bccaee56Smlarkin #define AQ_MAXQ 8 121190bcc8eSjmatthew #define AQ_RSS_KEYSIZE 40 122190bcc8eSjmatthew #define AQ_RSS_REDIR_ENTRIES 12 123bccaee56Smlarkin 124bccaee56Smlarkin #define AQ_TXD_NUM 2048 125bccaee56Smlarkin #define AQ_RXD_NUM 2048 126bccaee56Smlarkin 12700f24cf6Sjmatthew #define AQ_TX_MAX_SEGMENTS 32 128bccaee56Smlarkin 129bccaee56Smlarkin #define AQ_LINKSTAT_IRQ 31 130bccaee56Smlarkin 131bccaee56Smlarkin #define RPF_ACTION_HOST 1 132bccaee56Smlarkin 133bccaee56Smlarkin #define AQ_FW_SOFTRESET_REG 0x0000 134bccaee56Smlarkin #define AQ_FW_SOFTRESET_DIS (1 << 14) 135bccaee56Smlarkin #define AQ_FW_SOFTRESET_RESET (1 << 15) 136bccaee56Smlarkin #define AQ_FW_VERSION_REG 0x0018 137bccaee56Smlarkin #define AQ_HW_REVISION_REG 0x001c 138b760e38cSjmatthew #define AQ2_HW_FPGA_VERSION_REG 0x00f4 139bccaee56Smlarkin #define AQ_GLB_NVR_INTERFACE1_REG 0x0100 140bccaee56Smlarkin #define AQ_FW_MBOX_CMD_REG 0x0200 141bccaee56Smlarkin #define AQ_FW_MBOX_CMD_EXECUTE 0x00008000 142bccaee56Smlarkin #define AQ_FW_MBOX_CMD_BUSY 0x00000100 143bccaee56Smlarkin #define AQ_FW_MBOX_ADDR_REG 0x0208 144bccaee56Smlarkin #define AQ_FW_MBOX_VAL_REG 0x020C 145bccaee56Smlarkin #define AQ_FW_GLB_CPU_SEM_REG(i) (0x03a0 + (i) * 4) 146bccaee56Smlarkin #define AQ_FW_SEM_RAM_REG AQ_FW_GLB_CPU_SEM_REG(2) 147b760e38cSjmatthew #define AQ2_ART_SEM_REG AQ_FW_GLB_CPU_SEM_REG(3) 148bccaee56Smlarkin #define AQ_FW_GLB_CTL2_REG 0x0404 149bccaee56Smlarkin #define AQ_GLB_GENERAL_PROVISIONING9_REG 0x0520 150bccaee56Smlarkin #define AQ_GLB_NVR_PROVISIONING2_REG 0x0534 151bccaee56Smlarkin #define AQ_INTR_STATUS_REG 0x2000 /* intr status */ 152bccaee56Smlarkin #define AQ_INTR_STATUS_CLR_REG 0x2050 /* intr status clear */ 153bccaee56Smlarkin #define AQ_INTR_MASK_REG 0x2060 /* intr mask set */ 154bccaee56Smlarkin #define AQ_INTR_MASK_CLR_REG 0x2070 /* intr mask clear */ 155bccaee56Smlarkin #define AQ_INTR_AUTOMASK_REG 0x2090 156bccaee56Smlarkin 157bccaee56Smlarkin /* AQ_INTR_IRQ_MAP_TXRX_REG 0x2100-0x2140 */ 158bccaee56Smlarkin #define AQ_INTR_IRQ_MAP_TXRX_REG(i) (0x2100 + ((i) / 2) * 4) 159bccaee56Smlarkin #define AQ_INTR_IRQ_MAP_TX_REG(i) AQ_INTR_IRQ_MAP_TXRX_REG(i) 160bccaee56Smlarkin #define AQ_INTR_IRQ_MAP_TX_IRQMAP(i) (0x1FU << (((i) & 1) ? 16 : 24)) 161bccaee56Smlarkin #define AQ_INTR_IRQ_MAP_TX_EN(i) (1U << (((i) & 1) ? 23 : 31)) 162bccaee56Smlarkin #define AQ_INTR_IRQ_MAP_RX_REG(i) AQ_INTR_IRQ_MAP_TXRX_REG(i) 163bccaee56Smlarkin #define AQ_INTR_IRQ_MAP_RX_IRQMAP(i) (0x1FU << (((i) & 1) ? 0 : 8)) 164bccaee56Smlarkin #define AQ_INTR_IRQ_MAP_RX_EN(i) (1U << (((i) & 1) ? 7 : 15)) 165bccaee56Smlarkin 166bccaee56Smlarkin /* AQ_GEN_INTR_MAP_REG[AQ_RINGS_NUM] 0x2180-0x2200 */ 167bccaee56Smlarkin #define AQ_GEN_INTR_MAP_REG(i) (0x2180 + (i) * 4) 168bccaee56Smlarkin #define AQ_B0_ERR_INT 8U 169bccaee56Smlarkin 170bccaee56Smlarkin #define AQ_INTR_CTRL_REG 0x2300 171bccaee56Smlarkin #define AQ_INTR_CTRL_IRQMODE ((1 << 0) | (1 << 1)) 172bccaee56Smlarkin #define AQ_INTR_CTRL_IRQMODE_LEGACY 0 173bccaee56Smlarkin #define AQ_INTR_CTRL_IRQMODE_MSI 1 174bccaee56Smlarkin #define AQ_INTR_CTRL_IRQMODE_MSIX 2 175bccaee56Smlarkin #define AQ_INTR_CTRL_MULTIVEC (1 << 2) 176bccaee56Smlarkin #define AQ_INTR_CTRL_RESET_DIS (1 << 29) 177dcec61dcSmiod #define AQ_INTR_CTRL_RESET_IRQ (1U << 31) 178bccaee56Smlarkin #define AQ_MBOXIF_POWER_GATING_CONTROL_REG 0x32a8 179bccaee56Smlarkin 180bccaee56Smlarkin #define FW_MPI_MBOX_ADDR_REG 0x0360 181bccaee56Smlarkin #define FW1X_MPI_INIT1_REG 0x0364 182bccaee56Smlarkin #define FW1X_MPI_INIT2_REG 0x0370 183bccaee56Smlarkin #define FW1X_MPI_EFUSEADDR_REG 0x0374 184bccaee56Smlarkin 185bccaee56Smlarkin #define FW2X_MPI_EFUSEADDR_REG 0x0364 186bccaee56Smlarkin #define FW2X_MPI_CONTROL_REG 0x0368 /* 64bit */ 187bccaee56Smlarkin #define FW2X_MPI_STATE_REG 0x0370 /* 64bit */ 188bccaee56Smlarkin #define FW_BOOT_EXIT_CODE_REG 0x0388 189bccaee56Smlarkin 190bccaee56Smlarkin #define FW_BOOT_EXIT_CODE_REG 0x0388 191bccaee56Smlarkin #define RBL_STATUS_DEAD 0x0000dead 192bccaee56Smlarkin #define RBL_STATUS_SUCCESS 0x0000abba 193bccaee56Smlarkin #define RBL_STATUS_FAILURE 0x00000bad 194bccaee56Smlarkin #define RBL_STATUS_HOST_BOOT 0x0000f1a7 195bccaee56Smlarkin #define FW_MPI_DAISY_CHAIN_STATUS_REG 0x0704 196bccaee56Smlarkin #define AQ_PCI_REG_CONTROL_6_REG 0x1014 197bccaee56Smlarkin 198bccaee56Smlarkin #define FW_MPI_RESETCTRL_REG 0x4000 199bccaee56Smlarkin #define FW_MPI_RESETCTRL_RESET_DIS (1 << 29) 200bccaee56Smlarkin 201bccaee56Smlarkin #define RX_SYSCONTROL_REG 0x5000 202bccaee56Smlarkin #define RX_SYSCONTROL_RESET_DIS (1 << 29) 203bccaee56Smlarkin 204bccaee56Smlarkin #define RX_TCP_RSS_HASH_REG 0x5040 205190bcc8eSjmatthew #define RX_TCP_RSS_HASH_RPF2 (0xf << 16) 206190bcc8eSjmatthew #define RX_TCP_RSS_HASH_TYPE (0xffff) 207bccaee56Smlarkin 208bccaee56Smlarkin #define RPF_L2BC_REG 0x5100 209bccaee56Smlarkin #define RPF_L2BC_EN (1 << 0) 210bccaee56Smlarkin #define RPF_L2BC_PROMISC (1 << 3) 211bccaee56Smlarkin #define RPF_L2BC_ACTION 0x7000 212bccaee56Smlarkin #define RPF_L2BC_THRESHOLD 0xFFFF0000 213bccaee56Smlarkin 214bccaee56Smlarkin #define AQ_HW_MAC_OWN 0 215bccaee56Smlarkin 216bccaee56Smlarkin /* RPF_L2UC_*_REG[34] (actual [38]?) */ 217bccaee56Smlarkin #define RPF_L2UC_LSW_REG(i) (0x5110 + (i) * 8) 218bccaee56Smlarkin #define RPF_L2UC_MSW_REG(i) (0x5114 + (i) * 8) 219bccaee56Smlarkin #define RPF_L2UC_MSW_MACADDR_HI 0xFFFF 220bccaee56Smlarkin #define RPF_L2UC_MSW_ACTION 0x70000 221b760e38cSjmatthew #define RPF_L2UC_MSW_TAG 0x03c00000 222dcec61dcSmiod #define RPF_L2UC_MSW_EN (1U << 31) 223bccaee56Smlarkin #define AQ_HW_MAC_NUM 34 224bccaee56Smlarkin 225bccaee56Smlarkin /* RPF_MCAST_FILTER_REG[8] 0x5250-0x5270 */ 226bccaee56Smlarkin #define RPF_MCAST_FILTER_REG(i) (0x5250 + (i) * 4) 227dcec61dcSmiod #define RPF_MCAST_FILTER_EN (1U << 31) 228bccaee56Smlarkin #define RPF_MCAST_FILTER_MASK_REG 0x5270 229bccaee56Smlarkin #define RPF_MCAST_FILTER_MASK_ALLMULTI (1 << 14) 230bccaee56Smlarkin 231bccaee56Smlarkin #define RPF_VLAN_MODE_REG 0x5280 232bccaee56Smlarkin #define RPF_VLAN_MODE_PROMISC (1 << 1) 233bccaee56Smlarkin #define RPF_VLAN_MODE_ACCEPT_UNTAGGED (1 << 2) 234bccaee56Smlarkin #define RPF_VLAN_MODE_UNTAGGED_ACTION 0x38 235bccaee56Smlarkin 236bccaee56Smlarkin #define RPF_VLAN_TPID_REG 0x5284 237bccaee56Smlarkin #define RPF_VLAN_TPID_OUTER 0xFFFF0000 238bccaee56Smlarkin #define RPF_VLAN_TPID_INNER 0xFFFF 239bccaee56Smlarkin 240bccaee56Smlarkin /* RPF_ETHERTYPE_FILTER_REG[AQ_RINGS_NUM] 0x5300-0x5380 */ 241bccaee56Smlarkin #define RPF_ETHERTYPE_FILTER_REG(i) (0x5300 + (i) * 4) 242dcec61dcSmiod #define RPF_ETHERTYPE_FILTER_EN (1U << 31) 243bccaee56Smlarkin 244bccaee56Smlarkin /* RPF_L3_FILTER_REG[8] 0x5380-0x53a0 */ 245bccaee56Smlarkin #define RPF_L3_FILTER_REG(i) (0x5380 + (i) * 4) 246dcec61dcSmiod #define RPF_L3_FILTER_L4_EN (1U << 31) 247bccaee56Smlarkin 248bccaee56Smlarkin #define RX_FLR_RSS_CONTROL1_REG 0x54c0 249dcec61dcSmiod #define RX_FLR_RSS_CONTROL1_EN (1U << 31) 250bccaee56Smlarkin 251bccaee56Smlarkin #define RPF_RPB_RX_TC_UPT_REG 0x54c4 252bccaee56Smlarkin #define RPF_RPB_RX_TC_UPT_MASK(i) (0x00000007 << ((i) * 4)) 253bccaee56Smlarkin 254190bcc8eSjmatthew #define RPF_RSS_KEY_ADDR_REG 0x54d0 255190bcc8eSjmatthew #define RPF_RSS_KEY_ADDR 0x1f 256190bcc8eSjmatthew #define RPF_RSS_KEY_WR_EN (1 << 5) 257190bcc8eSjmatthew #define RPF_RSS_KEY_WR_DATA_REG 0x54d4 258190bcc8eSjmatthew #define RPF_RSS_KEY_RD_DATA_REG 0x54d8 259190bcc8eSjmatthew 260190bcc8eSjmatthew #define RPF_RSS_REDIR_ADDR_REG 0x54e0 261190bcc8eSjmatthew #define RPF_RSS_REDIR_ADDR 0xf 262190bcc8eSjmatthew #define RPF_RSS_REDIR_WR_EN (1 << 4) 263190bcc8eSjmatthew 264190bcc8eSjmatthew #define RPF_RSS_REDIR_WR_DATA_REG 0x54e4 265190bcc8eSjmatthew 266190bcc8eSjmatthew 2675e728153Sjmatthew #define RPO_HWCSUM_REG 0x5580 2685e728153Sjmatthew #define RPO_HWCSUM_L4CSUM_EN (1 << 0) 2695e728153Sjmatthew #define RPO_HWCSUM_IP4CSUM_EN (1 << 1) 2705e728153Sjmatthew 271bccaee56Smlarkin #define RPB_RPF_RX_REG 0x5700 272bccaee56Smlarkin #define RPB_RPF_RX_TC_MODE (1 << 8) 273bccaee56Smlarkin #define RPB_RPF_RX_FC_MODE 0x30 274bccaee56Smlarkin #define RPB_RPF_RX_BUF_EN (1 << 0) 275bccaee56Smlarkin 276bccaee56Smlarkin /* RPB_RXB_BUFSIZE_REG[AQ_TRAFFICCLASS_NUM] 0x5710-0x5790 */ 277bccaee56Smlarkin #define RPB_RXB_BUFSIZE_REG(i) (0x5710 + (i) * 0x10) 278bccaee56Smlarkin #define RPB_RXB_BUFSIZE 0x1FF 279bccaee56Smlarkin #define RPB_RXB_XOFF_REG(i) (0x5714 + (i) * 0x10) 280dcec61dcSmiod #define RPB_RXB_XOFF_EN (1U << 31) 281bccaee56Smlarkin #define RPB_RXB_XOFF_THRESH_HI 0x3FFF0000 282bccaee56Smlarkin #define RPB_RXB_XOFF_THRESH_LO 0x3FFF 283bccaee56Smlarkin 284d04289f5Sjmatthew #define RX_DMA_DESC_CACHE_INIT_REG 0x5a00 285d04289f5Sjmatthew #define RX_DMA_DESC_CACHE_INIT (1 << 0) 286d04289f5Sjmatthew 287bccaee56Smlarkin #define RX_DMA_INT_DESC_WRWB_EN_REG 0x5a30 288bccaee56Smlarkin #define RX_DMA_INT_DESC_WRWB_EN (1 << 2) 289bccaee56Smlarkin #define RX_DMA_INT_DESC_MODERATE_EN (1 << 3) 290bccaee56Smlarkin 291bccaee56Smlarkin #define RX_INTR_MODERATION_CTL_REG(i) (0x5a40 + (i) * 4) 292bccaee56Smlarkin #define RX_INTR_MODERATION_CTL_EN (1 << 1) 2938c5cbf79Sjmatthew #define RX_INTR_MODERATION_CTL_MIN (0xFF << 8) 2948c5cbf79Sjmatthew #define RX_INTR_MODERATION_CTL_MAX (0x1FF << 16) 295bccaee56Smlarkin 296bccaee56Smlarkin #define RX_DMA_DESC_BASE_ADDRLSW_REG(i) (0x5b00 + (i) * 0x20) 297bccaee56Smlarkin #define RX_DMA_DESC_BASE_ADDRMSW_REG(i) (0x5b04 + (i) * 0x20) 298bccaee56Smlarkin #define RX_DMA_DESC_REG(i) (0x5b08 + (i) * 0x20) 299bccaee56Smlarkin #define RX_DMA_DESC_LEN (0x3FF << 3) 300bccaee56Smlarkin #define RX_DMA_DESC_RESET (1 << 25) 301bccaee56Smlarkin #define RX_DMA_DESC_HEADER_SPLIT (1 << 28) 302bccaee56Smlarkin #define RX_DMA_DESC_VLAN_STRIP (1 << 29) 303dcec61dcSmiod #define RX_DMA_DESC_EN (1U << 31) 304bccaee56Smlarkin #define RX_DMA_DESC_HEAD_PTR_REG(i) (0x5b0c + (i) * 0x20) 305bccaee56Smlarkin #define RX_DMA_DESC_HEAD_PTR 0xFFF 306bccaee56Smlarkin #define RX_DMA_DESC_TAIL_PTR_REG(i) (0x5b10 + (i) * 0x20) 307bccaee56Smlarkin #define RX_DMA_DESC_BUFSIZE_REG(i) (0x5b18 + (i) * 0x20) 308bccaee56Smlarkin #define RX_DMA_DESC_BUFSIZE_DATA 0x000F 309bccaee56Smlarkin #define RX_DMA_DESC_BUFSIZE_HDR 0x0FF0 310bccaee56Smlarkin 311bccaee56Smlarkin #define RX_DMA_DCAD_REG(i) (0x6100 + (i) * 4) 312bccaee56Smlarkin #define RX_DMA_DCAD_CPUID 0xFF 313bccaee56Smlarkin #define RX_DMA_DCAD_PAYLOAD_EN (1 << 29) 314bccaee56Smlarkin #define RX_DMA_DCAD_HEADER_EN (1 << 30) 315dcec61dcSmiod #define RX_DMA_DCAD_DESC_EN (1U << 31) 316bccaee56Smlarkin 317bccaee56Smlarkin #define RX_DMA_DCA_REG 0x6180 318dcec61dcSmiod #define RX_DMA_DCA_EN (1U << 31) 319bccaee56Smlarkin #define RX_DMA_DCA_MODE 0xF 320bccaee56Smlarkin 321bccaee56Smlarkin #define TX_SYSCONTROL_REG 0x7000 322bccaee56Smlarkin #define TX_SYSCONTROL_RESET_DIS (1 << 29) 323bccaee56Smlarkin 324bccaee56Smlarkin #define TX_TPO2_REG 0x7040 325bccaee56Smlarkin #define TX_TPO2_EN (1 << 16) 326bccaee56Smlarkin 327bccaee56Smlarkin #define TPS_DESC_VM_ARB_MODE_REG 0x7300 328bccaee56Smlarkin #define TPS_DESC_VM_ARB_MODE (1 << 0) 329bccaee56Smlarkin #define TPS_DESC_RATE_REG 0x7310 330dcec61dcSmiod #define TPS_DESC_RATE_TA_RST (1U << 31) 331bccaee56Smlarkin #define TPS_DESC_RATE_LIM 0x7FF 332bccaee56Smlarkin #define TPS_DESC_TC_ARB_MODE_REG 0x7200 333bccaee56Smlarkin #define TPS_DESC_TC_ARB_MODE 0x3 334bccaee56Smlarkin #define TPS_DATA_TC_ARB_MODE_REG 0x7100 335bccaee56Smlarkin #define TPS_DATA_TC_ARB_MODE (1 << 0) 336bccaee56Smlarkin 337bccaee56Smlarkin /* TPS_DATA_TCT_REG[AQ_TRAFFICCLASS_NUM] 0x7110-0x7130 */ 338bccaee56Smlarkin #define TPS_DATA_TCT_REG(i) (0x7110 + (i) * 4) 339bccaee56Smlarkin #define TPS_DATA_TCT_CREDIT_MAX 0xFFF0000 340bccaee56Smlarkin #define TPS_DATA_TCT_WEIGHT 0x1FF 3415bd4e6eeSkettenis #define TPS2_DATA_TCT_CREDIT_MAX 0xFFFF0000 3425bd4e6eeSkettenis #define TPS2_DATA_TCT_WEIGHT 0x7FFF 343bccaee56Smlarkin /* TPS_DATA_TCT_REG[AQ_TRAFFICCLASS_NUM] 0x7210-0x7230 */ 344bccaee56Smlarkin #define TPS_DESC_TCT_REG(i) (0x7210 + (i) * 4) 345bccaee56Smlarkin #define TPS_DESC_TCT_CREDIT_MAX 0xFFF0000 346bccaee56Smlarkin #define TPS_DESC_TCT_WEIGHT 0x1FF 347bccaee56Smlarkin 348bccaee56Smlarkin #define AQ_HW_TXBUF_MAX 160 349bccaee56Smlarkin #define AQ_HW_RXBUF_MAX 320 3505bd4e6eeSkettenis #define AQ2_HW_TXBUF_MAX 128 3515bd4e6eeSkettenis #define AQ2_HW_RXBUF_MAX 192 352bccaee56Smlarkin 3535e728153Sjmatthew #define TPO_HWCSUM_REG 0x7800 3545e728153Sjmatthew #define TPO_HWCSUM_L4CSUM_EN (1 << 0) 3555e728153Sjmatthew #define TPO_HWCSUM_IP4CSUM_EN (1 << 1) 3565e728153Sjmatthew 357bccaee56Smlarkin #define THM_LSO_TCP_FLAG1_REG 0x7820 358bccaee56Smlarkin #define THM_LSO_TCP_FLAG1_FIRST 0xFFF 359bccaee56Smlarkin #define THM_LSO_TCP_FLAG1_MID 0xFFF0000 360bccaee56Smlarkin #define THM_LSO_TCP_FLAG2_REG 0x7824 361bccaee56Smlarkin #define THM_LSO_TCP_FLAG2_LAST 0xFFF 362bccaee56Smlarkin 363bccaee56Smlarkin #define TPB_TX_BUF_REG 0x7900 364bccaee56Smlarkin #define TPB_TX_BUF_EN (1 << 0) 365bccaee56Smlarkin #define TPB_TX_BUF_SCP_INS_EN (1 << 2) 366b760e38cSjmatthew #define TPB_TX_BUF_CLK_GATE_EN (1 << 5) 367bccaee56Smlarkin #define TPB_TX_BUF_TC_MODE_EN (1 << 8) 368bccaee56Smlarkin 369b760e38cSjmatthew 370bccaee56Smlarkin /* TPB_TXB_BUFSIZE_REG[AQ_TRAFFICCLASS_NUM] 0x7910-7990 */ 371bccaee56Smlarkin #define TPB_TXB_BUFSIZE_REG(i) (0x7910 + (i) * 0x10) 372bccaee56Smlarkin #define TPB_TXB_BUFSIZE (0xFF) 373bccaee56Smlarkin #define TPB_TXB_THRESH_REG(i) (0x7914 + (i) * 0x10) 374bccaee56Smlarkin #define TPB_TXB_THRESH_HI 0x1FFF0000 375bccaee56Smlarkin #define TPB_TXB_THRESH_LO 0x1FFF 376bccaee56Smlarkin 377bccaee56Smlarkin #define AQ_HW_TX_DMA_TOTAL_REQ_LIMIT_REG 0x7b20 378bccaee56Smlarkin 379bccaee56Smlarkin #define TX_DMA_INT_DESC_WRWB_EN_REG 0x7b40 380bccaee56Smlarkin #define TX_DMA_INT_DESC_WRWB_EN (1 << 1) 381bccaee56Smlarkin #define TX_DMA_INT_DESC_MODERATE_EN (1 << 4) 382bccaee56Smlarkin 383bccaee56Smlarkin #define TX_DMA_DESC_BASE_ADDRLSW_REG(i) (0x7c00 + (i) * 0x40) 384bccaee56Smlarkin #define TX_DMA_DESC_BASE_ADDRMSW_REG(i) (0x7c04 + (i) * 0x40) 385bccaee56Smlarkin #define TX_DMA_DESC_REG(i) (0x7c08 + (i) * 0x40) 386bccaee56Smlarkin #define TX_DMA_DESC_LEN 0x00000FF8 387bccaee56Smlarkin #define TX_DMA_DESC_EN 0x80000000 388bccaee56Smlarkin #define TX_DMA_DESC_HEAD_PTR_REG(i) (0x7c0c + (i) * 0x40) 389bccaee56Smlarkin #define TX_DMA_DESC_HEAD_PTR 0x00000FFF 390bccaee56Smlarkin #define TX_DMA_DESC_TAIL_PTR_REG(i) (0x7c10 + (i) * 0x40) 391bccaee56Smlarkin #define TX_DMA_DESC_WRWB_THRESH_REG(i) (0x7c18 + (i) * 0x40) 392bccaee56Smlarkin #define TX_DMA_DESC_WRWB_THRESH 0x00003F00 393bccaee56Smlarkin 394bccaee56Smlarkin #define TDM_DCAD_REG(i) (0x8400 + (i) * 4) 395bccaee56Smlarkin #define TDM_DCAD_CPUID 0x7F 396bccaee56Smlarkin #define TDM_DCAD_CPUID_EN 0x80000000 397bccaee56Smlarkin 398bccaee56Smlarkin #define TDM_DCA_REG 0x8480 399dcec61dcSmiod #define TDM_DCA_EN (1U << 31) 400bccaee56Smlarkin #define TDM_DCA_MODE 0xF 401bccaee56Smlarkin 402bccaee56Smlarkin #define TX_INTR_MODERATION_CTL_REG(i) (0x8980 + (i) * 4) 403bccaee56Smlarkin #define TX_INTR_MODERATION_CTL_EN (1 << 1) 4048c5cbf79Sjmatthew #define TX_INTR_MODERATION_CTL_MIN (0xFF << 8) 4058c5cbf79Sjmatthew #define TX_INTR_MODERATION_CTL_MAX (0x1FF << 16) 406bccaee56Smlarkin 407b760e38cSjmatthew /* AQ2 registers */ 408b760e38cSjmatthew 409b760e38cSjmatthew #define AQ2_MIF_HOST_FINISHED_STATUS_WRITE_REG 0x0e00 410b760e38cSjmatthew #define AQ2_MIF_HOST_FINISHED_STATUS_READ_REG 0x0e04 411b760e38cSjmatthew #define AQ2_MIF_HOST_FINISHED_STATUS_ACK (1 << 0) 412b760e38cSjmatthew 413b760e38cSjmatthew #define AQ2_MCP_HOST_REQ_INT_REG 0x0f00 414b760e38cSjmatthew #define AQ2_MCP_HOST_REQ_INT_READY (1 << 0) 415b760e38cSjmatthew #define AQ2_MCP_HOST_REQ_INT_SET_REG 0x0f04 416b760e38cSjmatthew #define AQ2_MCP_HOST_REQ_INT_CLR_REG 0x0f08 417b760e38cSjmatthew 418b760e38cSjmatthew #define AQ2_MIF_BOOT_REG 0x3040 419b760e38cSjmatthew #define AQ2_MIF_BOOT_HOST_DATA_LOADED (1 << 16) 420b760e38cSjmatthew #define AQ2_MIF_BOOT_BOOT_STARTED (1 << 24) 421b760e38cSjmatthew #define AQ2_MIF_BOOT_CRASH_INIT (1 << 27) 422b760e38cSjmatthew #define AQ2_MIF_BOOT_BOOT_CODE_FAILED (1 << 28) 423b760e38cSjmatthew #define AQ2_MIF_BOOT_FW_INIT_FAILED (1 << 29) 424dcec61dcSmiod #define AQ2_MIF_BOOT_FW_INIT_COMP_SUCCESS (1U << 31) 425b760e38cSjmatthew 426b760e38cSjmatthew /* AQ2 action resolver table */ 427b760e38cSjmatthew #define AQ2_ART_ACTION_ACT_SHIFT 8 428b760e38cSjmatthew #define AQ2_ART_ACTION_RSS 0x0080 429b760e38cSjmatthew #define AQ2_ART_ACTION_INDEX_SHIFT 2 430b760e38cSjmatthew #define AQ2_ART_ACTION_ENABLE 0x0001 431b760e38cSjmatthew #define AQ2_ART_ACTION(act, rss, idx, en) \ 432b760e38cSjmatthew (((act) << AQ2_ART_ACTION_ACT_SHIFT) | \ 433b760e38cSjmatthew ((rss) ? AQ2_ART_ACTION_RSS : 0) | \ 434b760e38cSjmatthew ((idx) << AQ2_ART_ACTION_INDEX_SHIFT) | \ 435b760e38cSjmatthew ((en) ? AQ2_ART_ACTION_ENABLE : 0)) 436b760e38cSjmatthew #define AQ2_ART_ACTION_DROP AQ2_ART_ACTION(0, 0, 0, 1) 437b760e38cSjmatthew #define AQ2_ART_ACTION_DISABLE AQ2_ART_ACTION(0, 0, 0, 0) 438b760e38cSjmatthew #define AQ2_ART_ACTION_ASSIGN_QUEUE(q) AQ2_ART_ACTION(1, 0, (q), 1) 439b760e38cSjmatthew #define AQ2_ART_ACTION_ASSIGN_TC(tc) AQ2_ART_ACTION(1, 1, (tc), 1) 440b760e38cSjmatthew 441b760e38cSjmatthew #define AQ2_RPF_TAG_PCP_MASK 0xe0000000 442b760e38cSjmatthew #define AQ2_RPF_TAG_PCP_SHIFT 29 443b760e38cSjmatthew #define AQ2_RPF_TAG_FLEX_MASK 0x18000000 444b760e38cSjmatthew #define AQ2_RPF_TAG_UNKNOWN_MASK 0x07000000 445b760e38cSjmatthew #define AQ2_RPF_TAG_L4_MASK 0x00e00000 446b760e38cSjmatthew #define AQ2_RPF_TAG_L3_V6_MASK 0x001c0000 447b760e38cSjmatthew #define AQ2_RPF_TAG_L3_V4_MASK 0x00038000 448b760e38cSjmatthew #define AQ2_RPF_TAG_UNTAG_MASK 0x00004000 449b760e38cSjmatthew #define AQ2_RPF_TAG_VLAN_MASK 0x00003c00 450b760e38cSjmatthew #define AQ2_RPF_TAG_ET_MASK 0x00000380 451b760e38cSjmatthew #define AQ2_RPF_TAG_ALLMC_MASK 0x00000040 452b760e38cSjmatthew #define AQ2_RPF_TAG_UC_MASK 0x0000002f 453b760e38cSjmatthew 454b760e38cSjmatthew /* index of aq2_filter_art_set() */ 455b760e38cSjmatthew #define AQ2_RPF_INDEX_L2_PROMISC_OFF 0 456b760e38cSjmatthew #define AQ2_RPF_INDEX_VLAN_PROMISC_OFF 1 457b760e38cSjmatthew #define AQ2_RPF_INDEX_L3L4_USER 8 458b760e38cSjmatthew #define AQ2_RPF_INDEX_ET_PCP_USER 24 459b760e38cSjmatthew #define AQ2_RPF_INDEX_VLAN_USER 40 460b760e38cSjmatthew #define AQ2_RPF_INDEX_PCP_TO_TC 56 461b760e38cSjmatthew 462b760e38cSjmatthew #define AQ2_RPF_L2BC_TAG_REG 0x50f0 463b760e38cSjmatthew #define AQ2_RPF_L2BC_TAG_MASK 0x0000003f 464b760e38cSjmatthew 465b760e38cSjmatthew #define AQ2_RPF_NEW_CTRL_REG 0x5104 466b760e38cSjmatthew #define AQ2_RPF_NEW_CTRL_ENABLE (1 << 11) 467b760e38cSjmatthew 468b760e38cSjmatthew #define AQ2_RPF_REDIR2_REG 0x54c8 469b760e38cSjmatthew #define AQ2_RPF_REDIR2_INDEX (1 << 12) 470b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE 0x00000100 471b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_NONE 0 472b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_IP (1 << 0) 473b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_TCP4 (1 << 1) 474b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_UDP4 (1 << 2) 475b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_IP6 (1 << 3) 476b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_TCP6 (1 << 4) 477b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_UDP6 (1 << 5) 478b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_IP6EX (1 << 6) 479b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_TCP6EX (1 << 7) 480b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_UDP6EX (1 << 8) 481b760e38cSjmatthew #define AQ2_RPF_REDIR2_HASHTYPE_ALL 0x00000100 482b760e38cSjmatthew 483b760e38cSjmatthew #define AQ2_RPF_REC_TAB_ENABLE_REG 0x6ff0 484b760e38cSjmatthew #define AQ2_RPF_REC_TAB_ENABLE_MASK 0x0000ffff 485b760e38cSjmatthew 486b760e38cSjmatthew #define AQ2_LAUNCHTIME_CTRL_REG 0x7a1c 487b760e38cSjmatthew #define AQ2_LAUNCHTIME_CTRL_RATIO 0x0000ff00 488b760e38cSjmatthew #define AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_QUARTER 4 489b760e38cSjmatthew #define AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_HALF 2 490b760e38cSjmatthew #define AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_FULL 1 491b760e38cSjmatthew 492b760e38cSjmatthew #define AQ2_TX_INTR_MODERATION_CTL_REG(i) (0x7c28 + (i) * 0x40) 493b760e38cSjmatthew #define AQ2_TX_INTR_MODERATION_CTL_EN (1 << 1) 494b760e38cSjmatthew #define AQ2_TX_INTR_MODERATION_CTL_MIN 0x0000ff00 495b760e38cSjmatthew #define AQ2_TX_INTR_MODERATION_CTL_MAX 0x01ff0000 496b760e38cSjmatthew 497b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_MTU_REG 0x12000 498b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_MAC_ADDRESS_REG 0x12008 499b760e38cSjmatthew 500b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_CONTROL_REG 0x12010 501b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE 0x0000000f 502b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_INVALID 0 503b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_ACTIVE 1 504b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_SLEEP_PROXY 2 505b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_LOWPOWER 3 506b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_SHUTDOWN 4 507b760e38cSjmatthew 508b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_REG 0x12018 509b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_DOWNSHIFT (1 << 27) 510b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_TX (1 << 25) 511b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_RX (1 << 24) 512b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_10G (1 << 20) 513b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_5G (1 << 19) 514b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_2G5 (1 << 18) 515b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_1G (1 << 17) 516b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_100M (1 << 16) 517b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10G (1 << 15) 518b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N5G (1 << 14) 519b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_5G (1 << 13) 520b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N2G5 (1 << 12) 521b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_2G5 (1 << 11) 522b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G (1 << 10) 523b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M (1 << 9) 524b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M (1 << 8) 525b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G_HD (1 << 7) 526b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M_HD (1 << 6) 527b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M_HD (1 << 5) 528b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EXTERNAL_LOOPBACK (1 << 4) 529b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_INTERNAL_LOOPBACK (1 << 3) 530b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_MINIMAL_LINK_SPEED (1 << 2) 531b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_LINK_RENEGOTIATE (1 << 1) 532b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_LINK_UP (1 << 0) 533b760e38cSjmatthew 534b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_REG 0x12a58 535b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_QUEUE_OR_TC 0x00800000 536b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_RX_QUEUE_TC_INDEX 0x007c0000 537b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_ACCEPT 0x00010000 538b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_QUEUE_OR_TC 0x00008000 539b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_RX_QUEUE_TC_INDEX 0x00007c00 540b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_ACCEPT 0x00000100 541b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_QUEUE_OR_TC 0x00000080 542b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_RX_QUEUE_TX_INDEX 0x0000007c 543b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_MCAST 0x00000002 544b760e38cSjmatthew #define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_ALL 0x00000001 545b760e38cSjmatthew 546b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_REG 0x13000 547b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_B 0xffff0000 548b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_B_S 16 549b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_A 0x0000ffff 550b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_A_S 0 551b760e38cSjmatthew 552b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_BUNDLE_REG 0x13004 553b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_MAC_REG 0x13008 554b760e38cSjmatthew 555b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_PHY_REG 0x1300c 556b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_BUILD 0xffff0000 557b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_BUILD_S 16 558b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_MINOR 0x0000ff00 559b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_MINOR_S 8 560b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_MAJOR 0x000000ff 561b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_MAJOR_S 0 562b760e38cSjmatthew 563b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_IFACE_REG 0x13010 564b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER 0x0000000f 565b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_A0 0 566b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_B0 1 567b760e38cSjmatthew 568b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_REG 0x13014 569b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_DUPLEX (1 << 11) 570b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_EEE (1 << 10) 571b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_PAUSE_RX (1 << 9) 572b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_PAUSE_TX (1 << 8) 573b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE 0x000000f0 574b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_S 4 575b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_10G 6 576b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_5G 5 577b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_2G5 4 578b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_1G 3 579b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_100M 2 580b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_10M 1 581b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_INVALID 0 582b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_LINK_STATUS_STATE 0x0000000f 583b760e38cSjmatthew 584b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_FILTER_CAPS_REG 0x13774 585b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_RESOLVER_BASE_INDEX 0x00ff0000 586b760e38cSjmatthew #define AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_RESOLVER_BASE_INDEX_SHIFT 16 587b760e38cSjmatthew 588b760e38cSjmatthew #define AQ2_RPF_ACT_ART_REQ_TAG_REG(i) (0x14000 + (i) * 0x10) 589b760e38cSjmatthew #define AQ2_RPF_ACT_ART_REQ_MASK_REG(i) (0x14004 + (i) * 0x10) 590b760e38cSjmatthew #define AQ2_RPF_ACT_ART_REQ_ACTION_REG(i) (0x14008 + (i) * 0x10) 591b760e38cSjmatthew 592bccaee56Smlarkin #define __LOWEST_SET_BIT(__mask) (((((uint32_t)__mask) - 1) & ((uint32_t)__mask)) ^ ((uint32_t)__mask)) 593bccaee56Smlarkin #define __SHIFTIN(__x, __mask) ((__x) * __LOWEST_SET_BIT(__mask)) 594bccaee56Smlarkin 595bccaee56Smlarkin #define AQ_READ_REG(sc, reg) \ 596bccaee56Smlarkin bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)) 597b760e38cSjmatthew #define AQ_READ_REGS(sc, reg, p, cnt) \ 598b760e38cSjmatthew bus_space_read_region_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (p), (cnt)); 599bccaee56Smlarkin 600bccaee56Smlarkin #define AQ_WRITE_REG(sc, reg, val) \ 601bccaee56Smlarkin bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 602bccaee56Smlarkin 603bccaee56Smlarkin #define AQ_WRITE_REG_BIT(sc, reg, mask, val) \ 604bccaee56Smlarkin do { \ 605bccaee56Smlarkin uint32_t _v; \ 606bccaee56Smlarkin _v = AQ_READ_REG((sc), (reg)); \ 607bccaee56Smlarkin _v &= ~(mask); \ 608bccaee56Smlarkin if ((val) != 0) \ 609bccaee56Smlarkin _v |= __SHIFTIN((val), (mask)); \ 610bccaee56Smlarkin AQ_WRITE_REG((sc), (reg), _v); \ 611bccaee56Smlarkin } while (/* CONSTCOND */ 0) 612bccaee56Smlarkin 613bccaee56Smlarkin #define AQ_READ64_REG(sc, reg) \ 614bccaee56Smlarkin ((uint64_t)AQ_READ_REG(sc, reg) | \ 615bccaee56Smlarkin (((uint64_t)AQ_READ_REG(sc, (reg) + 4)) << 32)) 616bccaee56Smlarkin 617bccaee56Smlarkin #define AQ_WRITE64_REG(sc, reg, val) \ 618bccaee56Smlarkin do { \ 619bccaee56Smlarkin AQ_WRITE_REG(sc, reg, (uint32_t)val); \ 620bccaee56Smlarkin AQ_WRITE_REG(sc, reg + 4, (uint32_t)(val >> 32)); \ 621bccaee56Smlarkin } while (/* CONSTCOND */0) 622bccaee56Smlarkin 623bccaee56Smlarkin #define WAIT_FOR(expr, us, n, errp) \ 624bccaee56Smlarkin do { \ 625bccaee56Smlarkin unsigned int _n; \ 626bccaee56Smlarkin for (_n = n; (!(expr)) && _n != 0; --_n) { \ 627bccaee56Smlarkin delay((us)); \ 628bccaee56Smlarkin } \ 629bccaee56Smlarkin if ((errp != NULL)) { \ 630bccaee56Smlarkin if (_n == 0) \ 631bccaee56Smlarkin *(errp) = ETIMEDOUT; \ 632bccaee56Smlarkin else \ 633bccaee56Smlarkin *(errp) = 0; \ 634bccaee56Smlarkin } \ 635bccaee56Smlarkin } while (/* CONSTCOND */ 0) 636bccaee56Smlarkin 637bccaee56Smlarkin #define FW_VERSION_MAJOR(sc) (((sc)->sc_fw_version >> 24) & 0xff) 638bccaee56Smlarkin #define FW_VERSION_MINOR(sc) (((sc)->sc_fw_version >> 16) & 0xff) 639bccaee56Smlarkin #define FW_VERSION_BUILD(sc) ((sc)->sc_fw_version & 0xffff) 640bccaee56Smlarkin 641bccaee56Smlarkin #define FEATURES_MIPS 0x00000001 642bccaee56Smlarkin #define FEATURES_TPO2 0x00000002 643bccaee56Smlarkin #define FEATURES_RPF2 0x00000004 644bccaee56Smlarkin #define FEATURES_MPI_AQ 0x00000008 64545994699Sjmatthew #define FEATURES_AQ1_REV_A0 0x01000000 64645994699Sjmatthew #define FEATURES_AQ1_REV_A (FEATURES_AQ1_REV_A0) 64745994699Sjmatthew #define FEATURES_AQ1_REV_B0 0x02000000 64845994699Sjmatthew #define FEATURES_AQ1_REV_B1 0x04000000 64945994699Sjmatthew #define FEATURES_AQ1_REV_B (FEATURES_AQ1_REV_B0|FEATURES_AQ1_REV_B1) 65045994699Sjmatthew #define FEATURES_AQ1 (FEATURES_AQ1_REV_A|FEATURES_AQ1_REV_B) 651b760e38cSjmatthew #define FEATURES_AQ2 0x10000000 652b760e38cSjmatthew #define FEATURES_AQ2_IFACE_A0 0x20000000 653b760e38cSjmatthew #define FEATURES_AQ2_IFACE_B0 0x40000000 65445994699Sjmatthew #define HWTYPE_AQ1_P(sc) (((sc)->sc_features & FEATURES_AQ1) != 0) 655b760e38cSjmatthew #define HWTYPE_AQ2_P(sc) (((sc)->sc_features & FEATURES_AQ2) != 0) 656bccaee56Smlarkin 65745994699Sjmatthew /* lock for firmware interface */ 658bccaee56Smlarkin #define AQ_MPI_LOCK(sc) mtx_enter(&(sc)->sc_mpi_mutex); 659bccaee56Smlarkin #define AQ_MPI_UNLOCK(sc) mtx_leave(&(sc)->sc_mpi_mutex); 660bccaee56Smlarkin 661bccaee56Smlarkin #define FW2X_CTRL_10BASET_HD (1 << 0) 662bccaee56Smlarkin #define FW2X_CTRL_10BASET_FD (1 << 1) 663bccaee56Smlarkin #define FW2X_CTRL_100BASETX_HD (1 << 2) 664bccaee56Smlarkin #define FW2X_CTRL_100BASET4_HD (1 << 3) 665bccaee56Smlarkin #define FW2X_CTRL_100BASET2_HD (1 << 4) 666bccaee56Smlarkin #define FW2X_CTRL_100BASETX_FD (1 << 5) 667bccaee56Smlarkin #define FW2X_CTRL_100BASET2_FD (1 << 6) 668bccaee56Smlarkin #define FW2X_CTRL_1000BASET_HD (1 << 7) 669bccaee56Smlarkin #define FW2X_CTRL_1000BASET_FD (1 << 8) 670bccaee56Smlarkin #define FW2X_CTRL_2P5GBASET_FD (1 << 9) 671bccaee56Smlarkin #define FW2X_CTRL_5GBASET_FD (1 << 10) 672bccaee56Smlarkin #define FW2X_CTRL_10GBASET_FD (1 << 11) 673bccaee56Smlarkin #define FW2X_CTRL_RESERVED1 (1ULL << 32) 674bccaee56Smlarkin #define FW2X_CTRL_10BASET_EEE (1ULL << 33) 675bccaee56Smlarkin #define FW2X_CTRL_RESERVED2 (1ULL << 34) 676bccaee56Smlarkin #define FW2X_CTRL_PAUSE (1ULL << 35) 677bccaee56Smlarkin #define FW2X_CTRL_ASYMMETRIC_PAUSE (1ULL << 36) 678bccaee56Smlarkin #define FW2X_CTRL_100BASETX_EEE (1ULL << 37) 679bccaee56Smlarkin #define FW2X_CTRL_RESERVED3 (1ULL << 38) 680bccaee56Smlarkin #define FW2X_CTRL_RESERVED4 (1ULL << 39) 681bccaee56Smlarkin #define FW2X_CTRL_1000BASET_FD_EEE (1ULL << 40) 682bccaee56Smlarkin #define FW2X_CTRL_2P5GBASET_FD_EEE (1ULL << 41) 683bccaee56Smlarkin #define FW2X_CTRL_5GBASET_FD_EEE (1ULL << 42) 684bccaee56Smlarkin #define FW2X_CTRL_10GBASET_FD_EEE (1ULL << 43) 685bccaee56Smlarkin #define FW2X_CTRL_RESERVED5 (1ULL << 44) 686bccaee56Smlarkin #define FW2X_CTRL_RESERVED6 (1ULL << 45) 687bccaee56Smlarkin #define FW2X_CTRL_RESERVED7 (1ULL << 46) 688bccaee56Smlarkin #define FW2X_CTRL_RESERVED8 (1ULL << 47) 689bccaee56Smlarkin #define FW2X_CTRL_RESERVED9 (1ULL << 48) 690bccaee56Smlarkin #define FW2X_CTRL_CABLE_DIAG (1ULL << 49) 691bccaee56Smlarkin #define FW2X_CTRL_TEMPERATURE (1ULL << 50) 692bccaee56Smlarkin #define FW2X_CTRL_DOWNSHIFT (1ULL << 51) 693bccaee56Smlarkin #define FW2X_CTRL_PTP_AVB_EN (1ULL << 52) 694bccaee56Smlarkin #define FW2X_CTRL_MEDIA_DETECT (1ULL << 53) 695bccaee56Smlarkin #define FW2X_CTRL_LINK_DROP (1ULL << 54) 696bccaee56Smlarkin #define FW2X_CTRL_SLEEP_PROXY (1ULL << 55) 697bccaee56Smlarkin #define FW2X_CTRL_WOL (1ULL << 56) 698bccaee56Smlarkin #define FW2X_CTRL_MAC_STOP (1ULL << 57) 699bccaee56Smlarkin #define FW2X_CTRL_EXT_LOOPBACK (1ULL << 58) 700bccaee56Smlarkin #define FW2X_CTRL_INT_LOOPBACK (1ULL << 59) 701bccaee56Smlarkin #define FW2X_CTRL_EFUSE_AGENT (1ULL << 60) 702bccaee56Smlarkin #define FW2X_CTRL_WOL_TIMER (1ULL << 61) 703bccaee56Smlarkin #define FW2X_CTRL_STATISTICS (1ULL << 62) 704bccaee56Smlarkin #define FW2X_CTRL_TRANSACTION_ID (1ULL << 63) 705bccaee56Smlarkin 706bccaee56Smlarkin #define FW2X_CTRL_RATE_100M FW2X_CTRL_100BASETX_FD 707bccaee56Smlarkin #define FW2X_CTRL_RATE_1G FW2X_CTRL_1000BASET_FD 708bccaee56Smlarkin #define FW2X_CTRL_RATE_2G5 FW2X_CTRL_2P5GBASET_FD 709bccaee56Smlarkin #define FW2X_CTRL_RATE_5G FW2X_CTRL_5GBASET_FD 710bccaee56Smlarkin #define FW2X_CTRL_RATE_10G FW2X_CTRL_10GBASET_FD 711bccaee56Smlarkin #define FW2X_CTRL_RATE_MASK \ 712bccaee56Smlarkin (FW2X_CTRL_RATE_100M | \ 713bccaee56Smlarkin FW2X_CTRL_RATE_1G | \ 714bccaee56Smlarkin FW2X_CTRL_RATE_2G5 | \ 715bccaee56Smlarkin FW2X_CTRL_RATE_5G | \ 716bccaee56Smlarkin FW2X_CTRL_RATE_10G) 717bccaee56Smlarkin #define FW2X_CTRL_EEE_MASK \ 718bccaee56Smlarkin (FW2X_CTRL_10BASET_EEE | \ 719bccaee56Smlarkin FW2X_CTRL_100BASETX_EEE | \ 720bccaee56Smlarkin FW2X_CTRL_1000BASET_FD_EEE | \ 721bccaee56Smlarkin FW2X_CTRL_2P5GBASET_FD_EEE | \ 722bccaee56Smlarkin FW2X_CTRL_5GBASET_FD_EEE | \ 723bccaee56Smlarkin FW2X_CTRL_10GBASET_FD_EEE) 724bccaee56Smlarkin 72545994699Sjmatthew enum aq_hwtype { 72645994699Sjmatthew HWTYPE_AQ1, 727b760e38cSjmatthew HWTYPE_AQ2 72845994699Sjmatthew }; 72945994699Sjmatthew 730bccaee56Smlarkin enum aq_fw_bootloader_mode { 731bccaee56Smlarkin FW_BOOT_MODE_UNKNOWN = 0, 732bccaee56Smlarkin FW_BOOT_MODE_FLB, 733bccaee56Smlarkin FW_BOOT_MODE_RBL_FLASH, 734bccaee56Smlarkin FW_BOOT_MODE_RBL_HOST_BOOTLOAD 735bccaee56Smlarkin }; 736bccaee56Smlarkin 737bccaee56Smlarkin enum aq_media_type { 738bccaee56Smlarkin AQ_MEDIA_TYPE_UNKNOWN = 0, 739bccaee56Smlarkin AQ_MEDIA_TYPE_FIBRE, 740bccaee56Smlarkin AQ_MEDIA_TYPE_TP 741bccaee56Smlarkin }; 742bccaee56Smlarkin 743bccaee56Smlarkin enum aq_link_speed { 744bccaee56Smlarkin AQ_LINK_NONE = 0, 745b760e38cSjmatthew AQ_LINK_10M = (1 << 0), 746b760e38cSjmatthew AQ_LINK_100M = (1 << 1), 747b760e38cSjmatthew AQ_LINK_1G = (1 << 2), 748b760e38cSjmatthew AQ_LINK_2G5 = (1 << 3), 749b760e38cSjmatthew AQ_LINK_5G = (1 << 4), 750b760e38cSjmatthew AQ_LINK_10G = (1 << 5) 751bccaee56Smlarkin }; 752bccaee56Smlarkin 753bccaee56Smlarkin #define AQ_LINK_ALL (AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | \ 754bccaee56Smlarkin AQ_LINK_5G | AQ_LINK_10G ) 755bccaee56Smlarkin #define AQ_LINK_AUTO AQ_LINK_ALL 756bccaee56Smlarkin 757bccaee56Smlarkin enum aq_link_eee { 758bccaee56Smlarkin AQ_EEE_DISABLE = 0, 759bccaee56Smlarkin AQ_EEE_ENABLE = 1 760bccaee56Smlarkin }; 761bccaee56Smlarkin 762bccaee56Smlarkin enum aq_hw_fw_mpi_state { 763bccaee56Smlarkin MPI_DEINIT = 0, 764bccaee56Smlarkin MPI_RESET = 1, 765bccaee56Smlarkin MPI_INIT = 2, 766bccaee56Smlarkin MPI_POWER = 4 767bccaee56Smlarkin }; 768bccaee56Smlarkin 769bccaee56Smlarkin enum aq_link_fc { 770bccaee56Smlarkin AQ_FC_NONE = 0, 771bccaee56Smlarkin AQ_FC_RX = (1 << 0), 772bccaee56Smlarkin AQ_FC_TX = (1 << 1), 773bccaee56Smlarkin AQ_FC_ALL = (AQ_FC_RX | AQ_FC_TX) 774bccaee56Smlarkin }; 775bccaee56Smlarkin 776bccaee56Smlarkin struct aq_dmamem { 777bccaee56Smlarkin bus_dmamap_t aqm_map; 778bccaee56Smlarkin bus_dma_segment_t aqm_seg; 779bccaee56Smlarkin int aqm_nsegs; 780bccaee56Smlarkin size_t aqm_size; 781bccaee56Smlarkin caddr_t aqm_kva; 782bccaee56Smlarkin }; 783bccaee56Smlarkin 784bccaee56Smlarkin #define AQ_DMA_MAP(_aqm) ((_aqm)->aqm_map) 785bccaee56Smlarkin #define AQ_DMA_DVA(_aqm) ((_aqm)->aqm_map->dm_segs[0].ds_addr) 786bccaee56Smlarkin #define AQ_DMA_KVA(_aqm) ((void *)(_aqm)->aqm_kva) 787bccaee56Smlarkin #define AQ_DMA_LEN(_aqm) ((_aqm)->aqm_size) 788bccaee56Smlarkin 789bccaee56Smlarkin 790bccaee56Smlarkin struct aq_mailbox_header { 791bccaee56Smlarkin uint32_t version; 792bccaee56Smlarkin uint32_t transaction_id; 793bccaee56Smlarkin int32_t error; 794bccaee56Smlarkin } __packed __aligned(4); 795bccaee56Smlarkin 796bccaee56Smlarkin struct aq_hw_stats_s { 797bccaee56Smlarkin uint32_t uprc; 798bccaee56Smlarkin uint32_t mprc; 799bccaee56Smlarkin uint32_t bprc; 800bccaee56Smlarkin uint32_t erpt; 801bccaee56Smlarkin uint32_t uptc; 802bccaee56Smlarkin uint32_t mptc; 803bccaee56Smlarkin uint32_t bptc; 804bccaee56Smlarkin uint32_t erpr; 805bccaee56Smlarkin uint32_t mbtc; 806bccaee56Smlarkin uint32_t bbtc; 807bccaee56Smlarkin uint32_t mbrc; 808bccaee56Smlarkin uint32_t bbrc; 809bccaee56Smlarkin uint32_t ubrc; 810bccaee56Smlarkin uint32_t ubtc; 811bccaee56Smlarkin uint32_t ptc; 812bccaee56Smlarkin uint32_t prc; 813bccaee56Smlarkin uint32_t dpc; /* not exists in fw2x_msm_statistics */ 814bccaee56Smlarkin uint32_t cprc; /* not exists in fw2x_msm_statistics */ 815bccaee56Smlarkin } __packed __aligned(4); 816bccaee56Smlarkin 817bccaee56Smlarkin struct aq_fw2x_capabilities { 818bccaee56Smlarkin uint32_t caps_lo; 819bccaee56Smlarkin uint32_t caps_hi; 820bccaee56Smlarkin } __packed __aligned(4); 821bccaee56Smlarkin 822bccaee56Smlarkin struct aq_fw2x_msm_statistics { 823bccaee56Smlarkin uint32_t uprc; 824bccaee56Smlarkin uint32_t mprc; 825bccaee56Smlarkin uint32_t bprc; 826bccaee56Smlarkin uint32_t erpt; 827bccaee56Smlarkin uint32_t uptc; 828bccaee56Smlarkin uint32_t mptc; 829bccaee56Smlarkin uint32_t bptc; 830bccaee56Smlarkin uint32_t erpr; 831bccaee56Smlarkin uint32_t mbtc; 832bccaee56Smlarkin uint32_t bbtc; 833bccaee56Smlarkin uint32_t mbrc; 834bccaee56Smlarkin uint32_t bbrc; 835bccaee56Smlarkin uint32_t ubrc; 836bccaee56Smlarkin uint32_t ubtc; 837bccaee56Smlarkin uint32_t ptc; 838bccaee56Smlarkin uint32_t prc; 839bccaee56Smlarkin } __packed __aligned(4); 840bccaee56Smlarkin 841bccaee56Smlarkin struct aq_fw2x_phy_cable_diag_data { 842bccaee56Smlarkin uint32_t lane_data[4]; 843bccaee56Smlarkin } __packed __aligned(4); 844bccaee56Smlarkin 845bccaee56Smlarkin struct aq_fw2x_mailbox { /* struct fwHostInterface */ 846bccaee56Smlarkin struct aq_mailbox_header header; 847bccaee56Smlarkin struct aq_fw2x_msm_statistics msm; /* msmStatistics_t msm; */ 848bccaee56Smlarkin 849bccaee56Smlarkin uint32_t phy_info1; 850bccaee56Smlarkin #define PHYINFO1_FAULT_CODE __BITS(31,16) 851bccaee56Smlarkin #define PHYINFO1_PHY_H_BIT __BITS(0,15) 852bccaee56Smlarkin uint32_t phy_info2; 853bccaee56Smlarkin #define PHYINFO2_TEMPERATURE __BITS(15,0) 854bccaee56Smlarkin #define PHYINFO2_CABLE_LEN __BITS(23,16) 855bccaee56Smlarkin 856bccaee56Smlarkin struct aq_fw2x_phy_cable_diag_data diag_data; 857bccaee56Smlarkin uint32_t reserved[8]; 858bccaee56Smlarkin 859bccaee56Smlarkin struct aq_fw2x_capabilities caps; 860bccaee56Smlarkin 861bccaee56Smlarkin /* ... */ 862bccaee56Smlarkin } __packed __aligned(4); 863bccaee56Smlarkin 864bccaee56Smlarkin struct aq_rx_desc_read { 865bccaee56Smlarkin uint64_t buf_addr; 866bccaee56Smlarkin uint64_t hdr_addr; 867bccaee56Smlarkin } __packed; 868bccaee56Smlarkin 869bccaee56Smlarkin struct aq_rx_desc_wb { 870bccaee56Smlarkin uint32_t type; 871bccaee56Smlarkin #define AQ_RXDESC_TYPE_RSSTYPE 0x000f 872bccaee56Smlarkin #define AQ_RXDESC_TYPE_ETHER 0x0030 873bccaee56Smlarkin #define AQ_RXDESC_TYPE_PROTO 0x01c0 874bccaee56Smlarkin #define AQ_RXDESC_TYPE_VLAN (1 << 9) 875bccaee56Smlarkin #define AQ_RXDESC_TYPE_VLAN2 (1 << 10) 876bccaee56Smlarkin #define AQ_RXDESC_TYPE_DMA_ERR (1 << 12) 877bccaee56Smlarkin #define AQ_RXDESC_TYPE_V4_SUM (1 << 19) 8785e728153Sjmatthew #define AQ_RXDESC_TYPE_L4_SUM (1 << 20) 879bccaee56Smlarkin uint32_t rss_hash; 880bccaee56Smlarkin uint16_t status; 881bccaee56Smlarkin #define AQ_RXDESC_STATUS_DD (1 << 0) 882bccaee56Smlarkin #define AQ_RXDESC_STATUS_EOP (1 << 1) 883bccaee56Smlarkin #define AQ_RXDESC_STATUS_MACERR (1 << 2) 8845e728153Sjmatthew #define AQ_RXDESC_STATUS_V4_SUM_NG (1 << 3) 885bccaee56Smlarkin #define AQ_RXDESC_STATUS_L4_SUM_ERR (1 << 4) 886bccaee56Smlarkin #define AQ_RXDESC_STATUS_L4_SUM_OK (1 << 5) 887bccaee56Smlarkin uint16_t pkt_len; 888bccaee56Smlarkin uint16_t next_desc_ptr; 889bccaee56Smlarkin uint16_t vlan; 890bccaee56Smlarkin } __packed; 891bccaee56Smlarkin 892bccaee56Smlarkin struct aq_tx_desc { 893bccaee56Smlarkin uint64_t buf_addr; 894bccaee56Smlarkin uint32_t ctl1; 895bccaee56Smlarkin #define AQ_TXDESC_CTL1_TYPE_TXD 0x00000001 896bccaee56Smlarkin #define AQ_TXDESC_CTL1_TYPE_TXC 0x00000002 897bccaee56Smlarkin #define AQ_TXDESC_CTL1_BLEN_SHIFT 4 89831f14b89Sjmatthew #define AQ_TXDESC_CTL1_VLAN_SHIFT 4 899bccaee56Smlarkin #define AQ_TXDESC_CTL1_DD (1 << 20) 900bccaee56Smlarkin #define AQ_TXDESC_CTL1_CMD_EOP (1 << 21) 901bccaee56Smlarkin #define AQ_TXDESC_CTL1_CMD_VLAN (1 << 22) 902bccaee56Smlarkin #define AQ_TXDESC_CTL1_CMD_FCS (1 << 23) 903bccaee56Smlarkin #define AQ_TXDESC_CTL1_CMD_IP4CSUM (1 << 24) 904bccaee56Smlarkin #define AQ_TXDESC_CTL1_CMD_L4CSUM (1 << 25) 905bccaee56Smlarkin #define AQ_TXDESC_CTL1_CMD_WB (1 << 27) 906bccaee56Smlarkin 907bccaee56Smlarkin #define AQ_TXDESC_CTL1_VID_SHIFT 4 908bccaee56Smlarkin uint32_t ctl2; 909bccaee56Smlarkin #define AQ_TXDESC_CTL2_LEN_SHIFT 14 910bccaee56Smlarkin #define AQ_TXDESC_CTL2_CTX_EN (1 << 13) 911bccaee56Smlarkin } __packed; 912bccaee56Smlarkin 913bccaee56Smlarkin struct aq_slot { 914bccaee56Smlarkin bus_dmamap_t as_map; 915bccaee56Smlarkin struct mbuf *as_m; 916bccaee56Smlarkin }; 917bccaee56Smlarkin 918bccaee56Smlarkin struct aq_rxring { 919bccaee56Smlarkin struct ifiqueue *rx_ifiq; 920bccaee56Smlarkin struct aq_dmamem rx_mem; 921bccaee56Smlarkin struct aq_slot *rx_slots; 922bccaee56Smlarkin int rx_q; 923bccaee56Smlarkin int rx_irq; 924bccaee56Smlarkin 925bccaee56Smlarkin struct timeout rx_refill; 926bccaee56Smlarkin struct if_rxring rx_rxr; 927bccaee56Smlarkin uint32_t rx_prod; 928bccaee56Smlarkin uint32_t rx_cons; 9290425cdaeSjmatthew 9300425cdaeSjmatthew struct mbuf *rx_m_head; 9310425cdaeSjmatthew struct mbuf **rx_m_tail; 9320425cdaeSjmatthew int rx_m_error; 933bccaee56Smlarkin }; 934bccaee56Smlarkin 935bccaee56Smlarkin struct aq_txring { 936bccaee56Smlarkin struct ifqueue *tx_ifq; 937bccaee56Smlarkin struct aq_dmamem tx_mem; 938bccaee56Smlarkin struct aq_slot *tx_slots; 939bccaee56Smlarkin int tx_q; 940bccaee56Smlarkin int tx_irq; 941bccaee56Smlarkin uint32_t tx_prod; 942bccaee56Smlarkin uint32_t tx_cons; 943bccaee56Smlarkin }; 944bccaee56Smlarkin 945bccaee56Smlarkin struct aq_queues { 946bccaee56Smlarkin char q_name[16]; 947bccaee56Smlarkin void *q_ihc; 948bccaee56Smlarkin struct aq_softc *q_sc; 949bccaee56Smlarkin int q_index; 950bccaee56Smlarkin struct aq_rxring q_rx; 951bccaee56Smlarkin struct aq_txring q_tx; 952bccaee56Smlarkin }; 953bccaee56Smlarkin 954bccaee56Smlarkin 955bccaee56Smlarkin struct aq_softc; 956bccaee56Smlarkin struct aq_firmware_ops { 957bccaee56Smlarkin int (*reset)(struct aq_softc *); 95845994699Sjmatthew int (*get_mac_addr)(struct aq_softc *); 959bccaee56Smlarkin int (*set_mode)(struct aq_softc *, enum aq_hw_fw_mpi_state, 960bccaee56Smlarkin enum aq_link_speed, enum aq_link_fc, enum aq_link_eee); 961bccaee56Smlarkin int (*get_mode)(struct aq_softc *, enum aq_hw_fw_mpi_state *, 962bccaee56Smlarkin enum aq_link_speed *, enum aq_link_fc *, enum aq_link_eee *); 963bccaee56Smlarkin int (*get_stats)(struct aq_softc *, struct aq_hw_stats_s *); 964bccaee56Smlarkin }; 965bccaee56Smlarkin 966bccaee56Smlarkin struct aq_softc { 967bccaee56Smlarkin struct device sc_dev; 968bccaee56Smlarkin uint16_t sc_product; 969bccaee56Smlarkin uint16_t sc_revision; 970bccaee56Smlarkin bus_dma_tag_t sc_dmat; 971bccaee56Smlarkin pci_chipset_tag_t sc_pc; 972bccaee56Smlarkin pcitag_t sc_pcitag; 973bccaee56Smlarkin int sc_nqueues; 974bccaee56Smlarkin struct aq_queues sc_queues[AQ_MAXQ]; 975bccaee56Smlarkin struct intrmap *sc_intrmap; 976bccaee56Smlarkin void *sc_ih; 977bccaee56Smlarkin bus_space_handle_t sc_ioh; 978bccaee56Smlarkin bus_space_tag_t sc_iot; 979bccaee56Smlarkin 980bccaee56Smlarkin uint32_t sc_mbox_addr; 981bccaee56Smlarkin int sc_rbl_enabled; 982bccaee56Smlarkin int sc_fast_start_enabled; 983bccaee56Smlarkin int sc_flash_present; 984b760e38cSjmatthew int sc_art_filter_base_index; 985bccaee56Smlarkin uint32_t sc_fw_version; 986bccaee56Smlarkin const struct aq_firmware_ops *sc_fw_ops; 987bccaee56Smlarkin uint64_t sc_fw_caps; 988bccaee56Smlarkin enum aq_media_type sc_media_type; 989bccaee56Smlarkin enum aq_link_speed sc_available_rates; 990bccaee56Smlarkin uint32_t sc_features; 991bccaee56Smlarkin int sc_linkstat_irq; 992bccaee56Smlarkin struct arpcom sc_arpcom; 993bccaee56Smlarkin struct ifmedia sc_media; 994bccaee56Smlarkin 995bccaee56Smlarkin struct ether_addr sc_enaddr; 996bccaee56Smlarkin struct mutex sc_mpi_mutex; 997bccaee56Smlarkin }; 998bccaee56Smlarkin 999bccaee56Smlarkin const struct pci_matchid aq_devices[] = { 1000bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC100 }, 1001bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC107 }, 1002bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC108 }, 1003bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC109 }, 1004bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC111 }, 1005bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC112 }, 1006b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113 }, 1007b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113C }, 1008b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113CA }, 1009b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113CS }, 1010b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC114CS }, 1011b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC115C }, 1012b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC116C }, 1013bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC100S }, 1014bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC107S }, 1015bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC108S }, 1016bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC109S }, 1017bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC111S }, 1018bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC112S }, 1019bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D100 }, 1020bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D107 }, 1021bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D108 }, 1022bccaee56Smlarkin { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D109 }, 1023bccaee56Smlarkin }; 1024bccaee56Smlarkin 1025bccaee56Smlarkin const struct aq_product { 1026bccaee56Smlarkin pci_vendor_id_t aq_vendor; 1027bccaee56Smlarkin pci_product_id_t aq_product; 102845994699Sjmatthew enum aq_hwtype aq_hwtype; 1029bccaee56Smlarkin enum aq_media_type aq_media_type; 1030bccaee56Smlarkin enum aq_link_speed aq_available_rates; 1031bccaee56Smlarkin } aq_products[] = { 103245994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC100, HWTYPE_AQ1, 1033bccaee56Smlarkin AQ_MEDIA_TYPE_FIBRE, AQ_LINK_ALL 1034bccaee56Smlarkin }, 103545994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC107, HWTYPE_AQ1, 1036bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_ALL 1037bccaee56Smlarkin }, 103845994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC108, HWTYPE_AQ1, 1039bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G 1040bccaee56Smlarkin }, 104145994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC109, HWTYPE_AQ1, 1042bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 1043bccaee56Smlarkin }, 104445994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC111, HWTYPE_AQ1, 1045bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G 1046bccaee56Smlarkin }, 104745994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC112, HWTYPE_AQ1, 1048bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 1049bccaee56Smlarkin }, 105045994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC100S, HWTYPE_AQ1, 1051bccaee56Smlarkin AQ_MEDIA_TYPE_FIBRE, AQ_LINK_ALL 1052bccaee56Smlarkin }, 105345994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC107S, HWTYPE_AQ1, 1054bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_ALL 1055bccaee56Smlarkin }, 105645994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC108S, HWTYPE_AQ1, 1057bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G 1058bccaee56Smlarkin }, 105945994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC109S, HWTYPE_AQ1, 1060bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 1061bccaee56Smlarkin }, 106245994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC111S, HWTYPE_AQ1, 1063bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G 1064bccaee56Smlarkin }, 106545994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC112S, HWTYPE_AQ1, 1066bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 1067bccaee56Smlarkin }, 106845994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D100, HWTYPE_AQ1, 1069bccaee56Smlarkin AQ_MEDIA_TYPE_FIBRE, AQ_LINK_ALL 1070bccaee56Smlarkin }, 107145994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D107, HWTYPE_AQ1, 1072bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_ALL 1073bccaee56Smlarkin }, 107445994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D108, HWTYPE_AQ1, 1075bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G 1076bccaee56Smlarkin }, 107745994699Sjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D109, HWTYPE_AQ1, 1078bccaee56Smlarkin AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 107945994699Sjmatthew }, 1080b760e38cSjmatthew 1081b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113, HWTYPE_AQ2, 1082b760e38cSjmatthew AQ_MEDIA_TYPE_TP, AQ_LINK_ALL | AQ_LINK_10M 1083b760e38cSjmatthew }, 1084b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113C, HWTYPE_AQ2, 1085b760e38cSjmatthew AQ_MEDIA_TYPE_TP, AQ_LINK_ALL | AQ_LINK_10M 1086b760e38cSjmatthew }, 1087b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113CA, HWTYPE_AQ2, 1088b760e38cSjmatthew AQ_MEDIA_TYPE_TP, AQ_LINK_ALL | AQ_LINK_10M 1089b760e38cSjmatthew }, 1090b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113CS, HWTYPE_AQ2, 1091b760e38cSjmatthew AQ_MEDIA_TYPE_TP, AQ_LINK_ALL | AQ_LINK_10M 1092b760e38cSjmatthew }, 1093b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC114CS, HWTYPE_AQ2, 1094b760e38cSjmatthew AQ_MEDIA_TYPE_TP, 1095b760e38cSjmatthew AQ_LINK_10M | AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G 1096b760e38cSjmatthew }, 1097b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC115C, HWTYPE_AQ2, 1098b760e38cSjmatthew AQ_MEDIA_TYPE_TP, 1099b760e38cSjmatthew AQ_LINK_10M | AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 1100b760e38cSjmatthew }, 1101b760e38cSjmatthew { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC116C, HWTYPE_AQ2, 1102b760e38cSjmatthew AQ_MEDIA_TYPE_TP, AQ_LINK_10M | AQ_LINK_100M | AQ_LINK_1G 1103b760e38cSjmatthew }, 1104bccaee56Smlarkin }; 1105bccaee56Smlarkin 1106bccaee56Smlarkin int aq_match(struct device *, void *, void *); 1107bccaee56Smlarkin void aq_attach(struct device *, struct device *, void *); 1108bccaee56Smlarkin int aq_activate(struct device *, int); 1109bccaee56Smlarkin int aq_intr(void *); 11101d7ac227Sjmatthew int aq_intr_link(void *); 11111d7ac227Sjmatthew int aq_intr_queue(void *); 1112190bcc8eSjmatthew int aq_init_rss(struct aq_softc *); 1113bccaee56Smlarkin int aq_hw_reset(struct aq_softc *); 11141d7ac227Sjmatthew int aq_hw_init(struct aq_softc *, int, int); 1115bccaee56Smlarkin void aq_hw_qos_set(struct aq_softc *); 1116bccaee56Smlarkin void aq_hw_init_tx_path(struct aq_softc *); 1117bccaee56Smlarkin void aq_hw_init_rx_path(struct aq_softc *); 1118bccaee56Smlarkin int aq_set_mac_addr(struct aq_softc *, int, uint8_t *); 1119bccaee56Smlarkin int aq_set_linkmode(struct aq_softc *, enum aq_link_speed, 1120bccaee56Smlarkin enum aq_link_fc, enum aq_link_eee); 1121bccaee56Smlarkin void aq_watchdog(struct ifnet *); 1122bccaee56Smlarkin void aq_enable_intr(struct aq_softc *, int, int); 11239f7de937Sjmatthew int aq_rxrinfo(struct aq_softc *, struct if_rxrinfo *); 1124bccaee56Smlarkin int aq_ioctl(struct ifnet *, u_long, caddr_t); 1125bccaee56Smlarkin int aq_up(struct aq_softc *); 1126bccaee56Smlarkin void aq_down(struct aq_softc *); 1127bccaee56Smlarkin void aq_iff(struct aq_softc *); 1128bccaee56Smlarkin void aq_start(struct ifqueue *); 1129bccaee56Smlarkin void aq_ifmedia_status(struct ifnet *, struct ifmediareq *); 1130bccaee56Smlarkin int aq_ifmedia_change(struct ifnet *); 1131bccaee56Smlarkin void aq_update_link_status(struct aq_softc *); 1132bccaee56Smlarkin 113345994699Sjmatthew int aq1_fw_reboot(struct aq_softc *); 113445994699Sjmatthew int aq1_fw_read_version(struct aq_softc *); 113545994699Sjmatthew int aq1_fw_version_init(struct aq_softc *); 113645994699Sjmatthew int aq1_hw_init_ucp(struct aq_softc *); 113745994699Sjmatthew void aq1_global_software_reset(struct aq_softc *); 113845994699Sjmatthew int aq1_mac_soft_reset(struct aq_softc *, enum aq_fw_bootloader_mode *); 113945994699Sjmatthew int aq1_mac_soft_reset_rbl(struct aq_softc *, enum aq_fw_bootloader_mode *); 114045994699Sjmatthew int aq1_mac_soft_reset_flb(struct aq_softc *); 114145994699Sjmatthew int aq1_fw_downld_dwords(struct aq_softc *, uint32_t, uint32_t *, uint32_t); 114245994699Sjmatthew 1143b760e38cSjmatthew int aq2_interface_buffer_read(struct aq_softc *, uint32_t, uint32_t *, 1144b760e38cSjmatthew uint32_t); 1145b760e38cSjmatthew int aq2_fw_reboot(struct aq_softc *); 1146b760e38cSjmatthew int aq2_filter_art_set(struct aq_softc *, uint32_t, uint32_t, uint32_t, 1147b760e38cSjmatthew uint32_t action); 1148b760e38cSjmatthew 1149bccaee56Smlarkin void aq_refill(void *); 1150bccaee56Smlarkin int aq_rx_fill(struct aq_softc *, struct aq_rxring *); 1151bccaee56Smlarkin static inline unsigned int aq_rx_fill_slots(struct aq_softc *, 1152bccaee56Smlarkin struct aq_rxring *, uint); 1153bccaee56Smlarkin 1154bccaee56Smlarkin int aq_dmamem_alloc(struct aq_softc *, struct aq_dmamem *, 1155bccaee56Smlarkin bus_size_t, u_int); 1156bccaee56Smlarkin void aq_dmamem_free(struct aq_softc *, struct aq_dmamem *); 1157bccaee56Smlarkin 115845994699Sjmatthew int aq1_get_mac_addr(struct aq_softc *); 115945994699Sjmatthew 1160bccaee56Smlarkin int aq_fw1x_reset(struct aq_softc *); 1161bccaee56Smlarkin int aq_fw1x_get_mode(struct aq_softc *, enum aq_hw_fw_mpi_state *, 1162bccaee56Smlarkin enum aq_link_speed *, enum aq_link_fc *, enum aq_link_eee *); 1163bccaee56Smlarkin int aq_fw1x_set_mode(struct aq_softc *, enum aq_hw_fw_mpi_state, 1164bccaee56Smlarkin enum aq_link_speed, enum aq_link_fc, enum aq_link_eee); 1165bccaee56Smlarkin int aq_fw1x_get_stats(struct aq_softc *, struct aq_hw_stats_s *); 1166bccaee56Smlarkin 1167bccaee56Smlarkin int aq_fw2x_reset(struct aq_softc *); 1168bccaee56Smlarkin int aq_fw2x_get_mode(struct aq_softc *, enum aq_hw_fw_mpi_state *, 1169bccaee56Smlarkin enum aq_link_speed *, enum aq_link_fc *, enum aq_link_eee *); 1170bccaee56Smlarkin int aq_fw2x_set_mode(struct aq_softc *, enum aq_hw_fw_mpi_state, 1171bccaee56Smlarkin enum aq_link_speed, enum aq_link_fc, enum aq_link_eee); 1172bccaee56Smlarkin int aq_fw2x_get_stats(struct aq_softc *, struct aq_hw_stats_s *); 1173bccaee56Smlarkin 1174b760e38cSjmatthew int aq2_fw_reset(struct aq_softc *); 1175b760e38cSjmatthew int aq2_get_mac_addr(struct aq_softc *); 1176b760e38cSjmatthew int aq2_fw_get_mode(struct aq_softc *, enum aq_hw_fw_mpi_state *, 1177b760e38cSjmatthew enum aq_link_speed *, enum aq_link_fc *, enum aq_link_eee *); 1178b760e38cSjmatthew int aq2_fw_set_mode(struct aq_softc *, enum aq_hw_fw_mpi_state, 1179b760e38cSjmatthew enum aq_link_speed, enum aq_link_fc, enum aq_link_eee); 1180b760e38cSjmatthew int aq2_fw_get_stats(struct aq_softc *, struct aq_hw_stats_s *); 1181b760e38cSjmatthew 1182bccaee56Smlarkin const struct aq_firmware_ops aq_fw1x_ops = { 1183bccaee56Smlarkin .reset = aq_fw1x_reset, 118445994699Sjmatthew .get_mac_addr = aq1_get_mac_addr, 1185bccaee56Smlarkin .set_mode = aq_fw1x_set_mode, 1186bccaee56Smlarkin .get_mode = aq_fw1x_get_mode, 1187bccaee56Smlarkin .get_stats = aq_fw1x_get_stats, 1188bccaee56Smlarkin }; 1189bccaee56Smlarkin 1190bccaee56Smlarkin const struct aq_firmware_ops aq_fw2x_ops = { 1191bccaee56Smlarkin .reset = aq_fw2x_reset, 119245994699Sjmatthew .get_mac_addr = aq1_get_mac_addr, 1193bccaee56Smlarkin .set_mode = aq_fw2x_set_mode, 1194bccaee56Smlarkin .get_mode = aq_fw2x_get_mode, 1195bccaee56Smlarkin .get_stats = aq_fw2x_get_stats, 1196bccaee56Smlarkin }; 1197bccaee56Smlarkin 1198b760e38cSjmatthew const struct aq_firmware_ops aq2_fw_ops = { 1199b760e38cSjmatthew .reset = aq2_fw_reset, 1200b760e38cSjmatthew .get_mac_addr = aq2_get_mac_addr, 1201b760e38cSjmatthew .set_mode = aq2_fw_set_mode, 1202b760e38cSjmatthew .get_mode = aq2_fw_get_mode, 1203b760e38cSjmatthew .get_stats = aq2_fw_get_stats 1204b760e38cSjmatthew }; 1205b760e38cSjmatthew 1206471aeecfSnaddy const struct cfattach aq_ca = { 1207bccaee56Smlarkin sizeof(struct aq_softc), aq_match, aq_attach, NULL, 1208bccaee56Smlarkin aq_activate 1209bccaee56Smlarkin }; 1210bccaee56Smlarkin 1211bccaee56Smlarkin struct cfdriver aq_cd = { 1212bccaee56Smlarkin NULL, "aq", DV_IFNET 1213bccaee56Smlarkin }; 1214bccaee56Smlarkin 1215bccaee56Smlarkin int 1216bccaee56Smlarkin aq_match(struct device *dev, void *match, void *aux) 1217bccaee56Smlarkin { 1218bccaee56Smlarkin return pci_matchbyid((struct pci_attach_args *)aux, aq_devices, 1219bccaee56Smlarkin sizeof(aq_devices) / sizeof(aq_devices[0])); 1220bccaee56Smlarkin } 1221bccaee56Smlarkin 1222bccaee56Smlarkin const struct aq_product * 1223bccaee56Smlarkin aq_lookup(const struct pci_attach_args *pa) 1224bccaee56Smlarkin { 1225bccaee56Smlarkin unsigned int i; 1226bccaee56Smlarkin 1227bccaee56Smlarkin for (i = 0; i < sizeof(aq_products) / sizeof(aq_products[0]); i++) { 1228bccaee56Smlarkin if (PCI_VENDOR(pa->pa_id) == aq_products[i].aq_vendor && 1229bccaee56Smlarkin PCI_PRODUCT(pa->pa_id) == aq_products[i].aq_product) { 1230bccaee56Smlarkin return &aq_products[i]; 1231bccaee56Smlarkin } 1232bccaee56Smlarkin } 1233bccaee56Smlarkin 1234bccaee56Smlarkin return NULL; 1235bccaee56Smlarkin } 1236bccaee56Smlarkin 1237bccaee56Smlarkin void 1238bccaee56Smlarkin aq_attach(struct device *parent, struct device *self, void *aux) 1239bccaee56Smlarkin { 1240bccaee56Smlarkin struct aq_softc *sc = (struct aq_softc *)self; 1241bccaee56Smlarkin struct pci_attach_args *pa = aux; 1242bccaee56Smlarkin const struct aq_product *aqp; 1243a97e1fbfSjmatthew pcireg_t bar, memtype; 1244bccaee56Smlarkin pci_chipset_tag_t pc; 1245bccaee56Smlarkin pci_intr_handle_t ih; 1246bccaee56Smlarkin int (*isr)(void *); 1247bccaee56Smlarkin const char *intrstr; 1248bccaee56Smlarkin pcitag_t tag; 1249bccaee56Smlarkin struct ifnet *ifp = &sc->sc_arpcom.ac_if; 12508c5cbf79Sjmatthew int txmin, txmax, rxmin, rxmax; 12511d7ac227Sjmatthew int irqmode, irqnum; 1252bccaee56Smlarkin int i; 1253bccaee56Smlarkin 1254bccaee56Smlarkin mtx_init(&sc->sc_mpi_mutex, IPL_NET); 1255bccaee56Smlarkin 1256bccaee56Smlarkin sc->sc_dmat = pa->pa_dmat; 1257bccaee56Smlarkin sc->sc_pc = pc = pa->pa_pc; 1258bccaee56Smlarkin sc->sc_pcitag = tag = pa->pa_tag; 1259bccaee56Smlarkin 1260bccaee56Smlarkin sc->sc_product = PCI_PRODUCT(pa->pa_id); 1261bccaee56Smlarkin sc->sc_revision = PCI_REVISION(pa->pa_class); 1262bccaee56Smlarkin 1263bccaee56Smlarkin aqp = aq_lookup(pa); 1264bccaee56Smlarkin 1265bccaee56Smlarkin bar = pci_conf_read(pc, tag, AQ_BAR0); 12667bebb76eSjmatthew if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM) { 12677bebb76eSjmatthew printf(": wrong BAR type\n"); 1268bccaee56Smlarkin return; 1269bccaee56Smlarkin } 1270bccaee56Smlarkin 1271bccaee56Smlarkin memtype = pci_mapreg_type(pc, tag, AQ_BAR0); 1272bccaee56Smlarkin if (pci_mapreg_map(pa, AQ_BAR0, memtype, 0, &sc->sc_iot, &sc->sc_ioh, 1273bccaee56Smlarkin NULL, NULL, 0)) { 1274bccaee56Smlarkin printf(": failed to map BAR0\n"); 1275bccaee56Smlarkin return; 1276bccaee56Smlarkin } 1277bccaee56Smlarkin 1278bccaee56Smlarkin sc->sc_nqueues = 1; 12791d7ac227Sjmatthew sc->sc_linkstat_irq = AQ_LINKSTAT_IRQ; 12801d7ac227Sjmatthew isr = aq_intr; 12811d7ac227Sjmatthew irqnum = 0; 1282bccaee56Smlarkin 1283bccaee56Smlarkin if (pci_intr_map_msix(pa, 0, &ih) == 0) { 12841d7ac227Sjmatthew int nmsix = pci_intr_msix_count(pa); 1285b760e38cSjmatthew /* don't do rss on aq2 yet */ 1286b760e38cSjmatthew if (aqp->aq_hwtype == HWTYPE_AQ1 && nmsix > 1) { 12871d7ac227Sjmatthew nmsix--; 12881d7ac227Sjmatthew sc->sc_intrmap = intrmap_create(&sc->sc_dev, 12891d7ac227Sjmatthew nmsix, AQ_MAXQ, INTRMAP_POWEROF2); 12901d7ac227Sjmatthew sc->sc_nqueues = intrmap_count(sc->sc_intrmap); 12911d7ac227Sjmatthew KASSERT(sc->sc_nqueues > 0); 12921d7ac227Sjmatthew KASSERT(powerof2(sc->sc_nqueues)); 12931d7ac227Sjmatthew 12941d7ac227Sjmatthew sc->sc_linkstat_irq = 0; 12951d7ac227Sjmatthew isr = aq_intr_link; 12961d7ac227Sjmatthew irqnum++; 12971d7ac227Sjmatthew } 1298bccaee56Smlarkin irqmode = AQ_INTR_CTRL_IRQMODE_MSIX; 1299bccaee56Smlarkin } else if (pci_intr_map_msi(pa, &ih) == 0) { 1300bccaee56Smlarkin irqmode = AQ_INTR_CTRL_IRQMODE_MSI; 1301bccaee56Smlarkin } else if (pci_intr_map(pa, &ih) == 0) { 1302bccaee56Smlarkin irqmode = AQ_INTR_CTRL_IRQMODE_LEGACY; 1303bccaee56Smlarkin } else { 1304bccaee56Smlarkin printf(": failed to map interrupt\n"); 1305bccaee56Smlarkin return; 1306bccaee56Smlarkin } 1307bccaee56Smlarkin 1308bccaee56Smlarkin sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, 1309bccaee56Smlarkin IPL_NET | IPL_MPSAFE, isr, sc, self->dv_xname); 1310bccaee56Smlarkin intrstr = pci_intr_string(pa->pa_pc, ih); 1311bccaee56Smlarkin if (intrstr) 1312bccaee56Smlarkin printf(": %s", intrstr); 1313bccaee56Smlarkin 13141d7ac227Sjmatthew if (sc->sc_nqueues > 1) 13151d7ac227Sjmatthew printf(", %d queues", sc->sc_nqueues); 13161d7ac227Sjmatthew 131745994699Sjmatthew switch (aqp->aq_hwtype) { 131845994699Sjmatthew case HWTYPE_AQ1: 131945994699Sjmatthew if (aq1_fw_reboot(sc)) 1320bccaee56Smlarkin return; 132145994699Sjmatthew break; 1322b760e38cSjmatthew case HWTYPE_AQ2: 1323b760e38cSjmatthew if (aq2_fw_reboot(sc)) 1324b760e38cSjmatthew return; 1325b760e38cSjmatthew break; 132645994699Sjmatthew default: 1327bccaee56Smlarkin return; 132845994699Sjmatthew } 1329bccaee56Smlarkin 1330bccaee56Smlarkin if (aq_hw_reset(sc)) 1331bccaee56Smlarkin return; 1332bccaee56Smlarkin 133345994699Sjmatthew if (sc->sc_fw_ops->get_mac_addr(sc)) 1334bccaee56Smlarkin return; 1335636503bfSjmatthew printf(", address %s", ether_sprintf(sc->sc_enaddr.ether_addr_octet)); 1336bccaee56Smlarkin 1337190bcc8eSjmatthew if (aq_init_rss(sc)) 1338190bcc8eSjmatthew return; 1339190bcc8eSjmatthew 13401d7ac227Sjmatthew if (aq_hw_init(sc, irqmode, (sc->sc_nqueues > 1))) 1341bccaee56Smlarkin return; 1342bccaee56Smlarkin 1343bccaee56Smlarkin sc->sc_media_type = aqp->aq_media_type; 1344bccaee56Smlarkin sc->sc_available_rates = aqp->aq_available_rates; 1345bccaee56Smlarkin 1346bccaee56Smlarkin ifmedia_init(&sc->sc_media, IFM_IMASK, aq_ifmedia_change, 1347bccaee56Smlarkin aq_ifmedia_status); 1348bccaee56Smlarkin 1349bccaee56Smlarkin bcopy(sc->sc_enaddr.ether_addr_octet, sc->sc_arpcom.ac_enaddr, 6); 1350bccaee56Smlarkin strlcpy(ifp->if_xname, self->dv_xname, IFNAMSIZ); 1351bccaee56Smlarkin ifp->if_softc = sc; 1352bccaee56Smlarkin ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX; 1353bccaee56Smlarkin ifp->if_xflags = IFXF_MPSAFE; 1354bccaee56Smlarkin ifp->if_ioctl = aq_ioctl; 1355bccaee56Smlarkin ifp->if_qstart = aq_start; 1356bccaee56Smlarkin ifp->if_watchdog = aq_watchdog; 1357bccaee56Smlarkin ifp->if_hardmtu = 9000; 13585e728153Sjmatthew ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_IPv4 | 13595e728153Sjmatthew IFCAP_CSUM_UDPv4 | IFCAP_CSUM_UDPv6 | IFCAP_CSUM_TCPv4 | 13605e728153Sjmatthew IFCAP_CSUM_TCPv6; 136131f14b89Sjmatthew #if NVLAN > 0 136231f14b89Sjmatthew ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 136331f14b89Sjmatthew #endif 1364cf96265bSbluhm ifq_init_maxlen(&ifp->if_snd, AQ_TXD_NUM); 1365bccaee56Smlarkin 1366bccaee56Smlarkin ifmedia_init(&sc->sc_media, IFM_IMASK, aq_ifmedia_change, 1367bccaee56Smlarkin aq_ifmedia_status); 1368b760e38cSjmatthew if (sc->sc_available_rates & AQ_LINK_10M) { 1369b760e38cSjmatthew ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_T, 0, NULL); 1370b760e38cSjmatthew ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_T|IFM_FDX, 0, 1371b760e38cSjmatthew NULL); 1372b760e38cSjmatthew } 1373b760e38cSjmatthew 1374bccaee56Smlarkin if (sc->sc_available_rates & AQ_LINK_100M) { 1375bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_100_TX, 0, NULL); 1376bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, 1377bccaee56Smlarkin NULL); 1378bccaee56Smlarkin } 1379bccaee56Smlarkin 1380bccaee56Smlarkin if (sc->sc_available_rates & AQ_LINK_1G) { 1381bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_1000_T, 0, NULL); 1382bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_1000_T|IFM_FDX, 0, 1383bccaee56Smlarkin NULL); 1384bccaee56Smlarkin } 1385bccaee56Smlarkin 1386bccaee56Smlarkin if (sc->sc_available_rates & AQ_LINK_2G5) { 1387bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_2500_T, 0, NULL); 1388bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_2500_T | IFM_FDX, 1389bccaee56Smlarkin 0, NULL); 1390bccaee56Smlarkin } 1391bccaee56Smlarkin 1392bccaee56Smlarkin if (sc->sc_available_rates & AQ_LINK_5G) { 1393bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_5000_T, 0, NULL); 1394bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_5000_T | IFM_FDX, 1395bccaee56Smlarkin 0, NULL); 1396bccaee56Smlarkin } 1397bccaee56Smlarkin 1398bccaee56Smlarkin if (sc->sc_available_rates & AQ_LINK_10G) { 1399bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_10G_T, 0, NULL); 1400bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_10G_T | IFM_FDX, 1401bccaee56Smlarkin 0, NULL); 1402bccaee56Smlarkin } 1403bccaee56Smlarkin 1404bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); 1405bccaee56Smlarkin ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO | IFM_FDX, 0, NULL); 1406bccaee56Smlarkin ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); 1407bccaee56Smlarkin aq_set_linkmode(sc, AQ_LINK_AUTO, AQ_FC_NONE, AQ_EEE_DISABLE); 1408bccaee56Smlarkin 1409bccaee56Smlarkin if_attach(ifp); 1410bccaee56Smlarkin ether_ifattach(ifp); 1411bccaee56Smlarkin 1412bccaee56Smlarkin if_attach_iqueues(ifp, sc->sc_nqueues); 1413bccaee56Smlarkin if_attach_queues(ifp, sc->sc_nqueues); 1414bccaee56Smlarkin 14158c5cbf79Sjmatthew /* 14168c5cbf79Sjmatthew * set interrupt moderation for up to 20k interrupts per second, 14178c5cbf79Sjmatthew * more rx than tx. these values are in units of 2us. 14188c5cbf79Sjmatthew */ 14198c5cbf79Sjmatthew txmin = 20; 14208c5cbf79Sjmatthew txmax = 200; 14218c5cbf79Sjmatthew rxmin = 6; 14228c5cbf79Sjmatthew rxmax = 60; 14238c5cbf79Sjmatthew 1424bccaee56Smlarkin for (i = 0; i < sc->sc_nqueues; i++) { 1425bccaee56Smlarkin struct aq_queues *aq = &sc->sc_queues[i]; 1426bccaee56Smlarkin struct aq_rxring *rx = &aq->q_rx; 1427bccaee56Smlarkin struct aq_txring *tx = &aq->q_tx; 14281d7ac227Sjmatthew pci_intr_handle_t ih; 1429bccaee56Smlarkin 1430bccaee56Smlarkin aq->q_sc = sc; 1431bccaee56Smlarkin aq->q_index = i; 1432bccaee56Smlarkin rx->rx_q = i; 1433bccaee56Smlarkin rx->rx_ifiq = ifp->if_iqs[i]; 14340425cdaeSjmatthew rx->rx_m_head = NULL; 14350425cdaeSjmatthew rx->rx_m_tail = &rx->rx_m_head; 14360425cdaeSjmatthew rx->rx_m_error = 0; 1437bccaee56Smlarkin ifp->if_iqs[i]->ifiq_softc = aq; 1438bccaee56Smlarkin timeout_set(&rx->rx_refill, aq_refill, rx); 1439bccaee56Smlarkin 1440bccaee56Smlarkin tx->tx_q = i; 1441bccaee56Smlarkin tx->tx_ifq = ifp->if_ifqs[i]; 1442bccaee56Smlarkin ifp->if_ifqs[i]->ifq_softc = aq; 1443bccaee56Smlarkin 14441d7ac227Sjmatthew snprintf(aq->q_name, sizeof(aq->q_name), "%s:%u", 14451d7ac227Sjmatthew DEVNAME(sc), i); 14461d7ac227Sjmatthew 1447bccaee56Smlarkin if (sc->sc_nqueues > 1) { 14481d7ac227Sjmatthew if (pci_intr_map_msix(pa, irqnum, &ih)) { 1449636503bfSjmatthew printf(": unable to map msi-x vector %d\n", 1450636503bfSjmatthew irqnum); 14511d7ac227Sjmatthew return; 14521d7ac227Sjmatthew } 14531d7ac227Sjmatthew 14541d7ac227Sjmatthew aq->q_ihc = pci_intr_establish_cpu(sc->sc_pc, ih, 14551d7ac227Sjmatthew IPL_NET | IPL_MPSAFE, intrmap_cpu(sc->sc_intrmap, i), 14561d7ac227Sjmatthew aq_intr_queue, aq, aq->q_name); 14571d7ac227Sjmatthew if (aq->q_ihc == NULL) { 1458636503bfSjmatthew printf(": unable to establish interrupt %d\n", 1459636503bfSjmatthew irqnum); 14601d7ac227Sjmatthew return; 14611d7ac227Sjmatthew } 14621d7ac227Sjmatthew rx->rx_irq = irqnum; 14631d7ac227Sjmatthew tx->tx_irq = irqnum; 14641d7ac227Sjmatthew irqnum++; 14651d7ac227Sjmatthew } else { 14661d7ac227Sjmatthew rx->rx_irq = irqnum++; 14671d7ac227Sjmatthew tx->tx_irq = irqnum++; 1468bccaee56Smlarkin } 1469bccaee56Smlarkin 1470b760e38cSjmatthew if (HWTYPE_AQ2_P(sc)) { 1471b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_TX_INTR_MODERATION_CTL_REG(i), 1472b760e38cSjmatthew AQ2_TX_INTR_MODERATION_CTL_MIN, txmin); 1473b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_TX_INTR_MODERATION_CTL_REG(i), 1474b760e38cSjmatthew AQ2_TX_INTR_MODERATION_CTL_MAX, txmax); 1475b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_TX_INTR_MODERATION_CTL_REG(i), 1476b760e38cSjmatthew AQ2_TX_INTR_MODERATION_CTL_EN, 1); 1477b760e38cSjmatthew } else { 14788c5cbf79Sjmatthew AQ_WRITE_REG_BIT(sc, TX_INTR_MODERATION_CTL_REG(i), 14798c5cbf79Sjmatthew TX_INTR_MODERATION_CTL_MIN, txmin); 14808c5cbf79Sjmatthew AQ_WRITE_REG_BIT(sc, TX_INTR_MODERATION_CTL_REG(i), 14818c5cbf79Sjmatthew TX_INTR_MODERATION_CTL_MAX, txmax); 14828c5cbf79Sjmatthew AQ_WRITE_REG_BIT(sc, TX_INTR_MODERATION_CTL_REG(i), 14838c5cbf79Sjmatthew TX_INTR_MODERATION_CTL_EN, 1); 1484b760e38cSjmatthew } 14858c5cbf79Sjmatthew AQ_WRITE_REG_BIT(sc, RX_INTR_MODERATION_CTL_REG(i), 14868c5cbf79Sjmatthew RX_INTR_MODERATION_CTL_MIN, rxmin); 14878c5cbf79Sjmatthew AQ_WRITE_REG_BIT(sc, RX_INTR_MODERATION_CTL_REG(i), 14888c5cbf79Sjmatthew RX_INTR_MODERATION_CTL_MAX, rxmax); 14898c5cbf79Sjmatthew AQ_WRITE_REG_BIT(sc, RX_INTR_MODERATION_CTL_REG(i), 14908c5cbf79Sjmatthew RX_INTR_MODERATION_CTL_EN, 1); 1491bccaee56Smlarkin } 1492bccaee56Smlarkin 1493bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TX_DMA_INT_DESC_WRWB_EN_REG, 14948c5cbf79Sjmatthew TX_DMA_INT_DESC_WRWB_EN, 0); 1495bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TX_DMA_INT_DESC_WRWB_EN_REG, 14968c5cbf79Sjmatthew TX_DMA_INT_DESC_MODERATE_EN, 1); 1497bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_INT_DESC_WRWB_EN_REG, 14988c5cbf79Sjmatthew RX_DMA_INT_DESC_WRWB_EN, 0); 1499bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_INT_DESC_WRWB_EN_REG, 15008c5cbf79Sjmatthew RX_DMA_INT_DESC_MODERATE_EN, 1); 1501bccaee56Smlarkin 1502bccaee56Smlarkin aq_enable_intr(sc, 1, 0); 1503bccaee56Smlarkin printf("\n"); 1504bccaee56Smlarkin } 1505bccaee56Smlarkin 1506bccaee56Smlarkin int 150745994699Sjmatthew aq1_fw_reboot(struct aq_softc *sc) 1508bccaee56Smlarkin { 1509bccaee56Smlarkin uint32_t ver, v, boot_exit_code; 1510bccaee56Smlarkin int i, error; 1511bccaee56Smlarkin enum aq_fw_bootloader_mode mode; 1512bccaee56Smlarkin 1513bccaee56Smlarkin mode = FW_BOOT_MODE_UNKNOWN; 1514bccaee56Smlarkin 1515bccaee56Smlarkin ver = AQ_READ_REG(sc, AQ_FW_VERSION_REG); 1516bccaee56Smlarkin 1517bccaee56Smlarkin for (i = 1000; i > 0; i--) { 1518bccaee56Smlarkin v = AQ_READ_REG(sc, FW_MPI_DAISY_CHAIN_STATUS_REG); 1519bccaee56Smlarkin boot_exit_code = AQ_READ_REG(sc, FW_BOOT_EXIT_CODE_REG); 1520bccaee56Smlarkin if (v != 0x06000000 || boot_exit_code != 0) 1521bccaee56Smlarkin break; 1522bccaee56Smlarkin } 1523bccaee56Smlarkin 1524bccaee56Smlarkin if (i <= 0) { 1525636503bfSjmatthew printf(": F/W reset failed. Neither RBL nor FLB started"); 1526bccaee56Smlarkin return ETIMEDOUT; 1527bccaee56Smlarkin } 1528bccaee56Smlarkin 1529bccaee56Smlarkin sc->sc_rbl_enabled = (boot_exit_code != 0); 1530bccaee56Smlarkin 1531bccaee56Smlarkin /* 1532bccaee56Smlarkin * Having FW version 0 is an indicator that cold start 1533bccaee56Smlarkin * is in progress. This means two things: 1534bccaee56Smlarkin * 1) Driver have to wait for FW/HW to finish boot (500ms giveup) 1535bccaee56Smlarkin * 2) Driver may skip reset sequence and save time. 1536bccaee56Smlarkin */ 1537bccaee56Smlarkin if (sc->sc_fast_start_enabled && (ver != 0)) { 153845994699Sjmatthew if (aq1_fw_read_version(sc) == 0) 153945994699Sjmatthew goto faststart; 1540bccaee56Smlarkin } 1541bccaee56Smlarkin 154245994699Sjmatthew error = aq1_mac_soft_reset(sc, &mode); 1543bccaee56Smlarkin if (error != 0) { 1544bccaee56Smlarkin printf("%s: MAC reset failed: %d\n", DEVNAME(sc), error); 1545bccaee56Smlarkin return error; 1546bccaee56Smlarkin } 1547bccaee56Smlarkin 1548bccaee56Smlarkin switch (mode) { 1549bccaee56Smlarkin case FW_BOOT_MODE_FLB: 1550bccaee56Smlarkin DPRINTF(("%s: FLB> F/W successfully loaded from flash.", 1551bccaee56Smlarkin DEVNAME(sc))); 1552bccaee56Smlarkin sc->sc_flash_present = 1; 155345994699Sjmatthew break; 1554bccaee56Smlarkin case FW_BOOT_MODE_RBL_FLASH: 1555bccaee56Smlarkin DPRINTF(("%s: RBL> F/W loaded from flash. Host Bootload " 1556bccaee56Smlarkin "disabled.", DEVNAME(sc))); 1557bccaee56Smlarkin sc->sc_flash_present = 1; 155845994699Sjmatthew break; 1559bccaee56Smlarkin case FW_BOOT_MODE_UNKNOWN: 1560bccaee56Smlarkin printf("%s: F/W bootload error: unknown bootloader type", 1561bccaee56Smlarkin DEVNAME(sc)); 1562bccaee56Smlarkin return ENOTSUP; 1563bccaee56Smlarkin case FW_BOOT_MODE_RBL_HOST_BOOTLOAD: 1564bccaee56Smlarkin printf("%s: RBL> F/W Host Bootload not implemented", DEVNAME(sc)); 1565bccaee56Smlarkin return ENOTSUP; 1566bccaee56Smlarkin } 1567bccaee56Smlarkin 156845994699Sjmatthew faststart: 156945994699Sjmatthew error = aq1_fw_read_version(sc); 157045994699Sjmatthew if (error != 0) 157145994699Sjmatthew return error; 157245994699Sjmatthew 157345994699Sjmatthew error = aq1_fw_version_init(sc); 157445994699Sjmatthew if (error != 0) 157545994699Sjmatthew return error; 157645994699Sjmatthew 157745994699Sjmatthew return aq1_hw_init_ucp(sc); 1578bccaee56Smlarkin } 1579bccaee56Smlarkin 1580bccaee56Smlarkin int 158145994699Sjmatthew aq1_mac_soft_reset_rbl(struct aq_softc *sc, enum aq_fw_bootloader_mode *mode) 1582bccaee56Smlarkin { 1583bccaee56Smlarkin int timo; 1584bccaee56Smlarkin 1585bccaee56Smlarkin DPRINTF(("%s: RBL> MAC reset STARTED!\n", DEVNAME(sc))); 1586bccaee56Smlarkin 1587bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_GLB_CTL2_REG, 0x40e1); 1588bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_GLB_CPU_SEM_REG(0), 1); 1589bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_MBOXIF_POWER_GATING_CONTROL_REG, 0); 1590bccaee56Smlarkin 1591bccaee56Smlarkin /* MAC FW will reload PHY FW if 1E.1000.3 was cleaned - #undone */ 1592bccaee56Smlarkin AQ_WRITE_REG(sc, FW_BOOT_EXIT_CODE_REG, RBL_STATUS_DEAD); 1593bccaee56Smlarkin 159445994699Sjmatthew aq1_global_software_reset(sc); 1595bccaee56Smlarkin 1596bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_GLB_CTL2_REG, 0x40e0); 1597bccaee56Smlarkin 1598bccaee56Smlarkin /* Wait for RBL to finish boot process. */ 1599bccaee56Smlarkin #define RBL_TIMEOUT_MS 10000 1600bccaee56Smlarkin uint16_t rbl_status; 1601bccaee56Smlarkin for (timo = RBL_TIMEOUT_MS; timo > 0; timo--) { 1602bccaee56Smlarkin rbl_status = AQ_READ_REG(sc, FW_BOOT_EXIT_CODE_REG) & 0xffff; 1603bccaee56Smlarkin if (rbl_status != 0 && rbl_status != RBL_STATUS_DEAD) 1604bccaee56Smlarkin break; 1605bccaee56Smlarkin delay(1000); 1606bccaee56Smlarkin } 1607bccaee56Smlarkin 1608bccaee56Smlarkin if (timo <= 0) { 1609bccaee56Smlarkin printf("%s: RBL> RBL restart failed: timeout\n", DEVNAME(sc)); 1610bccaee56Smlarkin return EBUSY; 1611bccaee56Smlarkin } 1612bccaee56Smlarkin 1613bccaee56Smlarkin switch (rbl_status) { 1614bccaee56Smlarkin case RBL_STATUS_SUCCESS: 1615bccaee56Smlarkin if (mode != NULL) 1616bccaee56Smlarkin *mode = FW_BOOT_MODE_RBL_FLASH; 1617bccaee56Smlarkin DPRINTF(("%s: RBL> reset complete! [Flash]\n", DEVNAME(sc))); 1618bccaee56Smlarkin break; 1619bccaee56Smlarkin case RBL_STATUS_HOST_BOOT: 1620bccaee56Smlarkin if (mode != NULL) 1621bccaee56Smlarkin *mode = FW_BOOT_MODE_RBL_HOST_BOOTLOAD; 1622bccaee56Smlarkin DPRINTF(("%s: RBL> reset complete! [Host Bootload]\n", 1623bccaee56Smlarkin DEVNAME(sc))); 1624bccaee56Smlarkin break; 1625bccaee56Smlarkin case RBL_STATUS_FAILURE: 1626bccaee56Smlarkin default: 1627bccaee56Smlarkin printf("%s: unknown RBL status 0x%x\n", DEVNAME(sc), 1628bccaee56Smlarkin rbl_status); 1629bccaee56Smlarkin return EBUSY; 1630bccaee56Smlarkin } 1631bccaee56Smlarkin 1632bccaee56Smlarkin return 0; 1633bccaee56Smlarkin } 1634bccaee56Smlarkin 1635bccaee56Smlarkin int 163645994699Sjmatthew aq1_mac_soft_reset_flb(struct aq_softc *sc) 1637bccaee56Smlarkin { 1638bccaee56Smlarkin uint32_t v; 1639bccaee56Smlarkin int timo; 1640bccaee56Smlarkin 1641bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_GLB_CTL2_REG, 0x40e1); 1642bccaee56Smlarkin /* 1643bccaee56Smlarkin * Let Felicity hardware to complete SMBUS transaction before 1644bccaee56Smlarkin * Global software reset. 1645bccaee56Smlarkin */ 1646bccaee56Smlarkin delay(50000); 1647bccaee56Smlarkin 1648bccaee56Smlarkin /* 1649bccaee56Smlarkin * If SPI burst transaction was interrupted(before running the script), 1650bccaee56Smlarkin * global software reset may not clear SPI interface. 1651bccaee56Smlarkin * Clean it up manually before global reset. 1652bccaee56Smlarkin */ 1653bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_GLB_NVR_PROVISIONING2_REG, 0x00a0); 1654bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_GLB_NVR_INTERFACE1_REG, 0x009f); 1655bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_GLB_NVR_INTERFACE1_REG, 0x809f); 1656bccaee56Smlarkin delay(50000); 1657bccaee56Smlarkin 1658bccaee56Smlarkin v = AQ_READ_REG(sc, AQ_FW_SOFTRESET_REG); 1659bccaee56Smlarkin v &= ~AQ_FW_SOFTRESET_DIS; 1660bccaee56Smlarkin v |= AQ_FW_SOFTRESET_RESET; 1661bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_SOFTRESET_REG, v); 1662bccaee56Smlarkin 1663bccaee56Smlarkin /* Kickstart. */ 1664bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_GLB_CTL2_REG, 0x80e0); 1665bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_MBOXIF_POWER_GATING_CONTROL_REG, 0); 1666bccaee56Smlarkin if (!sc->sc_fast_start_enabled) 1667bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_GLB_GENERAL_PROVISIONING9_REG, 1); 1668bccaee56Smlarkin 1669bccaee56Smlarkin /* 1670bccaee56Smlarkin * For the case SPI burst transaction was interrupted (by MCP reset 1671bccaee56Smlarkin * above), wait until it is completed by hardware. 1672bccaee56Smlarkin */ 1673bccaee56Smlarkin delay(50000); 1674bccaee56Smlarkin 1675bccaee56Smlarkin /* MAC Kickstart */ 1676bccaee56Smlarkin if (!sc->sc_fast_start_enabled) { 1677bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_GLB_CTL2_REG, 0x180e0); 1678bccaee56Smlarkin 1679bccaee56Smlarkin uint32_t flb_status; 1680bccaee56Smlarkin for (timo = 0; timo < 1000; timo++) { 1681bccaee56Smlarkin flb_status = AQ_READ_REG(sc, 1682bccaee56Smlarkin FW_MPI_DAISY_CHAIN_STATUS_REG) & 0x10; 1683bccaee56Smlarkin if (flb_status != 0) 1684bccaee56Smlarkin break; 1685bccaee56Smlarkin delay(1000); 1686bccaee56Smlarkin } 1687bccaee56Smlarkin if (flb_status == 0) { 1688bccaee56Smlarkin printf("%s: FLB> MAC kickstart failed: timed out\n", 1689bccaee56Smlarkin DEVNAME(sc)); 1690bccaee56Smlarkin return ETIMEDOUT; 1691bccaee56Smlarkin } 1692bccaee56Smlarkin DPRINTF(("%s: FLB> MAC kickstart done, %d ms\n", DEVNAME(sc), 1693bccaee56Smlarkin timo)); 1694bccaee56Smlarkin /* FW reset */ 1695bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_GLB_CTL2_REG, 0x80e0); 1696bccaee56Smlarkin /* 1697bccaee56Smlarkin * Let Felicity hardware complete SMBUS transaction before 1698bccaee56Smlarkin * Global software reset. 1699bccaee56Smlarkin */ 1700bccaee56Smlarkin delay(50000); 1701bccaee56Smlarkin sc->sc_fast_start_enabled = true; 1702bccaee56Smlarkin } 1703bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_GLB_CPU_SEM_REG(0), 1); 1704bccaee56Smlarkin 1705bccaee56Smlarkin /* PHY Kickstart: #undone */ 170645994699Sjmatthew aq1_global_software_reset(sc); 1707bccaee56Smlarkin 1708bccaee56Smlarkin for (timo = 0; timo < 1000; timo++) { 1709bccaee56Smlarkin if (AQ_READ_REG(sc, AQ_FW_VERSION_REG) != 0) 1710bccaee56Smlarkin break; 1711bccaee56Smlarkin delay(10000); 1712bccaee56Smlarkin } 1713bccaee56Smlarkin if (timo >= 1000) { 1714bccaee56Smlarkin printf("%s: FLB> Global Soft Reset failed\n", DEVNAME(sc)); 1715bccaee56Smlarkin return ETIMEDOUT; 1716bccaee56Smlarkin } 1717bccaee56Smlarkin DPRINTF(("%s: FLB> F/W restart: %d ms\n", DEVNAME(sc), timo * 10)); 1718bccaee56Smlarkin 1719bccaee56Smlarkin return 0; 1720bccaee56Smlarkin 1721bccaee56Smlarkin } 1722bccaee56Smlarkin 1723bccaee56Smlarkin int 172445994699Sjmatthew aq1_mac_soft_reset(struct aq_softc *sc, enum aq_fw_bootloader_mode *mode) 1725bccaee56Smlarkin { 1726bccaee56Smlarkin if (sc->sc_rbl_enabled) 172745994699Sjmatthew return aq1_mac_soft_reset_rbl(sc, mode); 1728bccaee56Smlarkin 1729bccaee56Smlarkin if (mode != NULL) 1730bccaee56Smlarkin *mode = FW_BOOT_MODE_FLB; 173145994699Sjmatthew return aq1_mac_soft_reset_flb(sc); 1732bccaee56Smlarkin } 1733bccaee56Smlarkin 1734bccaee56Smlarkin void 173545994699Sjmatthew aq1_global_software_reset(struct aq_softc *sc) 1736bccaee56Smlarkin { 1737bccaee56Smlarkin uint32_t v; 1738bccaee56Smlarkin 1739bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_SYSCONTROL_REG, RX_SYSCONTROL_RESET_DIS, 0); 1740bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TX_SYSCONTROL_REG, TX_SYSCONTROL_RESET_DIS, 0); 1741bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, FW_MPI_RESETCTRL_REG, 1742bccaee56Smlarkin FW_MPI_RESETCTRL_RESET_DIS, 0); 1743bccaee56Smlarkin 1744bccaee56Smlarkin v = AQ_READ_REG(sc, AQ_FW_SOFTRESET_REG); 1745bccaee56Smlarkin v &= ~AQ_FW_SOFTRESET_DIS; 1746bccaee56Smlarkin v |= AQ_FW_SOFTRESET_RESET; 1747bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_SOFTRESET_REG, v); 1748bccaee56Smlarkin } 1749bccaee56Smlarkin 1750bccaee56Smlarkin int 175145994699Sjmatthew aq1_fw_read_version(struct aq_softc *sc) 1752bccaee56Smlarkin { 1753bccaee56Smlarkin int i, error = EBUSY; 1754bccaee56Smlarkin #define MAC_FW_START_TIMEOUT_MS 10000 1755bccaee56Smlarkin for (i = 0; i < MAC_FW_START_TIMEOUT_MS; i++) { 1756bccaee56Smlarkin sc->sc_fw_version = AQ_READ_REG(sc, AQ_FW_VERSION_REG); 1757bccaee56Smlarkin if (sc->sc_fw_version != 0) { 1758bccaee56Smlarkin error = 0; 1759bccaee56Smlarkin break; 1760bccaee56Smlarkin } 1761bccaee56Smlarkin delay(1000); 1762bccaee56Smlarkin } 1763bccaee56Smlarkin return error; 1764bccaee56Smlarkin } 1765bccaee56Smlarkin 1766bccaee56Smlarkin int 176745994699Sjmatthew aq1_fw_version_init(struct aq_softc *sc) 1768bccaee56Smlarkin { 1769bccaee56Smlarkin int error = 0; 1770bccaee56Smlarkin char fw_vers[sizeof("F/W version xxxxx.xxxxx.xxxxx")]; 1771bccaee56Smlarkin 1772bccaee56Smlarkin if (FW_VERSION_MAJOR(sc) == 1) { 1773bccaee56Smlarkin sc->sc_fw_ops = &aq_fw1x_ops; 1774bccaee56Smlarkin } else if ((FW_VERSION_MAJOR(sc) == 2) || (FW_VERSION_MAJOR(sc) == 3)) { 1775bccaee56Smlarkin sc->sc_fw_ops = &aq_fw2x_ops; 1776bccaee56Smlarkin } else { 1777636503bfSjmatthew printf(": Unsupported F/W version %d.%d.%d\n", 1778bccaee56Smlarkin FW_VERSION_MAJOR(sc), FW_VERSION_MINOR(sc), 1779bccaee56Smlarkin FW_VERSION_BUILD(sc)); 1780bccaee56Smlarkin return ENOTSUP; 1781bccaee56Smlarkin } 1782bccaee56Smlarkin snprintf(fw_vers, sizeof(fw_vers), "F/W version %d.%d.%d", 1783bccaee56Smlarkin FW_VERSION_MAJOR(sc), FW_VERSION_MINOR(sc), FW_VERSION_BUILD(sc)); 1784bccaee56Smlarkin 1785bccaee56Smlarkin /* detect revision */ 1786bccaee56Smlarkin uint32_t hwrev = AQ_READ_REG(sc, AQ_HW_REVISION_REG); 1787bccaee56Smlarkin switch (hwrev & 0x0000000f) { 1788bccaee56Smlarkin case 0x01: 178945994699Sjmatthew printf(", Atlantic A0, %s", fw_vers); 179045994699Sjmatthew sc->sc_features |= FEATURES_AQ1_REV_A0 | 1791bccaee56Smlarkin FEATURES_MPI_AQ | FEATURES_MIPS; 1792bccaee56Smlarkin break; 1793bccaee56Smlarkin case 0x02: 179445994699Sjmatthew printf(", Atlantic B0, %s", fw_vers); 179545994699Sjmatthew sc->sc_features |= FEATURES_AQ1_REV_B0 | 1796bccaee56Smlarkin FEATURES_MPI_AQ | FEATURES_MIPS | 1797bccaee56Smlarkin FEATURES_TPO2 | FEATURES_RPF2; 1798bccaee56Smlarkin break; 1799bccaee56Smlarkin case 0x0A: 180045994699Sjmatthew printf(", Atlantic B1, %s", fw_vers); 180145994699Sjmatthew sc->sc_features |= FEATURES_AQ1_REV_B1 | 1802bccaee56Smlarkin FEATURES_MPI_AQ | FEATURES_MIPS | 1803bccaee56Smlarkin FEATURES_TPO2 | FEATURES_RPF2; 1804bccaee56Smlarkin break; 1805bccaee56Smlarkin default: 180645994699Sjmatthew printf(": Unknown revision (0x%08x)\n", hwrev); 1807bccaee56Smlarkin error = ENOTSUP; 1808bccaee56Smlarkin break; 1809bccaee56Smlarkin } 1810bccaee56Smlarkin return error; 1811bccaee56Smlarkin } 1812bccaee56Smlarkin 1813bccaee56Smlarkin int 181445994699Sjmatthew aq1_hw_init_ucp(struct aq_softc *sc) 1815bccaee56Smlarkin { 1816bccaee56Smlarkin int timo; 1817bccaee56Smlarkin 1818bccaee56Smlarkin if (FW_VERSION_MAJOR(sc) == 1) { 1819bccaee56Smlarkin if (AQ_READ_REG(sc, FW1X_MPI_INIT2_REG) == 0) { 1820bccaee56Smlarkin uint32_t data; 1821bccaee56Smlarkin arc4random_buf(&data, sizeof(data)); 1822bccaee56Smlarkin data &= 0xfefefefe; 1823bccaee56Smlarkin data |= 0x02020202; 1824bccaee56Smlarkin AQ_WRITE_REG(sc, FW1X_MPI_INIT2_REG, data); 1825bccaee56Smlarkin } 1826bccaee56Smlarkin AQ_WRITE_REG(sc, FW1X_MPI_INIT1_REG, 0); 1827bccaee56Smlarkin } 1828bccaee56Smlarkin 1829bccaee56Smlarkin for (timo = 100; timo > 0; timo--) { 1830bccaee56Smlarkin sc->sc_mbox_addr = AQ_READ_REG(sc, FW_MPI_MBOX_ADDR_REG); 1831bccaee56Smlarkin if (sc->sc_mbox_addr != 0) 1832bccaee56Smlarkin break; 1833bccaee56Smlarkin delay(1000); 1834bccaee56Smlarkin } 1835bccaee56Smlarkin 1836bccaee56Smlarkin #define AQ_FW_MIN_VERSION 0x01050006 1837bccaee56Smlarkin #define AQ_FW_MIN_VERSION_STR "1.5.6" 1838bccaee56Smlarkin if (sc->sc_fw_version < AQ_FW_MIN_VERSION) { 1839bccaee56Smlarkin printf("%s: atlantic: wrong FW version: " AQ_FW_MIN_VERSION_STR 1840bccaee56Smlarkin " or later required, this is %d.%d.%d\n", 1841bccaee56Smlarkin DEVNAME(sc), 1842bccaee56Smlarkin FW_VERSION_MAJOR(sc), 1843bccaee56Smlarkin FW_VERSION_MINOR(sc), 1844bccaee56Smlarkin FW_VERSION_BUILD(sc)); 1845bccaee56Smlarkin return ENOTSUP; 1846bccaee56Smlarkin } 1847bccaee56Smlarkin 1848bccaee56Smlarkin if (sc->sc_mbox_addr == 0) 1849bccaee56Smlarkin printf("%s: NULL MBOX!!\n", DEVNAME(sc)); 1850bccaee56Smlarkin 1851bccaee56Smlarkin return 0; 1852bccaee56Smlarkin } 1853bccaee56Smlarkin 1854bccaee56Smlarkin int 1855b760e38cSjmatthew aq2_interface_buffer_read(struct aq_softc *sc, uint32_t reg0, uint32_t *data0, 1856b760e38cSjmatthew uint32_t size0) 1857b760e38cSjmatthew { 1858b760e38cSjmatthew uint32_t tid0, tid1, reg, *data, size; 1859b760e38cSjmatthew int timo; 1860b760e38cSjmatthew 1861b760e38cSjmatthew for (timo = 10000; timo > 0; timo--) { 1862b760e38cSjmatthew tid0 = AQ_READ_REG(sc, AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_REG); 1863b760e38cSjmatthew if (((tid0 & AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_A) 1864b760e38cSjmatthew >> AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_A_S) != 1865b760e38cSjmatthew ((tid0 & AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_B) 1866b760e38cSjmatthew >> AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_B_S)) { 1867b760e38cSjmatthew delay(10); 1868b760e38cSjmatthew continue; 1869b760e38cSjmatthew } 1870b760e38cSjmatthew 1871b760e38cSjmatthew for (reg = reg0, data = data0, size = size0; 1872b760e38cSjmatthew size >= 4; reg += 4, data++, size -= 4) { 1873b760e38cSjmatthew *data = AQ_READ_REG(sc, reg); 1874b760e38cSjmatthew } 1875b760e38cSjmatthew 1876b760e38cSjmatthew tid1 = AQ_READ_REG(sc, AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_REG); 1877b760e38cSjmatthew if (tid0 == tid1) 1878b760e38cSjmatthew break; 1879b760e38cSjmatthew } 1880b760e38cSjmatthew if (timo == 0) { 1881b760e38cSjmatthew printf("%s: interface buffer read timeout\n", DEVNAME(sc)); 1882b760e38cSjmatthew return ETIMEDOUT; 1883b760e38cSjmatthew } 1884b760e38cSjmatthew return 0; 1885b760e38cSjmatthew } 1886b760e38cSjmatthew 1887b760e38cSjmatthew int 1888b760e38cSjmatthew aq2_fw_reboot(struct aq_softc *sc) 1889b760e38cSjmatthew { 1890b760e38cSjmatthew uint32_t v; 1891b760e38cSjmatthew int timo, err; 1892b760e38cSjmatthew char buf[32]; 1893b760e38cSjmatthew uint32_t filter_caps[3]; 1894b760e38cSjmatthew 1895b760e38cSjmatthew sc->sc_fw_ops = &aq2_fw_ops; 1896b760e38cSjmatthew sc->sc_features = FEATURES_AQ2; 1897b760e38cSjmatthew 1898b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_MCP_HOST_REQ_INT_CLR_REG, 1); 1899b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_MIF_BOOT_REG, 1); /* reboot request */ 1900b760e38cSjmatthew for (timo = 200000; timo > 0; timo--) { 1901b760e38cSjmatthew v = AQ_READ_REG(sc, AQ2_MIF_BOOT_REG); 1902b760e38cSjmatthew if ((v & AQ2_MIF_BOOT_BOOT_STARTED) && v != 0xffffffff) 1903b760e38cSjmatthew break; 1904b760e38cSjmatthew delay(10); 1905b760e38cSjmatthew } 1906b760e38cSjmatthew if (timo <= 0) { 1907b760e38cSjmatthew printf(": FW reboot timeout\n"); 1908b760e38cSjmatthew return ETIMEDOUT; 1909b760e38cSjmatthew } 1910b760e38cSjmatthew 1911b760e38cSjmatthew for (timo = 2000000; timo > 0; timo--) { 1912b760e38cSjmatthew v = AQ_READ_REG(sc, AQ2_MIF_BOOT_REG); 1913b760e38cSjmatthew if ((v & AQ2_MIF_BOOT_FW_INIT_FAILED) || 1914b760e38cSjmatthew (v & AQ2_MIF_BOOT_FW_INIT_COMP_SUCCESS)) 1915b760e38cSjmatthew break; 1916b760e38cSjmatthew v = AQ_READ_REG(sc, AQ2_MCP_HOST_REQ_INT_REG); 1917b760e38cSjmatthew if (v & AQ2_MCP_HOST_REQ_INT_READY) 1918b760e38cSjmatthew break; 1919b760e38cSjmatthew delay(10); 1920b760e38cSjmatthew } 1921b760e38cSjmatthew if (timo <= 0) { 1922b760e38cSjmatthew printf(": FW restart timeout\n"); 1923b760e38cSjmatthew return ETIMEDOUT; 1924b760e38cSjmatthew } 1925b760e38cSjmatthew 1926b760e38cSjmatthew v = AQ_READ_REG(sc, AQ2_MIF_BOOT_REG); 1927b760e38cSjmatthew if (v & AQ2_MIF_BOOT_FW_INIT_FAILED) { 1928b760e38cSjmatthew printf(": FW restart failed\n"); 1929b760e38cSjmatthew return ETIMEDOUT; 1930b760e38cSjmatthew } 1931b760e38cSjmatthew 1932b760e38cSjmatthew v = AQ_READ_REG(sc, AQ2_MCP_HOST_REQ_INT_REG); 1933b760e38cSjmatthew if (v & AQ2_MCP_HOST_REQ_INT_READY) { 1934b760e38cSjmatthew printf(": firmware required\n"); 1935b760e38cSjmatthew return ENXIO; 1936b760e38cSjmatthew } 1937b760e38cSjmatthew 1938b760e38cSjmatthew /* 1939b760e38cSjmatthew * Get aq2 firmware version. 1940b760e38cSjmatthew * Note that the bit layout and its meaning are different from aq1. 1941b760e38cSjmatthew */ 1942b760e38cSjmatthew err = aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_VERSION_BUNDLE_REG, 1943b760e38cSjmatthew (uint32_t *)&v, sizeof(v)); 1944b760e38cSjmatthew if (err != 0) 1945b760e38cSjmatthew return err; 1946b760e38cSjmatthew 1947b760e38cSjmatthew sc->sc_fw_version = 1948b760e38cSjmatthew (((v & AQ2_FW_INTERFACE_OUT_VERSION_MAJOR) >> 1949b760e38cSjmatthew AQ2_FW_INTERFACE_OUT_VERSION_MAJOR_S) << 24) | 1950b760e38cSjmatthew (((v & AQ2_FW_INTERFACE_OUT_VERSION_MINOR) >> 1951b760e38cSjmatthew AQ2_FW_INTERFACE_OUT_VERSION_MINOR_S) << 16) | 1952b760e38cSjmatthew (((v & AQ2_FW_INTERFACE_OUT_VERSION_BUILD) >> 1953b760e38cSjmatthew AQ2_FW_INTERFACE_OUT_VERSION_BUILD_S)); 1954b760e38cSjmatthew 1955b760e38cSjmatthew err = aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_VERSION_IFACE_REG, 1956b760e38cSjmatthew (uint32_t *)&v, sizeof(v)); 1957b760e38cSjmatthew if (err != 0) 1958b760e38cSjmatthew return err; 1959b760e38cSjmatthew 1960b760e38cSjmatthew switch (v & AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER) { 1961b760e38cSjmatthew case AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_A0: 1962b760e38cSjmatthew sc->sc_features |= FEATURES_AQ2_IFACE_A0; 1963b760e38cSjmatthew strncpy(buf, "A0", sizeof(buf)); 1964b760e38cSjmatthew break; 1965b760e38cSjmatthew case AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_B0: 1966b760e38cSjmatthew sc->sc_features |= FEATURES_AQ2_IFACE_B0; 1967b760e38cSjmatthew strncpy(buf, "B0", sizeof(buf)); 1968b760e38cSjmatthew break; 1969b760e38cSjmatthew default: 1970b760e38cSjmatthew snprintf(buf, sizeof(buf), "(unknown 0x%08x)", v); 1971b760e38cSjmatthew break; 1972b760e38cSjmatthew } 1973f98b2f6aSkettenis printf(", Atlantic2 %s, F/W version %d.%d.%d", buf, 1974b760e38cSjmatthew FW_VERSION_MAJOR(sc), FW_VERSION_MINOR(sc), FW_VERSION_BUILD(sc)); 1975b760e38cSjmatthew 1976b760e38cSjmatthew aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_FILTER_CAPS_REG, 1977b760e38cSjmatthew filter_caps, sizeof(filter_caps)); 1978b760e38cSjmatthew sc->sc_art_filter_base_index = ((filter_caps[2] & 1979b760e38cSjmatthew AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_RESOLVER_BASE_INDEX) >> 1980b760e38cSjmatthew AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_RESOLVER_BASE_INDEX_SHIFT) * 8; 1981b760e38cSjmatthew 1982b760e38cSjmatthew /* debug info */ 1983b760e38cSjmatthew v = AQ_READ_REG(sc, AQ_HW_REVISION_REG); 1984b760e38cSjmatthew DPRINTF(("%s: HW Rev: 0x%08x\n", DEVNAME(sc), v)); 1985b760e38cSjmatthew 1986b760e38cSjmatthew return 0; 1987b760e38cSjmatthew } 1988b760e38cSjmatthew 1989b760e38cSjmatthew int 1990bccaee56Smlarkin aq_hw_reset(struct aq_softc *sc) 1991bccaee56Smlarkin { 1992bccaee56Smlarkin int error; 1993bccaee56Smlarkin 1994bccaee56Smlarkin /* disable irq */ 1995bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, AQ_INTR_CTRL_REG, AQ_INTR_CTRL_RESET_DIS, 0); 1996bccaee56Smlarkin 1997bccaee56Smlarkin /* apply */ 1998bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, AQ_INTR_CTRL_REG, AQ_INTR_CTRL_RESET_IRQ, 1); 1999bccaee56Smlarkin 2000bccaee56Smlarkin /* wait ack 10 times by 1ms */ 2001bccaee56Smlarkin WAIT_FOR( 2002bccaee56Smlarkin (AQ_READ_REG(sc, AQ_INTR_CTRL_REG) & AQ_INTR_CTRL_RESET_IRQ) == 0, 2003bccaee56Smlarkin 1000, 10, &error); 2004bccaee56Smlarkin if (error != 0) { 2005636503bfSjmatthew printf(": IRQ reset failed: %d\n", error); 2006bccaee56Smlarkin return error; 2007bccaee56Smlarkin } 2008bccaee56Smlarkin 2009bccaee56Smlarkin return sc->sc_fw_ops->reset(sc); 2010bccaee56Smlarkin } 2011bccaee56Smlarkin 2012bccaee56Smlarkin int 201345994699Sjmatthew aq1_get_mac_addr(struct aq_softc *sc) 2014bccaee56Smlarkin { 2015bccaee56Smlarkin uint32_t mac_addr[2]; 2016bccaee56Smlarkin uint32_t efuse_shadow_addr; 2017bccaee56Smlarkin int err; 2018bccaee56Smlarkin 2019bccaee56Smlarkin efuse_shadow_addr = 0; 2020bccaee56Smlarkin if (FW_VERSION_MAJOR(sc) >= 2) 2021bccaee56Smlarkin efuse_shadow_addr = AQ_READ_REG(sc, FW2X_MPI_EFUSEADDR_REG); 2022bccaee56Smlarkin else 2023bccaee56Smlarkin efuse_shadow_addr = AQ_READ_REG(sc, FW1X_MPI_EFUSEADDR_REG); 2024bccaee56Smlarkin 2025bccaee56Smlarkin if (efuse_shadow_addr == 0) { 2026636503bfSjmatthew printf(": cannot get efuse addr\n"); 2027bccaee56Smlarkin return ENXIO; 2028bccaee56Smlarkin } 2029bccaee56Smlarkin 2030bccaee56Smlarkin DPRINTF(("%s: efuse_shadow_addr = %x\n", DEVNAME(sc), efuse_shadow_addr)); 2031bccaee56Smlarkin 2032bccaee56Smlarkin memset(mac_addr, 0, sizeof(mac_addr)); 203345994699Sjmatthew err = aq1_fw_downld_dwords(sc, efuse_shadow_addr + (40 * 4), 2034bccaee56Smlarkin mac_addr, 2); 2035bccaee56Smlarkin if (err < 0) 2036bccaee56Smlarkin return err; 2037bccaee56Smlarkin 2038bccaee56Smlarkin if (mac_addr[0] == 0 && mac_addr[1] == 0) { 2039636503bfSjmatthew printf(": mac address not found\n"); 2040bccaee56Smlarkin return ENXIO; 2041bccaee56Smlarkin } 2042bccaee56Smlarkin 2043bccaee56Smlarkin DPRINTF(("%s: mac0 %x mac1 %x\n", DEVNAME(sc), mac_addr[0], 2044bccaee56Smlarkin mac_addr[1])); 2045bccaee56Smlarkin 2046bccaee56Smlarkin mac_addr[0] = htobe32(mac_addr[0]); 2047bccaee56Smlarkin mac_addr[1] = htobe32(mac_addr[1]); 2048bccaee56Smlarkin 2049bccaee56Smlarkin DPRINTF(("%s: mac0 %x mac1 %x\n", DEVNAME(sc), mac_addr[0], 2050bccaee56Smlarkin mac_addr[1])); 2051bccaee56Smlarkin 2052bccaee56Smlarkin memcpy(sc->sc_enaddr.ether_addr_octet, 2053bccaee56Smlarkin (uint8_t *)mac_addr, ETHER_ADDR_LEN); 2054bccaee56Smlarkin 2055bccaee56Smlarkin return 0; 2056bccaee56Smlarkin } 2057bccaee56Smlarkin 2058bccaee56Smlarkin int 2059bccaee56Smlarkin aq_activate(struct device *self, int act) 2060bccaee56Smlarkin { 2061bccaee56Smlarkin return 0; 2062bccaee56Smlarkin } 2063bccaee56Smlarkin 2064bccaee56Smlarkin int 206545994699Sjmatthew aq1_fw_downld_dwords(struct aq_softc *sc, uint32_t addr, uint32_t *p, 2066bccaee56Smlarkin uint32_t cnt) 2067bccaee56Smlarkin { 2068bccaee56Smlarkin uint32_t v; 2069bccaee56Smlarkin int error = 0; 2070bccaee56Smlarkin 2071bccaee56Smlarkin WAIT_FOR(AQ_READ_REG(sc, AQ_FW_SEM_RAM_REG) == 1, 1, 10000, &error); 2072bccaee56Smlarkin if (error != 0) { 2073bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_SEM_RAM_REG, 1); 2074bccaee56Smlarkin v = AQ_READ_REG(sc, AQ_FW_SEM_RAM_REG); 2075bccaee56Smlarkin if (v == 0) { 2076bccaee56Smlarkin printf("%s: %s:%d: timeout\n", 2077bccaee56Smlarkin DEVNAME(sc), __func__, __LINE__); 2078bccaee56Smlarkin return ETIMEDOUT; 2079bccaee56Smlarkin } 2080bccaee56Smlarkin } 2081bccaee56Smlarkin 2082bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_MBOX_ADDR_REG, addr); 2083bccaee56Smlarkin 2084bccaee56Smlarkin error = 0; 2085bccaee56Smlarkin for (; cnt > 0 && error == 0; cnt--) { 2086bccaee56Smlarkin /* execute mailbox interface */ 2087bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, AQ_FW_MBOX_CMD_REG, 2088bccaee56Smlarkin AQ_FW_MBOX_CMD_EXECUTE, 1); 208945994699Sjmatthew if (sc->sc_features & FEATURES_AQ1_REV_B1) { 2090bccaee56Smlarkin WAIT_FOR(AQ_READ_REG(sc, AQ_FW_MBOX_ADDR_REG) != addr, 2091bccaee56Smlarkin 1, 1000, &error); 2092bccaee56Smlarkin } else { 2093bccaee56Smlarkin WAIT_FOR((AQ_READ_REG(sc, AQ_FW_MBOX_CMD_REG) & 2094bccaee56Smlarkin AQ_FW_MBOX_CMD_BUSY) == 0, 2095bccaee56Smlarkin 1, 1000, &error); 2096bccaee56Smlarkin } 2097bccaee56Smlarkin *p++ = AQ_READ_REG(sc, AQ_FW_MBOX_VAL_REG); 2098bccaee56Smlarkin addr += sizeof(uint32_t); 2099bccaee56Smlarkin } 2100bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_FW_SEM_RAM_REG, 1); 2101bccaee56Smlarkin 2102bccaee56Smlarkin if (error != 0) 2103bccaee56Smlarkin printf("%s: %s:%d: timeout\n", 2104bccaee56Smlarkin DEVNAME(sc), __func__, __LINE__); 2105bccaee56Smlarkin 2106bccaee56Smlarkin return error; 2107bccaee56Smlarkin } 2108bccaee56Smlarkin 2109bccaee56Smlarkin int 2110bccaee56Smlarkin aq_fw2x_reset(struct aq_softc *sc) 2111bccaee56Smlarkin { 2112bccaee56Smlarkin struct aq_fw2x_capabilities caps = { 0 }; 2113bccaee56Smlarkin int error; 2114bccaee56Smlarkin 211545994699Sjmatthew error = aq1_fw_downld_dwords(sc, 2116bccaee56Smlarkin sc->sc_mbox_addr + offsetof(struct aq_fw2x_mailbox, caps), 2117bccaee56Smlarkin (uint32_t *)&caps, sizeof caps / sizeof(uint32_t)); 2118bccaee56Smlarkin if (error != 0) { 2119bccaee56Smlarkin printf("%s: fw2x> can't get F/W capabilities mask, error %d\n", 2120bccaee56Smlarkin DEVNAME(sc), error); 2121bccaee56Smlarkin return error; 2122bccaee56Smlarkin } 2123bccaee56Smlarkin sc->sc_fw_caps = caps.caps_lo | ((uint64_t)caps.caps_hi << 32); 2124bccaee56Smlarkin 2125bccaee56Smlarkin DPRINTF(("%s: fw2x> F/W capabilities=0x%llx\n", DEVNAME(sc), 2126bccaee56Smlarkin sc->sc_fw_caps)); 2127bccaee56Smlarkin 2128bccaee56Smlarkin return 0; 2129bccaee56Smlarkin } 2130bccaee56Smlarkin 2131bccaee56Smlarkin int 2132bccaee56Smlarkin aq_fw1x_reset(struct aq_softc *sc) 2133bccaee56Smlarkin { 2134bccaee56Smlarkin printf("%s: unimplemented %s\n", DEVNAME(sc), __func__); 2135bccaee56Smlarkin return 0; 2136bccaee56Smlarkin } 2137bccaee56Smlarkin 2138bccaee56Smlarkin int 2139bccaee56Smlarkin aq_fw1x_set_mode(struct aq_softc *sc, enum aq_hw_fw_mpi_state w, 2140bccaee56Smlarkin enum aq_link_speed x, enum aq_link_fc y, enum aq_link_eee z) 2141bccaee56Smlarkin { 2142bccaee56Smlarkin return 0; 2143bccaee56Smlarkin } 2144bccaee56Smlarkin 2145bccaee56Smlarkin int 2146bccaee56Smlarkin aq_fw1x_get_mode(struct aq_softc *sc, enum aq_hw_fw_mpi_state *w, 2147bccaee56Smlarkin enum aq_link_speed *x, enum aq_link_fc *y, enum aq_link_eee *z) 2148bccaee56Smlarkin { 2149bccaee56Smlarkin return 0; 2150bccaee56Smlarkin } 2151bccaee56Smlarkin 2152bccaee56Smlarkin int 2153bccaee56Smlarkin aq_fw1x_get_stats(struct aq_softc *sc, struct aq_hw_stats_s *w) 2154bccaee56Smlarkin { 2155bccaee56Smlarkin return 0; 2156bccaee56Smlarkin } 2157bccaee56Smlarkin 2158bccaee56Smlarkin 2159bccaee56Smlarkin int 2160bccaee56Smlarkin aq_fw2x_get_mode(struct aq_softc *sc, enum aq_hw_fw_mpi_state *modep, 2161bccaee56Smlarkin enum aq_link_speed *speedp, enum aq_link_fc *fcp, enum aq_link_eee *eeep) 2162bccaee56Smlarkin { 2163bccaee56Smlarkin uint64_t mpi_state, mpi_ctrl; 2164bccaee56Smlarkin enum aq_link_speed speed; 2165bccaee56Smlarkin enum aq_link_fc fc; 2166bccaee56Smlarkin 2167bccaee56Smlarkin AQ_MPI_LOCK(sc); 2168bccaee56Smlarkin 2169bccaee56Smlarkin mpi_state = AQ_READ64_REG(sc, FW2X_MPI_STATE_REG); 2170bccaee56Smlarkin if (modep != NULL) { 2171bccaee56Smlarkin mpi_ctrl = AQ_READ64_REG(sc, FW2X_MPI_CONTROL_REG); 2172bccaee56Smlarkin if (mpi_ctrl & FW2X_CTRL_RATE_MASK) 2173bccaee56Smlarkin *modep = MPI_INIT; 2174bccaee56Smlarkin else 2175bccaee56Smlarkin *modep = MPI_DEINIT; 2176bccaee56Smlarkin } 2177bccaee56Smlarkin 2178bccaee56Smlarkin AQ_MPI_UNLOCK(sc); 2179bccaee56Smlarkin 2180bccaee56Smlarkin if (mpi_state & FW2X_CTRL_RATE_10G) 2181bccaee56Smlarkin speed = AQ_LINK_10G; 2182bccaee56Smlarkin else if (mpi_state & FW2X_CTRL_RATE_5G) 2183bccaee56Smlarkin speed = AQ_LINK_5G; 2184bccaee56Smlarkin else if (mpi_state & FW2X_CTRL_RATE_2G5) 2185bccaee56Smlarkin speed = AQ_LINK_2G5; 2186bccaee56Smlarkin else if (mpi_state & FW2X_CTRL_RATE_1G) 2187bccaee56Smlarkin speed = AQ_LINK_1G; 2188bccaee56Smlarkin else if (mpi_state & FW2X_CTRL_RATE_100M) 2189bccaee56Smlarkin speed = AQ_LINK_100M; 2190bccaee56Smlarkin else 2191bccaee56Smlarkin speed = AQ_LINK_NONE; 2192bccaee56Smlarkin if (speedp != NULL) 2193bccaee56Smlarkin *speedp = speed; 2194bccaee56Smlarkin 2195bccaee56Smlarkin fc = AQ_FC_NONE; 2196bccaee56Smlarkin if (mpi_state & FW2X_CTRL_PAUSE) 2197bccaee56Smlarkin fc |= AQ_FC_RX; 2198bccaee56Smlarkin if (mpi_state & FW2X_CTRL_ASYMMETRIC_PAUSE) 2199bccaee56Smlarkin fc |= AQ_FC_TX; 2200bccaee56Smlarkin if (fcp != NULL) 2201bccaee56Smlarkin *fcp = fc; 2202bccaee56Smlarkin 2203bccaee56Smlarkin if (eeep != NULL) 2204bccaee56Smlarkin *eeep = AQ_EEE_DISABLE; 2205bccaee56Smlarkin 2206bccaee56Smlarkin return 0; 2207bccaee56Smlarkin } 2208bccaee56Smlarkin 2209bccaee56Smlarkin int 2210bccaee56Smlarkin aq_fw2x_get_stats(struct aq_softc *sc, struct aq_hw_stats_s *w) 2211bccaee56Smlarkin { 2212bccaee56Smlarkin return 0; 2213bccaee56Smlarkin } 2214bccaee56Smlarkin 2215b760e38cSjmatthew static int 2216b760e38cSjmatthew aq2_fw_wait_shared_ack(struct aq_softc *sc) 2217b760e38cSjmatthew { 2218b760e38cSjmatthew int error; 2219b760e38cSjmatthew 2220b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_MIF_HOST_FINISHED_STATUS_WRITE_REG, 2221b760e38cSjmatthew AQ2_MIF_HOST_FINISHED_STATUS_ACK); 2222b760e38cSjmatthew WAIT_FOR((AQ_READ_REG(sc, AQ2_MIF_HOST_FINISHED_STATUS_READ_REG) & 2223b760e38cSjmatthew AQ2_MIF_HOST_FINISHED_STATUS_ACK) == 0, 100, 100000, &error); 2224b760e38cSjmatthew 2225b760e38cSjmatthew return error; 2226b760e38cSjmatthew } 2227b760e38cSjmatthew 2228b760e38cSjmatthew int 2229b760e38cSjmatthew aq2_fw_reset(struct aq_softc *sc) 2230b760e38cSjmatthew { 2231b760e38cSjmatthew uint32_t v; 2232b760e38cSjmatthew int error; 2233b760e38cSjmatthew 2234b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_FW_INTERFACE_IN_LINK_CONTROL_REG, 2235b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE, 2236b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_ACTIVE); 2237b760e38cSjmatthew 2238b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_FW_INTERFACE_IN_MTU_REG, 2239b760e38cSjmatthew /*AQ2_JUMBO_MTU*/ MCLBYTES + sizeof(struct ether_header)); 2240b760e38cSjmatthew 2241b760e38cSjmatthew v = AQ_READ_REG(sc, AQ2_FW_INTERFACE_IN_REQUEST_POLICY_REG); 2242b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_QUEUE_OR_TC; 2243b760e38cSjmatthew v &= ~AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_RX_QUEUE_TC_INDEX; 2244b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_ACCEPT; 2245b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_QUEUE_OR_TC; 2246b760e38cSjmatthew v &= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_RX_QUEUE_TC_INDEX; 2247b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_ACCEPT; 2248b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_QUEUE_OR_TC; 2249b760e38cSjmatthew v &= ~AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_RX_QUEUE_TX_INDEX; 2250b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_FW_INTERFACE_IN_REQUEST_POLICY_REG, v); 2251b760e38cSjmatthew 2252b760e38cSjmatthew error = aq2_fw_wait_shared_ack(sc); 2253b760e38cSjmatthew if (error != 0) 2254b760e38cSjmatthew printf(": reset timed out\n"); 2255b760e38cSjmatthew return error; 2256b760e38cSjmatthew } 2257b760e38cSjmatthew 2258b760e38cSjmatthew int 2259b760e38cSjmatthew aq2_get_mac_addr(struct aq_softc *sc) 2260b760e38cSjmatthew { 2261b760e38cSjmatthew uint32_t mac_addr[2]; 2262b760e38cSjmatthew 2263b760e38cSjmatthew memset(mac_addr, 0, sizeof(mac_addr)); 2264b760e38cSjmatthew AQ_READ_REGS(sc, AQ2_FW_INTERFACE_IN_MAC_ADDRESS_REG, 2265b760e38cSjmatthew mac_addr, nitems(mac_addr)); 2266b760e38cSjmatthew 2267d685096fSkettenis #ifdef __HAVE_FDT 2268d685096fSkettenis if (mac_addr[0] == 0 && mac_addr[1] == 0 && 2269d685096fSkettenis PCITAG_NODE(sc->sc_pcitag)) { 2270d685096fSkettenis OF_getprop(PCITAG_NODE(sc->sc_pcitag), "local-mac-address", 2271d685096fSkettenis mac_addr, ETHER_ADDR_LEN); 2272d685096fSkettenis } 2273d685096fSkettenis #endif 2274d685096fSkettenis 2275b760e38cSjmatthew if (mac_addr[0] == 0 && mac_addr[1] == 0) { 2276b760e38cSjmatthew printf(": mac address not found\n"); 2277b760e38cSjmatthew return ENXIO; 2278b760e38cSjmatthew } 2279b760e38cSjmatthew 2280b760e38cSjmatthew mac_addr[0] = htole32(mac_addr[0]); 2281b760e38cSjmatthew mac_addr[1] = htole32(mac_addr[1]); 2282b760e38cSjmatthew 2283b760e38cSjmatthew memcpy(sc->sc_enaddr.ether_addr_octet, 2284b760e38cSjmatthew (uint8_t *)mac_addr, ETHER_ADDR_LEN); 2285b760e38cSjmatthew return 0; 2286b760e38cSjmatthew } 2287b760e38cSjmatthew 2288b760e38cSjmatthew int 2289b760e38cSjmatthew aq2_fw_set_mode(struct aq_softc *sc, enum aq_hw_fw_mpi_state w, 2290b760e38cSjmatthew enum aq_link_speed speed, enum aq_link_fc fc, enum aq_link_eee eee) 2291b760e38cSjmatthew { 2292b760e38cSjmatthew uint32_t v, ov; 2293b760e38cSjmatthew int error; 2294b760e38cSjmatthew 2295b760e38cSjmatthew AQ_MPI_LOCK(sc); 2296b760e38cSjmatthew 2297b760e38cSjmatthew v = AQ_READ_REG(sc, AQ2_FW_INTERFACE_IN_LINK_OPTIONS_REG); 2298b760e38cSjmatthew v &= ~( 2299b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10G | 2300b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N5G | 2301b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_5G | 2302b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N2G5 | 2303b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_2G5 | 2304b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G | 2305b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M | 2306b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M | 2307b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G_HD | 2308b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M_HD | 2309b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M_HD); 2310b760e38cSjmatthew 2311b760e38cSjmatthew v &= ~AQ2_FW_INTERFACE_IN_LINK_OPTIONS_LINK_UP; 2312b760e38cSjmatthew ov = v; 2313b760e38cSjmatthew 2314b760e38cSjmatthew if (speed & AQ_LINK_10G) 2315b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10G; 2316b760e38cSjmatthew if (speed & AQ_LINK_5G) 2317b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N5G | 2318b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_5G; 2319b760e38cSjmatthew if (speed & AQ_LINK_2G5) 2320b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N2G5 | 2321b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_2G5; 2322b760e38cSjmatthew if (speed & AQ_LINK_1G) 2323b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G | 2324b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G_HD; 2325b760e38cSjmatthew if (speed & AQ_LINK_100M) 2326b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M | 2327b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M_HD; 2328b760e38cSjmatthew if (speed & AQ_LINK_10M) { 2329b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M | 2330b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M_HD; 2331b760e38cSjmatthew } 2332b760e38cSjmatthew 2333b760e38cSjmatthew /* flow control */ 2334b760e38cSjmatthew v &= ~(AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_TX | 2335b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_RX); 2336b760e38cSjmatthew if (fc & AQ_FC_TX) 2337b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_TX; 2338b760e38cSjmatthew if (fc & AQ_FC_RX) 2339b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_RX; 2340b760e38cSjmatthew 2341b760e38cSjmatthew if (speed == AQ_LINK_NONE) { 2342b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_FW_INTERFACE_IN_LINK_CONTROL_REG, 2343b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE, 2344b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_SHUTDOWN); 2345b760e38cSjmatthew } else { 2346b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_FW_INTERFACE_IN_LINK_CONTROL_REG, 2347b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE, 2348b760e38cSjmatthew AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_ACTIVE); 2349b760e38cSjmatthew v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_LINK_UP; 2350b760e38cSjmatthew } 2351b760e38cSjmatthew 2352b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_FW_INTERFACE_IN_LINK_OPTIONS_REG, v); 2353b760e38cSjmatthew error = aq2_fw_wait_shared_ack(sc); 2354b760e38cSjmatthew 2355b760e38cSjmatthew AQ_MPI_UNLOCK(sc); 2356b760e38cSjmatthew return error; 2357b760e38cSjmatthew } 2358b760e38cSjmatthew 2359b760e38cSjmatthew int 2360b760e38cSjmatthew aq2_fw_get_mode(struct aq_softc *sc, enum aq_hw_fw_mpi_state *modep, 2361b760e38cSjmatthew enum aq_link_speed *speedp, enum aq_link_fc *fcp, enum aq_link_eee *eeep) 2362b760e38cSjmatthew { 2363b760e38cSjmatthew uint32_t v; 2364b760e38cSjmatthew enum aq_link_speed speed; 2365b760e38cSjmatthew enum aq_link_fc fc = 0; 2366b760e38cSjmatthew enum aq_link_eee eee; 2367b760e38cSjmatthew 2368b760e38cSjmatthew if (modep != NULL) 2369b760e38cSjmatthew *modep = MPI_INIT; 2370b760e38cSjmatthew 2371b760e38cSjmatthew v = AQ_READ_REG(sc, AQ2_FW_INTERFACE_OUT_LINK_STATUS_REG); 2372b760e38cSjmatthew switch ((v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE) >> 2373b760e38cSjmatthew AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_S) { 2374b760e38cSjmatthew case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_10G: 2375b760e38cSjmatthew speed = AQ_LINK_10G; 2376b760e38cSjmatthew break; 2377b760e38cSjmatthew case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_5G: 2378b760e38cSjmatthew speed = AQ_LINK_5G; 2379b760e38cSjmatthew break; 2380b760e38cSjmatthew case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_2G5: 2381b760e38cSjmatthew speed = AQ_LINK_2G5; 2382b760e38cSjmatthew break; 2383b760e38cSjmatthew case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_1G: 2384b760e38cSjmatthew speed = AQ_LINK_1G; 2385b760e38cSjmatthew break; 2386b760e38cSjmatthew case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_100M: 2387b760e38cSjmatthew speed = AQ_LINK_100M; 2388b760e38cSjmatthew break; 2389b760e38cSjmatthew case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_10M: 2390b760e38cSjmatthew speed = AQ_LINK_10M; 2391b760e38cSjmatthew break; 2392b760e38cSjmatthew case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_INVALID: 2393b760e38cSjmatthew default: 2394b760e38cSjmatthew speed = AQ_LINK_NONE; 2395b760e38cSjmatthew break; 2396b760e38cSjmatthew } 2397b760e38cSjmatthew if (speedp != NULL) 2398b760e38cSjmatthew *speedp = speed; 2399b760e38cSjmatthew 2400b760e38cSjmatthew if (v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_PAUSE_TX) 2401b760e38cSjmatthew fc |= AQ_FC_TX; 2402b760e38cSjmatthew if (v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_PAUSE_RX) 2403b760e38cSjmatthew fc |= AQ_FC_RX; 2404b760e38cSjmatthew if (fcp != NULL) 2405b760e38cSjmatthew *fcp = fc; 2406b760e38cSjmatthew 2407b760e38cSjmatthew eee = (v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_EEE) ? 2408b760e38cSjmatthew AQ_EEE_ENABLE : AQ_EEE_DISABLE; 2409b760e38cSjmatthew if (eeep != NULL) 2410b760e38cSjmatthew *eeep = eee; 2411b760e38cSjmatthew 2412b760e38cSjmatthew return 0; 2413b760e38cSjmatthew } 2414b760e38cSjmatthew 2415b760e38cSjmatthew int 2416b760e38cSjmatthew aq2_fw_get_stats(struct aq_softc *sc, struct aq_hw_stats_s *w) 2417b760e38cSjmatthew { 2418b760e38cSjmatthew return 0; 2419b760e38cSjmatthew } 2420b760e38cSjmatthew 2421bccaee56Smlarkin void 2422bccaee56Smlarkin aq_hw_l3_filter_set(struct aq_softc *sc) 2423bccaee56Smlarkin { 2424bccaee56Smlarkin int i; 2425bccaee56Smlarkin 2426bccaee56Smlarkin /* clear all filter */ 2427bccaee56Smlarkin for (i = 0; i < 8; i++) { 2428bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L3_FILTER_REG(i), 2429bccaee56Smlarkin RPF_L3_FILTER_L4_EN, 0); 2430bccaee56Smlarkin } 2431bccaee56Smlarkin } 2432bccaee56Smlarkin 2433bccaee56Smlarkin int 24341d7ac227Sjmatthew aq_hw_init(struct aq_softc *sc, int irqmode, int multivec) 2435bccaee56Smlarkin { 2436bccaee56Smlarkin uint32_t v; 2437bccaee56Smlarkin 2438b760e38cSjmatthew if (HWTYPE_AQ1_P(sc)) { 2439bccaee56Smlarkin /* Force limit MRRS on RDM/TDM to 2K */ 2440bccaee56Smlarkin v = AQ_READ_REG(sc, AQ_PCI_REG_CONTROL_6_REG); 2441b760e38cSjmatthew AQ_WRITE_REG(sc, AQ_PCI_REG_CONTROL_6_REG, 2442b760e38cSjmatthew (v & ~0x0707) | 0x0404); 2443bccaee56Smlarkin 2444bccaee56Smlarkin /* 2445bccaee56Smlarkin * TX DMA total request limit. B0 hardware is not capable to 2446bccaee56Smlarkin * handle more than (8K-MRRS) incoming DMA data. 2447bccaee56Smlarkin * Value 24 in 256byte units 2448bccaee56Smlarkin */ 2449bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_HW_TX_DMA_TOTAL_REQ_LIMIT_REG, 24); 2450b760e38cSjmatthew } 2451b760e38cSjmatthew 2452b760e38cSjmatthew if (HWTYPE_AQ2_P(sc)) { 2453b760e38cSjmatthew uint32_t fpgaver, speed; 2454b760e38cSjmatthew fpgaver = AQ_READ_REG(sc, AQ2_HW_FPGA_VERSION_REG); 2455b760e38cSjmatthew if (fpgaver < 0x01000000) 2456b760e38cSjmatthew speed = AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_FULL; 2457b760e38cSjmatthew else if (fpgaver >= 0x01008502) 2458b760e38cSjmatthew speed = AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_HALF; 2459b760e38cSjmatthew else 2460b760e38cSjmatthew speed = AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_QUARTER; 2461b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_LAUNCHTIME_CTRL_REG, 2462b760e38cSjmatthew AQ2_LAUNCHTIME_CTRL_RATIO, speed); 2463b760e38cSjmatthew } 2464bccaee56Smlarkin 2465bccaee56Smlarkin aq_hw_init_tx_path(sc); 2466bccaee56Smlarkin aq_hw_init_rx_path(sc); 2467bccaee56Smlarkin 2468bccaee56Smlarkin if (aq_set_mac_addr(sc, AQ_HW_MAC_OWN, sc->sc_enaddr.ether_addr_octet)) 2469bccaee56Smlarkin return EINVAL; 2470bccaee56Smlarkin 2471bccaee56Smlarkin aq_set_linkmode(sc, AQ_LINK_NONE, AQ_FC_NONE, AQ_EEE_DISABLE); 2472bccaee56Smlarkin 2473bccaee56Smlarkin aq_hw_qos_set(sc); 2474bccaee56Smlarkin 2475b760e38cSjmatthew if (HWTYPE_AQ2_P(sc)) { 2476b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_RPF_NEW_CTRL_REG, 2477b760e38cSjmatthew AQ2_RPF_NEW_CTRL_ENABLE, 1); 2478b760e38cSjmatthew } 2479b760e38cSjmatthew 2480bccaee56Smlarkin /* Enable interrupt */ 2481bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_INTR_CTRL_REG, AQ_INTR_CTRL_RESET_DIS); 24821d7ac227Sjmatthew AQ_WRITE_REG_BIT(sc, AQ_INTR_CTRL_REG, AQ_INTR_CTRL_MULTIVEC, multivec); 2483bccaee56Smlarkin 2484bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, AQ_INTR_CTRL_REG, AQ_INTR_CTRL_IRQMODE, irqmode); 2485bccaee56Smlarkin 2486bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_INTR_AUTOMASK_REG, 0xffffffff); 2487bccaee56Smlarkin 2488bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_GEN_INTR_MAP_REG(0), 2489bccaee56Smlarkin ((AQ_B0_ERR_INT << 24) | (1U << 31)) | 2490bccaee56Smlarkin ((AQ_B0_ERR_INT << 16) | (1 << 23)) 2491bccaee56Smlarkin ); 2492bccaee56Smlarkin 2493bccaee56Smlarkin /* link interrupt */ 2494bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_GEN_INTR_MAP_REG(3), 2495bccaee56Smlarkin (1 << 7) | sc->sc_linkstat_irq); 2496bccaee56Smlarkin 2497bccaee56Smlarkin return 0; 2498bccaee56Smlarkin } 2499bccaee56Smlarkin 2500bccaee56Smlarkin void 2501bccaee56Smlarkin aq_hw_init_tx_path(struct aq_softc *sc) 2502bccaee56Smlarkin { 2503bccaee56Smlarkin /* Tx TC/RSS number config */ 2504bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPB_TX_BUF_REG, TPB_TX_BUF_TC_MODE_EN, 1); 2505bccaee56Smlarkin 2506bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, THM_LSO_TCP_FLAG1_REG, 2507bccaee56Smlarkin THM_LSO_TCP_FLAG1_FIRST, 0x0ff6); 2508bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, THM_LSO_TCP_FLAG1_REG, 2509bccaee56Smlarkin THM_LSO_TCP_FLAG1_MID, 0x0ff6); 2510bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, THM_LSO_TCP_FLAG2_REG, 2511bccaee56Smlarkin THM_LSO_TCP_FLAG2_LAST, 0x0f7f); 2512bccaee56Smlarkin 2513bccaee56Smlarkin /* misc */ 2514bccaee56Smlarkin AQ_WRITE_REG(sc, TX_TPO2_REG, 2515bccaee56Smlarkin (sc->sc_features & FEATURES_TPO2) ? TX_TPO2_EN : 0); 2516bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TDM_DCA_REG, TDM_DCA_EN, 0); 2517bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TDM_DCA_REG, TDM_DCA_MODE, 0); 2518bccaee56Smlarkin 2519bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPB_TX_BUF_REG, TPB_TX_BUF_SCP_INS_EN, 1); 2520b760e38cSjmatthew 2521b760e38cSjmatthew if ((sc->sc_features & FEATURES_AQ1_REV_B) || HWTYPE_AQ2_P(sc)) { 2522b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, TPB_TX_BUF_REG, TPB_TX_BUF_CLK_GATE_EN, 0); 2523b760e38cSjmatthew } 2524bccaee56Smlarkin } 2525bccaee56Smlarkin 2526bccaee56Smlarkin void 2527bccaee56Smlarkin aq_hw_init_rx_path(struct aq_softc *sc) 2528bccaee56Smlarkin { 2529bccaee56Smlarkin int i; 2530bccaee56Smlarkin 2531bccaee56Smlarkin /* clear setting */ 2532bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_TC_MODE, 0); 2533bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_FC_MODE, 0); 2534b760e38cSjmatthew 2535b760e38cSjmatthew if (HWTYPE_AQ2_P(sc)) { 2536b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_RPF_REDIR2_REG, 2537b760e38cSjmatthew AQ2_RPF_REDIR2_HASHTYPE, AQ2_RPF_REDIR2_HASHTYPE_ALL); 2538bccaee56Smlarkin } 2539bccaee56Smlarkin 2540190bcc8eSjmatthew if (sc->sc_nqueues > 1) { 2541190bcc8eSjmatthew uint32_t bits; 2542190bcc8eSjmatthew 2543190bcc8eSjmatthew AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_TC_MODE, 1); 2544190bcc8eSjmatthew AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_FC_MODE, 1); 2545190bcc8eSjmatthew 2546190bcc8eSjmatthew switch (sc->sc_nqueues) { 2547190bcc8eSjmatthew case 2: 2548190bcc8eSjmatthew bits = 0x11111111; 2549190bcc8eSjmatthew break; 2550190bcc8eSjmatthew case 4: 2551190bcc8eSjmatthew bits = 0x22222222; 2552190bcc8eSjmatthew break; 2553190bcc8eSjmatthew case 8: 2554190bcc8eSjmatthew bits = 0x33333333; 2555190bcc8eSjmatthew break; 2556190bcc8eSjmatthew } 2557190bcc8eSjmatthew 2558190bcc8eSjmatthew AQ_WRITE_REG(sc, RX_FLR_RSS_CONTROL1_REG, 2559190bcc8eSjmatthew RX_FLR_RSS_CONTROL1_EN | bits); 2560b760e38cSjmatthew } else { 2561b760e38cSjmatthew AQ_WRITE_REG(sc, RX_FLR_RSS_CONTROL1_REG, 0); 2562b760e38cSjmatthew } 2563b760e38cSjmatthew 2564b760e38cSjmatthew if (HWTYPE_AQ1_P(sc)) { 2565b760e38cSjmatthew for (i = 0; i < 32; i++) { 2566b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, RPF_ETHERTYPE_FILTER_REG(i), 2567b760e38cSjmatthew RPF_ETHERTYPE_FILTER_EN, 0); 2568b760e38cSjmatthew } 2569190bcc8eSjmatthew } 2570190bcc8eSjmatthew 2571bccaee56Smlarkin /* L2 and Multicast filters */ 2572bccaee56Smlarkin for (i = 0; i < AQ_HW_MAC_NUM; i++) { 2573bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(i), RPF_L2UC_MSW_EN, 0); 2574bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(i), RPF_L2UC_MSW_ACTION, 2575bccaee56Smlarkin RPF_ACTION_HOST); 2576bccaee56Smlarkin } 2577bccaee56Smlarkin AQ_WRITE_REG(sc, RPF_MCAST_FILTER_MASK_REG, 0); 2578bccaee56Smlarkin AQ_WRITE_REG(sc, RPF_MCAST_FILTER_REG(0), 0x00010fff); 2579bccaee56Smlarkin 2580bccaee56Smlarkin /* Vlan filters */ 2581bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_VLAN_TPID_REG, RPF_VLAN_TPID_OUTER, 2582bccaee56Smlarkin ETHERTYPE_QINQ); 2583bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_VLAN_TPID_REG, RPF_VLAN_TPID_INNER, 2584bccaee56Smlarkin ETHERTYPE_VLAN); 258531f14b89Sjmatthew AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, RPF_VLAN_MODE_PROMISC, 1); 2586bccaee56Smlarkin 2587b760e38cSjmatthew if ((sc->sc_features & FEATURES_AQ1_REV_B) || HWTYPE_AQ2_P(sc)) { 2588bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, 2589bccaee56Smlarkin RPF_VLAN_MODE_ACCEPT_UNTAGGED, 1); 2590bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, 2591bccaee56Smlarkin RPF_VLAN_MODE_UNTAGGED_ACTION, RPF_ACTION_HOST); 2592bccaee56Smlarkin } 2593bccaee56Smlarkin 2594b760e38cSjmatthew if (HWTYPE_AQ2_P(sc)) { 2595b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_RPF_REC_TAB_ENABLE_REG, 2596b760e38cSjmatthew AQ2_RPF_REC_TAB_ENABLE_MASK, 0xffff); 2597b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(0), 2598b760e38cSjmatthew RPF_L2UC_MSW_TAG, 1); 2599b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, AQ2_RPF_L2BC_TAG_REG, 2600b760e38cSjmatthew AQ2_RPF_L2BC_TAG_MASK, 1); 2601b760e38cSjmatthew 2602b760e38cSjmatthew aq2_filter_art_set(sc, AQ2_RPF_INDEX_L2_PROMISC_OFF, 2603b760e38cSjmatthew 0, AQ2_RPF_TAG_UC_MASK | AQ2_RPF_TAG_ALLMC_MASK, 2604b760e38cSjmatthew AQ2_ART_ACTION_DROP); 2605b760e38cSjmatthew aq2_filter_art_set(sc, AQ2_RPF_INDEX_VLAN_PROMISC_OFF, 2606b760e38cSjmatthew 0, AQ2_RPF_TAG_VLAN_MASK | AQ2_RPF_TAG_UNTAG_MASK, 2607b760e38cSjmatthew AQ2_ART_ACTION_DROP); 2608b760e38cSjmatthew 2609cd4a963cSjsg for (i = 0; i < 8; i++) { 2610b760e38cSjmatthew aq2_filter_art_set(sc, AQ2_RPF_INDEX_PCP_TO_TC + i, 2611b760e38cSjmatthew (i << AQ2_RPF_TAG_PCP_SHIFT), AQ2_RPF_TAG_PCP_MASK, 2612b760e38cSjmatthew AQ2_ART_ACTION_ASSIGN_TC(i % sc->sc_nqueues)); 2613b760e38cSjmatthew } 2614b760e38cSjmatthew 2615b760e38cSjmatthew } else if (HWTYPE_AQ1_P(sc)) { 2616190bcc8eSjmatthew if (sc->sc_features & FEATURES_RPF2) 2617b760e38cSjmatthew AQ_WRITE_REG(sc, RX_TCP_RSS_HASH_REG, 2618b760e38cSjmatthew RX_TCP_RSS_HASH_RPF2); 2619190bcc8eSjmatthew else 2620bccaee56Smlarkin AQ_WRITE_REG(sc, RX_TCP_RSS_HASH_REG, 0); 2621bccaee56Smlarkin 2622190bcc8eSjmatthew /* we might want to figure out what this magic number does */ 2623b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, RX_TCP_RSS_HASH_REG, 2624b760e38cSjmatthew RX_TCP_RSS_HASH_TYPE, 0x001e); 2625b760e38cSjmatthew } 2626190bcc8eSjmatthew 2627bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2BC_REG, RPF_L2BC_EN, 1); 2628bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2BC_REG, RPF_L2BC_ACTION, RPF_ACTION_HOST); 2629bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2BC_REG, RPF_L2BC_THRESHOLD, 0xffff); 2630bccaee56Smlarkin 2631bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DCA_REG, RX_DMA_DCA_EN, 0); 2632bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DCA_REG, RX_DMA_DCA_MODE, 0); 2633bccaee56Smlarkin } 2634bccaee56Smlarkin 2635bccaee56Smlarkin /* set multicast filter. index 0 for own address */ 2636bccaee56Smlarkin int 2637bccaee56Smlarkin aq_set_mac_addr(struct aq_softc *sc, int index, uint8_t *enaddr) 2638bccaee56Smlarkin { 2639bccaee56Smlarkin uint32_t h, l; 2640bccaee56Smlarkin 2641bccaee56Smlarkin if (index >= AQ_HW_MAC_NUM) 2642bccaee56Smlarkin return EINVAL; 2643bccaee56Smlarkin 2644bccaee56Smlarkin if (enaddr == NULL) { 2645bccaee56Smlarkin /* disable */ 2646bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, 2647bccaee56Smlarkin RPF_L2UC_MSW_REG(index), RPF_L2UC_MSW_EN, 0); 2648bccaee56Smlarkin return 0; 2649bccaee56Smlarkin } 2650bccaee56Smlarkin 2651bccaee56Smlarkin h = (enaddr[0] << 8) | (enaddr[1]); 2652bccaee56Smlarkin l = ((uint32_t)enaddr[2] << 24) | (enaddr[3] << 16) | 2653bccaee56Smlarkin (enaddr[4] << 8) | (enaddr[5]); 2654bccaee56Smlarkin 2655bccaee56Smlarkin /* disable, set, and enable */ 2656bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index), RPF_L2UC_MSW_EN, 0); 2657bccaee56Smlarkin AQ_WRITE_REG(sc, RPF_L2UC_LSW_REG(index), l); 2658bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index), 2659bccaee56Smlarkin RPF_L2UC_MSW_MACADDR_HI, h); 2660b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index), 2661b760e38cSjmatthew RPF_L2UC_MSW_ACTION, RPF_ACTION_HOST); 2662b760e38cSjmatthew if (HWTYPE_AQ2_P(sc)) 2663b760e38cSjmatthew AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index), 2664b760e38cSjmatthew RPF_L2UC_MSW_TAG, 1); 2665bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index), RPF_L2UC_MSW_EN, 1); 2666bccaee56Smlarkin 2667bccaee56Smlarkin return 0; 2668bccaee56Smlarkin } 2669bccaee56Smlarkin 2670bccaee56Smlarkin int 2671bccaee56Smlarkin aq_get_linkmode(struct aq_softc *sc, enum aq_link_speed *speed, 2672bccaee56Smlarkin enum aq_link_fc *fc, enum aq_link_eee *eee) 2673bccaee56Smlarkin { 2674bccaee56Smlarkin enum aq_hw_fw_mpi_state mode; 2675bccaee56Smlarkin int error; 2676bccaee56Smlarkin 2677bccaee56Smlarkin error = sc->sc_fw_ops->get_mode(sc, &mode, speed, fc, eee); 2678bccaee56Smlarkin if (error != 0) 2679bccaee56Smlarkin return error; 2680bccaee56Smlarkin if (mode != MPI_INIT) 2681bccaee56Smlarkin return ENXIO; 2682bccaee56Smlarkin 2683bccaee56Smlarkin return 0; 2684bccaee56Smlarkin } 2685bccaee56Smlarkin 2686bccaee56Smlarkin int 2687bccaee56Smlarkin aq_set_linkmode(struct aq_softc *sc, enum aq_link_speed speed, 2688bccaee56Smlarkin enum aq_link_fc fc, enum aq_link_eee eee) 2689bccaee56Smlarkin { 2690bccaee56Smlarkin return sc->sc_fw_ops->set_mode(sc, MPI_INIT, speed, fc, eee); 2691bccaee56Smlarkin } 2692bccaee56Smlarkin 2693bccaee56Smlarkin int 2694bccaee56Smlarkin aq_fw2x_set_mode(struct aq_softc *sc, enum aq_hw_fw_mpi_state mode, 2695bccaee56Smlarkin enum aq_link_speed speed, enum aq_link_fc fc, enum aq_link_eee eee) 2696bccaee56Smlarkin { 2697bccaee56Smlarkin uint64_t mpi_ctrl; 2698bccaee56Smlarkin int error = 0; 2699bccaee56Smlarkin 2700bccaee56Smlarkin AQ_MPI_LOCK(sc); 2701bccaee56Smlarkin 2702bccaee56Smlarkin mpi_ctrl = AQ_READ64_REG(sc, FW2X_MPI_CONTROL_REG); 2703bccaee56Smlarkin 2704bccaee56Smlarkin switch (mode) { 2705bccaee56Smlarkin case MPI_INIT: 2706bccaee56Smlarkin mpi_ctrl &= ~FW2X_CTRL_RATE_MASK; 2707bccaee56Smlarkin if (speed & AQ_LINK_10G) 2708bccaee56Smlarkin mpi_ctrl |= FW2X_CTRL_RATE_10G; 2709bccaee56Smlarkin if (speed & AQ_LINK_5G) 2710bccaee56Smlarkin mpi_ctrl |= FW2X_CTRL_RATE_5G; 2711bccaee56Smlarkin if (speed & AQ_LINK_2G5) 2712bccaee56Smlarkin mpi_ctrl |= FW2X_CTRL_RATE_2G5; 2713bccaee56Smlarkin if (speed & AQ_LINK_1G) 2714bccaee56Smlarkin mpi_ctrl |= FW2X_CTRL_RATE_1G; 2715bccaee56Smlarkin if (speed & AQ_LINK_100M) 2716bccaee56Smlarkin mpi_ctrl |= FW2X_CTRL_RATE_100M; 2717bccaee56Smlarkin 2718bccaee56Smlarkin mpi_ctrl &= ~FW2X_CTRL_LINK_DROP; 2719bccaee56Smlarkin 2720bccaee56Smlarkin mpi_ctrl &= ~FW2X_CTRL_EEE_MASK; 2721bccaee56Smlarkin if (eee == AQ_EEE_ENABLE) 2722bccaee56Smlarkin mpi_ctrl |= FW2X_CTRL_EEE_MASK; 2723bccaee56Smlarkin 2724bccaee56Smlarkin mpi_ctrl &= ~(FW2X_CTRL_PAUSE | FW2X_CTRL_ASYMMETRIC_PAUSE); 2725bccaee56Smlarkin if (fc & AQ_FC_RX) 2726bccaee56Smlarkin mpi_ctrl |= FW2X_CTRL_PAUSE; 2727bccaee56Smlarkin if (fc & AQ_FC_TX) 2728bccaee56Smlarkin mpi_ctrl |= FW2X_CTRL_ASYMMETRIC_PAUSE; 2729bccaee56Smlarkin break; 2730bccaee56Smlarkin case MPI_DEINIT: 2731bccaee56Smlarkin mpi_ctrl &= ~(FW2X_CTRL_RATE_MASK | FW2X_CTRL_EEE_MASK); 2732bccaee56Smlarkin mpi_ctrl &= ~(FW2X_CTRL_PAUSE | FW2X_CTRL_ASYMMETRIC_PAUSE); 2733bccaee56Smlarkin break; 2734bccaee56Smlarkin default: 2735bccaee56Smlarkin printf("%s: fw2x> unknown MPI state %d\n", DEVNAME(sc), mode); 2736bccaee56Smlarkin error = EINVAL; 2737bccaee56Smlarkin goto failure; 2738bccaee56Smlarkin } 2739bccaee56Smlarkin AQ_WRITE64_REG(sc, FW2X_MPI_CONTROL_REG, mpi_ctrl); 2740bccaee56Smlarkin 2741bccaee56Smlarkin failure: 2742bccaee56Smlarkin AQ_MPI_UNLOCK(sc); 2743bccaee56Smlarkin return error; 2744bccaee56Smlarkin } 2745bccaee56Smlarkin 2746bccaee56Smlarkin void 2747bccaee56Smlarkin aq_hw_qos_set(struct aq_softc *sc) 2748bccaee56Smlarkin { 2749bccaee56Smlarkin uint32_t tc = 0; 2750bccaee56Smlarkin uint32_t buff_size; 2751bccaee56Smlarkin 2752bccaee56Smlarkin /* TPS Descriptor rate init */ 2753bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPS_DESC_RATE_REG, TPS_DESC_RATE_TA_RST, 0); 2754bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPS_DESC_RATE_REG, TPS_DESC_RATE_LIM, 0xa); 2755bccaee56Smlarkin 2756bccaee56Smlarkin /* TPS VM init */ 2757bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPS_DESC_VM_ARB_MODE_REG, TPS_DESC_VM_ARB_MODE, 0); 2758bccaee56Smlarkin 2759bccaee56Smlarkin /* TPS TC credits init */ 2760bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPS_DESC_TC_ARB_MODE_REG, TPS_DESC_TC_ARB_MODE, 0); 2761bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPS_DATA_TC_ARB_MODE_REG, TPS_DATA_TC_ARB_MODE, 0); 2762bccaee56Smlarkin 27635bd4e6eeSkettenis if (HWTYPE_AQ2_P(sc)) { 27645bd4e6eeSkettenis AQ_WRITE_REG_BIT(sc, TPS_DATA_TCT_REG(tc), 27655bd4e6eeSkettenis TPS2_DATA_TCT_CREDIT_MAX, 0xfff0); 27665bd4e6eeSkettenis AQ_WRITE_REG_BIT(sc, TPS_DATA_TCT_REG(tc), 27675bd4e6eeSkettenis TPS2_DATA_TCT_WEIGHT, 0x640); 27685bd4e6eeSkettenis } else { 2769bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPS_DATA_TCT_REG(tc), 2770bccaee56Smlarkin TPS_DATA_TCT_CREDIT_MAX, 0xfff); 2771bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPS_DATA_TCT_REG(tc), 2772bccaee56Smlarkin TPS_DATA_TCT_WEIGHT, 0x64); 27735bd4e6eeSkettenis } 2774bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPS_DESC_TCT_REG(tc), 2775bccaee56Smlarkin TPS_DESC_TCT_CREDIT_MAX, 0x50); 2776bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPS_DESC_TCT_REG(tc), 2777bccaee56Smlarkin TPS_DESC_TCT_WEIGHT, 0x1e); 2778bccaee56Smlarkin 2779bccaee56Smlarkin /* Tx buf size */ 2780bccaee56Smlarkin tc = 0; 27815bd4e6eeSkettenis buff_size = HWTYPE_AQ2_P(sc) ? AQ2_HW_TXBUF_MAX : AQ_HW_TXBUF_MAX; 2782bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPB_TXB_BUFSIZE_REG(tc), TPB_TXB_BUFSIZE, 2783bccaee56Smlarkin buff_size); 2784bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPB_TXB_THRESH_REG(tc), TPB_TXB_THRESH_HI, 2785bccaee56Smlarkin (buff_size * (1024 / 32) * 66) / 100); 2786bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPB_TXB_THRESH_REG(tc), TPB_TXB_THRESH_LO, 2787bccaee56Smlarkin (buff_size * (1024 / 32) * 50) / 100); 2788bccaee56Smlarkin 2789bccaee56Smlarkin /* QoS Rx buf size per TC */ 2790bccaee56Smlarkin tc = 0; 27915bd4e6eeSkettenis buff_size = HWTYPE_AQ2_P(sc) ? AQ2_HW_RXBUF_MAX : AQ_HW_RXBUF_MAX; 2792bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPB_RXB_BUFSIZE_REG(tc), RPB_RXB_BUFSIZE, 2793bccaee56Smlarkin buff_size); 2794bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPB_RXB_XOFF_REG(tc), RPB_RXB_XOFF_EN, 0); 2795bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPB_RXB_XOFF_REG(tc), RPB_RXB_XOFF_THRESH_HI, 2796bccaee56Smlarkin (buff_size * (1024 / 32) * 66) / 100); 2797bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPB_RXB_XOFF_REG(tc), RPB_RXB_XOFF_THRESH_LO, 2798bccaee56Smlarkin (buff_size * (1024 / 32) * 50) / 100); 2799bccaee56Smlarkin 2800bccaee56Smlarkin /* QoS 802.1p priority -> TC mapping */ 2801bccaee56Smlarkin int i_priority; 2802bccaee56Smlarkin for (i_priority = 0; i_priority < 8; i_priority++) { 2803bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_RPB_RX_TC_UPT_REG, 2804bccaee56Smlarkin RPF_RPB_RX_TC_UPT_MASK(i_priority), 0); 2805bccaee56Smlarkin } 2806bccaee56Smlarkin } 2807bccaee56Smlarkin 2808190bcc8eSjmatthew int 2809190bcc8eSjmatthew aq_init_rss(struct aq_softc *sc) 2810190bcc8eSjmatthew { 2811190bcc8eSjmatthew uint32_t rss_key[AQ_RSS_KEYSIZE / sizeof(uint32_t)]; 2812190bcc8eSjmatthew uint32_t redir; 2813190bcc8eSjmatthew int bits, queue; 2814190bcc8eSjmatthew int error; 2815190bcc8eSjmatthew int i; 2816190bcc8eSjmatthew 2817190bcc8eSjmatthew if (sc->sc_nqueues == 1) 2818190bcc8eSjmatthew return 0; 2819190bcc8eSjmatthew 2820190bcc8eSjmatthew /* rss key is composed of 32 bit registers */ 2821190bcc8eSjmatthew stoeplitz_to_key(rss_key, sizeof(rss_key)); 2822190bcc8eSjmatthew for (i = 0; i < nitems(rss_key); i++) { 2823*175a7a0dSjmatthew AQ_WRITE_REG(sc, RPF_RSS_KEY_WR_DATA_REG, htobe32(rss_key[i])); 2824190bcc8eSjmatthew AQ_WRITE_REG_BIT(sc, RPF_RSS_KEY_ADDR_REG, RPF_RSS_KEY_ADDR, 2825190bcc8eSjmatthew nitems(rss_key) - 1 - i); 2826190bcc8eSjmatthew AQ_WRITE_REG_BIT(sc, RPF_RSS_KEY_ADDR_REG, RPF_RSS_KEY_WR_EN, 2827190bcc8eSjmatthew 1); 2828190bcc8eSjmatthew WAIT_FOR((AQ_READ_REG(sc, RPF_RSS_KEY_ADDR_REG) & 2829190bcc8eSjmatthew RPF_RSS_KEY_WR_EN) == 0, 1000, 10, &error); 2830190bcc8eSjmatthew if (error != 0) { 2831190bcc8eSjmatthew printf(": timed out setting rss key\n"); 2832190bcc8eSjmatthew return error; 2833190bcc8eSjmatthew } 2834190bcc8eSjmatthew } 2835190bcc8eSjmatthew 2836190bcc8eSjmatthew /* 2837190bcc8eSjmatthew * the redirection table has 64 entries, each entry is a 3 bit 2838190bcc8eSjmatthew * queue number, packed into a 16 bit register, so there are 12 2839190bcc8eSjmatthew * registers to program. 2840190bcc8eSjmatthew */ 2841190bcc8eSjmatthew bits = 0; 2842190bcc8eSjmatthew redir = 0; 2843190bcc8eSjmatthew queue = 0; 2844190bcc8eSjmatthew for (i = 0; i < AQ_RSS_REDIR_ENTRIES; i++) { 2845190bcc8eSjmatthew while (bits < 16) { 2846190bcc8eSjmatthew redir |= (queue << bits); 2847190bcc8eSjmatthew bits += 3; 2848190bcc8eSjmatthew queue++; 2849190bcc8eSjmatthew if (queue == sc->sc_nqueues) 2850190bcc8eSjmatthew queue = 0; 2851190bcc8eSjmatthew } 2852190bcc8eSjmatthew 2853190bcc8eSjmatthew AQ_WRITE_REG(sc, RPF_RSS_REDIR_WR_DATA_REG, htole16(redir)); 2854190bcc8eSjmatthew AQ_WRITE_REG_BIT(sc, RPF_RSS_REDIR_ADDR_REG, RPF_RSS_REDIR_ADDR, 2855190bcc8eSjmatthew i); 2856190bcc8eSjmatthew AQ_WRITE_REG_BIT(sc, RPF_RSS_REDIR_ADDR_REG, 2857190bcc8eSjmatthew RPF_RSS_REDIR_WR_EN, 1); 2858190bcc8eSjmatthew WAIT_FOR((AQ_READ_REG(sc, RPF_RSS_REDIR_ADDR_REG) & 2859190bcc8eSjmatthew RPF_RSS_REDIR_WR_EN) == 0, 1000, 10, &error); 2860190bcc8eSjmatthew if (error != 0) { 2861190bcc8eSjmatthew printf(": timed out setting rss table\n"); 2862190bcc8eSjmatthew return error; 2863190bcc8eSjmatthew } 2864190bcc8eSjmatthew redir >>= 16; 2865190bcc8eSjmatthew bits -= 16; 2866190bcc8eSjmatthew } 2867190bcc8eSjmatthew 2868190bcc8eSjmatthew return 0; 2869190bcc8eSjmatthew } 2870190bcc8eSjmatthew 2871bccaee56Smlarkin void 2872bccaee56Smlarkin aq_txring_reset(struct aq_softc *sc, struct aq_txring *tx, int start) 2873bccaee56Smlarkin { 2874bccaee56Smlarkin daddr_t paddr; 2875bccaee56Smlarkin 2876bccaee56Smlarkin tx->tx_prod = 0; 2877bccaee56Smlarkin tx->tx_cons = 0; 2878bccaee56Smlarkin 2879bccaee56Smlarkin /* empty slots? */ 2880bccaee56Smlarkin 2881bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TX_DMA_DESC_REG(tx->tx_q), TX_DMA_DESC_EN, 0); 2882bccaee56Smlarkin 2883bccaee56Smlarkin if (start == 0) 2884bccaee56Smlarkin return; 2885bccaee56Smlarkin 2886bccaee56Smlarkin paddr = AQ_DMA_DVA(&tx->tx_mem); 2887bccaee56Smlarkin AQ_WRITE_REG(sc, TX_DMA_DESC_BASE_ADDRLSW_REG(tx->tx_q), paddr); 2888bccaee56Smlarkin AQ_WRITE_REG(sc, TX_DMA_DESC_BASE_ADDRMSW_REG(tx->tx_q), 2889bccaee56Smlarkin paddr >> 32); 2890bccaee56Smlarkin 2891bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TX_DMA_DESC_REG(tx->tx_q), TX_DMA_DESC_LEN, 2892bccaee56Smlarkin AQ_TXD_NUM / 8); 2893bccaee56Smlarkin 2894bccaee56Smlarkin tx->tx_prod = AQ_READ_REG(sc, TX_DMA_DESC_TAIL_PTR_REG(tx->tx_q)); 2895bccaee56Smlarkin tx->tx_cons = tx->tx_prod; 2896bccaee56Smlarkin AQ_WRITE_REG(sc, TX_DMA_DESC_WRWB_THRESH_REG(tx->tx_q), 0); 2897bccaee56Smlarkin 2898bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, AQ_INTR_IRQ_MAP_TX_REG(tx->tx_q), 2899bccaee56Smlarkin AQ_INTR_IRQ_MAP_TX_IRQMAP(tx->tx_q), tx->tx_irq); 2900bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, AQ_INTR_IRQ_MAP_TX_REG(tx->tx_q), 2901bccaee56Smlarkin AQ_INTR_IRQ_MAP_TX_EN(tx->tx_q), 1); 2902bccaee56Smlarkin 2903bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TX_DMA_DESC_REG(tx->tx_q), TX_DMA_DESC_EN, 1); 2904bccaee56Smlarkin 2905bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TDM_DCAD_REG(tx->tx_q), TDM_DCAD_CPUID, 0); 2906bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TDM_DCAD_REG(tx->tx_q), TDM_DCAD_CPUID_EN, 0); 2907bccaee56Smlarkin } 2908bccaee56Smlarkin 2909bccaee56Smlarkin void 2910bccaee56Smlarkin aq_rxring_reset(struct aq_softc *sc, struct aq_rxring *rx, int start) 2911bccaee56Smlarkin { 2912bccaee56Smlarkin daddr_t paddr; 291331f14b89Sjmatthew int strip; 2914bccaee56Smlarkin 2915bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DESC_REG(rx->rx_q), RX_DMA_DESC_EN, 0); 2916bccaee56Smlarkin /* drain */ 2917bccaee56Smlarkin 2918bccaee56Smlarkin if (start == 0) 2919bccaee56Smlarkin return; 2920bccaee56Smlarkin 2921bccaee56Smlarkin paddr = AQ_DMA_DVA(&rx->rx_mem); 2922bccaee56Smlarkin AQ_WRITE_REG(sc, RX_DMA_DESC_BASE_ADDRLSW_REG(rx->rx_q), paddr); 2923bccaee56Smlarkin AQ_WRITE_REG(sc, RX_DMA_DESC_BASE_ADDRMSW_REG(rx->rx_q), 2924bccaee56Smlarkin paddr >> 32); 2925bccaee56Smlarkin 2926bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DESC_REG(rx->rx_q), RX_DMA_DESC_LEN, 2927bccaee56Smlarkin AQ_RXD_NUM / 8); 2928bccaee56Smlarkin 2929bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DESC_BUFSIZE_REG(rx->rx_q), 2930bccaee56Smlarkin RX_DMA_DESC_BUFSIZE_DATA, MCLBYTES / 1024); 2931bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DESC_BUFSIZE_REG(rx->rx_q), 2932bccaee56Smlarkin RX_DMA_DESC_BUFSIZE_HDR, 0); 2933bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DESC_REG(rx->rx_q), 2934bccaee56Smlarkin RX_DMA_DESC_HEADER_SPLIT, 0); 293531f14b89Sjmatthew 293631f14b89Sjmatthew #if NVLAN > 0 293731f14b89Sjmatthew strip = 1; 293831f14b89Sjmatthew #else 293931f14b89Sjmatthew strip = 0; 294031f14b89Sjmatthew #endif 2941bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DESC_REG(rx->rx_q), 294231f14b89Sjmatthew RX_DMA_DESC_VLAN_STRIP, strip); 2943bccaee56Smlarkin 2944bccaee56Smlarkin rx->rx_cons = AQ_READ_REG(sc, RX_DMA_DESC_HEAD_PTR_REG(rx->rx_q)) & 2945bccaee56Smlarkin RX_DMA_DESC_HEAD_PTR; 2946bccaee56Smlarkin AQ_WRITE_REG(sc, RX_DMA_DESC_TAIL_PTR_REG(rx->rx_q), rx->rx_cons); 2947bccaee56Smlarkin rx->rx_prod = rx->rx_cons; 2948bccaee56Smlarkin 2949bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, AQ_INTR_IRQ_MAP_RX_REG(rx->rx_q), 2950bccaee56Smlarkin AQ_INTR_IRQ_MAP_RX_IRQMAP(rx->rx_q), rx->rx_irq); 2951bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, AQ_INTR_IRQ_MAP_RX_REG(rx->rx_q), 2952bccaee56Smlarkin AQ_INTR_IRQ_MAP_RX_EN(rx->rx_q), 1); 2953bccaee56Smlarkin 2954bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DCAD_REG(rx->rx_q), 2955bccaee56Smlarkin RX_DMA_DCAD_CPUID, 0); 2956bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DCAD_REG(rx->rx_q), 2957bccaee56Smlarkin RX_DMA_DCAD_DESC_EN, 0); 2958bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DCAD_REG(rx->rx_q), 2959bccaee56Smlarkin RX_DMA_DCAD_HEADER_EN, 0); 2960bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DCAD_REG(rx->rx_q), 2961bccaee56Smlarkin RX_DMA_DCAD_PAYLOAD_EN, 0); 2962bccaee56Smlarkin 2963bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RX_DMA_DESC_REG(rx->rx_q), RX_DMA_DESC_EN, 1); 2964bccaee56Smlarkin } 2965bccaee56Smlarkin 2966bccaee56Smlarkin static inline unsigned int 2967bccaee56Smlarkin aq_rx_fill_slots(struct aq_softc *sc, struct aq_rxring *rx, uint nslots) 2968bccaee56Smlarkin { 2969bccaee56Smlarkin struct aq_rx_desc_read *ring, *rd; 2970bccaee56Smlarkin struct aq_slot *as; 2971bccaee56Smlarkin struct mbuf *m; 2972bccaee56Smlarkin uint p, fills; 2973bccaee56Smlarkin 2974bccaee56Smlarkin ring = AQ_DMA_KVA(&rx->rx_mem); 2975bccaee56Smlarkin p = rx->rx_prod; 2976bccaee56Smlarkin 2977bccaee56Smlarkin bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&rx->rx_mem), 0, 2978bccaee56Smlarkin AQ_DMA_LEN(&rx->rx_mem), BUS_DMASYNC_POSTWRITE); 2979bccaee56Smlarkin 2980bccaee56Smlarkin for (fills = 0; fills < nslots; fills++) { 2981bccaee56Smlarkin as = &rx->rx_slots[p]; 2982bccaee56Smlarkin rd = &ring[p]; 2983bccaee56Smlarkin 2984bccaee56Smlarkin m = MCLGETL(NULL, M_DONTWAIT, MCLBYTES + ETHER_ALIGN); 2985bccaee56Smlarkin if (m == NULL) 2986bccaee56Smlarkin break; 2987bccaee56Smlarkin 29880425cdaeSjmatthew m->m_data += (m->m_ext.ext_size - (MCLBYTES + ETHER_ALIGN)); 2989bccaee56Smlarkin m->m_data += ETHER_ALIGN; 2990bccaee56Smlarkin m->m_len = m->m_pkthdr.len = MCLBYTES; 2991bccaee56Smlarkin 2992bccaee56Smlarkin if (bus_dmamap_load_mbuf(sc->sc_dmat, as->as_map, m, 2993bccaee56Smlarkin BUS_DMA_NOWAIT) != 0) { 2994bccaee56Smlarkin m_freem(m); 2995bccaee56Smlarkin break; 2996bccaee56Smlarkin } 2997bccaee56Smlarkin as->as_m = m; 2998bccaee56Smlarkin 29990b663382Sjmatthew bus_dmamap_sync(sc->sc_dmat, as->as_map, 0, 30000b663382Sjmatthew as->as_map->dm_mapsize, BUS_DMASYNC_PREREAD); 3001bccaee56Smlarkin htolem64(&rd->buf_addr, as->as_map->dm_segs[0].ds_addr); 3002bccaee56Smlarkin rd->hdr_addr = 0; 3003bccaee56Smlarkin p++; 3004bccaee56Smlarkin if (p == AQ_RXD_NUM) 3005bccaee56Smlarkin p = 0; 3006bccaee56Smlarkin } 3007bccaee56Smlarkin 3008bccaee56Smlarkin bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&rx->rx_mem), 0, 3009bccaee56Smlarkin AQ_DMA_LEN(&rx->rx_mem), BUS_DMASYNC_PREWRITE); 3010bccaee56Smlarkin 3011bccaee56Smlarkin rx->rx_prod = p; 3012bccaee56Smlarkin AQ_WRITE_REG(sc, RX_DMA_DESC_TAIL_PTR_REG(rx->rx_q), rx->rx_prod); 3013bccaee56Smlarkin return (nslots - fills); 3014bccaee56Smlarkin } 3015bccaee56Smlarkin 3016bccaee56Smlarkin int 3017bccaee56Smlarkin aq_rx_fill(struct aq_softc *sc, struct aq_rxring *rx) 3018bccaee56Smlarkin { 3019bccaee56Smlarkin u_int slots; 3020bccaee56Smlarkin 3021bccaee56Smlarkin slots = if_rxr_get(&rx->rx_rxr, AQ_RXD_NUM); 3022bccaee56Smlarkin if (slots == 0) 3023bccaee56Smlarkin return 1; 3024bccaee56Smlarkin 3025bccaee56Smlarkin slots = aq_rx_fill_slots(sc, rx, slots); 3026bccaee56Smlarkin if_rxr_put(&rx->rx_rxr, slots); 3027bccaee56Smlarkin return 0; 3028bccaee56Smlarkin } 3029bccaee56Smlarkin 3030bccaee56Smlarkin void 3031bccaee56Smlarkin aq_refill(void *xq) 3032bccaee56Smlarkin { 3033bccaee56Smlarkin struct aq_queues *q = xq; 3034bccaee56Smlarkin struct aq_softc *sc = q->q_sc; 3035bccaee56Smlarkin 3036bccaee56Smlarkin aq_rx_fill(sc, &q->q_rx); 3037bccaee56Smlarkin 3038bccaee56Smlarkin if (if_rxr_inuse(&q->q_rx.rx_rxr) == 0) 3039bccaee56Smlarkin timeout_add(&q->q_rx.rx_refill, 1); 3040bccaee56Smlarkin } 3041bccaee56Smlarkin 3042bccaee56Smlarkin void 3043bccaee56Smlarkin aq_rxeof(struct aq_softc *sc, struct aq_rxring *rx) 3044bccaee56Smlarkin { 3045bccaee56Smlarkin struct ifnet *ifp = &sc->sc_arpcom.ac_if; 3046bccaee56Smlarkin struct aq_rx_desc_wb *rxd; 3047bccaee56Smlarkin struct aq_rx_desc_wb *ring; 3048bccaee56Smlarkin struct aq_slot *as; 3049bccaee56Smlarkin uint32_t end, idx; 3050bccaee56Smlarkin uint16_t pktlen, status; 3051bccaee56Smlarkin uint32_t rxd_type; 30520425cdaeSjmatthew struct mbuf *m, *mb; 3053bccaee56Smlarkin struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 3054bccaee56Smlarkin int rxfree; 3055bccaee56Smlarkin 3056bccaee56Smlarkin if (!ISSET(ifp->if_flags, IFF_RUNNING)) 3057bccaee56Smlarkin return; 3058bccaee56Smlarkin 3059bccaee56Smlarkin end = AQ_READ_REG(sc, RX_DMA_DESC_HEAD_PTR_REG(rx->rx_q)) & 3060bccaee56Smlarkin RX_DMA_DESC_HEAD_PTR; 3061bccaee56Smlarkin 3062bccaee56Smlarkin bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&rx->rx_mem), 0, 3063bccaee56Smlarkin AQ_DMA_LEN(&rx->rx_mem), BUS_DMASYNC_POSTREAD); 3064bccaee56Smlarkin 3065bccaee56Smlarkin rxfree = 0; 3066bccaee56Smlarkin idx = rx->rx_cons; 3067bccaee56Smlarkin ring = AQ_DMA_KVA(&rx->rx_mem); 3068bccaee56Smlarkin while (idx != end) { 3069bccaee56Smlarkin rxd = &ring[idx]; 3070bccaee56Smlarkin as = &rx->rx_slots[idx]; 3071bccaee56Smlarkin 3072bccaee56Smlarkin bus_dmamap_sync(sc->sc_dmat, as->as_map, 0, 3073bccaee56Smlarkin as->as_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 3074bccaee56Smlarkin bus_dmamap_unload(sc->sc_dmat, as->as_map); 3075bccaee56Smlarkin 3076bccaee56Smlarkin status = lemtoh16(&rxd->status); 3077bccaee56Smlarkin if ((status & AQ_RXDESC_STATUS_DD) == 0) 3078bccaee56Smlarkin break; 3079bccaee56Smlarkin 3080bccaee56Smlarkin rxfree++; 30810425cdaeSjmatthew mb = as->as_m; 3082bccaee56Smlarkin as->as_m = NULL; 3083bccaee56Smlarkin 3084bccaee56Smlarkin pktlen = lemtoh16(&rxd->pkt_len); 3085bccaee56Smlarkin rxd_type = lemtoh32(&rxd->type); 3086190bcc8eSjmatthew if ((rxd_type & AQ_RXDESC_TYPE_RSSTYPE) != 0) { 3087190bcc8eSjmatthew mb->m_pkthdr.ph_flowid = lemtoh32(&rxd->rss_hash); 3088190bcc8eSjmatthew mb->m_pkthdr.csum_flags |= M_FLOWID; 3089190bcc8eSjmatthew } 309031f14b89Sjmatthew 30910425cdaeSjmatthew mb->m_pkthdr.len = 0; 30920425cdaeSjmatthew mb->m_next = NULL; 30930425cdaeSjmatthew *rx->rx_m_tail = mb; 30940425cdaeSjmatthew rx->rx_m_tail = &mb->m_next; 30950425cdaeSjmatthew 30960425cdaeSjmatthew m = rx->rx_m_head; 30970425cdaeSjmatthew 309831f14b89Sjmatthew #if NVLAN > 0 309931f14b89Sjmatthew if (rxd_type & (AQ_RXDESC_TYPE_VLAN | AQ_RXDESC_TYPE_VLAN2)) { 310031f14b89Sjmatthew m->m_pkthdr.ether_vtag = lemtoh16(&rxd->vlan); 310131f14b89Sjmatthew m->m_flags |= M_VLANTAG; 310231f14b89Sjmatthew } 310331f14b89Sjmatthew #endif 3104bccaee56Smlarkin 31055e728153Sjmatthew if ((rxd_type & AQ_RXDESC_TYPE_V4_SUM) && 31065e728153Sjmatthew ((status & AQ_RXDESC_STATUS_V4_SUM_NG) == 0)) 31075e728153Sjmatthew m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; 31085e728153Sjmatthew 31095e728153Sjmatthew if ((rxd_type & AQ_RXDESC_TYPE_L4_SUM) && 31105e728153Sjmatthew (status & AQ_RXDESC_STATUS_L4_SUM_OK)) 31115e728153Sjmatthew m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK | 31125e728153Sjmatthew M_TCP_CSUM_IN_OK; 31135e728153Sjmatthew 3114bccaee56Smlarkin if ((status & AQ_RXDESC_STATUS_MACERR) || 3115bccaee56Smlarkin (rxd_type & AQ_RXDESC_TYPE_DMA_ERR)) { 3116bccaee56Smlarkin printf("%s:rx: rx error (status %x type %x)\n", 3117bccaee56Smlarkin DEVNAME(sc), status, rxd_type); 31180425cdaeSjmatthew rx->rx_m_error = 1; 31190425cdaeSjmatthew } 31200425cdaeSjmatthew 31210425cdaeSjmatthew if (status & AQ_RXDESC_STATUS_EOP) { 31220425cdaeSjmatthew mb->m_len = pktlen - m->m_pkthdr.len; 31230425cdaeSjmatthew m->m_pkthdr.len = pktlen; 31240425cdaeSjmatthew if (rx->rx_m_error != 0) { 31250425cdaeSjmatthew ifp->if_ierrors++; 3126bccaee56Smlarkin m_freem(m); 3127bccaee56Smlarkin } else { 3128bccaee56Smlarkin ml_enqueue(&ml, m); 3129bccaee56Smlarkin } 3130bccaee56Smlarkin 31310425cdaeSjmatthew rx->rx_m_head = NULL; 31320425cdaeSjmatthew rx->rx_m_tail = &rx->rx_m_head; 31330425cdaeSjmatthew rx->rx_m_error = 0; 31340425cdaeSjmatthew } else { 31350425cdaeSjmatthew mb->m_len = MCLBYTES; 31360425cdaeSjmatthew m->m_pkthdr.len += mb->m_len; 31370425cdaeSjmatthew } 31380425cdaeSjmatthew 3139bccaee56Smlarkin idx++; 3140bccaee56Smlarkin if (idx == AQ_RXD_NUM) 3141bccaee56Smlarkin idx = 0; 3142bccaee56Smlarkin } 31430b663382Sjmatthew 31440b663382Sjmatthew bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&rx->rx_mem), 0, 31450b663382Sjmatthew AQ_DMA_LEN(&rx->rx_mem), BUS_DMASYNC_PREREAD); 31460b663382Sjmatthew 3147bccaee56Smlarkin rx->rx_cons = idx; 3148bccaee56Smlarkin 3149bccaee56Smlarkin if (rxfree > 0) { 3150bccaee56Smlarkin if_rxr_put(&rx->rx_rxr, rxfree); 3151bccaee56Smlarkin if (ifiq_input(rx->rx_ifiq, &ml)) 3152bccaee56Smlarkin if_rxr_livelocked(&rx->rx_rxr); 3153bccaee56Smlarkin 3154bccaee56Smlarkin aq_rx_fill(sc, rx); 3155bccaee56Smlarkin if (if_rxr_inuse(&rx->rx_rxr) == 0) 3156bccaee56Smlarkin timeout_add(&rx->rx_refill, 1); 3157bccaee56Smlarkin } 3158bccaee56Smlarkin } 3159bccaee56Smlarkin 3160bccaee56Smlarkin void 3161bccaee56Smlarkin aq_txeof(struct aq_softc *sc, struct aq_txring *tx) 3162bccaee56Smlarkin { 3163bccaee56Smlarkin struct ifnet *ifp = &sc->sc_arpcom.ac_if; 3164bccaee56Smlarkin struct aq_slot *as; 3165bccaee56Smlarkin uint32_t idx, end, free; 3166bccaee56Smlarkin 3167bccaee56Smlarkin if (!ISSET(ifp->if_flags, IFF_RUNNING)) 3168bccaee56Smlarkin return; 3169bccaee56Smlarkin 3170bccaee56Smlarkin idx = tx->tx_cons; 3171bccaee56Smlarkin end = AQ_READ_REG(sc, TX_DMA_DESC_HEAD_PTR_REG(tx->tx_q)) & 3172bccaee56Smlarkin TX_DMA_DESC_HEAD_PTR; 3173bccaee56Smlarkin free = 0; 3174bccaee56Smlarkin 3175bccaee56Smlarkin bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&tx->tx_mem), 0, 3176bccaee56Smlarkin AQ_DMA_LEN(&tx->tx_mem), BUS_DMASYNC_POSTREAD); 3177bccaee56Smlarkin 3178bccaee56Smlarkin while (idx != end) { 3179bccaee56Smlarkin as = &tx->tx_slots[idx]; 318000f24cf6Sjmatthew 318100f24cf6Sjmatthew if (as->as_m != NULL) { 31820b663382Sjmatthew bus_dmamap_sync(sc->sc_dmat, as->as_map, 0, 31830b663382Sjmatthew as->as_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); 3184bccaee56Smlarkin bus_dmamap_unload(sc->sc_dmat, as->as_map); 3185bccaee56Smlarkin 3186bccaee56Smlarkin m_freem(as->as_m); 3187bccaee56Smlarkin as->as_m = NULL; 318800f24cf6Sjmatthew } 3189bccaee56Smlarkin 3190bccaee56Smlarkin idx++; 3191bccaee56Smlarkin if (idx == AQ_TXD_NUM) 3192bccaee56Smlarkin idx = 0; 3193bccaee56Smlarkin free++; 3194bccaee56Smlarkin } 3195bccaee56Smlarkin 31960b663382Sjmatthew bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&tx->tx_mem), 0, 31970b663382Sjmatthew AQ_DMA_LEN(&tx->tx_mem), BUS_DMASYNC_PREREAD); 31980b663382Sjmatthew 3199bccaee56Smlarkin tx->tx_cons = idx; 3200bccaee56Smlarkin 3201bccaee56Smlarkin if (free != 0) { 3202bccaee56Smlarkin if (ifq_is_oactive(tx->tx_ifq)) 3203bccaee56Smlarkin ifq_restart(tx->tx_ifq); 3204bccaee56Smlarkin } 3205bccaee56Smlarkin } 3206bccaee56Smlarkin 3207bccaee56Smlarkin void 3208bccaee56Smlarkin aq_start(struct ifqueue *ifq) 3209bccaee56Smlarkin { 3210bccaee56Smlarkin struct aq_queues *aq = ifq->ifq_softc; 3211bccaee56Smlarkin struct aq_softc *sc = aq->q_sc; 3212bccaee56Smlarkin struct aq_txring *tx = &aq->q_tx; 3213bccaee56Smlarkin struct aq_tx_desc *ring, *txd; 3214bccaee56Smlarkin struct aq_slot *as; 3215bccaee56Smlarkin struct mbuf *m; 3216bccaee56Smlarkin uint32_t idx, free, used, ctl1, ctl2; 321700f24cf6Sjmatthew int error, i; 3218bccaee56Smlarkin 3219bccaee56Smlarkin idx = tx->tx_prod; 3220bccaee56Smlarkin free = tx->tx_cons + AQ_TXD_NUM - tx->tx_prod; 3221bccaee56Smlarkin used = 0; 3222bccaee56Smlarkin 3223bccaee56Smlarkin bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&tx->tx_mem), 0, 3224bccaee56Smlarkin AQ_DMA_LEN(&tx->tx_mem), BUS_DMASYNC_POSTWRITE); 3225bccaee56Smlarkin ring = (struct aq_tx_desc *)AQ_DMA_KVA(&tx->tx_mem); 3226bccaee56Smlarkin 3227bccaee56Smlarkin for (;;) { 322831f14b89Sjmatthew if (used + AQ_TX_MAX_SEGMENTS + 1 >= free) { 3229bccaee56Smlarkin ifq_set_oactive(ifq); 3230bccaee56Smlarkin break; 3231bccaee56Smlarkin } 3232bccaee56Smlarkin 3233bccaee56Smlarkin m = ifq_dequeue(ifq); 3234bccaee56Smlarkin if (m == NULL) 3235bccaee56Smlarkin break; 3236bccaee56Smlarkin 3237bccaee56Smlarkin as = &tx->tx_slots[idx]; 3238bccaee56Smlarkin 323900f24cf6Sjmatthew error = bus_dmamap_load_mbuf(sc->sc_dmat, as->as_map, m, 324000f24cf6Sjmatthew BUS_DMA_STREAMING | BUS_DMA_NOWAIT); 324100f24cf6Sjmatthew if (error == EFBIG) { 324200f24cf6Sjmatthew if (m_defrag(m, M_DONTWAIT)) { 3243bccaee56Smlarkin m_freem(m); 3244bccaee56Smlarkin break; 3245bccaee56Smlarkin } 3246bccaee56Smlarkin 324700f24cf6Sjmatthew error = bus_dmamap_load_mbuf(sc->sc_dmat, as->as_map, 324800f24cf6Sjmatthew m, BUS_DMA_STREAMING | BUS_DMA_NOWAIT); 324900f24cf6Sjmatthew } 325000f24cf6Sjmatthew if (error != 0) { 3251bccaee56Smlarkin m_freem(m); 3252bccaee56Smlarkin break; 3253bccaee56Smlarkin } 3254bccaee56Smlarkin 3255bccaee56Smlarkin as->as_m = m; 3256bccaee56Smlarkin 3257bccaee56Smlarkin #if NBPFILTER > 0 325866048eb6Sjmatthew if (ifq->ifq_if->if_bpf) 325966048eb6Sjmatthew bpf_mtap_ether(ifq->ifq_if->if_bpf, m, BPF_DIRECTION_OUT); 3260bccaee56Smlarkin #endif 3261bccaee56Smlarkin bus_dmamap_sync(sc->sc_dmat, as->as_map, 0, 3262bccaee56Smlarkin as->as_map->dm_mapsize, BUS_DMASYNC_PREWRITE); 3263bccaee56Smlarkin 3264bccaee56Smlarkin ctl2 = m->m_pkthdr.len << AQ_TXDESC_CTL2_LEN_SHIFT; 326500f24cf6Sjmatthew ctl1 = AQ_TXDESC_CTL1_TYPE_TXD | AQ_TXDESC_CTL1_CMD_FCS; 326631f14b89Sjmatthew #if NVLAN > 0 326731f14b89Sjmatthew if (m->m_flags & M_VLANTAG) { 326831f14b89Sjmatthew txd = ring + idx; 326931f14b89Sjmatthew txd->buf_addr = 0; 327031f14b89Sjmatthew txd->ctl1 = htole32(AQ_TXDESC_CTL1_TYPE_TXC | 327131f14b89Sjmatthew (m->m_pkthdr.ether_vtag << AQ_TXDESC_CTL1_VLAN_SHIFT)); 327231f14b89Sjmatthew txd->ctl2 = 0; 327331f14b89Sjmatthew 327431f14b89Sjmatthew ctl1 |= AQ_TXDESC_CTL1_CMD_VLAN; 327531f14b89Sjmatthew ctl2 |= AQ_TXDESC_CTL2_CTX_EN; 327631f14b89Sjmatthew 327731f14b89Sjmatthew idx++; 327831f14b89Sjmatthew if (idx == AQ_TXD_NUM) 327931f14b89Sjmatthew idx = 0; 328031f14b89Sjmatthew used++; 328131f14b89Sjmatthew } 328231f14b89Sjmatthew #endif 3283bccaee56Smlarkin 32845e728153Sjmatthew if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT) 32855e728153Sjmatthew ctl1 |= AQ_TXDESC_CTL1_CMD_IP4CSUM; 32865e728153Sjmatthew if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT | M_UDP_CSUM_OUT)) 32875e728153Sjmatthew ctl1 |= AQ_TXDESC_CTL1_CMD_L4CSUM; 32885e728153Sjmatthew 328900f24cf6Sjmatthew for (i = 0; i < as->as_map->dm_nsegs; i++) { 329000f24cf6Sjmatthew 329100f24cf6Sjmatthew if (i == as->as_map->dm_nsegs - 1) 329200f24cf6Sjmatthew ctl1 |= AQ_TXDESC_CTL1_CMD_EOP | 329300f24cf6Sjmatthew AQ_TXDESC_CTL1_CMD_WB; 329400f24cf6Sjmatthew 329500f24cf6Sjmatthew txd = ring + idx; 329600f24cf6Sjmatthew txd->buf_addr = htole64(as->as_map->dm_segs[i].ds_addr); 329700f24cf6Sjmatthew txd->ctl1 = htole32(ctl1 | 329800f24cf6Sjmatthew (as->as_map->dm_segs[i].ds_len << 329900f24cf6Sjmatthew AQ_TXDESC_CTL1_BLEN_SHIFT)); 3300bccaee56Smlarkin txd->ctl2 = htole32(ctl2); 3301bccaee56Smlarkin 3302bccaee56Smlarkin idx++; 3303bccaee56Smlarkin if (idx == AQ_TXD_NUM) 3304bccaee56Smlarkin idx = 0; 3305bccaee56Smlarkin used++; 3306bccaee56Smlarkin } 330700f24cf6Sjmatthew } 3308bccaee56Smlarkin 3309bccaee56Smlarkin bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&tx->tx_mem), 0, 3310bccaee56Smlarkin AQ_DMA_LEN(&tx->tx_mem), BUS_DMASYNC_PREWRITE); 3311bccaee56Smlarkin 3312bccaee56Smlarkin if (used != 0) { 3313bccaee56Smlarkin tx->tx_prod = idx; 3314bccaee56Smlarkin AQ_WRITE_REG(sc, TX_DMA_DESC_TAIL_PTR_REG(tx->tx_q), 3315bccaee56Smlarkin tx->tx_prod); 3316bccaee56Smlarkin } 3317bccaee56Smlarkin } 3318bccaee56Smlarkin 3319bccaee56Smlarkin int 33201d7ac227Sjmatthew aq_intr_queue(void *arg) 33211d7ac227Sjmatthew { 33221d7ac227Sjmatthew struct aq_queues *aq = arg; 33231d7ac227Sjmatthew struct aq_softc *sc = aq->q_sc; 33241d7ac227Sjmatthew uint32_t status; 33251d7ac227Sjmatthew uint32_t clear; 33261d7ac227Sjmatthew 33271d7ac227Sjmatthew status = AQ_READ_REG(sc, AQ_INTR_STATUS_REG); 33281d7ac227Sjmatthew clear = 0; 33291d7ac227Sjmatthew if (status & (1 << aq->q_tx.tx_irq)) { 33301d7ac227Sjmatthew clear |= (1 << aq->q_tx.tx_irq); 33311d7ac227Sjmatthew aq_txeof(sc, &aq->q_tx); 33321d7ac227Sjmatthew } 33331d7ac227Sjmatthew 33341d7ac227Sjmatthew if (status & (1 << aq->q_rx.rx_irq)) { 33351d7ac227Sjmatthew clear |= (1 << aq->q_rx.rx_irq); 33361d7ac227Sjmatthew aq_rxeof(sc, &aq->q_rx); 33371d7ac227Sjmatthew } 33381d7ac227Sjmatthew 33391d7ac227Sjmatthew AQ_WRITE_REG(sc, AQ_INTR_STATUS_CLR_REG, clear); 33401d7ac227Sjmatthew return (clear != 0); 33411d7ac227Sjmatthew } 33421d7ac227Sjmatthew 33431d7ac227Sjmatthew int 33441d7ac227Sjmatthew aq_intr_link(void *arg) 33451d7ac227Sjmatthew { 33461d7ac227Sjmatthew struct aq_softc *sc = arg; 33471d7ac227Sjmatthew uint32_t status; 33481d7ac227Sjmatthew 33491d7ac227Sjmatthew status = AQ_READ_REG(sc, AQ_INTR_STATUS_REG); 33501d7ac227Sjmatthew if (status & (1 << sc->sc_linkstat_irq)) { 33511d7ac227Sjmatthew aq_update_link_status(sc); 33521d7ac227Sjmatthew AQ_WRITE_REG(sc, AQ_INTR_STATUS_REG, (1 << sc->sc_linkstat_irq)); 33531d7ac227Sjmatthew return 1; 33541d7ac227Sjmatthew } 33551d7ac227Sjmatthew 33561d7ac227Sjmatthew return 0; 33571d7ac227Sjmatthew } 33581d7ac227Sjmatthew 33591d7ac227Sjmatthew int 3360bccaee56Smlarkin aq_intr(void *arg) 3361bccaee56Smlarkin { 3362bccaee56Smlarkin struct aq_softc *sc = arg; 3363bccaee56Smlarkin struct aq_queues *aq = &sc->sc_queues[0]; 3364bccaee56Smlarkin uint32_t status; 3365bccaee56Smlarkin 3366bccaee56Smlarkin status = AQ_READ_REG(sc, AQ_INTR_STATUS_REG); 3367bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_INTR_STATUS_CLR_REG, 0xffffffff); 3368bccaee56Smlarkin 3369bccaee56Smlarkin if (status & (1 << sc->sc_linkstat_irq)) 3370bccaee56Smlarkin aq_update_link_status(sc); 3371bccaee56Smlarkin 3372bccaee56Smlarkin if (status & (1 << aq->q_tx.tx_irq)) { 3373bccaee56Smlarkin aq_txeof(sc, &aq->q_tx); 3374bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_INTR_STATUS_CLR_REG, 3375bccaee56Smlarkin (1 << aq->q_tx.tx_irq)); 3376bccaee56Smlarkin } 3377bccaee56Smlarkin if (status & (1 << aq->q_rx.rx_irq)) { 3378bccaee56Smlarkin aq_rxeof(sc, &aq->q_rx); 3379bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_INTR_STATUS_CLR_REG, 3380bccaee56Smlarkin (1 << aq->q_rx.rx_irq)); 3381bccaee56Smlarkin } 3382bccaee56Smlarkin 3383bccaee56Smlarkin return 1; 3384bccaee56Smlarkin } 3385bccaee56Smlarkin 3386bccaee56Smlarkin void 3387bccaee56Smlarkin aq_watchdog(struct ifnet *ifp) 3388bccaee56Smlarkin { 3389bccaee56Smlarkin 3390bccaee56Smlarkin } 3391bccaee56Smlarkin 3392bccaee56Smlarkin void 3393bccaee56Smlarkin aq_free_slots(struct aq_softc *sc, struct aq_slot *slots, int allocated, 3394bccaee56Smlarkin int total) 3395bccaee56Smlarkin { 3396bccaee56Smlarkin struct aq_slot *as; 3397bccaee56Smlarkin 3398bccaee56Smlarkin int i = allocated; 3399bccaee56Smlarkin while (i-- > 0) { 3400bccaee56Smlarkin as = &slots[i]; 3401bccaee56Smlarkin bus_dmamap_destroy(sc->sc_dmat, as->as_map); 3402bccaee56Smlarkin if (as->as_m != NULL) 3403bccaee56Smlarkin m_freem(as->as_m); 3404bccaee56Smlarkin } 3405bccaee56Smlarkin free(slots, M_DEVBUF, total * sizeof(*as)); 3406bccaee56Smlarkin } 3407bccaee56Smlarkin 3408bccaee56Smlarkin int 3409bccaee56Smlarkin aq_queue_up(struct aq_softc *sc, struct aq_queues *aq) 3410bccaee56Smlarkin { 3411bccaee56Smlarkin struct aq_rxring *rx; 3412bccaee56Smlarkin struct aq_txring *tx; 3413bccaee56Smlarkin struct aq_slot *as; 34140425cdaeSjmatthew int i, mtu; 3415bccaee56Smlarkin 3416bccaee56Smlarkin rx = &aq->q_rx; 3417bccaee56Smlarkin rx->rx_slots = mallocarray(sizeof(*as), AQ_RXD_NUM, M_DEVBUF, 3418bccaee56Smlarkin M_WAITOK | M_ZERO); 3419bccaee56Smlarkin if (rx->rx_slots == NULL) { 3420bccaee56Smlarkin printf("%s: failed to allocate rx slots %d\n", DEVNAME(sc), 3421bccaee56Smlarkin aq->q_index); 3422bccaee56Smlarkin return ENOMEM; 3423bccaee56Smlarkin } 3424bccaee56Smlarkin 3425bccaee56Smlarkin for (i = 0; i < AQ_RXD_NUM; i++) { 3426bccaee56Smlarkin as = &rx->rx_slots[i]; 3427bccaee56Smlarkin if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 3428bccaee56Smlarkin BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, 3429bccaee56Smlarkin &as->as_map) != 0) { 3430bccaee56Smlarkin printf("%s: failed to allocate rx dma maps %d\n", 3431bccaee56Smlarkin DEVNAME(sc), aq->q_index); 3432bccaee56Smlarkin goto destroy_rx_slots; 3433bccaee56Smlarkin } 3434bccaee56Smlarkin } 3435bccaee56Smlarkin 3436bccaee56Smlarkin if (aq_dmamem_alloc(sc, &rx->rx_mem, AQ_RXD_NUM * 3437bccaee56Smlarkin sizeof(struct aq_rx_desc_read), PAGE_SIZE) != 0) { 3438bccaee56Smlarkin printf("%s: unable to allocate rx ring %d\n", DEVNAME(sc), 3439bccaee56Smlarkin aq->q_index); 3440bccaee56Smlarkin goto destroy_rx_slots; 3441bccaee56Smlarkin } 3442bccaee56Smlarkin 3443bccaee56Smlarkin tx = &aq->q_tx; 3444bccaee56Smlarkin tx->tx_slots = mallocarray(sizeof(*as), AQ_TXD_NUM, M_DEVBUF, 3445bccaee56Smlarkin M_WAITOK | M_ZERO); 3446bccaee56Smlarkin if (tx->tx_slots == NULL) { 3447bccaee56Smlarkin printf("%s: failed to allocate tx slots %d\n", DEVNAME(sc), 3448bccaee56Smlarkin aq->q_index); 3449bccaee56Smlarkin goto destroy_rx_ring; 3450bccaee56Smlarkin } 3451bccaee56Smlarkin 34520425cdaeSjmatthew mtu = sc->sc_arpcom.ac_if.if_hardmtu; 3453bccaee56Smlarkin for (i = 0; i < AQ_TXD_NUM; i++) { 3454bccaee56Smlarkin as = &tx->tx_slots[i]; 34550425cdaeSjmatthew if (bus_dmamap_create(sc->sc_dmat, mtu, AQ_TX_MAX_SEGMENTS, 34560425cdaeSjmatthew MCLBYTES, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, 3457bccaee56Smlarkin &as->as_map) != 0) { 3458bccaee56Smlarkin printf("%s: failed to allocated tx dma maps %d\n", 3459bccaee56Smlarkin DEVNAME(sc), aq->q_index); 3460bccaee56Smlarkin goto destroy_tx_slots; 3461bccaee56Smlarkin } 3462bccaee56Smlarkin } 3463bccaee56Smlarkin 3464bccaee56Smlarkin if (aq_dmamem_alloc(sc, &tx->tx_mem, AQ_TXD_NUM * 3465bccaee56Smlarkin sizeof(struct aq_tx_desc), PAGE_SIZE) != 0) { 3466bccaee56Smlarkin printf("%s: unable to allocate tx ring %d\n", DEVNAME(sc), 3467bccaee56Smlarkin aq->q_index); 3468bccaee56Smlarkin goto destroy_tx_slots; 3469bccaee56Smlarkin } 3470bccaee56Smlarkin 34710b663382Sjmatthew bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&tx->tx_mem), 34720b663382Sjmatthew 0, AQ_DMA_LEN(&tx->tx_mem), 34730b663382Sjmatthew BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 34740b663382Sjmatthew 34750b663382Sjmatthew bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&rx->rx_mem), 34760b663382Sjmatthew 0, AQ_DMA_LEN(&rx->rx_mem), 34770b663382Sjmatthew BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 34780b663382Sjmatthew 3479bccaee56Smlarkin aq_txring_reset(sc, tx, 1); 3480bccaee56Smlarkin aq_rxring_reset(sc, rx, 1); 3481bccaee56Smlarkin return 0; 3482bccaee56Smlarkin 3483bccaee56Smlarkin destroy_tx_slots: 3484bccaee56Smlarkin aq_free_slots(sc, tx->tx_slots, i, AQ_TXD_NUM); 3485bccaee56Smlarkin tx->tx_slots = NULL; 3486bccaee56Smlarkin i = AQ_RXD_NUM; 3487bccaee56Smlarkin 3488bccaee56Smlarkin destroy_rx_ring: 3489bccaee56Smlarkin aq_dmamem_free(sc, &rx->rx_mem); 3490bccaee56Smlarkin destroy_rx_slots: 3491bccaee56Smlarkin aq_free_slots(sc, rx->rx_slots, i, AQ_RXD_NUM); 3492bccaee56Smlarkin rx->rx_slots = NULL; 3493bccaee56Smlarkin return ENOMEM; 3494bccaee56Smlarkin } 3495bccaee56Smlarkin 3496bccaee56Smlarkin void 3497bccaee56Smlarkin aq_queue_down(struct aq_softc *sc, struct aq_queues *aq) 3498bccaee56Smlarkin { 3499bccaee56Smlarkin struct aq_txring *tx; 3500bccaee56Smlarkin struct aq_rxring *rx; 3501bccaee56Smlarkin 3502bccaee56Smlarkin tx = &aq->q_tx; 3503bccaee56Smlarkin aq_txring_reset(sc, &aq->q_tx, 0); 3504bccaee56Smlarkin if (tx->tx_slots != NULL) { 3505bccaee56Smlarkin aq_free_slots(sc, tx->tx_slots, AQ_TXD_NUM, AQ_TXD_NUM); 3506bccaee56Smlarkin tx->tx_slots = NULL; 3507bccaee56Smlarkin } 3508bccaee56Smlarkin 35090b663382Sjmatthew bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&tx->tx_mem), 35100b663382Sjmatthew 0, AQ_DMA_LEN(&tx->tx_mem), 35110b663382Sjmatthew BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 35120b663382Sjmatthew 3513bccaee56Smlarkin aq_dmamem_free(sc, &tx->tx_mem); 3514bccaee56Smlarkin 3515bccaee56Smlarkin rx = &aq->q_rx; 35160425cdaeSjmatthew m_freem(rx->rx_m_head); 35170425cdaeSjmatthew rx->rx_m_head = NULL; 35180425cdaeSjmatthew rx->rx_m_tail = &rx->rx_m_head; 35190425cdaeSjmatthew rx->rx_m_error = 0; 3520bccaee56Smlarkin aq_rxring_reset(sc, &aq->q_rx, 0); 3521bccaee56Smlarkin if (rx->rx_slots != NULL) { 3522bccaee56Smlarkin aq_free_slots(sc, rx->rx_slots, AQ_RXD_NUM, AQ_RXD_NUM); 3523bccaee56Smlarkin rx->rx_slots = NULL; 3524bccaee56Smlarkin } 3525bccaee56Smlarkin 35260b663382Sjmatthew bus_dmamap_sync(sc->sc_dmat, AQ_DMA_MAP(&rx->rx_mem), 35270b663382Sjmatthew 0, AQ_DMA_LEN(&rx->rx_mem), 35280b663382Sjmatthew BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 35290b663382Sjmatthew 3530bccaee56Smlarkin aq_dmamem_free(sc, &rx->rx_mem); 3531bccaee56Smlarkin } 3532bccaee56Smlarkin 3533d04289f5Sjmatthew void 3534d04289f5Sjmatthew aq_invalidate_rx_desc_cache(struct aq_softc *sc) 3535d04289f5Sjmatthew { 3536d04289f5Sjmatthew uint32_t cache; 3537d04289f5Sjmatthew 3538d04289f5Sjmatthew cache = AQ_READ_REG(sc, RX_DMA_DESC_CACHE_INIT_REG); 3539d04289f5Sjmatthew AQ_WRITE_REG_BIT(sc, RX_DMA_DESC_CACHE_INIT_REG, RX_DMA_DESC_CACHE_INIT, 3540d04289f5Sjmatthew (cache & RX_DMA_DESC_CACHE_INIT) ^ RX_DMA_DESC_CACHE_INIT); 3541d04289f5Sjmatthew } 3542d04289f5Sjmatthew 3543bccaee56Smlarkin int 3544bccaee56Smlarkin aq_up(struct aq_softc *sc) 3545bccaee56Smlarkin { 3546bccaee56Smlarkin struct ifnet *ifp = &sc->sc_arpcom.ac_if; 3547bccaee56Smlarkin int i; 3548bccaee56Smlarkin 3549d04289f5Sjmatthew aq_invalidate_rx_desc_cache(sc); 3550d04289f5Sjmatthew 3551bccaee56Smlarkin for (i = 0; i < sc->sc_nqueues; i++) { 3552bccaee56Smlarkin if (aq_queue_up(sc, &sc->sc_queues[i]) != 0) 3553bccaee56Smlarkin goto downqueues; 3554bccaee56Smlarkin } 3555bccaee56Smlarkin 35564025c162Sjmatthew aq_set_mac_addr(sc, AQ_HW_MAC_OWN, sc->sc_arpcom.ac_enaddr); 35574025c162Sjmatthew 35585e728153Sjmatthew AQ_WRITE_REG_BIT(sc, TPO_HWCSUM_REG, TPO_HWCSUM_IP4CSUM_EN, 1); 35595e728153Sjmatthew AQ_WRITE_REG_BIT(sc, TPO_HWCSUM_REG, TPO_HWCSUM_L4CSUM_EN, 1); 35605e728153Sjmatthew 35615e728153Sjmatthew AQ_WRITE_REG_BIT(sc, RPO_HWCSUM_REG, RPO_HWCSUM_IP4CSUM_EN, 1); 35625e728153Sjmatthew AQ_WRITE_REG_BIT(sc, RPO_HWCSUM_REG, RPO_HWCSUM_L4CSUM_EN, 1); 3563bccaee56Smlarkin 3564bccaee56Smlarkin SET(ifp->if_flags, IFF_RUNNING); 3565bccaee56Smlarkin aq_enable_intr(sc, 1, 1); 3566bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, TPB_TX_BUF_REG, TPB_TX_BUF_EN, 1); 3567bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_BUF_EN, 1); 3568bccaee56Smlarkin 3569bccaee56Smlarkin for (i = 0; i < sc->sc_nqueues; i++) { 3570bccaee56Smlarkin struct aq_queues *aq = &sc->sc_queues[i]; 3571bccaee56Smlarkin 35720425cdaeSjmatthew if_rxr_init(&aq->q_rx.rx_rxr, howmany(ifp->if_hardmtu, MCLBYTES), 35730425cdaeSjmatthew AQ_RXD_NUM - 1); 3574bccaee56Smlarkin aq_rx_fill(sc, &aq->q_rx); 3575bccaee56Smlarkin 3576bccaee56Smlarkin ifq_clr_oactive(aq->q_tx.tx_ifq); 3577bccaee56Smlarkin } 3578bccaee56Smlarkin 3579bccaee56Smlarkin return ENETRESET; 3580bccaee56Smlarkin 3581bccaee56Smlarkin downqueues: 3582bccaee56Smlarkin for (i = 0; i < sc->sc_nqueues; i++) 3583bccaee56Smlarkin aq_queue_down(sc, &sc->sc_queues[i]); 3584bccaee56Smlarkin return ENOMEM; 3585bccaee56Smlarkin } 3586bccaee56Smlarkin 3587bccaee56Smlarkin void 3588bccaee56Smlarkin aq_down(struct aq_softc *sc) 3589bccaee56Smlarkin { 3590bccaee56Smlarkin struct ifnet *ifp = &sc->sc_arpcom.ac_if; 3591bccaee56Smlarkin int i; 3592bccaee56Smlarkin 3593bccaee56Smlarkin CLR(ifp->if_flags, IFF_RUNNING); 3594bccaee56Smlarkin 3595bccaee56Smlarkin aq_enable_intr(sc, 1, 0); 3596bccaee56Smlarkin intr_barrier(sc->sc_ih); 3597bccaee56Smlarkin 3598d04289f5Sjmatthew AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_BUF_EN, 0); 3599bccaee56Smlarkin for (i = 0; i < sc->sc_nqueues; i++) { 3600bccaee56Smlarkin /* queue intr barrier? */ 3601bccaee56Smlarkin aq_queue_down(sc, &sc->sc_queues[i]); 3602bccaee56Smlarkin } 3603d04289f5Sjmatthew 3604d04289f5Sjmatthew aq_invalidate_rx_desc_cache(sc); 3605bccaee56Smlarkin } 3606bccaee56Smlarkin 3607bccaee56Smlarkin void 3608bccaee56Smlarkin aq_enable_intr(struct aq_softc *sc, int link, int txrx) 3609bccaee56Smlarkin { 3610bccaee56Smlarkin uint32_t imask = 0; 3611bccaee56Smlarkin int i; 3612bccaee56Smlarkin 3613bccaee56Smlarkin if (txrx) { 3614bccaee56Smlarkin for (i = 0; i < sc->sc_nqueues; i++) { 3615bccaee56Smlarkin imask |= (1 << sc->sc_queues[i].q_tx.tx_irq); 3616bccaee56Smlarkin imask |= (1 << sc->sc_queues[i].q_rx.rx_irq); 3617bccaee56Smlarkin } 3618bccaee56Smlarkin } 3619bccaee56Smlarkin 3620bccaee56Smlarkin if (link) 3621bccaee56Smlarkin imask |= (1 << sc->sc_linkstat_irq); 3622bccaee56Smlarkin 3623bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_INTR_MASK_REG, imask); 3624bccaee56Smlarkin AQ_WRITE_REG(sc, AQ_INTR_STATUS_CLR_REG, 0xffffffff); 3625bccaee56Smlarkin } 3626bccaee56Smlarkin 3627bccaee56Smlarkin void 3628bccaee56Smlarkin aq_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr) 3629bccaee56Smlarkin { 3630bccaee56Smlarkin struct aq_softc *aq = ifp->if_softc; 3631bccaee56Smlarkin enum aq_link_speed speed; 3632bccaee56Smlarkin enum aq_link_fc fc; 3633bccaee56Smlarkin int media; 3634bccaee56Smlarkin int flow; 3635bccaee56Smlarkin 3636bccaee56Smlarkin if (aq_get_linkmode(aq, &speed, &fc, NULL) != 0) 3637bccaee56Smlarkin return; 3638bccaee56Smlarkin 3639bccaee56Smlarkin switch (speed) { 3640bccaee56Smlarkin case AQ_LINK_10G: 3641bccaee56Smlarkin media = IFM_10G_T; 3642bccaee56Smlarkin break; 3643bccaee56Smlarkin case AQ_LINK_5G: 3644bccaee56Smlarkin media = IFM_5000_T; 3645bccaee56Smlarkin break; 3646bccaee56Smlarkin case AQ_LINK_2G5: 3647bccaee56Smlarkin media = IFM_2500_T; 3648bccaee56Smlarkin break; 3649bccaee56Smlarkin case AQ_LINK_1G: 3650bccaee56Smlarkin media = IFM_1000_T; 3651bccaee56Smlarkin break; 3652bccaee56Smlarkin case AQ_LINK_100M: 3653bccaee56Smlarkin media = IFM_100_TX; 3654bccaee56Smlarkin break; 3655b760e38cSjmatthew case AQ_LINK_10M: 3656b760e38cSjmatthew media = IFM_10_T; 3657b760e38cSjmatthew break; 3658bccaee56Smlarkin case AQ_LINK_NONE: 3659bccaee56Smlarkin media = 0; 3660bccaee56Smlarkin break; 3661bccaee56Smlarkin } 3662bccaee56Smlarkin 3663bccaee56Smlarkin flow = 0; 3664bccaee56Smlarkin if (fc & AQ_FC_RX) 3665bccaee56Smlarkin flow |= IFM_ETH_RXPAUSE; 3666bccaee56Smlarkin if (fc & AQ_FC_TX) 3667bccaee56Smlarkin flow |= IFM_ETH_TXPAUSE; 3668bccaee56Smlarkin 3669bccaee56Smlarkin ifmr->ifm_status = IFM_AVALID; 3670bccaee56Smlarkin if (speed != AQ_LINK_NONE) { 3671bccaee56Smlarkin ifmr->ifm_status |= IFM_ACTIVE; 3672bccaee56Smlarkin ifmr->ifm_active = IFM_ETHER | IFM_AUTO | media | flow; 3673bccaee56Smlarkin } 3674bccaee56Smlarkin } 3675bccaee56Smlarkin 3676bccaee56Smlarkin int 3677bccaee56Smlarkin aq_ifmedia_change(struct ifnet *ifp) 3678bccaee56Smlarkin { 3679bccaee56Smlarkin struct aq_softc *sc = ifp->if_softc; 3680bccaee56Smlarkin enum aq_link_speed rate = AQ_LINK_NONE; 3681bccaee56Smlarkin enum aq_link_fc fc = AQ_FC_NONE; 3682bccaee56Smlarkin 3683bccaee56Smlarkin if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER) 3684bccaee56Smlarkin return EINVAL; 3685bccaee56Smlarkin 3686bccaee56Smlarkin switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { 3687bccaee56Smlarkin case IFM_AUTO: 3688bccaee56Smlarkin rate = AQ_LINK_AUTO; 3689bccaee56Smlarkin break; 3690bccaee56Smlarkin case IFM_NONE: 3691bccaee56Smlarkin rate = AQ_LINK_NONE; 3692bccaee56Smlarkin break; 3693b760e38cSjmatthew case IFM_10_T: 3694b760e38cSjmatthew rate = AQ_LINK_10M; 3695b760e38cSjmatthew break; 3696bccaee56Smlarkin case IFM_100_TX: 3697bccaee56Smlarkin rate = AQ_LINK_100M; 3698bccaee56Smlarkin break; 3699bccaee56Smlarkin case IFM_1000_T: 3700bccaee56Smlarkin rate = AQ_LINK_1G; 3701bccaee56Smlarkin break; 3702bccaee56Smlarkin case IFM_2500_T: 3703bccaee56Smlarkin rate = AQ_LINK_2G5; 3704bccaee56Smlarkin break; 3705bccaee56Smlarkin case IFM_5000_T: 3706bccaee56Smlarkin rate = AQ_LINK_5G; 3707bccaee56Smlarkin break; 3708bccaee56Smlarkin case IFM_10G_T: 3709bccaee56Smlarkin rate = AQ_LINK_10G; 3710bccaee56Smlarkin break; 3711bccaee56Smlarkin default: 3712bccaee56Smlarkin return ENODEV; 3713bccaee56Smlarkin } 3714bccaee56Smlarkin 3715bccaee56Smlarkin if (sc->sc_media.ifm_media & IFM_FLOW) 3716bccaee56Smlarkin fc = AQ_FC_ALL; 3717bccaee56Smlarkin 3718bccaee56Smlarkin return aq_set_linkmode(sc, rate, fc, AQ_EEE_DISABLE); 3719bccaee56Smlarkin } 3720bccaee56Smlarkin 3721bccaee56Smlarkin void 3722bccaee56Smlarkin aq_update_link_status(struct aq_softc *sc) 3723bccaee56Smlarkin { 3724bccaee56Smlarkin struct ifnet *ifp = &sc->sc_arpcom.ac_if; 3725bccaee56Smlarkin enum aq_link_speed speed; 3726bccaee56Smlarkin enum aq_link_fc fc; 3727bccaee56Smlarkin 3728bccaee56Smlarkin if (aq_get_linkmode(sc, &speed, &fc, NULL) != 0) 3729bccaee56Smlarkin return; 3730bccaee56Smlarkin 3731bccaee56Smlarkin if (speed == AQ_LINK_NONE) { 3732bccaee56Smlarkin if (ifp->if_link_state != LINK_STATE_DOWN) { 3733bccaee56Smlarkin ifp->if_link_state = LINK_STATE_DOWN; 3734bccaee56Smlarkin if_link_state_change(ifp); 3735bccaee56Smlarkin } 3736bccaee56Smlarkin } else { 3737bccaee56Smlarkin if (ifp->if_link_state != LINK_STATE_FULL_DUPLEX) { 3738bccaee56Smlarkin ifp->if_link_state = LINK_STATE_FULL_DUPLEX; 3739bccaee56Smlarkin if_link_state_change(ifp); 3740bccaee56Smlarkin } 3741bccaee56Smlarkin } 3742bccaee56Smlarkin } 3743bccaee56Smlarkin 37449f7de937Sjmatthew int 37459f7de937Sjmatthew aq_rxrinfo(struct aq_softc *sc, struct if_rxrinfo *ifri) 37469f7de937Sjmatthew { 37479f7de937Sjmatthew struct if_rxring_info *ifr; 37489f7de937Sjmatthew int i; 37499f7de937Sjmatthew int error; 37509f7de937Sjmatthew 37519f7de937Sjmatthew ifr = mallocarray(sc->sc_nqueues, sizeof(*ifr), M_TEMP, 37529f7de937Sjmatthew M_WAITOK | M_ZERO | M_CANFAIL); 37539f7de937Sjmatthew if (ifr == NULL) 37549f7de937Sjmatthew return (ENOMEM); 37559f7de937Sjmatthew 37569f7de937Sjmatthew for (i = 0; i < sc->sc_nqueues; i++) { 37579f7de937Sjmatthew ifr[i].ifr_size = MCLBYTES; 37589f7de937Sjmatthew ifr[i].ifr_info = sc->sc_queues[i].q_rx.rx_rxr; 37599f7de937Sjmatthew } 37609f7de937Sjmatthew 37619f7de937Sjmatthew error = if_rxr_info_ioctl(ifri, sc->sc_nqueues, ifr); 37629f7de937Sjmatthew free(ifr, M_TEMP, sc->sc_nqueues * sizeof(*ifr)); 37639f7de937Sjmatthew 37649f7de937Sjmatthew return (error); 37659f7de937Sjmatthew } 3766bccaee56Smlarkin 3767bccaee56Smlarkin int 3768bccaee56Smlarkin aq_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 3769bccaee56Smlarkin { 3770bccaee56Smlarkin struct aq_softc *sc = ifp->if_softc; 3771bccaee56Smlarkin struct ifreq *ifr = (struct ifreq *)data; 3772bccaee56Smlarkin int error = 0, s; 3773bccaee56Smlarkin 3774bccaee56Smlarkin s = splnet(); 3775bccaee56Smlarkin 3776bccaee56Smlarkin switch (cmd) { 3777bccaee56Smlarkin case SIOCSIFADDR: 3778bccaee56Smlarkin ifp->if_flags |= IFF_UP; 3779bccaee56Smlarkin if ((ifp->if_flags & IFF_RUNNING) == 0) 3780bccaee56Smlarkin error = aq_up(sc); 3781bccaee56Smlarkin break; 3782bccaee56Smlarkin case SIOCSIFFLAGS: 3783bccaee56Smlarkin if (ifp->if_flags & IFF_UP) { 3784bccaee56Smlarkin if (ifp->if_flags & IFF_RUNNING) 3785bccaee56Smlarkin error = ENETRESET; 3786bccaee56Smlarkin else 3787bccaee56Smlarkin error = aq_up(sc); 3788bccaee56Smlarkin } else { 3789bccaee56Smlarkin if (ifp->if_flags & IFF_RUNNING) 3790bccaee56Smlarkin aq_down(sc); 3791bccaee56Smlarkin } 3792bccaee56Smlarkin break; 3793bccaee56Smlarkin case SIOCSIFMEDIA: 3794bccaee56Smlarkin case SIOCGIFMEDIA: 3795bccaee56Smlarkin error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 3796bccaee56Smlarkin break; 37979f7de937Sjmatthew 37989f7de937Sjmatthew case SIOCGIFRXR: 37999f7de937Sjmatthew error = aq_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data); 38009f7de937Sjmatthew break; 38019f7de937Sjmatthew 3802bccaee56Smlarkin default: 3803bccaee56Smlarkin error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data); 3804bccaee56Smlarkin } 3805bccaee56Smlarkin 3806bccaee56Smlarkin if (error == ENETRESET) { 3807bccaee56Smlarkin if (ifp->if_flags & IFF_RUNNING) 3808bccaee56Smlarkin aq_iff(sc); 3809bccaee56Smlarkin error = 0; 3810bccaee56Smlarkin } 3811bccaee56Smlarkin 3812bccaee56Smlarkin splx(s); 3813bccaee56Smlarkin return error; 3814bccaee56Smlarkin } 3815bccaee56Smlarkin 3816b760e38cSjmatthew int 3817b760e38cSjmatthew aq2_filter_art_set(struct aq_softc *sc, uint32_t idx, 3818b760e38cSjmatthew uint32_t tag, uint32_t mask, uint32_t action) 3819b760e38cSjmatthew { 3820b760e38cSjmatthew int error; 3821b760e38cSjmatthew 3822b760e38cSjmatthew AQ_MPI_LOCK(sc); 3823b760e38cSjmatthew 3824b760e38cSjmatthew WAIT_FOR(AQ_READ_REG(sc, AQ2_ART_SEM_REG) == 1, 10, 1000, &error); 3825b760e38cSjmatthew if (error != 0) { 3826b760e38cSjmatthew printf("%s: AQ2_ART_SEM_REG timeout\n", DEVNAME(sc)); 3827b760e38cSjmatthew goto out; 3828b760e38cSjmatthew } 3829b760e38cSjmatthew 3830b760e38cSjmatthew idx += sc->sc_art_filter_base_index; 3831b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_RPF_ACT_ART_REQ_TAG_REG(idx), tag); 3832b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_RPF_ACT_ART_REQ_MASK_REG(idx), mask); 3833b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_RPF_ACT_ART_REQ_ACTION_REG(idx), action); 3834b760e38cSjmatthew 3835b760e38cSjmatthew AQ_WRITE_REG(sc, AQ2_ART_SEM_REG, 1); 3836b760e38cSjmatthew 3837b760e38cSjmatthew out: 3838b760e38cSjmatthew AQ_MPI_UNLOCK(sc); 3839b760e38cSjmatthew return error; 3840b760e38cSjmatthew } 3841b760e38cSjmatthew 3842bccaee56Smlarkin void 3843bccaee56Smlarkin aq_iff(struct aq_softc *sc) 3844bccaee56Smlarkin { 3845bccaee56Smlarkin struct ifnet *ifp = &sc->sc_arpcom.ac_if; 3846bccaee56Smlarkin struct arpcom *ac = &sc->sc_arpcom; 3847bccaee56Smlarkin struct ether_multi *enm; 3848bccaee56Smlarkin struct ether_multistep step; 3849b760e38cSjmatthew uint32_t action; 3850bccaee56Smlarkin int idx; 3851bccaee56Smlarkin 3852b760e38cSjmatthew if (HWTYPE_AQ2_P(sc)) { 3853b760e38cSjmatthew action = (ifp->if_flags & IFF_PROMISC) ? 3854b760e38cSjmatthew AQ2_ART_ACTION_DISABLE : AQ2_ART_ACTION_DROP; 3855b760e38cSjmatthew aq2_filter_art_set(sc, AQ2_RPF_INDEX_L2_PROMISC_OFF, 0, 3856b760e38cSjmatthew AQ2_RPF_TAG_UC_MASK | AQ2_RPF_TAG_ALLMC_MASK, action); 3857b760e38cSjmatthew aq2_filter_art_set(sc, AQ2_RPF_INDEX_VLAN_PROMISC_OFF, 0, 3858b760e38cSjmatthew AQ2_RPF_TAG_VLAN_MASK | AQ2_RPF_TAG_UNTAG_MASK, action); 3859b760e38cSjmatthew } 3860b760e38cSjmatthew 38614025c162Sjmatthew if (ifp->if_flags & IFF_PROMISC) { 3862bccaee56Smlarkin ifp->if_flags |= IFF_ALLMULTI; 3863bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2BC_REG, RPF_L2BC_PROMISC, 1); 38644025c162Sjmatthew } else if (ac->ac_multirangecnt > 0 || 38654025c162Sjmatthew ac->ac_multicnt >= AQ_HW_MAC_NUM) { 38664025c162Sjmatthew ifp->if_flags |= IFF_ALLMULTI; 3867bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2BC_REG, RPF_L2BC_PROMISC, 0); 3868bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_MCAST_FILTER_MASK_REG, 3869bccaee56Smlarkin RPF_MCAST_FILTER_MASK_ALLMULTI, 1); 3870bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_MCAST_FILTER_REG(0), 3871bccaee56Smlarkin RPF_MCAST_FILTER_EN, 1); 3872bccaee56Smlarkin } else { 38734025c162Sjmatthew ifp->if_flags &= ~IFF_ALLMULTI; 3874bccaee56Smlarkin idx = AQ_HW_MAC_OWN + 1; 3875bccaee56Smlarkin 3876bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_L2BC_REG, RPF_L2BC_PROMISC, 0); 3877bccaee56Smlarkin 3878bccaee56Smlarkin ETHER_FIRST_MULTI(step, ac, enm); 3879bccaee56Smlarkin while (enm != NULL) { 3880bccaee56Smlarkin aq_set_mac_addr(sc, idx++, enm->enm_addrlo); 3881bccaee56Smlarkin ETHER_NEXT_MULTI(step, enm); 3882bccaee56Smlarkin } 3883bccaee56Smlarkin 3884bccaee56Smlarkin for (; idx < AQ_HW_MAC_NUM; idx++) 3885bccaee56Smlarkin aq_set_mac_addr(sc, idx, NULL); 3886bccaee56Smlarkin 3887bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_MCAST_FILTER_MASK_REG, 3888bccaee56Smlarkin RPF_MCAST_FILTER_MASK_ALLMULTI, 0); 3889bccaee56Smlarkin AQ_WRITE_REG_BIT(sc, RPF_MCAST_FILTER_REG(0), 38904025c162Sjmatthew RPF_MCAST_FILTER_EN, 0); 3891bccaee56Smlarkin } 3892bccaee56Smlarkin } 3893bccaee56Smlarkin 3894bccaee56Smlarkin int 3895bccaee56Smlarkin aq_dmamem_alloc(struct aq_softc *sc, struct aq_dmamem *aqm, 3896bccaee56Smlarkin bus_size_t size, u_int align) 3897bccaee56Smlarkin { 3898bccaee56Smlarkin aqm->aqm_size = size; 3899bccaee56Smlarkin 3900bccaee56Smlarkin if (bus_dmamap_create(sc->sc_dmat, aqm->aqm_size, 1, 3901bccaee56Smlarkin aqm->aqm_size, 0, 3902bccaee56Smlarkin BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, 3903bccaee56Smlarkin &aqm->aqm_map) != 0) 3904bccaee56Smlarkin return (1); 3905bccaee56Smlarkin if (bus_dmamem_alloc(sc->sc_dmat, aqm->aqm_size, 3906bccaee56Smlarkin align, 0, &aqm->aqm_seg, 1, &aqm->aqm_nsegs, 3907bccaee56Smlarkin BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) 3908bccaee56Smlarkin goto destroy; 3909bccaee56Smlarkin if (bus_dmamem_map(sc->sc_dmat, &aqm->aqm_seg, aqm->aqm_nsegs, 3910d59ec8ecSjmatthew aqm->aqm_size, &aqm->aqm_kva, 3911d59ec8ecSjmatthew BUS_DMA_WAITOK | BUS_DMA_COHERENT) != 0) 3912bccaee56Smlarkin goto free; 3913bccaee56Smlarkin if (bus_dmamap_load(sc->sc_dmat, aqm->aqm_map, aqm->aqm_kva, 3914bccaee56Smlarkin aqm->aqm_size, NULL, BUS_DMA_WAITOK) != 0) 3915bccaee56Smlarkin goto unmap; 3916bccaee56Smlarkin 3917bccaee56Smlarkin return (0); 3918bccaee56Smlarkin unmap: 3919bccaee56Smlarkin bus_dmamem_unmap(sc->sc_dmat, aqm->aqm_kva, aqm->aqm_size); 3920bccaee56Smlarkin free: 3921bccaee56Smlarkin bus_dmamem_free(sc->sc_dmat, &aqm->aqm_seg, 1); 3922bccaee56Smlarkin destroy: 3923bccaee56Smlarkin bus_dmamap_destroy(sc->sc_dmat, aqm->aqm_map); 3924bccaee56Smlarkin return (1); 3925bccaee56Smlarkin } 3926bccaee56Smlarkin 3927bccaee56Smlarkin void 3928bccaee56Smlarkin aq_dmamem_free(struct aq_softc *sc, struct aq_dmamem *aqm) 3929bccaee56Smlarkin { 3930bccaee56Smlarkin bus_dmamap_unload(sc->sc_dmat, aqm->aqm_map); 3931bccaee56Smlarkin bus_dmamem_unmap(sc->sc_dmat, aqm->aqm_kva, aqm->aqm_size); 3932bccaee56Smlarkin bus_dmamem_free(sc->sc_dmat, &aqm->aqm_seg, 1); 3933bccaee56Smlarkin bus_dmamap_destroy(sc->sc_dmat, aqm->aqm_map); 3934bccaee56Smlarkin } 3935