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