aboutsummaryrefslogtreecommitdiff
path: root/lib/sg_cmds_extra.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sg_cmds_extra.c')
-rw-r--r--lib/sg_cmds_extra.c127
1 files changed, 83 insertions, 44 deletions
diff --git a/lib/sg_cmds_extra.c b/lib/sg_cmds_extra.c
index d162bb7c..345d51bd 100644
--- a/lib/sg_cmds_extra.c
+++ b/lib/sg_cmds_extra.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2012 Douglas Gilbert.
+ * Copyright (c) 1999-2013 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.
@@ -164,7 +164,7 @@ sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " get LBA status: response%s\n",
(ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -246,7 +246,7 @@ sg_ll_report_tgt_prt_grp2(int sg_fd, void * resp, int mx_resp_len,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " report target port group: "
"response%s\n", (ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -283,7 +283,7 @@ sg_ll_set_tgt_prt_grp(int sg_fd, void * paramp, int param_len, int noisy,
if ((verbose > 1) && paramp && param_len) {
fprintf(sg_warnings_strm, " set target port groups "
"parameter list:\n");
- dStrHex((const char *)paramp, param_len, -1);
+ dStrHexErr((const char *)paramp, param_len, -1);
}
}
@@ -396,7 +396,7 @@ sg_ll_report_referrals(int sg_fd, uint64_t start_llba, int one_seg,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " report referrals: response%s\n",
(ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -436,7 +436,7 @@ sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit, int devofl_bit,
if ((verbose > 1) && paramp && param_len) {
fprintf(sg_warnings_strm, " Send diagnostic parameter "
"list:\n");
- dStrHex((const char *)paramp, param_len, -1);
+ dStrHexErr((const char *)paramp, param_len, -1);
}
}
@@ -544,7 +544,7 @@ sg_ll_receive_diag(int sg_fd, int pcv, int pg_code, void * resp,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " receive diagnostic results: "
"response%s\n", (ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -618,7 +618,7 @@ sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist, int dl_format,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " read defect (10): response%s\n",
(ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -691,7 +691,7 @@ sg_ll_read_media_serial_num(int sg_fd, void * resp, int mx_resp_len,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " read media serial number: respon"
"se%s\n", (ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -767,7 +767,7 @@ sg_ll_report_id_info(int sg_fd, int itype, void * resp, int max_resp_len,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " report identifying information: "
"response%s\n", (ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -807,7 +807,7 @@ sg_ll_set_id_info(int sg_fd, int itype, void * paramp, int param_len,
if ((verbose > 1) && paramp && param_len) {
fprintf(sg_warnings_strm, " Set identifying information "
"parameter list:\n");
- dStrHex((const char *)paramp, param_len, -1);
+ dStrHexErr((const char *)paramp, param_len, -1);
}
}
@@ -886,7 +886,7 @@ sg_ll_format_unit(int sg_fd, int fmtpinfo, int longlist, int fmtdata,
}
if ((verbose > 1) && (param_len > 0)) {
fprintf(sg_warnings_strm, " format parameter list:\n");
- dStrHex((const char *)paramp, param_len, -1);
+ dStrHexErr((const char *)paramp, param_len, -1);
}
ptvp = construct_scsi_pt_obj();
@@ -952,7 +952,7 @@ sg_ll_reassign_blocks(int sg_fd, int longlba, int longlist, void * paramp,
}
if (verbose > 1) {
fprintf(sg_warnings_strm, " reassign blocks parameter list\n");
- dStrHex((const char *)paramp, param_len, -1);
+ dStrHexErr((const char *)paramp, param_len, -1);
}
ptvp = construct_scsi_pt_obj();
@@ -1055,7 +1055,7 @@ sg_ll_persistent_reserve_in(int sg_fd, int rq_servact, void * resp,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " persistent reserve in: "
"response%s\n", (ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -1094,7 +1094,7 @@ sg_ll_persistent_reserve_out(int sg_fd, int rq_servact, int rq_scope,
if (verbose > 1) {
fprintf(sg_warnings_strm, " Persistent Reservation Out "
"parameters:\n");
- dStrHex((const char *)paramp, param_len, 0);
+ dStrHexErr((const char *)paramp, param_len, 0);
}
}
@@ -1244,7 +1244,7 @@ sg_ll_read_long10(int sg_fd, int pblock, int correct, unsigned int lba,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " read long(10): response%s\n",
(ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -1349,7 +1349,7 @@ sg_ll_read_long16(int sg_fd, int pblock, int correct, uint64_t llba,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " read long(16): response%s\n",
(ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -1599,7 +1599,7 @@ sg_ll_verify10(int sg_fd, int vrprotect, int dpo, int bytchk,
k = data_out_len > 4104 ? 4104 : data_out_len;
fprintf(sg_warnings_strm, " data_out buffer%s\n",
(data_out_len > 4104 ? ", first 4104 bytes" : ""));
- dStrHex((const char *)data_out, k, verbose < 5);
+ dStrHexErr((const char *)data_out, k, verbose < 5);
}
}
ptvp = construct_scsi_pt_obj();
@@ -1702,7 +1702,7 @@ sg_ll_verify16(int sg_fd, int vrprotect, int dpo, int bytchk, uint64_t llba,
k = data_out_len > 4104 ? 4104 : data_out_len;
fprintf(sg_warnings_strm, " data_out buffer%s\n",
(data_out_len > 4104 ? ", first 4104 bytes" : ""));
- dStrHex((const char *)data_out, k, verbose < 5);
+ dStrHexErr((const char *)data_out, k, verbose < 5);
}
}
ptvp = construct_scsi_pt_obj();
@@ -1985,7 +1985,7 @@ sg_ll_read_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " read buffer: response%s\n",
(ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -2026,7 +2026,7 @@ sg_ll_write_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset,
if ((verbose > 1) && paramp && param_len) {
fprintf(sg_warnings_strm, " Write buffer parameter list%s:\n",
((param_len > 256) ? " (first 256 bytes)" : ""));
- dStrHex((const char *)paramp,
+ dStrHexErr((const char *)paramp,
((param_len > 256) ? 256 : param_len), -1);
}
}
@@ -2107,7 +2107,7 @@ sg_ll_unmap_v2(int sg_fd, int anchor, int group_num, int timeout_secs,
fprintf(sg_warnings_strm, "\n");
if ((verbose > 1) && paramp && param_len) {
fprintf(sg_warnings_strm, " unmap parameter list:\n");
- dStrHex((const char *)paramp, param_len, -1);
+ dStrHexErr((const char *)paramp, param_len, -1);
}
}
@@ -2203,7 +2203,7 @@ sg_ll_read_block_limits(int sg_fd, void * resp, int mx_resp_len,
if ((verbose > 2) && (ret > 0)) {
fprintf(sg_warnings_strm, " read block limits: response%s\n",
(ret > 256 ? ", first 256 bytes" : ""));
- dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
}
ret = 0;
}
@@ -2211,7 +2211,22 @@ sg_ll_read_block_limits(int sg_fd, void * resp, int mx_resp_len,
return ret;
}
-/* Invokes a SCSI RECEIVE COPY RESULTS command. Return of 0 -> success,
+/* If error or debug, want to know the service action */
+#define REC_COPY_RESULTS_NUM_SAS 9
+static const char * receive_copy_results_sas[REC_COPY_RESULTS_NUM_SAS] = {
+ "status (LID1)",
+ "data (LID1)",
+ "unused [0x2]",
+ "operating parameters",
+ "failure details (LID1)",
+ "status (LID4)",
+ "data (LID4)",
+ "ROD token information", /* this is different name */
+ "Report all ROD tokens", /* this is different name */
+};
+
+/* Invokes a SCSI RECEIVE COPY RESULTS command. Actually cover all current
+ * uses of opcode 0x84 (Third-party copy IN). Return of 0 -> success,
* SG_LIB_CAT_INVALID_OP -> Receive copy results not supported,
* SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION,
* SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND,
@@ -2225,9 +2240,23 @@ sg_ll_receive_copy_results(int sg_fd, int sa, int list_id, void * resp,
{RECEIVE_COPY_RESULTS_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
+ const char * old_opcode_name = "Receive copy results";
+ char b[64];
+ if ((sa >= REC_COPY_RESULTS_NUM_SAS) || ( sa < 0))
+ snprintf(b, sizeof(b), "%s [sa=0x%x]", old_opcode_name, sa);
+ else
+ snprintf(b, sizeof(b), "%s [sa: %s]", old_opcode_name,
+ receive_copy_results_sas[sa]);
rcvcopyresCmdBlk[1] = (unsigned char)(sa & 0x1f);
- rcvcopyresCmdBlk[2] = (unsigned char)(list_id);
+ if (sa <= 4) /* LID1 variants */
+ rcvcopyresCmdBlk[2] = (unsigned char)(list_id);
+ else if ((sa >= 5) && (sa <= 7)) { /* LID4 variants */
+ rcvcopyresCmdBlk[2] = (unsigned char)((list_id >> 24) & 0xff);
+ rcvcopyresCmdBlk[3] = (unsigned char)((list_id >> 16) & 0xff);
+ rcvcopyresCmdBlk[4] = (unsigned char)((list_id >> 8) & 0xff);
+ rcvcopyresCmdBlk[5] = (unsigned char)(list_id & 0xff);
+ }
rcvcopyresCmdBlk[10] = (unsigned char)((mx_resp_len >> 24) & 0xff);
rcvcopyresCmdBlk[11] = (unsigned char)((mx_resp_len >> 16) & 0xff);
rcvcopyresCmdBlk[12] = (unsigned char)((mx_resp_len >> 8) & 0xff);
@@ -2236,7 +2265,7 @@ sg_ll_receive_copy_results(int sg_fd, int sa, int list_id, void * resp,
if (NULL == sg_warnings_strm)
sg_warnings_strm = stderr;
if (verbose) {
- fprintf(sg_warnings_strm, " Receive copy results cmd: ");
+ fprintf(sg_warnings_strm, " %s cmd: ", b);
for (k = 0; k < RECEIVE_COPY_RESULTS_CMDLEN; ++k)
fprintf(sg_warnings_strm, "%02x ", rcvcopyresCmdBlk[k]);
fprintf(sg_warnings_strm, "\n");
@@ -2244,17 +2273,15 @@ sg_ll_receive_copy_results(int sg_fd, int sa, int list_id, void * resp,
ptvp = construct_scsi_pt_obj();
if (NULL == ptvp) {
- fprintf(sg_warnings_strm, "receive copy results: out of "
- "memory\n");
+ fprintf(sg_warnings_strm, "%s: out of memory\n", b);
return -1;
}
set_scsi_pt_cdb(ptvp, rcvcopyresCmdBlk, sizeof(rcvcopyresCmdBlk));
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);
- ret = sg_cmds_process_resp(ptvp, "receive copy results", res,
- mx_resp_len, sense_b, noisy, verbose,
- &sense_cat);
+ ret = sg_cmds_process_resp(ptvp, b, res, mx_resp_len, sense_b, noisy,
+ verbose, &sense_cat);
if (-1 == ret)
;
else if (-2 == ret) {
@@ -2280,47 +2307,59 @@ sg_ll_receive_copy_results(int sg_fd, int sa, int list_id, void * resp,
return ret;
}
-/* Invokes a SCSI RECEIVE COPY RESULTS command. Return of 0 -> success,
+
+/* SPC-4 rev 35 and later calls this opcode (0x83) "Third-party copy OUT"
+ * The original EXTENDED COPY command (now called EXTENDED COPY (LID1))
+ * is the only one supported by sg_ll_extended_copy(). Another function
+ * perhaps sg_ll_3party_copy_out() is needed for the other service actions
+ * ( > 0 ). */
+
+/* Invokes a SCSI EXTENDED COPY (LID1) command. Return of 0 -> success,
* SG_LIB_CAT_INVALID_OP -> Receive copy results not supported,
* SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION,
* SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND,
* -1 -> other failure */
int
-sg_ll_extended_copy(int sg_fd, void * resp,
- int mx_resp_len, int noisy, int verbose)
+sg_ll_extended_copy(int sg_fd, void * paramp, int param_len, int noisy,
+ int verbose)
{
int k, res, ret, sense_cat;
unsigned char xcopyCmdBlk[EXTENDED_COPY_CMDLEN] =
{EXTENDED_COPY_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
+ const char * opcode_name = "Extended copy (LID1)";
- xcopyCmdBlk[10] = (unsigned char)((mx_resp_len >> 24) & 0xff);
- xcopyCmdBlk[11] = (unsigned char)((mx_resp_len >> 16) & 0xff);
- xcopyCmdBlk[12] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- xcopyCmdBlk[13] = (unsigned char)(mx_resp_len & 0xff);
+ xcopyCmdBlk[10] = (unsigned char)((param_len >> 24) & 0xff);
+ xcopyCmdBlk[11] = (unsigned char)((param_len >> 16) & 0xff);
+ xcopyCmdBlk[12] = (unsigned char)((param_len >> 8) & 0xff);
+ xcopyCmdBlk[13] = (unsigned char)(param_len & 0xff);
if (NULL == sg_warnings_strm)
sg_warnings_strm = stderr;
if (verbose) {
- fprintf(sg_warnings_strm, " Extended copy cmd: ");
+ fprintf(sg_warnings_strm, " %s cmd: ", opcode_name);
for (k = 0; k < EXTENDED_COPY_CMDLEN; ++k)
fprintf(sg_warnings_strm, "%02x ", xcopyCmdBlk[k]);
fprintf(sg_warnings_strm, "\n");
+ if ((verbose > 1) && paramp && param_len) {
+ fprintf(sg_warnings_strm, " %s parameter list:\n",
+ opcode_name);
+ dStrHexErr((const char *)paramp, param_len, -1);
+ }
}
ptvp = construct_scsi_pt_obj();
if (NULL == ptvp) {
- fprintf(sg_warnings_strm, "extended copy: out of memory\n");
+ fprintf(sg_warnings_strm, "%s: out of memory\n", opcode_name);
return -1;
}
set_scsi_pt_cdb(ptvp, xcopyCmdBlk, sizeof(xcopyCmdBlk));
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
- set_scsi_pt_data_out(ptvp, (unsigned char *)resp, mx_resp_len);
+ set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len);
res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
- ret = sg_cmds_process_resp(ptvp, "extended copy", res,
- mx_resp_len, sense_b, noisy, verbose,
- &sense_cat);
+ ret = sg_cmds_process_resp(ptvp, opcode_name, res, 0, sense_b,
+ noisy, verbose, &sense_cat);
if (-1 == ret)
;
else if (-2 == ret) {