1e948693eSPhilip Paeps /*- 23c838a9fSAndrew Rybchenko * Copyright (c) 2009-2015 Solarflare Communications Inc. 33c838a9fSAndrew Rybchenko * All rights reserved. 4e948693eSPhilip Paeps * 5e948693eSPhilip Paeps * Redistribution and use in source and binary forms, with or without 63c838a9fSAndrew Rybchenko * modification, are permitted provided that the following conditions are met: 7e948693eSPhilip Paeps * 83c838a9fSAndrew Rybchenko * 1. Redistributions of source code must retain the above copyright notice, 93c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer. 103c838a9fSAndrew Rybchenko * 2. Redistributions in binary form must reproduce the above copyright notice, 113c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer in the documentation 123c838a9fSAndrew Rybchenko * and/or other materials provided with the distribution. 133c838a9fSAndrew Rybchenko * 143c838a9fSAndrew Rybchenko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 153c838a9fSAndrew Rybchenko * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 163c838a9fSAndrew Rybchenko * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 173c838a9fSAndrew Rybchenko * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 183c838a9fSAndrew Rybchenko * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 193c838a9fSAndrew Rybchenko * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 203c838a9fSAndrew Rybchenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 213c838a9fSAndrew Rybchenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 223c838a9fSAndrew Rybchenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 233c838a9fSAndrew Rybchenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 243c838a9fSAndrew Rybchenko * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 253c838a9fSAndrew Rybchenko * 263c838a9fSAndrew Rybchenko * The views and conclusions contained in the software and documentation are 273c838a9fSAndrew Rybchenko * those of the authors and should not be interpreted as representing official 283c838a9fSAndrew Rybchenko * policies, either expressed or implied, of the FreeBSD Project. 29e948693eSPhilip Paeps */ 30e948693eSPhilip Paeps 315dee87d7SPhilip Paeps #include <sys/cdefs.h> 325dee87d7SPhilip Paeps __FBSDID("$FreeBSD$"); 335dee87d7SPhilip Paeps 34e948693eSPhilip Paeps #include "efsys.h" 35e948693eSPhilip Paeps #include "efx.h" 36e948693eSPhilip Paeps #include "efx_types.h" 37e948693eSPhilip Paeps #include "efx_regs.h" 38e948693eSPhilip Paeps #include "efx_impl.h" 39e948693eSPhilip Paeps 40e948693eSPhilip Paeps #if EFSYS_OPT_NVRAM 41e948693eSPhilip Paeps 42e948693eSPhilip Paeps #if EFSYS_OPT_FALCON 43e948693eSPhilip Paeps 443c838a9fSAndrew Rybchenko static efx_nvram_ops_t __efx_nvram_falcon_ops = { 45e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 46e948693eSPhilip Paeps falcon_nvram_test, /* envo_test */ 47e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 48e948693eSPhilip Paeps falcon_nvram_size, /* envo_size */ 49e948693eSPhilip Paeps falcon_nvram_get_version, /* envo_get_version */ 50e948693eSPhilip Paeps falcon_nvram_rw_start, /* envo_rw_start */ 51e948693eSPhilip Paeps falcon_nvram_read_chunk, /* envo_read_chunk */ 52e948693eSPhilip Paeps falcon_nvram_erase, /* envo_erase */ 53e948693eSPhilip Paeps falcon_nvram_write_chunk, /* envo_write_chunk */ 54e948693eSPhilip Paeps falcon_nvram_rw_finish, /* envo_rw_finish */ 55e948693eSPhilip Paeps falcon_nvram_set_version, /* envo_set_version */ 56e948693eSPhilip Paeps }; 57e948693eSPhilip Paeps 58e948693eSPhilip Paeps #endif /* EFSYS_OPT_FALCON */ 59e948693eSPhilip Paeps 60e948693eSPhilip Paeps #if EFSYS_OPT_SIENA 61e948693eSPhilip Paeps 623c838a9fSAndrew Rybchenko static efx_nvram_ops_t __efx_nvram_siena_ops = { 63e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 64e948693eSPhilip Paeps siena_nvram_test, /* envo_test */ 65e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 66e948693eSPhilip Paeps siena_nvram_size, /* envo_size */ 67e948693eSPhilip Paeps siena_nvram_get_version, /* envo_get_version */ 68e948693eSPhilip Paeps siena_nvram_rw_start, /* envo_rw_start */ 69e948693eSPhilip Paeps siena_nvram_read_chunk, /* envo_read_chunk */ 70e948693eSPhilip Paeps siena_nvram_erase, /* envo_erase */ 71e948693eSPhilip Paeps siena_nvram_write_chunk, /* envo_write_chunk */ 72e948693eSPhilip Paeps siena_nvram_rw_finish, /* envo_rw_finish */ 73e948693eSPhilip Paeps siena_nvram_set_version, /* envo_set_version */ 74e948693eSPhilip Paeps }; 75e948693eSPhilip Paeps 76e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 77e948693eSPhilip Paeps 783c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON 793c838a9fSAndrew Rybchenko 803c838a9fSAndrew Rybchenko static efx_nvram_ops_t __efx_nvram_hunt_ops = { 813c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG 823c838a9fSAndrew Rybchenko hunt_nvram_test, /* envo_test */ 833c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 843c838a9fSAndrew Rybchenko hunt_nvram_size, /* envo_size */ 853c838a9fSAndrew Rybchenko hunt_nvram_get_version, /* envo_get_version */ 863c838a9fSAndrew Rybchenko hunt_nvram_rw_start, /* envo_rw_start */ 873c838a9fSAndrew Rybchenko hunt_nvram_read_chunk, /* envo_read_chunk */ 883c838a9fSAndrew Rybchenko hunt_nvram_erase, /* envo_erase */ 893c838a9fSAndrew Rybchenko hunt_nvram_write_chunk, /* envo_write_chunk */ 903c838a9fSAndrew Rybchenko hunt_nvram_rw_finish, /* envo_rw_finish */ 913c838a9fSAndrew Rybchenko hunt_nvram_set_version, /* envo_set_version */ 923c838a9fSAndrew Rybchenko }; 933c838a9fSAndrew Rybchenko 943c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */ 953c838a9fSAndrew Rybchenko 96*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 97e948693eSPhilip Paeps efx_nvram_init( 98e948693eSPhilip Paeps __in efx_nic_t *enp) 99e948693eSPhilip Paeps { 100e948693eSPhilip Paeps efx_nvram_ops_t *envop; 101*460cb568SAndrew Rybchenko efx_rc_t rc; 102e948693eSPhilip Paeps 103e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 104e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 105e948693eSPhilip Paeps EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM)); 106e948693eSPhilip Paeps 107e948693eSPhilip Paeps switch (enp->en_family) { 108e948693eSPhilip Paeps #if EFSYS_OPT_FALCON 109e948693eSPhilip Paeps case EFX_FAMILY_FALCON: 110e948693eSPhilip Paeps envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops; 111e948693eSPhilip Paeps break; 112e948693eSPhilip Paeps #endif /* EFSYS_OPT_FALCON */ 113e948693eSPhilip Paeps 114e948693eSPhilip Paeps #if EFSYS_OPT_SIENA 115e948693eSPhilip Paeps case EFX_FAMILY_SIENA: 116e948693eSPhilip Paeps envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops; 117e948693eSPhilip Paeps break; 118e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 119e948693eSPhilip Paeps 1203c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON 1213c838a9fSAndrew Rybchenko case EFX_FAMILY_HUNTINGTON: 1223c838a9fSAndrew Rybchenko envop = (efx_nvram_ops_t *)&__efx_nvram_hunt_ops; 1233c838a9fSAndrew Rybchenko break; 1243c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */ 1253c838a9fSAndrew Rybchenko 126e948693eSPhilip Paeps default: 127e948693eSPhilip Paeps EFSYS_ASSERT(0); 128e948693eSPhilip Paeps rc = ENOTSUP; 129e948693eSPhilip Paeps goto fail1; 130e948693eSPhilip Paeps } 131e948693eSPhilip Paeps 132e948693eSPhilip Paeps enp->en_envop = envop; 133e948693eSPhilip Paeps enp->en_mod_flags |= EFX_MOD_NVRAM; 134e948693eSPhilip Paeps 135e948693eSPhilip Paeps return (0); 136e948693eSPhilip Paeps 137e948693eSPhilip Paeps fail1: 138*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 139e948693eSPhilip Paeps 140e948693eSPhilip Paeps return (rc); 141e948693eSPhilip Paeps } 142e948693eSPhilip Paeps 143e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 144e948693eSPhilip Paeps 145*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 146e948693eSPhilip Paeps efx_nvram_test( 147e948693eSPhilip Paeps __in efx_nic_t *enp) 148e948693eSPhilip Paeps { 149e948693eSPhilip Paeps efx_nvram_ops_t *envop = enp->en_envop; 150*460cb568SAndrew Rybchenko efx_rc_t rc; 151e948693eSPhilip Paeps 152e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 153e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 154e948693eSPhilip Paeps 155e948693eSPhilip Paeps if ((rc = envop->envo_test(enp)) != 0) 156e948693eSPhilip Paeps goto fail1; 157e948693eSPhilip Paeps 158e948693eSPhilip Paeps return (0); 159e948693eSPhilip Paeps 160e948693eSPhilip Paeps fail1: 161*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 162e948693eSPhilip Paeps 163e948693eSPhilip Paeps return (rc); 164e948693eSPhilip Paeps } 165e948693eSPhilip Paeps 166e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 167e948693eSPhilip Paeps 168*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 169e948693eSPhilip Paeps efx_nvram_size( 170e948693eSPhilip Paeps __in efx_nic_t *enp, 171e948693eSPhilip Paeps __in efx_nvram_type_t type, 172e948693eSPhilip Paeps __out size_t *sizep) 173e948693eSPhilip Paeps { 174e948693eSPhilip Paeps efx_nvram_ops_t *envop = enp->en_envop; 175*460cb568SAndrew Rybchenko efx_rc_t rc; 176e948693eSPhilip Paeps 177e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 178e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 179e948693eSPhilip Paeps 180e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 181e948693eSPhilip Paeps 182e948693eSPhilip Paeps if ((rc = envop->envo_size(enp, type, sizep)) != 0) 183e948693eSPhilip Paeps goto fail1; 184e948693eSPhilip Paeps 185e948693eSPhilip Paeps return (0); 186e948693eSPhilip Paeps 187e948693eSPhilip Paeps fail1: 188*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 189e948693eSPhilip Paeps 190e948693eSPhilip Paeps return (rc); 191e948693eSPhilip Paeps } 192e948693eSPhilip Paeps 193*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 194e948693eSPhilip Paeps efx_nvram_get_version( 195e948693eSPhilip Paeps __in efx_nic_t *enp, 196e948693eSPhilip Paeps __in efx_nvram_type_t type, 197e948693eSPhilip Paeps __out uint32_t *subtypep, 198e948693eSPhilip Paeps __out_ecount(4) uint16_t version[4]) 199e948693eSPhilip Paeps { 200e948693eSPhilip Paeps efx_nvram_ops_t *envop = enp->en_envop; 201*460cb568SAndrew Rybchenko efx_rc_t rc; 202e948693eSPhilip Paeps 203e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 204e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 205e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 206e948693eSPhilip Paeps 207e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 208e948693eSPhilip Paeps 209e948693eSPhilip Paeps if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0) 210e948693eSPhilip Paeps goto fail1; 211e948693eSPhilip Paeps 212e948693eSPhilip Paeps return (0); 213e948693eSPhilip Paeps 214e948693eSPhilip Paeps fail1: 215*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 216e948693eSPhilip Paeps 217e948693eSPhilip Paeps return (rc); 218e948693eSPhilip Paeps } 219e948693eSPhilip Paeps 220*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 221e948693eSPhilip Paeps efx_nvram_rw_start( 222e948693eSPhilip Paeps __in efx_nic_t *enp, 223e948693eSPhilip Paeps __in efx_nvram_type_t type, 224e948693eSPhilip Paeps __out_opt size_t *chunk_sizep) 225e948693eSPhilip Paeps { 226e948693eSPhilip Paeps efx_nvram_ops_t *envop = enp->en_envop; 227*460cb568SAndrew Rybchenko efx_rc_t rc; 228e948693eSPhilip Paeps 229e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 230e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 231e948693eSPhilip Paeps 232e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 233e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 234e948693eSPhilip Paeps 235e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 236e948693eSPhilip Paeps 237e948693eSPhilip Paeps if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0) 238e948693eSPhilip Paeps goto fail1; 239e948693eSPhilip Paeps 240e948693eSPhilip Paeps enp->en_nvram_locked = type; 241e948693eSPhilip Paeps 242e948693eSPhilip Paeps return (0); 243e948693eSPhilip Paeps 244e948693eSPhilip Paeps fail1: 245*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 246e948693eSPhilip Paeps 247e948693eSPhilip Paeps return (rc); 248e948693eSPhilip Paeps } 249e948693eSPhilip Paeps 250*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 251e948693eSPhilip Paeps efx_nvram_read_chunk( 252e948693eSPhilip Paeps __in efx_nic_t *enp, 253e948693eSPhilip Paeps __in efx_nvram_type_t type, 254e948693eSPhilip Paeps __in unsigned int offset, 255e948693eSPhilip Paeps __out_bcount(size) caddr_t data, 256e948693eSPhilip Paeps __in size_t size) 257e948693eSPhilip Paeps { 258e948693eSPhilip Paeps efx_nvram_ops_t *envop = enp->en_envop; 259*460cb568SAndrew Rybchenko efx_rc_t rc; 260e948693eSPhilip Paeps 261e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 262e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 263e948693eSPhilip Paeps 264e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 265e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 266e948693eSPhilip Paeps 267e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 268e948693eSPhilip Paeps 269e948693eSPhilip Paeps if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0) 270e948693eSPhilip Paeps goto fail1; 271e948693eSPhilip Paeps 272e948693eSPhilip Paeps return (0); 273e948693eSPhilip Paeps 274e948693eSPhilip Paeps fail1: 275*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 276e948693eSPhilip Paeps 277e948693eSPhilip Paeps return (rc); 278e948693eSPhilip Paeps } 279e948693eSPhilip Paeps 280*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 281e948693eSPhilip Paeps efx_nvram_erase( 282e948693eSPhilip Paeps __in efx_nic_t *enp, 283e948693eSPhilip Paeps __in efx_nvram_type_t type) 284e948693eSPhilip Paeps { 285e948693eSPhilip Paeps efx_nvram_ops_t *envop = enp->en_envop; 286*460cb568SAndrew Rybchenko efx_rc_t rc; 287e948693eSPhilip Paeps 288e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 289e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 290e948693eSPhilip Paeps 291e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 292e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 293e948693eSPhilip Paeps 294e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 295e948693eSPhilip Paeps 296e948693eSPhilip Paeps if ((rc = envop->envo_erase(enp, type)) != 0) 297e948693eSPhilip Paeps goto fail1; 298e948693eSPhilip Paeps 299e948693eSPhilip Paeps return (0); 300e948693eSPhilip Paeps 301e948693eSPhilip Paeps fail1: 302*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 303e948693eSPhilip Paeps 304e948693eSPhilip Paeps return (rc); 305e948693eSPhilip Paeps } 306e948693eSPhilip Paeps 307*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 308e948693eSPhilip Paeps efx_nvram_write_chunk( 309e948693eSPhilip Paeps __in efx_nic_t *enp, 310e948693eSPhilip Paeps __in efx_nvram_type_t type, 311e948693eSPhilip Paeps __in unsigned int offset, 312e948693eSPhilip Paeps __in_bcount(size) caddr_t data, 313e948693eSPhilip Paeps __in size_t size) 314e948693eSPhilip Paeps { 315e948693eSPhilip Paeps efx_nvram_ops_t *envop = enp->en_envop; 316*460cb568SAndrew Rybchenko efx_rc_t rc; 317e948693eSPhilip Paeps 318e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 319e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 320e948693eSPhilip Paeps 321e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 322e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 323e948693eSPhilip Paeps 324e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 325e948693eSPhilip Paeps 326e948693eSPhilip Paeps if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0) 327e948693eSPhilip Paeps goto fail1; 328e948693eSPhilip Paeps 329e948693eSPhilip Paeps return (0); 330e948693eSPhilip Paeps 331e948693eSPhilip Paeps fail1: 332*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 333e948693eSPhilip Paeps 334e948693eSPhilip Paeps return (rc); 335e948693eSPhilip Paeps } 336e948693eSPhilip Paeps 337e948693eSPhilip Paeps void 338e948693eSPhilip Paeps efx_nvram_rw_finish( 339e948693eSPhilip Paeps __in efx_nic_t *enp, 340e948693eSPhilip Paeps __in efx_nvram_type_t type) 341e948693eSPhilip Paeps { 342e948693eSPhilip Paeps efx_nvram_ops_t *envop = enp->en_envop; 343e948693eSPhilip Paeps 344e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 345e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 346e948693eSPhilip Paeps 347e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 348e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 349e948693eSPhilip Paeps 350e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 351e948693eSPhilip Paeps 352e948693eSPhilip Paeps envop->envo_rw_finish(enp, type); 353e948693eSPhilip Paeps 354e948693eSPhilip Paeps enp->en_nvram_locked = EFX_NVRAM_INVALID; 355e948693eSPhilip Paeps } 356e948693eSPhilip Paeps 357*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 358e948693eSPhilip Paeps efx_nvram_set_version( 359e948693eSPhilip Paeps __in efx_nic_t *enp, 360e948693eSPhilip Paeps __in efx_nvram_type_t type, 3613c838a9fSAndrew Rybchenko __in_ecount(4) uint16_t version[4]) 362e948693eSPhilip Paeps { 363e948693eSPhilip Paeps efx_nvram_ops_t *envop = enp->en_envop; 364*460cb568SAndrew Rybchenko efx_rc_t rc; 365e948693eSPhilip Paeps 366e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 367e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 368e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 369e948693eSPhilip Paeps 370e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 371e948693eSPhilip Paeps 372e948693eSPhilip Paeps /* 373e948693eSPhilip Paeps * The Siena implementation of envo_set_version() will attempt to 374e948693eSPhilip Paeps * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector. 375e948693eSPhilip Paeps * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 376e948693eSPhilip Paeps */ 377e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 378e948693eSPhilip Paeps 379e948693eSPhilip Paeps if ((rc = envop->envo_set_version(enp, type, version)) != 0) 380e948693eSPhilip Paeps goto fail1; 381e948693eSPhilip Paeps 382e948693eSPhilip Paeps return (0); 383e948693eSPhilip Paeps 384e948693eSPhilip Paeps fail1: 385*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 386e948693eSPhilip Paeps 387e948693eSPhilip Paeps return (rc); 388e948693eSPhilip Paeps } 389e948693eSPhilip Paeps 390e948693eSPhilip Paeps void 391e948693eSPhilip Paeps efx_nvram_fini( 392e948693eSPhilip Paeps __in efx_nic_t *enp) 393e948693eSPhilip Paeps { 394e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 395e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 396e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 397e948693eSPhilip Paeps 398e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 399e948693eSPhilip Paeps 400e948693eSPhilip Paeps enp->en_envop = NULL; 401e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_NVRAM; 402e948693eSPhilip Paeps } 403e948693eSPhilip Paeps 404e948693eSPhilip Paeps #endif /* EFSYS_OPT_NVRAM */ 4053c838a9fSAndrew Rybchenko 4063c838a9fSAndrew Rybchenko #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD 4073c838a9fSAndrew Rybchenko 4083c838a9fSAndrew Rybchenko /* 4093c838a9fSAndrew Rybchenko * Internal MCDI request handling 4103c838a9fSAndrew Rybchenko */ 4113c838a9fSAndrew Rybchenko 412*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 4133c838a9fSAndrew Rybchenko efx_mcdi_nvram_partitions( 4143c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 4153c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 4163c838a9fSAndrew Rybchenko __in size_t size, 4173c838a9fSAndrew Rybchenko __out unsigned int *npartnp) 4183c838a9fSAndrew Rybchenko { 4193c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 4203c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN, 4213c838a9fSAndrew Rybchenko MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)]; 4223c838a9fSAndrew Rybchenko unsigned int npartn; 423*460cb568SAndrew Rybchenko efx_rc_t rc; 4243c838a9fSAndrew Rybchenko 4253c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 4263c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_PARTITIONS; 4273c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 4283c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN; 4293c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 4303c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX; 4313c838a9fSAndrew Rybchenko 4323c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 4333c838a9fSAndrew Rybchenko 4343c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 4353c838a9fSAndrew Rybchenko rc = req.emr_rc; 4363c838a9fSAndrew Rybchenko goto fail1; 4373c838a9fSAndrew Rybchenko } 4383c838a9fSAndrew Rybchenko 4393c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) { 4403c838a9fSAndrew Rybchenko rc = EMSGSIZE; 4413c838a9fSAndrew Rybchenko goto fail2; 4423c838a9fSAndrew Rybchenko } 4433c838a9fSAndrew Rybchenko npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); 4443c838a9fSAndrew Rybchenko 4453c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) { 4463c838a9fSAndrew Rybchenko rc = ENOENT; 4473c838a9fSAndrew Rybchenko goto fail3; 4483c838a9fSAndrew Rybchenko } 4493c838a9fSAndrew Rybchenko 4503c838a9fSAndrew Rybchenko if (size < npartn * sizeof (uint32_t)) { 4513c838a9fSAndrew Rybchenko rc = ENOSPC; 4523c838a9fSAndrew Rybchenko goto fail3; 4533c838a9fSAndrew Rybchenko } 4543c838a9fSAndrew Rybchenko 4553c838a9fSAndrew Rybchenko *npartnp = npartn; 4563c838a9fSAndrew Rybchenko 4573c838a9fSAndrew Rybchenko memcpy(data, 4583c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID), 4593c838a9fSAndrew Rybchenko (npartn * sizeof (uint32_t))); 4603c838a9fSAndrew Rybchenko 4613c838a9fSAndrew Rybchenko return (0); 4623c838a9fSAndrew Rybchenko 4633c838a9fSAndrew Rybchenko fail3: 4643c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 4653c838a9fSAndrew Rybchenko fail2: 4663c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 4673c838a9fSAndrew Rybchenko fail1: 468*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 4693c838a9fSAndrew Rybchenko 4703c838a9fSAndrew Rybchenko return (rc); 4713c838a9fSAndrew Rybchenko } 4723c838a9fSAndrew Rybchenko 473*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 4743c838a9fSAndrew Rybchenko efx_mcdi_nvram_metadata( 4753c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 4763c838a9fSAndrew Rybchenko __in uint32_t partn, 4773c838a9fSAndrew Rybchenko __out uint32_t *subtypep, 4783c838a9fSAndrew Rybchenko __out_ecount(4) uint16_t version[4], 4793c838a9fSAndrew Rybchenko __out_bcount_opt(size) char *descp, 4803c838a9fSAndrew Rybchenko __in size_t size) 4813c838a9fSAndrew Rybchenko { 4823c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 4833c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN, 4843c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_LENMAX)]; 485*460cb568SAndrew Rybchenko efx_rc_t rc; 4863c838a9fSAndrew Rybchenko 4873c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 4883c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_METADATA; 4893c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 4903c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN; 4913c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 4923c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX; 4933c838a9fSAndrew Rybchenko 4943c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); 4953c838a9fSAndrew Rybchenko 4963c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 4973c838a9fSAndrew Rybchenko 4983c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 4993c838a9fSAndrew Rybchenko rc = req.emr_rc; 5003c838a9fSAndrew Rybchenko goto fail1; 5013c838a9fSAndrew Rybchenko } 5023c838a9fSAndrew Rybchenko 5033c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) { 5043c838a9fSAndrew Rybchenko rc = EMSGSIZE; 5053c838a9fSAndrew Rybchenko goto fail2; 5063c838a9fSAndrew Rybchenko } 5073c838a9fSAndrew Rybchenko 5083c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 5093c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_SUBTYPE_VALID)) { 5103c838a9fSAndrew Rybchenko *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE); 5113c838a9fSAndrew Rybchenko } else { 5123c838a9fSAndrew Rybchenko *subtypep = 0; 5133c838a9fSAndrew Rybchenko } 5143c838a9fSAndrew Rybchenko 5153c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 5163c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_VERSION_VALID)) { 5173c838a9fSAndrew Rybchenko version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W); 5183c838a9fSAndrew Rybchenko version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X); 5193c838a9fSAndrew Rybchenko version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y); 5203c838a9fSAndrew Rybchenko version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z); 5213c838a9fSAndrew Rybchenko } else { 5223c838a9fSAndrew Rybchenko version[0] = version[1] = version[2] = version[3] = 0; 5233c838a9fSAndrew Rybchenko } 5243c838a9fSAndrew Rybchenko 5253c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 5263c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION_VALID)) { 5273c838a9fSAndrew Rybchenko /* Return optional descrition string */ 5283c838a9fSAndrew Rybchenko if ((descp != NULL) && (size > 0)) { 5293c838a9fSAndrew Rybchenko size_t desclen; 5303c838a9fSAndrew Rybchenko 5313c838a9fSAndrew Rybchenko descp[0] = '\0'; 5323c838a9fSAndrew Rybchenko desclen = (req.emr_out_length_used 5333c838a9fSAndrew Rybchenko - MC_CMD_NVRAM_METADATA_OUT_LEN(0)); 5343c838a9fSAndrew Rybchenko 5353c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(desclen, <=, 5363c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM); 5373c838a9fSAndrew Rybchenko 5383c838a9fSAndrew Rybchenko if (size < desclen) { 5393c838a9fSAndrew Rybchenko rc = ENOSPC; 5403c838a9fSAndrew Rybchenko goto fail3; 5413c838a9fSAndrew Rybchenko } 5423c838a9fSAndrew Rybchenko 5433c838a9fSAndrew Rybchenko memcpy(descp, MCDI_OUT2(req, char, 5443c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION), 5453c838a9fSAndrew Rybchenko desclen); 5463c838a9fSAndrew Rybchenko 5473c838a9fSAndrew Rybchenko /* Ensure string is NUL terminated */ 5483c838a9fSAndrew Rybchenko descp[desclen] = '\0'; 5493c838a9fSAndrew Rybchenko } 5503c838a9fSAndrew Rybchenko } 5513c838a9fSAndrew Rybchenko 5523c838a9fSAndrew Rybchenko return (0); 5533c838a9fSAndrew Rybchenko 5543c838a9fSAndrew Rybchenko fail3: 5553c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 5563c838a9fSAndrew Rybchenko fail2: 5573c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 5583c838a9fSAndrew Rybchenko fail1: 559*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5603c838a9fSAndrew Rybchenko 5613c838a9fSAndrew Rybchenko return (rc); 5623c838a9fSAndrew Rybchenko } 5633c838a9fSAndrew Rybchenko 564*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5653c838a9fSAndrew Rybchenko efx_mcdi_nvram_info( 5663c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 5673c838a9fSAndrew Rybchenko __in uint32_t partn, 5683c838a9fSAndrew Rybchenko __out_opt size_t *sizep, 5693c838a9fSAndrew Rybchenko __out_opt uint32_t *addressp, 5703c838a9fSAndrew Rybchenko __out_opt uint32_t *erase_sizep) 5713c838a9fSAndrew Rybchenko { 5723c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN, 5733c838a9fSAndrew Rybchenko MC_CMD_NVRAM_INFO_OUT_LEN)]; 5743c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 575*460cb568SAndrew Rybchenko efx_rc_t rc; 5763c838a9fSAndrew Rybchenko 5773c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 5783c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_INFO; 5793c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 5803c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN; 5813c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 5823c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_INFO_OUT_LEN; 5833c838a9fSAndrew Rybchenko 5843c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn); 5853c838a9fSAndrew Rybchenko 5863c838a9fSAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req); 5873c838a9fSAndrew Rybchenko 5883c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 5893c838a9fSAndrew Rybchenko rc = req.emr_rc; 5903c838a9fSAndrew Rybchenko goto fail1; 5913c838a9fSAndrew Rybchenko } 5923c838a9fSAndrew Rybchenko 5933c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) { 5943c838a9fSAndrew Rybchenko rc = EMSGSIZE; 5953c838a9fSAndrew Rybchenko goto fail2; 5963c838a9fSAndrew Rybchenko } 5973c838a9fSAndrew Rybchenko 5983c838a9fSAndrew Rybchenko if (sizep) 5993c838a9fSAndrew Rybchenko *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE); 6003c838a9fSAndrew Rybchenko 6013c838a9fSAndrew Rybchenko if (addressp) 6023c838a9fSAndrew Rybchenko *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR); 6033c838a9fSAndrew Rybchenko 6043c838a9fSAndrew Rybchenko if (erase_sizep) 6053c838a9fSAndrew Rybchenko *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE); 6063c838a9fSAndrew Rybchenko 6073c838a9fSAndrew Rybchenko return (0); 6083c838a9fSAndrew Rybchenko 6093c838a9fSAndrew Rybchenko fail2: 6103c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 6113c838a9fSAndrew Rybchenko fail1: 612*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 6133c838a9fSAndrew Rybchenko 6143c838a9fSAndrew Rybchenko return (rc); 6153c838a9fSAndrew Rybchenko } 6163c838a9fSAndrew Rybchenko 617*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 6183c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_start( 6193c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 6203c838a9fSAndrew Rybchenko __in uint32_t partn) 6213c838a9fSAndrew Rybchenko { 6223c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_IN_LEN, 6233c838a9fSAndrew Rybchenko MC_CMD_NVRAM_UPDATE_START_OUT_LEN)]; 6243c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 625*460cb568SAndrew Rybchenko efx_rc_t rc; 6263c838a9fSAndrew Rybchenko 6273c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 6283c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; 6293c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 6303c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN; 6313c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 6323c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN; 6333c838a9fSAndrew Rybchenko 6343c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn); 6353c838a9fSAndrew Rybchenko 6363c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 6373c838a9fSAndrew Rybchenko 6383c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 6393c838a9fSAndrew Rybchenko rc = req.emr_rc; 6403c838a9fSAndrew Rybchenko goto fail1; 6413c838a9fSAndrew Rybchenko } 6423c838a9fSAndrew Rybchenko 6433c838a9fSAndrew Rybchenko return (0); 6443c838a9fSAndrew Rybchenko 6453c838a9fSAndrew Rybchenko fail1: 646*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 6473c838a9fSAndrew Rybchenko 6483c838a9fSAndrew Rybchenko return (rc); 6493c838a9fSAndrew Rybchenko } 6503c838a9fSAndrew Rybchenko 651*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 6523c838a9fSAndrew Rybchenko efx_mcdi_nvram_read( 6533c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 6543c838a9fSAndrew Rybchenko __in uint32_t partn, 6553c838a9fSAndrew Rybchenko __in uint32_t offset, 6563c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 6573c838a9fSAndrew Rybchenko __in size_t size) 6583c838a9fSAndrew Rybchenko { 6593c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 6603c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_LEN, 6613c838a9fSAndrew Rybchenko MC_CMD_NVRAM_READ_OUT_LENMAX)]; 662*460cb568SAndrew Rybchenko efx_rc_t rc; 6633c838a9fSAndrew Rybchenko 6643c838a9fSAndrew Rybchenko if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) { 6653c838a9fSAndrew Rybchenko rc = EINVAL; 6663c838a9fSAndrew Rybchenko goto fail1; 6673c838a9fSAndrew Rybchenko } 6683c838a9fSAndrew Rybchenko 6693c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 6703c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_READ; 6713c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 6723c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_READ_IN_LEN; 6733c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 6743c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX; 6753c838a9fSAndrew Rybchenko 6763c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_TYPE, partn); 6773c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_OFFSET, offset); 6783c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_LENGTH, size); 6793c838a9fSAndrew Rybchenko 6803c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 6813c838a9fSAndrew Rybchenko 6823c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 6833c838a9fSAndrew Rybchenko rc = req.emr_rc; 6843c838a9fSAndrew Rybchenko goto fail1; 6853c838a9fSAndrew Rybchenko } 6863c838a9fSAndrew Rybchenko 6873c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) { 6883c838a9fSAndrew Rybchenko rc = EMSGSIZE; 6893c838a9fSAndrew Rybchenko goto fail2; 6903c838a9fSAndrew Rybchenko } 6913c838a9fSAndrew Rybchenko 6923c838a9fSAndrew Rybchenko memcpy(data, 6933c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER), 6943c838a9fSAndrew Rybchenko size); 6953c838a9fSAndrew Rybchenko 6963c838a9fSAndrew Rybchenko return (0); 6973c838a9fSAndrew Rybchenko 6983c838a9fSAndrew Rybchenko fail2: 6993c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 7003c838a9fSAndrew Rybchenko fail1: 701*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7023c838a9fSAndrew Rybchenko 7033c838a9fSAndrew Rybchenko return (rc); 7043c838a9fSAndrew Rybchenko } 7053c838a9fSAndrew Rybchenko 706*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7073c838a9fSAndrew Rybchenko efx_mcdi_nvram_erase( 7083c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7093c838a9fSAndrew Rybchenko __in uint32_t partn, 7103c838a9fSAndrew Rybchenko __in uint32_t offset, 7113c838a9fSAndrew Rybchenko __in size_t size) 7123c838a9fSAndrew Rybchenko { 7133c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 7143c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN, 7153c838a9fSAndrew Rybchenko MC_CMD_NVRAM_ERASE_OUT_LEN)]; 716*460cb568SAndrew Rybchenko efx_rc_t rc; 7173c838a9fSAndrew Rybchenko 7183c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 7193c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_ERASE; 7203c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 7213c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; 7223c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7233c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN; 7243c838a9fSAndrew Rybchenko 7253c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); 7263c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); 7273c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); 7283c838a9fSAndrew Rybchenko 7293c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 7303c838a9fSAndrew Rybchenko 7313c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7323c838a9fSAndrew Rybchenko rc = req.emr_rc; 7333c838a9fSAndrew Rybchenko goto fail1; 7343c838a9fSAndrew Rybchenko } 7353c838a9fSAndrew Rybchenko 7363c838a9fSAndrew Rybchenko return (0); 7373c838a9fSAndrew Rybchenko 7383c838a9fSAndrew Rybchenko fail1: 739*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7403c838a9fSAndrew Rybchenko 7413c838a9fSAndrew Rybchenko return (rc); 7423c838a9fSAndrew Rybchenko } 7433c838a9fSAndrew Rybchenko 744*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7453c838a9fSAndrew Rybchenko efx_mcdi_nvram_write( 7463c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7473c838a9fSAndrew Rybchenko __in uint32_t partn, 7483c838a9fSAndrew Rybchenko __in uint32_t offset, 7493c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 7503c838a9fSAndrew Rybchenko __in size_t size) 7513c838a9fSAndrew Rybchenko { 7523c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 7533c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_WRITE_IN_LENMAX, 7543c838a9fSAndrew Rybchenko MC_CMD_NVRAM_WRITE_OUT_LEN)]; 755*460cb568SAndrew Rybchenko efx_rc_t rc; 7563c838a9fSAndrew Rybchenko 7573c838a9fSAndrew Rybchenko if (size > MC_CMD_NVRAM_WRITE_IN_LENMAX) { 7583c838a9fSAndrew Rybchenko rc = EINVAL; 7593c838a9fSAndrew Rybchenko goto fail1; 7603c838a9fSAndrew Rybchenko } 7613c838a9fSAndrew Rybchenko 7623c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 7633c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_WRITE; 7643c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 7653c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size); 7663c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7673c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN; 7683c838a9fSAndrew Rybchenko 7693c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); 7703c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); 7713c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size); 7723c838a9fSAndrew Rybchenko 7733c838a9fSAndrew Rybchenko memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), 7743c838a9fSAndrew Rybchenko data, size); 7753c838a9fSAndrew Rybchenko 7763c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 7773c838a9fSAndrew Rybchenko 7783c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7793c838a9fSAndrew Rybchenko rc = req.emr_rc; 7803c838a9fSAndrew Rybchenko goto fail2; 7813c838a9fSAndrew Rybchenko } 7823c838a9fSAndrew Rybchenko 7833c838a9fSAndrew Rybchenko return (0); 7843c838a9fSAndrew Rybchenko 7853c838a9fSAndrew Rybchenko fail2: 7863c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 7873c838a9fSAndrew Rybchenko fail1: 788*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7893c838a9fSAndrew Rybchenko 7903c838a9fSAndrew Rybchenko return (rc); 7913c838a9fSAndrew Rybchenko } 7923c838a9fSAndrew Rybchenko 793*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7943c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_finish( 7953c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7963c838a9fSAndrew Rybchenko __in uint32_t partn, 7973c838a9fSAndrew Rybchenko __in boolean_t reboot) 7983c838a9fSAndrew Rybchenko { 7993c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 8003c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN, 8013c838a9fSAndrew Rybchenko MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN)]; 802*460cb568SAndrew Rybchenko efx_rc_t rc; 8033c838a9fSAndrew Rybchenko 8043c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 8053c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH; 8063c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8073c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN; 8083c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8093c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN; 8103c838a9fSAndrew Rybchenko 8113c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn); 8123c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot); 8133c838a9fSAndrew Rybchenko 8143c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8153c838a9fSAndrew Rybchenko 8163c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8173c838a9fSAndrew Rybchenko rc = req.emr_rc; 8183c838a9fSAndrew Rybchenko goto fail1; 8193c838a9fSAndrew Rybchenko } 8203c838a9fSAndrew Rybchenko 8213c838a9fSAndrew Rybchenko return (0); 8223c838a9fSAndrew Rybchenko 8233c838a9fSAndrew Rybchenko fail1: 824*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8253c838a9fSAndrew Rybchenko 8263c838a9fSAndrew Rybchenko return (rc); 8273c838a9fSAndrew Rybchenko } 8283c838a9fSAndrew Rybchenko 8293c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG 8303c838a9fSAndrew Rybchenko 831*460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8323c838a9fSAndrew Rybchenko efx_mcdi_nvram_test( 8333c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8343c838a9fSAndrew Rybchenko __in uint32_t partn) 8353c838a9fSAndrew Rybchenko { 8363c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 8373c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN, 8383c838a9fSAndrew Rybchenko MC_CMD_NVRAM_TEST_OUT_LEN)]; 8393c838a9fSAndrew Rybchenko int result; 840*460cb568SAndrew Rybchenko efx_rc_t rc; 8413c838a9fSAndrew Rybchenko 8423c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 8433c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_TEST; 8443c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8453c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; 8463c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8473c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; 8483c838a9fSAndrew Rybchenko 8493c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn); 8503c838a9fSAndrew Rybchenko 8513c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8523c838a9fSAndrew Rybchenko 8533c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8543c838a9fSAndrew Rybchenko rc = req.emr_rc; 8553c838a9fSAndrew Rybchenko goto fail1; 8563c838a9fSAndrew Rybchenko } 8573c838a9fSAndrew Rybchenko 8583c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { 8593c838a9fSAndrew Rybchenko rc = EMSGSIZE; 8603c838a9fSAndrew Rybchenko goto fail2; 8613c838a9fSAndrew Rybchenko } 8623c838a9fSAndrew Rybchenko 8633c838a9fSAndrew Rybchenko result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); 8643c838a9fSAndrew Rybchenko if (result == MC_CMD_NVRAM_TEST_FAIL) { 8653c838a9fSAndrew Rybchenko 8663c838a9fSAndrew Rybchenko EFSYS_PROBE1(nvram_test_failure, int, partn); 8673c838a9fSAndrew Rybchenko 8683c838a9fSAndrew Rybchenko rc = (EINVAL); 8693c838a9fSAndrew Rybchenko goto fail3; 8703c838a9fSAndrew Rybchenko } 8713c838a9fSAndrew Rybchenko 8723c838a9fSAndrew Rybchenko return (0); 8733c838a9fSAndrew Rybchenko 8743c838a9fSAndrew Rybchenko fail3: 8753c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 8763c838a9fSAndrew Rybchenko fail2: 8773c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 8783c838a9fSAndrew Rybchenko fail1: 879*460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8803c838a9fSAndrew Rybchenko 8813c838a9fSAndrew Rybchenko return (rc); 8823c838a9fSAndrew Rybchenko } 8833c838a9fSAndrew Rybchenko 8843c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 8853c838a9fSAndrew Rybchenko 8863c838a9fSAndrew Rybchenko 8873c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ 888