1283514Sarybchik/*- 2300607Sarybchik * Copyright (c) 2010-2016 Solarflare Communications, Inc. 3283514Sarybchik * All rights reserved. 4283514Sarybchik * 5283514Sarybchik * This software was developed in part by OKTET Labs Ltd. under contract for 6283514Sarybchik * Solarflare Communications, Inc. 7283514Sarybchik * 8283514Sarybchik * Redistribution and use in source and binary forms, with or without 9283514Sarybchik * modification, are permitted provided that the following conditions 10283514Sarybchik * are met: 11283514Sarybchik * 1. Redistributions of source code must retain the above copyright 12283514Sarybchik * notice, this list of conditions and the following disclaimer. 13283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright 14283514Sarybchik * notice, this list of conditions and the following disclaimer in the 15283514Sarybchik * documentation and/or other materials provided with the distribution. 16283514Sarybchik * 17283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18283514Sarybchik * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19283514Sarybchik * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20283514Sarybchik * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21283514Sarybchik * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22283514Sarybchik * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23283514Sarybchik * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24283514Sarybchik * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25283514Sarybchik * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26283514Sarybchik * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27283514Sarybchik * SUCH DAMAGE. 28283514Sarybchik */ 29283514Sarybchik 30283514Sarybchik#include <sys/cdefs.h> 31283514Sarybchik__FBSDID("$FreeBSD: releng/11.0/sys/dev/sfxge/sfxge_nvram.c 300607 2016-05-24 12:16:57Z arybchik $"); 32283514Sarybchik 33283514Sarybchik 34283514Sarybchik#include <sys/types.h> 35283514Sarybchik#include <sys/malloc.h> 36283514Sarybchik 37283514Sarybchik#include "common/efx.h" 38283514Sarybchik#include "sfxge.h" 39283514Sarybchik 40283514Sarybchik/* These data make no real sense, they are here just to make sfupdate happy. 41283514Sarybchik * Any code that would rely on it is broken. 42283514Sarybchik */ 43283514Sarybchikstatic const uint8_t fake_dynamic_cfg_nvram[] = { 44283514Sarybchik 0x7a, 0xda, 0x10, 0xef, 0x0c, 0x00, 0x00, 0x00, 45283514Sarybchik 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 46283514Sarybchik 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 47283514Sarybchik 0x08, 0x00, 0x00, 0x00, 0x90, 0x04, 0x00, 0x52, 48283514Sarybchik 0x56, 0x01, 0xc3, 0x78, 0x01, 0x00, 0x03, 0x10, 49283514Sarybchik 0x08, 0x00, 0x00, 0x00, 0x90, 0x04, 0x00, 0x52, 50283514Sarybchik 0x56, 0x01, 0xc3, 0x78, 0x57, 0x1a, 0x10, 0xef, 51283514Sarybchik 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 52283514Sarybchik 0x02, 0x0b, 0x64, 0x7d, 0xee, 0xee, 0xee, 0xee 53283514Sarybchik}; 54283514Sarybchik 55283514Sarybchikstatic int 56283514Sarybchiksfxge_nvram_rw(struct sfxge_softc *sc, sfxge_ioc_t *ip, efx_nvram_type_t type, 57283514Sarybchik boolean_t write) 58283514Sarybchik{ 59283514Sarybchik efx_nic_t *enp = sc->enp; 60283514Sarybchik size_t total_size = ip->u.nvram.size; 61283514Sarybchik size_t chunk_size; 62283514Sarybchik off_t off; 63283514Sarybchik int rc = 0; 64283514Sarybchik uint8_t *buf; 65283514Sarybchik 66283514Sarybchik if (type == EFX_NVRAM_DYNAMIC_CFG && sc->family == EFX_FAMILY_SIENA) { 67283514Sarybchik if (write) 68283514Sarybchik return (0); 69283514Sarybchik rc = copyout(fake_dynamic_cfg_nvram, ip->u.nvram.data, 70283514Sarybchik MIN(total_size, sizeof(fake_dynamic_cfg_nvram))); 71283514Sarybchik return (rc); 72283514Sarybchik } 73283514Sarybchik 74283514Sarybchik if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0) 75283514Sarybchik goto fail1; 76283514Sarybchik 77283514Sarybchik buf = malloc(chunk_size, M_TEMP, M_WAITOK); 78283514Sarybchik 79283514Sarybchik off = 0; 80283514Sarybchik while (total_size) { 81283514Sarybchik size_t len = MIN(chunk_size, total_size); 82283514Sarybchik 83283514Sarybchik if (write) { 84283514Sarybchik rc = copyin(ip->u.nvram.data + off, buf, len); 85283514Sarybchik if (rc != 0) 86283514Sarybchik goto fail3; 87283514Sarybchik rc = efx_nvram_write_chunk(enp, type, 88283514Sarybchik ip->u.nvram.offset + off, buf, len); 89283514Sarybchik if (rc != 0) 90283514Sarybchik goto fail3; 91283514Sarybchik } else { 92283514Sarybchik rc = efx_nvram_read_chunk(enp, type, 93283514Sarybchik ip->u.nvram.offset + off, buf, len); 94283514Sarybchik if (rc != 0) 95283514Sarybchik goto fail3; 96283514Sarybchik rc = copyout(buf, ip->u.nvram.data + off, len); 97283514Sarybchik if (rc != 0) 98283514Sarybchik goto fail3; 99283514Sarybchik } 100283514Sarybchik 101283514Sarybchik total_size -= len; 102283514Sarybchik off += len; 103283514Sarybchik } 104283514Sarybchik 105283514Sarybchikfail3: 106283514Sarybchik free(buf, M_TEMP); 107283514Sarybchik efx_nvram_rw_finish(enp, type); 108283514Sarybchikfail1: 109283514Sarybchik return (rc); 110283514Sarybchik} 111283514Sarybchik 112283514Sarybchik 113283514Sarybchikstatic int 114283514Sarybchiksfxge_nvram_erase(struct sfxge_softc *sc, efx_nvram_type_t type) 115283514Sarybchik{ 116283514Sarybchik efx_nic_t *enp = sc->enp; 117283514Sarybchik size_t chunk_size; 118283514Sarybchik int rc = 0; 119283514Sarybchik 120283514Sarybchik if (type == EFX_NVRAM_DYNAMIC_CFG && sc->family == EFX_FAMILY_SIENA) 121283514Sarybchik return (0); 122283514Sarybchik 123283514Sarybchik if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0) 124283514Sarybchik return (rc); 125283514Sarybchik 126283514Sarybchik rc = efx_nvram_erase(enp, type); 127283514Sarybchik 128283514Sarybchik efx_nvram_rw_finish(enp, type); 129283514Sarybchik return (rc); 130283514Sarybchik} 131283514Sarybchik 132283514Sarybchikint 133283514Sarybchiksfxge_nvram_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ip) 134283514Sarybchik{ 135283514Sarybchik static const efx_nvram_type_t nvram_types[] = { 136283514Sarybchik [SFXGE_NVRAM_TYPE_BOOTROM] = EFX_NVRAM_BOOTROM, 137283514Sarybchik [SFXGE_NVRAM_TYPE_BOOTROM_CFG] = EFX_NVRAM_BOOTROM_CFG, 138283514Sarybchik [SFXGE_NVRAM_TYPE_MC] = EFX_NVRAM_MC_FIRMWARE, 139283514Sarybchik [SFXGE_NVRAM_TYPE_MC_GOLDEN] = EFX_NVRAM_MC_GOLDEN, 140283514Sarybchik [SFXGE_NVRAM_TYPE_PHY] = EFX_NVRAM_PHY, 141283514Sarybchik [SFXGE_NVRAM_TYPE_NULL_PHY] = EFX_NVRAM_NULLPHY, 142283514Sarybchik [SFXGE_NVRAM_TYPE_FPGA] = EFX_NVRAM_FPGA, 143283514Sarybchik [SFXGE_NVRAM_TYPE_FCFW] = EFX_NVRAM_FCFW, 144283514Sarybchik [SFXGE_NVRAM_TYPE_CPLD] = EFX_NVRAM_CPLD, 145283514Sarybchik [SFXGE_NVRAM_TYPE_FPGA_BACKUP] = EFX_NVRAM_FPGA_BACKUP, 146283514Sarybchik [SFXGE_NVRAM_TYPE_DYNAMIC_CFG] = EFX_NVRAM_DYNAMIC_CFG, 147283514Sarybchik }; 148283514Sarybchik 149283514Sarybchik efx_nic_t *enp = sc->enp; 150283514Sarybchik efx_nvram_type_t type; 151283514Sarybchik int rc = 0; 152283514Sarybchik 153283514Sarybchik if (ip->u.nvram.type > SFXGE_NVRAM_TYPE_DYNAMIC_CFG) 154283514Sarybchik return (EINVAL); 155283514Sarybchik type = nvram_types[ip->u.nvram.type]; 156283514Sarybchik if (type == EFX_NVRAM_MC_GOLDEN && 157283514Sarybchik (ip->u.nvram.op == SFXGE_NVRAM_OP_WRITE || 158283514Sarybchik ip->u.nvram.op == SFXGE_NVRAM_OP_ERASE || 159283514Sarybchik ip->u.nvram.op == SFXGE_NVRAM_OP_SET_VER)) 160283514Sarybchik return (EOPNOTSUPP); 161283514Sarybchik 162283514Sarybchik switch (ip->u.nvram.op) { 163283514Sarybchik case SFXGE_NVRAM_OP_SIZE: 164283514Sarybchik { 165283514Sarybchik size_t size; 166283514Sarybchik 167283514Sarybchik if (type == EFX_NVRAM_DYNAMIC_CFG && sc->family == EFX_FAMILY_SIENA) { 168283514Sarybchik ip->u.nvram.size = sizeof(fake_dynamic_cfg_nvram); 169283514Sarybchik } else { 170283514Sarybchik if ((rc = efx_nvram_size(enp, type, &size)) != 0) 171283514Sarybchik return (rc); 172283514Sarybchik ip->u.nvram.size = size; 173283514Sarybchik } 174283514Sarybchik break; 175283514Sarybchik } 176283514Sarybchik case SFXGE_NVRAM_OP_READ: 177283514Sarybchik rc = sfxge_nvram_rw(sc, ip, type, B_FALSE); 178283514Sarybchik break; 179283514Sarybchik case SFXGE_NVRAM_OP_WRITE: 180283514Sarybchik rc = sfxge_nvram_rw(sc, ip, type, B_TRUE); 181283514Sarybchik break; 182283514Sarybchik case SFXGE_NVRAM_OP_ERASE: 183283514Sarybchik rc = sfxge_nvram_erase(sc, type); 184283514Sarybchik break; 185283514Sarybchik case SFXGE_NVRAM_OP_GET_VER: 186283514Sarybchik rc = efx_nvram_get_version(enp, type, &ip->u.nvram.subtype, 187283514Sarybchik &ip->u.nvram.version[0]); 188283514Sarybchik break; 189283514Sarybchik case SFXGE_NVRAM_OP_SET_VER: 190283514Sarybchik rc = efx_nvram_set_version(enp, type, &ip->u.nvram.version[0]); 191283514Sarybchik break; 192283514Sarybchik default: 193283514Sarybchik rc = EOPNOTSUPP; 194283514Sarybchik break; 195283514Sarybchik } 196283514Sarybchik 197283514Sarybchik return (rc); 198283514Sarybchik} 199