Commit e1035c54 authored by dpgilbert's avatar dpgilbert
Browse files

[SCSI]: prepare for calling REPORT SUPPORTED OPERATION CODES command and associated work

git-svn-id: https://svn.code.sf.net/p/smartmontools/code/trunk@5392 4ea69e1a-61f1-4043-bf83-b5c94c648137
parent c85a1294
$Id$
2022-05-27 Douglas Gilbert <dgilbert@interlog.com>
[SCSI]: prepare for calling REPORT SUPPORTED OPERATION
CODES [RSOC] command (and several others that use an
additional "service action" code to identify them). For
SCSI devices >= SPC-4 plan to call the RSOC command and
cache its result. Use that cache to determine if
commands like GET PHYSICAL ELEMENT STATUS are supported.
2022-05-26 Christian Franke <franke@computer.org>
INSTALL: Update ./configure description and Windows info.
......
......@@ -889,7 +889,7 @@ bool freebsd_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop)
char buff[256];
const int sz = (int)sizeof(buff);
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < (int)iop->cmnd_len; ++k)
j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
......@@ -1253,7 +1253,7 @@ bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
const unsigned char * ucp = iop->cmnd;
const char * np;
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
pout(" [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < iop->cmnd_len; ++k)
pout("%02x ", ucp[k]);
......
......@@ -542,7 +542,7 @@ static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report,
const int sz = (int)sizeof(buff);
pout(">>>> do_scsi_cmnd_io: sg_io_ifc=%d\n", (int)sg_io_ifc);
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < (int)iop->cmnd_len; ++k)
j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
......@@ -921,7 +921,7 @@ bool linux_aacraid_device::scsi_pass_through(scsi_cmnd_io *iop)
char buff[256];
const int sz = (int)sizeof(buff);
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < (int)iop->cmnd_len; ++k)
j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
......@@ -1226,7 +1226,7 @@ bool linux_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop)
char buff[256];
const int sz = (int)sizeof(buff);
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < (int)iop->cmnd_len; ++k)
j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
......
......@@ -357,7 +357,7 @@ bool netbsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
const unsigned char * ucp = iop->cmnd;
const char * np;
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
pout(" [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < iop->cmnd_len; ++k)
pout("%02x ", ucp[k]);
......
......@@ -244,7 +244,7 @@ bool openbsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
const unsigned char * ucp = iop->cmnd;
const char * np;
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
pout(" [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < iop->cmnd_len; ++k)
pout("%02x ", ucp[k]);
......
......@@ -240,7 +240,7 @@ int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
const unsigned char * ucp = iop->cmnd;
const char * np;
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
pout(" [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < (int)iop->cmnd_len; ++k)
pout("%02x ", ucp[k]);
......
......@@ -2830,7 +2830,7 @@ bool win_scsi_device::scsi_pass_through(struct scsi_cmnd_io * iop)
char buff[256];
const int sz = (int)sizeof(buff);
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < (int)iop->cmnd_len; ++k)
j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
......@@ -2959,7 +2959,7 @@ static long scsi_pass_through_direct(HANDLE fd, UCHAR targetid, struct scsi_cmnd
char buff[256];
const int sz = (int)sizeof(buff);
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < (int)iop->cmnd_len; ++k)
j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
......@@ -3396,7 +3396,7 @@ bool win_aacraid_device::scsi_pass_through(struct scsi_cmnd_io *iop)
const char * np;
char buff[256];
const int sz = (int)sizeof(buff);
np = scsi_get_opcode_name(ucp[0]);
np = scsi_get_opcode_name(ucp[0], false, 0);
j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < (int)iop->cmnd_len; ++k)
j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
......
......@@ -199,30 +199,38 @@ is_scsi_cdb(const uint8_t * cdbp, int clen)
struct scsi_opcode_name {
uint8_t opcode;
bool sa_valid;
uint16_t sa;
const char * name;
};
/* Array assumed to be sorted by opcode then service action (sa) */
static struct scsi_opcode_name opcode_name_arr[] = {
/* in ascending opcode order */
{TEST_UNIT_READY, "test unit ready"}, /* 0x00 */
{REQUEST_SENSE, "request sense"}, /* 0x03 */
{INQUIRY, "inquiry"}, /* 0x12 */
{MODE_SELECT, "mode select(6)"}, /* 0x15 */
{MODE_SENSE, "mode sense(6)"}, /* 0x1a */
{START_STOP_UNIT, "start stop unit"}, /* 0x1b */
{RECEIVE_DIAGNOSTIC, "receive diagnostic"}, /* 0x1c */
{SEND_DIAGNOSTIC, "send diagnostic"}, /* 0x1d */
{READ_CAPACITY_10, "read capacity(10)"}, /* 0x25 */
{READ_DEFECT_10, "read defect list(10)"}, /* 0x37 */
{LOG_SELECT, "log select"}, /* 0x4c */
{LOG_SENSE, "log sense"}, /* 0x4d */
{MODE_SELECT_10, "mode select(10)"}, /* 0x55 */
{MODE_SENSE_10, "mode sense(10)"}, /* 0x5a */
{SAT_ATA_PASSTHROUGH_16, "ata pass-through(16)"}, /* 0x85 */
{READ_CAPACITY_16, "read capacity(16)"}, /* 0x9e,0x10 */
{REPORT_LUNS, "report luns"}, /* 0xa0 */
{SAT_ATA_PASSTHROUGH_12, "ata pass-through(12)"}, /* 0xa1 */
{READ_DEFECT_12, "read defect list(12)"}, /* 0xb7 */
{TEST_UNIT_READY, false, 0, "test unit ready"}, /* 0x00 */
{REQUEST_SENSE, false, 0, "request sense"}, /* 0x03 */
{INQUIRY, false, 0, "inquiry"}, /* 0x12 */
{MODE_SELECT_6, false, 0, "mode select(6)"}, /* 0x15 */
{MODE_SENSE_6, false, 0, "mode sense(6)"}, /* 0x1a */
{START_STOP_UNIT, false, 0, "start stop unit"}, /* 0x1b */
{RECEIVE_DIAGNOSTIC, false, 0, "receive diagnostic"}, /* 0x1c */
{SEND_DIAGNOSTIC, false, 0, "send diagnostic"}, /* 0x1d */
{READ_CAPACITY_10, false, 0, "read capacity(10)"}, /* 0x25 */
{READ_DEFECT_10, false, 0, "read defect list(10)"}, /* 0x37 */
{LOG_SELECT, false, 0, "log select"}, /* 0x4c */
{LOG_SENSE, false, 0, "log sense"}, /* 0x4d */
{MODE_SELECT_10, false, 0, "mode select(10)"}, /* 0x55 */
{MODE_SENSE_10, false, 0, "mode sense(10)"}, /* 0x5a */
{SAT_ATA_PASSTHROUGH_16, false, 0, "ata pass-through(16)"}, /* 0x85 */
{SERVICE_ACTION_IN_16, true, SAI_READ_CAPACITY_16, "read capacity(16)"},
/* 0x9e,0x10 */
{SERVICE_ACTION_IN_16, true, SAI_GET_PHY_ELEM_STATUS,
"get physical element status"}, /* 0x9e,0x17 */
{REPORT_LUNS, false, 0, "report luns"}, /* 0xa0 */
{SAT_ATA_PASSTHROUGH_12, false, 0, "ata pass-through(12)"}, /* 0xa1 */
{MAINTENANCE_IN_12, true, MI_REP_SUP_OPCODES,
"report suported operation codes"}, /* 0xa3,0xc */
{READ_DEFECT_12, false, 0, "read defect list(12)"}, /* 0xb7 */
};
static const char * vendor_specific = "<vendor specific>";
......@@ -230,7 +238,7 @@ static const char * vendor_specific = "<vendor specific>";
/* Need to expand to take service action into account. For commands
* of interest the service action is in the 2nd command byte */
const char *
scsi_get_opcode_name(uint8_t opcode)
scsi_get_opcode_name(uint8_t opcode, bool sa_valid, uint16_t sa)
{
static const int len = sizeof(opcode_name_arr) /
sizeof(opcode_name_arr[0]);
......@@ -239,9 +247,16 @@ scsi_get_opcode_name(uint8_t opcode)
return vendor_specific;
for (int k = 0; k < len; ++k) {
struct scsi_opcode_name * onp = &opcode_name_arr[k];
if (opcode == onp->opcode)
return onp->name;
else if (opcode < onp->opcode)
if (opcode == onp->opcode) {
if ((! sa_valid) && (! onp->sa_valid))
return onp->name;
if (sa_valid && onp->sa_valid) {
if (sa == onp->sa)
return onp->name;
}
/* should see sa_valid and ! onp->sa_valid (or vice versa) */
} else if (opcode < onp->opcode)
return NULL;
}
return NULL;
......@@ -690,7 +705,7 @@ scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
io_hdr.dxfer_len = bufLen;
io_hdr.dxferp = pBuf;
cdb[0] = MODE_SENSE;
cdb[0] = MODE_SENSE_6;
cdb[2] = (pc << 6) | (pagenum & 0x3f);
cdb[3] = subpagenum;
cdb[4] = bufLen;
......@@ -743,7 +758,7 @@ scsiModeSelect(scsi_device * device, int sp, uint8_t *pBuf, int bufLen)
io_hdr.dxfer_dir = DXFER_TO_DEVICE;
io_hdr.dxfer_len = hdr_plus_1_pg;
io_hdr.dxferp = pBuf;
cdb[0] = MODE_SELECT;
cdb[0] = MODE_SELECT_6;
cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */
cdb[4] = hdr_plus_1_pg; /* make sure only one page sent */
io_hdr.cmnd = cdb;
......@@ -1294,7 +1309,7 @@ scsiReadCapacity16(scsi_device * device, uint8_t *pBuf, int bufLen)
io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
io_hdr.dxfer_len = bufLen;
io_hdr.dxferp = pBuf;
cdb[0] = READ_CAPACITY_16;
cdb[0] = SERVICE_ACTION_IN_16;
cdb[1] = SAI_READ_CAPACITY_16;
sg_put_unaligned_be32(bufLen, cdb + 10);
io_hdr.cmnd = cdb;
......
......@@ -39,14 +39,14 @@
#ifndef LOG_SENSE
#define LOG_SENSE 0x4d
#endif
#ifndef MODE_SENSE
#define MODE_SENSE 0x1a
#ifndef MODE_SENSE_6
#define MODE_SENSE_6 0x1a
#endif
#ifndef MODE_SENSE_10
#define MODE_SENSE_10 0x5a
#endif
#ifndef MODE_SELECT
#define MODE_SELECT 0x15
#ifndef MODE_SELECT_6
#define MODE_SELECT_6 0x15
#endif
#ifndef MODE_SELECT_10
#define MODE_SELECT_10 0x55
......@@ -78,12 +78,21 @@
#ifndef READ_CAPACITY_10
#define READ_CAPACITY_10 0x25
#endif
#ifndef READ_CAPACITY_16
#define READ_CAPACITY_16 0x9e
#ifndef SERVICE_ACTION_IN_16
#define SERVICE_ACTION_IN_16 0x9e
#endif
#ifndef SAI_READ_CAPACITY_16 /* service action for READ_CAPACITY_16 */
#ifndef SAI_READ_CAPACITY_16 /* service action in for READ_CAPACITY_16 */
#define SAI_READ_CAPACITY_16 0x10
#endif
#ifndef SAI_GET_PHY_ELEM_STATUS /* Get physical element status */
#define SAI_GET_PHY_ELEM_STATUS 0x17
#endif
#ifndef MAINTENANCE_IN_12
#define MAINTENANCE_IN_12 0xa3
#endif
#ifndef MI_REP_SUP_OPCODES
#define MI_REP_SUP_OPCODES 0xc /* maintenance in (12) */
#endif
#ifndef SAT_ATA_PASSTHROUGH_12
#define SAT_ATA_PASSTHROUGH_12 0xa1
......@@ -514,7 +523,7 @@ int scsiSmartSelfTestAbort(scsi_device * device);
const char * scsiTapeAlertsTapeDevice(unsigned short code);
const char * scsiTapeAlertsChangerDevice(unsigned short code);
const char * scsi_get_opcode_name(uint8_t opcode);
const char * scsi_get_opcode_name(uint8_t opcode, bool sa_valid, uint16_t sa);
void scsi_format_id_string(char * out, const uint8_t * in, int n);
void dStrHex(const uint8_t * up, int len, int no_ascii);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment