xref: /openbsd-src/sys/dev/pci/if_aq_pci.c (revision 175a7a0dd01a931df9ee79879a51fa27ff079ebc)
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