1 /*-
2 * Copyright 2009 Solarflare Communications Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include "efsys.h"
30 #include "efx.h"
31 #include "efx_types.h"
32 #include "efx_regs.h"
33 #include "efx_impl.h"
34
35 #if EFSYS_OPT_NVRAM
36
37 #if EFSYS_OPT_FALCON
38
39 static efx_nvram_ops_t __cs __efx_nvram_falcon_ops = {
40 #if EFSYS_OPT_DIAG
41 falcon_nvram_test, /* envo_test */
42 #endif /* EFSYS_OPT_DIAG */
43 falcon_nvram_size, /* envo_size */
44 falcon_nvram_get_version, /* envo_get_version */
45 falcon_nvram_rw_start, /* envo_rw_start */
46 falcon_nvram_read_chunk, /* envo_read_chunk */
47 falcon_nvram_erase, /* envo_erase */
48 falcon_nvram_write_chunk, /* envo_write_chunk */
49 falcon_nvram_rw_finish, /* envo_rw_finish */
50 falcon_nvram_set_version, /* envo_set_version */
51 };
52
53 #endif /* EFSYS_OPT_FALCON */
54
55 #if EFSYS_OPT_SIENA
56
57 static efx_nvram_ops_t __cs __efx_nvram_siena_ops = {
58 #if EFSYS_OPT_DIAG
59 siena_nvram_test, /* envo_test */
60 #endif /* EFSYS_OPT_DIAG */
61 siena_nvram_size, /* envo_size */
62 siena_nvram_get_version, /* envo_get_version */
63 siena_nvram_rw_start, /* envo_rw_start */
64 siena_nvram_read_chunk, /* envo_read_chunk */
65 siena_nvram_erase, /* envo_erase */
66 siena_nvram_write_chunk, /* envo_write_chunk */
67 siena_nvram_rw_finish, /* envo_rw_finish */
68 siena_nvram_set_version, /* envo_set_version */
69 };
70
71 #endif /* EFSYS_OPT_SIENA */
72
73 __checkReturn int
efx_nvram_init(__in efx_nic_t * enp)74 efx_nvram_init(
75 __in efx_nic_t *enp)
76 {
77 efx_nvram_ops_t *envop;
78 int rc;
79
80 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
81 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
82 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
83
84 switch (enp->en_family) {
85 #if EFSYS_OPT_FALCON
86 case EFX_FAMILY_FALCON:
87 envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops;
88 break;
89 #endif /* EFSYS_OPT_FALCON */
90
91 #if EFSYS_OPT_SIENA
92 case EFX_FAMILY_SIENA:
93 envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops;
94 break;
95 #endif /* EFSYS_OPT_SIENA */
96
97 default:
98 EFSYS_ASSERT(0);
99 rc = ENOTSUP;
100 goto fail1;
101 }
102
103 enp->en_envop = envop;
104 enp->en_mod_flags |= EFX_MOD_NVRAM;
105
106 return (0);
107
108 fail1:
109 EFSYS_PROBE1(fail1, int, rc);
110
111 return (rc);
112 }
113
114 #if EFSYS_OPT_DIAG
115
116 __checkReturn int
efx_nvram_test(__in efx_nic_t * enp)117 efx_nvram_test(
118 __in efx_nic_t *enp)
119 {
120 efx_nvram_ops_t *envop = enp->en_envop;
121 int rc;
122
123 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
124 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
125
126 if ((rc = envop->envo_test(enp)) != 0)
127 goto fail1;
128
129 return (0);
130
131 fail1:
132 EFSYS_PROBE1(fail1, int, rc);
133
134 return (rc);
135 }
136
137 #endif /* EFSYS_OPT_DIAG */
138
139 __checkReturn int
efx_nvram_size(__in efx_nic_t * enp,__in efx_nvram_type_t type,__out size_t * sizep)140 efx_nvram_size(
141 __in efx_nic_t *enp,
142 __in efx_nvram_type_t type,
143 __out size_t *sizep)
144 {
145 efx_nvram_ops_t *envop = enp->en_envop;
146 int rc;
147
148 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
149 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
150
151 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
152
153 if ((rc = envop->envo_size(enp, type, sizep)) != 0)
154 goto fail1;
155
156 return (0);
157
158 fail1:
159 EFSYS_PROBE1(fail1, int, rc);
160
161 return (rc);
162 }
163
164 __checkReturn int
165 efx_nvram_get_version(
166 __in efx_nic_t *enp,
167 __in efx_nvram_type_t type,
168 __out uint32_t *subtypep,
169 __out_ecount(4) uint16_t version[4])
170 {
171 efx_nvram_ops_t *envop = enp->en_envop;
172 int rc;
173
174 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
175 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
176 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
177
178 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
179
180 if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0)
181 goto fail1;
182
183 return (0);
184
185 fail1:
186 EFSYS_PROBE1(fail1, int, rc);
187
188 return (rc);
189 }
190
191 __checkReturn int
efx_nvram_rw_start(__in efx_nic_t * enp,__in efx_nvram_type_t type,__out_opt size_t * chunk_sizep)192 efx_nvram_rw_start(
193 __in efx_nic_t *enp,
194 __in efx_nvram_type_t type,
195 __out_opt size_t *chunk_sizep)
196 {
197 efx_nvram_ops_t *envop = enp->en_envop;
198 int rc;
199
200 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
201 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
202
203 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
204 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
205
206 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
207
208 if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0)
209 goto fail1;
210
211 enp->en_nvram_locked = type;
212
213 return (0);
214
215 fail1:
216 EFSYS_PROBE1(fail1, int, rc);
217
218 return (rc);
219 }
220
221 __checkReturn int
efx_nvram_read_chunk(__in efx_nic_t * enp,__in efx_nvram_type_t type,__in unsigned int offset,__out_bcount (size)caddr_t data,__in size_t size)222 efx_nvram_read_chunk(
223 __in efx_nic_t *enp,
224 __in efx_nvram_type_t type,
225 __in unsigned int offset,
226 __out_bcount(size) caddr_t data,
227 __in size_t size)
228 {
229 efx_nvram_ops_t *envop = enp->en_envop;
230 int rc;
231
232 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
233 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
234
235 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
236 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
237
238 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
239
240 if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0)
241 goto fail1;
242
243 return (0);
244
245 fail1:
246 EFSYS_PROBE1(fail1, int, rc);
247
248 return (rc);
249 }
250
251 __checkReturn int
efx_nvram_erase(__in efx_nic_t * enp,__in efx_nvram_type_t type)252 efx_nvram_erase(
253 __in efx_nic_t *enp,
254 __in efx_nvram_type_t type)
255 {
256 efx_nvram_ops_t *envop = enp->en_envop;
257 int rc;
258
259 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
260 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
261
262 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
263 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
264
265 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
266
267 if ((rc = envop->envo_erase(enp, type)) != 0)
268 goto fail1;
269
270 return (0);
271
272 fail1:
273 EFSYS_PROBE1(fail1, int, rc);
274
275 return (rc);
276 }
277
278 __checkReturn int
efx_nvram_write_chunk(__in efx_nic_t * enp,__in efx_nvram_type_t type,__in unsigned int offset,__in_bcount (size)caddr_t data,__in size_t size)279 efx_nvram_write_chunk(
280 __in efx_nic_t *enp,
281 __in efx_nvram_type_t type,
282 __in unsigned int offset,
283 __in_bcount(size) caddr_t data,
284 __in size_t size)
285 {
286 efx_nvram_ops_t *envop = enp->en_envop;
287 int rc;
288
289 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
290 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
291
292 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
293 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
294
295 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
296
297 if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0)
298 goto fail1;
299
300 return (0);
301
302 fail1:
303 EFSYS_PROBE1(fail1, int, rc);
304
305 return (rc);
306 }
307
308 void
efx_nvram_rw_finish(__in efx_nic_t * enp,__in efx_nvram_type_t type)309 efx_nvram_rw_finish(
310 __in efx_nic_t *enp,
311 __in efx_nvram_type_t type)
312 {
313 efx_nvram_ops_t *envop = enp->en_envop;
314
315 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
316 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
317
318 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
319 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
320
321 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
322
323 envop->envo_rw_finish(enp, type);
324
325 enp->en_nvram_locked = EFX_NVRAM_INVALID;
326 }
327
328 __checkReturn int
efx_nvram_set_version(__in efx_nic_t * enp,__in efx_nvram_type_t type,__out uint16_t version[4])329 efx_nvram_set_version(
330 __in efx_nic_t *enp,
331 __in efx_nvram_type_t type,
332 __out uint16_t version[4])
333 {
334 efx_nvram_ops_t *envop = enp->en_envop;
335 int rc;
336
337 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
338 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
339 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
340
341 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
342
343 /*
344 * The Siena implementation of envo_set_version() will attempt to
345 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
346 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
347 */
348 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
349
350 if ((rc = envop->envo_set_version(enp, type, version)) != 0)
351 goto fail1;
352
353 return (0);
354
355 fail1:
356 EFSYS_PROBE1(fail1, int, rc);
357
358 return (rc);
359 }
360
361 void
efx_nvram_fini(__in efx_nic_t * enp)362 efx_nvram_fini(
363 __in efx_nic_t *enp)
364 {
365 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
366 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
367 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
368
369 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
370
371 enp->en_envop = NULL;
372 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
373 }
374
375 #endif /* EFSYS_OPT_NVRAM */
376