1227569Sphilip/*- 2227569Sphilip * Copyright 2009 Solarflare Communications Inc. All rights reserved. 3227569Sphilip * 4227569Sphilip * Redistribution and use in source and binary forms, with or without 5227569Sphilip * modification, are permitted provided that the following conditions 6227569Sphilip * are met: 7227569Sphilip * 1. Redistributions of source code must retain the above copyright 8227569Sphilip * notice, this list of conditions and the following disclaimer. 9227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright 10227569Sphilip * notice, this list of conditions and the following disclaimer in the 11227569Sphilip * documentation and/or other materials provided with the distribution. 12227569Sphilip * 13227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14227569Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15227569Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16227569Sphilip * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17227569Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18227569Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19227569Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20227569Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21227569Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22227569Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23227569Sphilip * SUCH DAMAGE. 24227569Sphilip */ 25227569Sphilip 26228078Sphilip#include <sys/cdefs.h> 27228078Sphilip__FBSDID("$FreeBSD$"); 28228078Sphilip 29227569Sphilip#include "efsys.h" 30227569Sphilip#include "efx.h" 31227569Sphilip#include "efx_types.h" 32227569Sphilip#include "efx_impl.h" 33227569Sphilip 34227569Sphilip __checkReturn int 35227569Sphilipefx_port_init( 36227569Sphilip __in efx_nic_t *enp) 37227569Sphilip{ 38227569Sphilip efx_port_t *epp = &(enp->en_port); 39227569Sphilip efx_phy_ops_t *epop = epp->ep_epop; 40227569Sphilip int rc; 41227569Sphilip 42227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 43227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 44227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 45227569Sphilip 46227569Sphilip if (enp->en_mod_flags & EFX_MOD_PORT) { 47227569Sphilip rc = EINVAL; 48227569Sphilip goto fail1; 49227569Sphilip } 50227569Sphilip 51227569Sphilip enp->en_mod_flags |= EFX_MOD_PORT; 52227569Sphilip 53227569Sphilip epp->ep_mac_type = EFX_MAC_INVALID; 54227569Sphilip epp->ep_link_mode = EFX_LINK_UNKNOWN; 55227569Sphilip epp->ep_mac_poll_needed = B_TRUE; 56227569Sphilip epp->ep_mac_drain = B_TRUE; 57227569Sphilip 58227569Sphilip /* Configure the MAC */ 59227569Sphilip if ((rc = efx_mac_select(enp)) != 0) 60227569Sphilip goto fail1; 61227569Sphilip 62227569Sphilip epp->ep_emop->emo_reconfigure(enp); 63227569Sphilip 64227569Sphilip /* 65227569Sphilip * Turn on the PHY if available, otherwise reset it, and 66227569Sphilip * reconfigure it with the current configuration. 67227569Sphilip */ 68227569Sphilip if (epop->epo_power != NULL) { 69227569Sphilip if ((rc = epop->epo_power(enp, B_TRUE)) != 0) 70227569Sphilip goto fail2; 71227569Sphilip } else { 72227569Sphilip if ((rc = epop->epo_reset(enp)) != 0) 73227569Sphilip goto fail2; 74227569Sphilip } 75227569Sphilip 76227569Sphilip EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY); 77227569Sphilip enp->en_reset_flags &= ~EFX_RESET_PHY; 78227569Sphilip 79227569Sphilip if ((rc = epop->epo_reconfigure(enp)) != 0) 80227569Sphilip goto fail3; 81227569Sphilip 82227569Sphilip return (0); 83227569Sphilip 84227569Sphilipfail3: 85227569Sphilip EFSYS_PROBE(fail3); 86227569Sphilipfail2: 87227569Sphilip EFSYS_PROBE(fail2); 88227569Sphilipfail1: 89227569Sphilip EFSYS_PROBE1(fail1, int, rc); 90227569Sphilip 91227569Sphilip enp->en_mod_flags &= ~EFX_MOD_PORT; 92227569Sphilip 93227569Sphilip return (rc); 94227569Sphilip} 95227569Sphilip 96227569Sphilip __checkReturn int 97227569Sphilipefx_port_poll( 98227569Sphilip __in efx_nic_t *enp, 99227569Sphilip __out efx_link_mode_t *link_modep) 100227569Sphilip{ 101227569Sphilip efx_port_t *epp = &(enp->en_port); 102227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 103227569Sphilip efx_link_mode_t ignore_link_mode; 104227569Sphilip int rc; 105227569Sphilip 106227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 107227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 108227569Sphilip 109227569Sphilip EFSYS_ASSERT(emop != NULL); 110227569Sphilip EFSYS_ASSERT(!epp->ep_mac_stats_pending); 111227569Sphilip 112227569Sphilip if (link_modep == NULL) 113227569Sphilip link_modep = &ignore_link_mode; 114227569Sphilip 115227569Sphilip if ((rc = emop->emo_poll(enp, link_modep)) != 0) 116227569Sphilip goto fail1; 117227569Sphilip 118227569Sphilip return (0); 119227569Sphilip 120227569Sphilipfail1: 121227569Sphilip EFSYS_PROBE1(fail1, int, rc); 122227569Sphilip 123227569Sphilip return (rc); 124227569Sphilip} 125227569Sphilip 126227569Sphilip#if EFSYS_OPT_LOOPBACK 127227569Sphilip 128227569Sphilip __checkReturn int 129227569Sphilipefx_port_loopback_set( 130227569Sphilip __in efx_nic_t *enp, 131227569Sphilip __in efx_link_mode_t link_mode, 132227569Sphilip __in efx_loopback_type_t loopback_type) 133227569Sphilip{ 134227569Sphilip efx_port_t *epp = &(enp->en_port); 135227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 136227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 137227569Sphilip int rc; 138227569Sphilip 139227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 140227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 141227569Sphilip EFSYS_ASSERT(emop != NULL); 142227569Sphilip 143227569Sphilip EFSYS_ASSERT(link_mode < EFX_LINK_NMODES); 144227569Sphilip if ((1 << loopback_type) & ~encp->enc_loopback_types[link_mode]) { 145227569Sphilip rc = ENOTSUP; 146227569Sphilip goto fail1; 147227569Sphilip } 148227569Sphilip 149227569Sphilip if (epp->ep_loopback_type == loopback_type && 150227569Sphilip epp->ep_loopback_link_mode == link_mode) 151227569Sphilip return (0); 152227569Sphilip 153227569Sphilip if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0) 154227569Sphilip goto fail2; 155227569Sphilip 156227569Sphilip return (0); 157227569Sphilip 158227569Sphilipfail2: 159227569Sphilip EFSYS_PROBE(fail2); 160227569Sphilipfail1: 161227569Sphilip EFSYS_PROBE1(fail1, int, rc); 162227569Sphilip 163227569Sphilip return (rc); 164227569Sphilip} 165227569Sphilip 166227569Sphilip#if EFSYS_OPT_NAMES 167227569Sphilip 168227569Sphilipstatic const char __cs * __cs __efx_loopback_type_name[] = { 169227569Sphilip "OFF", 170227569Sphilip "DATA", 171227569Sphilip "GMAC", 172227569Sphilip "XGMII", 173227569Sphilip "XGXS", 174227569Sphilip "XAUI", 175227569Sphilip "GMII", 176227569Sphilip "SGMII", 177227569Sphilip "XGBR", 178227569Sphilip "XFI", 179227569Sphilip "XAUI_FAR", 180227569Sphilip "GMII_FAR", 181227569Sphilip "SGMII_FAR", 182227569Sphilip "XFI_FAR", 183227569Sphilip "GPHY", 184227569Sphilip "PHY_XS", 185227569Sphilip "PCS", 186227569Sphilip "PMA_PMD", 187227569Sphilip}; 188227569Sphilip 189227569Sphilip __checkReturn const char __cs * 190227569Sphilipefx_loopback_type_name( 191227569Sphilip __in efx_nic_t *enp, 192227569Sphilip __in efx_loopback_type_t type) 193227569Sphilip{ 194227569Sphilip _NOTE(ARGUNUSED(enp)) 195227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 196227569Sphilip EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES); 197227569Sphilip 198227569Sphilip return (__efx_loopback_type_name[type]); 199227569Sphilip} 200227569Sphilip 201227569Sphilip#endif /* EFSYS_OPT_NAMES */ 202227569Sphilip 203227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 204227569Sphilip 205227569Sphilip void 206227569Sphilipefx_port_fini( 207227569Sphilip __in efx_nic_t *enp) 208227569Sphilip{ 209227569Sphilip efx_port_t *epp = &(enp->en_port); 210227569Sphilip efx_phy_ops_t *epop = epp->ep_epop; 211227569Sphilip 212227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 213227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 214227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 215227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 216227569Sphilip 217227569Sphilip EFSYS_ASSERT(epp->ep_mac_drain); 218227569Sphilip 219227569Sphilip epp->ep_emop = NULL; 220227569Sphilip epp->ep_mac_type = EFX_MAC_INVALID; 221227569Sphilip epp->ep_mac_drain = B_FALSE; 222227569Sphilip epp->ep_mac_poll_needed = B_FALSE; 223227569Sphilip 224227569Sphilip /* Turn off the PHY */ 225227569Sphilip if (epop->epo_power != NULL) 226227569Sphilip (void) epop->epo_power(enp, B_FALSE); 227227569Sphilip 228227569Sphilip enp->en_mod_flags &= ~EFX_MOD_PORT; 229227569Sphilip} 230