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