diff --git a/sm5/TODO b/sm5/TODO
index 42b63770455bd534b7fcdef4693bfbcecac0675a..7ed0a01c2234d36007cc1d1cc012050b19981528 100644
--- a/sm5/TODO
+++ b/sm5/TODO
@@ -1,6 +1,6 @@
 TODO list for smartmontools:
 
-$Id: TODO,v 1.51 2004/04/11 17:13:39 chrfranke Exp $
+$Id: TODO,v 1.52 2004/04/17 10:44:47 ballen4705 Exp $
 
 SATA devices
 ------------
@@ -49,11 +49,20 @@ Add interface to Megaraid ATA RAID controllers (Erik)
 
 smartctl: 
 ---------
+Add command line option to issue SMART SAVE ATTRIBUTE VALUES command
+Feature Register value ATA_SMART_SAVE 0xd3
+
 Perhaps modify the -q option (quiet mode) so that it only warns of ATA
 errors if they have (say) taken place in the last 168 hours (week).
 
 Parse and print additional Attribute flag meanings (IBM ones, eg
-performance etc).
+performance etc).  These are now documented in atacmds.h -- we just
+need to modify the format of the Attribute table.
+
+Modify the SMART self-test log table printing so that we ALSO print
+the value of the self-test failure checkpoint byte, if it's one of the
+recognized values.  See routine SelfTestFailureCodeName and
+documentation in atacmds.h.
 
 smartd:
 -------
diff --git a/sm5/atacmds.c b/sm5/atacmds.c
index 85493a35a4b8abd868e6ea591222e174ff9ec139..f8525b44091cc915ecbd2c3750dcc6a1be02dae5 100644
--- a/sm5/atacmds.c
+++ b/sm5/atacmds.c
@@ -35,7 +35,7 @@
 #include "extern.h"
 #include "utility.h"
 
-const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.147 2004/04/09 00:28:43 ballen4705 Exp $"
+const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.148 2004/04/17 10:44:47 ballen4705 Exp $"
 ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -175,6 +175,32 @@ const char *vendorattributeargs[] = {
   NULL
 };
 
+// This are the meanings of the Self-test failure checkpoint byte.
+// This is in the self-test log at offset 4 bytes into the self-test
+// descriptor and in the SMART READ DATA structure at byte offset
+// 371. These codes are not well documented.  The meanings returned by
+// this routine are used (at least) by Maxtor and IBM. Returns NULL if
+// not recognized.  Currently the maximum length is 15 bytes.
+const char *SelfTestFailureCodeName(unsigned char which){
+  
+  switch (which) {
+  case 0:
+    return "Write_Test";
+  case 1:
+    return "Servo_Basic";
+  case 2:
+    return "Servo_Random";
+  case 3:
+    return "G-list_Scan";
+  case 4:
+    return "Handling_Damage";
+  case 5:
+    return "Read_Scan";
+  default:
+    return NULL;
+  }
+}
+
 // This is a utility function for parsing pairs like "9,minutes" or
 // "220,temp", and putting the correct flag into the attributedefs
 // array.  Returns 1 if problem, 0 if pair has been recongized.
diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index ac6aea8f7b2d1e5e140870fecd1b281fb57505bc..4c028e371b9515750f68d6fd491e31ccf41a1e21 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -35,7 +35,7 @@
 #include "extern.h"
 #include "utility.h"
 
-const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.147 2004/04/09 00:28:43 ballen4705 Exp $"
+const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.148 2004/04/17 10:44:47 ballen4705 Exp $"
 ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -175,6 +175,32 @@ const char *vendorattributeargs[] = {
   NULL
 };
 
