diff --git a/sm5/atacmds.c b/sm5/atacmds.c
index 3e5693be88f5e9f9011c30df40947851e4406708..7189e8ecd8c5e59d2ca8e8b2071cd78bb0c9372f 100644
--- a/sm5/atacmds.c
+++ b/sm5/atacmds.c
@@ -1,4 +1,4 @@
-//  $Id: atacmds.c,v 1.8 2002/10/15 14:24:26 ballen4705 Exp $
+//  $Id: atacmds.c,v 1.9 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * atacmds.c
  * 
@@ -27,11 +27,15 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <syslog.h>
 #include "atacmds.h"
 
-
-// These Drive Identity tables are taken from hdparm 5.2. That's the
-// "Gold Standard"
+// These Drive Identity tables are taken from hdparm 5.2, and are also
+// given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
+// that SMART was first added into the ATA/ATAPI-3 Standard with
+// Revision 3 of the document, July 25, 1995.  Look at the "Document
+// Status" revision commands at the beginning of
+// http://www.t13.org/project/d2008r6.pdf to see this.
 #define NOVAL_0			0x0000
 #define NOVAL_1			0xffff
 /* word 81: minor version number */
@@ -45,10 +49,10 @@ const char *minor_str[] = {			/* word 81 value: */
   "ATA-2 X3T10 948D prior to revision 2k",	/* 0x0005	*/
   "ATA-3 X3T10 2008D revision 1",		/* 0x0006	*/
   "ATA-2 X3T10 948D revision 2k",		/* 0x0007	*/
-  "ATA-3 X3T10 2008D revision 0",		/* 0x0008	*/
+  "ATA-3 X3T10 2008D revision 0",		/* 0x0008	*/ /* SMART NOT INCLUDED */
   "ATA-2 X3T10 948D revision 3",		/* 0x0009	*/
   "ATA-3 published, ANSI X3.298-199x",		/* 0x000a	*/
-  "ATA-3 X3T10 2008D revision 6",		/* 0x000b	*/
+  "ATA-3 X3T10 2008D revision 6",		/* 0x000b	*/ /* 1st VERSION WITH SMART */
   "ATA-3 X3T13 2008D revision 7 and 7a",	/* 0x000c	*/
   "ATA/ATAPI-4 X3T13 1153D revision 6",		/* 0x000d	*/
   "ATA/ATAPI-4 T13 1153D revision 13",		/* 0x000e	*/
@@ -71,7 +75,7 @@ const char *minor_str[] = {			/* word 81 value: */
   "reserved"					/* 0x001f-0xfffe*/
 };
 
-const char actual_ver[] = { 
+const int actual_ver[] = { 
   /* word 81 value: */
   0,		/* 0x0000	WARNING: 	*/
   1,		/* 0x0001	WARNING: 	*/
@@ -81,7 +85,7 @@ const char actual_ver[] = {
   2,		/* 0x0005	WARNING:   corresponds 		*/
   3,		/* 0x0006	WARNING:   *exactly*		*/
   2,		/* 0x0007	WARNING:   to the ATA/		*/
-  3,		/* 0x0008	WARNING:   ATAPI version	*/
+  -3, /*<== */	/* 0x0008	WARNING:   ATAPI version	*/
   2,		/* 0x0009	WARNING:   listed in	 	*/
   3,		/* 0x000a	WARNING:   the 		 	*/
   3,		/* 0x000b	WARNING:   minor_str 		*/
@@ -106,19 +110,72 @@ const char actual_ver[] = {
 };
 
 
+// Used to warn users about invalid checksums.  However we will not
+// abort on invalid checksums.
+void checksumwarning(const char *string){
+  printf("Warning! %s error: invalid checksum.\n",string);
+  fprintf(stderr,"Warning! %s error: invalid checksum.\n",string);
+  syslog(LOG_INFO,"Warning! %s error: invalid checksum.\n",string);
+  return;
+}
 
-int ataReadHDIdentity ( int device, struct hd_driveid *buf)
-{
-   if (ioctl ( device , HDIO_GET_IDENTITY, buf ) != 0)
-   { 
-       perror ("ATA GET HD Failed");
-       return -1; 
-   }
-
-   return 0;
+// We no longer use this function, because the IOCTL appears to return
+// only the drive identity at the time that the system was booted
+// (perhaps from the BIOS.  It doesn't correctly reflect the current
+// state information, and for example the checksum is usually
+// wrong. The replacement function follows afterwards
+#if (0)
+int ataReadHDIdentity ( int device, struct hd_driveid *buf){
+  if (ioctl(device, HDIO_GET_IDENTITY, buf )){ 
+    perror ("ATA GET HD Failed");
+    return -1; 
+  }
+  return 0;
 }
+#endif
+
 
+// Reads current Device Identity info (512 bytes) into buf
+int ataReadHDIdentity (int device, struct hd_driveid *buf){
+  unsigned char parms[HDIO_DRIVE_CMD_HDR_SIZE+sizeof(*buf)]=
+    {WIN_IDENTIFY, 0, 0, 1,};
+
+  if (ioctl(device ,HDIO_DRIVE_CMD,parms)){ 
+    perror ("ATA GET HD Identity Failed");
+    return -1; 
+  }
+  
+  // copy data into driveid structure
+  memcpy(buf,parms+HDIO_DRIVE_CMD_HDR_SIZE,sizeof(*buf));
+  
+  // If driveid structure contains a checksum, then compute it, and
+  // issue a warning message if something is wrong.  I prefer this
+  // rather than simply exiting at this point, though that is another
+  // option.
+
+  // Note -- the declaration that appears in
+  // /usr/include/linux/hdregs.h: short words160_255[95], is WRONG.
+  // It should say: short words160_255[96]. I have written to Andre
+  // Hedrick about this on Oct 17 2002.  Please remove this comment
+  // once the fix has made it into the stock kernel tree.
+  if ((buf->words160_255[95] & 0x00ff) == 0x00a5){
+    unsigned char cksum=0;
+    int i;
+
+    for (i=0;i<sizeof(*buf);i++)
+      cksum+=parms[i+HDIO_DRIVE_CMD_HDR_SIZE];
+    
+    if (cksum)
+      checksumwarning("Drive Identity Structure");
+  }
+ 
+ return 0;
+}
 
+// Returns ATA version as an integer, and a pointer to a string
+// describing which revision.  Note that Revision 0 of ATA-3 does NOT
+// support SMART.  For this one case we return -3 rather than +3 as
+// the version number.  See notes above.
 int ataVersionInfo (const char** description, struct hd_driveid drive){
   unsigned short major,minor;
   int i,atavalue=0;
@@ -157,25 +214,55 @@ int ataVersionInfo (const char** description, struct hd_driveid drive){
   return atavalue;
 }
 
+// returns 1 if SMART supported, 0 if not supported or can't tell
+int ataSmartSupport(struct hd_driveid drive){
+  unsigned short word82,word83;
 
-int ataSmartSupport ( struct hd_driveid drive){
+  // get correct bits of IDENTIFY DEVICE structure
 #ifdef __NEW_HD_DRIVE_ID
-  if (drive.command_set_1 & 0x0001)
+  word82=drive.command_set_1;
+  word83=drive.command_set_2;
 #else
-  if (drive.command_sets & 0x0001)
+  word82=drive.command_sets;
+  word83=drive.word83;
 #endif
-    return 1; /* drive supports S.M.A.R.T. and is disabled */
-  return 0;
+
+  // Note this does not work for ATA3 < Revision 6, when word82 and word83 were added
+  // we should check for ATA3 Rev 0 in minor identity code...  
+  return (word83 & 0x0001<<14) && !(word83 & 0x0001<<15) && (word82 & 0x0001);
 }
 
-int ataReadSmartValues (int device, struct ata_smart_values *data){	
+// returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
+int ataIsSmartEnabled(struct hd_driveid drive){
+    unsigned short word85,word87;
+
+  // Get correct bits of IDENTIFY DRIVE structure
+#ifdef __NEW_HD_DRIVE_ID
+  word85=drive.cfs_enable_1;
+  word87=drive.csf_default;
+#else
+  word85=drive.word85;
+  word87=drive.word87;
+#endif
+  
+  if ((word87 & 0x0001<<14) && !(word87 & 0x0001<<15))
+    // word85 contains valid information, so
+    return word85 & 0x0001;
+  
+  // Since we can't rely word85, we don't know if SMART is enabled.
+  return -1;
+}
+
+
+// Reads SMART attributes into *data
+int ataReadSmartValues(int device, struct ata_smart_values *data){	
   int i;
   unsigned char chksum=0;
   unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE]= 
     {WIN_SMART, 0, SMART_READ_VALUES, 1};
   
   if (ioctl(device,HDIO_DRIVE_CMD,buf)){
-    perror ("Smart Values Read failed");
+    perror ("SMART Values Read failed");
     return -1;
   }
   
@@ -184,10 +271,8 @@ int ataReadSmartValues (int device, struct ata_smart_values *data){
     chksum+=buf[i+HDIO_DRIVE_CMD_HDR_SIZE];
   
   // verify that checksum vanishes
-  if (chksum){
-    perror ("Smart Read Failed, Checksum error!");
-    return -1;
-  }	
+  if (chksum)
+    checksumwarning("SMART Data Structure");
   
   // copy data and return
   memcpy(data,buf+HDIO_DRIVE_CMD_HDR_SIZE,ATA_SMART_SEC_SIZE);
@@ -195,293 +280,321 @@ int ataReadSmartValues (int device, struct ata_smart_values *data){
 }
 
 
-int ataReadSelfTestLog (int device, struct ata_smart_selftestlog *data)
-{	
-   int i;
-   unsigned char chksum=0;	
-   unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE + 
-                      ATA_SMART_SEC_SIZE] = 
-                      { WIN_SMART, 0x06, SMART_READ_LOG_SECTOR, 1};
-
-   if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
-   {
-       perror ("Smart Error Log Read failed");
-       return -1;
-   }
-   
-   // compute checksum
-   for (i=0;i<ATA_SMART_SEC_SIZE;i++)
-     chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
-
-   if (chksum){
-     fprintf(stderr,"Smart Self Test Log Checksum Incorrect!\n");
-     return -1;
-   }
-
-   memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
-
-   return 0;
+// Reads the Self Test Log (log #6)
+int ataReadSelfTestLog (int device, struct ata_smart_selftestlog *data){	
+  int i;
+  unsigned char chksum=0;	
+  unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE] = 
+    {WIN_SMART, 0x06, SMART_READ_LOG_SECTOR, 1,};
+  
+  // get data from device
+  if (ioctl(device, HDIO_DRIVE_CMD, buf)){
+    perror ("SMART Error Log Read failed");
+    return -1;
+  }
+  
+  // compute its checksum, and issue a warning if needed
+  for (i=0;i<ATA_SMART_SEC_SIZE;i++)
+    chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
+  if (chksum)
+    checksumwarning("SMART Self-Test Log");
+  
+  // copy data back to the user and return
+  memcpy(data,buf+HDIO_DRIVE_CMD_HDR_SIZE, ATA_SMART_SEC_SIZE); 
+  return 0;
 }
 
-
-int ataReadErrorLog (int device, struct ata_smart_errorlog *data)
-{	
-   int i;
-   unsigned char chksum=0;	
-   unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE + 
-                      ATA_SMART_SEC_SIZE] = 
-                      { WIN_SMART, 0x01, SMART_READ_LOG_SECTOR, 1};
-
-   if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
-   {
-       perror ("Smart Error Log Read failed");
-       return -1;
-   }
-
-   // compute checksum
-   for (i=0;i<ATA_SMART_SEC_SIZE;i++)
-     chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
-
-   if (chksum){
-     fprintf(stderr,"Smart Error Log Checksum Incorrect!\n");
-     return -1;
-   }
-   memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
-
-   return 0;
+// Reads the Error Log (log #1)
+int ataReadErrorLog (int device, struct ata_smart_errorlog *data){	
+  int i;
+  unsigned char chksum=0;	
+  unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE] = 
+    {WIN_SMART, 0x01, SMART_READ_LOG_SECTOR, 1,};
+  
+  // get data from device
+  if (ioctl(device,HDIO_DRIVE_CMD,&buf)) {
+    perror ("SMART Error Log Read failed");
+    return -1;
+  }
+  
+  // compute checksum and issue warning if needed
+  for (i=0;i<ATA_SMART_SEC_SIZE;i++)
+    chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
+  if (chksum)
+    checksumwarning("SMART Error Log");
+  
+  //copy data back to user and return
+  memcpy(data, buf+HDIO_DRIVE_CMD_HDR_SIZE, ATA_SMART_SEC_SIZE);
+  return 0;
 }
 
 
-int ataReadSmartThresholds ( int device, struct ata_smart_thresholds *data)
-{	
-   unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE + 
-                      ATA_SMART_SEC_SIZE] = 
-                      { WIN_SMART, 1, SMART_READ_THRESHOLDS, 1};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
-   {
-       perror ("Smart Thresholds Read failed");
-       return -1;
-   }
-
-   memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
-
-   return 0;
+// This routine is marked as "Obsolete" in the ATA-5 spec, but it's
+// very important for us.  Together with the SMART READ DATA command
+// above, it's the only way for us to find out if the SMART status is
+// good or not.  Hopefully this will get fixed -- I will find a way to
+// get SMART Status directly.
+int ataReadSmartThresholds ( int device, struct ata_smart_thresholds *data){
+  int i;
+  unsigned char chksum=0;	
+  unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE] = 
+    {WIN_SMART, 1, SMART_READ_THRESHOLDS, 1,};
+  
+  // get data from device
+  if (ioctl(device ,HDIO_DRIVE_CMD, buf)){
+    perror ("SMART Thresholds Read failed");
+    return -1;
+  }
+  
+  // compute checksum and issue warning if needed
+  for (i=0;i<ATA_SMART_SEC_SIZE;i++)
+    chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
+  if (chksum)
+    checksumwarning("SMART Attribute Thresholds");
+  
+  // copy data back to user and return
+  memcpy(data,buf+HDIO_DRIVE_CMD_HDR_SIZE, ATA_SMART_SEC_SIZE);
+  return 0;
 }
 
-int ataSetSmartThresholds ( int device, struct ata_smart_thresholds *data)
-{	
-   unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE + 
-		           ATA_SMART_SEC_SIZE] = 
-                           { WIN_SMART, 1, 0xD7, 1};
-	
-   memcpy( &buf[HDIO_DRIVE_CMD_HDR_SIZE],  data , ATA_SMART_SEC_SIZE);
-
-   if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *)  &buf ) != 0)
-   {
-       perror ("Smart Thresholds Read failed");
-       return -1;
-   }
 
-   return 0;
+// This routine is not currently in use, and it's been marked as
+// "Obsolete" in the ANSI ATA-5 spec.  So it should probably be left
+// alone and unused.
+int ataSetSmartThresholds ( int device, struct ata_smart_thresholds *data){	
+  unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE] = 
+    {WIN_SMART, 1, 0xD7, 1,};
+  
+  memcpy(buf+HDIO_DRIVE_CMD_HDR_SIZE, data, ATA_SMART_SEC_SIZE);
+  
+  if (ioctl(device, HDIO_DRIVE_CMD, buf)){
+    perror ("SMART Thresholds Read failed");
+    return -1;
+  }
+  
+  return 0;
 }
 
 
-int ataEnableSmart (int device )
-{	
+int ataEnableSmart (int device ){	
+  unsigned char parms[4] = {WIN_SMART, 1, SMART_ENABLE, 0};
+  
+  if (ioctl ( device , HDIO_DRIVE_CMD,  &parms )){
+    perror ("SMART Enable failed");
+    return -1;
+  }
+  
+  return 0;
+}
 
-   unsigned char parms[4] = { WIN_SMART, 1, SMART_ENABLE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Enable failed");
-      return -1;
-   }
-	
-   return 0;
- }
-
-
-int ataDisableSmart (int device )
-{	
-	
-   unsigned char parms[4] = { WIN_SMART, 1, SMART_DISABLE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Disable failed");
-      return -1;
-   }
 
-   return 0;
+int ataDisableSmart (int device ){	
+  unsigned char parms[4] = {WIN_SMART, 1, SMART_DISABLE, 0};
+  
+  if (ioctl(device , HDIO_DRIVE_CMD, parms )){
+    perror ("SMART Disable failed");
+    return -1;
+  }
+  
+  return 0;
 }
 
 int ataEnableAutoSave(int device){
-   unsigned char parms[4] = { WIN_SMART, 241, SMART_AUTOSAVE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Enable Auto-save failed");
-      return -1;
-   }
-	
-   return 0;
-};
+  unsigned char parms[4] = {WIN_SMART, 241, SMART_AUTOSAVE, 0};
+  
+  if (ioctl(device , HDIO_DRIVE_CMD,  parms )){
+    perror ("SMART Enable Auto-save failed");
+    return -1;
+  }
+  
+  return 0;
+}
 
 int ataDisableAutoSave(int device){
-   unsigned char parms[4] = { WIN_SMART, 0, SMART_AUTOSAVE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Disable Auto-save failed");
-      return -1;
-   }
-	
-   return 0;
-};
-
-int ataEnableAutoOffline (int device )
-{	
-
-   /* timer hard coded to 4 hours */
-   unsigned char parms[4] = { WIN_SMART, 248, SMART_AUTO_OFFLINE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-       perror ("Smart Enable Automatic Offline failed");
-       return -1;
-   }
-
-   return 0;
+  unsigned char parms[4] = {WIN_SMART, 0, SMART_AUTOSAVE, 0};
+  
+  if (ioctl(device, HDIO_DRIVE_CMD, parms)){
+    perror ("SMART Disable Auto-save failed");
+    return -1;
+  }
+  
+  return 0;
 }
 
+// Note that in the ATA-5 standard this command is marked "OBSOLETE"
+int ataEnableAutoOffline (int device ){	
+  
+  /* timer hard coded to 4 hours */
+  unsigned char parms[4] = {WIN_SMART, 248, SMART_AUTO_OFFLINE, 0};
+  
+  if (ioctl(device , HDIO_DRIVE_CMD, parms)){
+    perror ("SMART Enable Automatic Offline failed");
+    return -1;
+  }
+  
+  return 0;
+}
 
-int ataDisableAutoOffline (int device )
-{	
-   unsigned char parms[4] = { WIN_SMART, 0, SMART_AUTO_OFFLINE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Disable Automatic Offline failed");
-      return -1;
-   }
-
-   return 0;
+// Another Obsolete Command!
+int ataDisableAutoOffline (int device ){	
+  unsigned char parms[4] = {WIN_SMART, 0, SMART_AUTO_OFFLINE, 0};
+  
+  if (ioctl(device , HDIO_DRIVE_CMD, parms)){
+    perror ("SMART Disable Automatic Offline failed");
+    return -1;
+  }
+  
+  return 0;
 }
 
 
 // Not being used correctly.  Must examine the CL and CH registers to
-// see what the smart status was.  How to fix this?  I don't know...
+// see what the smart status was.  Look at ataSmartStatus2()
 int ataSmartStatus (int device ){	
-   unsigned char parms[4] = { WIN_SMART, 0, SMART_STATUS, 0};
+   unsigned char parms[4] = {WIN_SMART, 0, SMART_STATUS, 0};
 
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms))
-      return -1;
-   return 0;
-}
-
-
-
-int ataSmartTest (int device, int testtype)
-{	
-   unsigned char parms[4] = { WIN_SMART, testtype, 
-                    SMART_IMMEDIATE_OFFLINE, 0};
-   
-   if (ioctl ( device , HDIO_DRIVE_CMD, &parms) != 0)
-   {
-       perror ("Smart Offline failed");
-       return -1;
+   if (ioctl(device, HDIO_DRIVE_CMD, parms)){
+     perror("Return SMART Status failed");
+     return -1;
    }
-
-   printf("Completed Off-line command\n");
-	
    return 0;
 }
 
-
-int ataSmartOfflineTest (int device)
-{	
-   return ataSmartTest( device, OFFLINE_FULL_SCAN  );
+// If SMART is enabled, supported, and working, then this call is
+// guaranteed to return 1, else zero.  Silent inverse of
+// ataSmartStatus()
+int ataDoesSmartWork(int device){	
+   unsigned char parms[4] = {WIN_SMART, 0, SMART_STATUS, 0};
+   return !ioctl(device, HDIO_DRIVE_CMD, parms);
 }
 
-int ataSmartShortSelfTest (int device)
-{	
-   return ataSmartTest( device, SHORT_SELF_TEST  );
-}
 
-int ataSmartExtendSelfTest (int device)
-{	
-   return ataSmartTest( device, EXTEND_SELF_TEST  );
-}
-
-int ataSmartShortCapSelfTest (int device)
-{	
-   return ataSmartTest( device, SHORT_CAPTIVE_SELF_TEST );
+// This function needs to be properly tested and debugged.  I am not
+// yet sure if this is right; have asked Andre for help.  May need to
+// use IDE_DRIVE_TASK.  Does CONFIG_IDE_TASKFILE_IO need to be
+// configured into the kernel?
+int ataSmartStatus2(int device){
+  unsigned char normal_cyl_lo=0x4f, normal_cyl_hi=0xc2;
+  unsigned char failed_cyl_lo=0xf4, failed_cyl_hi=0x2c;
+
+  unsigned char parms[HDIO_DRIVE_TASK_HDR_SIZE]=
+    {WIN_SMART,    // CMD
+     SMART_STATUS, // FR
+     0,            // NS
+     0,            // SC
+     0,            // CL
+     0,            // CH
+     0             // SEL -- Andre, is this right?? Or should it be 1?
+    };
+
+  // load CL and CH values
+  parms[4]=normal_cyl_lo;
+  parms[5]=normal_cyl_hi;
+
+  if (ioctl(device,HDIO_DRIVE_TASK,&parms)){
+    perror ("SMART Status command failed.");
+    return -1;
+  }
+  
+  // Cyl low and Cyl high unchanged means "Good SMART status"
+  if (parms[4]==normal_cyl_lo && parms[5]==normal_cyl_hi)
+    return 0;
+
+  // These values mean "Bad SMART status"
+  if (parms[4]==failed_cyl_lo && parms[5]==failed_cyl_hi)
+    return 1;
+
+  // We haven't gotten output that makes sense; print out some debugging info
+  perror("SMART Status returned register values that don't make sense:\n");
+  printf("CMD=0x%02x\n",parms[0]);
+  printf("FR =0x%02x\n",parms[1]);
+  printf("NS =0x%02x\n",parms[2]);
+  printf("SC =0x%02x\n",parms[3]);
+  printf("CL =0x%02x\n",parms[4]);
+  printf("CH =0x%02x\n",parms[5]);
+  printf("SEL=0x%02x\n",parms[6]);
+
+  return -1;
 }
 
-int ataSmartExtendCapSelfTest (int device)
-{
-   return ataSmartTest( device, EXTEND_CAPTIVE_SELF_TEST );
+// This is the way to execute ALL tests: offline, short self-test,
+// extended self test, with and without captive mode, etc.
+int ataSmartTest(int device, int testtype){	
+  unsigned char parms[4] = {WIN_SMART, 0, SMART_IMMEDIATE_OFFLINE};
+  char cmdmsg[128],*type,*captive;
+
+  parms[1]=testtype;
+
+  // Set up strings that describe the type of test
+  if (testtype==SHORT_CAPTIVE_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST)
+    captive="captive";
+  else
+    captive="off-line";
+
+  if (testtype==OFFLINE_FULL_SCAN)
+    type="off-line";
+  else  if (testtype==SHORT_SELF_TEST || testtype==SHORT_CAPTIVE_SELF_TEST)
+    type="Short self-test";
+  else 
+    type="Extended self-test";
+
+  //  Print ouf message that we are sending the command to test
+  if (testtype==ABORT_SELF_TEST)
+    sprintf(cmdmsg,"Abort SMART off-line mode self-test routine");
+  else
+    sprintf(cmdmsg,"Execute SMART %s routine immediately in %s mode",type,captive);
+  printf("Sending command: \"%s\".\n",cmdmsg);
+
+  // Now send the command to test
+  if (ioctl(device , HDIO_DRIVE_CMD, parms)){
+    char errormsg[128];
+    sprintf(errormsg,"Command \"%s\" failed.\n\n",cmdmsg); 
+    perror (errormsg);
+    return -1;
+  }
+  
+  // Since the command succeeded, tell user
+  if (testtype==ABORT_SELF_TEST)
+    printf("Self-testing aborted!\n");
+  else
+    printf("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg);
+  return 0;
 }
 
 
-int ataSmartSelfTestAbort (int device)
-{
-   return ataSmartTest( device, 127 );
-}
-
 /* Test Time Functions */
-
-int isOfflineTestTime ( struct ata_smart_values data)
-{
-   return (int) data.total_time_to_complete_off_line;
-}
-
-
-int isShortSelfTestTime ( struct ata_smart_values data)
-{
-   return (int) data.short_test_completion_time;
-}
-
-
-int isExtendedSelfTestTime ( struct ata_smart_values data)
-{
-   return (int) data.extend_test_completion_time;
+int TestTime(struct ata_smart_values data,int testtype){
+  switch (testtype){
+  case OFFLINE_FULL_SCAN:
+    return (int) data.total_time_to_complete_off_line;
+  case SHORT_SELF_TEST:
+  case SHORT_CAPTIVE_SELF_TEST:
+    return (int) data.short_test_completion_time;
+  case EXTEND_SELF_TEST:
+  case EXTEND_CAPTIVE_SELF_TEST:
+    return (int) data.extend_test_completion_time;
+  default:
+    return 0;
+  }
 }
 
 
-int isSmartErrorLogCapable ( struct ata_smart_values data)
-{
+int isSmartErrorLogCapable ( struct ata_smart_values data){
    return data.errorlog_capability & 0x01;
 }
-
-
-int isSupportExecuteOfflineImmediate ( struct ata_smart_values data)
-{
+int isSupportExecuteOfflineImmediate ( struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x01;
 }
-
-
-int isSupportAutomaticTimer ( struct ata_smart_values data)
-{
+int isSupportAutomaticTimer ( struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x02;
 }
-
-
-int isSupportOfflineAbort ( struct ata_smart_values data)
-{
+int isSupportOfflineAbort ( struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x04;
 }
-
-
-int isSupportOfflineSurfaceScan ( struct ata_smart_values data)
-{
+int isSupportOfflineSurfaceScan ( struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x08;
 }
-
-
-int isSupportSelfTest (struct ata_smart_values data)
-{
+int isSupportSelfTest (struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x10;
 }
 
diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index 16f5cf9bfb70736cbf7e49a31da1da1dc4180ea5..45e9a820dda258e1df780553c72f07c77c34724b 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -1,4 +1,4 @@
-//  $Id: atacmds.cpp,v 1.8 2002/10/15 14:24:26 ballen4705 Exp $
+//  $Id: atacmds.cpp,v 1.9 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * atacmds.c
  * 
@@ -27,11 +27,15 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <syslog.h>
 #include "atacmds.h"
 
-
-// These Drive Identity tables are taken from hdparm 5.2. That's the
-// "Gold Standard"
+// These Drive Identity tables are taken from hdparm 5.2, and are also
+// given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
+// that SMART was first added into the ATA/ATAPI-3 Standard with
+// Revision 3 of the document, July 25, 1995.  Look at the "Document
+// Status" revision commands at the beginning of
+// http://www.t13.org/project/d2008r6.pdf to see this.
 #define NOVAL_0			0x0000
 #define NOVAL_1			0xffff
 /* word 81: minor version number */
@@ -45,10 +49,10 @@ const char *minor_str[] = {			/* word 81 value: */
   "ATA-2 X3T10 948D prior to revision 2k",	/* 0x0005	*/
   "ATA-3 X3T10 2008D revision 1",		/* 0x0006	*/
   "ATA-2 X3T10 948D revision 2k",		/* 0x0007	*/
-  "ATA-3 X3T10 2008D revision 0",		/* 0x0008	*/
+  "ATA-3 X3T10 2008D revision 0",		/* 0x0008	*/ /* SMART NOT INCLUDED */
   "ATA-2 X3T10 948D revision 3",		/* 0x0009	*/
   "ATA-3 published, ANSI X3.298-199x",		/* 0x000a	*/
-  "ATA-3 X3T10 2008D revision 6",		/* 0x000b	*/
+  "ATA-3 X3T10 2008D revision 6",		/* 0x000b	*/ /* 1st VERSION WITH SMART */
   "ATA-3 X3T13 2008D revision 7 and 7a",	/* 0x000c	*/
   "ATA/ATAPI-4 X3T13 1153D revision 6",		/* 0x000d	*/
   "ATA/ATAPI-4 T13 1153D revision 13",		/* 0x000e	*/
@@ -71,7 +75,7 @@ const char *minor_str[] = {			/* word 81 value: */
   "reserved"					/* 0x001f-0xfffe*/
 };
 
-const char actual_ver[] = { 
+const int actual_ver[] = { 
   /* word 81 value: */
   0,		/* 0x0000	WARNING: 	*/
   1,		/* 0x0001	WARNING: 	*/
@@ -81,7 +85,7 @@ const char actual_ver[] = {
   2,		/* 0x0005	WARNING:   corresponds 		*/
   3,		/* 0x0006	WARNING:   *exactly*		*/
   2,		/* 0x0007	WARNING:   to the ATA/		*/
-  3,		/* 0x0008	WARNING:   ATAPI version	*/
+  -3, /*<== */	/* 0x0008	WARNING:   ATAPI version	*/
   2,		/* 0x0009	WARNING:   listed in	 	*/
   3,		/* 0x000a	WARNING:   the 		 	*/
   3,		/* 0x000b	WARNING:   minor_str 		*/
@@ -106,19 +110,72 @@ const char actual_ver[] = {
 };
 
 
+// Used to warn users about invalid checksums.  However we will not
+// abort on invalid checksums.
+void checksumwarning(const char *string){
+  printf("Warning! %s error: invalid checksum.\n",string);
+  fprintf(stderr,"Warning! %s error: invalid checksum.\n",string);
+  syslog(LOG_INFO,"Warning! %s error: invalid checksum.\n",string);
+  return;
+}
 
-int ataReadHDIdentity ( int device, struct hd_driveid *buf)
-{
-   if (ioctl ( device , HDIO_GET_IDENTITY, buf ) != 0)
-   { 
-       perror ("ATA GET HD Failed");
-       return -1; 
-   }
-
-   return 0;
+// We no longer use this function, because the IOCTL appears to return
+// only the drive identity at the time that the system was booted
+// (perhaps from the BIOS.  It doesn't correctly reflect the current
+// state information, and for example the checksum is usually
+// wrong. The replacement function follows afterwards
+#if (0)
+int ataReadHDIdentity ( int device, struct hd_driveid *buf){
+  if (ioctl(device, HDIO_GET_IDENTITY, buf )){ 
+    perror ("ATA GET HD Failed");
+    return -1; 
+  }
+  return 0;
 }
+#endif
+
 
+// Reads current Device Identity info (512 bytes) into buf
+int ataReadHDIdentity (int device, struct hd_driveid *buf){
+  unsigned char parms[HDIO_DRIVE_CMD_HDR_SIZE+sizeof(*buf)]=
+    {WIN_IDENTIFY, 0, 0, 1,};
+
+  if (ioctl(device ,HDIO_DRIVE_CMD,parms)){ 
+    perror ("ATA GET HD Identity Failed");
+    return -1; 
+  }
+  
+  // copy data into driveid structure
+  memcpy(buf,parms+HDIO_DRIVE_CMD_HDR_SIZE,sizeof(*buf));
+  
+  // If driveid structure contains a checksum, then compute it, and
+  // issue a warning message if something is wrong.  I prefer this
+  // rather than simply exiting at this point, though that is another
+  // option.
+
+  // Note -- the declaration that appears in
+  // /usr/include/linux/hdregs.h: short words160_255[95], is WRONG.
+  // It should say: short words160_255[96]. I have written to Andre
+  // Hedrick about this on Oct 17 2002.  Please remove this comment
+  // once the fix has made it into the stock kernel tree.
+  if ((buf->words160_255[95] & 0x00ff) == 0x00a5){
+    unsigned char cksum=0;
+    int i;
+
+    for (i=0;i<sizeof(*buf);i++)
+      cksum+=parms[i+HDIO_DRIVE_CMD_HDR_SIZE];
+    
+    if (cksum)
+      checksumwarning("Drive Identity Structure");
+  }
+ 
+ return 0;
+}
 
+// Returns ATA version as an integer, and a pointer to a string
+// describing which revision.  Note that Revision 0 of ATA-3 does NOT
+// support SMART.  For this one case we return -3 rather than +3 as
+// the version number.  See notes above.
 int ataVersionInfo (const char** description, struct hd_driveid drive){
   unsigned short major,minor;
   int i,atavalue=0;
@@ -157,25 +214,55 @@ int ataVersionInfo (const char** description, struct hd_driveid drive){
   return atavalue;
 }
 
+// returns 1 if SMART supported, 0 if not supported or can't tell
+int ataSmartSupport(struct hd_driveid drive){
+  unsigned short word82,word83;
 
-int ataSmartSupport ( struct hd_driveid drive){
+  // get correct bits of IDENTIFY DEVICE structure
 #ifdef __NEW_HD_DRIVE_ID
-  if (drive.command_set_1 & 0x0001)
+  word82=drive.command_set_1;
+  word83=drive.command_set_2;
 #else
-  if (drive.command_sets & 0x0001)
+  word82=drive.command_sets;
+  word83=drive.word83;
 #endif
-    return 1; /* drive supports S.M.A.R.T. and is disabled */
-  return 0;
+
+  // Note this does not work for ATA3 < Revision 6, when word82 and word83 were added
+  // we should check for ATA3 Rev 0 in minor identity code...  
+  return (word83 & 0x0001<<14) && !(word83 & 0x0001<<15) && (word82 & 0x0001);
 }
 
-int ataReadSmartValues (int device, struct ata_smart_values *data){	
+// returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
+int ataIsSmartEnabled(struct hd_driveid drive){
+    unsigned short word85,word87;
+
+  // Get correct bits of IDENTIFY DRIVE structure
+#ifdef __NEW_HD_DRIVE_ID
+  word85=drive.cfs_enable_1;
+  word87=drive.csf_default;
+#else
+  word85=drive.word85;
+  word87=drive.word87;
+#endif
+  
+  if ((word87 & 0x0001<<14) && !(word87 & 0x0001<<15))
+    // word85 contains valid information, so
+    return word85 & 0x0001;
+  
+  // Since we can't rely word85, we don't know if SMART is enabled.
+  return -1;
+}
+
+
+// Reads SMART attributes into *data
+int ataReadSmartValues(int device, struct ata_smart_values *data){	
   int i;
   unsigned char chksum=0;
   unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE]= 
     {WIN_SMART, 0, SMART_READ_VALUES, 1};
   
   if (ioctl(device,HDIO_DRIVE_CMD,buf)){
-    perror ("Smart Values Read failed");
+    perror ("SMART Values Read failed");
     return -1;
   }
   
@@ -184,10 +271,8 @@ int ataReadSmartValues (int device, struct ata_smart_values *data){
     chksum+=buf[i+HDIO_DRIVE_CMD_HDR_SIZE];
   
   // verify that checksum vanishes
-  if (chksum){
-    perror ("Smart Read Failed, Checksum error!");
-    return -1;
-  }	
+  if (chksum)
+    checksumwarning("SMART Data Structure");
   
   // copy data and return
   memcpy(data,buf+HDIO_DRIVE_CMD_HDR_SIZE,ATA_SMART_SEC_SIZE);
@@ -195,293 +280,321 @@ int ataReadSmartValues (int device, struct ata_smart_values *data){
 }
 
 
-int ataReadSelfTestLog (int device, struct ata_smart_selftestlog *data)
-{	
-   int i;
-   unsigned char chksum=0;	
-   unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE + 
-                      ATA_SMART_SEC_SIZE] = 
-                      { WIN_SMART, 0x06, SMART_READ_LOG_SECTOR, 1};
-
-   if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
-   {
-       perror ("Smart Error Log Read failed");
-       return -1;
-   }
-   
-   // compute checksum
-   for (i=0;i<ATA_SMART_SEC_SIZE;i++)
-     chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
-
-   if (chksum){
-     fprintf(stderr,"Smart Self Test Log Checksum Incorrect!\n");
-     return -1;
-   }
-
-   memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
-
-   return 0;
+// Reads the Self Test Log (log #6)
+int ataReadSelfTestLog (int device, struct ata_smart_selftestlog *data){	
+  int i;
+  unsigned char chksum=0;	
+  unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE] = 
+    {WIN_SMART, 0x06, SMART_READ_LOG_SECTOR, 1,};
+  
+  // get data from device
+  if (ioctl(device, HDIO_DRIVE_CMD, buf)){
+    perror ("SMART Error Log Read failed");
+    return -1;
+  }
+  
+  // compute its checksum, and issue a warning if needed
+  for (i=0;i<ATA_SMART_SEC_SIZE;i++)
+    chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
+  if (chksum)
+    checksumwarning("SMART Self-Test Log");
+  
+  // copy data back to the user and return
+  memcpy(data,buf+HDIO_DRIVE_CMD_HDR_SIZE, ATA_SMART_SEC_SIZE); 
+  return 0;
 }
 
-
-int ataReadErrorLog (int device, struct ata_smart_errorlog *data)
-{	
-   int i;
-   unsigned char chksum=0;	
-   unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE + 
-                      ATA_SMART_SEC_SIZE] = 
-                      { WIN_SMART, 0x01, SMART_READ_LOG_SECTOR, 1};
-
-   if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
-   {
-       perror ("Smart Error Log Read failed");
-       return -1;
-   }
-
-   // compute checksum
-   for (i=0;i<ATA_SMART_SEC_SIZE;i++)
-     chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
-
-   if (chksum){
-     fprintf(stderr,"Smart Error Log Checksum Incorrect!\n");
-     return -1;
-   }
-   memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
-
-   return 0;
+// Reads the Error Log (log #1)
+int ataReadErrorLog (int device, struct ata_smart_errorlog *data){	
+  int i;
+  unsigned char chksum=0;	
+  unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE] = 
+    {WIN_SMART, 0x01, SMART_READ_LOG_SECTOR, 1,};
+  
+  // get data from device
+  if (ioctl(device,HDIO_DRIVE_CMD,&buf)) {
+    perror ("SMART Error Log Read failed");
+    return -1;
+  }
+  
+  // compute checksum and issue warning if needed
+  for (i=0;i<ATA_SMART_SEC_SIZE;i++)
+    chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
+  if (chksum)
+    checksumwarning("SMART Error Log");
+  
+  //copy data back to user and return
+  memcpy(data, buf+HDIO_DRIVE_CMD_HDR_SIZE, ATA_SMART_SEC_SIZE);
+  return 0;
 }
 
 
-int ataReadSmartThresholds ( int device, struct ata_smart_thresholds *data)
-{	
-   unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE + 
-                      ATA_SMART_SEC_SIZE] = 
-                      { WIN_SMART, 1, SMART_READ_THRESHOLDS, 1};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
-   {
-       perror ("Smart Thresholds Read failed");
-       return -1;
-   }
-
-   memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
-
-   return 0;
+// This routine is marked as "Obsolete" in the ATA-5 spec, but it's
+// very important for us.  Together with the SMART READ DATA command
+// above, it's the only way for us to find out if the SMART status is
+// good or not.  Hopefully this will get fixed -- I will find a way to
+// get SMART Status directly.
+int ataReadSmartThresholds ( int device, struct ata_smart_thresholds *data){
+  int i;
+  unsigned char chksum=0;	
+  unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE] = 
+    {WIN_SMART, 1, SMART_READ_THRESHOLDS, 1,};
+  
+  // get data from device
+  if (ioctl(device ,HDIO_DRIVE_CMD, buf)){
+    perror ("SMART Thresholds Read failed");
+    return -1;
+  }
+  
+  // compute checksum and issue warning if needed
+  for (i=0;i<ATA_SMART_SEC_SIZE;i++)
+    chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
+  if (chksum)
+    checksumwarning("SMART Attribute Thresholds");
+  
+  // copy data back to user and return
+  memcpy(data,buf+HDIO_DRIVE_CMD_HDR_SIZE, ATA_SMART_SEC_SIZE);
+  return 0;
 }
 
-int ataSetSmartThresholds ( int device, struct ata_smart_thresholds *data)
-{	
-   unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE + 
-		           ATA_SMART_SEC_SIZE] = 
-                           { WIN_SMART, 1, 0xD7, 1};
-	
-   memcpy( &buf[HDIO_DRIVE_CMD_HDR_SIZE],  data , ATA_SMART_SEC_SIZE);
-
-   if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *)  &buf ) != 0)
-   {
-       perror ("Smart Thresholds Read failed");
-       return -1;
-   }
 
-   return 0;
+// This routine is not currently in use, and it's been marked as
+// "Obsolete" in the ANSI ATA-5 spec.  So it should probably be left
+// alone and unused.
+int ataSetSmartThresholds ( int device, struct ata_smart_thresholds *data){	
+  unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE] = 
+    {WIN_SMART, 1, 0xD7, 1,};
+  
+  memcpy(buf+HDIO_DRIVE_CMD_HDR_SIZE, data, ATA_SMART_SEC_SIZE);
+  
+  if (ioctl(device, HDIO_DRIVE_CMD, buf)){
+    perror ("SMART Thresholds Read failed");
+    return -1;
+  }
+  
+  return 0;
 }
 
 
-int ataEnableSmart (int device )
-{	
+int ataEnableSmart (int device ){	
+  unsigned char parms[4] = {WIN_SMART, 1, SMART_ENABLE, 0};
+  
+  if (ioctl ( device , HDIO_DRIVE_CMD,  &parms )){
+    perror ("SMART Enable failed");
+    return -1;
+  }
+  
+  return 0;
+}
 
-   unsigned char parms[4] = { WIN_SMART, 1, SMART_ENABLE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Enable failed");
-      return -1;
-   }
-	
-   return 0;
- }
-
-
-int ataDisableSmart (int device )
-{	
-	
-   unsigned char parms[4] = { WIN_SMART, 1, SMART_DISABLE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Disable failed");
-      return -1;
-   }
 
-   return 0;
+int ataDisableSmart (int device ){	
+  unsigned char parms[4] = {WIN_SMART, 1, SMART_DISABLE, 0};
+  
+  if (ioctl(device , HDIO_DRIVE_CMD, parms )){
+    perror ("SMART Disable failed");
+    return -1;
+  }
+  
+  return 0;
 }
 
 int ataEnableAutoSave(int device){
-   unsigned char parms[4] = { WIN_SMART, 241, SMART_AUTOSAVE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Enable Auto-save failed");
-      return -1;
-   }
-	
-   return 0;
-};
+  unsigned char parms[4] = {WIN_SMART, 241, SMART_AUTOSAVE, 0};
+  
+  if (ioctl(device , HDIO_DRIVE_CMD,  parms )){
+    perror ("SMART Enable Auto-save failed");
+    return -1;
+  }
+  
+  return 0;
+}
 
 int ataDisableAutoSave(int device){
-   unsigned char parms[4] = { WIN_SMART, 0, SMART_AUTOSAVE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Disable Auto-save failed");
-      return -1;
-   }
-	
-   return 0;
-};
-
-int ataEnableAutoOffline (int device )
-{	
-
-   /* timer hard coded to 4 hours */
-   unsigned char parms[4] = { WIN_SMART, 248, SMART_AUTO_OFFLINE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-       perror ("Smart Enable Automatic Offline failed");
-       return -1;
-   }
-
-   return 0;
+  unsigned char parms[4] = {WIN_SMART, 0, SMART_AUTOSAVE, 0};
+  
+  if (ioctl(device, HDIO_DRIVE_CMD, parms)){
+    perror ("SMART Disable Auto-save failed");
+    return -1;
+  }
+  
+  return 0;
 }
 
+// Note that in the ATA-5 standard this command is marked "OBSOLETE"
+int ataEnableAutoOffline (int device ){	
+  
+  /* timer hard coded to 4 hours */
+  unsigned char parms[4] = {WIN_SMART, 248, SMART_AUTO_OFFLINE, 0};
+  
+  if (ioctl(device , HDIO_DRIVE_CMD, parms)){
+    perror ("SMART Enable Automatic Offline failed");
+    return -1;
+  }
+  
+  return 0;
+}
 
-int ataDisableAutoOffline (int device )
-{	
-   unsigned char parms[4] = { WIN_SMART, 0, SMART_AUTO_OFFLINE, 0};
-	
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms ) != 0)
-   {
-      perror ("Smart Disable Automatic Offline failed");
-      return -1;
-   }
-
-   return 0;
+// Another Obsolete Command!
+int ataDisableAutoOffline (int device ){	
+  unsigned char parms[4] = {WIN_SMART, 0, SMART_AUTO_OFFLINE, 0};
+  
+  if (ioctl(device , HDIO_DRIVE_CMD, parms)){
+    perror ("SMART Disable Automatic Offline failed");
+    return -1;
+  }
+  
+  return 0;
 }
 
 
 // Not being used correctly.  Must examine the CL and CH registers to
-// see what the smart status was.  How to fix this?  I don't know...
+// see what the smart status was.  Look at ataSmartStatus2()
 int ataSmartStatus (int device ){	
-   unsigned char parms[4] = { WIN_SMART, 0, SMART_STATUS, 0};
+   unsigned char parms[4] = {WIN_SMART, 0, SMART_STATUS, 0};
 
-   if (ioctl ( device , HDIO_DRIVE_CMD,  &parms))
-      return -1;
-   return 0;
-}
-
-
-
-int ataSmartTest (int device, int testtype)
-{	
-   unsigned char parms[4] = { WIN_SMART, testtype, 
-                    SMART_IMMEDIATE_OFFLINE, 0};
-   
-   if (ioctl ( device , HDIO_DRIVE_CMD, &parms) != 0)
-   {
-       perror ("Smart Offline failed");
-       return -1;
+   if (ioctl(device, HDIO_DRIVE_CMD, parms)){
+     perror("Return SMART Status failed");
+     return -1;
    }
-
-   printf("Completed Off-line command\n");
-	
    return 0;
 }
 
-
-int ataSmartOfflineTest (int device)
-{	
-   return ataSmartTest( device, OFFLINE_FULL_SCAN  );
+// If SMART is enabled, supported, and working, then this call is
+// guaranteed to return 1, else zero.  Silent inverse of
+// ataSmartStatus()
+int ataDoesSmartWork(int device){	
+   unsigned char parms[4] = {WIN_SMART, 0, SMART_STATUS, 0};
+   return !ioctl(device, HDIO_DRIVE_CMD, parms);
 }
 
-int ataSmartShortSelfTest (int device)
-{	
-   return ataSmartTest( device, SHORT_SELF_TEST  );
-}
 
-int ataSmartExtendSelfTest (int device)
-{	
-   return ataSmartTest( device, EXTEND_SELF_TEST  );
-}
-
-int ataSmartShortCapSelfTest (int device)
-{	
-   return ataSmartTest( device, SHORT_CAPTIVE_SELF_TEST );
+// This function needs to be properly tested and debugged.  I am not
+// yet sure if this is right; have asked Andre for help.  May need to
+// use IDE_DRIVE_TASK.  Does CONFIG_IDE_TASKFILE_IO need to be
+// configured into the kernel?
+int ataSmartStatus2(int device){
+  unsigned char normal_cyl_lo=0x4f, normal_cyl_hi=0xc2;
+  unsigned char failed_cyl_lo=0xf4, failed_cyl_hi=0x2c;
+
+  unsigned char parms[HDIO_DRIVE_TASK_HDR_SIZE]=
+    {WIN_SMART,    // CMD
+     SMART_STATUS, // FR
+     0,            // NS
+     0,            // SC
+     0,            // CL
+     0,            // CH
+     0             // SEL -- Andre, is this right?? Or should it be 1?
+    };
+
+  // load CL and CH values
+  parms[4]=normal_cyl_lo;
+  parms[5]=normal_cyl_hi;
+
+  if (ioctl(device,HDIO_DRIVE_TASK,&parms)){
+    perror ("SMART Status command failed.");
+    return -1;
+  }
+  
+  // Cyl low and Cyl high unchanged means "Good SMART status"
+  if (parms[4]==normal_cyl_lo && parms[5]==normal_cyl_hi)
+    return 0;
+
+  // These values mean "Bad SMART status"
+  if (parms[4]==failed_cyl_lo && parms[5]==failed_cyl_hi)
+    return 1;
+
+  // We haven't gotten output that makes sense; print out some debugging info
+  perror("SMART Status returned register values that don't make sense:\n");
+  printf("CMD=0x%02x\n",parms[0]);
+  printf("FR =0x%02x\n",parms[1]);
+  printf("NS =0x%02x\n",parms[2]);
+  printf("SC =0x%02x\n",parms[3]);
+  printf("CL =0x%02x\n",parms[4]);
+  printf("CH =0x%02x\n",parms[5]);
+  printf("SEL=0x%02x\n",parms[6]);
+
+  return -1;
 }
 
-int ataSmartExtendCapSelfTest (int device)
-{
-   return ataSmartTest( device, EXTEND_CAPTIVE_SELF_TEST );
+// This is the way to execute ALL tests: offline, short self-test,
+// extended self test, with and without captive mode, etc.
+int ataSmartTest(int device, int testtype){	
+  unsigned char parms[4] = {WIN_SMART, 0, SMART_IMMEDIATE_OFFLINE};
+  char cmdmsg[128],*type,*captive;
+
+  parms[1]=testtype;
+
+  // Set up strings that describe the type of test
+  if (testtype==SHORT_CAPTIVE_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST)
+    captive="captive";
+  else
+    captive="off-line";
+
+  if (testtype==OFFLINE_FULL_SCAN)
+    type="off-line";
+  else  if (testtype==SHORT_SELF_TEST || testtype==SHORT_CAPTIVE_SELF_TEST)
+    type="Short self-test";
+  else 
+    type="Extended self-test";
+
+  //  Print ouf message that we are sending the command to test
+  if (testtype==ABORT_SELF_TEST)
+    sprintf(cmdmsg,"Abort SMART off-line mode self-test routine");
+  else
+    sprintf(cmdmsg,"Execute SMART %s routine immediately in %s mode",type,captive);
+  printf("Sending command: \"%s\".\n",cmdmsg);
+
+  // Now send the command to test
+  if (ioctl(device , HDIO_DRIVE_CMD, parms)){
+    char errormsg[128];
+    sprintf(errormsg,"Command \"%s\" failed.\n\n",cmdmsg); 
+    perror (errormsg);
+    return -1;
+  }
+  
+  // Since the command succeeded, tell user
+  if (testtype==ABORT_SELF_TEST)
+    printf("Self-testing aborted!\n");
+  else
+    printf("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg);
+  return 0;
 }
 
 
-int ataSmartSelfTestAbort (int device)
-{
-   return ataSmartTest( device, 127 );
-}
-
 /* Test Time Functions */
-
-int isOfflineTestTime ( struct ata_smart_values data)
-{
-   return (int) data.total_time_to_complete_off_line;
-}
-
-
-int isShortSelfTestTime ( struct ata_smart_values data)
-{
-   return (int) data.short_test_completion_time;
-}
-
-
-int isExtendedSelfTestTime ( struct ata_smart_values data)
-{
-   return (int) data.extend_test_completion_time;
+int TestTime(struct ata_smart_values data,int testtype){
+  switch (testtype){
+  case OFFLINE_FULL_SCAN:
+    return (int) data.total_time_to_complete_off_line;
+  case SHORT_SELF_TEST:
+  case SHORT_CAPTIVE_SELF_TEST:
+    return (int) data.short_test_completion_time;
+  case EXTEND_SELF_TEST:
+  case EXTEND_CAPTIVE_SELF_TEST:
+    return (int) data.extend_test_completion_time;
+  default:
+    return 0;
+  }
 }
 
 
-int isSmartErrorLogCapable ( struct ata_smart_values data)
-{
+int isSmartErrorLogCapable ( struct ata_smart_values data){
    return data.errorlog_capability & 0x01;
 }
-
-
-int isSupportExecuteOfflineImmediate ( struct ata_smart_values data)
-{
+int isSupportExecuteOfflineImmediate ( struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x01;
 }
-
-
-int isSupportAutomaticTimer ( struct ata_smart_values data)
-{
+int isSupportAutomaticTimer ( struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x02;
 }
-
-
-int isSupportOfflineAbort ( struct ata_smart_values data)
-{
+int isSupportOfflineAbort ( struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x04;
 }
-
-
-int isSupportOfflineSurfaceScan ( struct ata_smart_values data)
-{
+int isSupportOfflineSurfaceScan ( struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x08;
 }
-
-
-int isSupportSelfTest (struct ata_smart_values data)
-{
+int isSupportSelfTest (struct ata_smart_values data){
    return data.offline_data_collection_capability & 0x10;
 }
 
diff --git a/sm5/atacmds.h b/sm5/atacmds.h
index 40acfcea415961bed5979482b86df67b8fdc1f9a..c5b2012a71222b26b8e47693f0c4ecc179afde31 100644
--- a/sm5/atacmds.h
+++ b/sm5/atacmds.h
@@ -1,4 +1,4 @@
-//  $Id: atacmds.h,v 1.12 2002/10/15 14:24:26 ballen4705 Exp $
+//  $Id: atacmds.h,v 1.13 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * atacmds.h
  *
@@ -72,6 +72,12 @@
 #define SMART_WRITE_LOG_SECTOR 0xd6
 #endif
 
+// The following is obsolete -- don't use it!
+#ifndef SMART_WRITE_THRESHOLDS
+#define SMART_WRITE_THRESHOLDS  0xd7
+#endif
+
+
 #ifndef SMART_ENABLE
 #define SMART_ENABLE		0xd8
 #endif
@@ -84,6 +90,7 @@
 #define SMART_STATUS		0xda
 #endif
 
+// The following is also marked obsolete in ATA-5
 #ifndef SMART_AUTO_OFFLINE
 #define SMART_AUTO_OFFLINE	0xdb
 #endif
@@ -91,6 +98,7 @@
 #define OFFLINE_FULL_SCAN		0
 #define SHORT_SELF_TEST			1
 #define EXTEND_SELF_TEST		2
+#define ABORT_SELF_TEST                 127
 #define SHORT_CAPTIVE_SELF_TEST		129
 #define EXTEND_CAPTIVE_SELF_TEST	130
 
@@ -306,22 +314,19 @@ int ataSmartSelfTestAbort (int device);
 int ataVersionInfo (const char **description, struct hd_driveid drive);
 
 
-/*  int ataSmartSupport ( int device, struct hd_driveid drive)
-*   Check if S.M.A.R.T. is supported and enabled in drive 
-*	returns -1:if S.M.A.R.T. capability can not be checked
-*	returns	0: if drive does not support S.M.A.R.T.
-*			1: if drive supports S.M.A.R.T. but not enabled 
-*			2: if drive supports S.M.A.R.T. and enabled 
-*		  255: if drive supports S.M.A.R.T. but does not   
-*			   support ATA-4. 
-*	ATA 3 and lower do not support S.M.A.R.T. enabled bit
-*   Attempt a Read S.M.A.R.T. attributes to check if enabled
-*/ 
+// If SMART supported, this is guaranteed to return 1 if SMART is enabled, else 0.
+int ataDoesSmartWork(int device);
 
+// returns 1 if SMART supported, 0 if not supported or can't tell
 int ataSmartSupport ( struct hd_driveid drive);
 
-/* Check SMART for Threshold failure */
+// Return values:
+//  1: SMART enabled
+//  0: SMART disabled
+// -1: can't tell if SMART is enabled -- try issuing ataDoesSmartWork command to see
+int ataIsSmartEnabled(struct hd_driveid drive);
 
+/* Check SMART for Threshold failure */
 int ataCheckSmart ( struct ata_smart_values data, struct ata_smart_thresholds thresholds);
 
 /* int isOfflineTestTime ( struct ata_smart_values data)
@@ -355,6 +360,8 @@ int isSupportOfflineSurfaceScan ( struct ata_smart_values data);
 int isSupportSelfTest (struct ata_smart_values data);
 
 
+int ataSmartTest(int device, int testtype);
 
+int TestTime(struct ata_smart_values data,int testtype);
 
 #endif /* _ATACMDS_H_ */
diff --git a/sm5/ataprint.c b/sm5/ataprint.c
index 98e65df217d709c1993120332ac10066ba9e844a..c20078a61c3baf48679af296f74a01dff542c238 100644
--- a/sm5/ataprint.c
+++ b/sm5/ataprint.c
@@ -1,4 +1,4 @@
-//  $Id: ataprint.c,v 1.12 2002/10/17 04:03:33 ballen4705 Exp $
+//  $Id: ataprint.c,v 1.13 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * ataprint.c
  *
@@ -23,15 +23,56 @@
  *
  */
 
+#include <ctype.h>
+#include <stdio.h>
 #include "ataprint.h"
 #include "smartctl.h"
 #include "extern.h"
 
+// Function for printing ASCII byte-swapped strings, skipping white
+// space. This is needed on little-endian architectures, eg Intel,
+// Alpha. If someone wants to run this on SPARC they'll need to test
+// for the Endian-ness and skip the byte swapping if it's big-endian.
+void printswap(char *in, unsigned int n){
+  unsigned int i;
+  char out[64];
+
+  // swap bytes
+  for (i=0;i<n;i+=2){
+    unsigned int j=i+1;
+    out[i]=in[j];
+    out[j]=in[i];
+  }
+
+  // find the end of the white space
+  for (i=0;i<n && isspace(out[i]);i++);
+
+  // and do the printing starting from first non-white space
+  if (n-i)
+    printf("%.*s\n",n-i,out+i);
+  else
+    printf("[No Information Found]\n");
+
+  return;
+}
+
+
 void ataPrintDriveInfo (struct hd_driveid drive){
   int version;
   const char *description;
   char unknown[64];
 
+  // print out model, serial # and firmware versions  (byte-swap ASCI strings)
+  printf("Device Model:     ");
+  printswap(drive.model,40);
+
+  printf("Serial Number:    ");
+  printswap(drive.serial_no,20);
+
+  printf("Firmware Version: ");
+  printswap(drive.fw_rev,8);
+
+  // now get ATA version info
   version=ataVersionInfo(&description,drive);
 
   // unrecognized minor revision code
@@ -40,17 +81,20 @@ void ataPrintDriveInfo (struct hd_driveid drive){
     description=unknown;
   }
   
-  // print out information for user
-  printf("Device Model:     %.40s\n",drive.model);
-  printf("Serial Number:    %.20s\n",drive.serial_no);
-  printf("Firmware Version: %.8s\n",drive.fw_rev);
-  printf("ATA Version is:   %i\n",version);
+  
+  // SMART Support was first added into the ATA/ATAPI-3 Standard with
+  // Revision 3 of the document, July 25, 1995.  Look at the "Document
+  // Status" revision commands at the beginning of
+  // http://www.t13.org/project/d2008r6.pdf to see this.  So it's not
+  // enough to check if we are ATA-3.  Version=-3 indicates ATA-3
+  // BEFORE Revision 3.
+  printf("ATA Version is:   %i\n",version>0?version:-1*version);
   printf("ATA Standard is:  %s\n",description);
-
+  
   if (version>=3)
     return;
-
-  printf("SMART is only supported in ATA version 3 or greater\n");
+  
+  printf("SMART is only available in ATA Version 3 Revision 3 or greater.\n\n");
   exit (0);
 }
 
@@ -62,55 +106,61 @@ void PrintSmartOfflineStatus ( struct ata_smart_values data)
 {
    printf ("Off-line data collection status: ");	
    
-   switch (data.offline_data_collection_status)
-   {
-      case 0x0: case 0x80:
-          printf ("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf("never started.\n");
-          break;
-      case 0x01: case 0x81:
-          printf ("(0x%02x)\tReserved.\n",
-                  data.offline_data_collection_status);
-          break;
-      case 0x02: case 0x82:
-          printf ("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf ("completed without error.\n");
-          break;
-      case 0x03: case 0x83:
-          printf ("(0x%02x)\tReserved.\n",
-                  data.offline_data_collection_status);
-          break;
-      case 0x04: case 0x84:
-          printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf ("suspended by an interrupting command.\n");
-          break;
-      case 0x05: case 0x85:
-          printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf ("aborted by an interrupting command.\n");
-          break;
-      case 0x06: case 0x86:
-          printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf ("aborted by the device with a fatal error.\n");
-          break;
-      default:
-          if ( ((data.offline_data_collection_status >= 0x07) &&
-                (data.offline_data_collection_status <= 0x3f)) ||
-                ((data.offline_data_collection_status >= 0xc0) &&
-                (data.offline_data_collection_status <= 0xff)) )
-          {
-              printf ("(0x%02x)\tVendor Specific.\n",
-                      data.offline_data_collection_status);
-          } 
-          else 
-          {
-              printf ("(0x%02x)\tReserved.\n",
-                      data.offline_data_collection_status);
-          }
+   switch (data.offline_data_collection_status){
+   case 0x00:
+   case 0x80:
+     printf ("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf("never started.\n");
+     break;
+   case 0x01:
+   case 0x81:
+     printf ("(0x%02x)\tReserved.\n",
+	     data.offline_data_collection_status);
+     break;
+   case 0x02:
+   case 0x82:
+     printf ("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf ("completed without error.\n");
+     break;
+   case 0x03:
+   case 0x83:
+     printf ("(0x%02x)\tReserved.\n",
+	     data.offline_data_collection_status);
+     break;
+   case 0x04:
+   case 0x84:
+     printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf ("suspended by an interrupting command from host.\n");
+     break;
+   case 0x05:
+   case 0x85:
+     printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf ("aborted by an interrupting command from host.\n");
+     break;
+   case 0x06:
+   case 0x86:
+     printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf ("aborted by the device with a fatal error.\n");
+     break;
+   default:
+     if ( ((data.offline_data_collection_status >= 0x07) &&
+	   (data.offline_data_collection_status <= 0x3f)) ||
+	  ((data.offline_data_collection_status >= 0xc0) &&
+	   (data.offline_data_collection_status <= 0xff)) )
+       {
+	 printf ("(0x%02x)\tVendor Specific.\n",
+		 data.offline_data_collection_status);
+       } 
+     else 
+       {
+	 printf ("(0x%02x)\tReserved.\n",
+		 data.offline_data_collection_status);
+       }
    }
 }
 
@@ -236,8 +286,7 @@ void PrintSmartCapability ( struct ata_smart_values data)
    
    if (data.smart_capability == 0x00)
    {
-       printf ("automatic saving of SMART data"); 
-       printf ("\t\t\t\t\tis not implemented.\n");
+       printf ("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n");
    } 
    else 
    {
@@ -451,9 +500,9 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data)
   
   // starting printing error log info
   if (data.ata_error_count<=5)
-      printf ( "ATA Error Count: %u\n\n", data.ata_error_count);
+      printf ( "ATA Error Count: %u\n", data.ata_error_count);
   else
-      printf ( "ATA Error Count: %u (only the most recent five errors are shown below)\n\n",
+      printf ( "ATA Error Count: %u (only the most recent five errors are shown below)\n",
 	       data.ata_error_count);
 
   printf(  "Acronyms used below:\n");
@@ -530,7 +579,7 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data)
 void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data){
   int i,j;
 
-  printf("\nSMART Self-test log, version number %u\n",data.revnumber);
+  printf("SMART Self-test log, version number %u\n",data.revnumber);
   if (data.revnumber!=0x01)
     printf("Warning - structure revision number does not match spec!\n");
   
@@ -540,7 +589,7 @@ void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data){
   }
 
   // print log      
-  printf("\nNum  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error\n");
+  printf("Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error\n");
   for (i=20;i>=0;i--){
 
     struct ata_smart_selftestlog_struct *log;
@@ -595,25 +644,24 @@ void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data){
   return;
 }
 
-void ataPsuedoCheckSmart ( struct ata_smart_values data, 
+void ataPseudoCheckSmart ( struct ata_smart_values data, 
                            struct ata_smart_thresholds thresholds) {
-   int i;
-   int failed = 0;
-   for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++ ) {
-     if (data.vendor_attributes[i].id &&   
-	  thresholds.thres_entries[i].id &&
-	  data.vendor_attributes[i].status.flag.prefailure &&
-	  (data.vendor_attributes[i].current < thresholds.thres_entries[i].threshold) &&
-	  (thresholds.thres_entries[i].threshold != 0xFE)){
-       printf("Attribute ID %i Failed\n", 
-	      data.vendor_attributes[i].id);
-       failed = 1;
-     } 
-   }   
-   printf("%s\n", ( failed )?
-	  "SMART overall-health self-assessment test result: FAILED!\n"
-	  "Drive failure expected in less than 24 hours. SAVE ALL DATA\n":
-	  "SMART overall-health self-assessment test result: PASSED\n");
+  int i;
+  int failed = 0;
+  for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++) {
+    if (data.vendor_attributes[i].id &&   
+	thresholds.thres_entries[i].id &&
+	data.vendor_attributes[i].status.flag.prefailure &&
+	(data.vendor_attributes[i].current < thresholds.thres_entries[i].threshold) &&
+	(thresholds.thres_entries[i].threshold != 0xFE)){
+      printf("Attribute ID %i Failed\n",data.vendor_attributes[i].id);
+      failed = 1;
+    } 
+  }   
+  printf("%s\n", ( failed )?
+	 "SMART overall-health self-assessment test result: FAILED!\n"
+	 "Drive failure expected in less than 24 hours. SAVE ALL DATA":
+	 "SMART overall-health self-assessment test result: PASSED");
 }
 
 void ataPrintSmartAttribName ( unsigned char id ){
@@ -722,322 +770,195 @@ void ataPrintSmartAttribName ( unsigned char id ){
  Called by smartctl to access ataprint  
 **/
 
-void ataPrintMain ( int fd )
-{
-   struct hd_driveid drive;
-   struct ata_smart_values smartval;
-   struct ata_smart_thresholds smartthres;
-   struct ata_smart_errorlog smarterror;
-   struct ata_smart_selftestlog smartselftest;
-
-   if ( driveinfo )
-   {
-      if (  ataReadHDIdentity ( fd, &drive) != 0 )
-      {
-         printf("Smartctl: Hard Drive Identity Failed\n");
-         exit(0);	
-      } 
-		
-      ataPrintDriveInfo(drive); 
-		
-
-      if (ataSmartSupport(drive))
-      {
-          printf ("SMART support is: ");
-	  
-          if ( ataSmartStatus(fd) != 0) 
-          {
-              printf( "Disabled\n");
-              printf( "Use option -%c to enable\n\n", SMARTENABLE );
-              exit(0);
-          }
-          else { 
-              printf( "Enabled\n\n");
-          } 
-      }
-      else {
-           printf("SMART support is: Unavailable. Device lacks SMART capability.\n\n");
-	   exit (0);
-      }
+void ataPrintMain (int fd){
+  struct hd_driveid drive;
+  struct ata_smart_values smartval;
+  struct ata_smart_thresholds smartthres;
+  struct ata_smart_errorlog smarterror;
+  struct ata_smart_selftestlog smartselftest;
+  int timewait;
+  
+  // Start by getting Drive ID information.  We need this, to know if SMART is supported.
+  if (ataReadHDIdentity(fd,&drive)){
+    printf("Smartctl: Hard Drive Read Identity Failed\n\n");
+    exit(-1);	
   }
-
-  if ( smartdisable )
-  {
-		
-     if ( ataDisableSmart(fd) != 0) 
-     {
-	printf( "Smartctl: SMART Enable Failed\n");
-	exit(-1);
-     }
-    
-     printf("SMART Disabled\n");
-     exit (0);
-		
-   }
-
-   if ( smartenable )
-   {
-      if ( ataEnableSmart(fd) != 0) 
-	{
-          printf( "Smartctl: SMART Enable Failed\n");
-          exit(-1);
-	}
-
-      if (ataSmartStatus(fd)==0)
-	printf("SMART Enabled\n");
-      else
-	printf( "Smartctl: SMART Enable Failed for unknown reasons\n");
-   }
-   
-   
-   if ( smartautosavedisable ){
-     if (ataDisableAutoSave(fd) != 0)
-       {
-	 printf( "Smartctl: SMART Disable Attribute Autosave Failed\n");
-	 exit(-1);
-       }     
-     printf("SMART Attribute Autosave Disabled\n");
-   }
-	
-   if ( smartautosaveenable ){
-     if (ataEnableAutoSave(fd) != 0)
-       {
-	 printf( "Smartctl: SMART Enable Attribute Autosave Failed\n");
-	 exit(-1);
-       } 
-     printf("SMART Attribute Autosave Enabled\n");
-   }
-
-   /* for everything else read values and thresholds 
-   are needed */	
-
-   if ( ataReadSmartValues ( fd, &smartval) != 0 )
-   {
-      printf("Smartctl: SMART Values Read Failed\n");
-      exit (-1);
-   }
-
-   if ( ataReadSmartThresholds ( fd, &smartthres) != 0 )
-   {
-      printf("Smartctl: SMART Thresholds Read Failed\n");
-      exit (-1); 
-   }
-	
-   if ( checksmart )
-   {
-	/* pseudo is used because linux does not support access to
-	   Task File registers */
-	// I am very confused by this comment.  Does anyone get it?  Bruce
-      ataPsuedoCheckSmart ( smartval , smartthres);
-
-   }
-	
-   if (  generalsmartvalues )
-   {
-      ataPrintGeneralSmartValues( smartval ); 
-   }
-
-   if ( smartvendorattrib )
-   {
-      PrintSmartAttribWithThres( smartval, smartthres);
-   }
-	
-   if ( smarterrorlog )
-   {
-      if ( isSmartErrorLogCapable(smartval) == 0)
-      {
-          printf("Device does not support Error Logging\n");
-      } 
-      else
-      {
-         if ( ataReadErrorLog ( fd, &smarterror) != 0 )
-	 {
-             printf("Smartctl: SMART Errorlog Read Failed\n");
-         }
-         else
-         {
-             ataPrintSmartErrorlog ( smarterror); 
-         }
-      }
+  
+  // Print most drive identity information if requested
+  if (driveinfo){
+    printf("\n=== START OF INFORMATION SECTION ===\n");
+    ataPrintDriveInfo(drive);
+  }
+  
+  // now check if drive supports SMART; otherwise time to exit
+  if (!ataSmartSupport(drive)){
+    printf("SMART support is: Unavailable - device lacks SMART capability.\n");
+    exit (0);
+  }
+  
+  // Now print remaining drive info: is SMART enabled?    
+  if (driveinfo){
+    printf("SMART support is: Available - device has SMART capability.\n");
+    if (ataDoesSmartWork(fd))
+      printf("SMART support is: Enabled\n");
+    else
+      printf("SMART support is: Disabled\n");
+  }
+  
+  // START OF THE ENABLE/DISABLE SECTION OF THE CODE
+  if (smartenable || smartdisable || 
+      smartautosaveenable || smartautosavedisable || 
+      smartautoofflineenable || smartautoofflinedisable)
+    printf("\n=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
+
+  // Enable/Disable SMART commands
+  if (smartenable){
+    if (ataEnableSmart(fd)) {
+      printf("Smartctl: SMART Enable Failed.\n\n");
+      exit(-1);
     }
-	
-
-   if ( smartselftestlog )
-   {
-       if ( isSmartErrorLogCapable(smartval) == 0)
-       {
-           printf("Device does not support Self Test Logging\n");
-       }
-       else
-       {
-	    if (  ataReadSelfTestLog( fd, &smartselftest) != 0 )
-            {
-                printf("Smartctl: SMART Self Test Log Read Failed\n");
-            }
-            else
-            {
-                 ataPrintSmartSelfTestlog (smartselftest); 
-            }
-        } 
+    else
+      printf("SMART Enabled.\n");
+  }
+  
+  // From here on, every command requires that SMART be enabled...
+  if (!ataDoesSmartWork(fd)) {
+    printf("SMART Disabled. Use option -%c to enable it.\n", SMARTENABLE );
+    exit(0);
+  }
+  
+  // Turn off SMART on device
+  if (smartdisable){    
+    if (ataDisableSmart(fd)) {
+      printf( "Smartctl: SMART Disable Failed.\n\n");
+      exit(-1);
     }
+    printf("SMART Disabled. Use option -%c to enable it.\n",SMARTENABLE);
+    exit (0);		
+  }
+  
+  // Enable/Disable Auto-save attributes
+  if (smartautosaveenable){
+    if (ataEnableAutoSave(fd)){
+      printf( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n");
+      exit(-1);
+    } 
+    printf("SMART Attribute Autosave Enabled\n");
+  }
+  if (smartautosavedisable){
+    if (ataDisableAutoSave(fd)){
+      printf( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n");
+      exit(-1);
+    }     
+    printf("SMART Attribute Autosave Disabled\n");
+  }
+  
+  // for everything else read values and thresholds are needed
+  if (ataReadSmartValues(fd, &smartval)){
+    printf("Smartctl: SMART Values Read Failed.\n\n");
+    exit (-1);
+  }
+  if (ataReadSmartThresholds(fd, &smartthres)){
+    printf("Smartctl: SMART Thresholds Read Failed.\n\n");
+    exit (-1); 
+  }
 
-    if (  smartautoofflineenable  )
-    {
-        if ( !isSupportAutomaticTimer (smartval))
-        {
-            printf("Device does not support SMART Automatic Timers\n");
-            exit(-1);
-        }
-
-        if ( ataEnableAutoOffline (fd) != 0) 
-        {
-            printf( "Smartctl: SMART Enable Automatic Offline Failed\n");
-            exit(-1);
-        }
-        
-        printf ("SMART Automatic Offline Testing Enabled every four hours\n");
+  // Enable/Disable Off-line testing
+  if (smartautoofflineenable){
+    if (!isSupportAutomaticTimer (smartval)){
+      printf("Device does not support SMART Automatic Timers.\n\n");
+      exit(-1);
     }
+    if (ataEnableAutoOffline (fd)){
+      printf( "Smartctl: SMART Enable Automatic Offline Failed.\n\n");
+      exit(-1);
+    }    
+    printf ("SMART Automatic Offline Testing Enabled every four hours.\n");
+  }
+  if (smartautoofflinedisable){
+    if (!isSupportAutomaticTimer (smartval)){
+      printf("Device does not support SMART Automatic Timers.\n\n");
+      exit(-1);
+    }		
+    if ( ataDisableAutoOffline (fd)){
+      printf( "Smartctl: SMART Disable Automatic Offline Failed.\n\n");
+      exit(-1);
+    }
+    printf ("SMART Automatic Offline Testing Disabled.\n");
+  }
 
-    if (  smartautoofflinedisable  )
-    {
-        if ( !isSupportAutomaticTimer (smartval))
-        {
-            printf("Device does not support SMART Automatic Timers\n");
-            exit(-1);
-        }
-			
-        if ( ataDisableAutoOffline (fd) != 0) 
-        {
-            printf( "Smartctl: SMART Disable Automatic Offline Failed\n");
-            exit(-1);
-        }
-         
-        printf ("SMART Automatic Offline Testing Disabled\n");
-
-     }
-
-
-     if ( smartexeoffimmediate )
-     {
-        if ( ataSmartOfflineTest (fd) != 0) 
-	{
-            printf( "Smartctl: SMART Offline Failed\n");
-            exit(-1);
-        }
-
-        printf ("Drive Command Successful offline test has begun\n");
-        printf ("Please wait %d seconds for test to complete\n", 
-                 isOfflineTestTime(smartval) );
-        printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
-	exit (0);
-     }
-
-     if ( smartshortcapselftest )
-     {
-         if ( ! isSupportSelfTest(smartval) )
-         {
-             printf ("ERROR: device does not support Self-Test function\n");
-             exit(-1);
-         }
-		
-         if ( ataSmartShortCapSelfTest (fd) != 0) 
-         {
-              printf( "Smartctl: SMART Short Self Test Failed\n");
-              exit(-1);
-         }
-     
-         printf ("Drive Command Successful offline test has begun\n");
-         printf ("Please wait %d minutes for test to complete\n", 
-                  isShortSelfTestTime (smartval) );
-	 printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
+  // START OF READ-ONLY OPTIONS APART FROM -p and -i
+  if (checksmart || generalsmartvalues || smartvendorattrib || smarterrorlog || smartselftestlog)
+    printf("\n=== START OF READ SMART DATA SECTION ===\n");
+
+  // Check SMART status
+  if (checksmart)
+    // Eventually when working use the ataSmartStatus2 function here.
+    // This will then not require read values & thresholds above, and
+    // shouldl be moved in the code to just before the read values &
+    // thresholds statements.
+    ataPseudoCheckSmart(smartval, smartthres);
+  
+  // Print general SMART values
+  if (generalsmartvalues)
+    ataPrintGeneralSmartValues(smartval); 
+  
+  // Print vendor-specific attributes
+  if (smartvendorattrib)
+    PrintSmartAttribWithThres(smartval, smartthres);
 	
-         /* Make sure Offline testing is last thing done */
-        exit (0);
-     }
+  // Print SMART error log
+  if (smarterrorlog){
+    if (!isSmartErrorLogCapable(smartval))
+      printf("Device does not support Error Logging\n");
+    else {
+      if (ataReadErrorLog(fd, &smarterror))
+	printf("Smartctl: SMART Errorlog Read Failed\n");
+      else
+	ataPrintSmartErrorlog(smarterror);
+    }
+  }
 
-     if ( smartshortselftest )
-     {
-        if ( ! isSupportSelfTest(smartval) )
-        {
-            printf ("ERROR: device does not support Self-Test function\n");
-            exit(-1);
-        }
-		
-        if ( ataSmartShortSelfTest (fd) != 0) 
-        {
-            printf( "Smartctl: SMART Short Self Test Failed\n");
-            exit(-1);
-        }
-
-        printf ("Drive Command Successful offline test has begun\n");
-        printf ("Please wait %d minutes for test to complete\n", 
-                 isShortSelfTestTime (smartval) );
-        printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
-		
-	/* Make sure Offline testing is last thing done */
-	exit (0);
-     }
- 
-	
-     if ( smartextendselftest )
-     {
-        if ( ! isSupportSelfTest(smartval) )
-        {
-           printf ("ERROR: device does not support Self-Test function\n");
-           exit(-1);
-        }
-
-        if ( ataSmartExtendSelfTest (fd) != 0) 
-        {
-           printf( "SMART Extended Self Test Failed\n");
-           exit(-1);
-        }
-		
-        printf ("Drive Command Successful self test has begun\n");
-        printf ("Please wait %d minutes for test to complete\n", 
-                 isExtendedSelfTestTime(smartval) );
-        printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
-	
-        exit (0);
-     }
+  // Print SMART self-test log
+  if (smartselftestlog){
+    if (!isSmartErrorLogCapable(smartval))
+      printf("Device does not support Self Test Logging\n");
+    else {
+      if(ataReadSelfTestLog(fd, &smartselftest))
+	printf("Smartctl: SMART Self Test Log Read Failed\n");
+      else
+	ataPrintSmartSelfTestlog(smartselftest); 
+    } 
+  }
+  
+  // START OF THE TESTING SECTION OF THE CODE.  IF NO TESTING, RETURN
+  if (testcase==-1)
+    return;
 
-	
-     if ( smartextendcapselftest )
-     {
-         if ( ! isSupportSelfTest(smartval) )
-         {
-            printf ("ERROR: device does not support self test function\n");
-            exit(-1);
-         }
-
-         if ( ataSmartExtendCapSelfTest (fd) != 0) 
-         {
-            printf( "SMART Extended Self Test Failed\n");
-            exit(-1);
-         }
-		
-            printf ("Drive Command Successful captive extended self test has begun\n");
-            printf ("Please wait %d minutes for test to complete\n", 
-                    isExtendedSelfTestTime(smartval) );
-            printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
-            exit (0);
-     }
+  printf("\n=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
 
-     if ( smartselftestabort )
-     {
-        if ( ! isSupportSelfTest(smartval) )
-        {
-            printf ("ERROR: device does not support Self-Test function\n");
-            exit(-1);
-        }
-
-        if ( ataSmartSelfTestAbort (fd) != 0) 
-        {
-            printf( "SMART Self Test Abort Failed\n");
-            exit(-1);
-        }
-		
-        printf ("Drive Command Successful self test aborted\n");
-    }		
-	
+  
+  // if doing a self-test, be sure it's supported by the hardware
+  if (testcase==OFFLINE_FULL_SCAN &&  !isSupportExecuteOfflineImmediate(smartval)){
+    printf("ERROR: device does not support Execute Off-Line Immediate function.\n\n");
+    exit(-1);
+  }
+  else if (!isSupportSelfTest(smartval)){
+    printf ("ERROR: device does not support Self-Test functions.\n\n");
+    exit(-1);
+  }
+  
+  // Now do the test
+  if (ataSmartTest(fd, testcase))
+    exit(-1);
+  
+  // Tell user how long test will take to complete  
+  if ((timewait=TestTime(smartval,testcase))){ 
+    printf ("Please wait %d %s for test to complete.\n",
+	    timewait, testcase==OFFLINE_FULL_SCAN?"seconds":"minutes");
+    
+    if (testcase!=SHORT_CAPTIVE_SELF_TEST && testcase!=EXTEND_CAPTIVE_SELF_TEST)
+      printf ("Use smartctl -%c to abort test.\n", SMARTSELFTESTABORT);	
+  }    
+  return;
 }
diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp
index 544a339e8005cdb87218353f688d3f4140c7005b..4834cb2f3c649c84a3fca0d0c1586fe9237380bf 100644
--- a/sm5/ataprint.cpp
+++ b/sm5/ataprint.cpp
@@ -1,4 +1,4 @@
-//  $Id: ataprint.cpp,v 1.12 2002/10/17 04:03:33 ballen4705 Exp $
+//  $Id: ataprint.cpp,v 1.13 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * ataprint.c
  *
@@ -23,15 +23,56 @@
  *
  */
 
+#include <ctype.h>
+#include <stdio.h>
 #include "ataprint.h"
 #include "smartctl.h"
 #include "extern.h"
 
+// Function for printing ASCII byte-swapped strings, skipping white
+// space. This is needed on little-endian architectures, eg Intel,
+// Alpha. If someone wants to run this on SPARC they'll need to test
+// for the Endian-ness and skip the byte swapping if it's big-endian.
+void printswap(char *in, unsigned int n){
+  unsigned int i;
+  char out[64];
+
+  // swap bytes
+  for (i=0;i<n;i+=2){
+    unsigned int j=i+1;
+    out[i]=in[j];
+    out[j]=in[i];
+  }
+
+  // find the end of the white space
+  for (i=0;i<n && isspace(out[i]);i++);
+
+  // and do the printing starting from first non-white space
+  if (n-i)
+    printf("%.*s\n",n-i,out+i);
+  else
+    printf("[No Information Found]\n");
+
+  return;
+}
+
+
 void ataPrintDriveInfo (struct hd_driveid drive){
   int version;
   const char *description;
   char unknown[64];
 
+  // print out model, serial # and firmware versions  (byte-swap ASCI strings)
+  printf("Device Model:     ");
+  printswap(drive.model,40);
+
+  printf("Serial Number:    ");
+  printswap(drive.serial_no,20);
+
+  printf("Firmware Version: ");
+  printswap(drive.fw_rev,8);
+
+  // now get ATA version info
   version=ataVersionInfo(&description,drive);
 
   // unrecognized minor revision code
@@ -40,17 +81,20 @@ void ataPrintDriveInfo (struct hd_driveid drive){
     description=unknown;
   }
   
-  // print out information for user
-  printf("Device Model:     %.40s\n",drive.model);
-  printf("Serial Number:    %.20s\n",drive.serial_no);
-  printf("Firmware Version: %.8s\n",drive.fw_rev);
-  printf("ATA Version is:   %i\n",version);
+  
+  // SMART Support was first added into the ATA/ATAPI-3 Standard with
+  // Revision 3 of the document, July 25, 1995.  Look at the "Document
+  // Status" revision commands at the beginning of
+  // http://www.t13.org/project/d2008r6.pdf to see this.  So it's not
+  // enough to check if we are ATA-3.  Version=-3 indicates ATA-3
+  // BEFORE Revision 3.
+  printf("ATA Version is:   %i\n",version>0?version:-1*version);
   printf("ATA Standard is:  %s\n",description);
-
+  
   if (version>=3)
     return;
-
-  printf("SMART is only supported in ATA version 3 or greater\n");
+  
+  printf("SMART is only available in ATA Version 3 Revision 3 or greater.\n\n");
   exit (0);
 }
 
@@ -62,55 +106,61 @@ void PrintSmartOfflineStatus ( struct ata_smart_values data)
 {
    printf ("Off-line data collection status: ");	
    
-   switch (data.offline_data_collection_status)
-   {
-      case 0x0: case 0x80:
-          printf ("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf("never started.\n");
-          break;
-      case 0x01: case 0x81:
-          printf ("(0x%02x)\tReserved.\n",
-                  data.offline_data_collection_status);
-          break;
-      case 0x02: case 0x82:
-          printf ("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf ("completed without error.\n");
-          break;
-      case 0x03: case 0x83:
-          printf ("(0x%02x)\tReserved.\n",
-                  data.offline_data_collection_status);
-          break;
-      case 0x04: case 0x84:
-          printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf ("suspended by an interrupting command.\n");
-          break;
-      case 0x05: case 0x85:
-          printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf ("aborted by an interrupting command.\n");
-          break;
-      case 0x06: case 0x86:
-          printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-                  data.offline_data_collection_status);
-          printf ("aborted by the device with a fatal error.\n");
-          break;
-      default:
-          if ( ((data.offline_data_collection_status >= 0x07) &&
-                (data.offline_data_collection_status <= 0x3f)) ||
-                ((data.offline_data_collection_status >= 0xc0) &&
-                (data.offline_data_collection_status <= 0xff)) )
-          {
-              printf ("(0x%02x)\tVendor Specific.\n",
-                      data.offline_data_collection_status);
-          } 
-          else 
-          {
-              printf ("(0x%02x)\tReserved.\n",
-                      data.offline_data_collection_status);
-          }
+   switch (data.offline_data_collection_status){
+   case 0x00:
+   case 0x80:
+     printf ("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf("never started.\n");
+     break;
+   case 0x01:
+   case 0x81:
+     printf ("(0x%02x)\tReserved.\n",
+	     data.offline_data_collection_status);
+     break;
+   case 0x02:
+   case 0x82:
+     printf ("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf ("completed without error.\n");
+     break;
+   case 0x03:
+   case 0x83:
+     printf ("(0x%02x)\tReserved.\n",
+	     data.offline_data_collection_status);
+     break;
+   case 0x04:
+   case 0x84:
+     printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf ("suspended by an interrupting command from host.\n");
+     break;
+   case 0x05:
+   case 0x85:
+     printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf ("aborted by an interrupting command from host.\n");
+     break;
+   case 0x06:
+   case 0x86:
+     printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
+	     data.offline_data_collection_status);
+     printf ("aborted by the device with a fatal error.\n");
+     break;
+   default:
+     if ( ((data.offline_data_collection_status >= 0x07) &&
+	   (data.offline_data_collection_status <= 0x3f)) ||
+	  ((data.offline_data_collection_status >= 0xc0) &&
+	   (data.offline_data_collection_status <= 0xff)) )
+       {
+	 printf ("(0x%02x)\tVendor Specific.\n",
+		 data.offline_data_collection_status);
+       } 
+     else 
+       {
+	 printf ("(0x%02x)\tReserved.\n",
+		 data.offline_data_collection_status);
+       }
    }
 }
 
@@ -236,8 +286,7 @@ void PrintSmartCapability ( struct ata_smart_values data)
    
    if (data.smart_capability == 0x00)
    {
-       printf ("automatic saving of SMART data"); 
-       printf ("\t\t\t\t\tis not implemented.\n");
+       printf ("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n");
    } 
    else 
    {
@@ -451,9 +500,9 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data)
   
   // starting printing error log info
   if (data.ata_error_count<=5)
-      printf ( "ATA Error Count: %u\n\n", data.ata_error_count);
+      printf ( "ATA Error Count: %u\n", data.ata_error_count);
   else
-      printf ( "ATA Error Count: %u (only the most recent five errors are shown below)\n\n",
+      printf ( "ATA Error Count: %u (only the most recent five errors are shown below)\n",
 	       data.ata_error_count);
 
   printf(  "Acronyms used below:\n");
@@ -530,7 +579,7 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data)
 void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data){
   int i,j;
 
-  printf("\nSMART Self-test log, version number %u\n",data.revnumber);
+  printf("SMART Self-test log, version number %u\n",data.revnumber);
   if (data.revnumber!=0x01)
     printf("Warning - structure revision number does not match spec!\n");
   
@@ -540,7 +589,7 @@ void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data){
   }
 
   // print log      
-  printf("\nNum  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error\n");
+  printf("Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error\n");
   for (i=20;i>=0;i--){
 
     struct ata_smart_selftestlog_struct *log;
@@ -595,25 +644,24 @@ void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data){
   return;
 }
 
-void ataPsuedoCheckSmart ( struct ata_smart_values data, 
+void ataPseudoCheckSmart ( struct ata_smart_values data, 
                            struct ata_smart_thresholds thresholds) {
-   int i;
-   int failed = 0;
-   for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++ ) {
-     if (data.vendor_attributes[i].id &&   
-	  thresholds.thres_entries[i].id &&
-	  data.vendor_attributes[i].status.flag.prefailure &&
-	  (data.vendor_attributes[i].current < thresholds.thres_entries[i].threshold) &&
-	  (thresholds.thres_entries[i].threshold != 0xFE)){
-       printf("Attribute ID %i Failed\n", 
-	      data.vendor_attributes[i].id);
-       failed = 1;
-     } 
-   }   
-   printf("%s\n", ( failed )?
-	  "SMART overall-health self-assessment test result: FAILED!\n"
-	  "Drive failure expected in less than 24 hours. SAVE ALL DATA\n":
-	  "SMART overall-health self-assessment test result: PASSED\n");
+  int i;
+  int failed = 0;
+  for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++) {
+    if (data.vendor_attributes[i].id &&   
+	thresholds.thres_entries[i].id &&
+	data.vendor_attributes[i].status.flag.prefailure &&
+	(data.vendor_attributes[i].current < thresholds.thres_entries[i].threshold) &&
+	(thresholds.thres_entries[i].threshold != 0xFE)){
+      printf("Attribute ID %i Failed\n",data.vendor_attributes[i].id);
+      failed = 1;
+    } 
+  }   
+  printf("%s\n", ( failed )?
+	 "SMART overall-health self-assessment test result: FAILED!\n"
+	 "Drive failure expected in less than 24 hours. SAVE ALL DATA":
+	 "SMART overall-health self-assessment test result: PASSED");
 }
 
 void ataPrintSmartAttribName ( unsigned char id ){
@@ -722,322 +770,195 @@ void ataPrintSmartAttribName ( unsigned char id ){
  Called by smartctl to access ataprint  
 **/
 
-void ataPrintMain ( int fd )
-{
-   struct hd_driveid drive;
-   struct ata_smart_values smartval;
-   struct ata_smart_thresholds smartthres;
-   struct ata_smart_errorlog smarterror;
-   struct ata_smart_selftestlog smartselftest;
-
-   if ( driveinfo )
-   {
-      if (  ataReadHDIdentity ( fd, &drive) != 0 )
-      {
-         printf("Smartctl: Hard Drive Identity Failed\n");
-         exit(0);	
-      } 
-		
-      ataPrintDriveInfo(drive); 
-		
-
-      if (ataSmartSupport(drive))
-      {
-          printf ("SMART support is: ");
-	  
-          if ( ataSmartStatus(fd) != 0) 
-          {
-              printf( "Disabled\n");
-              printf( "Use option -%c to enable\n\n", SMARTENABLE );
-              exit(0);
-          }
-          else { 
-              printf( "Enabled\n\n");
-          } 
-      }
-      else {
-           printf("SMART support is: Unavailable. Device lacks SMART capability.\n\n");
-	   exit (0);
-      }
+void ataPrintMain (int fd){
+  struct hd_driveid drive;
+  struct ata_smart_values smartval;
+  struct ata_smart_thresholds smartthres;
+  struct ata_smart_errorlog smarterror;
+  struct ata_smart_selftestlog smartselftest;
+  int timewait;
+  
+  // Start by getting Drive ID information.  We need this, to know if SMART is supported.
+  if (ataReadHDIdentity(fd,&drive)){
+    printf("Smartctl: Hard Drive Read Identity Failed\n\n");
+    exit(-1);	
   }
-
-  if ( smartdisable )
-  {
-		
-     if ( ataDisableSmart(fd) != 0) 
-     {
-	printf( "Smartctl: SMART Enable Failed\n");
-	exit(-1);
-     }
-    
-     printf("SMART Disabled\n");
-     exit (0);
-		
-   }
-
-   if ( smartenable )
-   {
-      if ( ataEnableSmart(fd) != 0) 
-	{
-          printf( "Smartctl: SMART Enable Failed\n");
-          exit(-1);
-	}
-
-      if (ataSmartStatus(fd)==0)
-	printf("SMART Enabled\n");
-      else
-	printf( "Smartctl: SMART Enable Failed for unknown reasons\n");
-   }
-   
-   
-   if ( smartautosavedisable ){
-     if (ataDisableAutoSave(fd) != 0)
-       {
-	 printf( "Smartctl: SMART Disable Attribute Autosave Failed\n");
-	 exit(-1);
-       }     
-     printf("SMART Attribute Autosave Disabled\n");
-   }
-	
-   if ( smartautosaveenable ){
-     if (ataEnableAutoSave(fd) != 0)
-       {
-	 printf( "Smartctl: SMART Enable Attribute Autosave Failed\n");
-	 exit(-1);
-       } 
-     printf("SMART Attribute Autosave Enabled\n");
-   }
-
-   /* for everything else read values and thresholds 
-   are needed */	
-
-   if ( ataReadSmartValues ( fd, &smartval) != 0 )
-   {
-      printf("Smartctl: SMART Values Read Failed\n");
-      exit (-1);
-   }
-
-   if ( ataReadSmartThresholds ( fd, &smartthres) != 0 )
-   {
-      printf("Smartctl: SMART Thresholds Read Failed\n");
-      exit (-1); 
-   }
-	
-   if ( checksmart )
-   {
-	/* pseudo is used because linux does not support access to
-	   Task File registers */
-	// I am very confused by this comment.  Does anyone get it?  Bruce
-      ataPsuedoCheckSmart ( smartval , smartthres);
-
-   }
-	
-   if (  generalsmartvalues )
-   {
-      ataPrintGeneralSmartValues( smartval ); 
-   }
-
-   if ( smartvendorattrib )
-   {
-      PrintSmartAttribWithThres( smartval, smartthres);
-   }
-	
-   if ( smarterrorlog )
-   {
-      if ( isSmartErrorLogCapable(smartval) == 0)
-      {
-          printf("Device does not support Error Logging\n");
-      } 
-      else
-      {
-         if ( ataReadErrorLog ( fd, &smarterror) != 0 )
-	 {
-             printf("Smartctl: SMART Errorlog Read Failed\n");
-         }
-         else
-         {
-             ataPrintSmartErrorlog ( smarterror); 
-         }
-      }
+  
+  // Print most drive identity information if requested
+  if (driveinfo){
+    printf("\n=== START OF INFORMATION SECTION ===\n");
+    ataPrintDriveInfo(drive);
+  }
+  
+  // now check if drive supports SMART; otherwise time to exit
+  if (!ataSmartSupport(drive)){
+    printf("SMART support is: Unavailable - device lacks SMART capability.\n");
+    exit (0);
+  }
+  
+  // Now print remaining drive info: is SMART enabled?    
+  if (driveinfo){
+    printf("SMART support is: Available - device has SMART capability.\n");
+    if (ataDoesSmartWork(fd))
+      printf("SMART support is: Enabled\n");
+    else
+      printf("SMART support is: Disabled\n");
+  }
+  
+  // START OF THE ENABLE/DISABLE SECTION OF THE CODE
+  if (smartenable || smartdisable || 
+      smartautosaveenable || smartautosavedisable || 
+      smartautoofflineenable || smartautoofflinedisable)
+    printf("\n=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
+
+  // Enable/Disable SMART commands
+  if (smartenable){
+    if (ataEnableSmart(fd)) {
+      printf("Smartctl: SMART Enable Failed.\n\n");
+      exit(-1);
     }
-	
-
-   if ( smartselftestlog )
-   {
-       if ( isSmartErrorLogCapable(smartval) == 0)
-       {
-           printf("Device does not support Self Test Logging\n");
-       }
-       else
-       {
-	    if (  ataReadSelfTestLog( fd, &smartselftest) != 0 )
-            {
-                printf("Smartctl: SMART Self Test Log Read Failed\n");
-            }
-            else
-            {
-                 ataPrintSmartSelfTestlog (smartselftest); 
-            }
-        } 
+    else
+      printf("SMART Enabled.\n");
+  }
+  
+  // From here on, every command requires that SMART be enabled...
+  if (!ataDoesSmartWork(fd)) {
+    printf("SMART Disabled. Use option -%c to enable it.\n", SMARTENABLE );
+    exit(0);
+  }
+  
+  // Turn off SMART on device
+  if (smartdisable){    
+    if (ataDisableSmart(fd)) {
+      printf( "Smartctl: SMART Disable Failed.\n\n");
+      exit(-1);
     }
+    printf("SMART Disabled. Use option -%c to enable it.\n",SMARTENABLE);
+    exit (0);		
+  }
+  
+  // Enable/Disable Auto-save attributes
+  if (smartautosaveenable){
+    if (ataEnableAutoSave(fd)){
+      printf( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n");
+      exit(-1);
+    } 
+    printf("SMART Attribute Autosave Enabled\n");
+  }
+  if (smartautosavedisable){
+    if (ataDisableAutoSave(fd)){
+      printf( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n");
+      exit(-1);
+    }     
+    printf("SMART Attribute Autosave Disabled\n");
+  }
+  
+  // for everything else read values and thresholds are needed
+  if (ataReadSmartValues(fd, &smartval)){
+    printf("Smartctl: SMART Values Read Failed.\n\n");
+    exit (-1);
+  }
+  if (ataReadSmartThresholds(fd, &smartthres)){
+    printf("Smartctl: SMART Thresholds Read Failed.\n\n");
+    exit (-1); 
+  }
 
-    if (  smartautoofflineenable  )
-    {
-        if ( !isSupportAutomaticTimer (smartval))
-        {
-            printf("Device does not support SMART Automatic Timers\n");
-            exit(-1);
-        }
-
-        if ( ataEnableAutoOffline (fd) != 0) 
-        {
-            printf( "Smartctl: SMART Enable Automatic Offline Failed\n");
-            exit(-1);
-        }
-        
-        printf ("SMART Automatic Offline Testing Enabled every four hours\n");
+  // Enable/Disable Off-line testing
+  if (smartautoofflineenable){
+    if (!isSupportAutomaticTimer (smartval)){
+      printf("Device does not support SMART Automatic Timers.\n\n");
+      exit(-1);
     }
+    if (ataEnableAutoOffline (fd)){
+      printf( "Smartctl: SMART Enable Automatic Offline Failed.\n\n");
+      exit(-1);
+    }    
+    printf ("SMART Automatic Offline Testing Enabled every four hours.\n");
+  }
+  if (smartautoofflinedisable){
+    if (!isSupportAutomaticTimer (smartval)){
+      printf("Device does not support SMART Automatic Timers.\n\n");
+      exit(-1);
+    }		
+    if ( ataDisableAutoOffline (fd)){
+      printf( "Smartctl: SMART Disable Automatic Offline Failed.\n\n");
+      exit(-1);
+    }
+    printf ("SMART Automatic Offline Testing Disabled.\n");
+  }
 
-    if (  smartautoofflinedisable  )
-    {
-        if ( !isSupportAutomaticTimer (smartval))
-        {
-            printf("Device does not support SMART Automatic Timers\n");
-            exit(-1);
-        }
-			
-        if ( ataDisableAutoOffline (fd) != 0) 
-        {
-            printf( "Smartctl: SMART Disable Automatic Offline Failed\n");
-            exit(-1);
-        }
-         
-        printf ("SMART Automatic Offline Testing Disabled\n");
-
-     }
-
-
-     if ( smartexeoffimmediate )
-     {
-        if ( ataSmartOfflineTest (fd) != 0) 
-	{
-            printf( "Smartctl: SMART Offline Failed\n");
-            exit(-1);
-        }
-
-        printf ("Drive Command Successful offline test has begun\n");
-        printf ("Please wait %d seconds for test to complete\n", 
-                 isOfflineTestTime(smartval) );
-        printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
-	exit (0);
-     }
-
-     if ( smartshortcapselftest )
-     {
-         if ( ! isSupportSelfTest(smartval) )
-         {
-             printf ("ERROR: device does not support Self-Test function\n");
-             exit(-1);
-         }
-		
-         if ( ataSmartShortCapSelfTest (fd) != 0) 
-         {
-              printf( "Smartctl: SMART Short Self Test Failed\n");
-              exit(-1);
-         }
-     
-         printf ("Drive Command Successful offline test has begun\n");
-         printf ("Please wait %d minutes for test to complete\n", 
-                  isShortSelfTestTime (smartval) );
-	 printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
+  // START OF READ-ONLY OPTIONS APART FROM -p and -i
+  if (checksmart || generalsmartvalues || smartvendorattrib || smarterrorlog || smartselftestlog)
+    printf("\n=== START OF READ SMART DATA SECTION ===\n");
+
+  // Check SMART status
+  if (checksmart)
+    // Eventually when working use the ataSmartStatus2 function here.
+    // This will then not require read values & thresholds above, and
+    // shouldl be moved in the code to just before the read values &
+    // thresholds statements.
+    ataPseudoCheckSmart(smartval, smartthres);
+  
+  // Print general SMART values
+  if (generalsmartvalues)
+    ataPrintGeneralSmartValues(smartval); 
+  
+  // Print vendor-specific attributes
+  if (smartvendorattrib)
+    PrintSmartAttribWithThres(smartval, smartthres);
 	
-         /* Make sure Offline testing is last thing done */
-        exit (0);
-     }
+  // Print SMART error log
+  if (smarterrorlog){
+    if (!isSmartErrorLogCapable(smartval))
+      printf("Device does not support Error Logging\n");
+    else {
+      if (ataReadErrorLog(fd, &smarterror))
+	printf("Smartctl: SMART Errorlog Read Failed\n");
+      else
+	ataPrintSmartErrorlog(smarterror);
+    }
+  }
 
-     if ( smartshortselftest )
-     {
-        if ( ! isSupportSelfTest(smartval) )
-        {
-            printf ("ERROR: device does not support Self-Test function\n");
-            exit(-1);
-        }
-		
-        if ( ataSmartShortSelfTest (fd) != 0) 
-        {
-            printf( "Smartctl: SMART Short Self Test Failed\n");
-            exit(-1);
-        }
-
-        printf ("Drive Command Successful offline test has begun\n");
-        printf ("Please wait %d minutes for test to complete\n", 
-                 isShortSelfTestTime (smartval) );
-        printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
-		
-	/* Make sure Offline testing is last thing done */
-	exit (0);
-     }
- 
-	
-     if ( smartextendselftest )
-     {
-        if ( ! isSupportSelfTest(smartval) )
-        {
-           printf ("ERROR: device does not support Self-Test function\n");
-           exit(-1);
-        }
-
-        if ( ataSmartExtendSelfTest (fd) != 0) 
-        {
-           printf( "SMART Extended Self Test Failed\n");
-           exit(-1);
-        }
-		
-        printf ("Drive Command Successful self test has begun\n");
-        printf ("Please wait %d minutes for test to complete\n", 
-                 isExtendedSelfTestTime(smartval) );
-        printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
-	
-        exit (0);
-     }
+  // Print SMART self-test log
+  if (smartselftestlog){
+    if (!isSmartErrorLogCapable(smartval))
+      printf("Device does not support Self Test Logging\n");
+    else {
+      if(ataReadSelfTestLog(fd, &smartselftest))
+	printf("Smartctl: SMART Self Test Log Read Failed\n");
+      else
+	ataPrintSmartSelfTestlog(smartselftest); 
+    } 
+  }
+  
+  // START OF THE TESTING SECTION OF THE CODE.  IF NO TESTING, RETURN
+  if (testcase==-1)
+    return;
 
-	
-     if ( smartextendcapselftest )
-     {
-         if ( ! isSupportSelfTest(smartval) )
-         {
-            printf ("ERROR: device does not support self test function\n");
-            exit(-1);
-         }
-
-         if ( ataSmartExtendCapSelfTest (fd) != 0) 
-         {
-            printf( "SMART Extended Self Test Failed\n");
-            exit(-1);
-         }
-		
-            printf ("Drive Command Successful captive extended self test has begun\n");
-            printf ("Please wait %d minutes for test to complete\n", 
-                    isExtendedSelfTestTime(smartval) );
-            printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
-            exit (0);
-     }
+  printf("\n=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
 
-     if ( smartselftestabort )
-     {
-        if ( ! isSupportSelfTest(smartval) )
-        {
-            printf ("ERROR: device does not support Self-Test function\n");
-            exit(-1);
-        }
-
-        if ( ataSmartSelfTestAbort (fd) != 0) 
-        {
-            printf( "SMART Self Test Abort Failed\n");
-            exit(-1);
-        }
-		
-        printf ("Drive Command Successful self test aborted\n");
-    }		
-	
+  
+  // if doing a self-test, be sure it's supported by the hardware
+  if (testcase==OFFLINE_FULL_SCAN &&  !isSupportExecuteOfflineImmediate(smartval)){
+    printf("ERROR: device does not support Execute Off-Line Immediate function.\n\n");
+    exit(-1);
+  }
+  else if (!isSupportSelfTest(smartval)){
+    printf ("ERROR: device does not support Self-Test functions.\n\n");
+    exit(-1);
+  }
+  
+  // Now do the test
+  if (ataSmartTest(fd, testcase))
+    exit(-1);
+  
+  // Tell user how long test will take to complete  
+  if ((timewait=TestTime(smartval,testcase))){ 
+    printf ("Please wait %d %s for test to complete.\n",
+	    timewait, testcase==OFFLINE_FULL_SCAN?"seconds":"minutes");
+    
+    if (testcase!=SHORT_CAPTIVE_SELF_TEST && testcase!=EXTEND_CAPTIVE_SELF_TEST)
+      printf ("Use smartctl -%c to abort test.\n", SMARTSELFTESTABORT);	
+  }    
+  return;
 }
diff --git a/sm5/ataprint.h b/sm5/ataprint.h
index bc3f0ebb0661e4b730f367de4abaf5b858a71750..2184b51913c7feb52312e524fa4e092abc6e8cb9 100644
--- a/sm5/ataprint.h
+++ b/sm5/ataprint.h
@@ -1,4 +1,4 @@
-//  $Id: ataprint.h,v 1.5 2002/10/15 14:24:27 ballen4705 Exp $
+//  $Id: ataprint.h,v 1.6 2002/10/20 19:22:02 ballen4705 Exp $
 
 /*
  * ataprint.c
@@ -32,11 +32,7 @@
 #include "atacmds.h"
 
 
-/* Print Format of Structures for SMART information */
-
-
 /* Prints ATA Drive Information and S.M.A.R.T. Capability */
-
 void ataPrintDriveInfo (struct hd_driveid);
 
 void ataPrintGeneralSmartValues (struct ata_smart_values);
@@ -52,12 +48,11 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
 
 void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data);
 
-void ataPsuedoCheckSmart (struct ata_smart_values , 
+void ataPseudoCheckSmart (struct ata_smart_values , 
                           struct ata_smart_thresholds );
 
 /* Prints Attribute Name for standard SMART attributes */
 /* prints 20 character string */
-
 void ataPrintSmartAttribName (unsigned char id);
 
 void ataPrintMain ( int fd );
diff --git a/sm5/extern.h b/sm5/extern.h
index ce81cd2bacf3453ecdf38bae1040945bed8f8c06..a49096f4ff22608bbd70d18299ba0228f3e9ab9a 100644
--- a/sm5/extern.h
+++ b/sm5/extern.h
@@ -1,4 +1,4 @@
-//  $Id: extern.h,v 1.5 2002/10/15 14:24:27 ballen4705 Exp $
+//  $Id: extern.h,v 1.6 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * extern.h
  *
@@ -46,5 +46,5 @@ extern unsigned char smartautoofflinedisable;
 extern unsigned char smartautosaveenable;
 extern unsigned char smartautosavedisable;
 extern unsigned char smart009minutes;
-
+extern int           testcase;
 #endif
diff --git a/sm5/smartctl.c b/sm5/smartctl.c
index f90a0429158fa89a8da07123bb15d1a47b943235..c4995adc39cf061ab315cf167947f95a74ca5f10 100644
--- a/sm5/smartctl.c
+++ b/sm5/smartctl.c
@@ -1,4 +1,4 @@
-//  $Id: smartctl.c,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $
+//  $Id: smartctl.c,v 1.10 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * smartctl.c
  *
@@ -58,6 +58,7 @@ unsigned char smartautosaveenable     = FALSE;
 unsigned char smartautosavedisable    = FALSE;
 unsigned char printcopyleft           = FALSE;
 unsigned char smart009minutes         = FALSE;
+int           testcase                = -1;
 
 
 /*  void Usage (void) 
@@ -66,7 +67,7 @@ unsigned char smart009minutes         = FALSE;
 
 
 void Usage ( void){
-  printf( "usage: smartctl -[options] [device]\n");
+  printf( "Usage: smartctl -[options] [device]\n\n");
   printf( "Read Only Options:\n");
   printf( "\t\t%c\t\tShow version, copyright and license information\n", PRINTCOPYLEFT);
   printf( "\t\t%c\t\tShow all S.M.A.R.T. Information (ATA and SCSI)\n",  SMARTVERBOSEALL);
@@ -94,12 +95,12 @@ void Usage ( void){
   printf( "\t\t%c\t\tExecute Short Self Test (Captive Mode) (ATA Only)\n",    SMARTSHORTCAPSELFTEST );
   printf( "\t\t%c\t\tExecute Extended Self Test (ATA Only)\n",                SMARTEXTENDSELFTEST );
   printf( "\t\t%c\t\tExecute Extended Self Test (Captive Mode) (ATA Only)\n", SMARTEXTENDCAPSELFTEST );
-  printf( "\t\t%c\t\tExecute Self Test Abort (ATA Only)\n\n",                 SMARTSELFTESTABORT );
+  printf( "\t\t%c\t\tExecute Self Test Abort (ATA Only)\n",                 SMARTSELFTESTABORT );
   printf( "Examples:\n");
   printf("\tsmartctl -etf /dev/hda   (Enables S.M.A.R.T. on first disk)\n");
   printf("\tsmartctl -a   /dev/hda   (Prints all S.M.A.R.T. information)\n");
-  printf("\tsmartctl -X   /dev/hda   (Executes extended disk self-test)\n");
-  printf("Please see the man pages or the web site for further information.\n");
+  printf("\tsmartctl -X   /dev/hda   (Executes extended disk self-test)\n\n");
+  printf("Please see the man pages or %s for further information.\n",PROJECTHOME);
 
 }
 
@@ -131,7 +132,6 @@ void ParseOpts (int argc, char** argv){
       driveinfo  = TRUE;
       break;		
     case CHECKSMART :
-      driveinfo  = TRUE;
       checksmart = TRUE;		
       break;
     case SMARTVERBOSEALL :
@@ -174,21 +174,27 @@ void ParseOpts (int argc, char** argv){
       break;
     case SMARTEXEOFFIMMEDIATE:
       smartexeoffimmediate = TRUE;
+      testcase=OFFLINE_FULL_SCAN;
       break;
     case SMARTSHORTSELFTEST :
       smartshortselftest = TRUE;
+      testcase=SHORT_SELF_TEST;
       break;
     case SMARTEXTENDSELFTEST :
       smartextendselftest = TRUE;
+      testcase=EXTEND_SELF_TEST;
       break;
     case SMARTSHORTCAPSELFTEST:
       smartshortcapselftest = TRUE;
+      testcase=SHORT_CAPTIVE_SELF_TEST;
       break;
     case SMARTEXTENDCAPSELFTEST:
       smartextendcapselftest = TRUE;
+      testcase=EXTEND_CAPTIVE_SELF_TEST;
       break;
     case SMARTSELFTESTABORT:
       smartselftestabort = TRUE;
+      testcase=ABORT_SELF_TEST;
       break;
     default:
       Usage();
@@ -197,9 +203,9 @@ void ParseOpts (int argc, char** argv){
     
     if ( (smartexeoffimmediate + smartshortselftest +
 	  smartextendselftest + smartshortcapselftest +
-	  smartextendcapselftest ) > 1){
+	  smartextendcapselftest +smartselftestabort ) > 1){
       Usage();
-      printf ("\n ERROR: smartctl can only run a single test at a time \n");
+      printf ("\nERROR: smartctl can only run a single test (or abort) at a time.\n\n");
       exit(-1);
     }
   }
@@ -212,19 +218,20 @@ int main (int argc, char **argv){
   char *device;
   
   printf("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
-  printf("Home page of smartctl is %s\n\n",PROJECTHOME);
+  printf("Home page of smartctl is %s\n",PROJECTHOME);
   
   // Part input arguments
   ParseOpts (argc,argv);
   
   // Print Copyright/License info if needed
   if (printcopyleft){
-    printf("smartctl comes with ABSOLUTELY NO WARRANTY. This\n");
+    printf("\nsmartctl comes with ABSOLUTELY NO WARRANTY. This\n");
     printf("is free software, and you are welcome to redistribute it\n");
     printf("under the terms of the GNU General Public License Version 2.\n");
     printf("See http://www.gnu.org for further details.\n\n");
-    printf("CVS version ID %s\n","$Id: smartctl.c,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $");
-    exit(0);
+    printf("CVS version ID %s\n","$Id: smartctl.c,v 1.10 2002/10/20 19:22:02 ballen4705 Exp $");
+    if (argc==2)
+      exit(0);
  }
 
   // Further argument checking
diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp
index aed6cba2b36724df946186f62e9e21a6fe5d269f..1a5bf755d71194154e3a944bcc9d4e5f6f087f58 100644
--- a/sm5/smartctl.cpp
+++ b/sm5/smartctl.cpp
@@ -1,4 +1,4 @@
-//  $Id: smartctl.cpp,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $
+//  $Id: smartctl.cpp,v 1.10 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * smartctl.c
  *
@@ -58,6 +58,7 @@ unsigned char smartautosaveenable     = FALSE;
 unsigned char smartautosavedisable    = FALSE;
 unsigned char printcopyleft           = FALSE;
 unsigned char smart009minutes         = FALSE;
+int           testcase                = -1;
 
 
 /*  void Usage (void) 
@@ -66,7 +67,7 @@ unsigned char smart009minutes         = FALSE;
 
 
 void Usage ( void){
-  printf( "usage: smartctl -[options] [device]\n");
+  printf( "Usage: smartctl -[options] [device]\n\n");
   printf( "Read Only Options:\n");
   printf( "\t\t%c\t\tShow version, copyright and license information\n", PRINTCOPYLEFT);
   printf( "\t\t%c\t\tShow all S.M.A.R.T. Information (ATA and SCSI)\n",  SMARTVERBOSEALL);
@@ -94,12 +95,12 @@ void Usage ( void){
   printf( "\t\t%c\t\tExecute Short Self Test (Captive Mode) (ATA Only)\n",    SMARTSHORTCAPSELFTEST );
   printf( "\t\t%c\t\tExecute Extended Self Test (ATA Only)\n",                SMARTEXTENDSELFTEST );
   printf( "\t\t%c\t\tExecute Extended Self Test (Captive Mode) (ATA Only)\n", SMARTEXTENDCAPSELFTEST );
-  printf( "\t\t%c\t\tExecute Self Test Abort (ATA Only)\n\n",                 SMARTSELFTESTABORT );
+  printf( "\t\t%c\t\tExecute Self Test Abort (ATA Only)\n",                 SMARTSELFTESTABORT );
   printf( "Examples:\n");
   printf("\tsmartctl -etf /dev/hda   (Enables S.M.A.R.T. on first disk)\n");
   printf("\tsmartctl -a   /dev/hda   (Prints all S.M.A.R.T. information)\n");
-  printf("\tsmartctl -X   /dev/hda   (Executes extended disk self-test)\n");
-  printf("Please see the man pages or the web site for further information.\n");
+  printf("\tsmartctl -X   /dev/hda   (Executes extended disk self-test)\n\n");
+  printf("Please see the man pages or %s for further information.\n",PROJECTHOME);
 
 }
 
@@ -131,7 +132,6 @@ void ParseOpts (int argc, char** argv){
       driveinfo  = TRUE;
       break;		
     case CHECKSMART :
-      driveinfo  = TRUE;
       checksmart = TRUE;		
       break;
     case SMARTVERBOSEALL :
@@ -174,21 +174,27 @@ void ParseOpts (int argc, char** argv){
       break;
     case SMARTEXEOFFIMMEDIATE:
       smartexeoffimmediate = TRUE;
+      testcase=OFFLINE_FULL_SCAN;
       break;
     case SMARTSHORTSELFTEST :
       smartshortselftest = TRUE;
+      testcase=SHORT_SELF_TEST;
       break;
     case SMARTEXTENDSELFTEST :
       smartextendselftest = TRUE;
+      testcase=EXTEND_SELF_TEST;
       break;
     case SMARTSHORTCAPSELFTEST:
       smartshortcapselftest = TRUE;
+      testcase=SHORT_CAPTIVE_SELF_TEST;
       break;
     case SMARTEXTENDCAPSELFTEST:
       smartextendcapselftest = TRUE;
+      testcase=EXTEND_CAPTIVE_SELF_TEST;
       break;
     case SMARTSELFTESTABORT:
       smartselftestabort = TRUE;
+      testcase=ABORT_SELF_TEST;
       break;
     default:
       Usage();
@@ -197,9 +203,9 @@ void ParseOpts (int argc, char** argv){
     
     if ( (smartexeoffimmediate + smartshortselftest +
 	  smartextendselftest + smartshortcapselftest +
-	  smartextendcapselftest ) > 1){
+	  smartextendcapselftest +smartselftestabort ) > 1){
       Usage();
-      printf ("\n ERROR: smartctl can only run a single test at a time \n");
+      printf ("\nERROR: smartctl can only run a single test (or abort) at a time.\n\n");
       exit(-1);
     }
   }
@@ -212,19 +218,20 @@ int main (int argc, char **argv){
   char *device;
   
   printf("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
-  printf("Home page of smartctl is %s\n\n",PROJECTHOME);
+  printf("Home page of smartctl is %s\n",PROJECTHOME);
   
   // Part input arguments
   ParseOpts (argc,argv);
   
   // Print Copyright/License info if needed
   if (printcopyleft){
-    printf("smartctl comes with ABSOLUTELY NO WARRANTY. This\n");
+    printf("\nsmartctl comes with ABSOLUTELY NO WARRANTY. This\n");
     printf("is free software, and you are welcome to redistribute it\n");
     printf("under the terms of the GNU General Public License Version 2.\n");
     printf("See http://www.gnu.org for further details.\n\n");
-    printf("CVS version ID %s\n","$Id: smartctl.cpp,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $");
-    exit(0);
+    printf("CVS version ID %s\n","$Id: smartctl.cpp,v 1.10 2002/10/20 19:22:02 ballen4705 Exp $");
+    if (argc==2)
+      exit(0);
  }
 
   // Further argument checking
diff --git a/sm5/smartd.c b/sm5/smartd.c
index 900cfe55da1c49a968e67b617901c4e6a0418d13..b593fbcb9180f638ae54e4958a7f8640d05e38ed 100644
--- a/sm5/smartd.c
+++ b/sm5/smartd.c
@@ -1,4 +1,4 @@
-//  $Id: smartd.c,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $
+//  $Id: smartd.c,v 1.10 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * smartd.c
  *
@@ -117,6 +117,10 @@ void atadevicescan ( atadevices_t *devices){
     
     printout(LOG_INFO,"%s Found and is SMART capable\n",device);
     
+    // This makes NO sense.  We may want to know if the drive supports
+    // Offline Surface Scan, for example.  But checking if it supports
+    // self-tests seems useless. In any case, smartd NEVER uses this
+    // field anywhere...
     devices[numatadevices].selftest = 
       isSupportSelfTest(devices[numatadevices].smartval);
 
@@ -213,6 +217,8 @@ int ataCheckDevice( atadevices_t *drive){
   if ((failed=ataCheckSmart(tempsmartval,tempsmartthres)))
     printout(LOG_CRIT,"Device: %s, Failed attribute: %i\n",drive->devicename,failed);
   
+  // WHEN IT WORKS, we should here add a call to ataSmartStatus2()
+
   // see if any values have changed.  Second argument is new values
   ataCompareSmartValues (drive , tempsmartval);
   
@@ -272,7 +278,7 @@ char copyleftstring[]=
 "is free software, and you are welcome to redistribute it\n"
 "under the terms of the GNU General Public License Version 2.\n"
 "See http://www.gnu.org for further details.\n\n"
-"CVS Version ID $Id: smartd.c,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $\n";
+"CVS Version ID $Id: smartd.c,v 1.10 2002/10/20 19:22:02 ballen4705 Exp $\n";
 
 const char opts[] = { DEBUGMODE, EMAILNOTIFICATION, PRINTCOPYLEFT,'\0' };
 
diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp
index d070985caca394a87426fca58c598cd3418cae6d..ce1aa9ff2fca8952d7aa55d37d206e0e15c2ce80 100644
--- a/sm5/smartd.cpp
+++ b/sm5/smartd.cpp
@@ -1,4 +1,4 @@
-//  $Id: smartd.cpp,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $
+//  $Id: smartd.cpp,v 1.10 2002/10/20 19:22:02 ballen4705 Exp $
 /*
  * smartd.c
  *
@@ -117,6 +117,10 @@ void atadevicescan ( atadevices_t *devices){
     
     printout(LOG_INFO,"%s Found and is SMART capable\n",device);
     
+    // This makes NO sense.  We may want to know if the drive supports
+    // Offline Surface Scan, for example.  But checking if it supports
+    // self-tests seems useless. In any case, smartd NEVER uses this
+    // field anywhere...
     devices[numatadevices].selftest = 
       isSupportSelfTest(devices[numatadevices].smartval);
 
@@ -213,6 +217,8 @@ int ataCheckDevice( atadevices_t *drive){
   if ((failed=ataCheckSmart(tempsmartval,tempsmartthres)))
     printout(LOG_CRIT,"Device: %s, Failed attribute: %i\n",drive->devicename,failed);
   
+  // WHEN IT WORKS, we should here add a call to ataSmartStatus2()
+
   // see if any values have changed.  Second argument is new values
   ataCompareSmartValues (drive , tempsmartval);
   
@@ -272,7 +278,7 @@ char copyleftstring[]=
 "is free software, and you are welcome to redistribute it\n"
 "under the terms of the GNU General Public License Version 2.\n"
 "See http://www.gnu.org for further details.\n\n"
-"CVS Version ID $Id: smartd.cpp,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $\n";
+"CVS Version ID $Id: smartd.cpp,v 1.10 2002/10/20 19:22:02 ballen4705 Exp $\n";
 
 const char opts[] = { DEBUGMODE, EMAILNOTIFICATION, PRINTCOPYLEFT,'\0' };