aboutsummaryrefslogtreecommitdiff
path: root/sys/cam
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2022-01-13 18:45:28 +0000
committerAlexander Motin <mav@FreeBSD.org>2022-01-13 18:57:35 +0000
commit2e19fae49fd4ab2360971463cee99a62198973b1 (patch)
tree6d439c8efde8b86061b6bbfc8402c8201a7a4038 /sys/cam
parent1d41a4940463429ec68e8baf9edf2ce98a5938c9 (diff)
downloadsrc-2e19fae49fd4ab2360971463cee99a62198973b1.tar.gz
src-2e19fae49fd4ab2360971463cee99a62198973b1.zip
sesutil: Avoid setting reserved bits.
Weird side of SES specification is that some bits have different meaning or semantics in status and control pages. This patch fixes non-zero writes into reserved fields, that caused errors on some enclosures when trying to control locate/fault LEDs, keeping other bits unchanged. MFC after: 2 weeks Sposonred by: iXsystems, Inc.
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/scsi/scsi_ses.h44
1 files changed, 44 insertions, 0 deletions
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
@@ -2058,6 +2058,50 @@ union ses_status_element {
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;