1 /*
   2  * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  * 1. Redistributions of source code must retain the above copyright
   8  *    notice, this list of conditions and the following disclaimer.
   9  * 2. Redistributions in binary form must reproduce the above copyright
  10  *    notice, this list of conditions and the following disclaimer in the
  11  *    documentation and/or other materials provided with the distribution.
  12  *
  13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
  14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23  * SUCH DAMAGE.
  24  */
  25 
  26 #include "efsys.h"
  27 #include "efx.h"
  28 #include "efx_types.h"
  29 #include "efx_regs.h"
  30 #include "efx_impl.h"
  31 
  32 #if EFSYS_OPT_NVRAM
  33 
  34 #if EFSYS_OPT_FALCON
  35 
  36 static efx_nvram_ops_t  __cs    __efx_nvram_falcon_ops = {
  37 #if EFSYS_OPT_DIAG
  38         falcon_nvram_test,              /* envo_test */
  39 #endif  /* EFSYS_OPT_DIAG */
  40         falcon_nvram_size,              /* envo_size */
  41         falcon_nvram_get_version,       /* envo_get_version */
  42         falcon_nvram_rw_start,          /* envo_rw_start */
  43         falcon_nvram_read_chunk,        /* envo_read_chunk */
  44         falcon_nvram_erase,             /* envo_erase */
  45         falcon_nvram_write_chunk,       /* envo_write_chunk */
  46         falcon_nvram_rw_finish,         /* envo_rw_finish */
  47         falcon_nvram_set_version,       /* envo_set_version */
  48 };
  49 
  50 #endif  /* EFSYS_OPT_FALCON */
  51 
  52 #if EFSYS_OPT_SIENA
  53 
  54 static efx_nvram_ops_t  __cs    __efx_nvram_siena_ops = {
  55 #if EFSYS_OPT_DIAG
  56         siena_nvram_test,               /* envo_test */
  57 #endif  /* EFSYS_OPT_DIAG */
  58         siena_nvram_size,               /* envo_size */
  59         siena_nvram_get_version,        /* envo_get_version */
  60         siena_nvram_rw_start,           /* envo_rw_start */
  61         siena_nvram_read_chunk,         /* envo_read_chunk */
  62         siena_nvram_erase,              /* envo_erase */
  63         siena_nvram_write_chunk,        /* envo_write_chunk */
  64         siena_nvram_rw_finish,          /* envo_rw_finish */
  65         siena_nvram_set_version,        /* envo_set_version */
  66 };
  67 
  68 #endif  /* EFSYS_OPT_SIENA */
  69 
  70         __checkReturn   int
  71 efx_nvram_init(
  72         __in            efx_nic_t *enp)
  73 {
  74         efx_nvram_ops_t *envop;
  75         int rc;
  76 
  77         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  78         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  79         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
  80 
  81         switch (enp->en_family) {
  82 #if EFSYS_OPT_FALCON
  83         case EFX_FAMILY_FALCON:
  84                 envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops;
  85                 break;
  86 #endif  /* EFSYS_OPT_FALCON */
  87 
  88 #if EFSYS_OPT_SIENA
  89         case EFX_FAMILY_SIENA:
  90                 envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops;
  91                 break;
  92 #endif  /* EFSYS_OPT_SIENA */
  93 
  94         default:
  95                 EFSYS_ASSERT(0);
  96                 rc = ENOTSUP;
  97                 goto fail1;
  98         }
  99 
 100         enp->en_envop = envop;
 101         enp->en_mod_flags |= EFX_MOD_NVRAM;
 102 
 103         return (0);
 104 
 105 fail1:
 106         EFSYS_PROBE1(fail1, int, rc);
 107 
 108         return (rc);
 109 }
 110 
 111 #if EFSYS_OPT_DIAG
 112 
 113         __checkReturn           int
 114 efx_nvram_test(
 115         __in                    efx_nic_t *enp)
 116 {
 117         efx_nvram_ops_t *envop = enp->en_envop;
 118         int rc;
 119 
 120         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 121         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 122 
 123         if ((rc = envop->envo_test(enp)) != 0)
 124                 goto fail1;
 125 
 126         return (0);
 127 
 128 fail1:
 129         EFSYS_PROBE1(fail1, int, rc);
 130 
 131         return (rc);
 132 }
 133 
 134 #endif  /* EFSYS_OPT_DIAG */
 135 
 136         __checkReturn           int
 137 efx_nvram_size(
 138         __in                    efx_nic_t *enp,
 139         __in                    efx_nvram_type_t type,
 140         __out                   size_t *sizep)
 141 {
 142         efx_nvram_ops_t *envop = enp->en_envop;
 143         int rc;
 144 
 145         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 146         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 147 
 148         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
 149 
 150         if ((rc = envop->envo_size(enp, type, sizep)) != 0)
 151                 goto fail1;
 152 
 153         return (0);
 154 
 155 fail1:
 156         EFSYS_PROBE1(fail1, int, rc);
 157 
 158         return (rc);
 159 }
 160 
 161         __checkReturn           int
 162 efx_nvram_get_version(
 163         __in                    efx_nic_t *enp,
 164         __in                    efx_nvram_type_t type,
 165         __out                   uint32_t *subtypep,
 166         __out_ecount(4)         uint16_t version[4])
 167 {
 168         efx_nvram_ops_t *envop = enp->en_envop;
 169         int rc;
 170 
 171         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 172         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
 173         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 174 
 175         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
 176 
 177         if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0)
 178                 goto fail1;
 179 
 180         return (0);
 181 
 182 fail1:
 183         EFSYS_PROBE1(fail1, int, rc);
 184 
 185         return (rc);
 186 }
 187 
 188         __checkReturn           int
 189 efx_nvram_rw_start(
 190         __in                    efx_nic_t *enp,
 191         __in                    efx_nvram_type_t type,
 192         __out_opt               size_t *chunk_sizep)
 193 {
 194         efx_nvram_ops_t *envop = enp->en_envop;
 195         int rc;
 196 
 197         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 198         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 199 
 200         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
 201         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
 202 
 203         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
 204 
 205         if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0)
 206                 goto fail1;
 207 
 208         enp->en_nvram_locked = type;
 209 
 210         return (0);
 211 
 212 fail1:
 213         EFSYS_PROBE1(fail1, int, rc);
 214 
 215         return (rc);
 216 }
 217 
 218         __checkReturn           int
 219 efx_nvram_read_chunk(
 220         __in                    efx_nic_t *enp,
 221         __in                    efx_nvram_type_t type,
 222         __in                    unsigned int offset,
 223         __out_bcount(size)      caddr_t data,
 224         __in                    size_t size)
 225 {
 226         efx_nvram_ops_t *envop = enp->en_envop;
 227         int rc;
 228 
 229         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 230         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 231 
 232         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
 233         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
 234 
 235         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
 236 
 237         if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0)
 238                 goto fail1;
 239 
 240         return (0);
 241 
 242 fail1:
 243         EFSYS_PROBE1(fail1, int, rc);
 244 
 245         return (rc);
 246 }
 247 
 248         __checkReturn           int
 249 efx_nvram_erase(
 250         __in                    efx_nic_t *enp,
 251         __in                    efx_nvram_type_t type)
 252 {
 253         efx_nvram_ops_t *envop = enp->en_envop;
 254         int rc;
 255 
 256         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 257         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 258 
 259         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
 260         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
 261 
 262         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
 263 
 264         if ((rc = envop->envo_erase(enp, type)) != 0)
 265                 goto fail1;
 266 
 267         return (0);
 268 
 269 fail1:
 270         EFSYS_PROBE1(fail1, int, rc);
 271 
 272         return (rc);
 273 }
 274 
 275         __checkReturn           int
 276 efx_nvram_write_chunk(
 277         __in                    efx_nic_t *enp,
 278         __in                    efx_nvram_type_t type,
 279         __in                    unsigned int offset,
 280         __in_bcount(size)       caddr_t data,
 281         __in                    size_t size)
 282 {
 283         efx_nvram_ops_t *envop = enp->en_envop;
 284         int rc;
 285 
 286         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 287         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 288 
 289         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
 290         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
 291 
 292         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
 293 
 294         if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0)
 295                 goto fail1;
 296 
 297         return (0);
 298 
 299 fail1:
 300         EFSYS_PROBE1(fail1, int, rc);
 301 
 302         return (rc);
 303 }
 304 
 305                                 void
 306 efx_nvram_rw_finish(
 307         __in                    efx_nic_t *enp,
 308         __in                    efx_nvram_type_t type)
 309 {
 310         efx_nvram_ops_t *envop = enp->en_envop;
 311 
 312         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 313         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 314 
 315         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
 316         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
 317 
 318         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
 319 
 320         envop->envo_rw_finish(enp, type);
 321 
 322         enp->en_nvram_locked = EFX_NVRAM_INVALID;
 323 }
 324 
 325         __checkReturn           int
 326 efx_nvram_set_version(
 327         __in                    efx_nic_t *enp,
 328         __in                    efx_nvram_type_t type,
 329         __out                   uint16_t version[4])
 330 {
 331         efx_nvram_ops_t *envop = enp->en_envop;
 332         int rc;
 333 
 334         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 335         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
 336         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 337 
 338         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
 339 
 340         /*
 341          * The Siena implementation of envo_set_version() will attempt to
 342          * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
 343          * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
 344          */
 345         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
 346 
 347         if ((rc = envop->envo_set_version(enp, type, version)) != 0)
 348                 goto fail1;
 349 
 350         return (0);
 351 
 352 fail1:
 353         EFSYS_PROBE1(fail1, int, rc);
 354 
 355         return (rc);
 356 }
 357 
 358 void
 359 efx_nvram_fini(
 360         __in            efx_nic_t *enp)
 361 {
 362         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 363         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
 364         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
 365 
 366         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
 367 
 368         enp->en_envop = NULL;
 369         enp->en_mod_flags &= ~EFX_MOD_NVRAM;
 370 }
 371 
 372 #endif  /* EFSYS_OPT_NVRAM */