aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2018-01-13 06:38:53 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2018-01-13 06:38:53 +0000
commit239d147229acac3d3504360a38cd5ec8505d0d5e (patch)
tree308272c943a93228ac732eff81e7f94840d6e76e /lib
parent605b21190ce9af77ee3533e12b2e59a7f883ffee (diff)
downloadsg3_utils-239d147229acac3d3504360a38cd5ec8505d0d5e.tar.gz
sg_ses_microcode: add --dry-run and --ealsd; sg_write_buffer: add --dry-run
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@744 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib')
-rw-r--r--lib/sg_cmds_basic.c2
-rw-r--r--lib/sg_cmds_extra.c31
-rw-r--r--lib/sg_lib.c5
-rw-r--r--lib/sg_lib_data.c9
-rw-r--r--lib/sg_pt_freebsd.c139
-rw-r--r--lib/sg_pt_linux_nvme.c51
6 files changed, 147 insertions, 90 deletions
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 479d45b3..2f0cbac0 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -36,7 +36,7 @@
#endif
-static const char * const version_str = "1.78 20180104";
+static const char * const version_str = "1.79 20180112";
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
diff --git a/lib/sg_cmds_extra.c b/lib/sg_cmds_extra.c
index cbd8e626..a6072c95 100644
--- a/lib/sg_cmds_extra.c
+++ b/lib/sg_cmds_extra.c
@@ -452,7 +452,7 @@ sg_ll_report_referrals(int sg_fd, uint64_t start_llba, bool one_seg,
* value is taken as the timeout value in seconds. Return of 0 -> success,
* various SG_LIB_CAT_* positive values or -1 -> other errors */
int
-sg_ll_send_diag(int sg_fd, int sf_code, bool pf_bit, bool sf_bit,
+sg_ll_send_diag(int sg_fd, int st_code, bool pf_bit, bool st_bit,
bool devofl_bit, bool unitofl_bit, int long_duration,
void * paramp, int param_len, bool noisy, int verbose)
{
@@ -463,10 +463,10 @@ sg_ll_send_diag(int sg_fd, int sf_code, bool pf_bit, bool sf_bit,
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
- senddiag_cdb[1] = (unsigned char)(sf_code << 5);
+ senddiag_cdb[1] = (unsigned char)(st_code << 5);
if (pf_bit)
senddiag_cdb[1] |= 0x10;
- if (sf_bit)
+ if (st_bit)
senddiag_cdb[1] |= 0x4;
if (devofl_bit)
senddiag_cdb[1] |= 0x2;
@@ -851,19 +851,32 @@ sg_ll_format_unit(int sg_fd, int fmtpinfo, bool longlist, bool fmtdata,
bool cmplst, int dlist_format, int timeout_secs,
void * paramp, int param_len, bool noisy, int verbose)
{
- return sg_ll_format_unit2(sg_fd, fmtpinfo, longlist, fmtdata, cmplst,
- dlist_format, 0, timeout_secs, paramp,
- param_len, noisy, verbose);
+ return sg_ll_format_unit_v2(sg_fd, fmtpinfo, longlist, fmtdata, cmplst,
+ dlist_format, 0, timeout_secs, paramp,
+ param_len, noisy, verbose);
}
-/* Invokes a FORMAT UNIT (SBC-4) command. Return of 0 -> success,
- * various SG_LIB_CAT_* positive values or -1 -> other errors.
- * FFMT field added in sbc4r10 [20160121] */
+/* Invokes a FORMAT UNIT (SBC-3) command. Return of 0 -> success,
+ * various SG_LIB_CAT_* positive values or -1 -> other errors */
int
sg_ll_format_unit2(int sg_fd, int fmtpinfo, bool longlist, bool fmtdata,
bool cmplst, int dlist_format, int ffmt, int timeout_secs,
void * paramp, int param_len, bool noisy, int verbose)
{
+ return sg_ll_format_unit_v2(sg_fd, fmtpinfo, longlist, fmtdata, cmplst,
+ dlist_format, ffmt, timeout_secs, paramp,
+ param_len, noisy, verbose);
+}
+
+/* Invokes a FORMAT UNIT (SBC-4) command. Return of 0 -> success,
+ * various SG_LIB_CAT_* positive values or -1 -> other errors.
+ * FFMT field added in sbc4r10 [20160121] */
+int
+sg_ll_format_unit_v2(int sg_fd, int fmtpinfo, bool longlist, bool fmtdata,
+ bool cmplst, int dlist_format, int ffmt,
+ int timeout_secs, void * paramp, int param_len,
+ bool noisy, int verbose)
+{
static const char * const cdb_name_s = "format unit";
int k, res, ret, sense_cat, tmout;
unsigned char fu_cdb[FORMAT_UNIT_CMDLEN] =
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index f6bafb52..314a5508 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -27,13 +27,14 @@
*
*/
+#define _POSIX_C_SOURCE 200809L /* for posix_memalign() */
+#define __STDC_FORMAT_MACROS 1
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
-#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#ifdef HAVE_CONFIG_H
@@ -3265,6 +3266,8 @@ sg_memalign(uint32_t num_bytes, uint32_t align_to, uint8_t ** buff_to_free,
size_t psz;
uint8_t * res;
+ if (buff_to_free) /* make sure buff_to_free is NULL if alloc fails */
+ *buff_to_free = NULL;
psz = (align_to > 0) ? align_to : sg_get_page_size();
if (0 == num_bytes)
num_bytes = psz; /* ugly to handle otherwise */
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index b3842632..5ac4a9bb 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -17,7 +17,7 @@
#include "sg_lib_data.h"
-const char * sg_lib_version_str = "2.36 20180104";/* spc5r17, sbc4r15 */
+const char * sg_lib_version_str = "2.37 20180109";/* spc5r17, sbc4r15 */
/* indexed by pdt; those that map to own index do not decay */
@@ -1507,6 +1507,8 @@ struct sg_lib_value_name_t sg_lib_scsi_feature_sets[] =
{0x0, 0, NULL}, /* 0x0 is reserved sfs; trailing sentinel */
};
+#if (SG_SCSI_STRINGS && HAVE_NVME && (! IGNORE_NVME))
+
/* .value is completion queue's DW3 as follows: ((DW3 >> 17) & 0x3ff)
* .peri_dev_type is an index for the sg_lib_scsi_status_sense_arr[]
* .name is taken from NVMe 1.3a document, section 4.6.1.2.1 with less
@@ -1516,7 +1518,6 @@ struct sg_lib_value_name_t sg_lib_scsi_feature_sets[] =
* Bits 29:28 are reserved, bit 27:25 are the "Status Code Type" (SCT)
* and bits 24:17 are the Status Code (SC). This table is in ascending
* order of its .value field so a binary search could be done on it. */
-#ifdef SG_SCSI_STRINGS
struct sg_lib_value_name_t sg_lib_nvme_cmd_status_arr[] =
{
/* Generic command status values, Status Code Type (SCT): 0h
@@ -1665,7 +1666,7 @@ struct sg_lib_4tuple_u8 sg_lib_scsi_status_sense_arr[] =
};
-#else /* no SG_SCSI_STRINGS define in config.sys */
+#else /* (SG_SCSI_STRINGS && HAVE_NVME && (! IGNORE_NVME)) */
struct sg_lib_value_name_t sg_lib_nvme_cmd_status_arr[] =
{
@@ -1680,4 +1681,4 @@ struct sg_lib_4tuple_u8 sg_lib_scsi_status_sense_arr[] =
{0xff, 0xff, 0xff, 0xff},
};
-#endif /* SG_SCSI_STRINGS */
+#endif /* (SG_SCSI_STRINGS && HAVE_NVME && (! IGNORE_NVME)) */
diff --git a/lib/sg_pt_freebsd.c b/lib/sg_pt_freebsd.c
index 9ded65ca..efad6d12 100644
--- a/lib/sg_pt_freebsd.c
+++ b/lib/sg_pt_freebsd.c
@@ -5,7 +5,7 @@
* license that can be found in the BSD_LICENSE file.
*/
-/* sg_pt_freebsd version 1.21 20180104 */
+/* sg_pt_freebsd version 1.22 20180112 */
#include <stdio.h>
#include <stdlib.h>
@@ -39,7 +39,13 @@
#include "sg_lib.h"
#include "sg_unaligned.h"
#include "sg_pt_nvme.h"
+
+#if (HAVE_NVME && (! IGNORE_NVME))
#include "freebsd_nvme_ioctl.h"
+#else
+#define NVME_CTRLR_PREFIX "/dev/nvme"
+#define NVME_NS_PREFIX "ns"
+#endif
#define FREEBSD_MAXDEV 64
@@ -128,10 +134,12 @@ pr2ws(const char * fmt, ...)
return n;
}
+#if (HAVE_NVME && (! IGNORE_NVME))
static inline bool is_aligned(const void * pointer, size_t byte_count)
{
- return (sg_uintptr_t)pointer % byte_count == 0;
+ return ((sg_uintptr_t)pointer % byte_count) == 0;
}
+#endif
/* Returns >= 0 if successful. If error in Unix returns negated errno. */
int
@@ -577,34 +585,6 @@ set_scsi_pt_flags(struct sg_pt_base * objp, int flags)
if (flags) { ; } /* unused, suppress warning */
}
-static int
-nvme_pt_low(struct freebsd_dev_channel *fdc_p, void * dxferp, uint32_t len,
- bool is_read, struct nvme_pt_command * npcp, int vb)
-{
- int err, status;
- uint8_t opcode;
- char b[80];
-
- if (fdc_p->dev_fd < 0) {
- if (vb)
- pr2ws("%s: is_nvme is true but dev_fd<0, inconsistent\n",
- __func__);
- return -EINVAL;
- }
- npcp->buf = dxferp;
- npcp->len = len;
- npcp->is_read = (uint32_t)is_read;
- opcode = npcp->cmd.opc;
- err = ioctl(fdc_p->dev_fd, NVME_PASSTHROUGH_CMD, npcp);
- if (err < 0)
- return -errno;
- status = ((npcp->cpl.status.sct << 8) | npcp->cpl.status.sc);
- if (status && vb)
- pr2ws("%s: opcode=0x%x, status: %s\n", __func__, opcode,
- sg_get_nvme_cmd_status_str(status, sizeof(b), b));
- return status;
-}
-
/* Executes SCSI command (or at least forwards it to lower layers).
* Clears os_err field prior to active call (whose result may set it
* again). */
@@ -950,6 +930,8 @@ get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b)
#define MICROCODE_CHANGED_ASCQ 0x1 /* with TARGET_CHANGED_ASC */
#define MICROCODE_CHANGED_WO_RESET_ASCQ 0x16
+#if (HAVE_NVME && (! IGNORE_NVME))
+
static void
build_sense_buffer(bool desc, uint8_t *buf, uint8_t skey, uint8_t asc,
uint8_t ascq)
@@ -1069,6 +1051,36 @@ mk_sense_invalid_fld(struct sg_pt_freebsd_scsi * ptp, bool in_cdb,
__func__, asc, in_cdb ? 'C' : 'D', in_byte, in_bit);
}
+/* Does actual ioctl(NVME_PASSTHROUGH_CMD). Returns 0 on success; negative
+ * values are Unix negated errno values; positive values are NVMe status. */
+static int
+nvme_pt_low(struct freebsd_dev_channel *fdc_p, void * dxferp, uint32_t len,
+ bool is_read, struct nvme_pt_command * npcp, int vb)
+{
+ int err, status;
+ uint8_t opcode;
+ char b[80];
+
+ if (fdc_p->dev_fd < 0) {
+ if (vb)
+ pr2ws("%s: is_nvme is true but dev_fd<0, inconsistent\n",
+ __func__);
+ return -EINVAL;
+ }
+ npcp->buf = dxferp;
+ npcp->len = len;
+ npcp->is_read = (uint32_t)is_read;
+ opcode = npcp->cmd.opc;
+ err = ioctl(fdc_p->dev_fd, NVME_PASSTHROUGH_CMD, npcp);
+ if (err < 0)
+ return -errno; /* Assume Unix error in normal place */
+ status = ((npcp->cpl.status.sct << 8) | npcp->cpl.status.sc);
+ if (status && vb)
+ pr2ws("%s: opcode=0x%x, status: %s\n", __func__, opcode,
+ sg_get_nvme_cmd_status_str(status, sizeof(b), b));
+ return status;
+}
+
static int
sntl_cache_identity(struct freebsd_dev_channel * fdc_p, int vb)
{
@@ -1081,7 +1093,7 @@ sntl_cache_identity(struct freebsd_dev_channel * fdc_p, int vb)
&fdc_p->free_nvme_id_ctlp, vb > 3);
if (NULL == fdc_p->nvme_id_ctlp) {
pr2ws("%s: sg_memalign() failed to get memory\n", __func__);
- return SG_LIB_OS_BASE_ERR + ENOMEM;
+ return -ENOMEM;
}
memset(npc_up, 0, sizeof(npc));
npc_up[SG_NVME_PT_OPCODE] = 0x6; /* Identify */
@@ -1094,12 +1106,11 @@ sntl_cache_identity(struct freebsd_dev_channel * fdc_p, int vb)
err = nvme_pt_low(fdc_p, fdc_p->nvme_id_ctlp, pg_sz, true, &npc, vb);
if (err) {
if (err < 0) {
- err = -err;
if (vb > 1)
pr2ws("%s: do_nvme_pt() failed: %s (errno=%d)\n", __func__,
- strerror(err), err);
- return SG_LIB_OS_BASE_ERR + err;
- } else {
+ strerror(-err), -err);
+ return err;
+ } else { /* non-zero NVMe command status */
fdc_p->nvme_status = err;
return SG_LIB_NVME_STATUS;
}
@@ -1132,7 +1143,7 @@ sntl_inq(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
fdc_p = get_fdc_p(ptp);
if (NULL == fdc_p) {
pr2ws("%s: get_fdc_p() failed, no file descriptor ?\n", __func__);
- return SG_LIB_OS_BASE_ERR + EINVAL;
+ return -EINVAL;
}
if (NULL == fdc_p->nvme_id_ctlp) {
res = sntl_cache_identity(fdc_p, vb);
@@ -1246,7 +1257,7 @@ sntl_rluns(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
fdc_p = get_fdc_p(ptp);
if (NULL == fdc_p) {
pr2ws("%s: get_fdc_p() failed, no file descriptor ?\n", __func__);
- return SG_LIB_OS_BASE_ERR + EINVAL;
+ return -EINVAL;
}
sel_report = cdbp[2];
alloc_len = sg_get_unaligned_be32(cdbp + 6);
@@ -1282,7 +1293,7 @@ sntl_rluns(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
rl_doutp = (uint8_t *)calloc(num + 1, 8);
if (NULL == rl_doutp) {
pr2ws("%s: calloc() failed to get memory\n", __func__);
- return SG_LIB_OS_BASE_ERR + ENOMEM;
+ return -ENOMEM;
}
for (k = 0, up = rl_doutp + 8; k < num; ++k, up += 8)
sg_put_unaligned_be16(k, up);
@@ -1316,7 +1327,7 @@ sntl_tur(struct sg_pt_freebsd_scsi * ptp, int vb)
fdc_p = get_fdc_p(ptp);
if (NULL == fdc_p) {
pr2ws("%s: get_fdc_p() failed, no file descriptor ?\n", __func__);
- return SG_LIB_OS_BASE_ERR + EINVAL;
+ return -EINVAL;
}
if (NULL == fdc_p->nvme_id_ctlp) {
res = sntl_cache_identity(fdc_p, vb);
@@ -1334,11 +1345,10 @@ sntl_tur(struct sg_pt_freebsd_scsi * ptp, int vb)
err = nvme_pt_low(fdc_p, NULL, 0, false, &npc, vb);
if (err) {
if (err < 0) {
- err = -err;
if (vb > 1)
pr2ws("%s: do_nvme_pt() failed: %s (errno=%d)\n", __func__,
- strerror(err), err);
- return SG_LIB_OS_BASE_ERR + err;
+ strerror(-err), -err);
+ return err;
} else {
fdc_p->nvme_status = err;
mk_sense_from_nvme_status(ptp, err, vb);
@@ -1372,7 +1382,7 @@ sntl_req_sense(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
fdc_p = get_fdc_p(ptp);
if (NULL == fdc_p) {
pr2ws("%s: get_fdc_p() failed, no file descriptor ?\n", __func__);
- return SG_LIB_OS_BASE_ERR + EINVAL;
+ return -EINVAL;
}
if (NULL == fdc_p->nvme_id_ctlp) {
res = sntl_cache_identity(fdc_p, vb);
@@ -1392,11 +1402,10 @@ sntl_req_sense(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
err = nvme_pt_low(fdc_p, NULL, 0, false, &npc, vb);
if (err) {
if (err < 0) {
- err = -err;
if (vb > 1)
pr2ws("%s: do_nvme_pt() failed: %s (errno=%d)\n", __func__,
- strerror(err), err);
- return SG_LIB_OS_BASE_ERR + err;
+ strerror(-err), -err);
+ return err;
} else {
fdc_p->nvme_status = err;
mk_sense_from_nvme_status(ptp, err, vb);
@@ -1450,7 +1459,7 @@ sntl_senddiag(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
fdc_p = get_fdc_p(ptp);
if (NULL == fdc_p) {
pr2ws("%s: get_fdc_p() failed, no file descriptor ?\n", __func__);
- return SG_LIB_OS_BASE_ERR + EINVAL;
+ return -EINVAL;
}
if (self_test || st_cd) {
memset(npc_up, 0, sizeof(npc));
@@ -1472,7 +1481,8 @@ sntl_senddiag(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
break;
default:
pr2ws("%s: bad self-test code [0x%x]\n", __func__, st_cd);
- return SG_LIB_SYNTAX_ERROR;
+ mk_sense_invalid_fld(ptp, true, 1, 7, vb);
+ return 0;
}
sg_put_unaligned_le32(nvme_dst, npc_up + SG_NVME_PT_CDW10);
err = nvme_pt_low(fdc_p, NULL, 0x0, false, &npc, vb);
@@ -1541,11 +1551,10 @@ sntl_senddiag(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
do_low:
if (err) {
if (err < 0) {
- err = -err;
if (vb > 1)
pr2ws("%s: do_nvme_pt() failed: %s (errno=%d)\n",
- __func__, strerror(err), err);
- return SG_LIB_OS_BASE_ERR + err;
+ __func__, strerror(-err), -err);
+ return err;
} else {
fdc_p->nvme_status = err;
mk_sense_from_nvme_status(ptp, err, vb);
@@ -1582,7 +1591,7 @@ sntl_recvdiag(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
fdc_p = get_fdc_p(ptp);
if (NULL == fdc_p) {
pr2ws("%s: get_fdc_p() failed, no file descriptor ?\n", __func__);
- return SG_LIB_OS_BASE_ERR + EINVAL;
+ return -EINVAL;
}
din_len = ptp->dxfer_len;
if (pcv) {
@@ -1637,11 +1646,10 @@ sntl_recvdiag(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
err = nvme_pt_low(fdc_p, ptp->dxferp, 0x1000, true, &npc, vb);
if (err) {
if (err < 0) {
- err = -err;
if (vb > 1)
pr2ws("%s: do_nvme_pt() failed: %s (errno=%d)\n",
- __func__, strerror(err), err);
- return SG_LIB_OS_BASE_ERR + err;
+ __func__, strerror(-err), -err);
+ return err;
} else {
fdc_p->nvme_status = err;
mk_sense_from_nvme_status(ptp, err, vb);
@@ -1680,7 +1688,7 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int vb)
if (fd < 0) {
if (NULL == fdc_p) {
pr2ws("%s: no device handle in object or fd ?\n", __func__);
- return SG_LIB_FILE_ERROR;
+ return -EINVAL;
}
} else {
int han = fd - FREEBSD_FDOFFSET;
@@ -1761,11 +1769,10 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int vb)
err = nvme_pt_low(fdc_p, dxferp, io_len, in_xfer, &npc, vb);
if (err) {
if (err < 0) {
- err = -err;
if (vb > 1)
pr2ws("%s: do_nvme_pt() failed: %s (errno=%d)\n",
- __func__, strerror(err), err);
- return SG_LIB_OS_BASE_ERR + err;
+ __func__, strerror(-err), -err);
+ return err;
} else {
fdc_p->nvme_status = err;
mk_sense_from_nvme_status(ptp, err, vb);
@@ -1776,3 +1783,17 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int vb)
ptp->resid = 0; /* Just hoping ... */
return 0;
}
+
+#else /* if not(HAVE_NVME && (! IGNORE_NVME)) */
+
+static int
+sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int vb)
+{
+ if (vb)
+ pr2ws("%s: not supported\n", __func__);
+ if (vp) { ; } /* suppress warning */
+ if (fd) { ; } /* suppress warning */
+ return -ENOTTY; /* inappropriate ioctl error */
+}
+
+#endif /* (HAVE_NVME && (! IGNORE_NVME)) */
diff --git a/lib/sg_pt_linux_nvme.c b/lib/sg_pt_linux_nvme.c
index 9c2d8124..f62366f7 100644
--- a/lib/sg_pt_linux_nvme.c
+++ b/lib/sg_pt_linux_nvme.c
@@ -112,7 +112,7 @@
static inline bool is_aligned(const void * pointer, size_t byte_count)
{
- return (sg_uintptr_t)pointer % byte_count == 0;
+ return ((sg_uintptr_t)pointer % byte_count) == 0;
}
@@ -136,6 +136,8 @@ pr2ws(const char * fmt, ...)
return n;
}
+#if (HAVE_NVME && (! IGNORE_NVME))
+
/* This trims given NVMe block device name in Linux (e.g. /dev/nvme0n1p5)
* to the name of its associated char device (e.g. /dev/nvme0). If this
* occurs true is returned and the char device name is placed in 'b' (as
@@ -283,9 +285,10 @@ mk_sense_invalid_fld(struct sg_pt_linux_scsi * ptp, bool in_cdb, int in_byte,
/* Returns 0 for success. Returns SG_LIB_NVME_STATUS if there is non-zero
* NVMe status (from the completion queue) with the value placed in
- * ptp->nvme_status. If Unix error from ioctl add equivalent errno value to
- * SG_LIB_OS_BASE_ERR. Should not return negative values. CDW0 from
- * the completion queue is placed in ptp->nvme_result on success. */
+ * ptp->nvme_status. If Unix error from ioctl then return negated value
+ * (equivalent -errno from basic Unix system functions like open()).
+ * CDW0 from the completion queue is placed in ptp->nvme_result in the
+ * absence of a Unix error. */
static int
do_nvme_admin_cmd(struct sg_pt_linux_scsi * ptp,
struct sg_nvme_passthru_cmd *cmdp, const void * dp,
@@ -318,14 +321,14 @@ do_nvme_admin_cmd(struct sg_pt_linux_scsi * ptp,
res = ioctl(ptp->dev_fd, NVME_IOCTL_ADMIN_CMD, cmdp);
if (0 != res) {
if (res < 0) { /* OS error (errno negated) */
- res = (-res & 0x3ff); /* clear DNR and More, if present */
- ptp->os_err = res;
+ ptp->os_err = -res;
if (vb > 3) {
pr2ws("%s: ioctl opcode=0x%x failed: %s "
- "(errno=%d)\n", __func__, *up, strerror(res), res);
+ "(errno=%d)\n", __func__, *up, strerror(-res), -res);
}
- return SG_LIB_OS_BASE_ERR + res;
+ return res;
} else { /* NVMe errors are positive return values */
+ res &= 0x3ff; /* clear DNR and More bits */
ptp->nvme_status = res;
if (vb > 2) {
char b[80];
@@ -364,20 +367,20 @@ sntl_cache_identity(struct sg_pt_linux_scsi * ptp, int time_secs, int vb)
{
struct sg_nvme_passthru_cmd cmd;
uint32_t pg_sz = sg_get_page_size();
- void * vp;
+ uint8_t * up;
- vp = sg_memalign(pg_sz, pg_sz, &ptp->free_nvme_id_ctlp, vb > 3);
- ptp->nvme_id_ctlp = vp;
- if (NULL == vp) {
+ up = sg_memalign(pg_sz, pg_sz, &ptp->free_nvme_id_ctlp, vb > 3);
+ ptp->nvme_id_ctlp = up;
+ if (NULL == up) {
pr2ws("%s: sg_memalign() failed to get memory\n", __func__);
- return SG_LIB_OS_BASE_ERR + ENOMEM;
+ return -ENOMEM;
}
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = 0x6; /* Identify */
cmd.cdw10 = 0x1; /* CNS=0x1 Identify controller */
cmd.addr = (uint64_t)(sg_uintptr_t)ptp->nvme_id_ctlp;
cmd.data_len = pg_sz;
- return do_nvme_admin_cmd(ptp, &cmd, vp, true, time_secs, vb);
+ return do_nvme_admin_cmd(ptp, &cmd, up, true, time_secs, vb);
}
static const char * nvme_scsi_vendor_str = "NVMe ";
@@ -543,7 +546,7 @@ sntl_rluns(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, int time_secs,
rl_doutp = (uint8_t *)calloc(num + 1, 8);
if (NULL == rl_doutp) {
pr2ws("%s: calloc() failed to get memory\n", __func__);
- return SG_LIB_OS_BASE_ERR + ENOMEM;
+ return -ENOMEM;
}
for (k = 0, up = rl_doutp + 8; k < num; ++k, up += 8)
sg_put_unaligned_be16(k, up);
@@ -710,7 +713,8 @@ sntl_senddiag(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
break;
default:
pr2ws("%s: bad self-test code [0x%x]\n", __func__, st_cd);
- return SG_LIB_SYNTAX_ERROR;
+ mk_sense_invalid_fld(ptp, true, 1, 7, vb);
+ return 0;
}
sg_put_unaligned_le32(nvme_dst, cmd_up + SG_NVME_PT_CDW10);
res = do_nvme_admin_cmd(ptp, &cmd, NULL, false, time_secs, vb);
@@ -928,3 +932,18 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int time_secs, int vb)
}
return do_nvme_admin_cmd(ptp, &cmd, dp, is_read, time_secs, vb);
}
+
+#else /* (HAVE_NVME && (! IGNORE_NVME)) */
+
+int
+sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int time_secs, int vb)
+{
+ if (vb)
+ pr2ws("%s: not supported\n", __func__);
+ if (vp) { ; } /* suppress warning */
+ if (fd) { ; } /* suppress warning */
+ if (time_secs) { ; } /* suppress warning */
+ return -ENOTTY; /* inappropriate ioctl error */
+}
+
+#endif /* (HAVE_NVME && (! IGNORE_NVME)) */