aboutsummaryrefslogtreecommitdiff
path: root/lib/sg_cmds_extra.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2020-07-24 18:56:21 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2020-07-24 18:56:21 +0000
commit985b5cda4750a8a033ebb4162cbb65f1eaed93ba (patch)
tree0f0d306533dee63d5d7b9fb498a394fff3dcb0eb /lib/sg_cmds_extra.c
parent5d21382d1a81a0aa3da2c27235171a8b88357c00 (diff)
downloadsg3_utils-985b5cda4750a8a033ebb4162cbb65f1eaed93ba.tar.gz
sg_turs: estimated time-to-ready, add --delay=MS option; sg_requests: cleanup; sg_pt: add partial_clear_scsi_pt_obj, get_scsi_pt_cdb_len and get_scsi_pt_cdb_buf
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@857 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib/sg_cmds_extra.c')
-rw-r--r--lib/sg_cmds_extra.c142
1 files changed, 97 insertions, 45 deletions
diff --git a/lib/sg_cmds_extra.c b/lib/sg_cmds_extra.c
index 71af0358..7874dd16 100644
--- a/lib/sg_cmds_extra.c
+++ b/lib/sg_cmds_extra.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2019 Douglas Gilbert.
+ * Copyright (c) 1999-2020 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -448,12 +448,15 @@ sg_ll_report_referrals(int sg_fd, uint64_t start_llba, bool one_seg,
* value is taken as the timeout value in seconds. Return of 0 -> success,
* various SG_LIB_CAT_* positive values or -1 -> other errors */
int
-sg_ll_send_diag_pt(struct sg_pt_base * ptvp, int st_code, bool pf_bit,
- bool st_bit, bool devofl_bit, bool unitofl_bit,
- int long_duration, void * paramp, int param_len,
- bool noisy, int vb)
+sg_ll_send_diag_com(struct sg_pt_base * ptvp, int sg_fd, int st_code,
+ bool pf_bit, bool st_bit, bool devofl_bit,
+ bool unitofl_bit, int long_duration, void * paramp,
+ int param_len, bool noisy, int vb)
{
static const char * const cdb_s = "Send diagnostic";
+ bool ptvp_given = false;
+ bool local_sense = true;
+ bool local_cdb = true;
int res, ret, s_cat, tmout;
uint8_t senddiag_cdb[SEND_DIAGNOSTIC_CMDLEN] =
{SEND_DIAGNOSTIC_CMD, 0, 0, 0, 0, 0};
@@ -488,9 +491,24 @@ sg_ll_send_diag_pt(struct sg_pt_base * ptvp, int st_code, bool pf_bit,
pr2ws(" %s timeout: %d seconds\n", cdb_s, tmout);
}
}
-
- set_scsi_pt_cdb(ptvp, senddiag_cdb, sizeof(senddiag_cdb));
- set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ if (ptvp) {
+ ptvp_given = true;
+ partial_clear_scsi_pt_obj(ptvp);
+ if (get_scsi_pt_cdb_buf(ptvp))
+ local_cdb = false; /* N.B. Ignores locally built cdb */
+ else
+ set_scsi_pt_cdb(ptvp, senddiag_cdb, sizeof(senddiag_cdb));
+ if (get_scsi_pt_sense_buf(ptvp))
+ local_sense = false;
+ else
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ } else {
+ ptvp = construct_scsi_pt_obj_with_fd(sg_fd, vb);
+ if (NULL == ptvp)
+ return sg_convert_errno(ENOMEM);
+ set_scsi_pt_cdb(ptvp, senddiag_cdb, sizeof(senddiag_cdb));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ }
set_scsi_pt_data_out(ptvp, (uint8_t *)paramp, param_len);
res = do_scsi_pt(ptvp, -1, tmout, vb);
ret = sg_cmds_process_resp(ptvp, cdb_s, res, noisy, vb, &s_cat);
@@ -509,34 +527,49 @@ sg_ll_send_diag_pt(struct sg_pt_base * ptvp, int st_code, bool pf_bit,
} else
ret = 0;
+ if (ptvp_given) {
+ if (local_sense) /* stop caller trying to access local sense */
+ set_scsi_pt_sense(ptvp, NULL, 0);
+ if (local_cdb)
+ set_scsi_pt_cdb(ptvp, NULL, 0);
+ } else {
+ if (ptvp)
+ destruct_scsi_pt_obj(ptvp);
+ }
return ret;
}
int
+sg_ll_send_diag_pt(struct sg_pt_base * ptvp, int st_code, bool pf_bit,
+ bool st_bit, bool devofl_bit, bool unitofl_bit,
+ int long_duration, void * paramp, int param_len,
+ bool noisy, int vb)
+{
+ return sg_ll_send_diag_com(ptvp, -1, st_code, pf_bit, st_bit, devofl_bit,
+ unitofl_bit, long_duration, paramp,
+ param_len, noisy, vb);
+}
+
+int
sg_ll_send_diag(int sg_fd, int st_code, bool pf_bit, bool st_bit,
bool devofl_bit, bool unitofl_bit, int long_duration,
void * paramp, int param_len, bool noisy, int vb)
{
- int ret;
- struct sg_pt_base * ptvp;
-
- ptvp = construct_scsi_pt_obj_with_fd(sg_fd, vb);
- if (NULL == ptvp)
- return sg_convert_errno(ENOMEM);
- ret = sg_ll_send_diag_pt(ptvp, st_code, pf_bit, st_bit, devofl_bit,
- unitofl_bit, long_duration, paramp, param_len,
- noisy, vb);
- destruct_scsi_pt_obj(ptvp);
- return ret;
+ return sg_ll_send_diag_com(NULL, sg_fd, st_code, pf_bit, st_bit,
+ devofl_bit, unitofl_bit, long_duration, paramp,
+ param_len, noisy, vb);
}
/* Invokes a SCSI RECEIVE DIAGNOSTIC RESULTS command. Return of 0 -> success,
* various SG_LIB_CAT_* positive values or -1 -> other errors */
-int
-sg_ll_receive_diag_pt(struct sg_pt_base * ptvp, bool pcv, int pg_code,
- void * resp, int mx_resp_len, int timeout_secs,
- int * residp, bool noisy, int vb)
+static int
+sg_ll_receive_diag_com(struct sg_pt_base * ptvp, int sg_fd, bool pcv,
+ int pg_code, void * resp, int mx_resp_len,
+ int timeout_secs, int * residp, bool noisy, int vb)
{
+ bool ptvp_given = false;
+ bool local_sense = true;
+ bool local_cdb = true;
int resid = 0;
int res, ret, s_cat;
static const char * const cdb_s = "Receive diagnostic results";
@@ -559,8 +592,24 @@ sg_ll_receive_diag_pt(struct sg_pt_base * ptvp, bool pcv, int pg_code,
if (timeout_secs <= 0)
timeout_secs = DEF_PT_TIMEOUT;
- set_scsi_pt_cdb(ptvp, rcvdiag_cdb, sizeof(rcvdiag_cdb));
- set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ if (ptvp) {
+ ptvp_given = true;
+ partial_clear_scsi_pt_obj(ptvp);
+ if (get_scsi_pt_cdb_buf(ptvp))
+ local_cdb = false; /* N.B. Ignores locally built cdb */
+ else
+ set_scsi_pt_cdb(ptvp, rcvdiag_cdb, sizeof(rcvdiag_cdb));
+ if (get_scsi_pt_sense_buf(ptvp))
+ local_sense = false;
+ else
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ } else {
+ ptvp = construct_scsi_pt_obj_with_fd(sg_fd, vb);
+ if (NULL == ptvp)
+ return sg_convert_errno(ENOMEM);
+ set_scsi_pt_cdb(ptvp, rcvdiag_cdb, sizeof(rcvdiag_cdb));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ }
set_scsi_pt_data_in(ptvp, (uint8_t *)resp, mx_resp_len);
res = do_scsi_pt(ptvp, -1, timeout_secs, vb);
ret = sg_cmds_process_resp(ptvp, cdb_s, res, noisy, vb, &s_cat);
@@ -593,9 +642,27 @@ sg_ll_receive_diag_pt(struct sg_pt_base * ptvp, bool pcv, int pg_code,
}
ret = 0;
}
+
+ if (ptvp_given) {
+ if (local_sense) /* stop caller trying to access local sense */
+ set_scsi_pt_sense(ptvp, NULL, 0);
+ if (local_cdb)
+ set_scsi_pt_cdb(ptvp, NULL, 0);
+ } else {
+ if (ptvp)
+ destruct_scsi_pt_obj(ptvp);
+ }
return ret;
}
+int
+sg_ll_receive_diag_pt(struct sg_pt_base * ptvp, bool pcv, int pg_code,
+ void * resp, int mx_resp_len, int timeout_secs,
+ int * residp, bool noisy, int vb)
+{
+ return sg_ll_receive_diag_com(ptvp, -1, pcv, pg_code, resp, mx_resp_len,
+ timeout_secs, residp, noisy, vb);
+}
/* Invokes a SCSI RECEIVE DIAGNOSTIC RESULTS command. Return of 0 -> success,
* various SG_LIB_CAT_* positive values or -1 -> other errors */
@@ -603,16 +670,8 @@ int
sg_ll_receive_diag(int sg_fd, bool pcv, int pg_code, void * resp,
int mx_resp_len, bool noisy, int vb)
{
- int ret;
- struct sg_pt_base * ptvp;
-
- ptvp = construct_scsi_pt_obj_with_fd(sg_fd, vb);
- if (NULL == ptvp)
- return sg_convert_errno(ENOMEM);
- ret = sg_ll_receive_diag_pt(ptvp, pcv, pg_code, resp, mx_resp_len, 0,
- NULL, noisy, vb);
- destruct_scsi_pt_obj(ptvp);
- return ret;
+ return sg_ll_receive_diag_com(NULL, sg_fd, pcv, pg_code, resp,
+ mx_resp_len, 0, NULL, noisy, vb);
}
int
@@ -620,16 +679,9 @@ sg_ll_receive_diag_v2(int sg_fd, bool pcv, int pg_code, void * resp,
int mx_resp_len, int timeout_secs, int * residp,
bool noisy, int vb)
{
- int ret;
- struct sg_pt_base * ptvp;
-
- ptvp = construct_scsi_pt_obj_with_fd(sg_fd, vb);
- if (NULL == ptvp)
- return sg_convert_errno(ENOMEM);
- ret = sg_ll_receive_diag_pt(ptvp, pcv, pg_code, resp, mx_resp_len,
- timeout_secs, residp, noisy, vb);
- destruct_scsi_pt_obj(ptvp);
- return ret;
+ return sg_ll_receive_diag_com(NULL, sg_fd, pcv, pg_code, resp,
+ mx_resp_len, timeout_secs, residp, noisy,
+ vb);
}
/* Invokes a SCSI READ DEFECT DATA (10) command (SBC). Return of 0 -> success