xref: /freebsd/sys/dev/sfxge/common/efx_phy.c (revision 0b3105a37d7adcadcb720112fed4dc4e8040be99)
1 /*-
2  * Copyright (c) 2007-2015 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are
27  * those of the authors and should not be interpreted as representing official
28  * policies, either expressed or implied, of the FreeBSD Project.
29  */
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #include "efx.h"
35 #include "efx_impl.h"
36 #if EFSYS_OPT_FALCON
37 #include "falcon_nvram.h"
38 #endif
39 
40 #if EFSYS_OPT_MAC_FALCON_XMAC
41 #include "falcon_xmac.h"
42 #endif
43 
44 #if EFSYS_OPT_MAC_FALCON_GMAC
45 #include "falcon_gmac.h"
46 #endif
47 
48 #if EFSYS_OPT_PHY_NULL
49 #include "nullphy.h"
50 #endif
51 
52 #if EFSYS_OPT_PHY_QT2022C2
53 #include "qt2022c2.h"
54 #endif
55 
56 #if EFSYS_OPT_PHY_SFX7101
57 #include "sfx7101.h"
58 #endif
59 
60 #if EFSYS_OPT_PHY_TXC43128
61 #include "txc43128.h"
62 #endif
63 
64 #if EFSYS_OPT_PHY_SFT9001
65 #include "sft9001.h"
66 #endif
67 
68 #if EFSYS_OPT_PHY_QT2025C
69 #include "qt2025c.h"
70 #endif
71 
72 #if EFSYS_OPT_PHY_NULL
73 static efx_phy_ops_t	__efx_phy_null_ops = {
74 	NULL,				/* epo_power */
75 	nullphy_reset,			/* epo_reset */
76 	nullphy_reconfigure,		/* epo_reconfigure */
77 	nullphy_verify,			/* epo_verify */
78 	NULL,				/* epo_uplink_check */
79 	nullphy_downlink_check,		/* epo_downlink_check */
80 	nullphy_oui_get,		/* epo_oui_get */
81 #if EFSYS_OPT_PHY_STATS
82 	nullphy_stats_update,		/* epo_stats_update */
83 #endif	/* EFSYS_OPT_PHY_STATS */
84 #if EFSYS_OPT_PHY_PROPS
85 #if EFSYS_OPT_NAMES
86 	nullphy_prop_name,		/* epo_prop_name */
87 #endif
88 	nullphy_prop_get,		/* epo_prop_get */
89 	nullphy_prop_set,		/* epo_prop_set */
90 #endif	/* EFSYS_OPT_PHY_PROPS */
91 #if EFSYS_OPT_BIST
92 	NULL,				/* epo_bist_enable_offline */
93 	NULL,				/* epo_bist_start */
94 	NULL,				/* epo_bist_poll */
95 	NULL,				/* epo_bist_stop */
96 #endif	/* EFSYS_OPT_BIST */
97 };
98 #endif	/* EFSYS_OPT_PHY_NULL */
99 
100 #if EFSYS_OPT_PHY_QT2022C2
101 static efx_phy_ops_t	__efx_phy_qt2022c2_ops = {
102 	NULL,				/* epo_power */
103 	qt2022c2_reset,			/* epo_reset */
104 	qt2022c2_reconfigure,		/* epo_reconfigure */
105 	qt2022c2_verify,		/* epo_verify */
106 	qt2022c2_uplink_check,		/* epo_uplink_check */
107 	qt2022c2_downlink_check,	/* epo_downlink_check */
108 	qt2022c2_oui_get,		/* epo_oui_get */
109 #if EFSYS_OPT_PHY_STATS
110 	qt2022c2_stats_update,		/* epo_stats_update */
111 #endif	/* EFSYS_OPT_PHY_STATS */
112 #if EFSYS_OPT_PHY_PROPS
113 #if EFSYS_OPT_NAMES
114 	qt2022c2_prop_name,		/* epo_prop_name */
115 #endif
116 	qt2022c2_prop_get,		/* epo_prop_get */
117 	qt2022c2_prop_set,		/* epo_prop_set */
118 #endif	/* EFSYS_OPT_PHY_PROPS */
119 #if EFSYS_OPT_BIST
120 	NULL,				/* epo_bist_enable_offline */
121 	NULL,				/* epo_bist_start */
122 	NULL,				/* epo_bist_poll */
123 	NULL,				/* epo_bist_stop */
124 #endif	/* EFSYS_OPT_BIST */
125 };
126 #endif	/* EFSYS_OPT_PHY_QT2022C2 */
127 
128 #if EFSYS_OPT_PHY_SFX7101
129 static efx_phy_ops_t	__efx_phy_sfx7101_ops = {
130 	sfx7101_power,			/* epo_power */
131 	sfx7101_reset,			/* epo_reset */
132 	sfx7101_reconfigure,		/* epo_reconfigure */
133 	sfx7101_verify,			/* epo_verify */
134 	sfx7101_uplink_check,		/* epo_uplink_check */
135 	sfx7101_downlink_check,		/* epo_downlink_check */
136 	sfx7101_oui_get,		/* epo_oui_get */
137 #if EFSYS_OPT_PHY_STATS
138 	sfx7101_stats_update,		/* epo_stats_update */
139 #endif	/* EFSYS_OPT_PHY_STATS */
140 #if EFSYS_OPT_PHY_PROPS
141 #if EFSYS_OPT_NAMES
142 	sfx7101_prop_name,		/* epo_prop_name */
143 #endif
144 	sfx7101_prop_get,		/* epo_prop_get */
145 	sfx7101_prop_set,		/* epo_prop_set */
146 #endif	/* EFSYS_OPT_PHY_PROPS */
147 #if EFSYS_OPT_BIST
148 	NULL,				/* epo_bist_enable_offline */
149 	NULL,				/* epo_bist_start */
150 	NULL,				/* epo_bist_poll */
151 	NULL,				/* epo_bist_stop */
152 #endif	/* EFSYS_OPT_BIST */
153 };
154 #endif	/* EFSYS_OPT_PHY_SFX7101 */
155 
156 #if EFSYS_OPT_PHY_TXC43128
157 static efx_phy_ops_t	__efx_phy_txc43128_ops = {
158 	NULL,				/* epo_power */
159 	txc43128_reset,			/* epo_reset */
160 	txc43128_reconfigure,		/* epo_reconfigure */
161 	txc43128_verify,		/* epo_verify */
162 	txc43128_uplink_check,		/* epo_uplink_check */
163 	txc43128_downlink_check,	/* epo_downlink_check */
164 	txc43128_oui_get,		/* epo_oui_get */
165 #if EFSYS_OPT_PHY_STATS
166 	txc43128_stats_update,		/* epo_stats_update */
167 #endif	/* EFSYS_OPT_PHY_STATS */
168 #if EFSYS_OPT_PHY_PROPS
169 #if EFSYS_OPT_NAMES
170 	txc43128_prop_name,		/* epo_prop_name */
171 #endif
172 	txc43128_prop_get,		/* epo_prop_get */
173 	txc43128_prop_set,		/* epo_prop_set */
174 #endif	/* EFSYS_OPT_PHY_PROPS */
175 #if EFSYS_OPT_BIST
176 	NULL,				/* epo_bist_enable_offline */
177 	NULL,				/* epo_bist_start */
178 	NULL,				/* epo_bist_poll */
179 	NULL,				/* epo_bist_stop */
180 #endif	/* EFSYS_OPT_BIST */
181 };
182 #endif	/* EFSYS_OPT_PHY_TXC43128 */
183 
184 #if EFSYS_OPT_PHY_SFT9001
185 static efx_phy_ops_t	__efx_phy_sft9001_ops = {
186 	NULL,				/* epo_power */
187 	sft9001_reset,			/* epo_reset */
188 	sft9001_reconfigure,		/* epo_reconfigure */
189 	sft9001_verify,			/* epo_verify */
190 	sft9001_uplink_check,		/* epo_uplink_check */
191 	sft9001_downlink_check,		/* epo_downlink_check */
192 	sft9001_oui_get,		/* epo_oui_get */
193 #if EFSYS_OPT_PHY_STATS
194 	sft9001_stats_update,		/* epo_stats_update */
195 #endif	/* EFSYS_OPT_PHY_STATS */
196 #if EFSYS_OPT_PHY_PROPS
197 #if EFSYS_OPT_NAMES
198 	sft9001_prop_name,		/* epo_prop_name */
199 #endif
200 	sft9001_prop_get,		/* epo_prop_get */
201 	sft9001_prop_set,		/* epo_prop_set */
202 #endif	/* EFSYS_OPT_PHY_PROPS */
203 #if EFSYS_OPT_BIST
204 	NULL,				/* epo_bist_enable_offline */
205 	sft9001_bist_start,		/* epo_bist_start */
206 	sft9001_bist_poll,		/* epo_bist_poll */
207 	sft9001_bist_stop,		/* epo_bist_stop */
208 #endif	/* EFSYS_OPT_BIST */
209 };
210 #endif	/* EFSYS_OPT_PHY_SFT9001 */
211 
212 #if EFSYS_OPT_PHY_QT2025C
213 static efx_phy_ops_t	__efx_phy_qt2025c_ops = {
214 	NULL,				/* epo_power */
215 	qt2025c_reset,			/* epo_reset */
216 	qt2025c_reconfigure,		/* epo_reconfigure */
217 	qt2025c_verify,			/* epo_verify */
218 	qt2025c_uplink_check,		/* epo_uplink_check */
219 	qt2025c_downlink_check,		/* epo_downlink_check */
220 	qt2025c_oui_get,		/* epo_oui_get */
221 #if EFSYS_OPT_PHY_STATS
222 	qt2025c_stats_update,		/* epo_stats_update */
223 #endif	/* EFSYS_OPT_PHY_STATS */
224 #if EFSYS_OPT_PHY_PROPS
225 #if EFSYS_OPT_NAMES
226 	qt2025c_prop_name,		/* epo_prop_name */
227 #endif
228 	qt2025c_prop_get,		/* epo_prop_get */
229 	qt2025c_prop_set,		/* epo_prop_set */
230 #endif	/* EFSYS_OPT_PHY_PROPS */
231 #if EFSYS_OPT_BIST
232 	NULL,				/* epo_bist_enable_offline */
233 	NULL,				/* epo_bist_start */
234 	NULL,				/* epo_bist_poll */
235 	NULL,				/* epo_bist_stop */
236 #endif	/* EFSYS_OPT_BIST */
237 };
238 #endif	/* EFSYS_OPT_PHY_QT2025C */
239 
240 #if EFSYS_OPT_SIENA
241 static efx_phy_ops_t	__efx_phy_siena_ops = {
242 	siena_phy_power,		/* epo_power */
243 	NULL,				/* epo_reset */
244 	siena_phy_reconfigure,		/* epo_reconfigure */
245 	siena_phy_verify,		/* epo_verify */
246 	NULL,				/* epo_uplink_check */
247 	NULL,				/* epo_downlink_check */
248 	siena_phy_oui_get,		/* epo_oui_get */
249 #if EFSYS_OPT_PHY_STATS
250 	siena_phy_stats_update,		/* epo_stats_update */
251 #endif	/* EFSYS_OPT_PHY_STATS */
252 #if EFSYS_OPT_PHY_PROPS
253 #if EFSYS_OPT_NAMES
254 	siena_phy_prop_name,		/* epo_prop_name */
255 #endif
256 	siena_phy_prop_get,		/* epo_prop_get */
257 	siena_phy_prop_set,		/* epo_prop_set */
258 #endif	/* EFSYS_OPT_PHY_PROPS */
259 #if EFSYS_OPT_BIST
260 	NULL,				/* epo_bist_enable_offline */
261 	siena_phy_bist_start, 		/* epo_bist_start */
262 	siena_phy_bist_poll,		/* epo_bist_poll */
263 	siena_phy_bist_stop,		/* epo_bist_stop */
264 #endif	/* EFSYS_OPT_BIST */
265 };
266 #endif	/* EFSYS_OPT_SIENA */
267 
268 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
269 static efx_phy_ops_t	__efx_phy_ef10_ops = {
270 	ef10_phy_power,			/* epo_power */
271 	NULL,				/* epo_reset */
272 	ef10_phy_reconfigure,		/* epo_reconfigure */
273 	ef10_phy_verify,		/* epo_verify */
274 	NULL,				/* epo_uplink_check */
275 	NULL,				/* epo_downlink_check */
276 	ef10_phy_oui_get,		/* epo_oui_get */
277 #if EFSYS_OPT_PHY_STATS
278 	ef10_phy_stats_update,		/* epo_stats_update */
279 #endif	/* EFSYS_OPT_PHY_STATS */
280 #if EFSYS_OPT_PHY_PROPS
281 #if EFSYS_OPT_NAMES
282 	ef10_phy_prop_name,		/* epo_prop_name */
283 #endif
284 	ef10_phy_prop_get,		/* epo_prop_get */
285 	ef10_phy_prop_set,		/* epo_prop_set */
286 #endif	/* EFSYS_OPT_PHY_PROPS */
287 #if EFSYS_OPT_BIST
288 	/* FIXME: Are these BIST methods appropriate for Medford? */
289 	hunt_bist_enable_offline,	/* epo_bist_enable_offline */
290 	hunt_bist_start,		/* epo_bist_start */
291 	hunt_bist_poll,			/* epo_bist_poll */
292 	hunt_bist_stop,			/* epo_bist_stop */
293 #endif	/* EFSYS_OPT_BIST */
294 };
295 #endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
296 
297 	__checkReturn	efx_rc_t
298 efx_phy_probe(
299 	__in		efx_nic_t *enp)
300 {
301 	efx_port_t *epp = &(enp->en_port);
302 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
303 	efx_phy_ops_t *epop;
304 	efx_rc_t rc;
305 
306 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
307 
308 	epp->ep_port = encp->enc_port;
309 	epp->ep_phy_type = encp->enc_phy_type;
310 
311 	/* Hook in operations structure */
312 	switch (enp->en_family) {
313 #if EFSYS_OPT_FALCON
314 	case EFX_FAMILY_FALCON:
315 		switch (epp->ep_phy_type) {
316 #if EFSYS_OPT_PHY_NULL
317 		case PHY_TYPE_NONE_DECODE:
318 			epop = (efx_phy_ops_t *)&__efx_phy_null_ops;
319 			break;
320 #endif
321 #if EFSYS_OPT_PHY_QT2022C2
322 		case PHY_TYPE_QT2022C2_DECODE:
323 			epop = (efx_phy_ops_t *)&__efx_phy_qt2022c2_ops;
324 			break;
325 #endif
326 #if EFSYS_OPT_PHY_SFX7101
327 		case PHY_TYPE_SFX7101_DECODE:
328 			epop = (efx_phy_ops_t *)&__efx_phy_sfx7101_ops;
329 			break;
330 #endif
331 #if EFSYS_OPT_PHY_TXC43128
332 		case PHY_TYPE_TXC43128_DECODE:
333 			epop = (efx_phy_ops_t *)&__efx_phy_txc43128_ops;
334 			break;
335 #endif
336 #if EFSYS_OPT_PHY_SFT9001
337 		case PHY_TYPE_SFT9001A_DECODE:
338 		case PHY_TYPE_SFT9001B_DECODE:
339 			epop = (efx_phy_ops_t *)&__efx_phy_sft9001_ops;
340 			break;
341 #endif
342 #if EFSYS_OPT_PHY_QT2025C
343 		case EFX_PHY_QT2025C:
344 			epop = (efx_phy_ops_t *)&__efx_phy_qt2025c_ops;
345 			break;
346 #endif
347 		default:
348 			rc = ENOTSUP;
349 			goto fail1;
350 		}
351 		break;
352 #endif	/* EFSYS_OPT_FALCON */
353 #if EFSYS_OPT_SIENA
354 	case EFX_FAMILY_SIENA:
355 		epop = (efx_phy_ops_t *)&__efx_phy_siena_ops;
356 		break;
357 #endif	/* EFSYS_OPT_SIENA */
358 #if EFSYS_OPT_HUNTINGTON
359 	case EFX_FAMILY_HUNTINGTON:
360 		epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops;
361 		break;
362 #endif	/* EFSYS_OPT_HUNTINGTON */
363 #if EFSYS_OPT_MEDFORD
364 	case EFX_FAMILY_MEDFORD:
365 		epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops;
366 		break;
367 #endif	/* EFSYS_OPT_MEDFORD */
368 	default:
369 		rc = ENOTSUP;
370 		goto fail1;
371 	}
372 
373 	epp->ep_epop = epop;
374 
375 	return (0);
376 
377 fail1:
378 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
379 
380 	epp->ep_port = 0;
381 	epp->ep_phy_type = 0;
382 
383 	return (rc);
384 }
385 
386 	__checkReturn	efx_rc_t
387 efx_phy_verify(
388 	__in		efx_nic_t *enp)
389 {
390 	efx_port_t *epp = &(enp->en_port);
391 	efx_phy_ops_t *epop = epp->ep_epop;
392 
393 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
394 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
395 
396 	return (epop->epo_verify(enp));
397 }
398 
399 #if EFSYS_OPT_PHY_LED_CONTROL
400 
401 	__checkReturn	efx_rc_t
402 efx_phy_led_set(
403 	__in		efx_nic_t *enp,
404 	__in		efx_phy_led_mode_t mode)
405 {
406 	efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
407 	efx_port_t *epp = &(enp->en_port);
408 	efx_phy_ops_t *epop = epp->ep_epop;
409 	uint32_t mask;
410 	efx_rc_t rc;
411 
412 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
413 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
414 
415 	if (epp->ep_phy_led_mode == mode)
416 		goto done;
417 
418 	mask = (1 << EFX_PHY_LED_DEFAULT);
419 	mask |= encp->enc_led_mask;
420 
421 	if (!((1 << mode) & mask)) {
422 		rc = ENOTSUP;
423 		goto fail1;
424 	}
425 
426 	EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
427 	epp->ep_phy_led_mode = mode;
428 
429 	if ((rc = epop->epo_reconfigure(enp)) != 0)
430 		goto fail2;
431 
432 done:
433 	return (0);
434 
435 fail2:
436 	EFSYS_PROBE(fail2);
437 fail1:
438 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
439 
440 	return (rc);
441 }
442 #endif	/* EFSYS_OPT_PHY_LED_CONTROL */
443 
444 			void
445 efx_phy_adv_cap_get(
446 	__in		efx_nic_t *enp,
447 	__in		uint32_t flag,
448 	__out		uint32_t *maskp)
449 {
450 	efx_port_t *epp = &(enp->en_port);
451 
452 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
453 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
454 
455 	switch (flag) {
456 	case EFX_PHY_CAP_CURRENT:
457 		*maskp = epp->ep_adv_cap_mask;
458 		break;
459 	case EFX_PHY_CAP_DEFAULT:
460 		*maskp = epp->ep_default_adv_cap_mask;
461 		break;
462 	case EFX_PHY_CAP_PERM:
463 		*maskp = epp->ep_phy_cap_mask;
464 		break;
465 	default:
466 		EFSYS_ASSERT(B_FALSE);
467 		break;
468 	}
469 }
470 
471 	__checkReturn	efx_rc_t
472 efx_phy_adv_cap_set(
473 	__in		efx_nic_t *enp,
474 	__in		uint32_t mask)
475 {
476 	efx_port_t *epp = &(enp->en_port);
477 	efx_phy_ops_t *epop = epp->ep_epop;
478 	uint32_t old_mask;
479 	efx_rc_t rc;
480 
481 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
482 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
483 
484 	if ((mask & ~epp->ep_phy_cap_mask) != 0) {
485 		rc = ENOTSUP;
486 		goto fail1;
487 	}
488 
489 	if (epp->ep_adv_cap_mask == mask)
490 		goto done;
491 
492 	old_mask = epp->ep_adv_cap_mask;
493 	epp->ep_adv_cap_mask = mask;
494 
495 	if ((rc = epop->epo_reconfigure(enp)) != 0)
496 		goto fail2;
497 
498 done:
499 	return (0);
500 
501 fail2:
502 	EFSYS_PROBE(fail2);
503 
504 	epp->ep_adv_cap_mask = old_mask;
505 	/* Reconfigure for robustness */
506 	if (epop->epo_reconfigure(enp) != 0) {
507 		/*
508 		 * We may have an inconsistent view of our advertised speed
509 		 * capabilities.
510 		 */
511 		EFSYS_ASSERT(0);
512 	}
513 
514 fail1:
515 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
516 
517 	return (rc);
518 }
519 
520 	void
521 efx_phy_lp_cap_get(
522 	__in		efx_nic_t *enp,
523 	__out		uint32_t *maskp)
524 {
525 	efx_port_t *epp = &(enp->en_port);
526 
527 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
528 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
529 
530 	*maskp = epp->ep_lp_cap_mask;
531 }
532 
533 	__checkReturn	efx_rc_t
534 efx_phy_oui_get(
535 	__in		efx_nic_t *enp,
536 	__out		uint32_t *ouip)
537 {
538 	efx_port_t *epp = &(enp->en_port);
539 	efx_phy_ops_t *epop = epp->ep_epop;
540 
541 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
542 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
543 
544 	return (epop->epo_oui_get(enp, ouip));
545 }
546 
547 			void
548 efx_phy_media_type_get(
549 	__in		efx_nic_t *enp,
550 	__out		efx_phy_media_type_t *typep)
551 {
552 	efx_port_t *epp = &(enp->en_port);
553 
554 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
555 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
556 
557 	if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
558 		*typep = epp->ep_module_type;
559 	else
560 		*typep = epp->ep_fixed_port_type;
561 }
562 
563 	__checkReturn	efx_rc_t
564 efx_phy_module_get_info(
565 	__in			efx_nic_t *enp,
566 	__in			uint8_t dev_addr,
567 	__in			uint8_t offset,
568 	__in			uint8_t len,
569 	__out_bcount(len)	uint8_t *data)
570 {
571 	efx_rc_t rc;
572 
573 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
574 	EFSYS_ASSERT(data != NULL);
575 
576 	if ((uint32_t)offset + len > 0xff) {
577 		rc = EINVAL;
578 		goto fail1;
579 	}
580 
581 	if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr,
582 	    offset, len, data)) != 0)
583 		goto fail2;
584 
585 	return (0);
586 
587 fail2:
588 	EFSYS_PROBE(fail2);
589 fail1:
590 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
591 
592 	return (rc);
593 }
594 
595 #if EFSYS_OPT_PHY_STATS
596 
597 #if EFSYS_OPT_NAMES
598 
599 /* START MKCONFIG GENERATED PhyStatNamesBlock d5f79b4bc2c050fe */
600 static const char 	*__efx_phy_stat_name[] = {
601 	"oui",
602 	"pma_pmd_link_up",
603 	"pma_pmd_rx_fault",
604 	"pma_pmd_tx_fault",
605 	"pma_pmd_rev_a",
606 	"pma_pmd_rev_b",
607 	"pma_pmd_rev_c",
608 	"pma_pmd_rev_d",
609 	"pcs_link_up",
610 	"pcs_rx_fault",
611 	"pcs_tx_fault",
612 	"pcs_ber",
613 	"pcs_block_errors",
614 	"phy_xs_link_up",
615 	"phy_xs_rx_fault",
616 	"phy_xs_tx_fault",
617 	"phy_xs_align",
618 	"phy_xs_sync_a",
619 	"phy_xs_sync_b",
620 	"phy_xs_sync_c",
621 	"phy_xs_sync_d",
622 	"an_link_up",
623 	"an_master",
624 	"an_local_rx_ok",
625 	"an_remote_rx_ok",
626 	"cl22ext_link_up",
627 	"snr_a",
628 	"snr_b",
629 	"snr_c",
630 	"snr_d",
631 	"pma_pmd_signal_a",
632 	"pma_pmd_signal_b",
633 	"pma_pmd_signal_c",
634 	"pma_pmd_signal_d",
635 	"an_complete",
636 	"pma_pmd_rev_major",
637 	"pma_pmd_rev_minor",
638 	"pma_pmd_rev_micro",
639 	"pcs_fw_version_0",
640 	"pcs_fw_version_1",
641 	"pcs_fw_version_2",
642 	"pcs_fw_version_3",
643 	"pcs_fw_build_yy",
644 	"pcs_fw_build_mm",
645 	"pcs_fw_build_dd",
646 	"pcs_op_mode",
647 };
648 
649 /* END MKCONFIG GENERATED PhyStatNamesBlock */
650 
651 					const char *
652 efx_phy_stat_name(
653 	__in				efx_nic_t *enp,
654 	__in				efx_phy_stat_t type)
655 {
656 	_NOTE(ARGUNUSED(enp))
657 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
658 	EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
659 
660 	return (__efx_phy_stat_name[type]);
661 }
662 
663 #endif	/* EFSYS_OPT_NAMES */
664 
665 	__checkReturn			efx_rc_t
666 efx_phy_stats_update(
667 	__in				efx_nic_t *enp,
668 	__in				efsys_mem_t *esmp,
669 	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
670 {
671 	efx_port_t *epp = &(enp->en_port);
672 	efx_phy_ops_t *epop = epp->ep_epop;
673 
674 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
675 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
676 
677 	return (epop->epo_stats_update(enp, esmp, stat));
678 }
679 
680 #endif	/* EFSYS_OPT_PHY_STATS */
681 
682 #if EFSYS_OPT_PHY_PROPS
683 
684 #if EFSYS_OPT_NAMES
685 		const char *
686 efx_phy_prop_name(
687 	__in	efx_nic_t *enp,
688 	__in	unsigned int id)
689 {
690 	efx_port_t *epp = &(enp->en_port);
691 	efx_phy_ops_t *epop = epp->ep_epop;
692 
693 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
694 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
695 
696 	return (epop->epo_prop_name(enp, id));
697 }
698 #endif	/* EFSYS_OPT_NAMES */
699 
700 	__checkReturn	efx_rc_t
701 efx_phy_prop_get(
702 	__in		efx_nic_t *enp,
703 	__in		unsigned int id,
704 	__in		uint32_t flags,
705 	__out		uint32_t *valp)
706 {
707 	efx_port_t *epp = &(enp->en_port);
708 	efx_phy_ops_t *epop = epp->ep_epop;
709 
710 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
711 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
712 
713 	return (epop->epo_prop_get(enp, id, flags, valp));
714 }
715 
716 	__checkReturn	efx_rc_t
717 efx_phy_prop_set(
718 	__in		efx_nic_t *enp,
719 	__in		unsigned int id,
720 	__in		uint32_t val)
721 {
722 	efx_port_t *epp = &(enp->en_port);
723 	efx_phy_ops_t *epop = epp->ep_epop;
724 
725 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
726 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
727 
728 	return (epop->epo_prop_set(enp, id, val));
729 }
730 #endif	/* EFSYS_OPT_PHY_STATS */
731 
732 #if EFSYS_OPT_BIST
733 
734 	__checkReturn		efx_rc_t
735 efx_bist_enable_offline(
736 	__in			efx_nic_t *enp)
737 {
738 	efx_port_t *epp = &(enp->en_port);
739 	efx_phy_ops_t *epop = epp->ep_epop;
740 	efx_rc_t rc;
741 
742 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
743 
744 	if (epop->epo_bist_enable_offline == NULL) {
745 		rc = ENOTSUP;
746 		goto fail1;
747 	}
748 
749 	if ((rc = epop->epo_bist_enable_offline(enp)) != 0)
750 		goto fail2;
751 
752 	return (0);
753 
754 fail2:
755 	EFSYS_PROBE(fail2);
756 fail1:
757 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
758 
759 	return (rc);
760 
761 }
762 
763 	__checkReturn		efx_rc_t
764 efx_bist_start(
765 	__in			efx_nic_t *enp,
766 	__in			efx_bist_type_t type)
767 {
768 	efx_port_t *epp = &(enp->en_port);
769 	efx_phy_ops_t *epop = epp->ep_epop;
770 	efx_rc_t rc;
771 
772 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
773 
774 	EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
775 	EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
776 	EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_BIST_TYPE_UNKNOWN);
777 
778 	if (epop->epo_bist_start == NULL) {
779 		rc = ENOTSUP;
780 		goto fail1;
781 	}
782 
783 	if ((rc = epop->epo_bist_start(enp, type)) != 0)
784 		goto fail2;
785 
786 	epp->ep_current_bist = type;
787 
788 	return (0);
789 
790 fail2:
791 	EFSYS_PROBE(fail2);
792 fail1:
793 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
794 
795 	return (rc);
796 }
797 
798 	__checkReturn		efx_rc_t
799 efx_bist_poll(
800 	__in			efx_nic_t *enp,
801 	__in			efx_bist_type_t type,
802 	__out			efx_bist_result_t *resultp,
803 	__out_opt		uint32_t *value_maskp,
804 	__out_ecount_opt(count)	unsigned long *valuesp,
805 	__in			size_t count)
806 {
807 	efx_port_t *epp = &(enp->en_port);
808 	efx_phy_ops_t *epop = epp->ep_epop;
809 	efx_rc_t rc;
810 
811 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
812 
813 	EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
814 	EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
815 	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
816 
817 	EFSYS_ASSERT(epop->epo_bist_poll != NULL);
818 	if (epop->epo_bist_poll == NULL) {
819 		rc = ENOTSUP;
820 		goto fail1;
821 	}
822 
823 	if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
824 	    valuesp, count)) != 0)
825 		goto fail2;
826 
827 	return (0);
828 
829 fail2:
830 	EFSYS_PROBE(fail2);
831 fail1:
832 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
833 
834 	return (rc);
835 }
836 
837 			void
838 efx_bist_stop(
839 	__in		efx_nic_t *enp,
840 	__in		efx_bist_type_t type)
841 {
842 	efx_port_t *epp = &(enp->en_port);
843 	efx_phy_ops_t *epop = epp->ep_epop;
844 
845 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
846 
847 	EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
848 	EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
849 	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
850 
851 	EFSYS_ASSERT(epop->epo_bist_stop != NULL);
852 
853 	if (epop->epo_bist_stop != NULL)
854 		epop->epo_bist_stop(enp, type);
855 
856 	epp->ep_current_bist = EFX_BIST_TYPE_UNKNOWN;
857 }
858 
859 #endif	/* EFSYS_OPT_BIST */
860 			void
861 efx_phy_unprobe(
862 	__in	efx_nic_t *enp)
863 {
864 	efx_port_t *epp = &(enp->en_port);
865 
866 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
867 
868 	epp->ep_epop = NULL;
869 
870 	epp->ep_adv_cap_mask = 0;
871 
872 	epp->ep_port = 0;
873 	epp->ep_phy_type = 0;
874 }
875