diff options
author | Alexander Motin <mav@FreeBSD.org> | 2022-01-13 18:45:28 +0000 |
---|---|---|
committer | Alexander Motin <mav@FreeBSD.org> | 2022-01-13 18:57:35 +0000 |
commit | 2e19fae49fd4ab2360971463cee99a62198973b1 (patch) | |
tree | 6d439c8efde8b86061b6bbfc8402c8201a7a4038 /sys/cam | |
parent | 1d41a4940463429ec68e8baf9edf2ce98a5938c9 (diff) | |
download | src-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.h | 44 |
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; |