]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/sfxge/common/efx_nvram.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / sfxge / common / efx_nvram.c
1 /*-
2  * Copyright (c) 2009-2015 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/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "efsys.h"
35 #include "efx.h"
36 #include "efx_types.h"
37 #include "efx_regs.h"
38 #include "efx_impl.h"
39
40 #if EFSYS_OPT_NVRAM
41
42 #if EFSYS_OPT_FALCON
43
44 static efx_nvram_ops_t  __efx_nvram_falcon_ops = {
45 #if EFSYS_OPT_DIAG
46         falcon_nvram_test,              /* envo_test */
47 #endif  /* EFSYS_OPT_DIAG */
48         falcon_nvram_size,              /* envo_size */
49         falcon_nvram_get_version,       /* envo_get_version */
50         falcon_nvram_rw_start,          /* envo_rw_start */
51         falcon_nvram_read_chunk,        /* envo_read_chunk */
52         falcon_nvram_erase,             /* envo_erase */
53         falcon_nvram_write_chunk,       /* envo_write_chunk */
54         falcon_nvram_rw_finish,         /* envo_rw_finish */
55         falcon_nvram_set_version,       /* envo_set_version */
56 };
57
58 #endif  /* EFSYS_OPT_FALCON */
59
60 #if EFSYS_OPT_SIENA
61
62 static efx_nvram_ops_t  __efx_nvram_siena_ops = {
63 #if EFSYS_OPT_DIAG
64         siena_nvram_test,               /* envo_test */
65 #endif  /* EFSYS_OPT_DIAG */
66         siena_nvram_size,               /* envo_size */
67         siena_nvram_get_version,        /* envo_get_version */
68         siena_nvram_rw_start,           /* envo_rw_start */
69         siena_nvram_read_chunk,         /* envo_read_chunk */
70         siena_nvram_erase,              /* envo_erase */
71         siena_nvram_write_chunk,        /* envo_write_chunk */
72         siena_nvram_rw_finish,          /* envo_rw_finish */
73         siena_nvram_set_version,        /* envo_set_version */
74 };
75
76 #endif  /* EFSYS_OPT_SIENA */
77
78 #if EFSYS_OPT_HUNTINGTON
79
80 static efx_nvram_ops_t  __efx_nvram_hunt_ops = {
81 #if EFSYS_OPT_DIAG
82         hunt_nvram_test,                /* envo_test */
83 #endif  /* EFSYS_OPT_DIAG */
84         hunt_nvram_size,                /* envo_size */
85         hunt_nvram_get_version,         /* envo_get_version */
86         hunt_nvram_rw_start,            /* envo_rw_start */
87         hunt_nvram_read_chunk,          /* envo_read_chunk */
88         hunt_nvram_erase,               /* envo_erase */
89         hunt_nvram_write_chunk,         /* envo_write_chunk */
90         hunt_nvram_rw_finish,           /* envo_rw_finish */
91         hunt_nvram_set_version,         /* envo_set_version */
92 };
93
94 #endif  /* EFSYS_OPT_HUNTINGTON */
95
96         __checkReturn   int
97 efx_nvram_init(
98         __in            efx_nic_t *enp)
99 {
100         efx_nvram_ops_t *envop;
101         int rc;
102
103         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
104         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
105         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
106
107         switch (enp->en_family) {
108 #if EFSYS_OPT_FALCON
109         case EFX_FAMILY_FALCON:
110                 envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops;
111                 break;
112 #endif  /* EFSYS_OPT_FALCON */
113
114 #if EFSYS_OPT_SIENA
115         case EFX_FAMILY_SIENA:
116                 envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops;
117                 break;
118 #endif  /* EFSYS_OPT_SIENA */
119
120 #if EFSYS_OPT_HUNTINGTON
121         case EFX_FAMILY_HUNTINGTON:
122                 envop = (efx_nvram_ops_t *)&__efx_nvram_hunt_ops;
123                 break;
124 #endif  /* EFSYS_OPT_HUNTINGTON */
125
126         default:
127                 EFSYS_ASSERT(0);
128                 rc = ENOTSUP;
129                 goto fail1;
130         }
131
132         enp->en_envop = envop;
133         enp->en_mod_flags |= EFX_MOD_NVRAM;
134
135         return (0);
136
137 fail1:
138         EFSYS_PROBE1(fail1, int, rc);
139
140         return (rc);
141 }
142
143 #if EFSYS_OPT_DIAG
144
145         __checkReturn           int
146 efx_nvram_test(
147         __in                    efx_nic_t *enp)
148 {
149         efx_nvram_ops_t *envop = enp->en_envop;
150         int rc;
151
152         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
153         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
154
155         if ((rc = envop->envo_test(enp)) != 0)
156                 goto fail1;
157
158         return (0);
159
160 fail1:
161         EFSYS_PROBE1(fail1, int, rc);
162
163         return (rc);
164 }
165
166 #endif  /* EFSYS_OPT_DIAG */
167
168         __checkReturn           int
169 efx_nvram_size(
170         __in                    efx_nic_t *enp,
171         __in                    efx_nvram_type_t type,
172         __out                   size_t *sizep)
173 {
174         efx_nvram_ops_t *envop = enp->en_envop;
175         int rc;
176
177         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
178         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
179
180         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
181
182         if ((rc = envop->envo_size(enp, type, sizep)) != 0)
183                 goto fail1;
184
185         return (0);
186
187 fail1:
188         EFSYS_PROBE1(fail1, int, rc);
189
190         return (rc);
191 }
192
193         __checkReturn           int
194 efx_nvram_get_version(
195         __in                    efx_nic_t *enp,
196         __in                    efx_nvram_type_t type,
197         __out                   uint32_t *subtypep,
198         __out_ecount(4)         uint16_t version[4])
199 {
200         efx_nvram_ops_t *envop = enp->en_envop;
201         int rc;
202
203         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
204         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
205         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
206
207         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
208
209         if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0)
210                 goto fail1;
211
212         return (0);
213
214 fail1:
215         EFSYS_PROBE1(fail1, int, rc);
216
217         return (rc);
218 }
219
220         __checkReturn           int
221 efx_nvram_rw_start(
222         __in                    efx_nic_t *enp,
223         __in                    efx_nvram_type_t type,
224         __out_opt               size_t *chunk_sizep)
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, ==, EFX_NVRAM_INVALID);
236
237         if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0)
238                 goto fail1;
239
240         enp->en_nvram_locked = type;
241
242         return (0);
243
244 fail1:
245         EFSYS_PROBE1(fail1, int, rc);
246
247         return (rc);
248 }
249
250         __checkReturn           int
251 efx_nvram_read_chunk(
252         __in                    efx_nic_t *enp,
253         __in                    efx_nvram_type_t type,
254         __in                    unsigned int offset,
255         __out_bcount(size)      caddr_t data,
256         __in                    size_t size)
257 {
258         efx_nvram_ops_t *envop = enp->en_envop;
259         int rc;
260
261         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
262         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
263
264         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
265         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
266
267         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
268
269         if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0)
270                 goto fail1;
271
272         return (0);
273
274 fail1:
275         EFSYS_PROBE1(fail1, int, rc);
276
277         return (rc);
278 }
279
280         __checkReturn           int
281 efx_nvram_erase(
282         __in                    efx_nic_t *enp,
283         __in                    efx_nvram_type_t type)
284 {
285         efx_nvram_ops_t *envop = enp->en_envop;
286         int rc;
287
288         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
289         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
290
291         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
292         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
293
294         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
295
296         if ((rc = envop->envo_erase(enp, type)) != 0)
297                 goto fail1;
298
299         return (0);
300
301 fail1:
302         EFSYS_PROBE1(fail1, int, rc);
303
304         return (rc);
305 }
306
307         __checkReturn           int
308 efx_nvram_write_chunk(
309         __in                    efx_nic_t *enp,
310         __in                    efx_nvram_type_t type,
311         __in                    unsigned int offset,
312         __in_bcount(size)       caddr_t data,
313         __in                    size_t size)
314 {
315         efx_nvram_ops_t *envop = enp->en_envop;
316         int rc;
317
318         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
319         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
320
321         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
322         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
323
324         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
325
326         if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0)
327                 goto fail1;
328
329         return (0);
330
331 fail1:
332         EFSYS_PROBE1(fail1, int, rc);
333
334         return (rc);
335 }
336
337                                 void
338 efx_nvram_rw_finish(
339         __in                    efx_nic_t *enp,
340         __in                    efx_nvram_type_t type)
341 {
342         efx_nvram_ops_t *envop = enp->en_envop;
343
344         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
345         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
346
347         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
348         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
349
350         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
351
352         envop->envo_rw_finish(enp, type);
353
354         enp->en_nvram_locked = EFX_NVRAM_INVALID;
355 }
356
357         __checkReturn           int
358 efx_nvram_set_version(
359         __in                    efx_nic_t *enp,
360         __in                    efx_nvram_type_t type,
361         __in_ecount(4)          uint16_t version[4])
362 {
363         efx_nvram_ops_t *envop = enp->en_envop;
364         int rc;
365
366         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
367         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
368         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
369
370         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
371
372         /*
373          * The Siena implementation of envo_set_version() will attempt to
374          * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
375          * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
376          */
377         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
378
379         if ((rc = envop->envo_set_version(enp, type, version)) != 0)
380                 goto fail1;
381
382         return (0);
383
384 fail1:
385         EFSYS_PROBE1(fail1, int, rc);
386
387         return (rc);
388 }
389
390 void
391 efx_nvram_fini(
392         __in            efx_nic_t *enp)
393 {
394         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
395         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
396         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
397
398         EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
399
400         enp->en_envop = NULL;
401         enp->en_mod_flags &= ~EFX_MOD_NVRAM;
402 }
403
404 #endif  /* EFSYS_OPT_NVRAM */
405
406 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
407
408 /*
409  * Internal MCDI request handling
410  */
411
412         __checkReturn           int
413 efx_mcdi_nvram_partitions(
414         __in                    efx_nic_t *enp,
415         __out_bcount(size)      caddr_t data,
416         __in                    size_t size,
417         __out                   unsigned int *npartnp)
418 {
419         efx_mcdi_req_t req;
420         uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
421                             MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
422         unsigned int npartn;
423         int rc;
424
425         (void) memset(payload, 0, sizeof (payload));
426         req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
427         req.emr_in_buf = payload;
428         req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
429         req.emr_out_buf = payload;
430         req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
431
432         efx_mcdi_execute(enp, &req);
433
434         if (req.emr_rc != 0) {
435                 rc = req.emr_rc;
436                 goto fail1;
437         }
438
439         if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
440                 rc = EMSGSIZE;
441                 goto fail2;
442         }
443         npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
444
445         if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
446                 rc = ENOENT;
447                 goto fail3;
448         }
449
450         if (size < npartn * sizeof (uint32_t)) {
451                 rc = ENOSPC;
452                 goto fail3;
453         }
454
455         *npartnp = npartn;
456
457         memcpy(data,
458             MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
459             (npartn * sizeof (uint32_t)));
460
461         return (0);
462
463 fail3:
464         EFSYS_PROBE(fail3);
465 fail2:
466         EFSYS_PROBE(fail2);
467 fail1:
468         EFSYS_PROBE1(fail1, int, rc);
469
470         return (rc);
471 }
472
473         __checkReturn           int
474 efx_mcdi_nvram_metadata(
475         __in                    efx_nic_t *enp,
476         __in                    uint32_t partn,
477         __out                   uint32_t *subtypep,
478         __out_ecount(4)         uint16_t version[4],
479         __out_bcount_opt(size)  char *descp,
480         __in                    size_t size)
481 {
482         efx_mcdi_req_t req;
483         uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
484                             MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
485         int rc;
486
487         (void) memset(payload, 0, sizeof (payload));
488         req.emr_cmd = MC_CMD_NVRAM_METADATA;
489         req.emr_in_buf = payload;
490         req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
491         req.emr_out_buf = payload;
492         req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
493
494         MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
495
496         efx_mcdi_execute(enp, &req);
497
498         if (req.emr_rc != 0) {
499                 rc = req.emr_rc;
500                 goto fail1;
501         }
502
503         if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
504                 rc = EMSGSIZE;
505                 goto fail2;
506         }
507
508         if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
509                 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
510                 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
511         } else {
512                 *subtypep = 0;
513         }
514
515         if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
516                 NVRAM_METADATA_OUT_VERSION_VALID)) {
517                 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
518                 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
519                 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
520                 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
521         } else {
522                 version[0] = version[1] = version[2] = version[3] = 0;
523         }
524
525         if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
526                 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
527                 /* Return optional descrition string */
528                 if ((descp != NULL) && (size > 0)) {
529                         size_t desclen;
530
531                         descp[0] = '\0';
532                         desclen = (req.emr_out_length_used
533                             - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
534
535                         EFSYS_ASSERT3U(desclen, <=,
536                             MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
537
538                         if (size < desclen) {
539                                 rc = ENOSPC;
540                                 goto fail3;
541                         }
542
543                         memcpy(descp, MCDI_OUT2(req, char,
544                                 NVRAM_METADATA_OUT_DESCRIPTION),
545                             desclen);
546
547                         /* Ensure string is NUL terminated */
548                         descp[desclen] = '\0';
549                 }
550         }
551
552         return (0);
553
554 fail3:
555         EFSYS_PROBE(fail3);
556 fail2:
557         EFSYS_PROBE(fail2);
558 fail1:
559         EFSYS_PROBE1(fail1, int, rc);
560
561         return (rc);
562 }
563
564         __checkReturn           int
565 efx_mcdi_nvram_info(
566         __in                    efx_nic_t *enp,
567         __in                    uint32_t partn,
568         __out_opt               size_t *sizep,
569         __out_opt               uint32_t *addressp,
570         __out_opt               uint32_t *erase_sizep)
571 {
572         uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
573                             MC_CMD_NVRAM_INFO_OUT_LEN)];
574         efx_mcdi_req_t req;
575         int rc;
576
577         (void) memset(payload, 0, sizeof (payload));
578         req.emr_cmd = MC_CMD_NVRAM_INFO;
579         req.emr_in_buf = payload;
580         req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
581         req.emr_out_buf = payload;
582         req.emr_out_length = MC_CMD_NVRAM_INFO_OUT_LEN;
583
584         MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
585
586         efx_mcdi_execute_quiet(enp, &req);
587
588         if (req.emr_rc != 0) {
589                 rc = req.emr_rc;
590                 goto fail1;
591         }
592
593         if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
594                 rc = EMSGSIZE;
595                 goto fail2;
596         }
597
598         if (sizep)
599                 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
600
601         if (addressp)
602                 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
603
604         if (erase_sizep)
605                 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
606
607         return (0);
608
609 fail2:
610         EFSYS_PROBE(fail2);
611 fail1:
612         EFSYS_PROBE1(fail1, int, rc);
613
614         return (rc);
615 }
616
617         __checkReturn           int
618 efx_mcdi_nvram_update_start(
619         __in                    efx_nic_t *enp,
620         __in                    uint32_t partn)
621 {
622         uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_IN_LEN,
623                             MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
624         efx_mcdi_req_t req;
625         int rc;
626
627         (void) memset(payload, 0, sizeof (payload));
628         req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
629         req.emr_in_buf = payload;
630         req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN;
631         req.emr_out_buf = payload;
632         req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
633
634         MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn);
635
636         efx_mcdi_execute(enp, &req);
637
638         if (req.emr_rc != 0) {
639                 rc = req.emr_rc;
640                 goto fail1;
641         }
642
643         return (0);
644
645 fail1:
646         EFSYS_PROBE1(fail1, int, rc);
647
648         return (rc);
649 }
650
651         __checkReturn           int
652 efx_mcdi_nvram_read(
653         __in                    efx_nic_t *enp,
654         __in                    uint32_t partn,
655         __in                    uint32_t offset,
656         __out_bcount(size)      caddr_t data,
657         __in                    size_t size)
658 {
659         efx_mcdi_req_t req;
660         uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_LEN,
661                             MC_CMD_NVRAM_READ_OUT_LENMAX)];
662         int rc;
663
664         if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
665                 rc = EINVAL;
666                 goto fail1;
667         }
668
669         (void) memset(payload, 0, sizeof (payload));
670         req.emr_cmd = MC_CMD_NVRAM_READ;
671         req.emr_in_buf = payload;
672         req.emr_in_length = MC_CMD_NVRAM_READ_IN_LEN;
673         req.emr_out_buf = payload;
674         req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
675
676         MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_TYPE, partn);
677         MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_OFFSET, offset);
678         MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_LENGTH, size);
679
680         efx_mcdi_execute(enp, &req);
681
682         if (req.emr_rc != 0) {
683                 rc = req.emr_rc;
684                 goto fail1;
685         }
686
687         if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
688                 rc = EMSGSIZE;
689                 goto fail2;
690         }
691
692         memcpy(data,
693             MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
694             size);
695
696         return (0);
697
698 fail2:
699         EFSYS_PROBE(fail2);
700 fail1:
701         EFSYS_PROBE1(fail1, int, rc);
702
703         return (rc);
704 }
705
706         __checkReturn           int
707 efx_mcdi_nvram_erase(
708         __in                    efx_nic_t *enp,
709         __in                    uint32_t partn,
710         __in                    uint32_t offset,
711         __in                    size_t size)
712 {
713         efx_mcdi_req_t req;
714         uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
715                             MC_CMD_NVRAM_ERASE_OUT_LEN)];
716         int rc;
717
718         (void) memset(payload, 0, sizeof (payload));
719         req.emr_cmd = MC_CMD_NVRAM_ERASE;
720         req.emr_in_buf = payload;
721         req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
722         req.emr_out_buf = payload;
723         req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
724
725         MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
726         MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
727         MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
728
729         efx_mcdi_execute(enp, &req);
730
731         if (req.emr_rc != 0) {
732                 rc = req.emr_rc;
733                 goto fail1;
734         }
735
736         return (0);
737
738 fail1:
739         EFSYS_PROBE1(fail1, int, rc);
740
741         return (rc);
742 }
743
744         __checkReturn           int
745 efx_mcdi_nvram_write(
746         __in                    efx_nic_t *enp,
747         __in                    uint32_t partn,
748         __in                    uint32_t offset,
749         __out_bcount(size)      caddr_t data,
750         __in                    size_t size)
751 {
752         efx_mcdi_req_t req;
753         uint8_t payload[MAX(MC_CMD_NVRAM_WRITE_IN_LENMAX,
754                             MC_CMD_NVRAM_WRITE_OUT_LEN)];
755         int rc;
756
757         if (size > MC_CMD_NVRAM_WRITE_IN_LENMAX) {
758                 rc = EINVAL;
759                 goto fail1;
760         }
761
762         (void) memset(payload, 0, sizeof (payload));
763         req.emr_cmd = MC_CMD_NVRAM_WRITE;
764         req.emr_in_buf = payload;
765         req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
766         req.emr_out_buf = payload;
767         req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
768
769         MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
770         MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
771         MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
772
773         memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
774             data, size);
775
776         efx_mcdi_execute(enp, &req);
777
778         if (req.emr_rc != 0) {
779                 rc = req.emr_rc;
780                 goto fail2;
781         }
782
783         return (0);
784
785 fail2:
786         EFSYS_PROBE(fail2);
787 fail1:
788         EFSYS_PROBE1(fail1, int, rc);
789
790         return (rc);
791 }
792
793         __checkReturn           int
794 efx_mcdi_nvram_update_finish(
795         __in                    efx_nic_t *enp,
796         __in                    uint32_t partn,
797         __in                    boolean_t reboot)
798 {
799         efx_mcdi_req_t req;
800         uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN,
801                             MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN)];
802         int rc;
803
804         (void) memset(payload, 0, sizeof (payload));
805         req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
806         req.emr_in_buf = payload;
807         req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN;
808         req.emr_out_buf = payload;
809         req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN;
810
811         MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn);
812         MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot);
813
814         efx_mcdi_execute(enp, &req);
815
816         if (req.emr_rc != 0) {
817                 rc = req.emr_rc;
818                 goto fail1;
819         }
820
821         return (0);
822
823 fail1:
824         EFSYS_PROBE1(fail1, int, rc);
825
826         return (rc);
827 }
828
829 #if EFSYS_OPT_DIAG
830
831         __checkReturn           int
832 efx_mcdi_nvram_test(
833         __in                    efx_nic_t *enp,
834         __in                    uint32_t partn)
835 {
836         efx_mcdi_req_t req;
837         uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
838                             MC_CMD_NVRAM_TEST_OUT_LEN)];
839         int result;
840         int rc;
841
842         (void) memset(payload, 0, sizeof (payload));
843         req.emr_cmd = MC_CMD_NVRAM_TEST;
844         req.emr_in_buf = payload;
845         req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
846         req.emr_out_buf = payload;
847         req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
848
849         MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
850
851         efx_mcdi_execute(enp, &req);
852
853         if (req.emr_rc != 0) {
854                 rc = req.emr_rc;
855                 goto fail1;
856         }
857
858         if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
859                 rc = EMSGSIZE;
860                 goto fail2;
861         }
862
863         result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
864         if (result == MC_CMD_NVRAM_TEST_FAIL) {
865
866                 EFSYS_PROBE1(nvram_test_failure, int, partn);
867
868                 rc = (EINVAL);
869                 goto fail3;
870         }
871
872         return (0);
873
874 fail3:
875         EFSYS_PROBE(fail3);
876 fail2:
877         EFSYS_PROBE(fail2);
878 fail1:
879         EFSYS_PROBE1(fail1, int, rc);
880
881         return (rc);
882 }
883
884 #endif  /* EFSYS_OPT_DIAG */
885
886
887 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */