2 * Copyright 2007-2009 Solarflare Communications Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
31 #include "efx_types.h"
35 #include "falcon_nvram.h"
38 #if EFSYS_OPT_MAC_FALCON_XMAC
39 #include "falcon_xmac.h"
42 #if EFSYS_OPT_MAC_FALCON_GMAC
43 #include "falcon_gmac.h"
46 #if EFSYS_OPT_PHY_NULL
50 #if EFSYS_OPT_PHY_QT2022C2
54 #if EFSYS_OPT_PHY_SFX7101
58 #if EFSYS_OPT_PHY_TXC43128
62 #if EFSYS_OPT_PHY_SFT9001
66 #if EFSYS_OPT_PHY_QT2025C
70 #if EFSYS_OPT_PHY_NULL
71 static efx_phy_ops_t __cs __efx_phy_null_ops = {
73 nullphy_reset, /* epo_reset */
74 nullphy_reconfigure, /* epo_reconfigure */
75 nullphy_verify, /* epo_verify */
76 NULL, /* epo_uplink_check */
77 nullphy_downlink_check, /* epo_downlink_check */
78 nullphy_oui_get, /* epo_oui_get */
79 #if EFSYS_OPT_PHY_STATS
80 nullphy_stats_update, /* epo_stats_update */
81 #endif /* EFSYS_OPT_PHY_STATS */
82 #if EFSYS_OPT_PHY_PROPS
84 nullphy_prop_name, /* epo_prop_name */
86 nullphy_prop_get, /* epo_prop_get */
87 nullphy_prop_set, /* epo_prop_set */
88 #endif /* EFSYS_OPT_PHY_PROPS */
89 #if EFSYS_OPT_PHY_BIST
90 NULL, /* epo_bist_start */
91 NULL, /* epo_bist_poll */
92 NULL, /* epo_bist_stop */
93 #endif /* EFSYS_OPT_PHY_BIST */
95 #endif /* EFSYS_OPT_PHY_NULL */
97 #if EFSYS_OPT_PHY_QT2022C2
98 static efx_phy_ops_t __cs __efx_phy_qt2022c2_ops = {
100 qt2022c2_reset, /* epo_reset */
101 qt2022c2_reconfigure, /* epo_reconfigure */
102 qt2022c2_verify, /* epo_verify */
103 qt2022c2_uplink_check, /* epo_uplink_check */
104 qt2022c2_downlink_check, /* epo_downlink_check */
105 qt2022c2_oui_get, /* epo_oui_get */
106 #if EFSYS_OPT_PHY_STATS
107 qt2022c2_stats_update, /* epo_stats_update */
108 #endif /* EFSYS_OPT_PHY_STATS */
109 #if EFSYS_OPT_PHY_PROPS
111 qt2022c2_prop_name, /* epo_prop_name */
113 qt2022c2_prop_get, /* epo_prop_get */
114 qt2022c2_prop_set, /* epo_prop_set */
115 #endif /* EFSYS_OPT_PHY_PROPS */
116 #if EFSYS_OPT_PHY_BIST
117 NULL, /* epo_bist_start */
118 NULL, /* epo_bist_poll */
119 NULL, /* epo_bist_stop */
120 #endif /* EFSYS_OPT_PHY_BIST */
122 #endif /* EFSYS_OPT_PHY_QT2022C2 */
124 #if EFSYS_OPT_PHY_SFX7101
125 static efx_phy_ops_t __cs __efx_phy_sfx7101_ops = {
126 sfx7101_power, /* epo_power */
127 sfx7101_reset, /* epo_reset */
128 sfx7101_reconfigure, /* epo_reconfigure */
129 sfx7101_verify, /* epo_verify */
130 sfx7101_uplink_check, /* epo_uplink_check */
131 sfx7101_downlink_check, /* epo_downlink_check */
132 sfx7101_oui_get, /* epo_oui_get */
133 #if EFSYS_OPT_PHY_STATS
134 sfx7101_stats_update, /* epo_stats_update */
135 #endif /* EFSYS_OPT_PHY_STATS */
136 #if EFSYS_OPT_PHY_PROPS
138 sfx7101_prop_name, /* epo_prop_name */
140 sfx7101_prop_get, /* epo_prop_get */
141 sfx7101_prop_set, /* epo_prop_set */
142 #endif /* EFSYS_OPT_PHY_PROPS */
143 #if EFSYS_OPT_PHY_BIST
144 NULL, /* epo_bist_start */
145 NULL, /* epo_bist_poll */
146 NULL, /* epo_bist_stop */
147 #endif /* EFSYS_OPT_PHY_BIST */
149 #endif /* EFSYS_OPT_PHY_SFX7101 */
151 #if EFSYS_OPT_PHY_TXC43128
152 static efx_phy_ops_t __cs __efx_phy_txc43128_ops = {
153 NULL, /* epo_power */
154 txc43128_reset, /* epo_reset */
155 txc43128_reconfigure, /* epo_reconfigure */
156 txc43128_verify, /* epo_verify */
157 txc43128_uplink_check, /* epo_uplink_check */
158 txc43128_downlink_check, /* epo_downlink_check */
159 txc43128_oui_get, /* epo_oui_get */
160 #if EFSYS_OPT_PHY_STATS
161 txc43128_stats_update, /* epo_stats_update */
162 #endif /* EFSYS_OPT_PHY_STATS */
163 #if EFSYS_OPT_PHY_PROPS
165 txc43128_prop_name, /* epo_prop_name */
167 txc43128_prop_get, /* epo_prop_get */
168 txc43128_prop_set, /* epo_prop_set */
169 #endif /* EFSYS_OPT_PHY_PROPS */
170 #if EFSYS_OPT_PHY_BIST
171 NULL, /* epo_bist_start */
172 NULL, /* epo_bist_poll */
173 NULL, /* epo_bist_stop */
174 #endif /* EFSYS_OPT_PHY_BIST */
176 #endif /* EFSYS_OPT_PHY_TXC43128 */
178 #if EFSYS_OPT_PHY_SFT9001
179 static efx_phy_ops_t __cs __efx_phy_sft9001_ops = {
180 NULL, /* epo_power */
181 sft9001_reset, /* epo_reset */
182 sft9001_reconfigure, /* epo_reconfigure */
183 sft9001_verify, /* epo_verify */
184 sft9001_uplink_check, /* epo_uplink_check */
185 sft9001_downlink_check, /* epo_downlink_check */
186 sft9001_oui_get, /* epo_oui_get */
187 #if EFSYS_OPT_PHY_STATS
188 sft9001_stats_update, /* epo_stats_update */
189 #endif /* EFSYS_OPT_PHY_STATS */
190 #if EFSYS_OPT_PHY_PROPS
192 sft9001_prop_name, /* epo_prop_name */
194 sft9001_prop_get, /* epo_prop_get */
195 sft9001_prop_set, /* epo_prop_set */
196 #endif /* EFSYS_OPT_PHY_PROPS */
197 #if EFSYS_OPT_PHY_BIST
198 sft9001_bist_start, /* epo_bist_start */
199 sft9001_bist_poll, /* epo_bist_poll */
200 sft9001_bist_stop, /* epo_bist_stop */
201 #endif /* EFSYS_OPT_PHY_BIST */
203 #endif /* EFSYS_OPT_PHY_SFT9001 */
205 #if EFSYS_OPT_PHY_QT2025C
206 static efx_phy_ops_t __cs __efx_phy_qt2025c_ops = {
207 NULL, /* epo_power */
208 qt2025c_reset, /* epo_reset */
209 qt2025c_reconfigure, /* epo_reconfigure */
210 qt2025c_verify, /* epo_verify */
211 qt2025c_uplink_check, /* epo_uplink_check */
212 qt2025c_downlink_check, /* epo_downlink_check */
213 qt2025c_oui_get, /* epo_oui_get */
214 #if EFSYS_OPT_PHY_STATS
215 qt2025c_stats_update, /* epo_stats_update */
216 #endif /* EFSYS_OPT_PHY_STATS */
217 #if EFSYS_OPT_PHY_PROPS
219 qt2025c_prop_name, /* epo_prop_name */
221 qt2025c_prop_get, /* epo_prop_get */
222 qt2025c_prop_set, /* epo_prop_set */
223 #endif /* EFSYS_OPT_PHY_PROPS */
224 #if EFSYS_OPT_PHY_BIST
225 NULL, /* epo_bist_start */
226 NULL, /* epo_bist_poll */
227 NULL, /* epo_bist_stop */
228 #endif /* EFSYS_OPT_PHY_BIST */
230 #endif /* EFSYS_OPT_PHY_QT2025C */
233 static efx_phy_ops_t __cs __efx_phy_siena_ops = {
234 siena_phy_power, /* epo_power */
235 NULL, /* epo_reset */
236 siena_phy_reconfigure, /* epo_reconfigure */
237 siena_phy_verify, /* epo_verify */
238 NULL, /* epo_uplink_check */
239 NULL, /* epo_downlink_check */
240 siena_phy_oui_get, /* epo_oui_get */
241 #if EFSYS_OPT_PHY_STATS
242 siena_phy_stats_update, /* epo_stats_update */
243 #endif /* EFSYS_OPT_PHY_STATS */
244 #if EFSYS_OPT_PHY_PROPS
246 siena_phy_prop_name, /* epo_prop_name */
248 siena_phy_prop_get, /* epo_prop_get */
249 siena_phy_prop_set, /* epo_prop_set */
250 #endif /* EFSYS_OPT_PHY_PROPS */
251 #if EFSYS_OPT_PHY_BIST
252 siena_phy_bist_start, /* epo_bist_start */
253 siena_phy_bist_poll, /* epo_bist_poll */
254 siena_phy_bist_stop, /* epo_bist_stop */
255 #endif /* EFSYS_OPT_PHY_BIST */
257 #endif /* EFSYS_OPT_SIENA */
263 efx_port_t *epp = &(enp->en_port);
264 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
268 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
270 epp->ep_port = encp->enc_port;
271 epp->ep_phy_type = encp->enc_phy_type;
273 /* Hook in operations structure */
274 switch (enp->en_family) {
276 case EFX_FAMILY_FALCON:
277 switch (epp->ep_phy_type) {
278 #if EFSYS_OPT_PHY_NULL
279 case PHY_TYPE_NONE_DECODE:
280 epop = (efx_phy_ops_t *)&__efx_phy_null_ops;
283 #if EFSYS_OPT_PHY_QT2022C2
284 case PHY_TYPE_QT2022C2_DECODE:
285 epop = (efx_phy_ops_t *)&__efx_phy_qt2022c2_ops;
288 #if EFSYS_OPT_PHY_SFX7101
289 case PHY_TYPE_SFX7101_DECODE:
290 epop = (efx_phy_ops_t *)&__efx_phy_sfx7101_ops;
293 #if EFSYS_OPT_PHY_TXC43128
294 case PHY_TYPE_TXC43128_DECODE:
295 epop = (efx_phy_ops_t *)&__efx_phy_txc43128_ops;
298 #if EFSYS_OPT_PHY_SFT9001
299 case PHY_TYPE_SFT9001A_DECODE:
300 case PHY_TYPE_SFT9001B_DECODE:
301 epop = (efx_phy_ops_t *)&__efx_phy_sft9001_ops;
304 #if EFSYS_OPT_PHY_QT2025C
305 case EFX_PHY_QT2025C:
306 epop = (efx_phy_ops_t *)&__efx_phy_qt2025c_ops;
314 #endif /* EFSYS_OPT_FALCON */
316 case EFX_FAMILY_SIENA:
317 epop = (efx_phy_ops_t *)&__efx_phy_siena_ops;
319 #endif /* EFSYS_OPT_SIENA */
330 EFSYS_PROBE1(fail1, int, rc);
333 epp->ep_phy_type = 0;
342 efx_port_t *epp = &(enp->en_port);
343 efx_phy_ops_t *epop = epp->ep_epop;
345 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
346 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
348 return (epop->epo_verify(enp));
351 #if EFSYS_OPT_PHY_LED_CONTROL
356 __in efx_phy_led_mode_t mode)
358 efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
359 efx_port_t *epp = &(enp->en_port);
360 efx_phy_ops_t *epop = epp->ep_epop;
364 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
365 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
367 if (epp->ep_phy_led_mode == mode)
370 mask = (1 << EFX_PHY_LED_DEFAULT);
371 mask |= encp->enc_led_mask;
373 if (!((1 << mode) & mask)) {
378 EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
379 epp->ep_phy_led_mode = mode;
381 if ((rc = epop->epo_reconfigure(enp)) != 0)
390 EFSYS_PROBE1(fail1, int, rc);
394 #endif /* EFSYS_OPT_PHY_LED_CONTROL */
400 __out uint32_t *maskp)
402 efx_port_t *epp = &(enp->en_port);
404 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
405 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
408 case EFX_PHY_CAP_CURRENT:
409 *maskp = epp->ep_adv_cap_mask;
411 case EFX_PHY_CAP_DEFAULT:
412 *maskp = epp->ep_default_adv_cap_mask;
414 case EFX_PHY_CAP_PERM:
415 *maskp = epp->ep_phy_cap_mask;
418 EFSYS_ASSERT(B_FALSE);
428 efx_port_t *epp = &(enp->en_port);
429 efx_phy_ops_t *epop = epp->ep_epop;
433 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
434 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
436 if ((mask & ~epp->ep_phy_cap_mask) != 0) {
441 if (epp->ep_adv_cap_mask == mask)
444 old_mask = epp->ep_adv_cap_mask;
445 epp->ep_adv_cap_mask = mask;
447 if ((rc = epop->epo_reconfigure(enp)) != 0)
456 epp->ep_adv_cap_mask = old_mask;
457 /* Reconfigure for robustness */
458 if (epop->epo_reconfigure(enp) != 0) {
460 * We may have an inconsistent view of our advertised speed
467 EFSYS_PROBE1(fail1, int, rc);
475 __out uint32_t *maskp)
477 efx_port_t *epp = &(enp->en_port);
479 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
480 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
482 *maskp = epp->ep_lp_cap_mask;
488 __out uint32_t *ouip)
490 efx_port_t *epp = &(enp->en_port);
491 efx_phy_ops_t *epop = epp->ep_epop;
493 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
494 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
496 return (epop->epo_oui_get(enp, ouip));
500 efx_phy_media_type_get(
502 __out efx_phy_media_type_t *typep)
504 efx_port_t *epp = &(enp->en_port);
506 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
507 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
509 if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
510 *typep = epp->ep_module_type;
512 *typep = epp->ep_fixed_port_type;
515 #if EFSYS_OPT_PHY_STATS
519 /* START MKCONFIG GENERATED PhyStatNamesBlock 271268f3da0e804f */
520 static const char __cs * __cs __efx_phy_stat_name[] = {
569 /* END MKCONFIG GENERATED PhyStatNamesBlock */
574 __in efx_phy_stat_t type)
576 _NOTE(ARGUNUSED(enp))
577 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
578 EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
580 return (__efx_phy_stat_name[type]);
583 #endif /* EFSYS_OPT_NAMES */
586 efx_phy_stats_update(
588 __in efsys_mem_t *esmp,
589 __out_ecount(EFX_PHY_NSTATS) uint32_t *stat)
591 efx_port_t *epp = &(enp->en_port);
592 efx_phy_ops_t *epop = epp->ep_epop;
594 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
595 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
597 return (epop->epo_stats_update(enp, esmp, stat));
600 #endif /* EFSYS_OPT_PHY_STATS */
602 #if EFSYS_OPT_PHY_PROPS
608 __in unsigned int id)
610 efx_port_t *epp = &(enp->en_port);
611 efx_phy_ops_t *epop = epp->ep_epop;
613 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
614 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
616 return (epop->epo_prop_name(enp, id));
618 #endif /* EFSYS_OPT_NAMES */
623 __in unsigned int id,
625 __out uint32_t *valp)
627 efx_port_t *epp = &(enp->en_port);
628 efx_phy_ops_t *epop = epp->ep_epop;
630 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
631 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
633 return (epop->epo_prop_get(enp, id, flags, valp));
639 __in unsigned int id,
642 efx_port_t *epp = &(enp->en_port);
643 efx_phy_ops_t *epop = epp->ep_epop;
645 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
646 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
648 return (epop->epo_prop_set(enp, id, val));
650 #endif /* EFSYS_OPT_PHY_STATS */
652 #if EFSYS_OPT_PHY_BIST
657 __in efx_phy_bist_type_t type)
659 efx_port_t *epp = &(enp->en_port);
660 efx_phy_ops_t *epop = epp->ep_epop;
663 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
664 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
666 EFSYS_ASSERT3U(type, !=, EFX_PHY_BIST_TYPE_UNKNOWN);
667 EFSYS_ASSERT3U(type, <, EFX_PHY_BIST_TYPE_NTYPES);
668 EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_PHY_BIST_TYPE_UNKNOWN);
670 if (epop->epo_bist_start == NULL) {
675 if ((rc = epop->epo_bist_start(enp, type)) != 0)
678 epp->ep_current_bist = type;
685 EFSYS_PROBE1(fail1, int, rc);
693 __in efx_phy_bist_type_t type,
694 __out efx_phy_bist_result_t *resultp,
695 __out_opt uint32_t *value_maskp,
696 __out_ecount_opt(count) unsigned long *valuesp,
699 efx_port_t *epp = &(enp->en_port);
700 efx_phy_ops_t *epop = epp->ep_epop;
703 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
704 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
706 EFSYS_ASSERT3U(type, !=, EFX_PHY_BIST_TYPE_UNKNOWN);
707 EFSYS_ASSERT3U(type, <, EFX_PHY_BIST_TYPE_NTYPES);
708 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
710 EFSYS_ASSERT(epop->epo_bist_poll != NULL);
711 if (epop->epo_bist_poll == NULL) {
716 if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
717 valuesp, count)) != 0)
725 EFSYS_PROBE1(fail1, int, rc);
733 __in efx_phy_bist_type_t type)
735 efx_port_t *epp = &(enp->en_port);
736 efx_phy_ops_t *epop = epp->ep_epop;
738 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
739 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
741 EFSYS_ASSERT3U(type, !=, EFX_PHY_BIST_TYPE_UNKNOWN);
742 EFSYS_ASSERT3U(type, <, EFX_PHY_BIST_TYPE_NTYPES);
743 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
745 EFSYS_ASSERT(epop->epo_bist_stop != NULL);
747 if (epop->epo_bist_stop != NULL)
748 epop->epo_bist_stop(enp, type);
750 epp->ep_current_bist = EFX_PHY_BIST_TYPE_UNKNOWN;
753 #endif /* EFSYS_OPT_PHY_BIST */
758 efx_port_t *epp = &(enp->en_port);
760 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
764 epp->ep_adv_cap_mask = 0;
767 epp->ep_phy_type = 0;