1e948693eSPhilip Paeps /*- 2e948693eSPhilip Paeps * Copyright 2009 Solarflare Communications Inc. All rights reserved. 3e948693eSPhilip Paeps * 4e948693eSPhilip Paeps * Redistribution and use in source and binary forms, with or without 5e948693eSPhilip Paeps * modification, are permitted provided that the following conditions 6e948693eSPhilip Paeps * are met: 7e948693eSPhilip Paeps * 1. Redistributions of source code must retain the above copyright 8e948693eSPhilip Paeps * notice, this list of conditions and the following disclaimer. 9e948693eSPhilip Paeps * 2. Redistributions in binary form must reproduce the above copyright 10e948693eSPhilip Paeps * notice, this list of conditions and the following disclaimer in the 11e948693eSPhilip Paeps * documentation and/or other materials provided with the distribution. 12e948693eSPhilip Paeps * 13e948693eSPhilip Paeps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14e948693eSPhilip Paeps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15e948693eSPhilip Paeps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16e948693eSPhilip Paeps * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17e948693eSPhilip Paeps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18e948693eSPhilip Paeps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19e948693eSPhilip Paeps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20e948693eSPhilip Paeps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21e948693eSPhilip Paeps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22e948693eSPhilip Paeps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23e948693eSPhilip Paeps * SUCH DAMAGE. 24e948693eSPhilip Paeps */ 25e948693eSPhilip Paeps 26*5dee87d7SPhilip Paeps #include <sys/cdefs.h> 27*5dee87d7SPhilip Paeps __FBSDID("$FreeBSD$"); 28*5dee87d7SPhilip Paeps 29e948693eSPhilip Paeps #include "efsys.h" 30e948693eSPhilip Paeps #include "efx.h" 31e948693eSPhilip Paeps #include "efx_types.h" 32e948693eSPhilip Paeps #include "efx_impl.h" 33e948693eSPhilip Paeps 34e948693eSPhilip Paeps __checkReturn int 35e948693eSPhilip Paeps efx_port_init( 36e948693eSPhilip Paeps __in efx_nic_t *enp) 37e948693eSPhilip Paeps { 38e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 39e948693eSPhilip Paeps efx_phy_ops_t *epop = epp->ep_epop; 40e948693eSPhilip Paeps int rc; 41e948693eSPhilip Paeps 42e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 43e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 44e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 45e948693eSPhilip Paeps 46e948693eSPhilip Paeps if (enp->en_mod_flags & EFX_MOD_PORT) { 47e948693eSPhilip Paeps rc = EINVAL; 48e948693eSPhilip Paeps goto fail1; 49e948693eSPhilip Paeps } 50e948693eSPhilip Paeps 51e948693eSPhilip Paeps enp->en_mod_flags |= EFX_MOD_PORT; 52e948693eSPhilip Paeps 53e948693eSPhilip Paeps epp->ep_mac_type = EFX_MAC_INVALID; 54e948693eSPhilip Paeps epp->ep_link_mode = EFX_LINK_UNKNOWN; 55e948693eSPhilip Paeps epp->ep_mac_poll_needed = B_TRUE; 56e948693eSPhilip Paeps epp->ep_mac_drain = B_TRUE; 57e948693eSPhilip Paeps 58e948693eSPhilip Paeps /* Configure the MAC */ 59e948693eSPhilip Paeps if ((rc = efx_mac_select(enp)) != 0) 60e948693eSPhilip Paeps goto fail1; 61e948693eSPhilip Paeps 62e948693eSPhilip Paeps epp->ep_emop->emo_reconfigure(enp); 63e948693eSPhilip Paeps 64e948693eSPhilip Paeps /* 65e948693eSPhilip Paeps * Turn on the PHY if available, otherwise reset it, and 66e948693eSPhilip Paeps * reconfigure it with the current configuration. 67e948693eSPhilip Paeps */ 68e948693eSPhilip Paeps if (epop->epo_power != NULL) { 69e948693eSPhilip Paeps if ((rc = epop->epo_power(enp, B_TRUE)) != 0) 70e948693eSPhilip Paeps goto fail2; 71e948693eSPhilip Paeps } else { 72e948693eSPhilip Paeps if ((rc = epop->epo_reset(enp)) != 0) 73e948693eSPhilip Paeps goto fail2; 74e948693eSPhilip Paeps } 75e948693eSPhilip Paeps 76e948693eSPhilip Paeps EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY); 77e948693eSPhilip Paeps enp->en_reset_flags &= ~EFX_RESET_PHY; 78e948693eSPhilip Paeps 79e948693eSPhilip Paeps if ((rc = epop->epo_reconfigure(enp)) != 0) 80e948693eSPhilip Paeps goto fail3; 81e948693eSPhilip Paeps 82e948693eSPhilip Paeps return (0); 83e948693eSPhilip Paeps 84e948693eSPhilip Paeps fail3: 85e948693eSPhilip Paeps EFSYS_PROBE(fail3); 86e948693eSPhilip Paeps fail2: 87e948693eSPhilip Paeps EFSYS_PROBE(fail2); 88e948693eSPhilip Paeps fail1: 89e948693eSPhilip Paeps EFSYS_PROBE1(fail1, int, rc); 90e948693eSPhilip Paeps 91e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_PORT; 92e948693eSPhilip Paeps 93e948693eSPhilip Paeps return (rc); 94e948693eSPhilip Paeps } 95e948693eSPhilip Paeps 96e948693eSPhilip Paeps __checkReturn int 97e948693eSPhilip Paeps efx_port_poll( 98e948693eSPhilip Paeps __in efx_nic_t *enp, 99e948693eSPhilip Paeps __out efx_link_mode_t *link_modep) 100e948693eSPhilip Paeps { 101e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 102e948693eSPhilip Paeps efx_mac_ops_t *emop = epp->ep_emop; 103e948693eSPhilip Paeps efx_link_mode_t ignore_link_mode; 104e948693eSPhilip Paeps int rc; 105e948693eSPhilip Paeps 106e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 107e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 108e948693eSPhilip Paeps 109e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 110e948693eSPhilip Paeps EFSYS_ASSERT(!epp->ep_mac_stats_pending); 111e948693eSPhilip Paeps 112e948693eSPhilip Paeps if (link_modep == NULL) 113e948693eSPhilip Paeps link_modep = &ignore_link_mode; 114e948693eSPhilip Paeps 115e948693eSPhilip Paeps if ((rc = emop->emo_poll(enp, link_modep)) != 0) 116e948693eSPhilip Paeps goto fail1; 117e948693eSPhilip Paeps 118e948693eSPhilip Paeps return (0); 119e948693eSPhilip Paeps 120e948693eSPhilip Paeps fail1: 121e948693eSPhilip Paeps EFSYS_PROBE1(fail1, int, rc); 122e948693eSPhilip Paeps 123e948693eSPhilip Paeps return (rc); 124e948693eSPhilip Paeps } 125e948693eSPhilip Paeps 126e948693eSPhilip Paeps #if EFSYS_OPT_LOOPBACK 127e948693eSPhilip Paeps 128e948693eSPhilip Paeps __checkReturn int 129e948693eSPhilip Paeps efx_port_loopback_set( 130e948693eSPhilip Paeps __in efx_nic_t *enp, 131e948693eSPhilip Paeps __in efx_link_mode_t link_mode, 132e948693eSPhilip Paeps __in efx_loopback_type_t loopback_type) 133e948693eSPhilip Paeps { 134e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 135e948693eSPhilip Paeps efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 136e948693eSPhilip Paeps efx_mac_ops_t *emop = epp->ep_emop; 137e948693eSPhilip Paeps int rc; 138e948693eSPhilip Paeps 139e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 140e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 141e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 142e948693eSPhilip Paeps 143e948693eSPhilip Paeps EFSYS_ASSERT(link_mode < EFX_LINK_NMODES); 144e948693eSPhilip Paeps if ((1 << loopback_type) & ~encp->enc_loopback_types[link_mode]) { 145e948693eSPhilip Paeps rc = ENOTSUP; 146e948693eSPhilip Paeps goto fail1; 147e948693eSPhilip Paeps } 148e948693eSPhilip Paeps 149e948693eSPhilip Paeps if (epp->ep_loopback_type == loopback_type && 150e948693eSPhilip Paeps epp->ep_loopback_link_mode == link_mode) 151e948693eSPhilip Paeps return (0); 152e948693eSPhilip Paeps 153e948693eSPhilip Paeps if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0) 154e948693eSPhilip Paeps goto fail2; 155e948693eSPhilip Paeps 156e948693eSPhilip Paeps return (0); 157e948693eSPhilip Paeps 158e948693eSPhilip Paeps fail2: 159e948693eSPhilip Paeps EFSYS_PROBE(fail2); 160e948693eSPhilip Paeps fail1: 161e948693eSPhilip Paeps EFSYS_PROBE1(fail1, int, rc); 162e948693eSPhilip Paeps 163e948693eSPhilip Paeps return (rc); 164e948693eSPhilip Paeps } 165e948693eSPhilip Paeps 166e948693eSPhilip Paeps #if EFSYS_OPT_NAMES 167e948693eSPhilip Paeps 168e948693eSPhilip Paeps static const char __cs * __cs __efx_loopback_type_name[] = { 169e948693eSPhilip Paeps "OFF", 170e948693eSPhilip Paeps "DATA", 171e948693eSPhilip Paeps "GMAC", 172e948693eSPhilip Paeps "XGMII", 173e948693eSPhilip Paeps "XGXS", 174e948693eSPhilip Paeps "XAUI", 175e948693eSPhilip Paeps "GMII", 176e948693eSPhilip Paeps "SGMII", 177e948693eSPhilip Paeps "XGBR", 178e948693eSPhilip Paeps "XFI", 179e948693eSPhilip Paeps "XAUI_FAR", 180e948693eSPhilip Paeps "GMII_FAR", 181e948693eSPhilip Paeps "SGMII_FAR", 182e948693eSPhilip Paeps "XFI_FAR", 183e948693eSPhilip Paeps "GPHY", 184e948693eSPhilip Paeps "PHY_XS", 185e948693eSPhilip Paeps "PCS", 186e948693eSPhilip Paeps "PMA_PMD", 187e948693eSPhilip Paeps }; 188e948693eSPhilip Paeps 189e948693eSPhilip Paeps __checkReturn const char __cs * 190e948693eSPhilip Paeps efx_loopback_type_name( 191e948693eSPhilip Paeps __in efx_nic_t *enp, 192e948693eSPhilip Paeps __in efx_loopback_type_t type) 193e948693eSPhilip Paeps { 194e948693eSPhilip Paeps _NOTE(ARGUNUSED(enp)) 195e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 196e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES); 197e948693eSPhilip Paeps 198e948693eSPhilip Paeps return (__efx_loopback_type_name[type]); 199e948693eSPhilip Paeps } 200e948693eSPhilip Paeps 201e948693eSPhilip Paeps #endif /* EFSYS_OPT_NAMES */ 202e948693eSPhilip Paeps 203e948693eSPhilip Paeps #endif /* EFSYS_OPT_LOOPBACK */ 204e948693eSPhilip Paeps 205e948693eSPhilip Paeps void 206e948693eSPhilip Paeps efx_port_fini( 207e948693eSPhilip Paeps __in efx_nic_t *enp) 208e948693eSPhilip Paeps { 209e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 210e948693eSPhilip Paeps efx_phy_ops_t *epop = epp->ep_epop; 211e948693eSPhilip Paeps 212e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 213e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 214e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 215e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 216e948693eSPhilip Paeps 217e948693eSPhilip Paeps EFSYS_ASSERT(epp->ep_mac_drain); 218e948693eSPhilip Paeps 219e948693eSPhilip Paeps epp->ep_emop = NULL; 220e948693eSPhilip Paeps epp->ep_mac_type = EFX_MAC_INVALID; 221e948693eSPhilip Paeps epp->ep_mac_drain = B_FALSE; 222e948693eSPhilip Paeps epp->ep_mac_poll_needed = B_FALSE; 223e948693eSPhilip Paeps 224e948693eSPhilip Paeps /* Turn off the PHY */ 225e948693eSPhilip Paeps if (epop->epo_power != NULL) 226e948693eSPhilip Paeps (void) epop->epo_power(enp, B_FALSE); 227e948693eSPhilip Paeps 228e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_PORT; 229e948693eSPhilip Paeps } 230