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 */ 25228078Sphilip 26228078Sphilip#include <sys/cdefs.h> 27228078Sphilip__FBSDID("$FreeBSD$"); 28228078Sphilip 29227569Sphilip#include "efsys.h" 30227569Sphilip#include "efx.h" 31227569Sphilip#include "efx_impl.h" 32227569Sphilip 33227569Sphilip#if EFSYS_OPT_SIENA 34227569Sphilip 35227569Sphilipstatic __checkReturn int 36227569Sphilipsiena_nic_get_partn_mask( 37227569Sphilip __in efx_nic_t *enp, 38227569Sphilip __out unsigned int *maskp) 39227569Sphilip{ 40227569Sphilip efx_mcdi_req_t req; 41227569Sphilip uint8_t outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN]; 42227569Sphilip int rc; 43227569Sphilip 44227569Sphilip req.emr_cmd = MC_CMD_NVRAM_TYPES; 45227569Sphilip EFX_STATIC_ASSERT(MC_CMD_NVRAM_TYPES_IN_LEN == 0); 46227569Sphilip req.emr_in_buf = NULL; 47227569Sphilip req.emr_in_length = 0; 48227569Sphilip req.emr_out_buf = outbuf; 49227569Sphilip req.emr_out_length = sizeof (outbuf); 50227569Sphilip 51227569Sphilip efx_mcdi_execute(enp, &req); 52227569Sphilip 53227569Sphilip if (req.emr_rc != 0) { 54227569Sphilip rc = req.emr_rc; 55227569Sphilip goto fail1; 56227569Sphilip } 57227569Sphilip 58227569Sphilip if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) { 59227569Sphilip rc = EMSGSIZE; 60227569Sphilip goto fail2; 61227569Sphilip } 62227569Sphilip 63227569Sphilip *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES); 64227569Sphilip 65227569Sphilip return (0); 66227569Sphilip 67227569Sphilipfail2: 68227569Sphilip EFSYS_PROBE(fail2); 69227569Sphilipfail1: 70227569Sphilip EFSYS_PROBE1(fail1, int, rc); 71227569Sphilip 72227569Sphilip return (rc); 73227569Sphilip} 74227569Sphilip 75227569Sphilipstatic __checkReturn int 76227569Sphilipsiena_nic_exit_assertion_handler( 77227569Sphilip __in efx_nic_t *enp) 78227569Sphilip{ 79227569Sphilip efx_mcdi_req_t req; 80227569Sphilip uint8_t payload[MC_CMD_REBOOT_IN_LEN]; 81227569Sphilip int rc; 82227569Sphilip 83227569Sphilip req.emr_cmd = MC_CMD_REBOOT; 84227569Sphilip req.emr_in_buf = payload; 85227569Sphilip req.emr_in_length = MC_CMD_REBOOT_IN_LEN; 86227569Sphilip EFX_STATIC_ASSERT(MC_CMD_REBOOT_OUT_LEN == 0); 87227569Sphilip req.emr_out_buf = NULL; 88227569Sphilip req.emr_out_length = 0; 89227569Sphilip 90227569Sphilip MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS, 91227569Sphilip MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION); 92227569Sphilip 93227569Sphilip efx_mcdi_execute(enp, &req); 94227569Sphilip 95227569Sphilip if (req.emr_rc != 0 && req.emr_rc != EIO) { 96227569Sphilip rc = req.emr_rc; 97227569Sphilip goto fail1; 98227569Sphilip } 99227569Sphilip 100227569Sphilip return (0); 101227569Sphilip 102227569Sphilipfail1: 103227569Sphilip EFSYS_PROBE1(fail1, int, rc); 104227569Sphilip 105227569Sphilip return (rc); 106227569Sphilip} 107227569Sphilip 108227569Sphilipstatic __checkReturn int 109227569Sphilipsiena_nic_read_assertion( 110227569Sphilip __in efx_nic_t *enp) 111227569Sphilip{ 112227569Sphilip efx_mcdi_req_t req; 113227569Sphilip uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN, 114227569Sphilip MC_CMD_GET_ASSERTS_OUT_LEN)]; 115227569Sphilip const char *reason; 116227569Sphilip unsigned int flags; 117227569Sphilip unsigned int index; 118227569Sphilip unsigned int ofst; 119227569Sphilip int retry; 120227569Sphilip int rc; 121227569Sphilip 122227569Sphilip /* 123227569Sphilip * Before we attempt to chat to the MC, we should verify that the MC 124227569Sphilip * isn't in it's assertion handler, either due to a previous reboot, 125227569Sphilip * or because we're reinitializing due to an eec_exception(). 126227569Sphilip * 127227569Sphilip * Use GET_ASSERTS to read any assertion state that may be present. 128227569Sphilip * Retry this command twice. Once because a boot-time assertion failure 129227569Sphilip * might cause the 1st MCDI request to fail. And once again because 130227569Sphilip * we might race with siena_nic_exit_assertion_handler() running on the 131227569Sphilip * other port. 132227569Sphilip */ 133227569Sphilip retry = 2; 134227569Sphilip do { 135227569Sphilip req.emr_cmd = MC_CMD_GET_ASSERTS; 136227569Sphilip req.emr_in_buf = payload; 137227569Sphilip req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN; 138227569Sphilip req.emr_out_buf = payload; 139227569Sphilip req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN; 140227569Sphilip 141227569Sphilip MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1); 142227569Sphilip efx_mcdi_execute(enp, &req); 143227569Sphilip 144227569Sphilip } while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0); 145227569Sphilip 146227569Sphilip if (req.emr_rc != 0) { 147227569Sphilip rc = req.emr_rc; 148227569Sphilip goto fail1; 149227569Sphilip } 150227569Sphilip 151227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) { 152227569Sphilip rc = EMSGSIZE; 153227569Sphilip goto fail2; 154227569Sphilip } 155227569Sphilip 156227569Sphilip /* Print out any assertion state recorded */ 157227569Sphilip flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS); 158227569Sphilip if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS) 159227569Sphilip return (0); 160227569Sphilip 161227569Sphilip reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL) 162227569Sphilip ? "system-level assertion" 163227569Sphilip : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL) 164227569Sphilip ? "thread-level assertion" 165227569Sphilip : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED) 166227569Sphilip ? "watchdog reset" 167227569Sphilip : "unknown assertion"; 168227569Sphilip EFSYS_PROBE3(mcpu_assertion, 169227569Sphilip const char *, reason, unsigned int, 170227569Sphilip MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS), 171227569Sphilip unsigned int, 172227569Sphilip MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS)); 173227569Sphilip 174227569Sphilip /* Print out the registers */ 175227569Sphilip ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST; 176227569Sphilip for (index = 1; index < 32; index++) { 177227569Sphilip EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int, 178227569Sphilip EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst), 179227569Sphilip EFX_DWORD_0)); 180227569Sphilip ofst += sizeof (efx_dword_t); 181227569Sphilip } 182227569Sphilip EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN); 183227569Sphilip 184227569Sphilip return (0); 185227569Sphilip 186227569Sphilipfail2: 187227569Sphilip EFSYS_PROBE(fail2); 188227569Sphilipfail1: 189227569Sphilip EFSYS_PROBE1(fail1, int, rc); 190227569Sphilip 191227569Sphilip return (rc); 192227569Sphilip} 193227569Sphilip 194227569Sphilipstatic __checkReturn int 195227569Sphilipsiena_nic_attach( 196227569Sphilip __in efx_nic_t *enp, 197227569Sphilip __in boolean_t attach) 198227569Sphilip{ 199227569Sphilip efx_mcdi_req_t req; 200227569Sphilip uint8_t payload[MC_CMD_DRV_ATTACH_IN_LEN]; 201227569Sphilip int rc; 202227569Sphilip 203227569Sphilip req.emr_cmd = MC_CMD_DRV_ATTACH; 204227569Sphilip req.emr_in_buf = payload; 205227569Sphilip req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN; 206227569Sphilip req.emr_out_buf = NULL; 207227569Sphilip req.emr_out_length = 0; 208227569Sphilip 209227569Sphilip MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0); 210227569Sphilip MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1); 211227569Sphilip 212227569Sphilip efx_mcdi_execute(enp, &req); 213227569Sphilip 214227569Sphilip if (req.emr_rc != 0) { 215227569Sphilip rc = req.emr_rc; 216227569Sphilip goto fail1; 217227569Sphilip } 218227569Sphilip 219227569Sphilip if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) { 220227569Sphilip rc = EMSGSIZE; 221227569Sphilip goto fail2; 222227569Sphilip } 223227569Sphilip 224227569Sphilip return (0); 225227569Sphilip 226227569Sphilipfail2: 227227569Sphilip EFSYS_PROBE(fail2); 228227569Sphilipfail1: 229227569Sphilip EFSYS_PROBE1(fail1, int, rc); 230227569Sphilip 231227569Sphilip return (rc); 232227569Sphilip} 233227569Sphilip 234227569Sphilip#if EFSYS_OPT_PCIE_TUNE 235227569Sphilip 236227569Sphilip __checkReturn int 237227569Sphilipsiena_nic_pcie_extended_sync( 238227569Sphilip __in efx_nic_t *enp) 239227569Sphilip{ 240227569Sphilip uint8_t inbuf[MC_CMD_WORKAROUND_IN_LEN]; 241227569Sphilip efx_mcdi_req_t req; 242227569Sphilip int rc; 243227569Sphilip 244227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 245227569Sphilip 246227569Sphilip req.emr_cmd = MC_CMD_WORKAROUND; 247227569Sphilip req.emr_in_buf = inbuf; 248227569Sphilip req.emr_in_length = sizeof (inbuf); 249227569Sphilip EFX_STATIC_ASSERT(MC_CMD_WORKAROUND_OUT_LEN == 0); 250227569Sphilip req.emr_out_buf = NULL; 251227569Sphilip req.emr_out_length = 0; 252227569Sphilip 253227569Sphilip MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, MC_CMD_WORKAROUND_BUG17230); 254227569Sphilip MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, 1); 255227569Sphilip 256227569Sphilip efx_mcdi_execute(enp, &req); 257227569Sphilip 258227569Sphilip if (req.emr_rc != 0) { 259227569Sphilip rc = req.emr_rc; 260227569Sphilip goto fail1; 261227569Sphilip } 262227569Sphilip 263227569Sphilip return (0); 264227569Sphilip 265227569Sphilipfail1: 266227569Sphilip EFSYS_PROBE1(fail1, int, rc); 267227569Sphilip 268227569Sphilip return (rc); 269227569Sphilip} 270227569Sphilip 271227569Sphilip#endif /* EFSYS_OPT_PCIE_TUNE */ 272227569Sphilip 273227569Sphilipstatic __checkReturn int 274227569Sphilipsiena_board_cfg( 275227569Sphilip __in efx_nic_t *enp) 276227569Sphilip{ 277227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 278227569Sphilip efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip); 279227569Sphilip uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LEN, 280227569Sphilip MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)]; 281227569Sphilip efx_mcdi_req_t req; 282227569Sphilip uint8_t *src; 283227569Sphilip int rc; 284227569Sphilip 285227569Sphilip /* Board configuration */ 286227569Sphilip req.emr_cmd = MC_CMD_GET_BOARD_CFG; 287227569Sphilip EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0); 288227569Sphilip req.emr_in_buf = NULL; 289227569Sphilip req.emr_in_length = 0; 290227569Sphilip req.emr_out_buf = outbuf; 291227569Sphilip req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LEN; 292227569Sphilip 293227569Sphilip efx_mcdi_execute(enp, &req); 294227569Sphilip 295227569Sphilip if (req.emr_rc != 0) { 296227569Sphilip rc = req.emr_rc; 297227569Sphilip goto fail1; 298227569Sphilip } 299227569Sphilip 300227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LEN) { 301227569Sphilip rc = EMSGSIZE; 302227569Sphilip goto fail2; 303227569Sphilip } 304227569Sphilip 305227569Sphilip if (emip->emi_port == 1) 306227569Sphilip src = MCDI_OUT2(req, uint8_t, 307227569Sphilip GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0); 308227569Sphilip else 309227569Sphilip src = MCDI_OUT2(req, uint8_t, 310227569Sphilip GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1); 311227569Sphilip EFX_MAC_ADDR_COPY(encp->enc_mac_addr, src); 312227569Sphilip 313227569Sphilip encp->enc_board_type = MCDI_OUT_DWORD(req, 314227569Sphilip GET_BOARD_CFG_OUT_BOARD_TYPE); 315227569Sphilip 316227569Sphilip /* Resource limits */ 317227569Sphilip req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS; 318227569Sphilip EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0); 319227569Sphilip req.emr_in_buf = NULL; 320227569Sphilip req.emr_in_length = 0; 321227569Sphilip req.emr_out_buf = outbuf; 322227569Sphilip req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN; 323227569Sphilip 324227569Sphilip efx_mcdi_execute(enp, &req); 325227569Sphilip 326227569Sphilip if (req.emr_rc == 0) { 327227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) { 328227569Sphilip rc = EMSGSIZE; 329227569Sphilip goto fail3; 330227569Sphilip } 331227569Sphilip 332227569Sphilip encp->enc_evq_limit = MCDI_OUT_DWORD(req, 333227569Sphilip GET_RESOURCE_LIMITS_OUT_EVQ); 334227569Sphilip encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, 335227569Sphilip MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ)); 336227569Sphilip encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, 337227569Sphilip MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ)); 338227569Sphilip } else if (req.emr_rc == ENOTSUP) { 339227569Sphilip encp->enc_evq_limit = 1024; 340227569Sphilip encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET; 341227569Sphilip encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET; 342227569Sphilip } else { 343227569Sphilip rc = req.emr_rc; 344227569Sphilip goto fail4; 345227569Sphilip } 346227569Sphilip 347227569Sphilip encp->enc_buftbl_limit = SIENA_SRAM_ROWS - 348227569Sphilip (encp->enc_txq_limit * 16) - (encp->enc_rxq_limit * 64); 349227569Sphilip 350227569Sphilip return (0); 351227569Sphilip 352227569Sphilipfail4: 353227569Sphilip EFSYS_PROBE(fail4); 354227569Sphilipfail3: 355227569Sphilip EFSYS_PROBE(fail3); 356227569Sphilipfail2: 357227569Sphilip EFSYS_PROBE(fail2); 358227569Sphilipfail1: 359227569Sphilip EFSYS_PROBE1(fail1, int, rc); 360227569Sphilip 361227569Sphilip return (rc); 362227569Sphilip} 363227569Sphilip 364227569Sphilipstatic __checkReturn int 365227569Sphilipsiena_phy_cfg( 366227569Sphilip __in efx_nic_t *enp) 367227569Sphilip{ 368227569Sphilip efx_port_t *epp = &(enp->en_port); 369227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 370227569Sphilip efx_mcdi_req_t req; 371227569Sphilip uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN]; 372227569Sphilip int rc; 373227569Sphilip 374227569Sphilip req.emr_cmd = MC_CMD_GET_PHY_CFG; 375227569Sphilip EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0); 376227569Sphilip req.emr_in_buf = NULL; 377227569Sphilip req.emr_in_length = 0; 378227569Sphilip req.emr_out_buf = outbuf; 379227569Sphilip req.emr_out_length = sizeof (outbuf); 380227569Sphilip 381227569Sphilip efx_mcdi_execute(enp, &req); 382227569Sphilip 383227569Sphilip if (req.emr_rc != 0) { 384227569Sphilip rc = req.emr_rc; 385227569Sphilip goto fail1; 386227569Sphilip } 387227569Sphilip 388227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) { 389227569Sphilip rc = EMSGSIZE; 390227569Sphilip goto fail2; 391227569Sphilip } 392227569Sphilip 393227569Sphilip encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE); 394227569Sphilip#if EFSYS_OPT_NAMES 395227569Sphilip (void) strncpy(encp->enc_phy_name, 396227569Sphilip MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME), 397227569Sphilip MIN(sizeof (encp->enc_phy_name) - 1, 398227569Sphilip MC_CMD_GET_PHY_CFG_OUT_NAME_LEN)); 399227569Sphilip#endif /* EFSYS_OPT_NAMES */ 400227569Sphilip (void) memset(encp->enc_phy_revision, 0, 401227569Sphilip sizeof (encp->enc_phy_revision)); 402227569Sphilip memcpy(encp->enc_phy_revision, 403227569Sphilip MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION), 404227569Sphilip MIN(sizeof (encp->enc_phy_revision) - 1, 405227569Sphilip MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN)); 406227569Sphilip#if EFSYS_OPT_PHY_LED_CONTROL 407227569Sphilip encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) | 408227569Sphilip (1 << EFX_PHY_LED_OFF) | 409227569Sphilip (1 << EFX_PHY_LED_ON)); 410227569Sphilip#endif /* EFSYS_OPT_PHY_LED_CONTROL */ 411227569Sphilip 412227569Sphilip#if EFSYS_OPT_PHY_PROPS 413227569Sphilip encp->enc_phy_nprops = 0; 414227569Sphilip#endif /* EFSYS_OPT_PHY_PROPS */ 415227569Sphilip 416227569Sphilip /* Get the media type of the fixed port, if recognised. */ 417227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI); 418227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4); 419227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4); 420227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP); 421227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS); 422227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T); 423227569Sphilip epp->ep_fixed_port_type = 424227569Sphilip MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE); 425227569Sphilip if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES) 426227569Sphilip epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID; 427227569Sphilip 428227569Sphilip epp->ep_phy_cap_mask = 429227569Sphilip MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP); 430227569Sphilip#if EFSYS_OPT_PHY_FLAGS 431227569Sphilip encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS); 432227569Sphilip#endif /* EFSYS_OPT_PHY_FLAGS */ 433227569Sphilip 434227569Sphilip encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT); 435227569Sphilip 436227569Sphilip /* Populate internal state */ 437227569Sphilip encp->enc_siena_channel = 438227569Sphilip (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL); 439227569Sphilip 440227569Sphilip#if EFSYS_OPT_PHY_STATS 441227569Sphilip encp->enc_siena_phy_stat_mask = 442227569Sphilip MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK); 443227569Sphilip 444227569Sphilip /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ 445227569Sphilip siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask, 446227569Sphilip NULL, &encp->enc_phy_stat_mask, NULL); 447227569Sphilip#endif /* EFSYS_OPT_PHY_STATS */ 448227569Sphilip 449227569Sphilip#if EFSYS_OPT_PHY_BIST 450227569Sphilip encp->enc_bist_mask = 0; 451227569Sphilip if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 452227569Sphilip GET_PHY_CFG_OUT_BIST_CABLE_SHORT)) 453227569Sphilip encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT); 454227569Sphilip if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 455227569Sphilip GET_PHY_CFG_OUT_BIST_CABLE_LONG)) 456227569Sphilip encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG); 457227569Sphilip if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 458227569Sphilip GET_PHY_CFG_OUT_BIST)) 459227569Sphilip encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL); 460227569Sphilip#endif /* EFSYS_OPT_BIST */ 461227569Sphilip 462227569Sphilip return (0); 463227569Sphilip 464227569Sphilipfail2: 465227569Sphilip EFSYS_PROBE(fail2); 466227569Sphilipfail1: 467227569Sphilip EFSYS_PROBE1(fail1, int, rc); 468227569Sphilip 469227569Sphilip return (rc); 470227569Sphilip} 471227569Sphilip 472227569Sphilip#if EFSYS_OPT_LOOPBACK 473227569Sphilip 474227569Sphilipstatic __checkReturn int 475227569Sphilipsiena_loopback_cfg( 476227569Sphilip __in efx_nic_t *enp) 477227569Sphilip{ 478227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 479227569Sphilip efx_mcdi_req_t req; 480227569Sphilip uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN]; 481227569Sphilip int rc; 482227569Sphilip 483227569Sphilip req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES; 484227569Sphilip EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0); 485227569Sphilip req.emr_in_buf = NULL; 486227569Sphilip req.emr_in_length = 0; 487227569Sphilip req.emr_out_buf = outbuf; 488227569Sphilip req.emr_out_length = sizeof (outbuf); 489227569Sphilip 490227569Sphilip efx_mcdi_execute(enp, &req); 491227569Sphilip 492227569Sphilip if (req.emr_rc != 0) { 493227569Sphilip rc = req.emr_rc; 494227569Sphilip goto fail1; 495227569Sphilip } 496227569Sphilip 497227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) { 498227569Sphilip rc = EMSGSIZE; 499227569Sphilip goto fail2; 500227569Sphilip } 501227569Sphilip 502227569Sphilip /* 503227569Sphilip * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree 504227569Sphilip * in siena_phy.c:siena_phy_get_link() 505227569Sphilip */ 506227569Sphilip encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK & 507227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) & 508227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 509227569Sphilip encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK & 510227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) & 511227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 512227569Sphilip encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK & 513227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) & 514227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 515227569Sphilip encp->enc_loopback_types[EFX_LINK_UNKNOWN] = 516227569Sphilip (1 << EFX_LOOPBACK_OFF) | 517227569Sphilip encp->enc_loopback_types[EFX_LINK_100FDX] | 518227569Sphilip encp->enc_loopback_types[EFX_LINK_1000FDX] | 519227569Sphilip encp->enc_loopback_types[EFX_LINK_10000FDX]; 520227569Sphilip 521227569Sphilip return (0); 522227569Sphilip 523227569Sphilipfail2: 524227569Sphilip EFSYS_PROBE(fail2); 525227569Sphilipfail1: 526227569Sphilip EFSYS_PROBE1(fail1, int, rc); 527227569Sphilip 528227569Sphilip return (rc); 529227569Sphilip} 530227569Sphilip 531227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 532227569Sphilip 533227569Sphilip#if EFSYS_OPT_MON_STATS 534227569Sphilip 535227569Sphilipstatic __checkReturn int 536227569Sphilipsiena_monitor_cfg( 537227569Sphilip __in efx_nic_t *enp) 538227569Sphilip{ 539227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 540227569Sphilip efx_mcdi_req_t req; 541227569Sphilip uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX]; 542227569Sphilip int rc; 543227569Sphilip 544227569Sphilip req.emr_cmd = MC_CMD_SENSOR_INFO; 545227569Sphilip EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0); 546227569Sphilip req.emr_in_buf = NULL; 547227569Sphilip req.emr_in_length = 0; 548227569Sphilip req.emr_out_buf = outbuf; 549227569Sphilip req.emr_out_length = sizeof (outbuf); 550227569Sphilip 551227569Sphilip efx_mcdi_execute(enp, &req); 552227569Sphilip 553227569Sphilip if (req.emr_rc != 0) { 554227569Sphilip rc = req.emr_rc; 555227569Sphilip goto fail1; 556227569Sphilip } 557227569Sphilip 558227569Sphilip if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) { 559227569Sphilip rc = EMSGSIZE; 560227569Sphilip goto fail2; 561227569Sphilip } 562227569Sphilip 563227569Sphilip encp->enc_siena_mon_stat_mask = 564227569Sphilip MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK); 565227569Sphilip encp->enc_mon_type = EFX_MON_SFC90X0; 566227569Sphilip 567227569Sphilip siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask, 568227569Sphilip NULL, &(encp->enc_mon_stat_mask), NULL); 569227569Sphilip 570227569Sphilip return (0); 571227569Sphilip 572227569Sphilipfail2: 573227569Sphilip EFSYS_PROBE(fail2); 574227569Sphilipfail1: 575227569Sphilip EFSYS_PROBE1(fail1, int, rc); 576227569Sphilip 577227569Sphilip return (rc); 578227569Sphilip} 579227569Sphilip 580227569Sphilip#endif /* EFSYS_OPT_MON_STATS */ 581227569Sphilip 582227569Sphilip __checkReturn int 583227569Sphilipsiena_nic_probe( 584227569Sphilip __in efx_nic_t *enp) 585227569Sphilip{ 586227569Sphilip efx_port_t *epp = &(enp->en_port); 587227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 588227569Sphilip siena_link_state_t sls; 589227569Sphilip unsigned int mask; 590227569Sphilip int rc; 591227569Sphilip 592227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 593227569Sphilip 594227569Sphilip /* Read clear any assertion state */ 595227569Sphilip if ((rc = siena_nic_read_assertion(enp)) != 0) 596227569Sphilip goto fail1; 597227569Sphilip 598227569Sphilip /* Exit the assertion handler */ 599227569Sphilip if ((rc = siena_nic_exit_assertion_handler(enp)) != 0) 600227569Sphilip goto fail2; 601227569Sphilip 602227569Sphilip /* Wrestle control from the BMC */ 603227569Sphilip if ((rc = siena_nic_attach(enp, B_TRUE)) != 0) 604227569Sphilip goto fail3; 605227569Sphilip 606227569Sphilip if ((rc = siena_board_cfg(enp)) != 0) 607227569Sphilip goto fail4; 608227569Sphilip 609227569Sphilip encp->enc_evq_moderation_max = 610227569Sphilip EFX_EV_TIMER_QUANTUM << FRF_CZ_TIMER_VAL_WIDTH; 611227569Sphilip 612227569Sphilip if ((rc = siena_phy_cfg(enp)) != 0) 613227569Sphilip goto fail5; 614227569Sphilip 615227569Sphilip /* Obtain the default PHY advertised capabilities */ 616227569Sphilip if ((rc = siena_nic_reset(enp)) != 0) 617227569Sphilip goto fail6; 618227569Sphilip if ((rc = siena_phy_get_link(enp, &sls)) != 0) 619227569Sphilip goto fail7; 620227569Sphilip epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask; 621227569Sphilip epp->ep_adv_cap_mask = sls.sls_adv_cap_mask; 622227569Sphilip 623227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 624227569Sphilip if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0) 625227569Sphilip goto fail8; 626227569Sphilip enp->en_u.siena.enu_partn_mask = mask; 627227569Sphilip#endif 628227569Sphilip 629227569Sphilip#if EFSYS_OPT_MAC_STATS 630227569Sphilip /* Wipe the MAC statistics */ 631227569Sphilip if ((rc = siena_mac_stats_clear(enp)) != 0) 632227569Sphilip goto fail9; 633227569Sphilip#endif 634227569Sphilip 635227569Sphilip#if EFSYS_OPT_LOOPBACK 636227569Sphilip if ((rc = siena_loopback_cfg(enp)) != 0) 637227569Sphilip goto fail10; 638227569Sphilip#endif 639227569Sphilip 640227569Sphilip#if EFSYS_OPT_MON_STATS 641227569Sphilip if ((rc = siena_monitor_cfg(enp)) != 0) 642227569Sphilip goto fail11; 643227569Sphilip#endif 644227569Sphilip 645227569Sphilip encp->enc_features = enp->en_features; 646227569Sphilip 647227569Sphilip return (0); 648227569Sphilip 649227569Sphilip#if EFSYS_OPT_MON_STATS 650227569Sphilipfail11: 651227569Sphilip EFSYS_PROBE(fail11); 652227569Sphilip#endif 653227569Sphilip#if EFSYS_OPT_LOOPBACK 654227569Sphilipfail10: 655227569Sphilip EFSYS_PROBE(fail10); 656227569Sphilip#endif 657227569Sphilip#if EFSYS_OPT_MAC_STATS 658227569Sphilipfail9: 659227569Sphilip EFSYS_PROBE(fail9); 660227569Sphilip#endif 661227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 662227569Sphilipfail8: 663227569Sphilip EFSYS_PROBE(fail8); 664227569Sphilip#endif 665227569Sphilipfail7: 666227569Sphilip EFSYS_PROBE(fail7); 667227569Sphilipfail6: 668227569Sphilip EFSYS_PROBE(fail6); 669227569Sphilipfail5: 670227569Sphilip EFSYS_PROBE(fail5); 671227569Sphilipfail4: 672227569Sphilip EFSYS_PROBE(fail4); 673227569Sphilipfail3: 674227569Sphilip EFSYS_PROBE(fail3); 675227569Sphilipfail2: 676227569Sphilip EFSYS_PROBE(fail2); 677227569Sphilipfail1: 678227569Sphilip EFSYS_PROBE1(fail1, int, rc); 679227569Sphilip 680227569Sphilip return (rc); 681227569Sphilip} 682227569Sphilip 683227569Sphilip __checkReturn int 684227569Sphilipsiena_nic_reset( 685227569Sphilip __in efx_nic_t *enp) 686227569Sphilip{ 687227569Sphilip efx_mcdi_req_t req; 688227569Sphilip int rc; 689227569Sphilip 690227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 691227569Sphilip 692227569Sphilip /* siena_nic_reset() is called to recover from BADASSERT failures. */ 693227569Sphilip if ((rc = siena_nic_read_assertion(enp)) != 0) 694227569Sphilip goto fail1; 695227569Sphilip if ((rc = siena_nic_exit_assertion_handler(enp)) != 0) 696227569Sphilip goto fail2; 697227569Sphilip 698227569Sphilip req.emr_cmd = MC_CMD_PORT_RESET; 699227569Sphilip EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0); 700227569Sphilip req.emr_in_buf = NULL; 701227569Sphilip req.emr_in_length = 0; 702227569Sphilip EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0); 703227569Sphilip req.emr_out_buf = NULL; 704227569Sphilip req.emr_out_length = 0; 705227569Sphilip 706227569Sphilip efx_mcdi_execute(enp, &req); 707227569Sphilip 708227569Sphilip if (req.emr_rc != 0) { 709227569Sphilip rc = req.emr_rc; 710227569Sphilip goto fail3; 711227569Sphilip } 712227569Sphilip 713227569Sphilip return (0); 714227569Sphilip 715227569Sphilipfail3: 716227569Sphilip EFSYS_PROBE(fail3); 717227569Sphilipfail2: 718227569Sphilip EFSYS_PROBE(fail2); 719227569Sphilipfail1: 720227569Sphilip EFSYS_PROBE1(fail1, int, rc); 721227569Sphilip 722227569Sphilip return (0); 723227569Sphilip} 724227569Sphilip 725227569Sphilipstatic __checkReturn int 726227569Sphilipsiena_nic_logging( 727227569Sphilip __in efx_nic_t *enp) 728227569Sphilip{ 729227569Sphilip efx_mcdi_req_t req; 730227569Sphilip uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN]; 731227569Sphilip int rc; 732227569Sphilip 733227569Sphilip req.emr_cmd = MC_CMD_LOG_CTRL; 734227569Sphilip req.emr_in_buf = payload; 735227569Sphilip req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN; 736227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0); 737227569Sphilip req.emr_out_buf = NULL; 738227569Sphilip req.emr_out_length = 0; 739227569Sphilip 740227569Sphilip MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST, 741227569Sphilip MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ); 742227569Sphilip MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0); 743227569Sphilip 744227569Sphilip efx_mcdi_execute(enp, &req); 745227569Sphilip 746227569Sphilip if (req.emr_rc != 0) { 747227569Sphilip rc = req.emr_rc; 748227569Sphilip goto fail1; 749227569Sphilip } 750227569Sphilip 751227569Sphilip return (0); 752227569Sphilip 753227569Sphilipfail1: 754227569Sphilip EFSYS_PROBE1(fail1, int, rc); 755227569Sphilip 756227569Sphilip return (rc); 757227569Sphilip} 758227569Sphilip 759227569Sphilipstatic void 760227569Sphilipsiena_nic_rx_cfg( 761227569Sphilip __in efx_nic_t *enp) 762227569Sphilip{ 763227569Sphilip efx_oword_t oword; 764227569Sphilip 765227569Sphilip /* 766227569Sphilip * RX_INGR_EN is always enabled on Siena, because we rely on 767227569Sphilip * the RX parser to be resiliant to missing SOP/EOP. 768227569Sphilip */ 769227569Sphilip EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 770227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1); 771227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 772227569Sphilip 773227569Sphilip /* Disable parsing of additional 802.1Q in Q packets */ 774227569Sphilip EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 775227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0); 776227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 777227569Sphilip} 778227569Sphilip 779227569Sphilipstatic void 780227569Sphilipsiena_nic_usrev_dis( 781227569Sphilip __in efx_nic_t *enp) 782227569Sphilip{ 783227569Sphilip efx_oword_t oword; 784227569Sphilip 785227569Sphilip EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1); 786227569Sphilip EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword); 787227569Sphilip} 788227569Sphilip 789227569Sphilip __checkReturn int 790227569Sphilipsiena_nic_init( 791227569Sphilip __in efx_nic_t *enp) 792227569Sphilip{ 793227569Sphilip int rc; 794227569Sphilip 795227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 796227569Sphilip 797227569Sphilip if ((rc = siena_nic_logging(enp)) != 0) 798227569Sphilip goto fail1; 799227569Sphilip 800227569Sphilip siena_sram_init(enp); 801227569Sphilip 802227569Sphilip /* Configure Siena's RX block */ 803227569Sphilip siena_nic_rx_cfg(enp); 804227569Sphilip 805227569Sphilip /* Disable USR_EVents for now */ 806227569Sphilip siena_nic_usrev_dis(enp); 807227569Sphilip 808227569Sphilip /* bug17057: Ensure set_link is called */ 809227569Sphilip if ((rc = siena_phy_reconfigure(enp)) != 0) 810227569Sphilip goto fail2; 811227569Sphilip 812227569Sphilip return (0); 813227569Sphilip 814227569Sphilipfail2: 815227569Sphilip EFSYS_PROBE(fail2); 816227569Sphilipfail1: 817227569Sphilip EFSYS_PROBE1(fail1, int, rc); 818227569Sphilip 819227569Sphilip return (rc); 820227569Sphilip} 821227569Sphilip 822227569Sphilip void 823227569Sphilipsiena_nic_fini( 824227569Sphilip __in efx_nic_t *enp) 825227569Sphilip{ 826227569Sphilip _NOTE(ARGUNUSED(enp)) 827227569Sphilip} 828227569Sphilip 829227569Sphilip void 830227569Sphilipsiena_nic_unprobe( 831227569Sphilip __in efx_nic_t *enp) 832227569Sphilip{ 833227569Sphilip (void) siena_nic_attach(enp, B_FALSE); 834227569Sphilip} 835227569Sphilip 836227569Sphilip#if EFSYS_OPT_DIAG 837227569Sphilip 838227569Sphilipstatic efx_register_set_t __cs __siena_registers[] = { 839227569Sphilip { FR_AZ_ADR_REGION_REG_OFST, 0, 1 }, 840227569Sphilip { FR_CZ_USR_EV_CFG_OFST, 0, 1 }, 841227569Sphilip { FR_AZ_RX_CFG_REG_OFST, 0, 1 }, 842227569Sphilip { FR_AZ_TX_CFG_REG_OFST, 0, 1 }, 843227569Sphilip { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 }, 844227569Sphilip { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 }, 845227569Sphilip { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 }, 846227569Sphilip { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 }, 847227569Sphilip { FR_AZ_DP_CTRL_REG_OFST, 0, 1 }, 848227569Sphilip { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1}, 849227569Sphilip { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1}, 850227569Sphilip { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1}, 851227569Sphilip { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1} 852227569Sphilip}; 853227569Sphilip 854227569Sphilipstatic const uint32_t __cs __siena_register_masks[] = { 855227569Sphilip 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 856227569Sphilip 0x000103FF, 0x00000000, 0x00000000, 0x00000000, 857227569Sphilip 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000, 858227569Sphilip 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF, 859227569Sphilip 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF, 860227569Sphilip 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000, 861227569Sphilip 0x00000003, 0x00000000, 0x00000000, 0x00000000, 862227569Sphilip 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 863227569Sphilip 0x00000FFF, 0x00000000, 0x00000000, 0x00000000, 864227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 865227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 866227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 867227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000 868227569Sphilip}; 869227569Sphilip 870227569Sphilipstatic efx_register_set_t __cs __siena_tables[] = { 871227569Sphilip { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP, 872227569Sphilip FR_AZ_RX_FILTER_TBL0_ROWS }, 873227569Sphilip { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP, 874227569Sphilip FR_CZ_RX_MAC_FILTER_TBL0_ROWS }, 875227569Sphilip { FR_AZ_RX_DESC_PTR_TBL_OFST, 876227569Sphilip FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS }, 877227569Sphilip { FR_AZ_TX_DESC_PTR_TBL_OFST, 878227569Sphilip FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS }, 879227569Sphilip { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS }, 880227569Sphilip { FR_CZ_TX_FILTER_TBL0_OFST, 881227569Sphilip FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS }, 882227569Sphilip { FR_CZ_TX_MAC_FILTER_TBL0_OFST, 883227569Sphilip FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS } 884227569Sphilip}; 885227569Sphilip 886227569Sphilipstatic const uint32_t __cs __siena_table_masks[] = { 887227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF, 888227569Sphilip 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000, 889227569Sphilip 0xFFFFFFFF, 0x0FFFFFFF, 0x01800000, 0x00000000, 890227569Sphilip 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000, 891227569Sphilip 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000, 892227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF, 893227569Sphilip 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000, 894227569Sphilip}; 895227569Sphilip 896227569Sphilip __checkReturn int 897227569Sphilipsiena_nic_register_test( 898227569Sphilip __in efx_nic_t *enp) 899227569Sphilip{ 900227569Sphilip efx_register_set_t *rsp; 901227569Sphilip const uint32_t *dwordp; 902227569Sphilip unsigned int nitems; 903227569Sphilip unsigned int count; 904227569Sphilip int rc; 905227569Sphilip 906227569Sphilip /* Fill out the register mask entries */ 907227569Sphilip EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks) 908227569Sphilip == EFX_ARRAY_SIZE(__siena_registers) * 4); 909227569Sphilip 910227569Sphilip nitems = EFX_ARRAY_SIZE(__siena_registers); 911227569Sphilip dwordp = __siena_register_masks; 912227569Sphilip for (count = 0; count < nitems; ++count) { 913227569Sphilip rsp = __siena_registers + count; 914227569Sphilip rsp->mask.eo_u32[0] = *dwordp++; 915227569Sphilip rsp->mask.eo_u32[1] = *dwordp++; 916227569Sphilip rsp->mask.eo_u32[2] = *dwordp++; 917227569Sphilip rsp->mask.eo_u32[3] = *dwordp++; 918227569Sphilip } 919227569Sphilip 920227569Sphilip /* Fill out the register table entries */ 921227569Sphilip EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks) 922227569Sphilip == EFX_ARRAY_SIZE(__siena_tables) * 4); 923227569Sphilip 924227569Sphilip nitems = EFX_ARRAY_SIZE(__siena_tables); 925227569Sphilip dwordp = __siena_table_masks; 926227569Sphilip for (count = 0; count < nitems; ++count) { 927227569Sphilip rsp = __siena_tables + count; 928227569Sphilip rsp->mask.eo_u32[0] = *dwordp++; 929227569Sphilip rsp->mask.eo_u32[1] = *dwordp++; 930227569Sphilip rsp->mask.eo_u32[2] = *dwordp++; 931227569Sphilip rsp->mask.eo_u32[3] = *dwordp++; 932227569Sphilip } 933227569Sphilip 934227569Sphilip if ((rc = efx_nic_test_registers(enp, __siena_registers, 935227569Sphilip EFX_ARRAY_SIZE(__siena_registers))) != 0) 936227569Sphilip goto fail1; 937227569Sphilip 938227569Sphilip if ((rc = efx_nic_test_tables(enp, __siena_tables, 939227569Sphilip EFX_PATTERN_BYTE_ALTERNATE, 940227569Sphilip EFX_ARRAY_SIZE(__siena_tables))) != 0) 941227569Sphilip goto fail2; 942227569Sphilip 943227569Sphilip if ((rc = efx_nic_test_tables(enp, __siena_tables, 944227569Sphilip EFX_PATTERN_BYTE_CHANGING, 945227569Sphilip EFX_ARRAY_SIZE(__siena_tables))) != 0) 946227569Sphilip goto fail3; 947227569Sphilip 948227569Sphilip if ((rc = efx_nic_test_tables(enp, __siena_tables, 949227569Sphilip EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0) 950227569Sphilip goto fail4; 951227569Sphilip 952227569Sphilip return (0); 953227569Sphilip 954227569Sphilipfail4: 955227569Sphilip EFSYS_PROBE(fail4); 956227569Sphilipfail3: 957227569Sphilip EFSYS_PROBE(fail3); 958227569Sphilipfail2: 959227569Sphilip EFSYS_PROBE(fail2); 960227569Sphilipfail1: 961227569Sphilip EFSYS_PROBE1(fail1, int, rc); 962227569Sphilip 963227569Sphilip return (rc); 964227569Sphilip} 965227569Sphilip 966227569Sphilip#endif /* EFSYS_OPT_DIAG */ 967227569Sphilip 968227569Sphilip#endif /* EFSYS_OPT_SIENA */ 969