sfxge_nvram.c revision 284555
1239671Srwatson/*-
2239671Srwatson * Copyright (c) 2010-2015 Solarflare Communications, Inc.
3244899Srwatson * All rights reserved.
4239671Srwatson *
5239671Srwatson * This software was developed in part by OKTET Labs Ltd. under contract for
6244899Srwatson * Solarflare Communications, Inc.
7244899Srwatson *
8244899Srwatson * Redistribution and use in source and binary forms, with or without
9244899Srwatson * modification, are permitted provided that the following conditions
10239671Srwatson * are met:
11239671Srwatson * 1. Redistributions of source code must retain the above copyright
12239671Srwatson *    notice, this list of conditions and the following disclaimer.
13239671Srwatson * 2. Redistributions in binary form must reproduce the above copyright
14239671Srwatson *    notice, this list of conditions and the following disclaimer in the
15239671Srwatson *    documentation and/or other materials provided with the distribution.
16239671Srwatson *
17239671Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18239671Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19239671Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20239671Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21239671Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22239671Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23239671Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24239671Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25239671Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26239671Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27239671Srwatson * SUCH DAMAGE.
28239671Srwatson */
29239671Srwatson
30239671Srwatson#include <sys/cdefs.h>
31239671Srwatson__FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/sfxge_nvram.c 284555 2015-06-18 15:46:39Z arybchik $");
32239671Srwatson
33239671Srwatson
34239671Srwatson#include <sys/types.h>
35244899Srwatson#include <sys/malloc.h>
36239671Srwatson
37239671Srwatson#include "common/efx.h"
38239671Srwatson#include "sfxge.h"
39239671Srwatson
40239671Srwatson/* These data make no real sense, they are here just to make sfupdate happy.
41239671Srwatson * Any code that would rely on it is broken.
42239671Srwatson */
43239671Srwatsonstatic const uint8_t fake_dynamic_cfg_nvram[] = {
44239671Srwatson	0x7a, 0xda, 0x10, 0xef, 0x0c, 0x00, 0x00, 0x00,
45239671Srwatson	0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
46239671Srwatson	0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10,
47239671Srwatson	0x08, 0x00, 0x00, 0x00, 0x90, 0x04, 0x00, 0x52,
48245330Srwatson	0x56, 0x01, 0xc3, 0x78, 0x01, 0x00, 0x03, 0x10,
49239671Srwatson	0x08, 0x00, 0x00, 0x00, 0x90, 0x04, 0x00, 0x52,
50239671Srwatson	0x56, 0x01, 0xc3, 0x78, 0x57, 0x1a, 0x10, 0xef,
51239671Srwatson	0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
52239671Srwatson	0x02, 0x0b, 0x64, 0x7d, 0xee, 0xee, 0xee, 0xee
53239671Srwatson};
54239671Srwatson
55239671Srwatsonstatic int
56239671Srwatsonsfxge_nvram_rw(struct sfxge_softc *sc, sfxge_ioc_t *ip, efx_nvram_type_t type,
57239671Srwatson	       boolean_t write)
58239671Srwatson{
59244942Srwatson	efx_nic_t *enp = sc->enp;
60244899Srwatson	size_t total_size = ip->u.nvram.size;
61244899Srwatson	size_t chunk_size;
62244942Srwatson	off_t off;
63244899Srwatson	int rc = 0;
64239671Srwatson	uint8_t *buf;
65239671Srwatson
66239671Srwatson	if (type == EFX_NVRAM_DYNAMIC_CFG && sc->family == EFX_FAMILY_SIENA) {
67239671Srwatson		if (write)
68239671Srwatson			return (0);
69239671Srwatson		rc = copyout(fake_dynamic_cfg_nvram, ip->u.nvram.data,
70239671Srwatson			     MIN(total_size, sizeof(fake_dynamic_cfg_nvram)));
71239671Srwatson		return (rc);
72239671Srwatson	}
73245330Srwatson
74239671Srwatson	if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
75239671Srwatson		goto fail1;
76239671Srwatson
77239671Srwatson	buf = malloc(chunk_size, M_TEMP, M_WAITOK);
78239671Srwatson	if (buf == NULL) {
79239671Srwatson		rc = ENOMEM;
80239671Srwatson		goto fail2;
81239671Srwatson	}
82239671Srwatson
83239671Srwatson	off = 0;
84239671Srwatson	while (total_size) {
85239671Srwatson		size_t len = MIN(chunk_size, total_size);
86239671Srwatson
87239671Srwatson		if (write) {
88239671Srwatson			rc = copyin(ip->u.nvram.data + off, buf, len);
89239671Srwatson			if (rc != 0)
90239671Srwatson				goto fail3;
91239671Srwatson			rc = efx_nvram_write_chunk(enp, type,
92239671Srwatson						   ip->u.nvram.offset + off, buf, len);
93239671Srwatson			if (rc != 0)
94239671Srwatson				goto fail3;
95239671Srwatson		} else {
96239671Srwatson			rc = efx_nvram_read_chunk(enp, type,
97239671Srwatson						  ip->u.nvram.offset + off, buf, len);
98239671Srwatson			if (rc != 0)
99239671Srwatson				goto fail3;
100239671Srwatson			rc = copyout(buf, ip->u.nvram.data + off, len);
101239671Srwatson			if (rc != 0)
102239671Srwatson				goto fail3;
103239671Srwatson		}
104239671Srwatson
105239671Srwatson		total_size -= len;
106239671Srwatson		off += len;
107239671Srwatson	}
108239671Srwatson
109239671Srwatsonfail3:
110239671Srwatson	free(buf, M_TEMP);
111239671Srwatsonfail2:
112239671Srwatson	efx_nvram_rw_finish(enp, type);
113239671Srwatsonfail1:
114239671Srwatson	return (rc);
115239671Srwatson}
116239671Srwatson
117239671Srwatson
118239671Srwatsonstatic int
119239671Srwatsonsfxge_nvram_erase(struct sfxge_softc *sc, efx_nvram_type_t type)
120239671Srwatson{
121239671Srwatson	efx_nic_t *enp = sc->enp;
122239671Srwatson	size_t chunk_size;
123239671Srwatson	int rc = 0;
124261274Sbrooks
125261274Sbrooks	if (type == EFX_NVRAM_DYNAMIC_CFG && sc->family == EFX_FAMILY_SIENA)
126261274Sbrooks		return (0);
127261274Sbrooks
128261274Sbrooks	if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
129261274Sbrooks		return (rc);
130261274Sbrooks
131261274Sbrooks	rc = efx_nvram_erase(enp, type);
132239671Srwatson
133239671Srwatson	efx_nvram_rw_finish(enp, type);
134270058Sbz	return (rc);
135270058Sbz}
136270058Sbz
137270058Sbzint
138270058Sbzsfxge_nvram_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ip)
139270058Sbz{
140270058Sbz	static const efx_nvram_type_t nvram_types[] = {
141270058Sbz		[SFXGE_NVRAM_TYPE_BOOTROM]  = EFX_NVRAM_BOOTROM,
142270058Sbz		[SFXGE_NVRAM_TYPE_BOOTROM_CFG]  = EFX_NVRAM_BOOTROM_CFG,
143270058Sbz		[SFXGE_NVRAM_TYPE_MC]  = EFX_NVRAM_MC_FIRMWARE,
144270058Sbz		[SFXGE_NVRAM_TYPE_MC_GOLDEN]  = EFX_NVRAM_MC_GOLDEN,
145270058Sbz		[SFXGE_NVRAM_TYPE_PHY]  = EFX_NVRAM_PHY,
146270058Sbz		[SFXGE_NVRAM_TYPE_NULL_PHY]  = EFX_NVRAM_NULLPHY,
147270058Sbz		[SFXGE_NVRAM_TYPE_FPGA]  = EFX_NVRAM_FPGA,
148270058Sbz		[SFXGE_NVRAM_TYPE_FCFW]  = EFX_NVRAM_FCFW,
149270058Sbz		[SFXGE_NVRAM_TYPE_CPLD]  = EFX_NVRAM_CPLD,
150270058Sbz		[SFXGE_NVRAM_TYPE_FPGA_BACKUP]  = EFX_NVRAM_FPGA_BACKUP,
151270058Sbz		[SFXGE_NVRAM_TYPE_DYNAMIC_CFG]  = EFX_NVRAM_DYNAMIC_CFG,
152270058Sbz	};
153270058Sbz
154270058Sbz	efx_nic_t *enp = sc->enp;
155270058Sbz	efx_nvram_type_t type;
156270058Sbz	int rc = 0;
157270058Sbz
158270058Sbz	if (ip->u.nvram.type > SFXGE_NVRAM_TYPE_DYNAMIC_CFG)
159270058Sbz		return (EINVAL);
160270058Sbz	type = nvram_types[ip->u.nvram.type];
161270058Sbz	if (type == EFX_NVRAM_MC_GOLDEN &&
162270058Sbz	    (ip->u.nvram.op == SFXGE_NVRAM_OP_WRITE ||
163270058Sbz	     ip->u.nvram.op == SFXGE_NVRAM_OP_ERASE ||
164270058Sbz	     ip->u.nvram.op == SFXGE_NVRAM_OP_SET_VER))
165270058Sbz		return (EOPNOTSUPP);
166270058Sbz
167270058Sbz	switch (ip->u.nvram.op) {
168270058Sbz	case SFXGE_NVRAM_OP_SIZE:
169270058Sbz	{
170270058Sbz		size_t size;
171270058Sbz
172270058Sbz		if (type == EFX_NVRAM_DYNAMIC_CFG && sc->family == EFX_FAMILY_SIENA) {
173270058Sbz			ip->u.nvram.size = sizeof(fake_dynamic_cfg_nvram);
174239671Srwatson		} else {
175239671Srwatson			if ((rc = efx_nvram_size(enp, type, &size)) != 0)
176239671Srwatson				return (rc);
177239671Srwatson			ip->u.nvram.size = size;
178239671Srwatson		}
179239671Srwatson		break;
180239671Srwatson	}
181239671Srwatson	case SFXGE_NVRAM_OP_READ:
182239671Srwatson		rc = sfxge_nvram_rw(sc, ip, type, B_FALSE);
183239671Srwatson		break;
184245330Srwatson	case SFXGE_NVRAM_OP_WRITE:
185270058Sbz		rc = sfxge_nvram_rw(sc, ip, type, B_TRUE);
186245330Srwatson		break;
187270058Sbz	case SFXGE_NVRAM_OP_ERASE:
188245330Srwatson		rc = sfxge_nvram_erase(sc, type);
189245330Srwatson		break;
190239671Srwatson	case SFXGE_NVRAM_OP_GET_VER:
191239671Srwatson		rc = efx_nvram_get_version(enp, type, &ip->u.nvram.subtype,
192239671Srwatson					   &ip->u.nvram.version[0]);
193239671Srwatson		break;
194239671Srwatson	case SFXGE_NVRAM_OP_SET_VER:
195239671Srwatson		rc = efx_nvram_set_version(enp, type, &ip->u.nvram.version[0]);
196239671Srwatson		break;
197239671Srwatson	default:
198239671Srwatson		rc = EOPNOTSUPP;
199239671Srwatson		break;
200245329Srwatson	}
201245330Srwatson
202245330Srwatson	return (rc);
203245330Srwatson}
204245330Srwatson