1 /*
   2  * Copyright (c) 2009-2016 Solarflare Communications Inc.
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions are met:
   7  *
   8  * 1. Redistributions of source code must retain the above copyright notice,
   9  *    this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright notice,
  11  *    this list of conditions and the following disclaimer in the documentation
  12  *    and/or other materials provided with the distribution.
  13  *
  14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25  *
  26  * The views and conclusions contained in the software and documentation are
  27  * those of the authors and should not be interpreted as representing official
  28  * policies, either expressed or implied, of the FreeBSD Project.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/ddi.h>
  33 #include <sys/sunddi.h>
  34 #include <sys/stream.h>
  35 #include <sys/dlpi.h>
  36 
  37 #include "sfxge.h"
  38 
  39 static int
  40 sfxge_nvram_rw(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type,
  41     boolean_t write)
  42 {
  43         int (*op)(efx_nic_t *, efx_nvram_type_t, unsigned int, caddr_t, size_t);
  44         efx_nic_t *enp = sp->s_enp;
  45         size_t chunk_size;
  46         off_t off;
  47         int rc;
  48 
  49         op = (write) ? efx_nvram_write_chunk : efx_nvram_read_chunk;
  50 
  51         if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
  52                 goto fail1;
  53 
  54         off = 0;
  55         while (snip->sni_size) {
  56                 size_t len = MIN(chunk_size, snip->sni_size);
  57                 caddr_t buf = (caddr_t)(&snip->sni_data[off]);
  58 
  59                 if ((rc = op(enp, type, snip->sni_offset + off, buf, len)) != 0)
  60                         goto fail2;
  61 
  62                 snip->sni_size -= len;
  63                 off += len;
  64         }
  65 
  66         efx_nvram_rw_finish(enp, type);
  67         return (0);
  68 
  69 fail2:
  70         DTRACE_PROBE(fail2);
  71         efx_nvram_rw_finish(enp, type);
  72 fail1:
  73         DTRACE_PROBE1(fail1, int, rc);
  74         return (rc);
  75 }
  76 
  77 
  78 static int
  79 sfxge_nvram_erase(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type)
  80 {
  81         efx_nic_t *enp = sp->s_enp;
  82         size_t chunk_size;
  83         int rc;
  84         _NOTE(ARGUNUSED(snip));
  85 
  86         if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
  87                 goto fail1;
  88 
  89         if ((rc = efx_nvram_erase(enp, type)) != 0)
  90                 goto fail2;
  91 
  92         efx_nvram_rw_finish(enp, type);
  93         return (0);
  94 
  95 fail2:
  96         DTRACE_PROBE(fail2);
  97         efx_nvram_rw_finish(enp, type);
  98 fail1:
  99         DTRACE_PROBE1(fail1, int, rc);
 100         return (rc);
 101 }
 102 
 103 int
 104 sfxge_nvram_ioctl(sfxge_t *sp, sfxge_nvram_ioc_t *snip)
 105 {
 106         efx_nic_t *enp = sp->s_enp;
 107         efx_nvram_type_t type;
 108         int rc;
 109 
 110         switch (snip->sni_type) {
 111         case SFXGE_NVRAM_TYPE_BOOTROM:
 112                 type = EFX_NVRAM_BOOTROM;
 113                 break;
 114         case SFXGE_NVRAM_TYPE_BOOTROM_CFG:
 115                 type = EFX_NVRAM_BOOTROM_CFG;
 116                 break;
 117         case SFXGE_NVRAM_TYPE_MC:
 118                 type = EFX_NVRAM_MC_FIRMWARE;
 119                 break;
 120         case SFXGE_NVRAM_TYPE_MC_GOLDEN:
 121                 type = EFX_NVRAM_MC_GOLDEN;
 122                 if (snip->sni_op == SFXGE_NVRAM_OP_WRITE ||
 123                     snip->sni_op == SFXGE_NVRAM_OP_ERASE ||
 124                     snip->sni_op == SFXGE_NVRAM_OP_SET_VER) {
 125                         rc = ENOTSUP;
 126                         goto fail1;
 127                 }
 128                 break;
 129         case SFXGE_NVRAM_TYPE_PHY:
 130                 type = EFX_NVRAM_PHY;
 131                 break;
 132         case SFXGE_NVRAM_TYPE_NULL_PHY:
 133                 type = EFX_NVRAM_NULLPHY;
 134                 break;
 135         case SFXGE_NVRAM_TYPE_FPGA: /* PTP timestamping FPGA */
 136                 type = EFX_NVRAM_FPGA;
 137                 break;
 138         case SFXGE_NVRAM_TYPE_FCFW:
 139                 type = EFX_NVRAM_FCFW;
 140                 break;
 141         case SFXGE_NVRAM_TYPE_CPLD:
 142                 type = EFX_NVRAM_CPLD;
 143                 break;
 144         case SFXGE_NVRAM_TYPE_FPGA_BACKUP:
 145                 type = EFX_NVRAM_FPGA_BACKUP;
 146                 break;
 147         case SFXGE_NVRAM_TYPE_DYNAMIC_CFG:
 148                 type = EFX_NVRAM_DYNAMIC_CFG;
 149                 break;
 150         default:
 151                 rc = EINVAL;
 152                 goto fail2;
 153         }
 154 
 155         if (snip->sni_size > sizeof (snip->sni_data)) {
 156                 rc = ENOSPC;
 157                 goto fail3;
 158         }
 159 
 160         switch (snip->sni_op) {
 161         case SFXGE_NVRAM_OP_SIZE:
 162         {
 163                 size_t size;
 164                 if ((rc = efx_nvram_size(enp, type, &size)) != 0)
 165                         goto fail4;
 166                 snip->sni_size = (uint32_t)size;
 167                 break;
 168         }
 169         case SFXGE_NVRAM_OP_READ:
 170                 if ((rc = sfxge_nvram_rw(sp, snip, type, B_FALSE)) != 0)
 171                         goto fail4;
 172                 break;
 173         case SFXGE_NVRAM_OP_WRITE:
 174                 if ((rc = sfxge_nvram_rw(sp, snip, type, B_TRUE)) != 0)
 175                         goto fail4;
 176                 break;
 177         case SFXGE_NVRAM_OP_ERASE:
 178                 if ((rc = sfxge_nvram_erase(sp, snip, type)) != 0)
 179                         goto fail4;
 180                 break;
 181         case SFXGE_NVRAM_OP_GET_VER:
 182                 if ((rc = efx_nvram_get_version(enp, type, &snip->sni_subtype,
 183                     &snip->sni_version[0])) != 0)
 184                         goto fail4;
 185                 break;
 186         case SFXGE_NVRAM_OP_SET_VER:
 187                 if ((rc = efx_nvram_set_version(enp, type,
 188                     &snip->sni_version[0])) != 0)
 189                         goto fail4;
 190                 break;
 191         default:
 192                 rc = ENOTSUP;
 193                 goto fail5;
 194         }
 195 
 196         return (0);
 197 
 198 fail5:
 199         DTRACE_PROBE(fail5);
 200 fail4:
 201         DTRACE_PROBE(fail4);
 202 fail3:
 203         DTRACE_PROBE(fail3);
 204 fail2:
 205         DTRACE_PROBE(fail2);
 206 fail1:
 207         DTRACE_PROBE1(fail1, int, rc);
 208 
 209         return (rc);
 210 }