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 "efsys.h"
27 #include "efx.h"
28 #include "efx_types.h"
29 #include "efx_regs.h"
30 #include "efx_impl.h"
31
32 #if EFSYS_OPT_NVRAM
33
34 #if EFSYS_OPT_FALCON
35
36 static efx_nvram_ops_t __cs __efx_nvram_falcon_ops = {
37 #if EFSYS_OPT_DIAG
38 falcon_nvram_test, /* envo_test */
39 #endif /* EFSYS_OPT_DIAG */
40 falcon_nvram_size, /* envo_size */
41 falcon_nvram_get_version, /* envo_get_version */
42 falcon_nvram_rw_start, /* envo_rw_start */
43 falcon_nvram_read_chunk, /* envo_read_chunk */
44 falcon_nvram_erase, /* envo_erase */
45 falcon_nvram_write_chunk, /* envo_write_chunk */
46 falcon_nvram_rw_finish, /* envo_rw_finish */
47 falcon_nvram_set_version, /* envo_set_version */
48 };
49
50 #endif /* EFSYS_OPT_FALCON */
51
52 #if EFSYS_OPT_SIENA
53
54 static efx_nvram_ops_t __cs __efx_nvram_siena_ops = {
55 #if EFSYS_OPT_DIAG
56 siena_nvram_test, /* envo_test */
57 #endif /* EFSYS_OPT_DIAG */
58 siena_nvram_size, /* envo_size */
59 siena_nvram_get_version, /* envo_get_version */
60 siena_nvram_rw_start, /* envo_rw_start */
61 siena_nvram_read_chunk, /* envo_read_chunk */
62 siena_nvram_erase, /* envo_erase */
63 siena_nvram_write_chunk, /* envo_write_chunk */
64 siena_nvram_rw_finish, /* envo_rw_finish */
65 siena_nvram_set_version, /* envo_set_version */
66 };
67
68 #endif /* EFSYS_OPT_SIENA */
69
70 __checkReturn int
71 efx_nvram_init(
72 __in efx_nic_t *enp)
73 {
74 efx_nvram_ops_t *envop;
75 int rc;
76
77 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
78 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
79 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
80
81 switch (enp->en_family) {
82 #if EFSYS_OPT_FALCON
83 case EFX_FAMILY_FALCON:
84 envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops;
85 break;
86 #endif /* EFSYS_OPT_FALCON */
87
88 #if EFSYS_OPT_SIENA
89 case EFX_FAMILY_SIENA:
90 envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops;
91 break;
92 #endif /* EFSYS_OPT_SIENA */
93
94 default:
95 EFSYS_ASSERT(0);
96 rc = ENOTSUP;
97 goto fail1;
98 }
99
100 enp->en_envop = envop;
101 enp->en_mod_flags |= EFX_MOD_NVRAM;
102
103 return (0);
104
105 fail1:
106 EFSYS_PROBE1(fail1, int, rc);
107
108 return (rc);
109 }
110
111 #if EFSYS_OPT_DIAG
112
113 __checkReturn int
114 efx_nvram_test(
115 __in efx_nic_t *enp)
116 {
117 efx_nvram_ops_t *envop = enp->en_envop;
118 int rc;
119
120 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
121 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
122
123 if ((rc = envop->envo_test(enp)) != 0)
124 goto fail1;
125
126 return (0);
127
128 fail1:
129 EFSYS_PROBE1(fail1, int, rc);
130
131 return (rc);
132 }
133
134 #endif /* EFSYS_OPT_DIAG */
135
136 __checkReturn int
137 efx_nvram_size(
138 __in efx_nic_t *enp,
139 __in efx_nvram_type_t type,
140 __out size_t *sizep)
141 {
142 efx_nvram_ops_t *envop = enp->en_envop;
143 int rc;
144
145 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
146 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
147
148 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
149
150 if ((rc = envop->envo_size(enp, type, sizep)) != 0)
151 goto fail1;
152
153 return (0);
154
155 fail1:
156 EFSYS_PROBE1(fail1, int, rc);
157
158 return (rc);
159 }
160
161 __checkReturn int
162 efx_nvram_get_version(
163 __in efx_nic_t *enp,
164 __in efx_nvram_type_t type,
165 __out uint32_t *subtypep,
166 __out_ecount(4) uint16_t version[4])
167 {
168 efx_nvram_ops_t *envop = enp->en_envop;
169 int rc;
170
171 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
172 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
173 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
174
175 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
176
177 if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0)
178 goto fail1;
179
180 return (0);
181
182 fail1:
183 EFSYS_PROBE1(fail1, int, rc);
184
185 return (rc);
186 }
187
188 __checkReturn int
189 efx_nvram_rw_start(
190 __in efx_nic_t *enp,
191 __in efx_nvram_type_t type,
192 __out_opt size_t *chunk_sizep)
193 {
194 efx_nvram_ops_t *envop = enp->en_envop;
195 int rc;
196
197 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
198 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
199
200 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
201 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
202
203 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
204
205 if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0)
206 goto fail1;
207
208 enp->en_nvram_locked = type;
209
210 return (0);
211
212 fail1:
213 EFSYS_PROBE1(fail1, int, rc);
214
215 return (rc);
216 }
217
218 __checkReturn int
219 efx_nvram_read_chunk(
220 __in efx_nic_t *enp,
221 __in efx_nvram_type_t type,
222 __in unsigned int offset,
223 __out_bcount(size) caddr_t data,
224 __in size_t size)
225 {
226 efx_nvram_ops_t *envop = enp->en_envop;
227 int rc;
228
229 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
230 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
231
232 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
233 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
234
235 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
236
237 if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0)
238 goto fail1;
239
240 return (0);
241
242 fail1:
243 EFSYS_PROBE1(fail1, int, rc);
244
245 return (rc);
246 }
247
248 __checkReturn int
249 efx_nvram_erase(
250 __in efx_nic_t *enp,
251 __in efx_nvram_type_t type)
252 {
253 efx_nvram_ops_t *envop = enp->en_envop;
254 int rc;
255
256 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
257 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
258
259 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
260 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
261
262 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
263
264 if ((rc = envop->envo_erase(enp, type)) != 0)
265 goto fail1;
266
267 return (0);
268
269 fail1:
270 EFSYS_PROBE1(fail1, int, rc);
271
272 return (rc);
273 }
274
275 __checkReturn int
276 efx_nvram_write_chunk(
277 __in efx_nic_t *enp,
278 __in efx_nvram_type_t type,
279 __in unsigned int offset,
280 __in_bcount(size) caddr_t data,
281 __in size_t size)
282 {
283 efx_nvram_ops_t *envop = enp->en_envop;
284 int rc;
285
286 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
287 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
288
289 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
290 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
291
292 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
293
294 if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0)
295 goto fail1;
296
297 return (0);
298
299 fail1:
300 EFSYS_PROBE1(fail1, int, rc);
301
302 return (rc);
303 }
304
305 void
306 efx_nvram_rw_finish(
307 __in efx_nic_t *enp,
308 __in efx_nvram_type_t type)
309 {
310 efx_nvram_ops_t *envop = enp->en_envop;
311
312 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
314
315 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
316 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
317
318 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
319
320 envop->envo_rw_finish(enp, type);
321
322 enp->en_nvram_locked = EFX_NVRAM_INVALID;
323 }
324
325 __checkReturn int
326 efx_nvram_set_version(
327 __in efx_nic_t *enp,
328 __in efx_nvram_type_t type,
329 __out uint16_t version[4])
330 {
331 efx_nvram_ops_t *envop = enp->en_envop;
332 int rc;
333
334 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
335 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
336 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
337
338 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
339
340 /*
341 * The Siena implementation of envo_set_version() will attempt to
342 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
343 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
344 */
345 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
346
347 if ((rc = envop->envo_set_version(enp, type, version)) != 0)
348 goto fail1;
349
350 return (0);
351
352 fail1:
353 EFSYS_PROBE1(fail1, int, rc);
354
355 return (rc);
356 }
357
358 void
359 efx_nvram_fini(
360 __in efx_nic_t *enp)
361 {
362 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
363 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
364 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
365
366 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
367
368 enp->en_envop = NULL;
369 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
370 }
371
372 #endif /* EFSYS_OPT_NVRAM */