aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2022-02-18 05:36:07 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2022-02-18 05:36:07 +0000
commit8385f6006c857fb6a7e66b4b29da1d91c5300bb6 (patch)
treeab5c5d5dd98601663aaaa68e1b7b88d6e52fa0ad /src
parentb3918431020005cc1fbf1d3fe836da0048c15c8c (diff)
downloadsg3_utils-8385f6006c857fb6a7e66b4b29da1d91c5300bb6.tar.gz
sg_read_buffer: add --eh_code= and --no_output options; sg_inq, sg_vpd: Device Identication VPD page, change IEEE Company_id to AOI
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@938 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r--src/sg_inq.c39
-rw-r--r--src/sg_read_buffer.c449
-rw-r--r--src/sg_vpd.c10
-rw-r--r--src/sg_vpd_vendor.c17
-rw-r--r--src/sg_write_x.c5
-rw-r--r--src/sg_z_act_query.c5
6 files changed, 324 insertions, 201 deletions
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 38b033b6..92333975 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -51,7 +51,7 @@
#include "sg_pt_nvme.h"
#endif
-static const char * version_str = "2.14 20220109"; /* spc6r06 */
+static const char * version_str = "2.16 20220217"; /* spc6r06 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -1337,12 +1337,11 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
{
int u, j, m, id_len, p_id, c_set, piv, assoc, desig_type, i_len;
int off, ci_off, c_id, d_id, naa, vsi, k;
- uint64_t vsei;
- uint64_t id_ext;
+ uint64_t vsei, id_ext, ccc_id;
const uint8_t * bp;
const uint8_t * ip;
- char b[64];
const char * cp;
+ char b[64];
if (buff[2] != 0) {
/*
@@ -1452,11 +1451,8 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
hex2stderr(ip, i_len, -1);
break;
}
- c_id = sg_get_unaligned_be24(ip + ci_off);
- printf(" IEEE Company_id: 0x%x\n", c_id);
- vsei = sg_get_unaligned_be48(ip + ci_off + 3);
- printf(" Vendor Specific Extension Identifier: 0x%" PRIx64
- "\n", vsei);
+ ccc_id = sg_get_unaligned_be64(ip + ci_off);
+ printf(" IEEE identifier: 0x%" PRIx64 "\n", ccc_id);
if (12 == i_len) {
d_id = sg_get_unaligned_be32(ip + 8);
printf(" Directory ID: 0x%x\n", d_id);
@@ -1487,7 +1483,7 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
vsi = sg_get_unaligned_be24(ip + 5);
printf(" NAA 2, vendor specific identifier A: 0x%x\n",
d_id);
- printf(" IEEE Company_id: 0x%x\n", c_id);
+ printf(" AOI: 0x%x\n", c_id);
printf(" vendor specific identifier B: 0x%x\n", vsi);
printf(" [0x");
for (m = 0; m < 8; ++m)
@@ -1521,7 +1517,7 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
vsei <<= 8;
vsei |= ip[3 + m];
}
- printf(" NAA 5, IEEE Company_id: 0x%x\n", c_id);
+ printf(" NAA 5, AOI: 0x%x\n", c_id);
printf(" Vendor Specific Identifier: 0x%" PRIx64
"\n", vsei);
printf(" [0x");
@@ -1543,7 +1539,7 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
vsei <<= 8;
vsei |= ip[3 + m];
}
- printf(" NAA 6, IEEE Company_id: 0x%x\n", c_id);
+ printf(" NAA 6, AOI: 0x%x\n", c_id);
printf(" Vendor Specific Identifier: 0x%" PRIx64 "\n",
vsei);
vsei = sg_get_unaligned_be64(ip + 8);
@@ -2032,9 +2028,8 @@ decode_softw_inf_id(uint8_t * buff, int len, int do_hex)
len -= 4;
buff += 4;
for ( ; len > 5; len -= 6, buff += 6)
- printf(" IEEE Company_id: 0x%06x, vendor specific extension "
- "id: 0x%06x\n", sg_get_unaligned_be24(buff + 0),
- sg_get_unaligned_be24(buff + 3));
+ printf(" IEEE identifier: 0x%" PRIx64 "\n",
+ sg_get_unaligned_be48(buff + 0));
}
/* VPD_ATA_INFO [0x89] */
@@ -2189,7 +2184,7 @@ decode_b0_vpd(uint8_t * buff, int len, int do_hex)
}
pdt = PDT_MASK & buff[0];
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
if (len < 16) {
pr2serr("Block limits VPD page length too short=%d\n", len);
return;
@@ -2335,7 +2330,7 @@ decode_b1_vpd(uint8_t * buff, int len, int do_hex)
}
pdt = PDT_MASK & buff[0];
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
if (len < 64) {
pr2serr("Block device characteristics VPD page length too "
"short=%d\n", len);
@@ -2410,7 +2405,7 @@ decode_b3_vpd(uint8_t * buff, int len, int do_hex)
}
pdt = PDT_MASK & buff[0];
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
if (len < 0x10) {
pr2serr("Referrals VPD page length too short=%d\n", len);
return;
@@ -3541,7 +3536,7 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
pdt = rp[0] & PDT_MASK;
if (! op->do_raw && (op->do_hex < 2)) {
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
printf("VPD INQUIRY: Block limits page (SBC)\n");
break;
case PDT_TAPE: case PDT_MCHANGER:
@@ -3569,7 +3564,7 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
pdt = rp[0] & PDT_MASK;
if (! op->do_raw && (op->do_hex < 2)) {
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
printf("VPD INQUIRY: Block device characteristics page "
"(SBC)\n");
break;
@@ -3607,7 +3602,7 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
pdt = rp[0] & PDT_MASK;
if (! op->do_raw && (op->do_hex < 2)) {
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
printf("VPD INQUIRY: Referrals VPD page (SBC)\n");
break;
default:
@@ -3902,7 +3897,7 @@ show_nvme_id_ctrl(const uint8_t *dinp, const char *dev_name, int do_long)
printf(" PCI vendor ID VID/SSVID: 0x%x/0x%x\n",
sg_get_unaligned_le16(dinp + 0),
sg_get_unaligned_le16(dinp + 2));
- printf(" IEEE OUI Identifier: 0x%x\n",
+ printf(" IEEE OUI Identifier: 0x%x\n", /* this has been renamed AOI */
sg_get_unaligned_le24(dinp + 73));
got_fguid = ! sg_all_zeros(dinp + 112, 16);
if (got_fguid) {
diff --git a/src/sg_read_buffer.c b/src/sg_read_buffer.c
index 01a79c33..cbc5023b 100644
--- a/src/sg_read_buffer.c
+++ b/src/sg_read_buffer.c
@@ -39,8 +39,7 @@
* device.
*/
-static const char * version_str = "1.34 20220118"; /* spc6r05 */
-
+static const char * version_str = "1.35 20220217"; /* spc6r06 */
#ifndef SG_READ_BUFFER_10_CMD
#define SG_READ_BUFFER_10_CMD 0x3c
@@ -51,13 +50,26 @@ static const char * version_str = "1.34 20220118"; /* spc6r05 */
#define SG_READ_BUFFER_16_CMDLEN 16
#endif
+#define MODE_HEADER_DATA 0
+#define MODE_VENDOR 1
+#define MODE_DATA 2
+#define MODE_DESCRIPTOR 3
+#define MODE_ECHO_BUFFER 0x0A
+#define MODE_ECHO_BDESC 0x0B
+#define MODE_READ_MICROCODE_ST 0x0F
+#define MODE_EN_EX_ECHO 0x1A
+#define MODE_ERR_HISTORY 0x1C
+
#define MAX_DEF_INHEX_LEN 8192
-#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
-#define DEF_PT_TIMEOUT 60 /* 60 seconds */
+#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
+#define DEF_PT_TIMEOUT 60 /* 60 seconds */
+#define DEF_RESPONSE_LEN 4 /* increased to 64 fo MODE_ERR_HISTORY */
static struct option long_options[] = {
{"16", no_argument, 0, 'L'},
+ {"eh_code", required_argument, 0, 'e'},
+ {"eh-code", required_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
{"id", required_argument, 0, 'i'},
@@ -65,6 +77,8 @@ static struct option long_options[] = {
{"length", required_argument, 0, 'l'},
{"long", no_argument, 0, 'L'},
{"mode", required_argument, 0, 'm'},
+ {"no_output", no_argument, 0, 'N'},
+ {"no-output", no_argument, 0, 'N'},
{"offset", required_argument, 0, 'o'},
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'R'},
@@ -74,19 +88,48 @@ static struct option long_options[] = {
{0, 0, 0, 0}, /* sentinel */
};
+struct opts_t {
+ bool do_long;
+ bool o_readonly;
+ bool do_raw;
+ bool eh_code_given;
+ bool no_output;
+ bool rb_id_given;
+ bool rb_len_given;
+ bool rb_mode_given;
+ bool verbose_given;
+ bool version_given;
+ int sg_fd;
+ int do_help;
+ int do_hex;
+ int eh_code;
+ int rb_id;
+ int rb_len;
+ int rb_mode;
+ int rb_mode_sp;
+ int verbose;
+ uint64_t rb_offset;
+ const char * device_name;
+ const char * inhex_name;
+};
+
static void
usage()
{
- pr2serr("Usage: sg_read_buffer [--16] [--help] [--hex] [--id=ID] "
- "[--inhex=FN]\n"
- " [--length=LEN] [--long] [--mode=MO] "
- "[--offset=OFF]\n"
- " [--raw] [--readonly] [--specific=MS] "
- "[--verbose]\n"
- " [--version] DEVICE\n"
+ pr2serr("Usage: sg_read_buffer [--16] [--eh_code=EHC] [--help] [--hex] "
+ "[--id=ID]\n"
+ " [--inhex=FN] [--length=LEN] [--long] "
+ "[--mode=MO]\n"
+ " [--no_output] [--offset=OFF] [--raw] "
+ "[--readonly]\n"
+ " [--specific=MS] [--verbose] [--version] "
+ "DEVICE\n"
" where:\n"
" --16|-L issue READ BUFFER(16) (def: 10)\n"
+ " --eh_code=EHC|-e EHC same as '-m eh -i EHC' where "
+ "EHC is the\n"
+ " error history code\n"
" --help|-h print out usage message\n"
" --hex|-H print output in hex\n"
" --id=ID|-i ID buffer identifier (0 (default) to 255)\n"
@@ -94,10 +137,12 @@ usage()
"decode\n"
" rather than DEVICE. If --raw given "
"then binary\n"
- " --length=LEN|-l LEN length in bytes to read (def: 4)\n"
+ " --length=LEN|-l LEN length in bytes to read (def: 4, "
+ "64 for eh)\n"
" --long|-L issue READ BUFFER(16) (def: 10)\n"
" --mode=MO|-m MO read buffer mode, MO is number or "
"acronym (def: 0)\n"
+ " --no_output|-N perform the command then exit\n"
" --offset=OFF|-o OFF buffer offset (unit: bytes, def: 0)\n"
" --raw|-r output response in binary to stdout\n"
" --readonly|-R open DEVICE read-only (def: read-write)\n"
@@ -106,22 +151,12 @@ usage()
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n\n"
"Performs a SCSI READ BUFFER (10 or 16) command. Use '-m xxx' to "
- "list\navailable modes. Numbers given in options are decimal "
- "unless they have\na hex indicator (e.g. a leading '0x').\n"
+ "list\navailable modes. Some responses are decoded, others are "
+ "output in hex.\n"
);
}
-#define MODE_HEADER_DATA 0
-#define MODE_VENDOR 1
-#define MODE_DATA 2
-#define MODE_DESCRIPTOR 3
-#define MODE_ECHO_BUFFER 0x0A
-#define MODE_ECHO_BDESC 0x0B
-#define MODE_READ_MICROCODE_ST 0x0F
-#define MODE_EN_EX_ECHO 0x1A
-#define MODE_ERR_HISTORY 0x1C
-
static struct mode_s {
const char *mode_string;
int mode;
@@ -138,7 +173,7 @@ static struct mode_s {
"(spc-5)"},
{ "en_ex", MODE_EN_EX_ECHO,
"enable expander communications protocol and echo buffer (spc-3)"},
- { "err_hist", MODE_ERR_HISTORY, "error history (spc-4)"},
+ { "err_hist|eh", MODE_ERR_HISTORY, "error history (spc-4)"},
{ NULL, 999, NULL}, /* end sentinel */
};
@@ -159,9 +194,8 @@ print_modes(void)
/* Invokes a SCSI READ BUFFER(10) command (spc5r02). Return of 0 -> success,
* various SG_LIB_CAT_* positive values or -1 -> other errors */
static int
-sg_ll_read_buffer_10(int sg_fd, int rb_mode, int rb_mode_sp, int rb_id,
- uint32_t rb_offset, void * resp, int mx_resp_len,
- int * residp, bool noisy, int verbose)
+sg_ll_read_buffer_10(void * resp, int * residp, bool noisy,
+ const struct opts_t * op)
{
int ret, res, sense_cat;
uint8_t rb10_cb[SG_READ_BUFFER_10_CMDLEN] =
@@ -169,13 +203,13 @@ sg_ll_read_buffer_10(int sg_fd, int rb_mode, int rb_mode_sp, int rb_id,
uint8_t sense_b[SENSE_BUFF_LEN] = {0};
struct sg_pt_base * ptvp;
- rb10_cb[1] = (uint8_t)(rb_mode & 0x1f);
- if (rb_mode_sp)
- rb10_cb[1] |= (uint8_t)((rb_mode_sp & 0x7) << 5);
- rb10_cb[2] = (uint8_t)rb_id;
- sg_put_unaligned_be24(rb_offset, rb10_cb + 3);
- sg_put_unaligned_be24(mx_resp_len, rb10_cb + 6);
- if (verbose) {
+ rb10_cb[1] = (uint8_t)(op->rb_mode & 0x1f);
+ if (op->rb_mode_sp)
+ rb10_cb[1] |= (uint8_t)((op->rb_mode_sp & 0x7) << 5);
+ rb10_cb[2] = (uint8_t)op->rb_id;
+ sg_put_unaligned_be24(op->rb_offset, rb10_cb + 3);
+ sg_put_unaligned_be24(op->rb_len, rb10_cb + 6);
+ if (op->verbose) {
char b[128];
pr2serr(" Read buffer(10) cdb: %s\n",
@@ -190,10 +224,10 @@ sg_ll_read_buffer_10(int sg_fd, int rb_mode, int rb_mode_sp, int rb_id,
}
set_scsi_pt_cdb(ptvp, rb10_cb, sizeof(rb10_cb));
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
- set_scsi_pt_data_in(ptvp, (uint8_t *)resp, mx_resp_len);
- res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
- ret = sg_cmds_process_resp(ptvp, "Read buffer(10)", res, noisy, verbose,
- &sense_cat);
+ set_scsi_pt_data_in(ptvp, (uint8_t *)resp, op->rb_len);
+ res = do_scsi_pt(ptvp, op->sg_fd, DEF_PT_TIMEOUT, op->verbose);
+ ret = sg_cmds_process_resp(ptvp, "Read buffer(10)", res, noisy,
+ op->verbose, &sense_cat);
if (-1 == ret) {
if (get_scsi_pt_transport_err(ptvp))
ret = SG_LIB_TRANSPORT_ERROR;
@@ -210,7 +244,7 @@ sg_ll_read_buffer_10(int sg_fd, int rb_mode, int rb_mode_sp, int rb_id,
break;
}
} else {
- if ((verbose > 2) && (ret > 0)) {
+ if ((op->verbose > 2) && (ret > 0)) {
pr2serr(" Read buffer(10): response%s\n",
(ret > 256 ? ", first 256 bytes" : ""));
hex2stderr((const uint8_t *)resp, (ret > 256 ? 256 : ret), -1);
@@ -226,9 +260,8 @@ sg_ll_read_buffer_10(int sg_fd, int rb_mode, int rb_mode_sp, int rb_id,
/* Invokes a SCSI READ BUFFER(16) command (spc5r02). Return of 0 -> success,
* various SG_LIB_CAT_* positive values or -1 -> other errors */
static int
-sg_ll_read_buffer_16(int sg_fd, int rb_mode, int rb_mode_sp, int rb_id,
- uint64_t rb_offset, void * resp, int mx_resp_len,
- int * residp, bool noisy, int verbose)
+sg_ll_read_buffer_16(void * resp, int * residp, bool noisy,
+ const struct opts_t * op)
{
int ret, res, sense_cat;
uint8_t rb16_cb[SG_READ_BUFFER_16_CMDLEN] =
@@ -237,13 +270,13 @@ sg_ll_read_buffer_16(int sg_fd, int rb_mode, int rb_mode_sp, int rb_id,
uint8_t sense_b[SENSE_BUFF_LEN] = {0};
struct sg_pt_base * ptvp;
- rb16_cb[1] = (uint8_t)(rb_mode & 0x1f);
- if (rb_mode_sp)
- rb16_cb[1] |= (uint8_t)((rb_mode_sp & 0x7) << 5);
- sg_put_unaligned_be64(rb_offset, rb16_cb + 2);
- sg_put_unaligned_be24(mx_resp_len, rb16_cb + 11);
- rb16_cb[14] = (uint8_t)rb_id;
- if (verbose) {
+ rb16_cb[1] = (uint8_t)(op->rb_mode & 0x1f);
+ if (op->rb_mode_sp)
+ rb16_cb[1] |= (uint8_t)((op->rb_mode_sp & 0x7) << 5);
+ sg_put_unaligned_be64(op->rb_offset, rb16_cb + 2);
+ sg_put_unaligned_be32(op->rb_len, rb16_cb + 10);
+ rb16_cb[14] = (uint8_t)op->rb_id;
+ if (op->verbose) {
char b[128];
pr2serr(" Read buffer(16) cdb: %s\n",
@@ -253,15 +286,15 @@ sg_ll_read_buffer_16(int sg_fd, int rb_mode, int rb_mode_sp, int rb_id,
ptvp = construct_scsi_pt_obj();
if (NULL == ptvp) {
- pr2serr("Read buffer(16): out of memory\n");
+ pr2serr("%s: out of memory\n", __func__);
return -1;
}
set_scsi_pt_cdb(ptvp, rb16_cb, sizeof(rb16_cb));
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
- set_scsi_pt_data_in(ptvp, (uint8_t *)resp, mx_resp_len);
- res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
- ret = sg_cmds_process_resp(ptvp, "Read buffer(16)", res, noisy, verbose,
- &sense_cat);
+ set_scsi_pt_data_in(ptvp, (uint8_t *)resp, op->rb_len);
+ res = do_scsi_pt(ptvp, op->sg_fd, DEF_PT_TIMEOUT, op->verbose);
+ ret = sg_cmds_process_resp(ptvp, "Read buffer(16)", res, noisy,
+ op->verbose, &sense_cat);
if (-1 == ret) {
if (get_scsi_pt_transport_err(ptvp))
ret = SG_LIB_TRANSPORT_ERROR;
@@ -278,7 +311,7 @@ sg_ll_read_buffer_16(int sg_fd, int rb_mode, int rb_mode_sp, int rb_id,
break;
}
} else {
- if ((verbose > 2) && (ret > 0)) {
+ if ((op->verbose > 2) && (ret > 0)) {
pr2serr(" Read buffer(16): response%s\n",
(ret > 256 ? ", first 256 bytes" : ""));
hex2stderr((const uint8_t *)resp, (ret > 256 ? 256 : ret), -1);
@@ -343,7 +376,7 @@ struct sg_lib_simple_value_name_t down_micro_st_arr[] = {
};
static void
-decode_microcode_status(uint8_t * resp, int rb_len)
+decode_microcode_status(const uint8_t * resp, const struct opts_t * op)
{
int n;
uint32_t u;
@@ -351,7 +384,7 @@ decode_microcode_status(uint8_t * resp, int rb_len)
const struct sg_lib_simple_value_name_t * vnp;
char b[32];
- if ((NULL == resp) || (rb_len < 1))
+ if ((NULL == resp) || (op->rb_len < 1))
return;
n = resp[0];
if (n < (int)SG_ARRAY_SIZE(act_micro_st_arr))
@@ -362,7 +395,7 @@ decode_microcode_status(uint8_t * resp, int rb_len)
}
printf("Activated microcode status: %s\n", cp);
- if (rb_len < 2)
+ if (op->rb_len < 2)
return;
n = resp[1];
if (n < (int)SG_ARRAY_SIZE(red_micro_st_arr))
@@ -373,7 +406,7 @@ decode_microcode_status(uint8_t * resp, int rb_len)
}
printf("Redundant microcode status: %s\n", cp);
- if (rb_len < 3)
+ if (op->rb_len < 3)
return;
n = resp[2];
for (vnp = down_micro_st_arr, cp = NULL; vnp->name; ++vnp) {
@@ -388,11 +421,11 @@ decode_microcode_status(uint8_t * resp, int rb_len)
}
printf("Download microcode status: %s\n", cp);
- if (rb_len > 7) {
+ if (op->rb_len > 7) {
u = sg_get_unaligned_be32(resp + 4);
printf("Download microcode maximum size (bytes): %u [0x%x]\n", u, u);
}
- if (rb_len > 15) {
+ if (op->rb_len > 15) {
u = sg_get_unaligned_be32(resp + 12);
printf("Download microcode expected buffer offset (bytes): %u "
"[0x%x]\n", u, u);
@@ -400,6 +433,59 @@ decode_microcode_status(uint8_t * resp, int rb_len)
}
static void
+decode_error_history(const uint8_t * resp, const struct opts_t * op)
+{
+ static const char * eh_s = "Error history";
+ int k, num;
+ uint32_t dir_len;
+ const uint8_t * up;
+
+ if (op->rb_id < 0x4) { /* eh directory variants */
+ if (op->rb_len < 8) {
+ pr2serr("%s response buffer too short [%d] to show directory "
+ "header\n", eh_s, op->rb_len);
+ return;
+ }
+ printf("%s directory header:\n", eh_s);
+ printf(" T10 Vendor: %.8s\n", resp + 0);
+ printf(" Version: %u\n", resp[8]);
+ printf(" EHS_retrieved: %u\n", 0x3 & (resp[9] >> 3));
+ printf(" EHS_source: %u\n", 0x3 & (resp[9] >> 1));
+ printf(" CLR_SUP: %u\n", 0x1 & resp[9]);
+ if (op->rb_len < 32) {
+ pr2serr("%s response buffer too short [%d] to show directory "
+ "length\n", eh_s, op->rb_len);
+ return;
+ }
+ dir_len = sg_get_unaligned_be16(resp + 30);
+ printf(" Directory length: %u\n", dir_len);
+ if ((unsigned)op->rb_len < (32 + dir_len)) {
+ pr2serr("%s directory entries truncated, try adding '-l %u' "
+ "option\n", eh_s, 32 + dir_len);
+ }
+ num = (op->rb_len - 32) / 8;
+ for (k = 0, up = resp + 32; k < num; ++k, up += 8) {
+ if (k > 0)
+ printf("\n");
+ printf(" Supported buffer ID: 0x%x\n", up[0]);
+ printf(" Buffer format: 0x%x\n", up[1]);
+ printf(" Buffer source: 0x%x\n", 0xf & up[2]);
+ printf(" Maximum available length: 0x%x\n",
+ sg_get_unaligned_be32(up + 4));
+ }
+ } else if ((op->rb_id >= 0x10) && (op->rb_id <= 0xef))
+ hex2stdout(resp, op->rb_len, (op->verbose > 1 ? 0 : 1));
+ else if (0xfe == op->rb_id)
+ pr2serr("clear %s I_T nexus [0x%x]\n", eh_s, op->rb_id);
+ else if (0xff == op->rb_id)
+ pr2serr("clear %s I_T nexus and release any snapshots [0x%x]\n",
+ eh_s, op->rb_id);
+ else
+ pr2serr("Reserved Buffer ID value [0x%x] for %s\n", op->rb_id, eh_s);
+
+}
+
+static void
dStrRaw(const uint8_t * str, int len)
{
int k;
@@ -411,84 +497,90 @@ dStrRaw(const uint8_t * str, int len)
int
main(int argc, char * argv[])
{
- bool do_long = false;
- bool o_readonly = false;
- bool do_raw = false;
- bool verbose_given = false;
- bool version_given = false;
int res, c, len, k;
int inhex_len = 0;
- int sg_fd = -1;
- int do_help = 0;
- int do_hex = 0;
- int rb_id = 0;
- int rb_len = 4;
- int rb_mode = 0;
- int rb_mode_sp = 0;
int resid = 0;
- int verbose = 0;
int ret = 0;
int64_t ll;
- uint64_t rb_offset = 0;
- const char * device_name = NULL;
- const char * fname = NULL;
+ const char * cp = NULL;
uint8_t * resp = NULL;
uint8_t * free_resp = NULL;
const struct mode_s * mp;
+ struct opts_t opts = {0};
+ struct opts_t * op = &opts;
+
+ op->sg_fd = -1;
+ op->rb_len = DEF_RESPONSE_LEN;
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "hHi:I:l:Lm:o:rRS:vV", long_options,
+ c = getopt_long(argc, argv, "e:hHi:I:l:Lm:No:rRS:vV", long_options,
&option_index);
if (c == -1)
break;
switch (c) {
+ case 'e':
+ if (op->rb_mode_given && (MODE_ERR_HISTORY != op->rb_mode)) {
+ pr2serr("mode incompatible with --eh_code= option\n");
+ return SG_LIB_CONTRADICT;
+ }
+ op->eh_code = sg_get_num(optarg);
+ if ((op->eh_code < 0) || (op->eh_code > 255)) {
+ pr2serr("argument to '--eh_code=' should be in the range 0 "
+ "to 255\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->rb_mode = MODE_ERR_HISTORY;
+ op->eh_code_given = true;
+ break;
case 'h':
case '?':
- ++do_help;
+ ++op->do_help;
break;
case 'H':
- ++do_hex;
+ ++op->do_hex;
break;
case 'i':
- rb_id = sg_get_num(optarg);
- if ((rb_id < 0) || (rb_id > 255)) {
- pr2serr("argument to '--id' should be in the range 0 to "
+ op->rb_id = sg_get_num(optarg);
+ if ((op->rb_id < 0) || (op->rb_id > 255)) {
+ pr2serr("argument to '--id=' should be in the range 0 to "
"255\n");
return SG_LIB_SYNTAX_ERROR;
}
+ op->rb_id_given = true;
break;
case 'I':
- if (fname) {
+ if (op->inhex_name) {
pr2serr("--inhex= option given more than once. Once only "
"please\n");
return SG_LIB_SYNTAX_ERROR;
} else
- fname = optarg;
+ op->inhex_name = optarg;
break;
case 'l':
- rb_len = sg_get_num(optarg);
- if (rb_len < 0) {
+ op->rb_len = sg_get_num(optarg);
+ if (op->rb_len < 0) {
pr2serr("bad argument to '--length'\n");
return SG_LIB_SYNTAX_ERROR;
}
- if (rb_len > 0xffffff) {
+ if (op->rb_len > 0xffffff) {
pr2serr("argument to '--length' must be <= 0xffffff\n");
return SG_LIB_SYNTAX_ERROR;
}
+ op->rb_len_given = true;
break;
case 'L':
- do_long = true;
+ op->do_long = true;
break;
case 'm':
if (NULL == optarg) {
pr2serr("bad argument to '--mode'\n");
return SG_LIB_SYNTAX_ERROR;
} else if (isdigit((uint8_t)*optarg)) {
- rb_mode = sg_get_num(optarg);
- if ((rb_mode < 0) || (rb_mode > 31)) {
+ op->rb_mode = sg_get_num(optarg);
+ if ((op->rb_mode < 0) || (op->rb_mode > 31)) {
pr2serr("argument to '--mode' should be in the range 0 "
"to 31\n");
return SG_LIB_SYNTAX_ERROR;
@@ -496,9 +588,24 @@ main(int argc, char * argv[])
} else {
len = strlen(optarg);
for (mp = modes; mp->mode_string; ++mp) {
- if (0 == strncmp(mp->mode_string, optarg, len)) {
- rb_mode = mp->mode;
- break;
+ cp = strchr(mp->mode_string, '|');
+ if (NULL == cp) {
+ if (0 == strncmp(mp->mode_string, optarg, len)) {
+ op->rb_mode = mp->mode;
+ break;
+ }
+ } else {
+ int f_len = cp - mp->mode_string;
+
+ if ((f_len == len) &&
+ (0 == memcmp(mp->mode_string, optarg, len))) {
+ op->rb_mode = mp->mode;
+ break;
+ }
+ if (0 == strncmp(cp + 1, optarg, len)) {
+ op->rb_mode = mp->mode;
+ break;
+ }
}
}
if (NULL == mp->mode_string) {
@@ -506,6 +613,14 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
}
+ if (op->eh_code_given && (MODE_ERR_HISTORY != op->rb_mode)) {
+ pr2serr("mode incompatible with --eh_code= option\n");
+ return SG_LIB_CONTRADICT;
+ }
+ op->rb_mode_given = true;
+ break;
+ case 'N':
+ op->no_output = true;
break;
case 'o':
ll = sg_get_llnum(optarg);
@@ -513,27 +628,27 @@ main(int argc, char * argv[])
pr2serr("bad argument to '--offset'\n");
return SG_LIB_SYNTAX_ERROR;
}
- rb_offset = ll;
+ op->rb_offset = ll;
break;
case 'r':
- do_raw = true;
+ op->do_raw = true;
break;
case 'R':
- o_readonly = true;
+ op->o_readonly = true;
break;
case 'S':
- rb_mode_sp = sg_get_num(optarg);
- if ((rb_mode_sp < 0) || (rb_mode_sp > 7)) {
+ op->rb_mode_sp = sg_get_num(optarg);
+ if ((op->rb_mode_sp < 0) || (op->rb_mode_sp > 7)) {
pr2serr("expected argument to '--specific' to be 0 to 7\n");
return SG_LIB_SYNTAX_ERROR;
}
break;
case 'v':
- verbose_given = true;
- ++verbose;
+ op->verbose_given = true;
+ ++op->verbose;
break;
case 'V':
- version_given = true;
+ op->version_given = true;
break;
default:
pr2serr("unrecognised option code 0x%x ??\n", c);
@@ -541,8 +656,8 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
}
- if (do_help) {
- if (do_help > 1) {
+ if (op->do_help) {
+ if (op->do_help > 1) {
usage();
pr2serr("\n");
print_modes();
@@ -551,8 +666,8 @@ main(int argc, char * argv[])
return 0;
}
if (optind < argc) {
- if (NULL == device_name) {
- device_name = argv[optind];
+ if (NULL == op->device_name) {
+ op->device_name = argv[optind];
++optind;
}
if (optind < argc) {
@@ -565,54 +680,67 @@ main(int argc, char * argv[])
#ifdef DEBUG
pr2serr("In DEBUG mode, ");
- if (verbose_given && version_given) {
+ if (op->verbose_given && op->version_given) {
pr2serr("but override: '-vV' given, zero verbose and continue\n");
- verbose_given = false;
- version_given = false;
- verbose = 0;
- } else if (! verbose_given) {
+ op->verbose_given = false;
+ op->version_given = false;
+ op->verbose = 0;
+ } else if (! op->verbose_given) {
pr2serr("set '-vv'\n");
- verbose = 2;
+ op->verbose = 2;
} else
- pr2serr("keep verbose=%d\n", verbose);
+ pr2serr("keep verbose=%d\n", op->verbose);
#else
- if (verbose_given && version_given)
+ if (op->verbose_given && op->version_given)
pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
#endif
- if (version_given) {
+ if (op->version_given) {
pr2serr("version: %s\n", version_str);
return 0;
}
+ if ((MODE_ERR_HISTORY == op->rb_mode) && (NULL == op->inhex_name)) {
+ if (! op->rb_len_given)
+ op->rb_len = 64;
+ }
+ if (op->eh_code_given) {
+ if (op->rb_id_given && (op->eh_code != op->rb_id)) {
+ pr2serr("Buffer ID incompatible with --eh_code= option\n");
+ return SG_LIB_CONTRADICT;
+ }
+ op->rb_id = op->eh_code;
+ }
- if (device_name && fname) {
+ if (op->device_name && op->inhex_name) {
pr2serr("Confused: both DEVICE (%s) and --inhex= option given. One "
- "only please\n", device_name);
+ "only please\n", op->device_name);
return SG_LIB_SYNTAX_ERROR;
- } else if (fname) {
- rb_len = (rb_len > MAX_DEF_INHEX_LEN) ? rb_len : MAX_DEF_INHEX_LEN;
- resp = (uint8_t *)sg_memalign(rb_len, 0, &free_resp, false);
- ret = sg_f2hex_arr(fname, do_raw, false, resp, &inhex_len, rb_len);
+ } else if (op->inhex_name) {
+ op->rb_len = (op->rb_len > MAX_DEF_INHEX_LEN) ? op->rb_len :
+ MAX_DEF_INHEX_LEN;
+ resp = (uint8_t *)sg_memalign(op->rb_len, 0, &free_resp, false);
+ ret = sg_f2hex_arr(op->inhex_name, op->do_raw, false, resp,
+ &inhex_len, op->rb_len);
if (ret)
goto fini;
- if (do_raw)
- do_raw = false; /* only used for input in this case */
- rb_len = inhex_len;
+ if (op->do_raw)
+ op->do_raw = false; /* only used for input in this case */
+ op->rb_len = inhex_len;
resid = 0;
goto decode_result;
- } else if (NULL == device_name) {
+ } else if (NULL == op->device_name) {
pr2serr("Missing device name!\n\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
- len = rb_len ? rb_len : 8;
+ len = op->rb_len ? op->rb_len : 8;
resp = (uint8_t *)sg_memalign(len, 0, &free_resp, false);
if (NULL == resp) {
pr2serr("unable to allocate %d bytes on the heap\n", len);
return SG_LIB_CAT_OTHER;
}
- if (do_raw) {
+ if (op->do_raw) {
if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
perror("sg_set_binary_mode");
ret = SG_LIB_FILE_ERROR;
@@ -622,55 +750,56 @@ main(int argc, char * argv[])
#ifdef SG_LIB_WIN32
#ifdef SG_LIB_WIN32_DIRECT
- if (verbose > 4)
+ if (op->verbose > 4)
pr2serr("Initial win32 SPT interface state: %s\n",
scsi_pt_win32_spt_state() ? "direct" : "indirect");
scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */);
#endif
#endif
- sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
- if (sg_fd < 0) {
- if (verbose)
- pr2serr("open error: %s: %s\n", device_name,
- safe_strerror(-sg_fd));
- ret = sg_convert_errno(-sg_fd);
+ op->sg_fd = sg_cmds_open_device(op->device_name, op->o_readonly,
+ op->verbose);
+ if (op->sg_fd < 0) {
+ if (op->verbose)
+ pr2serr("open error: %s: %s\n", op->device_name,
+ safe_strerror(-op->sg_fd));
+ ret = sg_convert_errno(-op->sg_fd);
goto fini;
}
- if (do_long)
- res = sg_ll_read_buffer_16(sg_fd, rb_mode, rb_mode_sp, rb_id,
- rb_offset, resp, rb_len, &resid, true,
- verbose);
- else if (rb_offset > 0xffffff) {
+ if (op->do_long)
+ res = sg_ll_read_buffer_16(resp, &resid, true, op);
+ else if (op->rb_offset > 0xffffff) {
pr2serr("--offset value is too large for READ BUFFER(10), try "
"--16\n");
ret = SG_LIB_SYNTAX_ERROR;
goto fini;
} else
- res = sg_ll_read_buffer_10(sg_fd, rb_mode, rb_mode_sp, rb_id,
- (uint32_t)rb_offset, resp, rb_len, &resid,
- true, verbose);
+ res = sg_ll_read_buffer_10(resp, &resid, true, op);
if (0 != res) {
char b[80];
ret = res;
if (res > 0) {
- sg_get_category_sense_str(res, sizeof(b), b, verbose);
- pr2serr("Read buffer(%d) failed: %s\n", (do_long ? 16 : 10), b);
+ sg_get_category_sense_str(res, sizeof(b), b, op->verbose);
+ pr2serr("Read buffer(%d) failed: %s\n",
+ (op->do_long ? 16 : 10), b);
}
goto fini;
}
if (resid > 0)
- rb_len -= resid; /* got back less than requested */
+ op->rb_len -= resid; /* got back less than requested */
+ if (op->no_output)
+ goto fini;
decode_result:
- if (rb_len > 0) {
- if (do_raw)
- dStrRaw(resp, rb_len);
- else if (do_hex || (rb_len < 4))
- hex2stdout((const uint8_t *)resp, rb_len, ((do_hex > 1) ? 0 : 1));
- else {
- switch (rb_mode) {
+ if (op->rb_len > 0) {
+ if (op->do_raw)
+ dStrRaw(resp, op->rb_len);
+ else if (op->do_hex || (op->rb_len < 4)) {
+ k = (op->do_hex > 2) ? -1 : (2 - op->do_hex);
+ hex2stdout(resp, op->rb_len, k);
+ } else {
+ switch (op->rb_mode) {
case MODE_DESCRIPTOR:
k = sg_get_unaligned_be24(resp + 1);
printf("OFFSET BOUNDARY: %d, Buffer offset alignment: "
@@ -683,11 +812,13 @@ decode_result:
printf("Echo buffer capacity: %d (0x%x)\n", k, k);
break;
case MODE_READ_MICROCODE_ST:
- decode_microcode_status(resp, rb_len);
+ decode_microcode_status(resp, op);
+ break;
+ case MODE_ERR_HISTORY:
+ decode_error_history(resp, op);
break;
default:
- hex2stdout((const uint8_t *)resp, rb_len,
- (verbose > 1 ? 0 : 1));
+ hex2stdout(resp, op->rb_len, (op->verbose > 1 ? 0 : 1));
break;
}
}
@@ -696,15 +827,15 @@ decode_result:
fini:
if (free_resp)
free(free_resp);
- if (sg_fd >= 0) {
- res = sg_cmds_close_device(sg_fd);
+ if (op->sg_fd >= 0) {
+ res = sg_cmds_close_device(op->sg_fd);
if (res < 0) {
pr2serr("close error: %s\n", safe_strerror(-res));
if (0 == ret)
ret = sg_convert_errno(-res);
}
}
- if (0 == verbose) {
+ if (0 == op->verbose) {
if (! sg_if_can2stderr("sg_read_buffer failed: ", 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 46b7e603..31954183 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -40,7 +40,7 @@
*/
-static const char * version_str = "1.68 20220118"; /* spc6r06 + sbc5r01 */
+static const char * version_str = "1.69 20220217"; /* spc6r06 + sbc5r01 */
/* standard VPD pages, in ascending page number order */
#define VPD_SUPPORTED_VPDS 0x0
@@ -1150,11 +1150,9 @@ decode_softw_inf_id(uint8_t * buff, int len, int do_hex)
}
len -= 4;
buff += 4;
- for ( ; len > 5; len -= 6, buff += 6) {
- printf(" IEEE Company_id: 0x%06x, vendor specific extension "
- "id: 0x%06x\n", sg_get_unaligned_be24(buff),
- sg_get_unaligned_be24(buff + 3));
- }
+ for ( ; len > 5; len -= 6, buff += 6)
+ printf(" IEEE identifier: 0x%" PRIx64 "\n",
+ sg_get_unaligned_be48(buff + 0));
}
/* VPD_ATA_INFO */
diff --git a/src/sg_vpd_vendor.c b/src/sg_vpd_vendor.c
index 4f3b25e5..d79ccc7d 100644
--- a/src/sg_vpd_vendor.c
+++ b/src/sg_vpd_vendor.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2019 Douglas Gilbert.
+ * Copyright (c) 2006-2022 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.
@@ -11,6 +11,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <string.h>
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
@@ -232,11 +233,11 @@ dup_sanity_chk(int sz_opts_t, int sz_values_name_t)
sz_values_name_t);
}
-static int
+static bool
is_like_pdt(int actual_pdt, const struct svpd_values_name_t * vnp)
{
if (actual_pdt == vnp->pdt)
- return 1;
+ return true;
if (PDT_DISK == vnp->pdt) {
switch (actual_pdt) {
case PDT_DISK:
@@ -244,21 +245,21 @@ is_like_pdt(int actual_pdt, const struct svpd_values_name_t * vnp)
case PDT_PROCESSOR:
case PDT_SAC:
case PDT_ZBC:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
} else if (PDT_TAPE == vnp->pdt) {
switch (actual_pdt) {
case PDT_TAPE:
case PDT_MCHANGER:
case PDT_ADC:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
} else
- return 0;
+ return false;
}
static const struct svpd_values_name_t *
diff --git a/src/sg_write_x.c b/src/sg_write_x.c
index 81ee1a67..b7c34f75 100644
--- a/src/sg_write_x.c
+++ b/src/sg_write_x.c
@@ -38,7 +38,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.30 20220127";
+static const char * version_str = "1.31 20220217";
/* Protection Information refers to 8 bytes of extra information usually
* associated with each logical block and is often abbreviated to PI while
@@ -2197,10 +2197,9 @@ main(int argc, char * argv[])
uint64_t addr_arr[MAX_NUM_ADDR];
uint32_t num_arr[MAX_NUM_ADDR];
struct stat if_stat, sf_stat;
- struct opts_t opts;
+ struct opts_t opts = {0};
op = &opts;
- memset(op, 0, sizeof(opts));
memset(&if_stat, 0, sizeof(if_stat));
memset(&sf_stat, 0, sizeof(sf_stat));
op->numblocks = DEF_WR_NUMBLOCKS;
diff --git a/src/sg_z_act_query.c b/src/sg_z_act_query.c
index a345b2e8..cd347820 100644
--- a/src/sg_z_act_query.c
+++ b/src/sg_z_act_query.c
@@ -38,7 +38,7 @@
* command to the given SCSI device. Based on zbc2r12.pdf .
*/
-static const char * version_str = "1.02 20211203";
+static const char * version_str = "1.03 20211217";
#define SG_ZBC_IN_CMDLEN 16
#define Z_ACTIVATE_SA 0x8
@@ -365,10 +365,9 @@ main(int argc, char * argv[])
uint8_t * free_zibp = NULL;
const char * sa_name;
char b[80];
- struct opts_t opts;
+ struct opts_t opts = {0};
struct opts_t * op = &opts;
- memset(&opts, 0, sizeof(opts));
while (1) {
int option_index = 0;