diff --git a/smartmontools/ChangeLog b/smartmontools/ChangeLog index 812275209d5dbe26ef92ce93d2033f3526d42534..65fcf940a816736abd704eb08668f66dd6540271 100644 --- a/smartmontools/ChangeLog +++ b/smartmontools/ChangeLog @@ -1,5 +1,14 @@ $Id$ +2022-02-27 Douglas Gilbert <dgilbert@interlog.com> + + scsicmds.cpp scsiprint.cpp and others: route all SCSI pass + through calls in scsicmds.cpp via the renamed function: + scsi_pass_through_yield_sense() which will absorb up to + three pending Unit Attentions [see ticket 179]. Use + aggregate initialization (e.g. 'uint8_t b[32] = {};') to + bypass the need for many memset() calls. + 2022-02-26 Douglas Gilbert <dgilbert@interlog.com> ataprint.cpp: add suggestion when 'Read Device Identity @@ -143,7 +152,7 @@ $Id$ scsiprint.cpp: my tape drive gives a nuisance TapeAlert warning after each power cycle. With '-xj' output this - leads a a JSON array with a lot of 'null' entries. Change + leads a JSON array with a lot of 'null' entries. Change the JSON indexing so it is compact and add a 'descriptor_idx' attribute if the position is important to the end user. In the case of TapeAlert the relative @@ -288,7 +297,7 @@ $Id$ 2021-12-21 Douglas Gilbert <dgilbert@interlog.com> scsiprint.cpp: fix listing of subpages as proposed by Yannick - Hemery <yannick.hemery@corp.ovh.com> in in smt's github pull/122 + Hemery <yannick.hemery@corp.ovh.com> in smt's github pull/122 2021-12-18 Christian Franke <franke@computer.org> diff --git a/smartmontools/dev_areca.cpp b/smartmontools/dev_areca.cpp index c454d4f4a45488bc30720ba1a64f4aef4191e051..784e4e7b6e3b18fc457b8fa7fbcdfdae32cf7d95 100644 --- a/smartmontools/dev_areca.cpp +++ b/smartmontools/dev_areca.cpp @@ -120,11 +120,11 @@ int generic_areca_device::arcmsr_command_handler(unsigned long arcmsr_cmd, unsig int ioctlreturn = 0; sSRB_BUFFER sBuf; - struct scsi_cmnd_io iop; + struct scsi_cmnd_io iop = {}; int dir = DXFER_TO_DEVICE; - uint8_t cdb[10]={0}; - uint8_t sense[32]={0}; + uint8_t cdb[10]={}; + uint8_t sense[32]={}; unsigned char *areca_return_packet; int total = 0; @@ -133,7 +133,6 @@ int generic_areca_device::arcmsr_command_handler(unsigned long arcmsr_cmd, unsig unsigned char *ptr = &return_buff[0]; memset((unsigned char *)&sBuf, 0, sizeof(sBuf)); - memset(&iop, 0, sizeof(iop)); sBuf.srbioctl.HeaderLength = sizeof(sARCMSR_IO_HDR); memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR)); diff --git a/smartmontools/dev_jmb39x_raid.cpp b/smartmontools/dev_jmb39x_raid.cpp index 67737891bcbf1c665a9c6870d446743a713f7e07..dd768ecaa85e20f82d2414f3b5a0225e9b9a1389 100644 --- a/smartmontools/dev_jmb39x_raid.cpp +++ b/smartmontools/dev_jmb39x_raid.cpp @@ -271,7 +271,8 @@ static int scsi_get_lba_size(scsi_device * scsidev) static bool scsi_read_lba8(scsi_device * scsidev, uint8_t lba8, uint8_t (& data)[512]) { - struct scsi_cmnd_io io_hdr; memset(&io_hdr, 0, sizeof(io_hdr)); + struct scsi_cmnd_io io_hdr = {}; + io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = 512; io_hdr.dxferp = data; @@ -288,7 +289,8 @@ static bool scsi_read_lba8(scsi_device * scsidev, uint8_t lba8, uint8_t (& data) static bool scsi_write_lba8(scsi_device * scsidev, uint8_t lba8, const uint8_t (& data)[512]) { - struct scsi_cmnd_io io_hdr; memset(&io_hdr, 0, sizeof(io_hdr)); + struct scsi_cmnd_io io_hdr = {}; + io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = 512; io_hdr.dxferp = const_cast<uint8_t *>(data); diff --git a/smartmontools/scsiata.cpp b/smartmontools/scsiata.cpp index bb0d7c5d3607bcde4d97ac2e66d3106ca2d81ac8..24af7f1214def779431f54c6de3a8e8ba2b1de2a 100644 --- a/smartmontools/scsiata.cpp +++ b/smartmontools/scsiata.cpp @@ -256,11 +256,11 @@ bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) ) return false; - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; struct sg_scsi_sense_hdr ssh; - unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN]; - unsigned char sense[32]; + unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN] = {}; + unsigned char sense[32] = {}; const unsigned char * ardp; int ard_len, have_sense; int extend = 0; @@ -272,9 +272,6 @@ bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) int passthru_size = DEF_SAT_ATA_PASSTHRU_SIZE; bool sense_descriptor = true; - memset(cdb, 0, sizeof(cdb)); - memset(sense, 0, sizeof(sense)); - // Set data direction // TODO: This works only for commands where sector_count holds count! switch (in.direction) { @@ -346,7 +343,6 @@ bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) cdb[14] = lo.command; } - memset(&io_hdr, 0, sizeof(io_hdr)); if (0 == t_length) { io_hdr.dxfer_dir = DXFER_NONE; io_hdr.dxfer_len = 0; @@ -639,9 +635,9 @@ usbcypress_device::~usbcypress_device() #define USBCYPRESS_PASSTHROUGH_LEN 16 int usbcypress_device::ata_command_interface(smart_command_set command, int select, char *data) { - struct scsi_cmnd_io io_hdr; - unsigned char cdb[USBCYPRESS_PASSTHROUGH_LEN]; - unsigned char sense[32]; + struct scsi_cmnd_io io_hdr = {}; + unsigned char cdb[USBCYPRESS_PASSTHROUGH_LEN] = {}; + unsigned char sense[32] = {}; int copydata = 0; int outlen = 0; int ck_cond = 0; /* set to 1 to read register(s) back */ @@ -656,9 +652,6 @@ int usbcypress_device::ata_command_interface(smart_command_set command, int sele int lba_high = 0; int passthru_size = USBCYPRESS_PASSTHROUGH_LEN; - memset(cdb, 0, sizeof(cdb)); - memset(sense, 0, sizeof(sense)); - ata_command = ATA_SMART_CMD; switch (command) { case CHECK_POWER_MODE: @@ -766,7 +759,6 @@ int usbcypress_device::ata_command_interface(smart_command_set command, int sele cdb[10] = lba_high; cdb[12] = ata_command; - memset(&io_hdr, 0, sizeof(io_hdr)); if (0 == t_length) { io_hdr.dxfer_dir = DXFER_NONE; io_hdr.dxfer_len = 0; @@ -961,8 +953,7 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou if (m_port < 0) return set_err(EIO, "Unknown JMicron port"); - scsi_cmnd_io io_hdr; - memset(&io_hdr, 0, sizeof(io_hdr)); + scsi_cmnd_io io_hdr = {}; bool rwbit = true; unsigned char smart_status = 0xff; @@ -1082,8 +1073,7 @@ bool usbjmicron_device::get_registers(unsigned short addr, cdb[12] = 0x06; cdb[13] = 0x7b; - scsi_cmnd_io io_hdr; - memset(&io_hdr, 0, sizeof(io_hdr)); + scsi_cmnd_io io_hdr = {}; io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = size; io_hdr.dxferp = buf; @@ -1142,8 +1132,7 @@ bool usbprolific_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & o ) return false; - scsi_cmnd_io io_hdr; - memset(&io_hdr, 0, sizeof(io_hdr)); + scsi_cmnd_io io_hdr = {}; unsigned char cmd_rw = 0x10; // Read switch (in.direction) { @@ -1280,12 +1269,11 @@ bool usbsunplus_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou ) return false; - scsi_cmnd_io io_hdr; + scsi_cmnd_io io_hdr = {}; unsigned char cdb[12]; if (in.in_regs.is_48bit_cmd()) { // Set "previous" registers - memset(&io_hdr, 0, sizeof(io_hdr)); io_hdr.dxfer_dir = DXFER_NONE; cdb[ 0] = 0xf8; diff --git a/smartmontools/scsicmds.cpp b/smartmontools/scsicmds.cpp index 8a1d46ac4d6129cdbad663bf77f97f1da26182d3..b90b913461a780c2598c9e4d39dd22b64197895c 100644 --- a/smartmontools/scsicmds.cpp +++ b/smartmontools/scsicmds.cpp @@ -49,8 +49,8 @@ supported_vpd_pages * supported_vpd_pages_p = NULL; supported_vpd_pages::supported_vpd_pages(scsi_device * device) : num_valid(0) { - unsigned char b[0xfc]; /* pre SPC-3 INQUIRY max response size */ - memset(b, 0, sizeof(b)); + unsigned char b[0xfc] = {}; /* pre SPC-3 INQUIRY max response size */ + if (device && (0 == scsiInquiryVpd(device, SCSI_VPD_SUPPORTED_VPD_PAGES, b, sizeof(b)))) { num_valid = sg_get_unaligned_be16(b + 2); @@ -232,7 +232,8 @@ static const char * vendor_specific = "<vendor specific>"; const char * scsi_get_opcode_name(uint8_t opcode) { - int len = sizeof(opcode_name_arr) / sizeof(opcode_name_arr[0]); + static const int len = sizeof(opcode_name_arr) / + sizeof(opcode_name_arr[0]); if (opcode >= 0xc0) return vendor_specific; @@ -274,6 +275,7 @@ scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo) switch (sinfo->sense_key) { case SCSI_SK_NO_SENSE: case SCSI_SK_RECOVERED_ERR: + case SCSI_SK_COMPLETED: return SIMPLE_NO_ERROR; case SCSI_SK_NOT_READY: if (SCSI_ASC_NO_MEDIUM == sinfo->asc) @@ -301,6 +303,10 @@ scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo) return SIMPLE_ERR_TRY_AGAIN; case SCSI_SK_ABORTED_COMMAND: return SIMPLE_ERR_ABORTED_COMMAND; + case SCSI_SK_DATA_PROTECT: + return SIMPLE_ERR_PROTECTION; + case SCSI_SK_MISCOMPARE: + return SIMPLE_ERR_MISCOMPARE; default: return SIMPLE_ERR_UNKNOWN; } @@ -336,6 +342,10 @@ scsiErrString(int scsiErr) return "unknown error (unexpected sense key)"; case SIMPLE_ERR_ABORTED_COMMAND: return "aborted command"; + case SIMPLE_ERR_PROTECTION: + return "data protection error"; + case SIMPLE_ERR_MISCOMPARE: + return "miscompare"; default: return "unknown error"; } @@ -550,9 +560,9 @@ scsiLogSense(scsi_device * device, int pagenum, int subpagenum, uint8_t *pBuf, int bufLen, int known_resp_len) { int pageLen; - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; if (known_resp_len > bufLen) @@ -569,8 +579,6 @@ scsiLogSense(scsi_device * device, int pagenum, int subpagenum, uint8_t *pBuf, else memset(pBuf, 0, pageLen); - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = pageLen; io_hdr.dxferp = pBuf; @@ -584,9 +592,8 @@ scsiLogSense(scsi_device * device, int pagenum, int subpagenum, uint8_t *pBuf, io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); int res; if ((res = scsiSimpleSenseFilter(&sinfo))) return res; @@ -619,9 +626,8 @@ scsiLogSense(scsi_device * device, int pagenum, int subpagenum, uint8_t *pBuf, io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); int status = scsiSimpleSenseFilter(&sinfo); if (0 != status) return status; @@ -642,13 +648,11 @@ int scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum, int subpagenum, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -663,9 +667,8 @@ scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum, io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -677,15 +680,13 @@ int scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[6]; + uint8_t cdb[6] = {}; uint8_t sense[32]; if ((bufLen < 0) || (bufLen > 255)) return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -699,16 +700,9 @@ scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc, io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); int status = scsiSimpleSenseFilter(&sinfo); - if (SIMPLE_ERR_TRY_AGAIN == status) { - if (!device->scsi_pass_through(&io_hdr)) - return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); - status = scsiSimpleSenseFilter(&sinfo); - } if ((0 == status) && (ALL_MODE_PAGES != pagenum)) { int offset; @@ -731,9 +725,9 @@ scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc, int scsiModeSelect(scsi_device * device, int sp, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[6]; + uint8_t cdb[6] = {}; uint8_t sense[32]; int pg_offset, pg_len, hdr_plus_1_pg; @@ -746,8 +740,6 @@ scsiModeSelect(scsi_device * device, int sp, uint8_t *pBuf, int bufLen) return -EINVAL; pBuf[0] = 0; /* Length of returned mode sense data reserved for SELECT */ pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */ - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = hdr_plus_1_pg; io_hdr.dxferp = pBuf; @@ -760,9 +752,8 @@ scsiModeSelect(scsi_device * device, int sp, uint8_t *pBuf, int bufLen) io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -774,13 +765,11 @@ int scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -794,16 +783,9 @@ scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc, io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); int status = scsiSimpleSenseFilter(&sinfo); - if (SIMPLE_ERR_TRY_AGAIN == status) { - if (!device->scsi_pass_through(&io_hdr)) - return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); - status = scsiSimpleSenseFilter(&sinfo); - } if ((0 == status) && (ALL_MODE_PAGES != pagenum)) { int offset; @@ -826,9 +808,9 @@ scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc, int scsiModeSelect10(scsi_device * device, int sp, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; int pg_offset, pg_len, hdr_plus_1_pg; @@ -842,8 +824,6 @@ scsiModeSelect10(scsi_device * device, int sp, uint8_t *pBuf, int bufLen) pBuf[0] = 0; pBuf[1] = 0; /* Length of returned mode sense data reserved for SELECT */ pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */ - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = hdr_plus_1_pg; io_hdr.dxferp = pBuf; @@ -857,9 +837,8 @@ scsiModeSelect10(scsi_device * device, int sp, uint8_t *pBuf, int bufLen) io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -870,14 +849,12 @@ int scsiStdInquiry(scsi_device * device, uint8_t *pBuf, int bufLen) { struct scsi_sense_disect sinfo; - struct scsi_cmnd_io io_hdr; - uint8_t cdb[6]; + struct scsi_cmnd_io io_hdr = {}; + uint8_t cdb[6] = {}; uint8_t sense[32]; if ((bufLen < 0) || (bufLen > 1023)) return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -889,9 +866,8 @@ scsiStdInquiry(scsi_device * device, uint8_t *pBuf, int bufLen) io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -902,9 +878,9 @@ scsiStdInquiry(scsi_device * device, uint8_t *pBuf, int bufLen) int scsiInquiryVpd(scsi_device * device, int vpd_page, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[6]; + uint8_t cdb[6] = {}; uint8_t sense[32]; int res; @@ -917,8 +893,6 @@ scsiInquiryVpd(scsi_device * device, int vpd_page, uint8_t *pBuf, int bufLen) if ((bufLen < 0) || (bufLen > 1023)) return -EINVAL; try_again: - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); if (bufLen > 1) pBuf[1] = 0x0; io_hdr.dxfer_dir = DXFER_FROM_DEVICE; @@ -934,9 +908,8 @@ try_again: io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); if ((SCSI_STATUS_CHECK_CONDITION == io_hdr.scsi_status) && (SCSI_SK_ILLEGAL_REQUEST == sinfo.sense_key) && (SCSI_ASC_INVALID_FIELD == sinfo.asc) && @@ -963,14 +936,13 @@ try_again: int scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info) { - struct scsi_cmnd_io io_hdr; - uint8_t cdb[6]; + struct scsi_cmnd_io io_hdr = {}; + uint8_t cdb[6] = {}; uint8_t sense[32]; - uint8_t buff[18]; - const int sz_buff = sizeof(buff); + uint8_t buff[18] = {}; + bool ok; + static const int sz_buff = sizeof(buff); - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = sz_buff; io_hdr.dxferp = buff; @@ -982,7 +954,13 @@ scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info) io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (sense_info) + ok = scsi_pass_through_yield_sense(device, &io_hdr, *sense_info); + else { + scsi_sense_disect dummy_sense; + ok = scsi_pass_through_yield_sense(device, &io_hdr, dummy_sense); + } + if (! ok) return -device->get_errno(); if (sense_info) { uint8_t resp_code = buff[0] & 0x7f; @@ -1051,12 +1029,11 @@ scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info) int scsiSetPowerCondition(scsi_device * device, int power_cond, int pcond_modifier) { - struct scsi_cmnd_io io_hdr; - uint8_t cdb[6]; + struct scsi_cmnd_io io_hdr = {}; + struct scsi_sense_disect sinfo; + uint8_t cdb[6] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_NONE; cdb[0] = START_STOP_UNIT; /* IMMED bit (cdb[1] = 0x1) not set, therefore will wait */ @@ -1071,10 +1048,10 @@ scsiSetPowerCondition(scsi_device * device, int power_cond, int pcond_modifier) io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - return 0; + return scsiSimpleSenseFilter(&sinfo); } /* SEND DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if command @@ -1084,13 +1061,11 @@ int scsiSendDiagnostic(scsi_device * device, int functioncode, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[6]; + uint8_t cdb[6] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = bufLen ? DXFER_TO_DEVICE: DXFER_NONE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -1109,22 +1084,20 @@ scsiSendDiagnostic(scsi_device * device, int functioncode, uint8_t *pBuf, /* worst case is an extended foreground self test on a big disk */ io_hdr.timeout = SCSI_TIMEOUT_SELF_TEST; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } /* TEST UNIT READY command. SPC-3 section 6.33 (rev 22a) */ static int -_testunitready(scsi_device * device, struct scsi_sense_disect * sinfo) +_testunitready(scsi_device * device, struct scsi_sense_disect * sinfop) { - struct scsi_cmnd_io io_hdr; - uint8_t cdb[6]; + struct scsi_cmnd_io io_hdr = {}; + bool ok; + uint8_t cdb[6] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_NONE; io_hdr.dxfer_len = 0; io_hdr.dxferp = NULL; @@ -1135,9 +1108,14 @@ _testunitready(scsi_device * device, struct scsi_sense_disect * sinfo) io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) - return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, sinfo); + if (sinfop) + ok = scsi_pass_through_yield_sense(device, &io_hdr, *sinfop); + else { + struct scsi_sense_disect dummy_si; + ok = scsi_pass_through_yield_sense(device, &io_hdr, dummy_si); + } + if (! ok) + return -device->get_errno(); return 0; } @@ -1152,15 +1130,7 @@ scsiTestUnitReady(scsi_device * device) status = _testunitready(device, &sinfo); if (0 != status) return status; - status = scsiSimpleSenseFilter(&sinfo); - if (SIMPLE_ERR_TRY_AGAIN == status) { - /* power on reset, media changed, ok ... try again */ - status = _testunitready(device, &sinfo); - if (0 != status) - return status; - status = scsiSimpleSenseFilter(&sinfo); - } - return status; + return scsiSimpleSenseFilter(&sinfo); } /* READ DEFECT (10) command. Returns 0 if ok, 1 if NOT READY, 2 if @@ -1171,13 +1141,11 @@ int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -1191,9 +1159,8 @@ scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) - return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) + return -device->get_errno(); /* Look for "(Primary|Grown) defect list not found" */ if ((sinfo.resp_code >= 0x70) && (0x1c == sinfo.asc)) return 101; @@ -1208,13 +1175,11 @@ int scsiReadDefect12(scsi_device * device, int req_plist, int req_glist, int dl_format, int addrDescIndex, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[12]; + uint8_t cdb[12] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -1229,36 +1194,54 @@ scsiReadDefect12(scsi_device * device, int req_plist, int req_glist, io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); /* Look for "(Primary|Grown) defect list not found" */ if ((sinfo.resp_code >= 0x70) && (0x1c == sinfo.asc)) return 101; return scsiSimpleSenseFilter(&sinfo); } -/* Call scsi_pass_through, and retry only if a UNIT_ATTENTION is raised. - * As for scsi_pass_through, return false on error. */ +/* Call scsi_pass_through, and retry only if a UNIT_ATTENTION (UA) is raised. + * When false returned, the caller should invoke device->get_error(). + * When true returned, the caller should check sinfo. + * All SCSI commands can receive pending Unit Attentions, apart from: + * INQUIRY, REPORT LUNS, REQUEST SENSE and NOTIFY DATA TRANSFER DEVICE + * (ADC-3 spec). The first three are the important ones. */ bool -scsi_pass_through_with_retry(scsi_device * device, scsi_cmnd_io * iop) +scsi_pass_through_yield_sense(scsi_device * device, scsi_cmnd_io * iop, + /* OUT param */ scsi_sense_disect & sinfo) { - scsi_sense_disect sinfo; + int k; + uint32_t opcode = (iop->cmnd_len > 0) ? iop->cmnd[0] : 0xffff; - if (!device->scsi_pass_through(iop)) - return false; + if (scsi_debugmode > 2) + pout("%s: opcode: 0x%x\n", __func__, opcode); - scsi_do_sense_disect(iop, &sinfo); + if (! device->scsi_pass_through(iop)) + return false; // this will be missing device, timeout, etc - int err = scsiSimpleSenseFilter(&sinfo); - if (SIMPLE_ERR_TRY_AGAIN != err) - return true; + scsi_do_sense_disect(iop, &sinfo); - if (scsi_debugmode > 0) - pout("%s failed with errno=%d [%s], retrying\n", - __func__, err, scsiErrString(err)); + switch (opcode) { + case INQUIRY: + case REPORT_LUNS: + case REQUEST_SENSE: + return true; /* in these cases, it shouldn't be a UA */ + default: + break; /* continue on for all other SCSI commands to check for UA */ + } - return device->scsi_pass_through(iop); + /* There can be multiple UAs pending, allow for three */ + for (k = 0; (k < 3) && (SCSI_SK_UNIT_ATTENTION == sinfo.sense_key); ++k) { + if (scsi_debugmode > 0) + pout("%s Unit Attention %d: asc/ascq=0x%x,0x%x, retrying\n", + __func__, k + 1, sinfo.asc, sinfo.ascq); + if (! device->scsi_pass_through(iop)) + return false; + scsi_do_sense_disect(iop, &sinfo); + } + return true; } /* READ CAPACITY (10) command. Returns 0 if ok, 1 if NOT READY, 2 if @@ -1269,15 +1252,12 @@ scsiReadCapacity10(scsi_device * device, unsigned int * last_lbap, unsigned int * lb_sizep) { int res; - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; - uint8_t resp[8]; + uint8_t resp[8] = {}; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - memset(resp, 0, sizeof(resp)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = sizeof(resp); io_hdr.dxferp = resp; @@ -1288,9 +1268,8 @@ scsiReadCapacity10(scsi_device * device, unsigned int * last_lbap, io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!scsi_pass_through_with_retry(device, &io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); res = scsiSimpleSenseFilter(&sinfo); if (res) return res; @@ -1307,13 +1286,11 @@ scsiReadCapacity10(scsi_device * device, unsigned int * last_lbap, int scsiReadCapacity16(scsi_device * device, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[16]; + uint8_t cdb[16] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -1326,9 +1303,8 @@ scsiReadCapacity16(scsi_device * device, uint8_t *pBuf, int bufLen) io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!scsi_pass_through_with_retry(device, &io_hdr)) + if (!scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -1621,10 +1597,9 @@ scsiSetExceptionControlAndWarning(scsi_device * device, int enabled, int scsiGetTemp(scsi_device * device, uint8_t *currenttemp, uint8_t *triptemp) { - uint8_t tBuf[252]; + uint8_t tBuf[252] = {}; int err; - memset(tBuf, 0, sizeof(tBuf)); if ((err = scsiLogSense(device, TEMPERATURE_LPAGE, 0, tBuf, sizeof(tBuf), 0))) { *currenttemp = 0; @@ -1647,17 +1622,16 @@ scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage, uint8_t *asc, uint8_t *ascq, uint8_t *currenttemp, uint8_t *triptemp) { - uint8_t tBuf[252]; + uint8_t tBuf[252] = {}; struct scsi_sense_disect sense_info; int err; uint8_t currTemp, trTemp; + memset(&sense_info, 0, sizeof(sense_info)); *asc = 0; *ascq = 0; *currenttemp = 0; *triptemp = 0; - memset(tBuf,0,sizeof(tBuf)); // need to clear stack space of junk - memset(&sense_info, 0, sizeof(sense_info)); if (hasIELogPage) { if ((err = scsiLogSense(device, IE_LPAGE, 0, tBuf, sizeof(tBuf), 0))) { @@ -1947,8 +1921,8 @@ static const char * TapeAlertsMessageTable[]= { const char * scsiTapeAlertsTapeDevice(unsigned short code) { - const int num = sizeof(TapeAlertsMessageTable) / - sizeof(TapeAlertsMessageTable[0]); + static const int num = sizeof(TapeAlertsMessageTable) / + sizeof(TapeAlertsMessageTable[0]); return (code < num) ? TapeAlertsMessageTable[code] : "Unknown Alert"; } @@ -2095,8 +2069,8 @@ static const char * ChangerTapeAlertsMessageTable[]= { const char * scsiTapeAlertsChangerDevice(unsigned short code) { - const int num = sizeof(ChangerTapeAlertsMessageTable) / - sizeof(ChangerTapeAlertsMessageTable[0]); + static const int num = sizeof(ChangerTapeAlertsMessageTable) / + sizeof(ChangerTapeAlertsMessageTable[0]); return (code < num) ? ChangerTapeAlertsMessageTable[code] : "Unknown Alert"; @@ -2333,9 +2307,8 @@ scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec, int modese_len) { int err, offset; - uint8_t buff[64]; + uint8_t buff[64] = {}; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0, MPAGE_CONTROL_CURRENT, @@ -2426,7 +2399,7 @@ scsiDecodeNonMediumErrPage(unsigned char *resp, memset(nmep, 0, sizeof(*nmep)); int num = sg_get_unaligned_be16(resp + 2); unsigned char * ucp = &resp[0] + 4; - int szof = sizeof(nmep->counterPC0); + static int szof = sizeof(nmep->counterPC0); while (num > 3) { int pc = sg_get_unaligned_be16(ucp + 0); int pl = ucp[3] + 4; @@ -2563,10 +2536,9 @@ int scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current) { int err, offset; - uint8_t buff[64]; + uint8_t buff[64] = {}; int pc = current ? MPAGE_CONTROL_CURRENT : MPAGE_CONTROL_DEFAULT; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0, pc, buff, sizeof(buff)))) { @@ -2602,10 +2574,9 @@ scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp, int * haw_zbcp) { int err, offset; - uint8_t buff[64]; + uint8_t buff[64] = {}; int pc = MPAGE_CONTROL_DEFAULT; - memset(buff, 0, sizeof(buff)); if ((0 == scsiInquiryVpd(device, SCSI_VPD_BLOCK_DEVICE_CHARACTERISTICS, buff, sizeof(buff))) && ((sg_get_unaligned_be16(buff + 2)) > 2)) { @@ -2648,11 +2619,11 @@ scsiGetSetCache(scsi_device * device, int modese_len, short int * wcep, short int * rcdp) { int err, offset, resp_len, sp; - uint8_t buff[64], ch_buff[64]; + uint8_t buff[64] = {}; + uint8_t ch_buff[64]; short set_wce = *wcep; short set_rcd = *rcdp; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { err = scsiModeSense(device, CACHING_PAGE, 0, MPAGE_CONTROL_CURRENT, buff, sizeof(buff)); @@ -2751,10 +2722,9 @@ int scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len) { int err, offset, resp_len, sp; - uint8_t buff[64]; + uint8_t buff[64] = {}; uint8_t ch_buff[64]; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0, MPAGE_CONTROL_CURRENT, @@ -2822,9 +2792,8 @@ int scsiFetchTransportProtocol(scsi_device * device, int modese_len) { int err, offset; - uint8_t buff[64]; + uint8_t buff[64] {}; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { if ((err = scsiModeSense(device, PROTOCOL_SPECIFIC_PORT_PAGE, 0, MPAGE_CONTROL_CURRENT, diff --git a/smartmontools/scsicmds.h b/smartmontools/scsicmds.h index f844230de85f467c639f72d10f837f3f02dac002..a0b73932fccecbb22163d3ef719fca2e9d9f88ae 100644 --- a/smartmontools/scsicmds.h +++ b/smartmontools/scsicmds.h @@ -305,7 +305,10 @@ Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */ #define SCSI_SK_HARDWARE_ERROR 0x4 #define SCSI_SK_ILLEGAL_REQUEST 0x5 #define SCSI_SK_UNIT_ATTENTION 0x6 +#define SCSI_SK_DATA_PROTECT 0x7 #define SCSI_SK_ABORTED_COMMAND 0xb +#define SCSI_SK_MISCOMPARE 0xe +#define SCSI_SK_COMPLETED 0xf /* defines for useful Additional Sense Codes (ASCs) */ #define SCSI_ASC_NOT_READY 0x4 /* more info in ASCQ code */ @@ -331,6 +334,8 @@ Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */ #define SIMPLE_ERR_MEDIUM_HARDWARE 9 /* medium or hardware error */ #define SIMPLE_ERR_UNKNOWN 10 /* unknown sense value */ #define SIMPLE_ERR_ABORTED_COMMAND 11 /* probably transport error */ +#define SIMPLE_ERR_PROTECTION 12 /* data protect sense key */ +#define SIMPLE_ERR_MISCOMPARE 13 /* from VERIFY commands */ /* defines for functioncode parameter in SENDDIAGNOSTIC function */ @@ -450,7 +455,8 @@ int scsiSetPowerCondition(scsi_device * device, int power_cond, int scsiSendDiagnostic(scsi_device * device, int functioncode, uint8_t *pBuf, int bufLen); -bool scsi_pass_through_with_retry(scsi_device * device, scsi_cmnd_io * iop); +bool scsi_pass_through_yield_sense(scsi_device * device, scsi_cmnd_io * iop, + struct scsi_sense_disect & sinfo); int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format, uint8_t *pBuf, int bufLen); diff --git a/smartmontools/scsinvme.cpp b/smartmontools/scsinvme.cpp index f2db1366ae7ece6434b9660c7fcea76b7c2f6226..f4fda25f92c8bdbb65ec59dac334d2ae24ac841e 100644 --- a/smartmontools/scsinvme.cpp +++ b/smartmontools/scsinvme.cpp @@ -95,7 +95,7 @@ bool sntasmedia_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & cdb[7] = (uint8_t)cdw10_hi; //cdb[8..15] = ? - scsi_cmnd_io io_hdr; memset(&io_hdr, 0, sizeof(io_hdr)); + scsi_cmnd_io io_hdr = {}; io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; @@ -213,8 +213,7 @@ bool sntjmicron_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & for (unsigned i = 0; i < (SNT_JMICRON_NVM_CMD_LEN / sizeof(uint32_t)); i++) swapx(&nvm_cmd[i]); - scsi_cmnd_io io_nvm; - memset(&io_nvm, 0, sizeof(io_nvm)); + scsi_cmnd_io io_nvm = {}; io_nvm.cmnd = cdb; io_nvm.cmnd_len = SNT_JMICRON_CDB_LEN; @@ -233,8 +232,7 @@ bool sntjmicron_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & unsigned char cdb[SNT_JMICRON_CDB_LEN] = { 0 }; cdb[0] = SAT_ATA_PASSTHROUGH_12; - scsi_cmnd_io io_data; - memset(&io_data, 0, sizeof(io_data)); + scsi_cmnd_io io_data = {}; io_data.cmnd = cdb; io_data.cmnd_len = SNT_JMICRON_CDB_LEN; @@ -278,8 +276,7 @@ bool sntjmicron_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & unsigned nvm_reply[SNT_JMICRON_NVM_CMD_LEN / sizeof(unsigned)] = { 0 }; - scsi_cmnd_io io_reply; - memset(&io_reply, 0, sizeof(io_reply)); + scsi_cmnd_io io_reply = {}; io_reply.cmnd = cdb; io_reply.cmnd_len = SNT_JMICRON_CDB_LEN; @@ -375,7 +372,7 @@ bool sntrealtek_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & cdb[3] = in.opcode; cdb[4] = (uint8_t)in.cdw10; - scsi_cmnd_io io_hdr; memset(&io_hdr, 0, sizeof(io_hdr)); + scsi_cmnd_io io_hdr = {}; io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; diff --git a/smartmontools/scsiprint.cpp b/smartmontools/scsiprint.cpp index f711d6685bceb98a72cb8fe73d4446a4576ab89c..a37feac7e013eddac20189ce1416458012742188 100644 --- a/smartmontools/scsiprint.cpp +++ b/smartmontools/scsiprint.cpp @@ -3126,6 +3126,7 @@ int scsiPrintMain(scsi_device * device, const scsi_print_options & options) { bool checkedSupportedLogPages = false; + bool envRepDone = false; uint8_t peripheral_type = 0; int returnval = 0; int res, durationSec; @@ -3373,9 +3374,10 @@ scsiPrintMain(scsi_device * device, const scsi_print_options & options) scsiGetSupportedLogPages(device); checkedSupportedLogPages = true; } - if (gEnviroReportingLPage && options.smart_env_rep) + if (gEnviroReportingLPage && options.smart_env_rep) { scsiPrintEnviroReporting(device); - else if (gTempLPage) + envRepDone = true; + } else if (gTempLPage) scsiPrintTemp(device); // in the 'smartctl -A' case only want: "Accumulated power on time" if ((! options.smart_background_log) && is_disk) { @@ -3488,7 +3490,7 @@ scsiPrintMain(scsi_device * device, const scsi_print_options & options) if (options.tape_alert) { if (! checkedSupportedLogPages) { scsiGetSupportedLogPages(device); - // checkedSupportedLogPages = true; // not needed when last + checkedSupportedLogPages = true; } res = 0; if (gTapeAlertsLPage) { @@ -3569,10 +3571,26 @@ scsiPrintMain(scsi_device * device, const scsi_print_options & options) pout("Self Test returned without error\n"); any_output = true; } - if (options.sasphy && gProtocolSpecificLPage) { - if (scsiPrintSasPhy(device, options.sasphy_reset)) - return returnval | FAILSMART; - any_output = true; + if (options.sasphy) { + if (! checkedSupportedLogPages) { + scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } + if (gProtocolSpecificLPage) { + if (scsiPrintSasPhy(device, options.sasphy_reset)) + return returnval | FAILSMART; + any_output = true; + } + } + if (options.smart_env_rep && ! envRepDone) { + if (! checkedSupportedLogPages) { + scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } + if (gEnviroReportingLPage) { + scsiPrintEnviroReporting(device); + any_output = true; + } } if (options.set_standby == 1) {