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 }