diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2020-01-25 12:58:12 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2020-01-25 12:58:12 +0000 |
commit | e541eac9a0aa7a5e9eaa9d1c9e3c58d7605963b0 (patch) | |
tree | 6fe48e57ba62239b1f043fcee45bab93688da043 /src | |
parent | 68c8a6cc83711259bd90e6296c63ee384d477b18 (diff) | |
download | sg3_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.c | 41 | ||||
-rw-r--r-- | src/sg_format.c | 287 | ||||
-rw-r--r-- | src/sg_inq.c | 6 | ||||
-rw-r--r-- | src/sg_luns.c | 7 | ||||
-rw-r--r-- | src/sg_modes.c | 19 | ||||
-rw-r--r-- | src/sg_readcap.c | 12 | ||||
-rw-r--r-- | src/sg_rep_zones.c | 8 | ||||
-rw-r--r-- | src/sg_seek.c | 9 | ||||
-rw-r--r-- | src/sg_vpd.c | 6 |
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)"}, |