/* * Copyright (c) 2009-2016 Solarflare Communications Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing official * policies, either expressed or implied, of the FreeBSD Project. */ #include #include #include #include #include #include "sfxge.h" static int sfxge_nvram_rw(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type, boolean_t write) { int (*op)(efx_nic_t *, efx_nvram_type_t, unsigned int, caddr_t, size_t); efx_nic_t *enp = sp->s_enp; size_t chunk_size; off_t off; int rc; op = (write) ? efx_nvram_write_chunk : efx_nvram_read_chunk; if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0) goto fail1; off = 0; while (snip->sni_size) { size_t len = MIN(chunk_size, snip->sni_size); caddr_t buf = (caddr_t)(&snip->sni_data[off]); if ((rc = op(enp, type, snip->sni_offset + off, buf, len)) != 0) goto fail2; snip->sni_size -= len; off += len; } efx_nvram_rw_finish(enp, type); return (0); fail2: DTRACE_PROBE(fail2); efx_nvram_rw_finish(enp, type); fail1: DTRACE_PROBE1(fail1, int, rc); return (rc); } static int sfxge_nvram_erase(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type) { efx_nic_t *enp = sp->s_enp; size_t chunk_size; int rc; _NOTE(ARGUNUSED(snip)); if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0) goto fail1; if ((rc = efx_nvram_erase(enp, type)) != 0) goto fail2; efx_nvram_rw_finish(enp, type); return (0); fail2: DTRACE_PROBE(fail2); efx_nvram_rw_finish(enp, type); fail1: DTRACE_PROBE1(fail1, int, rc); return (rc); } int sfxge_nvram_ioctl(sfxge_t *sp, sfxge_nvram_ioc_t *snip) { efx_nic_t *enp = sp->s_enp; efx_nvram_type_t type; int rc; switch (snip->sni_type) { case SFXGE_NVRAM_TYPE_BOOTROM: type = EFX_NVRAM_BOOTROM; break; case SFXGE_NVRAM_TYPE_BOOTROM_CFG: type = EFX_NVRAM_BOOTROM_CFG; break; case SFXGE_NVRAM_TYPE_MC: type = EFX_NVRAM_MC_FIRMWARE; break; case SFXGE_NVRAM_TYPE_MC_GOLDEN: type = EFX_NVRAM_MC_GOLDEN; if (snip->sni_op == SFXGE_NVRAM_OP_WRITE || snip->sni_op == SFXGE_NVRAM_OP_ERASE || snip->sni_op == SFXGE_NVRAM_OP_SET_VER) { rc = ENOTSUP; goto fail1; } break; case SFXGE_NVRAM_TYPE_PHY: type = EFX_NVRAM_PHY; break; case SFXGE_NVRAM_TYPE_NULL_PHY: type = EFX_NVRAM_NULLPHY; break; case SFXGE_NVRAM_TYPE_FPGA: /* PTP timestamping FPGA */ type = EFX_NVRAM_FPGA; break; case SFXGE_NVRAM_TYPE_FCFW: type = EFX_NVRAM_FCFW; break; case SFXGE_NVRAM_TYPE_CPLD: type = EFX_NVRAM_CPLD; break; case SFXGE_NVRAM_TYPE_FPGA_BACKUP: type = EFX_NVRAM_FPGA_BACKUP; break; case SFXGE_NVRAM_TYPE_DYNAMIC_CFG: type = EFX_NVRAM_DYNAMIC_CFG; break; default: rc = EINVAL; goto fail2; } if (snip->sni_size > sizeof (snip->sni_data)) { rc = ENOSPC; goto fail3; } switch (snip->sni_op) { case SFXGE_NVRAM_OP_SIZE: { size_t size; if ((rc = efx_nvram_size(enp, type, &size)) != 0) goto fail4; snip->sni_size = (uint32_t)size; break; } case SFXGE_NVRAM_OP_READ: if ((rc = sfxge_nvram_rw(sp, snip, type, B_FALSE)) != 0) goto fail4; break; case SFXGE_NVRAM_OP_WRITE: if ((rc = sfxge_nvram_rw(sp, snip, type, B_TRUE)) != 0) goto fail4; break; case SFXGE_NVRAM_OP_ERASE: if ((rc = sfxge_nvram_erase(sp, snip, type)) != 0) goto fail4; break; case SFXGE_NVRAM_OP_GET_VER: if ((rc = efx_nvram_get_version(enp, type, &snip->sni_subtype, &snip->sni_version[0])) != 0) goto fail4; break; case SFXGE_NVRAM_OP_SET_VER: if ((rc = efx_nvram_set_version(enp, type, &snip->sni_version[0])) != 0) goto fail4; break; default: rc = ENOTSUP; goto fail5; } return (0); fail5: DTRACE_PROBE(fail5); fail4: DTRACE_PROBE(fail4); fail3: DTRACE_PROBE(fail3); fail2: DTRACE_PROBE(fail2); fail1: DTRACE_PROBE1(fail1, int, rc); return (rc); }