1227569Sphilip/*-
2227569Sphilip * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
3227569Sphilip *
4227569Sphilip * Redistribution and use in source and binary forms, with or without
5227569Sphilip * modification, are permitted provided that the following conditions
6227569Sphilip * are met:
7227569Sphilip * 1. Redistributions of source code must retain the above copyright
8227569Sphilip *    notice, this list of conditions and the following disclaimer.
9227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright
10227569Sphilip *    notice, this list of conditions and the following disclaimer in the
11227569Sphilip *    documentation and/or other materials provided with the distribution.
12227569Sphilip *
13227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14227569Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15227569Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16227569Sphilip * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17227569Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18227569Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19227569Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20227569Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21227569Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22227569Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23227569Sphilip * SUCH DAMAGE.
24227569Sphilip */
25228078Sphilip
26228078Sphilip#include <sys/cdefs.h>
27228078Sphilip__FBSDID("$FreeBSD$");
28228078Sphilip
29227569Sphilip#include "efsys.h"
30227569Sphilip#include "efx.h"
31227569Sphilip#include "efx_impl.h"
32227569Sphilip
33227569Sphilip#if EFSYS_OPT_SIENA
34227569Sphilip
35227569Sphilipstatic	__checkReturn		int
36227569Sphilipsiena_nic_get_partn_mask(
37227569Sphilip	__in			efx_nic_t *enp,
38227569Sphilip	__out			unsigned int *maskp)
39227569Sphilip{
40227569Sphilip	efx_mcdi_req_t req;
41227569Sphilip	uint8_t outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN];
42227569Sphilip	int rc;
43227569Sphilip
44227569Sphilip	req.emr_cmd = MC_CMD_NVRAM_TYPES;
45227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_NVRAM_TYPES_IN_LEN == 0);
46227569Sphilip	req.emr_in_buf = NULL;
47227569Sphilip	req.emr_in_length = 0;
48227569Sphilip	req.emr_out_buf = outbuf;
49227569Sphilip	req.emr_out_length = sizeof (outbuf);
50227569Sphilip
51227569Sphilip	efx_mcdi_execute(enp, &req);
52227569Sphilip
53227569Sphilip	if (req.emr_rc != 0) {
54227569Sphilip		rc = req.emr_rc;
55227569Sphilip		goto fail1;
56227569Sphilip	}
57227569Sphilip
58227569Sphilip	if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
59227569Sphilip		rc = EMSGSIZE;
60227569Sphilip		goto fail2;
61227569Sphilip	}
62227569Sphilip
63227569Sphilip	*maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
64227569Sphilip
65227569Sphilip	return (0);
66227569Sphilip
67227569Sphilipfail2:
68227569Sphilip	EFSYS_PROBE(fail2);
69227569Sphilipfail1:
70227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
71227569Sphilip
72227569Sphilip	return (rc);
73227569Sphilip}
74227569Sphilip
75227569Sphilipstatic	__checkReturn	int
76227569Sphilipsiena_nic_exit_assertion_handler(
77227569Sphilip	__in		efx_nic_t *enp)
78227569Sphilip{
79227569Sphilip	efx_mcdi_req_t req;
80227569Sphilip	uint8_t payload[MC_CMD_REBOOT_IN_LEN];
81227569Sphilip	int rc;
82227569Sphilip
83227569Sphilip	req.emr_cmd = MC_CMD_REBOOT;
84227569Sphilip	req.emr_in_buf = payload;
85227569Sphilip	req.emr_in_length = MC_CMD_REBOOT_IN_LEN;
86227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_REBOOT_OUT_LEN == 0);
87227569Sphilip	req.emr_out_buf = NULL;
88227569Sphilip	req.emr_out_length = 0;
89227569Sphilip
90227569Sphilip	MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS,
91227569Sphilip			    MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
92227569Sphilip
93227569Sphilip	efx_mcdi_execute(enp, &req);
94227569Sphilip
95227569Sphilip	if (req.emr_rc != 0 && req.emr_rc != EIO) {
96227569Sphilip		rc = req.emr_rc;
97227569Sphilip		goto fail1;
98227569Sphilip	}
99227569Sphilip
100227569Sphilip	return (0);
101227569Sphilip
102227569Sphilipfail1:
103227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
104227569Sphilip
105227569Sphilip	return (rc);
106227569Sphilip}
107227569Sphilip
108227569Sphilipstatic	__checkReturn	int
109227569Sphilipsiena_nic_read_assertion(
110227569Sphilip	__in		efx_nic_t *enp)
111227569Sphilip{
112227569Sphilip	efx_mcdi_req_t req;
113227569Sphilip	uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN,
114227569Sphilip			    MC_CMD_GET_ASSERTS_OUT_LEN)];
115227569Sphilip	const char *reason;
116227569Sphilip	unsigned int flags;
117227569Sphilip	unsigned int index;
118227569Sphilip	unsigned int ofst;
119227569Sphilip	int retry;
120227569Sphilip	int rc;
121227569Sphilip
122227569Sphilip	/*
123227569Sphilip	 * Before we attempt to chat to the MC, we should verify that the MC
124227569Sphilip	 * isn't in it's assertion handler, either due to a previous reboot,
125227569Sphilip	 * or because we're reinitializing due to an eec_exception().
126227569Sphilip	 *
127227569Sphilip	 * Use GET_ASSERTS to read any assertion state that may be present.
128227569Sphilip	 * Retry this command twice. Once because a boot-time assertion failure
129227569Sphilip	 * might cause the 1st MCDI request to fail. And once again because
130227569Sphilip	 * we might race with siena_nic_exit_assertion_handler() running on the
131227569Sphilip	 * other port.
132227569Sphilip	 */
133227569Sphilip	retry = 2;
134227569Sphilip	do {
135227569Sphilip		req.emr_cmd = MC_CMD_GET_ASSERTS;
136227569Sphilip		req.emr_in_buf = payload;
137227569Sphilip		req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN;
138227569Sphilip		req.emr_out_buf = payload;
139227569Sphilip		req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN;
140227569Sphilip
141227569Sphilip		MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1);
142227569Sphilip		efx_mcdi_execute(enp, &req);
143227569Sphilip
144227569Sphilip	} while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0);
145227569Sphilip
146227569Sphilip	if (req.emr_rc != 0) {
147227569Sphilip		rc = req.emr_rc;
148227569Sphilip		goto fail1;
149227569Sphilip	}
150227569Sphilip
151227569Sphilip	if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) {
152227569Sphilip		rc = EMSGSIZE;
153227569Sphilip		goto fail2;
154227569Sphilip	}
155227569Sphilip
156227569Sphilip	/* Print out any assertion state recorded */
157227569Sphilip	flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS);
158227569Sphilip	if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
159227569Sphilip		return (0);
160227569Sphilip
161227569Sphilip	reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
162227569Sphilip		? "system-level assertion"
163227569Sphilip		: (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
164227569Sphilip		? "thread-level assertion"
165227569Sphilip		: (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
166227569Sphilip		? "watchdog reset"
167227569Sphilip		: "unknown assertion";
168227569Sphilip	EFSYS_PROBE3(mcpu_assertion,
169227569Sphilip	    const char *, reason, unsigned int,
170227569Sphilip	    MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS),
171227569Sphilip	    unsigned int,
172227569Sphilip	    MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS));
173227569Sphilip
174227569Sphilip	/* Print out the registers */
175227569Sphilip	ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST;
176227569Sphilip	for (index = 1; index < 32; index++) {
177227569Sphilip		EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int,
178227569Sphilip			    EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst),
179227569Sphilip					    EFX_DWORD_0));
180227569Sphilip		ofst += sizeof (efx_dword_t);
181227569Sphilip	}
182227569Sphilip	EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN);
183227569Sphilip
184227569Sphilip	return (0);
185227569Sphilip
186227569Sphilipfail2:
187227569Sphilip	EFSYS_PROBE(fail2);
188227569Sphilipfail1:
189227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
190227569Sphilip
191227569Sphilip	return (rc);
192227569Sphilip}
193227569Sphilip
194227569Sphilipstatic	__checkReturn	int
195227569Sphilipsiena_nic_attach(
196227569Sphilip	__in		efx_nic_t *enp,
197227569Sphilip	__in		boolean_t attach)
198227569Sphilip{
199227569Sphilip	efx_mcdi_req_t req;
200227569Sphilip	uint8_t payload[MC_CMD_DRV_ATTACH_IN_LEN];
201227569Sphilip	int rc;
202227569Sphilip
203227569Sphilip	req.emr_cmd = MC_CMD_DRV_ATTACH;
204227569Sphilip	req.emr_in_buf = payload;
205227569Sphilip	req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN;
206227569Sphilip	req.emr_out_buf = NULL;
207227569Sphilip	req.emr_out_length = 0;
208227569Sphilip
209227569Sphilip	MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0);
210227569Sphilip	MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1);
211227569Sphilip
212227569Sphilip	efx_mcdi_execute(enp, &req);
213227569Sphilip
214227569Sphilip	if (req.emr_rc != 0) {
215227569Sphilip		rc = req.emr_rc;
216227569Sphilip		goto fail1;
217227569Sphilip	}
218227569Sphilip
219227569Sphilip	if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) {
220227569Sphilip		rc = EMSGSIZE;
221227569Sphilip		goto fail2;
222227569Sphilip	}
223227569Sphilip
224227569Sphilip	return (0);
225227569Sphilip
226227569Sphilipfail2:
227227569Sphilip	EFSYS_PROBE(fail2);
228227569Sphilipfail1:
229227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
230227569Sphilip
231227569Sphilip	return (rc);
232227569Sphilip}
233227569Sphilip
234227569Sphilip#if EFSYS_OPT_PCIE_TUNE
235227569Sphilip
236227569Sphilip	__checkReturn	int
237227569Sphilipsiena_nic_pcie_extended_sync(
238227569Sphilip	__in		efx_nic_t *enp)
239227569Sphilip{
240227569Sphilip	uint8_t inbuf[MC_CMD_WORKAROUND_IN_LEN];
241227569Sphilip	efx_mcdi_req_t req;
242227569Sphilip	int rc;
243227569Sphilip
244227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
245227569Sphilip
246227569Sphilip	req.emr_cmd = MC_CMD_WORKAROUND;
247227569Sphilip	req.emr_in_buf = inbuf;
248227569Sphilip	req.emr_in_length = sizeof (inbuf);
249227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_WORKAROUND_OUT_LEN == 0);
250227569Sphilip	req.emr_out_buf = NULL;
251227569Sphilip	req.emr_out_length = 0;
252227569Sphilip
253227569Sphilip	MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, MC_CMD_WORKAROUND_BUG17230);
254227569Sphilip	MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, 1);
255227569Sphilip
256227569Sphilip	efx_mcdi_execute(enp, &req);
257227569Sphilip
258227569Sphilip	if (req.emr_rc != 0) {
259227569Sphilip		rc = req.emr_rc;
260227569Sphilip		goto fail1;
261227569Sphilip	}
262227569Sphilip
263227569Sphilip	return (0);
264227569Sphilip
265227569Sphilipfail1:
266227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
267227569Sphilip
268227569Sphilip	return (rc);
269227569Sphilip}
270227569Sphilip
271227569Sphilip#endif	/* EFSYS_OPT_PCIE_TUNE */
272227569Sphilip
273227569Sphilipstatic	__checkReturn	int
274227569Sphilipsiena_board_cfg(
275227569Sphilip	__in		efx_nic_t *enp)
276227569Sphilip{
277227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
278227569Sphilip	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
279227569Sphilip	uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LEN,
280227569Sphilip		    MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)];
281227569Sphilip	efx_mcdi_req_t req;
282227569Sphilip	uint8_t *src;
283227569Sphilip	int rc;
284227569Sphilip
285227569Sphilip	/* Board configuration */
286227569Sphilip	req.emr_cmd = MC_CMD_GET_BOARD_CFG;
287227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0);
288227569Sphilip	req.emr_in_buf = NULL;
289227569Sphilip	req.emr_in_length = 0;
290227569Sphilip	req.emr_out_buf = outbuf;
291227569Sphilip	req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LEN;
292227569Sphilip
293227569Sphilip	efx_mcdi_execute(enp, &req);
294227569Sphilip
295227569Sphilip	if (req.emr_rc != 0) {
296227569Sphilip		rc = req.emr_rc;
297227569Sphilip		goto fail1;
298227569Sphilip	}
299227569Sphilip
300227569Sphilip	if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LEN) {
301227569Sphilip		rc = EMSGSIZE;
302227569Sphilip		goto fail2;
303227569Sphilip	}
304227569Sphilip
305227569Sphilip	if (emip->emi_port == 1)
306227569Sphilip		src = MCDI_OUT2(req, uint8_t,
307227569Sphilip			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0);
308227569Sphilip	else
309227569Sphilip		src = MCDI_OUT2(req, uint8_t,
310227569Sphilip			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1);
311227569Sphilip	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, src);
312227569Sphilip
313227569Sphilip	encp->enc_board_type = MCDI_OUT_DWORD(req,
314227569Sphilip				    GET_BOARD_CFG_OUT_BOARD_TYPE);
315227569Sphilip
316227569Sphilip	/* Resource limits */
317227569Sphilip	req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS;
318227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0);
319227569Sphilip	req.emr_in_buf = NULL;
320227569Sphilip	req.emr_in_length = 0;
321227569Sphilip	req.emr_out_buf = outbuf;
322227569Sphilip	req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN;
323227569Sphilip
324227569Sphilip	efx_mcdi_execute(enp, &req);
325227569Sphilip
326227569Sphilip	if (req.emr_rc == 0) {
327227569Sphilip		if (req.emr_out_length_used < MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) {
328227569Sphilip			rc = EMSGSIZE;
329227569Sphilip			goto fail3;
330227569Sphilip		}
331227569Sphilip
332227569Sphilip		encp->enc_evq_limit = MCDI_OUT_DWORD(req,
333227569Sphilip		    GET_RESOURCE_LIMITS_OUT_EVQ);
334227569Sphilip		encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET,
335227569Sphilip		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ));
336227569Sphilip		encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET,
337227569Sphilip		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ));
338227569Sphilip	} else if (req.emr_rc == ENOTSUP) {
339227569Sphilip		encp->enc_evq_limit = 1024;
340227569Sphilip		encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
341227569Sphilip		encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
342227569Sphilip	} else {
343227569Sphilip		rc = req.emr_rc;
344227569Sphilip		goto fail4;
345227569Sphilip	}
346227569Sphilip
347227569Sphilip	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
348227569Sphilip	    (encp->enc_txq_limit * 16) - (encp->enc_rxq_limit * 64);
349227569Sphilip
350227569Sphilip	return (0);
351227569Sphilip
352227569Sphilipfail4:
353227569Sphilip	EFSYS_PROBE(fail4);
354227569Sphilipfail3:
355227569Sphilip	EFSYS_PROBE(fail3);
356227569Sphilipfail2:
357227569Sphilip	EFSYS_PROBE(fail2);
358227569Sphilipfail1:
359227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
360227569Sphilip
361227569Sphilip	return (rc);
362227569Sphilip}
363227569Sphilip
364227569Sphilipstatic	__checkReturn	int
365227569Sphilipsiena_phy_cfg(
366227569Sphilip	__in		efx_nic_t *enp)
367227569Sphilip{
368227569Sphilip	efx_port_t *epp = &(enp->en_port);
369227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
370227569Sphilip	efx_mcdi_req_t req;
371227569Sphilip	uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
372227569Sphilip	int rc;
373227569Sphilip
374227569Sphilip	req.emr_cmd = MC_CMD_GET_PHY_CFG;
375227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0);
376227569Sphilip	req.emr_in_buf = NULL;
377227569Sphilip	req.emr_in_length = 0;
378227569Sphilip	req.emr_out_buf = outbuf;
379227569Sphilip	req.emr_out_length = sizeof (outbuf);
380227569Sphilip
381227569Sphilip	efx_mcdi_execute(enp, &req);
382227569Sphilip
383227569Sphilip	if (req.emr_rc != 0) {
384227569Sphilip		rc = req.emr_rc;
385227569Sphilip		goto fail1;
386227569Sphilip	}
387227569Sphilip
388227569Sphilip	if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) {
389227569Sphilip		rc = EMSGSIZE;
390227569Sphilip		goto fail2;
391227569Sphilip	}
392227569Sphilip
393227569Sphilip	encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE);
394227569Sphilip#if EFSYS_OPT_NAMES
395227569Sphilip	(void) strncpy(encp->enc_phy_name,
396227569Sphilip		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME),
397227569Sphilip		MIN(sizeof (encp->enc_phy_name) - 1,
398227569Sphilip		    MC_CMD_GET_PHY_CFG_OUT_NAME_LEN));
399227569Sphilip#endif	/* EFSYS_OPT_NAMES */
400227569Sphilip	(void) memset(encp->enc_phy_revision, 0,
401227569Sphilip	    sizeof (encp->enc_phy_revision));
402227569Sphilip	memcpy(encp->enc_phy_revision,
403227569Sphilip		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION),
404227569Sphilip		MIN(sizeof (encp->enc_phy_revision) - 1,
405227569Sphilip		    MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN));
406227569Sphilip#if EFSYS_OPT_PHY_LED_CONTROL
407227569Sphilip	encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) |
408227569Sphilip			    (1 << EFX_PHY_LED_OFF) |
409227569Sphilip			    (1 << EFX_PHY_LED_ON));
410227569Sphilip#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
411227569Sphilip
412227569Sphilip#if EFSYS_OPT_PHY_PROPS
413227569Sphilip	encp->enc_phy_nprops  = 0;
414227569Sphilip#endif	/* EFSYS_OPT_PHY_PROPS */
415227569Sphilip
416227569Sphilip	/* Get the media type of the fixed port, if recognised. */
417227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI);
418227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4);
419227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4);
420227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP);
421227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS);
422227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T);
423227569Sphilip	epp->ep_fixed_port_type =
424227569Sphilip		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE);
425227569Sphilip	if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES)
426227569Sphilip		epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID;
427227569Sphilip
428227569Sphilip	epp->ep_phy_cap_mask =
429227569Sphilip		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP);
430227569Sphilip#if EFSYS_OPT_PHY_FLAGS
431227569Sphilip	encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS);
432227569Sphilip#endif	/* EFSYS_OPT_PHY_FLAGS */
433227569Sphilip
434227569Sphilip	encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT);
435227569Sphilip
436227569Sphilip	/* Populate internal state */
437227569Sphilip	encp->enc_siena_channel =
438227569Sphilip		(uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL);
439227569Sphilip
440227569Sphilip#if EFSYS_OPT_PHY_STATS
441227569Sphilip	encp->enc_siena_phy_stat_mask =
442227569Sphilip		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK);
443227569Sphilip
444227569Sphilip	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
445227569Sphilip	siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask,
446227569Sphilip			    NULL, &encp->enc_phy_stat_mask, NULL);
447227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
448227569Sphilip
449227569Sphilip#if EFSYS_OPT_PHY_BIST
450227569Sphilip	encp->enc_bist_mask = 0;
451227569Sphilip	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
452227569Sphilip	    GET_PHY_CFG_OUT_BIST_CABLE_SHORT))
453227569Sphilip		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT);
454227569Sphilip	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
455227569Sphilip	    GET_PHY_CFG_OUT_BIST_CABLE_LONG))
456227569Sphilip		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG);
457227569Sphilip	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
458227569Sphilip	    GET_PHY_CFG_OUT_BIST))
459227569Sphilip		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL);
460227569Sphilip#endif	/* EFSYS_OPT_BIST */
461227569Sphilip
462227569Sphilip	return (0);
463227569Sphilip
464227569Sphilipfail2:
465227569Sphilip	EFSYS_PROBE(fail2);
466227569Sphilipfail1:
467227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
468227569Sphilip
469227569Sphilip	return (rc);
470227569Sphilip}
471227569Sphilip
472227569Sphilip#if EFSYS_OPT_LOOPBACK
473227569Sphilip
474227569Sphilipstatic	__checkReturn	int
475227569Sphilipsiena_loopback_cfg(
476227569Sphilip	__in		efx_nic_t *enp)
477227569Sphilip{
478227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
479227569Sphilip	efx_mcdi_req_t req;
480227569Sphilip	uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN];
481227569Sphilip	int rc;
482227569Sphilip
483227569Sphilip	req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
484227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0);
485227569Sphilip	req.emr_in_buf = NULL;
486227569Sphilip	req.emr_in_length = 0;
487227569Sphilip	req.emr_out_buf = outbuf;
488227569Sphilip	req.emr_out_length = sizeof (outbuf);
489227569Sphilip
490227569Sphilip	efx_mcdi_execute(enp, &req);
491227569Sphilip
492227569Sphilip	if (req.emr_rc != 0) {
493227569Sphilip		rc = req.emr_rc;
494227569Sphilip		goto fail1;
495227569Sphilip	}
496227569Sphilip
497227569Sphilip	if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) {
498227569Sphilip		rc = EMSGSIZE;
499227569Sphilip		goto fail2;
500227569Sphilip	}
501227569Sphilip
502227569Sphilip	/*
503227569Sphilip	 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
504227569Sphilip	 * in siena_phy.c:siena_phy_get_link()
505227569Sphilip	 */
506227569Sphilip	encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK &
507227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) &
508227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
509227569Sphilip	encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK &
510227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) &
511227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
512227569Sphilip	encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK &
513227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) &
514227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
515227569Sphilip	encp->enc_loopback_types[EFX_LINK_UNKNOWN] =
516227569Sphilip	    (1 << EFX_LOOPBACK_OFF) |
517227569Sphilip	    encp->enc_loopback_types[EFX_LINK_100FDX] |
518227569Sphilip	    encp->enc_loopback_types[EFX_LINK_1000FDX] |
519227569Sphilip	    encp->enc_loopback_types[EFX_LINK_10000FDX];
520227569Sphilip
521227569Sphilip	return (0);
522227569Sphilip
523227569Sphilipfail2:
524227569Sphilip	EFSYS_PROBE(fail2);
525227569Sphilipfail1:
526227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
527227569Sphilip
528227569Sphilip	return (rc);
529227569Sphilip}
530227569Sphilip
531227569Sphilip#endif	/* EFSYS_OPT_LOOPBACK */
532227569Sphilip
533227569Sphilip#if EFSYS_OPT_MON_STATS
534227569Sphilip
535227569Sphilipstatic	__checkReturn	int
536227569Sphilipsiena_monitor_cfg(
537227569Sphilip	__in		efx_nic_t *enp)
538227569Sphilip{
539227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
540227569Sphilip	efx_mcdi_req_t req;
541227569Sphilip	uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX];
542227569Sphilip	int rc;
543227569Sphilip
544227569Sphilip	req.emr_cmd = MC_CMD_SENSOR_INFO;
545227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0);
546227569Sphilip	req.emr_in_buf = NULL;
547227569Sphilip	req.emr_in_length = 0;
548227569Sphilip	req.emr_out_buf = outbuf;
549227569Sphilip	req.emr_out_length = sizeof (outbuf);
550227569Sphilip
551227569Sphilip	efx_mcdi_execute(enp, &req);
552227569Sphilip
553227569Sphilip	if (req.emr_rc != 0) {
554227569Sphilip		rc = req.emr_rc;
555227569Sphilip		goto fail1;
556227569Sphilip	}
557227569Sphilip
558227569Sphilip	if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) {
559227569Sphilip		rc = EMSGSIZE;
560227569Sphilip		goto fail2;
561227569Sphilip	}
562227569Sphilip
563227569Sphilip	encp->enc_siena_mon_stat_mask =
564227569Sphilip		MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
565227569Sphilip	encp->enc_mon_type = EFX_MON_SFC90X0;
566227569Sphilip
567227569Sphilip	siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask,
568227569Sphilip			    NULL, &(encp->enc_mon_stat_mask), NULL);
569227569Sphilip
570227569Sphilip	return (0);
571227569Sphilip
572227569Sphilipfail2:
573227569Sphilip	EFSYS_PROBE(fail2);
574227569Sphilipfail1:
575227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
576227569Sphilip
577227569Sphilip	return (rc);
578227569Sphilip}
579227569Sphilip
580227569Sphilip#endif	/* EFSYS_OPT_MON_STATS */
581227569Sphilip
582227569Sphilip	__checkReturn	int
583227569Sphilipsiena_nic_probe(
584227569Sphilip	__in		efx_nic_t *enp)
585227569Sphilip{
586227569Sphilip	efx_port_t *epp = &(enp->en_port);
587227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
588227569Sphilip	siena_link_state_t sls;
589227569Sphilip	unsigned int mask;
590227569Sphilip	int rc;
591227569Sphilip
592227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
593227569Sphilip
594227569Sphilip	/* Read clear any assertion state */
595227569Sphilip	if ((rc = siena_nic_read_assertion(enp)) != 0)
596227569Sphilip		goto fail1;
597227569Sphilip
598227569Sphilip	/* Exit the assertion handler */
599227569Sphilip	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
600227569Sphilip		goto fail2;
601227569Sphilip
602227569Sphilip	/* Wrestle control from the BMC */
603227569Sphilip	if ((rc = siena_nic_attach(enp, B_TRUE)) != 0)
604227569Sphilip		goto fail3;
605227569Sphilip
606227569Sphilip	if ((rc = siena_board_cfg(enp)) != 0)
607227569Sphilip		goto fail4;
608227569Sphilip
609227569Sphilip	encp->enc_evq_moderation_max =
610227569Sphilip		EFX_EV_TIMER_QUANTUM << FRF_CZ_TIMER_VAL_WIDTH;
611227569Sphilip
612227569Sphilip	if ((rc = siena_phy_cfg(enp)) != 0)
613227569Sphilip		goto fail5;
614227569Sphilip
615227569Sphilip	/* Obtain the default PHY advertised capabilities */
616227569Sphilip	if ((rc = siena_nic_reset(enp)) != 0)
617227569Sphilip		goto fail6;
618227569Sphilip	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
619227569Sphilip		goto fail7;
620227569Sphilip	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
621227569Sphilip	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
622227569Sphilip
623227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
624227569Sphilip	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
625227569Sphilip		goto fail8;
626227569Sphilip	enp->en_u.siena.enu_partn_mask = mask;
627227569Sphilip#endif
628227569Sphilip
629227569Sphilip#if EFSYS_OPT_MAC_STATS
630227569Sphilip	/* Wipe the MAC statistics */
631227569Sphilip	if ((rc = siena_mac_stats_clear(enp)) != 0)
632227569Sphilip		goto fail9;
633227569Sphilip#endif
634227569Sphilip
635227569Sphilip#if EFSYS_OPT_LOOPBACK
636227569Sphilip	if ((rc = siena_loopback_cfg(enp)) != 0)
637227569Sphilip		goto fail10;
638227569Sphilip#endif
639227569Sphilip
640227569Sphilip#if EFSYS_OPT_MON_STATS
641227569Sphilip	if ((rc = siena_monitor_cfg(enp)) != 0)
642227569Sphilip		goto fail11;
643227569Sphilip#endif
644227569Sphilip
645227569Sphilip	encp->enc_features = enp->en_features;
646227569Sphilip
647227569Sphilip	return (0);
648227569Sphilip
649227569Sphilip#if EFSYS_OPT_MON_STATS
650227569Sphilipfail11:
651227569Sphilip	EFSYS_PROBE(fail11);
652227569Sphilip#endif
653227569Sphilip#if EFSYS_OPT_LOOPBACK
654227569Sphilipfail10:
655227569Sphilip	EFSYS_PROBE(fail10);
656227569Sphilip#endif
657227569Sphilip#if EFSYS_OPT_MAC_STATS
658227569Sphilipfail9:
659227569Sphilip	EFSYS_PROBE(fail9);
660227569Sphilip#endif
661227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
662227569Sphilipfail8:
663227569Sphilip	EFSYS_PROBE(fail8);
664227569Sphilip#endif
665227569Sphilipfail7:
666227569Sphilip	EFSYS_PROBE(fail7);
667227569Sphilipfail6:
668227569Sphilip	EFSYS_PROBE(fail6);
669227569Sphilipfail5:
670227569Sphilip	EFSYS_PROBE(fail5);
671227569Sphilipfail4:
672227569Sphilip	EFSYS_PROBE(fail4);
673227569Sphilipfail3:
674227569Sphilip	EFSYS_PROBE(fail3);
675227569Sphilipfail2:
676227569Sphilip	EFSYS_PROBE(fail2);
677227569Sphilipfail1:
678227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
679227569Sphilip
680227569Sphilip	return (rc);
681227569Sphilip}
682227569Sphilip
683227569Sphilip	__checkReturn	int
684227569Sphilipsiena_nic_reset(
685227569Sphilip	__in		efx_nic_t *enp)
686227569Sphilip{
687227569Sphilip	efx_mcdi_req_t req;
688227569Sphilip	int rc;
689227569Sphilip
690227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
691227569Sphilip
692227569Sphilip	/* siena_nic_reset() is called to recover from BADASSERT failures. */
693227569Sphilip	if ((rc = siena_nic_read_assertion(enp)) != 0)
694227569Sphilip		goto fail1;
695227569Sphilip	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
696227569Sphilip		goto fail2;
697227569Sphilip
698227569Sphilip	req.emr_cmd = MC_CMD_PORT_RESET;
699227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0);
700227569Sphilip	req.emr_in_buf = NULL;
701227569Sphilip	req.emr_in_length = 0;
702227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0);
703227569Sphilip	req.emr_out_buf = NULL;
704227569Sphilip	req.emr_out_length = 0;
705227569Sphilip
706227569Sphilip	efx_mcdi_execute(enp, &req);
707227569Sphilip
708227569Sphilip	if (req.emr_rc != 0) {
709227569Sphilip		rc = req.emr_rc;
710227569Sphilip		goto fail3;
711227569Sphilip	}
712227569Sphilip
713227569Sphilip	return (0);
714227569Sphilip
715227569Sphilipfail3:
716227569Sphilip	EFSYS_PROBE(fail3);
717227569Sphilipfail2:
718227569Sphilip	EFSYS_PROBE(fail2);
719227569Sphilipfail1:
720227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
721227569Sphilip
722227569Sphilip	return (0);
723227569Sphilip}
724227569Sphilip
725227569Sphilipstatic	__checkReturn	int
726227569Sphilipsiena_nic_logging(
727227569Sphilip	__in		efx_nic_t *enp)
728227569Sphilip{
729227569Sphilip	efx_mcdi_req_t req;
730227569Sphilip	uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN];
731227569Sphilip	int rc;
732227569Sphilip
733227569Sphilip	req.emr_cmd = MC_CMD_LOG_CTRL;
734227569Sphilip	req.emr_in_buf = payload;
735227569Sphilip	req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN;
736227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0);
737227569Sphilip	req.emr_out_buf = NULL;
738227569Sphilip	req.emr_out_length = 0;
739227569Sphilip
740227569Sphilip	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST,
741227569Sphilip		    MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ);
742227569Sphilip	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0);
743227569Sphilip
744227569Sphilip	efx_mcdi_execute(enp, &req);
745227569Sphilip
746227569Sphilip	if (req.emr_rc != 0) {
747227569Sphilip		rc = req.emr_rc;
748227569Sphilip		goto fail1;
749227569Sphilip	}
750227569Sphilip
751227569Sphilip	return (0);
752227569Sphilip
753227569Sphilipfail1:
754227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
755227569Sphilip
756227569Sphilip	return (rc);
757227569Sphilip}
758227569Sphilip
759227569Sphilipstatic			void
760227569Sphilipsiena_nic_rx_cfg(
761227569Sphilip	__in		efx_nic_t *enp)
762227569Sphilip{
763227569Sphilip	efx_oword_t oword;
764227569Sphilip
765227569Sphilip	/*
766227569Sphilip	 * RX_INGR_EN is always enabled on Siena, because we rely on
767227569Sphilip	 * the RX parser to be resiliant to missing SOP/EOP.
768227569Sphilip	 */
769227569Sphilip	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
770227569Sphilip	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
771227569Sphilip	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
772227569Sphilip
773227569Sphilip	/* Disable parsing of additional 802.1Q in Q packets */
774227569Sphilip	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
775227569Sphilip	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
776227569Sphilip	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
777227569Sphilip}
778227569Sphilip
779227569Sphilipstatic			void
780227569Sphilipsiena_nic_usrev_dis(
781227569Sphilip	__in		efx_nic_t *enp)
782227569Sphilip{
783227569Sphilip	efx_oword_t	oword;
784227569Sphilip
785227569Sphilip	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
786227569Sphilip	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
787227569Sphilip}
788227569Sphilip
789227569Sphilip	__checkReturn	int
790227569Sphilipsiena_nic_init(
791227569Sphilip	__in		efx_nic_t *enp)
792227569Sphilip{
793227569Sphilip	int rc;
794227569Sphilip
795227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
796227569Sphilip
797227569Sphilip	if ((rc = siena_nic_logging(enp)) != 0)
798227569Sphilip		goto fail1;
799227569Sphilip
800227569Sphilip	siena_sram_init(enp);
801227569Sphilip
802227569Sphilip	/* Configure Siena's RX block */
803227569Sphilip	siena_nic_rx_cfg(enp);
804227569Sphilip
805227569Sphilip	/* Disable USR_EVents for now */
806227569Sphilip	siena_nic_usrev_dis(enp);
807227569Sphilip
808227569Sphilip	/* bug17057: Ensure set_link is called */
809227569Sphilip	if ((rc = siena_phy_reconfigure(enp)) != 0)
810227569Sphilip		goto fail2;
811227569Sphilip
812227569Sphilip	return (0);
813227569Sphilip
814227569Sphilipfail2:
815227569Sphilip	EFSYS_PROBE(fail2);
816227569Sphilipfail1:
817227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
818227569Sphilip
819227569Sphilip	return (rc);
820227569Sphilip}
821227569Sphilip
822227569Sphilip			void
823227569Sphilipsiena_nic_fini(
824227569Sphilip	__in		efx_nic_t *enp)
825227569Sphilip{
826227569Sphilip	_NOTE(ARGUNUSED(enp))
827227569Sphilip}
828227569Sphilip
829227569Sphilip			void
830227569Sphilipsiena_nic_unprobe(
831227569Sphilip	__in		efx_nic_t *enp)
832227569Sphilip{
833227569Sphilip	(void) siena_nic_attach(enp, B_FALSE);
834227569Sphilip}
835227569Sphilip
836227569Sphilip#if EFSYS_OPT_DIAG
837227569Sphilip
838227569Sphilipstatic efx_register_set_t __cs	__siena_registers[] = {
839227569Sphilip	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
840227569Sphilip	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
841227569Sphilip	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
842227569Sphilip	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
843227569Sphilip	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
844227569Sphilip	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
845227569Sphilip	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
846227569Sphilip	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
847227569Sphilip	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
848227569Sphilip	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
849227569Sphilip	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
850227569Sphilip	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
851227569Sphilip	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
852227569Sphilip};
853227569Sphilip
854227569Sphilipstatic const uint32_t __cs	__siena_register_masks[] = {
855227569Sphilip	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
856227569Sphilip	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
857227569Sphilip	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
858227569Sphilip	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
859227569Sphilip	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
860227569Sphilip	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
861227569Sphilip	0x00000003, 0x00000000, 0x00000000, 0x00000000,
862227569Sphilip	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
863227569Sphilip	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
864227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
865227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
866227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
867227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
868227569Sphilip};
869227569Sphilip
870227569Sphilipstatic efx_register_set_t __cs	__siena_tables[] = {
871227569Sphilip	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
872227569Sphilip	    FR_AZ_RX_FILTER_TBL0_ROWS },
873227569Sphilip	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
874227569Sphilip	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
875227569Sphilip	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
876227569Sphilip	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
877227569Sphilip	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
878227569Sphilip	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
879227569Sphilip	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
880227569Sphilip	{ FR_CZ_TX_FILTER_TBL0_OFST,
881227569Sphilip	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
882227569Sphilip	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
883227569Sphilip	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
884227569Sphilip};
885227569Sphilip
886227569Sphilipstatic const uint32_t __cs	__siena_table_masks[] = {
887227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
888227569Sphilip	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
889227569Sphilip	0xFFFFFFFF, 0x0FFFFFFF, 0x01800000, 0x00000000,
890227569Sphilip	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
891227569Sphilip	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
892227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
893227569Sphilip	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
894227569Sphilip};
895227569Sphilip
896227569Sphilip	__checkReturn	int
897227569Sphilipsiena_nic_register_test(
898227569Sphilip	__in		efx_nic_t *enp)
899227569Sphilip{
900227569Sphilip	efx_register_set_t *rsp;
901227569Sphilip	const uint32_t *dwordp;
902227569Sphilip	unsigned int nitems;
903227569Sphilip	unsigned int count;
904227569Sphilip	int rc;
905227569Sphilip
906227569Sphilip	/* Fill out the register mask entries */
907227569Sphilip	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
908227569Sphilip		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
909227569Sphilip
910227569Sphilip	nitems = EFX_ARRAY_SIZE(__siena_registers);
911227569Sphilip	dwordp = __siena_register_masks;
912227569Sphilip	for (count = 0; count < nitems; ++count) {
913227569Sphilip		rsp = __siena_registers + count;
914227569Sphilip		rsp->mask.eo_u32[0] = *dwordp++;
915227569Sphilip		rsp->mask.eo_u32[1] = *dwordp++;
916227569Sphilip		rsp->mask.eo_u32[2] = *dwordp++;
917227569Sphilip		rsp->mask.eo_u32[3] = *dwordp++;
918227569Sphilip	}
919227569Sphilip
920227569Sphilip	/* Fill out the register table entries */
921227569Sphilip	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
922227569Sphilip		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
923227569Sphilip
924227569Sphilip	nitems = EFX_ARRAY_SIZE(__siena_tables);
925227569Sphilip	dwordp = __siena_table_masks;
926227569Sphilip	for (count = 0; count < nitems; ++count) {
927227569Sphilip		rsp = __siena_tables + count;
928227569Sphilip		rsp->mask.eo_u32[0] = *dwordp++;
929227569Sphilip		rsp->mask.eo_u32[1] = *dwordp++;
930227569Sphilip		rsp->mask.eo_u32[2] = *dwordp++;
931227569Sphilip		rsp->mask.eo_u32[3] = *dwordp++;
932227569Sphilip	}
933227569Sphilip
934227569Sphilip	if ((rc = efx_nic_test_registers(enp, __siena_registers,
935227569Sphilip	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
936227569Sphilip		goto fail1;
937227569Sphilip
938227569Sphilip	if ((rc = efx_nic_test_tables(enp, __siena_tables,
939227569Sphilip	    EFX_PATTERN_BYTE_ALTERNATE,
940227569Sphilip	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
941227569Sphilip		goto fail2;
942227569Sphilip
943227569Sphilip	if ((rc = efx_nic_test_tables(enp, __siena_tables,
944227569Sphilip	    EFX_PATTERN_BYTE_CHANGING,
945227569Sphilip	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
946227569Sphilip		goto fail3;
947227569Sphilip
948227569Sphilip	if ((rc = efx_nic_test_tables(enp, __siena_tables,
949227569Sphilip	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
950227569Sphilip		goto fail4;
951227569Sphilip
952227569Sphilip	return (0);
953227569Sphilip
954227569Sphilipfail4:
955227569Sphilip	EFSYS_PROBE(fail4);
956227569Sphilipfail3:
957227569Sphilip	EFSYS_PROBE(fail3);
958227569Sphilipfail2:
959227569Sphilip	EFSYS_PROBE(fail2);
960227569Sphilipfail1:
961227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
962227569Sphilip
963227569Sphilip	return (rc);
964227569Sphilip}
965227569Sphilip
966227569Sphilip#endif	/* EFSYS_OPT_DIAG */
967227569Sphilip
968227569Sphilip#endif	/* EFSYS_OPT_SIENA */
969