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_VPD
35*49ef7e06SGarrett D'Amore
36*49ef7e06SGarrett D'Amore #define TAG_TYPE_LBN 7
37*49ef7e06SGarrett D'Amore #define TAG_TYPE_WIDTH 1
38*49ef7e06SGarrett D'Amore #define TAG_TYPE_LARGE_ITEM_DECODE 1
39*49ef7e06SGarrett D'Amore #define TAG_TYPE_SMALL_ITEM_DECODE 0
40*49ef7e06SGarrett D'Amore
41*49ef7e06SGarrett D'Amore #define TAG_SMALL_ITEM_NAME_LBN 3
42*49ef7e06SGarrett D'Amore #define TAG_SMALL_ITEM_NAME_WIDTH 4
43*49ef7e06SGarrett D'Amore #define TAG_SMALL_ITEM_SIZE_LBN 0
44*49ef7e06SGarrett D'Amore #define TAG_SMALL_ITEM_SIZE_WIDTH 3
45*49ef7e06SGarrett D'Amore
46*49ef7e06SGarrett D'Amore #define TAG_LARGE_ITEM_NAME_LBN 0
47*49ef7e06SGarrett D'Amore #define TAG_LARGE_ITEM_NAME_WIDTH 7
48*49ef7e06SGarrett D'Amore
49*49ef7e06SGarrett D'Amore #define TAG_NAME_END_DECODE 0x0f
50*49ef7e06SGarrett D'Amore #define TAG_NAME_ID_STRING_DECODE 0x02
51*49ef7e06SGarrett D'Amore #define TAG_NAME_VPD_R_DECODE 0x10
52*49ef7e06SGarrett D'Amore #define TAG_NAME_VPD_W_DECODE 0x11
53*49ef7e06SGarrett D'Amore
54*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
55*49ef7e06SGarrett D'Amore
56*49ef7e06SGarrett D'Amore static const efx_vpd_ops_t __efx_vpd_siena_ops = {
57*49ef7e06SGarrett D'Amore siena_vpd_init, /* evpdo_init */
58*49ef7e06SGarrett D'Amore siena_vpd_size, /* evpdo_size */
59*49ef7e06SGarrett D'Amore siena_vpd_read, /* evpdo_read */
60*49ef7e06SGarrett D'Amore siena_vpd_verify, /* evpdo_verify */
61*49ef7e06SGarrett D'Amore siena_vpd_reinit, /* evpdo_reinit */
62*49ef7e06SGarrett D'Amore siena_vpd_get, /* evpdo_get */
63*49ef7e06SGarrett D'Amore siena_vpd_set, /* evpdo_set */
64*49ef7e06SGarrett D'Amore siena_vpd_next, /* evpdo_next */
65*49ef7e06SGarrett D'Amore siena_vpd_write, /* evpdo_write */
66*49ef7e06SGarrett D'Amore siena_vpd_fini, /* evpdo_fini */
67*49ef7e06SGarrett D'Amore };
68*49ef7e06SGarrett D'Amore
69*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
70*49ef7e06SGarrett D'Amore
71*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
72*49ef7e06SGarrett D'Amore
73*49ef7e06SGarrett D'Amore static const efx_vpd_ops_t __efx_vpd_ef10_ops = {
74*49ef7e06SGarrett D'Amore ef10_vpd_init, /* evpdo_init */
75*49ef7e06SGarrett D'Amore ef10_vpd_size, /* evpdo_size */
76*49ef7e06SGarrett D'Amore ef10_vpd_read, /* evpdo_read */
77*49ef7e06SGarrett D'Amore ef10_vpd_verify, /* evpdo_verify */
78*49ef7e06SGarrett D'Amore ef10_vpd_reinit, /* evpdo_reinit */
79*49ef7e06SGarrett D'Amore ef10_vpd_get, /* evpdo_get */
80*49ef7e06SGarrett D'Amore ef10_vpd_set, /* evpdo_set */
81*49ef7e06SGarrett D'Amore ef10_vpd_next, /* evpdo_next */
82*49ef7e06SGarrett D'Amore ef10_vpd_write, /* evpdo_write */
83*49ef7e06SGarrett D'Amore ef10_vpd_fini, /* evpdo_fini */
84*49ef7e06SGarrett D'Amore };
85*49ef7e06SGarrett D'Amore
86*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
87*49ef7e06SGarrett D'Amore
88*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_init(__in efx_nic_t * enp)89*49ef7e06SGarrett D'Amore efx_vpd_init(
90*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
91*49ef7e06SGarrett D'Amore {
92*49ef7e06SGarrett D'Amore const efx_vpd_ops_t *evpdop;
93*49ef7e06SGarrett D'Amore efx_rc_t rc;
94*49ef7e06SGarrett D'Amore
95*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
96*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
97*49ef7e06SGarrett D'Amore EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_VPD));
98*49ef7e06SGarrett D'Amore
99*49ef7e06SGarrett D'Amore switch (enp->en_family) {
100*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
101*49ef7e06SGarrett D'Amore case EFX_FAMILY_SIENA:
102*49ef7e06SGarrett D'Amore evpdop = &__efx_vpd_siena_ops;
103*49ef7e06SGarrett D'Amore break;
104*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
105*49ef7e06SGarrett D'Amore
106*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON
107*49ef7e06SGarrett D'Amore case EFX_FAMILY_HUNTINGTON:
108*49ef7e06SGarrett D'Amore evpdop = &__efx_vpd_ef10_ops;
109*49ef7e06SGarrett D'Amore break;
110*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON */
111*49ef7e06SGarrett D'Amore
112*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MEDFORD
113*49ef7e06SGarrett D'Amore case EFX_FAMILY_MEDFORD:
114*49ef7e06SGarrett D'Amore evpdop = &__efx_vpd_ef10_ops;
115*49ef7e06SGarrett D'Amore break;
116*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MEDFORD */
117*49ef7e06SGarrett D'Amore
118*49ef7e06SGarrett D'Amore default:
119*49ef7e06SGarrett D'Amore EFSYS_ASSERT(0);
120*49ef7e06SGarrett D'Amore rc = ENOTSUP;
121*49ef7e06SGarrett D'Amore goto fail1;
122*49ef7e06SGarrett D'Amore }
123*49ef7e06SGarrett D'Amore
124*49ef7e06SGarrett D'Amore if (evpdop->evpdo_init != NULL) {
125*49ef7e06SGarrett D'Amore if ((rc = evpdop->evpdo_init(enp)) != 0)
126*49ef7e06SGarrett D'Amore goto fail2;
127*49ef7e06SGarrett D'Amore }
128*49ef7e06SGarrett D'Amore
129*49ef7e06SGarrett D'Amore enp->en_evpdop = evpdop;
130*49ef7e06SGarrett D'Amore enp->en_mod_flags |= EFX_MOD_VPD;
131*49ef7e06SGarrett D'Amore
132*49ef7e06SGarrett D'Amore return (0);
133*49ef7e06SGarrett D'Amore
134*49ef7e06SGarrett D'Amore fail2:
135*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
136*49ef7e06SGarrett D'Amore fail1:
137*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
138*49ef7e06SGarrett D'Amore
139*49ef7e06SGarrett D'Amore return (rc);
140*49ef7e06SGarrett D'Amore }
141*49ef7e06SGarrett D'Amore
142*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_size(__in efx_nic_t * enp,__out size_t * sizep)143*49ef7e06SGarrett D'Amore efx_vpd_size(
144*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
145*49ef7e06SGarrett D'Amore __out size_t *sizep)
146*49ef7e06SGarrett D'Amore {
147*49ef7e06SGarrett D'Amore const efx_vpd_ops_t *evpdop = enp->en_evpdop;
148*49ef7e06SGarrett D'Amore efx_rc_t rc;
149*49ef7e06SGarrett D'Amore
150*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
151*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
152*49ef7e06SGarrett D'Amore
153*49ef7e06SGarrett D'Amore if ((rc = evpdop->evpdo_size(enp, sizep)) != 0)
154*49ef7e06SGarrett D'Amore goto fail1;
155*49ef7e06SGarrett D'Amore
156*49ef7e06SGarrett D'Amore return (0);
157*49ef7e06SGarrett D'Amore
158*49ef7e06SGarrett D'Amore fail1:
159*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
160*49ef7e06SGarrett D'Amore
161*49ef7e06SGarrett D'Amore return (rc);
162*49ef7e06SGarrett D'Amore }
163*49ef7e06SGarrett D'Amore
164*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_read(__in efx_nic_t * enp,__out_bcount (size)caddr_t data,__in size_t size)165*49ef7e06SGarrett D'Amore efx_vpd_read(
166*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
167*49ef7e06SGarrett D'Amore __out_bcount(size) caddr_t data,
168*49ef7e06SGarrett D'Amore __in size_t size)
169*49ef7e06SGarrett D'Amore {
170*49ef7e06SGarrett D'Amore const efx_vpd_ops_t *evpdop = enp->en_evpdop;
171*49ef7e06SGarrett D'Amore efx_rc_t rc;
172*49ef7e06SGarrett D'Amore
173*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
174*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
175*49ef7e06SGarrett D'Amore
176*49ef7e06SGarrett D'Amore if ((rc = evpdop->evpdo_read(enp, data, size)) != 0)
177*49ef7e06SGarrett D'Amore goto fail1;
178*49ef7e06SGarrett D'Amore
179*49ef7e06SGarrett D'Amore return (0);
180*49ef7e06SGarrett D'Amore
181*49ef7e06SGarrett D'Amore fail1:
182*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
183*49ef7e06SGarrett D'Amore
184*49ef7e06SGarrett D'Amore return (rc);
185*49ef7e06SGarrett D'Amore }
186*49ef7e06SGarrett D'Amore
187*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_verify(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)188*49ef7e06SGarrett D'Amore efx_vpd_verify(
189*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
190*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
191*49ef7e06SGarrett D'Amore __in size_t size)
192*49ef7e06SGarrett D'Amore {
193*49ef7e06SGarrett D'Amore const efx_vpd_ops_t *evpdop = enp->en_evpdop;
194*49ef7e06SGarrett D'Amore efx_rc_t rc;
195*49ef7e06SGarrett D'Amore
196*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
197*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
198*49ef7e06SGarrett D'Amore
199*49ef7e06SGarrett D'Amore if ((rc = evpdop->evpdo_verify(enp, data, size)) != 0)
200*49ef7e06SGarrett D'Amore goto fail1;
201*49ef7e06SGarrett D'Amore
202*49ef7e06SGarrett D'Amore return (0);
203*49ef7e06SGarrett D'Amore
204*49ef7e06SGarrett D'Amore fail1:
205*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
206*49ef7e06SGarrett D'Amore
207*49ef7e06SGarrett D'Amore return (rc);
208*49ef7e06SGarrett D'Amore }
209*49ef7e06SGarrett D'Amore
210*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_reinit(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)211*49ef7e06SGarrett D'Amore efx_vpd_reinit(
212*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
213*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
214*49ef7e06SGarrett D'Amore __in size_t size)
215*49ef7e06SGarrett D'Amore {
216*49ef7e06SGarrett D'Amore const efx_vpd_ops_t *evpdop = enp->en_evpdop;
217*49ef7e06SGarrett D'Amore efx_rc_t rc;
218*49ef7e06SGarrett D'Amore
219*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
220*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
221*49ef7e06SGarrett D'Amore
222*49ef7e06SGarrett D'Amore if (evpdop->evpdo_reinit == NULL) {
223*49ef7e06SGarrett D'Amore rc = ENOTSUP;
224*49ef7e06SGarrett D'Amore goto fail1;
225*49ef7e06SGarrett D'Amore }
226*49ef7e06SGarrett D'Amore
227*49ef7e06SGarrett D'Amore if ((rc = evpdop->evpdo_reinit(enp, data, size)) != 0)
228*49ef7e06SGarrett D'Amore goto fail2;
229*49ef7e06SGarrett D'Amore
230*49ef7e06SGarrett D'Amore return (0);
231*49ef7e06SGarrett D'Amore
232*49ef7e06SGarrett D'Amore fail2:
233*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
234*49ef7e06SGarrett D'Amore fail1:
235*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
236*49ef7e06SGarrett D'Amore
237*49ef7e06SGarrett D'Amore return (rc);
238*49ef7e06SGarrett D'Amore }
239*49ef7e06SGarrett D'Amore
240*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_get(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size,__inout efx_vpd_value_t * evvp)241*49ef7e06SGarrett D'Amore efx_vpd_get(
242*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
243*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
244*49ef7e06SGarrett D'Amore __in size_t size,
245*49ef7e06SGarrett D'Amore __inout efx_vpd_value_t *evvp)
246*49ef7e06SGarrett D'Amore {
247*49ef7e06SGarrett D'Amore const efx_vpd_ops_t *evpdop = enp->en_evpdop;
248*49ef7e06SGarrett D'Amore efx_rc_t rc;
249*49ef7e06SGarrett D'Amore
250*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
251*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
252*49ef7e06SGarrett D'Amore
253*49ef7e06SGarrett D'Amore if ((rc = evpdop->evpdo_get(enp, data, size, evvp)) != 0)
254*49ef7e06SGarrett D'Amore goto fail1;
255*49ef7e06SGarrett D'Amore
256*49ef7e06SGarrett D'Amore return (0);
257*49ef7e06SGarrett D'Amore
258*49ef7e06SGarrett D'Amore fail1:
259*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
260*49ef7e06SGarrett D'Amore
261*49ef7e06SGarrett D'Amore return (rc);
262*49ef7e06SGarrett D'Amore }
263*49ef7e06SGarrett D'Amore
264*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_set(__in efx_nic_t * enp,__inout_bcount (size)caddr_t data,__in size_t size,__in efx_vpd_value_t * evvp)265*49ef7e06SGarrett D'Amore efx_vpd_set(
266*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
267*49ef7e06SGarrett D'Amore __inout_bcount(size) caddr_t data,
268*49ef7e06SGarrett D'Amore __in size_t size,
269*49ef7e06SGarrett D'Amore __in efx_vpd_value_t *evvp)
270*49ef7e06SGarrett D'Amore {
271*49ef7e06SGarrett D'Amore const efx_vpd_ops_t *evpdop = enp->en_evpdop;
272*49ef7e06SGarrett D'Amore efx_rc_t rc;
273*49ef7e06SGarrett D'Amore
274*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
275*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
276*49ef7e06SGarrett D'Amore
277*49ef7e06SGarrett D'Amore if ((rc = evpdop->evpdo_set(enp, data, size, evvp)) != 0)
278*49ef7e06SGarrett D'Amore goto fail1;
279*49ef7e06SGarrett D'Amore
280*49ef7e06SGarrett D'Amore return (0);
281*49ef7e06SGarrett D'Amore
282*49ef7e06SGarrett D'Amore fail1:
283*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
284*49ef7e06SGarrett D'Amore
285*49ef7e06SGarrett D'Amore return (rc);
286*49ef7e06SGarrett D'Amore }
287*49ef7e06SGarrett D'Amore
288*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_next(__in efx_nic_t * enp,__inout_bcount (size)caddr_t data,__in size_t size,__out efx_vpd_value_t * evvp,__inout unsigned int * contp)289*49ef7e06SGarrett D'Amore efx_vpd_next(
290*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
291*49ef7e06SGarrett D'Amore __inout_bcount(size) caddr_t data,
292*49ef7e06SGarrett D'Amore __in size_t size,
293*49ef7e06SGarrett D'Amore __out efx_vpd_value_t *evvp,
294*49ef7e06SGarrett D'Amore __inout unsigned int *contp)
295*49ef7e06SGarrett D'Amore {
296*49ef7e06SGarrett D'Amore const efx_vpd_ops_t *evpdop = enp->en_evpdop;
297*49ef7e06SGarrett D'Amore efx_rc_t rc;
298*49ef7e06SGarrett D'Amore
299*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
300*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
301*49ef7e06SGarrett D'Amore
302*49ef7e06SGarrett D'Amore if ((rc = evpdop->evpdo_next(enp, data, size, evvp, contp)) != 0)
303*49ef7e06SGarrett D'Amore goto fail1;
304*49ef7e06SGarrett D'Amore
305*49ef7e06SGarrett D'Amore return (0);
306*49ef7e06SGarrett D'Amore
307*49ef7e06SGarrett D'Amore fail1:
308*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
309*49ef7e06SGarrett D'Amore
310*49ef7e06SGarrett D'Amore return (rc);
311*49ef7e06SGarrett D'Amore }
312*49ef7e06SGarrett D'Amore
313*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_write(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)314*49ef7e06SGarrett D'Amore efx_vpd_write(
315*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
316*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
317*49ef7e06SGarrett D'Amore __in size_t size)
318*49ef7e06SGarrett D'Amore {
319*49ef7e06SGarrett D'Amore const efx_vpd_ops_t *evpdop = enp->en_evpdop;
320*49ef7e06SGarrett D'Amore efx_rc_t rc;
321*49ef7e06SGarrett D'Amore
322*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
323*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
324*49ef7e06SGarrett D'Amore
325*49ef7e06SGarrett D'Amore if ((rc = evpdop->evpdo_write(enp, data, size)) != 0)
326*49ef7e06SGarrett D'Amore goto fail1;
327*49ef7e06SGarrett D'Amore
328*49ef7e06SGarrett D'Amore return (0);
329*49ef7e06SGarrett D'Amore
330*49ef7e06SGarrett D'Amore fail1:
331*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
332*49ef7e06SGarrett D'Amore
333*49ef7e06SGarrett D'Amore return (rc);
334*49ef7e06SGarrett D'Amore }
335*49ef7e06SGarrett D'Amore
336*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_vpd_next_tag(__in caddr_t data,__in size_t size,__inout unsigned int * offsetp,__out efx_vpd_tag_t * tagp,__out uint16_t * lengthp)337*49ef7e06SGarrett D'Amore efx_vpd_next_tag(
338*49ef7e06SGarrett D'Amore __in caddr_t data,
339*49ef7e06SGarrett D'Amore __in size_t size,
340*49ef7e06SGarrett D'Amore __inout unsigned int *offsetp,
341*49ef7e06SGarrett D'Amore __out efx_vpd_tag_t *tagp,
342*49ef7e06SGarrett D'Amore __out uint16_t *lengthp)
343*49ef7e06SGarrett D'Amore {
344*49ef7e06SGarrett D'Amore efx_byte_t byte;
345*49ef7e06SGarrett D'Amore efx_word_t word;
346*49ef7e06SGarrett D'Amore uint8_t name;
347*49ef7e06SGarrett D'Amore uint16_t length;
348*49ef7e06SGarrett D'Amore size_t headlen;
349*49ef7e06SGarrett D'Amore efx_rc_t rc;
350*49ef7e06SGarrett D'Amore
351*49ef7e06SGarrett D'Amore if (*offsetp >= size) {
352*49ef7e06SGarrett D'Amore rc = EFAULT;
353*49ef7e06SGarrett D'Amore goto fail1;
354*49ef7e06SGarrett D'Amore }
355*49ef7e06SGarrett D'Amore
356*49ef7e06SGarrett D'Amore EFX_POPULATE_BYTE_1(byte, EFX_BYTE_0, data[*offsetp]);
357*49ef7e06SGarrett D'Amore
358*49ef7e06SGarrett D'Amore switch (EFX_BYTE_FIELD(byte, TAG_TYPE)) {
359*49ef7e06SGarrett D'Amore case TAG_TYPE_SMALL_ITEM_DECODE:
360*49ef7e06SGarrett D'Amore headlen = 1;
361*49ef7e06SGarrett D'Amore
362*49ef7e06SGarrett D'Amore name = EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_NAME);
363*49ef7e06SGarrett D'Amore length = (uint16_t)EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_SIZE);
364*49ef7e06SGarrett D'Amore
365*49ef7e06SGarrett D'Amore break;
366*49ef7e06SGarrett D'Amore
367*49ef7e06SGarrett D'Amore case TAG_TYPE_LARGE_ITEM_DECODE:
368*49ef7e06SGarrett D'Amore headlen = 3;
369*49ef7e06SGarrett D'Amore
370*49ef7e06SGarrett D'Amore if (*offsetp + headlen > size) {
371*49ef7e06SGarrett D'Amore rc = EFAULT;
372*49ef7e06SGarrett D'Amore goto fail2;
373*49ef7e06SGarrett D'Amore }
374*49ef7e06SGarrett D'Amore
375*49ef7e06SGarrett D'Amore name = EFX_BYTE_FIELD(byte, TAG_LARGE_ITEM_NAME);
376*49ef7e06SGarrett D'Amore EFX_POPULATE_WORD_2(word,
377*49ef7e06SGarrett D'Amore EFX_BYTE_0, data[*offsetp + 1],
378*49ef7e06SGarrett D'Amore EFX_BYTE_1, data[*offsetp + 2]);
379*49ef7e06SGarrett D'Amore length = EFX_WORD_FIELD(word, EFX_WORD_0);
380*49ef7e06SGarrett D'Amore
381*49ef7e06SGarrett D'Amore break;
382*49ef7e06SGarrett D'Amore
383*49ef7e06SGarrett D'Amore default:
384*49ef7e06SGarrett D'Amore rc = EFAULT;
385*49ef7e06SGarrett D'Amore goto fail2;
386*49ef7e06SGarrett D'Amore }
387*49ef7e06SGarrett D'Amore
388*49ef7e06SGarrett D'Amore if (*offsetp + headlen + length > size) {
389*49ef7e06SGarrett D'Amore rc = EFAULT;
390*49ef7e06SGarrett D'Amore goto fail3;
391*49ef7e06SGarrett D'Amore }
392*49ef7e06SGarrett D'Amore
393*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(TAG_NAME_END_DECODE == EFX_VPD_END);
394*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(TAG_NAME_ID_STRING_DECODE == EFX_VPD_ID);
395*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(TAG_NAME_VPD_R_DECODE == EFX_VPD_RO);
396*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(TAG_NAME_VPD_W_DECODE == EFX_VPD_RW);
397*49ef7e06SGarrett D'Amore if (name != EFX_VPD_END && name != EFX_VPD_ID &&
398*49ef7e06SGarrett D'Amore name != EFX_VPD_RO) {
399*49ef7e06SGarrett D'Amore rc = EFAULT;
400*49ef7e06SGarrett D'Amore goto fail4;
401*49ef7e06SGarrett D'Amore }
402*49ef7e06SGarrett D'Amore
403*49ef7e06SGarrett D'Amore *tagp = name;
404*49ef7e06SGarrett D'Amore *lengthp = length;
405*49ef7e06SGarrett D'Amore *offsetp += headlen;
406*49ef7e06SGarrett D'Amore
407*49ef7e06SGarrett D'Amore return (0);
408*49ef7e06SGarrett D'Amore
409*49ef7e06SGarrett D'Amore fail4:
410*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail4);
411*49ef7e06SGarrett D'Amore fail3:
412*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
413*49ef7e06SGarrett D'Amore fail2:
414*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
415*49ef7e06SGarrett D'Amore fail1:
416*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
417*49ef7e06SGarrett D'Amore
418*49ef7e06SGarrett D'Amore return (rc);
419*49ef7e06SGarrett D'Amore }
420*49ef7e06SGarrett D'Amore
421*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_vpd_next_keyword(__in_bcount (size)caddr_t tag,__in size_t size,__in unsigned int pos,__out efx_vpd_keyword_t * keywordp,__out uint8_t * lengthp)422*49ef7e06SGarrett D'Amore efx_vpd_next_keyword(
423*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t tag,
424*49ef7e06SGarrett D'Amore __in size_t size,
425*49ef7e06SGarrett D'Amore __in unsigned int pos,
426*49ef7e06SGarrett D'Amore __out efx_vpd_keyword_t *keywordp,
427*49ef7e06SGarrett D'Amore __out uint8_t *lengthp)
428*49ef7e06SGarrett D'Amore {
429*49ef7e06SGarrett D'Amore efx_vpd_keyword_t keyword;
430*49ef7e06SGarrett D'Amore uint8_t length;
431*49ef7e06SGarrett D'Amore efx_rc_t rc;
432*49ef7e06SGarrett D'Amore
433*49ef7e06SGarrett D'Amore if (pos + 3U > size) {
434*49ef7e06SGarrett D'Amore rc = EFAULT;
435*49ef7e06SGarrett D'Amore goto fail1;
436*49ef7e06SGarrett D'Amore }
437*49ef7e06SGarrett D'Amore
438*49ef7e06SGarrett D'Amore keyword = EFX_VPD_KEYWORD(tag[pos], tag[pos + 1]);
439*49ef7e06SGarrett D'Amore length = tag[pos + 2];
440*49ef7e06SGarrett D'Amore
441*49ef7e06SGarrett D'Amore if (length == 0 || pos + 3U + length > size) {
442*49ef7e06SGarrett D'Amore rc = EFAULT;
443*49ef7e06SGarrett D'Amore goto fail2;
444*49ef7e06SGarrett D'Amore }
445*49ef7e06SGarrett D'Amore
446*49ef7e06SGarrett D'Amore *keywordp = keyword;
447*49ef7e06SGarrett D'Amore *lengthp = length;
448*49ef7e06SGarrett D'Amore
449*49ef7e06SGarrett D'Amore return (0);
450*49ef7e06SGarrett D'Amore
451*49ef7e06SGarrett D'Amore fail2:
452*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
453*49ef7e06SGarrett D'Amore fail1:
454*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
455*49ef7e06SGarrett D'Amore
456*49ef7e06SGarrett D'Amore return (rc);
457*49ef7e06SGarrett D'Amore }
458*49ef7e06SGarrett D'Amore
459*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_hunk_length(__in_bcount (size)caddr_t data,__in size_t size,__out size_t * lengthp)460*49ef7e06SGarrett D'Amore efx_vpd_hunk_length(
461*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
462*49ef7e06SGarrett D'Amore __in size_t size,
463*49ef7e06SGarrett D'Amore __out size_t *lengthp)
464*49ef7e06SGarrett D'Amore {
465*49ef7e06SGarrett D'Amore efx_vpd_tag_t tag;
466*49ef7e06SGarrett D'Amore unsigned int offset;
467*49ef7e06SGarrett D'Amore uint16_t taglen;
468*49ef7e06SGarrett D'Amore efx_rc_t rc;
469*49ef7e06SGarrett D'Amore
470*49ef7e06SGarrett D'Amore offset = 0;
471*49ef7e06SGarrett D'Amore _NOTE(CONSTANTCONDITION)
472*49ef7e06SGarrett D'Amore while (1) {
473*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_next_tag(data, size, &offset,
474*49ef7e06SGarrett D'Amore &tag, &taglen)) != 0)
475*49ef7e06SGarrett D'Amore goto fail1;
476*49ef7e06SGarrett D'Amore offset += taglen;
477*49ef7e06SGarrett D'Amore if (tag == EFX_VPD_END)
478*49ef7e06SGarrett D'Amore break;
479*49ef7e06SGarrett D'Amore }
480*49ef7e06SGarrett D'Amore
481*49ef7e06SGarrett D'Amore *lengthp = offset;
482*49ef7e06SGarrett D'Amore
483*49ef7e06SGarrett D'Amore return (0);
484*49ef7e06SGarrett D'Amore
485*49ef7e06SGarrett D'Amore fail1:
486*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
487*49ef7e06SGarrett D'Amore
488*49ef7e06SGarrett D'Amore return (rc);
489*49ef7e06SGarrett D'Amore }
490*49ef7e06SGarrett D'Amore
491*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_hunk_verify(__in_bcount (size)caddr_t data,__in size_t size,__out_opt boolean_t * cksummedp)492*49ef7e06SGarrett D'Amore efx_vpd_hunk_verify(
493*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
494*49ef7e06SGarrett D'Amore __in size_t size,
495*49ef7e06SGarrett D'Amore __out_opt boolean_t *cksummedp)
496*49ef7e06SGarrett D'Amore {
497*49ef7e06SGarrett D'Amore efx_vpd_tag_t tag;
498*49ef7e06SGarrett D'Amore efx_vpd_keyword_t keyword;
499*49ef7e06SGarrett D'Amore unsigned int offset;
500*49ef7e06SGarrett D'Amore unsigned int pos;
501*49ef7e06SGarrett D'Amore unsigned int i;
502*49ef7e06SGarrett D'Amore uint16_t taglen;
503*49ef7e06SGarrett D'Amore uint8_t keylen;
504*49ef7e06SGarrett D'Amore uint8_t cksum;
505*49ef7e06SGarrett D'Amore boolean_t cksummed = B_FALSE;
506*49ef7e06SGarrett D'Amore efx_rc_t rc;
507*49ef7e06SGarrett D'Amore
508*49ef7e06SGarrett D'Amore /*
509*49ef7e06SGarrett D'Amore * Parse every tag,keyword in the existing VPD. If the csum is present,
510*49ef7e06SGarrett D'Amore * the assert it is correct, and is the final keyword in the RO block.
511*49ef7e06SGarrett D'Amore */
512*49ef7e06SGarrett D'Amore offset = 0;
513*49ef7e06SGarrett D'Amore _NOTE(CONSTANTCONDITION)
514*49ef7e06SGarrett D'Amore while (1) {
515*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_next_tag(data, size, &offset,
516*49ef7e06SGarrett D'Amore &tag, &taglen)) != 0)
517*49ef7e06SGarrett D'Amore goto fail1;
518*49ef7e06SGarrett D'Amore if (tag == EFX_VPD_END)
519*49ef7e06SGarrett D'Amore break;
520*49ef7e06SGarrett D'Amore else if (tag == EFX_VPD_ID)
521*49ef7e06SGarrett D'Amore goto done;
522*49ef7e06SGarrett D'Amore
523*49ef7e06SGarrett D'Amore for (pos = 0; pos != taglen; pos += 3 + keylen) {
524*49ef7e06SGarrett D'Amore /* RV keyword must be the last in the block */
525*49ef7e06SGarrett D'Amore if (cksummed) {
526*49ef7e06SGarrett D'Amore rc = EFAULT;
527*49ef7e06SGarrett D'Amore goto fail2;
528*49ef7e06SGarrett D'Amore }
529*49ef7e06SGarrett D'Amore
530*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_next_keyword(data + offset,
531*49ef7e06SGarrett D'Amore taglen, pos, &keyword, &keylen)) != 0)
532*49ef7e06SGarrett D'Amore goto fail3;
533*49ef7e06SGarrett D'Amore
534*49ef7e06SGarrett D'Amore if (keyword == EFX_VPD_KEYWORD('R', 'V')) {
535*49ef7e06SGarrett D'Amore cksum = 0;
536*49ef7e06SGarrett D'Amore for (i = 0; i < offset + pos + 4; i++)
537*49ef7e06SGarrett D'Amore cksum += data[i];
538*49ef7e06SGarrett D'Amore
539*49ef7e06SGarrett D'Amore if (cksum != 0) {
540*49ef7e06SGarrett D'Amore rc = EFAULT;
541*49ef7e06SGarrett D'Amore goto fail4;
542*49ef7e06SGarrett D'Amore }
543*49ef7e06SGarrett D'Amore
544*49ef7e06SGarrett D'Amore cksummed = B_TRUE;
545*49ef7e06SGarrett D'Amore }
546*49ef7e06SGarrett D'Amore }
547*49ef7e06SGarrett D'Amore
548*49ef7e06SGarrett D'Amore done:
549*49ef7e06SGarrett D'Amore offset += taglen;
550*49ef7e06SGarrett D'Amore }
551*49ef7e06SGarrett D'Amore
552*49ef7e06SGarrett D'Amore if (!cksummed) {
553*49ef7e06SGarrett D'Amore rc = EFAULT;
554*49ef7e06SGarrett D'Amore goto fail5;
555*49ef7e06SGarrett D'Amore }
556*49ef7e06SGarrett D'Amore
557*49ef7e06SGarrett D'Amore if (cksummedp != NULL)
558*49ef7e06SGarrett D'Amore *cksummedp = cksummed;
559*49ef7e06SGarrett D'Amore
560*49ef7e06SGarrett D'Amore return (0);
561*49ef7e06SGarrett D'Amore
562*49ef7e06SGarrett D'Amore fail5:
563*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail5);
564*49ef7e06SGarrett D'Amore fail4:
565*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail4);
566*49ef7e06SGarrett D'Amore fail3:
567*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
568*49ef7e06SGarrett D'Amore fail2:
569*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
570*49ef7e06SGarrett D'Amore fail1:
571*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
572*49ef7e06SGarrett D'Amore
573*49ef7e06SGarrett D'Amore return (rc);
574*49ef7e06SGarrett D'Amore }
575*49ef7e06SGarrett D'Amore
576*49ef7e06SGarrett D'Amore static uint8_t __efx_vpd_blank_pid[] = {
577*49ef7e06SGarrett D'Amore /* Large resource type ID length 1 */
578*49ef7e06SGarrett D'Amore 0x82, 0x01, 0x00,
579*49ef7e06SGarrett D'Amore /* Product name ' ' */
580*49ef7e06SGarrett D'Amore 0x32,
581*49ef7e06SGarrett D'Amore };
582*49ef7e06SGarrett D'Amore
583*49ef7e06SGarrett D'Amore static uint8_t __efx_vpd_blank_r[] = {
584*49ef7e06SGarrett D'Amore /* Large resource type VPD-R length 4 */
585*49ef7e06SGarrett D'Amore 0x90, 0x04, 0x00,
586*49ef7e06SGarrett D'Amore /* RV keyword length 1 */
587*49ef7e06SGarrett D'Amore 'R', 'V', 0x01,
588*49ef7e06SGarrett D'Amore /* RV payload checksum */
589*49ef7e06SGarrett D'Amore 0x00,
590*49ef7e06SGarrett D'Amore };
591*49ef7e06SGarrett D'Amore
592*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_hunk_reinit(__in_bcount (size)caddr_t data,__in size_t size,__in boolean_t wantpid)593*49ef7e06SGarrett D'Amore efx_vpd_hunk_reinit(
594*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
595*49ef7e06SGarrett D'Amore __in size_t size,
596*49ef7e06SGarrett D'Amore __in boolean_t wantpid)
597*49ef7e06SGarrett D'Amore {
598*49ef7e06SGarrett D'Amore unsigned int offset = 0;
599*49ef7e06SGarrett D'Amore unsigned int pos;
600*49ef7e06SGarrett D'Amore efx_byte_t byte;
601*49ef7e06SGarrett D'Amore uint8_t cksum;
602*49ef7e06SGarrett D'Amore efx_rc_t rc;
603*49ef7e06SGarrett D'Amore
604*49ef7e06SGarrett D'Amore if (size < 0x100) {
605*49ef7e06SGarrett D'Amore rc = ENOSPC;
606*49ef7e06SGarrett D'Amore goto fail1;
607*49ef7e06SGarrett D'Amore }
608*49ef7e06SGarrett D'Amore
609*49ef7e06SGarrett D'Amore if (wantpid) {
610*49ef7e06SGarrett D'Amore (void) memcpy(data + offset, __efx_vpd_blank_pid,
611*49ef7e06SGarrett D'Amore sizeof (__efx_vpd_blank_pid));
612*49ef7e06SGarrett D'Amore offset += sizeof (__efx_vpd_blank_pid);
613*49ef7e06SGarrett D'Amore }
614*49ef7e06SGarrett D'Amore
615*49ef7e06SGarrett D'Amore (void) memcpy(data + offset, __efx_vpd_blank_r,
616*49ef7e06SGarrett D'Amore sizeof (__efx_vpd_blank_r));
617*49ef7e06SGarrett D'Amore offset += sizeof (__efx_vpd_blank_r);
618*49ef7e06SGarrett D'Amore
619*49ef7e06SGarrett D'Amore /* Update checksum */
620*49ef7e06SGarrett D'Amore cksum = 0;
621*49ef7e06SGarrett D'Amore for (pos = 0; pos < offset; pos++)
622*49ef7e06SGarrett D'Amore cksum += data[pos];
623*49ef7e06SGarrett D'Amore data[offset - 1] -= cksum;
624*49ef7e06SGarrett D'Amore
625*49ef7e06SGarrett D'Amore /* Append trailing tag */
626*49ef7e06SGarrett D'Amore EFX_POPULATE_BYTE_3(byte,
627*49ef7e06SGarrett D'Amore TAG_TYPE, TAG_TYPE_SMALL_ITEM_DECODE,
628*49ef7e06SGarrett D'Amore TAG_SMALL_ITEM_NAME, TAG_NAME_END_DECODE,
629*49ef7e06SGarrett D'Amore TAG_SMALL_ITEM_SIZE, 0);
630*49ef7e06SGarrett D'Amore data[offset] = EFX_BYTE_FIELD(byte, EFX_BYTE_0);
631*49ef7e06SGarrett D'Amore offset++;
632*49ef7e06SGarrett D'Amore
633*49ef7e06SGarrett D'Amore return (0);
634*49ef7e06SGarrett D'Amore
635*49ef7e06SGarrett D'Amore fail1:
636*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
637*49ef7e06SGarrett D'Amore
638*49ef7e06SGarrett D'Amore return (rc);
639*49ef7e06SGarrett D'Amore }
640*49ef7e06SGarrett D'Amore
641*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_hunk_next(__in_bcount (size)caddr_t data,__in size_t size,__out efx_vpd_tag_t * tagp,__out efx_vpd_keyword_t * keywordp,__out_opt unsigned int * payloadp,__out_opt uint8_t * paylenp,__inout unsigned int * contp)642*49ef7e06SGarrett D'Amore efx_vpd_hunk_next(
643*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
644*49ef7e06SGarrett D'Amore __in size_t size,
645*49ef7e06SGarrett D'Amore __out efx_vpd_tag_t *tagp,
646*49ef7e06SGarrett D'Amore __out efx_vpd_keyword_t *keywordp,
647*49ef7e06SGarrett D'Amore __out_opt unsigned int *payloadp,
648*49ef7e06SGarrett D'Amore __out_opt uint8_t *paylenp,
649*49ef7e06SGarrett D'Amore __inout unsigned int *contp)
650*49ef7e06SGarrett D'Amore {
651*49ef7e06SGarrett D'Amore efx_vpd_tag_t tag;
652*49ef7e06SGarrett D'Amore efx_vpd_keyword_t keyword = 0;
653*49ef7e06SGarrett D'Amore unsigned int offset;
654*49ef7e06SGarrett D'Amore unsigned int pos;
655*49ef7e06SGarrett D'Amore unsigned int index;
656*49ef7e06SGarrett D'Amore uint16_t taglen;
657*49ef7e06SGarrett D'Amore uint8_t keylen;
658*49ef7e06SGarrett D'Amore uint8_t paylen;
659*49ef7e06SGarrett D'Amore efx_rc_t rc;
660*49ef7e06SGarrett D'Amore
661*49ef7e06SGarrett D'Amore offset = index = 0;
662*49ef7e06SGarrett D'Amore _NOTE(CONSTANTCONDITION)
663*49ef7e06SGarrett D'Amore while (1) {
664*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_next_tag(data, size, &offset,
665*49ef7e06SGarrett D'Amore &tag, &taglen)) != 0)
666*49ef7e06SGarrett D'Amore goto fail1;
667*49ef7e06SGarrett D'Amore
668*49ef7e06SGarrett D'Amore if (tag == EFX_VPD_END) {
669*49ef7e06SGarrett D'Amore keyword = 0;
670*49ef7e06SGarrett D'Amore paylen = 0;
671*49ef7e06SGarrett D'Amore index = 0;
672*49ef7e06SGarrett D'Amore break;
673*49ef7e06SGarrett D'Amore }
674*49ef7e06SGarrett D'Amore
675*49ef7e06SGarrett D'Amore if (tag == EFX_VPD_ID) {
676*49ef7e06SGarrett D'Amore if (index++ == *contp) {
677*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(taglen, <, 0x100);
678*49ef7e06SGarrett D'Amore keyword = 0;
679*49ef7e06SGarrett D'Amore paylen = (uint8_t)MIN(taglen, 0xff);
680*49ef7e06SGarrett D'Amore
681*49ef7e06SGarrett D'Amore goto done;
682*49ef7e06SGarrett D'Amore }
683*49ef7e06SGarrett D'Amore } else {
684*49ef7e06SGarrett D'Amore for (pos = 0; pos != taglen; pos += 3 + keylen) {
685*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_next_keyword(data + offset,
686*49ef7e06SGarrett D'Amore taglen, pos, &keyword, &keylen)) != 0)
687*49ef7e06SGarrett D'Amore goto fail2;
688*49ef7e06SGarrett D'Amore
689*49ef7e06SGarrett D'Amore if (index++ == *contp) {
690*49ef7e06SGarrett D'Amore offset += pos + 3;
691*49ef7e06SGarrett D'Amore paylen = keylen;
692*49ef7e06SGarrett D'Amore
693*49ef7e06SGarrett D'Amore goto done;
694*49ef7e06SGarrett D'Amore }
695*49ef7e06SGarrett D'Amore }
696*49ef7e06SGarrett D'Amore }
697*49ef7e06SGarrett D'Amore
698*49ef7e06SGarrett D'Amore offset += taglen;
699*49ef7e06SGarrett D'Amore }
700*49ef7e06SGarrett D'Amore
701*49ef7e06SGarrett D'Amore done:
702*49ef7e06SGarrett D'Amore *tagp = tag;
703*49ef7e06SGarrett D'Amore *keywordp = keyword;
704*49ef7e06SGarrett D'Amore if (payloadp != NULL)
705*49ef7e06SGarrett D'Amore *payloadp = offset;
706*49ef7e06SGarrett D'Amore if (paylenp != NULL)
707*49ef7e06SGarrett D'Amore *paylenp = paylen;
708*49ef7e06SGarrett D'Amore
709*49ef7e06SGarrett D'Amore *contp = index;
710*49ef7e06SGarrett D'Amore return (0);
711*49ef7e06SGarrett D'Amore
712*49ef7e06SGarrett D'Amore fail2:
713*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
714*49ef7e06SGarrett D'Amore fail1:
715*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
716*49ef7e06SGarrett D'Amore
717*49ef7e06SGarrett D'Amore return (rc);
718*49ef7e06SGarrett D'Amore }
719*49ef7e06SGarrett D'Amore
720*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_vpd_hunk_get(__in_bcount (size)caddr_t data,__in size_t size,__in efx_vpd_tag_t tag,__in efx_vpd_keyword_t keyword,__out unsigned int * payloadp,__out uint8_t * paylenp)721*49ef7e06SGarrett D'Amore efx_vpd_hunk_get(
722*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
723*49ef7e06SGarrett D'Amore __in size_t size,
724*49ef7e06SGarrett D'Amore __in efx_vpd_tag_t tag,
725*49ef7e06SGarrett D'Amore __in efx_vpd_keyword_t keyword,
726*49ef7e06SGarrett D'Amore __out unsigned int *payloadp,
727*49ef7e06SGarrett D'Amore __out uint8_t *paylenp)
728*49ef7e06SGarrett D'Amore {
729*49ef7e06SGarrett D'Amore efx_vpd_tag_t itag;
730*49ef7e06SGarrett D'Amore efx_vpd_keyword_t ikeyword;
731*49ef7e06SGarrett D'Amore unsigned int offset;
732*49ef7e06SGarrett D'Amore unsigned int pos;
733*49ef7e06SGarrett D'Amore uint16_t taglen;
734*49ef7e06SGarrett D'Amore uint8_t keylen;
735*49ef7e06SGarrett D'Amore efx_rc_t rc;
736*49ef7e06SGarrett D'Amore
737*49ef7e06SGarrett D'Amore offset = 0;
738*49ef7e06SGarrett D'Amore _NOTE(CONSTANTCONDITION)
739*49ef7e06SGarrett D'Amore while (1) {
740*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_next_tag(data, size, &offset,
741*49ef7e06SGarrett D'Amore &itag, &taglen)) != 0)
742*49ef7e06SGarrett D'Amore goto fail1;
743