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