siena_nic.c revision 279182
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: head/sys/dev/sfxge/common/siena_nic.c 279182 2015-02-22 19:13:52Z arybchik $");
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);
279278941Sarybchik	uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LENMIN,
280227569Sphilip		    MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)];
281227569Sphilip	efx_mcdi_req_t req;
282279048Sarybchik	uint8_t *mac_addr;
283279048Sarybchik	efx_dword_t *capabilities;
284227569Sphilip	int rc;
285227569Sphilip
286227569Sphilip	/* Board configuration */
287227569Sphilip	req.emr_cmd = MC_CMD_GET_BOARD_CFG;
288227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0);
289227569Sphilip	req.emr_in_buf = NULL;
290227569Sphilip	req.emr_in_length = 0;
291227569Sphilip	req.emr_out_buf = outbuf;
292278941Sarybchik	req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMIN;
293227569Sphilip
294227569Sphilip	efx_mcdi_execute(enp, &req);
295227569Sphilip
296227569Sphilip	if (req.emr_rc != 0) {
297227569Sphilip		rc = req.emr_rc;
298227569Sphilip		goto fail1;
299227569Sphilip	}
300227569Sphilip
301278941Sarybchik	if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
302227569Sphilip		rc = EMSGSIZE;
303227569Sphilip		goto fail2;
304227569Sphilip	}
305227569Sphilip
306279048Sarybchik	if (emip->emi_port == 1) {
307279048Sarybchik		mac_addr = MCDI_OUT2(req, uint8_t,
308227569Sphilip			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0);
309279048Sarybchik		capabilities = MCDI_OUT2(req, efx_dword_t,
310279048Sarybchik			    GET_BOARD_CFG_OUT_CAPABILITIES_PORT0);
311279048Sarybchik	} else {
312279048Sarybchik		mac_addr = MCDI_OUT2(req, uint8_t,
313227569Sphilip			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1);
314279048Sarybchik		capabilities = MCDI_OUT2(req, efx_dword_t,
315279048Sarybchik			    GET_BOARD_CFG_OUT_CAPABILITIES_PORT1);
316279048Sarybchik	}
317279048Sarybchik	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
318227569Sphilip
319227569Sphilip	encp->enc_board_type = MCDI_OUT_DWORD(req,
320227569Sphilip				    GET_BOARD_CFG_OUT_BOARD_TYPE);
321227569Sphilip
322279048Sarybchik	/* Additional capabilities */
323279048Sarybchik	encp->enc_clk_mult = 1;
324279048Sarybchik	if (MCDI_CMD_DWORD_FIELD(capabilities, CAPABILITIES_TURBO)) {
325279048Sarybchik		enp->en_features |= EFX_FEATURE_TURBO;
326279048Sarybchik
327279048Sarybchik		if (MCDI_CMD_DWORD_FIELD(capabilities,
328279048Sarybchik		    CAPABILITIES_TURBO_ACTIVE))
329279048Sarybchik			encp->enc_clk_mult = 2;
330279048Sarybchik	}
331279048Sarybchik
332279182Sarybchik	encp->enc_evq_timer_quantum_ns =
333279182Sarybchik		EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
334279182Sarybchik	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
335279182Sarybchik		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
336279048Sarybchik
337227569Sphilip	/* Resource limits */
338227569Sphilip	req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS;
339227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0);
340227569Sphilip	req.emr_in_buf = NULL;
341227569Sphilip	req.emr_in_length = 0;
342227569Sphilip	req.emr_out_buf = outbuf;
343227569Sphilip	req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN;
344227569Sphilip
345227569Sphilip	efx_mcdi_execute(enp, &req);
346227569Sphilip
347227569Sphilip	if (req.emr_rc == 0) {
348278839Sarybchik		if (req.emr_out_length_used <
349278839Sarybchik		    MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) {
350227569Sphilip			rc = EMSGSIZE;
351227569Sphilip			goto fail3;
352227569Sphilip		}
353227569Sphilip
354227569Sphilip		encp->enc_evq_limit = MCDI_OUT_DWORD(req,
355227569Sphilip		    GET_RESOURCE_LIMITS_OUT_EVQ);
356227569Sphilip		encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET,
357227569Sphilip		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ));
358227569Sphilip		encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET,
359227569Sphilip		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ));
360227569Sphilip	} else if (req.emr_rc == ENOTSUP) {
361227569Sphilip		encp->enc_evq_limit = 1024;
362227569Sphilip		encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
363227569Sphilip		encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
364227569Sphilip	} else {
365227569Sphilip		rc = req.emr_rc;
366227569Sphilip		goto fail4;
367227569Sphilip	}
368227569Sphilip
369227569Sphilip	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
370279098Sarybchik	    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
371279098Sarybchik	    (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
372227569Sphilip
373227569Sphilip	return (0);
374227569Sphilip
375227569Sphilipfail4:
376227569Sphilip	EFSYS_PROBE(fail4);
377227569Sphilipfail3:
378227569Sphilip	EFSYS_PROBE(fail3);
379227569Sphilipfail2:
380227569Sphilip	EFSYS_PROBE(fail2);
381227569Sphilipfail1:
382227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
383227569Sphilip
384227569Sphilip	return (rc);
385227569Sphilip}
386227569Sphilip
387227569Sphilipstatic	__checkReturn	int
388227569Sphilipsiena_phy_cfg(
389227569Sphilip	__in		efx_nic_t *enp)
390227569Sphilip{
391227569Sphilip	efx_port_t *epp = &(enp->en_port);
392227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
393227569Sphilip	efx_mcdi_req_t req;
394227569Sphilip	uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
395227569Sphilip	int rc;
396227569Sphilip
397227569Sphilip	req.emr_cmd = MC_CMD_GET_PHY_CFG;
398227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0);
399227569Sphilip	req.emr_in_buf = NULL;
400227569Sphilip	req.emr_in_length = 0;
401227569Sphilip	req.emr_out_buf = outbuf;
402227569Sphilip	req.emr_out_length = sizeof (outbuf);
403227569Sphilip
404227569Sphilip	efx_mcdi_execute(enp, &req);
405227569Sphilip
406227569Sphilip	if (req.emr_rc != 0) {
407227569Sphilip		rc = req.emr_rc;
408227569Sphilip		goto fail1;
409227569Sphilip	}
410227569Sphilip
411227569Sphilip	if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) {
412227569Sphilip		rc = EMSGSIZE;
413227569Sphilip		goto fail2;
414227569Sphilip	}
415227569Sphilip
416227569Sphilip	encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE);
417227569Sphilip#if EFSYS_OPT_NAMES
418227569Sphilip	(void) strncpy(encp->enc_phy_name,
419227569Sphilip		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME),
420227569Sphilip		MIN(sizeof (encp->enc_phy_name) - 1,
421227569Sphilip		    MC_CMD_GET_PHY_CFG_OUT_NAME_LEN));
422227569Sphilip#endif	/* EFSYS_OPT_NAMES */
423227569Sphilip	(void) memset(encp->enc_phy_revision, 0,
424227569Sphilip	    sizeof (encp->enc_phy_revision));
425227569Sphilip	memcpy(encp->enc_phy_revision,
426227569Sphilip		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION),
427227569Sphilip		MIN(sizeof (encp->enc_phy_revision) - 1,
428227569Sphilip		    MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN));
429227569Sphilip#if EFSYS_OPT_PHY_LED_CONTROL
430227569Sphilip	encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) |
431227569Sphilip			    (1 << EFX_PHY_LED_OFF) |
432227569Sphilip			    (1 << EFX_PHY_LED_ON));
433227569Sphilip#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
434227569Sphilip
435227569Sphilip#if EFSYS_OPT_PHY_PROPS
436227569Sphilip	encp->enc_phy_nprops  = 0;
437227569Sphilip#endif	/* EFSYS_OPT_PHY_PROPS */
438227569Sphilip
439227569Sphilip	/* Get the media type of the fixed port, if recognised. */
440227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI);
441227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4);
442227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4);
443227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP);
444227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS);
445227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T);
446227569Sphilip	epp->ep_fixed_port_type =
447227569Sphilip		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE);
448227569Sphilip	if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES)
449227569Sphilip		epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID;
450227569Sphilip
451227569Sphilip	epp->ep_phy_cap_mask =
452227569Sphilip		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP);
453227569Sphilip#if EFSYS_OPT_PHY_FLAGS
454227569Sphilip	encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS);
455227569Sphilip#endif	/* EFSYS_OPT_PHY_FLAGS */
456227569Sphilip
457227569Sphilip	encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT);
458227569Sphilip
459227569Sphilip	/* Populate internal state */
460227569Sphilip	encp->enc_siena_channel =
461227569Sphilip		(uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL);
462227569Sphilip
463227569Sphilip#if EFSYS_OPT_PHY_STATS
464227569Sphilip	encp->enc_siena_phy_stat_mask =
465227569Sphilip		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK);
466227569Sphilip
467227569Sphilip	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
468227569Sphilip	siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask,
469227569Sphilip			    NULL, &encp->enc_phy_stat_mask, NULL);
470227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
471227569Sphilip
472227569Sphilip#if EFSYS_OPT_PHY_BIST
473227569Sphilip	encp->enc_bist_mask = 0;
474227569Sphilip	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
475227569Sphilip	    GET_PHY_CFG_OUT_BIST_CABLE_SHORT))
476227569Sphilip		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT);
477227569Sphilip	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
478227569Sphilip	    GET_PHY_CFG_OUT_BIST_CABLE_LONG))
479227569Sphilip		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG);
480227569Sphilip	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
481227569Sphilip	    GET_PHY_CFG_OUT_BIST))
482227569Sphilip		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL);
483279141Sarybchik#endif	/* EFSYS_OPT_PHY_BIST */
484227569Sphilip
485227569Sphilip	return (0);
486227569Sphilip
487227569Sphilipfail2:
488227569Sphilip	EFSYS_PROBE(fail2);
489227569Sphilipfail1:
490227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
491227569Sphilip
492227569Sphilip	return (rc);
493227569Sphilip}
494227569Sphilip
495227569Sphilip#if EFSYS_OPT_LOOPBACK
496227569Sphilip
497227569Sphilipstatic	__checkReturn	int
498227569Sphilipsiena_loopback_cfg(
499227569Sphilip	__in		efx_nic_t *enp)
500227569Sphilip{
501227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
502227569Sphilip	efx_mcdi_req_t req;
503227569Sphilip	uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN];
504227569Sphilip	int rc;
505227569Sphilip
506227569Sphilip	req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
507227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0);
508227569Sphilip	req.emr_in_buf = NULL;
509227569Sphilip	req.emr_in_length = 0;
510227569Sphilip	req.emr_out_buf = outbuf;
511227569Sphilip	req.emr_out_length = sizeof (outbuf);
512227569Sphilip
513227569Sphilip	efx_mcdi_execute(enp, &req);
514227569Sphilip
515227569Sphilip	if (req.emr_rc != 0) {
516227569Sphilip		rc = req.emr_rc;
517227569Sphilip		goto fail1;
518227569Sphilip	}
519227569Sphilip
520227569Sphilip	if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) {
521227569Sphilip		rc = EMSGSIZE;
522227569Sphilip		goto fail2;
523227569Sphilip	}
524227569Sphilip
525227569Sphilip	/*
526227569Sphilip	 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
527227569Sphilip	 * in siena_phy.c:siena_phy_get_link()
528227569Sphilip	 */
529227569Sphilip	encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK &
530227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) &
531227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
532227569Sphilip	encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK &
533227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) &
534227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
535227569Sphilip	encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK &
536227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) &
537227569Sphilip	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
538227569Sphilip	encp->enc_loopback_types[EFX_LINK_UNKNOWN] =
539227569Sphilip	    (1 << EFX_LOOPBACK_OFF) |
540227569Sphilip	    encp->enc_loopback_types[EFX_LINK_100FDX] |
541227569Sphilip	    encp->enc_loopback_types[EFX_LINK_1000FDX] |
542227569Sphilip	    encp->enc_loopback_types[EFX_LINK_10000FDX];
543227569Sphilip
544227569Sphilip	return (0);
545227569Sphilip
546227569Sphilipfail2:
547227569Sphilip	EFSYS_PROBE(fail2);
548227569Sphilipfail1:
549227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
550227569Sphilip
551227569Sphilip	return (rc);
552227569Sphilip}
553227569Sphilip
554227569Sphilip#endif	/* EFSYS_OPT_LOOPBACK */
555227569Sphilip
556227569Sphilip#if EFSYS_OPT_MON_STATS
557227569Sphilip
558227569Sphilipstatic	__checkReturn	int
559227569Sphilipsiena_monitor_cfg(
560227569Sphilip	__in		efx_nic_t *enp)
561227569Sphilip{
562227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
563227569Sphilip	efx_mcdi_req_t req;
564227569Sphilip	uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX];
565227569Sphilip	int rc;
566227569Sphilip
567227569Sphilip	req.emr_cmd = MC_CMD_SENSOR_INFO;
568227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0);
569227569Sphilip	req.emr_in_buf = NULL;
570227569Sphilip	req.emr_in_length = 0;
571227569Sphilip	req.emr_out_buf = outbuf;
572227569Sphilip	req.emr_out_length = sizeof (outbuf);
573227569Sphilip
574227569Sphilip	efx_mcdi_execute(enp, &req);
575227569Sphilip
576227569Sphilip	if (req.emr_rc != 0) {
577227569Sphilip		rc = req.emr_rc;
578227569Sphilip		goto fail1;
579227569Sphilip	}
580227569Sphilip
581227569Sphilip	if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) {
582227569Sphilip		rc = EMSGSIZE;
583227569Sphilip		goto fail2;
584227569Sphilip	}
585227569Sphilip
586227569Sphilip	encp->enc_siena_mon_stat_mask =
587227569Sphilip		MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
588227569Sphilip	encp->enc_mon_type = EFX_MON_SFC90X0;
589227569Sphilip
590227569Sphilip	siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask,
591227569Sphilip			    NULL, &(encp->enc_mon_stat_mask), NULL);
592227569Sphilip
593227569Sphilip	return (0);
594227569Sphilip
595227569Sphilipfail2:
596227569Sphilip	EFSYS_PROBE(fail2);
597227569Sphilipfail1:
598227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
599227569Sphilip
600227569Sphilip	return (rc);
601227569Sphilip}
602227569Sphilip
603227569Sphilip#endif	/* EFSYS_OPT_MON_STATS */
604227569Sphilip
605227569Sphilip	__checkReturn	int
606227569Sphilipsiena_nic_probe(
607227569Sphilip	__in		efx_nic_t *enp)
608227569Sphilip{
609227569Sphilip	efx_port_t *epp = &(enp->en_port);
610227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
611227569Sphilip	siena_link_state_t sls;
612227569Sphilip	unsigned int mask;
613227569Sphilip	int rc;
614227569Sphilip
615227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
616227569Sphilip
617227569Sphilip	/* Read clear any assertion state */
618227569Sphilip	if ((rc = siena_nic_read_assertion(enp)) != 0)
619227569Sphilip		goto fail1;
620227569Sphilip
621227569Sphilip	/* Exit the assertion handler */
622227569Sphilip	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
623227569Sphilip		goto fail2;
624227569Sphilip
625227569Sphilip	/* Wrestle control from the BMC */
626227569Sphilip	if ((rc = siena_nic_attach(enp, B_TRUE)) != 0)
627227569Sphilip		goto fail3;
628227569Sphilip
629227569Sphilip	if ((rc = siena_board_cfg(enp)) != 0)
630227569Sphilip		goto fail4;
631227569Sphilip
632227569Sphilip	if ((rc = siena_phy_cfg(enp)) != 0)
633227569Sphilip		goto fail5;
634227569Sphilip
635227569Sphilip	/* Obtain the default PHY advertised capabilities */
636227569Sphilip	if ((rc = siena_nic_reset(enp)) != 0)
637227569Sphilip		goto fail6;
638227569Sphilip	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
639227569Sphilip		goto fail7;
640227569Sphilip	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
641227569Sphilip	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
642227569Sphilip
643227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
644227569Sphilip	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
645227569Sphilip		goto fail8;
646227569Sphilip	enp->en_u.siena.enu_partn_mask = mask;
647227569Sphilip#endif
648227569Sphilip
649227569Sphilip#if EFSYS_OPT_MAC_STATS
650227569Sphilip	/* Wipe the MAC statistics */
651227569Sphilip	if ((rc = siena_mac_stats_clear(enp)) != 0)
652227569Sphilip		goto fail9;
653227569Sphilip#endif
654227569Sphilip
655227569Sphilip#if EFSYS_OPT_LOOPBACK
656227569Sphilip	if ((rc = siena_loopback_cfg(enp)) != 0)
657227569Sphilip		goto fail10;
658227569Sphilip#endif
659227569Sphilip
660227569Sphilip#if EFSYS_OPT_MON_STATS
661227569Sphilip	if ((rc = siena_monitor_cfg(enp)) != 0)
662227569Sphilip		goto fail11;
663227569Sphilip#endif
664227569Sphilip
665227569Sphilip	encp->enc_features = enp->en_features;
666227569Sphilip
667227569Sphilip	return (0);
668227569Sphilip
669227569Sphilip#if EFSYS_OPT_MON_STATS
670227569Sphilipfail11:
671227569Sphilip	EFSYS_PROBE(fail11);
672227569Sphilip#endif
673227569Sphilip#if EFSYS_OPT_LOOPBACK
674227569Sphilipfail10:
675227569Sphilip	EFSYS_PROBE(fail10);
676227569Sphilip#endif
677227569Sphilip#if EFSYS_OPT_MAC_STATS
678227569Sphilipfail9:
679227569Sphilip	EFSYS_PROBE(fail9);
680227569Sphilip#endif
681227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
682227569Sphilipfail8:
683227569Sphilip	EFSYS_PROBE(fail8);
684227569Sphilip#endif
685227569Sphilipfail7:
686227569Sphilip	EFSYS_PROBE(fail7);
687227569Sphilipfail6:
688227569Sphilip	EFSYS_PROBE(fail6);
689227569Sphilipfail5:
690227569Sphilip	EFSYS_PROBE(fail5);
691227569Sphilipfail4:
692227569Sphilip	EFSYS_PROBE(fail4);
693227569Sphilipfail3:
694227569Sphilip	EFSYS_PROBE(fail3);
695227569Sphilipfail2:
696227569Sphilip	EFSYS_PROBE(fail2);
697227569Sphilipfail1:
698227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
699227569Sphilip
700227569Sphilip	return (rc);
701227569Sphilip}
702227569Sphilip
703227569Sphilip	__checkReturn	int
704227569Sphilipsiena_nic_reset(
705227569Sphilip	__in		efx_nic_t *enp)
706227569Sphilip{
707227569Sphilip	efx_mcdi_req_t req;
708227569Sphilip	int rc;
709227569Sphilip
710227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
711227569Sphilip
712227569Sphilip	/* siena_nic_reset() is called to recover from BADASSERT failures. */
713227569Sphilip	if ((rc = siena_nic_read_assertion(enp)) != 0)
714227569Sphilip		goto fail1;
715227569Sphilip	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
716227569Sphilip		goto fail2;
717227569Sphilip
718227569Sphilip	req.emr_cmd = MC_CMD_PORT_RESET;
719227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0);
720227569Sphilip	req.emr_in_buf = NULL;
721227569Sphilip	req.emr_in_length = 0;
722227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0);
723227569Sphilip	req.emr_out_buf = NULL;
724227569Sphilip	req.emr_out_length = 0;
725227569Sphilip
726227569Sphilip	efx_mcdi_execute(enp, &req);
727227569Sphilip
728227569Sphilip	if (req.emr_rc != 0) {
729227569Sphilip		rc = req.emr_rc;
730227569Sphilip		goto fail3;
731227569Sphilip	}
732227569Sphilip
733227569Sphilip	return (0);
734227569Sphilip
735227569Sphilipfail3:
736227569Sphilip	EFSYS_PROBE(fail3);
737227569Sphilipfail2:
738227569Sphilip	EFSYS_PROBE(fail2);
739227569Sphilipfail1:
740227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
741227569Sphilip
742227569Sphilip	return (0);
743227569Sphilip}
744227569Sphilip
745227569Sphilipstatic	__checkReturn	int
746227569Sphilipsiena_nic_logging(
747227569Sphilip	__in		efx_nic_t *enp)
748227569Sphilip{
749227569Sphilip	efx_mcdi_req_t req;
750227569Sphilip	uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN];
751227569Sphilip	int rc;
752227569Sphilip
753227569Sphilip	req.emr_cmd = MC_CMD_LOG_CTRL;
754227569Sphilip	req.emr_in_buf = payload;
755227569Sphilip	req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN;
756227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0);
757227569Sphilip	req.emr_out_buf = NULL;
758227569Sphilip	req.emr_out_length = 0;
759227569Sphilip
760227569Sphilip	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST,
761227569Sphilip		    MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ);
762227569Sphilip	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0);
763227569Sphilip
764227569Sphilip	efx_mcdi_execute(enp, &req);
765227569Sphilip
766227569Sphilip	if (req.emr_rc != 0) {
767227569Sphilip		rc = req.emr_rc;
768227569Sphilip		goto fail1;
769227569Sphilip	}
770227569Sphilip
771227569Sphilip	return (0);
772227569Sphilip
773227569Sphilipfail1:
774227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
775227569Sphilip
776227569Sphilip	return (rc);
777227569Sphilip}
778227569Sphilip
779227569Sphilipstatic			void
780227569Sphilipsiena_nic_rx_cfg(
781227569Sphilip	__in		efx_nic_t *enp)
782227569Sphilip{
783227569Sphilip	efx_oword_t oword;
784227569Sphilip
785227569Sphilip	/*
786227569Sphilip	 * RX_INGR_EN is always enabled on Siena, because we rely on
787227569Sphilip	 * the RX parser to be resiliant to missing SOP/EOP.
788227569Sphilip	 */
789227569Sphilip	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
790227569Sphilip	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
791227569Sphilip	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
792227569Sphilip
793227569Sphilip	/* Disable parsing of additional 802.1Q in Q packets */
794227569Sphilip	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
795227569Sphilip	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
796227569Sphilip	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
797227569Sphilip}
798227569Sphilip
799227569Sphilipstatic			void
800227569Sphilipsiena_nic_usrev_dis(
801227569Sphilip	__in		efx_nic_t *enp)
802227569Sphilip{
803227569Sphilip	efx_oword_t	oword;
804227569Sphilip
805227569Sphilip	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
806227569Sphilip	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
807227569Sphilip}
808227569Sphilip
809227569Sphilip	__checkReturn	int
810227569Sphilipsiena_nic_init(
811227569Sphilip	__in		efx_nic_t *enp)
812227569Sphilip{
813227569Sphilip	int rc;
814227569Sphilip
815227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
816227569Sphilip
817227569Sphilip	if ((rc = siena_nic_logging(enp)) != 0)
818227569Sphilip		goto fail1;
819227569Sphilip
820227569Sphilip	siena_sram_init(enp);
821227569Sphilip
822227569Sphilip	/* Configure Siena's RX block */
823227569Sphilip	siena_nic_rx_cfg(enp);
824227569Sphilip
825227569Sphilip	/* Disable USR_EVents for now */
826227569Sphilip	siena_nic_usrev_dis(enp);
827227569Sphilip
828227569Sphilip	/* bug17057: Ensure set_link is called */
829227569Sphilip	if ((rc = siena_phy_reconfigure(enp)) != 0)
830227569Sphilip		goto fail2;
831227569Sphilip
832227569Sphilip	return (0);
833227569Sphilip
834227569Sphilipfail2:
835227569Sphilip	EFSYS_PROBE(fail2);
836227569Sphilipfail1:
837227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
838227569Sphilip
839227569Sphilip	return (rc);
840227569Sphilip}
841227569Sphilip
842227569Sphilip			void
843227569Sphilipsiena_nic_fini(
844227569Sphilip	__in		efx_nic_t *enp)
845227569Sphilip{
846227569Sphilip	_NOTE(ARGUNUSED(enp))
847227569Sphilip}
848227569Sphilip
849227569Sphilip			void
850227569Sphilipsiena_nic_unprobe(
851227569Sphilip	__in		efx_nic_t *enp)
852227569Sphilip{
853227569Sphilip	(void) siena_nic_attach(enp, B_FALSE);
854227569Sphilip}
855227569Sphilip
856227569Sphilip#if EFSYS_OPT_DIAG
857227569Sphilip
858227569Sphilipstatic efx_register_set_t __cs	__siena_registers[] = {
859227569Sphilip	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
860227569Sphilip	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
861227569Sphilip	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
862227569Sphilip	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
863227569Sphilip	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
864227569Sphilip	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
865227569Sphilip	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
866227569Sphilip	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
867227569Sphilip	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
868227569Sphilip	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
869227569Sphilip	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
870227569Sphilip	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
871227569Sphilip	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
872227569Sphilip};
873227569Sphilip
874227569Sphilipstatic const uint32_t __cs	__siena_register_masks[] = {
875227569Sphilip	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
876227569Sphilip	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
877227569Sphilip	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
878227569Sphilip	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
879227569Sphilip	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
880227569Sphilip	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
881227569Sphilip	0x00000003, 0x00000000, 0x00000000, 0x00000000,
882227569Sphilip	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
883227569Sphilip	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
884227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
885227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
886227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
887227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
888227569Sphilip};
889227569Sphilip
890227569Sphilipstatic efx_register_set_t __cs	__siena_tables[] = {
891227569Sphilip	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
892227569Sphilip	    FR_AZ_RX_FILTER_TBL0_ROWS },
893227569Sphilip	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
894227569Sphilip	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
895227569Sphilip	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
896227569Sphilip	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
897227569Sphilip	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
898227569Sphilip	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
899227569Sphilip	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
900227569Sphilip	{ FR_CZ_TX_FILTER_TBL0_OFST,
901227569Sphilip	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
902227569Sphilip	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
903227569Sphilip	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
904227569Sphilip};
905227569Sphilip
906227569Sphilipstatic const uint32_t __cs	__siena_table_masks[] = {
907227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
908227569Sphilip	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
909279095Sarybchik	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
910227569Sphilip	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
911227569Sphilip	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
912227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
913227569Sphilip	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
914227569Sphilip};
915227569Sphilip
916227569Sphilip	__checkReturn	int
917227569Sphilipsiena_nic_register_test(
918227569Sphilip	__in		efx_nic_t *enp)
919227569Sphilip{
920227569Sphilip	efx_register_set_t *rsp;
921227569Sphilip	const uint32_t *dwordp;
922227569Sphilip	unsigned int nitems;
923227569Sphilip	unsigned int count;
924227569Sphilip	int rc;
925227569Sphilip
926227569Sphilip	/* Fill out the register mask entries */
927227569Sphilip	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
928227569Sphilip		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
929227569Sphilip
930227569Sphilip	nitems = EFX_ARRAY_SIZE(__siena_registers);
931227569Sphilip	dwordp = __siena_register_masks;
932227569Sphilip	for (count = 0; count < nitems; ++count) {
933227569Sphilip		rsp = __siena_registers + count;
934227569Sphilip		rsp->mask.eo_u32[0] = *dwordp++;
935227569Sphilip		rsp->mask.eo_u32[1] = *dwordp++;
936227569Sphilip		rsp->mask.eo_u32[2] = *dwordp++;
937227569Sphilip		rsp->mask.eo_u32[3] = *dwordp++;
938227569Sphilip	}
939227569Sphilip
940227569Sphilip	/* Fill out the register table entries */
941227569Sphilip	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
942227569Sphilip		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
943227569Sphilip
944227569Sphilip	nitems = EFX_ARRAY_SIZE(__siena_tables);
945227569Sphilip	dwordp = __siena_table_masks;
946227569Sphilip	for (count = 0; count < nitems; ++count) {
947227569Sphilip		rsp = __siena_tables + count;
948227569Sphilip		rsp->mask.eo_u32[0] = *dwordp++;
949227569Sphilip		rsp->mask.eo_u32[1] = *dwordp++;
950227569Sphilip		rsp->mask.eo_u32[2] = *dwordp++;
951227569Sphilip		rsp->mask.eo_u32[3] = *dwordp++;
952227569Sphilip	}
953227569Sphilip
954227569Sphilip	if ((rc = efx_nic_test_registers(enp, __siena_registers,
955227569Sphilip	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
956227569Sphilip		goto fail1;
957227569Sphilip
958227569Sphilip	if ((rc = efx_nic_test_tables(enp, __siena_tables,
959227569Sphilip	    EFX_PATTERN_BYTE_ALTERNATE,
960227569Sphilip	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
961227569Sphilip		goto fail2;
962227569Sphilip
963227569Sphilip	if ((rc = efx_nic_test_tables(enp, __siena_tables,
964227569Sphilip	    EFX_PATTERN_BYTE_CHANGING,
965227569Sphilip	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
966227569Sphilip		goto fail3;
967227569Sphilip
968227569Sphilip	if ((rc = efx_nic_test_tables(enp, __siena_tables,
969227569Sphilip	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
970227569Sphilip		goto fail4;
971227569Sphilip
972227569Sphilip	return (0);
973227569Sphilip
974227569Sphilipfail4:
975227569Sphilip	EFSYS_PROBE(fail4);
976227569Sphilipfail3:
977227569Sphilip	EFSYS_PROBE(fail3);
978227569Sphilipfail2:
979227569Sphilip	EFSYS_PROBE(fail2);
980227569Sphilipfail1:
981227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
982227569Sphilip
983227569Sphilip	return (rc);
984227569Sphilip}
985227569Sphilip
986227569Sphilip#endif	/* EFSYS_OPT_DIAG */
987227569Sphilip
988227569Sphilip#endif	/* EFSYS_OPT_SIENA */
989