+// This are the meanings of the Self-test failure checkpoint byte.
+// This is in the self-test log at offset 4 bytes into the self-test
+// descriptor and in the SMART READ DATA structure at byte offset
+// 371. These codes are not well documented.  The meanings returned by
+// this routine are used (at least) by Maxtor and IBM. Returns NULL if
+// not recognized.  Currently the maximum length is 15 bytes.
+const char *SelfTestFailureCodeName(unsigned char which){
+  
+  switch (which) {
+  case 0:
+    return "Write_Test";
+  case 1:
+    return "Servo_Basic";
+  case 2:
+    return "Servo_Random";
+  case 3:
+    return "G-list_Scan";
+  case 4:
+    return "Handling_Damage";
+  case 5:
+    return "Read_Scan";
+  default:
+    return NULL;
+  }
+}
+
 // This is a utility function for parsing pairs like "9,minutes" or
 // "220,temp", and putting the correct flag into the attributedefs
 // array.  Returns 1 if problem, 0 if pair has been recongized.
diff --git a/sm5/atacmds.h b/sm5/atacmds.h
index 94b76fbc75bf1b0bf03481800ff3fd31b541908f..03902ea5c207f57ca9dfc4ce246e85f246cba192 100644
--- a/sm5/atacmds.h
+++ b/sm5/atacmds.h
@@ -25,7 +25,7 @@
 #ifndef ATACMDS_H_
 #define ATACMDS_H_
 
-#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.68 2004/04/09 00:28:44 ballen4705 Exp $\n"
+#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.69 2004/04/17 10:44:47 ballen4705 Exp $\n"
 
 #include "int64.h"
 
