xref: /freebsd/sys/dev/sfxge/common/efx_phy.c (revision 807b6a646a0a0dbc258bf239468b5d9f901d1f92)
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
269 static efx_phy_ops_t	__efx_phy_hunt_ops = {
270 	hunt_phy_power,			/* epo_power */
271 	NULL,				/* epo_reset */
272 	hunt_phy_reconfigure,		/* epo_reconfigure */
273 	hunt_phy_verify,		/* epo_verify */
274 	NULL,				/* epo_uplink_check */
275 	NULL,				/* epo_downlink_check */
276 	hunt_phy_oui_get,		/* epo_oui_get */
277 #if EFSYS_OPT_PHY_STATS
278 	hunt_phy_stats_update,		/* epo_stats_update */
279 #endif	/* EFSYS_OPT_PHY_STATS */
280 #if EFSYS_OPT_PHY_PROPS
281 #if EFSYS_OPT_NAMES
282 	hunt_phy_prop_name,		/* epo_prop_name */
283 #endif
284 	hunt_phy_prop_get,		/* epo_prop_get */
285 	hunt_phy_prop_set,		/* epo_prop_set */
286 #endif	/* EFSYS_OPT_PHY_PROPS */
287 #if EFSYS_OPT_BIST
288 	hunt_bist_enable_offline,	/* epo_bist_enable_offline */
289 	hunt_bist_start,		/* epo_bist_start */
290 	hunt_bist_poll,			/* epo_bist_poll */
291 	hunt_bist_stop,			/* epo_bist_stop */
292 #endif	/* EFSYS_OPT_BIST */
293 };
294 #endif	/* EFSYS_OPT_HUNTINGTON */
295 
296 	__checkReturn	efx_rc_t
297 efx_phy_probe(
298 	__in		efx_nic_t *enp)
299 {
300 	efx_port_t *epp = &(enp->en_port);
301 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
302 	efx_phy_ops_t *epop;
303 	efx_rc_t rc;
304 
305 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
306 
307 	epp->ep_port = encp->enc_port;
308 	epp->ep_phy_type = encp->enc_phy_type;
309 
310 	/* Hook in operations structure */
311 	switch (enp->en_family) {
312 #if EFSYS_OPT_FALCON
313 	case EFX_FAMILY_FALCON:
314 		switch (epp->ep_phy_type) {
315 #if EFSYS_OPT_PHY_NULL
316 		case PHY_TYPE_NONE_DECODE:
317 			epop = (efx_phy_ops_t *)&__efx_phy_null_ops;
318 			break;
319 #endif
320 #if EFSYS_OPT_PHY_QT2022C2
321 		case PHY_TYPE_QT2022C2_DECODE:
322 			epop = (efx_phy_ops_t *)&__efx_phy_qt2022c2_ops;
323 			break;
324 #endif
325 #if EFSYS_OPT_PHY_SFX7101
326 		case PHY_TYPE_SFX7101_DECODE:
327 			epop = (efx_phy_ops_t *)&__efx_phy_sfx7101_ops;
328 			break;
329 #endif
330 #if EFSYS_OPT_PHY_TXC43128
331 		case PHY_TYPE_TXC43128_DECODE:
332 			epop = (efx_phy_ops_t *)&__efx_phy_txc43128_ops;
333 			break;
334 #endif
335 #if EFSYS_OPT_PHY_SFT9001
336 		case PHY_TYPE_SFT9001A_DECODE:
337 		case PHY_TYPE_SFT9001B_DECODE:
338 			epop = (efx_phy_ops_t *)&__efx_phy_sft9001_ops;
339 			break;
340 #endif
341 #if EFSYS_OPT_PHY_QT2025C
342 		case EFX_PHY_QT2025C:
343 			epop = (efx_phy_ops_t *)&__efx_phy_qt2025c_ops;
344 			break;
345 #endif
346 		default:
347 			rc = ENOTSUP;
348 			goto fail1;
349 		}
350 		break;
351 #endif	/* EFSYS_OPT_FALCON */
352 #if EFSYS_OPT_SIENA
353 	case EFX_FAMILY_SIENA:
354 		epop = (efx_phy_ops_t *)&__efx_phy_siena_ops;
355 		break;
356 #endif	/* EFSYS_OPT_SIENA */
357 #if EFSYS_OPT_HUNTINGTON
358 	case EFX_FAMILY_HUNTINGTON:
359 		epop = (efx_phy_ops_t *)&__efx_phy_hunt_ops;
360 		break;
361 #endif	/* EFSYS_OPT_HUNTINGTON */
362 	default:
363 		rc = ENOTSUP;
364 		goto fail1;
365 	}
366 
367 	epp->ep_epop = epop;
368 
369 	return (0);
370 
371 fail1:
372 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
373 
374 	epp->ep_port = 0;
375 	epp->ep_phy_type = 0;
376 
377 	return (rc);
378 }
379 
380 	__checkReturn	efx_rc_t
381 efx_phy_verify(
382 	__in		efx_nic_t *enp)
383 {
384 	efx_port_t *epp = &(enp->en_port);
385 	efx_phy_ops_t *epop = epp->ep_epop;
386 
387 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
388 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
389 
390 	return (epop->epo_verify(enp));
391 }
392 
393 #if EFSYS_OPT_PHY_LED_CONTROL
394 
395 	__checkReturn	efx_rc_t
396 efx_phy_led_set(
397 	__in		efx_nic_t *enp,
398 	__in		efx_phy_led_mode_t mode)
399 {
400 	efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
401 	efx_port_t *epp = &(enp->en_port);
402 	efx_phy_ops_t *epop = epp->ep_epop;
403 	uint32_t mask;
404 	efx_rc_t rc;
405 
406 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
407 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
408 
409 	if (epp->ep_phy_led_mode == mode)
410 		goto done;
411 
412 	mask = (1 << EFX_PHY_LED_DEFAULT);
413 	mask |= encp->enc_led_mask;
414 
415 	if (!((1 << mode) & mask)) {
416 		rc = ENOTSUP;
417 		goto fail1;
418 	}
419 
420 	EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
421 	epp->ep_phy_led_mode = mode;
422 
423 	if ((rc = epop->epo_reconfigure(enp)) != 0)
424 		goto fail2;
425 
426 done:
427 	return (0);
428 
429 fail2:
430 	EFSYS_PROBE(fail2);
431 fail1:
432 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
433 
434 	return (rc);
435 }
436 #endif	/* EFSYS_OPT_PHY_LED_CONTROL */
437 
438 			void
439 efx_phy_adv_cap_get(
440 	__in		efx_nic_t *enp,
441 	__in		uint32_t flag,
442 	__out		uint32_t *maskp)
443 {
444 	efx_port_t *epp = &(enp->en_port);
445 
446 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
447 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
448 
449 	switch (flag) {
450 	case EFX_PHY_CAP_CURRENT:
451 		*maskp = epp->ep_adv_cap_mask;
452 		break;
453 	case EFX_PHY_CAP_DEFAULT:
454 		*maskp = epp->ep_default_adv_cap_mask;
455 		break;
456 	case EFX_PHY_CAP_PERM:
457 		*maskp = epp->ep_phy_cap_mask;
458 		break;
459 	default:
460 		EFSYS_ASSERT(B_FALSE);
461 		break;
462 	}
463 }
464 
465 	__checkReturn	efx_rc_t
466 efx_phy_adv_cap_set(
467 	__in		efx_nic_t *enp,
468 	__in		uint32_t mask)
469 {
470 	efx_port_t *epp = &(enp->en_port);
471 	efx_phy_ops_t *epop = epp->ep_epop;
472 	uint32_t old_mask;
473 	efx_rc_t rc;
474 
475 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
476 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
477 
478 	if ((mask & ~epp->ep_phy_cap_mask) != 0) {
479 		rc = ENOTSUP;
480 		goto fail1;
481 	}
482 
483 	if (epp->ep_adv_cap_mask == mask)
484 		goto done;
485 
486 	old_mask = epp->ep_adv_cap_mask;
487 	epp->ep_adv_cap_mask = mask;
488 
489 	if ((rc = epop->epo_reconfigure(enp)) != 0)
490 		goto fail2;
491 
492 done:
493 	return (0);
494 
495 fail2:
496 	EFSYS_PROBE(fail2);
497 
498 	epp->ep_adv_cap_mask = old_mask;
499 	/* Reconfigure for robustness */
500 	if (epop->epo_reconfigure(enp) != 0) {
501 		/*
502 		 * We may have an inconsistent view of our advertised speed
503 		 * capabilities.
504 		 */
505 		EFSYS_ASSERT(0);
506 	}
507 
508 fail1:
509 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
510 
511 	return (rc);
512 }
513 
514 	void
515 efx_phy_lp_cap_get(
516 	__in		efx_nic_t *enp,
517 	__out		uint32_t *maskp)
518 {
519 	efx_port_t *epp = &(enp->en_port);
520 
521 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
522 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
523 
524 	*maskp = epp->ep_lp_cap_mask;
525 }
526 
527 	__checkReturn	efx_rc_t
528 efx_phy_oui_get(
529 	__in		efx_nic_t *enp,
530 	__out		uint32_t *ouip)
531 {
532 	efx_port_t *epp = &(enp->en_port);
533 	efx_phy_ops_t *epop = epp->ep_epop;
534 
535 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
536 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
537 
538 	return (epop->epo_oui_get(enp, ouip));
539 }
540 
541 			void
542 efx_phy_media_type_get(
543 	__in		efx_nic_t *enp,
544 	__out		efx_phy_media_type_t *typep)
545 {
546 	efx_port_t *epp = &(enp->en_port);
547 
548 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
549 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
550 
551 	if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
552 		*typep = epp->ep_module_type;
553 	else
554 		*typep = epp->ep_fixed_port_type;
555 }
556 
557 #if EFSYS_OPT_PHY_STATS
558 
559 #if EFSYS_OPT_NAMES
560 
561 /* START MKCONFIG GENERATED PhyStatNamesBlock d5f79b4bc2c050fe */
562 static const char 	*__efx_phy_stat_name[] = {
563 	"oui",
564 	"pma_pmd_link_up",
565 	"pma_pmd_rx_fault",
566 	"pma_pmd_tx_fault",
567 	"pma_pmd_rev_a",
568 	"pma_pmd_rev_b",
569 	"pma_pmd_rev_c",
570 	"pma_pmd_rev_d",
571 	"pcs_link_up",
572 	"pcs_rx_fault",
573 	"pcs_tx_fault",
574 	"pcs_ber",
575 	"pcs_block_errors",
576 	"phy_xs_link_up",
577 	"phy_xs_rx_fault",
578 	"phy_xs_tx_fault",
579 	"phy_xs_align",
580 	"phy_xs_sync_a",
581 	"phy_xs_sync_b",
582 	"phy_xs_sync_c",
583 	"phy_xs_sync_d",
584 	"an_link_up",
585 	"an_master",
586 	"an_local_rx_ok",
587 	"an_remote_rx_ok",
588 	"cl22ext_link_up",
589 	"snr_a",
590 	"snr_b",
591 	"snr_c",
592 	"snr_d",
593 	"pma_pmd_signal_a",
594 	"pma_pmd_signal_b",
595 	"pma_pmd_signal_c",
596 	"pma_pmd_signal_d",
597 	"an_complete",
598 	"pma_pmd_rev_major",
599 	"pma_pmd_rev_minor",
600 	"pma_pmd_rev_micro",
601 	"pcs_fw_version_0",
602 	"pcs_fw_version_1",
603 	"pcs_fw_version_2",
604 	"pcs_fw_version_3",
605 	"pcs_fw_build_yy",
606 	"pcs_fw_build_mm",
607 	"pcs_fw_build_dd",
608 	"pcs_op_mode",
609 };
610 
611 /* END MKCONFIG GENERATED PhyStatNamesBlock */
612 
613 					const char *
614 efx_phy_stat_name(
615 	__in				efx_nic_t *enp,
616 	__in				efx_phy_stat_t type)
617 {
618 	_NOTE(ARGUNUSED(enp))
619 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
620 	EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
621 
622 	return (__efx_phy_stat_name[type]);
623 }
624 
625 #endif	/* EFSYS_OPT_NAMES */
626 
627 	__checkReturn			efx_rc_t
628 efx_phy_stats_update(
629 	__in				efx_nic_t *enp,
630 	__in				efsys_mem_t *esmp,
631 	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
632 {
633 	efx_port_t *epp = &(enp->en_port);
634 	efx_phy_ops_t *epop = epp->ep_epop;
635 
636 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
637 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
638 
639 	return (epop->epo_stats_update(enp, esmp, stat));
640 }
641 
642 #endif	/* EFSYS_OPT_PHY_STATS */
643 
644 #if EFSYS_OPT_PHY_PROPS
645 
646 #if EFSYS_OPT_NAMES
647 		const char *
648 efx_phy_prop_name(
649 	__in	efx_nic_t *enp,
650 	__in	unsigned int id)
651 {
652 	efx_port_t *epp = &(enp->en_port);
653 	efx_phy_ops_t *epop = epp->ep_epop;
654 
655 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
656 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
657 
658 	return (epop->epo_prop_name(enp, id));
659 }
660 #endif	/* EFSYS_OPT_NAMES */
661 
662 	__checkReturn	efx_rc_t
663 efx_phy_prop_get(
664 	__in		efx_nic_t *enp,
665 	__in		unsigned int id,
666 	__in		uint32_t flags,
667 	__out		uint32_t *valp)
668 {
669 	efx_port_t *epp = &(enp->en_port);
670 	efx_phy_ops_t *epop = epp->ep_epop;
671 
672 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
673 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
674 
675 	return (epop->epo_prop_get(enp, id, flags, valp));
676 }
677 
678 	__checkReturn	efx_rc_t
679 efx_phy_prop_set(
680 	__in		efx_nic_t *enp,
681 	__in		unsigned int id,
682 	__in		uint32_t val)
683 {
684 	efx_port_t *epp = &(enp->en_port);
685 	efx_phy_ops_t *epop = epp->ep_epop;
686 
687 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
688 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
689 
690 	return (epop->epo_prop_set(enp, id, val));
691 }
692 #endif	/* EFSYS_OPT_PHY_STATS */
693 
694 #if EFSYS_OPT_BIST
695 
696 	__checkReturn		efx_rc_t
697 efx_bist_enable_offline(
698 	__in			efx_nic_t *enp)
699 {
700 	efx_port_t *epp = &(enp->en_port);
701 	efx_phy_ops_t *epop = epp->ep_epop;
702 	efx_rc_t rc;
703 
704 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
705 
706 	if (epop->epo_bist_enable_offline == NULL) {
707 		rc = ENOTSUP;
708 		goto fail1;
709 	}
710 
711 	if ((rc = epop->epo_bist_enable_offline(enp)) != 0)
712 		goto fail2;
713 
714 	return (0);
715 
716 fail2:
717 	EFSYS_PROBE(fail2);
718 fail1:
719 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
720 
721 	return (rc);
722 
723 }
724 
725 	__checkReturn		efx_rc_t
726 efx_bist_start(
727 	__in			efx_nic_t *enp,
728 	__in			efx_bist_type_t type)
729 {
730 	efx_port_t *epp = &(enp->en_port);
731 	efx_phy_ops_t *epop = epp->ep_epop;
732 	efx_rc_t rc;
733 
734 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
735 
736 	EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
737 	EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
738 	EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_BIST_TYPE_UNKNOWN);
739 
740 	if (epop->epo_bist_start == NULL) {
741 		rc = ENOTSUP;
742 		goto fail1;
743 	}
744 
745 	if ((rc = epop->epo_bist_start(enp, type)) != 0)
746 		goto fail2;
747 
748 	epp->ep_current_bist = type;
749 
750 	return (0);
751 
752 fail2:
753 	EFSYS_PROBE(fail2);
754 fail1:
755 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
756 
757 	return (rc);
758 }
759 
760 	__checkReturn		efx_rc_t
761 efx_bist_poll(
762 	__in			efx_nic_t *enp,
763 	__in			efx_bist_type_t type,
764 	__out			efx_bist_result_t *resultp,
765 	__out_opt		uint32_t *value_maskp,
766 	__out_ecount_opt(count)	unsigned long *valuesp,
767 	__in			size_t count)
768 {
769 	efx_port_t *epp = &(enp->en_port);
770 	efx_phy_ops_t *epop = epp->ep_epop;
771 	efx_rc_t rc;
772 
773 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
774 
775 	EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
776 	EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
777 	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
778 
779 	EFSYS_ASSERT(epop->epo_bist_poll != NULL);
780 	if (epop->epo_bist_poll == NULL) {
781 		rc = ENOTSUP;
782 		goto fail1;
783 	}
784 
785 	if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
786 	    valuesp, count)) != 0)
787 		goto fail2;
788 
789 	return (0);
790 
791 fail2:
792 	EFSYS_PROBE(fail2);
793 fail1:
794 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
795 
796 	return (rc);
797 }
798 
799 			void
800 efx_bist_stop(
801 	__in		efx_nic_t *enp,
802 	__in		efx_bist_type_t type)
803 {
804 	efx_port_t *epp = &(enp->en_port);
805 	efx_phy_ops_t *epop = epp->ep_epop;
806 
807 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
808 
809 	EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
810 	EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
811 	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
812 
813 	EFSYS_ASSERT(epop->epo_bist_stop != NULL);
814 
815 	if (epop->epo_bist_stop != NULL)
816 		epop->epo_bist_stop(enp, type);
817 
818 	epp->ep_current_bist = EFX_BIST_TYPE_UNKNOWN;
819 }
820 
821 #endif	/* EFSYS_OPT_BIST */
822 			void
823 efx_phy_unprobe(
824 	__in	efx_nic_t *enp)
825 {
826 	efx_port_t *epp = &(enp->en_port);
827 
828 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
829 
830 	epp->ep_epop = NULL;
831 
832 	epp->ep_adv_cap_mask = 0;
833 
834 	epp->ep_port = 0;
835 	epp->ep_phy_type = 0;
836 }
837