xref: /illumos-gate/usr/src/uts/common/io/sfxge/sfxge_nvram.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
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 }
211