@@ -151,13 +151,13 @@ struct ata_smart_attribute {
 // both normal operation and off-line testing.
 #define ATTRIBUTE_FLAGS_ONLINE(x) (x & 0x02)
 
-// 2: Performance bit
 
-// The following are (probably) IBM's or Quantum's definitions for the
+// The following are (probably) IBM's, Maxtors and  Quantum's definitions for the
 // vendor-specific bits:
+// 2: Performance type bit
 #define ATTRIBUTE_FLAGS_PERFORMANCE(x) (x & 0x04)
 
-// 3: Errorrate bit
+// 3: Errorrate type bit
 #define ATTRIBUTE_FLAGS_ERRORRATE(x) (x & 0x08)
 
 // 4: Eventcount bit
@@ -178,20 +178,29 @@ struct ata_smart_values {
   unsigned char offline_data_collection_status;
   unsigned char self_test_exec_status;  //IBM # segments for offline collection
   unsigned short int total_time_to_complete_off_line; // IBM different
-  unsigned char vendor_specific_366; // IBM curent segment pointer
+  unsigned char vendor_specific_366; // Maxtor & IBM curent segment pointer
   unsigned char offline_data_collection_capability;
   unsigned short int smart_capability;
   unsigned char errorlog_capability;
-  unsigned char vendor_specific_371;  // IBM: self-test failure checkpoint
+  unsigned char vendor_specific_371;  // Maxtor, IBM: self-test failure checkpoint see below!
   unsigned char short_test_completion_time;
   unsigned char extend_test_completion_time;
   unsigned char conveyance_test_completion_time;
   unsigned char reserved_375_385[11];
-  unsigned char vendor_specific_386_510[125];
+  unsigned char vendor_specific_386_510[125]; // Maxtor bytes 508-509 Attribute/Threshold Revision #
   unsigned char chksum;
 }; 
 #pragma pack()
 
+/* Maxtor, IBM: self-test failure checkpoint byte meaning:
+ 00 - write test
+ 01 - servo basic
+ 02 - servo random
+ 03 - G-list scan
+ 04 - Handling damage
+ 05 - Read scan
+*/
+
 /* Vendor attribute of SMART Threshold (compare to ata_smart_attribute above) */
 #pragma pack(1)
 struct ata_smart_threshold_entry {
@@ -453,6 +462,15 @@ void checksumwarning(const char *string);
 int64_t ATAReturnAttributeRawValue(unsigned char id, struct ata_smart_values *data);
 
 
+// This are the meanings of the Self-test failure checkpoint byte.
+// This is in the self-test log at offset 4 bytes into the self-test
+// descriptor and in the SMART READ DATA structure at byte offset
+// 371. These codes are not well documented.  The meanings returned by
+// this routine are used (at least) by Maxtor and IBM. Returns NULL if
+// not recognized.
+const char *SelfTestFailureCodeName(unsigned char which);
+
+
 #define MAX_ATTRIBUTE_NUM 256
 
 extern const char *vendorattributeargs[];
diff --git a/sm5/smartd.c b/sm5/smartd.c
index 51fb8ef639798032a606dbf7013c82f584ce86f4..764bd990739d1ba4cb08836ea0a9983197c17858 100644
--- a/sm5/smartd.c
+++ b/sm5/smartd.c
@@ -98,7 +98,7 @@ int getdomainname(char *, int); /* no declaration in header files! */
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, 
                   *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid;
 
-static const char *filenameandversion="$Id: smartd.c,v 1.316 2004/04/14 13:27:20 chrfranke Exp $";
+static const char *filenameandversion="$Id: smartd.c,v 1.317 2004/04/17 10:44:47 ballen4705 Exp $";
 #ifdef NEED_SOLARIS_ATA_CODE
 extern const char *os_solaris_ata_s_cvsid;
 #endif
@@ -109,7 +109,7 @@ extern const char *syslog_win32_c_cvsid;
 extern const char *int64_vc6_c_cvsid;
 #endif
 #endif
-const char *smartd_c_cvsid="$Id: smartd.c,v 1.316 2004/04/14 13:27:20 chrfranke Exp $" 
+const char *smartd_c_cvsid="$Id: smartd.c,v 1.317 2004/04/17 10:44:47 ballen4705 Exp $" 
 ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID
 KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID
 #ifdef SYSLOG_H_CVSID
@@ -1461,7 +1461,7 @@ static int SCSIDeviceScan(cfgfile *cfg) {
   // smart if it is off). This may change to be the same as the ATA side.
   if (!scsi_IsExceptionControlEnabled(&iec)) {
     PrintOut(LOG_INFO, "Device: %s, IE (SMART) not enabled, skip device\n"
-                        "Try 'smartctl -s on %s' to turn on SMART features\n", 
+	               "Try 'smartctl -s on %s' to turn on SMART features\n", 
                         device, device);
     CloseDevice(fd, device);
     return 3;
diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp
index 97b62d4fcdcad96155a3a54620732bdf3409a850..0955750883d0175d5879652a0c218a85aff91d7d 100644
--- a/sm5/smartd.cpp
+++ b/sm5/smartd.cpp
@@ -98,7 +98,7 @@ int getdomainname(char *, int); /* no declaration in header files! */
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, 
                   *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid;
 
-static const char *filenameandversion="$Id: smartd.cpp,v 1.316 2004/04/14 13:27:20 chrfranke Exp $";
+static const char *filenameandversion="$Id: smartd.cpp,v 1.317 2004/04/17 10:44:47 ballen4705 Exp $";
 #ifdef NEED_SOLARIS_ATA_CODE
 extern const char *os_solaris_ata_s_cvsid;
 #endif
@@ -109,7 +109,7 @@ extern const char *syslog_win32_c_cvsid;
 extern const char *int64_vc6_c_cvsid;
 #endif
 #endif
-const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.316 2004/04/14 13:27:20 chrfranke Exp $" 
+const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.317 2004/04/17 10:44:47 ballen4705 Exp $" 
 ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID
 KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID
 #ifdef SYSLOG_H_CVSID
@@ -1461,7 +1461,7 @@ static int SCSIDeviceScan(cfgfile *cfg) {
   // smart if it is off). This may change to be the same as the ATA side.
   if (!scsi_IsExceptionControlEnabled(&iec)) {
     PrintOut(LOG_INFO, "Device: %s, IE (SMART) not enabled, skip device\n"
-                        "Try 'smartctl -s on %s' to turn on SMART features\n", 
+	               "Try 'smartctl -s on %s' to turn on SMART features\n", 
                         device, device);
     CloseDevice(fd, device);
     return 3;