aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2017-11-15 06:21:21 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2017-11-15 06:21:21 +0000
commitcad489950e9fc29fe8786ddee2e163831abb3322 (patch)
treef5263f4d234ec6894c61a8561a4a77c06068c7bc /src
parent098b15e48f02ac4b501dc383456be94b25c1266b (diff)
downloadsg3_utils-cad489950e9fc29fe8786ddee2e163831abb3322.tar.gz
rename sg_write_atomic to sg_write_x; sg_inq: decode NVMe identify for Linux+FreeBSD
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@731 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/Makefile.in38
-rw-r--r--src/sg_format.c4
-rw-r--r--src/sg_inq.c253
-rw-r--r--src/sg_logs.c46
-rw-r--r--src/sg_read_long.c2
-rw-r--r--src/sg_sat_identify.c2
-rw-r--r--src/sg_sat_phy_event.c4
-rw-r--r--src/sg_sat_read_gplog.c4
-rw-r--r--src/sg_sat_set_features.c4
-rw-r--r--src/sg_scan_win32.c4
-rw-r--r--src/sg_ses.c10
-rw-r--r--src/sg_test_rwbuf.c4
-rw-r--r--src/sg_write_long.c4
-rw-r--r--src/sg_write_x.c (renamed from src/sg_write_atomic.c)6
-rw-r--r--src/sginfo.c2
16 files changed, 306 insertions, 89 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1012a78d..4c3bb1ca 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,8 +8,8 @@ bin_PROGRAMS = \
sg_reset_wp sg_rmsn sg_rtpg sg_safte sg_sanitize sg_sat_identify \
sg_sat_phy_event sg_sat_read_gplog sg_sat_set_features sg_senddiag \
sg_ses sg_ses_microcode sg_start sg_stpg sg_sync sg_timestamp \
- sg_turs sg_unmap sg_verify sg_vpd sg_wr_mode sg_write_atomic \
- sg_write_buffer sg_write_long sg_write_same sg_write_verify sg_zone
+ sg_turs sg_unmap sg_verify sg_vpd sg_wr_mode sg_write_buffer \
+ sg_write_long sg_write_same sg_write_verify sg_write_x sg_zone
sg_scan_SOURCES =
@@ -168,8 +168,6 @@ sg_vpd_LDADD = ../lib/libsgutils2.la @os_libs@
sg_wr_mode_LDADD = ../lib/libsgutils2.la @os_libs@
-sg_write_atomic_LDADD = ../lib/libsgutils2.la @os_libs@
-
sg_write_buffer_LDADD = ../lib/libsgutils2.la @os_libs@
sg_write_long_LDADD = ../lib/libsgutils2.la @os_libs@
@@ -178,6 +176,8 @@ sg_write_same_LDADD = ../lib/libsgutils2.la @os_libs@
sg_write_verify_LDADD = ../lib/libsgutils2.la @os_libs@
+sg_write_x_LDADD = ../lib/libsgutils2.la @os_libs@
+
sg_xcopy_LDADD = ../lib/libsgutils2.la @os_libs@
sg_zone_LDADD = ../lib/libsgutils2.la @os_libs@
diff --git a/src/Makefile.in b/src/Makefile.in
index fcfe1332..7b446b09 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -106,9 +106,9 @@ bin_PROGRAMS = sg_bg_ctl$(EXEEXT) sg_compare_and_write$(EXEEXT) \
sg_start$(EXEEXT) sg_stpg$(EXEEXT) sg_sync$(EXEEXT) \
sg_timestamp$(EXEEXT) sg_turs$(EXEEXT) sg_unmap$(EXEEXT) \
sg_verify$(EXEEXT) sg_vpd$(EXEEXT) sg_wr_mode$(EXEEXT) \
- sg_write_atomic$(EXEEXT) sg_write_buffer$(EXEEXT) \
- sg_write_long$(EXEEXT) sg_write_same$(EXEEXT) \
- sg_write_verify$(EXEEXT) sg_zone$(EXEEXT) $(am__EXEEXT_1) \
+ sg_write_buffer$(EXEEXT) sg_write_long$(EXEEXT) \
+ sg_write_same$(EXEEXT) sg_write_verify$(EXEEXT) \
+ sg_write_x$(EXEEXT) sg_zone$(EXEEXT) $(am__EXEEXT_1) \
$(am__EXEEXT_2) $(am__EXEEXT_3)
@OS_LINUX_TRUE@am__append_1 = \
@OS_LINUX_TRUE@ sg_copy_results sg_dd sg_emc_trespass sg_map sg_map26 sg_rbuf \
@@ -317,9 +317,6 @@ sg_vpd_DEPENDENCIES = ../lib/libsgutils2.la
sg_wr_mode_SOURCES = sg_wr_mode.c
sg_wr_mode_OBJECTS = sg_wr_mode.$(OBJEXT)
sg_wr_mode_DEPENDENCIES = ../lib/libsgutils2.la
-sg_write_atomic_SOURCES = sg_write_atomic.c
-sg_write_atomic_OBJECTS = sg_write_atomic.$(OBJEXT)
-sg_write_atomic_DEPENDENCIES = ../lib/libsgutils2.la
sg_write_buffer_SOURCES = sg_write_buffer.c
sg_write_buffer_OBJECTS = sg_write_buffer.$(OBJEXT)
sg_write_buffer_DEPENDENCIES = ../lib/libsgutils2.la
@@ -332,6 +329,9 @@ sg_write_same_DEPENDENCIES = ../lib/libsgutils2.la
sg_write_verify_SOURCES = sg_write_verify.c
sg_write_verify_OBJECTS = sg_write_verify.$(OBJEXT)
sg_write_verify_DEPENDENCIES = ../lib/libsgutils2.la
+sg_write_x_SOURCES = sg_write_x.c
+sg_write_x_OBJECTS = sg_write_x.$(OBJEXT)
+sg_write_x_DEPENDENCIES = ../lib/libsgutils2.la
sg_xcopy_SOURCES = sg_xcopy.c
sg_xcopy_OBJECTS = sg_xcopy.$(OBJEXT)
sg_xcopy_DEPENDENCIES = ../lib/libsgutils2.la
@@ -394,10 +394,9 @@ SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c sg_dd.c \
sg_sat_read_gplog.c sg_sat_set_features.c $(sg_scan_SOURCES) \
sg_senddiag.c sg_ses.c sg_ses_microcode.c sg_start.c sg_stpg.c \
sg_sync.c sg_test_rwbuf.c sg_timestamp.c sg_turs.c sg_unmap.c \
- sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_atomic.c \
- sg_write_buffer.c sg_write_long.c sg_write_same.c \
- sg_write_verify.c sg_xcopy.c sg_zone.c sginfo.c sgm_dd.c \
- sgp_dd.c
+ sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
+ sg_write_long.c sg_write_same.c sg_write_verify.c sg_write_x.c \
+ sg_xcopy.c sg_zone.c sginfo.c sgm_dd.c sgp_dd.c
DIST_SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c \
sg_dd.c sg_decode_sense.c sg_emc_trespass.c sg_format.c \
sg_get_config.c sg_get_lba_status.c sg_ident.c \
@@ -412,10 +411,9 @@ DIST_SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c \
$(am__sg_scan_SOURCES_DIST) sg_senddiag.c sg_ses.c \
sg_ses_microcode.c sg_start.c sg_stpg.c sg_sync.c \
sg_test_rwbuf.c sg_timestamp.c sg_turs.c sg_unmap.c \
- sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_atomic.c \
- sg_write_buffer.c sg_write_long.c sg_write_same.c \
- sg_write_verify.c sg_xcopy.c sg_zone.c sginfo.c sgm_dd.c \
- sgp_dd.c
+ sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
+ sg_write_long.c sg_write_same.c sg_write_verify.c sg_write_x.c \
+ sg_xcopy.c sg_zone.c sginfo.c sgm_dd.c sgp_dd.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -636,11 +634,11 @@ sg_verify_LDADD = ../lib/libsgutils2.la @os_libs@
sg_vpd_SOURCES = sg_vpd.c sg_vpd_vendor.c
sg_vpd_LDADD = ../lib/libsgutils2.la @os_libs@
sg_wr_mode_LDADD = ../lib/libsgutils2.la @os_libs@
-sg_write_atomic_LDADD = ../lib/libsgutils2.la @os_libs@
sg_write_buffer_LDADD = ../lib/libsgutils2.la @os_libs@
sg_write_long_LDADD = ../lib/libsgutils2.la @os_libs@
sg_write_same_LDADD = ../lib/libsgutils2.la @os_libs@
sg_write_verify_LDADD = ../lib/libsgutils2.la @os_libs@
+sg_write_x_LDADD = ../lib/libsgutils2.la @os_libs@
sg_xcopy_LDADD = ../lib/libsgutils2.la @os_libs@
sg_zone_LDADD = ../lib/libsgutils2.la @os_libs@
all: all-am
@@ -950,10 +948,6 @@ sg_wr_mode$(EXEEXT): $(sg_wr_mode_OBJECTS) $(sg_wr_mode_DEPENDENCIES) $(EXTRA_sg
@rm -f sg_wr_mode$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_wr_mode_OBJECTS) $(sg_wr_mode_LDADD) $(LIBS)
-sg_write_atomic$(EXEEXT): $(sg_write_atomic_OBJECTS) $(sg_write_atomic_DEPENDENCIES) $(EXTRA_sg_write_atomic_DEPENDENCIES)
- @rm -f sg_write_atomic$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(sg_write_atomic_OBJECTS) $(sg_write_atomic_LDADD) $(LIBS)
-
sg_write_buffer$(EXEEXT): $(sg_write_buffer_OBJECTS) $(sg_write_buffer_DEPENDENCIES) $(EXTRA_sg_write_buffer_DEPENDENCIES)
@rm -f sg_write_buffer$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_write_buffer_OBJECTS) $(sg_write_buffer_LDADD) $(LIBS)
@@ -970,6 +964,10 @@ sg_write_verify$(EXEEXT): $(sg_write_verify_OBJECTS) $(sg_write_verify_DEPENDENC
@rm -f sg_write_verify$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_write_verify_OBJECTS) $(sg_write_verify_LDADD) $(LIBS)
+sg_write_x$(EXEEXT): $(sg_write_x_OBJECTS) $(sg_write_x_DEPENDENCIES) $(EXTRA_sg_write_x_DEPENDENCIES)
+ @rm -f sg_write_x$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(sg_write_x_OBJECTS) $(sg_write_x_LDADD) $(LIBS)
+
sg_xcopy$(EXEEXT): $(sg_xcopy_OBJECTS) $(sg_xcopy_DEPENDENCIES) $(EXTRA_sg_xcopy_DEPENDENCIES)
@rm -f sg_xcopy$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_xcopy_OBJECTS) $(sg_xcopy_LDADD) $(LIBS)
@@ -1055,11 +1053,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_vpd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_vpd_vendor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_wr_mode.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_write_atomic.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_write_buffer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_write_long.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_write_same.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_write_verify.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_write_x.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_xcopy.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_zone.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sginfo.Po@am__quote@
diff --git a/src/sg_format.c b/src/sg_format.c
index 53aa2739..f403e0cd 100644
--- a/src/sg_format.c
+++ b/src/sg_format.c
@@ -37,7 +37,7 @@
#include "sg_pr2serr.h"
#include "sg_pt.h"
-static const char * version_str = "1.40 20171030";
+static const char * version_str = "1.41 20171107";
#define RW_ERROR_RECOVERY_PAGE 1 /* can give alternate with --mode=MP */
@@ -734,7 +734,7 @@ print_read_cap(int fd, const struct opts_t * op)
block_size = sg_get_unaligned_be32(resp_buff + 4);
if (0xffffffff == last_blk_addr) {
if (op->verbose)
- printf("Read Capacity (10) reponse "
+ printf("Read Capacity (10) response "
"indicates that Read Capacity "
"(16) is required\n");
return -2;
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 25dce472..8d25605e 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -42,8 +42,11 @@
#include "sg_pt.h"
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
+#ifdef HAVE_NVME
+#include "sg_pt_nvme.h"
+#endif
-static const char * version_str = "1.71 20171104"; /* SPC-5 rev 17 */
+static const char * version_str = "1.73 20171114"; /* SPC-5 rev 17 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -429,10 +432,10 @@ cl_new_process(struct opts_t * op, int argc, char * argv[])
#endif /* SG_SCSI_STRINGS */
#else /* SG_LIB_LINUX */
#ifdef SG_SCSI_STRINGS
- c = getopt_long(argc, argv, "B:cdeEhHiI:l:m:NOp:rsuvVx", long_options,
+ c = getopt_long(argc, argv, "B:cdeEfhHiI:l:m:NOp:rsuvVx", long_options,
&option_index);
#else
- c = getopt_long(argc, argv, "B:cdeEhHiI:l:m:p:rsuvVx", long_options,
+ c = getopt_long(argc, argv, "B:cdeEfhHiI:l:m:p:rsuvVx", long_options,
&option_index);
#endif /* SG_SCSI_STRINGS */
#endif /* SG_LIB_LINUX */
@@ -467,7 +470,7 @@ cl_new_process(struct opts_t * op, int argc, char * argv[])
case 'e':
op->do_vpd = true;
break;
- case 'E':
+ case 'E': /* --extended */
case 'x':
op->do_decode = true;
op->do_vpd = true;
@@ -3220,8 +3223,8 @@ std_inq_process(int sg_fd, const struct opts_t * op, int inhex_len)
res = try_ata_identify(sg_fd, op->do_hex, op->do_raw,
op->do_verbose);
if (0 != res) {
- pr2serr("Both SCSI INQUIRY and fetching ATA information "
- "failed on %s\n", op->device_name);
+ pr2serr("SCSI INQUIRY, NVMe Identify and fetching ATA "
+ "information failed on %s\n", op->device_name);
return SG_LIB_CAT_OTHER;
}
#else
@@ -3765,6 +3768,236 @@ out:
return res;
}
+#ifdef HAVE_NVME
+
+static void
+do_nvme_identify_hex_raw(const unsigned char * b, int b_len,
+ const struct opts_t * op)
+{
+ if (op->do_raw)
+ dStrRaw((const char *)b, b_len);
+ else if (op->do_hex) {
+ if (op->do_hex < 3) {
+ printf("data_in buffer:\n");
+ dStrHex((const char *)b, b_len, 0);
+ } else
+ dStrHex((const char *)b, b_len, -1);
+ }
+}
+
+const char * rperf[] = {"Best", "Better", "Good", "Degraded"};
+
+static int
+do_nvme_id_ns(struct sg_pt_base * ptvp, uint32_t nsid,
+ struct sg_nvme_passthru_cmd * id_cmdp, uint8_t * id_din,
+ int id_din_len, const struct opts_t * op)
+{
+ bool got_eui_128 = false;
+ int ret = 0;
+ int vb = op->do_verbose;
+ uint32_t u, k, off, num_lbaf, flbas, flba_info, md_size, lb_size;
+ uint64_t ns_sz, eui_64;
+ struct sg_nvme_passthru_cmd cmd_back;
+
+ clear_scsi_pt_obj(ptvp);
+ id_cmdp->nsid = nsid;
+ id_cmdp->cdw10 = 0x0; /* CNS=0x0 Identify NS */
+ set_scsi_pt_data_in(ptvp, id_din, id_din_len);
+ set_scsi_pt_sense(ptvp, (unsigned char *)&cmd_back, sizeof(cmd_back));
+ set_scsi_pt_cdb(ptvp, (const uint8_t *)id_cmdp, sizeof(*id_cmdp));
+ ret = do_scsi_pt(ptvp, -1, 0 /* timeout (def: 1 min) */, vb);
+ if (vb > 2) {
+ pr2serr("do_scsi_pt() result is %d\n", ret);
+ pr2serr("do_scsi_pt() result via sense buffer:\n");
+ dStrHex((const char *)&cmd_back, sizeof(cmd_back), 0);
+ }
+ if (ret)
+ return ret;
+ num_lbaf = id_din[25] + 1; /* spec says this is "0's based value" */
+ flbas = id_din[26] & 0xf; /* index of active LBA format (for this ns) */
+ if (op->do_hex || op->do_raw) {
+ do_nvme_identify_hex_raw(id_din, sizeof(id_din), op);
+ return ret;
+ }
+ ns_sz = sg_get_unaligned_le64(id_din + 0);
+ eui_64 = sg_get_unaligned_be64(id_din + 120); /* N.B. big endian */
+ if (! sg_all_zeros(id_din + 104, 16))
+ got_eui_128 = true;
+ printf(" Namespace size/capacity: %" PRIu64 "/%" PRIu64
+ " blocks\n", ns_sz, sg_get_unaligned_le64(id_din + 8));
+ printf(" Namespace utilization: %" PRIu64 " blocks\n",
+ sg_get_unaligned_le64(id_din + 16));
+ if (got_eui_128) { /* N.B. big endian */
+ printf(" NGUID: 0x%02x", id_din[104]);
+ for (k = 1; k < 16; ++k)
+ printf("%02x", id_din[104 + k]);
+ printf("\n");
+ } else if (op->do_force)
+ printf(" NGUID: 0x0\n");
+ if (eui_64)
+ printf(" EUI-64: 0x%" PRIx64 "\n", eui_64); /* N.B. big endian */
+ printf(" Number of LBA formats: %u\n", num_lbaf);
+ printf(" Index LBA size: %u\n", flbas);
+ for (k = 0, off = 128; k < num_lbaf; ++k, off += 4) {
+ printf(" LBA format %u support:", k);
+ if (k == flbas)
+ printf(" <-- active\n");
+ else
+ printf("\n");
+ flba_info = sg_get_unaligned_le32(id_din + off);
+ md_size = flba_info & 0xffff;
+ lb_size = flba_info >> 16 & 0xff;
+ if (lb_size > 31) {
+ pr2serr("%s: logical block size exponent of %u implies a LB "
+ "size larger than 4 billion bytes, ignore\n", __func__,
+ lb_size);
+ continue;
+ }
+ lb_size = 1U << lb_size;
+ ns_sz *= lb_size;
+ ns_sz /= 500*1000*1000;
+ if (ns_sz & 0x1)
+ ns_sz = (ns_sz / 2) + 1;
+ else
+ ns_sz = ns_sz / 2;
+ u = (flba_info >> 24) & 0x3;
+ printf(" Logical block size: %u bytes\n", lb_size);
+ printf(" Approximate namespace size: %" PRIu64 " GB\n", ns_sz);
+ printf(" Metadata size: %u bytes\n", md_size);
+ printf(" Relative performance: %s [0x%x]\n", rperf[u], u);
+ }
+ return ret;
+}
+
+/* Send a NVMe Identify(CNS=1) and decode Controller info */
+static int
+do_nvme_identify(int pt_fd, const struct opts_t * op)
+{
+ bool got_fguid;
+ int ret = 0;
+ int vb = op->do_verbose;
+ uint8_t ver_min, ver_ter;
+ uint16_t ver_maj;
+ uint32_t k, ver, nsid, max_nsid;
+ uint64_t sz1, sz2;
+ struct sg_pt_base * ptvp;
+ struct sg_nvme_passthru_cmd identify_cmd;
+ struct sg_nvme_passthru_cmd cmd_back;
+ struct sg_nvme_passthru_cmd * id_cmdp = &identify_cmd;
+ uint8_t id_din[4096];
+
+ if (op->do_raw) {
+ if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
+ perror("sg_set_binary_mode");
+ return SG_LIB_FILE_ERROR;
+ }
+ }
+ ptvp = construct_scsi_pt_obj_with_fd(pt_fd, vb);
+ if (NULL == ptvp) {
+ pr2serr("%s: memory problem\n", __func__);
+ return SG_LIB_CAT_OTHER;
+ }
+ memset(id_cmdp, 0, sizeof(*id_cmdp));
+ id_cmdp->opcode = 0x6;
+ nsid = get_pt_nvme_nsid(ptvp);
+ id_cmdp->cdw10 = 0x1; /* CNS=0x1 Identify controller */
+ set_scsi_pt_data_in(ptvp, id_din, sizeof(id_din));
+ set_scsi_pt_cdb(ptvp, (const uint8_t *)id_cmdp, sizeof(*id_cmdp));
+ set_scsi_pt_sense(ptvp, (unsigned char *)&cmd_back, sizeof(cmd_back));
+ ret = do_scsi_pt(ptvp, -1, 0 /* timeout (def: 1 min) */, vb);
+ if (vb > 2) {
+ pr2serr("do_scsi_pt result is %d\n", ret);
+ pr2serr("do_scsi_pt result via sense buffer:\n");
+ dStrHex((const char *)&cmd_back, sizeof(cmd_back), 0);
+ }
+ if (ret)
+ goto err_out;
+ max_nsid = sg_get_unaligned_le16(id_din + 516);
+ if (op->do_raw || op->do_hex) {
+ do_nvme_identify_hex_raw(id_din, sizeof(id_din), op);
+ goto skip1;
+ }
+ printf("Identify controller for %s:\n", op->device_name);
+ printf(" Model number: %.40s\n", (const char *)(id_din + 24));
+ printf(" Serial number: %.20s\n", (const char *)(id_din + 4));
+ printf(" Firmware revision: %.8s\n", (const char *)(id_din + 64));
+ ver = sg_get_unaligned_le32(id_din + 80);
+ ver_maj = (ver >> 16);
+ ver_min = (ver >> 8) & 0xff;
+ ver_ter = (ver & 0xff);
+ printf(" Version: %u.%u", ver_maj, ver_min);
+ if ((ver_maj > 1) || ((1 == ver_maj) && (ver_min > 2)) ||
+ ((1 == ver_maj) && (2 == ver_min) && (ver_ter > 0)))
+ printf(".%u\n", ver_ter);
+ else
+ printf("\n");
+ printf(" PCI vendor ID VID/SSVID: 0x%x/0x%x\n",
+ sg_get_unaligned_le16(id_din + 0),
+ sg_get_unaligned_le16(id_din + 2));
+ printf(" IEEE OUI Identifier: 0x%x\n",
+ sg_get_unaligned_le24(id_din + 73));
+ got_fguid = ! sg_all_zeros(id_din + 112, 16);
+ if (got_fguid) {
+ printf(" FGUID: 0x%02x", id_din[112]);
+ for (k = 1; k < 16; ++k)
+ printf("%02x", id_din[112 + k]);
+ printf("\n");
+ } else if (op->do_force)
+ printf(" FGUID: 0x0\n");
+ printf(" Controller ID: 0x%x\n", sg_get_unaligned_le16(id_din + 78));
+ if (op->do_force) {
+ printf(" Management endpoint capabilities, over a PCIe port: %d\n",
+ !! (0x2 & id_din[255]));
+ printf(" Management endpoint capabilities, over a SMBus/I2C port: "
+ "%d\n", !! (0x1 & id_din[255]));
+ }
+ printf(" Number of namespaces: %u\n", max_nsid);
+ sz1 = sg_get_unaligned_le64(id_din + 280); /* lower 64 bits */
+ sz2 = sg_get_unaligned_le64(id_din + 288); /* upper 64 bits */
+ if (sz2)
+ printf(" Total NVM capacity: huge ...\n");
+ else if (sz1)
+ printf(" Total NVM capacity: %" PRIu64 " bytes\n", sz1);
+ else if (op->do_force)
+ printf(" Total NVM capacity: 0 bytes\n");
+skip1:
+ if (nsid > 0) {
+ if ((! op->do_raw) || (op->do_hex < 3)) {
+ printf(" Namespace %u (derived from device name):\n", nsid);
+ if (nsid > max_nsid)
+ pr2serr("NSID from device (%u) should not exceed number of "
+ "namespaces (%u)\n", nsid, max_nsid);
+ }
+ ret = do_nvme_id_ns(ptvp, nsid, id_cmdp, id_din, sizeof(id_din), op);
+ if (ret)
+ goto err_out;
+
+ } else { /* nsid=0 so char device; loop over all namespaces */
+ for (k = 1; k <= max_nsid; ++k) {
+ if ((! op->do_raw) || (op->do_hex < 3))
+ printf(" Namespace %u (of %u):\n", k, max_nsid);
+ ret = do_nvme_id_ns(ptvp, k, id_cmdp, id_din, sizeof(id_din), op);
+ if (ret)
+ goto err_out;
+ }
+ }
+err_out:
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
+#else
+
+static int
+do_nvme_identify(int pt_fd, const struct opts_t * op)
+{
+ pr2serr("%s: not implemented, no <linux/nvme_ioctl.h>\n", __func__);
+ if (op->do_verbose)
+ pr2serr("Need to build on system with NVMe development headers\n");
+ return 0;
+}
+#endif
+
int
main(int argc, char * argv[])
@@ -4007,6 +4240,11 @@ main(int argc, char * argv[])
}
#endif
memset(rsp_buff, 0, sizeof(rsp_buff));
+ n = check_pt_file_handle(sg_fd, op->device_name, op->do_verbose);
+ if ((3 == n) || (4 == n)) { /* NVMe char or NVMe block */
+ ret = do_nvme_identify(sg_fd, op);
+ goto fini;
+ }
#if defined(SG_LIB_LINUX) && defined(SG_SCSI_STRINGS)
if (op->do_ata) {
@@ -4018,7 +4256,7 @@ main(int argc, char * argv[])
ret = SG_LIB_CAT_OTHER;
} else
ret = 0;
- goto err_out;
+ goto fini;
}
#endif
@@ -4045,6 +4283,7 @@ main(int argc, char * argv[])
}
}
+fini:
err_out:
res = sg_cmds_close_device(sg_fd);
if (res < 0) {
diff --git a/src/sg_logs.c b/src/sg_logs.c
index eadfe2e3..e4d4bf97 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -32,7 +32,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.55 20171103"; /* spc5r17 + sbc4r11 */
+static const char * version_str = "1.57 20171112"; /* spc5r17 + sbc4r11 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -535,9 +535,9 @@ usage(int hval)
pr2serr(
" where sg_logs' lesser used options are:\n"
" --control=PC|-c PC page control(PC) (default: 1)\n"
- " 0: current threshhold, 1: current "
+ " 0: current threshold, 1: current "
"cumulative\n"
- " 2: default threshhold, 3: default "
+ " 2: default threshold, 3: default "
"cumulative\n"
" --list|-l list supported log page names (equivalent to "
"'-p sp')\n"
@@ -593,8 +593,8 @@ usage_old()
" -A fetch and decode all log pages and subpages\n"
" -b shorten the output of some log pages\n"
" -c=PC page control(PC) (default: 1)\n"
- " 0: current threshhold, 1: current cumulative\n"
- " 2: default threshhold, 3: default cumulative\n"
+ " 0: current threshold, 1: current cumulative\n"
+ " 2: default threshold, 3: default cumulative\n"
" -e enumerate known log pages\n"
" -f=FL filter match parameter code or pdt\n"
" -h output in hex (default: decode if known)\n"
@@ -1319,20 +1319,6 @@ dStrRaw(const char* str, int len)
printf("%c", str[k]);
}
-/* Assumes an integral numbers of bytes pointed to by 'xp' of length
- * 'num_bytes' given. [So the number of bits modulo 8 must be zero.]
- * Returns true if all bytes are 0xff (which is the same as all bits
- * being set), else returns false. */
-static bool
-all_bits_set(const uint8_t * xp, int num_bytes)
-{
- for ( ; num_bytes > 0; ++xp, --num_bytes) {
- if (0xff != *xp)
- return false;
- }
- return true; /* also in degenerate case when 'num_bytes' <= 0 */
-}
-
/* Returns 'xp' with "unknown" if all bits set; otherwise decoded (big endian)
* number in 'xp'. Number rendered in decimal if in_hex=false otherwise in
* hex with leading '0x' prepended. */
@@ -1340,7 +1326,7 @@ static char *
num_or_unknown(const uint8_t * xp, int num_bytes /* max is 8 */, bool in_hex,
char * b, int blen)
{
- if (all_bits_set(xp, num_bytes))
+ if (sg_all_ffs(xp, num_bytes))
snprintf(b, blen, "unknown");
else {
uint64_t num = sg_get_unaligned_be(num_bytes, xp);
@@ -2796,7 +2782,7 @@ show_self_test_page(const uint8_t * resp, int len, const struct opts_t * op)
printf(" self-test result: %s [%d]\n", self_test_result[res], res);
if (bp[5])
printf(" self-test number = %d\n", (int)bp[5]);
- if (! all_bits_set(bp + 8, 8)) {
+ if (! sg_all_ffs(bp + 8, 8)) {
ull = sg_get_unaligned_be64(bp + 8);
if ((res > 0) && ( res < 0xf))
printf(" address of first error = 0x%" PRIx64 "\n", ull);
@@ -2950,7 +2936,7 @@ show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op)
break;
case 3:
if (extra > 7) {
- if (all_bits_set(bp + 4, 4))
+ if (sg_all_ffs(bp + 4, 4))
printf(" Specified cycle count over device lifetime "
"= -1");
else
@@ -2960,7 +2946,7 @@ show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op)
break;
case 4:
if (extra > 7) {
- if (all_bits_set(bp + 4, 4))
+ if (sg_all_ffs(bp + 4, 4))
printf(" Accumulated start-stop cycles = -1");
else
printf(" Accumulated start-stop cycles = %u",
@@ -2969,7 +2955,7 @@ show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op)
break;
case 5:
if (extra > 7) {
- if (all_bits_set(bp + 4, 4))
+ if (sg_all_ffs(bp + 4, 4))
printf(" Specified load-unload count over device "
"lifetime = -1");
else
@@ -2979,7 +2965,7 @@ show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op)
break;
case 6:
if (extra > 7) {
- if (all_bits_set(bp + 4, 4))
+ if (sg_all_ffs(bp + 4, 4))
printf(" Accumulated load-unload cycles = -1");
else
printf(" Accumulated load-unload cycles = %u",
@@ -4051,7 +4037,7 @@ show_format_status_page(const uint8_t * resp, int len,
if (pl < 5)
printf(" Format data out: <empty>\n");
else {
- if (all_bits_set(bp + 4, pl - 4))
+ if (sg_all_ffs(bp + 4, pl - 4))
printf(" Format data out: <not available>\n");
else {
printf(" Format data out:\n");
@@ -4081,7 +4067,7 @@ show_format_status_page(const uint8_t * resp, int len,
if (is_count) {
k = pl - 4;
xp = bp + 4;
- if (all_bits_set(xp, k))
+ if (sg_all_ffs(xp, k))
printf(" <not available>\n");
else {
if (k > (int)sizeof(ull)) {
@@ -5393,7 +5379,7 @@ show_sequential_access_page(const uint8_t * resp, int len,
}
}
ull = sg_get_unaligned_be(pl - 4, bp + 4);
- all_set = all_bits_set(bp + 4, pl - 4);
+ all_set = sg_all_ffs(bp + 4, pl - 4);
gbytes = ull / 1000000000;
switch (pc) {
case 0:
@@ -6000,7 +5986,7 @@ show_mchanger_diag_data_page(const uint8_t * resp, int len,
v = sg_get_unaligned_be16(bp + 48);
printf(" Medium transport address: 0x%x\n", v);
v = sg_get_unaligned_be16(bp + 50);
- printf(" Intial address: 0x%x\n", v);
+ printf(" Initial address: 0x%x\n", v);
v = sg_get_unaligned_be16(bp + 52);
printf(" Last successful address: 0x%x\n", v);
v = sg_get_unaligned_be16(bp + 54);
@@ -6040,7 +6026,7 @@ volume_stats_partition(const uint8_t * xp, int len, bool in_hex)
pn = sg_get_unaligned_be16(xp + 2);
ffs_last_fe = false;
all_ffs = false;
- if (all_bits_set(xp + 4, dl - 3)) {
+ if (sg_all_ffs(xp + 4, dl - 3)) {
switch (xp[4 + dl - 3]) {
case 0xff:
all_ffs = true;
diff --git a/src/sg_read_long.c b/src/sg_read_long.c
index 620c1bae..111c5b3c 100644
--- a/src/sg_read_long.c
+++ b/src/sg_read_long.c
@@ -8,7 +8,7 @@
This program issues the SCSI command READ LONG to a given SCSI device.
It sends the command with the logical block address passed as the lba
argument, and the transfer length set to the xfer_len argument. the
- buffer to be writen to the device filled with 0xff, this buffer includes
+ buffer to be written to the device filled with 0xff, this buffer includes
the sector data and the ECC bytes.
*/
diff --git a/src/sg_sat_identify.c b/src/sg_sat_identify.c
index 5efa5008..ca6431ab 100644
--- a/src/sg_sat_identify.c
+++ b/src/sg_sat_identify.c
@@ -38,7 +38,7 @@
#define SAT_ATA_PASS_THROUGH32_LEN 32
#define SAT_ATA_PASS_THROUGH16 0x85
#define SAT_ATA_PASS_THROUGH16_LEN 16
-#define SAT_ATA_PASS_THROUGH12 0xa1 /* clashes with MMC BLANK comand */
+#define SAT_ATA_PASS_THROUGH12 0xa1 /* clashes with MMC BLANK command */
#define SAT_ATA_PASS_THROUGH12_LEN 12
#define SAT_ATA_RETURN_DESC 9 /* ATA Return (sense) Descriptor */
#define ASCQ_ATA_PT_INFO_AVAILABLE 0x1d
diff --git a/src/sg_sat_phy_event.c b/src/sg_sat_phy_event.c
index fe7d1aeb..720fc9db 100644
--- a/src/sg_sat_phy_event.c
+++ b/src/sg_sat_phy_event.c
@@ -24,7 +24,7 @@
#include "sg_cmds_extra.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.09 20171010";
+static const char * version_str = "1.10 20171107";
/* This program uses a ATA PASS-THROUGH SCSI command. This usage is
* defined in the SCSI to ATA Translation (SAT) drafts and standards.
@@ -46,7 +46,7 @@ static const char * version_str = "1.09 20171010";
#define SAT_ATA_PASS_THROUGH16 0x85
#define SAT_ATA_PASS_THROUGH16_LEN 16
-#define SAT_ATA_PASS_THROUGH12 0xa1 /* clashes with MMC BLANK comand */
+#define SAT_ATA_PASS_THROUGH12 0xa1 /* clashes with MMC BLANK command */
#define SAT_ATA_PASS_THROUGH12_LEN 12
#define SAT_ATA_RETURN_DESC 9 /* ATA Return (sense) Descriptor */
#define ASCQ_ATA_PT_INFO_AVAILABLE 0x1d
diff --git a/src/sg_sat_read_gplog.c b/src/sg_sat_read_gplog.c
index 5e1bb5ad..7feadeb5 100644
--- a/src/sg_sat_read_gplog.c
+++ b/src/sg_sat_read_gplog.c
@@ -41,7 +41,7 @@
#define SAT_ATA_PASS_THROUGH16 0x85
#define SAT_ATA_PASS_THROUGH16_LEN 16
-#define SAT_ATA_PASS_THROUGH12 0xa1 /* clashes with MMC BLANK comand */
+#define SAT_ATA_PASS_THROUGH12 0xa1 /* clashes with MMC BLANK command */
#define SAT_ATA_PASS_THROUGH12_LEN 12
#define SAT_ATA_RETURN_DESC 9 /* ATA Return (sense) Descriptor */
#define ASCQ_ATA_PT_INFO_AVAILABLE 0x1d
@@ -51,7 +51,7 @@
#define DEF_TIMEOUT 20
-static const char * version_str = "1.15 20171010";
+static const char * version_str = "1.16 20171107";
struct opts_t {
bool ck_cond;
diff --git a/src/sg_sat_set_features.c b/src/sg_sat_set_features.c
index 6215b237..2d84ff78 100644
--- a/src/sg_sat_set_features.c
+++ b/src/sg_sat_set_features.c
@@ -40,7 +40,7 @@
#define SAT_ATA_PASS_THROUGH16 0x85
#define SAT_ATA_PASS_THROUGH16_LEN 16
-#define SAT_ATA_PASS_THROUGH12 0xa1 /* clashes with MMC BLANK comand */
+#define SAT_ATA_PASS_THROUGH12 0xa1 /* clashes with MMC BLANK command */
#define SAT_ATA_PASS_THROUGH12_LEN 12
#define SAT_ATA_RETURN_DESC 9 /* ATA Return (sense) Descriptor */
#define ASCQ_ATA_PT_INFO_AVAILABLE 0x1d
@@ -49,7 +49,7 @@
#define DEF_TIMEOUT 20
-static const char * version_str = "1.14 20171010";
+static const char * version_str = "1.15 20171107";
static struct option long_options[] = {
{"count", required_argument, 0, 'c'},
diff --git a/src/sg_scan_win32.c b/src/sg_scan_win32.c
index 22d14919..7bbad556 100644
--- a/src/sg_scan_win32.c
+++ b/src/sg_scan_win32.c
@@ -40,7 +40,7 @@
#include "sg_pt_win32.h"
-static const char * version_str = "1.17 (win32) 20171007";
+static const char * version_str = "1.18 (win32) 20171107";
#define MAX_SCSI_ELEMS 2048
#define MAX_ADAPTER_NUM 128
@@ -341,7 +341,7 @@ query_dev_uid(HANDLE hdevice, union STORAGE_DEVICE_UID_DATA * data)
}
/* Updates storage_arr based on sep. Returns 1 if update occurred, 0 if
- * no update occured. */
+ * no update occurred. */
static int
check_devices(const struct storage_elem * sep)
{
diff --git a/src/sg_ses.c b/src/sg_ses.c
index c4123d02..2fd810d8 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -32,7 +32,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.23 20171020"; /* ses4r01 */
+static const char * version_str = "2.24 20171112"; /* ses4r01 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -2894,13 +2894,7 @@ truncated:
static bool
saddr_non_zero(const uint8_t * bp)
{
- int k;
-
- for (k = 0; k < 8; ++k) {
- if (bp[k])
- return true;
- }
- return false;
+ return ! sg_all_zeros(bp, 8);
}
static const char * sas_device_type[] = {
diff --git a/src/sg_test_rwbuf.c b/src/sg_test_rwbuf.c
index 4e86e7c3..0ab5c613 100644
--- a/src/sg_test_rwbuf.c
+++ b/src/sg_test_rwbuf.c
@@ -3,7 +3,7 @@
* heavily based on Douglas Gilbert's sg_rbuf program.
* (c) 1999-2017 Douglas Gilbert
*
- * Program to test the SCSI host adapter by issueing
+ * Program to test the SCSI host adapter by issuing
* write and read operations on a device's buffer
* and calculating checksums.
* NOTE: If you can not reserve the buffer of the device
@@ -43,7 +43,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "1.12 20171020";
+static const char * version_str = "1.13 20171107";
#define BPI (signed)(sizeof(int))
diff --git a/src/sg_write_long.c b/src/sg_write_long.c
index 63ca64bf..252425e3 100644
--- a/src/sg_write_long.c
+++ b/src/sg_write_long.c
@@ -8,7 +8,7 @@
* This program issues the SCSI command WRITE LONG to a given SCSI device.
* It sends the command with the logical block address passed as the lba
* argument, and the transfer length set to the xfer_len argument. the
- * buffer to be writen to the device filled with 0xff, this buffer includes
+ * buffer to be written to the device filled with 0xff, this buffer includes
* the sector data and the ECC bytes.
*
* This code was contributed by Saeed Bishara
@@ -34,7 +34,7 @@
#include "sg_cmds_extra.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.14 20171008";
+static const char * version_str = "1.15 20171107";
#define MAX_XFER_LEN 10000
diff --git a/src/sg_write_atomic.c b/src/sg_write_x.c
index 4d669e91..8fc450a1 100644
--- a/src/sg_write_atomic.c
+++ b/src/sg_write_x.c
@@ -30,10 +30,10 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.02 20171024";
+static const char * version_str = "1.03 20171115";
-#define ME "sg_write_atomic: "
+#define ME "sg_write_x: "
#define WRITE_ATOMIC16_OP 0x9c
#define WRITE_16_OP 0x8a
@@ -121,7 +121,7 @@ struct opts_t {
static void
usage()
{
- pr2serr("Usage: sg_write_atomic [--16] [--32] [--app-tag=AT] "
+ pr2serr("Usage: sg_write_x [--16] [--32] [--app-tag=AT] "
"[--boundary=AB]\n"
" [--bs=LBS] [--dld=DLD] [--dpo] "
"[--fua] "
diff --git a/src/sginfo.c b/src/sginfo.c
index 8e6f946a..7d1faa59 100644
--- a/src/sginfo.c
+++ b/src/sginfo.c
@@ -5,7 +5,7 @@
* ./sginfo [options] /dev/sg2 [replace parameters]
*
* Options are:
- * -6 do 6 byte mode sense + select (deafult: 10 byte)
+ * -6 do 6 byte mode sense + select (default: 10 byte)
* -a display all mode pages reported by the device: equivalent to '-t 63'.
* -A display all mode pages and subpages reported by the device: equivalent
* to '-t 63,255'.