aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2020-08-03 04:16:31 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2020-08-03 04:16:31 +0000
commit936a3271c9f9d86c9592e1406bdd254341ff2849 (patch)
tree9670d1c5e49bf15e036c7f43830fad570571176f /lib
parent33f7b2296c779583acd5475484f57552ba437c41 (diff)
downloadsg3_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.c61
-rw-r--r--lib/sg_lib_data.c4
-rw-r--r--lib/sg_pt_freebsd.c84
-rw-r--r--lib/sg_pt_linux.c20
-rw-r--r--lib/sg_pt_linux_nvme.c167
-rw-r--r--lib/sg_pt_osf1.c10
-rw-r--r--lib/sg_pt_solaris.c10
-rw-r--r--lib/sg_pt_win32.c10
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;
+}