]> git.proxmox.com Git - mirror_smartmontools-debian.git/blobdiff - scsicmds.cpp
Refresh original patches with new upstream release
[mirror_smartmontools-debian.git] / scsicmds.cpp
index 3adc913f1f543e4999b24dc7a7c9fc7fd8b5d308..9d0439469006fc4826583f72af7bd7102c3c2aa6 100644 (file)
@@ -1,13 +1,11 @@
 /*
  * scsicmds.cpp
  *
- * Home page of code is: http://smartmontools.sourceforge.net
+ * Home page of code is: http://www.smartmontools.org
  *
- * Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2002-8 Bruce Allen
  * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
- *
- * Additional SCSI work:
- * Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com>
+ * Copyright (C) 2003-16 Douglas Gilbert <dgilbert@interlog.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -40,6 +38,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
+#include <ctype.h>
 
 #include "config.h"
 #include "int64.h"
@@ -48,7 +47,7 @@
 #include "dev_interface.h"
 #include "utility.h"
 
-const char *scsicmds_c_cvsid="$Id: scsicmds.cpp 3807 2013-04-18 17:11:12Z chrfranke $"
+const char *scsicmds_c_cvsid="$Id: scsicmds.cpp 4414 2017-03-27 21:00:46Z chrfranke $"
   SCSICMDS_H_CVSID;
 
 // Print SCSI debug messages?
@@ -59,14 +58,12 @@ supported_vpd_pages * supported_vpd_pages_p = NULL;
 
 supported_vpd_pages::supported_vpd_pages(scsi_device * device) : num_valid(0)
 {
-    unsigned char b[0x1fc];     /* size chosen for old INQUIRY command */
-    int n;
-
+    unsigned char b[0xfc];     /* pre SPC-3 INQUIRY max response size */
     memset(b, 0, sizeof(b));
     if (device && (0 == scsiInquiryVpd(device, SCSI_VPD_SUPPORTED_VPD_PAGES,
                    b, sizeof(b)))) {
         num_valid = (b[2] << 8) + b[3];
-        n = sizeof(pages);
+        int n = sizeof(pages);
         if (num_valid > n)
             num_valid = n;
         memcpy(pages, b + 4, num_valid);
@@ -90,7 +87,6 @@ void
 dStrHex(const char* str, int len, int no_ascii)
 {
     const char* p = str;
-    unsigned char c;
     char buff[82];
     int a = 0;
     const int bpstart = 5;
@@ -109,7 +105,7 @@ dStrHex(const char* str, int len, int no_ascii)
 
     for(i = 0; i < len; i++)
     {
-        c = *p++;
+        unsigned char c = *p++;
         bpos += 3;
         if (bpos == (bpstart + (9 * 3)))
             bpos++;
@@ -124,6 +120,9 @@ dStrHex(const char* str, int len, int no_ascii)
         }
         if (cpos > (cpstart+15))
         {
+            while (cpos > 0 && buff[cpos-1] == ' ')
+              cpos--;
+            buff[cpos] = 0;
             pout("%s\n", buff);
             bpos = bpstart;
             cpos = cpstart;
@@ -135,6 +134,9 @@ dStrHex(const char* str, int len, int no_ascii)
     }
     if (cpos > cpstart)
     {
+        while (cpos > 0 && buff[cpos-1] == ' ')
+          cpos--;
+        buff[cpos] = 0;
         pout("%s\n", buff);
     }
 }
@@ -174,14 +176,12 @@ static const char * vendor_specific = "<vendor specific>";
 const char *
 scsi_get_opcode_name(UINT8 opcode)
 {
-    int k;
     int len = sizeof(opcode_name_arr) / sizeof(opcode_name_arr[0]);
-    struct scsi_opcode_name * onp;
 
     if (opcode >= 0xc0)
         return vendor_specific;
-    for (k = 0; k < len; ++k) {
-        onp = &opcode_name_arr[k];
+    for (int k = 0; k < len; ++k) {
+        struct scsi_opcode_name * onp = &opcode_name_arr[k];
         if (opcode == onp->opcode)
             return onp->name;
         else if (opcode < onp->opcode)
@@ -194,11 +194,9 @@ void
 scsi_do_sense_disect(const struct scsi_cmnd_io * io_buf,
                      struct scsi_sense_disect * out)
 {
-    int resp_code;
-
     memset(out, 0, sizeof(struct scsi_sense_disect));
     if (SCSI_STATUS_CHECK_CONDITION == io_buf->scsi_status) {
-        resp_code = (io_buf->sensep[0] & 0x7f);
+        int resp_code = (io_buf->sensep[0] & 0x7f);
         out->resp_code = resp_code;
         if (resp_code >= 0x72) {
             out->sense_key = (io_buf->sensep[1] & 0xf);
@@ -301,19 +299,19 @@ scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc, int page_len,
                      int * off, int m_assoc, int m_desig_type, int m_code_set)
 {
     const unsigned char * ucp;
-    int k, c_set, assoc, desig_type;
+    int k;
 
     for (k = *off, ucp = initial_desig_desc ; (k + 3) < page_len; ) {
         k = (k < 0) ? 0 : (k + ucp[k + 3] + 4);
         if ((k + 4) > page_len)
             break;
-        c_set = (ucp[k] & 0xf);
+        int c_set = (ucp[k] & 0xf);
         if ((m_code_set >= 0) && (m_code_set != c_set))
             continue;
-        assoc = ((ucp[k + 1] >> 4) & 0x3);
+        int assoc = ((ucp[k + 1] >> 4) & 0x3);
         if ((m_assoc >= 0) && (m_assoc != assoc))
             continue;
-        desig_type = (ucp[k + 1] & 0xf);
+        int desig_type = (ucp[k + 1] & 0xf);
         if ((m_desig_type >= 0) && (m_desig_type != desig_type))
             continue;
         *off = k;
@@ -329,11 +327,6 @@ int
 scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
                       int * transport)
 {
-    int m, c_set, assoc, desig_type, i_len, naa, off, u, have_scsi_ns;
-    const unsigned char * ucp;
-    const unsigned char * ip;
-    int si = 0;
-
     if (transport)
         *transport = -1;
     if (slen < 32) {
@@ -341,25 +334,29 @@ scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
             s[0] = '\0';
         return -1;
     }
-    have_scsi_ns = 0;
+
     s[0] = '\0';
-    off = -1;
+    int si = 0;
+    int have_scsi_ns = 0;
+    int off = -1;
+    int u;
     while ((u = scsi_vpd_dev_id_iter(b, blen, &off, -1, -1, -1)) == 0) {
-        ucp = b + off;
-        i_len = ucp[3];
+        const unsigned char * ucp = b + off;
+        int i_len = ucp[3];
         if ((off + i_len + 4) > blen) {
             snprintf(s+si, slen-si, "error: designator length");
             return -1;
         }
-        assoc = ((ucp[1] >> 4) & 0x3);
+        int assoc = ((ucp[1] >> 4) & 0x3);
         if (transport && assoc && (ucp[1] & 0x80) && (*transport < 0))
             *transport = (ucp[0] >> 4) & 0xf;
         if (0 != assoc)
             continue;
-        ip = ucp + 4;
-        c_set = (ucp[0] & 0xf);
-        desig_type = (ucp[1] & 0xf);
+        const unsigned char * ip = ucp + 4;
+        int c_set = (ucp[0] & 0xf);
+        int desig_type = (ucp[1] & 0xf);
 
+        int naa;
         switch (desig_type) {
         case 0: /* vendor specific */
         case 1: /* T10 vendor identification */
@@ -372,7 +369,7 @@ scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
             if (have_scsi_ns)
                 si = 0;
             si += snprintf(s+si, slen-si, "0x");
-            for (m = 0; m < i_len; ++m)
+            for (int m = 0; m < i_len; ++m)
                 si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
             break;
         case 3: /* NAA */
@@ -393,7 +390,7 @@ scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
                     return -1;
                 }
                 si += snprintf(s+si, slen-si, "0x");
-                for (m = 0; m < 8; ++m)
+                for (int m = 0; m < 8; ++m)
                     si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
             } else if ((3 == naa ) || (5 == naa)) {
                 /* NAA=3 Locally assigned; NAA=5 IEEE Registered */
@@ -402,7 +399,7 @@ scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
                     return -1;
                 }
                 si += snprintf(s+si, slen-si, "0x");
-                for (m = 0; m < 8; ++m)
+                for (int m = 0; m < 8; ++m)
                     si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
             } else if (6 == naa) {      /* NAA IEEE Registered extended */
                 if (16 != i_len) {
@@ -410,7 +407,7 @@ scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
                     return -1;
                 }
                 si += snprintf(s+si, slen-si, "0x");
-                for (m = 0; m < 16; ++m)
+                for (int m = 0; m < 16; ++m)
                     si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
             }
             break;
@@ -460,7 +457,6 @@ scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
     UINT8 cdb[10];
     UINT8 sense[32];
     int pageLen;
-    int status, res;
 
     if (known_resp_len > bufLen)
         return -EIO;
@@ -493,6 +489,7 @@ scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
         if (!device->scsi_pass_through(&io_hdr))
           return -device->get_errno();
         scsi_do_sense_disect(&io_hdr, &sinfo);
+        int res;
         if ((res = scsiSimpleSenseFilter(&sinfo)))
             return res;
         /* sanity check on response */
@@ -528,7 +525,7 @@ scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
     if (!device->scsi_pass_through(&io_hdr))
       return -device->get_errno();
     scsi_do_sense_disect(&io_hdr, &sinfo);
-    status = scsiSimpleSenseFilter(&sinfo);
+    int status = scsiSimpleSenseFilter(&sinfo);
     if (0 != status)
         return status;
     /* sanity check on response */
@@ -588,7 +585,6 @@ scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
     struct scsi_sense_disect sinfo;
     UINT8 cdb[6];
     UINT8 sense[32];
-    int status;
 
     if ((bufLen < 0) || (bufLen > 255))
         return -EINVAL;
@@ -610,7 +606,7 @@ scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
     if (!device->scsi_pass_through(&io_hdr))
       return -device->get_errno();
     scsi_do_sense_disect(&io_hdr, &sinfo);
-    status = scsiSimpleSenseFilter(&sinfo);
+    int status = scsiSimpleSenseFilter(&sinfo);
     if (SIMPLE_ERR_TRY_AGAIN == status) {
         if (!device->scsi_pass_through(&io_hdr))
           return -device->get_errno();
@@ -686,7 +682,6 @@ scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc,
     struct scsi_sense_disect sinfo;
     UINT8 cdb[10];
     UINT8 sense[32];
-    int status;
 
     memset(&io_hdr, 0, sizeof(io_hdr));
     memset(cdb, 0, sizeof(cdb));
@@ -707,7 +702,7 @@ scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc,
     if (!device->scsi_pass_through(&io_hdr))
       return -device->get_errno();
     scsi_do_sense_disect(&io_hdr, &sinfo);
-    status = scsiSimpleSenseFilter(&sinfo);
+    int status = scsiSimpleSenseFilter(&sinfo);
     if (SIMPLE_ERR_TRY_AGAIN == status) {
         if (!device->scsi_pass_through(&io_hdr))
           return -device->get_errno();
@@ -878,8 +873,6 @@ scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info)
     UINT8 cdb[6];
     UINT8 sense[32];
     UINT8 buff[18];
-    int len;
-    UINT8 resp_code;
 
     memset(&io_hdr, 0, sizeof(io_hdr));
     memset(cdb, 0, sizeof(cdb));
@@ -897,13 +890,13 @@ scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info)
     if (!device->scsi_pass_through(&io_hdr))
       return -device->get_errno();
     if (sense_info) {
-        resp_code = buff[0] & 0x7f;
+        UINT8 resp_code = buff[0] & 0x7f;
         sense_info->resp_code = resp_code;
         sense_info->sense_key = buff[2] & 0xf;
         sense_info->asc = 0;
         sense_info->ascq = 0;
         if ((0x70 == resp_code) || (0x71 == resp_code)) {
-            len = buff[7] + 8;
+            int len = buff[7] + 8;
             if (len > 13) {
                 sense_info->asc = buff[12];
                 sense_info->ascq = buff[13];
@@ -988,40 +981,6 @@ scsiSendDiagnostic(scsi_device * device, int functioncode, UINT8 *pBuf,
     return scsiSimpleSenseFilter(&sinfo);
 }
 
-/* RECEIVE DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if
- * command not supported, 3 if field in command not supported or returns
- * negated errno. SPC-3 section 6.18 (rev 22a) */
-int
-scsiReceiveDiagnostic(scsi_device * device, int pcv, int pagenum, UINT8 *pBuf,
-                      int bufLen)
-{
-    struct scsi_cmnd_io io_hdr;
-    struct scsi_sense_disect sinfo;
-    UINT8 cdb[6];
-    UINT8 sense[32];
-
-    memset(&io_hdr, 0, sizeof(io_hdr));
-    memset(cdb, 0, sizeof(cdb));
-    io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
-    io_hdr.dxfer_len = bufLen;
-    io_hdr.dxferp = pBuf;
-    cdb[0] = RECEIVE_DIAGNOSTIC;
-    cdb[1] = pcv;
-    cdb[2] = pagenum;
-    cdb[3] = (bufLen >> 8) & 0xff;
-    cdb[4] = bufLen & 0xff;
-    io_hdr.cmnd = cdb;
-    io_hdr.cmnd_len = sizeof(cdb);
-    io_hdr.sensep = sense;
-    io_hdr.max_sense_len = sizeof(sense);
-    io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
-
-    if (!device->scsi_pass_through(&io_hdr))
-      return -device->get_errno();
-    scsi_do_sense_disect(&io_hdr, &sinfo);
-    return scsiSimpleSenseFilter(&sinfo);
-}
-
 /* TEST UNIT READY command. SPC-3 section 6.33 (rev 22a) */
 static int
 _testunitready(scsi_device * device, struct scsi_sense_disect * sinfo)
@@ -1071,7 +1030,8 @@ scsiTestUnitReady(scsi_device * device)
 }
 
 /* READ DEFECT (10) command. Returns 0 if ok, 1 if NOT READY, 2 if
- * command not supported, 3 if field in command not supported or returns
+ * command not supported, 3 if field in command not supported, 101 if
+ * defect list not found (e.g. SSD may not have defect list) or returns
  * negated errno. SBC-2 section 5.12 (rev 16) */
 int
 scsiReadDefect10(scsi_device * device, int req_plist, int req_glist,
@@ -1101,11 +1061,15 @@ scsiReadDefect10(scsi_device * device, int req_plist, int req_glist,
     if (!device->scsi_pass_through(&io_hdr))
       return -device->get_errno();
     scsi_do_sense_disect(&io_hdr, &sinfo);
+    /* Look for "(Primary|Grown) defect list not found" */
+    if ((sinfo.resp_code >= 0x70) && (0x1c == sinfo.asc))
+        return 101;
     return scsiSimpleSenseFilter(&sinfo);
 }
 
 /* READ DEFECT (12) command. Returns 0 if ok, 1 if NOT READY, 2 if
- * command not supported, 3 if field in command not supported or returns
+ * command not supported, 3 if field in command not supported, 101 if
+ * defect list not found (e.g. SSD may not have defect list) or returns
  * negated errno. SBC-3 section 5.18 (rev 35; vale Mark Evans) */
 int
 scsiReadDefect12(scsi_device * device, int req_plist, int req_glist,
@@ -1141,6 +1105,9 @@ scsiReadDefect12(scsi_device * device, int req_plist, int req_glist,
     if (!device->scsi_pass_through(&io_hdr))
       return -device->get_errno();
     scsi_do_sense_disect(&io_hdr, &sinfo);
+    /* Look for "(Primary|Grown) defect list not found" */
+    if ((sinfo.resp_code >= 0x70) && (0x1c == sinfo.asc))
+        return 101;
     return scsiSimpleSenseFilter(&sinfo);
 }
 
@@ -1228,7 +1195,7 @@ scsiGetSize(scsi_device * device, unsigned int * lb_sizep,
             int * lb_per_pb_expp)
 {
     unsigned int last_lba = 0, lb_size = 0;
-    int k, res;
+    int res;
     uint64_t ret_val = 0;
     UINT8 rc16resp[32];
 
@@ -1245,7 +1212,7 @@ scsiGetSize(scsi_device * device, unsigned int * lb_sizep,
                 pout("scsiGetSize: READ CAPACITY(16) failed, res=%d\n", res);
             return 0;
         }
-        for (k = 0; k < 8; ++k) {
+        for (int k = 0; k < 8; ++k) {
             if (k > 0)
                 ret_val <<= 8;
             ret_val |= rc16resp[k + 0];
@@ -1290,10 +1257,10 @@ scsiGetProtPBInfo(scsi_device * device, unsigned char * rc16_12_31p)
 int
 scsiModePageOffset(const UINT8 * resp, int len, int modese_len)
 {
-    int resp_len, bd_len;
     int offset = -1;
 
     if (resp) {
+        int resp_len, bd_len;
         if (10 == modese_len) {
             resp_len = (resp[0] << 8) + resp[1] + 2;
             bd_len = (resp[6] << 8) + resp[7];
@@ -1380,11 +1347,9 @@ scsiFetchIECmpage(scsi_device * device, struct scsi_iec_mode_page *iecp,
 int
 scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
 {
-    int offset;
-
     if (iecp && iecp->gotCurrent) {
-        offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
-                                    iecp->modese_len);
+        int offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
+                                        iecp->modese_len);
         if (offset >= 0)
             return (iecp->raw_curr[offset + 2] & DEXCPT_ENABLE) ? 0 : 1;
         else
@@ -1396,11 +1361,9 @@ scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
 int
 scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
 {
-    int offset;
-
     if (iecp && iecp->gotCurrent) {
-        offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
-                                    iecp->modese_len);
+        int offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
+                                        iecp->modese_len);
         if (offset >= 0)
             return (iecp->raw_curr[offset + 2] & EWASC_ENABLE) ? 1 : 0;
         else
@@ -1428,10 +1391,9 @@ int
 scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
                                   const struct scsi_iec_mode_page *iecp)
 {
-    int k, offset, resp_len;
+    int offset, resp_len;
     int err = 0;
     UINT8 rout[SCSI_IECMP_RAW_LEN];
-    int sp, eCEnabled, wEnabled;
 
     if ((! iecp) || (! iecp->gotCurrent))
         return -EINVAL;
@@ -1440,14 +1402,15 @@ scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
     if (offset < 0)
         return -EINVAL;
     memcpy(rout, iecp->raw_curr, SCSI_IECMP_RAW_LEN);
+    /* mask out DPOFUA device specific (disk) parameter bit */
     if (10 == iecp->modese_len) {
         resp_len = (rout[0] << 8) + rout[1] + 2;
-        rout[3] &= 0xef;    /* for disks mask out DPOFUA bit */
+        rout[3] &= 0xef;
     } else {
         resp_len = rout[0] + 1;
-        rout[2] &= 0xef;    /* for disks mask out DPOFUA bit */
+        rout[2] &= 0xef;
     }
-    sp = (rout[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
+    int sp = (rout[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
     if (enabled) {
         rout[offset + 2] = SCSI_IEC_MP_BYTE2_ENABLED;
         if (scsi_debugmode > 2)
@@ -1466,7 +1429,7 @@ scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
 
             rout[offset + 2] = chg2 ? (rout[offset + 2] & chg2) :
                                       iecp->raw_curr[offset + 2];
-            for (k = 3; k < 12; ++k) {
+            for (int k = 3; k < 12; ++k) {
                 if (0 == iecp->raw_chg[offset + k])
                     rout[offset + k] = iecp->raw_curr[offset + k];
             }
@@ -1477,8 +1440,8 @@ scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
             return 0;
         }
     } else { /* disabling Exception Control and (temperature) Warnings */
-        eCEnabled = (rout[offset + 2] & DEXCPT_ENABLE) ? 0 : 1;
-        wEnabled = (rout[offset + 2] & EWASC_ENABLE) ? 1 : 0;
+        int eCEnabled = (rout[offset + 2] & DEXCPT_ENABLE) ? 0 : 1;
+        int wEnabled = (rout[offset + 2] & EWASC_ENABLE) ? 1 : 0;
         if ((! eCEnabled) && (! wEnabled)) {
             if (scsi_debugmode > 0)
                 pout("scsiSetExceptionControlAndWarning: already disabled\n");
@@ -1490,7 +1453,7 @@ scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
             if (iecp->gotChangeable &&
                 (iecp->raw_chg[offset + 2] & DEXCPT_ENABLE))
                 rout[offset + 2] |= DEXCPT_ENABLE;
-                rout[offset + 2] &= TEST_DISABLE;/* clear TEST bit for spec */
+            rout[offset + 2] &= TEST_DISABLE; /* clear TEST bit for spec */
         }
     }
     if (10 == iecp->modese_len)
@@ -1530,8 +1493,6 @@ scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
     UINT8 tBuf[252];
     struct scsi_sense_disect sense_info;
     int err;
-    int temperatureSet = 0;
-    unsigned short pagesize;
     UINT8 currTemp, trTemp;
 
     *asc = 0;
@@ -1547,7 +1508,7 @@ scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
             return err;
         }
         // pull out page size from response, don't forget to add 4
-        pagesize = (unsigned short) ((tBuf[2] << 8) | tBuf[3]) + 4;
+        unsigned short pagesize = (unsigned short) ((tBuf[2] << 8) | tBuf[3]) + 4;
         if ((pagesize < 4) || tBuf[4] || tBuf[5]) {
             pout("Log Sense failed, IE page, bad parameter code or length\n");
             return SIMPLE_ERR_BAD_PARAM;
@@ -1572,7 +1533,7 @@ scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
     }
     *asc = sense_info.asc;
     *ascq = sense_info.ascq;
-    if ((! temperatureSet) && hasTempLogPage) {
+    if (hasTempLogPage) {
         if (0 == scsiGetTemp(device, &currTemp, &trTemp)) {
             *currenttemp = currTemp;
             *triptemp = trTemp;
@@ -2107,30 +2068,6 @@ scsiGetIEString(UINT8 asc, UINT8 ascq)
 }
 
 
-/* This is not documented in t10.org, page 0x80 is vendor specific */
-/* Some IBM disks do an offline read-scan when they get this command. */
-int
-scsiSmartIBMOfflineTest(scsi_device * device)
-{
-    UINT8 tBuf[256];
-    int res;
-
-    memset(tBuf, 0, sizeof(tBuf));
-    /* Build SMART Off-line Immediate Diag Header */
-    tBuf[0] = 0x80; /* Page Code */
-    tBuf[1] = 0x00; /* Reserved */
-    tBuf[2] = 0x00; /* Page Length MSB */
-    tBuf[3] = 0x04; /* Page Length LSB */
-    tBuf[4] = 0x03; /* SMART Revision */
-    tBuf[5] = 0x00; /* Reserved */
-    tBuf[6] = 0x00; /* Off-line Immediate Time MSB */
-    tBuf[7] = 0x00; /* Off-line Immediate Time LSB */
-    res = scsiSendDiagnostic(device, SCSI_DIAG_NO_SELF_TEST, tBuf, 8);
-    if (res)
-        pout("IBM offline test failed [%s]\n", scsiErrString(res));
-    return res;
-}
-
 int
 scsiSmartDefaultSelfTest(scsi_device * device)
 {
@@ -2205,7 +2142,7 @@ int
 scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec,
                               int modese_len)
 {
-    int err, offset, res;
+    int err, offset;
     UINT8 buff[64];
 
     memset(buff, 0, sizeof(buff));
@@ -2231,7 +2168,7 @@ scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec,
     if (offset < 0)
         return -EINVAL;
     if (buff[offset + 1] >= 0xa) {
-        res = (buff[offset + 10] << 8) | buff[offset + 11];
+        int res = (buff[offset + 10] << 8) | buff[offset + 11];
         *durationSec = res;
         return 0;
     }
@@ -2242,17 +2179,13 @@ scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec,
 void
 scsiDecodeErrCounterPage(unsigned char * resp, struct scsiErrorCounter *ecp)
 {
-    int k, j, num, pl, pc;
-    unsigned char * ucp;
-    unsigned char * xp;
-    uint64_t * ullp;
-
     memset(ecp, 0, sizeof(*ecp));
-    num = (resp[2] << 8) | resp[3];
-    ucp = &resp[0] + 4;
+    int num = (resp[2] << 8) | resp[3];
+    unsigned char * ucp = &resp[0] + 4;
     while (num > 3) {
-        pc = (ucp[0] << 8) | ucp[1];
-        pl = ucp[3] + 4;
+        int pc = (ucp[0] << 8) | ucp[1];
+        int pl = ucp[3] + 4;
+        uint64_t * ullp;
         switch (pc) {
             case 0:
             case 1:
@@ -2269,14 +2202,14 @@ scsiDecodeErrCounterPage(unsigned char * resp, struct scsiErrorCounter *ecp)
                 ullp = &ecp->counter[7];
                 break;
         }
-        k = pl - 4;
-        xp = ucp + 4;
+        int k = pl - 4;
+        unsigned char * xp = ucp + 4;
         if (k > (int)sizeof(*ullp)) {
             xp += (k - sizeof(*ullp));
             k = sizeof(*ullp);
         }
         *ullp = 0;
-        for (j = 0; j < k; ++j) {
+        for (int j = 0; j < k; ++j) {
             if (j > 0)
                 *ullp <<= 8;
             *ullp |= xp[j];
@@ -2290,17 +2223,15 @@ void
 scsiDecodeNonMediumErrPage(unsigned char *resp,
                            struct scsiNonMediumError *nmep)
 {
-    int k, j, num, pl, pc, szof;
-    unsigned char * ucp;
-    unsigned char * xp;
-
     memset(nmep, 0, sizeof(*nmep));
-    num = (resp[2] << 8) | resp[3];
-    ucp = &resp[0] + 4;
-    szof = sizeof(nmep->counterPC0);
+    int num = (resp[2] << 8) | resp[3];
+    unsigned char * ucp = &resp[0] + 4;
+    int szof = sizeof(nmep->counterPC0);
     while (num > 3) {
-        pc = (ucp[0] << 8) | ucp[1];
-        pl = ucp[3] + 4;
+        int pc = (ucp[0] << 8) | ucp[1];
+        int pl = ucp[3] + 4;
+        int k;
+        unsigned char * xp;
         switch (pc) {
             case 0:
                 nmep->gotPC0 = 1;
@@ -2311,7 +2242,7 @@ scsiDecodeNonMediumErrPage(unsigned char *resp,
                     k = szof;
                 }
                 nmep->counterPC0 = 0;
-                for (j = 0; j < k; ++j) {
+                for (int j = 0; j < k; ++j) {
                     if (j > 0)
                         nmep->counterPC0 <<= 8;
                     nmep->counterPC0 |= xp[j];
@@ -2326,7 +2257,7 @@ scsiDecodeNonMediumErrPage(unsigned char *resp,
                     k = szof;
                 }
                 nmep->counterTFE_H = 0;
-                for (j = 0; j < k; ++j) {
+                for (int j = 0; j < k; ++j) {
                     if (j > 0)
                         nmep->counterTFE_H <<= 8;
                     nmep->counterTFE_H |= xp[j];
@@ -2341,7 +2272,7 @@ scsiDecodeNonMediumErrPage(unsigned char *resp,
                     k = szof;
                 }
                 nmep->counterPE_H = 0;
-                for (j = 0; j < k; ++j) {
+                for (int j = 0; j < k; ++j) {
                     if (j > 0)
                         nmep->counterPE_H <<= 8;
                     nmep->counterPE_H |= xp[j];
@@ -2367,7 +2298,7 @@ scsiDecodeNonMediumErrPage(unsigned char *resp,
 int
 scsiCountFailedSelfTests(scsi_device * fd, int noisy)
 {
-    int num, k, n, err, res, fails, fail_hour;
+    int num, k, err, fails, fail_hour;
     UINT8 * ucp;
     unsigned char resp[LOG_RESP_SELF_TEST_LEN];
 
@@ -2396,13 +2327,13 @@ scsiCountFailedSelfTests(scsi_device * fd, int noisy)
     for (k = 0, ucp = resp + 4; k < 20; ++k, ucp += 20 ) {
 
         // timestamp in power-on hours (or zero if test in progress)
-        n = (ucp[6] << 8) | ucp[7];
+        int n = (ucp[6] << 8) | ucp[7];
 
         // The spec says "all 20 bytes will be zero if no test" but
         // DG has found otherwise.  So this is a heuristic.
         if ((0 == n) && (0 == ucp[4]))
             break;
-        res = ucp[4] & 0xf;
+        int res = ucp[4] & 0xf;
         if ((res > 2) && (res < 8)) {
             fails++;
             if (1 == fails)
@@ -2478,9 +2409,10 @@ scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current)
  * RIGID_DISK_DRIVE_GEOMETRY_PAGE mode page. */
 
 int
-scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp)
+scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp,
+           int * haw_zbcp)
 {
-    int err, offset, speed;
+    int err, offset;
     UINT8 buff[64];
     int pc = MPAGE_CONTROL_DEFAULT;
 
@@ -2488,13 +2420,17 @@ scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp)
     if ((0 == scsiInquiryVpd(device, SCSI_VPD_BLOCK_DEVICE_CHARACTERISTICS,
                              buff, sizeof(buff))) &&
         (((buff[2] << 8) + buff[3]) > 2)) {
-        speed = (buff[4] << 8) + buff[5];
+        int speed = (buff[4] << 8) + buff[5];
         if (form_factorp)
             *form_factorp = buff[7] & 0xf;
+        if (haw_zbcp)
+            *haw_zbcp = !!(0x10 & buff[8]);
         return speed;
     }
     if (form_factorp)
         *form_factorp = 0;
+    if (haw_zbcp)
+        *haw_zbcp = 0;
     if (modese_len <= 6) {
         if ((err = scsiModeSense(device, RIGID_DISK_DRIVE_GEOMETRY_PAGE, 0, pc,
                                  buff, sizeof(buff)))) {
@@ -2598,12 +2534,13 @@ scsiGetSetCache(scsi_device * device,  int modese_len, short int * wcep,
           buff[offset + 2] &= 0xfe; // clear bit
     }
 
+    /* mask out DPOFUA device specific (disk) parameter bit */
     if (10 == modese_len) {
         resp_len = (buff[0] << 8) + buff[1] + 2;
-        buff[3] &= 0xef;    /* for disks mask out DPOFUA bit */
+        buff[3] &= 0xef;
     } else {
         resp_len = buff[0] + 1;
-        buff[2] &= 0xef;    /* for disks mask out DPOFUA bit */
+        buff[2] &= 0xef;
     }
     sp = 0; /* Do not change saved values */
     if (10 == modese_len)
@@ -2666,14 +2603,15 @@ scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len)
     if (err)
         return err;
     if (0 == (ch_buff[offset + 2] & 2))
-        return SIMPLE_ERR_BAD_PARAM;  /* GLTSD bit not chageable */
+        return SIMPLE_ERR_BAD_PARAM;  /* GLTSD bit not changeable */
 
+    /* mask out DPOFUA device specific (disk) parameter bit */
     if (10 == modese_len) {
         resp_len = (buff[0] << 8) + buff[1] + 2;
-        buff[3] &= 0xef;    /* for disks mask out DPOFUA bit */
+        buff[3] &= 0xef;    
     } else {
         resp_len = buff[0] + 1;
-        buff[2] &= 0xef;    /* for disks mask out DPOFUA bit */
+        buff[2] &= 0xef;
     }
     sp = (buff[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
     if (enabled)
@@ -2728,7 +2666,7 @@ const unsigned char *
 sg_scsi_sense_desc_find(const unsigned char * sensep, int sense_len,
                         int desc_type)
 {
-    int add_sen_len, add_len, desc_len, k;
+    int add_sen_len;
     const unsigned char * descp;
 
     if ((sense_len < 8) || (0 == (add_sen_len = sensep[7])))
@@ -2738,9 +2676,9 @@ sg_scsi_sense_desc_find(const unsigned char * sensep, int sense_len,
     add_sen_len = (add_sen_len < (sense_len - 8)) ?
                          add_sen_len : (sense_len - 8);
     descp = &sensep[8];
-    for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
+    for (int desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
         descp += desc_len;
-        add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
+        int add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
         desc_len = add_len + 2;
         if (descp[0] == desc_type)
             return descp;