1227569Sphilip/*-
2227569Sphilip * Copyright 2007-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 */
25227569Sphilip
26228100Sphilip#include <sys/cdefs.h>
27228100Sphilip__FBSDID("$FreeBSD$");
28228100Sphilip
29227569Sphilip#include "efsys.h"
30227569Sphilip#include "efx.h"
31227569Sphilip#include "efx_types.h"
32227569Sphilip#include "efx_regs.h"
33227569Sphilip#include "efx_impl.h"
34227569Sphilip#if EFSYS_OPT_FALCON
35227569Sphilip#include "falcon_nvram.h"
36227569Sphilip#endif
37227569Sphilip
38227569Sphilip#if EFSYS_OPT_MAC_FALCON_XMAC
39227569Sphilip#include "falcon_xmac.h"
40227569Sphilip#endif
41227569Sphilip
42227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC
43227569Sphilip#include "falcon_gmac.h"
44227569Sphilip#endif
45227569Sphilip
46227569Sphilip#if EFSYS_OPT_PHY_NULL
47227569Sphilip#include "nullphy.h"
48227569Sphilip#endif
49227569Sphilip
50227569Sphilip#if EFSYS_OPT_PHY_QT2022C2
51227569Sphilip#include "qt2022c2.h"
52227569Sphilip#endif
53227569Sphilip
54227569Sphilip#if EFSYS_OPT_PHY_SFX7101
55227569Sphilip#include "sfx7101.h"
56227569Sphilip#endif
57227569Sphilip
58227569Sphilip#if EFSYS_OPT_PHY_TXC43128
59227569Sphilip#include "txc43128.h"
60227569Sphilip#endif
61227569Sphilip
62227569Sphilip#if EFSYS_OPT_PHY_SFT9001
63227569Sphilip#include "sft9001.h"
64227569Sphilip#endif
65227569Sphilip
66227569Sphilip#if EFSYS_OPT_PHY_QT2025C
67227569Sphilip#include "qt2025c.h"
68227569Sphilip#endif
69227569Sphilip
70227569Sphilip#if EFSYS_OPT_PHY_NULL
71227569Sphilipstatic efx_phy_ops_t	__cs __efx_phy_null_ops = {
72227569Sphilip	NULL,				/* epo_power */
73227569Sphilip	nullphy_reset,			/* epo_reset */
74227569Sphilip	nullphy_reconfigure,		/* epo_reconfigure */
75227569Sphilip	nullphy_verify,			/* epo_verify */
76227569Sphilip	NULL,				/* epo_uplink_check */
77227569Sphilip	nullphy_downlink_check,		/* epo_downlink_check */
78227569Sphilip	nullphy_oui_get,		/* epo_oui_get */
79227569Sphilip#if EFSYS_OPT_PHY_STATS
80227569Sphilip	nullphy_stats_update,		/* epo_stats_update */
81227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
82227569Sphilip#if EFSYS_OPT_PHY_PROPS
83227569Sphilip#if EFSYS_OPT_NAMES
84227569Sphilip	nullphy_prop_name,		/* epo_prop_name */
85227569Sphilip#endif
86227569Sphilip	nullphy_prop_get,		/* epo_prop_get */
87227569Sphilip	nullphy_prop_set,		/* epo_prop_set */
88227569Sphilip#endif	/* EFSYS_OPT_PHY_PROPS */
89227569Sphilip#if EFSYS_OPT_PHY_BIST
90227569Sphilip	NULL,				/* epo_bist_start */
91227569Sphilip	NULL,				/* epo_bist_poll */
92227569Sphilip	NULL,				/* epo_bist_stop */
93227569Sphilip#endif	/* EFSYS_OPT_PHY_BIST */
94227569Sphilip};
95227569Sphilip#endif	/* EFSYS_OPT_PHY_NULL */
96227569Sphilip
97227569Sphilip#if EFSYS_OPT_PHY_QT2022C2
98227569Sphilipstatic efx_phy_ops_t	__cs __efx_phy_qt2022c2_ops = {
99227569Sphilip	NULL,				/* epo_power */
100227569Sphilip	qt2022c2_reset,			/* epo_reset */
101227569Sphilip	qt2022c2_reconfigure,		/* epo_reconfigure */
102227569Sphilip	qt2022c2_verify,		/* epo_verify */
103227569Sphilip	qt2022c2_uplink_check,		/* epo_uplink_check */
104227569Sphilip	qt2022c2_downlink_check,	/* epo_downlink_check */
105227569Sphilip	qt2022c2_oui_get,		/* epo_oui_get */
106227569Sphilip#if EFSYS_OPT_PHY_STATS
107227569Sphilip	qt2022c2_stats_update,		/* epo_stats_update */
108227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
109227569Sphilip#if EFSYS_OPT_PHY_PROPS
110227569Sphilip#if EFSYS_OPT_NAMES
111227569Sphilip	qt2022c2_prop_name,		/* epo_prop_name */
112227569Sphilip#endif
113227569Sphilip	qt2022c2_prop_get,		/* epo_prop_get */
114227569Sphilip	qt2022c2_prop_set,		/* epo_prop_set */
115227569Sphilip#endif	/* EFSYS_OPT_PHY_PROPS */
116227569Sphilip#if EFSYS_OPT_PHY_BIST
117227569Sphilip	NULL,				/* epo_bist_start */
118227569Sphilip	NULL,				/* epo_bist_poll */
119227569Sphilip	NULL,				/* epo_bist_stop */
120227569Sphilip#endif	/* EFSYS_OPT_PHY_BIST */
121227569Sphilip};
122227569Sphilip#endif	/* EFSYS_OPT_PHY_QT2022C2 */
123227569Sphilip
124227569Sphilip#if EFSYS_OPT_PHY_SFX7101
125227569Sphilipstatic efx_phy_ops_t	__cs __efx_phy_sfx7101_ops = {
126227569Sphilip	sfx7101_power,			/* epo_power */
127227569Sphilip	sfx7101_reset,			/* epo_reset */
128227569Sphilip	sfx7101_reconfigure,		/* epo_reconfigure */
129227569Sphilip	sfx7101_verify,			/* epo_verify */
130227569Sphilip	sfx7101_uplink_check,		/* epo_uplink_check */
131227569Sphilip	sfx7101_downlink_check,		/* epo_downlink_check */
132227569Sphilip	sfx7101_oui_get,		/* epo_oui_get */
133227569Sphilip#if EFSYS_OPT_PHY_STATS
134227569Sphilip	sfx7101_stats_update,		/* epo_stats_update */
135227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
136227569Sphilip#if EFSYS_OPT_PHY_PROPS
137227569Sphilip#if EFSYS_OPT_NAMES
138227569Sphilip	sfx7101_prop_name,		/* epo_prop_name */
139227569Sphilip#endif
140227569Sphilip	sfx7101_prop_get,		/* epo_prop_get */
141227569Sphilip	sfx7101_prop_set,		/* epo_prop_set */
142227569Sphilip#endif	/* EFSYS_OPT_PHY_PROPS */
143227569Sphilip#if EFSYS_OPT_PHY_BIST
144227569Sphilip	NULL,				/* epo_bist_start */
145227569Sphilip	NULL,				/* epo_bist_poll */
146227569Sphilip	NULL,				/* epo_bist_stop */
147227569Sphilip#endif	/* EFSYS_OPT_PHY_BIST */
148227569Sphilip};
149227569Sphilip#endif	/* EFSYS_OPT_PHY_SFX7101 */
150227569Sphilip
151227569Sphilip#if EFSYS_OPT_PHY_TXC43128
152227569Sphilipstatic efx_phy_ops_t	__cs __efx_phy_txc43128_ops = {
153227569Sphilip	NULL,				/* epo_power */
154227569Sphilip	txc43128_reset,			/* epo_reset */
155227569Sphilip	txc43128_reconfigure,		/* epo_reconfigure */
156227569Sphilip	txc43128_verify,		/* epo_verify */
157227569Sphilip	txc43128_uplink_check,		/* epo_uplink_check */
158227569Sphilip	txc43128_downlink_check,	/* epo_downlink_check */
159227569Sphilip	txc43128_oui_get,		/* epo_oui_get */
160227569Sphilip#if EFSYS_OPT_PHY_STATS
161227569Sphilip	txc43128_stats_update,		/* epo_stats_update */
162227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
163227569Sphilip#if EFSYS_OPT_PHY_PROPS
164227569Sphilip#if EFSYS_OPT_NAMES
165227569Sphilip	txc43128_prop_name,		/* epo_prop_name */
166227569Sphilip#endif
167227569Sphilip	txc43128_prop_get,		/* epo_prop_get */
168227569Sphilip	txc43128_prop_set,		/* epo_prop_set */
169227569Sphilip#endif	/* EFSYS_OPT_PHY_PROPS */
170227569Sphilip#if EFSYS_OPT_PHY_BIST
171227569Sphilip	NULL,				/* epo_bist_start */
172227569Sphilip	NULL,				/* epo_bist_poll */
173227569Sphilip	NULL,				/* epo_bist_stop */
174227569Sphilip#endif	/* EFSYS_OPT_PHY_BIST */
175227569Sphilip};
176227569Sphilip#endif	/* EFSYS_OPT_PHY_TXC43128 */
177227569Sphilip
178227569Sphilip#if EFSYS_OPT_PHY_SFT9001
179227569Sphilipstatic efx_phy_ops_t	__cs __efx_phy_sft9001_ops = {
180227569Sphilip	NULL,				/* epo_power */
181227569Sphilip	sft9001_reset,			/* epo_reset */
182227569Sphilip	sft9001_reconfigure,		/* epo_reconfigure */
183227569Sphilip	sft9001_verify,			/* epo_verify */
184227569Sphilip	sft9001_uplink_check,		/* epo_uplink_check */
185227569Sphilip	sft9001_downlink_check,		/* epo_downlink_check */
186227569Sphilip	sft9001_oui_get,		/* epo_oui_get */
187227569Sphilip#if EFSYS_OPT_PHY_STATS
188227569Sphilip	sft9001_stats_update,		/* epo_stats_update */
189227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
190227569Sphilip#if EFSYS_OPT_PHY_PROPS
191227569Sphilip#if EFSYS_OPT_NAMES
192227569Sphilip	sft9001_prop_name,		/* epo_prop_name */
193227569Sphilip#endif
194227569Sphilip	sft9001_prop_get,		/* epo_prop_get */
195227569Sphilip	sft9001_prop_set,		/* epo_prop_set */
196227569Sphilip#endif	/* EFSYS_OPT_PHY_PROPS */
197227569Sphilip#if EFSYS_OPT_PHY_BIST
198227569Sphilip	sft9001_bist_start,		/* epo_bist_start */
199227569Sphilip	sft9001_bist_poll,		/* epo_bist_poll */
200227569Sphilip	sft9001_bist_stop,		/* epo_bist_stop */
201227569Sphilip#endif	/* EFSYS_OPT_PHY_BIST */
202227569Sphilip};
203227569Sphilip#endif	/* EFSYS_OPT_PHY_SFT9001 */
204227569Sphilip
205227569Sphilip#if EFSYS_OPT_PHY_QT2025C
206227569Sphilipstatic efx_phy_ops_t	__cs __efx_phy_qt2025c_ops = {
207227569Sphilip	NULL,				/* epo_power */
208227569Sphilip	qt2025c_reset,			/* epo_reset */
209227569Sphilip	qt2025c_reconfigure,		/* epo_reconfigure */
210227569Sphilip	qt2025c_verify,			/* epo_verify */
211227569Sphilip	qt2025c_uplink_check,		/* epo_uplink_check */
212227569Sphilip	qt2025c_downlink_check,		/* epo_downlink_check */
213227569Sphilip	qt2025c_oui_get,		/* epo_oui_get */
214227569Sphilip#if EFSYS_OPT_PHY_STATS
215227569Sphilip	qt2025c_stats_update,		/* epo_stats_update */
216227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
217227569Sphilip#if EFSYS_OPT_PHY_PROPS
218227569Sphilip#if EFSYS_OPT_NAMES
219227569Sphilip	qt2025c_prop_name,		/* epo_prop_name */
220227569Sphilip#endif
221227569Sphilip	qt2025c_prop_get,		/* epo_prop_get */
222227569Sphilip	qt2025c_prop_set,		/* epo_prop_set */
223227569Sphilip#endif	/* EFSYS_OPT_PHY_PROPS */
224227569Sphilip#if EFSYS_OPT_PHY_BIST
225227569Sphilip	NULL,				/* epo_bist_start */
226227569Sphilip	NULL,				/* epo_bist_poll */
227227569Sphilip	NULL,				/* epo_bist_stop */
228227569Sphilip#endif	/* EFSYS_OPT_PHY_BIST */
229227569Sphilip};
230227569Sphilip#endif	/* EFSYS_OPT_PHY_QT2025C */
231227569Sphilip
232227569Sphilip#if EFSYS_OPT_SIENA
233227569Sphilipstatic efx_phy_ops_t	__cs __efx_phy_siena_ops = {
234227569Sphilip	siena_phy_power,		/* epo_power */
235227569Sphilip	NULL,				/* epo_reset */
236227569Sphilip	siena_phy_reconfigure,		/* epo_reconfigure */
237227569Sphilip	siena_phy_verify,		/* epo_verify */
238227569Sphilip	NULL,				/* epo_uplink_check */
239227569Sphilip	NULL,				/* epo_downlink_check */
240227569Sphilip	siena_phy_oui_get,		/* epo_oui_get */
241227569Sphilip#if EFSYS_OPT_PHY_STATS
242227569Sphilip	siena_phy_stats_update,		/* epo_stats_update */
243227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
244227569Sphilip#if EFSYS_OPT_PHY_PROPS
245227569Sphilip#if EFSYS_OPT_NAMES
246227569Sphilip	siena_phy_prop_name,		/* epo_prop_name */
247227569Sphilip#endif
248227569Sphilip	siena_phy_prop_get,		/* epo_prop_get */
249227569Sphilip	siena_phy_prop_set,		/* epo_prop_set */
250227569Sphilip#endif	/* EFSYS_OPT_PHY_PROPS */
251227569Sphilip#if EFSYS_OPT_PHY_BIST
252227569Sphilip	siena_phy_bist_start, 		/* epo_bist_start */
253227569Sphilip	siena_phy_bist_poll,		/* epo_bist_poll */
254227569Sphilip	siena_phy_bist_stop,		/* epo_bist_stop */
255227569Sphilip#endif	/* EFSYS_OPT_PHY_BIST */
256227569Sphilip};
257227569Sphilip#endif	/* EFSYS_OPT_SIENA */
258227569Sphilip
259227569Sphilip	__checkReturn	int
260227569Sphilipefx_phy_probe(
261227569Sphilip	__in		efx_nic_t *enp)
262227569Sphilip{
263227569Sphilip	efx_port_t *epp = &(enp->en_port);
264227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
265227569Sphilip	efx_phy_ops_t *epop;
266227569Sphilip	int rc;
267227569Sphilip
268227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
269227569Sphilip
270227569Sphilip	epp->ep_port = encp->enc_port;
271227569Sphilip	epp->ep_phy_type = encp->enc_phy_type;
272227569Sphilip
273227569Sphilip	/* Hook in operations structure */
274227569Sphilip	switch (enp->en_family) {
275227569Sphilip#if EFSYS_OPT_FALCON
276227569Sphilip	case EFX_FAMILY_FALCON:
277227569Sphilip		switch (epp->ep_phy_type) {
278227569Sphilip#if EFSYS_OPT_PHY_NULL
279227569Sphilip		case PHY_TYPE_NONE_DECODE:
280227569Sphilip			epop = (efx_phy_ops_t *)&__efx_phy_null_ops;
281227569Sphilip			break;
282227569Sphilip#endif
283227569Sphilip#if EFSYS_OPT_PHY_QT2022C2
284227569Sphilip		case PHY_TYPE_QT2022C2_DECODE:
285227569Sphilip			epop = (efx_phy_ops_t *)&__efx_phy_qt2022c2_ops;
286227569Sphilip			break;
287227569Sphilip#endif
288227569Sphilip#if EFSYS_OPT_PHY_SFX7101
289227569Sphilip		case PHY_TYPE_SFX7101_DECODE:
290227569Sphilip			epop = (efx_phy_ops_t *)&__efx_phy_sfx7101_ops;
291227569Sphilip			break;
292227569Sphilip#endif
293227569Sphilip#if EFSYS_OPT_PHY_TXC43128
294227569Sphilip		case PHY_TYPE_TXC43128_DECODE:
295227569Sphilip			epop = (efx_phy_ops_t *)&__efx_phy_txc43128_ops;
296227569Sphilip			break;
297227569Sphilip#endif
298227569Sphilip#if EFSYS_OPT_PHY_SFT9001
299227569Sphilip		case PHY_TYPE_SFT9001A_DECODE:
300227569Sphilip		case PHY_TYPE_SFT9001B_DECODE:
301227569Sphilip			epop = (efx_phy_ops_t *)&__efx_phy_sft9001_ops;
302227569Sphilip			break;
303227569Sphilip#endif
304227569Sphilip#if EFSYS_OPT_PHY_QT2025C
305227569Sphilip		case EFX_PHY_QT2025C:
306227569Sphilip			epop = (efx_phy_ops_t *)&__efx_phy_qt2025c_ops;
307227569Sphilip			break;
308227569Sphilip#endif
309227569Sphilip		default:
310227569Sphilip			rc = ENOTSUP;
311227569Sphilip			goto fail1;
312227569Sphilip		}
313227569Sphilip		break;
314227569Sphilip#endif	/* EFSYS_OPT_FALCON */
315227569Sphilip#if EFSYS_OPT_SIENA
316227569Sphilip	case EFX_FAMILY_SIENA:
317227569Sphilip		epop = (efx_phy_ops_t *)&__efx_phy_siena_ops;
318227569Sphilip		break;
319227569Sphilip#endif	/* EFSYS_OPT_SIENA */
320227569Sphilip	default:
321227569Sphilip		rc = ENOTSUP;
322227569Sphilip		goto fail1;
323227569Sphilip	}
324227569Sphilip
325227569Sphilip	epp->ep_epop = epop;
326227569Sphilip
327227569Sphilip	return (0);
328227569Sphilip
329227569Sphilipfail1:
330227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
331227569Sphilip
332227569Sphilip	epp->ep_port = 0;
333227569Sphilip	epp->ep_phy_type = 0;
334227569Sphilip
335227569Sphilip	return (rc);
336227569Sphilip}
337227569Sphilip
338227569Sphilip	__checkReturn	int
339227569Sphilipefx_phy_verify(
340227569Sphilip	__in		efx_nic_t *enp)
341227569Sphilip{
342227569Sphilip	efx_port_t *epp = &(enp->en_port);
343227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
344227569Sphilip
345227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
346227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
347227569Sphilip
348227569Sphilip	return (epop->epo_verify(enp));
349227569Sphilip}
350227569Sphilip
351227569Sphilip#if EFSYS_OPT_PHY_LED_CONTROL
352227569Sphilip
353227569Sphilip	__checkReturn	int
354227569Sphilipefx_phy_led_set(
355227569Sphilip	__in		efx_nic_t *enp,
356227569Sphilip	__in		efx_phy_led_mode_t mode)
357227569Sphilip{
358227569Sphilip	efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
359227569Sphilip	efx_port_t *epp = &(enp->en_port);
360227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
361227569Sphilip	uint32_t mask;
362227569Sphilip	int rc;
363227569Sphilip
364227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
365227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
366227569Sphilip
367227569Sphilip	if (epp->ep_phy_led_mode == mode)
368227569Sphilip		goto done;
369227569Sphilip
370227569Sphilip	mask = (1 << EFX_PHY_LED_DEFAULT);
371227569Sphilip	mask |= encp->enc_led_mask;
372227569Sphilip
373227569Sphilip	if (!((1 << mode) & mask)) {
374227569Sphilip		rc = ENOTSUP;
375227569Sphilip		goto fail1;
376227569Sphilip	}
377227569Sphilip
378227569Sphilip	EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
379227569Sphilip	epp->ep_phy_led_mode = mode;
380227569Sphilip
381227569Sphilip	if ((rc = epop->epo_reconfigure(enp)) != 0)
382227569Sphilip		goto fail2;
383227569Sphilip
384227569Sphilipdone:
385227569Sphilip	return (0);
386227569Sphilip
387227569Sphilipfail2:
388227569Sphilip	EFSYS_PROBE(fail2);
389227569Sphilipfail1:
390227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
391227569Sphilip
392227569Sphilip	return (rc);
393227569Sphilip}
394227569Sphilip#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
395227569Sphilip
396227569Sphilip			void
397227569Sphilipefx_phy_adv_cap_get(
398227569Sphilip	__in		efx_nic_t *enp,
399227569Sphilip	__in		uint32_t flag,
400227569Sphilip	__out		uint32_t *maskp)
401227569Sphilip{
402227569Sphilip	efx_port_t *epp = &(enp->en_port);
403227569Sphilip
404227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
405227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
406227569Sphilip
407227569Sphilip	switch (flag) {
408227569Sphilip	case EFX_PHY_CAP_CURRENT:
409227569Sphilip		*maskp = epp->ep_adv_cap_mask;
410227569Sphilip		break;
411227569Sphilip	case EFX_PHY_CAP_DEFAULT:
412227569Sphilip		*maskp = epp->ep_default_adv_cap_mask;
413227569Sphilip		break;
414227569Sphilip	case EFX_PHY_CAP_PERM:
415227569Sphilip		*maskp = epp->ep_phy_cap_mask;
416227569Sphilip		break;
417227569Sphilip	default:
418227569Sphilip		EFSYS_ASSERT(B_FALSE);
419227569Sphilip		break;
420227569Sphilip	}
421227569Sphilip}
422227569Sphilip
423227569Sphilip	__checkReturn	int
424227569Sphilipefx_phy_adv_cap_set(
425227569Sphilip	__in		efx_nic_t *enp,
426227569Sphilip	__in		uint32_t mask)
427227569Sphilip{
428227569Sphilip	efx_port_t *epp = &(enp->en_port);
429227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
430227569Sphilip	int rc;
431227569Sphilip
432227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
433227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
434227569Sphilip
435227569Sphilip	if ((mask & ~epp->ep_phy_cap_mask) != 0) {
436227569Sphilip		rc = ENOTSUP;
437227569Sphilip		goto fail1;
438227569Sphilip	}
439227569Sphilip
440227569Sphilip	if (epp->ep_adv_cap_mask == mask)
441227569Sphilip		goto done;
442227569Sphilip
443227569Sphilip	epp->ep_adv_cap_mask = mask;
444227569Sphilip
445227569Sphilip	if ((rc = epop->epo_reconfigure(enp)) != 0)
446227569Sphilip		goto fail2;
447227569Sphilip
448227569Sphilipdone:
449227569Sphilip	return (0);
450227569Sphilip
451227569Sphilipfail2:
452227569Sphilip	EFSYS_PROBE(fail2);
453227569Sphilipfail1:
454227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
455227569Sphilip
456227569Sphilip	return (rc);
457227569Sphilip}
458227569Sphilip
459227569Sphilip	void
460227569Sphilipefx_phy_lp_cap_get(
461227569Sphilip	__in		efx_nic_t *enp,
462227569Sphilip	__out		uint32_t *maskp)
463227569Sphilip{
464227569Sphilip	efx_port_t *epp = &(enp->en_port);
465227569Sphilip
466227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
467227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
468227569Sphilip
469227569Sphilip	*maskp = epp->ep_lp_cap_mask;
470227569Sphilip}
471227569Sphilip
472227569Sphilip	__checkReturn	int
473227569Sphilipefx_phy_oui_get(
474227569Sphilip	__in		efx_nic_t *enp,
475227569Sphilip	__out		uint32_t *ouip)
476227569Sphilip{
477227569Sphilip	efx_port_t *epp = &(enp->en_port);
478227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
479227569Sphilip
480227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
481227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
482227569Sphilip
483227569Sphilip	return (epop->epo_oui_get(enp, ouip));
484227569Sphilip}
485227569Sphilip
486227569Sphilip			void
487227569Sphilipefx_phy_media_type_get(
488227569Sphilip	__in		efx_nic_t *enp,
489227569Sphilip	__out		efx_phy_media_type_t *typep)
490227569Sphilip{
491227569Sphilip	efx_port_t *epp = &(enp->en_port);
492227569Sphilip
493227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
494227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
495227569Sphilip
496227569Sphilip	if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
497227569Sphilip		*typep = epp->ep_module_type;
498227569Sphilip	else
499227569Sphilip		*typep = epp->ep_fixed_port_type;
500227569Sphilip}
501227569Sphilip
502227569Sphilip#if EFSYS_OPT_PHY_STATS
503227569Sphilip
504227569Sphilip#if EFSYS_OPT_NAMES
505227569Sphilip
506227569Sphilip/* START MKCONFIG GENERATED PhyStatNamesBlock 271268f3da0e804f */
507227569Sphilipstatic const char 	__cs * __cs __efx_phy_stat_name[] = {
508227569Sphilip	"oui",
509227569Sphilip	"pma_pmd_link_up",
510227569Sphilip	"pma_pmd_rx_fault",
511227569Sphilip	"pma_pmd_tx_fault",
512227569Sphilip	"pma_pmd_rev_a",
513227569Sphilip	"pma_pmd_rev_b",
514227569Sphilip	"pma_pmd_rev_c",
515227569Sphilip	"pma_pmd_rev_d",
516227569Sphilip	"pcs_link_up",
517227569Sphilip	"pcs_rx_fault",
518227569Sphilip	"pcs_tx_fault",
519227569Sphilip	"pcs_ber",
520227569Sphilip	"pcs_block_errors",
521227569Sphilip	"phy_xs_link_up",
522227569Sphilip	"phy_xs_rx_fault",
523227569Sphilip	"phy_xs_tx_fault",
524227569Sphilip	"phy_xs_align",
525227569Sphilip	"phy_xs_sync_a",
526227569Sphilip	"phy_xs_sync_b",
527227569Sphilip	"phy_xs_sync_c",
528227569Sphilip	"phy_xs_sync_d",
529227569Sphilip	"an_link_up",
530227569Sphilip	"an_master",
531227569Sphilip	"an_local_rx_ok",
532227569Sphilip	"an_remote_rx_ok",
533227569Sphilip	"cl22ext_link_up",
534227569Sphilip	"snr_a",
535227569Sphilip	"snr_b",
536227569Sphilip	"snr_c",
537227569Sphilip	"snr_d",
538227569Sphilip	"pma_pmd_signal_a",
539227569Sphilip	"pma_pmd_signal_b",
540227569Sphilip	"pma_pmd_signal_c",
541227569Sphilip	"pma_pmd_signal_d",
542227569Sphilip	"an_complete",
543227569Sphilip	"pma_pmd_rev_major",
544227569Sphilip	"pma_pmd_rev_minor",
545227569Sphilip	"pma_pmd_rev_micro",
546227569Sphilip	"pcs_fw_version_0",
547227569Sphilip	"pcs_fw_version_1",
548227569Sphilip	"pcs_fw_version_2",
549227569Sphilip	"pcs_fw_version_3",
550227569Sphilip	"pcs_fw_build_yy",
551227569Sphilip	"pcs_fw_build_mm",
552227569Sphilip	"pcs_fw_build_dd",
553227569Sphilip	"pcs_op_mode",
554227569Sphilip};
555227569Sphilip
556227569Sphilip/* END MKCONFIG GENERATED PhyStatNamesBlock */
557227569Sphilip
558227569Sphilip					const char __cs *
559227569Sphilipefx_phy_stat_name(
560227569Sphilip	__in				efx_nic_t *enp,
561227569Sphilip	__in				efx_phy_stat_t type)
562227569Sphilip{
563227569Sphilip	_NOTE(ARGUNUSED(enp))
564227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
565227569Sphilip	EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
566227569Sphilip
567227569Sphilip	return (__efx_phy_stat_name[type]);
568227569Sphilip}
569227569Sphilip
570227569Sphilip#endif	/* EFSYS_OPT_NAMES */
571227569Sphilip
572227569Sphilip	__checkReturn			int
573227569Sphilipefx_phy_stats_update(
574227569Sphilip	__in				efx_nic_t *enp,
575227569Sphilip	__in				efsys_mem_t *esmp,
576227569Sphilip	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
577227569Sphilip{
578227569Sphilip	efx_port_t *epp = &(enp->en_port);
579227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
580227569Sphilip
581227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
582227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
583227569Sphilip
584227569Sphilip	return (epop->epo_stats_update(enp, esmp, stat));
585227569Sphilip}
586227569Sphilip
587227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
588227569Sphilip
589227569Sphilip#if EFSYS_OPT_PHY_PROPS
590227569Sphilip
591227569Sphilip#if EFSYS_OPT_NAMES
592227569Sphilip		const char __cs *
593227569Sphilipefx_phy_prop_name(
594227569Sphilip	__in	efx_nic_t *enp,
595227569Sphilip	__in	unsigned int id)
596227569Sphilip{
597227569Sphilip	efx_port_t *epp = &(enp->en_port);
598227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
599227569Sphilip
600227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
601227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
602227569Sphilip
603227569Sphilip	return (epop->epo_prop_name(enp, id));
604227569Sphilip}
605227569Sphilip#endif	/* EFSYS_OPT_NAMES */
606227569Sphilip
607227569Sphilip	__checkReturn	int
608227569Sphilipefx_phy_prop_get(
609227569Sphilip	__in		efx_nic_t *enp,
610227569Sphilip	__in		unsigned int id,
611227569Sphilip	__in		uint32_t flags,
612227569Sphilip	__out		uint32_t *valp)
613227569Sphilip{
614227569Sphilip	efx_port_t *epp = &(enp->en_port);
615227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
616227569Sphilip
617227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
618227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
619227569Sphilip
620227569Sphilip	return (epop->epo_prop_get(enp, id, flags, valp));
621227569Sphilip}
622227569Sphilip
623227569Sphilip	__checkReturn	int
624227569Sphilipefx_phy_prop_set(
625227569Sphilip	__in		efx_nic_t *enp,
626227569Sphilip	__in		unsigned int id,
627227569Sphilip	__in		uint32_t val)
628227569Sphilip{
629227569Sphilip	efx_port_t *epp = &(enp->en_port);
630227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
631227569Sphilip
632227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
633227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
634227569Sphilip
635227569Sphilip	return (epop->epo_prop_set(enp, id, val));
636227569Sphilip}
637227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
638227569Sphilip
639227569Sphilip#if EFSYS_OPT_PHY_BIST
640227569Sphilip
641227569Sphilip	__checkReturn		int
642227569Sphilipefx_phy_bist_start(
643227569Sphilip	__in			efx_nic_t *enp,
644227569Sphilip	__in			efx_phy_bist_type_t type)
645227569Sphilip{
646227569Sphilip	efx_port_t *epp = &(enp->en_port);
647227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
648227569Sphilip	int rc;
649227569Sphilip
650227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
651227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
652227569Sphilip
653227569Sphilip	EFSYS_ASSERT3U(type, !=, EFX_PHY_BIST_TYPE_UNKNOWN);
654227569Sphilip	EFSYS_ASSERT3U(type, <, EFX_PHY_BIST_TYPE_NTYPES);
655227569Sphilip	EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_PHY_BIST_TYPE_UNKNOWN);
656227569Sphilip
657227569Sphilip	if (epop->epo_bist_start == NULL) {
658227569Sphilip		rc = ENOTSUP;
659227569Sphilip		goto fail1;
660227569Sphilip	}
661227569Sphilip
662227569Sphilip	if ((rc = epop->epo_bist_start(enp, type)) != 0)
663227569Sphilip		goto fail2;
664227569Sphilip
665227569Sphilip	epp->ep_current_bist = type;
666227569Sphilip
667227569Sphilip	return (0);
668227569Sphilip
669227569Sphilipfail2:
670227569Sphilip	EFSYS_PROBE(fail2);
671227569Sphilipfail1:
672227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
673227569Sphilip
674227569Sphilip	return (rc);
675227569Sphilip}
676227569Sphilip
677227569Sphilip	__checkReturn		int
678227569Sphilipefx_phy_bist_poll(
679227569Sphilip	__in			efx_nic_t *enp,
680227569Sphilip	__in			efx_phy_bist_type_t type,
681227569Sphilip	__out			efx_phy_bist_result_t *resultp,
682227569Sphilip	__out_opt		uint32_t *value_maskp,
683227569Sphilip	__out_ecount_opt(count)	unsigned long *valuesp,
684227569Sphilip	__in			size_t count)
685227569Sphilip{
686227569Sphilip	efx_port_t *epp = &(enp->en_port);
687227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
688227569Sphilip	int rc;
689227569Sphilip
690227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
691227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
692227569Sphilip
693227569Sphilip	EFSYS_ASSERT3U(type, !=, EFX_PHY_BIST_TYPE_UNKNOWN);
694227569Sphilip	EFSYS_ASSERT3U(type, <, EFX_PHY_BIST_TYPE_NTYPES);
695227569Sphilip	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
696227569Sphilip
697227569Sphilip	EFSYS_ASSERT(epop->epo_bist_poll != NULL);
698227569Sphilip	if (epop->epo_bist_poll == NULL) {
699227569Sphilip		rc = ENOTSUP;
700227569Sphilip		goto fail1;
701227569Sphilip	}
702227569Sphilip
703227569Sphilip	if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
704227569Sphilip	    valuesp, count)) != 0)
705227569Sphilip		goto fail2;
706227569Sphilip
707227569Sphilip	return (0);
708227569Sphilip
709227569Sphilipfail2:
710227569Sphilip	EFSYS_PROBE(fail2);
711227569Sphilipfail1:
712227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
713227569Sphilip
714227569Sphilip	return (rc);
715227569Sphilip}
716227569Sphilip
717227569Sphilip			void
718227569Sphilipefx_phy_bist_stop(
719227569Sphilip	__in		efx_nic_t *enp,
720227569Sphilip	__in		efx_phy_bist_type_t type)
721227569Sphilip{
722227569Sphilip	efx_port_t *epp = &(enp->en_port);
723227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
724227569Sphilip
725227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
726227569Sphilip	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
727227569Sphilip
728227569Sphilip	EFSYS_ASSERT3U(type, !=, EFX_PHY_BIST_TYPE_UNKNOWN);
729227569Sphilip	EFSYS_ASSERT3U(type, <, EFX_PHY_BIST_TYPE_NTYPES);
730227569Sphilip	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
731227569Sphilip
732227569Sphilip	EFSYS_ASSERT(epop->epo_bist_stop != NULL);
733227569Sphilip
734227569Sphilip	if (epop->epo_bist_stop != NULL)
735227569Sphilip		epop->epo_bist_stop(enp, type);
736227569Sphilip
737227569Sphilip	epp->ep_current_bist = EFX_PHY_BIST_TYPE_UNKNOWN;
738227569Sphilip}
739227569Sphilip
740227569Sphilip#endif	/* EFSYS_OPT_PHY_BIST */
741227569Sphilip			void
742227569Sphilipefx_phy_unprobe(
743227569Sphilip	__in	efx_nic_t *enp)
744227569Sphilip{
745227569Sphilip	efx_port_t *epp = &(enp->en_port);
746227569Sphilip
747227569Sphilip	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
748227569Sphilip
749227569Sphilip	epp->ep_epop = NULL;
750227569Sphilip
751227569Sphilip	epp->ep_adv_cap_mask = 0;
752227569Sphilip
753227569Sphilip	epp->ep_port = 0;
754227569Sphilip	epp->ep_phy_type = 0;
755227569Sphilip}
756