aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2020-01-25 12:58:12 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2020-01-25 12:58:12 +0000
commite541eac9a0aa7a5e9eaa9d1c9e3c58d7605963b0 (patch)
tree6fe48e57ba62239b1f043fcee45bab93688da043 /src
parent68c8a6cc83711259bd90e6296c63ee384d477b18 (diff)
downloadsg3_utils-e541eac9a0aa7a5e9eaa9d1c9e3c58d7605963b0.tar.gz
sbc4r18+spc6r01 partial catch-up; sg_format: add FORMAT WITH PRESET support
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@839 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r--src/sg_dd.c41
-rw-r--r--src/sg_format.c287
-rw-r--r--src/sg_inq.c6
-rw-r--r--src/sg_luns.c7
-rw-r--r--src/sg_modes.c19
-rw-r--r--src/sg_readcap.c12
-rw-r--r--src/sg_rep_zones.c8
-rw-r--r--src/sg_seek.c9
-rw-r--r--src/sg_vpd.c6
9 files changed, 327 insertions, 68 deletions
diff --git a/src/sg_dd.c b/src/sg_dd.c
index 97513b76..f3782b2d 100644
--- a/src/sg_dd.c
+++ b/src/sg_dd.c
@@ -1,7 +1,7 @@
/* A utility program for copying files. Specialised for "files" that
* represent devices that understand the SCSI command set.
*
- * Copyright (C) 1999 - 2019 D. Gilbert and P. Allworth
+ * Copyright (C) 1999 - 2020 D. Gilbert and P. Allworth
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -66,7 +66,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "6.08 20191220";
+static const char * version_str = "6.09 20200117";
#define ME "sg_dd: "
@@ -94,6 +94,9 @@ static const char * version_str = "6.08 20191220";
#define READ_LONG_OPCODE 0x3E
#define READ_LONG_CMD_LEN 10
#define READ_LONG_DEF_BLK_INC 8
+#define VERIFY10 0x2f
+#define VERIFY12 0xaf
+#define VERIFY16 0x8f
#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
@@ -519,14 +522,18 @@ sg_build_scsi_cdb(uint8_t * cdbp, int cdb_sz, unsigned int blocks,
{
int sz_ind;
int rd_opcode[] = {0x8, 0x28, 0xa8, 0x88};
- int ve_opcode[] = {0xff /* no VERIFY(6) */, 0x2f, 0xaf, 0x8f};
+ int ve_opcode[] = {0xff /* no VERIFY(6) */, VERIFY10, VERIFY12, VERIFY16};
int wr_opcode[] = {0xa, 0x2a, 0xaa, 0x8a};
memset(cdbp, 0, cdb_sz);
- if (dpo)
- cdbp[1] |= 0x10;
- if (fua)
- cdbp[1] |= 0x8;
+ if (is_verify)
+ cdbp[1] = 0x2; /* (BYTCHK=1) << 1 */
+ else {
+ if (dpo)
+ cdbp[1] |= 0x10;
+ if (fua)
+ cdbp[1] |= 0x8;
+ }
switch (cdb_sz) {
case 6:
sz_ind = 0;
@@ -657,6 +664,7 @@ sg_read_low(int sg_fd, uint8_t * buff, int blocks, int64_t from_block,
slen = io_hdr.sb_len_wr;
switch (res) {
case SG_LIB_CAT_CLEAN:
+ case SG_LIB_CAT_CONDITION_MET:
break;
case SG_LIB_CAT_RECOVERED:
++recovered_errs;
@@ -1016,6 +1024,7 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
bool info_valid;
int res;
uint64_t io_addr = 0;
+ const char * op_str = do_verify ? "verifying" : "writing";
uint8_t wrCmd[MAX_SCSI_CDBSZ];
uint8_t senseBuff[SENSE_BUFF_LEN];
struct sg_io_hdr io_hdr;
@@ -1050,7 +1059,10 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
if (res < 0) {
if (ENOMEM == errno)
return -2;
- perror("writing (SG_IO) on sg device, error");
+ if (do_verify)
+ perror("verifying (SG_IO) on sg device, error");
+ else
+ perror("writing (SG_IO) on sg device, error");
return -1;
}
@@ -1059,6 +1071,7 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_CLEAN:
+ case SG_LIB_CAT_CONDITION_MET:
break;
case SG_LIB_CAT_RECOVERED:
++recovered_errs;
@@ -1068,16 +1081,16 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
pr2serr(" lba of last recovered error in this WRITE=0x%" PRIx64
"\n", io_addr);
if (verbose > 1)
- sg_chk_n_print3("writing", &io_hdr, true);
+ sg_chk_n_print3(op_str, &io_hdr, true);
} else {
- pr2serr("Recovered error: [no info] writing to block=0x%" PRIx64
- ", num=%d\n", to_block, blocks);
- sg_chk_n_print3("writing", &io_hdr, verbose > 1);
+ pr2serr("Recovered error: [no info] %s to block=0x%" PRIx64
+ ", num=%d\n", op_str, to_block, blocks);
+ sg_chk_n_print3(op_str, &io_hdr, verbose > 1);
}
break;
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
- sg_chk_n_print3("writing", &io_hdr, verbose > 1);
+ sg_chk_n_print3(op_str, &io_hdr, verbose > 1);
return res;
case SG_LIB_CAT_NOT_READY:
++unrecovered_errs;
@@ -1085,7 +1098,7 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
return res;
case SG_LIB_CAT_MEDIUM_HARD:
default:
- sg_chk_n_print3("writing", &io_hdr, verbose > 1);
+ sg_chk_n_print3(op_str, &io_hdr, verbose > 1);
++unrecovered_errs;
if (ofp->coe) {
pr2serr(">> ignored errors for out blk=%" PRId64 " for %d "
diff --git a/src/sg_format.c b/src/sg_format.c
index f30a4e6d..24f94bf6 100644
--- a/src/sg_format.c
+++ b/src/sg_format.c
@@ -6,7 +6,7 @@
*
* Copyright (C) 2003 Grant Grundler grundler at parisc-linux dot org
* Copyright (C) 2003 James Bottomley jejb at parisc-linux dot org
- * Copyright (C) 2005-2019 Douglas Gilbert dgilbert at interlog dot com
+ * Copyright (C) 2005-2020 Douglas Gilbert dgilbert at interlog dot com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -40,7 +40,7 @@
#include "sg_pr2serr.h"
#include "sg_pt.h"
-static const char * version_str = "1.60 20191220";
+static const char * version_str = "1.61 20200123";
#define RW_ERROR_RECOVERY_PAGE 1 /* can give alternate with --mode=MP */
@@ -72,6 +72,11 @@ static const char * version_str = "1.60 20191220";
/* FORMAT UNIT (SBC) and FORMAT MEDIUM (SSC) share the same opcode */
#define SG_FORMAT_MEDIUM_CMD 0x4
#define SG_FORMAT_MEDIUM_CMDLEN 6
+
+/* FORMAT WITH PRESET (new in sbc4r18) */
+#define SG_FORMAT_WITH_PRESET_CMD 0x38
+#define SG_FORMAT_WITH_PRESET_CMDLEN 10
+
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
struct opts_t {
@@ -79,13 +84,15 @@ struct opts_t {
bool cmplst_given;
bool dry_run; /* -d */
bool early; /* -e */
- bool fwait; /* -w (negate for immed) */
+ bool fmtmaxlba; /* -b (only with F_WITH_PRESET) */
+ bool fwait; /* -w (negated form IMMED) */
bool ip_def; /* -I */
bool long_lba; /* -l */
bool mode6; /* -6 */
bool pinfo; /* -p, deprecated, prefer fmtpinfo */
bool poll_type; /* -x 0|1 */
bool poll_type_given;
+ bool preset; /* -E */
bool quick; /* -Q */
bool do_rcap16; /* -l */
bool resize; /* -r */
@@ -98,6 +105,7 @@ struct opts_t {
int ffmt; /* -t value; fast_format if > 0 */
int fmtpinfo;
int format; /* -F */
+ uint32_t p_id; /* set by argument of --preset=id */
int mode_page; /* -M value */
int pfu; /* -P value */
int pie; /* -q value */
@@ -120,6 +128,7 @@ static struct option long_options[] = {
{"dry_run", no_argument, 0, 'd'},
{"early", no_argument, 0, 'e'},
{"ffmt", required_argument, 0, 't'},
+ {"fmtmaxlba", no_argument, 0, 'b'},
{"fmtpinfo", required_argument, 0, 'f'},
{"format", no_argument, 0, 'F'},
{"help", no_argument, 0, 'h'},
@@ -131,6 +140,7 @@ static struct option long_options[] = {
{"pfu", required_argument, 0, 'P'},
{"pie", required_argument, 0, 'q'},
{"poll", required_argument, 0, 'x'},
+ {"preset", required_argument, 0, 'E'},
{"quick", no_argument, 0, 'Q'},
{"resize", no_argument, 0, 'r'},
{"rto_req", no_argument, 0, 'R'},
@@ -153,15 +163,17 @@ usage()
printf("Usage:\n"
" sg_format [--cmplst=0|1] [--count=COUNT] [--dcrt] "
"[--dry-run] [--early]\n"
- " [--ffmt=FFMT] [--fmtpinfo=FPI] [--format] "
- "[--help] [--ip-def]\n"
- " [--long] [--mode=MP] [--pfu=PFU] [--pie=PIE] "
- "[--pinfo]\n"
- " [--poll=PT] [--quick] [--resize] [--rto_req] "
- "[--security]\n"
- " [--six] [--size=LB_SZ] [--tape=FM] "
- "[--timeout=SECS] [--verbose]\n"
- " [--verify] [--version] [--wait] DEVICE\n"
+ " [--ffmt=FFMT] [--fmtmaxlba] [--fmtpinfo=FPI] "
+ "[--format] [--help]\n"
+ " [--ip-def] [--long] [--mode=MP] [--pfu=PFU] "
+ "[--pie=PIE]\n"
+ " [--pinfo] [--poll=PT] [--preset=ID] [--quick] "
+ "[--resize]\n"
+ " [--rto_req] [--security] [--six] [--size=LB_SZ] "
+ "[--tape=FM]\n"
+ " [--timeout=SECS] [--verbose] [--verify] "
+ "[--version] [--wait]\n"
+ " DEVICE\n"
" where:\n"
" --cmplst=0|1\n"
" -C 0|1 sets CMPLST bit in format cdb "
@@ -190,6 +202,8 @@ usage()
"count and size)\n"
" use thrice for FORMAT UNIT command "
"only\n"
+ " --fmtmaxlba|-b sets FMTMAXLBA field in FORMAT WITH "
+ "PRESET\n"
" --help|-h prints out this usage message\n"
" --ip-def|-I use default initialization pattern\n"
" --long|-l allow for 64 bit lbas (default: assume "
@@ -204,8 +218,12 @@ usage()
" --poll=PT|-x PT PT is poll type, 0 for test unit "
"ready\n"
" 1 for request sense (def: 0 (1 "
- "for tape))\n");
- printf(" --quick|-Q start format without pause for user "
+ "for tape and\n"
+ " format with preset))\n");
+ printf(" --preset=ID|-E ID do FORMAT WITH PRESET command "
+ "with PRESET\n"
+ " IDENTIFIER field set to ID\n"
+ " --quick|-Q start format without pause for user "
"intervention\n"
" (i.e. no time to reconsider)\n"
" --resize|-r resize (rather than format) to COUNT "
@@ -231,17 +249,19 @@ usage()
" --verbose|-v increase verbosity\n"
" --verify|-y sets VERIFY bit in FORMAT MEDIUM (tape)\n"
" --version|-V print version details and exit\n"
- " --wait|-w format command waits until format "
- "operation completes\n"
+ " --wait|-w format commands wait until format "
+ "operations complete\n"
" (default: set IMMED=1 and poll with "
"Test Unit Ready)\n\n"
"\tExample: sg_format --format /dev/sdc\n\n"
"This utility formats a SCSI disk [FORMAT UNIT] or resizes "
"it. Alternatively\nif '--tape=FM' is given formats a tape "
- "[FORMAT MEDIUM].\n\n");
- printf("WARNING: This utility will destroy all the data on "
- "DEVICE when '--format'\n\t or '--tape' is given. Check that "
- "you have specified the correct\n\t DEVICE.\n");
+ "[FORMAT MEDIUM]. Another alternative\nis doing the FORMAT "
+ "WITH PRESET command when '--preset=ID' is given.\n\n");
+ printf("WARNING: This utility will destroy all the data on the "
+ "DEVICE when\n\t '--format', '--tape=FM' or '--preset=ID' "
+ "is given. Double check\n\t that you have specified the "
+ "correct DEVICE.\n");
}
/* Invokes a SCSI FORMAT MEDIUM command (SSC). Return of 0 -> success,
@@ -302,6 +322,61 @@ sg_ll_format_medium(int sg_fd, bool verify, bool immed, int format,
return ret;
}
+/* Invokes a SCSI FORMAT WITH PRESET command (SBC). Return of 0 -> success,
+ * various SG_LIB_CAT_* positive values or -1 -> other errors */
+static int
+sg_ll_format_with_preset(int sg_fd, bool immed, bool fmtmaxlba,
+ uint32_t preset_id, int timeout, bool noisy,
+ int verbose)
+{
+ int ret, res, sense_cat;
+ uint8_t fwp_cdb[SG_FORMAT_WITH_PRESET_CMDLEN] =
+ {SG_FORMAT_WITH_PRESET_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t sense_b[SENSE_BUFF_LEN];
+ struct sg_pt_base * ptvp;
+
+ if (immed)
+ fwp_cdb[1] |= 0x80;
+ if (fmtmaxlba)
+ fwp_cdb[1] |= 0x40;
+ if (preset_id > 0)
+ sg_put_unaligned_be32(preset_id, fwp_cdb + 2);
+ if (verbose) {
+ char b[128];
+
+ pr2serr(" Format with preset cdb: %s\n",
+ sg_get_command_str(fwp_cdb,
+ SG_FORMAT_WITH_PRESET_CMDLEN,
+ false, sizeof(b), b));
+ }
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ pr2serr("%s: out of memory\n", __func__);
+ return sg_convert_errno(ENOMEM);
+ }
+ set_scsi_pt_cdb(ptvp, fwp_cdb, sizeof(fwp_cdb));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ res = do_scsi_pt(ptvp, sg_fd, timeout, verbose);
+ ret = sg_cmds_process_resp(ptvp, "format with preset", res, noisy,
+ verbose, &sense_cat);
+ 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:
+ ret = 0;
+ break;
+ default:
+ ret = sense_cat;
+ break;
+ }
+ } else
+ ret = 0;
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
/* Return 0 on success, else see sg_ll_format_unit_v2() */
static int
scsi_format_unit(int fd, const struct opts_t * op)
@@ -493,7 +568,7 @@ scsi_format_medium(int fd, const struct opts_t * op)
tmout = op->timeout;
if (op->dry_run) {
res = 0;
- pr2serr("Due to --dry-run option bypassing FORMAT UNIT "
+ pr2serr("Due to --dry-run option bypassing FORMAT MEDIUM "
"command\n");
} else
res = sg_ll_format_medium(fd, op->verify, immed,
@@ -580,6 +655,114 @@ scsi_format_medium(int fd, const struct opts_t * op)
return 0;
}
+/* Return 0 on success, else see sg_ll_format_medium() above */
+static int
+scsi_format_with_preset(int fd, const struct opts_t * op)
+{
+ int res, progress, pr, rem, resp_len, tmout;
+ int vb = op->verbose;
+ bool immed = ! op->fwait;
+ char b[80];
+
+ if (immed)
+ tmout = SHORT_TIMEOUT;
+ else {
+ if (op->total_byte_count > EIGHT_TBYTE)
+ tmout = VLONG_FORMAT_TIMEOUT;
+ else if (op->total_byte_count > FOUR_TBYTE)
+ tmout = LONG_FORMAT_TIMEOUT;
+ else
+ tmout = FORMAT_TIMEOUT;
+ }
+ if (op->timeout > tmout)
+ tmout = op->timeout;
+ if (op->dry_run) {
+ res = 0;
+ pr2serr("Due to --dry-run option bypassing FORMAT WITH "
+ "PRESET command\n");
+ } else
+ res = sg_ll_format_with_preset(fd, immed, op->fmtmaxlba,
+ op->p_id, tmout, true, vb);
+ if (res) {
+ sg_get_category_sense_str(res, sizeof(b), b, vb);
+ pr2serr("Format with preset command: %s\n", b);
+ return res;
+ }
+ if (! immed)
+ return 0;
+
+ if (! op->dry_run)
+ printf("\nFormat with preset has started\n");
+ if (op->early) {
+ if (immed)
+ printf("Format continuing,\n Request sense can "
+ "be used to monitor progress\n");
+ return 0;
+ }
+
+ if (op->dry_run) {
+ printf("No point in polling for progress, so exit\n");
+ return 0;
+ }
+ if (! op->poll_type) {
+ for(;;) {
+ sleep_for(POLL_DURATION_SECS);
+ progress = -1;
+ res = sg_ll_test_unit_ready_progress(fd, 0, &progress,
+ true, (vb > 1) ? (vb - 1) : 0);
+ if (progress >= 0) {
+ pr = (progress * 100) / 65536;
+ rem = ((progress * 100) % 65536) / 656;
+ printf("Format in progress, %d.%02d%% done\n",
+ pr, rem);
+ } else
+ break;
+ }
+ }
+ if (op->poll_type || (SG_LIB_CAT_NOT_READY == res)) {
+ uint8_t * reqSense;
+ uint8_t * free_reqSense = NULL;
+
+ reqSense = sg_memalign(MAX_BUFF_SZ, 0, &free_reqSense, false);
+ if (NULL == reqSense) {
+ pr2serr("%s: unable to obtain heap for Request "
+ "Sense\n", __func__);
+ return sg_convert_errno(ENOMEM);
+ }
+ for(;;) {
+ sleep_for(POLL_DURATION_SECS);
+ memset(reqSense, 0x0, MAX_BUFF_SZ);
+ res = sg_ll_request_sense(fd, false, reqSense,
+ MAX_BUFF_SZ, false,
+ (vb > 1) ? (vb - 1) : 0);
+ if (res) {
+ pr2serr("polling with Request Sense command "
+ "failed [res=%d]\n", res);
+ break;
+ }
+ resp_len = reqSense[7] + 8;
+ if (vb > 1) {
+ pr2serr("Parameter data in hex:\n");
+ hex2stderr(reqSense, resp_len, 1);
+ }
+ progress = -1;
+ sg_get_sense_progress_fld(reqSense, resp_len,
+ &progress);
+ if (progress >= 0) {
+ pr = (progress * 100) / 65536;
+ rem = ((progress * 100) % 65536) / 656;
+ printf("Format in progress, %d.%02d%% done\n",
+ pr, rem);
+ } else
+ break;
+ }
+ if (free_reqSense)
+ free(free_reqSense);
+ }
+ printf("FORMAT WITH PRESET Complete\n");
+ return 0;
+}
+
#define VPD_DEVICE_ID 0x83
#define VPD_ASSOC_LU 0
#define VPD_ASSOC_TPORT 1
@@ -1033,6 +1216,7 @@ static int
parse_cmd_line(struct opts_t * op, int argc, char **argv)
{
int j;
+ int64_t ll;
op->cmplst = true; /* will be set false if FFMT > 0 */
op->mode_page = RW_ERROR_RECOVERY_PAGE;
@@ -1043,12 +1227,15 @@ parse_cmd_line(struct opts_t * op, int argc, char **argv)
int c;
c = getopt_long(argc, argv,
- "c:C:dDef:FhIlm:M:pP:q:QrRs:St:T:vVwx:y6",
+ "bc:C:dDeE:f:FhIlm:M:pP:q:QrRs:St:T:vVwx:y6",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
+ case 'b':
+ op->fmtmaxlba = true;
+ break;
case 'c':
if (0 == strcmp("-1", optarg))
op->blk_count = -1;
@@ -1079,6 +1266,17 @@ parse_cmd_line(struct opts_t * op, int argc, char **argv)
case 'e':
op->early = true;
break;
+ case 'E':
+ ll = sg_get_llnum(optarg);
+ if ((ll < 0) || (ll > UINT32_MAX)) {
+ pr2serr("bad argument to '--preset', need 32 "
+ "bit integer\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->p_id = (uint32_t)ll;
+ op->preset = true;
+ op->poll_type = 1; /* poll with REQUEST SENSE */
+ break;
case 'f':
op->fmtpinfo = sg_get_num(optarg);
if ((op->fmtpinfo < 0) || ( op->fmtpinfo > 3)) {
@@ -1240,9 +1438,10 @@ parse_cmd_line(struct opts_t * op, int argc, char **argv)
usage();
return SG_LIB_SYNTAX_ERROR;
}
- if (op->format && (op->tape >= 0)) {
- pr2serr("Cannot choose both '--format' and '--tape='; disk "
- "or tape, choose one only\n");
+ if (((int)(op->format > 0) + (int)(op->tape >= 0) + (int)op->preset)
+ > 1) {
+ pr2serr("Can choose only one of: '--format', '--tape=' and "
+ "'--preset='\n");
return SG_LIB_CONTRADICT;
}
if (op->ip_def && op->sec_init) {
@@ -1352,7 +1551,8 @@ main(int argc, char **argv)
goto out;
}
goto format_med;
- }
+ } else if (op->preset)
+ goto format_with_pre;
ret = fetch_block_desc(fd, dbuff, &calc_len, &bd_lb_sz, op);
if (ret) {
@@ -1428,7 +1628,6 @@ again_sp_false:
if (op->format) {
format_only:
-#if 1
if (op->quick)
goto skip_f_unit_reconsider;
printf("\nA FORMAT UNIT will commence in 15 seconds\n");
@@ -1455,9 +1654,6 @@ skip_f_unit_reconsider:
pr2serr(" try '-v' for more "
"information\n");
}
-#else
- pr2serr("FORMAT UNIT ignored, testing\n");
-#endif
}
goto out;
@@ -1487,8 +1683,35 @@ skip_f_med_reconsider:
if (res) {
pr2serr("FORMAT MEDIUM failed\n");
if (0 == vb)
- pr2serr(" try '-v' for more "
- "information\n");
+ pr2serr(" try '-v' for more information\n");
+ }
+ goto out;
+
+format_with_pre:
+ if (op->quick)
+ goto skip_f_with_pre_reconsider;
+ printf("\nA FORMAT WITH PRESET will commence in 15 seconds\n");
+ printf(" ALL data on %s will be DESTROYED\n",
+ op->device_name);
+ printf(" Press control-C to abort\n");
+ sleep_for(5);
+ printf("\nA FORMAT WITH PRESET will commence in 10 seconds\n");
+ printf(" ALL data on %s will be DESTROYED\n",
+ op->device_name);
+ printf(" Press control-C to abort\n");
+ sleep_for(5);
+ printf("\nA FORMAT WITH PRESET will commence in 5 seconds\n");
+ printf(" ALL data on %s will be DESTROYED\n",
+ op->device_name);
+ printf(" Press control-C to abort\n");
+ sleep_for(5);
+skip_f_with_pre_reconsider:
+ res = scsi_format_with_preset(fd, op);
+ ret = res;
+ if (res) {
+ pr2serr("FORMAT WITH PRESET failed\n");
+ if (0 == vb)
+ pr2serr(" try '-v' for more information\n");
}
out:
diff --git a/src/sg_inq.c b/src/sg_inq.c
index f1df8085..8aec3763 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 2000-2019 D. Gilbert
+ * Copyright (C) 2000-2020 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -51,7 +51,7 @@
#include "sg_pt_nvme.h"
#endif
-static const char * version_str = "2.03 20190913"; /* SPC-5 rev 22 */
+static const char * version_str = "2.04 20200123"; /* SPC-6 rev 01 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -108,6 +108,7 @@ static const char * version_str = "2.03 20190913"; /* SPC-5 rev 22 */
#define VPD_BLOCK_DEV_C_EXTENS 0xb5 /* sbc4r02 */
#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
+#define VPD_FORMAT_PRESETS 0xb8 /* sbc4r18 */
#ifndef SG_NVME_VPD_NICR
#define SG_NVME_VPD_NICR 0xde
@@ -190,6 +191,7 @@ static struct svpd_values_name_t vpd_pg[] = {
"identification, target device only"},
#endif
{VPD_EXT_INQ, 0, -1, 0, "ei", "Extended inquiry data"},
+ {VPD_FORMAT_PRESETS, 0, 0, 0, "fp", "Format presets"},
{VPD_LB_PROVISIONING, 0, 0, 0, "lbpv", "Logical block provisioning "
"(SBC)"},
{VPD_MAN_NET_ADDR, 0, -1, 0, "mna", "Management network addresses"},
diff --git a/src/sg_luns.c b/src/sg_luns.c
index 555e14d6..5217ea98 100644
--- a/src/sg_luns.c
+++ b/src/sg_luns.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2019 Douglas Gilbert.
+ * Copyright (c) 2004-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.
@@ -34,7 +34,7 @@
* and decodes the response.
*/
-static const char * version_str = "1.43 20190913";
+static const char * version_str = "1.44 20200115";
#define MAX_RLUNS_BUFF_LEN (1024 * 1024)
#define DEF_RLUNS_BUFF_LEN (1024 * 8)
@@ -252,6 +252,9 @@ decode_lun(const char * leadin, const uint8_t * lunp, bool lu_cong,
case 5:
printf("%sMANAGEMENT PROTOCOL %s\n", l_leadin, b);
break;
+ case 6:
+ printf("%sTARGET COMMANDS %s\n", l_leadin, b);
+ break;
default:
if (do_hex)
printf("%s%s 0x%02x\n", l_leadin, b, x);
diff --git a/src/sg_modes.c b/src/sg_modes.c
index dc8c4691..06d96334 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -32,7 +32,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.69 20200111";
+static const char * version_str = "1.71 20200121";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -253,6 +253,15 @@ static struct page_code_desc pc_desc_t_adc[] = {
{0x0, 0x0, NULL, NULL},
};
+static struct page_code_desc pc_desc_zbc[] = {
+ {0x1, 0x0, "rw", "Read-Write error recovery"},
+ {0x7, 0x0, "ve", "Verify error recovery"},
+ {0x8, 0x0, "ca", "Caching"},
+ {0xa, 0x2, "atag", "Application tag"},
+ {0x1c, 0x1, "bc", "Background control"},
+ {0x0, 0x0, NULL, NULL},
+};
+
struct pc_desc_group pcd_gr_arr[] = {
{pc_desc_common, "common"},
{pc_desc_disk, "disk"},
@@ -263,6 +272,7 @@ struct pc_desc_group pcd_gr_arr[] = {
{pc_desc_ses, "enclosure"},
{pc_desc_rbc, "reduced block"},
{pc_desc_adc, "adc"},
+ {pc_desc_zbc, "zbc"},
{pc_desc_t_fcp, "transport: FCP"},
{pc_desc_t_spi4, "transport: SPI"},
{pc_desc_t_sas, "transport: SAS"},
@@ -821,6 +831,9 @@ get_mpage_tbl_size(int scsi_ptype, int * sizep)
case PDT_ADC: /* automation device/interface */
*sizep = count_desc_elems(pc_desc_adc);
return &pc_desc_adc[0];
+ case PDT_ZBC:
+ *sizep = count_desc_elems(pc_desc_zbc);
+ return &pc_desc_zbc[0];
}
*sizep = 0;
return NULL;
@@ -1421,7 +1434,7 @@ main(int argc, char * argv[])
hex2stdout(rsp_buff, headerlen, 1);
goto fini;
}
- if (0 == inq_pdt)
+ if ((PDT_DISK == inq_pdt) || (PDT_ZBC == inq_pdt))
printf(" Mode data length=%d, medium type=0x%.2x, WP=%d,"
" DpoFua=%d, longlba=%d\n", md_len, medium_type,
!!(specific & 0x80), !!(specific & 0x10), (int)longlba);
@@ -1448,7 +1461,7 @@ main(int argc, char * argv[])
len = 16;
density_code_off = 8;
}
- else if (0 == inq_pdt) {
+ else if ((PDT_DISK == inq_pdt) || (PDT_ZBC == inq_pdt)) {
printf("> Direct access device block descriptors:\n");
density_code_off = 4;
}
diff --git a/src/sg_readcap.c b/src/sg_readcap.c
index a383ef84..571f92e3 100644
--- a/src/sg_readcap.c
+++ b/src/sg_readcap.c
@@ -1,7 +1,7 @@
/* This code is does a SCSI READ CAPACITY command on the given device
* and outputs the result.
*
- * Copyright (C) 1999 - 2018 D. Gilbert
+ * Copyright (C) 1999 - 2020 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -36,7 +36,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "4.04 20180911";
+static const char * version_str = "4.05 20200122";
#define ME "sg_readcap: "
@@ -83,12 +83,14 @@ struct opts_t {
static void
usage()
{
- pr2serr("Usage: sg_readcap [--brief] [--help] [--hex] [--lba=LBA] "
- "[--long] [--16]\n"
+ pr2serr("Usage: sg_readcap [--16] [--brief] [--help] [--hex] "
+ "[--lba=LBA] [--long]\n"
" [--pmi] [--raw] [--readonly] [--verbose] "
"[--version]\n"
" [--zbc] DEVICE\n"
" where:\n"
+ " --16 use READ CAPACITY (16) cdb (same as "
+ "--long)\n"
" --brief|-b brief, two hex numbers: number of blocks "
"and block size\n"
" --help|-h print this usage message and exit\n"
@@ -99,8 +101,6 @@ usage()
"valid with '--pmi']\n"
" --long|-l use READ CAPACITY (16) cdb (def: use "
"10 byte cdb)\n"
- " --16 use READ CAPACITY (16) cdb (same as "
- "--long)\n"
" --pmi|-p partial medium indicator (without this "
"option shows\n"
" total disk capacity) [made obsolete in "
diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c
index 3be9f5f0..cf390f19 100644
--- a/src/sg_rep_zones.c
+++ b/src/sg_rep_zones.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2019 Douglas Gilbert.
+ * Copyright (c) 2014-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.
@@ -38,7 +38,7 @@
* and decodes the response. Based on zbc-r02.pdf
*/
-static const char * version_str = "1.19 20191226";
+static const char * version_str = "1.20 20200122";
#define MAX_RZONES_BUFF_LEN (1024 * 1024)
#define DEF_RZONES_BUFF_LEN (1024 * 8)
@@ -472,8 +472,8 @@ main(int argc, char * argv[])
goto the_end;
}
same = reportZonesBuff[4] & 0xf;
- printf(" Same=%d: %s\n\n", same, same_desc_arr[same]);
- printf(" Maximum LBA: 0x%" PRIx64 "\n",
+ printf(" Same=%d: %s\n", same, same_desc_arr[same]);
+ printf(" Maximum LBA: 0x%" PRIx64 "\n\n",
sg_get_unaligned_be64(reportZonesBuff + 8));
zones = (len - 64) / 64;
for (k = 0, bp = reportZonesBuff + 64; k < zones; ++k, bp += 64) {
diff --git a/src/sg_seek.c b/src/sg_seek.c
index 9084fd75..f99c1f0f 100644
--- a/src/sg_seek.c
+++ b/src/sg_seek.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 Douglas Gilbert.
+ * Copyright (c) 2018-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.
@@ -49,7 +49,7 @@
* to that LBA ...
*/
-static const char * version_str = "1.07 20180911";
+static const char * version_str = "1.08 20200115";
#define BACKGROUND_CONTROL_SA 0x15
@@ -418,7 +418,10 @@ fini:
}
}
if (0 == verbose) {
- if (! sg_if_can2stderr("sg_seek failed: ", ret))
+ const char * e_str = (SG_LIB_CAT_CONDITION_MET == ret) ?
+ "sg_seek: " : "sg_seek: failed";
+
+ if (! sg_if_can2stderr(e_str, ret))
pr2serr("Some error occurred, try again with '-v' "
"or '-vv' for more information\n");
}
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index f18d8096..b91261af 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2019 Douglas Gilbert.
+ * Copyright (c) 2006-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.
@@ -40,7 +40,7 @@
*/
-static const char * version_str = "1.56 20191204"; /* spc5r22 + sbc4r17 */
+static const char * version_str = "1.57 20200123"; /* spc6r01 + sbc4r18 */
/* standard VPD pages, in ascending page number order */
#define VPD_SUPPORTED_VPDS 0x0
@@ -78,6 +78,7 @@ static const char * version_str = "1.56 20191204"; /* spc5r22 + sbc4r17 */
#define VPD_LB_PROTECTION 0xb5 /* SSC-5 */
#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
+#define VPD_FORMAT_PRESETS 0xb8 /* sbc4r18 */
#define VPD_NOPE_WANT_STD_INQ -2 /* request for standard inquiry */
/* Device identification VPD page associations */
@@ -210,6 +211,7 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{VPD_DTDE_ADDRESS, 0, 1, "dtde",
"Data transfer device element address (SSC)"},
{VPD_EXT_INQ, 0, -1, "ei", "Extended inquiry data"},
+ {VPD_FORMAT_PRESETS, 0, 0, "fp", "Format presets"},
{VPD_IMP_OP_DEF, 0, -1, "iod",
"Implemented operating definition (obsolete)"},
{VPD_LB_PROTECTION, 0, 0, "lbpro", "Logical block protection (SSC)"},