1 /*
   2  * Copyright 2007-2013 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 "falcon_nvram.h"
  29 #include "efx_types.h"
  30 #include "efx_impl.h"
  31 
  32 #if EFSYS_OPT_FALCON
  33 
  34 #if EFSYS_OPT_MON_LM87
  35 #include "lm87.h"
  36 #endif
  37 
  38 #if EFSYS_OPT_MON_MAX6647
  39 #include "max6647.h"
  40 #endif
  41 
  42 #if EFSYS_OPT_NVRAM_SFX7101
  43 #include "sfx7101.h"
  44 #endif
  45 
  46 #if EFSYS_OPT_NVRAM_SFT9001
  47 #include "sft9001.h"
  48 #endif
  49 
  50 #define FALCON_NVRAM_INIT_LOWEST_REG                            \
  51         MIN(CFG_VERSION_REG_SF_OFST,                            \
  52             MIN(CFG_FLASH_DEV_REG_SF_OFST,                      \
  53                 CFG_EEPROM_DEV_REG_SF_OFST))
  54 
  55 #define FALCON_NVRAM_INIT_HIGHEST_REG                           \
  56         MAX(CFG_VERSION_REG_SF_OFST,                            \
  57             MAX(CFG_FLASH_DEV_REG_SF_OFST,                      \
  58                 CFG_EEPROM_DEV_REG_SF_OFST))
  59 
  60 #define FALCON_NVRAM_INIT_NEEDED_CFG_SIZE                       \
  61         (FALCON_NVRAM_INIT_HIGHEST_REG + sizeof (efx_oword_t)   \
  62             - FALCON_NVRAM_INIT_LOWEST_REG)
  63 
  64         __checkReturn   int
  65 falcon_nvram_init(
  66         __in            efx_nic_t *enp)
  67 {
  68         falcon_spi_dev_t *fsdp;
  69         efx_oword_t oword;
  70         uint16_t version;
  71         int rc;
  72         uint8_t cfg[FALCON_NVRAM_INIT_NEEDED_CFG_SIZE];
  73         uint8_t *origin = cfg - FALCON_NVRAM_INIT_LOWEST_REG;
  74 
  75         /* All boards have flash and EEPROM */
  76         EFX_BAR_READO(enp, FR_AB_NIC_STAT_REG, &oword);
  77         EFX_SET_OWORD_FIELD(oword, FRF_AB_SF_PRST, 1);
  78         EFX_SET_OWORD_FIELD(oword, FRF_AB_EE_PRST, 1);
  79         EFX_BAR_WRITEO(enp, FR_AB_NIC_STAT_REG, &oword);
  80 
  81         /* Set up partial flash parameters */
  82         fsdp = &(enp->en_u.falcon.enu_fsd[FALCON_SPI_FLASH]);
  83         fsdp->fsd_sf_sel = 1;
  84         fsdp->fsd_adbcnt = 3;
  85         fsdp->fsd_munge = B_FALSE;
  86 
  87         if ((rc = falcon_nic_cfg_raw_read_verify(enp,
  88             FALCON_NVRAM_INIT_LOWEST_REG,
  89             FALCON_NVRAM_INIT_NEEDED_CFG_SIZE, cfg)) != 0)
  90                 goto fail1;
  91 
  92         version = EFX_WORD_FIELD(
  93                 *(efx_word_t *)(origin + CFG_VERSION_REG_SF_OFST), VERSION);
  94 
  95         if (version < 3) {
  96                 fsdp->fsd_size = (size_t)1 << 17;
  97                 fsdp->fsd_erase_cmd = 0x52;
  98                 fsdp->fsd_erase_size = (size_t)1 << 15;
  99                 fsdp->fsd_write_size = (size_t)1 << 8;
 100         } else {
 101                 efx_dword_t *dwordp =
 102                         (efx_dword_t *)(origin + CFG_FLASH_DEV_REG_SF_OFST);
 103 
 104                 if (EFX_DWORD_FIELD(*dwordp, SPI_DEV_ADBCNT) != 3 ||
 105                     EFX_DWORD_FIELD(*dwordp, SPI_DEV_SIZE) >= 24) {
 106                         rc = EINVAL;
 107                         goto fail2;
 108                 }
 109 
 110                 fsdp->fsd_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
 111                     SPI_DEV_SIZE);
 112                 fsdp->fsd_erase_cmd = EFX_DWORD_FIELD(*dwordp,
 113                                             SPI_DEV_ERASE_CMD);
 114                 fsdp->fsd_erase_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
 115                     SPI_DEV_ERASE_SIZE);
 116                 fsdp->fsd_write_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
 117                     SPI_DEV_WRITE_SIZE);
 118         }
 119 
 120         /* Configure the EEPROM */
 121         fsdp = &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
 122 
 123         fsdp->fsd_sf_sel = 0;
 124         if (version < 3) {
 125                 fsdp->fsd_adbcnt = 1;
 126                 fsdp->fsd_size = (size_t)1 << 9;
 127                 fsdp->fsd_munge = B_TRUE;
 128                 fsdp->fsd_erase_cmd = 0;
 129                 fsdp->fsd_erase_size = 1;
 130                 fsdp->fsd_write_size = (size_t)1 << 3;
 131         } else {
 132                 efx_dword_t *dwordp =
 133                         (efx_dword_t *)(origin + CFG_EEPROM_DEV_REG_SF_OFST);
 134 
 135                 fsdp->fsd_adbcnt = EFX_DWORD_FIELD(*dwordp, SPI_DEV_ADBCNT);
 136                 fsdp->fsd_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
 137                     SPI_DEV_SIZE);
 138                 fsdp->fsd_munge = (EFX_DWORD_FIELD(*dwordp, SPI_DEV_SIZE) >
 139                     fsdp->fsd_adbcnt * 8);
 140                 fsdp->fsd_erase_cmd = EFX_DWORD_FIELD(*dwordp,
 141                     SPI_DEV_ERASE_CMD);
 142                 fsdp->fsd_erase_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
 143                     SPI_DEV_ERASE_SIZE);
 144                 fsdp->fsd_write_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
 145                     SPI_DEV_WRITE_SIZE);
 146         }
 147 
 148         return (0);
 149 
 150 fail2:
 151         EFSYS_PROBE(fail2);
 152 fail1:
 153         EFSYS_PROBE1(fail1, int, rc);
 154 
 155         (void) memset(enp->en_u.falcon.enu_fsd, 0,
 156             sizeof (enp->en_u.falcon.enu_fsd));
 157 
 158         return (rc);
 159 }
 160 
 161 #if EFSYS_OPT_NVRAM
 162 
 163 typedef struct falcon_nvram_ops_s {
 164         int     (*fnvo_size)(efx_nic_t *, size_t *);
 165         int     (*fnvo_get_version)(efx_nic_t *, uint32_t *, uint16_t *);
 166         int     (*fnvo_rw_start)(efx_nic_t *, size_t *);
 167         int     (*fnvo_read_chunk)(efx_nic_t *, unsigned int,
 168                     caddr_t, size_t);
 169         int     (*fnvo_erase)(efx_nic_t *);
 170         int     (*fnvo_write_chunk)(efx_nic_t *, unsigned int,
 171                     caddr_t, size_t);
 172         void    (*fnvo_rw_finish)(efx_nic_t *);
 173 } falcon_nvram_ops_t;
 174 
 175 #if EFSYS_OPT_NVRAM_FALCON_BOOTROM
 176 
 177 #define FALCON_GPXE_IMAGE_OFFSET        0x8000
 178 #define FALCON_GPXE_IMAGE_SIZE          0x18000
 179 
 180 static  __checkReturn           int
 181 falcon_nvram_bootrom_size(
 182         __in                    efx_nic_t *enp,
 183         __out                   size_t *sizep)
 184 {
 185         _NOTE(ARGUNUSED(enp))
 186         EFSYS_ASSERT(sizep != NULL);
 187         *sizep = FALCON_GPXE_IMAGE_SIZE;
 188 
 189         return (0);
 190 }
 191 
 192 static  __checkReturn           int
 193 falcon_nvram_bootrom_get_version(
 194         __in                    efx_nic_t *enp,
 195         __out                   uint32_t *subtypep,
 196         __out_ecount(4)         uint16_t version[4])
 197 {
 198         const char prefix[] = "Solarstorm Boot Manager (v";
 199         char buf[16], p;
 200         size_t current, needle;
 201         uint16_t *versionp;
 202         int rc;
 203 
 204         version[0] = version[1] = version[2] = version[3] = 0;
 205         versionp = NULL;
 206         needle = 0;
 207 
 208         /*
 209          * Search from [current, end) for prefix, and return the
 210          * trailing four decimal number.
 211          */
 212         for (current = 0; current < 0x600; current++) {
 213                 if (current % sizeof (buf) == 0) {
 214                         if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_FLASH,
 215                             FALCON_GPXE_IMAGE_OFFSET + current, buf,
 216                             sizeof (buf))) != 0)
 217                                 break;
 218                 }
 219 
 220                 p = buf[current % sizeof (buf)];
 221                 if (versionp == NULL) {
 222                         if (prefix[needle] == p) {
 223                                 ++needle;
 224                                 if (needle == sizeof (prefix) - 1)
 225                                         versionp = version;
 226                         } else
 227                                 needle = 0;
 228                 } else {
 229                         if (p == ')' && versionp == version + 3)
 230                                 goto done;
 231                         else if (p >= '0' && p <= '9')
 232                                 *versionp = (*versionp * 10) + (p - '0');
 233                         else if (p == '.' && versionp != version + 3)
 234                                 ++versionp;
 235                         else
 236                                 /* Invalid format */
 237                                 break;
 238                 }
 239         }
 240 
 241         version[0] = version[1] = version[2] = version[3] = 0;
 242 
 243 done:
 244         *subtypep = 0;  /* Falcon bootrom is type 0 */
 245 
 246         return (0);
 247 }
 248 
 249 static  __checkReturn           int
 250 falcon_nvram_bootrom_rw_start(
 251         __in                    efx_nic_t *enp,
 252         __out                   size_t *chunk_sizep)
 253 {
 254         _NOTE(ARGUNUSED(enp))
 255         if (chunk_sizep != NULL)
 256                 *chunk_sizep = sizeof (efx_oword_t);
 257 
 258         return (0);
 259 }
 260 
 261 static  __checkReturn           int
 262 falcon_nvram_bootrom_read_chunk(
 263         __in                    efx_nic_t *enp,
 264         __in                    unsigned int offset,
 265         __out_bcount(size)      caddr_t data,
 266         __in                    size_t size)
 267 {
 268         int rc;
 269 
 270         EFSYS_ASSERT3U(size + offset, <=, FALCON_GPXE_IMAGE_SIZE);
 271 
 272         if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_FLASH,
 273             FALCON_GPXE_IMAGE_OFFSET + offset, data, size)) != 0)
 274                 goto fail1;
 275 
 276         return (0);
 277 
 278 fail1:
 279         EFSYS_PROBE1(fail1, int, rc);
 280 
 281         return (rc);
 282 }
 283 
 284 static   __checkReturn          int
 285 falcon_nvram_bootrom_erase(
 286         __in                    efx_nic_t *enp)
 287 {
 288         int rc;
 289 
 290         if ((rc = falcon_spi_dev_erase(enp, FALCON_SPI_FLASH,
 291             FALCON_GPXE_IMAGE_OFFSET, FALCON_GPXE_IMAGE_SIZE)) != 0)
 292                 goto fail1;
 293 
 294         return (0);
 295 
 296 fail1:
 297         EFSYS_PROBE1(fail1, int, rc);
 298 
 299         return (rc);
 300 }
 301 
 302 static  __checkReturn           int
 303 falcon_nvram_bootrom_write_chunk(
 304         __in                    efx_nic_t *enp,
 305         __in                    unsigned int offset,
 306         __out_bcount(size)      caddr_t base,
 307         __in                    size_t size)
 308 {
 309         int rc;
 310 
 311         if ((rc = falcon_spi_dev_write(enp, FALCON_SPI_FLASH,
 312             FALCON_GPXE_IMAGE_OFFSET + offset, base, size)) != 0)
 313                 goto fail1;
 314 
 315         return (0);
 316 
 317 fail1:
 318         EFSYS_PROBE1(fail1, int, rc);
 319 
 320         return (rc);
 321 }
 322 
 323 static falcon_nvram_ops_t       __cs    __falcon_nvram_bootrom_ops = {
 324         falcon_nvram_bootrom_size,              /* fnvo_size */
 325         falcon_nvram_bootrom_get_version,       /* fnvo_get_version */
 326         falcon_nvram_bootrom_rw_start,          /* fnvo_rw_start */
 327         falcon_nvram_bootrom_read_chunk,        /* fnvo_read_chunk */
 328         falcon_nvram_bootrom_erase,             /* fnvo_erase */
 329         falcon_nvram_bootrom_write_chunk,       /* fnvo_write_chunk */
 330         NULL,                                   /* fnvo_rw_finish */
 331 };
 332 
 333 #define FALCON_GPXE_CFG_OFFSET          0x800
 334 
 335 static  __checkReturn           int
 336 falcon_nvram_bootrom_cfg_size(
 337         __in                    efx_nic_t *enp,
 338         __out                   size_t *sizep)
 339 {
 340         falcon_spi_dev_t *fsdp =
 341                 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
 342         int rc;
 343 
 344         EFSYS_ASSERT(sizep != NULL);
 345         EFSYS_ASSERT(fsdp != NULL);
 346 
 347         if (fsdp->fsd_size < FALCON_GPXE_CFG_OFFSET) {
 348                 *sizep = 0;
 349                 rc = ENOTSUP;
 350                 goto fail1;
 351         }
 352 
 353         *sizep = fsdp->fsd_size - FALCON_GPXE_CFG_OFFSET;
 354 
 355         return (0);
 356 
 357 fail1:
 358         EFSYS_PROBE1(fail1, int, rc);
 359 
 360         return (rc);
 361 }
 362 
 363 static  __checkReturn           int
 364 falcon_nvram_bootrom_cfg_get_version(
 365         __in                    efx_nic_t *enp,
 366         __out                   uint32_t *subtypep,
 367         __out_ecount(4)         uint16_t version[4])
 368 {
 369         falcon_spi_dev_t *fsdp =
 370                 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
 371         int rc;
 372 
 373         EFSYS_ASSERT(fsdp != NULL);
 374         if (fsdp->fsd_size < FALCON_GPXE_CFG_OFFSET) {
 375                 rc = ENOTSUP;
 376                 goto fail1;
 377         }
 378 
 379         /* gpxecfg is not versioned */
 380         *subtypep = 0;
 381         version[0] = version[1] = version[2] = version[3];
 382 
 383         return (0);
 384 
 385 fail1:
 386         EFSYS_PROBE1(fail1, int, rc);
 387 
 388         return (rc);
 389 }
 390 
 391 static  __checkReturn           int
 392 falcon_nvram_bootrom_cfg_rw_start(
 393         __in                    efx_nic_t *enp,
 394         __out                   size_t *chunk_sizep)
 395 {
 396         falcon_spi_dev_t *fsdp =
 397                 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
 398         int rc;
 399 
 400         EFSYS_ASSERT(fsdp != NULL);
 401         if (fsdp->fsd_size < FALCON_GPXE_CFG_OFFSET) {
 402                 rc = ENOTSUP;
 403                 goto fail1;
 404         }
 405 
 406         if (chunk_sizep != NULL)
 407                 *chunk_sizep = sizeof (efx_oword_t);
 408 
 409         return (0);
 410 
 411 fail1:
 412         EFSYS_PROBE1(fail1, int, rc);
 413 
 414         return (rc);
 415 }
 416 
 417 
 418 static  __checkReturn           int
 419 falcon_nvram_bootrom_cfg_read_chunk(
 420         __in                    efx_nic_t *enp,
 421         __in                    unsigned int offset,
 422         __out_bcount(size)      caddr_t data,
 423         __in                    size_t size)
 424 {
 425         falcon_spi_dev_t *fsdp =
 426                 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
 427         int rc;
 428 
 429         EFSYS_ASSERT(fsdp != NULL);
 430         EFSYS_ASSERT3U(fsdp->fsd_size, >=, FALCON_GPXE_CFG_OFFSET);
 431         EFSYS_ASSERT3U(offset + size, <=,
 432             fsdp->fsd_size - FALCON_GPXE_CFG_OFFSET);
 433 
 434         if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_EEPROM,
 435             FALCON_GPXE_CFG_OFFSET + offset, data, size)) != 0)
 436                 goto fail1;
 437 
 438         return (0);
 439 
 440 fail1:
 441         EFSYS_PROBE1(fail1, int, rc);
 442 
 443         return (rc);
 444 }
 445 
 446 static  __checkReturn           int
 447 falcon_nvram_bootrom_cfg_write_chunk(
 448         __in                    efx_nic_t *enp,
 449         __in                    unsigned int offset,
 450         __in_bcount(size)       caddr_t base,
 451         __in                    size_t size)
 452 {
 453         falcon_spi_dev_t *fsdp =
 454                 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
 455         int rc;
 456 
 457         EFSYS_ASSERT(fsdp != NULL);
 458         EFSYS_ASSERT3U(fsdp->fsd_size, >=, FALCON_GPXE_CFG_OFFSET);
 459         EFSYS_ASSERT3U(offset + size, <=,
 460             fsdp->fsd_size - FALCON_GPXE_CFG_OFFSET);
 461 
 462         if ((rc = falcon_spi_dev_write(enp, FALCON_SPI_EEPROM,
 463             FALCON_GPXE_CFG_OFFSET + offset, base, size)) != 0)
 464                 goto fail1;
 465 
 466         return (0);
 467 
 468 fail1:
 469         EFSYS_PROBE1(fail1, int, rc);
 470 
 471         return (rc);
 472 }
 473 
 474 static falcon_nvram_ops_t       __cs    __falcon_nvram_bootrom_cfg_ops = {
 475         falcon_nvram_bootrom_cfg_size,          /* fnvo_size */
 476         falcon_nvram_bootrom_cfg_get_version,   /* fnvo_get_version */
 477         falcon_nvram_bootrom_cfg_rw_start,      /* fnvo_rw_start */
 478         falcon_nvram_bootrom_cfg_read_chunk,    /* fnvo_read_chunk */
 479         NULL,                                   /* fnvo_erase */
 480         falcon_nvram_bootrom_cfg_write_chunk,   /* fnvo_write_chunk */
 481         NULL,                                   /* fnvo_rw_finish */
 482 };
 483 
 484 #endif  /* EFSYS_OPT_NVRAM_FALCON_BOOTROM */
 485 
 486 #if EFSYS_OPT_NVRAM_SFX7101
 487 
 488 static falcon_nvram_ops_t       __cs    __falcon_sfx7101_ops = {
 489         sfx7101_nvram_size,             /* fnvo_size */
 490         sfx7101_nvram_get_version,      /* fnvo_get_version */
 491         sfx7101_nvram_rw_start,         /* fnvo_rw_start */
 492         sfx7101_nvram_read_chunk,       /* fnvo_read_chunk */
 493         sfx7101_nvram_erase,            /* fnvo_erase */
 494         sfx7101_nvram_write_chunk,      /* fnvo_write_chunk */
 495         sfx7101_nvram_rw_finish,        /* fnvo_rw_finish */
 496 };
 497 
 498 #endif  /* EFSYS_OPT_NVRAM_SFX7101 */
 499 
 500 #if EFSYS_OPT_NVRAM_SFT9001
 501 
 502 static falcon_nvram_ops_t       __cs    __falcon_sft9001_ops = {
 503         sft9001_nvram_size,             /* fnvo_size */
 504         sft9001_nvram_get_version,      /* fnvo_get_version */
 505         sft9001_nvram_rw_start,         /* fnvo_rw_start */
 506         sft9001_nvram_read_chunk,       /* fnvo_read_chunk */
 507         sft9001_nvram_erase,            /* fnvo_erase */
 508         sft9001_nvram_write_chunk,      /* fnvo_write_chunk */
 509         sft9001_nvram_rw_finish,        /* fnvo_rw_finish */
 510 };
 511 
 512 #endif  /* EFSYS_OPT_NVRAM_SFT9001 */
 513 
 514 static  __checkReturn           int
 515 falcon_nvram_get_ops(
 516         __in                    efx_nic_t *enp,
 517         __in                    efx_nvram_type_t type,
 518         __out                   falcon_nvram_ops_t **fnvopp)
 519 {
 520         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 521         falcon_nvram_ops_t *fnvop;
 522         int rc;
 523 
 524         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
 525 
 526         switch (type) {
 527 #if EFSYS_OPT_NVRAM_FALCON_BOOTROM
 528         case EFX_NVRAM_BOOTROM_CFG:
 529                 fnvop = (falcon_nvram_ops_t *)&__falcon_nvram_bootrom_cfg_ops;
 530                 goto done;
 531 
 532         case EFX_NVRAM_BOOTROM:
 533                 fnvop = (falcon_nvram_ops_t *)&__falcon_nvram_bootrom_ops;
 534                 goto done;
 535 #endif
 536         case EFX_NVRAM_PHY:
 537                 switch (encp->enc_phy_type) {
 538 #if EFSYS_OPT_NVRAM_SFX7101
 539                 case EFX_PHY_SFX7101:
 540                         fnvop = (falcon_nvram_ops_t *)&__falcon_sfx7101_ops;
 541                         goto done;
 542 #endif  /* EFSYS_OPT_NVRAM_SFX7101 */
 543 
 544 #if EFSYS_OPT_NVRAM_SFT9001
 545                 case EFX_PHY_SFT9001B:
 546                         fnvop = (falcon_nvram_ops_t *)&__falcon_sft9001_ops;
 547                         goto done;
 548 #endif  /* EFSYS_OPT_NVRAM_SFT9001 */
 549 
 550                 default:
 551                         break;
 552                 }
 553 
 554                 break;
 555 
 556         default:
 557                 break;
 558         }
 559 
 560         rc = ENOTSUP;
 561         goto fail1;
 562 
 563 done:
 564         *fnvopp = fnvop;
 565 
 566         return (0);
 567 
 568 fail1:
 569         EFSYS_PROBE1(fail1, int, rc);
 570 
 571         return (rc);
 572 }
 573 
 574 #if EFSYS_OPT_DIAG
 575 
 576         __checkReturn           int
 577 falcon_nvram_test(
 578         __in                    efx_nic_t *enp)
 579 {
 580         efx_nic_cfg_t enc;
 581         int rc;
 582 
 583         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 584         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
 585 
 586         if ((rc = falcon_nic_cfg_build(enp, &enc)) != 0)
 587                 goto fail1;
 588 
 589         return (0);
 590 
 591 fail1:
 592         EFSYS_PROBE1(fail1, int, rc);
 593 
 594         return (rc);
 595 }
 596 
 597 #endif  /* EFSYS_OPT_DIAG */
 598 
 599         __checkReturn           int
 600 falcon_nvram_size(
 601         __in                    efx_nic_t *enp,
 602         __in                    efx_nvram_type_t type,
 603         __out                   size_t *sizep)
 604 {
 605         falcon_nvram_ops_t *fnvop;
 606         int rc;
 607 
 608         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 609         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
 610 
 611         if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
 612                 goto fail1;
 613 
 614         if ((rc = fnvop->fnvo_size(enp, sizep)) != 0)
 615                 goto fail2;
 616 
 617         return (0);
 618 
 619 fail2:
 620         EFSYS_PROBE(fail2);
 621 fail1:
 622         EFSYS_PROBE1(fail1, int, rc);
 623 
 624         return (rc);
 625 }
 626 
 627         __checkReturn           int
 628 falcon_nvram_get_version(
 629         __in                    efx_nic_t *enp,
 630         __in                    efx_nvram_type_t type,
 631         __out                   uint32_t *subtypep,
 632         __out_ecount(4)         uint16_t version[4])
 633 {
 634         falcon_nvram_ops_t *fnvop;
 635         int rc;
 636 
 637         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 638         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
 639 
 640         if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
 641                 goto fail1;
 642 
 643         if ((rc = fnvop->fnvo_get_version(enp, subtypep, version)) != 0)
 644                 goto fail2;
 645 
 646         return (0);
 647 
 648 fail2:
 649         EFSYS_PROBE(fail2);
 650 fail1:
 651         EFSYS_PROBE1(fail1, int, rc);
 652 
 653         return (rc);
 654 }
 655 
 656         __checkReturn           int
 657 falcon_nvram_rw_start(
 658         __in                    efx_nic_t *enp,
 659         __in                    efx_nvram_type_t type,
 660         __out                   size_t *chunk_sizep)
 661 {
 662         falcon_nvram_ops_t *fnvop;
 663         int rc;
 664 
 665         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 666         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
 667 
 668         if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
 669                 goto fail1;
 670 
 671         if ((rc = fnvop->fnvo_rw_start(enp, chunk_sizep)) != 0)
 672                 goto fail2;
 673 
 674         return (0);
 675 
 676 fail2:
 677         EFSYS_PROBE(fail2);
 678 fail1:
 679         EFSYS_PROBE1(fail1, int, rc);
 680 
 681         return (rc);
 682 }
 683 
 684         __checkReturn           int
 685 falcon_nvram_read_chunk(
 686         __in                    efx_nic_t *enp,
 687         __in                    efx_nvram_type_t type,
 688         __in                    unsigned int offset,
 689         __out_bcount(size)      caddr_t data,
 690         __in                    size_t size)
 691 {
 692         falcon_nvram_ops_t *fnvop;
 693         int rc;
 694 
 695         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 696         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
 697 
 698         if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
 699                 goto fail1;
 700 
 701         if ((rc = fnvop->fnvo_read_chunk(enp, offset, data, size)) != 0)
 702                 goto fail2;
 703 
 704         return (0);
 705 
 706 fail2:
 707         EFSYS_PROBE(fail2);
 708 fail1:
 709         EFSYS_PROBE1(fail1, int, rc);
 710 
 711         return (rc);
 712 }
 713 
 714         __checkReturn           int
 715 falcon_nvram_erase(
 716         __in                    efx_nic_t *enp,
 717         __in                    efx_nvram_type_t type)
 718 {
 719         falcon_nvram_ops_t *fnvop;
 720         int rc;
 721 
 722         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 723         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
 724 
 725         if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
 726                 goto fail1;
 727 
 728         if (fnvop->fnvo_erase != NULL) {
 729                 if ((rc = fnvop->fnvo_erase(enp)) != 0)
 730                         goto fail2;
 731         }
 732 
 733         return (0);
 734 
 735 fail2:
 736         EFSYS_PROBE(fail2);
 737 fail1:
 738         EFSYS_PROBE1(fail1, int, rc);
 739 
 740         return (rc);
 741 }
 742 
 743         __checkReturn           int
 744 falcon_nvram_write_chunk(
 745         __in                    efx_nic_t *enp,
 746         __in                    efx_nvram_type_t type,
 747         __in                    unsigned int offset,
 748         __in_bcount(size)       caddr_t data,
 749         __in                    size_t size)
 750 {
 751         falcon_nvram_ops_t *fnvop;
 752         int rc;
 753 
 754         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 755         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
 756 
 757         if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
 758                 goto fail1;
 759 
 760         if ((rc = fnvop->fnvo_write_chunk(enp, offset, data, size)) != 0)
 761                 goto fail2;
 762 
 763         return (0);
 764 
 765 fail2:
 766         EFSYS_PROBE(fail2);
 767 fail1:
 768         EFSYS_PROBE1(fail1, int, rc);
 769 
 770         return (rc);
 771 }
 772 
 773                                 void
 774 falcon_nvram_rw_finish(
 775         __in                    efx_nic_t *enp,
 776         __in                    efx_nvram_type_t type)
 777 {
 778         falcon_nvram_ops_t *fnvop;
 779         int rc;
 780 
 781         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 782         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
 783 
 784         rc = falcon_nvram_get_ops(enp, type, &fnvop);
 785         EFSYS_ASSERT(rc == 0);
 786         if (rc == 0) {
 787                 if (fnvop->fnvo_rw_finish != NULL)
 788                         fnvop->fnvo_rw_finish(enp);
 789         }
 790 }
 791 
 792         __checkReturn           int
 793 falcon_nvram_set_version(
 794         __in                    efx_nic_t *enp,
 795         __in                    efx_nvram_type_t type,
 796         __out                   uint16_t version[4])
 797 {
 798         falcon_nvram_ops_t *fnvop;
 799         uint32_t subtype;
 800         uint16_t old_version[4];
 801         int rc;
 802 
 803         _NOTE(ARGUNUSED(enp))
 804         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 805         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
 806 
 807         /*
 808          * There is no room on Falcon to version anything, so it's
 809          * inferred where possible from the underlying entity.
 810          */
 811         if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
 812                 goto fail1;
 813 
 814         /*
 815          * The user *really should be setting the version correctly
 816          */
 817         if ((rc = fnvop->fnvo_get_version(enp, &subtype, old_version)) != 0)
 818                 goto fail2;
 819         EFSYS_ASSERT(memcmp(old_version, version, sizeof (old_version)) == 0);
 820 
 821         return (0);
 822 
 823 fail2:
 824         EFSYS_PROBE(fail2);
 825 fail1:
 826         EFSYS_PROBE1(fail1, int, rc);
 827 
 828         return (rc);
 829 }
 830 
 831 #endif  /* EFSYS_OPT_NVRAM */
 832 
 833                 void
 834 falcon_nvram_fini(
 835         __in    efx_nic_t *enp)
 836 {
 837         (void) memset(&enp->en_u.falcon.enu_fsd, 0,
 838             sizeof (enp->en_u.falcon.enu_fsd));
 839 }
 840 
 841 #endif  /* EFSYS_OPT_FALCON */