xref: /illumos-gate/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_element.c (revision 933ae53f0bf0708d7bf2756d3f21936a0d5fad82)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
25  * Use is subject to license terms.
26  */
27 
28 #include <sys/types.h>
29 #include <stddef.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <libnvpair.h>
33 
34 #include <scsi/libses.h>
35 #include "ses2_impl.h"
36 
37 static int
38 elem_parse_device(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
39 {
40 	ses2_device_status_impl_t *dip = (ses2_device_status_impl_t *)esip;
41 	int nverr;
42 
43 	SES_NV_ADD(uint64, nverr, nvl, SES_DEV_PROP_SLOT_ADDR,
44 	    dip->sdsi_slot_addr);
45 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
46 	    dip->sdsi_report);
47 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
48 	    dip->sdsi_ident);
49 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_RMV, dip->sdsi_rmv);
50 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_READY_TO_INSERT,
51 	    dip->sdsi_ready_to_insert);
52 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_ENC_BYP_B,
53 	    dip->sdsi_enclosure_bypassed_b);
54 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_ENC_BYP_A,
55 	    dip->sdsi_enclosure_bypassed_a);
56 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DO_NOT_REMOVE,
57 	    dip->sdsi_do_not_remove);
58 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_APP_BYP_A,
59 	    dip->sdsi_app_client_bypassed_a);
60 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DEV_BYP_B,
61 	    dip->sdsi_device_bypassed_b);
62 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DEV_BYP_A,
63 	    dip->sdsi_device_bypassed_a);
64 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_BYP_B,
65 	    dip->sdsi_bypassed_b);
66 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_BYP_A,
67 	    dip->sdsi_bypassed_a);
68 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_OFF,
69 	    dip->sdsi_device_off);
70 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_FAULT_RQSTD,
71 	    dip->sdsi_fault_reqstd);
72 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_FAULT_SENSED,
73 	    dip->sdsi_fault_sensed);
74 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_APP_BYP_B,
75 	    dip->sdsi_app_client_bypassed_b);
76 
77 	return (0);
78 }
79 
80 static int
81 elem_parse_psu(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
82 {
83 	ses2_psu_status_impl_t *pip = (ses2_psu_status_impl_t *)esip;
84 	int nverr;
85 
86 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
87 	    pip->spsi_ident);
88 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_DC_OVER_CURRENT,
89 	    pip->spsi_dc_over_current);
90 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_DC_UNDER_VOLTAGE,
91 	    pip->spsi_dc_under_voltage);
92 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_DC_OVER_VOLTAGE,
93 	    pip->spsi_dc_over_voltage);
94 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_DC_FAIL,
95 	    pip->spsi_dc_fail);
96 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_AC_FAIL,
97 	    pip->spsi_ac_fail);
98 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_TEMP_WARN,
99 	    pip->spsi_temp_warn);
100 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_OVERTEMP_FAIL,
101 	    pip->spsi_overtmp_fail);
102 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_OFF, pip->spsi_off);
103 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REQUESTED_ON,
104 	    pip->spsi_rqsted_on);
105 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, pip->spsi_fail);
106 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_HOT_SWAP,
107 	    pip->spsi_hot_swap);
108 
109 	return (0);
110 }
111 
112 static int
113 elem_parse_cooling(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
114 {
115 	ses2_cooling_status_impl_t *cip = (ses2_cooling_status_impl_t *)esip;
116 	int nverr;
117 
118 	SES_NV_ADD(uint64, nverr, nvl, SES_COOLING_PROP_FAN_SPEED,
119 	    SES2_ES_COOLING_ST_FAN_SPEED(cip));
120 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
121 	    cip->scsi_ident);
122 	SES_NV_ADD(uint64, nverr, nvl, SES_COOLING_PROP_SPEED_CODE,
123 	    cip->scsi_actual_speed_code);
124 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_OFF, cip->scsi_off);
125 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REQUESTED_ON,
126 	    cip->scsi_requested_on);
127 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, cip->scsi_fail);
128 
129 	return (0);
130 }
131 
132 static int
133 elem_parse_temp(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
134 {
135 	ses2_temp_status_impl_t *tip = (ses2_temp_status_impl_t *)esip;
136 	int nverr;
137 
138 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, tip->stsi_ident);
139 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, tip->stsi_fail);
140 	SES_NV_ADD(int64, nverr, nvl, SES_TEMP_PROP_TEMP,
141 	    SES2_ES_TEMP_ST_TEMPERATURE(tip));
142 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN_UNDER,
143 	    tip->stsi_ut_warn);
144 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_CRIT_UNDER,
145 	    tip->stsi_ut_fail);
146 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN_OVER,
147 	    tip->stsi_ot_warn);
148 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_CRIT_OVER,
149 	    tip->stsi_ot_fail);
150 
151 	return (0);
152 }
153 
154 static int
155 elem_parse_lock(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
156 {
157 	ses2_lock_status_impl_t *lip = (ses2_lock_status_impl_t *)esip;
158 	int nverr;
159 
160 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL,
161 	    lip->slsi_fail);
162 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
163 	    lip->slsi_ident);
164 	SES_NV_ADD(boolean_value, nverr, nvl, SES_LOCK_PROP_UNLOCKED,
165 	    lip->slsi_unlocked);
166 
167 	return (0);
168 }
169 
170 static int
171 elem_parse_alarm(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
172 {
173 	ses2_alarm_status_impl_t *aip = (ses2_alarm_status_impl_t *)esip;
174 	int nverr;
175 
176 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, aip->sasi_fail);
177 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
178 	    aip->sasi_ident);
179 	SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_UNRECOV,
180 	    aip->sasi_unrecov);
181 	SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_CRIT,
182 	    aip->sasi_crit);
183 	SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_NONCRIT,
184 	    aip->sasi_noncrit);
185 	SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_INFO,
186 	    aip->sasi_info);
187 	SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_REMIND,
188 	    aip->sasi_remind);
189 	SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_MUTED,
190 	    aip->sasi_muted);
191 	SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_RQST_MUTE,
192 	    aip->sasi_rqst_mute);
193 
194 	return (0);
195 }
196 
197 static int
198 elem_parse_esc(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
199 {
200 	ses2_controller_status_impl_t *cip =
201 	    (ses2_controller_status_impl_t *)esip;
202 	int nverr;
203 
204 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, cip->scsi_fail);
205 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, cip->scsi_ident);
206 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
207 	    cip->scsi_report);
208 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_HOT_SWAP,
209 	    cip->scsi_hot_swap);
210 
211 	return (0);
212 }
213 
214 static int
215 elem_parse_scc(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
216 {
217 	ses2_scc_status_impl_t *sip = (ses2_scc_status_impl_t *)esip;
218 	int nverr;
219 
220 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, sip->sss_fail);
221 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, sip->sss_ident);
222 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
223 	    sip->sss_report);
224 
225 	return (0);
226 }
227 
228 static int
229 elem_parse_cache(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
230 {
231 	ses2_nvcache_status_impl_t *np = (ses2_nvcache_status_impl_t *)esip;
232 	int nverr;
233 
234 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, np->snsi_fail);
235 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
236 	    np->snsi_ident);
237 	SES_NV_ADD(uint64, nverr, nvl, SES_CACHE_PROP_SIZE,
238 	    SES2_NVCACHE_SIZE(np));
239 
240 	return (0);
241 }
242 
243 static int
244 elem_parse_ups(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
245 {
246 	ses2_ups_status_impl_t *uip = (ses2_ups_status_impl_t *)esip;
247 	int nverr;
248 
249 	SES_NV_ADD(uint64, nverr, nvl, SES_UPS_PROP_TIMELEFT,
250 	    uip->susi_battery_status);
251 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_INTF_FAIL,
252 	    uip->susi_intf_fail);
253 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_WARN,
254 	    uip->susi_warn);
255 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_UPS_FAIL,
256 	    uip->susi_ups_fail);
257 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_DC_FAIL,
258 	    uip->susi_dc_fail);
259 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_AC_FAIL,
260 	    uip->susi_ac_fail);
261 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_AC_QUAL,
262 	    uip->susi_ac_qual);
263 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_AC_HI,
264 	    uip->susi_ac_hi);
265 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_AC_LO,
266 	    uip->susi_ac_lo);
267 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_BPF, uip->susi_bpf);
268 	SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_BATT_FAIL,
269 	    uip->susi_batt_fail);
270 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, uip->susi_fail);
271 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, uip->susi_ident);
272 
273 	return (0);
274 }
275 
276 static int
277 elem_parse_display(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
278 {
279 	ses2_display_status_impl_t *dip = (ses2_display_status_impl_t *)esip;
280 	int nverr;
281 
282 	SES_NV_ADD(uint64, nverr, nvl, SES_DPY_PROP_MODE,
283 	    dip->sdsi_display_mode_status);
284 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, dip->sdsi_fail);
285 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, dip->sdsi_ident);
286 	SES_NV_ADD(uint16, nverr, nvl, SES_DPY_PROP_CHAR,
287 	    dip->sdsi_display_character_status);
288 
289 	return (0);
290 }
291 
292 static int
293 elem_parse_keypad(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
294 {
295 	ses2_keypad_status_impl_t *kip = (ses2_keypad_status_impl_t *)esip;
296 	int nverr;
297 
298 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, kip->sksi_fail);
299 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, kip->sksi_ident);
300 
301 	return (0);
302 }
303 
304 static int
305 elem_parse_px(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
306 {
307 	ses2_port_status_impl_t *pip = (ses2_port_status_impl_t *)esip;
308 	int nverr;
309 
310 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, pip->spsi_fail);
311 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, pip->spsi_ident);
312 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
313 	    pip->spsi_report);
314 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PX_PROP_XMIT_FAIL,
315 	    pip->spsi_xmit_fail);
316 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PX_PROP_LOL, pip->spsi_lol);
317 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_DISABLED,
318 	    pip->spsi_disabled);
319 
320 	return (0);
321 }
322 
323 static int
324 elem_parse_lang(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
325 {
326 	ses2_lang_status_impl_t *lip = (ses2_lang_status_impl_t *)esip;
327 	int nverr;
328 
329 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
330 	    lip->slsi_ident);
331 	SES_NV_ADD(uint64, nverr, nvl, SES_LANG_PROP_LANGCODE,
332 	    SCSI_READ16(&lip->slsi_language_code));
333 
334 	return (0);
335 }
336 
337 static int
338 elem_parse_comm(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
339 {
340 	ses2_comm_status_impl_t *cip = (ses2_comm_status_impl_t *)esip;
341 	int nverr;
342 
343 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, cip->scsi_fail);
344 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
345 	    cip->scsi_ident);
346 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_DISABLED,
347 	    cip->scsi_disabled);
348 
349 	return (0);
350 }
351 
352 static int
353 elem_parse_voltage(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
354 {
355 	ses2_voltage_status_impl_t *vip = (ses2_voltage_status_impl_t *)esip;
356 	int nverr;
357 
358 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_CRIT_UNDER,
359 	    vip->svsi_crit_under);
360 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_CRIT_OVER,
361 	    vip->svsi_crit_over);
362 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN_UNDER,
363 	    vip->svsi_warn_under);
364 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN_OVER,
365 	    vip->svsi_warn_over);
366 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, vip->svsi_fail);
367 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, vip->svsi_ident);
368 	SES_NV_ADD(int64, nverr, nvl, SES_VS_PROP_VOLTAGE_MV,
369 	    SCSI_READ16(&vip->svsi_voltage));
370 
371 	return (0);
372 }
373 
374 static int
375 elem_parse_current(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
376 {
377 	ses2_current_status_impl_t *cip = (ses2_current_status_impl_t *)esip;
378 	int nverr;
379 
380 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_CRIT_OVER,
381 	    cip->scsi_crit_over);
382 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN_OVER,
383 	    cip->scsi_warn_over);
384 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, cip->scsi_fail);
385 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, cip->scsi_ident);
386 	SES_NV_ADD(int64, nverr, nvl, SES_CS_PROP_CURRENT_MA,
387 	    SCSI_READ16(&cip->scsi_current));
388 
389 	return (0);
390 }
391 
392 static int
393 elem_parse_itp(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
394 {
395 	ses2_itp_status_impl_t *iip = (ses2_itp_status_impl_t *)esip;
396 	int nverr;
397 
398 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, iip->sisi_fail);
399 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
400 	    iip->sisi_ident);
401 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
402 	    iip->sisi_report);
403 	SES_NV_ADD(boolean_value, nverr, nvl, SES_ITP_PROP_ENABLED,
404 	    iip->sisi_enabled);
405 
406 	return (0);
407 }
408 
409 static int
410 elem_parse_sse(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
411 {
412 	ses2_ss_status_impl_t *sip = (ses2_ss_status_impl_t *)esip;
413 	int nverr;
414 
415 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, sip->sss_fail);
416 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, sip->sss_ident);
417 	SES_NV_ADD(uint64, nverr, nvl, SES_SS_PROP_SHORT_STATUS,
418 	    sip->sss_short_status);
419 
420 	return (0);
421 }
422 
423 static int
424 elem_parse_arraydev(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
425 {
426 	ses2_array_device_status_impl_t *aip =
427 	    (ses2_array_device_status_impl_t *)esip;
428 	int nverr;
429 
430 	SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_RR_ABORT,
431 	    aip->sadsi_rr_abort);
432 	SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_REBUILD,
433 	    aip->sadsi_rebuild);
434 	SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_IN_FAILED_ARRAY,
435 	    aip->sadsi_in_failed_array);
436 	SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_IN_CRIT_ARRAY,
437 	    aip->sadsi_in_crit_array);
438 	SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_CONS_CHK,
439 	    aip->sadsi_cons_chk);
440 	SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_HOT_SPARE,
441 	    aip->sadsi_hot_spare);
442 	SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_RSVD_DEVICE,
443 	    aip->sadsi_rsvd_device);
444 	SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_OK, aip->sadsi_ok);
445 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
446 	    aip->sadsi_report);
447 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, aip->sadsi_ident);
448 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_RMV, aip->sadsi_rmv);
449 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_READY_TO_INSERT,
450 	    aip->sadsi_ready_to_insert);
451 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_ENC_BYP_B,
452 	    aip->sadsi_enclosure_bypassed_b);
453 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_ENC_BYP_A,
454 	    aip->sadsi_enclosure_bypassed_a);
455 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DO_NOT_REMOVE,
456 	    aip->sadsi_do_not_remove);
457 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_APP_BYP_A,
458 	    aip->sadsi_app_client_bypassed_a);
459 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DEV_BYP_B,
460 	    aip->sadsi_device_bypassed_b);
461 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DEV_BYP_A,
462 	    aip->sadsi_device_bypassed_a);
463 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_BYP_B,
464 	    aip->sadsi_bypassed_b);
465 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_BYP_A,
466 	    aip->sadsi_bypassed_a);
467 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_OFF,
468 	    aip->sadsi_device_off);
469 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_FAULT_RQSTD,
470 	    aip->sadsi_fault_reqstd);
471 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_FAULT_SENSED,
472 	    aip->sadsi_fault_sensed);
473 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_APP_BYP_B,
474 	    aip->sadsi_app_client_bypassed_b);
475 
476 	return (0);
477 }
478 
479 static int
480 elem_parse_expander(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
481 {
482 	ses2_expander_status_impl_t *eip = (ses2_expander_status_impl_t *)esip;
483 	int nverr;
484 
485 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, eip->sesi_fail);
486 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, eip->sesi_ident);
487 
488 	return (0);
489 }
490 
491 static int
492 elem_parse_sasconn(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
493 {
494 	ses2_sasconn_status_impl_t *sip = (ses2_sasconn_status_impl_t *)esip;
495 	int nverr;
496 
497 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, sip->sss_fail);
498 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, sip->sss_ident);
499 	SES_NV_ADD(uint64, nverr, nvl, SES_SC_PROP_CONNECTOR_TYPE,
500 	    sip->sss_connector_type);
501 	SES_NV_ADD(uint64, nverr, nvl, SES_SC_PROP_PHYSICAL_LINK,
502 	    sip->sss_connector_physical_link);
503 
504 	return (0);
505 }
506 
507 static const struct status_parser {
508 	ses2_element_type_t type;
509 	int (*func)(const ses2_elem_status_impl_t *, nvlist_t *);
510 } status_parsers[] = {
511 	{ SES_ET_DEVICE, elem_parse_device },
512 	{ SES_ET_POWER_SUPPLY, elem_parse_psu },
513 	{ SES_ET_COOLING, elem_parse_cooling },
514 	{ SES_ET_TEMPERATURE_SENSOR, elem_parse_temp },
515 	{ SES_ET_DOOR_LOCK, elem_parse_lock },
516 	{ SES_ET_AUDIBLE_ALARM, elem_parse_alarm },
517 	{ SES_ET_ESC_ELECTRONICS, elem_parse_esc },
518 	{ SES_ET_SCC_ELECTRONICS, elem_parse_scc },
519 	{ SES_ET_NONVOLATILE_CACHE, elem_parse_cache },
520 	{ SES_ET_UPS, elem_parse_ups },
521 	{ SES_ET_DISPLAY, elem_parse_display },
522 	{ SES_ET_KEY_PAD_ENTRY, elem_parse_keypad },
523 	{ SES_ET_SCSI_PORT_XCVR, elem_parse_px },
524 	{ SES_ET_LANGUAGE, elem_parse_lang },
525 	{ SES_ET_COMMUNICATION_PORT, elem_parse_comm },
526 	{ SES_ET_VOLTAGE_SENSOR, elem_parse_voltage },
527 	{ SES_ET_CURRENT_SENSOR, elem_parse_current },
528 	{ SES_ET_SCSI_TARGET_PORT, elem_parse_itp },
529 	{ SES_ET_SCSI_INITIATOR_PORT, elem_parse_itp },
530 	{ SES_ET_SIMPLE_SUBENCLOSURE, elem_parse_sse },
531 	{ SES_ET_ARRAY_DEVICE, elem_parse_arraydev },
532 	{ SES_ET_SAS_EXPANDER, elem_parse_expander },
533 	{ SES_ET_SAS_CONNECTOR, elem_parse_sasconn },
534 	{ (ses2_element_type_t)-1, NULL }
535 };
536 
537 static int
538 elem_parse_sd(ses_plugin_t *spp, ses_node_t *np)
539 {
540 	ses2_elem_status_impl_t *esip;
541 	const struct status_parser *sp;
542 	nvlist_t *nvl = ses_node_props(np);
543 	size_t len;
544 	int nverr;
545 	uint64_t type;
546 
547 	if ((esip = ses_plugin_page_lookup(spp,
548 	    ses_node_snapshot(np), SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
549 	    np, &len)) == NULL)
550 		return (0);
551 
552 	VERIFY(nvlist_lookup_uint64(nvl, SES_PROP_ELEMENT_TYPE,
553 	    &type) == 0);
554 
555 	SES_NV_ADD(uint64, nverr, nvl, SES_PROP_STATUS_CODE,
556 	    esip->sesi_common.sesi_status_code);
557 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_SWAP,
558 	    esip->sesi_common.sesi_swap);
559 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_DISABLED,
560 	    esip->sesi_common.sesi_disabled);
561 	SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_PRDFAIL,
562 	    esip->sesi_common.sesi_prdfail);
563 
564 	for (sp = &status_parsers[0]; sp->type != (ses2_element_type_t)-1; sp++)
565 		if (sp->type == type && sp->func != NULL)
566 			return (sp->func(esip, nvl));
567 
568 	return (0);
569 }
570 
571 static int
572 elem_parse_descr(ses_plugin_t *sp, ses_node_t *np)
573 {
574 	char *desc;
575 	size_t len;
576 	nvlist_t *props = ses_node_props(np);
577 	int nverr;
578 
579 	if ((desc = ses_plugin_page_lookup(sp, ses_node_snapshot(np),
580 	    SES2_DIAGPAGE_ELEMENT_DESC, np, &len)) == NULL)
581 		return (0);
582 
583 	SES_NV_ADD(fixed_string, nverr, props, SES_PROP_DESCRIPTION,
584 	    desc, len);
585 
586 	return (0);
587 }
588 
589 static int
590 elem_parse_aes_fc(const ses2_aes_descr_fc_eip_impl_t *fp,
591     nvlist_t *nvl, size_t len)
592 {
593 	int nverr, i;
594 	nvlist_t **nva;
595 	int nports;
596 
597 	if (len < offsetof(ses2_aes_descr_fc_eip_impl_t,
598 	    sadfi_ports))
599 		return (0);
600 
601 	SES_NV_ADD(uint64, nverr, nvl, SES_PROP_BAY_NUMBER,
602 	    fp->sadfi_bay_number);
603 	SES_NV_ADD(uint64, nverr, nvl, SES_FC_PROP_NODE_NAME,
604 	    SCSI_READ64(&fp->sadfi_node_name));
605 
606 	nports = MIN(fp->sadfi_n_ports,
607 	    (len - offsetof(ses2_aes_descr_fc_eip_impl_t,
608 	    sadfi_ports)) / sizeof (ses2_aes_port_descr_impl_t));
609 
610 	if (nports == 0)
611 		return (0);
612 
613 	nva = ses_zalloc(nports * sizeof (nvlist_t *));
614 	if (nva == NULL)
615 		return (-1);
616 
617 	for (i = 0; i < nports; i++) {
618 		if ((nverr = nvlist_alloc(&nva[i], NV_UNIQUE_NAME, 0)) != 0)
619 			goto fail;
620 		if ((nverr = nvlist_add_uint64(nva[i], SES_FC_PROP_LOOP_POS,
621 		    fp->sadfi_ports[i].sapdi_port_loop_position)) != 0)
622 			goto fail;
623 		if ((nverr = nvlist_add_uint64(nva[i], SES_FC_PROP_REQ_HARDADDR,
624 		    fp->sadfi_ports[i].sapdi_port_requested_hard_address)) != 0)
625 			goto fail;
626 		nverr = nvlist_add_uint64(nva[i], SES_FC_PROP_N_PORT_ID,
627 		    SCSI_READ24(fp->sadfi_ports[i].sapdi_n_port_identifier));
628 		if (nverr != 0)
629 			goto fail;
630 		if ((nverr = nvlist_add_uint64(nva[i], SES_FC_PROP_N_PORT_NAME,
631 		    SCSI_READ64(&fp->sadfi_ports[i].sapdi_n_port_name))) != 0)
632 			goto fail;
633 	}
634 
635 	if ((nverr = nvlist_add_nvlist_array(nvl, SES_FC_PROP_PORTS,
636 	    nva, nports)) != 0)
637 		goto fail;
638 
639 	for (i = 0; i < nports && nva[i] != NULL; i++)
640 		nvlist_free(nva[i]);
641 	ses_free(nva);
642 	return (0);
643 
644 fail:
645 	for (i = 0; i < nports && nva[i] != NULL; i++)
646 		nvlist_free(nva[i]);
647 	ses_free(nva);
648 	return (ses_set_nverrno(nverr, NULL));
649 }
650 
651 static int
652 elem_parse_aes_device(const ses2_aes_descr_eip_impl_t *dep, nvlist_t *nvl,
653     size_t len)
654 {
655 	ses2_aes_descr_fc_eip_impl_t *fp;
656 	ses2_aes_descr_sas0_eip_impl_t *s0ep;
657 	ses2_aes_descr_sas0_impl_t *s0p;
658 	ses2_aes_descr_impl_t *dip;
659 	nvlist_t **nva;
660 	int nverr, i;
661 	size_t nphy;
662 
663 	if (dep->sadei_eip) {
664 		s0ep = (ses2_aes_descr_sas0_eip_impl_t *)
665 		    dep->sadei_protocol_specific;
666 		s0p = (ses2_aes_descr_sas0_impl_t *)
667 		    dep->sadei_protocol_specific;
668 	} else {
669 		dip = (ses2_aes_descr_impl_t *)dep;
670 		s0ep = NULL;
671 		s0p = (ses2_aes_descr_sas0_impl_t *)
672 		    dip->sadei_protocol_specific;
673 	}
674 
675 	if (dep->sadei_invalid)
676 		return (0);
677 
678 	if (dep->sadei_protocol_identifier == SPC4_PROTO_FIBRE_CHANNEL) {
679 		fp = (ses2_aes_descr_fc_eip_impl_t *)
680 		    dep->sadei_protocol_specific;
681 
682 		if (!SES_WITHIN_PAGE_STRUCT(fp, dep, len))
683 			return (0);
684 
685 		return (elem_parse_aes_fc(fp, nvl, len -
686 		    offsetof(ses2_aes_descr_eip_impl_t,
687 		    sadei_protocol_specific)));
688 	} else if (dep->sadei_protocol_identifier != SPC4_PROTO_SAS) {
689 		return (0);
690 	}
691 
692 	if (s0p->sadsi_descriptor_type != SES2_AESD_SAS_DEVICE)
693 		return (0);
694 
695 	SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_SAS_NOT_ALL_PHYS,
696 	    s0p->sadsi_not_all_phys);
697 	if (s0ep != NULL) {
698 		SES_NV_ADD(uint64, nverr, nvl, SES_PROP_BAY_NUMBER,
699 		    s0ep->sadsi_bay_number);
700 		nphy = MIN(s0ep->sadsi_n_phy_descriptors,
701 		    (len - offsetof(ses2_aes_descr_sas0_eip_impl_t,
702 		    sadsi_phys)) / sizeof (ses2_aes_phy0_descr_impl_t));
703 	} else {
704 		nphy = MIN(s0p->sadsi_n_phy_descriptors,
705 		    (len - offsetof(ses2_aes_descr_sas0_impl_t,
706 		    sadsi_phys)) / sizeof (ses2_aes_phy0_descr_impl_t));
707 	}
708 
709 	if (nphy == 0)
710 		return (0);
711 
712 	nva = ses_zalloc(nphy * sizeof (nvlist_t *));
713 	if (nva == NULL)
714 		return (-1);
715 
716 	for (i = 0; i < nphy; i++) {
717 		ses2_aes_phy0_descr_impl_t *pp;
718 		pp = s0ep != NULL ? &s0ep->sadsi_phys[i] : &s0p->sadsi_phys[i];
719 		if ((nverr = nvlist_alloc(&nva[i], NV_UNIQUE_NAME, 0)) != 0)
720 			goto fail;
721 		if ((nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_DEVICE_TYPE,
722 		    pp->sapdi_device_type)) != 0)
723 			goto fail;
724 		if ((nverr = nvlist_add_boolean_value(nva[i],
725 		    SES_SAS_PROP_SMPI_PORT, pp->sapdi_smp_initiator_port)) != 0)
726 			goto fail;
727 		if ((nverr = nvlist_add_boolean_value(nva[i],
728 		    SES_SAS_PROP_STPI_PORT, pp->sapdi_stp_initiator_port)) != 0)
729 			goto fail;
730 		if ((nverr = nvlist_add_boolean_value(nva[i],
731 		    SES_SAS_PROP_SSPI_PORT, pp->sapdi_ssp_initiator_port)) != 0)
732 			goto fail;
733 		if ((nverr = nvlist_add_boolean_value(nva[i],
734 		    SES_SAS_PROP_SATA_DEVICE, pp->sapdi_sata_device)) != 0)
735 			goto fail;
736 		if ((nverr = nvlist_add_boolean_value(nva[i],
737 		    SES_SAS_PROP_SMPT_PORT, pp->sapdi_smp_target_port)) != 0)
738 			goto fail;
739 		if ((nverr = nvlist_add_boolean_value(nva[i],
740 		    SES_SAS_PROP_STPT_PORT, pp->sapdi_stp_target_port)) != 0)
741 			goto fail;
742 		if ((nverr = nvlist_add_boolean_value(nva[i],
743 		    SES_SAS_PROP_SSPT_PORT, pp->sapdi_ssp_target_port)) != 0)
744 			goto fail;
745 		nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_ATT_ADDR,
746 		    SCSI_READ64(&pp->sapdi_attached_sas_address));
747 		if (nverr != 0)
748 			goto fail;
749 		nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_ADDR,
750 		    SCSI_READ64(&pp->sapdi_sas_address));
751 		if (nverr != 0)
752 			goto fail;
753 		if ((nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_PHY_ID,
754 		    pp->sapdi_phy_identifier)) != 0)
755 			goto fail;
756 	}
757 
758 	if ((nverr = nvlist_add_nvlist_array(nvl, SES_SAS_PROP_PHYS,
759 	    nva, nphy)) != 0)
760 		goto fail;
761 
762 	for (i = 0; i < nphy && nva[i] != NULL; i++)
763 		nvlist_free(nva[i]);
764 	ses_free(nva);
765 	return (0);
766 
767 fail:
768 	for (i = 0; i < nphy && nva[i] != NULL; i++)
769 		nvlist_free(nva[i]);
770 	ses_free(nva);
771 	return (ses_set_nverrno(nverr, NULL));
772 }
773 
774 static int
775 elem_parse_aes_expander(const ses2_aes_descr_eip_impl_t *dep, nvlist_t *nvl,
776     size_t len)
777 {
778 	ses2_aes_descr_exp_impl_t *sep;
779 	nvlist_t **nva;
780 	int nverr, i;
781 	size_t nphy;
782 
783 	if (dep->sadei_invalid)
784 		return (0);
785 
786 	/*
787 	 * This should never happen; no current SAS expander can have any
788 	 * other kind of ports.  But maybe someday - one could envision a
789 	 * SAS expander with iSCSI target ports, for example.
790 	 */
791 	if (dep->sadei_protocol_identifier != SPC4_PROTO_SAS)
792 		return (0);
793 
794 	sep = (ses2_aes_descr_exp_impl_t *)dep->sadei_protocol_specific;
795 	if (sep->sadei_descriptor_type != SES2_AESD_SAS_OTHER)
796 		return (0);
797 
798 	SES_NV_ADD(uint64, nverr, nvl, SES_EXP_PROP_SAS_ADDR,
799 	    SCSI_READ64(&sep->sadei_sas_address));
800 
801 	nphy = MIN(sep->sadei_n_exp_phy_descriptors,
802 	    (len - offsetof(ses2_aes_descr_exp_impl_t,
803 	    sadei_phys)) / sizeof (ses2_aes_exp_phy_descr_impl_t));
804 
805 	if (nphy == 0)
806 		return (0);
807 
808 	nva = ses_zalloc(nphy * sizeof (nvlist_t *));
809 	if (nva == NULL)
810 		return (-1);
811 
812 	for (i = 0; i < nphy; i++) {
813 		if ((nverr = nvlist_alloc(&nva[i], NV_UNIQUE_NAME, 0)) != 0)
814 			goto fail;
815 		if ((nverr = nvlist_add_uint64(nva[i], SES_PROP_CE_IDX,
816 		    sep->sadei_phys[i].saepdi_connector_element_index)) != 0)
817 			goto fail;
818 		if ((nverr = nvlist_add_uint64(nva[i], SES_PROP_OE_IDX,
819 		    sep->sadei_phys[i].saepdi_other_element_index)) != 0)
820 			goto fail;
821 	}
822 
823 	if ((nverr = nvlist_add_nvlist_array(nvl, SES_SAS_PROP_PHYS,
824 	    nva, nphy)) != 0)
825 		goto fail;
826 
827 	for (i = 0; i < nphy && nva[i] != NULL; i++)
828 		nvlist_free(nva[i]);
829 	ses_free(nva);
830 	return (0);
831 
832 fail:
833 	for (i = 0; i < nphy && nva[i] != NULL; i++)
834 		nvlist_free(nva[i]);
835 	ses_free(nva);
836 	return (ses_set_nverrno(nverr, NULL));
837 }
838 
839 static int
840 elem_parse_aes_misc(const ses2_aes_descr_eip_impl_t *dep, nvlist_t *nvl,
841     size_t len)
842 {
843 	ses2_aes_descr_fc_eip_impl_t *fp;
844 	ses2_aes_descr_sas1_impl_t *s1p;
845 	nvlist_t **nva;
846 	int nverr, i;
847 	size_t nphy;
848 
849 	if (dep->sadei_invalid)
850 		return (0);
851 
852 	if (dep->sadei_protocol_identifier == SPC4_PROTO_FIBRE_CHANNEL) {
853 		fp = (ses2_aes_descr_fc_eip_impl_t *)
854 		    dep->sadei_protocol_specific;
855 
856 		if (!SES_WITHIN_PAGE_STRUCT(fp, dep, len))
857 			return (0);
858 
859 		return (elem_parse_aes_fc(fp, nvl, len -
860 		    offsetof(ses2_aes_descr_eip_impl_t,
861 		    sadei_protocol_specific)));
862 	} else if (dep->sadei_protocol_identifier != SPC4_PROTO_SAS) {
863 		return (0);
864 	}
865 
866 	s1p = (ses2_aes_descr_sas1_impl_t *)dep->sadei_protocol_specific;
867 	if (s1p->sadsi_descriptor_type == SES2_AESD_SAS_DEVICE)
868 		return (0);
869 
870 	nphy = MIN(s1p->sadsi_n_phy_descriptors,
871 	    (len - offsetof(ses2_aes_descr_sas1_impl_t,
872 	    sadsi_phys)) / sizeof (ses2_aes_phy1_descr_impl_t));
873 
874 	if (nphy == 0)
875 		return (0);
876 
877 	nva = ses_zalloc(nphy * sizeof (nvlist_t *));
878 	if (nva == NULL)
879 		return (-1);
880 
881 	for (i = 0; i < nphy; i++) {
882 		if ((nverr = nvlist_alloc(&nva[i], NV_UNIQUE_NAME, 0)) != 0)
883 			goto fail;
884 		if ((nverr = nvlist_add_uint64(nva[i], SES_PROP_CE_IDX,
885 		    s1p->sadsi_phys[i].sapdi_connector_element_index)) != 0)
886 			goto fail;
887 		if ((nverr = nvlist_add_uint64(nva[i], SES_PROP_OE_IDX,
888 		    s1p->sadsi_phys[i].sapdi_other_element_index)) != 0)
889 			goto fail;
890 		if ((nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_ADDR,
891 		    SCSI_READ64(&s1p->sadsi_phys[i].sapdi_sas_address))) != 0)
892 			goto fail;
893 	}
894 
895 	if ((nverr = nvlist_add_nvlist_array(nvl, SES_SAS_PROP_PHYS,
896 	    nva, nphy)) != 0)
897 		goto fail;
898 
899 	for (i = 0; i < nphy && nva[i] != NULL; i++)
900 		nvlist_free(nva[i]);
901 
902 	ses_free(nva);
903 	return (0);
904 
905 fail:
906 	for (i = 0; i < nphy && nva[i] != NULL; i++)
907 		nvlist_free(nva[i]);
908 	ses_free(nva);
909 	return (nverr);
910 }
911 
912 static const struct aes_parser {
913 	ses2_element_type_t type;
914 	int (*func)(const ses2_aes_descr_eip_impl_t *, nvlist_t *, size_t);
915 } aes_parsers[] = {
916 	{ SES_ET_DEVICE, elem_parse_aes_device },
917 	{ SES_ET_SCSI_TARGET_PORT, elem_parse_aes_misc },
918 	{ SES_ET_SCSI_INITIATOR_PORT, elem_parse_aes_misc },
919 	{ SES_ET_ESC_ELECTRONICS, elem_parse_aes_misc },
920 	{ SES_ET_ARRAY_DEVICE, elem_parse_aes_device },
921 	{ SES_ET_SAS_EXPANDER, elem_parse_aes_expander },
922 	{ (ses2_element_type_t)-1, NULL }
923 };
924 
925 static int
926 elem_parse_aes(ses_plugin_t *sp, ses_node_t *np)
927 {
928 	ses2_aes_descr_eip_impl_t *dep;
929 	nvlist_t *props = ses_node_props(np);
930 	const struct aes_parser *app;
931 	uint64_t type;
932 	size_t len;
933 
934 	if (ses_node_type(np) == SES_NODE_AGGREGATE)
935 		return (0);
936 
937 	VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE,
938 	    &type) == 0);
939 
940 	for (app = &aes_parsers[0]; app->func != NULL; app++)
941 		if (app->type == type)
942 			break;
943 	if (app->func == NULL)
944 		return (0);
945 
946 	if ((dep = ses_plugin_page_lookup(sp, ses_node_snapshot(np),
947 	    SES2_DIAGPAGE_ADDL_ELEM_STATUS, np, &len)) == NULL)
948 		return (0);
949 
950 	return (app->func(dep, props, len));
951 }
952 
953 static int
954 elem_parse_threshold(ses_plugin_t *sp, ses_node_t *np)
955 {
956 	ses_snap_t *snap = ses_node_snapshot(np);
957 	ses2_threshold_impl_t *tp;
958 	nvlist_t *nvl = ses_node_props(np);
959 	int nverr;
960 	uint64_t type;
961 	size_t len;
962 
963 	VERIFY(nvlist_lookup_uint64(nvl, SES_PROP_ELEMENT_TYPE,
964 	    &type) == 0);
965 
966 	switch (type) {
967 	case SES_ET_TEMPERATURE_SENSOR:
968 	case SES_ET_UPS:
969 	case SES_ET_VOLTAGE_SENSOR:
970 	case SES_ET_CURRENT_SENSOR:
971 		break;
972 	default:
973 		return (0);
974 	}
975 
976 	if ((tp = ses_plugin_page_lookup(sp, snap,
977 	    SES2_DIAGPAGE_THRESHOLD_IO, np, &len)) == NULL)
978 		return (0);
979 
980 	SES_NV_ADD(uint64, nverr, nvl, SES_PROP_THRESH_CRIT_HI,
981 	    tp->sti_high_crit);
982 	SES_NV_ADD(uint64, nverr, nvl, SES_PROP_THRESH_WARN_HI,
983 	    tp->sti_high_warn);
984 	SES_NV_ADD(uint64, nverr, nvl, SES_PROP_THRESH_CRIT_LO,
985 	    tp->sti_low_crit);
986 	SES_NV_ADD(uint64, nverr, nvl, SES_PROP_THRESH_WARN_LO,
987 	    tp->sti_low_warn);
988 
989 	return (0);
990 }
991 
992 int
993 ses2_fill_element_node(ses_plugin_t *sp, ses_node_t *np)
994 {
995 	int err;
996 
997 	if ((err = elem_parse_sd(sp, np)) != 0)
998 		return (err);
999 
1000 	if ((err = elem_parse_descr(sp, np)) != 0)
1001 		return (err);
1002 
1003 	if ((err = elem_parse_aes(sp, np)) != 0)
1004 		return (err);
1005 
1006 	if ((err = elem_parse_threshold(sp, np)) != 0)
1007 		return (err);
1008 
1009 	return (0);
1010 }
1011