diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2017-11-15 06:21:21 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2017-11-15 06:21:21 +0000 |
commit | cad489950e9fc29fe8786ddee2e163831abb3322 (patch) | |
tree | f5263f4d234ec6894c61a8561a4a77c06068c7bc /src | |
parent | 098b15e48f02ac4b501dc383456be94b25c1266b (diff) | |
download | sg3_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.am | 8 | ||||
-rw-r--r-- | src/Makefile.in | 38 | ||||
-rw-r--r-- | src/sg_format.c | 4 | ||||
-rw-r--r-- | src/sg_inq.c | 253 | ||||
-rw-r--r-- | src/sg_logs.c | 46 | ||||
-rw-r--r-- | src/sg_read_long.c | 2 | ||||
-rw-r--r-- | src/sg_sat_identify.c | 2 | ||||
-rw-r--r-- | src/sg_sat_phy_event.c | 4 | ||||
-rw-r--r-- | src/sg_sat_read_gplog.c | 4 | ||||
-rw-r--r-- | src/sg_sat_set_features.c | 4 | ||||
-rw-r--r-- | src/sg_scan_win32.c | 4 | ||||
-rw-r--r-- | src/sg_ses.c | 10 | ||||
-rw-r--r-- | src/sg_test_rwbuf.c | 4 | ||||
-rw-r--r-- | src/sg_write_long.c | 4 | ||||
-rw-r--r-- | src/sg_write_x.c (renamed from src/sg_write_atomic.c) | 6 | ||||
-rw-r--r-- | src/sginfo.c | 2 |
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'. |