2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright (c) 2017, Joyent, Inc.
17 * illumos specific bnxe related functions.
23 * Try to figure out which phy we should be using at this time based on the
24 * requested transceiver.
27 bnxe_get_phy_id(um_device_t
*um
)
29 if (um
->lm_dev
.params
.link
.num_phys
<= 1)
30 return (ELINK_INT_PHY
);
32 if (um
->lm_dev
.vars
.link
.link_up
) {
33 if ((um
->lm_dev
.vars
.link
.link_status
&
34 LINK_STATUS_SERDES_LINK
) &&
35 (um
->lm_dev
.params
.link
.phy
[ELINK_EXT_PHY2
].supported
&
36 ELINK_SUPPORTED_FIBRE
))
37 return (ELINK_EXT_PHY2
);
38 return (ELINK_EXT_PHY1
);
40 switch (elink_phy_selection(&um
->lm_dev
.params
.link
)) {
41 case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT
:
42 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY
:
43 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY
:
44 return (ELINK_EXT_PHY1
);
45 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY
:
46 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY
:
47 return (ELINK_EXT_PHY2
);
49 * The above hardware types are the only ones currently defined
50 * by the specification and common code. If we end up with an
51 * unknown value, then we default to what the hardware considers
52 * the default, which is PHY1.
55 return (ELINK_EXT_PHY1
);
61 bnxe_transceiver_info(void *arg
, uint_t id
, mac_transceiver_info_t
*infop
)
64 um_device_t
*um
= arg
;
65 struct elink_params
*params
;
66 struct elink_phy
*phy
;
67 boolean_t present
= B_FALSE
, usable
= B_FALSE
;
71 if (id
!= 0 || arg
== NULL
|| infop
== NULL
)
74 BNXE_LOCK_ENTER_PHY(um
);
75 phyid
= bnxe_get_phy_id(um
);
76 params
= &um
->lm_dev
.params
.link
;
77 phy
= ¶ms
->phy
[phyid
];
78 if (phy
->media_type
== ELINK_ETH_PHY_BASE_T
) {
79 BNXE_LOCK_EXIT_PHY(um
);
84 * Right now, the core OS-independent code from QLogic doesn't quite
85 * track whether or not the phy is plugged in, though it easily could.
86 * As such, the best way to determine whether or not the phy is present
87 * is to see if we can read the first byte from page 0xa0. We expect to
88 * get an explicit timeout if the device isn't present. We'll propagate
89 * EIO on any other error as we're not in a good state to understand
92 PHY_HW_LOCK(&um
->lm_dev
);
93 ret
= elink_read_sfp_module_eeprom(phy
, params
, 0xa0, 0, sizeof (buf
),
95 PHY_HW_UNLOCK(&um
->lm_dev
);
96 if (ret
!= ELINK_STATUS_OK
&& ret
!= ELINK_STATUS_TIMEOUT
) {
97 BNXE_LOCK_EXIT_PHY(um
);
100 if (ret
== ELINK_STATUS_OK
) {
102 if ((phy
->flags
& ELINK_FLAGS_SFP_NOT_APPROVED
) == 0)
105 BNXE_LOCK_EXIT_PHY(um
);
107 mac_transceiver_info_set_present(infop
, present
);
108 mac_transceiver_info_set_usable(infop
, usable
);
114 bnxe_transceiver_read(void *arg
, uint_t id
, uint_t page
, void *bp
,
115 size_t nbytes
, off_t offset
, size_t *nread
)
118 um_device_t
*um
= arg
;
119 struct elink_phy
*phy
;
120 struct elink_params
*params
;
123 if (id
!= 0 || bp
== NULL
|| nbytes
== 0 || nread
== NULL
||
124 (page
!= 0xa0 && page
!= 0xa2) || offset
< 0)
128 * Sanity check length params.
130 if (nbytes
> 256 || offset
>= 256 || (offset
+ nbytes
> 256)) {
134 BNXE_LOCK_ENTER_PHY(um
);
135 phyid
= bnxe_get_phy_id(um
);
136 params
= &um
->lm_dev
.params
.link
;
137 phy
= &um
->lm_dev
.params
.link
.phy
[phyid
];
139 if (phy
->media_type
== ELINK_ETH_PHY_BASE_T
) {
140 BNXE_LOCK_EXIT_PHY(um
);
145 PHY_HW_LOCK(&um
->lm_dev
);
146 ret
= elink_read_sfp_module_eeprom(phy
, params
, (uint8_t)page
,
147 (uint16_t)offset
, (uint16_t)nbytes
, bp
);
148 PHY_HW_UNLOCK(&um
->lm_dev
);
150 BNXE_LOCK_EXIT_PHY(um
);
153 case ELINK_STATUS_OK
:
156 case ELINK_OP_NOT_SUPPORTED
:
164 bnxe_fill_transceiver(um_device_t
*um
, void *arg
)
167 mac_capab_transceiver_t
*mct
= arg
;
171 * While there is nominally a dual-phy version of bnxe out there (see
172 * ELINK_DUAL_MEDIA and related macros), these haven't been seen in the
173 * wild. For now, only assume that we have a single phy.
175 mct
->mct_ntransceivers
= 1;
176 mct
->mct_info
= bnxe_transceiver_info
;
177 mct
->mct_read
= bnxe_transceiver_read
;