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 26228100Sphilip#include <sys/cdefs.h> 27228100Sphilip__FBSDID("$FreeBSD$"); 28228100Sphilip 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#if EFSYS_OPT_NVRAM 36227569Sphilip 37227569Sphilip#if EFSYS_OPT_FALCON 38227569Sphilip 39227569Sphilipstatic efx_nvram_ops_t __cs __efx_nvram_falcon_ops = { 40227569Sphilip#if EFSYS_OPT_DIAG 41227569Sphilip falcon_nvram_test, /* envo_test */ 42227569Sphilip#endif /* EFSYS_OPT_DIAG */ 43227569Sphilip falcon_nvram_size, /* envo_size */ 44227569Sphilip falcon_nvram_get_version, /* envo_get_version */ 45227569Sphilip falcon_nvram_rw_start, /* envo_rw_start */ 46227569Sphilip falcon_nvram_read_chunk, /* envo_read_chunk */ 47227569Sphilip falcon_nvram_erase, /* envo_erase */ 48227569Sphilip falcon_nvram_write_chunk, /* envo_write_chunk */ 49227569Sphilip falcon_nvram_rw_finish, /* envo_rw_finish */ 50227569Sphilip falcon_nvram_set_version, /* envo_set_version */ 51227569Sphilip}; 52227569Sphilip 53227569Sphilip#endif /* EFSYS_OPT_FALCON */ 54227569Sphilip 55227569Sphilip#if EFSYS_OPT_SIENA 56227569Sphilip 57227569Sphilipstatic efx_nvram_ops_t __cs __efx_nvram_siena_ops = { 58227569Sphilip#if EFSYS_OPT_DIAG 59227569Sphilip siena_nvram_test, /* envo_test */ 60227569Sphilip#endif /* EFSYS_OPT_DIAG */ 61227569Sphilip siena_nvram_size, /* envo_size */ 62227569Sphilip siena_nvram_get_version, /* envo_get_version */ 63227569Sphilip siena_nvram_rw_start, /* envo_rw_start */ 64227569Sphilip siena_nvram_read_chunk, /* envo_read_chunk */ 65227569Sphilip siena_nvram_erase, /* envo_erase */ 66227569Sphilip siena_nvram_write_chunk, /* envo_write_chunk */ 67227569Sphilip siena_nvram_rw_finish, /* envo_rw_finish */ 68227569Sphilip siena_nvram_set_version, /* envo_set_version */ 69227569Sphilip}; 70227569Sphilip 71227569Sphilip#endif /* EFSYS_OPT_SIENA */ 72227569Sphilip 73227569Sphilip __checkReturn int 74227569Sphilipefx_nvram_init( 75227569Sphilip __in efx_nic_t *enp) 76227569Sphilip{ 77227569Sphilip efx_nvram_ops_t *envop; 78227569Sphilip int rc; 79227569Sphilip 80227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 81227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 82227569Sphilip EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM)); 83227569Sphilip 84227569Sphilip switch (enp->en_family) { 85227569Sphilip#if EFSYS_OPT_FALCON 86227569Sphilip case EFX_FAMILY_FALCON: 87227569Sphilip envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops; 88227569Sphilip break; 89227569Sphilip#endif /* EFSYS_OPT_FALCON */ 90227569Sphilip 91227569Sphilip#if EFSYS_OPT_SIENA 92227569Sphilip case EFX_FAMILY_SIENA: 93227569Sphilip envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops; 94227569Sphilip break; 95227569Sphilip#endif /* EFSYS_OPT_SIENA */ 96227569Sphilip 97227569Sphilip default: 98227569Sphilip EFSYS_ASSERT(0); 99227569Sphilip rc = ENOTSUP; 100227569Sphilip goto fail1; 101227569Sphilip } 102227569Sphilip 103227569Sphilip enp->en_envop = envop; 104227569Sphilip enp->en_mod_flags |= EFX_MOD_NVRAM; 105227569Sphilip 106227569Sphilip return (0); 107227569Sphilip 108227569Sphilipfail1: 109227569Sphilip EFSYS_PROBE1(fail1, int, rc); 110227569Sphilip 111227569Sphilip return (rc); 112227569Sphilip} 113227569Sphilip 114227569Sphilip#if EFSYS_OPT_DIAG 115227569Sphilip 116227569Sphilip __checkReturn int 117227569Sphilipefx_nvram_test( 118227569Sphilip __in efx_nic_t *enp) 119227569Sphilip{ 120227569Sphilip efx_nvram_ops_t *envop = enp->en_envop; 121227569Sphilip int rc; 122227569Sphilip 123227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 124227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 125227569Sphilip 126227569Sphilip if ((rc = envop->envo_test(enp)) != 0) 127227569Sphilip goto fail1; 128227569Sphilip 129227569Sphilip return (0); 130227569Sphilip 131227569Sphilipfail1: 132227569Sphilip EFSYS_PROBE1(fail1, int, rc); 133227569Sphilip 134227569Sphilip return (rc); 135227569Sphilip} 136227569Sphilip 137227569Sphilip#endif /* EFSYS_OPT_DIAG */ 138227569Sphilip 139227569Sphilip __checkReturn int 140227569Sphilipefx_nvram_size( 141227569Sphilip __in efx_nic_t *enp, 142227569Sphilip __in efx_nvram_type_t type, 143227569Sphilip __out size_t *sizep) 144227569Sphilip{ 145227569Sphilip efx_nvram_ops_t *envop = enp->en_envop; 146227569Sphilip int rc; 147227569Sphilip 148227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 149227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 150227569Sphilip 151227569Sphilip EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 152227569Sphilip 153227569Sphilip if ((rc = envop->envo_size(enp, type, sizep)) != 0) 154227569Sphilip goto fail1; 155227569Sphilip 156227569Sphilip return (0); 157227569Sphilip 158227569Sphilipfail1: 159227569Sphilip EFSYS_PROBE1(fail1, int, rc); 160227569Sphilip 161227569Sphilip return (rc); 162227569Sphilip} 163227569Sphilip 164227569Sphilip __checkReturn int 165227569Sphilipefx_nvram_get_version( 166227569Sphilip __in efx_nic_t *enp, 167227569Sphilip __in efx_nvram_type_t type, 168227569Sphilip __out uint32_t *subtypep, 169227569Sphilip __out_ecount(4) uint16_t version[4]) 170227569Sphilip{ 171227569Sphilip efx_nvram_ops_t *envop = enp->en_envop; 172227569Sphilip int rc; 173227569Sphilip 174227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 175227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 176227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 177227569Sphilip 178227569Sphilip EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 179227569Sphilip 180227569Sphilip if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0) 181227569Sphilip goto fail1; 182227569Sphilip 183227569Sphilip return (0); 184227569Sphilip 185227569Sphilipfail1: 186227569Sphilip EFSYS_PROBE1(fail1, int, rc); 187227569Sphilip 188227569Sphilip return (rc); 189227569Sphilip} 190227569Sphilip 191227569Sphilip __checkReturn int 192227569Sphilipefx_nvram_rw_start( 193227569Sphilip __in efx_nic_t *enp, 194227569Sphilip __in efx_nvram_type_t type, 195227569Sphilip __out_opt size_t *chunk_sizep) 196227569Sphilip{ 197227569Sphilip efx_nvram_ops_t *envop = enp->en_envop; 198227569Sphilip int rc; 199227569Sphilip 200227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 201227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 202227569Sphilip 203227569Sphilip EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 204227569Sphilip EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 205227569Sphilip 206227569Sphilip EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 207227569Sphilip 208227569Sphilip if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0) 209227569Sphilip goto fail1; 210227569Sphilip 211227569Sphilip enp->en_nvram_locked = type; 212227569Sphilip 213227569Sphilip return (0); 214227569Sphilip 215227569Sphilipfail1: 216227569Sphilip EFSYS_PROBE1(fail1, int, rc); 217227569Sphilip 218227569Sphilip return (rc); 219227569Sphilip} 220227569Sphilip 221227569Sphilip __checkReturn int 222227569Sphilipefx_nvram_read_chunk( 223227569Sphilip __in efx_nic_t *enp, 224227569Sphilip __in efx_nvram_type_t type, 225227569Sphilip __in unsigned int offset, 226227569Sphilip __out_bcount(size) caddr_t data, 227227569Sphilip __in size_t size) 228227569Sphilip{ 229227569Sphilip efx_nvram_ops_t *envop = enp->en_envop; 230227569Sphilip int rc; 231227569Sphilip 232227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 233227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 234227569Sphilip 235227569Sphilip EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 236227569Sphilip EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 237227569Sphilip 238227569Sphilip EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 239227569Sphilip 240227569Sphilip if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0) 241227569Sphilip goto fail1; 242227569Sphilip 243227569Sphilip return (0); 244227569Sphilip 245227569Sphilipfail1: 246227569Sphilip EFSYS_PROBE1(fail1, int, rc); 247227569Sphilip 248227569Sphilip return (rc); 249227569Sphilip} 250227569Sphilip 251227569Sphilip __checkReturn int 252227569Sphilipefx_nvram_erase( 253227569Sphilip __in efx_nic_t *enp, 254227569Sphilip __in efx_nvram_type_t type) 255227569Sphilip{ 256227569Sphilip efx_nvram_ops_t *envop = enp->en_envop; 257227569Sphilip int rc; 258227569Sphilip 259227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 260227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 261227569Sphilip 262227569Sphilip EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 263227569Sphilip EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 264227569Sphilip 265227569Sphilip EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 266227569Sphilip 267227569Sphilip if ((rc = envop->envo_erase(enp, type)) != 0) 268227569Sphilip goto fail1; 269227569Sphilip 270227569Sphilip return (0); 271227569Sphilip 272227569Sphilipfail1: 273227569Sphilip EFSYS_PROBE1(fail1, int, rc); 274227569Sphilip 275227569Sphilip return (rc); 276227569Sphilip} 277227569Sphilip 278227569Sphilip __checkReturn int 279227569Sphilipefx_nvram_write_chunk( 280227569Sphilip __in efx_nic_t *enp, 281227569Sphilip __in efx_nvram_type_t type, 282227569Sphilip __in unsigned int offset, 283227569Sphilip __in_bcount(size) caddr_t data, 284227569Sphilip __in size_t size) 285227569Sphilip{ 286227569Sphilip efx_nvram_ops_t *envop = enp->en_envop; 287227569Sphilip int rc; 288227569Sphilip 289227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 290227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 291227569Sphilip 292227569Sphilip EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 293227569Sphilip EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 294227569Sphilip 295227569Sphilip EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 296227569Sphilip 297227569Sphilip if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0) 298227569Sphilip goto fail1; 299227569Sphilip 300227569Sphilip return (0); 301227569Sphilip 302227569Sphilipfail1: 303227569Sphilip EFSYS_PROBE1(fail1, int, rc); 304227569Sphilip 305227569Sphilip return (rc); 306227569Sphilip} 307227569Sphilip 308227569Sphilip void 309227569Sphilipefx_nvram_rw_finish( 310227569Sphilip __in efx_nic_t *enp, 311227569Sphilip __in efx_nvram_type_t type) 312227569Sphilip{ 313227569Sphilip efx_nvram_ops_t *envop = enp->en_envop; 314227569Sphilip 315227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 316227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 317227569Sphilip 318227569Sphilip EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 319227569Sphilip EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 320227569Sphilip 321227569Sphilip EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 322227569Sphilip 323227569Sphilip envop->envo_rw_finish(enp, type); 324227569Sphilip 325227569Sphilip enp->en_nvram_locked = EFX_NVRAM_INVALID; 326227569Sphilip} 327227569Sphilip 328227569Sphilip __checkReturn int 329227569Sphilipefx_nvram_set_version( 330227569Sphilip __in efx_nic_t *enp, 331227569Sphilip __in efx_nvram_type_t type, 332227569Sphilip __out uint16_t version[4]) 333227569Sphilip{ 334227569Sphilip efx_nvram_ops_t *envop = enp->en_envop; 335227569Sphilip int rc; 336227569Sphilip 337227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 338227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 339227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 340227569Sphilip 341227569Sphilip EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 342227569Sphilip 343227569Sphilip /* 344227569Sphilip * The Siena implementation of envo_set_version() will attempt to 345227569Sphilip * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector. 346227569Sphilip * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 347227569Sphilip */ 348227569Sphilip EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 349227569Sphilip 350227569Sphilip if ((rc = envop->envo_set_version(enp, type, version)) != 0) 351227569Sphilip goto fail1; 352227569Sphilip 353227569Sphilip return (0); 354227569Sphilip 355227569Sphilipfail1: 356227569Sphilip EFSYS_PROBE1(fail1, int, rc); 357227569Sphilip 358227569Sphilip return (rc); 359227569Sphilip} 360227569Sphilip 361227569Sphilipvoid 362227569Sphilipefx_nvram_fini( 363227569Sphilip __in efx_nic_t *enp) 364227569Sphilip{ 365227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 366227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 367227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 368227569Sphilip 369227569Sphilip EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 370227569Sphilip 371227569Sphilip enp->en_envop = NULL; 372227569Sphilip enp->en_mod_flags &= ~EFX_MOD_NVRAM; 373227569Sphilip} 374227569Sphilip 375227569Sphilip#endif /* EFSYS_OPT_NVRAM */ 376