From 3e6d9413f5a43dcd635c8d71e46562a3a3b46b9a Mon Sep 17 00:00:00 2001 From: shattered <shattered@4ea69e1a-61f1-4043-bf83-b5c94c648137> Date: Sun, 1 Apr 2007 16:49:48 +0000 Subject: [PATCH] Support CCISS controllers on FreeBSD, too. Compile- and run-tested on FreeBSD/i386 5.2.1, but not on Linux. git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@2386 4ea69e1a-61f1-4043-bf83-b5c94c648137 --- sm5/Makefile.am | 10 ++- sm5/cciss.cpp | 201 +++++++++++++++++++++++++++++++++++++++++++++ sm5/cciss.h | 9 ++ sm5/configure.in | 14 +++- sm5/os_freebsd.cpp | 68 +++++++++++++-- sm5/os_linux.cpp | 193 +------------------------------------------ 6 files changed, 290 insertions(+), 205 deletions(-) create mode 100644 sm5/cciss.cpp create mode 100644 sm5/cciss.h diff --git a/sm5/Makefile.am b/sm5/Makefile.am index 185e83fd8..dd3b1f73a 100644 --- a/sm5/Makefile.am +++ b/sm5/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in # -# $Id: Makefile.am,v 1.80 2006/10/21 18:34:31 chrfranke Exp $ +# $Id: Makefile.am,v 1.81 2007/04/01 16:49:44 shattered Exp $ # @SET_MAKE@ @@ -53,7 +53,9 @@ EXTRA_smartd_SOURCES = os_darwin.cpp \ os_solaris_ata.s \ os_win32.cpp \ os_generic.cpp \ - os_generic.h + os_generic.h \ + cciss.cpp \ + cciss.h if OS_WIN32_MINGW @@ -113,7 +115,9 @@ EXTRA_smartctl_SOURCES = os_linux.cpp \ os_solaris.h \ os_win32.cpp \ os_generic.cpp \ - os_generic.h + os_generic.h \ + cciss.cpp \ + cciss.h if OS_WIN32_MINGW diff --git a/sm5/cciss.cpp b/sm5/cciss.cpp new file mode 100644 index 000000000..21aee176f --- /dev/null +++ b/sm5/cciss.cpp @@ -0,0 +1,201 @@ +#include <stdio.h> +#include <string.h> +#include <sys/types.h> + +#include "config.h" + +#if defined(linux) +# ifdef HAVE_LINUX_COMPILER_H +# include <linux/compiler.h> +# endif +# if defined(HAVE_LINUX_CCISS_IOCTL_H) +# include <linux/cciss_ioctl.h> +# define _HAVE_CCISS +# endif +#elif defined(__FreeBSD__) && defined(HAVE_DEV_CISS_CISSIO_H) +# include <dev/ciss/cissio.h> +# define _HAVE_CCISS +#endif + +#ifdef _HAVE_CCISS +#include "int64.h" +#include "scsicmds.h" + +typedef struct _ReportLUNdata_struct +{ + uint8_t LUNListLength[4]; + uint32_t reserved; + uint8_t LUN[CISS_MAX_LUN][8]; +} ReportLunData_struct; + +/* Structure/defines of Report Physical LUNS of drive */ +#ifndef CISS_MAX_LUN +#define CISS_MAX_LUN 16 +#endif +#define CISS_MAX_PHYS_LUN 1024 +#define CISS_REPORT_PHYS 0xc3 + +#define LSCSI_DRIVER_SENSE 0x8 /* alternate CHECK CONDITION indication */ +#define SEND_IOCTL_RESP_SENSE_LEN 16 /* ioctl limitation */ + +static int cciss_getlun(int device, int target, unsigned char *physlun); +static int cciss_sendpassthru(unsigned int cmdtype, unsigned char *CDB, + unsigned int CDBlen, char *buff, + unsigned int size, unsigned int LunID, + unsigned char *scsi3addr, int fd); + +/* + This is an interface that uses the cciss passthrough to talk to the SMART controller on + the HP system. The cciss driver provides a way to send SCSI cmds through the CCISS passthrough. +*/ +int cciss_io_interface(int device, int target, struct scsi_cmnd_io * iop, int report) +{ + unsigned char pBuf[512] = {0}; + unsigned char phylun[1024] = {0}; + int iBufLen = 512; + int status = -1; + int len = 0; // used later in the code. + report = 0; + + cciss_getlun(device, target, phylun); + status = cciss_sendpassthru( 2, iop->cmnd, iop->cmnd_len, (char*) pBuf, iBufLen, 1, phylun, device); + + if (0 == status) + { + if (report > 0) + printf(" status=0\n"); + if (DXFER_FROM_DEVICE == iop->dxfer_dir) + { + memcpy(iop->dxferp, pBuf, iop->dxfer_len); + if (report > 1) + { + int trunc = (iop->dxfer_len > 256) ? 1 : 0; + printf(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len, + (trunc ? " [only first 256 bytes shown]" : "")); + dStrHex((const char*)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); + } + } + return 0; + } + iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */ + if (LSCSI_DRIVER_SENSE == ((status >> 24) & 0xf)) + iop->scsi_status = SCSI_STATUS_CHECK_CONDITION; + len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ? + SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len; + if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) && + iop->sensep && (len > 0)) + { + memcpy(iop->sensep, pBuf, len); + iop->resp_sense_len = iBufLen; + if (report > 1) + { + printf(" >>> Sense buffer, len=%d:\n", (int)len); + dStrHex((const char *)pBuf, len , 1); + } + } + if (report) + { + if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) { + printf(" status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff, + pBuf[2] & 0xf, pBuf[12], pBuf[13]); + } + else + printf(" status=0x%x\n", status); + } + if (iop->scsi_status > 0) + return 0; + else + { + if (report > 0) + printf(" ioctl status=0x%x but scsi status=0, fail with EIO\n", status); + return -EIO; /* give up, assume no device there */ + } +} + +static int cciss_sendpassthru(unsigned int cmdtype, unsigned char *CDB, + unsigned int CDBlen, char *buff, + unsigned int size, unsigned int LunID, + unsigned char *scsi3addr, int fd) +{ + int err ; + IOCTL_Command_struct iocommand; + + memset(&iocommand, 0, sizeof(iocommand)); + + if (cmdtype == 0) + { + // To controller; nothing to do + } + else if (cmdtype == 1) + { + iocommand.LUN_info.LogDev.VolId = LunID; + iocommand.LUN_info.LogDev.Mode = 1; + } + else if (cmdtype == 2) + { + memcpy(&iocommand.LUN_info.LunAddrBytes,scsi3addr,8); + iocommand.LUN_info.LogDev.Mode = 0; + } + else + { + fprintf(stderr, "cciss_sendpassthru: bad cmdtype\n"); + return 1; + } + + memcpy(&iocommand.Request.CDB[0], CDB, CDBlen); + iocommand.Request.CDBLen = CDBlen; + iocommand.Request.Type.Type = TYPE_CMD; + iocommand.Request.Type.Attribute = ATTR_SIMPLE; + iocommand.Request.Type.Direction = XFER_READ; + iocommand.Request.Timeout = 0; + + iocommand.buf_size = size; + iocommand.buf = (unsigned char *)buff; + + if ((err = ioctl(fd, CCISS_PASSTHRU, &iocommand))) + { + fprintf(stderr, "CCISS ioctl error %d (fd %d CDBLen %d buf_size %d)\n", + fd, err, CDBlen, size); + } + return err; +} + +static int cciss_getlun(int device, int target, unsigned char *physlun) +{ + unsigned char CDB[16]= {0}; + ReportLunData_struct *luns; + int reportlunsize = sizeof(*luns) + CISS_MAX_PHYS_LUN * 8; + int i; + int ret; + + luns = (ReportLunData_struct *)malloc(reportlunsize); + + memset(luns, 0, reportlunsize); + + /* Get Physical LUN Info (for physical device) */ + CDB[0] = CISS_REPORT_PHYS; + CDB[6] = (reportlunsize >> 24) & 0xFF; /* MSB */ + CDB[7] = (reportlunsize >> 16) & 0xFF; + CDB[8] = (reportlunsize >> 8) & 0xFF; + CDB[9] = reportlunsize & 0xFF; + + if ((ret = cciss_sendpassthru(0, CDB, 12, (char *)luns, reportlunsize, 0, NULL, device))) + { + free(luns); + return ret; + } + + for (i=0; i<CISS_MAX_LUN; i++) + { + if (luns->LUN[i][6] == target) + { + memcpy(physlun, luns->LUN[i], 8); + free(luns); + return 0; + } + } + + free(luns); + return ret; +} +#endif diff --git a/sm5/cciss.h b/sm5/cciss.h new file mode 100644 index 000000000..99452be66 --- /dev/null +++ b/sm5/cciss.h @@ -0,0 +1,9 @@ +#ifndef CCISS_H_ +#define CCISS_H_ + +#define CCISS_H_CVSID "$Id: cciss.h,v 1.1 2007/04/01 16:49:46 shattered Exp $\n" + +int cciss_io_interface(int device, int target, + struct scsi_cmnd_io * iop, int report); + +#endif /* CCISS_H_ */ diff --git a/sm5/configure.in b/sm5/configure.in index f5c9925f8..512a9910f 100644 --- a/sm5/configure.in +++ b/sm5/configure.in @@ -1,5 +1,5 @@ # -# $Id: configure.in,v 1.124 2007/01/05 16:14:24 chrfranke Exp $ +# $Id: configure.in,v 1.125 2007/04/01 16:49:47 shattered Exp $ # dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) @@ -7,7 +7,7 @@ AC_INIT(smartmontools, 5.38, smartmontools-support@lists.sourceforge.net) AC_CONFIG_SRCDIR(smartctl.cpp) smartmontools_configure_date=`date -u +"%Y/%m/%d %T %Z"` -smartmontools_cvs_tag=`echo '$Id: configure.in,v 1.124 2007/01/05 16:14:24 chrfranke Exp $'` +smartmontools_cvs_tag=`echo '$Id: configure.in,v 1.125 2007/04/01 16:49:47 shattered Exp $'` smartmontools_release_date=2006/12/20 smartmontools_release_time="20:37:59 UTC" @@ -37,6 +37,10 @@ case "${host}" in CPPFLAGS="$CPPFLAGS -mno-cygwin" LDFLAGS="$LDFLAGS -mno-cygwin" CPPFLAGS="$CPPFLAGS -idirafter ${srcdir}/posix -idirafter ${srcdir}/os_win32" + ;; + *-*-freebsd*) + CPPFLAGS="$CPPFLAGS -I/usr/src/sys" + ;; esac dnl Checks for libraries.needed for gethostbyname (Solaris needs @@ -59,6 +63,8 @@ AC_CHECK_HEADERS([sys/tweio.h]) AC_CHECK_HEADERS([sys/twereg.h]) dnl Check for FreeBSD twa include files... AC_CHECK_HEADERS([sys/tw_osl_ioctl.h]) +dnl Check for FreeBSD ciss include files... +AC_CHECK_HEADERS([dev/ciss/cissio.h]) dnl Check for Linux CCISS include file AC_CHECK_HEADERS([linux/cciss_ioctl.h]) dnl This header file needed at least for SuSE LINUX @@ -135,10 +141,10 @@ case "${host}" in AC_SUBST([os_deps], ['os_linux.o']) AC_SUBST([os_libs], ['']) ;; *-*-linux*) - AC_SUBST([os_deps], ['os_linux.o']) + AC_SUBST([os_deps], ['os_linux.o cciss.o']) AC_SUBST([os_libs], ['']) ;; *-*-freebsd*) - AC_SUBST([os_deps], ['os_freebsd.o']) + AC_SUBST([os_deps], ['os_freebsd.o cciss.o']) AC_SUBST([os_libs], ['-lcam']);; sparc-*-solaris*) AC_DEFINE_UNQUOTED(DEFAULT_MAILER, "mailx", [use mailx as default mailer]) diff --git a/sm5/os_freebsd.cpp b/sm5/os_freebsd.cpp index 43dc2cbfd..14253b07f 100644 --- a/sm5/os_freebsd.cpp +++ b/sm5/os_freebsd.cpp @@ -35,17 +35,21 @@ #include "int64.h" #include "atacmds.h" #include "scsicmds.h" +#include "cciss.h" #include "utility.h" +#include "extern.h" #include "os_freebsd.h" -static const char *filenameandversion="$Id: os_freebsd.cpp,v 1.51 2006/09/17 03:17:53 dpgilbert Exp $"; +static const char *filenameandversion="$Id: os_freebsd.cpp,v 1.52 2007/04/01 16:49:48 shattered Exp $"; -const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.51 2006/09/17 03:17:53 dpgilbert Exp $" \ +const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.52 2007/04/01 16:49:48 shattered Exp $" \ ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; // to hold onto exit code for atexit routine extern int exitstatus; +extern smartmonctrl * con; + // Private table of open devices: guaranteed zero on startup since // part of static data. struct freebsd_dev_channel *devicetable[FREEBSD_MAXDEV]; @@ -85,7 +89,7 @@ void print_smartctl_examples(){ } // Like open(). Return positive integer handle, used by functions below only. mode=="ATA" or "SCSI". -int deviceopen (const char* dev, char* mode __unused) { +int deviceopen (const char* dev, __unused char* mode) { struct freebsd_dev_channel *fdchan; int parse_ok, i; @@ -157,6 +161,15 @@ int deviceopen (const char* dev, char* mode __unused) { } } + if (parse_ok == CONTROLLER_CCISS) { + if ((fdchan->device = open(dev,O_RDWR))<0) { + int myerror = errno; // preserver across free call + free(fdchan); + errno=myerror; + return -1; + } + } + if (parse_ok == CONTROLLER_SCSI) { // this is really a NO-OP, as the parse takes care // of filling in correct details @@ -248,13 +261,13 @@ void printwarning(int msgNo, const char* extra) { return; } - // Interface to ATA devices. See os_linux.c -int marvell_command_interface(int fd __unused, smart_command_set command __unused, int select __unused, char *data __unused) { - return -1; + +int marvell_command_interface(__unused int fd, __unused smart_command_set command, __unused int select, __unused char *data) { + return -1; } -int highpoint_command_interface(int fd __unused, smart_command_set command __unused, int select __unused, char *data __unused) +int highpoint_command_interface(__unused int fd, __unused smart_command_set command, __unused int select, __unused char *data) { { return -1; } @@ -439,7 +452,7 @@ int ata_command_interface(int fd, smart_command_set command, int select, char *d // Interface to SCSI devices. See os_linux.c -int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) +int do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) { struct freebsd_dev_channel* con = NULL; struct cam_device* cam_dev = NULL; @@ -540,6 +553,40 @@ int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) return 0; } +/* Check and call the right interface. Maybe when the do_generic_scsi_cmd_io interface is better + we can take off this crude way of calling the right interface */ +int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report) +{ +struct freebsd_dev_channel *fdchan; + switch(con->controller_type) + { + case CONTROLLER_CCISS: + // check that "file descriptor" is valid + if (isnotopen(&dev_fd,&fdchan)) + return -ENOTTY; +#ifdef HAVE_DEV_CISS_CISSIO_H + return cciss_io_interface(fdchan->device, con->controller_port-1, iop, report); +#else + { + static int warned = 0; + if (!warned) { + pout("CCISS support is not available in this build of smartmontools,\n" + "/usr/src/sys/dev/ciss/cissio.h was not available at build time.\n\n"); + warned = 1; + } + } + errno = ENOSYS; + return -1; +#endif + // not reached + break; + default: + return do_normal_scsi_cmnd_io(dev_fd, iop, report); + // not reached + break; + } +} + // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520 @@ -878,6 +925,7 @@ static const char * fbsd_dev_scsi_tape2 = "nsa"; static const char * fbsd_dev_scsi_tape3 = "esa"; static const char * fbsd_dev_twe_ctrl = "twe"; static const char * fbsd_dev_twa_ctrl = "twa"; +static const char * fbsd_dev_cciss = "ciss"; static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) { int len; @@ -953,6 +1001,10 @@ static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel } return CONTROLLER_3WARE_678K_CHAR; } + // form /dev/ciss* + if (!strncmp(fbsd_dev_cciss, dev_name, + strlen(fbsd_dev_cciss))) + return CONTROLLER_CCISS; // we failed to recognize any of the forms return CONTROLLER_UNKNOWN; diff --git a/sm5/os_linux.cpp b/sm5/os_linux.cpp index d1db635c8..c0ba192c5 100644 --- a/sm5/os_linux.cpp +++ b/sm5/os_linux.cpp @@ -50,10 +50,6 @@ #include <fcntl.h> #include <glob.h> -#ifdef HAVE_LINUX_COMPILER_H -#include <linux/compiler.h> -#endif - #include <scsi/scsi_ioctl.h> #include <scsi/sg.h> #include <stdlib.h> @@ -73,11 +69,7 @@ extern smartmonctrl * con; #include "scsicmds.h" #include "utility.h" #include "extern.h" - -#ifdef HAVE_LINUX_CCISS_IOCTL_H -#include <linux/cciss_ioctl.h> -#endif - +#include "cciss.h" #ifndef ENOTSUP #define ENOTSUP ENOSYS @@ -87,9 +79,9 @@ typedef unsigned long long u8; #define ARGUSED(x) ((void)(x)) -static const char *filenameandversion="$Id: os_linux.cpp,v 1.92 2007/03/23 03:46:44 dpgilbert Exp $"; +static const char *filenameandversion="$Id: os_linux.cpp,v 1.93 2007/04/01 16:49:48 shattered Exp $"; -const char *os_XXXX_c_cvsid="$Id: os_linux.cpp,v 1.92 2007/03/23 03:46:44 dpgilbert Exp $" \ +const char *os_XXXX_c_cvsid="$Id: os_linux.cpp,v 1.93 2007/04/01 16:49:48 shattered Exp $" \ ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_LINUX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; // to hold onto exit code for atexit routine @@ -101,23 +93,6 @@ extern long long bytes; /* for passing global control variables */ extern smartmonctrl *con; -#ifdef HAVE_LINUX_CCISS_IOCTL_H -static int cciss_io_interface(int device, int target, - struct scsi_cmnd_io * iop, int report); - -typedef struct _ReportLUNdata_struct -{ - BYTE LUNListLength[4]; - DWORD reserved; - BYTE LUN[CISS_MAX_LUN][8]; -} ReportLunData_struct; -#endif - -/* Structure/defines of Report Physical LUNS of drive */ -#define CISS_MAX_PHYS_LUN 1024 -#define CISS_REPORT_PHYS 0xc3 - - /* This function will setup and fix device nodes for a 3ware controller. */ #define MAJOR_STRING_LENGTH 3 #define DEVICE_STRING_LENGTH 32 @@ -654,96 +629,6 @@ int ata_command_interface(int device, smart_command_set command, int select, cha return 0; } -#ifdef HAVE_LINUX_CCISS_IOCTL_H -// CCISS Smart Array Controller -static int cciss_sendpassthru(unsigned int cmdtype, unsigned char *CDB, - unsigned int CDBlen, char *buff, - unsigned int size, unsigned int LunID, - unsigned char *scsi3addr, int fd) -{ - int err ; - IOCTL_Command_struct iocommand; - - memset(&iocommand, 0, sizeof(iocommand)); - - if (cmdtype == 0) - { - // To controller; nothing to do - } - else if (cmdtype == 1) - { - iocommand.LUN_info.LogDev.VolId = LunID; - iocommand.LUN_info.LogDev.Mode = 1; - } - else if (cmdtype == 2) - { - memcpy(&iocommand.LUN_info.LunAddrBytes,scsi3addr,8); - iocommand.LUN_info.LogDev.Mode = 0; - } - else - { - fprintf(stderr, "cciss_sendpassthru: bad cmdtype\n"); - return 1; - } - - memcpy(&iocommand.Request.CDB[0], CDB, CDBlen); - iocommand.Request.CDBLen = CDBlen; - iocommand.Request.Type.Type = TYPE_CMD; - iocommand.Request.Type.Attribute = ATTR_SIMPLE; - iocommand.Request.Type.Direction = XFER_READ; - iocommand.Request.Timeout = 0; - - iocommand.buf_size = size; - iocommand.buf = (unsigned char *)buff; - - if ((err = ioctl(fd, CCISS_PASSTHRU, &iocommand))) - { - fprintf(stderr, "CCISS ioctl error %d\n", err); - } - return err; -} - -static int cciss_getlun(int device, int target, unsigned char *physlun) -{ - unsigned char CDB[16]= {0}; - ReportLunData_struct *luns; - int reportlunsize = sizeof(*luns) + CISS_MAX_PHYS_LUN * 8; - int i; - int ret; - - luns = (ReportLunData_struct *)malloc(reportlunsize); - - memset(luns, 0, reportlunsize); - - /* Get Physical LUN Info (for physical device) */ - CDB[0] = CISS_REPORT_PHYS; - CDB[6] = (reportlunsize >> 24) & 0xFF; /* MSB */ - CDB[7] = (reportlunsize >> 16) & 0xFF; - CDB[8] = (reportlunsize >> 8) & 0xFF; - CDB[9] = reportlunsize & 0xFF; - - if ((ret = cciss_sendpassthru(0, CDB, 12, (char *)luns, reportlunsize, 0, NULL, device))) - { - free(luns); - return ret; - } - - for (i=0; i<CISS_MAX_LUN; i++) - { - if (luns->LUN[i][6] == target) - { - memcpy(physlun, luns->LUN[i], 8); - free(luns); - return 0; - } - } - - free(luns); - return ret; -} -// end CCISS Smart Array Controller -#endif - // >>>>>> Start of general SCSI specific linux code /* Linux specific code. @@ -1120,78 +1005,6 @@ static int do_normal_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, // >>>>>> End of general SCSI specific linux code -#ifdef HAVE_LINUX_CCISS_IOCTL_H -/* cciss >> CCSISS I/O passthrough - This is an interface that uses the cciss passthrough to talk to the SMART controller on - the HP system. The cciss driver provides a way to send SCSI cmds through the CCISS passthrough - essentially the methods above and below pertain to SCSI, except for the SG driver which is not - involved. The CCISS driver does not engage the scsi subsystem. */ - static int cciss_io_interface(int device, int target, struct scsi_cmnd_io * iop, int report) - { - unsigned char pBuf[512] = {0}; - unsigned char phylun[1024] = {0}; - int iBufLen = 512; - int status = -1; - int len = 0; // used later in the code. - report = 0; - - cciss_getlun(device, target, phylun); - status = cciss_sendpassthru( 2, iop->cmnd, iop->cmnd_len, (char*) pBuf, iBufLen, 1, phylun, device); - - if (0 == status) - { - if (report > 0) - printf(" status=0\n"); - if (DXFER_FROM_DEVICE == iop->dxfer_dir) - { - memcpy(iop->dxferp, pBuf, iop->dxfer_len); - if (report > 1) - { - int trunc = (iop->dxfer_len > 256) ? 1 : 0; - printf(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len, - (trunc ? " [only first 256 bytes shown]" : "")); - dStrHex((const char*)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); - } - } - return 0; - } - iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */ - if (LSCSI_DRIVER_SENSE == ((status >> 24) & 0xf)) - iop->scsi_status = SCSI_STATUS_CHECK_CONDITION; - len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ? - SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len; - if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) && - iop->sensep && (len > 0)) - { - memcpy(iop->sensep, pBuf, len); - iop->resp_sense_len = iBufLen; - if (report > 1) - { - printf(" >>> Sense buffer, len=%d:\n", (int)len); - dStrHex((const char *)pBuf, len , 1); - } - } - if (report) - { - if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) { - printf(" status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff, - pBuf[2] & 0xf, pBuf[12], pBuf[13]); - } - else - printf(" status=0x%x\n", status); - } - if (iop->scsi_status > 0) - return 0; - else - { - if (report > 0) - printf(" ioctl status=0x%x but scsi status=0, fail with EIO\n", status); - return -EIO; /* give up, assume no device there */ - } - } -#endif - - // prototype void printwarning(smart_command_set command); -- GitLab