diff --git a/sys/cam/scsi/scsi_ses.h b/sys/cam/scsi/scsi_ses.h index 86cc88ad27f1..8a1c7118f99a 100644 --- a/sys/cam/scsi/scsi_ses.h +++ b/sys/cam/scsi/scsi_ses.h @@ -1,2470 +1,2514 @@ /* $FreeBSD$ */ /*- * SPDX-License-Identifier: (BSD-2-Clause-FreeBSD OR GPL-2.0) * * Copyright (c) 2000 by Matthew Jacob * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * the GNU Public License ("GPL"). * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifndef _SCSI_SES_H_ #define _SCSI_SES_H_ #include /*========================== Field Extraction Macros =========================*/ #define MK_ENUM(S, F, SUFFIX) S ## _ ## F ## SUFFIX #define GEN_GETTER(LS, US, LF, UF) \ static inline int \ LS ## _get_ ## LF(struct LS *elem) { \ return ((elem->bytes[MK_ENUM(US,UF,_BYTE)] & MK_ENUM(US,UF,_MASK)) \ >> MK_ENUM(US,UF,_SHIFT)); \ } #define GEN_SETTER(LS, US, LF, UF) \ static inline void \ LS ## _set_ ## LF(struct LS *elem, int val) { \ elem->bytes[MK_ENUM(US,UF,_BYTE)] &= ~MK_ENUM(US,UF,_MASK); \ elem->bytes[MK_ENUM(US,UF,_BYTE)] |= \ (val << MK_ENUM(US,UF,_SHIFT)) & MK_ENUM(US,UF,_MASK); \ } #define GEN_HDR_GETTER(LS, US, LF, UF) \ static inline int \ LS ## _get_ ## LF(struct LS *page) { \ return ((page->hdr.page_specific_flags & MK_ENUM(US,UF,_MASK)) \ >> MK_ENUM(US,UF,_SHIFT)); \ } #define GEN_HDR_SETTER(LS, US, LF, UF) \ static inline void \ LS ## _set_ ## LF(struct LS *page, int val) { \ page->hdr.page_specific_flags &= ~MK_ENUM(US,UF,_MASK); \ page->hdr.page_specific_flags |= \ (val << MK_ENUM(US,UF,_SHIFT)) & MK_ENUM(US,UF,_MASK); \ } #define GEN_ACCESSORS(LS, US, LF, UF) \ GEN_GETTER(LS, US, LF, UF) \ GEN_SETTER(LS, US, LF, UF) #define GEN_HDR_ACCESSORS(LS, US, LF, UF) \ GEN_HDR_GETTER(LS, US, LF, UF) \ GEN_HDR_SETTER(LS, US, LF, UF) /*=============== Common SCSI ENC Diagnostic Page Structures ===============*/ struct ses_page_hdr { uint8_t page_code; uint8_t page_specific_flags; uint8_t length[2]; uint8_t gen_code[4]; }; static inline size_t ses_page_length(const struct ses_page_hdr *hdr) { /* * The page length as received only accounts for bytes that * follow the length field, namely starting with the generation * code field. */ return (scsi_2btoul(hdr->length) + offsetof(struct ses_page_hdr, gen_code)); } /*============= SCSI ENC Configuration Diagnostic Page Structures ============*/ struct ses_enc_desc { uint8_t byte0; /* * reserved0 : 1, * rel_id : 3, relative enclosure process id * reserved1 : 1, * num_procs : 3; number of enclosure procesenc */ uint8_t subenc_id; /* Sub-enclosure Identifier */ uint8_t num_types; /* # of supported types */ uint8_t length; /* Enclosure Descriptor Length */ uint8_t logical_id[8]; /* formerly wwn */ uint8_t vendor_id[8]; uint8_t product_id[16]; uint8_t product_rev[4]; uint8_t vendor_bytes[]; }; static inline uint8_t * ses_enc_desc_last_byte(struct ses_enc_desc *encdesc) { return (&encdesc->length + encdesc->length); } static inline struct ses_enc_desc * ses_enc_desc_next(struct ses_enc_desc *encdesc) { return ((struct ses_enc_desc *)(ses_enc_desc_last_byte(encdesc) + 1)); } static inline int ses_enc_desc_is_complete(struct ses_enc_desc *encdesc, uint8_t *last_buf_byte) { return (&encdesc->length <= last_buf_byte && ses_enc_desc_last_byte(encdesc) <= last_buf_byte); } struct ses_elm_type_desc { uint8_t etype_elm_type; /* type of element */ uint8_t etype_maxelt; /* maximum supported */ uint8_t etype_subenc; /* in sub-enclosure #n */ uint8_t etype_txt_len; /* Type Descriptor Text Length */ }; struct ses_cfg_page { struct ses_page_hdr hdr; struct ses_enc_desc subencs[]; /* type descriptors */ /* type text */ }; static inline int ses_cfg_page_get_num_subenc(struct ses_cfg_page *page) { return (page->hdr.page_specific_flags + 1); } /*================ SCSI SES Control Diagnostic Page Structures ==============*/ struct ses_ctrl_common { uint8_t bytes[1]; }; enum ses_ctrl_common_field_data { SES_CTRL_COMMON_SELECT_BYTE = 0, SES_CTRL_COMMON_SELECT_MASK = 0x80, SES_CTRL_COMMON_SELECT_SHIFT = 7, SES_CTRL_COMMON_PRDFAIL_BYTE = 0, SES_CTRL_COMMON_PRDFAIL_MASK = 0x40, SES_CTRL_COMMON_PRDFAIL_SHIFT = 6, SES_CTRL_COMMON_DISABLE_BYTE = 0, SES_CTRL_COMMON_DISABLE_MASK = 0x20, SES_CTRL_COMMON_DISABLE_SHIFT = 5, SES_CTRL_COMMON_RST_SWAP_BYTE = 0, SES_CTRL_COMMON_RST_SWAP_MASK = 0x10, SES_CTRL_COMMON_RST_SWAP_SHIFT = 4 }; #define GEN_SES_CTRL_COMMON_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_common, SES_CTRL_COMMON, LCASE, UCASE) GEN_SES_CTRL_COMMON_ACCESSORS(select, SELECT) GEN_SES_CTRL_COMMON_ACCESSORS(prdfail, PRDFAIL) GEN_SES_CTRL_COMMON_ACCESSORS(disable, DISABLE) GEN_SES_CTRL_COMMON_ACCESSORS(rst_swap, RST_SWAP) #undef GEN_SES_CTRL_COMMON_ACCESSORS /*------------------------ Device Slot Control Element ----------------------*/ struct ses_ctrl_dev_slot { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_dev_slot_field_data { SES_CTRL_DEV_SLOT_RQST_ACTIVE_BYTE = 1, SES_CTRL_DEV_SLOT_RQST_ACTIVE_MASK = 0x80, SES_CTRL_DEV_SLOT_RQST_ACTIVE_SHIFT = 7, SES_CTRL_DEV_SLOT_DO_NOT_REMOVE_BYTE = 1, SES_CTRL_DEV_SLOT_DO_NOT_REMOVE_MASK = 0x40, SES_CTRL_DEV_SLOT_DO_NOT_REMOVE_SHIFT = 6, SES_CTRL_DEV_SLOT_RQST_MISSING_BYTE = 1, SES_CTRL_DEV_SLOT_RQST_MISSING_MASK = 0x10, SES_CTRL_DEV_SLOT_RQST_MISSING_SHIFT = 4, SES_CTRL_DEV_SLOT_RQST_INSERT_BYTE = 1, SES_CTRL_DEV_SLOT_RQST_INSERT_MASK = 0x08, SES_CTRL_DEV_SLOT_RQST_INSERT_SHIFT = 3, SES_CTRL_DEV_SLOT_RQST_REMOVE_BYTE = 1, SES_CTRL_DEV_SLOT_RQST_REMOVE_MASK = 0x04, SES_CTRL_DEV_SLOT_RQST_REMOVE_SHIFT = 2, SES_CTRL_DEV_SLOT_RQST_IDENT_BYTE = 1, SES_CTRL_DEV_SLOT_RQST_IDENT_MASK = 0x02, SES_CTRL_DEV_SLOT_RQST_IDENT_SHIFT = 1, SES_CTRL_DEV_SLOT_RQST_FAULT_BYTE = 2, SES_CTRL_DEV_SLOT_RQST_FAULT_MASK = 0x20, SES_CTRL_DEV_SLOT_RQST_FAULT_SHIFT = 5, SES_CTRL_DEV_SLOT_DEVICE_OFF_BYTE = 2, SES_CTRL_DEV_SLOT_DEVICE_OFF_MASK = 0x10, SES_CTRL_DEV_SLOT_DEVICE_OFF_SHIFT = 4, SES_CTRL_DEV_SLOT_ENABLE_BYP_A_BYTE = 2, SES_CTRL_DEV_SLOT_ENABLE_BYP_A_MASK = 0x08, SES_CTRL_DEV_SLOT_ENABLE_BYP_A_SHIFT = 3, SES_CTRL_DEV_SLOT_ENABLE_BYP_B_BYTE = 2, SES_CTRL_DEV_SLOT_ENABLE_BYP_B_MASK = 0x04, SES_CTRL_DEV_SLOT_ENABLE_BYP_B_SHIFT = 2 }; #define GEN_SES_CTRL_DEV_SLOT_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_dev_slot, SES_CTRL_DEV_SLOT, LCASE, UCASE) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_active, RQST_ACTIVE) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(do_not_remove, DO_NOT_REMOVE) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_missing, RQST_MISSING) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_insert, RQST_INSERT) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_remove, RQST_REMOVE) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_fault, RQST_FAULT) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(device_off, DEVICE_OFF) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(enable_byp_a, ENABLE_BYP_A) GEN_SES_CTRL_DEV_SLOT_ACCESSORS(enable_byp_b, ENABLE_BYP_B) #undef GEN_SES_CTRL_DEV_SLOT_ACCESSORS /*--------------------- Array Device Slot Control Element --------------------*/ struct ses_ctrl_array_dev_slot { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_array_dev_slot_field_data { SES_CTRL_ARRAY_DEV_SLOT_RQST_OK_BYTE = 0, SES_CTRL_ARRAY_DEV_SLOT_RQST_OK_MASK = 0x80, SES_CTRL_ARRAY_DEV_SLOT_RQST_OK_SHIFT = 7, SES_CTRL_ARRAY_DEV_SLOT_RQST_RSVD_DEVICE_BYTE = 0, SES_CTRL_ARRAY_DEV_SLOT_RQST_RSVD_DEVICE_MASK = 0x40, SES_CTRL_ARRAY_DEV_SLOT_RQST_RSVD_DEVICE_SHIFT = 6, SES_CTRL_ARRAY_DEV_SLOT_RQST_HOT_SPARE_BYTE = 0, SES_CTRL_ARRAY_DEV_SLOT_RQST_HOT_SPARE_MASK = 0x20, SES_CTRL_ARRAY_DEV_SLOT_RQST_HOT_SPARE_SHIFT = 5, SES_CTRL_ARRAY_DEV_SLOT_RQST_CONS_CHECK_BYTE = 0, SES_CTRL_ARRAY_DEV_SLOT_RQST_CONS_CHECK_MASK = 0x10, SES_CTRL_ARRAY_DEV_SLOT_RQST_CONS_CHECK_SHIFT = 4, SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_CRIT_ARRAY_BYTE = 0, SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_CRIT_ARRAY_MASK = 0x08, SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_CRIT_ARRAY_SHIFT = 3, SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_FAILED_ARRAY_BYTE = 0, SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_FAILED_ARRAY_MASK = 0x04, SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_FAILED_ARRAY_SHIFT = 2, SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_BYTE = 0, SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_MASK = 0x02, SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_SHIFT = 1, SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_ABORT_BYTE = 0, SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_ABORT_MASK = 0x01, SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_ABORT_SHIFT = 0 /* * The remaining fields are identical to the device * slot element type. Access them through the device slot * element type and its accessors. */ }; #define GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_array_dev_slot, SES_CTRL_ARRAY_DEV_SLOT, \ LCASE, UCASE) GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_ok, RQST_OK) GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_rsvd_device, RQST_RSVD_DEVICE) GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_hot_spare, RQST_HOT_SPARE) GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_cons_check, RQST_CONS_CHECK) GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_in_crit_array, RQST_IN_CRIT_ARRAY) GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_in_failed_array, RQST_IN_FAILED_ARRAY) GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_rebuild_remap, RQST_REBUILD_REMAP) GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_rebuild_remap_abort, RQST_REBUILD_REMAP_ABORT) #undef GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS /*----------------------- Power Supply Control Element -----------------------*/ struct ses_ctrl_power_supply { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_power_supply_field_data { SES_CTRL_POWER_SUPPLY_RQST_IDENT_BYTE = 0, SES_CTRL_POWER_SUPPLY_RQST_IDENT_MASK = 0x80, SES_CTRL_POWER_SUPPLY_RQST_IDENT_SHIFT = 7, SES_CTRL_POWER_SUPPLY_RQST_FAIL_BYTE = 2, SES_CTRL_POWER_SUPPLY_RQST_FAIL_MASK = 0x40, SES_CTRL_POWER_SUPPLY_RQST_FAIL_SHIFT = 6, SES_CTRL_POWER_SUPPLY_RQST_ON_BYTE = 2, SES_CTRL_POWER_SUPPLY_RQST_ON_MASK = 0x20, SES_CTRL_POWER_SUPPLY_RQST_ON_SHIFT = 5 }; #define GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_power_supply, SES_CTRL_POWER_SUPPLY, LCASE, UCASE) GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS(rqst_on, RQST_ON) #undef GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS /*-------------------------- Cooling Control Element -------------------------*/ struct ses_ctrl_cooling { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_cooling_field_data { SES_CTRL_COOLING_RQST_IDENT_BYTE = 0, SES_CTRL_COOLING_RQST_IDENT_MASK = 0x80, SES_CTRL_COOLING_RQST_IDENT_SHIFT = 7, SES_CTRL_COOLING_RQST_FAIL_BYTE = 2, SES_CTRL_COOLING_RQST_FAIL_MASK = 0x40, SES_CTRL_COOLING_RQST_FAIL_SHIFT = 6, SES_CTRL_COOLING_RQST_ON_BYTE = 2, SES_CTRL_COOLING_RQST_ON_MASK = 0x20, SES_CTRL_COOLING_RQST_ON_SHIFT = 5, SES_CTRL_COOLING_RQSTED_SPEED_CODE_BYTE = 2, SES_CTRL_COOLING_RQSTED_SPEED_CODE_MASK = 0x07, SES_CTRL_COOLING_RQSTED_SPEED_CODE_SHIFT = 2, SES_CTRL_COOLING_RQSTED_SPEED_CODE_UNCHANGED = 0x00, SES_CTRL_COOLING_RQSTED_SPEED_CODE_LOWEST = 0x01, SES_CTRL_COOLING_RQSTED_SPEED_CODE_HIGHEST = 0x07 }; #define GEN_SES_CTRL_COOLING_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_cooling, SES_CTRL_COOLING, LCASE, UCASE) GEN_SES_CTRL_COOLING_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_COOLING_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_COOLING_ACCESSORS(rqst_on, RQST_ON) GEN_SES_CTRL_COOLING_ACCESSORS(rqsted_speed_code, RQSTED_SPEED_CODE) #undef GEN_SES_CTRL_COOLING_ACCESSORS /*-------------------- Temperature Sensor Control Element --------------------*/ struct ses_ctrl_temp_sensor { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_temp_sensor_field_data { SES_CTRL_TEMP_SENSOR_RQST_IDENT_BYTE = 0, SES_CTRL_TEMP_SENSOR_RQST_IDENT_MASK = 0x80, SES_CTRL_TEMP_SENSOR_RQST_IDENT_SHIFT = 7, SES_CTRL_TEMP_SENSOR_RQST_FAIL_BYTE = 0, SES_CTRL_TEMP_SENSOR_RQST_FAIL_MASK = 0x40, SES_CTRL_TEMP_SENSOR_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_TEMP_SENSOR_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_temp_sensor, SES_CTRL_TEMP_SENSOR, LCASE, UCASE) GEN_SES_CTRL_TEMP_SENSOR_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_TEMP_SENSOR_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_TEMP_SENSOR_ACCESSORS /*------------------------- Door Lock Control Element ------------------------*/ struct ses_ctrl_door_lock { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_door_lock_field_data { SES_CTRL_DOOR_LOCK_RQST_IDENT_BYTE = 0, SES_CTRL_DOOR_LOCK_RQST_IDENT_MASK = 0x80, SES_CTRL_DOOR_LOCK_RQST_IDENT_SHIFT = 7, SES_CTRL_DOOR_LOCK_RQST_FAIL_BYTE = 0, SES_CTRL_DOOR_LOCK_RQST_FAIL_MASK = 0x40, SES_CTRL_DOOR_LOCK_RQST_FAIL_SHIFT = 6, SES_CTRL_DOOR_LOCK_UNLOCK_BYTE = 2, SES_CTRL_DOOR_LOCK_UNLOCK_MASK = 0x01, SES_CTRL_DOOR_LOCK_UNLOCK_SHIFT = 0 }; #define GEN_SES_CTRL_DOOR_LOCK_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_door_lock, SES_CTRL_DOOR_LOCK, LCASE, UCASE) GEN_SES_CTRL_DOOR_LOCK_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_DOOR_LOCK_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_DOOR_LOCK_ACCESSORS(unlock, UNLOCK) #undef GEN_SES_CTRL_DOOR_LOCK_ACCESSORS /*----------------------- Audible Alarm Control Element ----------------------*/ struct ses_ctrl_audible_alarm { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_audible_alarm_field_data { SES_CTRL_AUDIBLE_ALARM_RQST_IDENT_BYTE = 0, SES_CTRL_AUDIBLE_ALARM_RQST_IDENT_MASK = 0x80, SES_CTRL_AUDIBLE_ALARM_RQST_IDENT_SHIFT = 7, SES_CTRL_AUDIBLE_ALARM_RQST_FAIL_BYTE = 0, SES_CTRL_AUDIBLE_ALARM_RQST_FAIL_MASK = 0x40, SES_CTRL_AUDIBLE_ALARM_RQST_FAIL_SHIFT = 6, SES_CTRL_AUDIBLE_ALARM_SET_MUTE_BYTE = 2, SES_CTRL_AUDIBLE_ALARM_SET_MUTE_MASK = 0x40, SES_CTRL_AUDIBLE_ALARM_SET_MUTE_SHIFT = 6, SES_CTRL_AUDIBLE_ALARM_SET_REMIND_BYTE = 2, SES_CTRL_AUDIBLE_ALARM_SET_REMIND_MASK = 0x10, SES_CTRL_AUDIBLE_ALARM_SET_REMIND_SHIFT = 4, SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_BYTE = 2, SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_MASK = 0x0F, SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_SHIFT = 0, SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_INFO = 0x08, SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_NON_CRIT = 0x04, SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_CRIT = 0x02, SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_UNRECOV = 0x01 }; #define GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_audible_alarm, SES_CTRL_AUDIBLE_ALARM, LCASE, UCASE) GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(set_mute, SET_MUTE) GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(set_remind, SET_REMIND) GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(tone_control, TONE_CONTROL) #undef GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS /*--------- Enclosure Services Controller Electronics Control Element --------*/ struct ses_ctrl_ecc_electronics { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_ecc_electronics_field_data { SES_CTRL_ECC_ELECTRONICS_RQST_IDENT_BYTE = 0, SES_CTRL_ECC_ELECTRONICS_RQST_IDENT_MASK = 0x80, SES_CTRL_ECC_ELECTRONICS_RQST_IDENT_SHIFT = 7, SES_CTRL_ECC_ELECTRONICS_RQST_FAIL_BYTE = 0, SES_CTRL_ECC_ELECTRONICS_RQST_FAIL_MASK = 0x40, SES_CTRL_ECC_ELECTRONICS_RQST_FAIL_SHIFT = 6, SES_CTRL_ECC_ELECTRONICS_SELECT_ELEMENT_BYTE = 1, SES_CTRL_ECC_ELECTRONICS_SELECT_ELEMENT_MASK = 0x01, SES_CTRL_ECC_ELECTRONICS_SELECT_ELEMENT_SHIFT = 0 }; #define GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_ecc_electronics, SES_CTRL_ECC_ELECTRONICS, \ LCASE, UCASE) GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS(select_element, SELECT_ELEMENT) #undef GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS /*----------- SCSI Services Controller Electronics Control Element -----------*/ struct ses_ctrl_scc_electronics { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_scc_electronics_field_data { SES_CTRL_SCC_ELECTRONICS_RQST_IDENT_BYTE = 0, SES_CTRL_SCC_ELECTRONICS_RQST_IDENT_MASK = 0x80, SES_CTRL_SCC_ELECTRONICS_RQST_IDENT_SHIFT = 7, SES_CTRL_SCC_ELECTRONICS_RQST_FAIL_BYTE = 0, SES_CTRL_SCC_ELECTRONICS_RQST_FAIL_MASK = 0x40, SES_CTRL_SCC_ELECTRONICS_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_SCC_ELECTRONICS_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_scc_electronics, SES_CTRL_SCC_ELECTRONICS, \ LCASE, UCASE) GEN_SES_CTRL_SCC_ELECTRONICS_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_SCC_ELECTRONICS_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_SCC_ELECTRONICS_ACCESSORS /*--------------------- Nonvolatile Cache Control Element --------------------*/ struct ses_ctrl_nv_cache { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_nv_cache_field_data { SES_CTRL_NV_CACHE_RQST_IDENT_BYTE = 0, SES_CTRL_NV_CACHE_RQST_IDENT_MASK = 0x80, SES_CTRL_NV_CACHE_RQST_IDENT_SHIFT = 7, SES_CTRL_NV_CACHE_RQST_FAIL_BYTE = 0, SES_CTRL_NV_CACHE_RQST_FAIL_MASK = 0x40, SES_CTRL_NV_CACHE_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_NV_CACHE_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_nv_cache, SES_CTRL_NV_CACHE, LCASE, UCASE) GEN_SES_CTRL_NV_CACHE_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_NV_CACHE_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_NV_CACHE_ACCESSORS /*----------------- Invalid Operation Reason Control Element -----------------*/ struct ses_ctrl_invalid_op_reason { struct ses_ctrl_common common; uint8_t bytes[3]; }; /* There are no element specific fields currently defined in the spec. */ /*--------------- Uninterruptible Power Supply Control Element ---------------*/ struct ses_ctrl_ups { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_ups_field_data { SES_CTRL_UPS_RQST_IDENT_BYTE = 2, SES_CTRL_UPS_RQST_IDENT_MASK = 0x80, SES_CTRL_UPS_RQST_IDENT_SHIFT = 7, SES_CTRL_UPS_RQST_FAIL_BYTE = 2, SES_CTRL_UPS_RQST_FAIL_MASK = 0x40, SES_CTRL_UPS_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_UPS_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_ups, SES_CTRL_UPS, LCASE, UCASE) GEN_SES_CTRL_UPS_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_UPS_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_UPS_ACCESSORS /*-------------------------- Display Control Element -------------------------*/ struct ses_ctrl_display { struct ses_ctrl_common common; uint8_t bytes[1]; uint8_t display_character[2]; }; enum ses_ctrl_display_field_data { SES_CTRL_DISPLAY_RQST_IDENT_BYTE = 0, SES_CTRL_DISPLAY_RQST_IDENT_MASK = 0x80, SES_CTRL_DISPLAY_RQST_IDENT_SHIFT = 7, SES_CTRL_DISPLAY_RQST_FAIL_BYTE = 0, SES_CTRL_DISPLAY_RQST_FAIL_MASK = 0x40, SES_CTRL_DISPLAY_RQST_FAIL_SHIFT = 6, SES_CTRL_DISPLAY_DISPLAY_MODE_BYTE = 0, SES_CTRL_DISPLAY_DISPLAY_MODE_MASK = 0x03, SES_CTRL_DISPLAY_DISPLAY_MODE_SHIFT = 6, SES_CTRL_DISPLAY_DISPLAY_MODE_UNCHANGED = 0x0, SES_CTRL_DISPLAY_DISPLAY_MODE_ESP = 0x1, SES_CTRL_DISPLAY_DISPLAY_MODE_DC_FIELD = 0x2 }; #define GEN_SES_CTRL_DISPLAY_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_display, SES_CTRL_DISPLAY, LCASE, UCASE) GEN_SES_CTRL_DISPLAY_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_DISPLAY_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_DISPLAY_ACCESSORS(display_mode, DISPLAY_MODE) #undef GEN_SES_CTRL_DISPLAY_ACCESSORS /*----------------------- Key Pad Entry Control Element ----------------------*/ struct ses_ctrl_key_pad_entry { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_key_pad_entry_field_data { SES_CTRL_KEY_PAD_ENTRY_RQST_IDENT_BYTE = 0, SES_CTRL_KEY_PAD_ENTRY_RQST_IDENT_MASK = 0x80, SES_CTRL_KEY_PAD_ENTRY_RQST_IDENT_SHIFT = 7, SES_CTRL_KEY_PAD_ENTRY_RQST_FAIL_BYTE = 0, SES_CTRL_KEY_PAD_ENTRY_RQST_FAIL_MASK = 0x40, SES_CTRL_KEY_PAD_ENTRY_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_KEY_PAD_ENTRY_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_key_pad_entry, SES_CTRL_KEY_PAD_ENTRY, LCASE, UCASE) GEN_SES_CTRL_KEY_PAD_ENTRY_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_KEY_PAD_ENTRY_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_KEY_PAD_ENTRY_ACCESSORS /*------------------------- Enclosure Control Element ------------------------*/ struct ses_ctrl_enclosure { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_enclosure_field_data { SES_CTRL_ENCLOSURE_RQST_IDENT_BYTE = 0, SES_CTRL_ENCLOSURE_RQST_IDENT_MASK = 0x80, SES_CTRL_ENCLOSURE_RQST_IDENT_SHIFT = 7, SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_BYTE = 1, SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_MASK = 0xC0, SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_SHIFT = 6, SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_NONE = 0x0, SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_AFTER_DELAY = 0x1, SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_CANCEL = 0x2, SES_CTRL_ENCLOSURE_POWER_CYCLE_DELAY_BYTE = 1, SES_CTRL_ENCLOSURE_POWER_CYCLE_DELAY_MASK = 0x3F, SES_CTRL_ENCLOSURE_POWER_CYCLE_DELAY_SHIFT = 0, SES_CTRL_ENCLOSURE_POWER_CYCLE_DELAY_MAX = 60,/*minutes*/ SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_BYTE = 2, SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_MASK = 0xFC, SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_SHIFT = 2, SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_MAX_AUTO = 60, SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_MANUAL = 63, SES_CTRL_ENCLOSURE_RQST_FAIL_BYTE = 2, SES_CTRL_ENCLOSURE_RQST_FAIL_MASK = 0x02, SES_CTRL_ENCLOSURE_RQST_FAIL_SHIFT = 1, SES_CTRL_ENCLOSURE_RQST_WARN_BYTE = 2, SES_CTRL_ENCLOSURE_RQST_WARN_MASK = 0x01, SES_CTRL_ENCLOSURE_RQST_WARN_SHIFT = 0 }; #define GEN_SES_CTRL_ENCLOSURE_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_enclosure, SES_CTRL_ENCLOSURE, LCASE, UCASE) GEN_SES_CTRL_ENCLOSURE_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_ENCLOSURE_ACCESSORS(power_cycle_rqst, POWER_CYCLE_RQST) GEN_SES_CTRL_ENCLOSURE_ACCESSORS(power_cycle_delay, POWER_CYCLE_DELAY) GEN_SES_CTRL_ENCLOSURE_ACCESSORS(power_off_duration, POWER_OFF_DURATION) GEN_SES_CTRL_ENCLOSURE_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_ENCLOSURE_ACCESSORS(rqst_warn, RQST_WARN) #undef GEN_SES_CTRL_ENCLOSURE_ACCESSORS /*------------------- SCSI Port/Transceiver Control Element ------------------*/ struct ses_ctrl_scsi_port_or_xcvr { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_scsi_port_or_xcvr_field_data { SES_CTRL_SCSI_PORT_OR_XCVR_RQST_IDENT_BYTE = 0, SES_CTRL_SCSI_PORT_OR_XCVR_RQST_IDENT_MASK = 0x80, SES_CTRL_SCSI_PORT_OR_XCVR_RQST_IDENT_SHIFT = 7, SES_CTRL_SCSI_PORT_OR_XCVR_RQST_FAIL_BYTE = 0, SES_CTRL_SCSI_PORT_OR_XCVR_RQST_FAIL_MASK = 0x40, SES_CTRL_SCSI_PORT_OR_XCVR_RQST_FAIL_SHIFT = 6, SES_CTRL_SCSI_PORT_OR_XCVR_DISABLE_BYTE = 2, SES_CTRL_SCSI_PORT_OR_XCVR_DISABLE_MASK = 0x10, SES_CTRL_SCSI_PORT_OR_XCVR_DISABLE_SHIFT = 4 }; #define GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_scsi_port_or_xcvr, SES_CTRL_SCSI_PORT_OR_XCVR,\ LCASE, UCASE) GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS(disable, DISABLE) GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS /*------------------------- Language Control Element -------------------------*/ struct ses_ctrl_language { struct ses_ctrl_common common; uint8_t bytes[1]; uint8_t language_code[2]; }; enum ses_ctrl_language_field_data { SES_CTRL_LANGUAGE_RQST_IDENT_BYTE = 0, SES_CTRL_LANGUAGE_RQST_IDENT_MASK = 0x80, SES_CTRL_LANGUAGE_RQST_IDENT_SHIFT = 7 }; #define GEN_SES_CTRL_LANGUAGE_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_language, SES_CTRL_LANGUAGE, LCASE, UCASE) GEN_SES_CTRL_LANGUAGE_ACCESSORS(rqst_ident, RQST_IDENT) #undef GEN_SES_CTRL_LANGUAGE_ACCESSORS /*-------------------- Communication Port Control Element --------------------*/ struct ses_ctrl_comm_port { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_comm_port_field_data { SES_CTRL_COMM_PORT_RQST_IDENT_BYTE = 0, SES_CTRL_COMM_PORT_RQST_IDENT_MASK = 0x80, SES_CTRL_COMM_PORT_RQST_IDENT_SHIFT = 7, SES_CTRL_COMM_PORT_RQST_FAIL_BYTE = 0, SES_CTRL_COMM_PORT_RQST_FAIL_MASK = 0x40, SES_CTRL_COMM_PORT_RQST_FAIL_SHIFT = 6, SES_CTRL_COMM_PORT_DISABLE_BYTE = 2, SES_CTRL_COMM_PORT_DISABLE_MASK = 0x01, SES_CTRL_COMM_PORT_DISABLE_SHIFT = 0 }; #define GEN_SES_CTRL_COMM_PORT_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_comm_port, SES_CTRL_COMM_PORT, LCASE, UCASE) GEN_SES_CTRL_COMM_PORT_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_COMM_PORT_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_COMM_PORT_ACCESSORS(disable, DISABLE) #undef GEN_SES_CTRL_COMM_PORT_ACCESSORS /*---------------------- Voltage Sensor Control Element ----------------------*/ struct ses_ctrl_voltage_sensor { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_voltage_sensor_field_data { SES_CTRL_VOLTAGE_SENSOR_RQST_IDENT_BYTE = 0, SES_CTRL_VOLTAGE_SENSOR_RQST_IDENT_MASK = 0x80, SES_CTRL_VOLTAGE_SENSOR_RQST_IDENT_SHIFT = 7, SES_CTRL_VOLTAGE_SENSOR_RQST_FAIL_BYTE = 0, SES_CTRL_VOLTAGE_SENSOR_RQST_FAIL_MASK = 0x40, SES_CTRL_VOLTAGE_SENSOR_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_VOLTAGE_SENSOR_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_voltage_sensor, SES_CTRL_VOLTAGE_SENSOR, \ LCASE, UCASE) GEN_SES_CTRL_VOLTAGE_SENSOR_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_VOLTAGE_SENSOR_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_VOLTAGE_SENSOR_ACCESSORS /*---------------------- Current Sensor Control Element ----------------------*/ struct ses_ctrl_current_sensor { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_current_sensor_field_data { SES_CTRL_CURRENT_SENSOR_RQST_IDENT_BYTE = 0, SES_CTRL_CURRENT_SENSOR_RQST_IDENT_MASK = 0x80, SES_CTRL_CURRENT_SENSOR_RQST_IDENT_SHIFT = 7, SES_CTRL_CURRENT_SENSOR_RQST_FAIL_BYTE = 0, SES_CTRL_CURRENT_SENSOR_RQST_FAIL_MASK = 0x40, SES_CTRL_CURRENT_SENSOR_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_CURRENT_SENSOR_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_current_sensor, SES_CTRL_CURRENT_SENSOR, \ LCASE, UCASE) GEN_SES_CTRL_CURRENT_SENSOR_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_CURRENT_SENSOR_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_CURRENT_SENSOR_ACCESSORS /*--------------------- SCSI Target Port Control Element ---------------------*/ struct ses_ctrl_target_port { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_scsi_target_port_field_data { SES_CTRL_TARGET_PORT_RQST_IDENT_BYTE = 0, SES_CTRL_TARGET_PORT_RQST_IDENT_MASK = 0x80, SES_CTRL_TARGET_PORT_RQST_IDENT_SHIFT = 7, SES_CTRL_TARGET_PORT_RQST_FAIL_BYTE = 0, SES_CTRL_TARGET_PORT_RQST_FAIL_MASK = 0x40, SES_CTRL_TARGET_PORT_RQST_FAIL_SHIFT = 6, SES_CTRL_TARGET_PORT_ENABLE_BYTE = 2, SES_CTRL_TARGET_PORT_ENABLE_MASK = 0x01, SES_CTRL_TARGET_PORT_ENABLE_SHIFT = 0 }; #define GEN_SES_CTRL_TARGET_PORT_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_target_port, SES_CTRL_TARGET_PORT, LCASE, UCASE) GEN_SES_CTRL_TARGET_PORT_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_TARGET_PORT_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_TARGET_PORT_ACCESSORS(enable, ENABLE) #undef GEN_SES_CTRL_TARGET_PORT_ACCESSORS /*-------------------- SCSI Initiator Port Control Element -------------------*/ struct ses_ctrl_initiator_port { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_initiator_port_field_data { SES_CTRL_INITIATOR_PORT_RQST_IDENT_BYTE = 0, SES_CTRL_INITIATOR_PORT_RQST_IDENT_MASK = 0x80, SES_CTRL_INITIATOR_PORT_RQST_IDENT_SHIFT = 7, SES_CTRL_INITIATOR_PORT_RQST_FAIL_BYTE = 0, SES_CTRL_INITIATOR_PORT_RQST_FAIL_MASK = 0x40, SES_CTRL_INITIATOR_PORT_RQST_FAIL_SHIFT = 6, SES_CTRL_INITIATOR_PORT_ENABLE_BYTE = 2, SES_CTRL_INITIATOR_PORT_ENABLE_MASK = 0x01, SES_CTRL_INITIATOR_PORT_ENABLE_SHIFT = 0 }; #define GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_initiator_port, SES_CTRL_INITIATOR_PORT, \ LCASE, UCASE) GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS(rqst_fail, RQST_FAIL) GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS(enable, ENABLE) #undef GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS /*-------------------- Simple Subenclosure Control Element -------------------*/ struct ses_ctrl_simple_subenc { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_simple_subenc_field_data { SES_CTRL_SIMPlE_SUBSES_RQST_IDENT_BYTE = 0, SES_CTRL_SIMPlE_SUBSES_RQST_IDENT_MASK = 0x80, SES_CTRL_SIMPlE_SUBSES_RQST_IDENT_SHIFT = 7, SES_CTRL_SIMPlE_SUBSES_RQST_FAIL_BYTE = 0, SES_CTRL_SIMPlE_SUBSES_RQST_FAIL_MASK = 0x40, SES_CTRL_SIMPlE_SUBSES_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_SIMPlE_SUBSES_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_simple_subenc, SES_CTRL_SIMPlE_SUBSES, \ LCASE, UCASE) GEN_SES_CTRL_SIMPlE_SUBSES_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_SIMPlE_SUBSES_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_SIMPlE_SUBSES_ACCESSORS /*----------------------- SAS Expander Control Element -----------------------*/ struct ses_ctrl_sas_expander { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_sas_expander_field_data { SES_CTRL_SAS_EXPANDER_RQST_IDENT_BYTE = 0, SES_CTRL_SAS_EXPANDER_RQST_IDENT_MASK = 0x80, SES_CTRL_SAS_EXPANDER_RQST_IDENT_SHIFT = 7, SES_CTRL_SAS_EXPANDER_RQST_FAIL_BYTE = 0, SES_CTRL_SAS_EXPANDER_RQST_FAIL_MASK = 0x40, SES_CTRL_SAS_EXPANDER_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_SAS_EXPANDER_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_sas_expander, SES_CTRL_SAS_EXPANDER, LCASE, UCASE) GEN_SES_CTRL_SAS_EXPANDER_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_SAS_EXPANDER_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_SAS_EXPANDER_ACCESSORS /*----------------------- SAS Connector Control Element ----------------------*/ struct ses_ctrl_sas_connector { struct ses_ctrl_common common; uint8_t bytes[3]; }; enum ses_ctrl_sas_connector_field_data { SES_CTRL_SAS_CONNECTOR_RQST_IDENT_BYTE = 0, SES_CTRL_SAS_CONNECTOR_RQST_IDENT_MASK = 0x80, SES_CTRL_SAS_CONNECTOR_RQST_IDENT_SHIFT = 7, SES_CTRL_SAS_CONNECTOR_RQST_FAIL_BYTE = 2, SES_CTRL_SAS_CONNECTOR_RQST_FAIL_MASK = 0x40, SES_CTRL_SAS_CONNECTOR_RQST_FAIL_SHIFT = 6 }; #define GEN_SES_CTRL_SAS_CONNECTOR_ACCESSORS(LCASE, UCASE) \ GEN_ACCESSORS(ses_ctrl_sas_connector, SES_CTRL_SAS_CONNECTOR, \ LCASE, UCASE) GEN_SES_CTRL_SAS_CONNECTOR_ACCESSORS(rqst_ident, RQST_IDENT) GEN_SES_CTRL_SAS_CONNECTOR_ACCESSORS(rqst_fail, RQST_FAIL) #undef GEN_SES_CTRL_SAS_CONNECTOR_ACCESSORS /*------------------------- Universal Control Element ------------------------*/ union ses_ctrl_element { struct ses_ctrl_common common; struct ses_ctrl_dev_slot dev_slot; struct ses_ctrl_array_dev_slot array_dev_slot; struct ses_ctrl_power_supply power_supply; struct ses_ctrl_cooling cooling; struct ses_ctrl_temp_sensor temp_sensor; struct ses_ctrl_door_lock door_lock; struct ses_ctrl_audible_alarm audible_alarm; struct ses_ctrl_ecc_electronics ecc_electronics; struct ses_ctrl_scc_electronics scc_electronics; struct ses_ctrl_nv_cache nv_cache; struct ses_ctrl_invalid_op_reason invalid_op_reason; struct ses_ctrl_ups ups; struct ses_ctrl_display display; struct ses_ctrl_key_pad_entry key_pad_entry; struct ses_ctrl_scsi_port_or_xcvr scsi_port_or_xcvr; struct ses_ctrl_language language; struct ses_ctrl_comm_port comm_port; struct ses_ctrl_voltage_sensor voltage_sensor; struct ses_ctrl_current_sensor current_sensor; struct ses_ctrl_target_port target_port; struct ses_ctrl_initiator_port initiator_port; struct ses_ctrl_simple_subenc simple_subenc; struct ses_ctrl_sas_expander sas_expander; struct ses_ctrl_sas_connector sas_connector; }; /*--------------------- SCSI SES Control Diagnostic Page ---------------------*/ struct ses_ctrl_page { struct ses_page_hdr hdr; union ses_ctrl_element elements[]; }; enum ses_ctrl_page_field_data { SES_CTRL_PAGE_INFO_MASK = 0x08, SES_CTRL_PAGE_INFO_SHIFT = 3, SES_CTRL_PAGE_NON_CRIT_MASK = 0x04, SES_CTRL_PAGE_NON_CRIT_SHIFT = 2, SES_CTRL_PAGE_CRIT_MASK = 0x02, SES_CTRL_PAGE_CRIT_SHIFT = 1, SES_CTRL_PAGE_UNRECOV_MASK = 0x01, SES_CTRL_PAGE_UNRECOV_SHIFT = 0 }; #define GEN_SES_CTRL_PAGE_ACCESSORS(LCASE, UCASE) \ GEN_HDR_ACCESSORS(ses_ctrl_page, SES_CTRL_PAGE, LCASE, UCASE) GEN_SES_CTRL_PAGE_ACCESSORS(info, INFO) GEN_SES_CTRL_PAGE_ACCESSORS(non_crit, NON_CRIT) GEN_SES_CTRL_PAGE_ACCESSORS(crit, CRIT) GEN_SES_CTRL_PAGE_ACCESSORS(unrecov, UNRECOV) #undef GEN_SES_CTRL_PAGE_ACCESSORS /*================= SCSI SES Status Diagnostic Page Structures ===============*/ struct ses_status_common { uint8_t bytes[1]; }; enum ses_status_common_field_data { SES_STATUS_COMMON_PRDFAIL_BYTE = 0, SES_STATUS_COMMON_PRDFAIL_MASK = 0x40, SES_STATUS_COMMON_PRDFAIL_SHIFT = 6, SES_STATUS_COMMON_DISABLED_BYTE = 0, SES_STATUS_COMMON_DISABLED_MASK = 0x20, SES_STATUS_COMMON_DISABLED_SHIFT = 5, SES_STATUS_COMMON_SWAP_BYTE = 0, SES_STATUS_COMMON_SWAP_MASK = 0x10, SES_STATUS_COMMON_SWAP_SHIFT = 4, SES_STATUS_COMMON_ELEMENT_STATUS_CODE_BYTE = 0, SES_STATUS_COMMON_ELEMENT_STATUS_CODE_MASK = 0x0F, SES_STATUS_COMMON_ELEMENT_STATUS_CODE_SHIFT = 0 }; #define GEN_SES_STATUS_COMMON_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_common, SES_STATUS_COMMON, LCASE, UCASE) GEN_SES_STATUS_COMMON_ACCESSORS(prdfail, PRDFAIL) GEN_SES_STATUS_COMMON_ACCESSORS(disabled, DISABLED) GEN_SES_STATUS_COMMON_ACCESSORS(swap, SWAP) GEN_SES_STATUS_COMMON_ACCESSORS(element_status_code, ELEMENT_STATUS_CODE) #undef GEN_SES_STATUS_COMMON_ACCESSORS /*------------------------- Device Slot Status Element -----------------------*/ struct ses_status_dev_slot { struct ses_status_common common; uint8_t slot_address; uint8_t bytes[2]; }; enum ses_status_dev_slot_field_data { SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_A_BYTE = 0, SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_A_MASK = 0x80, SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_A_SHIFT = 7, SES_STATUS_DEV_SLOT_DO_NOT_REMOVE_BYTE = 0, SES_STATUS_DEV_SLOT_DO_NOT_REMOVE_MASK = 0x40, SES_STATUS_DEV_SLOT_DO_NOT_REMOVE_SHIFT = 6, SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_A_BYTE = 0, SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_A_MASK = 0x20, SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_A_SHIFT = 5, SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_B_BYTE = 0, SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_B_MASK = 0x10, SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_B_SHIFT = 4, SES_STATUS_DEV_SLOT_INSERT_READY_BYTE = 0, SES_STATUS_DEV_SLOT_INSERT_READY_MASK = 0x08, SES_STATUS_DEV_SLOT_INSERT_READY_SHIFT = 3, SES_STATUS_DEV_SLOT_REMOVE_BYTE = 0, SES_STATUS_DEV_SLOT_REMOVE_MASK = 0x04, SES_STATUS_DEV_SLOT_REMOVE_SHIFT = 2, SES_STATUS_DEV_SLOT_IDENT_BYTE = 0, SES_STATUS_DEV_SLOT_IDENT_MASK = 0x02, SES_STATUS_DEV_SLOT_IDENT_SHIFT = 1, SES_STATUS_DEV_SLOT_REPORT_BYTE = 0, SES_STATUS_DEV_SLOT_REPORT_MASK = 0x01, SES_STATUS_DEV_SLOT_REPORT_SHIFT = 0, SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_B_BYTE = 1, SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_B_MASK = 0x80, SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_B_SHIFT = 7, SES_STATUS_DEV_SLOT_FAULT_SENSED_BYTE = 1, SES_STATUS_DEV_SLOT_FAULT_SENSED_MASK = 0x40, SES_STATUS_DEV_SLOT_FAULT_SENSED_SHIFT = 6, SES_STATUS_DEV_SLOT_FAULT_REQUESTED_BYTE = 1, SES_STATUS_DEV_SLOT_FAULT_REQUESTED_MASK = 0x20, SES_STATUS_DEV_SLOT_FAULT_REQUESTED_SHIFT = 5, SES_STATUS_DEV_SLOT_DEVICE_OFF_BYTE = 1, SES_STATUS_DEV_SLOT_DEVICE_OFF_MASK = 0x10, SES_STATUS_DEV_SLOT_DEVICE_OFF_SHIFT = 4, SES_STATUS_DEV_SLOT_BYPED_A_BYTE = 1, SES_STATUS_DEV_SLOT_BYPED_A_MASK = 0x08, SES_STATUS_DEV_SLOT_BYPED_A_SHIFT = 3, SES_STATUS_DEV_SLOT_BYPED_B_BYTE = 1, SES_STATUS_DEV_SLOT_BYPED_B_MASK = 0x04, SES_STATUS_DEV_SLOT_BYPED_B_SHIFT = 2, SES_STATUS_DEV_SLOT_DEVICE_BYPED_A_BYTE = 1, SES_STATUS_DEV_SLOT_DEVICE_BYPED_A_MASK = 0x02, SES_STATUS_DEV_SLOT_DEVICE_BYPED_A_SHIFT = 1, SES_STATUS_DEV_SLOT_DEVICE_BYPED_B_BYTE = 1, SES_STATUS_DEV_SLOT_DEVICE_BYPED_B_MASK = 0x01, SES_STATUS_DEV_SLOT_DEVICE_BYPED_B_SHIFT = 0 }; #define GEN_SES_STATUS_DEV_SLOT_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_dev_slot, SES_STATUS_DEV_SLOT, LCASE, UCASE) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(app_client_byped_a, APP_CLIENT_BYPED_A) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(do_not_remove, DO_NOT_REMOVE) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(enclosure_byped_a, ENCLOSURE_BYPED_A) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(enclosure_byped_b, ENCLOSURE_BYPED_B) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(insert_ready, INSERT_READY) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(remove, REMOVE) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(ident, IDENT) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(report, REPORT) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(app_client_byped_b, APP_CLIENT_BYPED_B) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(fault_sensed, FAULT_SENSED) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(fault_requested, FAULT_REQUESTED) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(device_off, DEVICE_OFF) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(byped_a, BYPED_A) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(byped_b, BYPED_B) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(device_byped_a, DEVICE_BYPED_A) GEN_SES_STATUS_DEV_SLOT_ACCESSORS(device_byped_b, DEVICE_BYPED_B) #undef GEN_SES_STATUS_DEV_SLOT_ACCESSORS /*---------------------- Array Device Slot Status Element --------------------*/ struct ses_status_array_dev_slot { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_array_dev_slot_field_data { SES_STATUS_ARRAY_DEV_SLOT_OK_BYTE = 0, SES_STATUS_ARRAY_DEV_SLOT_OK_MASK = 0x80, SES_STATUS_ARRAY_DEV_SLOT_OK_SHIFT = 7, SES_STATUS_ARRAY_DEV_SLOT_RSVD_DEVICE_BYTE = 0, SES_STATUS_ARRAY_DEV_SLOT_RSVD_DEVICE_MASK = 0x40, SES_STATUS_ARRAY_DEV_SLOT_RSVD_DEVICE_SHIFT = 6, SES_STATUS_ARRAY_DEV_SLOT_HOT_SPARE_BYTE = 0, SES_STATUS_ARRAY_DEV_SLOT_HOT_SPARE_MASK = 0x20, SES_STATUS_ARRAY_DEV_SLOT_HOT_SPARE_SHIFT = 5, SES_STATUS_ARRAY_DEV_SLOT_CONS_CHECK_BYTE = 0, SES_STATUS_ARRAY_DEV_SLOT_CONS_CHECK_MASK = 0x10, SES_STATUS_ARRAY_DEV_SLOT_CONS_CHECK_SHIFT = 4, SES_STATUS_ARRAY_DEV_SLOT_IN_CRIT_ARRAY_BYTE = 0, SES_STATUS_ARRAY_DEV_SLOT_IN_CRIT_ARRAY_MASK = 0x08, SES_STATUS_ARRAY_DEV_SLOT_IN_CRIT_ARRAY_SHIFT = 3, SES_STATUS_ARRAY_DEV_SLOT_IN_FAILED_ARRAY_BYTE = 0, SES_STATUS_ARRAY_DEV_SLOT_IN_FAILED_ARRAY_MASK = 0x04, SES_STATUS_ARRAY_DEV_SLOT_IN_FAILED_ARRAY_SHIFT = 2, SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_BYTE = 0, SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_MASK = 0x02, SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_SHIFT = 1, SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_ABORT_BYTE = 0, SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_ABORT_MASK = 0x01, SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_ABORT_SHIFT = 0 /* * The remaining fields are identical to the device * slot element type. Access them through the device slot * element type and its accessors. */ }; #define GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_array_dev_slot, SES_STATUS_ARRAY_DEV_SLOT, \ LCASE, UCASE) GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(ok, OK) GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(rsvd_device, RSVD_DEVICE) GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(hot_spare, HOT_SPARE) GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(cons_check, CONS_CHECK) GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(in_crit_array, IN_CRIT_ARRAY) GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(in_failed_array, IN_FAILED_ARRAY) GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(rebuild_remap, REBUILD_REMAP) GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(rebuild_remap_abort, REBUILD_REMAP_ABORT) #undef GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS /*----------------------- Power Supply Status Element ------------------------*/ struct ses_status_power_supply { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_power_supply_field_data { SES_STATUS_POWER_SUPPLY_IDENT_BYTE = 0, SES_STATUS_POWER_SUPPLY_IDENT_MASK = 0x80, SES_STATUS_POWER_SUPPLY_IDENT_SHIFT = 7, SES_STATUS_POWER_SUPPLY_DC_OVER_VOLTAGE_BYTE = 1, SES_STATUS_POWER_SUPPLY_DC_OVER_VOLTAGE_MASK = 0x08, SES_STATUS_POWER_SUPPLY_DC_OVER_VOLTAGE_SHIFT = 3, SES_STATUS_POWER_SUPPLY_DC_UNDER_VOLTAGE_BYTE = 1, SES_STATUS_POWER_SUPPLY_DC_UNDER_VOLTAGE_MASK = 0x04, SES_STATUS_POWER_SUPPLY_DC_UNDER_VOLTAGE_SHIFT = 2, SES_STATUS_POWER_SUPPLY_DC_OVER_CURRENT_BYTE = 1, SES_STATUS_POWER_SUPPLY_DC_OVER_CURRENT_MASK = 0x02, SES_STATUS_POWER_SUPPLY_DC_OVER_CURRENT_SHIFT = 1, SES_STATUS_POWER_SUPPLY_HOT_SWAP_BYTE = 2, SES_STATUS_POWER_SUPPLY_HOT_SWAP_MASK = 0x80, SES_STATUS_POWER_SUPPLY_HOT_SWAP_SHIFT = 7, SES_STATUS_POWER_SUPPLY_FAIL_BYTE = 2, SES_STATUS_POWER_SUPPLY_FAIL_MASK = 0x40, SES_STATUS_POWER_SUPPLY_FAIL_SHIFT = 6, SES_STATUS_POWER_SUPPLY_REQUESTED_ON_BYTE = 2, SES_STATUS_POWER_SUPPLY_REQUESTED_ON_MASK = 0x20, SES_STATUS_POWER_SUPPLY_REQUESTED_ON_SHIFT = 5, SES_STATUS_POWER_SUPPLY_OFF_BYTE = 2, SES_STATUS_POWER_SUPPLY_OFF_MASK = 0x10, SES_STATUS_POWER_SUPPLY_OFF_SHIFT = 4, SES_STATUS_POWER_SUPPLY_OVERTMP_FAIL_BYTE = 2, SES_STATUS_POWER_SUPPLY_OVERTMP_FAIL_MASK = 0x08, SES_STATUS_POWER_SUPPLY_OVERTMP_FAIL_SHIFT = 3, SES_STATUS_POWER_SUPPLY_TEMP_WARN_BYTE = 2, SES_STATUS_POWER_SUPPLY_TEMP_WARN_MASK = 0x04, SES_STATUS_POWER_SUPPLY_TEMP_WARN_SHIFT = 2, SES_STATUS_POWER_SUPPLY_AC_FAIL_BYTE = 2, SES_STATUS_POWER_SUPPLY_AC_FAIL_MASK = 0x02, SES_STATUS_POWER_SUPPLY_AC_FAIL_SHIFT = 1, SES_STATUS_POWER_SUPPLY_DC_FAIL_BYTE = 2, SES_STATUS_POWER_SUPPLY_DC_FAIL_MASK = 0x01, SES_STATUS_POWER_SUPPLY_DC_FAIL_SHIFT = 0 }; #define GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_power_supply, SES_STATUS_POWER_SUPPLY, LCASE, UCASE) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(ident, IDENT) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(dc_over_voltage, DC_OVER_VOLTAGE) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(dc_under_voltage, DC_UNDER_VOLTAGE) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(dc_over_current, DC_OVER_CURRENT) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(hot_swap, HOT_SWAP) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(fail, FAIL) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(requested_on, REQUESTED_ON) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(off, OFF) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(overtmp_fail, OVERTMP_FAIL) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(temp_warn, TEMP_WARN) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(ac_fail, AC_FAIL) GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(dc_fail, DC_FAIL) #undef GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS /*-------------------------- Cooling Status Element --------------------------*/ struct ses_status_cooling { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_cooling_field_data { SES_STATUS_COOLING_IDENT_BYTE = 0, SES_STATUS_COOLING_IDENT_MASK = 0x80, SES_STATUS_COOLING_IDENT_SHIFT = 7, SES_STATUS_COOLING_ACTUAL_FAN_SPEED_MSB_BYTE = 0, SES_STATUS_COOLING_ACTUAL_FAN_SPEED_MSB_MASK = 0x07, SES_STATUS_COOLING_ACTUAL_FAN_SPEED_MSB_SHIFT = 0, SES_STATUS_COOLING_ACTUAL_FAN_SPEED_LSB_BYTE = 1, SES_STATUS_COOLING_ACTUAL_FAN_SPEED_LSB_MASK = 0xFF, SES_STATUS_COOLING_ACTUAL_FAN_SPEED_LSB_SHIFT = 0, SES_STATUS_COOLING_HOT_SWAP_BYTE = 2, SES_STATUS_COOLING_HOT_SWAP_MASK = 0x40, SES_STATUS_COOLING_HOT_SWAP_SHIFT = 6, SES_STATUS_COOLING_FAIL_BYTE = 2, SES_STATUS_COOLING_FAIL_MASK = 0x40, SES_STATUS_COOLING_FAIL_SHIFT = 6, SES_STATUS_COOLING_REQUESTED_ON_BYTE = 2, SES_STATUS_COOLING_REQUESTED_ON_MASK = 0x20, SES_STATUS_COOLING_REQUESTED_ON_SHIFT = 5, SES_STATUS_COOLING_OFF_BYTE = 2, SES_STATUS_COOLING_OFF_MASK = 0x20, SES_STATUS_COOLING_OFF_SHIFT = 5, SES_STATUS_COOLING_ACTUAL_SPEED_CODE_BYTE = 2, SES_STATUS_COOLING_ACTUAL_SPEED_CODE_MASK = 0x07, SES_STATUS_COOLING_ACTUAL_SPEED_CODE_SHIFT = 2, SES_STATUS_COOLING_ACTUAL_SPEED_CODE_STOPPED = 0x00, SES_STATUS_COOLING_ACTUAL_SPEED_CODE_LOWEST = 0x01, SES_STATUS_COOLING_ACTUAL_SPEED_CODE_HIGHEST = 0x07 }; #define GEN_SES_STATUS_COOLING_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_cooling, SES_STATUS_COOLING, LCASE, UCASE) GEN_SES_STATUS_COOLING_ACCESSORS(ident, IDENT) GEN_SES_STATUS_COOLING_ACCESSORS(actual_fan_speed_msb, ACTUAL_FAN_SPEED_MSB) GEN_SES_STATUS_COOLING_ACCESSORS(actual_fan_speed_lsb, ACTUAL_FAN_SPEED_LSB) GEN_SES_STATUS_COOLING_ACCESSORS(hot_swap, HOT_SWAP) GEN_SES_STATUS_COOLING_ACCESSORS(fail, FAIL) GEN_SES_STATUS_COOLING_ACCESSORS(requested_on, REQUESTED_ON) GEN_SES_STATUS_COOLING_ACCESSORS(off, OFF) GEN_SES_STATUS_COOLING_ACCESSORS(actual_speed_code, ACTUAL_SPEED_CODE) #undef GEN_SES_STATUS_COOLING_ACCESSORS static inline int ses_status_cooling_get_actual_fan_speed(struct ses_status_cooling *elem) { return (ses_status_cooling_get_actual_fan_speed_msb(elem) << 8 | ses_status_cooling_get_actual_fan_speed_lsb(elem)); } /*-------------------- Temperature Sensor Status Element ---------------------*/ struct ses_status_temp_sensor { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_temp_sensor_field_data { SES_STATUS_TEMP_SENSOR_IDENT_BYTE = 0, SES_STATUS_TEMP_SENSOR_IDENT_MASK = 0x80, SES_STATUS_TEMP_SENSOR_IDENT_SHIFT = 7, SES_STATUS_TEMP_SENSOR_FAIL_BYTE = 0, SES_STATUS_TEMP_SENSOR_FAIL_MASK = 0x40, SES_STATUS_TEMP_SENSOR_FAIL_SHIFT = 6, SES_STATUS_TEMP_SENSOR_TEMPERATURE_BYTE = 1, SES_STATUS_TEMP_SENSOR_TEMPERATURE_MASK = 0xFF, SES_STATUS_TEMP_SENSOR_TEMPERATURE_SHIFT = 0, SES_STATUS_TEMP_SENSOR_OT_FAILURE_BYTE = 2, SES_STATUS_TEMP_SENSOR_OT_FAILURE_MASK = 0x08, SES_STATUS_TEMP_SENSOR_OT_FAILURE_SHIFT = 3, SES_STATUS_TEMP_SENSOR_OT_WARNING_BYTE = 2, SES_STATUS_TEMP_SENSOR_OT_WARNING_MASK = 0x04, SES_STATUS_TEMP_SENSOR_OT_WARNING_SHIFT = 2, SES_STATUS_TEMP_SENSOR_UT_FAILURE_BYTE = 2, SES_STATUS_TEMP_SENSOR_UT_FAILURE_MASK = 0x02, SES_STATUS_TEMP_SENSOR_UT_FAILURE_SHIFT = 1, SES_STATUS_TEMP_SENSOR_UT_WARNING_BYTE = 2, SES_STATUS_TEMP_SENSOR_UT_WARNING_MASK = 0x01, SES_STATUS_TEMP_SENSOR_UT_WARNING_SHIFT = 0 }; #define GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_temp_sensor, SES_STATUS_TEMP_SENSOR, LCASE, UCASE) GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ident, IDENT) GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(fail, FAIL) GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(temperature, TEMPERATURE) GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ot_failure, OT_FAILURE) GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ot_warning, OT_WARNING) GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ut_failure, UT_FAILURE) GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ut_warning, UT_WARNING) #undef GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS /*------------------------- Door Lock Status Element -------------------------*/ struct ses_status_door_lock { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_door_lock_field_data { SES_STATUS_DOOR_LOCK_IDENT_BYTE = 0, SES_STATUS_DOOR_LOCK_IDENT_MASK = 0x80, SES_STATUS_DOOR_LOCK_IDENT_SHIFT = 7, SES_STATUS_DOOR_LOCK_FAIL_BYTE = 0, SES_STATUS_DOOR_LOCK_FAIL_MASK = 0x40, SES_STATUS_DOOR_LOCK_FAIL_SHIFT = 6, SES_STATUS_DOOR_LOCK_UNLOCKED_BYTE = 2, SES_STATUS_DOOR_LOCK_UNLOCKED_MASK = 0x01, SES_STATUS_DOOR_LOCK_UNLOCKED_SHIFT = 0 }; #define GEN_SES_STATUS_DOOR_LOCK_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_door_lock, SES_STATUS_DOOR_LOCK, LCASE, UCASE) GEN_SES_STATUS_DOOR_LOCK_ACCESSORS(ident, IDENT) GEN_SES_STATUS_DOOR_LOCK_ACCESSORS(fail, FAIL) GEN_SES_STATUS_DOOR_LOCK_ACCESSORS(unlocked, UNLOCKED) #undef GEN_SES_STATUS_DOOR_LOCK_ACCESSORS /*----------------------- Audible Alarm Status Element -----------------------*/ struct ses_status_audible_alarm { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_audible_alarm_field_data { SES_STATUS_AUDIBLE_ALARM_IDENT_BYTE = 0, SES_STATUS_AUDIBLE_ALARM_IDENT_MASK = 0x80, SES_STATUS_AUDIBLE_ALARM_IDENT_SHIFT = 7, SES_STATUS_AUDIBLE_ALARM_FAIL_BYTE = 0, SES_STATUS_AUDIBLE_ALARM_FAIL_MASK = 0x40, SES_STATUS_AUDIBLE_ALARM_FAIL_SHIFT = 6, SES_STATUS_AUDIBLE_ALARM_RQST_MUTE_BYTE = 2, SES_STATUS_AUDIBLE_ALARM_RQST_MUTE_MASK = 0x80, SES_STATUS_AUDIBLE_ALARM_RQST_MUTE_SHIFT = 7, SES_STATUS_AUDIBLE_ALARM_MUTED_BYTE = 2, SES_STATUS_AUDIBLE_ALARM_MUTED_MASK = 0x40, SES_STATUS_AUDIBLE_ALARM_MUTED_SHIFT = 6, SES_STATUS_AUDIBLE_ALARM_REMIND_BYTE = 2, SES_STATUS_AUDIBLE_ALARM_REMIND_MASK = 0x10, SES_STATUS_AUDIBLE_ALARM_REMIND_SHIFT = 4, SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_BYTE = 2, SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_MASK = 0x0F, SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_SHIFT = 0, SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_INFO = 0x08, SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_NON_CRIT = 0x04, SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_CRIT = 0x02, SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_UNRECOV = 0x01 }; #define GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_audible_alarm, SES_STATUS_AUDIBLE_ALARM, LCASE, UCASE) GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(ident, IDENT) GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(fail, FAIL) GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(rqst_mute, RQST_MUTE) GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(muted, MUTED) GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(remind, REMIND) GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(tone_indicator, TONE_INDICATOR) #undef GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS /*---------- Enclosure Services Statusler Electronics Status Element ---------*/ struct ses_status_ecc_electronics { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_ecc_electronics_field_data { SES_STATUS_ECC_ELECTRONICS_IDENT_BYTE = 0, SES_STATUS_ECC_ELECTRONICS_IDENT_MASK = 0x80, SES_STATUS_ECC_ELECTRONICS_IDENT_SHIFT = 7, SES_STATUS_ECC_ELECTRONICS_FAIL_BYTE = 0, SES_STATUS_ECC_ELECTRONICS_FAIL_MASK = 0x40, SES_STATUS_ECC_ELECTRONICS_FAIL_SHIFT = 6, SES_STATUS_ECC_ELECTRONICS_REPORT_BYTE = 1, SES_STATUS_ECC_ELECTRONICS_REPORT_MASK = 0x01, SES_STATUS_ECC_ELECTRONICS_REPORT_SHIFT = 0, SES_STATUS_ECC_ELECTRONICS_HOT_SWAP_BYTE = 2, SES_STATUS_ECC_ELECTRONICS_HOT_SWAP_MASK = 0x80, SES_STATUS_ECC_ELECTRONICS_HOT_SWAP_SHIFT = 7 }; #define GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_ecc_electronics, SES_STATUS_ECC_ELECTRONICS, \ LCASE, UCASE) GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(ident, IDENT) GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(fail, FAIL) GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(report, REPORT) GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(hot_swap, HOT_SWAP) #undef GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS /*------------ SCSI Services Statusler Electronics Status Element ------------*/ struct ses_status_scc_electronics { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_scc_electronics_field_data { SES_STATUS_SCC_ELECTRONICS_IDENT_BYTE = 0, SES_STATUS_SCC_ELECTRONICS_IDENT_MASK = 0x80, SES_STATUS_SCC_ELECTRONICS_IDENT_SHIFT = 7, SES_STATUS_SCC_ELECTRONICS_FAIL_BYTE = 0, SES_STATUS_SCC_ELECTRONICS_FAIL_MASK = 0x40, SES_STATUS_SCC_ELECTRONICS_FAIL_SHIFT = 6, SES_STATUS_SCC_ELECTRONICS_REPORT_BYTE = 1, SES_STATUS_SCC_ELECTRONICS_REPORT_MASK = 0x01, SES_STATUS_SCC_ELECTRONICS_REPORT_SHIFT = 0 }; #define GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_scc_electronics, SES_STATUS_SCC_ELECTRONICS, \ LCASE, UCASE) GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS(ident, IDENT) GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS(fail, FAIL) GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS(report, REPORT) #undef GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS /*--------------------- Nonvolatile Cache Status Element ---------------------*/ struct ses_status_nv_cache { struct ses_status_common common; uint8_t bytes[1]; uint8_t cache_size[2]; }; enum ses_status_nv_cache_field_data { SES_STATUS_NV_CACHE_IDENT_BYTE = 0, SES_STATUS_NV_CACHE_IDENT_MASK = 0x80, SES_STATUS_NV_CACHE_IDENT_SHIFT = 7, SES_STATUS_NV_CACHE_FAIL_BYTE = 0, SES_STATUS_NV_CACHE_FAIL_MASK = 0x40, SES_STATUS_NV_CACHE_FAIL_SHIFT = 6, SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_BYTE = 0, SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_MASK = 0x03, SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_SHIFT = 0, SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_BYTES = 0x0, SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_KBYTES = 0x1, SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_MBYTES = 0x2, SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_GBYTES = 0x3 }; #define GEN_SES_STATUS_NV_CACHE_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_nv_cache, SES_STATUS_NV_CACHE, LCASE, UCASE) GEN_SES_STATUS_NV_CACHE_ACCESSORS(ident, IDENT) GEN_SES_STATUS_NV_CACHE_ACCESSORS(fail, FAIL) GEN_SES_STATUS_NV_CACHE_ACCESSORS(size_multiplier, SIZE_MULTIPLIER) #undef GEN_SES_STATUS_NV_CACHE_ACCESSORS static inline uintmax_t ses_status_nv_cache_get_cache_size(struct ses_status_nv_cache *elem) { uintmax_t cache_size; int multiplier; /* Multiplier is in units of 2^10 */ cache_size = scsi_2btoul(elem->cache_size); multiplier = 10 * ses_status_nv_cache_get_size_multiplier(elem); return (cache_size << multiplier); } /*----------------- Invalid Operation Reason Status Element ------------------*/ struct ses_status_invalid_op_reason { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_invalid_op_field_data { SES_STATUS_INVALID_OP_REASON_TYPE_BYTE = 0, SES_STATUS_INVALID_OP_REASON_TYPE_MASK = 0xC0, SES_STATUS_INVALID_OP_REASON_TYPE_SHIFT = 6, SES_STATUS_INVALID_OP_REASON_TYPE_PC_ERROR = 0x00, SES_STATUS_INVALID_OP_REASON_TYPE_PF_ERROR = 0x01, SES_STATUS_INVALID_OP_REASON_TYPE_VS_ERROR = 0x03, SES_STATUS_INVALID_OP_REASON_PC_ERROR_PC_NOT_SUPPORTED_BYTE = 0, SES_STATUS_INVALID_OP_REASON_PC_ERROR_PC_NOT_SUPPORTED_MASK = 0x01, SES_STATUS_INVALID_OP_REASON_PC_ERROR_PC_NOT_SUPPORTED_SHIFT = 0, SES_STATUS_INVALID_OP_REASON_PF_ERROR_BIT_NUMBER_BYTE = 0, SES_STATUS_INVALID_OP_REASON_PF_ERROR_BIT_NUMBER_MASK = 0x03, SES_STATUS_INVALID_OP_REASON_PF_ERROR_BIT_NUMBER_SHIFT = 0 }; #define GEN_SES_STATUS_INVALID_OP_REASON_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_invalid_op_reason, SES_STATUS_INVALID_OP_REASON, \ LCASE, UCASE) GEN_SES_STATUS_INVALID_OP_REASON_ACCESSORS(type, TYPE) GEN_SES_STATUS_INVALID_OP_REASON_ACCESSORS(pc_error_pc_not_supported, PC_ERROR_PC_NOT_SUPPORTED) GEN_SES_STATUS_INVALID_OP_REASON_ACCESSORS(pf_error_bit_number, PF_ERROR_BIT_NUMBER) #undef GEN_SES_STATUS_INVALID_OP_ACCESSORS /*--------------- Uninterruptible Power Supply Status Element ----------------*/ struct ses_status_ups { struct ses_status_common common; /* Minutes of remaining capacity. */ uint8_t battery_status; uint8_t bytes[2]; }; enum ses_status_ups_field_data { SES_STATUS_UPS_AC_LO_BYTE = 0, SES_STATUS_UPS_AC_LO_MASK = 0x80, SES_STATUS_UPS_AC_LO_SHIFT = 7, SES_STATUS_UPS_AC_HI_BYTE = 0, SES_STATUS_UPS_AC_HI_MASK = 0x40, SES_STATUS_UPS_AC_HI_SHIFT = 6, SES_STATUS_UPS_AC_QUAL_BYTE = 0, SES_STATUS_UPS_AC_QUAL_MASK = 0x20, SES_STATUS_UPS_AC_QUAL_SHIFT = 5, SES_STATUS_UPS_AC_FAIL_BYTE = 0, SES_STATUS_UPS_AC_FAIL_MASK = 0x10, SES_STATUS_UPS_AC_FAIL_SHIFT = 4, SES_STATUS_UPS_DC_FAIL_BYTE = 0, SES_STATUS_UPS_DC_FAIL_MASK = 0x08, SES_STATUS_UPS_DC_FAIL_SHIFT = 3, SES_STATUS_UPS_UPS_FAIL_BYTE = 0, SES_STATUS_UPS_UPS_FAIL_MASK = 0x04, SES_STATUS_UPS_UPS_FAIL_SHIFT = 2, SES_STATUS_UPS_WARN_BYTE = 0, SES_STATUS_UPS_WARN_MASK = 0x02, SES_STATUS_UPS_WARN_SHIFT = 1, SES_STATUS_UPS_INTF_FAIL_BYTE = 0, SES_STATUS_UPS_INTF_FAIL_MASK = 0x01, SES_STATUS_UPS_INTF_FAIL_SHIFT = 0, SES_STATUS_UPS_IDENT_BYTE = 0, SES_STATUS_UPS_IDENT_MASK = 0x80, SES_STATUS_UPS_IDENT_SHIFT = 7, SES_STATUS_UPS_FAIL_BYTE = 1, SES_STATUS_UPS_FAIL_MASK = 0x40, SES_STATUS_UPS_FAIL_SHIFT = 6, SES_STATUS_UPS_BATT_FAIL_BYTE = 1, SES_STATUS_UPS_BATT_FAIL_MASK = 0x02, SES_STATUS_UPS_BATT_FAIL_SHIFT = 1, SES_STATUS_UPS_BPF_BYTE = 1, SES_STATUS_UPS_BPF_MASK = 0x01, SES_STATUS_UPS_BPF_SHIFT = 0 }; #define GEN_SES_STATUS_UPS_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_ups, SES_STATUS_UPS, LCASE, UCASE) GEN_SES_STATUS_UPS_ACCESSORS(ac_lo, AC_LO) GEN_SES_STATUS_UPS_ACCESSORS(ac_hi, AC_HI) GEN_SES_STATUS_UPS_ACCESSORS(ac_qual, AC_QUAL) GEN_SES_STATUS_UPS_ACCESSORS(ac_fail, AC_FAIL) GEN_SES_STATUS_UPS_ACCESSORS(dc_fail, DC_FAIL) GEN_SES_STATUS_UPS_ACCESSORS(ups_fail, UPS_FAIL) GEN_SES_STATUS_UPS_ACCESSORS(warn, WARN) GEN_SES_STATUS_UPS_ACCESSORS(intf_fail, INTF_FAIL) GEN_SES_STATUS_UPS_ACCESSORS(ident, IDENT) GEN_SES_STATUS_UPS_ACCESSORS(fail, FAIL) GEN_SES_STATUS_UPS_ACCESSORS(batt_fail, BATT_FAIL) GEN_SES_STATUS_UPS_ACCESSORS(bpf, BPF) #undef GEN_SES_STATUS_UPS_ACCESSORS /*-------------------------- Display Status Element --------------------------*/ struct ses_status_display { struct ses_status_common common; uint8_t bytes[1]; uint8_t display_character[2]; }; enum ses_status_display_field_data { SES_STATUS_DISPLAY_IDENT_BYTE = 0, SES_STATUS_DISPLAY_IDENT_MASK = 0x80, SES_STATUS_DISPLAY_IDENT_SHIFT = 7, SES_STATUS_DISPLAY_FAIL_BYTE = 0, SES_STATUS_DISPLAY_FAIL_MASK = 0x40, SES_STATUS_DISPLAY_FAIL_SHIFT = 6, SES_STATUS_DISPLAY_DISPLAY_MODE_BYTE = 0, SES_STATUS_DISPLAY_DISPLAY_MODE_MASK = 0x03, SES_STATUS_DISPLAY_DISPLAY_MODE_SHIFT = 6, SES_STATUS_DISPLAY_DISPLAY_MODE_DC_FIELD_UNSUPP = 0x0, SES_STATUS_DISPLAY_DISPLAY_MODE_DC_FIELD_SUPP = 0x1, SES_STATUS_DISPLAY_DISPLAY_MODE_DC_FIELD = 0x2 }; #define GEN_SES_STATUS_DISPLAY_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_display, SES_STATUS_DISPLAY, LCASE, UCASE) GEN_SES_STATUS_DISPLAY_ACCESSORS(ident, IDENT) GEN_SES_STATUS_DISPLAY_ACCESSORS(fail, FAIL) GEN_SES_STATUS_DISPLAY_ACCESSORS(display_mode, DISPLAY_MODE) #undef GEN_SES_STATUS_DISPLAY_ACCESSORS /*----------------------- Key Pad Entry Status Element -----------------------*/ struct ses_status_key_pad_entry { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_key_pad_entry_field_data { SES_STATUS_KEY_PAD_ENTRY_IDENT_BYTE = 0, SES_STATUS_KEY_PAD_ENTRY_IDENT_MASK = 0x80, SES_STATUS_KEY_PAD_ENTRY_IDENT_SHIFT = 7, SES_STATUS_KEY_PAD_ENTRY_FAIL_BYTE = 0, SES_STATUS_KEY_PAD_ENTRY_FAIL_MASK = 0x40, SES_STATUS_KEY_PAD_ENTRY_FAIL_SHIFT = 6 }; #define GEN_SES_STATUS_KEY_PAD_ENTRY_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_key_pad_entry, SES_STATUS_KEY_PAD_ENTRY, LCASE, UCASE) GEN_SES_STATUS_KEY_PAD_ENTRY_ACCESSORS(ident, IDENT) GEN_SES_STATUS_KEY_PAD_ENTRY_ACCESSORS(fail, FAIL) #undef GEN_SES_STATUS_KEY_PAD_ENTRY_ACCESSORS /*------------------------- Enclosure Status Element -------------------------*/ struct ses_status_enclosure { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_enclosure_field_data { SES_STATUS_ENCLOSURE_IDENT_BYTE = 0, SES_STATUS_ENCLOSURE_IDENT_MASK = 0x80, SES_STATUS_ENCLOSURE_IDENT_SHIFT = 7, SES_STATUS_ENCLOSURE_TIME_UNTIL_POWER_CYCLE_BYTE = 1, SES_STATUS_ENCLOSURE_TIME_UNTIL_POWER_CYCLE_MASK = 0xFC, SES_STATUS_ENCLOSURE_TIME_UNTIL_POWER_CYCLE_SHIFT = 2, SES_STATUS_ENCLOSURE_FAIL_BYTE = 1, SES_STATUS_ENCLOSURE_FAIL_MASK = 0x02, SES_STATUS_ENCLOSURE_FAIL_SHIFT = 1, SES_STATUS_ENCLOSURE_WARN_BYTE = 1, SES_STATUS_ENCLOSURE_WARN_MASK = 0x01, SES_STATUS_ENCLOSURE_WARN_SHIFT = 0, SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_BYTE = 2, SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_MASK = 0xFC, SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_SHIFT = 2, SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_MAX_AUTO = 60, SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_MANUAL = 63, SES_STATUS_ENCLOSURE_REQUESTED_FAIL_BYTE = 2, SES_STATUS_ENCLOSURE_REQUESTED_FAIL_MASK = 0x02, SES_STATUS_ENCLOSURE_REQUESTED_FAIL_SHIFT = 1, SES_STATUS_ENCLOSURE_REQUESTED_WARN_BYTE = 2, SES_STATUS_ENCLOSURE_REQUESTED_WARN_MASK = 0x01, SES_STATUS_ENCLOSURE_REQUESTED_WARN_SHIFT = 0 }; #define GEN_SES_STATUS_ENCLOSURE_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_enclosure, SES_STATUS_ENCLOSURE, LCASE, UCASE) GEN_SES_STATUS_ENCLOSURE_ACCESSORS(ident, IDENT) GEN_SES_STATUS_ENCLOSURE_ACCESSORS(time_until_power_cycle, TIME_UNTIL_POWER_CYCLE) GEN_SES_STATUS_ENCLOSURE_ACCESSORS(fail, FAIL) GEN_SES_STATUS_ENCLOSURE_ACCESSORS(warn, WARN) GEN_SES_STATUS_ENCLOSURE_ACCESSORS(requested_power_off_duration, REQUESTED_POWER_OFF_DURATION) GEN_SES_STATUS_ENCLOSURE_ACCESSORS(requested_fail, REQUESTED_FAIL) GEN_SES_STATUS_ENCLOSURE_ACCESSORS(requested_warn, REQUESTED_WARN) #undef GEN_SES_STATUS_ENCLOSURE_ACCESSORS /*------------------- SCSI Port/Transceiver Status Element -------------------*/ struct ses_status_scsi_port_or_xcvr { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_scsi_port_or_xcvr_field_data { SES_STATUS_SCSI_PORT_OR_XCVR_IDENT_BYTE = 0, SES_STATUS_SCSI_PORT_OR_XCVR_IDENT_MASK = 0x80, SES_STATUS_SCSI_PORT_OR_XCVR_IDENT_SHIFT = 7, SES_STATUS_SCSI_PORT_OR_XCVR_FAIL_BYTE = 0, SES_STATUS_SCSI_PORT_OR_XCVR_FAIL_MASK = 0x40, SES_STATUS_SCSI_PORT_OR_XCVR_FAIL_SHIFT = 6, SES_STATUS_SCSI_PORT_OR_XCVR_REPORT_BYTE = 1, SES_STATUS_SCSI_PORT_OR_XCVR_REPORT_MASK = 0x01, SES_STATUS_SCSI_PORT_OR_XCVR_REPORT_SHIFT = 0, SES_STATUS_SCSI_PORT_OR_XCVR_DISABLED_BYTE = 2, SES_STATUS_SCSI_PORT_OR_XCVR_DISABLED_MASK = 0x10, SES_STATUS_SCSI_PORT_OR_XCVR_DISABLED_SHIFT = 4, SES_STATUS_SCSI_PORT_OR_XCVR_LOL_BYTE = 2, SES_STATUS_SCSI_PORT_OR_XCVR_LOL_MASK = 0x02, SES_STATUS_SCSI_PORT_OR_XCVR_LOL_SHIFT = 1, SES_STATUS_SCSI_PORT_OR_XCVR_XMIT_FAIL_BYTE = 2, SES_STATUS_SCSI_PORT_OR_XCVR_XMIT_FAIL_MASK = 0x01, SES_STATUS_SCSI_PORT_OR_XCVR_XMIT_FAIL_SHIFT = 0 }; #define GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_scsi_port_or_xcvr, SES_STATUS_SCSI_PORT_OR_XCVR,\ LCASE, UCASE) GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(ident, IDENT) GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(fail, FAIL) GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(report, REPORT) GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(disable, DISABLED) GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(lol, LOL) GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(xmit_fail, XMIT_FAIL) #undef GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS /*------------------------- Language Status Element --------------------------*/ struct ses_status_language { struct ses_status_common common; uint8_t bytes[1]; uint8_t language_code[2]; }; enum ses_status_language_field_data { SES_STATUS_LANGUAGE_IDENT_BYTE = 0, SES_STATUS_LANGUAGE_IDENT_MASK = 0x80, SES_STATUS_LANGUAGE_IDENT_SHIFT = 7 }; #define GEN_SES_STATUS_LANGUAGE_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_language, SES_STATUS_LANGUAGE, LCASE, UCASE) GEN_SES_STATUS_LANGUAGE_ACCESSORS(ident, IDENT) #undef GEN_SES_STATUS_LANGUAGE_ACCESSORS /*-------------------- Communication Port Status Element ---------------------*/ struct ses_status_comm_port { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_comm_port_field_data { SES_STATUS_COMM_PORT_IDENT_BYTE = 0, SES_STATUS_COMM_PORT_IDENT_MASK = 0x80, SES_STATUS_COMM_PORT_IDENT_SHIFT = 7, SES_STATUS_COMM_PORT_FAIL_BYTE = 0, SES_STATUS_COMM_PORT_FAIL_MASK = 0x40, SES_STATUS_COMM_PORT_FAIL_SHIFT = 6, SES_STATUS_COMM_PORT_DISABLED_BYTE = 2, SES_STATUS_COMM_PORT_DISABLED_MASK = 0x01, SES_STATUS_COMM_PORT_DISABLED_SHIFT = 0 }; #define GEN_SES_STATUS_COMM_PORT_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_comm_port, SES_STATUS_COMM_PORT, LCASE, UCASE) GEN_SES_STATUS_COMM_PORT_ACCESSORS(ident, IDENT) GEN_SES_STATUS_COMM_PORT_ACCESSORS(fail, FAIL) GEN_SES_STATUS_COMM_PORT_ACCESSORS(disabled, DISABLED) #undef GEN_SES_STATUS_COMM_PORT_ACCESSORS /*---------------------- Voltage Sensor Status Element -----------------------*/ struct ses_status_voltage_sensor { struct ses_status_common common; uint8_t bytes[1]; uint8_t voltage[2]; }; enum ses_status_voltage_sensor_field_data { SES_STATUS_VOLTAGE_SENSOR_IDENT_BYTE = 0, SES_STATUS_VOLTAGE_SENSOR_IDENT_MASK = 0x80, SES_STATUS_VOLTAGE_SENSOR_IDENT_SHIFT = 7, SES_STATUS_VOLTAGE_SENSOR_FAIL_BYTE = 0, SES_STATUS_VOLTAGE_SENSOR_FAIL_MASK = 0x40, SES_STATUS_VOLTAGE_SENSOR_FAIL_SHIFT = 6, SES_STATUS_VOLTAGE_SENSOR_WARN_OVER_BYTE = 0, SES_STATUS_VOLTAGE_SENSOR_WARN_OVER_MASK = 0x08, SES_STATUS_VOLTAGE_SENSOR_WARN_OVER_SHIFT = 3, SES_STATUS_VOLTAGE_SENSOR_WARN_UNDER_BYTE = 0, SES_STATUS_VOLTAGE_SENSOR_WARN_UNDER_MASK = 0x04, SES_STATUS_VOLTAGE_SENSOR_WARN_UNDER_SHIFT = 2, SES_STATUS_VOLTAGE_SENSOR_CRIT_OVER_BYTE = 0, SES_STATUS_VOLTAGE_SENSOR_CRIT_OVER_MASK = 0x02, SES_STATUS_VOLTAGE_SENSOR_CRIT_OVER_SHIFT = 1, SES_STATUS_VOLTAGE_SENSOR_CRIT_UNDER_BYTE = 0, SES_STATUS_VOLTAGE_SENSOR_CRIT_UNDER_MASK = 0x01, SES_STATUS_VOLTAGE_SENSOR_CRIT_UNDER_SHIFT = 0 }; #define GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_voltage_sensor, SES_STATUS_VOLTAGE_SENSOR, \ LCASE, UCASE) GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(ident, IDENT) GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(fail, FAIL) GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(warn_over, WARN_OVER) GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(warn_under, WARN_UNDER) GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(crit_over, CRIT_OVER) GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(crit_under, CRIT_UNDER) #undef GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS /*---------------------- Current Sensor Status Element -----------------------*/ struct ses_status_current_sensor { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_current_sensor_field_data { SES_STATUS_CURRENT_SENSOR_IDENT_BYTE = 0, SES_STATUS_CURRENT_SENSOR_IDENT_MASK = 0x80, SES_STATUS_CURRENT_SENSOR_IDENT_SHIFT = 7, SES_STATUS_CURRENT_SENSOR_FAIL_BYTE = 0, SES_STATUS_CURRENT_SENSOR_FAIL_MASK = 0x40, SES_STATUS_CURRENT_SENSOR_FAIL_SHIFT = 6, SES_STATUS_CURRENT_SENSOR_WARN_OVER_BYTE = 0, SES_STATUS_CURRENT_SENSOR_WARN_OVER_MASK = 0x08, SES_STATUS_CURRENT_SENSOR_WARN_OVER_SHIFT = 3, SES_STATUS_CURRENT_SENSOR_CRIT_OVER_BYTE = 0, SES_STATUS_CURRENT_SENSOR_CRIT_OVER_MASK = 0x02, SES_STATUS_CURRENT_SENSOR_CRIT_OVER_SHIFT = 1 }; #define GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_current_sensor, SES_STATUS_CURRENT_SENSOR, \ LCASE, UCASE) GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(ident, IDENT) GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(fail, FAIL) GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(warn_over, WARN_OVER) GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(crit_over, CRIT_OVER) #undef GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS /*--------------------- SCSI Target Port Status Element ----------------------*/ struct ses_status_target_port { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_scsi_target_port_field_data { SES_STATUS_TARGET_PORT_IDENT_BYTE = 0, SES_STATUS_TARGET_PORT_IDENT_MASK = 0x80, SES_STATUS_TARGET_PORT_IDENT_SHIFT = 7, SES_STATUS_TARGET_PORT_FAIL_BYTE = 0, SES_STATUS_TARGET_PORT_FAIL_MASK = 0x40, SES_STATUS_TARGET_PORT_FAIL_SHIFT = 6, SES_STATUS_TARGET_PORT_REPORT_BYTE = 1, SES_STATUS_TARGET_PORT_REPORT_MASK = 0x01, SES_STATUS_TARGET_PORT_REPORT_SHIFT = 0, SES_STATUS_TARGET_PORT_ENABLED_BYTE = 2, SES_STATUS_TARGET_PORT_ENABLED_MASK = 0x01, SES_STATUS_TARGET_PORT_ENABLED_SHIFT = 0 }; #define GEN_SES_STATUS_TARGET_PORT_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_target_port, SES_STATUS_TARGET_PORT, LCASE, UCASE) GEN_SES_STATUS_TARGET_PORT_ACCESSORS(ident, IDENT) GEN_SES_STATUS_TARGET_PORT_ACCESSORS(fail, FAIL) GEN_SES_STATUS_TARGET_PORT_ACCESSORS(report, REPORT) GEN_SES_STATUS_TARGET_PORT_ACCESSORS(enabled, ENABLED) #undef GEN_SES_STATUS_TARGET_PORT_ACCESSORS /*-------------------- SCSI Initiator Port Status Element --------------------*/ struct ses_status_initiator_port { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_scsi_initiator_port_field_data { SES_STATUS_INITIATOR_PORT_IDENT_BYTE = 0, SES_STATUS_INITIATOR_PORT_IDENT_MASK = 0x80, SES_STATUS_INITIATOR_PORT_IDENT_SHIFT = 7, SES_STATUS_INITIATOR_PORT_FAIL_BYTE = 0, SES_STATUS_INITIATOR_PORT_FAIL_MASK = 0x40, SES_STATUS_INITIATOR_PORT_FAIL_SHIFT = 6, SES_STATUS_INITIATOR_PORT_REPORT_BYTE = 1, SES_STATUS_INITIATOR_PORT_REPORT_MASK = 0x01, SES_STATUS_INITIATOR_PORT_REPORT_SHIFT = 0, SES_STATUS_INITIATOR_PORT_ENABLED_BYTE = 2, SES_STATUS_INITIATOR_PORT_ENABLED_MASK = 0x01, SES_STATUS_INITIATOR_PORT_ENABLED_SHIFT = 0 }; #define GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_initiator_port, SES_STATUS_INITIATOR_PORT, \ LCASE, UCASE) GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(ident, IDENT) GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(fail, FAIL) GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(report, REPORT) GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(enabled, ENABLED) #undef GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS /*-------------------- Simple Subenclosure Status Element --------------------*/ struct ses_status_simple_subses { struct ses_status_common common; uint8_t bytes[2]; uint8_t short_enclosure_status; }; enum ses_status_simple_subses_field_data { SES_STATUS_SIMPlE_SUBSES_IDENT_BYTE = 0, SES_STATUS_SIMPlE_SUBSES_IDENT_MASK = 0x80, SES_STATUS_SIMPlE_SUBSES_IDENT_SHIFT = 7, SES_STATUS_SIMPlE_SUBSES_FAIL_BYTE = 0, SES_STATUS_SIMPlE_SUBSES_FAIL_MASK = 0x40, SES_STATUS_SIMPlE_SUBSES_FAIL_SHIFT = 6 }; #define GEN_SES_STATUS_SIMPlE_SUBSES_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_simple_subses, SES_STATUS_SIMPlE_SUBSES, \ LCASE, UCASE) GEN_SES_STATUS_SIMPlE_SUBSES_ACCESSORS(ident, IDENT) GEN_SES_STATUS_SIMPlE_SUBSES_ACCESSORS(fail, FAIL) #undef GEN_SES_STATUS_SIMPlE_SUBSES_ACCESSORS /*----------------------- SAS Expander Status Element ------------------------*/ struct ses_status_sas_expander { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_sas_expander_field_data { SES_STATUS_SAS_EXPANDER_IDENT_BYTE = 0, SES_STATUS_SAS_EXPANDER_IDENT_MASK = 0x80, SES_STATUS_SAS_EXPANDER_IDENT_SHIFT = 7, SES_STATUS_SAS_EXPANDER_FAIL_BYTE = 0, SES_STATUS_SAS_EXPANDER_FAIL_MASK = 0x40, SES_STATUS_SAS_EXPANDER_FAIL_SHIFT = 6 }; #define GEN_SES_STATUS_SAS_EXPANDER_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_sas_expander, SES_STATUS_SAS_EXPANDER, LCASE, UCASE) GEN_SES_STATUS_SAS_EXPANDER_ACCESSORS(ident, IDENT) GEN_SES_STATUS_SAS_EXPANDER_ACCESSORS(fail, FAIL) #undef GEN_SES_STATUS_SAS_EXPANDER_ACCESSORS /*----------------------- SAS Connector Status Element -----------------------*/ struct ses_status_sas_connector { struct ses_status_common common; uint8_t bytes[3]; }; enum ses_status_sas_connector_field_data { SES_STATUS_SAS_CONNECTOR_IDENT_BYTE = 0, SES_STATUS_SAS_CONNECTOR_IDENT_MASK = 0x80, SES_STATUS_SAS_CONNECTOR_IDENT_SHIFT = 7, SES_STATUS_SAS_CONNECTOR_TYPE_BYTE = 0, SES_STATUS_SAS_CONNECTOR_TYPE_MASK = 0x7F, SES_STATUS_SAS_CONNECTOR_TYPE_SHIFT = 0, SES_STATUS_SAS_CONNECTOR_PHYS_LINK_BYTE = 1, SES_STATUS_SAS_CONNECTOR_PHYS_LINK_MASK = 0xFF, SES_STATUS_SAS_CONNECTOR_PHYS_LINK_SHIFT = 0, SES_STATUS_SAS_CONNECTOR_PHYS_LINK_ALL = 0xFF, SES_STATUS_SAS_CONNECTOR_FAIL_BYTE = 2, SES_STATUS_SAS_CONNECTOR_FAIL_MASK = 0x40, SES_STATUS_SAS_CONNECTOR_FAIL_SHIFT = 6, }; #define GEN_SES_STATUS_SAS_CONNECTOR_ACCESSORS(LCASE, UCASE) \ GEN_GETTER(ses_status_sas_connector, SES_STATUS_SAS_CONNECTOR, \ LCASE, UCASE) GEN_SES_STATUS_SAS_CONNECTOR_ACCESSORS(ident, IDENT) GEN_SES_STATUS_SAS_CONNECTOR_ACCESSORS(type, TYPE) GEN_SES_STATUS_SAS_CONNECTOR_ACCESSORS(phys_link, PHYS_LINK) GEN_SES_STATUS_SAS_CONNECTOR_ACCESSORS(fail, FAIL) #undef GEN_SES_STATUS_SAS_CONNECTOR_ACCESSORS /*------------------------- Universal Status Element -------------------------*/ union ses_status_element { struct ses_status_common common; struct ses_status_dev_slot dev_slot; struct ses_status_array_dev_slot array_dev_slot; struct ses_status_power_supply power_supply; struct ses_status_cooling cooling; struct ses_status_temp_sensor temp_sensor; struct ses_status_door_lock door_lock; struct ses_status_audible_alarm audible_alarm; struct ses_status_ecc_electronics ecc_electronics; struct ses_status_scc_electronics scc_electronics; struct ses_status_nv_cache nv_cache; struct ses_status_invalid_op_reason invalid_op_reason; struct ses_status_ups ups; struct ses_status_display display; struct ses_status_key_pad_entry key_pad_entry; struct ses_status_scsi_port_or_xcvr scsi_port_or_xcvr; struct ses_status_language language; struct ses_status_comm_port comm_port; struct ses_status_voltage_sensor voltage_sensor; struct ses_status_current_sensor current_sensor; struct ses_status_target_port target_port; struct ses_status_initiator_port initiator_port; struct ses_status_simple_subses simple_subses; struct ses_status_sas_expander sas_expander; struct ses_status_sas_connector sas_connector; uint8_t bytes[4]; }; +/* + * Convert element status into control as much as possible. + * Some bits have different meaning in status and control, + * while others have the same and should be preserved. + */ +static inline void +ses_status_to_ctrl(uint8_t type, uint8_t *bytes) +{ + /* Updated to SES4r5. */ + static const uint8_t mask[][4] = { + { 0x60, 0x00, 0x00, 0x00 }, /* UNSPECIFIED */ + { 0x60, 0x00, 0x4e, 0x3c }, /* DEVICE */ + { 0x60, 0xc0, 0x00, 0x60 }, /* POWER */ + { 0x60, 0xc0, 0x00, 0x60 }, /* COOLING/FAN */ + { 0x60, 0xc0, 0x00, 0x80 }, /* THERM */ + { 0x60, 0xc0, 0x00, 0x01 }, /* DOORLOCK */ + { 0x60, 0xc0, 0x00, 0x5f }, /* ALARM */ + { 0x60, 0xf0, 0x01, 0x00 }, /* ESSC */ + { 0x60, 0xc0, 0x00, 0x00 }, /* SCC */ + { 0x60, 0xc0, 0x00, 0x00 }, /* NVRAM */ + { 0x60, 0x00, 0x00, 0x00 }, /* INV_OP_REASON */ + { 0x60, 0x00, 0x00, 0xe0 }, /* UPS */ + { 0x60, 0xc0, 0xff, 0xff }, /* DISPLAY */ + { 0x60, 0xc0, 0x00, 0x00 }, /* KEYPAD */ + { 0x60, 0x80, 0x00, 0xff }, /* ENCLOSURE */ + { 0x60, 0xc0, 0x00, 0x10 }, /* SCSIXVR */ + { 0x60, 0x80, 0xff, 0xff }, /* LANGUAGE */ + { 0x60, 0xc0, 0x00, 0x01 }, /* COMPORT */ + { 0x60, 0xc0, 0x00, 0x00 }, /* VOM */ + { 0x60, 0xc0, 0x00, 0x00 }, /* AMMETER */ + { 0x60, 0xc0, 0x00, 0x01 }, /* SCSI_TGT */ + { 0x60, 0xc0, 0x00, 0x01 }, /* SCSI_INI*/ + { 0x60, 0xc0, 0x00, 0x00 }, /* SUBENC */ + { 0x60, 0xff, 0x4e, 0x3c }, /* ARRAY_DEV */ + { 0x60, 0xc0, 0x00, 0x00 }, /* SAS_EXP */ + { 0x60, 0x80, 0x00, 0x40 }, /* SAS_CONN */ + }; + + if (type >= sizeof(mask) / sizeof(mask[0])) + type = 0; + for (int i = 0; i < 4; i++) + bytes[i] &= mask[type][i]; +} + /*===================== SCSI SES Status Diagnostic Page =====================*/ struct ses_status_page { struct ses_page_hdr hdr; union ses_status_element elements[]; }; enum ses_status_page_field_data { SES_STATUS_PAGE_INVOP_MASK = 0x10, SES_STATUS_PAGE_INVOP_SHIFT = 4, SES_STATUS_PAGE_INFO_MASK = 0x08, SES_STATUS_PAGE_INFO_SHIFT = 3, SES_STATUS_PAGE_NON_CRIT_MASK = 0x04, SES_STATUS_PAGE_NON_CRIT_SHIFT = 2, SES_STATUS_PAGE_CRIT_MASK = 0x02, SES_STATUS_PAGE_CRIT_SHIFT = 1, SES_STATUS_PAGE_UNRECOV_MASK = 0x01, SES_STATUS_PAGE_UNRECOV_SHIFT = 0, SES_STATUS_PAGE_CHANGED_MASK = SES_STATUS_PAGE_INVOP_MASK | SES_STATUS_PAGE_INFO_MASK | SES_STATUS_PAGE_NON_CRIT_MASK | SES_STATUS_PAGE_CRIT_MASK | SES_STATUS_PAGE_UNRECOV_MASK, SES_STATUS_PAGE_CHANGED_SHIFT = 0, }; #define GEN_SES_STATUS_PAGE_ACCESSORS(LCASE, UCASE) \ GEN_HDR_ACCESSORS(ses_status_page, SES_STATUS_PAGE, LCASE, UCASE) GEN_SES_STATUS_PAGE_ACCESSORS(invop, INVOP) GEN_SES_STATUS_PAGE_ACCESSORS(info, INFO) GEN_SES_STATUS_PAGE_ACCESSORS(non_crit, NON_CRIT) GEN_SES_STATUS_PAGE_ACCESSORS(crit, CRIT) GEN_SES_STATUS_PAGE_ACCESSORS(unrecov, UNRECOV) GEN_SES_STATUS_PAGE_ACCESSORS(changed, CHANGED) #undef GEN_SES_STATUS_PAGE_ACCESSORS /*================ SCSI SES Element Descriptor Diagnostic Page ===============*/ struct ses_elem_descr { uint8_t reserved[2]; uint8_t length[2]; char description[]; }; struct ses_elem_descr_page { struct ses_page_hdr hdr; struct ses_elem_descr descrs[]; }; /*============ SCSI SES Additional Element Status Diagnostic Page ============*/ struct ses_addl_elem_status_page { struct ses_page_hdr hdr; }; /*====================== Legacy (Deprecated) Structures ======================*/ struct ses_control_page_hdr { uint8_t page_code; uint8_t control_flags; uint8_t length[2]; uint8_t gen_code[4]; /* Followed by variable length array of descriptors. */ }; struct ses_status_page_hdr { uint8_t page_code; uint8_t status_flags; uint8_t length[2]; uint8_t gen_code[4]; /* Followed by variable length array of descriptors. */ }; /* ses_page_hdr.reserved values */ /* * Enclosure Status Diagnostic Page: * uint8_t reserved : 3, * invop : 1, * info : 1, * noncritical : 1, * critical : 1, * unrecov : 1; */ #define SES_ENCSTAT_UNRECOV 0x01 #define SES_ENCSTAT_CRITICAL 0x02 #define SES_ENCSTAT_NONCRITICAL 0x04 #define SES_ENCSTAT_INFO 0x08 #define SES_ENCSTAT_INVOP 0x10 /* Status mask: All of the above OR'd together */ #define SES_STATUS_MASK 0x1f #define SES_SET_STATUS_MASK 0xf /* Element Descriptor Diagnostic Page: unused */ /* Additional Element Status Diagnostic Page: unused */ /* Summary SES Status Defines, Common Status Codes */ #define SES_OBJSTAT_UNSUPPORTED 0 #define SES_OBJSTAT_OK 1 #define SES_OBJSTAT_CRIT 2 #define SES_OBJSTAT_NONCRIT 3 #define SES_OBJSTAT_UNRECOV 4 #define SES_OBJSTAT_NOTINSTALLED 5 #define SES_OBJSTAT_UNKNOWN 6 #define SES_OBJSTAT_NOTAVAIL 7 #define SES_OBJSTAT_NOACCESS 8 /* * For control pages, cstat[0] is the same for the * enclosure and is common across all device types. * * If SESCTL_CSEL is set, then PRDFAIL, DISABLE and RSTSWAP * are checked, otherwise bits that are specific to the device * type in the other 3 bytes of cstat or checked. */ #define SESCTL_CSEL 0x80 #define SESCTL_PRDFAIL 0x40 #define SESCTL_DISABLE 0x20 #define SESCTL_RSTSWAP 0x10 /* Control bits, Array Device Slot Elements, byte 1 */ #define SESCTL_RQSOK 0x80 /* RQST OK */ #define SESCTL_RQSRSV 0x40 /* RQST RSVD DEVICE */ #define SESCTL_RQSSPR 0x20 /* RQST HOT SPARE */ #define SESCTL_RQSCCH 0x10 /* RQST CONS CHECK */ #define SESCTL_RQSCRA 0x08 /* RQST IN CRIT ARRAY */ #define SESCTL_RQSFAA 0x04 /* RQST IN FAILED ARRAY */ #define SESCTL_RQSRR 0x02 /* RQST REBUI/REMAP */ #define SESCTL_RQSRRA 0x01 /* RQST R/R ABORT */ /* Control bits, [Array] Device Slot Elements, byte 2 */ #define SESCTL_RQSACT 0x80 /* RQST ACTIVE */ #define SESCTL_DRVLCK 0x40 /* DO NOT REMOVE */ #define SESCTL_RQSMSN 0x10 /* RQST MISSING */ #define SESCTL_RQSINS 0x08 /* RQST INSERT */ #define SESCTL_RQSRMV 0x04 /* RQST REMOVE */ #define SESCTL_RQSID 0x02 /* RQST IDENT */ /* Control bits, [Array] Device Slot Elements, byte 3 */ #define SESCTL_RQSFLT 0x20 /* RQST FAULT */ #define SESCTL_DEVOFF 0x10 /* DEVICE OFF */ #define SESCTL_ENBYPA 0x08 /* ENABLE BYP A */ #define SESCTL_ENBYPB 0x04 /* ENABLE BYP B */ /* Control bits, Generic, byte 3 */ #define SESCTL_RQSTFAIL 0x40 #define SESCTL_RQSTON 0x20 /* * Getting text for an object type is a little * trickier because it's string data that can * go up to 64 KBytes. Build this union and * fill the obj_id with the id of the object who's * help text you want, and if text is available, * obj_text will be filled in, null terminated. */ typedef union { unsigned int obj_id; char obj_text[1]; } ses_hlptxt; /*============================================================================*/ struct ses_elm_desc_hdr { uint8_t reserved[2]; uint8_t length[2]; }; /* * SES v2 r20 6.1.13 - Element Additional Status diagnostic page * Tables 26-28 (general), 29-32 (FC), 33-41 (SAS) * * Protocol identifier uses definitions in scsi_all.h; * SPSP_PROTO_FC, SPSP_PROTO_SAS are the only ones used here. */ struct ses_elm_fc_eip_hdr { uint8_t num_phys; uint8_t reserved[2]; uint8_t dev_slot_num; uint8_t node_name[8]; }; struct ses_elm_fc_noneip_hdr { uint8_t num_phys; uint8_t reserved; uint8_t node_name[8]; }; struct ses_elm_fc_base_hdr { uint8_t num_phys; }; union ses_elm_fc_hdr { struct ses_elm_fc_base_hdr base_hdr; struct ses_elm_fc_eip_hdr eip_hdr; struct ses_elm_fc_noneip_hdr noneip_hdr; }; struct ses_elm_fc_port { uint8_t port_loop_position; uint8_t bypass_reason; #define SES_FC_PORT_BYPASS_UNBYPASSED 0x00 #define SES_FC_PORT_BYPASS_LINKFAIL_RATE_TOO_HIGH 0x10 #define SES_FC_PORT_BYPASS_SYNC_LOSS_RATE_TOO_HIGH 0x11 #define SES_FC_PORT_BYPASS_SIGNAL_LOSS_RATE_TOO_HIGH 0x12 #define SES_FC_PORT_BYPASS_SEQPROTO_ERR_RATE_TOO_HIGH 0x13 #define SES_FC_PORT_BYPASS_INVAL_XMIT_RATE_TOO_HIGH 0x14 #define SES_FC_PORT_BYPASS_CRC_ERR_RATE_TOO_HIGH 0x15 #define SES_FC_PORT_BYPASS_ERR_RATE_RESERVED_BEGIN 0x16 #define SES_FC_PORT_BYPASS_ERR_RATE_RESERVED_END 0x1F #define SES_FC_PORT_BYPASS_LINKFAIL_COUNT_TOO_HIGH 0x20 #define SES_FC_PORT_BYPASS_SYNC_LOSS_COUNT_TOO_HIGH 0x21 #define SES_FC_PORT_BYPASS_SIGNAL_LOSS_COUNT_TOO_HIGH 0x22 #define SES_FC_PORT_BYPASS_SEQPROTO_ERR_COUNT_TOO_HIGH 0x23 #define SES_FC_PORT_BYPASS_INVAL_XMIT_COUNT_TOO_HIGH 0x24 #define SES_FC_PORT_BYPASS_CRC_ERR_COUNT_TOO_HIGH 0x25 #define SES_FC_PORT_BYPASS_ERR_COUNT_RESERVED_BEGIN 0x26 #define SES_FC_PORT_BYPASS_ERR_COUNT_RESERVED_END 0x2F #define SES_FC_PORT_BYPASS_RESERVED_BEGIN 0x30 #define SES_FC_PORT_BYPASS_RESERVED_END 0xBF #define SES_FC_PORT_BYPASS_VENDOR_SPECIFIC_BEGIN 0xC0 #define SES_FC_PORT_BYPASS_VENDOR_SPECIFIC_END 0xFF uint8_t port_req_hard_addr; uint8_t n_port_id[3]; uint8_t n_port_name[8]; }; struct ses_elm_sas_device_phy { uint8_t byte0; /* * uint8_t reserved0 : 1, * uint8_t device_type : 3, * uint8_t reserved1 : 4; */ uint8_t reserved0; /* Bit positions for initiator and target port protocols */ #define SES_SASOBJ_DEV_PHY_SMP 0x2 #define SES_SASOBJ_DEV_PHY_STP 0x4 #define SES_SASOBJ_DEV_PHY_SSP 0x8 /* Select all of the above protocols */ #define SES_SASOBJ_DEV_PHY_PROTOMASK 0xe uint8_t initiator_ports; /* * uint8_t reserved0 : 4, * uint8_t ssp : 1, * uint8_t stp : 1, * uint8_t smp : 1, * uint8_t reserved1 : 3; */ uint8_t target_ports; /* * uint8_t sata_port_selector : 1, * uint8_t reserved : 3, * uint8_t ssp : 1, * uint8_t stp : 1, * uint8_t smp : 1, * uint8_t sata_device : 1; */ uint8_t parent_addr[8]; /* SAS address of parent */ uint8_t phy_addr[8]; /* SAS address of this phy */ uint8_t phy_id; uint8_t reserved1[7]; }; #ifdef _KERNEL int ses_elm_sas_dev_phy_sata_dev(struct ses_elm_sas_device_phy *); int ses_elm_sas_dev_phy_sata_port(struct ses_elm_sas_device_phy *); int ses_elm_sas_dev_phy_dev_type(struct ses_elm_sas_device_phy *); #endif /* _KERNEL */ struct ses_elm_sas_expander_phy { uint8_t connector_index; uint8_t other_index; }; struct ses_elm_sas_port_phy { uint8_t phy_id; uint8_t reserved; uint8_t connector_index; uint8_t other_index; uint8_t phy_addr[8]; }; struct ses_elm_sas_type0_base_hdr { uint8_t num_phys; uint8_t byte1; /* * uint8_t descriptor_type : 2, * uint8_t reserved : 5, * uint8_t not_all_phys : 1; */ #define SES_SASOBJ_TYPE0_NOT_ALL_PHYS(obj) \ ((obj)->byte1 & 0x1) }; struct ses_elm_sas_type0_eip_hdr { struct ses_elm_sas_type0_base_hdr base; uint8_t reserved; uint8_t dev_slot_num; }; struct ses_elm_sas_type1_expander_hdr { uint8_t num_phys; uint8_t byte1; /* * uint8_t descriptor_type : 2, * uint8_t reserved : 6; */ uint8_t reserved[2]; uint8_t sas_addr[8]; }; struct ses_elm_sas_type1_nonexpander_hdr { uint8_t num_phys; uint8_t byte1; /* * uint8_t descriptor_type : 2, * uint8_t reserved : 6; */ uint8_t reserved[2]; }; /* NB: This is only usable for as long as the headers happen to match */ struct ses_elm_sas_base_hdr { uint8_t num_phys; uint8_t byte1; /* * uint8_t descriptor_type : 2, * uint8_t descr_specific : 6; */ #define SES_SASOBJ_TYPE_SLOT 0 #define SES_SASOBJ_TYPE_OTHER 1 }; union ses_elm_sas_hdr { struct ses_elm_sas_base_hdr base_hdr; struct ses_elm_sas_type0_base_hdr type0_noneip; struct ses_elm_sas_type0_eip_hdr type0_eip; struct ses_elm_sas_type1_expander_hdr type1_exp; struct ses_elm_sas_type1_nonexpander_hdr type1_nonexp; }; int ses_elm_sas_type0_not_all_phys(union ses_elm_sas_hdr *); int ses_elm_sas_descr_type(union ses_elm_sas_hdr *); /* * This structure for SPSP_PROTO_ATA is not defined by SES specs, * but purely my own design to make AHCI EM interoperate with SES. * Since no other software I know can talk to SEMB, and we do not * expose this this outside, it should be safe to do what we want. */ struct ses_elm_ata_hdr { uint8_t bus[4]; uint8_t target[4]; }; struct ses_elm_addlstatus_base_hdr { uint8_t byte0; /* * uint8_t invalid : 1, * uint8_t reserved : 2, * uint8_t eip : 1, * uint8_t proto_id : 4; */ uint8_t length; }; int ses_elm_addlstatus_proto(struct ses_elm_addlstatus_base_hdr *); int ses_elm_addlstatus_eip(struct ses_elm_addlstatus_base_hdr *); int ses_elm_addlstatus_invalid(struct ses_elm_addlstatus_base_hdr *); struct ses_elm_addlstatus_eip_hdr { struct ses_elm_addlstatus_base_hdr base; uint8_t byte2; #define SES_ADDL_EIP_EIIOE_MASK 3 #define SES_ADDL_EIP_EIIOE_SES2 0 #define SES_ADDL_EIP_EIIOE_GLOB 1 #define SES_ADDL_EIP_EIIOE_IND 2 #define SES_ADDL_EIP_EIIOE_MIX 3 #define SES_ADDL_EIP_EIIOE_EI_GLOB(x) \ (((x) & SES_ADDL_EIP_EIIOE_MASK) == SES_ADDL_EIP_EIIOE_GLOB) uint8_t element_index; /* NB: This define (currently) applies to all eip=1 headers */ #define SES_EIP_HDR_EXTRA_LEN 2 }; union ses_elm_addlstatus_descr_hdr { struct ses_elm_addlstatus_base_hdr base; struct ses_elm_addlstatus_eip_hdr eip; }; union ses_elm_addlstatus_proto_hdr { union ses_elm_fc_hdr fc; union ses_elm_sas_hdr sas; }; /*============================= Namespace Cleanup ============================*/ #undef GEN_HDR_ACCESSORS #undef GEN_ACCESSORS #undef GEN_HDR_SETTER #undef GEN_HDR_GETTER #undef GEN_SETTER #undef GEN_GETTER #undef MK_ENUM #endif /* _SCSI_SES_H_ */ diff --git a/usr.sbin/sesutil/sesutil.c b/usr.sbin/sesutil/sesutil.c index 9e6098e1da35..d78a9172e454 100644 --- a/usr.sbin/sesutil/sesutil.c +++ b/usr.sbin/sesutil/sesutil.c @@ -1,1008 +1,1009 @@ /*- * Copyright (c) 2019 Klara Inc. * Copyright (c) 2015 Baptiste Daroussin * Copyright (c) 2015 Allan Jude * Copyright (c) 2000 by Matthew Jacob * All rights reserved. * * Portions of this software were developed by Edward Tomasz Napierala * under sponsorship from Klara Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eltsub.h" #define SESUTIL_XO_VERSION "1" #define TEMPERATURE_OFFSET 20 #define PRINT_STYLE_DASHED 0 #define PRINT_STYLE_DASHED_2 1 #define PRINT_STYLE_CSV 2 #define PRINT_STYLE_CSV_2 3 static int encstatus(int argc, char **argv); static int fault(int argc, char **argv); static int locate(int argc, char **argv); static int objmap(int argc, char **argv); static int sesled(int argc, char **argv, bool fault); static int show(int argc, char **argv); static void sesutil_print(int *style, const char *fmt, ...) __printflike(2,3); static struct command { const char *name; const char *param; const char *desc; int (*exec)(int argc, char **argv); } cmds[] = { { "fault", "(||all) (on|off)", "Change the state of the fault LED associated with a disk", fault }, { "locate", "(||all) (on|off)", "Change the state of the locate LED associated with a disk", locate }, { "map", "", "Print a map of the devices managed by the enclosure", objmap } , { "show", "", "Print a human-friendly summary of the enclosure", show } , { "status", "", "Print the status of the enclosure", encstatus }, }; static const int nbcmds = nitems(cmds); static const char *uflag; static void usage(FILE *out, const char *subcmd) { int i; if (subcmd == NULL) { fprintf(out, "Usage: %s [-u /dev/ses] [options]\n", getprogname()); fprintf(out, "Commands supported:\n"); } for (i = 0; i < nbcmds; i++) { if (subcmd != NULL) { if (strcmp(subcmd, cmds[i].name) == 0) { fprintf(out, "Usage: %s %s [-u /dev/ses] " "%s\n\t%s\n", getprogname(), subcmd, cmds[i].param, cmds[i].desc); break; } continue; } fprintf(out, " %-12s%s\n\t\t%s\n\n", cmds[i].name, cmds[i].param, cmds[i].desc); } exit(EXIT_FAILURE); } static void do_led(int fd, unsigned int idx, elm_type_t type, bool onoff, bool setfault) { int state = onoff ? 1 : 0; encioc_elm_status_t o; struct ses_ctrl_dev_slot *slot; o.elm_idx = idx; if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); } - slot = (struct ses_ctrl_dev_slot *) &o.cstat[0]; + ses_status_to_ctrl(type, &o.cstat[0]); switch (type) { case ELMTYP_DEVICE: case ELMTYP_ARRAY_DEV: + slot = (struct ses_ctrl_dev_slot *) &o.cstat[0]; ses_ctrl_common_set_select(&slot->common, 1); if (setfault) ses_ctrl_dev_slot_set_rqst_fault(slot, state); else ses_ctrl_dev_slot_set_rqst_ident(slot, state); break; default: return; } if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_SETELMSTAT"); } } static bool disk_match(const char *devnames, const char *disk, size_t len) { const char *dname; dname = devnames; while ((dname = strstr(dname, disk)) != NULL) { if (dname[len] == '\0' || dname[len] == ',') { return (true); } dname++; } return (false); } static int sesled(int argc, char **argv, bool setfault) { encioc_elm_devnames_t objdn; encioc_element_t *objp; glob_t g; char *disk, *endptr; size_t len, i, ndisks; int fd; unsigned int nobj, j, sesid; bool all, isses, onoff; isses = false; all = false; onoff = false; if (argc != 3) { usage(stderr, (setfault ? "fault" : "locate")); } disk = argv[1]; sesid = strtoul(disk, &endptr, 10); if (*endptr == '\0') { endptr = strrchr(uflag, '*'); if (endptr != NULL && *endptr == '*') { xo_warnx("Must specifying a SES device (-u) to use a SES " "id# to identify a disk"); usage(stderr, (setfault ? "fault" : "locate")); } isses = true; } if (strcmp(argv[2], "on") == 0) { onoff = true; } else if (strcmp(argv[2], "off") == 0) { onoff = false; } else { usage(stderr, (setfault ? "fault" : "locate")); } if (strcmp(disk, "all") == 0) { all = true; } len = strlen(disk); /* Get the list of ses devices */ if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) == GLOB_NOMATCH) { globfree(&g); xo_errx(EXIT_FAILURE, "No SES devices found"); } ndisks = 0; for (i = 0; i < g.gl_pathc; i++) { /* ensure we only got numbers after ses */ if (strspn(g.gl_pathv[i] + 8, "0123456789") != strlen(g.gl_pathv[i] + 8)) { continue; } if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { /* * Don't treat non-access errors as critical if we are * accessing all devices */ if (errno == EACCES && g.gl_pathc > 1) { xo_err(EXIT_FAILURE, "unable to access SES device"); } xo_warn("unable to access SES device: %s", g.gl_pathv[i]); continue; } if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); } objp = calloc(nobj, sizeof(encioc_element_t)); if (objp == NULL) { close(fd); xo_err(EXIT_FAILURE, "calloc()"); } if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) { free(objp); close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); } if (isses) { if (sesid >= nobj) { free(objp); close(fd); xo_errx(EXIT_FAILURE, "Requested SES ID does not exist"); } do_led(fd, sesid, objp[sesid].elm_type, onoff, setfault); ndisks++; free(objp); close(fd); break; } for (j = 0; j < nobj; j++) { const int devnames_size = 128; char devnames[devnames_size]; if (all) { do_led(fd, objp[j].elm_idx, objp[j].elm_type, onoff, setfault); continue; } memset(&objdn, 0, sizeof(objdn)); memset(devnames, 0, devnames_size); objdn.elm_idx = objp[j].elm_idx; objdn.elm_names_size = devnames_size; objdn.elm_devnames = devnames; if (ioctl(fd, ENCIOC_GETELMDEVNAMES, (caddr_t) &objdn) <0) { continue; } if (objdn.elm_names_len > 0) { if (disk_match(objdn.elm_devnames, disk, len)) { do_led(fd, objdn.elm_idx, objp[j].elm_type, onoff, setfault); ndisks++; break; } } } free(objp); close(fd); } globfree(&g); if (ndisks == 0 && all == false) { xo_errx(EXIT_FAILURE, "Count not find the SES id of device '%s'", disk); } return (EXIT_SUCCESS); } static int locate(int argc, char **argv) { return (sesled(argc, argv, false)); } static int fault(int argc, char **argv) { return (sesled(argc, argv, true)); } static void sesutil_print(int *style, const char *fmt, ...) { va_list args; if (*style == PRINT_STYLE_DASHED) { xo_open_container("extra_status"); xo_emit("\t\tExtra status:\n"); *style = PRINT_STYLE_DASHED_2; } else if (*style == PRINT_STYLE_CSV) { xo_open_container("extra_status"); *style = PRINT_STYLE_CSV_2; } if (*style == PRINT_STYLE_DASHED_2) xo_emit("\t\t- "); else if (*style == PRINT_STYLE_CSV_2) xo_emit(", "); va_start(args, fmt); xo_emit_hv(NULL, fmt, args); va_end(args); if (*style == PRINT_STYLE_DASHED_2) xo_emit("\n"); } static void print_extra_status(int eletype, u_char *cstat, int style) { if (cstat[0] & 0x40) { sesutil_print(&style, "{e:predicted_failure/true} Predicted Failure"); } if (cstat[0] & 0x20) { sesutil_print(&style, "{e:disabled/true} Disabled"); } if (cstat[0] & 0x10) { sesutil_print(&style, "{e:swapped/true} Swapped"); } switch (eletype) { case ELMTYP_DEVICE: case ELMTYP_ARRAY_DEV: if (cstat[2] & 0x02) { sesutil_print(&style, "LED={q:led/locate}"); } if (cstat[2] & 0x20) { sesutil_print(&style, "LED={q:led/fault}"); } break; case ELMTYP_FAN: sesutil_print(&style, "Speed: {:speed/%d}{Uw:rpm}", (((0x7 & cstat[1]) << 8) + cstat[2]) * 10); break; case ELMTYP_THERM: if (cstat[2]) { sesutil_print(&style, "Temperature: {:temperature/%d}{Uw:C}", cstat[2] - TEMPERATURE_OFFSET); } else { sesutil_print(&style, "Temperature: -{q:temperature/reserved}"); } break; case ELMTYP_VOM: sesutil_print(&style, "Voltage: {:voltage/%.2f}{Uw:V}", be16dec(cstat + 2) / 100.0); break; } if (style) { xo_close_container("extra_status"); } } static int objmap(int argc, char **argv __unused) { encioc_string_t stri; encioc_elm_devnames_t e_devname; encioc_elm_status_t e_status; encioc_elm_desc_t e_desc; encioc_element_t *e_ptr; glob_t g; int fd; unsigned int j, nobj; size_t i; char str[32]; if (argc != 1) { usage(stderr, "map"); } /* Get the list of ses devices */ if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { globfree(&g); xo_errx(EXIT_FAILURE, "No SES devices found"); } xo_set_version(SESUTIL_XO_VERSION); xo_open_container("sesutil"); xo_open_list("enclosures"); for (i = 0; i < g.gl_pathc; i++) { /* ensure we only got numbers after ses */ if (strspn(g.gl_pathv[i] + 8, "0123456789") != strlen(g.gl_pathv[i] + 8)) { continue; } if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { /* * Don't treat non-access errors as critical if we are * accessing all devices */ if (errno == EACCES && g.gl_pathc > 1) { xo_err(EXIT_FAILURE, "unable to access SES device"); } xo_warn("unable to access SES device: %s", g.gl_pathv[i]); continue; } if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); } e_ptr = calloc(nobj, sizeof(encioc_element_t)); if (e_ptr == NULL) { close(fd); xo_err(EXIT_FAILURE, "calloc()"); } if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); } xo_open_instance("enclosures"); xo_emit("{t:enc/%s}:\n", g.gl_pathv[i] + 5); stri.bufsiz = sizeof(str); stri.buf = &str[0]; if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) xo_emit("\tEnclosure Name: {t:name/%s}\n", stri.buf); stri.bufsiz = sizeof(str); stri.buf = &str[0]; if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) xo_emit("\tEnclosure ID: {t:id/%s}\n", stri.buf); xo_open_list("elements"); for (j = 0; j < nobj; j++) { /* Get the status of the element */ memset(&e_status, 0, sizeof(e_status)); e_status.elm_idx = e_ptr[j].elm_idx; if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &e_status) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); } /* Get the description of the element */ memset(&e_desc, 0, sizeof(e_desc)); e_desc.elm_idx = e_ptr[j].elm_idx; e_desc.elm_desc_len = UINT16_MAX; e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); if (e_desc.elm_desc_str == NULL) { close(fd); xo_err(EXIT_FAILURE, "calloc()"); } if (ioctl(fd, ENCIOC_GETELMDESC, (caddr_t) &e_desc) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); } /* Get the device name(s) of the element */ memset(&e_devname, 0, sizeof(e_devname)); e_devname.elm_idx = e_ptr[j].elm_idx; e_devname.elm_names_size = 128; e_devname.elm_devnames = calloc(128, sizeof(char)); if (e_devname.elm_devnames == NULL) { close(fd); xo_err(EXIT_FAILURE, "calloc()"); } if (ioctl(fd, ENCIOC_GETELMDEVNAMES, (caddr_t) &e_devname) <0) { /* We don't care if this fails */ e_devname.elm_devnames[0] = '\0'; } xo_open_instance("elements"); xo_emit("\tElement {:id/%u}, Type: {:type/%s}\n", e_ptr[j].elm_idx, geteltnm(e_ptr[j].elm_type)); xo_emit("\t\tStatus: {:status/%s} ({q:status_code/0x%02x 0x%02x 0x%02x 0x%02x})\n", scode2ascii(e_status.cstat[0]), e_status.cstat[0], e_status.cstat[1], e_status.cstat[2], e_status.cstat[3]); if (e_desc.elm_desc_len > 0) { xo_emit("\t\tDescription: {:description/%s}\n", e_desc.elm_desc_str); } if (e_devname.elm_names_len > 0) { xo_emit("\t\tDevice Names: {:device_names/%s}\n", e_devname.elm_devnames); } print_extra_status(e_ptr[j].elm_type, e_status.cstat, PRINT_STYLE_DASHED); xo_close_instance("elements"); free(e_devname.elm_devnames); } xo_close_list("elements"); free(e_ptr); close(fd); } globfree(&g); xo_close_list("enclosures"); xo_close_container("sesutil"); xo_finish(); return (EXIT_SUCCESS); } /* * Get rid of the 'passN' devices, unless there's nothing else to show. */ static void skip_pass_devices(char *devnames, size_t devnameslen) { char *dev, devs[128], passes[128], *tmp; devs[0] = passes[0] = '\0'; tmp = devnames; while ((dev = strsep(&tmp, ",")) != NULL) { if (strncmp(dev, "pass", 4) == 0) { if (passes[0] != '\0') strlcat(passes, ",", sizeof(passes)); strlcat(passes, dev, sizeof(passes)); } else { if (devs[0] != '\0') strlcat(devs, ",", sizeof(devs)); strlcat(devs, dev, sizeof(devs)); } } strlcpy(devnames, devs, devnameslen); if (devnames[0] == '\0') strlcpy(devnames, passes, devnameslen); } static void fetch_device_details(char *devnames, char **model, char **serial, off_t *size) { char ident[DISK_IDENT_SIZE]; struct diocgattr_arg arg; char *tmp; off_t mediasize; int comma; int fd; comma = (int)strcspn(devnames, ","); asprintf(&tmp, "/dev/%.*s", comma, devnames); if (tmp == NULL) err(1, "asprintf"); fd = open(tmp, O_RDONLY); free(tmp); if (fd < 0) { /* * This can happen with a disk so broken it cannot * be probed by GEOM. */ *model = strdup("?"); *serial = strdup("?"); *size = -1; close(fd); return; } strlcpy(arg.name, "GEOM::descr", sizeof(arg.name)); arg.len = sizeof(arg.value.str); if (ioctl(fd, DIOCGATTR, &arg) == 0) *model = strdup(arg.value.str); else *model = NULL; if (ioctl(fd, DIOCGIDENT, ident) == 0) *serial = strdup(ident); else *serial = NULL; if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0) *size = mediasize; else *size = -1; close(fd); } static void show_device(int fd, int elm_idx, encioc_elm_status_t e_status, encioc_elm_desc_t e_desc) { encioc_elm_devnames_t e_devname; char *model, *serial; off_t size; /* Get the device name(s) of the element */ memset(&e_devname, 0, sizeof(e_devname)); e_devname.elm_idx = elm_idx; e_devname.elm_names_size = 128; e_devname.elm_devnames = calloc(128, sizeof(char)); if (e_devname.elm_devnames == NULL) { close(fd); xo_err(EXIT_FAILURE, "calloc()"); } if (ioctl(fd, ENCIOC_GETELMDEVNAMES, (caddr_t) &e_devname) < 0) { /* We don't care if this fails */ e_devname.elm_devnames[0] = '\0'; model = NULL; serial = NULL; size = -1; } else { skip_pass_devices(e_devname.elm_devnames, 128); fetch_device_details(e_devname.elm_devnames, &model, &serial, &size); } xo_open_instance("elements"); xo_emit("{e:type/device_slot}"); xo_emit("{d:description/%-15s} ", e_desc.elm_desc_len > 0 ? e_desc.elm_desc_str : "-"); xo_emit("{e:description/%-15s}", e_desc.elm_desc_len > 0 ? e_desc.elm_desc_str : ""); xo_emit("{d:device_names/%-7s} ", e_devname.elm_names_len > 0 ? e_devname.elm_devnames : "-"); xo_emit("{e:device_names/%s}", e_devname.elm_names_len > 0 ? e_devname.elm_devnames : ""); xo_emit("{d:model/%-25s} ", model ? model : "-"); xo_emit("{e:model/%s}", model ? model : ""); xo_emit("{d:serial/%-20s} ", serial != NULL ? serial : "-"); xo_emit("{e:serial/%s}", serial != NULL ? serial : ""); if ((e_status.cstat[0] & 0xf) == SES_OBJSTAT_OK && size >= 0) { xo_emit("{h,hn-1000:size/%ld}{e:status/%s}", size, scode2ascii(e_status.cstat[0])); } else { xo_emit("{:status/%s}", scode2ascii(e_status.cstat[0])); } print_extra_status(ELMTYP_ARRAY_DEV, e_status.cstat, PRINT_STYLE_CSV); xo_emit("\n"); xo_close_instance("elements"); free(e_devname.elm_devnames); } static void show_therm(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc) { if (e_desc.elm_desc_len <= 0) { /* We don't have a label to display; might as well skip it. */ return; } if (e_status.cstat[2] == 0) { /* No temperature to show. */ return; } xo_open_instance("elements"); xo_emit("{e:type/temperature_sensor}"); xo_emit("{:description/%s}: {:temperature/%d}{Uw:C}", e_desc.elm_desc_str, e_status.cstat[2] - TEMPERATURE_OFFSET); xo_close_instance("elements"); } static void show_vom(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc) { if (e_desc.elm_desc_len <= 0) { /* We don't have a label to display; might as well skip it. */ return; } if (e_status.cstat[2] == 0) { /* No voltage to show. */ return; } xo_open_instance("elements"); xo_emit("{e:type/voltage_sensor}"); xo_emit("{:description/%s}: {:voltage/%.2f}{Uw:V}", e_desc.elm_desc_str, be16dec(e_status.cstat + 2) / 100.0); xo_close_instance("elements"); } static int show(int argc, char **argv __unused) { encioc_string_t stri; encioc_elm_status_t e_status; encioc_elm_desc_t e_desc; encioc_element_t *e_ptr; glob_t g; elm_type_t prev_type; int fd; unsigned int j, nobj; size_t i; bool first_ses; char str[32]; if (argc != 1) { usage(stderr, "map"); } first_ses = true; /* Get the list of ses devices */ if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { globfree(&g); xo_errx(EXIT_FAILURE, "No SES devices found"); } xo_set_version(SESUTIL_XO_VERSION); xo_open_container("sesutil"); xo_open_list("enclosures"); for (i = 0; i < g.gl_pathc; i++) { /* ensure we only got numbers after ses */ if (strspn(g.gl_pathv[i] + 8, "0123456789") != strlen(g.gl_pathv[i] + 8)) { continue; } if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { /* * Don't treat non-access errors as critical if we are * accessing all devices */ if (errno == EACCES && g.gl_pathc > 1) { xo_err(EXIT_FAILURE, "unable to access SES device"); } xo_warn("unable to access SES device: %s", g.gl_pathv[i]); continue; } if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); } e_ptr = calloc(nobj, sizeof(encioc_element_t)); if (e_ptr == NULL) { close(fd); xo_err(EXIT_FAILURE, "calloc()"); } if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); } xo_open_instance("enclosures"); if (first_ses) first_ses = false; else xo_emit("\n"); xo_emit("{t:enc/%s}: ", g.gl_pathv[i] + 5); stri.bufsiz = sizeof(str); stri.buf = &str[0]; if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) xo_emit("<{t:name/%s}>; ", stri.buf); stri.bufsiz = sizeof(str); stri.buf = &str[0]; if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) xo_emit("ID: {t:id/%s}", stri.buf); xo_emit("\n"); xo_open_list("elements"); prev_type = -1; for (j = 0; j < nobj; j++) { /* Get the status of the element */ memset(&e_status, 0, sizeof(e_status)); e_status.elm_idx = e_ptr[j].elm_idx; if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &e_status) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); } /* * Skip "Unsupported" elements; those usually precede * the actual device entries and are not particularly * interesting. */ if (e_status.cstat[0] == SES_OBJSTAT_UNSUPPORTED) continue; /* Get the description of the element */ memset(&e_desc, 0, sizeof(e_desc)); e_desc.elm_idx = e_ptr[j].elm_idx; e_desc.elm_desc_len = UINT16_MAX; e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); if (e_desc.elm_desc_str == NULL) { close(fd); xo_err(EXIT_FAILURE, "calloc()"); } if (ioctl(fd, ENCIOC_GETELMDESC, (caddr_t) &e_desc) < 0) { close(fd); xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); } switch (e_ptr[j].elm_type) { case ELMTYP_DEVICE: case ELMTYP_ARRAY_DEV: if (e_ptr[j].elm_type != prev_type) xo_emit("Desc Dev Model Ident Size/Status\n"); show_device(fd, e_ptr[j].elm_idx, e_status, e_desc); prev_type = e_ptr[j].elm_type; break; case ELMTYP_THERM: if (e_ptr[j].elm_type != prev_type) xo_emit("\nTemperatures: "); else xo_emit(", "); prev_type = e_ptr[j].elm_type; show_therm(e_status, e_desc); break; case ELMTYP_VOM: if (e_ptr[j].elm_type != prev_type) xo_emit("\nVoltages: "); else xo_emit(", "); prev_type = e_ptr[j].elm_type; show_vom(e_status, e_desc); break; default: /* * Ignore stuff not interesting to the user. */ break; } } if (prev_type != (elm_type_t)-1 && prev_type != ELMTYP_DEVICE && prev_type != ELMTYP_ARRAY_DEV) xo_emit("\n"); xo_close_list("elements"); free(e_ptr); close(fd); } globfree(&g); xo_close_list("enclosures"); xo_close_container("sesutil"); xo_finish(); return (EXIT_SUCCESS); } static int encstatus(int argc, char **argv __unused) { glob_t g; int fd, status; size_t i, e; u_char estat; status = 0; if (argc != 1) { usage(stderr, "status"); } /* Get the list of ses devices */ if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { globfree(&g); xo_errx(EXIT_FAILURE, "No SES devices found"); } xo_set_version(SESUTIL_XO_VERSION); xo_open_container("sesutil"); xo_open_list("enclosures"); for (i = 0; i < g.gl_pathc; i++) { /* ensure we only got numbers after ses */ if (strspn(g.gl_pathv[i] + 8, "0123456789") != strlen(g.gl_pathv[i] + 8)) { continue; } if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { /* * Don't treat non-access errors as critical if we are * accessing all devices */ if (errno == EACCES && g.gl_pathc > 1) { xo_err(EXIT_FAILURE, "unable to access SES device"); } xo_warn("unable to access SES device: %s", g.gl_pathv[i]); continue; } if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) { xo_err(EXIT_FAILURE, "ENCIOC_GETENCSTAT"); close(fd); } xo_open_instance("enclosures"); xo_emit("{:enc/%s}: ", g.gl_pathv[i] + 5); e = 0; if (estat == 0) { if (status == 0) { status = 1; } xo_emit("{q:status/OK}"); } else { if (estat & SES_ENCSTAT_INFO) { xo_emit("{lq:status/INFO}"); e++; } if (estat & SES_ENCSTAT_NONCRITICAL) { if (e) xo_emit(","); xo_emit("{lq:status/NONCRITICAL}"); e++; } if (estat & SES_ENCSTAT_CRITICAL) { if (e) xo_emit(","); xo_emit("{lq:status/CRITICAL}"); e++; status = -1; } if (estat & SES_ENCSTAT_UNRECOV) { if (e) xo_emit(","); xo_emit("{lq:status/UNRECOV}"); e++; status = -1; } } xo_close_instance("enclosures"); xo_emit("\n"); close(fd); } globfree(&g); xo_close_list("enclosures"); xo_close_container("sesutil"); xo_finish(); if (status == 1) { return (EXIT_SUCCESS); } else { return (EXIT_FAILURE); } } int main(int argc, char **argv) { int i, ch; struct command *cmd = NULL; argc = xo_parse_args(argc, argv); if (argc < 0) exit(1); uflag = "/dev/ses[0-9]*"; while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) { switch (ch) { case 'u': uflag = optarg; break; case '?': default: usage(stderr, NULL); } } argc -= optind; argv += optind; if (argc < 1) { warnx("Missing command"); usage(stderr, NULL); } for (i = 0; i < nbcmds; i++) { if (strcmp(argv[0], cmds[i].name) == 0) { cmd = &cmds[i]; break; } } if (cmd == NULL) { warnx("unknown command %s", argv[0]); usage(stderr, NULL); } return (cmd->exec(argc, argv)); }