1227569Sphilip/*- 2227569Sphilip * Copyright 2007-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_regs.h" 33227569Sphilip#include "efx_impl.h" 34227569Sphilip 35227569Sphilip __checkReturn int 36227569Sphilipefx_sram_buf_tbl_set( 37227569Sphilip __in efx_nic_t *enp, 38227569Sphilip __in uint32_t id, 39227569Sphilip __in efsys_mem_t *esmp, 40227569Sphilip __in size_t n) 41227569Sphilip{ 42227569Sphilip efx_qword_t qword; 43227569Sphilip uint32_t start = id; 44227569Sphilip uint32_t stop = start + n; 45227569Sphilip efsys_dma_addr_t addr; 46227569Sphilip efx_oword_t oword; 47227569Sphilip unsigned int count; 48227569Sphilip int rc; 49227569Sphilip 50227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 51227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 52227569Sphilip 53227569Sphilip if (stop >= EFX_BUF_TBL_SIZE) { 54227569Sphilip rc = EFBIG; 55227569Sphilip goto fail1; 56227569Sphilip } 57227569Sphilip 58227569Sphilip /* Add the entries into the buffer table */ 59227569Sphilip addr = EFSYS_MEM_ADDR(esmp); 60227569Sphilip for (id = start; id != stop; id++) { 61227569Sphilip EFX_POPULATE_QWORD_5(qword, 62227569Sphilip FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0, 63227569Sphilip FRF_AZ_BUF_ADR_FBUF_DW0, 64227569Sphilip (uint32_t)((addr >> 12) & 0xffffffff), 65227569Sphilip FRF_AZ_BUF_ADR_FBUF_DW1, 66227569Sphilip (uint32_t)((addr >> 12) >> 32), 67227569Sphilip FRF_AZ_BUF_OWNER_ID_FBUF, 0); 68227569Sphilip 69227569Sphilip EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL, 70227569Sphilip id, &qword); 71227569Sphilip 72227569Sphilip addr += EFX_BUF_SIZE; 73227569Sphilip } 74227569Sphilip 75227569Sphilip EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 76227569Sphilip 77227569Sphilip /* Flush the write buffer */ 78227569Sphilip EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1, 79227569Sphilip FRF_AZ_BUF_CLR_CMD, 0); 80227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 81227569Sphilip 82227569Sphilip /* Poll for the last entry being written to the buffer table */ 83227569Sphilip EFSYS_ASSERT3U(id, ==, stop); 84227569Sphilip addr -= EFX_BUF_SIZE; 85227569Sphilip 86227569Sphilip count = 0; 87227569Sphilip do { 88227569Sphilip EFSYS_PROBE1(wait, unsigned int, count); 89227569Sphilip 90227569Sphilip /* Spin for 1 ms */ 91227569Sphilip EFSYS_SPIN(1000); 92227569Sphilip 93227569Sphilip EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL, 94227569Sphilip id - 1, &qword); 95227569Sphilip 96227569Sphilip if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) == 97227569Sphilip (uint32_t)((addr >> 12) & 0xffffffff) && 98227569Sphilip EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) == 99227569Sphilip (uint32_t)((addr >> 12) >> 32)) 100227569Sphilip goto verify; 101227569Sphilip 102227569Sphilip } while (++count < 100); 103227569Sphilip 104227569Sphilip rc = ETIMEDOUT; 105227569Sphilip goto fail2; 106227569Sphilip 107227569Sphilipverify: 108227569Sphilip /* Verify the rest of the entries in the buffer table */ 109227569Sphilip while (--id != start) { 110227569Sphilip addr -= EFX_BUF_SIZE; 111227569Sphilip 112227569Sphilip /* Read the buffer table entry */ 113227569Sphilip EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL, 114227569Sphilip id - 1, &qword); 115227569Sphilip 116227569Sphilip if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) != 117227569Sphilip (uint32_t)((addr >> 12) & 0xffffffff) || 118227569Sphilip EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) != 119227569Sphilip (uint32_t)((addr >> 12) >> 32)) { 120227569Sphilip rc = EFAULT; 121227569Sphilip goto fail3; 122227569Sphilip } 123227569Sphilip } 124227569Sphilip 125227569Sphilip return (0); 126227569Sphilip 127227569Sphilipfail3: 128227569Sphilip EFSYS_PROBE(fail3); 129227569Sphilip 130227569Sphilip id = stop; 131227569Sphilip 132227569Sphilipfail2: 133227569Sphilip EFSYS_PROBE(fail2); 134227569Sphilip 135227569Sphilip EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 136227569Sphilip FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1, 137227569Sphilip FRF_AZ_BUF_CLR_START_ID, start); 138227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 139227569Sphilip 140227569Sphilipfail1: 141227569Sphilip EFSYS_PROBE1(fail1, int, rc); 142227569Sphilip 143227569Sphilip return (rc); 144227569Sphilip} 145227569Sphilip 146227569Sphilip void 147227569Sphilipefx_sram_buf_tbl_clear( 148227569Sphilip __in efx_nic_t *enp, 149227569Sphilip __in uint32_t id, 150227569Sphilip __in size_t n) 151227569Sphilip{ 152227569Sphilip efx_oword_t oword; 153227569Sphilip uint32_t start = id; 154227569Sphilip uint32_t stop = start + n; 155227569Sphilip 156227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 157227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 158227569Sphilip 159227569Sphilip EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE); 160227569Sphilip 161227569Sphilip EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 162227569Sphilip 163227569Sphilip EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 164227569Sphilip FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1, 165227569Sphilip FRF_AZ_BUF_CLR_START_ID, start); 166227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 167227569Sphilip} 168227569Sphilip 169227569Sphilip 170227569Sphilip#if EFSYS_OPT_DIAG 171227569Sphilip 172227569Sphilipstatic void 173227569Sphilipefx_sram_byte_increment_set( 174227569Sphilip __in size_t row, 175227569Sphilip __in boolean_t negate, 176227569Sphilip __out efx_qword_t *eqp) 177227569Sphilip{ 178227569Sphilip size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 179227569Sphilip unsigned int index; 180227569Sphilip 181227569Sphilip _NOTE(ARGUNUSED(negate)) 182227569Sphilip 183227569Sphilip for (index = 0; index < sizeof (efx_qword_t); index++) 184227569Sphilip eqp->eq_u8[index] = offset + index; 185227569Sphilip} 186227569Sphilip 187227569Sphilipstatic void 188227569Sphilipefx_sram_all_the_same_set( 189227569Sphilip __in size_t row, 190227569Sphilip __in boolean_t negate, 191227569Sphilip __out efx_qword_t *eqp) 192227569Sphilip{ 193227569Sphilip _NOTE(ARGUNUSED(row)) 194227569Sphilip 195227569Sphilip if (negate) 196227569Sphilip EFX_SET_QWORD(*eqp); 197227569Sphilip else 198227569Sphilip EFX_ZERO_QWORD(*eqp); 199227569Sphilip} 200227569Sphilip 201227569Sphilipstatic void 202227569Sphilipefx_sram_bit_alternate_set( 203227569Sphilip __in size_t row, 204227569Sphilip __in boolean_t negate, 205227569Sphilip __out efx_qword_t *eqp) 206227569Sphilip{ 207227569Sphilip _NOTE(ARGUNUSED(row)) 208227569Sphilip 209227569Sphilip EFX_POPULATE_QWORD_2(*eqp, 210227569Sphilip EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa, 211227569Sphilip EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa); 212227569Sphilip} 213227569Sphilip 214227569Sphilipstatic void 215227569Sphilipefx_sram_byte_alternate_set( 216227569Sphilip __in size_t row, 217227569Sphilip __in boolean_t negate, 218227569Sphilip __out efx_qword_t *eqp) 219227569Sphilip{ 220227569Sphilip _NOTE(ARGUNUSED(row)) 221227569Sphilip 222227569Sphilip EFX_POPULATE_QWORD_2(*eqp, 223227569Sphilip EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00, 224227569Sphilip EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00); 225227569Sphilip} 226227569Sphilip 227227569Sphilipstatic void 228227569Sphilipefx_sram_byte_changing_set( 229227569Sphilip __in size_t row, 230227569Sphilip __in boolean_t negate, 231227569Sphilip __out efx_qword_t *eqp) 232227569Sphilip{ 233227569Sphilip size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 234227569Sphilip unsigned int index; 235227569Sphilip 236227569Sphilip for (index = 0; index < sizeof (efx_qword_t); index++) { 237227569Sphilip uint8_t byte; 238227569Sphilip 239227569Sphilip if (offset / 256 == 0) 240227569Sphilip byte = (uint8_t)((offset % 257) % 256); 241227569Sphilip else 242227569Sphilip byte = (uint8_t)(~((offset - 8) % 257) % 256); 243227569Sphilip 244227569Sphilip eqp->eq_u8[index] = (negate) ? ~byte : byte; 245227569Sphilip } 246227569Sphilip} 247227569Sphilip 248227569Sphilipstatic void 249227569Sphilipefx_sram_bit_sweep_set( 250227569Sphilip __in size_t row, 251227569Sphilip __in boolean_t negate, 252227569Sphilip __out efx_qword_t *eqp) 253227569Sphilip{ 254227569Sphilip size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 255227569Sphilip 256227569Sphilip if (negate) { 257227569Sphilip EFX_SET_QWORD(*eqp); 258227569Sphilip EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 259227569Sphilip } else { 260227569Sphilip EFX_ZERO_QWORD(*eqp); 261227569Sphilip EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 262227569Sphilip } 263227569Sphilip} 264227569Sphilip 265227569Sphilipefx_sram_pattern_fn_t __cs __efx_sram_pattern_fns[] = { 266227569Sphilip efx_sram_byte_increment_set, 267227569Sphilip efx_sram_all_the_same_set, 268227569Sphilip efx_sram_bit_alternate_set, 269227569Sphilip efx_sram_byte_alternate_set, 270227569Sphilip efx_sram_byte_changing_set, 271227569Sphilip efx_sram_bit_sweep_set 272227569Sphilip}; 273227569Sphilip 274227569Sphilip __checkReturn int 275227569Sphilipefx_sram_test( 276227569Sphilip __in efx_nic_t *enp, 277227569Sphilip __in efx_pattern_type_t type) 278227569Sphilip{ 279227569Sphilip efx_nic_ops_t *enop = enp->en_enop; 280227569Sphilip efx_sram_pattern_fn_t func; 281227569Sphilip 282227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 283227569Sphilip 284227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 285227569Sphilip 286227569Sphilip EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 287227569Sphilip EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 288227569Sphilip EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 289227569Sphilip 290227569Sphilip /* Select pattern generator */ 291227569Sphilip EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES); 292227569Sphilip func = __efx_sram_pattern_fns[type]; 293227569Sphilip 294227569Sphilip return (enop->eno_sram_test(enp, func)); 295227569Sphilip} 296227569Sphilip 297227569Sphilip#endif /* EFSYS_OPT_DIAG */ 298