diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2020-08-03 04:16:31 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2020-08-03 04:16:31 +0000 |
commit | 936a3271c9f9d86c9592e1406bdd254341ff2849 (patch) | |
tree | 9670d1c5e49bf15e036c7f43830fad570571176f /lib | |
parent | 33f7b2296c779583acd5475484f57552ba437c41 (diff) | |
download | sg3_utils-936a3271c9f9d86c9592e1406bdd254341ff2849.tar.gz |
sg_raw: fix --cmdfile= handling; add --nvm option; sg_pt: add do_nvm_pt(); sg_lib: fix crash in sg_f2hex_arr() when fname not found
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@860 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sg_lib.c | 61 | ||||
-rw-r--r-- | lib/sg_lib_data.c | 4 | ||||
-rw-r--r-- | lib/sg_pt_freebsd.c | 84 | ||||
-rw-r--r-- | lib/sg_pt_linux.c | 20 | ||||
-rw-r--r-- | lib/sg_pt_linux_nvme.c | 167 | ||||
-rw-r--r-- | lib/sg_pt_osf1.c | 10 | ||||
-rw-r--r-- | lib/sg_pt_solaris.c | 10 | ||||
-rw-r--r-- | lib/sg_pt_win32.c | 10 |
8 files changed, 266 insertions, 100 deletions
diff --git a/lib/sg_lib.c b/lib/sg_lib.c index 43a2ebbe..4e8c5ce9 100644 --- a/lib/sg_lib.c +++ b/lib/sg_lib.c @@ -52,7 +52,6 @@ #include "sg_lib.h" #include "sg_lib_data.h" #include "sg_unaligned.h" -#include "sg_pr2serr.h" /* sg_lib_version_str (and datestamp) defined in sg_lib_data.c file */ @@ -75,6 +74,20 @@ pr2ws(const char * fmt, ...) return n; } +/* Users of the sg_pr2serr.h header need this function definition */ +int +pr2serr(const char * fmt, ...) +{ + va_list args; + int n; + + va_start(args, fmt); + n = vfprintf(stderr, fmt, args); + va_end(args); + return n; +} + + /* Want safe, 'n += snprintf(b + n, blen - n, ...)' style sequence of * functions. Returns number of chars placed in cp excluding the * trailing null char. So for cp_max_len > 0 the return value is always @@ -2529,7 +2542,7 @@ sg_get_sfs_str(uint16_t sfs_code, int peri_type, int buff_len, char * buff, } if (verbose > 4) - pr2serr("%s: length of returned string (n) %d\n", __func__, n); + pr2ws("%s: length of returned string (n) %d\n", __func__, n); return buff; } @@ -3473,8 +3486,10 @@ sg_f2hex_arr(const char * fname, bool as_binary, bool no_space, char line[512]; char carry_over[4]; - if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len)) + if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len)) { + pr2ws("%s: bad arguments\n", __func__); return SG_LIB_LOGIC_ERROR; + } fn_len = strlen(fname); if (0 == fn_len) return SG_LIB_SYNTAX_ERROR; @@ -3486,7 +3501,7 @@ sg_f2hex_arr(const char * fname, bool as_binary, bool no_space, fd = open(fname, O_RDONLY); if (fd < 0) { err = errno; - pr2serr("unable to open binary file %s: %s\n", fname, + pr2ws("unable to open binary file %s: %s\n", fname, safe_strerror(err)); return sg_convert_errno(err); } @@ -3495,10 +3510,10 @@ sg_f2hex_arr(const char * fname, bool as_binary, bool no_space, if (k <= 0) { if (0 == k) { ret = SG_LIB_SYNTAX_ERROR; - pr2serr("read 0 bytes from binary file %s\n", fname); + pr2ws("read 0 bytes from binary file %s\n", fname); } else { ret = sg_convert_errno(errno); - pr2serr("read from binary file %s: %s\n", fname, + pr2ws("read from binary file %s: %s\n", fname, safe_strerror(errno)); } goto bin_fini; @@ -3511,7 +3526,7 @@ sg_f2hex_arr(const char * fname, bool as_binary, bool no_space, break; if (m < 0) { err = errno; - pr2serr("read from binary pipe %s: %s\n", fname, + pr2ws("read from binary pipe %s: %s\n", fname, safe_strerror(err)); ret = sg_convert_errno(err); goto bin_fini; @@ -3521,7 +3536,7 @@ sg_f2hex_arr(const char * fname, bool as_binary, bool no_space, } *mp_arr_len = k; bin_fini: - if (! has_stdin) + if ((fd >= 0) && (! has_stdin)) close(fd); return ret; } @@ -3533,7 +3548,7 @@ bin_fini: fp = fopen(fname, "r"); if (NULL == fp) { err = errno; - pr2serr("Unable to open %s for reading: %s\n", fname, + pr2ws("Unable to open %s for reading: %s\n", fname, safe_strerror(err)); ret = sg_convert_errno(err); goto fini; @@ -3564,7 +3579,7 @@ bin_fini: if (1 == sscanf(carry_over, "%4x", &h)) mp_arr[off - 1] = h; /* back up and overwrite */ else { - pr2serr("%s: carry_over error ['%s'] around line %d\n", + pr2ws("%s: carry_over error ['%s'] around line %d\n", __func__, carry_over, j + 1); ret = SG_LIB_SYNTAX_ERROR; goto fini; @@ -3586,7 +3601,7 @@ bin_fini: continue; k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t"); if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) { - pr2serr("%s: syntax error at line %d, pos %d\n", __func__, + pr2ws("%s: syntax error at line %d, pos %d\n", __func__, j + 1, m + k + 1); ret = SG_LIB_SYNTAX_ERROR; goto fini; @@ -3595,13 +3610,13 @@ bin_fini: for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1)); ++k, lcp += 2) { if (1 != sscanf(lcp, "%2x", &h)) { - pr2serr("%s: bad hex number in line %d, pos %d\n", + pr2ws("%s: bad hex number in line %d, pos %d\n", __func__, j + 1, (int)(lcp - line + 1)); ret = SG_LIB_SYNTAX_ERROR; goto fini; } if ((off + k) >= max_arr_len) { - pr2serr("%s: array length exceeded\n", __func__); + pr2ws("%s: array length exceeded\n", __func__); *mp_arr_len = max_arr_len; ret = SG_LIB_LBA_OUT_OF_RANGE; goto fini; @@ -3615,7 +3630,7 @@ bin_fini: for (k = 0; k < 1024; ++k) { if (1 == sscanf(lcp, "%10x", &h)) { if (h > 0xff) { - pr2serr("%s: hex number larger than 0xff in line " + pr2ws("%s: hex number larger than 0xff in line " "%d, pos %d\n", __func__, j + 1, (int)(lcp - line + 1)); ret = SG_LIB_SYNTAX_ERROR; @@ -3626,7 +3641,7 @@ bin_fini: carry_over[0] = *lcp; } if ((off + k) >= max_arr_len) { - pr2serr("%s: array length exceeded\n", __func__); + pr2ws("%s: array length exceeded\n", __func__); ret = SG_LIB_LBA_OUT_OF_RANGE; *mp_arr_len = max_arr_len; goto fini; @@ -3643,7 +3658,7 @@ bin_fini: --k; break; } - pr2serr("%s: error in line %d, at pos %d\n", __func__, + pr2ws("%s: error in line %d, at pos %d\n", __func__, j + 1, (int)(lcp - line + 1)); ret = SG_LIB_SYNTAX_ERROR; goto fini; @@ -3657,7 +3672,7 @@ bin_fini: fclose(fp); return 0; fini: - if (stdin != fp) + if (fp && (stdin != fp)) fclose(fp); return ret; } @@ -3694,18 +3709,6 @@ sg_ata_get_chars(const uint16_t * word_arr, int start_word, return op - ochars; } -int -pr2serr(const char * fmt, ...) -{ - va_list args; - int n; - - va_start(args, fmt); - n = vfprintf(stderr, fmt, args); - va_end(args); - return n; -} - #ifdef SG_LIB_FREEBSD #include <sys/param.h> #elif defined(SG_LIB_WIN32) diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c index e64c240d..0a8543af 100644 --- a/lib/sg_lib_data.c +++ b/lib/sg_lib_data.c @@ -19,7 +19,7 @@ #include "sg_lib_data.h" -const char * sg_lib_version_str = "2.76 20200708"; +const char * sg_lib_version_str = "2.77 20200731"; /* spc6r02, sbc4r20a, zbc2r04 */ @@ -635,7 +635,7 @@ struct sg_lib_value_name_t sg_lib_read_attr_arr[] = { /* A conveniently formatted list of SCSI ASC/ASCQ codes and their * corresponding text can be found at: www.t10.org/lists/asc-num.txt - * The following should match asc-num.txt dated 20200624 */ + * The following should match asc-num.txt dated 20200710 */ #ifdef SG_SCSI_STRINGS struct sg_lib_asc_ascq_range_t sg_lib_asc_ascq_range[] = diff --git a/lib/sg_pt_freebsd.c b/lib/sg_pt_freebsd.c index 4d2e5887..4fbe3434 100644 --- a/lib/sg_pt_freebsd.c +++ b/lib/sg_pt_freebsd.c @@ -57,8 +57,8 @@ struct freebsd_dev_channel { int unitnum; // the SCSI unit number - bool is_nvme; /* OS device type, if false ignore nvme_direct */ - bool nvme_direct; /* false: our SNTL; true: received NVMe command */ + bool is_nvme; /* OS device type, if false ignore nvme_our_sntl */ + bool nvme_our_sntl; /* true: our SNTL; false: received NVMe command */ bool is_char; uint32_t nsid; uint32_t nv_ctrlid; @@ -107,7 +107,7 @@ struct sg_pt_freebsd_scsi { // (dev_han - FREEBSD_FDOFFSET) is the // index into devicetable[] bool is_nvme; // copy of same field in fdc object - bool nvme_direct; // copy of same field in fdc object + bool nvme_our_sntl; // copy of same field in fdc object struct sg_sntl_dev_state_t * dev_statp; // points to associated fdc }; @@ -251,7 +251,7 @@ scsi_pt_open_flags(const char * device_name, int oflags, int vb) goto scsi_ata_try; } fdc_p->is_nvme = true; - fdc_p->nvme_direct = false; + fdc_p->nvme_our_sntl = true; /* guess at this stage */ fdc_p->is_char = is_char; fdc_p->nsid = (broadcast_nsid == nsid) ? 0 : nsid; fdc_p->nv_ctrlid = nv_ctrlid; @@ -462,19 +462,19 @@ partial_clear_scsi_pt_obj(struct sg_pt_base * vp) ptp->in_err = 0; ptp->os_err = 0; ptp->transport_err = 0; - if (ptp->nvme_direct) { - struct freebsd_dev_channel *fdc_p; - - fdc_p = get_fdc_p(ptp); - if (fdc_p) - fdc_p->nvme_result = 0; - } else { + if (ptp->nvme_our_sntl) { ptp->scsi_status = 0; ptp->dxfer_dir = CAM_DIR_NONE; ptp->dxferip = NULL; ptp->dxfer_ilen = 0; ptp->dxferop = NULL; ptp->dxfer_olen = 0; + } else { + struct freebsd_dev_channel *fdc_p; + + fdc_p = get_fdc_p(ptp); + if (fdc_p) + fdc_p->nvme_result = 0; } } @@ -816,7 +816,7 @@ get_scsi_pt_resid(const struct sg_pt_base * vp) { const struct sg_pt_freebsd_scsi * ptp = &vp->impl; - return ((NULL == ptp) || ptp->nvme_direct) ? 0 : ptp->resid; + return ((NULL == ptp) || (! ptp->nvme_our_sntl)) ? 0 : ptp->resid; } void @@ -870,15 +870,16 @@ get_scsi_pt_status_response(const struct sg_pt_base * vp) const struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp) { - if (ptp->nvme_direct) { + if (ptp->nvme_our_sntl) + return ptp->scsi_status; + else { const struct freebsd_dev_channel *fdc_p; fdc_p = get_fdc_cp(ptp); if (NULL == fdc_p) return -1; return (int)fdc_p->nvme_status; - } else - return ptp->scsi_status; + } } return -1; } @@ -890,15 +891,16 @@ get_pt_result(const struct sg_pt_base * vp) const struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp) { - if (ptp->nvme_direct) { + if (ptp->nvme_our_sntl) + return (uint32_t)ptp->scsi_status; + else { const struct freebsd_dev_channel *fdc_p; fdc_p = get_fdc_cp(ptp); if (NULL == fdc_p) return -1; return fdc_p->nvme_result; - } else - return (uint32_t)ptp->scsi_status; + } } return 0xffffffff; } @@ -2187,9 +2189,9 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int vb) if (vb > 3) pr2ws("%s: opcode=0x%x, fd=%d\n", __func__, cdbp[0], fd); scsi_cdb = sg_is_scsi_cdb(cdbp, n); - /* nvme_direct is true when NVMe command (64 byte) has been given */ - ptp->nvme_direct = ! scsi_cdb; - fdc_p->nvme_direct = ptp->nvme_direct; + /* nvme_our_sntl is false when NVMe command (64 byte) has been given */ + ptp->nvme_our_sntl = scsi_cdb; + fdc_p->nvme_our_sntl = ptp->nvme_our_sntl; if (scsi_cdb) { switch (cdbp[0]) { case SCSI_INQUIRY_OPC: @@ -2308,3 +2310,43 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int vb) } #endif /* (HAVE_NVME && (! IGNORE_NVME)) */ + +#if (HAVE_NVME && (! IGNORE_NVME)) + +int +do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int vb) +{ + if (vb) + pr2ws("%s: not supported, ", __func__); + if (vp) { } + if (submq) { } + if (timeout_secs) { } + return SCSI_PT_DO_NOT_SUPPORTED; +} + +#else /* (HAVE_NVME && (! IGNORE_NVME)) */ + +int +do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose) +{ + if (vb) { + pr2ws("%s: not supported, ", __func__); +#ifdef HAVE_NVME + pr2ws("HAVE_NVME, "); +#else + pr2ws("don't HAVE_NVME, "); +#endif + +#ifdef IGNORE_NVME + pr2ws("IGNORE_NVME"); +#else + pr2ws("don't IGNORE_NVME"); +#endif + } + if (vp) { } + if (submq) { } + if (timeout_secs) { } + return SCSI_PT_DO_NOT_SUPPORTED; +} + +#endif /* (HAVE_NVME && (! IGNORE_NVME)) */ diff --git a/lib/sg_pt_linux.c b/lib/sg_pt_linux.c index 9e8a571e..690abf82 100644 --- a/lib/sg_pt_linux.c +++ b/lib/sg_pt_linux.c @@ -471,7 +471,7 @@ clear_scsi_pt_obj(struct sg_pt_base * vp) ptp->is_sg = is_sg; ptp->is_bsg = is_bsg; ptp->is_nvme = is_nvme; - ptp->nvme_direct = false; + ptp->nvme_our_sntl = false; ptp->nvme_nsid = nvme_nsid; ptp->dev_stat = dev_stat; } @@ -486,9 +486,7 @@ partial_clear_scsi_pt_obj(struct sg_pt_base * vp) return; ptp->in_err = 0; ptp->os_err = 0; - if (ptp->nvme_direct) - ptp->nvme_result = 0; - else { + if (ptp->nvme_our_sntl) { ptp->io_hdr.device_status = 0; ptp->io_hdr.transport_status = 0; ptp->io_hdr.driver_status = 0; @@ -496,7 +494,8 @@ partial_clear_scsi_pt_obj(struct sg_pt_base * vp) ptp->io_hdr.din_xfer_len = 0; ptp->io_hdr.dout_xferp = 0; ptp->io_hdr.dout_xfer_len = 0; - } + } else + ptp->nvme_result = 0; } #ifndef SG_SET_GET_EXTENDED @@ -610,7 +609,7 @@ set_pt_file_handle(struct sg_pt_base * vp, int dev_fd, int verbose) ptp->is_sg = false; ptp->is_bsg = false; ptp->is_nvme = false; - ptp->nvme_direct = false; + ptp->nvme_our_sntl = false; ptp->nvme_nsid = 0; ptp->os_err = 0; } @@ -797,7 +796,7 @@ get_scsi_pt_resid(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; - if ((NULL == ptp) || (ptp->nvme_direct)) + if ((NULL == ptp) || (! ptp->nvme_our_sntl)) return 0; else if ((ptp->io_hdr.din_xfer_len > 0) && (ptp->io_hdr.dout_xfer_len > 0)) @@ -856,8 +855,8 @@ get_scsi_pt_status_response(const struct sg_pt_base * vp) if (NULL == ptp) return 0; - return (int)(ptp->nvme_direct ? ptp->nvme_status : - ptp->io_hdr.device_status); + return (int)(ptp->nvme_our_sntl ? ptp->io_hdr.device_status : + ptp->nvme_status); } uint32_t @@ -867,8 +866,7 @@ get_pt_result(const struct sg_pt_base * vp) if (NULL == ptp) return 0; - return ptp->nvme_direct ? ptp->nvme_result : - ptp->io_hdr.device_status; + return ptp->nvme_our_sntl ? ptp->io_hdr.device_status : ptp->nvme_result; } int diff --git a/lib/sg_pt_linux_nvme.c b/lib/sg_pt_linux_nvme.c index 60e042e3..b8d88696 100644 --- a/lib/sg_pt_linux_nvme.c +++ b/lib/sg_pt_linux_nvme.c @@ -345,7 +345,7 @@ sg_nvme_admin_cmd(struct sg_pt_linux_scsi * ptp, /* Now res contains NVMe completion queue CDW3 31:17 (15 bits) */ ptp->nvme_result = cmdp->result; - if (ptp->nvme_direct && ptp->io_hdr.response && + if ((! ptp->nvme_our_sntl) && ptp->io_hdr.response && (ptp->io_hdr.max_response_len > 3)) { /* build 32 byte "sense" buffer */ uint8_t * sbp = (uint8_t *)(sg_uintptr_t)ptp->io_hdr.response; @@ -1327,35 +1327,18 @@ fini: return res; } -/* Since ptp can be a char device (e.g. /dev/nvme0) or a blocks device - * (e.g. /dev/nvme0n1 or /dev/nvme0n1p3) use NVME_IOCTL_IO_CMD which is - * common to both (and takes a timeout). The difficult is that - * NVME_IOCTL_IO_CMD takes a nvme_passthru_cmd object point. */ static int -sntl_do_nvm_cmd(struct sg_pt_linux_scsi * ptp, struct sg_nvme_user_io * iop, - uint32_t dlen, bool is_read, int time_secs, int vb) +do_nvm_pt_low(struct sg_pt_linux_scsi * ptp, + struct sg_nvme_passthru_cmd *cmdp, void * dp, int dlen, + bool is_read, int time_secs, int vb) { - const uint32_t cmd_len = sizeof(struct sg_nvme_passthru_cmd); int res; uint32_t n; uint16_t sct_sc; - struct sg_nvme_passthru_cmd nvme_pt_cmd; - struct sg_nvme_passthru_cmd *cmdp = &nvme_pt_cmd; const uint8_t * up = ((const uint8_t *)cmdp) + SG_NVME_PT_OPCODE; - void * dp; char nam[64]; - memset(cmdp, 0, sizeof(*cmdp)); - cmdp->opcode = iop->opcode; - cmdp->flags = iop->flags; - cmdp->nsid = ptp->nvme_nsid; - cmdp->addr = iop->addr; - cmdp->data_len = dlen; - dp = (void *)iop->addr; - cmdp->cdw10 = iop->slba & 0xffffffff; - cmdp->cdw11 = (iop->slba >> 32) & 0xffffffff; - cmdp->cdw12 = iop->nblocks; /* lower 16 bits already "0's based" count */ if (vb) sg_get_nvme_opcode_name(*up, false /* NVM */ , sizeof(nam), nam); else @@ -1366,11 +1349,9 @@ sntl_do_nvm_cmd(struct sg_pt_linux_scsi * ptp, struct sg_nvme_user_io * iop, pr2ws("NVMe NVM command: %s\n", nam); hex2stderr((const uint8_t *)cmdp, cmd_len, 1); if ((vb > 3) && (! is_read) && dp) { - uint32_t len = sg_get_unaligned_le32(up + SG_NVME_PT_DATA_LEN); - - if (len > 0) { - n = len; - if ((len < 512) || (vb > 5)) + if (dlen > 0) { + n = dlen; + if ((dlen < 512) || (vb > 5)) pr2ws("\nData-out buffer (%u bytes):\n", n); else { pr2ws("\nData-out buffer (first 512 of %u bytes):\n", n); @@ -1392,7 +1373,7 @@ sntl_do_nvm_cmd(struct sg_pt_linux_scsi * ptp, struct sg_nvme_user_io * iop, /* Now res contains NVMe completion queue CDW3 31:17 (15 bits) */ ptp->nvme_result = cmdp->result; - if (ptp->nvme_direct && ptp->io_hdr.response && + if ((! ptp->nvme_our_sntl) && ptp->io_hdr.response && (ptp->io_hdr.max_response_len > 3)) { /* build 32 byte "sense" buffer */ uint8_t * sbp = (uint8_t *)(sg_uintptr_t)ptp->io_hdr.response; @@ -1423,11 +1404,9 @@ sntl_do_nvm_cmd(struct sg_pt_linux_scsi * ptp, struct sg_nvme_user_io * iop, return SG_LIB_NVME_STATUS; /* == SCSI_PT_DO_NVME_STATUS */ } if ((vb > 3) && is_read && dp) { - uint32_t len = sg_get_unaligned_le32(up + SG_NVME_PT_DATA_LEN); - - if (len > 0) { - n = len; - if ((len < 1024) || (vb > 5)) + if (dlen > 0) { + n = dlen; + if ((dlen < 1024) || (vb > 5)) pr2ws("\nData-in buffer (%u bytes):\n", n); else { pr2ws("\nData-in buffer (first 1024 of %u bytes):\n", n); @@ -1439,6 +1418,32 @@ sntl_do_nvm_cmd(struct sg_pt_linux_scsi * ptp, struct sg_nvme_user_io * iop, return 0; } +/* Since ptp can be a char device (e.g. /dev/nvme0) or a blocks device + * (e.g. /dev/nvme0n1 or /dev/nvme0n1p3) use NVME_IOCTL_IO_CMD which is + * common to both (and takes a timeout). The difficult is that + * NVME_IOCTL_IO_CMD takes a nvme_passthru_cmd object point. */ +static int +sntl_do_nvm_cmd(struct sg_pt_linux_scsi * ptp, struct sg_nvme_user_io * iop, + uint32_t dlen, bool is_read, int time_secs, int vb) +{ + + struct sg_nvme_passthru_cmd nvme_pt_cmd; + struct sg_nvme_passthru_cmd *cmdp = &nvme_pt_cmd; + void * dp = (void *)iop->addr; + + memset(cmdp, 0, sizeof(*cmdp)); + cmdp->opcode = iop->opcode; + cmdp->flags = iop->flags; + cmdp->nsid = ptp->nvme_nsid; + cmdp->addr = iop->addr; + cmdp->data_len = dlen; + cmdp->cdw10 = iop->slba & 0xffffffff; + cmdp->cdw11 = (iop->slba >> 32) & 0xffffffff; + cmdp->cdw12 = iop->nblocks; /* lower 16 bits already "0's based" count */ + + return do_nvm_pt_low(ptp, cmdp, dp, dlen, is_read, time_secs, vb); +} + static int sntl_read(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, int time_secs, int vb) @@ -1468,8 +1473,12 @@ sntl_read(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, } else nblks_t10 = num; } - if (0 == nblks_t10) /* NOP in SCSI */ + if (0 == nblks_t10) { /* NOP in SCSI */ + if (vb > 4) + pr2ws("%s: nblks_t10 is 0, a NOP in SCSI, can't map to NVMe\n", + __func__); return 0; + } iop->nblocks = nblks_t10 - 1; /* crazy "0's based" */ if (have_fua) iop->nblocks |= SG_NVME_NVM_CDW12_FUA; @@ -1512,8 +1521,12 @@ sntl_write(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, } else nblks_t10 = num; } - if (0 == nblks_t10) /* NOP in SCSI */ + if (0 == nblks_t10) { /* NOP in SCSI */ + if (vb > 4) + pr2ws("%s: nblks_t10 is 0, a NOP in SCSI, can't map to NVMe\n", + __func__); return 0; + } iop->nblocks = nblks_t10 - 1; if (have_fua) iop->nblocks |= SG_NVME_NVM_CDW12_FUA; @@ -1560,8 +1573,12 @@ sntl_verify(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, } else nblks_t10 = num; } - if (0 == nblks_t10) /* NOP in SCSI */ + if (0 == nblks_t10) { /* NOP in SCSI */ + if (vb > 4) + pr2ws("%s: nblks_t10 is 0, a NOP in SCSI, can't map to NVMe\n", + __func__); return 0; + } iop->nblocks = nblks_t10 - 1; if (bytchk) { iop->addr = (uint64_t)ptp->io_hdr.dout_xferp; @@ -1632,8 +1649,12 @@ sntl_write_same(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, } else nblks_t10 = num; } - if (0 == nblks_t10) /* NOP in SCSI */ + if (0 == nblks_t10) { /* NOP in SCSI */ + if (vb > 4) + pr2ws("%s: nblks_t10 is 0, a NOP in SCSI, can't map to NVMe\n", + __func__); return 0; + } iop->nblocks = nblks_t10 - 1; res = sntl_do_nvm_cmd(ptp, iop, 0, false, time_secs, vb); if (SG_LIB_NVME_STATUS == res) { @@ -1723,7 +1744,7 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int time_secs, int vb) cdbp[0], fd, hold_dev_fd, time_secs); scsi_cdb = sg_is_scsi_cdb(cdbp, n); /* direct NVMe command (i.e. 64 bytes long) or SNTL */ - ptp->nvme_direct = ! scsi_cdb; + ptp->nvme_our_sntl = scsi_cdb; if (scsi_cdb) { switch (cdbp[0]) { case SCSI_INQUIRY_OPC: @@ -1837,3 +1858,75 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int time_secs, int vb) } #endif /* (HAVE_NVME && (! IGNORE_NVME)) */ + +#if (HAVE_NVME && (! IGNORE_NVME)) + +int +do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int vb) +{ + bool is_read = false; + int dlen; + struct sg_pt_linux_scsi * ptp = &vp->impl; + struct sg_nvme_passthru_cmd cmd; + uint8_t * cmdp = (uint8_t *)&cmd; + void * dp = NULL; + + if (vb && (submq != 0)) + pr2ws("%s: warning, uses submit queue 0\n", __func__); + if (ptp->dev_fd < 0) { + if (vb > 1) + pr2ws("%s: no NVMe file descriptor given\n", __func__); + return SCSI_PT_DO_BAD_PARAMS; + } + if (! ptp->is_nvme) { + if (vb > 1) + pr2ws("%s: file descriptor is not NVMe device\n", __func__); + return SCSI_PT_DO_BAD_PARAMS; + } + if ((! ptp->io_hdr.request) || (64 != ptp->io_hdr.request_len)) { + if (vb > 1) + pr2ws("%s: no NVMe 64 byte command present\n", __func__); + return SCSI_PT_DO_BAD_PARAMS; + } + if (sizeof(cmd) > 64) + memset(cmdp + 64, 0, sizeof(cmd) - 64); + memcpy(cmdp, (uint8_t *)(sg_uintptr_t)ptp->io_hdr.request, 64); + ptp->nvme_our_sntl = false; + + dlen = ptp->io_hdr.din_xfer_len; + if (dlen > 0) { + is_read = true; + dp = (void *)(sg_uintptr_t)ptp->io_hdr.din_xferp; + } else { + dlen = ptp->io_hdr.dout_xfer_len; + if (dlen > 0) + dp = (void *)(sg_uintptr_t)ptp->io_hdr.dout_xferp; + } + return do_nvm_pt_low(ptp, &cmd, dp, dlen, is_read, timeout_secs, vb); +} + +#else /* (HAVE_NVME && (! IGNORE_NVME)) */ + +int +do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose) +{ + if (vb) { + pr2ws("%s: not supported, ", __func__); +#ifdef HAVE_NVME + pr2ws("HAVE_NVME, "); +#else + pr2ws("don't HAVE_NVME, "); +#endif + +#ifdef IGNORE_NVME + pr2ws("IGNORE_NVME"); +#else + pr2ws("don't IGNORE_NVME"); +#endif + if (vp) { } + if (submq) { } + if (timeout_secs) { } + return SCSI_PT_DO_NOT_SUPPORTED; +} + +#endif /* (HAVE_NVME && (! IGNORE_NVME)) */ diff --git a/lib/sg_pt_osf1.c b/lib/sg_pt_osf1.c index 5901b16b..99900fd3 100644 --- a/lib/sg_pt_osf1.c +++ b/lib/sg_pt_osf1.c @@ -640,3 +640,13 @@ get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) b[max_b_len - 1] = '\0'; return b; } + +int +do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose) +{ + if (vp) { } + if (submq) { } + if (timeout_secs) { } + if (verbose) { } + return SCSI_PT_DO_NOT_SUPPORTED; +} diff --git a/lib/sg_pt_solaris.c b/lib/sg_pt_solaris.c index c2444997..ec346ab4 100644 --- a/lib/sg_pt_solaris.c +++ b/lib/sg_pt_solaris.c @@ -519,3 +519,13 @@ get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) b[max_b_len - 1] = '\0'; return b; } + +int +do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose) +{ + if (vp) { } + if (submq) { } + if (timeout_secs) { } + if (verbose) { } + return SCSI_PT_DO_NOT_SUPPORTED; +} diff --git a/lib/sg_pt_win32.c b/lib/sg_pt_win32.c index 4e10f4cc..b894c584 100644 --- a/lib/sg_pt_win32.c +++ b/lib/sg_pt_win32.c @@ -3132,3 +3132,13 @@ nvme_pt(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp, } #endif /* (HAVE_NVME && (! IGNORE_NVME)) */ + +int +do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose) +{ + if (vp) { } + if (submq) { } + if (timeout_secs) { } + if (verbose) { } + return SCSI_PT_DO_NOT_SUPPORTED; +} |