aboutsummaryrefslogtreecommitdiff
path: root/lib/sg_cmds_basic.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2018-02-04 21:44:28 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2018-02-04 21:44:28 +0000
commit9fe92189ee2e0769daaefccf68d3fabff62b4f6b (patch)
treefc953c05ae1c6481008e3ab29b083cb4d74f14bb /lib/sg_cmds_basic.c
parenta89cc910e28cbdebc01e2414bc47bcc9a163c7df (diff)
downloadsg3_utils-9fe92189ee2e0769daaefccf68d3fabff62b4f6b.tar.gz
add sg_convert_errno() and sg_if_can2stderr(); work on NVMe support for Win32; add REPORT SUPPORTED OPCODES+TMFs to SNTL
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@749 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib/sg_cmds_basic.c')
-rw-r--r--lib/sg_cmds_basic.c179
1 files changed, 41 insertions, 138 deletions
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 7405372e..35a49912 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -36,7 +36,7 @@
#endif
-static const char * const version_str = "1.82 20180126";
+static const char * const version_str = "1.83 20180204";
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -333,12 +333,10 @@ create_pt_obj(const char * cname)
static const char * const inquiry_s = "inquiry";
-/* Invokes a SCSI INQUIRY command and yields the response. Returns 0 when
- * successful, various SG_LIB_CAT_* positive values or -1 -> other errors.
- * The CMDDT field is obsolete in the INQUIRY cdb. */
-int
-sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
- int mx_resp_len, bool noisy, int verbose)
+static int
+sg_ll_inquiry_com(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
+ int mx_resp_len, int timeout_secs, int * residp,
+ bool noisy, int verbose)
{
int res, ret, k, sense_cat, resid;
unsigned char inq_cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0};
@@ -347,9 +345,9 @@ sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
struct sg_pt_base * ptvp;
if (cmddt)
- inq_cdb[1] |= 2;
+ inq_cdb[1] |= 0x2;
if (evpd)
- inq_cdb[1] |= 1;
+ inq_cdb[1] |= 0x1;
inq_cdb[2] = (unsigned char)pg_op;
/* 16 bit allocation length (was 8, increased in spc3r09, 200209) */
sg_put_unaligned_be16((uint16_t)mx_resp_len, inq_cdb + 3);
@@ -365,21 +363,27 @@ sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
if (mx_resp_len > 4)
up[4] = 0;
}
- if (NULL == (ptvp = create_pt_obj(inquiry_s)))
+ if (timeout_secs <= 0)
+ timeout_secs = DEF_PT_TIMEOUT;
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ pr2ws("%s: out of memory\n", __func__);
+ if (residp)
+ *residp = 0;
return -1;
+ }
set_scsi_pt_cdb(ptvp, inq_cdb, sizeof(inq_cdb));
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len);
- res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ res = do_scsi_pt(ptvp, sg_fd, timeout_secs, verbose);
ret = sg_cmds_process_resp(ptvp, inquiry_s, res, mx_resp_len, sense_b,
noisy, verbose, &sense_cat);
resid = get_scsi_pt_resid(ptvp);
- if (-1 == ret) {
- int os_err = get_scsi_pt_os_err(ptvp);
-
- if ((os_err > 0) && (os_err < 47))
- ret = SG_LIB_OS_BASE_ERR + os_err;
- } else if (-2 == ret) {
+ if (residp)
+ *residp = resid;
+ if (-1 == ret)
+ ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
+ else if (-2 == ret) {
switch (sense_cat) {
case SG_LIB_CAT_RECOVERED:
case SG_LIB_CAT_NO_SENSE:
@@ -391,7 +395,7 @@ sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
}
} else if (ret < 4) {
if (verbose)
- pr2ws("%s: got too few bytes (%d)\n", inquiry_s, ret);
+ pr2ws("%s: got too few bytes (%d)\n", __func__, ret);
ret = SG_LIB_CAT_MALFORMED;
} else
ret = 0;
@@ -399,16 +403,27 @@ sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
if (resid > 0) {
if (resid > mx_resp_len) {
- pr2ws("%s: resid (%d) should never exceed requested len=%d\n",
- inquiry_s, resid, mx_resp_len);
+ pr2ws("%s resid (%d) should never exceed requested "
+ "len=%d\n", inquiry_s, resid, mx_resp_len);
return ret ? ret : SG_LIB_CAT_MALFORMED;
}
- /* zero unfilled section of response buffer */
+ /* zero unfilled section of response buffer, based on resid */
memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid);
}
return ret;
}
+/* Invokes a SCSI INQUIRY command and yields the response. Returns 0 when
+ * successful, various SG_LIB_CAT_* positive values or -1 -> other errors.
+ * The CMDDT field is obsolete in the INQUIRY cdb. */
+int
+sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
+ int mx_resp_len, bool noisy, int verbose)
+{
+ return sg_ll_inquiry_com(sg_fd, cmddt, evpd, pg_op, resp, mx_resp_len,
+ 0 /* timeout_sec */, NULL, noisy, verbose);
+}
+
/* Yields most of first 36 bytes of a standard INQUIRY (evpd==0) response.
* Returns 0 when successful, various SG_LIB_CAT_* positive values or
* -1 -> other errors */
@@ -416,55 +431,16 @@ int
sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
bool noisy, int verbose)
{
- int res, ret, k, sense_cat;
- unsigned char inq_cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0};
- unsigned char sense_b[SENSE_BUFF_LEN];
+ int ret;
unsigned char inq_resp[SAFE_STD_INQ_RESP_LEN];
- struct sg_pt_base * ptvp;
if (inq_data) {
memset(inq_data, 0, sizeof(* inq_data));
inq_data->peripheral_qualifier = 0x3;
inq_data->peripheral_type = 0x1f;
}
- inq_cdb[4] = (unsigned char)sizeof(inq_resp);
- if (verbose) {
- pr2ws(" %s cdb: ", inquiry_s);
- for (k = 0; k < INQUIRY_CMDLEN; ++k)
- pr2ws("%02x ", inq_cdb[k]);
- pr2ws("\n");
- }
- memset(inq_resp, 0, sizeof(inq_resp));
- inq_resp[0] = 0x7f; /* defensive prefill */
- if (NULL == ((ptvp = create_pt_obj(inquiry_s))))
- return -1;
- set_scsi_pt_cdb(ptvp, inq_cdb, sizeof(inq_cdb));
- set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
- set_scsi_pt_data_in(ptvp, inq_resp, sizeof(inq_resp));
- res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
- ret = sg_cmds_process_resp(ptvp, inquiry_s, res, sizeof(inq_resp),
- sense_b, noisy, verbose, &sense_cat);
- if (-1 == ret) {
- int os_err = get_scsi_pt_os_err(ptvp);
-
- if ((os_err > 0) && (os_err < 47))
- ret = SG_LIB_OS_BASE_ERR + os_err;
- } else if (-2 == ret) {
- switch (sense_cat) {
- case SG_LIB_CAT_RECOVERED:
- case SG_LIB_CAT_NO_SENSE:
- ret = 0;
- break;
- default:
- ret = sense_cat;
- break;
- }
- } else if (ret < 4) {
- if (verbose)
- pr2ws("%s: got too few bytes (%d)\n", inquiry_s, ret);
- ret = SG_LIB_CAT_MALFORMED;
- } else
- ret = 0;
+ ret = sg_ll_inquiry_com(sg_fd, false, false, 0, inq_resp,
+ sizeof(inq_resp), 0, NULL, noisy, verbose);
if (inq_data && (0 == ret)) {
inq_data->peripheral_qualifier = (inq_resp[0] >> 5) & 0x7;
@@ -479,7 +455,6 @@ sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
memcpy(inq_data->product, inq_resp + 16, 16);
memcpy(inq_data->revision, inq_resp + 32, 4);
}
- destruct_scsi_pt_obj(ptvp);
return ret;
}
@@ -499,80 +474,8 @@ sg_ll_inquiry_v2(int sg_fd, bool evpd, int pg_op, void * resp,
int mx_resp_len, int timeout_secs, int * residp,
bool noisy, int verbose)
{
- int res, ret, k, sense_cat, resid;
- unsigned char inq_cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0};
- unsigned char sense_b[SENSE_BUFF_LEN];
- unsigned char * up;
- struct sg_pt_base * ptvp;
-
- if (evpd)
- inq_cdb[1] |= 1;
- inq_cdb[2] = (unsigned char)pg_op;
- /* 16 bit allocation length (was 8, increased in spc3r09, 200209) */
- sg_put_unaligned_be16((uint16_t)mx_resp_len, inq_cdb + 3);
- if (verbose) {
- pr2ws(" inquiry cdb: ");
- for (k = 0; k < INQUIRY_CMDLEN; ++k)
- pr2ws("%02x ", inq_cdb[k]);
- pr2ws("\n");
- }
- if (resp && (mx_resp_len > 0)) {
- up = (unsigned char *)resp;
- up[0] = 0x7f; /* defensive prefill */
- if (mx_resp_len > 4)
- up[4] = 0;
- }
- if (timeout_secs <= 0)
- timeout_secs = DEF_PT_TIMEOUT;
- ptvp = construct_scsi_pt_obj();
- if (NULL == ptvp) {
- pr2ws("%s: out of memory\n", __func__);
- if (residp)
- *residp = 0;
- return -1;
- }
- set_scsi_pt_cdb(ptvp, inq_cdb, sizeof(inq_cdb));
- set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
- set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len);
- res = do_scsi_pt(ptvp, sg_fd, timeout_secs, verbose);
- ret = sg_cmds_process_resp(ptvp, "inquiry", res, mx_resp_len, sense_b,
- noisy, verbose, &sense_cat);
- resid = get_scsi_pt_resid(ptvp);
- if (residp)
- *residp = resid;
- if (-1 == ret) {
- int os_err = get_scsi_pt_os_err(ptvp);
-
- if ((os_err > 0) && (os_err < 47))
- ret = SG_LIB_OS_BASE_ERR + os_err;
- } else if (-2 == ret) {
- switch (sense_cat) {
- case SG_LIB_CAT_RECOVERED:
- case SG_LIB_CAT_NO_SENSE:
- ret = 0;
- break;
- default:
- ret = sense_cat;
- break;
- }
- } else if (ret < 4) {
- if (verbose)
- pr2ws("%s: got too few bytes (%d)\n", __func__, ret);
- ret = SG_LIB_CAT_MALFORMED;
- } else
- ret = 0;
- destruct_scsi_pt_obj(ptvp);
-
- if (resid > 0) {
- if (resid > mx_resp_len) {
- pr2ws("INQUIRY resid (%d) should never exceed requested "
- "len=%d\n", resid, mx_resp_len);
- return ret ? ret : SG_LIB_CAT_MALFORMED;
- }
- /* zero unfilled section of response buffer */
- memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid);
- }
- return ret;
+ return sg_ll_inquiry_com(sg_fd, false, evpd, pg_op, resp, mx_resp_len,
+ timeout_secs, residp, noisy, verbose);
}
/* Invokes a SCSI TEST UNIT READY command.