diff options
-rw-r--r-- | config.h.in | 3 | ||||
-rwxr-xr-x | configure | 57 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | lib/sg_pt_linux.c | 459 |
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 @@ -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 +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |