1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/ddi.h>
  29 #include <sys/sunddi.h>
  30 #include <sys/stream.h>
  31 #include <sys/dlpi.h>
  32 
  33 #include "sfxge.h"
  34 
  35 int
  36 sfxge_nvram_rw(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type,
  37     boolean_t write)
  38 {
  39         int (*op)(efx_nic_t *, efx_nvram_type_t, unsigned int, caddr_t, size_t);
  40         efx_nic_t *enp = sp->s_enp;
  41         size_t chunk_size;
  42         off_t off;
  43         int rc;
  44 
  45         op = (write) ? efx_nvram_write_chunk : efx_nvram_read_chunk;
  46 
  47         if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
  48                 goto fail1;
  49 
  50         off = 0;
  51         while (snip->sni_size) {
  52                 size_t len = MIN(chunk_size, snip->sni_size);
  53                 caddr_t buf = (caddr_t)(&snip->sni_data[off]);
  54 
  55                 if ((rc = op(enp, type, snip->sni_offset + off, buf, len)) != 0)
  56                         goto fail2;
  57 
  58                 snip->sni_size -= len;
  59                 off += len;
  60         }
  61 
  62         efx_nvram_rw_finish(enp, type);
  63         return (0);
  64 
  65 fail2:
  66         DTRACE_PROBE(fail2);
  67         efx_nvram_rw_finish(enp, type);
  68 fail1:
  69         DTRACE_PROBE1(fail1, int, rc);
  70         return (rc);
  71 }
  72 
  73 
  74 int
  75 sfxge_nvram_erase(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type)
  76 {
  77         efx_nic_t *enp = sp->s_enp;
  78         size_t chunk_size;
  79         int rc;
  80 
  81         if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
  82                 goto fail1;
  83 
  84         if ((rc = efx_nvram_erase(enp, type)) != 0)
  85                 goto fail2;
  86 
  87         efx_nvram_rw_finish(enp, type);
  88         return (0);
  89 
  90 fail2:
  91         DTRACE_PROBE(fail2);
  92         efx_nvram_rw_finish(enp, type);
  93 fail1:
  94         DTRACE_PROBE1(fail1, int, rc);
  95         return (rc);
  96 }
  97 
  98 int
  99 sfxge_nvram_ioctl(sfxge_t *sp, sfxge_nvram_ioc_t *snip)
 100 {
 101         efx_nic_t *enp = sp->s_enp;
 102         efx_nvram_type_t type;
 103         int rc;
 104 
 105         if (snip->sni_type == SFXGE_NVRAM_TYPE_MC_GOLDEN &&
 106             (snip->sni_op == SFXGE_NVRAM_OP_WRITE ||
 107             snip->sni_op == SFXGE_NVRAM_OP_ERASE ||
 108             snip->sni_op == SFXGE_NVRAM_OP_SET_VER)) {
 109                 rc = ENOTSUP;
 110                 goto fail4;
 111         }
 112 
 113         switch (snip->sni_type) {
 114         case SFXGE_NVRAM_TYPE_BOOTROM:
 115                 type = EFX_NVRAM_BOOTROM;
 116                 break;
 117         case SFXGE_NVRAM_TYPE_BOOTROM_CFG:
 118                 type = EFX_NVRAM_BOOTROM_CFG;
 119                 break;
 120         case SFXGE_NVRAM_TYPE_MC:
 121                 type = EFX_NVRAM_MC_FIRMWARE;
 122                 break;
 123         case SFXGE_NVRAM_TYPE_MC_GOLDEN:
 124                 type = EFX_NVRAM_MC_GOLDEN;
 125                 break;
 126         case SFXGE_NVRAM_TYPE_PHY:
 127                 type = EFX_NVRAM_PHY;
 128                 break;
 129         case SFXGE_NVRAM_TYPE_NULL_PHY:
 130                 type = EFX_NVRAM_NULLPHY;
 131                 break;
 132         case SFXGE_NVRAM_TYPE_FPGA: /* PTP timestamping FPGA */
 133                 type = EFX_NVRAM_FPGA;
 134                 break;
 135         default:
 136                 rc = EINVAL;
 137                 goto fail1;
 138         }
 139 
 140         if (snip->sni_size > sizeof (snip->sni_data)) {
 141                 rc = ENOSPC;
 142                 goto fail2;
 143         }
 144 
 145         switch (snip->sni_op) {
 146         case SFXGE_NVRAM_OP_SIZE:
 147         {
 148                 size_t size;
 149                 if ((rc = efx_nvram_size(enp, type, &size)) != 0)
 150                         goto fail3;
 151                 snip->sni_size = size;
 152                 break;
 153         }
 154         case SFXGE_NVRAM_OP_READ:
 155                 if ((rc = sfxge_nvram_rw(sp, snip, type, B_FALSE)) != 0)
 156                         goto fail3;
 157                 break;
 158         case SFXGE_NVRAM_OP_WRITE:
 159                 if ((rc = sfxge_nvram_rw(sp, snip, type, B_TRUE)) != 0)
 160                         goto fail3;
 161                 break;
 162         case SFXGE_NVRAM_OP_ERASE:
 163                 if ((rc = sfxge_nvram_erase(sp, snip, type)) != 0)
 164                         goto fail3;
 165                 break;
 166         case SFXGE_NVRAM_OP_GET_VER:
 167                 if ((rc = efx_nvram_get_version(enp, type, &snip->sni_subtype,
 168                     &snip->sni_version[0])) != 0)
 169                         goto fail3;
 170                 break;
 171         case SFXGE_NVRAM_OP_SET_VER:
 172                 if ((rc = efx_nvram_set_version(enp, type,
 173                     &snip->sni_version[0])) != 0)
 174                         goto fail3;
 175                 break;
 176         default:
 177                 rc = ENOTSUP;
 178                 goto fail4;
 179         }
 180 
 181         return (0);
 182 
 183 fail4:
 184         DTRACE_PROBE(fail4);
 185 fail3:
 186         DTRACE_PROBE(fail3);
 187 fail2:
 188         DTRACE_PROBE(fail2);
 189 fail1:
 190         DTRACE_PROBE1(fail1, int, rc);
 191 
 192         return (rc);
 193 }