aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2018-04-15 01:35:16 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2018-04-15 01:35:16 +0000
commitf65566c3934a9e22335dee20401cc1cc50865d56 (patch)
tree57d66e8a63006f4d6f4d9bfc589b83159e5f392e
parent040da21637161c189d1d1ca6505cdc1a3794126f (diff)
downloadsg3_utils-f65566c3934a9e22335dee20401cc1cc50865d56.tar.gz
sg_wr_mode: add --rtd option for RTD bit; sg_lib: add sg_ll_mode_select6_v2() and sg_ll_mode_select10_v2() for RTD bit
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@768 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog5
-rw-r--r--doc/sg_modes.82
-rw-r--r--doc/sg_wr_mode.837
-rw-r--r--include/sg_cmds_basic.h8
-rw-r--r--include/sg_unaligned.h7
-rw-r--r--lib/sg_cmds_basic2.c31
-rw-r--r--src/sg_modes.c33
-rw-r--r--src/sg_vpd.c6
-rw-r--r--src/sg_wr_mode.c92
9 files changed, 161 insertions, 60 deletions
diff --git a/ChangeLog b/ChangeLog
index eb8396f8..749de3f9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.43 [20180405] [svn: r767]
+Changelog for sg3_utils-1.43 [20180414] [svn: r768]
- sg_write_x: where x can be normal, atomic, or(write),
same, scattered, or stream writes with 16 or 32 byte
cdbs (sbc4r04 for atomic, sbc4r11 for scattered)
@@ -110,6 +110,7 @@ Changelog for sg3_utils-1.43 [20180405] [svn: r767]
- sg_unmap: add --all=ST,RN[,LA] option to unmap
large contiguous segments of a disk/ssd
- add --dry-run and --force options
+ - sg_wr_mode: add --rtd option for RTD bit
- manpages and usage messages: corrections from
Gris Ge via github
- group_number: is 6 bit field allowing 0 to 63,
@@ -120,6 +121,8 @@ Changelog for sg3_utils-1.43 [20180405] [svn: r767]
- add sg_ll_inquiry_v2()
- add sg_ll_log_sense_v2()
- add sg_ll_mode_sense10_v2()
+ - add sg_ll_mode_select6_v2() and
+ sg_ll_mode_select10_v2() for RTD bit
- add sg_ll_receive_diag_v2()
- add sg_ll_write_buffer_v2()
- add sg_get_llnum_nomult()
diff --git a/doc/sg_modes.8 b/doc/sg_modes.8
index e1ef2011..ce970e96 100644
--- a/doc/sg_modes.8
+++ b/doc/sg_modes.8
@@ -22,7 +22,7 @@ outputs the response. There is a 6 byte and 10 byte (cdb) variant of the
MODE SENSE command, this utility defaults to the 10 byte variant. The SPC\-4
standard (and SPC\-5 drafts) include a note stating that implementers should
migrate away from the SCSI MODE SELECT(6) and MODE SENSE(6) commands in
-favour of the 10 byte variants (e.g. MODE SEMSE(10)).
+favour of the 10 byte variants (e.g. MODE SENSE(10)).
.PP
This utility decodes mode page headers and block descriptors but outputs
the contents of each mode page in hex. It also has no facility to change
diff --git a/doc/sg_wr_mode.8 b/doc/sg_wr_mode.8
index 59f83467..c22be588 100644
--- a/doc/sg_wr_mode.8
+++ b/doc/sg_wr_mode.8
@@ -1,11 +1,11 @@
-.TH SG_WR_MODE "8" "February 2016" "sg3_utils\-1.42" SG3_UTILS
+.TH SG_WR_MODE "8" "April 2018" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_wr_mode \- write (modify) SCSI mode page
.SH SYNOPSIS
.B sg_wr_mode
-[\fI\-\-contents=H,H...\fR] [\fI\-\-dbd\fR] [\fI\-\-force\fR]
-[\fI\-\-help\fR] [\fI\-\-len=\fR10|6\fR] [\fI\-\-mask=M,M...\fR]
-[\fI\-\-page=PG_H[,SPG_H]\fR] [\fI\-\-save\fR] [\fI\-\-verbose\fR]
+[\fI\-\-contents=H,H...\fR] [\fI\-\-dbd\fR] [\fI\-\-force\fR] [\fI\-\-help\fR]
+[\fI\-\-len=10|6\fR] [\fI\-\-mask=M,M...\fR] [\fI\-\-page=PG_H[,SPG_H]\fR]
+[\fI\-\-rtd\fR] [\fI\-\-save\fR] [\fI\-\-six\fR] [\fI\-\-verbose\fR]
[\fI\-\-version\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
@@ -19,6 +19,15 @@ the block descriptor(s); if any block descriptors are fetched by the MODE
SENSE command then the same block descriptors are written back with the
following MODE SELECT command.
.PP
+If the \fI\-\-rtd\fR option is given then most other options apart from
+\fI\-\-save\fR, \fI\-\-len=\fR10|6\fR and \fI\-\-six\fR are ignored. In this
+case only a MODE SELECT command is sent to the \fIDEVICE\fR with the RTD
+bit (Revert To Defaults) set. This bit was added to this command in SPC\-5
+revision 11, so older devices may not support it. The Extended Inquiry VPD
+page has the RTD_SUP bit to indicate whether the \fIDEVICE\fR supports the
+RTD bit in the MODE SELECT(6 and 10) commands. When the \fI\-\-rtd\fR option
+is given the rest of this section can be ignored.
+.PP
If a contents argument is not given then the various components (i.e.
header, block descriptor(s) and mode page) of the "current" values of
the existing mode page are printed out. In this case the mode page is
@@ -111,6 +120,13 @@ be between 0 and fe inclusive. Notice that subpage code ff to fetch all
mode subpages (for a given mode page or all mode pages in the case of 3f,ff)
is disallowed.
.TP
+\fB\-R\fR, \fB\-\-rtd\fR
+when this option is given most other actions are bypassed and a MODE
+SELECT(6 or 10) command is sent to the \fIDEVICE\fR with the RTD bit set.
+This will cause all current values (and saved values if the \fI\-\-save\fR
+option is also given) of all mode pages to be reverted to their default
+values.
+.TP
\fB\-s\fR, \fB\-\-save\fR
changes the "saved" mode page when MODE SELECT is successful. By
default (i.e. when \fI\-\-save\fR is not used) only the "current" mode page
@@ -118,6 +134,17 @@ values are changed when MODE SELECT is successful. In this case the new mode
page will stay in effect until the device is reset (e.g. power cycled).
When it restarts the "saved" values for the mode page will be re\-instated.
So to make changes permanent use the \fI\-\-save\fR option.
+.br
+When used with the \fI\-\-rtd\fR option then both the current and saved
+values in each mode page are reverted to their default values. In the
+absence of \fI\-\-save\fR option only the current values in each mode page
+are reverted to their default values.
+.TP
+\fB\-6\fR, \fB\-\-six\fR
+this option will cause the 6 byte variants of MODE SENSE and MODE SELECT
+commands to be used. The default is to use the 10 byte options. This option
+is equivalent to using the \fI\-\-len=6\fR option.
+
.TP
\fB\-v\fR, \fB\-\-verbose\fR
increase the level of verbosity, (i.e. debug output).
@@ -190,7 +217,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004\-2016 Douglas Gilbert
+Copyright \(co 2004\-2018 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/include/sg_cmds_basic.h b/include/sg_cmds_basic.h
index 672b3ead..90863255 100644
--- a/include/sg_cmds_basic.h
+++ b/include/sg_cmds_basic.h
@@ -84,6 +84,10 @@ int sg_ll_log_sense_v2(int sg_fd, bool ppc, bool sp, int pc, int pg_code,
* -1 -> other failure */
int sg_ll_mode_select6(int sg_fd, bool pf, bool sp, void * paramp,
int param_len, bool noisy, int verbose);
+/* v2 adds RTD (revert to defaults) bit, added in spc5r11 */
+int sg_ll_mode_select6_v2(int sg_fd, bool pf, bool rtd, bool sp,
+ void * paramp, int param_len, bool noisy,
+ int verbose);
/* Invokes a SCSI MODE SELECT (10) command. Return of 0 -> success,
* SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ ->
@@ -92,6 +96,10 @@ int sg_ll_mode_select6(int sg_fd, bool pf, bool sp, void * paramp,
* -1 -> other failure */
int sg_ll_mode_select10(int sg_fd, bool pf, bool sp, void * paramp,
int param_len, bool noisy, int verbose);
+/* v2 adds RTD (revert to defaults) bi, added in spc5r11 */
+int sg_ll_mode_select10_v2(int sg_fd, bool pf, bool rtd, bool sp,
+ void * paramp, int param_len, bool noisy,
+ int verbose);
/* Invokes a SCSI MODE SENSE (6) command. Return of 0 -> success,
* SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ ->
diff --git a/include/sg_unaligned.h b/include/sg_unaligned.h
index 6d5a0917..ca702e86 100644
--- a/include/sg_unaligned.h
+++ b/include/sg_unaligned.h
@@ -42,9 +42,10 @@ extern "C" {
* generic version, use './configure --disable-fast-lebe ' . */
/* Note: Assumes that the source and destination locations do not overlap.
- * So please don't do things like these:
- * i = sg_get_unaligned_le64(&i);
- * sg_put_unaligned_le64(j, ((uint8_t *)&j) + 1); */
+ * An example of overlapping source and destination:
+ * sg_put_unaligned_le64(j, ((uint8_t *)&j) + 1);
+ * Best not to do things like that.
+ */
#ifdef HAVE_CONFIG_H
diff --git a/lib/sg_cmds_basic2.c b/lib/sg_cmds_basic2.c
index 7f9c4c2b..eb7e2fef 100644
--- a/lib/sg_cmds_basic2.c
+++ b/lib/sg_cmds_basic2.c
@@ -442,8 +442,8 @@ gen_err:
/* Invokes a SCSI MODE SELECT (6) command. Return of 0 -> success,
* various SG_LIB_CAT_* positive values or -1 -> other errors */
int
-sg_ll_mode_select6(int sg_fd, bool pf, bool sp, void * paramp, int param_len,
- bool noisy, int verbose)
+sg_ll_mode_select6_v2(int sg_fd, bool pf, bool rtd, bool sp, void * paramp,
+ int param_len, bool noisy, int verbose)
{
static const char * const cdb_name_s = "mode select(6)";
int res, ret, k, sense_cat;
@@ -453,6 +453,8 @@ sg_ll_mode_select6(int sg_fd, bool pf, bool sp, void * paramp, int param_len,
struct sg_pt_base * ptvp;
modes_cdb[1] = (uint8_t)((pf ? 0x10 : 0x0) | (sp ? 0x1 : 0x0));
+ if (rtd)
+ modes_cdb[1] |= 0x2;
modes_cdb[4] = (uint8_t)(param_len & 0xff);
if (param_len > 0xff) {
pr2ws("%s: param_len too big\n", cdb_name_s);
@@ -496,11 +498,20 @@ sg_ll_mode_select6(int sg_fd, bool pf, bool sp, void * paramp, int param_len,
return ret;
}
+int
+sg_ll_mode_select6(int sg_fd, bool pf, bool sp, void * paramp, int param_len,
+ bool noisy, int verbose)
+{
+ return sg_ll_mode_select6_v2(sg_fd, pf, false, sp, paramp, param_len,
+ noisy, verbose);
+}
+
/* Invokes a SCSI MODE SELECT (10) command. Return of 0 -> success,
- * various SG_LIB_CAT_* positive values or -1 -> other errors */
+ * various SG_LIB_CAT_* positive values or -1 -> other errors,
+ * v2 adds rtd (revert to defaults) bit (spc5r11). */
int
-sg_ll_mode_select10(int sg_fd, bool pf, bool sp, void * paramp, int param_len,
- bool noisy, int verbose)
+sg_ll_mode_select10_v2(int sg_fd, bool pf, bool rtd, bool sp, void * paramp,
+ int param_len, bool noisy, int verbose)
{
static const char * const cdb_name_s = "mode select(10)";
int res, ret, k, sense_cat;
@@ -510,6 +521,8 @@ sg_ll_mode_select10(int sg_fd, bool pf, bool sp, void * paramp, int param_len,
struct sg_pt_base * ptvp;
modes_cdb[1] = (uint8_t)((pf ? 0x10 : 0x0) | (sp ? 0x1 : 0x0));
+ if (rtd)
+ modes_cdb[1] |= 0x2;
sg_put_unaligned_be16((int16_t)param_len, modes_cdb + 7);
if (param_len > 0xffff) {
pr2ws("%s: param_len too big\n", cdb_name_s);
@@ -553,6 +566,14 @@ sg_ll_mode_select10(int sg_fd, bool pf, bool sp, void * paramp, int param_len,
return ret;
}
+int
+sg_ll_mode_select10(int sg_fd, bool pf, bool sp, void * paramp,
+ int param_len, bool noisy, int verbose)
+{
+ return sg_ll_mode_select10_v2(sg_fd, pf, false, sp, paramp, param_len,
+ noisy, verbose);
+}
+
/* MODE SENSE commands yield a response that has header then zero or more
* block descriptors followed by mode pages. In most cases users are
* interested in the first mode page. This function returns the (byte)
diff --git a/src/sg_modes.c b/src/sg_modes.c
index 412d6f96..0a839526 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -30,7 +30,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.59 20180329";
+static const char * version_str = "1.60 20180414";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -85,7 +85,7 @@ struct opts_t {
int do_hex;
int maxlen;
int do_raw;
- int do_verbose;
+ int verbose;
int page_control;
int pg_code;
int subpg_code;
@@ -300,7 +300,7 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
op->do_six = true;
break;
case 'v':
- ++op->do_verbose;
+ ++op->verbose;
break;
case 'V':
op->do_version = true;
@@ -390,7 +390,7 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
op->do_raw += 2;
break;
case 'v':
- ++op->do_verbose;
+ ++op->verbose;
break;
case 'V':
op->do_version = true;
@@ -898,7 +898,7 @@ examine_pages(int sg_fd, int inq_pdt, bool encserv, bool mchngr,
resid = 0;
if (op->do_six) {
res = sg_ll_mode_sense6(sg_fd, 0, 0, k, 0, rbuf, mresp_len,
- true, op->do_verbose);
+ true, op->verbose);
if (SG_LIB_CAT_INVALID_OP == res) {
pr2serr(">>>>>> try again without the '-6' switch for a 10 "
"byte MODE SENSE command\n");
@@ -909,7 +909,7 @@ examine_pages(int sg_fd, int inq_pdt, bool encserv, bool mchngr,
}
} else {
res = sg_ll_mode_sense10_v2(sg_fd, 0, 0, 0, k, 0, rbuf, mresp_len,
- 0, &resid, true, op->do_verbose);
+ 0, &resid, true, op->verbose);
if (SG_LIB_CAT_INVALID_OP == res) {
pr2serr(">>>>>> try again with a '-6' switch for a 6 byte "
"MODE SENSE command\n");
@@ -951,10 +951,10 @@ examine_pages(int sg_fd, int inq_pdt, bool encserv, bool mchngr,
printf(" [0x%x]\n", k);
if (op->do_hex)
hex2stdout(rbuf, len, 1);
- } else if (op->do_verbose) {
+ } else if (op->verbose) {
char b[80];
- sg_get_category_sense_str(res, sizeof(b), b, op->do_verbose - 1);
+ sg_get_category_sense_str(res, sizeof(b), b, op->verbose - 1);
pr2serr("MODE SENSE (%s) failed: %s\n", (op->do_six ? "6" : "10"),
b);
}
@@ -1069,16 +1069,16 @@ main(int argc, char * argv[])
}
if ((sg_fd = sg_cmds_open_device(op->device_name, ! op->o_readwrite,
- op->do_verbose)) < 0) {
+ op->verbose)) < 0) {
pr2serr("error opening file: %s: %s\n", op->device_name,
safe_strerror(-sg_fd));
ret = sg_convert_errno(-sg_fd);
goto fini;
}
- if (sg_simple_inquiry(sg_fd, &inq_out, true, op->do_verbose)) {
+ if ((res = sg_simple_inquiry(sg_fd, &inq_out, true, op->verbose))) {
pr2serr("%s doesn't respond to a SCSI INQUIRY\n", op->device_name);
- ret = SG_LIB_CAT_OTHER;
+ ret = (res > 0) ? res : sg_convert_errno(-res);
goto fini;
}
inq_pdt = inq_out.peripheral_type;
@@ -1123,7 +1123,7 @@ main(int argc, char * argv[])
if (op->do_six) {
res = sg_ll_mode_sense6(sg_fd, op->do_dbd, op->page_control,
op->pg_code, op->subpg_code, rsp_buff,
- rsp_buff_sz, true, op->do_verbose);
+ rsp_buff_sz, true, op->verbose);
if (SG_LIB_CAT_INVALID_OP == res)
pr2serr(">>>>>> try again without the '-6' switch for a 10 byte "
"MODE SENSE command\n");
@@ -1131,7 +1131,7 @@ main(int argc, char * argv[])
res = sg_ll_mode_sense10_v2(sg_fd, op->do_llbaa, op->do_dbd,
op->page_control, op->pg_code,
op->subpg_code, rsp_buff, rsp_buff_sz,
- 0, &resid, true, op->do_verbose);
+ 0, &resid, true, op->verbose);
if (SG_LIB_CAT_INVALID_OP == res)
pr2serr(">>>>>> try again with a '-6' switch for a 6 byte MODE "
"SENSE command\n");
@@ -1147,7 +1147,7 @@ main(int argc, char * argv[])
pr2serr("invalid field in cdb (perhaps page 0x%x not "
"supported)\n", op->pg_code);
} else if (res) {
- sg_get_category_sense_str(res, sizeof(b), b, op->do_verbose);
+ sg_get_category_sense_str(res, sizeof(b), b, op->verbose);
pr2serr("%s\n", b);
}
ret = res;
@@ -1364,5 +1364,10 @@ fini:
sg_cmds_close_device(sg_fd);
if (free_rsp_buff)
free(free_rsp_buff);
+ if (0 == op->verbose) {
+ if (! sg_if_can2stderr("sg_modes failed: ", ret))
+ pr2serr("Some error occurred, try again with '-v' or '-vv' for "
+ "more information\n");
+ }
return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 2a230333..1aad48df 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -38,7 +38,7 @@
*/
-static const char * version_str = "1.43 20180405"; /* spc5r19 + sbc4r15 */
+static const char * version_str = "1.43 20180410"; /* spc5r19 + sbc4r15 */
/* standard VPD pages, in ascending page number order */
#define VPD_SUPPORTED_VPDS 0x0
@@ -3493,7 +3493,7 @@ svpd_decode_all(int sg_fd, struct opts_t * op)
if (op->vpd_pn > 0)
max_pn = op->vpd_pn;
- if (sg_fd >= 0) {
+ if (sg_fd >= 0) { /* have valid open file descriptor (handle) */
res = vpd_fetch_page(sg_fd, rp, VPD_SUPPORTED_VPDS, op->maxlen,
op->do_quiet, op->verbose, &rlen);
if (res) {
@@ -3522,6 +3522,8 @@ svpd_decode_all(int sg_fd, struct opts_t * op)
if (pn > max_pn)
continue;
op->vpd_pn = pn;
+ if (k > 0)
+ printf("\n");
if (op->do_long)
printf("[0x%x] ", pn);
diff --git a/src/sg_wr_mode.c b/src/sg_wr_mode.c
index a5d35461..c6ebf13a 100644
--- a/src/sg_wr_mode.c
+++ b/src/sg_wr_mode.c
@@ -30,7 +30,7 @@
* mode page on the given device.
*/
-static const char * version_str = "1.23 20180329";
+static const char * version_str = "1.24 20180414";
#define ME "sg_wr_mode: "
@@ -48,7 +48,9 @@ static struct option long_options[] = {
{"len", required_argument, 0, 'l'},
{"mask", required_argument, 0, 'm'},
{"page", required_argument, 0, 'p'},
+ {"rtd", no_argument, 0, 'R'},
{"save", no_argument, 0, 's'},
+ {"six", no_argument, 0, '6'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
@@ -60,7 +62,9 @@ static void usage()
"[--help]\n"
" [--len=10|6] [--mask=M,M...] "
"[--page=PG_H[,SPG_H]]\n"
- " [--save] [--verbose] [--version] DEVICE\n"
+ " [--rtd] [--save] [--six] [--verbose] "
+ "[--version]\n"
+ " DEVICE\n"
" where:\n"
" --contents=H,H... | -c H,H... comma separated string "
"of hex numbers\n"
@@ -83,9 +87,13 @@ static void usage()
" --page=PG_H,SPG_H | -p PG_H,SPG_H page and subpage code "
"to be\n"
" written (in hex)\n"
+ " --rtd | -R set RTD bit (revert to defaults) in "
+ "cdb\n"
" --save | -s set 'save page' (SP) bit; default "
"don't so\n"
" only 'current' values changed\n"
+ " --six | -6 do SCSI MODE SENSE/SELECT(6) "
+ "commands\n"
" --verbose | -v increase verbosity\n"
" --version | -V print version string and exit\n\n"
"writes given mode page with SCSI MODE SELECT (10 or 6) "
@@ -309,7 +317,8 @@ int main(int argc, char * argv[])
bool force = false;
bool got_contents = false;
bool got_mask = false;
- bool mode_6 = false;
+ bool mode_6 = false; /* so default is mode_10 */
+ bool rtd = false; /* added in spc5r11 */
bool save = false;
int sg_fd, res, c, num, alloc_len, off, pdt;
int k, md_len, hdr_len, bd_len, mask_in_len;
@@ -331,12 +340,15 @@ int main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "c:dfhl:m:p:svV", long_options,
+ c = getopt_long(argc, argv, "6c:dfhl:m:p:RsvV", long_options,
&option_index);
if (c == -1)
break;
switch (c) {
+ case '6':
+ mode_6 = true;
+ break;
case 'c':
memset(read_in, 0, sizeof(read_in));
if (0 != build_mode_page(optarg, read_in, &read_in_len,
@@ -397,6 +409,9 @@ int main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
break;
+ case 'R':
+ rtd = true;
+ break;
case 's':
save = true;
break;
@@ -425,17 +440,17 @@ int main(int argc, char * argv[])
}
}
if (NULL == device_name) {
- pr2serr("missing device name!\n");
+ pr2serr("missing device name!\n\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
- if (pg_code < 0) {
- pr2serr("need page code (see '--page=')\n");
+ if ((pg_code < 0) && (! rtd)) {
+ pr2serr("need page code (see '--page=')\n\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
if (got_mask && force) {
- pr2serr("cannot use both '--force' and '--mask'\n");
+ pr2serr("cannot use both '--force' and '--mask'\n\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -445,6 +460,9 @@ int main(int argc, char * argv[])
pr2serr(ME "open error: %s: %s\n", device_name, safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
+ if (rtd)
+ goto revert_to_defaults;
+
if (0 == sg_simple_inquiry(sg_fd, &inq_data, false, verbose))
pdt = inq_data.peripheral_type;
else
@@ -471,23 +489,23 @@ int main(int argc, char * argv[])
sg_get_category_sense_str(res, sizeof(b), b, verbose);
pr2serr("%s%s\n", errStr, b);
}
- goto err_out;
+ goto fini;
}
off = sg_mode_page_offset(ref_md, alloc_len, mode_6, ebuff, EBUFF_SZ);
if (off < 0) {
pr2serr("%s%s\n", errStr, ebuff);
- goto err_out;
+ goto fini;
}
md_len = sg_msense_calc_length(ref_md, alloc_len, mode_6, &bd_len);
if (md_len < 0) {
pr2serr("%ssg_msense_calc_length() failed\n", errStr);
- goto err_out;
+ goto fini;
}
hdr_len = mode_6 ? 4 : 8;
if (got_contents) {
if (read_in_len < 2) {
pr2serr("contents length=%d too short\n", read_in_len);
- goto err_out;
+ goto fini;
}
ref_md[0] = 0; /* mode data length reserved for mode select */
if (! mode_6)
@@ -497,7 +515,7 @@ int main(int argc, char * argv[])
if (md_len > alloc_len) {
pr2serr("mode data length=%d exceeds allocation length=%d\n",
md_len, alloc_len);
- goto err_out;
+ goto fini;
}
if (got_mask) {
for (k = 0; k < (md_len - off); ++k) {
@@ -514,45 +532,42 @@ int main(int argc, char * argv[])
if ((! (ref_md[off] & 0x80)) && save) {
pr2serr("PS bit in existing mode page indicates that it is "
"not saveable\n but '--save' option given\n");
- goto err_out;
+ goto fini;
}
read_in[0] &= 0x7f; /* mask out PS bit, reserved in mode select */
if ((md_len - off) != read_in_len) {
pr2serr("contents length=%d but reference mode page "
"length=%d\n", read_in_len, md_len - off);
- goto err_out;
+ goto fini;
}
if (pg_code != (read_in[0] & 0x3f)) {
pr2serr("contents page_code=0x%x but reference "
"page_code=0x%x\n", (read_in[0] & 0x3f), pg_code);
- goto err_out;
+ goto fini;
}
if ((read_in[0] & 0x40) != (ref_md[off] & 0x40)) {
pr2serr("contents flags subpage but reference page does not "
"(or vice versa)\n");
- goto err_out;
+ goto fini;
}
if ((read_in[0] & 0x40) && (read_in[1] != sub_pg_code)) {
pr2serr("contents subpage_code=0x%x but reference "
"sub_page_code=0x%x\n", read_in[1], sub_pg_code);
- goto err_out;
+ goto fini;
}
} else
md_len = off + read_in_len; /* force length */
memcpy(ref_md + off, read_in, read_in_len);
if (mode_6)
- res = sg_ll_mode_select6(sg_fd, true /* PF */, save, ref_md,
- md_len, true, verbose);
+ res = sg_ll_mode_select6_v2(sg_fd, true /* PF */, rtd, save,
+ ref_md, md_len, true, verbose);
else
- res = sg_ll_mode_select10(sg_fd, true /* PF */, save, ref_md,
- md_len, true, verbose);
+ res = sg_ll_mode_select10_v2(sg_fd, true /* PF */, rtd, save,
+ ref_md, md_len, true, verbose);
ret = res;
- if (res) {
- sg_get_category_sense_str(res, sizeof(b), b, verbose);
- pr2serr("MODE SELECT (%d): %s\n", (mode_6 ? 6 : 10), b);
- goto err_out;
- }
+ if (res)
+ goto fini;
} else {
printf(">>> No contents given, so show current mode page data:\n");
printf(" header:\n");
@@ -565,12 +580,31 @@ int main(int argc, char * argv[])
printf(" mode page:\n");
hex2stdout(ref_md + off, md_len - off, -1);
}
-err_out:
+ ret = 0;
+ goto fini;
+
+revert_to_defaults:
+ if (verbose)
+ pr2serr("Doing MODE SELECT(%d) with revert to defaults (RTD) set "
+ "and SP=%d\n", mode_6 ? 6 : 10, !! save);
+ if (mode_6)
+ res = sg_ll_mode_select6_v2(sg_fd, false /* PF */, true /* rtd */,
+ save, NULL, 0, true, verbose);
+ else
+ res = sg_ll_mode_select10_v2(sg_fd, false /* PF */, true /* rtd */,
+ save, NULL, 0, true, verbose);
+ ret = res;
+fini:
res = sg_cmds_close_device(sg_fd);
if (res < 0) {
pr2serr("close error: %s\n", safe_strerror(-res));
if (0 == ret)
- return SG_LIB_FILE_ERROR;
+ ret = SG_LIB_FILE_ERROR;
+ }
+ if (0 == verbose) {
+ if (! sg_if_can2stderr("sg_wr_mode failed: ", ret))
+ pr2serr("Some error occurred, try again with '-v' or '-vv' for "
+ "more information\n");
}
return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}