aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure57
-rw-r--r--configure.ac4
-rw-r--r--lib/sg_pt_linux.c459
4 files changed, 456 insertions, 67 deletions
diff --git a/config.h.in b/config.h.in
index cde52337..2bb0ea7b 100644
--- a/config.h.in
+++ b/config.h.in
@@ -42,6 +42,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* ignore linux bsg */
+#undef IGNORE_LINUX_BSG
+
/* Name of package */
#undef PACKAGE
diff --git a/configure b/configure
index 2b1f449a..26759161 100755
--- a/configure
+++ b/configure
@@ -1490,6 +1490,7 @@ Optional Features:
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
+ --enable-no-linux-bsg ignore linux bsg (sgv4) if present
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -4412,7 +4413,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 4415 "configure"' > conftest.$ac_ext
+ echo '#line 4416 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -7469,11 +7470,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7472: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7473: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7476: \$? = $ac_status" >&5
+ echo "$as_me:7477: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7759,11 +7760,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7762: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7763: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7766: \$? = $ac_status" >&5
+ echo "$as_me:7767: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7863,11 +7864,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7866: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7867: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7870: \$? = $ac_status" >&5
+ echo "$as_me:7871: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -10240,7 +10241,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10243 "configure"
+#line 10244 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10340,7 +10341,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10343 "configure"
+#line 10344 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12741,11 +12742,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:12744: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:12745: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:12748: \$? = $ac_status" >&5
+ echo "$as_me:12749: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -12845,11 +12846,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:12848: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:12849: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:12852: \$? = $ac_status" >&5
+ echo "$as_me:12853: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -14443,11 +14444,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14446: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14447: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:14450: \$? = $ac_status" >&5
+ echo "$as_me:14451: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -14547,11 +14548,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14550: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14551: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:14554: \$? = $ac_status" >&5
+ echo "$as_me:14555: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -16767,11 +16768,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:16770: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16771: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:16774: \$? = $ac_status" >&5
+ echo "$as_me:16775: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -17057,11 +17058,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17060: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17061: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:17064: \$? = $ac_status" >&5
+ echo "$as_me:17065: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -17161,11 +17162,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17164: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17165: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:17168: \$? = $ac_status" >&5
+ echo "$as_me:17169: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -20450,6 +20451,16 @@ else
fi
+# Check whether --enable-no-linux-bsg was given.
+if test "${enable_no_linux_bsg+set}" = set; then
+ enableval=$enable_no_linux_bsg;
+cat >>confdefs.h <<_ACEOF
+#define IGNORE_LINUX_BSG 1
+_ACEOF
+
+
+fi
+
ac_config_files="$ac_config_files Makefile include/Makefile lib/Makefile src/Makefile doc/Makefile"
diff --git a/configure.ac b/configure.ac
index c4bc5bdf..cd494720 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,5 +66,9 @@ AM_CONDITIONAL(OS_SOLARIS, [echo $host_os | grep '^solaris' > /dev/null])
AM_CONDITIONAL(OS_WIN32_MINGW, [echo $host_os | grep '^mingw' > /dev/null])
AM_CONDITIONAL(OS_WIN32_CYGWIN, [echo $host_os | grep '^cygwin' > /dev/null])
+AC_ARG_ENABLE([no-linux-bsg],
+ AC_HELP_STRING([--enable-no-linux-bsg], [ignore linux bsg (sgv4) if present]),
+ AC_DEFINE_UNQUOTED(IGNORE_LINUX_BSG, 1, [ignore linux bsg], )
+)
AC_OUTPUT(Makefile include/Makefile lib/Makefile src/Makefile doc/Makefile)
diff --git a/lib/sg_pt_linux.c b/lib/sg_pt_linux.c
index 88d0108b..5bfbdc15 100644
--- a/lib/sg_pt_linux.c
+++ b/lib/sg_pt_linux.c
@@ -27,7 +27,7 @@
*
*/
-/* sg_pt_linux version 1.10 20090204 */
+/* sg_pt_linux version 1.11 20090307 */
#include <stdio.h>
#include <stdlib.h>
@@ -40,13 +40,70 @@
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "sg_pt.h"
#include "sg_lib.h"
#include "sg_linux_inc.h"
-
#define DEF_TIMEOUT 60000 /* 60,000 millisecs (60 seconds) */
+static const char * linux_host_bytes[] = {
+ "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT",
+ "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR",
+ "DID_RESET", "DID_BAD_INTR", "DID_PASSTHROUGH", "DID_SOFT_ERROR",
+ "DID_IMM_RETRY", "DID_REQUEUE"
+};
+
+#define LINUX_HOST_BYTES_SZ \
+ (int)(sizeof(linux_host_bytes) / sizeof(linux_host_bytes[0]))
+
+static const char * linux_driver_bytes[] = {
+ "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA",
+ "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD",
+ "DRIVER_SENSE"
+};
+
+#define LINUX_DRIVER_BYTES_SZ \
+ (int)(sizeof(linux_driver_bytes) / sizeof(linux_driver_bytes[0]))
+
+static const char * linux_driver_suggests[] = {
+ "SUGGEST_OK", "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP",
+ "SUGGEST_DIE", "UNKNOWN","UNKNOWN","UNKNOWN",
+ "SUGGEST_SENSE"
+};
+
+#define LINUX_DRIVER_SUGGESTS_SZ \
+ (int)(sizeof(linux_driver_suggests) / sizeof(linux_driver_suggests[0]))
+
+/*
+ * These defines are for constants that should be visible in the
+ * /usr/include/scsi directory (brought in by sg_linux_inc.h).
+ * Redefined and aliased here to decouple this code from
+ * sg_io_linux.h
+ */
+#ifndef DRIVER_MASK
+#define DRIVER_MASK 0x0f
+#endif
+#ifndef SUGGEST_MASK
+#define SUGGEST_MASK 0xf0
+#endif
+#ifndef DRIVER_SENSE
+#define DRIVER_SENSE 0x08
+#endif
+#define SG_LIB_DRIVER_MASK DRIVER_MASK
+#define SG_LIB_SUGGEST_MASK SUGGEST_MASK
+#define SG_LIB_DRIVER_SENSE DRIVER_SENSE
+
+
+
+// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+#if defined(IGNORE_LINUX_BSG) || ! defined(HAVE_LINUX_BSG_H)
+/* sgv3 via SG_IO ioctl on a sg node or other node that accepts that ioctl */
+
+
struct sg_pt_linux_scsi {
struct sg_io_hdr io_hdr;
int in_err;
@@ -267,25 +324,6 @@ do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose)
return 0;
}
-/*
- * These defines are for constants that should be visible in the
- * /usr/include/scsi directory (brought in by sg_linux_inc.h).
- * Redefined and aliased here to decouple this code from
- * sg_io_linux.h
- */
-#ifndef DRIVER_MASK
-#define DRIVER_MASK 0x0f
-#endif
-#ifndef SUGGEST_MASK
-#define SUGGEST_MASK 0xf0
-#endif
-#ifndef DRIVER_SENSE
-#define DRIVER_SENSE 0x08
-#endif
-#define SG_LIB_DRIVER_MASK DRIVER_MASK
-#define SG_LIB_SUGGEST_MASK SUGGEST_MASK
-#define SG_LIB_DRIVER_SENSE DRIVER_SENSE
-
int
get_scsi_pt_result_category(const struct sg_pt_base * vp)
{
@@ -357,42 +395,349 @@ get_scsi_pt_os_err(const struct sg_pt_base * vp)
return ptp->os_err;
}
-static const char * linux_host_bytes[] = {
- "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT",
- "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR",
- "DID_RESET", "DID_BAD_INTR", "DID_PASSTHROUGH", "DID_SOFT_ERROR",
- "DID_IMM_RETRY", "DID_REQUEUE"
-};
+char *
+get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len,
+ char * b)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+ int ds = ptp->io_hdr.driver_status;
+ int hs = ptp->io_hdr.host_status;
+ int n, m;
+ char * cp = b;
+ int driv, sugg;
+ const char * driv_cp = "invalid";
+ const char * sugg_cp = "invalid";
-#define LINUX_HOST_BYTES_SZ \
- (int)(sizeof(linux_host_bytes) / sizeof(linux_host_bytes[0]))
+ m = max_b_len;
+ n = 0;
+ if (hs) {
+ if ((hs < 0) || (hs >= LINUX_HOST_BYTES_SZ))
+ n = snprintf(cp, m, "Host_status=0x%02x is invalid\n", hs);
+ else
+ n = snprintf(cp, m, "Host_status=0x%02x [%s]\n", hs,
+ linux_host_bytes[hs]);
+ }
+ m -= n;
+ if (m < 1) {
+ b[max_b_len - 1] = '\0';
+ return b;
+ }
+ cp += n;
+ driv = ds & SG_LIB_DRIVER_MASK;
+ if (driv < LINUX_DRIVER_BYTES_SZ)
+ driv_cp = linux_driver_bytes[driv];
+ sugg = (ds & SG_LIB_SUGGEST_MASK) >> 4;
+ if (sugg < LINUX_DRIVER_SUGGESTS_SZ)
+ sugg_cp = linux_driver_suggests[sugg];
+ n = snprintf(cp, m, "Driver_status=0x%02x [%s, %s]\n", ds, driv_cp,
+ sugg_cp);
+ m -= n;
+ if (m < 1)
+ b[max_b_len - 1] = '\0';
+ return b;
+}
-static const char * linux_driver_bytes[] = {
- "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA",
- "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD",
- "DRIVER_SENSE"
-};
+char *
+get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+ const char * cp;
-#define LINUX_DRIVER_BYTES_SZ \
- (int)(sizeof(linux_driver_bytes) / sizeof(linux_driver_bytes[0]))
+ cp = safe_strerror(ptp->os_err);
+ strncpy(b, cp, max_b_len);
+ if ((int)strlen(cp) >= max_b_len)
+ b[max_b_len - 1] = '\0';
+ return b;
+}
-static const char * linux_driver_suggests[] = {
- "SUGGEST_OK", "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP",
- "SUGGEST_DIE", "UNKNOWN","UNKNOWN","UNKNOWN",
- "SUGGEST_SENSE"
+
+// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+#else /* allow for run selection of sg v3 or v4 (via bsg) */
+// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+
+#include <linux/types.h>
+#include <linux/bsg.h>
+
+#define DEF_TIMEOUT 60000 /* 60,000 millisecs (60 seconds) */
+
+struct sg_pt_linux_scsi {
+ struct sg_io_v4 io_hdr; /* use v4 header as it is more general */
+ int in_err;
+ int os_err;
+ unsigned char tmf_request[4];
};
-#define LINUX_DRIVER_SUGGESTS_SZ \
- (int)(sizeof(linux_driver_suggests) / sizeof(linux_driver_suggests[0]))
+struct sg_pt_base {
+ struct sg_pt_linux_scsi impl;
+};
+
+static int bsg_major_checked = 0;
+static int bsg_major = 0;
+
+
+
+static void
+find_bsg_major(int verbose)
+{
+ const char * proc_devices = "/proc/devices";
+ FILE *fp;
+ char a[128];
+ char b[128];
+ char * cp;
+ int n;
+
+ if (NULL == (fp = fopen(proc_devices, "r"))) {
+ if (NULL == sg_warnings_strm)
+ sg_warnings_strm = stderr;
+ if (verbose)
+ fprintf(sg_warnings_strm, "fopen %s failed: %s\n", proc_devices,
+ strerror(errno));
+ return;
+ }
+ while ((cp = fgets(b, sizeof(b), fp))) {
+ if ((1 == sscanf(b, "%s", a)) &&
+ (0 == memcmp(a, "Character", 9)))
+ break;
+ }
+ while (cp && (cp = fgets(b, sizeof(b), fp))) {
+ if (2 == sscanf(b, "%d %s", &n, a)) {
+ if (0 == strcmp("bsg", a)) {
+ bsg_major = n;
+ break;
+ }
+ } else
+ break;
+ }
+ if ((NULL == cp) && (verbose > 3)) {
+ if (NULL == sg_warnings_strm)
+ sg_warnings_strm = stderr;
+ fprintf(sg_warnings_strm, "found no bsg char device in %s\n",
+ proc_devices);
+ }
+ fclose(fp);
+}
+
+
+/* Returns >= 0 if successful. If error in Unix returns negated errno. */
+int
+scsi_pt_open_device(const char * device_name, int read_only, int verbose)
+{
+ int oflags = O_NONBLOCK;
+
+ oflags |= (read_only ? O_RDONLY : O_RDWR);
+ return scsi_pt_open_flags(device_name, oflags, verbose);
+}
+
+/* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed */
+/* together. The 'flags' argument is advisory and may be ignored. */
+/* Returns >= 0 if successful, otherwise returns negated errno. */
+int
+scsi_pt_open_flags(const char * device_name, int flags, int verbose)
+{
+ int fd;
+
+ if (! bsg_major_checked) {
+ bsg_major_checked = 1;
+ find_bsg_major(verbose);
+ }
+
+ if (verbose > 1) {
+ if (NULL == sg_warnings_strm)
+ sg_warnings_strm = stderr;
+ fprintf(sg_warnings_strm, "open %s with flags=0x%x\n", device_name,
+ flags);
+ }
+ fd = open(device_name, flags);
+ if (fd < 0)
+ fd = -errno;
+ return fd;
+}
+
+/* Returns 0 if successful. If error in Unix returns negated errno. */
+int
+scsi_pt_close_device(int device_fd)
+{
+ int res;
+
+ res = close(device_fd);
+ if (res < 0)
+ res = -errno;
+ return res;
+}
+
+
+struct sg_pt_base *
+construct_scsi_pt_obj()
+{
+ struct sg_pt_linux_scsi * ptp;
+
+ ptp = (struct sg_pt_linux_scsi *)
+ calloc(1, sizeof(struct sg_pt_linux_scsi));
+ if (ptp)
+ ptp->io_hdr.guard = 'Q';
+ return (struct sg_pt_base *)ptp;
+}
+
+void
+destruct_scsi_pt_obj(struct sg_pt_base * vp)
+{
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ if (ptp)
+ free(ptp);
+}
+
+void
+set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
+ int cdb_len)
+{
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ if (ptp->io_hdr.request)
+ ++ptp->in_err;
+ /* C99 has intptr_t instead of long */
+ ptp->io_hdr.request = (__u64)(long)cdb;
+ ptp->io_hdr.request_len = cdb_len;
+}
+
+void
+set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
+ int max_sense_len)
+{
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
+ if (ptp->io_hdr.response)
+ ++ptp->in_err;
+ memset(sense, 0, max_sense_len);
+ ptp->io_hdr.response = (__u64)(long)sense;
+ ptp->io_hdr.max_response_len = max_sense_len;
+}
+/* Setup for data transfer from device */
+void
+set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp,
+ int dxfer_len)
+{
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ if (ptp->io_hdr.din_xferp)
+ ++ptp->in_err;
+ if (dxfer_len > 0) {
+ ptp->io_hdr.din_xferp = (__u64)(long)dxferp;
+ ptp->io_hdr.din_xfer_len = dxfer_len;
+ }
+}
+
+/* Setup for data transfer toward device */
+void
+set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp,
+ int dxfer_len)
+{
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ if (ptp->io_hdr.dout_xferp)
+ ++ptp->in_err;
+ if (dxfer_len > 0) {
+ ptp->io_hdr.dout_xferp = (__u64)(long)dxferp;
+ ptp->io_hdr.dout_xfer_len = dxfer_len;
+ }
+}
+
+void
+set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id)
+{
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ ptp->io_hdr.spare_in = pack_id;
+}
+
+void
+set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag)
+{
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ ptp->io_hdr.request_tag = tag;
+}
+
+/* Note that task management function codes are transport specific */
+void
+set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code)
+{
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ ptp->io_hdr.subprotocol = 1; /* SCSI task management function */
+ ptp->tmf_request[0] = (unsigned char)tmf_code; /* assume it fits */
+ ptp->io_hdr.request = (__u64)(long)(&(ptp->tmf_request[0]));
+ ptp->io_hdr.request_len = 1;
+}
+
+void
+set_scsi_pt_task_attr(struct sg_pt_base * vp, int attribute, int priority)
+{
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ ptp->io_hdr.request_attr = attribute;
+ ptp->io_hdr.request_priority = priority;
+}
+
+/* N.B. Returns din_resid and ignores dout_resid */
+int
+get_scsi_pt_resid(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ return ptp->io_hdr.din_resid;
+}
+
+int
+get_scsi_pt_status_response(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ return ptp->io_hdr.device_status;
+}
+
+int
+get_scsi_pt_sense_len(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ return ptp->io_hdr.response_len;
+}
+
+int
+get_scsi_pt_duration_ms(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ return ptp->io_hdr.duration;
+}
+
+int
+get_scsi_pt_transport_err(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ return ptp->io_hdr.transport_status;
+}
+
+int
+get_scsi_pt_os_err(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ return ptp->os_err;
+}
+
+/* Combine driver and transport (called "host" in linux kernel) statuses */
char *
get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len,
char * b)
{
const struct sg_pt_linux_scsi * ptp = &vp->impl;
int ds = ptp->io_hdr.driver_status;
- int hs = ptp->io_hdr.host_status;
+ int hs = ptp->io_hdr.transport_status;
int n, m;
char * cp = b;
int driv, sugg;
@@ -401,7 +746,7 @@ get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len,
m = max_b_len;
n = 0;
- if (ptp->io_hdr.host_status) {
+ if (hs) {
if ((hs < 0) || (hs >= LINUX_HOST_BYTES_SZ))
n = snprintf(cp, m, "Host_status=0x%02x is invalid\n", hs);
else
@@ -428,6 +773,29 @@ get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len,
return b;
}
+int
+get_scsi_pt_result_category(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+ int dr_st = ptp->io_hdr.driver_status & SG_LIB_DRIVER_MASK;
+ int scsi_st = ptp->io_hdr.device_status & 0x7e;
+
+ if (ptp->os_err)
+ return SCSI_PT_RESULT_OS_ERR;
+ else if (ptp->io_hdr.transport_status)
+ return SCSI_PT_RESULT_TRANSPORT_ERR;
+ else if (dr_st && (SG_LIB_DRIVER_SENSE != dr_st))
+ return SCSI_PT_RESULT_TRANSPORT_ERR;
+ else if ((SG_LIB_DRIVER_SENSE == dr_st) ||
+ (SAM_STAT_CHECK_CONDITION == scsi_st) ||
+ (SAM_STAT_COMMAND_TERMINATED == scsi_st))
+ return SCSI_PT_RESULT_SENSE;
+ else if (scsi_st)
+ return SCSI_PT_RESULT_STATUS;
+ else
+ return SCSI_PT_RESULT_GOOD;
+}
+
char *
get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b)
{
@@ -440,3 +808,6 @@ 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;
}
+
+#endif
+// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<