1*49ef7e06SGarrett D'Amore /*
2*49ef7e06SGarrett D'Amore  * Copyright (c) 2009-2015 Solarflare Communications Inc.
3*49ef7e06SGarrett D'Amore  * All rights reserved.
4*49ef7e06SGarrett D'Amore  *
5*49ef7e06SGarrett D'Amore  * Redistribution and use in source and binary forms, with or without
6*49ef7e06SGarrett D'Amore  * modification, are permitted provided that the following conditions are met:
7*49ef7e06SGarrett D'Amore  *
8*49ef7e06SGarrett D'Amore  * 1. Redistributions of source code must retain the above copyright notice,
9*49ef7e06SGarrett D'Amore  *    this list of conditions and the following disclaimer.
10*49ef7e06SGarrett D'Amore  * 2. Redistributions in binary form must reproduce the above copyright notice,
11*49ef7e06SGarrett D'Amore  *    this list of conditions and the following disclaimer in the documentation
12*49ef7e06SGarrett D'Amore  *    and/or other materials provided with the distribution.
13*49ef7e06SGarrett D'Amore  *
14*49ef7e06SGarrett D'Amore  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15*49ef7e06SGarrett D'Amore  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*49ef7e06SGarrett D'Amore  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17*49ef7e06SGarrett D'Amore  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18*49ef7e06SGarrett D'Amore  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*49ef7e06SGarrett D'Amore  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*49ef7e06SGarrett D'Amore  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*49ef7e06SGarrett D'Amore  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*49ef7e06SGarrett D'Amore  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*49ef7e06SGarrett D'Amore  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24*49ef7e06SGarrett D'Amore  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*49ef7e06SGarrett D'Amore  *
26*49ef7e06SGarrett D'Amore  * The views and conclusions contained in the software and documentation are
27*49ef7e06SGarrett D'Amore  * those of the authors and should not be interpreted as representing official
28*49ef7e06SGarrett D'Amore  * policies, either expressed or implied, of the FreeBSD Project.
29*49ef7e06SGarrett D'Amore  */
30*49ef7e06SGarrett D'Amore 
31*49ef7e06SGarrett D'Amore #include "efx.h"
32*49ef7e06SGarrett D'Amore #include "efx_impl.h"
33*49ef7e06SGarrett D'Amore 
34*49ef7e06SGarrett D'Amore #if EFSYS_OPT_NVRAM
35*49ef7e06SGarrett D'Amore 
36*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
37*49ef7e06SGarrett D'Amore 
38*49ef7e06SGarrett D'Amore static const efx_nvram_ops_t	__efx_nvram_siena_ops = {
39*49ef7e06SGarrett D'Amore #if EFSYS_OPT_DIAG
40*49ef7e06SGarrett D'Amore 	siena_nvram_test,		/* envo_test */
41*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_DIAG */
42*49ef7e06SGarrett D'Amore 	siena_nvram_type_to_partn,	/* envo_type_to_partn */
43*49ef7e06SGarrett D'Amore 	siena_nvram_partn_size,		/* envo_partn_size */
44*49ef7e06SGarrett D'Amore 	siena_nvram_partn_rw_start,	/* envo_partn_rw_start */
45*49ef7e06SGarrett D'Amore 	siena_nvram_partn_read,		/* envo_partn_read */
46*49ef7e06SGarrett D'Amore 	siena_nvram_partn_erase,	/* envo_partn_erase */
47*49ef7e06SGarrett D'Amore 	siena_nvram_partn_write,	/* envo_partn_write */
48*49ef7e06SGarrett D'Amore 	siena_nvram_partn_rw_finish,	/* envo_partn_rw_finish */
49*49ef7e06SGarrett D'Amore 	siena_nvram_partn_get_version,	/* envo_partn_get_version */
50*49ef7e06SGarrett D'Amore 	siena_nvram_partn_set_version,	/* envo_partn_set_version */
51*49ef7e06SGarrett D'Amore 	NULL,				/* envo_partn_validate */
52*49ef7e06SGarrett D'Amore };
53*49ef7e06SGarrett D'Amore 
54*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_SIENA */
55*49ef7e06SGarrett D'Amore 
56*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
57*49ef7e06SGarrett D'Amore 
58*49ef7e06SGarrett D'Amore static const efx_nvram_ops_t	__efx_nvram_ef10_ops = {
59*49ef7e06SGarrett D'Amore #if EFSYS_OPT_DIAG
60*49ef7e06SGarrett D'Amore 	ef10_nvram_test,		/* envo_test */
61*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_DIAG */
62*49ef7e06SGarrett D'Amore 	ef10_nvram_type_to_partn,	/* envo_type_to_partn */
63*49ef7e06SGarrett D'Amore 	ef10_nvram_partn_size,		/* envo_partn_size */
64*49ef7e06SGarrett D'Amore 	ef10_nvram_partn_rw_start,	/* envo_partn_rw_start */
65*49ef7e06SGarrett D'Amore 	ef10_nvram_partn_read,		/* envo_partn_read */
66*49ef7e06SGarrett D'Amore 	ef10_nvram_partn_erase,		/* envo_partn_erase */
67*49ef7e06SGarrett D'Amore 	ef10_nvram_partn_write,		/* envo_partn_write */
68*49ef7e06SGarrett D'Amore 	ef10_nvram_partn_rw_finish,	/* envo_partn_rw_finish */
69*49ef7e06SGarrett D'Amore 	ef10_nvram_partn_get_version,	/* envo_partn_get_version */
70*49ef7e06SGarrett D'Amore 	ef10_nvram_partn_set_version,	/* envo_partn_set_version */
71*49ef7e06SGarrett D'Amore 	ef10_nvram_buffer_validate,	/* envo_buffer_validate */
72*49ef7e06SGarrett D'Amore };
73*49ef7e06SGarrett D'Amore 
74*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
75*49ef7e06SGarrett D'Amore 
76*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
efx_nvram_init(__in efx_nic_t * enp)77*49ef7e06SGarrett D'Amore efx_nvram_init(
78*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
79*49ef7e06SGarrett D'Amore {
80*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop;
81*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
82*49ef7e06SGarrett D'Amore 
83*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
84*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
85*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
86*49ef7e06SGarrett D'Amore 
87*49ef7e06SGarrett D'Amore 	switch (enp->en_family) {
88*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
89*49ef7e06SGarrett D'Amore 	case EFX_FAMILY_SIENA:
90*49ef7e06SGarrett D'Amore 		envop = &__efx_nvram_siena_ops;
91*49ef7e06SGarrett D'Amore 		break;
92*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_SIENA */
93*49ef7e06SGarrett D'Amore 
94*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON
95*49ef7e06SGarrett D'Amore 	case EFX_FAMILY_HUNTINGTON:
96*49ef7e06SGarrett D'Amore 		envop = &__efx_nvram_ef10_ops;
97*49ef7e06SGarrett D'Amore 		break;
98*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_HUNTINGTON */
99*49ef7e06SGarrett D'Amore 
100*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MEDFORD
101*49ef7e06SGarrett D'Amore 	case EFX_FAMILY_MEDFORD:
102*49ef7e06SGarrett D'Amore 		envop = &__efx_nvram_ef10_ops;
103*49ef7e06SGarrett D'Amore 		break;
104*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_MEDFORD */
105*49ef7e06SGarrett D'Amore 
106*49ef7e06SGarrett D'Amore 	default:
107*49ef7e06SGarrett D'Amore 		EFSYS_ASSERT(0);
108*49ef7e06SGarrett D'Amore 		rc = ENOTSUP;
109*49ef7e06SGarrett D'Amore 		goto fail1;
110*49ef7e06SGarrett D'Amore 	}
111*49ef7e06SGarrett D'Amore 
112*49ef7e06SGarrett D'Amore 	enp->en_envop = envop;
113*49ef7e06SGarrett D'Amore 	enp->en_mod_flags |= EFX_MOD_NVRAM;
114*49ef7e06SGarrett D'Amore 
115*49ef7e06SGarrett D'Amore 	return (0);
116*49ef7e06SGarrett D'Amore 
117*49ef7e06SGarrett D'Amore fail1:
118*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
119*49ef7e06SGarrett D'Amore 
120*49ef7e06SGarrett D'Amore 	return (rc);
121*49ef7e06SGarrett D'Amore }
122*49ef7e06SGarrett D'Amore 
123*49ef7e06SGarrett D'Amore #if EFSYS_OPT_DIAG
124*49ef7e06SGarrett D'Amore 
125*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_nvram_test(__in efx_nic_t * enp)126*49ef7e06SGarrett D'Amore efx_nvram_test(
127*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp)
128*49ef7e06SGarrett D'Amore {
129*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
130*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
131*49ef7e06SGarrett D'Amore 
132*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
133*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
134*49ef7e06SGarrett D'Amore 
135*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_test(enp)) != 0)
136*49ef7e06SGarrett D'Amore 		goto fail1;
137*49ef7e06SGarrett D'Amore 
138*49ef7e06SGarrett D'Amore 	return (0);
139*49ef7e06SGarrett D'Amore 
140*49ef7e06SGarrett D'Amore fail1:
141*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
142*49ef7e06SGarrett D'Amore 
143*49ef7e06SGarrett D'Amore 	return (rc);
144*49ef7e06SGarrett D'Amore }
145*49ef7e06SGarrett D'Amore 
146*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_DIAG */
147*49ef7e06SGarrett D'Amore 
148*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_nvram_size(__in efx_nic_t * enp,__in efx_nvram_type_t type,__out size_t * sizep)149*49ef7e06SGarrett D'Amore efx_nvram_size(
150*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
151*49ef7e06SGarrett D'Amore 	__in			efx_nvram_type_t type,
152*49ef7e06SGarrett D'Amore 	__out			size_t *sizep)
153*49ef7e06SGarrett D'Amore {
154*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
155*49ef7e06SGarrett D'Amore 	uint32_t partn;
156*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
157*49ef7e06SGarrett D'Amore 
158*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
159*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
160*49ef7e06SGarrett D'Amore 
161*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
162*49ef7e06SGarrett D'Amore 
163*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
164*49ef7e06SGarrett D'Amore 		goto fail1;
165*49ef7e06SGarrett D'Amore 
166*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
167*49ef7e06SGarrett D'Amore 		goto fail2;
168*49ef7e06SGarrett D'Amore 
169*49ef7e06SGarrett D'Amore 	return (0);
170*49ef7e06SGarrett D'Amore 
171*49ef7e06SGarrett D'Amore fail2:
172*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
173*49ef7e06SGarrett D'Amore fail1:
174*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
175*49ef7e06SGarrett D'Amore 	*sizep = 0;
176*49ef7e06SGarrett D'Amore 
177*49ef7e06SGarrett D'Amore 	return (rc);
178*49ef7e06SGarrett D'Amore }
179*49ef7e06SGarrett D'Amore 
180*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
181*49ef7e06SGarrett D'Amore efx_nvram_get_version(
182*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
183*49ef7e06SGarrett D'Amore 	__in			efx_nvram_type_t type,
184*49ef7e06SGarrett D'Amore 	__out			uint32_t *subtypep,
185*49ef7e06SGarrett D'Amore 	__out_ecount(4)		uint16_t version[4])
186*49ef7e06SGarrett D'Amore {
187*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
188*49ef7e06SGarrett D'Amore 	uint32_t partn;
189*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
190*49ef7e06SGarrett D'Amore 
191*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
192*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
193*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
194*49ef7e06SGarrett D'Amore 
195*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
196*49ef7e06SGarrett D'Amore 
197*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
198*49ef7e06SGarrett D'Amore 		goto fail1;
199*49ef7e06SGarrett D'Amore 
200*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_partn_get_version(enp, partn,
201*49ef7e06SGarrett D'Amore 		    subtypep, version)) != 0)
202*49ef7e06SGarrett D'Amore 		goto fail2;
203*49ef7e06SGarrett D'Amore 
204*49ef7e06SGarrett D'Amore 	return (0);
205*49ef7e06SGarrett D'Amore 
206*49ef7e06SGarrett D'Amore fail2:
207*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
208*49ef7e06SGarrett D'Amore fail1:
209*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
210*49ef7e06SGarrett D'Amore 
211*49ef7e06SGarrett D'Amore 	return (rc);
212*49ef7e06SGarrett D'Amore }
213*49ef7e06SGarrett D'Amore 
214*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_nvram_rw_start(__in efx_nic_t * enp,__in efx_nvram_type_t type,__out_opt size_t * chunk_sizep)215*49ef7e06SGarrett D'Amore efx_nvram_rw_start(
216*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
217*49ef7e06SGarrett D'Amore 	__in			efx_nvram_type_t type,
218*49ef7e06SGarrett D'Amore 	__out_opt		size_t *chunk_sizep)
219*49ef7e06SGarrett D'Amore {
220*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
221*49ef7e06SGarrett D'Amore 	uint32_t partn;
222*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
223*49ef7e06SGarrett D'Amore 
224*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
225*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
226*49ef7e06SGarrett D'Amore 
227*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
228*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
229*49ef7e06SGarrett D'Amore 
230*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
231*49ef7e06SGarrett D'Amore 
232*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
233*49ef7e06SGarrett D'Amore 		goto fail1;
234*49ef7e06SGarrett D'Amore 
235*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
236*49ef7e06SGarrett D'Amore 		goto fail2;
237*49ef7e06SGarrett D'Amore 
238*49ef7e06SGarrett D'Amore 	enp->en_nvram_locked = type;
239*49ef7e06SGarrett D'Amore 
240*49ef7e06SGarrett D'Amore 	return (0);
241*49ef7e06SGarrett D'Amore 
242*49ef7e06SGarrett D'Amore fail2:
243*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
244*49ef7e06SGarrett D'Amore fail1:
245*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
246*49ef7e06SGarrett D'Amore 
247*49ef7e06SGarrett D'Amore 	return (rc);
248*49ef7e06SGarrett D'Amore }
249*49ef7e06SGarrett D'Amore 
250*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
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)251*49ef7e06SGarrett D'Amore efx_nvram_read_chunk(
252*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
253*49ef7e06SGarrett D'Amore 	__in			efx_nvram_type_t type,
254*49ef7e06SGarrett D'Amore 	__in			unsigned int offset,
255*49ef7e06SGarrett D'Amore 	__out_bcount(size)	caddr_t data,
256*49ef7e06SGarrett D'Amore 	__in			size_t size)
257*49ef7e06SGarrett D'Amore {
258*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
259*49ef7e06SGarrett D'Amore 	uint32_t partn;
260*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
261*49ef7e06SGarrett D'Amore 
262*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
263*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
264*49ef7e06SGarrett D'Amore 
265*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
266*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
267*49ef7e06SGarrett D'Amore 
268*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
269*49ef7e06SGarrett D'Amore 
270*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
271*49ef7e06SGarrett D'Amore 		goto fail1;
272*49ef7e06SGarrett D'Amore 
273*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
274*49ef7e06SGarrett D'Amore 		goto fail2;
275*49ef7e06SGarrett D'Amore 
276*49ef7e06SGarrett D'Amore 	return (0);
277*49ef7e06SGarrett D'Amore 
278*49ef7e06SGarrett D'Amore fail2:
279*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
280*49ef7e06SGarrett D'Amore fail1:
281*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
282*49ef7e06SGarrett D'Amore 
283*49ef7e06SGarrett D'Amore 	return (rc);
284*49ef7e06SGarrett D'Amore }
285*49ef7e06SGarrett D'Amore 
286*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_nvram_erase(__in efx_nic_t * enp,__in efx_nvram_type_t type)287*49ef7e06SGarrett D'Amore efx_nvram_erase(
288*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
289*49ef7e06SGarrett D'Amore 	__in			efx_nvram_type_t type)
290*49ef7e06SGarrett D'Amore {
291*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
292*49ef7e06SGarrett D'Amore 	unsigned int offset = 0;
293*49ef7e06SGarrett D'Amore 	size_t size = 0;
294*49ef7e06SGarrett D'Amore 	uint32_t partn;
295*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
296*49ef7e06SGarrett D'Amore 
297*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
298*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
299*49ef7e06SGarrett D'Amore 
300*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
301*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
302*49ef7e06SGarrett D'Amore 
303*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
304*49ef7e06SGarrett D'Amore 
305*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
306*49ef7e06SGarrett D'Amore 		goto fail1;
307*49ef7e06SGarrett D'Amore 
308*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
309*49ef7e06SGarrett D'Amore 		goto fail2;
310*49ef7e06SGarrett D'Amore 
311*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
312*49ef7e06SGarrett D'Amore 		goto fail3;
313*49ef7e06SGarrett D'Amore 
314*49ef7e06SGarrett D'Amore 	return (0);
315*49ef7e06SGarrett D'Amore 
316*49ef7e06SGarrett D'Amore fail3:
317*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
318*49ef7e06SGarrett D'Amore fail2:
319*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
320*49ef7e06SGarrett D'Amore fail1:
321*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
322*49ef7e06SGarrett D'Amore 
323*49ef7e06SGarrett D'Amore 	return (rc);
324*49ef7e06SGarrett D'Amore }
325*49ef7e06SGarrett D'Amore 
326*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
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)327*49ef7e06SGarrett D'Amore efx_nvram_write_chunk(
328*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
329*49ef7e06SGarrett D'Amore 	__in			efx_nvram_type_t type,
330*49ef7e06SGarrett D'Amore 	__in			unsigned int offset,
331*49ef7e06SGarrett D'Amore 	__in_bcount(size)	caddr_t data,
332*49ef7e06SGarrett D'Amore 	__in			size_t size)
333*49ef7e06SGarrett D'Amore {
334*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
335*49ef7e06SGarrett D'Amore 	uint32_t partn;
336*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
337*49ef7e06SGarrett D'Amore 
338*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
339*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
340*49ef7e06SGarrett D'Amore 
341*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
342*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
343*49ef7e06SGarrett D'Amore 
344*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
345*49ef7e06SGarrett D'Amore 
346*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
347*49ef7e06SGarrett D'Amore 		goto fail1;
348*49ef7e06SGarrett D'Amore 
349*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
350*49ef7e06SGarrett D'Amore 		goto fail2;
351*49ef7e06SGarrett D'Amore 
352*49ef7e06SGarrett D'Amore 	return (0);
353*49ef7e06SGarrett D'Amore 
354*49ef7e06SGarrett D'Amore fail2:
355*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
356*49ef7e06SGarrett D'Amore fail1:
357*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
358*49ef7e06SGarrett D'Amore 
359*49ef7e06SGarrett D'Amore 	return (rc);
360*49ef7e06SGarrett D'Amore }
361*49ef7e06SGarrett D'Amore 
362*49ef7e06SGarrett D'Amore 				void
efx_nvram_rw_finish(__in efx_nic_t * enp,__in efx_nvram_type_t type)363*49ef7e06SGarrett D'Amore efx_nvram_rw_finish(
364*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
365*49ef7e06SGarrett D'Amore 	__in			efx_nvram_type_t type)
366*49ef7e06SGarrett D'Amore {
367*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
368*49ef7e06SGarrett D'Amore 	uint32_t partn;
369*49ef7e06SGarrett D'Amore 
370*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
371*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
372*49ef7e06SGarrett D'Amore 
373*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
374*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
375*49ef7e06SGarrett D'Amore 
376*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
377*49ef7e06SGarrett D'Amore 
378*49ef7e06SGarrett D'Amore 	if (envop->envo_type_to_partn(enp, type, &partn) == 0)
379*49ef7e06SGarrett D'Amore 		envop->envo_partn_rw_finish(enp, partn);
380*49ef7e06SGarrett D'Amore 
381*49ef7e06SGarrett D'Amore 	enp->en_nvram_locked = EFX_NVRAM_INVALID;
382*49ef7e06SGarrett D'Amore }
383*49ef7e06SGarrett D'Amore 
384*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
385*49ef7e06SGarrett D'Amore efx_nvram_set_version(
386*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
387*49ef7e06SGarrett D'Amore 	__in			efx_nvram_type_t type,
388*49ef7e06SGarrett D'Amore 	__in_ecount(4)		uint16_t version[4])
389*49ef7e06SGarrett D'Amore {
390*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
391*49ef7e06SGarrett D'Amore 	uint32_t partn;
392*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
393*49ef7e06SGarrett D'Amore 
394*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
395*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
396*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
397*49ef7e06SGarrett D'Amore 
398*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
399*49ef7e06SGarrett D'Amore 
400*49ef7e06SGarrett D'Amore 	/*
401*49ef7e06SGarrett D'Amore 	 * The Siena implementation of envo_set_version() will attempt to
402*49ef7e06SGarrett D'Amore 	 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
403*49ef7e06SGarrett D'Amore 	 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
404*49ef7e06SGarrett D'Amore 	 */
405*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
406*49ef7e06SGarrett D'Amore 
407*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
408*49ef7e06SGarrett D'Amore 		goto fail1;
409*49ef7e06SGarrett D'Amore 
410*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
411*49ef7e06SGarrett D'Amore 		goto fail2;
412*49ef7e06SGarrett D'Amore 
413*49ef7e06SGarrett D'Amore 	return (0);
414*49ef7e06SGarrett D'Amore 
415*49ef7e06SGarrett D'Amore fail2:
416*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
417*49ef7e06SGarrett D'Amore fail1:
418*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
419*49ef7e06SGarrett D'Amore 
420*49ef7e06SGarrett D'Amore 	return (rc);
421*49ef7e06SGarrett D'Amore }
422*49ef7e06SGarrett D'Amore 
423*49ef7e06SGarrett D'Amore /* Validate buffer contents (before writing to flash) */
424*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_nvram_validate(__in efx_nic_t * enp,__in efx_nvram_type_t type,__in_bcount (partn_size)caddr_t partn_data,__in size_t partn_size)425*49ef7e06SGarrett D'Amore efx_nvram_validate(
426*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
427*49ef7e06SGarrett D'Amore 	__in			efx_nvram_type_t type,
428*49ef7e06SGarrett D'Amore 	__in_bcount(partn_size)	caddr_t partn_data,
429*49ef7e06SGarrett D'Amore 	__in			size_t partn_size)
430*49ef7e06SGarrett D'Amore {
431*49ef7e06SGarrett D'Amore 	const efx_nvram_ops_t *envop = enp->en_envop;
432*49ef7e06SGarrett D'Amore 	uint32_t partn;
433*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
434*49ef7e06SGarrett D'Amore 
435*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
436*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
437*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
438*49ef7e06SGarrett D'Amore 
439*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
440*49ef7e06SGarrett D'Amore 
441*49ef7e06SGarrett D'Amore 
442*49ef7e06SGarrett D'Amore 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
443*49ef7e06SGarrett D'Amore 		goto fail1;
444*49ef7e06SGarrett D'Amore 
445*49ef7e06SGarrett D'Amore 	if (envop->envo_type_to_partn != NULL &&
446*49ef7e06SGarrett D'Amore 	    ((rc = envop->envo_buffer_validate(enp, partn,
447*49ef7e06SGarrett D'Amore 	    partn_data, partn_size)) != 0))
448*49ef7e06SGarrett D'Amore 		goto fail2;
449*49ef7e06SGarrett D'Amore 
450*49ef7e06SGarrett D'Amore 	return (0);
451*49ef7e06SGarrett D'Amore 
452*49ef7e06SGarrett D'Amore fail2:
453*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
454*49ef7e06SGarrett D'Amore fail1:
455*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
456*49ef7e06SGarrett D'Amore 
457*49ef7e06SGarrett D'Amore 	return (rc);
458*49ef7e06SGarrett D'Amore }
459*49ef7e06SGarrett D'Amore 
460*49ef7e06SGarrett D'Amore 
461*49ef7e06SGarrett D'Amore void
efx_nvram_fini(__in efx_nic_t * enp)462*49ef7e06SGarrett D'Amore efx_nvram_fini(
463*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
464*49ef7e06SGarrett D'Amore {
465*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
466*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
467*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
468*49ef7e06SGarrett D'Amore 
469*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
470*49ef7e06SGarrett D'Amore 
471*49ef7e06SGarrett D'Amore 	enp->en_envop = NULL;
472*49ef7e06SGarrett D'Amore 	enp->en_mod_flags &= ~EFX_MOD_NVRAM;
473*49ef7e06SGarrett D'Amore }
474*49ef7e06SGarrett D'Amore 
475*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_NVRAM */
476*49ef7e06SGarrett D'Amore 
477*49ef7e06SGarrett D'Amore #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
478*49ef7e06SGarrett D'Amore 
479*49ef7e06SGarrett D'Amore /*
480*49ef7e06SGarrett D'Amore  * Internal MCDI request handling
481*49ef7e06SGarrett D'Amore  */
482*49ef7e06SGarrett D'Amore 
483*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_mcdi_nvram_partitions(__in efx_nic_t * enp,__out_bcount (size)caddr_t data,__in size_t size,__out unsigned int * npartnp)484*49ef7e06SGarrett D'Amore efx_mcdi_nvram_partitions(
485*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
486*49ef7e06SGarrett D'Amore 	__out_bcount(size)	caddr_t data,
487*49ef7e06SGarrett D'Amore 	__in			size_t size,
488*49ef7e06SGarrett D'Amore 	__out			unsigned int *npartnp)
489*49ef7e06SGarrett D'Amore {
490*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
491*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
492*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
493*49ef7e06SGarrett D'Amore 	unsigned int npartn;
494*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
495*49ef7e06SGarrett D'Amore 
496*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
497*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
498*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
499*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
500*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
501*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
502*49ef7e06SGarrett D'Amore 
503*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
504*49ef7e06SGarrett D'Amore 
505*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
506*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
507*49ef7e06SGarrett D'Amore 		goto fail1;
508*49ef7e06SGarrett D'Amore 	}
509*49ef7e06SGarrett D'Amore 
510*49ef7e06SGarrett D'Amore 	if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
511*49ef7e06SGarrett D'Amore 		rc = EMSGSIZE;
512*49ef7e06SGarrett D'Amore 		goto fail2;
513*49ef7e06SGarrett D'Amore 	}
514*49ef7e06SGarrett D'Amore 	npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
515*49ef7e06SGarrett D'Amore 
516*49ef7e06SGarrett D'Amore 	if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
517*49ef7e06SGarrett D'Amore 		rc = ENOENT;
518*49ef7e06SGarrett D'Amore 		goto fail3;
519*49ef7e06SGarrett D'Amore 	}
520*49ef7e06SGarrett D'Amore 
521*49ef7e06SGarrett D'Amore 	if (size < npartn * sizeof (uint32_t)) {
522*49ef7e06SGarrett D'Amore 		rc = ENOSPC;
523*49ef7e06SGarrett D'Amore 		goto fail3;
524*49ef7e06SGarrett D'Amore 	}
525*49ef7e06SGarrett D'Amore 
526*49ef7e06SGarrett D'Amore 	*npartnp = npartn;
527*49ef7e06SGarrett D'Amore 
528*49ef7e06SGarrett D'Amore 	(void) memcpy(data,
529*49ef7e06SGarrett D'Amore 	    MCDI_OUT2(req, void, NVRAM_PARTITIONS_OUT_TYPE_ID),
530*49ef7e06SGarrett D'Amore 	    (npartn * sizeof (uint32_t)));
531*49ef7e06SGarrett D'Amore 
532*49ef7e06SGarrett D'Amore 	return (0);
533*49ef7e06SGarrett D'Amore 
534*49ef7e06SGarrett D'Amore fail3:
535*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
536*49ef7e06SGarrett D'Amore fail2:
537*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
538*49ef7e06SGarrett D'Amore fail1:
539*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
540*49ef7e06SGarrett D'Amore 
541*49ef7e06SGarrett D'Amore 	return (rc);
542*49ef7e06SGarrett D'Amore }
543*49ef7e06SGarrett D'Amore 
544*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
545*49ef7e06SGarrett D'Amore efx_mcdi_nvram_metadata(
546*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
547*49ef7e06SGarrett D'Amore 	__in			uint32_t partn,
548*49ef7e06SGarrett D'Amore 	__out			uint32_t *subtypep,
549*49ef7e06SGarrett D'Amore 	__out_ecount(4)		uint16_t version[4],
550*49ef7e06SGarrett D'Amore 	__out_bcount_opt(size)	char *descp,
551*49ef7e06SGarrett D'Amore 	__in			size_t size)
552*49ef7e06SGarrett D'Amore {
553*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
554*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
555*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
556*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
557*49ef7e06SGarrett D'Amore 
558*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
559*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_METADATA;
560*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
561*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
562*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
563*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
564*49ef7e06SGarrett D'Amore 
565*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
566*49ef7e06SGarrett D'Amore 
567*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
568*49ef7e06SGarrett D'Amore 
569*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
570*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
571*49ef7e06SGarrett D'Amore 		goto fail1;
572*49ef7e06SGarrett D'Amore 	}
573*49ef7e06SGarrett D'Amore 
574*49ef7e06SGarrett D'Amore 	if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
575*49ef7e06SGarrett D'Amore 		rc = EMSGSIZE;
576*49ef7e06SGarrett D'Amore 		goto fail2;
577*49ef7e06SGarrett D'Amore 	}
578*49ef7e06SGarrett D'Amore 
579*49ef7e06SGarrett D'Amore 	if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
580*49ef7e06SGarrett D'Amore 		NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
581*49ef7e06SGarrett D'Amore 		*subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
582*49ef7e06SGarrett D'Amore 	} else {
583*49ef7e06SGarrett D'Amore 		*subtypep = 0;
584*49ef7e06SGarrett D'Amore 	}
585*49ef7e06SGarrett D'Amore 
586*49ef7e06SGarrett D'Amore 	if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
587*49ef7e06SGarrett D'Amore 		NVRAM_METADATA_OUT_VERSION_VALID)) {
588*49ef7e06SGarrett D'Amore 		version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
589*49ef7e06SGarrett D'Amore 		version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
590*49ef7e06SGarrett D'Amore 		version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
591*49ef7e06SGarrett D'Amore 		version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
592*49ef7e06SGarrett D'Amore 	} else {
593*49ef7e06SGarrett D'Amore 		version[0] = version[1] = version[2] = version[3] = 0;
594*49ef7e06SGarrett D'Amore 	}
595*49ef7e06SGarrett D'Amore 
596*49ef7e06SGarrett D'Amore 	if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
597*49ef7e06SGarrett D'Amore 		NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
598*49ef7e06SGarrett D'Amore 		/* Return optional descrition string */
599*49ef7e06SGarrett D'Amore 		if ((descp != NULL) && (size > 0)) {
600*49ef7e06SGarrett D'Amore 			size_t desclen;
601*49ef7e06SGarrett D'Amore 
602*49ef7e06SGarrett D'Amore 			descp[0] = '\0';
603*49ef7e06SGarrett D'Amore 			desclen = (req.emr_out_length_used
604*49ef7e06SGarrett D'Amore 			    - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
605*49ef7e06SGarrett D'Amore 
606*49ef7e06SGarrett D'Amore 			EFSYS_ASSERT3U(desclen, <=,
607*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
608*49ef7e06SGarrett D'Amore 
609*49ef7e06SGarrett D'Amore 			if (size < desclen) {
610*49ef7e06SGarrett D'Amore 				rc = ENOSPC;
611*49ef7e06SGarrett D'Amore 				goto fail3;
612*49ef7e06SGarrett D'Amore 			}
613*49ef7e06SGarrett D'Amore 
614*49ef7e06SGarrett D'Amore 			(void) memcpy(descp, MCDI_OUT2(req, char,
615*49ef7e06SGarrett D'Amore 				NVRAM_METADATA_OUT_DESCRIPTION),
616*49ef7e06SGarrett D'Amore 			    desclen);
617*49ef7e06SGarrett D'Amore 
618*49ef7e06SGarrett D'Amore 			/* Ensure string is NUL terminated */
619*49ef7e06SGarrett D'Amore 			descp[desclen] = '\0';
620*49ef7e06SGarrett D'Amore 		}
621*49ef7e06SGarrett D'Amore 	}
622*49ef7e06SGarrett D'Amore 
623*49ef7e06SGarrett D'Amore 	return (0);
624*49ef7e06SGarrett D'Amore 
625*49ef7e06SGarrett D'Amore fail3:
626*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
627*49ef7e06SGarrett D'Amore fail2:
628*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
629*49ef7e06SGarrett D'Amore fail1:
630*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
631*49ef7e06SGarrett D'Amore 
632*49ef7e06SGarrett D'Amore 	return (rc);
633*49ef7e06SGarrett D'Amore }
634*49ef7e06SGarrett D'Amore 
635*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_mcdi_nvram_info(__in efx_nic_t * enp,__in uint32_t partn,__out_opt size_t * sizep,__out_opt uint32_t * addressp,__out_opt uint32_t * erase_sizep,__out_opt uint32_t * write_sizep)636*49ef7e06SGarrett D'Amore efx_mcdi_nvram_info(
637*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
638*49ef7e06SGarrett D'Amore 	__in			uint32_t partn,
639*49ef7e06SGarrett D'Amore 	__out_opt		size_t *sizep,
640*49ef7e06SGarrett D'Amore 	__out_opt		uint32_t *addressp,
641*49ef7e06SGarrett D'Amore 	__out_opt		uint32_t *erase_sizep,
642*49ef7e06SGarrett D'Amore 	__out_opt		uint32_t *write_sizep)
643*49ef7e06SGarrett D'Amore {
644*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
645*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
646*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
647*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
648*49ef7e06SGarrett D'Amore 
649*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
650*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_INFO;
651*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
652*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
653*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
654*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
655*49ef7e06SGarrett D'Amore 
656*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
657*49ef7e06SGarrett D'Amore 
658*49ef7e06SGarrett D'Amore 	efx_mcdi_execute_quiet(enp, &req);
659*49ef7e06SGarrett D'Amore 
660*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
661*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
662*49ef7e06SGarrett D'Amore 		goto fail1;
663*49ef7e06SGarrett D'Amore 	}
664*49ef7e06SGarrett D'Amore 
665*49ef7e06SGarrett D'Amore 	if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
666*49ef7e06SGarrett D'Amore 		rc = EMSGSIZE;
667*49ef7e06SGarrett D'Amore 		goto fail2;
668*49ef7e06SGarrett D'Amore 	}
669*49ef7e06SGarrett D'Amore 
670*49ef7e06SGarrett D'Amore 	if (sizep)
671*49ef7e06SGarrett D'Amore 		*sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
672*49ef7e06SGarrett D'Amore 
673*49ef7e06SGarrett D'Amore 	if (addressp)
674*49ef7e06SGarrett D'Amore 		*addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
675*49ef7e06SGarrett D'Amore 
676*49ef7e06SGarrett D'Amore 	if (erase_sizep)
677*49ef7e06SGarrett D'Amore 		*erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
678*49ef7e06SGarrett D'Amore 
679*49ef7e06SGarrett D'Amore 	if (write_sizep) {
680*49ef7e06SGarrett D'Amore 		*write_sizep =
681*49ef7e06SGarrett D'Amore 			(req.emr_out_length_used <
682*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
683*49ef7e06SGarrett D'Amore 			0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
684*49ef7e06SGarrett D'Amore 	}
685*49ef7e06SGarrett D'Amore 
686*49ef7e06SGarrett D'Amore 	return (0);
687*49ef7e06SGarrett D'Amore 
688*49ef7e06SGarrett D'Amore fail2:
689*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
690*49ef7e06SGarrett D'Amore fail1:
691*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
692*49ef7e06SGarrett D'Amore 
693*49ef7e06SGarrett D'Amore 	return (rc);
694*49ef7e06SGarrett D'Amore }
695*49ef7e06SGarrett D'Amore 
696*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_mcdi_nvram_update_start(__in efx_nic_t * enp,__in uint32_t partn)697*49ef7e06SGarrett D'Amore efx_mcdi_nvram_update_start(
698*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
699*49ef7e06SGarrett D'Amore 	__in			uint32_t partn)
700*49ef7e06SGarrett D'Amore {
701*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_IN_LEN,
702*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
703*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
704*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
705*49ef7e06SGarrett D'Amore 
706*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
707*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
708*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
709*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN;
710*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
711*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
712*49ef7e06SGarrett D'Amore 
713*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn);
714*49ef7e06SGarrett D'Amore 
715*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
716*49ef7e06SGarrett D'Amore 
717*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
718*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
719*49ef7e06SGarrett D'Amore 		goto fail1;
720*49ef7e06SGarrett D'Amore 	}
721*49ef7e06SGarrett D'Amore 
722*49ef7e06SGarrett D'Amore 	return (0);
723*49ef7e06SGarrett D'Amore 
724*49ef7e06SGarrett D'Amore fail1:
725*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
726*49ef7e06SGarrett D'Amore 
727*49ef7e06SGarrett D'Amore 	return (rc);
728*49ef7e06SGarrett D'Amore }
729*49ef7e06SGarrett D'Amore 
730*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_mcdi_nvram_read(__in efx_nic_t * enp,__in uint32_t partn,__in uint32_t offset,__out_bcount (size)caddr_t data,__in size_t size,__in uint32_t mode)731*49ef7e06SGarrett D'Amore efx_mcdi_nvram_read(
732*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
733*49ef7e06SGarrett D'Amore 	__in			uint32_t partn,
734*49ef7e06SGarrett D'Amore 	__in			uint32_t offset,
735*49ef7e06SGarrett D'Amore 	__out_bcount(size)	caddr_t data,
736*49ef7e06SGarrett D'Amore 	__in			size_t size,
737*49ef7e06SGarrett D'Amore 	__in			uint32_t mode)
738*49ef7e06SGarrett D'Amore {
739*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
740*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
741*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_READ_OUT_LENMAX)];
742*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
743*49ef7e06SGarrett D'Amore 
744*49ef7e06SGarrett D'Amore 	if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
745*49ef7e06SGarrett D'Amore 		rc = EINVAL;
746*49ef7e06SGarrett D'Amore 		goto fail1;
747*49ef7e06SGarrett D'Amore 	}
748*49ef7e06SGarrett D'Amore 
749*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
750*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_READ;
751*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
752*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
753*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
754*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
755*49ef7e06SGarrett D'Amore 
756*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
757*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
758*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
759*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
760*49ef7e06SGarrett D'Amore 
761*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
762*49ef7e06SGarrett D'Amore 
763*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
764*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
765*49ef7e06SGarrett D'Amore 		goto fail1;
766*49ef7e06SGarrett D'Amore 	}
767*49ef7e06SGarrett D'Amore 
768*49ef7e06SGarrett D'Amore 	if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
769*49ef7e06SGarrett D'Amore 		rc = EMSGSIZE;
770*49ef7e06SGarrett D'Amore 		goto fail2;
771*49ef7e06SGarrett D'Amore 	}
772*49ef7e06SGarrett D'Amore 
773*49ef7e06SGarrett D'Amore 	(void) memcpy(data,
774*49ef7e06SGarrett D'Amore 	    MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
775*49ef7e06SGarrett D'Amore 	    size);
776*49ef7e06SGarrett D'Amore 
777*49ef7e06SGarrett D'Amore 	return (0);
778*49ef7e06SGarrett D'Amore 
779*49ef7e06SGarrett D'Amore fail2:
780*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
781*49ef7e06SGarrett D'Amore fail1:
782*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
783*49ef7e06SGarrett D'Amore 
784*49ef7e06SGarrett D'Amore 	return (rc);
785*49ef7e06SGarrett D'Amore }
786*49ef7e06SGarrett D'Amore 
787*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_mcdi_nvram_erase(__in efx_nic_t * enp,__in uint32_t partn,__in uint32_t offset,__in size_t size)788*49ef7e06SGarrett D'Amore efx_mcdi_nvram_erase(
789*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
790*49ef7e06SGarrett D'Amore 	__in			uint32_t partn,
791*49ef7e06SGarrett D'Amore 	__in			uint32_t offset,
792*49ef7e06SGarrett D'Amore 	__in			size_t size)
793*49ef7e06SGarrett D'Amore {
794*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
795*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
796*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_ERASE_OUT_LEN)];
797*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
798*49ef7e06SGarrett D'Amore 
799*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
800*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_ERASE;
801*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
802*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
803*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
804*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
805*49ef7e06SGarrett D'Amore 
806*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
807*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
808*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
809*49ef7e06SGarrett D'Amore 
810*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
811*49ef7e06SGarrett D'Amore 
812*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
813*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
814*49ef7e06SGarrett D'Amore 		goto fail1;
815*49ef7e06SGarrett D'Amore 	}
816*49ef7e06SGarrett D'Amore 
817*49ef7e06SGarrett D'Amore 	return (0);
818*49ef7e06SGarrett D'Amore 
819*49ef7e06SGarrett D'Amore fail1:
820*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
821*49ef7e06SGarrett D'Amore 
822*49ef7e06SGarrett D'Amore 	return (rc);
823*49ef7e06SGarrett D'Amore }
824*49ef7e06SGarrett D'Amore 
825*49ef7e06SGarrett D'Amore /*
826*49ef7e06SGarrett D'Amore  * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
827*49ef7e06SGarrett D'Amore  * Sienna and EF10 based boards.  However EF10 based boards support the use
828*49ef7e06SGarrett D'Amore  * of this command with payloads up to the maximum MCDI V2 payload length.
829*49ef7e06SGarrett D'Amore  */
830*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_mcdi_nvram_write(__in efx_nic_t * enp,__in uint32_t partn,__in uint32_t offset,__out_bcount (size)caddr_t data,__in size_t size)831*49ef7e06SGarrett D'Amore efx_mcdi_nvram_write(
832*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
833*49ef7e06SGarrett D'Amore 	__in			uint32_t partn,
834*49ef7e06SGarrett D'Amore 	__in			uint32_t offset,
835*49ef7e06SGarrett D'Amore 	__out_bcount(size)	caddr_t data,
836*49ef7e06SGarrett D'Amore 	__in			size_t size)
837*49ef7e06SGarrett D'Amore {
838*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
839*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1,
840*49ef7e06SGarrett D'Amore 			    MCDI_CTL_SDU_LEN_MAX_V2)];
841*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
842*49ef7e06SGarrett D'Amore 	size_t max_data_size;
843*49ef7e06SGarrett D'Amore 
844*49ef7e06SGarrett D'Amore 	max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length
845*49ef7e06SGarrett D'Amore 	    - MC_CMD_NVRAM_WRITE_IN_LEN(0);
846*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0);
847*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(max_data_size, <,
848*49ef7e06SGarrett D'Amore 		    enp->en_nic_cfg.enc_mcdi_max_payload_length);
849*49ef7e06SGarrett D'Amore 
850*49ef7e06SGarrett D'Amore 	if (size > max_data_size) {
851*49ef7e06SGarrett D'Amore 		rc = EINVAL;
852*49ef7e06SGarrett D'Amore 		goto fail1;
853*49ef7e06SGarrett D'Amore 	}
854*49ef7e06SGarrett D'Amore 
855*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
856*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_WRITE;
857*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
858*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
859*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
860*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
861*49ef7e06SGarrett D'Amore 
862*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
863*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
864*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
865*49ef7e06SGarrett D'Amore 
866*49ef7e06SGarrett D'Amore 	(void) memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
867*49ef7e06SGarrett D'Amore 	    data, size);
868*49ef7e06SGarrett D'Amore 
869*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
870*49ef7e06SGarrett D'Amore 
871*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
872*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
873*49ef7e06SGarrett D'Amore 		goto fail2;
874*49ef7e06SGarrett D'Amore 	}
875*49ef7e06SGarrett D'Amore 
876*49ef7e06SGarrett D'Amore 	return (0);
877*49ef7e06SGarrett D'Amore 
878*49ef7e06SGarrett D'Amore fail2:
879*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
880*49ef7e06SGarrett D'Amore fail1:
881*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
882*49ef7e06SGarrett D'Amore 
883*49ef7e06SGarrett D'Amore 	return (rc);
884*49ef7e06SGarrett D'Amore }
885*49ef7e06SGarrett D'Amore 
886*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_mcdi_nvram_update_finish(__in efx_nic_t * enp,__in uint32_t partn,__in boolean_t reboot)887*49ef7e06SGarrett D'Amore efx_mcdi_nvram_update_finish(
888*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
889*49ef7e06SGarrett D'Amore 	__in			uint32_t partn,
890*49ef7e06SGarrett D'Amore 	__in			boolean_t reboot)
891*49ef7e06SGarrett D'Amore {
892*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
893*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN,
894*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN)];
895*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
896*49ef7e06SGarrett D'Amore 
897*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
898*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
899*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
900*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN;
901*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
902*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN;
903*49ef7e06SGarrett D'Amore 
904*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn);
905*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot);
906*49ef7e06SGarrett D'Amore 
907*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
908*49ef7e06SGarrett D'Amore 
909*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
910*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
911*49ef7e06SGarrett D'Amore 		goto fail1;
912*49ef7e06SGarrett D'Amore 	}
913*49ef7e06SGarrett D'Amore 
914*49ef7e06SGarrett D'Amore 	return (0);
915*49ef7e06SGarrett D'Amore 
916*49ef7e06SGarrett D'Amore fail1:
917*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
918*49ef7e06SGarrett D'Amore 
919*49ef7e06SGarrett D'Amore 	return (rc);
920*49ef7e06SGarrett D'Amore }
921*49ef7e06SGarrett D'Amore 
922*49ef7e06SGarrett D'Amore #if EFSYS_OPT_DIAG
923*49ef7e06SGarrett D'Amore 
924*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
efx_mcdi_nvram_test(__in efx_nic_t * enp,__in uint32_t partn)925*49ef7e06SGarrett D'Amore efx_mcdi_nvram_test(
926*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
927*49ef7e06SGarrett D'Amore 	__in			uint32_t partn)
928*49ef7e06SGarrett D'Amore {
929*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
930*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
931*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_TEST_OUT_LEN)];
932*49ef7e06SGarrett D'Amore 	int result;
933*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
934*49ef7e06SGarrett D'Amore 
935*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
936*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_TEST;
937*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
938*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
939*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
940*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
941*49ef7e06SGarrett D'Amore 
942*49ef7e06SGarrett D'Amore 	MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
943*49ef7e06SGarrett D'Amore 
944*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
945*49ef7e06SGarrett D'Amore 
946*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
947*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
948*49ef7e06SGarrett D'Amore 		goto fail1;
949*49ef7e06SGarrett D'Amore 	}
950*49ef7e06SGarrett D'Amore 
951*49ef7e06SGarrett D'Amore 	if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
952*49ef7e06SGarrett D'Amore 		rc = EMSGSIZE;
953*49ef7e06SGarrett D'Amore 		goto fail2;
954*49ef7e06SGarrett D'Amore 	}
955*49ef7e06SGarrett D'Amore 
956*49ef7e06SGarrett D'Amore 	result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
957*49ef7e06SGarrett D'Amore 	if (result == MC_CMD_NVRAM_TEST_FAIL) {
958*49ef7e06SGarrett D'Amore 
959*49ef7e06SGarrett D'Amore 		EFSYS_PROBE1(nvram_test_failure, int, partn);
960*49ef7e06SGarrett D'Amore 
961*49ef7e06SGarrett D'Amore 		rc = (EINVAL);
962*49ef7e06SGarrett D'Amore 		goto fail3;
963*49ef7e06SGarrett D'Amore 	}
964*49ef7e06SGarrett D'Amore 
965*49ef7e06SGarrett D'Amore 	return (0);
966*49ef7e06SGarrett D'Amore 
967*49ef7e06SGarrett D'Amore fail3:
968*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
969*49ef7e06SGarrett D'Amore fail2:
970*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
971*49ef7e06SGarrett D'Amore fail1:
972*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
973*49ef7e06SGarrett D'Amore 
974*49ef7e06SGarrett D'Amore 	return (rc);
975*49ef7e06SGarrett D'Amore }
976*49ef7e06SGarrett D'Amore 
977*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_DIAG */
978*49ef7e06SGarrett D'Amore 
979*49ef7e06SGarrett D'Amore 
980*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */
981