From a522417f6a4ee4cbc27a0299d163311f6074b1b2 Mon Sep 17 00:00:00 2001
From: ballen4705 <ballen4705@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Sat, 12 Oct 2002 11:10:01 +0000
Subject: [PATCH] Added "minutes" option -n to smartctl for Hitachi drives that
 store raw power on time attributes in minutes not hours

Removed lots of <CONTROL-M> characters from the SCSI files

Added code to identify the exact ATA/ATAPI spec of a drive
Modified the printout to be consistent (eg SMART everywhere,
not S.M.A.R.T. in some places and not in others).


git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@37 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/README       |   22 +-
 sm5/TODO         |    4 +-
 sm5/atacmds.c    |  164 +++--
 sm5/atacmds.cpp  |  164 +++--
 sm5/atacmds.h    |   37 +-
 sm5/ataprint.c   |  303 +++++----
 sm5/ataprint.cpp |  303 +++++----
 sm5/extern.h     |   83 +--
 sm5/scsicmds.c   | 1622 +++++++++++++++++++++++-----------------------
 sm5/scsicmds.cpp | 1622 +++++++++++++++++++++++-----------------------
 sm5/scsicmds.h   |  542 ++++++++--------
 sm5/scsiprint.h  |   56 +-
 sm5/smartctl.8   |   19 +-
 sm5/smartctl.c   |   73 +--
 sm5/smartctl.cpp |   73 +--
 sm5/smartctl.h   |    3 +-
 16 files changed, 2628 insertions(+), 2462 deletions(-)

diff --git a/sm5/README b/sm5/README
index 60193d41a..9c6f85ede 100644
--- a/sm5/README
+++ b/sm5/README
@@ -69,12 +69,17 @@ To install, use the commands:
 The tools require Linux kernel 2.2.14 or greater in order to run. Any
 recent Linux distribution should support this package.
  
-The files installed are:
-/usr/sbin/smartd                   [Executable daemon]
-/usr/sbin/smartctl                 [Executable command-line utility]
-/etc/rc.d/init.d/smartd            [Init/Startup script for smartd]
-/usr/share/man/man8/smartctl.8.gz  [Manual page]
-/usr/share/man/man8/smartd.8.gz    [Manual page]
+Ten files are installed:
+/usr/sbin/smartd                           [Executable daemon]
+/usr/sbin/smartctl                         [Executable command-line utility]
+/etc/rc.d/init.d/smartd                    [Init/Startup script for smartd]
+/usr/share/man/man8/smartctl.8.gz          [Manual page]
+/usr/share/man/man8/smartd.8.gz            [Manual page]
+/usr/share/doc/smartmontools-5.0/README    [What you are reading!]
+/usr/share/doc/smartmontools-5.0/TODO      [Things that need to be done/fixed]
+/usr/share/doc/smartmontools-5.0/CHANGELOG [A log of changes -- but we'll use CVS]
+/usr/share/doc/smartmontools-5.0/COPYING   [GNU Public License.] 
+/usr/share/doc/smartmontools-5.0/VERSION   [Version number -- don't ask!]
 
 Source and binary RPM files are available at the website listed above.
 
@@ -103,6 +108,9 @@ l	Prints only the S.M.A.R.T. error log
 L       Prints only the S.M.A.R.T. self-test log
 a	Prints all parameters for i,c,g,v,t,l,L
 
+Modify Display for Vendor-specific S.M.A.R.T. Raw Attribute Data:
+m       Converts Raw Attribute-009 from minutes to hours (Hitachi)
+
 Enable/Disable commands:
 e	Enables S.M.A.R.T. on device
 d	Disables S.M.A.R.T. on device
@@ -172,4 +180,4 @@ Fax: (408) 867-2115
 E-Mail: 250-1752@mcimail.com.
 
 
-$Id: README,v 1.4 2002/10/11 09:20:32 ballen4705 Exp $
+$Id: README,v 1.5 2002/10/12 11:10:01 ballen4705 Exp $
diff --git a/sm5/TODO b/sm5/TODO
index 6ad5411e8..c8527c2c5 100644
--- a/sm5/TODO
+++ b/sm5/TODO
@@ -2,7 +2,7 @@ TODO list for smartmontools:
 
 Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
-$Id: TODO,v 1.4 2002/10/11 09:20:32 ballen4705 Exp $
+$Id: TODO,v 1.5 2002/10/12 11:10:01 ballen4705 Exp $
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the Free
@@ -26,5 +26,3 @@ Produce version for ATA/ATAPI-7
 Modifications
 -------------
 Command line option to specify devices to look for in smartd startup
-
-Command line option to divide disk power-on lifetime by 60 if raw data is stored in minutes not hours (Hitachi!)
diff --git a/sm5/atacmds.c b/sm5/atacmds.c
index e03b045c0..a7d424ca2 100644
--- a/sm5/atacmds.c
+++ b/sm5/atacmds.c
@@ -1,4 +1,4 @@
-//  $Id: atacmds.c,v 1.2 2002/10/11 09:20:32 ballen4705 Exp $
+//  $Id: atacmds.c,v 1.3 2002/10/12 11:10:01 ballen4705 Exp $
 /*
  * atacmds.c
  *
@@ -21,6 +21,83 @@
 #include <string.h>
 #include "atacmds.h"
 
+
+// Drive identity stuff shamelessly ripped from hdparm 5.2
+#define NOVAL_0			0x0000
+#define NOVAL_1			0xffff
+/* word 81: minor version number */
+#define MINOR_MAX 0x1C
+const char *minor_str[] = {			/* word 81 value: */
+  "Device does not report version",		/* 0x0000	*/
+  "ATA-1 X3T9.2 781D prior to revision 4",	/* 0x0001	*/
+  "ATA-1 published, ANSI X3.221-1994",		/* 0x0002	*/
+  "ATA-1 X3T9.2 781D revision 4",		/* 0x0003	*/
+  "ATA-2 published, ANSI X3.279-1996",		/* 0x0004	*/
+  "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-2 X3T10 948D revision 3",		/* 0x0009	*/
+  "ATA-3 published, ANSI X3.298-199x",		/* 0x000a	*/
+  "ATA-3 X3T10 2008D revision 6",		/* 0x000b	*/
+  "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	*/
+  "ATA/ATAPI-4 X3T13 1153D revision 7",		/* 0x000f	*/
+  "ATA/ATAPI-4 T13 1153D revision 18",		/* 0x0010	*/
+  "ATA/ATAPI-4 T13 1153D revision 15",		/* 0x0011	*/
+  "ATA/ATAPI-4 published, ANSI NCITS 317-1998",	/* 0x0012	*/
+  "ATA/ATAPI-5 T13 1321D revision 3",	        /* 0x0013	*/
+  "ATA/ATAPI-4 T13 1153D revision 14",		/* 0x0014	*/
+  "ATA/ATAPI-5 T13 1321D revision 1",		/* 0x0015	*/
+  "ATA/ATAPI-5 published, ANSI NCITS 340-2000",	/* 0x0016	*/
+  "ATA/ATAPI-4 T13 1153D revision 17",		/* 0x0017	*/
+  "ATA/ATAPI-6 T13 1410D revision 0",		/* 0x0018	*/
+  "ATA/ATAPI-6 T13 1410D revision 3a",		/* 0x0019	*/
+  "Reserved",					/* 0x001a	*/
+  "ATA/ATAPI-6 T13 1410D revision 2",		/* 0x001b	*/
+  "ATA/ATAPI-6 T13 1410D revision 1",		/* 0x001c	*/
+  "reserved"					/* 0x001d	*/
+  "reserved"					/* 0x001e	*/
+  "reserved"					/* 0x001f-0xfffe*/
+};
+
+const char actual_ver[] = { 
+  /* word 81 value: */
+  0,		/* 0x0000	WARNING: 	*/
+  1,		/* 0x0001	WARNING: 	*/
+  1,		/* 0x0002	WARNING: 	*/
+  1,		/* 0x0003	WARNING: 	*/
+  2,		/* 0x0004	WARNING:   This array 		*/
+  2,		/* 0x0005	WARNING:   corresponds 		*/
+  3,		/* 0x0006	WARNING:   *exactly*		*/
+  2,		/* 0x0007	WARNING:   to the ATA/		*/
+  3,		/* 0x0008	WARNING:   ATAPI version	*/
+  2,		/* 0x0009	WARNING:   listed in	 	*/
+  3,		/* 0x000a	WARNING:   the 		 	*/
+  3,		/* 0x000b	WARNING:   minor_str 		*/
+  3,		/* 0x000c	WARNING:   array		*/
+  4,		/* 0x000d	WARNING:   above.		*/
+  4,		/* 0x000e	WARNING:  			*/
+  4,		/* 0x000f	WARNING:   If you change 	*/
+  4,		/* 0x0010	WARNING:   that one,      	*/
+  4,		/* 0x0011	WARNING:   change this one	*/
+  4,		/* 0x0012	WARNING:   too!!!        	*/
+  5,		/* 0x0013	WARNING:	*/
+  4,		/* 0x0014	WARNING:	*/
+  5,		/* 0x0015	WARNING:	*/
+  5,		/* 0x0016	WARNING:	*/
+  4,		/* 0x0017	WARNING:	*/
+  6,		/* 0x0018	WARNING:	*/
+  6,		/* 0x0019	WARNING:	*/
+  0,		/* 0x001a	WARNING:	*/
+  6,		/* 0x001b	WARNING:	*/
+  6,		/* 0x001c	WARNING:	*/
+  0		/* 0x001d-0xfffe    		*/
+};
+
+
+
 int ataReadHDIdentity ( int device, struct hd_driveid *buf)
 {
    if (ioctl ( device , HDIO_GET_IDENTITY, buf ) != 0)
@@ -33,64 +110,55 @@ int ataReadHDIdentity ( int device, struct hd_driveid *buf)
 }
 
 
-int ataVersionInfo ( struct hd_driveid drive)
-{
-   int i;
-   int atavalue = 0; 
-	
-#ifdef DEBUG
-#ifdef __NEW_HD_DRIVE_ID
-	printf ("Debug: Ata Version:	 %04x\n", drive.major_rev_num);
-#else
-	printf ("Debug: Ata Version:	 %04x\n", drive.word80);
-#endif
-#endif
- 
-#ifdef __NEW_HD_DRIVE_ID
-	if ( (drive.major_rev_num == 0xffff) || (drive.major_rev_num == 0x000) )
-#else
-	if ( (drive.word80 == 0xffff) || (drive.word80 == 0x000) )
-#endif
-	{
-		
-		return -1;
-
-	}
-
-	for ( i = 1; i < 16; i++ )
-	{
+int ataVersionInfo (const char** description, struct hd_driveid drive){
+  unsigned short major,minor;
+  int i,atavalue=0;
+  
+  // get major and minor ATA revision numbers
 #ifdef __NEW_HD_DRIVE_ID
-		if ( drive.major_rev_num &  ( 0x1 << i) )
+  major=drive.major_rev_num;
+  minor=drive.minor_rev_num;
 #else
-		
+  major=drive.word80;
+  minor=drive.word81;
 #endif
-		{
-			atavalue = i;
-		}
-	}
-	return atavalue;
+  
+  // First check if device has ANY ATA version information in it
+  if (major==NOVAL_0 || major==NOVAL_1) {
+    *description=NULL;
+    return -1;
+  }
+  
+  // The minor revision number has more information - try there first
+  if (minor && (minor<=MINOR_MAX)){
+    int std = actual_ver[minor];
+    if (std) {
+      *description=minor_str[minor];
+      return std;
+    }
+  }
+  
+  // HDPARM has a very complicated algorithm from here on. Since SMART only
+  // exists on ATA-3 and later standards, let's punt on this.  If you don't
+  // like it, please fix it.  The code's in CVS.
+  for (i=1; i<16;i++ )
+    if (major & (0x1<<i))
+      atavalue = i;
+  *description=NULL;
+  return atavalue;
 }
 
 
-
-
-int ataSmartSupport ( struct hd_driveid drive)
-{
+int ataSmartSupport ( struct hd_driveid drive){
 #ifdef __NEW_HD_DRIVE_ID
-	if ( drive.command_set_1 & 0x0001 ){
+  if (drive.command_set_1 & 0x0001)
 #else
-	if ( drive.command_sets & 0x0001 ){
+  if (drive.command_sets & 0x0001)
 #endif
-		return (1); /* drive supports S.M.A.R.T. and is disabled */
-	}
-			
-	return (0);
-
+    return 1; /* drive supports S.M.A.R.T. and is disabled */
+  return 0;
 }
 
-
-
-
 int ataReadSmartValues (int device, struct ata_smart_values *data)
 {	
    int i;
diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index 3de297e01..03ac761a9 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -1,4 +1,4 @@
-//  $Id: atacmds.cpp,v 1.2 2002/10/11 09:20:32 ballen4705 Exp $
+//  $Id: atacmds.cpp,v 1.3 2002/10/12 11:10:01 ballen4705 Exp $
 /*
  * atacmds.c
  *
@@ -21,6 +21,83 @@
 #include <string.h>
 #include "atacmds.h"
 
+
+// Drive identity stuff shamelessly ripped from hdparm 5.2
+#define NOVAL_0			0x0000
+#define NOVAL_1			0xffff
+/* word 81: minor version number */
+#define MINOR_MAX 0x1C
+const char *minor_str[] = {			/* word 81 value: */
+  "Device does not report version",		/* 0x0000	*/
+  "ATA-1 X3T9.2 781D prior to revision 4",	/* 0x0001	*/
+  "ATA-1 published, ANSI X3.221-1994",		/* 0x0002	*/
+  "ATA-1 X3T9.2 781D revision 4",		/* 0x0003	*/
+  "ATA-2 published, ANSI X3.279-1996",		/* 0x0004	*/
+  "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-2 X3T10 948D revision 3",		/* 0x0009	*/
+  "ATA-3 published, ANSI X3.298-199x",		/* 0x000a	*/
+  "ATA-3 X3T10 2008D revision 6",		/* 0x000b	*/
+  "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	*/
+  "ATA/ATAPI-4 X3T13 1153D revision 7",		/* 0x000f	*/
+  "ATA/ATAPI-4 T13 1153D revision 18",		/* 0x0010	*/
+  "ATA/ATAPI-4 T13 1153D revision 15",		/* 0x0011	*/
+  "ATA/ATAPI-4 published, ANSI NCITS 317-1998",	/* 0x0012	*/
+  "ATA/ATAPI-5 T13 1321D revision 3",	        /* 0x0013	*/
+  "ATA/ATAPI-4 T13 1153D revision 14",		/* 0x0014	*/
+  "ATA/ATAPI-5 T13 1321D revision 1",		/* 0x0015	*/
+  "ATA/ATAPI-5 published, ANSI NCITS 340-2000",	/* 0x0016	*/
+  "ATA/ATAPI-4 T13 1153D revision 17",		/* 0x0017	*/
+  "ATA/ATAPI-6 T13 1410D revision 0",		/* 0x0018	*/
+  "ATA/ATAPI-6 T13 1410D revision 3a",		/* 0x0019	*/
+  "Reserved",					/* 0x001a	*/
+  "ATA/ATAPI-6 T13 1410D revision 2",		/* 0x001b	*/
+  "ATA/ATAPI-6 T13 1410D revision 1",		/* 0x001c	*/
+  "reserved"					/* 0x001d	*/
+  "reserved"					/* 0x001e	*/
+  "reserved"					/* 0x001f-0xfffe*/
+};
+
+const char actual_ver[] = { 
+  /* word 81 value: */
+  0,		/* 0x0000	WARNING: 	*/
+  1,		/* 0x0001	WARNING: 	*/
+  1,		/* 0x0002	WARNING: 	*/
+  1,		/* 0x0003	WARNING: 	*/
+  2,		/* 0x0004	WARNING:   This array 		*/
+  2,		/* 0x0005	WARNING:   corresponds 		*/
+  3,		/* 0x0006	WARNING:   *exactly*		*/
+  2,		/* 0x0007	WARNING:   to the ATA/		*/
+  3,		/* 0x0008	WARNING:   ATAPI version	*/
+  2,		/* 0x0009	WARNING:   listed in	 	*/
+  3,		/* 0x000a	WARNING:   the 		 	*/
+  3,		/* 0x000b	WARNING:   minor_str 		*/
+  3,		/* 0x000c	WARNING:   array		*/
+  4,		/* 0x000d	WARNING:   above.		*/
+  4,		/* 0x000e	WARNING:  			*/
+  4,		/* 0x000f	WARNING:   If you change 	*/
+  4,		/* 0x0010	WARNING:   that one,      	*/
+  4,		/* 0x0011	WARNING:   change this one	*/
+  4,		/* 0x0012	WARNING:   too!!!        	*/
+  5,		/* 0x0013	WARNING:	*/
+  4,		/* 0x0014	WARNING:	*/
+  5,		/* 0x0015	WARNING:	*/
+  5,		/* 0x0016	WARNING:	*/
+  4,		/* 0x0017	WARNING:	*/
+  6,		/* 0x0018	WARNING:	*/
+  6,		/* 0x0019	WARNING:	*/
+  0,		/* 0x001a	WARNING:	*/
+  6,		/* 0x001b	WARNING:	*/
+  6,		/* 0x001c	WARNING:	*/
+  0		/* 0x001d-0xfffe    		*/
+};
+
+
+
 int ataReadHDIdentity ( int device, struct hd_driveid *buf)
 {
    if (ioctl ( device , HDIO_GET_IDENTITY, buf ) != 0)
@@ -33,64 +110,55 @@ int ataReadHDIdentity ( int device, struct hd_driveid *buf)
 }
 
 
-int ataVersionInfo ( struct hd_driveid drive)
-{
-   int i;
-   int atavalue = 0; 
-	
-#ifdef DEBUG
-#ifdef __NEW_HD_DRIVE_ID
-	printf ("Debug: Ata Version:	 %04x\n", drive.major_rev_num);
-#else
-	printf ("Debug: Ata Version:	 %04x\n", drive.word80);
-#endif
-#endif
- 
-#ifdef __NEW_HD_DRIVE_ID
-	if ( (drive.major_rev_num == 0xffff) || (drive.major_rev_num == 0x000) )
-#else
-	if ( (drive.word80 == 0xffff) || (drive.word80 == 0x000) )
-#endif
-	{
-		
-		return -1;
-
-	}
-
-	for ( i = 1; i < 16; i++ )
-	{
+int ataVersionInfo (const char** description, struct hd_driveid drive){
+  unsigned short major,minor;
+  int i,atavalue=0;
+  
+  // get major and minor ATA revision numbers
 #ifdef __NEW_HD_DRIVE_ID
-		if ( drive.major_rev_num &  ( 0x1 << i) )
+  major=drive.major_rev_num;
+  minor=drive.minor_rev_num;
 #else
-		
+  major=drive.word80;
+  minor=drive.word81;
 #endif
-		{
-			atavalue = i;
-		}
-	}
-	return atavalue;
+  
+  // First check if device has ANY ATA version information in it
+  if (major==NOVAL_0 || major==NOVAL_1) {
+    *description=NULL;
+    return -1;
+  }
+  
+  // The minor revision number has more information - try there first
+  if (minor && (minor<=MINOR_MAX)){
+    int std = actual_ver[minor];
+    if (std) {
+      *description=minor_str[minor];
+      return std;
+    }
+  }
+  
+  // HDPARM has a very complicated algorithm from here on. Since SMART only
+  // exists on ATA-3 and later standards, let's punt on this.  If you don't
+  // like it, please fix it.  The code's in CVS.
+  for (i=1; i<16;i++ )
+    if (major & (0x1<<i))
+      atavalue = i;
+  *description=NULL;
+  return atavalue;
 }
 
 
-
-
-int ataSmartSupport ( struct hd_driveid drive)
-{
+int ataSmartSupport ( struct hd_driveid drive){
 #ifdef __NEW_HD_DRIVE_ID
-	if ( drive.command_set_1 & 0x0001 ){
+  if (drive.command_set_1 & 0x0001)
 #else
-	if ( drive.command_sets & 0x0001 ){
+  if (drive.command_sets & 0x0001)
 #endif
-		return (1); /* drive supports S.M.A.R.T. and is disabled */
-	}
-			
-	return (0);
-
+    return 1; /* drive supports S.M.A.R.T. and is disabled */
+  return 0;
 }
 
-
-
-
 int ataReadSmartValues (int device, struct ata_smart_values *data)
 {	
    int i;
diff --git a/sm5/atacmds.h b/sm5/atacmds.h
index 3ca21074b..1d72bcff7 100644
--- a/sm5/atacmds.h
+++ b/sm5/atacmds.h
@@ -1,4 +1,4 @@
-//  $Id: atacmds.h,v 1.8 2002/10/11 12:48:27 ballen4705 Exp $
+//  $Id: atacmds.h,v 1.9 2002/10/12 11:10:01 ballen4705 Exp $
 /*
  * atacmds.h
  *
@@ -98,6 +98,9 @@
 #define HDIO_DRIVE_TASK_HDR_SIZE	7
 #endif
 
+
+
+
 /* Smart Values Data Structures */
 
 /* Smart Status Flags */
@@ -236,66 +239,40 @@ struct ata_smart_selftestlog {
 
 
 /* Read S.M.A.R.T information from drive */
-
-
 int ataReadHDIdentity (int device, struct hd_driveid *buf);
-
 int ataReadSmartValues (int device,struct ata_smart_values *);
-
 int ataReadSmartThresholds (int device, struct ata_smart_thresholds *);
-
 int ataReadErrorLog ( int device, struct ata_smart_errorlog *);
-
 int ataReadSelfTestLog (int device, struct ata_smart_selftestlog *);
-
 int ataSmartStatus ( int device);
-
 int ataSetSmartThresholds ( int device, struct ata_smart_thresholds *);
 
-
 /* Enable/Disable SMART on device */
-
 int ataEnableSmart ( int device );
-
 int ataDisableSmart (int device );
-
 int ataEnableAutoSave(int device);
-
 int ataDisableAutoSave(int device);
 
 /* Automatic Offline Testing */
-
 int ataEnableAutoOffline ( int device );
-
 int ataDisableAutoOffline (int device );
 
 
 /* S.M.A.R.T. test commands */
-
 int ataSmartOfflineTest (int device);
-
 int ataSmartExtendSelfTest (int device);
-
 int ataSmartShortSelfTest (int device);
-
 int ataSmartShortCapSelfTest (int device);
-
 int ataSmartExtendCapSelfTest (int device);
-
 int ataSmartSelfTestAbort (int device);
 
 /*Check Parameters of Smart Data */
 
 
 
-/* int ataVersionInfo ( struct hd_driveid drive) 
-*  Returns the latest compatibility of ATA/ATAPI Version  
-*  the device supports								
-* Returns -1 if Version command is not supported
-*/
- 
-int ataVersionInfo ( struct hd_driveid drive);
-
+// Returns the latest compatibility of ATA/ATAPI Version the device
+// supports. Returns -1 if Version command is not supported
+int ataVersionInfo (const char **description, struct hd_driveid drive);
 
 
 /*  int ataSmartSupport ( int device, struct hd_driveid drive)
diff --git a/sm5/ataprint.c b/sm5/ataprint.c
index 0f981c439..93a5b2b1d 100644
--- a/sm5/ataprint.c
+++ b/sm5/ataprint.c
@@ -1,4 +1,4 @@
-//  $Id: ataprint.c,v 1.6 2002/10/11 09:20:32 ballen4705 Exp $
+//  $Id: ataprint.c,v 1.7 2002/10/12 11:10:01 ballen4705 Exp $
 /*
  * ataprint.c
  *
@@ -19,13 +19,31 @@
 #include "smartctl.h"
 #include "extern.h"
 
-void ataPrintDriveInfo (struct hd_driveid drive)
-{
-  printf ("Device: %.40s  Supports ATA Version %i\n", 
-	  drive.model, ataVersionInfo ( drive) );
+void ataPrintDriveInfo (struct hd_driveid drive){
+  int version;
+  const char *description;
+  char unknown[32];
+
+  version=ataVersionInfo(&description,drive);
+
+  // unrecognized minor revision code
+  if (!description){
+    sprintf(unknown,"Unrecognized. Minor revision code: 0x%02x",drive.minor_rev_num);
+    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 minor number (version support) 0x%02x\n",drive.minor_rev_num);
+  printf("ATA Version is:   %i\n",version);
+  printf("ATA Standard is:  %s\n",description);
+
+  if (version>=3)
+    return;
+
+  printf("SMART is only supported in ATA version 3 or greater\n");
+  exit (0);
 }
 
 
@@ -41,35 +59,35 @@ void PrintSmartOfflineStatus ( struct ata_smart_values data)
       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");
+          printf("never started.\n");
           break;
       case 0x01: case 0x81:
-          printf ("(0x%02x)\tReserved\n",
+          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");
+          printf ("completed without error.\n");
           break;
       case 0x03: case 0x83:
-          printf ("(0x%02x)\tReserved\n",
+          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");
+          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");
+          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 fatal error\n");
+          printf ("aborted by the device with a fatal error.\n");
           break;
       default:
           if ( ((data.offline_data_collection_status >= 0x07) &&
@@ -77,12 +95,12 @@ void PrintSmartOfflineStatus ( struct ata_smart_values data)
                 ((data.offline_data_collection_status >= 0xc0) &&
                 (data.offline_data_collection_status <= 0xff)) )
           {
-              printf ("(0x%02x)\tVendor Specific\n",
+              printf ("(0x%02x)\tVendor Specific.\n",
                       data.offline_data_collection_status);
           } 
           else 
           {
-              printf ("(0x%02x)\tReserved\n",
+              printf ("(0x%02x)\tReserved.\n",
                       data.offline_data_collection_status);
           }
    }
@@ -99,17 +117,17 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
       case 0:
         printf ("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t",
                 data.self_test_exec_status);
-        printf ("without error or no self-test has ever \n\t\t\t\t\tbeen run\n");
+        printf ("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n");
         break;
        case 1:
          printf ("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t",
                  data.self_test_exec_status);
-         printf ("the host\n");
+         printf ("the host.\n");
          break;
        case 2:
          printf ("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t",
                  data.self_test_exec_status);
-         printf ("by the host with a hard or soft reset\n");
+         printf ("by the host with a hard or soft reset.\n");
          break;
        case 3:
           printf ("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t",
@@ -117,39 +135,39 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
           printf ("occurred while the device was executing\n\t\t\t\t\t");
           printf ("its self-test routine and the device \n\t\t\t\t\t");
           printf ("was unable to complete the self-test \n\t\t\t\t\t");
-          printf ("routine\n");
+          printf ("routine.\n");
           break;
        case 4:
           printf ("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
                   data.self_test_exec_status);
           printf ("a test element that failed and the test\n\t\t\t\t\t");
-          printf ("element that failed is not known\n");
+          printf ("element that failed is not known.\n");
           break;
        case 5:
           printf ("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
                   data.self_test_exec_status);
           printf ("the electrical element of the test\n\t\t\t\t\t");
-          printf ("failed\n");
+          printf ("failed.\n");
           break;
        case 6:
           printf ("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
                   data.self_test_exec_status);
           printf ("the servo (and/or seek) element of the \n\t\t\t\t\t");
-          printf ("test failed\n");
+          printf ("test failed.\n");
           break;
        case 7:
           printf ("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
                   data.self_test_exec_status);
-          printf ("the read element of the test failed\n");
+          printf ("the read element of the test failed.\n");
           break;
        case 15:
-          printf ("(%4d)\tSelf-test routine in progress\n\t\t\t\t\t",
+          printf ("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t",
                   data.self_test_exec_status);
-          printf ("%1d0%% of test remaining\n", 
+          printf ("%1d0%% of test remaining.\n", 
                   data.self_test_exec_status & 0x0f);
           break;
        default:
-          printf ("(%4d)\tReserved\n",
+          printf ("(%4d)\tReserved.\n",
                   data.self_test_exec_status);
           break;
    }
@@ -161,7 +179,7 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
 void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values data)
 {
    printf ("Total time to complete off-line \n");
-   printf ("data collection: \t\t (%4d) Seconds\n", 
+   printf ("data collection: \t\t (%4d) seconds.\n", 
            data.total_time_to_complete_off_line);
 }
 
@@ -169,35 +187,35 @@ void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values data)
 
 void PrintSmartOfflineCollectCap ( struct ata_smart_values data)
 {
-   printf ("Offline data collection \n");
-   printf ("Capabilities: \t\t\t (0x%02x)",
+   printf ("Offline data collection\n");
+   printf ("capabilities: \t\t\t (0x%02x) ",
             data.offline_data_collection_capability);
 
    if (data.offline_data_collection_capability == 0x00)
    {
-      printf ("\tOff-line data collection not supported\n");
+      printf ("\tOff-line data collection not supported.\n");
    } 
    else 
    {
       printf( "%s\n", isSupportExecuteOfflineImmediate(data)?
-              "SMART EXECUTE OFF-LINE IMMEDIATE" :
-              "NO SMART EXECUTE OFF-LINE IMMEDIATE");
+              "SMART execute Offline immediate." :
+              "No SMART execute Offline immediate.");
 
       printf( "\t\t\t\t\t%s\n", isSupportAutomaticTimer(data)? 
-              "Automatic timer ON/OFF support":
-              "NO Automatic timer ON/OFF support");
+              "Automatic timer ON/OFF support.":
+              "No Automatic timer ON/OFF support.");
 		
       printf( "\t\t\t\t\t%s\n", isSupportOfflineAbort(data)? 
-              "Abort Offline Collection upon new\n\t\t\t\t\tcommand":
-              "Suspend Offline Collection upon new\n\t\t\t\t\tcommand");
+              "Abort Offline collection upon new\n\t\t\t\t\tcommand.":
+              "Suspend Offline collection upon new\n\t\t\t\t\tcommand.");
 
       printf( "\t\t\t\t\t%s\n", isSupportOfflineSurfaceScan(data)? 
-              "Offline surface scan supported":
-              "NO Offline surface scan supported");
+              "Offline surface scan supported.":
+              "No Offline surface scan supported.");
 
       printf( "\t\t\t\t\t%s\n", isSupportSelfTest(data)? 
-              "Self-test supported":
-              "NO Self-test supported");
+              "Self-test supported.":
+              "No Self-test supported.");
     }
 }
 
@@ -205,24 +223,24 @@ void PrintSmartOfflineCollectCap ( struct ata_smart_values data)
 
 void PrintSmartCapability ( struct ata_smart_values data)
 {
-   printf ("Smart Capabilities:            ");
+   printf ("SMART capabilities:            ");
    printf ("(0x%04x)\t", data.smart_capability);
    
    if (data.smart_capability == 0x00)
    {
        printf ("automatic saving of SMART data"); 
-       printf ("\t\t\t\t\tis not implemented\n");
+       printf ("\t\t\t\t\tis not implemented.\n");
    } 
    else 
    {
 	
       printf( "%s\n", (data.smart_capability & 0x01)? 
-              "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode":
-              "does not save SMART data before\n\t\t\t\t\tentering power-saving mode");
+              "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.":
+              "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode.");
 		
       if ( data.smart_capability & 0x02 )
       {
-          printf ("\t\t\t\t\tSupports SMART auto save timer\n");
+          printf ("\t\t\t\t\tSupports SMART auto save timer.\n");
       }
    }
 }
@@ -236,11 +254,11 @@ void PrintSmartErrorLogCapability ( struct ata_smart_values data)
     
    if ( isSmartErrorLogCapable(data) )
    {
-      printf (" (0x%02x)\tError logging supported\n",
+      printf (" (0x%02x)\tError logging supported.\n",
                data.errorlog_capability);
    }
    else {
-       printf (" (0x%02x)\tError logging NOT supported\n",
+       printf (" (0x%02x)\tError logging NOT supported.\n",
                 data.errorlog_capability);
    }
 }
@@ -252,14 +270,14 @@ void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data)
    if ( isSupportSelfTest(data) )
    {
       printf ("Short self-test routine \n");
-      printf ("recommended polling time: \t (%4d) Minutes\n", 
+      printf ("recommended polling time: \t (%4d) minutes.\n", 
                data.short_test_completion_time);
 
    }
    else
    {
       printf ("Short self-test routine \n");
-      printf ("recommended polling time: \t        Not Supported\n");
+      printf ("recommended polling time: \t        Not Supported.\n");
    }
 }
 
@@ -269,13 +287,13 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data)
    if ( isSupportSelfTest(data) )
    {
       printf ("Extended self-test routine \n");
-      printf ("recommended polling time: \t (%4d) Minutes\n", 
+      printf ("recommended polling time: \t (%4d) minutes.\n", 
                data.extend_test_completion_time);
    }
    else
    {
       printf ("Extended self-test routine \n");
-      printf ("recommended polling time: \t        Not Supported\n");
+      printf ("recommended polling time: \t        Not Supported.\n");
    }
 }
 
@@ -290,40 +308,57 @@ void PrintSmartAttribWithThres ( struct ata_smart_values data,
    printf ("Revision Number: %i\n", data.revnumber);
    printf ("Attribute                    Flag     Value Worst Threshold Raw Value\n");
 	
-   for ( i = 0 ; i < 30 ; i++ )
-   {
-	   
-      if ( (data.vendor_attributes[i].id !=0) &&
-           (thresholds.thres_entries[i].id != 0))
-      {
-		   
-          ataPrintSmartAttribName(data.vendor_attributes[i].id);
-          printf(" 0x%04x   %.3i   %.3i   %.3i       ", 
-                 data.vendor_attributes[i].status.all,
-                 data.vendor_attributes[i].current,
-                 data.vendor_attributes[i].worst,
-                 thresholds.thres_entries[i].threshold);
-		  rawvalue = 0;
-          for (j = 0 ; j < 6 ; j++) 
-          {
-             rawvalue |= data.vendor_attributes[i].raw[j] << (8*j) ;
-          }
-	  /* handle IBM raw format */
-	  if (data.vendor_attributes[i].id!=194 || rawvalue<200)
-	    printf ("%llu\n", rawvalue);
-	  else
-	    printf("%u (Lifetime Min/Max %u/%u)\n",
-		   data.vendor_attributes[i].raw[0],		   
-		   data.vendor_attributes[i].raw[2],
-		   data.vendor_attributes[i].raw[4]);
-      }
+   for ( i = 0 ; i < 30 ; i++ ){
+     // step through all vendor attributes
+     if (data.vendor_attributes[i].id && thresholds.thres_entries[i].id){
+       ataPrintSmartAttribName(data.vendor_attributes[i].id);
+       // printing if they contain something sensible
+       printf(" 0x%04x   %.3i   %.3i   %.3i       ", 
+	      data.vendor_attributes[i].status.all,
+	      data.vendor_attributes[i].current,
+	      data.vendor_attributes[i].worst,
+	      thresholds.thres_entries[i].threshold);
+
+       // convert the six individual bytes to a long long (8 byte) integer
+       rawvalue = 0;
+       for (j = 0 ; j < 6 ; j++)
+	 rawvalue |= data.vendor_attributes[i].raw[j] << (8*j) ;
+
+       // This switch statement is where we handle Raw attributes
+       // that are stored in an unusual vendor-specific format,
+       switch (data.vendor_attributes[i].id){
+
+	 // Power on time
+       case 9:
+	 if (smart009minutes)
+	   // minutes
+	   printf ("%llu h + %2llu m\n",rawvalue/60,rawvalue%60);
+	 else
+	   // hours
+	   printf ("%llu\n", rawvalue);  //stored in hours
+	 break;
+	 
+	 // Temperature
+       case 194:
+	 printf ("%u", data.vendor_attributes[i].raw[0]);
+	 if (rawvalue==data.vendor_attributes[i].raw[0])
+	   printf("\n");
+	 else
+	   // The other bytes are in use. Try IBM's model
+	   printf(" (Lifetime Min/Max %u/%u)\n",data.vendor_attributes[i].raw[2],
+		  data.vendor_attributes[i].raw[4]);
+	 break;
+       default:
+	 printf("%llu\n", rawvalue);
+       }	    
+     }
    }
 }
 
 
 void ataPrintGeneralSmartValues  ( struct ata_smart_values data)
 {
-   printf ("\nGeneral Smart Values: \n");
+   printf ("\nGeneral SMART Values: \n");
 
    PrintSmartOfflineStatus (data); 
    printf("\n");
@@ -362,17 +397,15 @@ void ataPrintSmartThresholds (struct ata_smart_thresholds data)
 {
    int i;
 
-   printf ("Smart Thresholds\n");
-   printf ("Smart Threshold Revision Number: %i\n", data.revnumber);
+   printf ("SMART Thresholds\n");
+   printf ("SMART Threshold Revision Number: %i\n", data.revnumber);
 	
-   for ( i = 0 ; i < 30 ; i++)
-   {
-      if (data.thres_entries[i].id != 0)	
+   for ( i = 0 ; i < 30 ; i++) {
+      if (data.thres_entries[i].id)	
           printf ("Attribute %3i threshold: %02x (%2i)\n", 
                    data.thres_entries[i].id, 
                    data.thres_entries[i].threshold, 
                    data.thres_entries[i].threshold);
-	
    }
 }
 
@@ -412,7 +445,8 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data)
   if (data.ata_error_count<=5)
       printf ( "ATA Error Count: %u\n\n", data.ata_error_count);
   else
-      printf ( "ATA Error Count: %u (note: only most recent five errors are shown below)\n\n", data.ata_error_count);
+      printf ( "ATA Error Count: %u (only the most recent five errors are shown below)\n\n",
+	       data.ata_error_count);
 
   printf(  "Acronyms used below:\n");
   printf(  "DCR = Device Control Register\n");
@@ -554,31 +588,24 @@ void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data){
 }
 
 void ataPsuedoCheckSmart ( struct ata_smart_values data, 
-                           struct ata_smart_thresholds thresholds)
-{
+                           struct ata_smart_thresholds thresholds) {
    int i;
    int failed = 0;
-
-   for ( i = 0 ; i < 30 ; i++ )
-   {
-      if ( (data.vendor_attributes[i].id !=0) &&   
-           (thresholds.thres_entries[i].id != 0) &&
-           ( 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;
-      } 
-
-   }
-   
+   for (i = 0 ; i < 30 ; 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 )?
-     "Please save all data and call drive manufacture immediately.":
-     "Check S.M.A.R.T. Passed.");
+	  "SMART drive overall health self-assessment test result: FAILED!\n"
+	  "Drive failure expected in less than 24 hours. SAVE ALL DATA\n":
+	  "SMART drive overall health self-assessment test result: PASSED\n");
 }
 
 void ataPrintSmartAttribName ( unsigned char id )
@@ -683,20 +710,20 @@ void ataPrintMain ( int fd )
 
       if (ataSmartSupport(drive))
       {
-          printf ("Drive supports S.M.A.R.T. and is ");
+          printf ("SMART support is: ");
 	  
           if ( ataSmartStatus(fd) != 0) 
           {
-              printf( "disabled\n");
-              printf( "Use option -%c to enable\n", SMARTENABLE );
+              printf( "Disabled\n");
+              printf( "Use option -%c to enable\n\n", SMARTENABLE );
               exit(0);
           }
           else { 
-              printf( "enabled\n");
+              printf( "Enabled\n\n");
           } 
       }
       else {
-           printf("Drive does not support S.M.A.R.T.\n");
+           printf("SMART support is: Unavailable. Device lacks SMART capability.\n\n");
 	   exit (0);
       }
   }
@@ -706,11 +733,11 @@ void ataPrintMain ( int fd )
 		
      if ( ataDisableSmart(fd) != 0) 
      {
-	printf( "Smartctl: Smart Enable Failed\n");
+	printf( "Smartctl: SMART Enable Failed\n");
 	exit(-1);
      }
     
-     printf("S.M.A.R.T. Disabled\n");
+     printf("SMART Disabled\n");
      exit (0);
 		
    }
@@ -719,33 +746,33 @@ void ataPrintMain ( int fd )
    {
       if ( ataEnableSmart(fd) != 0) 
 	{
-          printf( "Smartctl: Smart Enable Failed\n");
+          printf( "Smartctl: SMART Enable Failed\n");
           exit(-1);
 	}
 
       if (ataSmartStatus(fd)==0)
-	printf("S.M.A.R.T. Enabled\n");
+	printf("SMART Enabled\n");
       else
-	printf( "Smartctl: Smart Enable Failed for unknown reasons\n");
+	printf( "Smartctl: SMART Enable Failed for unknown reasons\n");
    }
    
    
    if ( smartautosavedisable ){
      if (ataDisableAutoSave(fd) != 0)
        {
-	 printf( "Smartctl: Smart Disable Attribute Autosave Failed\n");
+	 printf( "Smartctl: SMART Disable Attribute Autosave Failed\n");
 	 exit(-1);
        }     
-     printf("S.M.A.R.T. Attribute Autosave Disabled\n");
+     printf("SMART Attribute Autosave Disabled\n");
    }
 	
    if ( smartautosaveenable ){
      if (ataEnableAutoSave(fd) != 0)
        {
-	 printf( "Smartctl: Smart Enable Attribute Autosave Failed\n");
+	 printf( "Smartctl: SMART Enable Attribute Autosave Failed\n");
 	 exit(-1);
        } 
-     printf("S.M.A.R.T. Attribute Autosave Enabled\n");
+     printf("SMART Attribute Autosave Enabled\n");
    }
 
    /* for everything else read values and thresholds 
@@ -753,13 +780,13 @@ void ataPrintMain ( int fd )
 
    if ( ataReadSmartValues ( fd, &smartval) != 0 )
    {
-      printf("Smartctl: Smart Values Read Failed\n");
+      printf("Smartctl: SMART Values Read Failed\n");
       exit (-1);
    }
 
    if ( ataReadSmartThresholds ( fd, &smartthres) != 0 )
    {
-      printf("Smartctl: Smart Thresholds Read Failed\n");
+      printf("Smartctl: SMART Thresholds Read Failed\n");
       exit (-1); 
    }
 	
@@ -792,7 +819,7 @@ void ataPrintMain ( int fd )
       {
          if ( ataReadErrorLog ( fd, &smarterror) != 0 )
 	 {
-             printf("Smartctl: Smart Errorlog Read Failed\n");
+             printf("Smartctl: SMART Errorlog Read Failed\n");
          }
          else
          {
@@ -812,7 +839,7 @@ void ataPrintMain ( int fd )
        {
 	    if (  ataReadSelfTestLog( fd, &smartselftest) != 0 )
             {
-                printf("Smartctl: Smart Self Test log Read Failed\n");
+                printf("Smartctl: SMART Self Test Log Read Failed\n");
             }
             else
             {
@@ -825,34 +852,34 @@ void ataPrintMain ( int fd )
     {
         if ( !isSupportAutomaticTimer (smartval))
         {
-            printf("Device does not support S.M.A.R.T. Automatic Timers\n");
+            printf("Device does not support SMART Automatic Timers\n");
             exit(-1);
         }
 
         if ( ataEnableAutoOffline (fd) != 0) 
         {
-            printf( "Smartctl: Smart Enable Automatic Offline Failed\n");
+            printf( "Smartctl: SMART Enable Automatic Offline Failed\n");
             exit(-1);
         }
         
-        printf ("S.M.A.R.T. Automatic Offline Testing Enabled every four hours\n");
+        printf ("SMART Automatic Offline Testing Enabled every four hours\n");
     }
 
     if (  smartautoofflinedisable  )
     {
         if ( !isSupportAutomaticTimer (smartval))
         {
-            printf("Device does not support S.M.A.R.T. Automatic Timers\n");
+            printf("Device does not support SMART Automatic Timers\n");
             exit(-1);
         }
 			
         if ( ataDisableAutoOffline (fd) != 0) 
         {
-            printf( "Smartctl: Smart Disable Automatic Offline Failed\n");
+            printf( "Smartctl: SMART Disable Automatic Offline Failed\n");
             exit(-1);
         }
          
-        printf ("S.M.A.R.T. Automatic Offline Testing Disabled\n");
+        printf ("SMART Automatic Offline Testing Disabled\n");
 
      }
 
@@ -861,7 +888,7 @@ void ataPrintMain ( int fd )
      {
         if ( ataSmartOfflineTest (fd) != 0) 
 	{
-            printf( "Smartctl: Smart Offline Failed\n");
+            printf( "Smartctl: SMART Offline Failed\n");
             exit(-1);
         }
 
@@ -882,7 +909,7 @@ void ataPrintMain ( int fd )
 		
          if ( ataSmartShortCapSelfTest (fd) != 0) 
          {
-              printf( "Smartctl: Smart Short Self Test Failed\n");
+              printf( "Smartctl: SMART Short Self Test Failed\n");
               exit(-1);
          }
      
@@ -905,7 +932,7 @@ void ataPrintMain ( int fd )
 		
         if ( ataSmartShortSelfTest (fd) != 0) 
         {
-            printf( "Smartctl: Smart Short Self Test Failed\n");
+            printf( "Smartctl: SMART Short Self Test Failed\n");
             exit(-1);
         }
 
@@ -929,7 +956,7 @@ void ataPrintMain ( int fd )
 
         if ( ataSmartExtendSelfTest (fd) != 0) 
         {
-           printf( "S.M.A.R.T. Extended Self Test Failed\n");
+           printf( "SMART Extended Self Test Failed\n");
            exit(-1);
         }
 		
@@ -952,7 +979,7 @@ void ataPrintMain ( int fd )
 
          if ( ataSmartExtendCapSelfTest (fd) != 0) 
          {
-            printf( "S.M.A.R.T. Extended Self Test Failed\n");
+            printf( "SMART Extended Self Test Failed\n");
             exit(-1);
          }
 		
@@ -973,7 +1000,7 @@ void ataPrintMain ( int fd )
 
         if ( ataSmartSelfTestAbort (fd) != 0) 
         {
-            printf( "S.M.A.R.T. Self Test Abort Failed\n");
+            printf( "SMART Self Test Abort Failed\n");
             exit(-1);
         }
 		
diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp
index c44b5cf29..e7d6ed2b3 100644
--- a/sm5/ataprint.cpp
+++ b/sm5/ataprint.cpp
@@ -1,4 +1,4 @@
-//  $Id: ataprint.cpp,v 1.6 2002/10/11 09:20:32 ballen4705 Exp $
+//  $Id: ataprint.cpp,v 1.7 2002/10/12 11:10:01 ballen4705 Exp $
 /*
  * ataprint.c
  *
@@ -19,13 +19,31 @@
 #include "smartctl.h"
 #include "extern.h"
 
-void ataPrintDriveInfo (struct hd_driveid drive)
-{
-  printf ("Device: %.40s  Supports ATA Version %i\n", 
-	  drive.model, ataVersionInfo ( drive) );
+void ataPrintDriveInfo (struct hd_driveid drive){
+  int version;
+  const char *description;
+  char unknown[32];
+
+  version=ataVersionInfo(&description,drive);
+
+  // unrecognized minor revision code
+  if (!description){
+    sprintf(unknown,"Unrecognized. Minor revision code: 0x%02x",drive.minor_rev_num);
+    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 minor number (version support) 0x%02x\n",drive.minor_rev_num);
+  printf("ATA Version is:   %i\n",version);
+  printf("ATA Standard is:  %s\n",description);
+
+  if (version>=3)
+    return;
+
+  printf("SMART is only supported in ATA version 3 or greater\n");
+  exit (0);
 }
 
 
@@ -41,35 +59,35 @@ void PrintSmartOfflineStatus ( struct ata_smart_values data)
       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");
+          printf("never started.\n");
           break;
       case 0x01: case 0x81:
-          printf ("(0x%02x)\tReserved\n",
+          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");
+          printf ("completed without error.\n");
           break;
       case 0x03: case 0x83:
-          printf ("(0x%02x)\tReserved\n",
+          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");
+          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");
+          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 fatal error\n");
+          printf ("aborted by the device with a fatal error.\n");
           break;
       default:
           if ( ((data.offline_data_collection_status >= 0x07) &&
@@ -77,12 +95,12 @@ void PrintSmartOfflineStatus ( struct ata_smart_values data)
                 ((data.offline_data_collection_status >= 0xc0) &&
                 (data.offline_data_collection_status <= 0xff)) )
           {
-              printf ("(0x%02x)\tVendor Specific\n",
+              printf ("(0x%02x)\tVendor Specific.\n",
                       data.offline_data_collection_status);
           } 
           else 
           {
-              printf ("(0x%02x)\tReserved\n",
+              printf ("(0x%02x)\tReserved.\n",
                       data.offline_data_collection_status);
           }
    }
@@ -99,17 +117,17 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
       case 0:
         printf ("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t",
                 data.self_test_exec_status);
-        printf ("without error or no self-test has ever \n\t\t\t\t\tbeen run\n");
+        printf ("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n");
         break;
        case 1:
          printf ("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t",
                  data.self_test_exec_status);
-         printf ("the host\n");
+         printf ("the host.\n");
          break;
        case 2:
          printf ("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t",
                  data.self_test_exec_status);
-         printf ("by the host with a hard or soft reset\n");
+         printf ("by the host with a hard or soft reset.\n");
          break;
        case 3:
           printf ("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t",
@@ -117,39 +135,39 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
           printf ("occurred while the device was executing\n\t\t\t\t\t");
           printf ("its self-test routine and the device \n\t\t\t\t\t");
           printf ("was unable to complete the self-test \n\t\t\t\t\t");
-          printf ("routine\n");
+          printf ("routine.\n");
           break;
        case 4:
           printf ("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
                   data.self_test_exec_status);
           printf ("a test element that failed and the test\n\t\t\t\t\t");
-          printf ("element that failed is not known\n");
+          printf ("element that failed is not known.\n");
           break;
        case 5:
           printf ("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
                   data.self_test_exec_status);
           printf ("the electrical element of the test\n\t\t\t\t\t");
-          printf ("failed\n");
+          printf ("failed.\n");
           break;
        case 6:
           printf ("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
                   data.self_test_exec_status);
           printf ("the servo (and/or seek) element of the \n\t\t\t\t\t");
-          printf ("test failed\n");
+          printf ("test failed.\n");
           break;
        case 7:
           printf ("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
                   data.self_test_exec_status);
-          printf ("the read element of the test failed\n");
+          printf ("the read element of the test failed.\n");
           break;
        case 15:
-          printf ("(%4d)\tSelf-test routine in progress\n\t\t\t\t\t",
+          printf ("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t",
                   data.self_test_exec_status);
-          printf ("%1d0%% of test remaining\n", 
+          printf ("%1d0%% of test remaining.\n", 
                   data.self_test_exec_status & 0x0f);
           break;
        default:
-          printf ("(%4d)\tReserved\n",
+          printf ("(%4d)\tReserved.\n",
                   data.self_test_exec_status);
           break;
    }
@@ -161,7 +179,7 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
 void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values data)
 {
    printf ("Total time to complete off-line \n");
-   printf ("data collection: \t\t (%4d) Seconds\n", 
+   printf ("data collection: \t\t (%4d) seconds.\n", 
            data.total_time_to_complete_off_line);
 }
 
@@ -169,35 +187,35 @@ void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values data)
 
 void PrintSmartOfflineCollectCap ( struct ata_smart_values data)
 {
-   printf ("Offline data collection \n");
-   printf ("Capabilities: \t\t\t (0x%02x)",
+   printf ("Offline data collection\n");
+   printf ("capabilities: \t\t\t (0x%02x) ",
             data.offline_data_collection_capability);
 
    if (data.offline_data_collection_capability == 0x00)
    {
-      printf ("\tOff-line data collection not supported\n");
+      printf ("\tOff-line data collection not supported.\n");
    } 
    else 
    {
       printf( "%s\n", isSupportExecuteOfflineImmediate(data)?
-              "SMART EXECUTE OFF-LINE IMMEDIATE" :
-              "NO SMART EXECUTE OFF-LINE IMMEDIATE");
+              "SMART execute Offline immediate." :
+              "No SMART execute Offline immediate.");
 
       printf( "\t\t\t\t\t%s\n", isSupportAutomaticTimer(data)? 
-              "Automatic timer ON/OFF support":
-              "NO Automatic timer ON/OFF support");
+              "Automatic timer ON/OFF support.":
+              "No Automatic timer ON/OFF support.");
 		
       printf( "\t\t\t\t\t%s\n", isSupportOfflineAbort(data)? 
-              "Abort Offline Collection upon new\n\t\t\t\t\tcommand":
-              "Suspend Offline Collection upon new\n\t\t\t\t\tcommand");
+              "Abort Offline collection upon new\n\t\t\t\t\tcommand.":
+              "Suspend Offline collection upon new\n\t\t\t\t\tcommand.");
 
       printf( "\t\t\t\t\t%s\n", isSupportOfflineSurfaceScan(data)? 
-              "Offline surface scan supported":
-              "NO Offline surface scan supported");
+              "Offline surface scan supported.":
+              "No Offline surface scan supported.");
 
       printf( "\t\t\t\t\t%s\n", isSupportSelfTest(data)? 
-              "Self-test supported":
-              "NO Self-test supported");
+              "Self-test supported.":
+              "No Self-test supported.");
     }
 }
 
@@ -205,24 +223,24 @@ void PrintSmartOfflineCollectCap ( struct ata_smart_values data)
 
 void PrintSmartCapability ( struct ata_smart_values data)
 {
-   printf ("Smart Capabilities:            ");
+   printf ("SMART capabilities:            ");
    printf ("(0x%04x)\t", data.smart_capability);
    
    if (data.smart_capability == 0x00)
    {
        printf ("automatic saving of SMART data"); 
-       printf ("\t\t\t\t\tis not implemented\n");
+       printf ("\t\t\t\t\tis not implemented.\n");
    } 
    else 
    {
 	
       printf( "%s\n", (data.smart_capability & 0x01)? 
-              "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode":
-              "does not save SMART data before\n\t\t\t\t\tentering power-saving mode");
+              "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.":
+              "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode.");
 		
       if ( data.smart_capability & 0x02 )
       {
-          printf ("\t\t\t\t\tSupports SMART auto save timer\n");
+          printf ("\t\t\t\t\tSupports SMART auto save timer.\n");
       }
    }
 }
@@ -236,11 +254,11 @@ void PrintSmartErrorLogCapability ( struct ata_smart_values data)
     
    if ( isSmartErrorLogCapable(data) )
    {
-      printf (" (0x%02x)\tError logging supported\n",
+      printf (" (0x%02x)\tError logging supported.\n",
                data.errorlog_capability);
    }
    else {
-       printf (" (0x%02x)\tError logging NOT supported\n",
+       printf (" (0x%02x)\tError logging NOT supported.\n",
                 data.errorlog_capability);
    }
 }
@@ -252,14 +270,14 @@ void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data)
    if ( isSupportSelfTest(data) )
    {
       printf ("Short self-test routine \n");
-      printf ("recommended polling time: \t (%4d) Minutes\n", 
+      printf ("recommended polling time: \t (%4d) minutes.\n", 
                data.short_test_completion_time);
 
    }
    else
    {
       printf ("Short self-test routine \n");
-      printf ("recommended polling time: \t        Not Supported\n");
+      printf ("recommended polling time: \t        Not Supported.\n");
    }
 }
 
@@ -269,13 +287,13 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data)
    if ( isSupportSelfTest(data) )
    {
       printf ("Extended self-test routine \n");
-      printf ("recommended polling time: \t (%4d) Minutes\n", 
+      printf ("recommended polling time: \t (%4d) minutes.\n", 
                data.extend_test_completion_time);
    }
    else
    {
       printf ("Extended self-test routine \n");
-      printf ("recommended polling time: \t        Not Supported\n");
+      printf ("recommended polling time: \t        Not Supported.\n");
    }
 }
 
@@ -290,40 +308,57 @@ void PrintSmartAttribWithThres ( struct ata_smart_values data,
    printf ("Revision Number: %i\n", data.revnumber);
    printf ("Attribute                    Flag     Value Worst Threshold Raw Value\n");
 	
-   for ( i = 0 ; i < 30 ; i++ )
-   {
-	   
-      if ( (data.vendor_attributes[i].id !=0) &&
-           (thresholds.thres_entries[i].id != 0))
-      {
-		   
-          ataPrintSmartAttribName(data.vendor_attributes[i].id);
-          printf(" 0x%04x   %.3i   %.3i   %.3i       ", 
-                 data.vendor_attributes[i].status.all,
-                 data.vendor_attributes[i].current,
-                 data.vendor_attributes[i].worst,
-                 thresholds.thres_entries[i].threshold);
-		  rawvalue = 0;
-          for (j = 0 ; j < 6 ; j++) 
-          {
-             rawvalue |= data.vendor_attributes[i].raw[j] << (8*j) ;
-          }
-	  /* handle IBM raw format */
-	  if (data.vendor_attributes[i].id!=194 || rawvalue<200)
-	    printf ("%llu\n", rawvalue);
-	  else
-	    printf("%u (Lifetime Min/Max %u/%u)\n",
-		   data.vendor_attributes[i].raw[0],		   
-		   data.vendor_attributes[i].raw[2],
-		   data.vendor_attributes[i].raw[4]);
-      }
+   for ( i = 0 ; i < 30 ; i++ ){
+     // step through all vendor attributes
+     if (data.vendor_attributes[i].id && thresholds.thres_entries[i].id){
+       ataPrintSmartAttribName(data.vendor_attributes[i].id);
+       // printing if they contain something sensible
+       printf(" 0x%04x   %.3i   %.3i   %.3i       ", 
+	      data.vendor_attributes[i].status.all,
+	      data.vendor_attributes[i].current,
+	      data.vendor_attributes[i].worst,
+	      thresholds.thres_entries[i].threshold);
+
+       // convert the six individual bytes to a long long (8 byte) integer
+       rawvalue = 0;
+       for (j = 0 ; j < 6 ; j++)
+	 rawvalue |= data.vendor_attributes[i].raw[j] << (8*j) ;
+
+       // This switch statement is where we handle Raw attributes
+       // that are stored in an unusual vendor-specific format,
+       switch (data.vendor_attributes[i].id){
+
+	 // Power on time
+       case 9:
+	 if (smart009minutes)
+	   // minutes
+	   printf ("%llu h + %2llu m\n",rawvalue/60,rawvalue%60);
+	 else
+	   // hours
+	   printf ("%llu\n", rawvalue);  //stored in hours
+	 break;
+	 
+	 // Temperature
+       case 194:
+	 printf ("%u", data.vendor_attributes[i].raw[0]);
+	 if (rawvalue==data.vendor_attributes[i].raw[0])
+	   printf("\n");
+	 else
+	   // The other bytes are in use. Try IBM's model
+	   printf(" (Lifetime Min/Max %u/%u)\n",data.vendor_attributes[i].raw[2],
+		  data.vendor_attributes[i].raw[4]);
+	 break;
+       default:
+	 printf("%llu\n", rawvalue);
+       }	    
+     }
    }
 }
 
 
 void ataPrintGeneralSmartValues  ( struct ata_smart_values data)
 {
-   printf ("\nGeneral Smart Values: \n");
+   printf ("\nGeneral SMART Values: \n");
 
    PrintSmartOfflineStatus (data); 
    printf("\n");
@@ -362,17 +397,15 @@ void ataPrintSmartThresholds (struct ata_smart_thresholds data)
 {
    int i;
 
-   printf ("Smart Thresholds\n");
-   printf ("Smart Threshold Revision Number: %i\n", data.revnumber);
+   printf ("SMART Thresholds\n");
+   printf ("SMART Threshold Revision Number: %i\n", data.revnumber);
 	
-   for ( i = 0 ; i < 30 ; i++)
-   {
-      if (data.thres_entries[i].id != 0)	
+   for ( i = 0 ; i < 30 ; i++) {
+      if (data.thres_entries[i].id)	
           printf ("Attribute %3i threshold: %02x (%2i)\n", 
                    data.thres_entries[i].id, 
                    data.thres_entries[i].threshold, 
                    data.thres_entries[i].threshold);
-	
    }
 }
 
@@ -412,7 +445,8 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data)
   if (data.ata_error_count<=5)
       printf ( "ATA Error Count: %u\n\n", data.ata_error_count);
   else
-      printf ( "ATA Error Count: %u (note: only most recent five errors are shown below)\n\n", data.ata_error_count);
+      printf ( "ATA Error Count: %u (only the most recent five errors are shown below)\n\n",
+	       data.ata_error_count);
 
   printf(  "Acronyms used below:\n");
   printf(  "DCR = Device Control Register\n");
@@ -554,31 +588,24 @@ void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data){
 }
 
 void ataPsuedoCheckSmart ( struct ata_smart_values data, 
-                           struct ata_smart_thresholds thresholds)
-{
+                           struct ata_smart_thresholds thresholds) {
    int i;
    int failed = 0;
-
-   for ( i = 0 ; i < 30 ; i++ )
-   {
-      if ( (data.vendor_attributes[i].id !=0) &&   
-           (thresholds.thres_entries[i].id != 0) &&
-           ( 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;
-      } 
-
-   }
-   
+   for (i = 0 ; i < 30 ; 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 )?
-     "Please save all data and call drive manufacture immediately.":
-     "Check S.M.A.R.T. Passed.");
+	  "SMART drive overall health self-assessment test result: FAILED!\n"
+	  "Drive failure expected in less than 24 hours. SAVE ALL DATA\n":
+	  "SMART drive overall health self-assessment test result: PASSED\n");
 }
 
 void ataPrintSmartAttribName ( unsigned char id )
@@ -683,20 +710,20 @@ void ataPrintMain ( int fd )
 
       if (ataSmartSupport(drive))
       {
-          printf ("Drive supports S.M.A.R.T. and is ");
+          printf ("SMART support is: ");
 	  
           if ( ataSmartStatus(fd) != 0) 
           {
-              printf( "disabled\n");
-              printf( "Use option -%c to enable\n", SMARTENABLE );
+              printf( "Disabled\n");
+              printf( "Use option -%c to enable\n\n", SMARTENABLE );
               exit(0);
           }
           else { 
-              printf( "enabled\n");
+              printf( "Enabled\n\n");
           } 
       }
       else {
-           printf("Drive does not support S.M.A.R.T.\n");
+           printf("SMART support is: Unavailable. Device lacks SMART capability.\n\n");
 	   exit (0);
       }
   }
@@ -706,11 +733,11 @@ void ataPrintMain ( int fd )
 		
      if ( ataDisableSmart(fd) != 0) 
      {
-	printf( "Smartctl: Smart Enable Failed\n");
+	printf( "Smartctl: SMART Enable Failed\n");
 	exit(-1);
      }
     
-     printf("S.M.A.R.T. Disabled\n");
+     printf("SMART Disabled\n");
      exit (0);
 		
    }
@@ -719,33 +746,33 @@ void ataPrintMain ( int fd )
    {
       if ( ataEnableSmart(fd) != 0) 
 	{
-          printf( "Smartctl: Smart Enable Failed\n");
+          printf( "Smartctl: SMART Enable Failed\n");
           exit(-1);
 	}
 
       if (ataSmartStatus(fd)==0)
-	printf("S.M.A.R.T. Enabled\n");
+	printf("SMART Enabled\n");
       else
-	printf( "Smartctl: Smart Enable Failed for unknown reasons\n");
+	printf( "Smartctl: SMART Enable Failed for unknown reasons\n");
    }
    
    
    if ( smartautosavedisable ){
      if (ataDisableAutoSave(fd) != 0)
        {
-	 printf( "Smartctl: Smart Disable Attribute Autosave Failed\n");
+	 printf( "Smartctl: SMART Disable Attribute Autosave Failed\n");
 	 exit(-1);
        }     
-     printf("S.M.A.R.T. Attribute Autosave Disabled\n");
+     printf("SMART Attribute Autosave Disabled\n");
    }
 	
    if ( smartautosaveenable ){
      if (ataEnableAutoSave(fd) != 0)
        {
-	 printf( "Smartctl: Smart Enable Attribute Autosave Failed\n");
+	 printf( "Smartctl: SMART Enable Attribute Autosave Failed\n");
 	 exit(-1);
        } 
-     printf("S.M.A.R.T. Attribute Autosave Enabled\n");
+     printf("SMART Attribute Autosave Enabled\n");
    }
 
    /* for everything else read values and thresholds 
@@ -753,13 +780,13 @@ void ataPrintMain ( int fd )
 
    if ( ataReadSmartValues ( fd, &smartval) != 0 )
    {
-      printf("Smartctl: Smart Values Read Failed\n");
+      printf("Smartctl: SMART Values Read Failed\n");
       exit (-1);
    }
 
    if ( ataReadSmartThresholds ( fd, &smartthres) != 0 )
    {
-      printf("Smartctl: Smart Thresholds Read Failed\n");
+      printf("Smartctl: SMART Thresholds Read Failed\n");
       exit (-1); 
    }
 	
@@ -792,7 +819,7 @@ void ataPrintMain ( int fd )
       {
          if ( ataReadErrorLog ( fd, &smarterror) != 0 )
 	 {
-             printf("Smartctl: Smart Errorlog Read Failed\n");
+             printf("Smartctl: SMART Errorlog Read Failed\n");
          }
          else
          {
@@ -812,7 +839,7 @@ void ataPrintMain ( int fd )
        {
 	    if (  ataReadSelfTestLog( fd, &smartselftest) != 0 )
             {
-                printf("Smartctl: Smart Self Test log Read Failed\n");
+                printf("Smartctl: SMART Self Test Log Read Failed\n");
             }
             else
             {
@@ -825,34 +852,34 @@ void ataPrintMain ( int fd )
     {
         if ( !isSupportAutomaticTimer (smartval))
         {
-            printf("Device does not support S.M.A.R.T. Automatic Timers\n");
+            printf("Device does not support SMART Automatic Timers\n");
             exit(-1);
         }
 
         if ( ataEnableAutoOffline (fd) != 0) 
         {
-            printf( "Smartctl: Smart Enable Automatic Offline Failed\n");
+            printf( "Smartctl: SMART Enable Automatic Offline Failed\n");
             exit(-1);
         }
         
-        printf ("S.M.A.R.T. Automatic Offline Testing Enabled every four hours\n");
+        printf ("SMART Automatic Offline Testing Enabled every four hours\n");
     }
 
     if (  smartautoofflinedisable  )
     {
         if ( !isSupportAutomaticTimer (smartval))
         {
-            printf("Device does not support S.M.A.R.T. Automatic Timers\n");
+            printf("Device does not support SMART Automatic Timers\n");
             exit(-1);
         }
 			
         if ( ataDisableAutoOffline (fd) != 0) 
         {
-            printf( "Smartctl: Smart Disable Automatic Offline Failed\n");
+            printf( "Smartctl: SMART Disable Automatic Offline Failed\n");
             exit(-1);
         }
          
-        printf ("S.M.A.R.T. Automatic Offline Testing Disabled\n");
+        printf ("SMART Automatic Offline Testing Disabled\n");
 
      }
 
@@ -861,7 +888,7 @@ void ataPrintMain ( int fd )
      {
         if ( ataSmartOfflineTest (fd) != 0) 
 	{
-            printf( "Smartctl: Smart Offline Failed\n");
+            printf( "Smartctl: SMART Offline Failed\n");
             exit(-1);
         }
 
@@ -882,7 +909,7 @@ void ataPrintMain ( int fd )
 		
          if ( ataSmartShortCapSelfTest (fd) != 0) 
          {
-              printf( "Smartctl: Smart Short Self Test Failed\n");
+              printf( "Smartctl: SMART Short Self Test Failed\n");
               exit(-1);
          }
      
@@ -905,7 +932,7 @@ void ataPrintMain ( int fd )
 		
         if ( ataSmartShortSelfTest (fd) != 0) 
         {
-            printf( "Smartctl: Smart Short Self Test Failed\n");
+            printf( "Smartctl: SMART Short Self Test Failed\n");
             exit(-1);
         }
 
@@ -929,7 +956,7 @@ void ataPrintMain ( int fd )
 
         if ( ataSmartExtendSelfTest (fd) != 0) 
         {
-           printf( "S.M.A.R.T. Extended Self Test Failed\n");
+           printf( "SMART Extended Self Test Failed\n");
            exit(-1);
         }
 		
@@ -952,7 +979,7 @@ void ataPrintMain ( int fd )
 
          if ( ataSmartExtendCapSelfTest (fd) != 0) 
          {
-            printf( "S.M.A.R.T. Extended Self Test Failed\n");
+            printf( "SMART Extended Self Test Failed\n");
             exit(-1);
          }
 		
@@ -973,7 +1000,7 @@ void ataPrintMain ( int fd )
 
         if ( ataSmartSelfTestAbort (fd) != 0) 
         {
-            printf( "S.M.A.R.T. Self Test Abort Failed\n");
+            printf( "SMART Self Test Abort Failed\n");
             exit(-1);
         }
 		
diff --git a/sm5/extern.h b/sm5/extern.h
index 25c51a6d0..3d955fde5 100644
--- a/sm5/extern.h
+++ b/sm5/extern.h
@@ -1,41 +1,42 @@
-//  $Id: extern.h,v 1.2 2002/10/11 09:20:32 ballen4705 Exp $
-/*
- * extern.h
- *
- * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _EXTERN_H_
-#define _EXTERN_H_
-
-extern unsigned char driveinfo;
-extern unsigned char checksmart;
-extern unsigned char smartvendorattrib;
-extern unsigned char generalsmartvalues;
-extern unsigned char smartselftestlog;
-extern unsigned char smarterrorlog;
-extern unsigned char smartdisable;
-extern unsigned char smartenable; 
-extern unsigned char smartstatus;
-extern unsigned char smartexeoffimmediate;
-extern unsigned char smartshortselftest;
-extern unsigned char smartextendselftest;
-extern unsigned char smartshortcapselftest;
-extern unsigned char smartextendcapselftest;
-extern unsigned char smartselftestabort;
-extern unsigned char smartautoofflineenable;
-extern unsigned char smartautoofflinedisable;
-extern unsigned char smartautosaveenable;
-extern unsigned char smartautosavedisable;
-
-#endif
+//  $Id: extern.h,v 1.3 2002/10/12 11:10:01 ballen4705 Exp $
+/*
+ * extern.h
+ *
+ * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _EXTERN_H_
+#define _EXTERN_H_
+
+extern unsigned char driveinfo;
+extern unsigned char checksmart;
+extern unsigned char smartvendorattrib;
+extern unsigned char generalsmartvalues;
+extern unsigned char smartselftestlog;
+extern unsigned char smarterrorlog;
+extern unsigned char smartdisable;
+extern unsigned char smartenable; 
+extern unsigned char smartstatus;
+extern unsigned char smartexeoffimmediate;
+extern unsigned char smartshortselftest;
+extern unsigned char smartextendselftest;
+extern unsigned char smartshortcapselftest;
+extern unsigned char smartextendcapselftest;
+extern unsigned char smartselftestabort;
+extern unsigned char smartautoofflineenable;
+extern unsigned char smartautoofflinedisable;
+extern unsigned char smartautosaveenable;
+extern unsigned char smartautosavedisable;
+extern unsigned char smart009minutes;
+
+#endif
diff --git a/sm5/scsicmds.c b/sm5/scsicmds.c
index 6882e25dc..ae02f29a7 100644
--- a/sm5/scsicmds.c
+++ b/sm5/scsicmds.c
@@ -1,811 +1,811 @@
-//  $Id: scsicmds.c,v 1.4 2002/10/11 09:20:32 ballen4705 Exp $
-
-/*
- * scsicmds.c
- *
- * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <linux/hdreg.h>
-#include <scsi/scsi.h>
-#include "scsicmds.h"
-
-
-
-
-UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf)
-{
-  struct cdb10hdr *ioctlhdr;
-  UINT8 tBuf[1024 + CDB_12_HDR_SIZE];
-  UINT8 status;
-
-  
-  memset ( &tBuf, 0, 255);
-    
-  ioctlhdr = (struct cdb10hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 1024;
-   
-  ioctlhdr->cdb[0] = LOG_SENSE;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = 0x40 | pagenum;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  ioctlhdr->cdb[6] = 0x00;
-  ioctlhdr->cdb[7] = 0x04;
-  ioctlhdr->cdb[8] = 0x00;
-  ioctlhdr->cdb[9] = 0x00;
-
-  status =  ioctl( device, 1 , &tBuf);
-
-	
-  memcpy ( pBuf, &tBuf[8], 1024); 
-
-  return status;
-  
-}
-
-
-
-
-UINT8 modesense (int device,  UINT8 pagenum, UINT8 *pBuf)
-{
-  
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = MODE_SENSE;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = pagenum;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  
-  status =  ioctl( device, 1 , &tBuf);
-  
-  memcpy ( pBuf, &tBuf[8], 256); 
-
-  return status;
-
-}
-
-
-
-
-UINT8 modeselect (int device,  UINT8 pagenum, UINT8 *pBuf)
-{
-  struct cdb6hdr *ioctlhdr;
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = pBuf[0] + 1;
-  ioctlhdr->outbufsize = 0;
-  
-  
-  ioctlhdr->cdb[0] = MODE_SELECT;
-  ioctlhdr->cdb[1] = 0x11;
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = pBuf[0] + 1;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  tBuf[CDB_6_HDR_SIZE + 3]  = 0x08;
-  tBuf[CDB_6_HDR_SIZE + 10] = 0x02;
-  
-    
-  memcpy ( &tBuf[ CDB_6_HDR_SIZE + MODE_DATA_HDR_SIZE],
-			 pBuf +  MODE_DATA_HDR_SIZE,
-			pBuf[0] - MODE_DATA_HDR_SIZE + 1);
-
-  tBuf[26] &= 0x3f;		
- 
-  status = ioctl( device, 1 , &tBuf);
-
-  return status;
-
-}
-
-
-
-
-UINT8 modesense10 (int device, UINT8 pagenum, UINT8 *pBuf)
-{
-  
-    struct cdb10hdr *ioctlhdr;
-  UINT8 tBuf[1024];
-  UINT8 status;
-	
-  memset ( &tBuf, 0, 1024);
-    
-  ioctlhdr = (struct cdb10hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = MODE_SELECT_10;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = 0x11;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  ioctlhdr->cdb[6] = 0x00;
-  ioctlhdr->cdb[7] = 0x00;
-  ioctlhdr->cdb[8] = 0xff;
-  ioctlhdr->cdb[9] = 0x00;
-
-  status =  ioctl( device, 1 , &tBuf);
- 
-  memcpy ( pBuf, &tBuf[8], 0xff); 
-  
-  return status;
-
-}
-
-
-
-
-UINT8 modeselect10 (int device,  UINT8 pagenum, UINT8 *pBuf)
-{
-  struct cdb10hdr *ioctlhdr;
-  UINT8 tBuf[CDB_10_MAX_DATA_SIZE + CDB_10_HDR_SIZE ];
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_10_MAX_DATA_SIZE + CDB_10_HDR_SIZE );
-
-  ioctlhdr = (struct cdb10hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = pBuf[0] + 1;
-  ioctlhdr->outbufsize = 0;
-  
-  ioctlhdr->cdb[0] = MODE_SELECT_10;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = pagenum;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  ioctlhdr->cdb[6] = 0x00;
-  ioctlhdr->cdb[7] = 0x00;
-  ioctlhdr->cdb[8] = pBuf[0] + 1;
-  ioctlhdr->cdb[9] = 0x00;
-  
-  tBuf[CDB_10_HDR_SIZE + 3]  = 0x08;
-  tBuf[CDB_10_HDR_SIZE + 10] = 0x02;
-  
-    
-  memcpy ( &tBuf[ CDB_10_HDR_SIZE + MODE_DATA_HDR_SIZE],
-			 pBuf +  MODE_DATA_HDR_SIZE,
-			pBuf[0] - MODE_DATA_HDR_SIZE + 1);
-
-  tBuf[26] &= 0x3f;		
- 
-  status = ioctl( device, 1 , &tBuf);
-
-  return status;
-
-}
-
-
-
-
-UINT8 stdinquiry ( int device, UINT8 *pBuf)
-{
- 
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = CDB_6_MAX_DATA_SIZE;
-   
-  ioctlhdr->cdb[0] = INQUIRY;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  
-  status =  ioctl( device, 1, &tBuf );
-  
-  memcpy ( pBuf, &tBuf[8], 255); 
-
-  return status;
-
-}
-
-
-
-
-UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf)
-{
- 
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = INQUIRY;
-  ioctlhdr->cdb[1] = 0x01;
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = pagenum;
-  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  
-  status =  ioctl( device, 6 , &tBuf);
-  /*status =  ioctl( device, 1 , &tBuf);*/
-  
-  memcpy ( pBuf, &tBuf[8], 255); 
-
-  return status;
-
-}
-
-
-
-
-UINT8 requestsense (int device, UINT8 *pBuf)
-{
-    
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = REQUEST_SENSE;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  
-  status =  ioctl( device, 1 , &tBuf);
-  
-  memcpy ( pBuf, &tBuf[8], 255); 
-
-  return status;
-}
-
-
-UINT8 senddiagnostic (int device, UINT8 functioncode,  UINT8 *pBuf)
-{
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = SEND_DIAGNOSTIC;
-  
-  if (functioncode != SCSI_DIAG_SELF_TEST)
-	ioctlhdr->cdb[1] = ( functioncode <<5 ) | 0x10;
-  
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  if (pBuf != NULL)
-  {
-	  ioctlhdr->inbufsize = pBuf[0];	
-      ioctlhdr->cdb[4] = pBuf[0];
-	  memcpy ( &tBuf[CDB_6_HDR_SIZE],
-				pBuf + 1,
-				pBuf[0]);
-  }
-
-  status =  ioctl( device, 1 , &tBuf);
-  
-  if (pBuf != NULL)
-  	memcpy ( pBuf, &tBuf[8], 256); 
-
-  return status;
-
-}
-
-
-
-UINT8 receivediagnostic (int device, UINT8 pagenum,  UINT8 *pBuf)
-{
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = RECEIVE_DIAGNOSTIC;
-  
-  ioctlhdr->cdb[1] = 0x01;
-  
-  ioctlhdr->cdb[2] = pagenum;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  
-
-  status =  ioctl( device, 1 , &tBuf);
-  
-  memcpy ( pBuf, &tBuf[8], 256); 
-
-  return status;
-
-}
-
-
-UINT8 testunitready (int device)
-{
-  return ioctl( device, 2 , NULL);
-
-}
-
-
-
-
-/* ModePage1C Handler */
-
-#define SMART_SUPPORT	0x00	
-
-UINT8 scsiSmartModePage1CHandler (int device, UINT8 setting, UINT8 *retval)
-{
-	char tBuf[CDB_6_MAX_DATA_SIZE];
-	
-	if (modesense ( device, 0x1c, (UINT8 *) &tBuf) != 0)
-	{
-		return 1;
-	}
-	
-	switch (setting)
-	{
-		case DEXCPT_DISABLE:
- 			tBuf[14] &= 0xf7;
-			tBuf[15] = 0x04;
-			break;
-		case DEXCPT_ENABLE:
-			tBuf[14] |= 0x08;
-			break;
-		case EWASC_ENABLE:
-			tBuf[14] |= 0x10;
-			break;
-		case EWASC_DISABLE:
-			tBuf[14] &= 0xef;
-			break;
-		case SMART_SUPPORT:
-			*retval = tBuf[14] & 0x08;
-			return 0;
-			break;
-		default:
-			return 1;
-	}
-			
-	if (modeselect ( device, 0x1c, (UINT8 *) &tBuf ) != 0)
-	{
-		return 1;
-	}
-	
-	return 0;
-}
-
-
-
-
-UINT8 scsiSmartSupport (int device, UINT8 *retval)
-{
-	return scsiSmartModePage1CHandler( device, SMART_SUPPORT, retval);
-}
-
-
-
-
-UINT8 scsiSmartEWASCEnable (int device)
-{
-	return scsiSmartModePage1CHandler( device, EWASC_ENABLE, NULL);
-}
-
-
-
-
-UINT8 scsiSmartEWASCDisable (int device)
-{
-	return scsiSmartModePage1CHandler( device, EWASC_DISABLE, NULL);
-}
-
-
-
-
-UINT8 scsiSmartDEXCPTEnable (int device)
-{
-	return scsiSmartModePage1CHandler( device, DEXCPT_ENABLE, NULL);
-}
-
-
-
-
-UINT8 scsiSmartDEXCPTDisable (int device)
-{
-	return scsiSmartModePage1CHandler( device, DEXCPT_DISABLE, NULL);
-}
-
-UINT8 scsiGetTemp ( int device, UINT8 *currenttemp, UINT8 *triptemp)
-{
-    
-   UINT8 tBuf[1024];
-
-  if (logsense ( device , TEMPERATURE_PAGE, (UINT8 *) &tBuf) != 0)
-  {
-     perror ( "Log Sense failed");
-     exit (1);
-  }
-  *currenttemp = tBuf[9];
-  *triptemp = tBuf[15];
-  return 0;
-}
-
-UINT8 scsiCheckSmart(int device, UINT8 method, UINT8 *retval,
-                     UINT8 *currenttemp, UINT8 *triptemp)
-{
-   UINT8 tBuf[1024];
-   UINT8 asc;
-   UINT8 ascq;
-   unsigned short pagesize;
- 
-   *currenttemp = *triptemp = 0;
-  
-   if ( method == CHECK_SMART_BY_LGPG_2F)
-   {
-      if (logsense ( device , SMART_PAGE, (UINT8 *) &tBuf) != 0)
-      {
-	perror ( "Log Sense failed");
-	exit (1);
-      }
-
-      pagesize = (unsigned short) (tBuf[2] << 8) | tBuf[3];
-
-      if ( !pagesize )
-      {
-	/* failed read of page 2F\n */
-	return 1;
-      } 
-
-      asc  = tBuf[8]; 
-      ascq = tBuf[9];
-
-      if ( pagesize == 8 && (currenttemp != NULL) && (triptemp != NULL) )
-      {
-	*currenttemp = tBuf[10];
-	*triptemp =  tBuf[11];
-      }	
-
-   }
-   else
-   {
-      if (requestsense ( device , (UINT8 *) &tBuf) != 0)
-      {
-	perror ( "Request Sense failed");
-	exit (1);
-      }
-      
-      asc = tBuf[12]; 
-      ascq = tBuf[13];
-	
-   }
-
-   if ( asc == 0x5d )
-	*retval = ascq;
-   else
-         *retval = 0;
-
-   return 0;
-}
-
-
-char* scsiTapeAlertsTapeDevice ( unsigned short code)
-{
-
-#define NUMENTRIESINTAPEALERTSTABLE 54
-
-    char *TapeAlertsMessageTable[]=
-    {  " ",
-   "The tape drive is having problems reading data. No data has been lost, but there has been a reduction in the performance of the tape.",
-   "The tape drive is having problems writing data. No data has been lost, but there has been a reduction in the performance of the tape.",
-   "The operation has stopped because an error has occurred while reading or writing data which the drive cannot correct.",
-   "Your data is at risk:\n1. Copy any data you require from this tape. \n2. Do not use this tape again.\n3. Restart the operation with a different tape.",
-   "The tape is damaged or the drive is faulty. Call the tape drive supplier helpline.",
-   "The tape is from a faulty batch or the tape drive is faulty:\n1. Use a good tape to test the drive.\n2. If problem persists, call the tape drive supplier helpline.",
-   "The tape cartridge has reached the end of its calculated useful life: \n1. Copy data you need to another tape.\n2. Discard the old tape.",
-   "The tape cartridge is not data-grade. Any data you back up to the tape is at risk. Replace the cartridge with a data-grade tape.",
-   "You are trying to write to a write-protected cartridge. Remove the write-protection or use another tape.",
-   "You cannot eject the cartridge because the tape drive is in use. Wait until the operation is complete before ejecting the cartridge.",
-   "The tape in the drive is a cleaning cartridge.",
-   "You have tried to load a cartridge of a type which is not supported by this drive.",
-   "The operation has failed because the tape in the drive has snapped:\n1. Discard the old tape.\n2. Restart the operation with a different tape.",
-   "The operation has failed because the tape in the drive has snapped:\n1. Do not attempt to extract the tape cartridge\n2. Call the tape drive supplier helpline.",
-   "The memory in the tape cartridge has failed, which reduces performance. Do not use the cartridge for further backup operations.",
-   "The operation has failed because the tape cartridge was manually ejected while the tape drive was actively writing or reading.",
-   "You have loaded of a type that is read-only in this drive. The cartridge will appear as write-protected.",
-   "The directory on the tape cartridge has been corrupted. File search performance will be degraded. The tape directory can be rebuilt by reading all the data on the cartridge.",
-   "The tape cartridge is nearing the end of its calculated life. It is recommended that you:\n1. Use another tape cartridge for your next backup.\n2.Store this tape in a safe place in case you need to restore data from it.",
-   "The tape drive needs cleaning:\n1. If the operation has stopped, eject the tape and clean the drive.\n2. If the operation has not stopped, wait for it ti finish and then clean the drive. Check the tape drive users manual for device specific cleaning instructions.",
-   "The tape drive is due for routine cleaning:\n1. Wait for the current operation to finish.\n2. The use a cleaning cartridge. Check the tape drive users manual for device specific cleaning instructions.",
-   "The last cleaning cartridge used in the tape drive has worn out:\n1. Discard the worn out cleaning cartridge.\n2. Wait for the current operation to finish.\n 3.Then use a new cleaning cartridge.",
-   "The last cleaning cartridge used in the tape drive was an invalid type:\n1. Do not use this cleaning cartridge in this drive.\n2. Wait for the current operation to finish.\n 3.Then use a new cleaning cartridge.",
-   "The tape drive has requested a retention operation",
-   "A redundant interface port on the tape drive has failed",
-   "A tape drive cooling fan has failed",
-   "A redundant power supply has failed inside the tape drive enclosure. Check the enclosure users manual for instructions on replacing the failed power supply.",
-   "The tape drive power consumption is outside the specified range.",
-   "Preventive maintenance of the tape drive is required. Check the tape drive users manual for device specific preventive maintenance tasks or call the tape drive supplier helpline.",
-   "The tape drive has a hardware fault:\n1. Eject the tape or magazine.\n2. Reset the drive.\n3. Restart the operation.",
-   "The tape drive has a hardware fault:\n1. Turn the tape drive off and then on again.\n2. Restart the operation.\n3. If the problem persists, call the tape drive supplier helpline.\n Check the tape drive users manual for device specific instructions on turning the device power in and off.",
-   "The tape drive has a problem with the host interface:\n1. Check the cables and cable connections.\n2. Restart the operation.",
-   "The operation has failed:\n1. Eject the tape or magazine.\n2. Insert the tape or magazine again.\n3. Restart the operation.",
-   "The firmware download has failed because you have tried to use the incorrect firmware for this tape drive. Obtain the correct firmware and try again.",
-   "Environmental conditions inside the tape drive are outside the specified humidity range.",
-   "Environmental conditions inside the tape drive are outside the specified temperature range.",
-   "The voltage supply to the tape drive is outside the specified range.",
-   "A hardware failure of the tape drive is predicted. Call the tape drive supplier helpline.",
-   "The tape drive may have a fault. Check for availability of diagnostic information and run extended diagnostics if applicable. Check the tape drive users manual for instruction on running extended diagnostic tests and retrieving diagnostic data",
-   "The changer mechanism is having difficulty communicating with the tape drive:\n1. Turn the autoloader off then on.\n2. Restart the operation.\n3. If problem persists, call the tape drive supplier helpline.",
-   "A tape has been left in the autoloader by a previous hardware fault:\n1. Insert an empty magazine to clear the fault.\n2. If the fault does not clear, turn the autoloader off and then on again.\n3. If the problem persists, call the tape drive supplier helpline.",
-   "There is a problem with the autoloader mechanism.",
-   "The operation has failed because the autoloader door is open:\n1. Clear any obstructions from the autoloader door.\n2. Eject the magazine and then insert it again.\n3. If the fault does not clear, turn the autoloader off and then on again.\n4. If the problem persists, call the tape drive supplier helpline.",
-   "The autoloader has a hardware fault:\n1. Turn the autoloader off and then on again.\n2. Restart the operation.\n3. If the problem persists, call the tape drive supplier helpline.\n Check the autoloader users manual for device specific instructions on turning the device power on and off.",
-   "The autoloader cannot operate without the magazine,\n1. Insert the magazine into the autoloader.\n 2. Restart the operation.",
-   "A hardware failure of the changer mechanism is predicted. Call the tape drive supplier helpline.",
-   " ",
-   " ",
-   " ",
-   "Media statistics have been lost at some time in the past",
-   "The tape directory on the tape cartridge just unloaded has been corrupted. File search performance will be degraded. The tape directory can be rebuilt by reading all the data.",
-   "The tape just unloaded could not write its system area successfully:\n1. Copy data to another tape cartridge.\n2. Discard the old cartridge.",
-   "The tape system are could not be read successfully at load time:\n1. Copy data to another tape cartridge.\n2. Discard the old cartridge.",
-   "The start or data could not be found on the tape:\n1. Check you are using the correct format tape.\n2. Discard the tape or return the tape to you supplier",
-    };
-            
-    return ( code > NUMENTRIESINTAPEALERTSTABLE)? "Unknown Alert" : TapeAlertsMessageTable[code];
-}
-
-
-char* scsiSmartGetSenseCode ( UINT8 ascq)
-{
-
- char *smartsensetable [] =   {
-	"FAILURE PREDICTION THRESHOLD EXCEEDED",
-	"MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED",
-	"LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"HARDWARE IMPENDING FAILURE CONTROLLER DETECTED",
-	"HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED",
-	"CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED",
-	"DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"SERVO IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"SERVO IMPENDING FAILURE CONTROLLER DETECTED",
-	"SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"SPINDLE IMPENDING FAILURE CONTROLLER DETECTED",
-	"SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED",
-	"FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"};
-
-	if ( ascq == 0xff)
-		return "SMART Sense: False Alarm";
-	else if ( ascq <= SMART_SENSE_MAX_ENTRY)
-		return smartsensetable[ascq];
-	else
-		return "Unknown Failure";
-
-}
-
-
-
-
-UINT8 scsiSmartOfflineTest (int device)
-{	
-	UINT8 tBuf[256];
-	
-	memset ( &tBuf, 0, 256);
-
-	/* Build SMART Off-line Immediate Diag Header */
-	tBuf[0] = 8;    /* Buffer Length n-1 */
-	tBuf[1] = 0x80; /* Page Code */
-	tBuf[2] = 0x00; /* Reserved */
-	tBuf[3] = 0x00; /* Page Length MSB */
-	tBuf[4] = 0x04; /* Page Length LSB */
-	tBuf[5] = 0x03; /* SMART Revision */
-	tBuf[6] = 0x00; /* Reserved */
-	tBuf[7] = 0x00; /* Off-line Immediate Time MSB */
-	tBuf[8] = 0x00; /* Off-line Immediate Time LSB */
-
-	return senddiagnostic (device, SCSI_DIAG_NO_SELF_TEST, (UINT8 *) &tBuf);
-}
-
-
-UINT8 scsiSmartShortSelfTest (int device)
-{	
-	return senddiagnostic (device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL);
-}
-
-
-UINT8 scsiSmartExtendSelfTest (int device)
-{	
-	return senddiagnostic (device, SCSI_DIAG_BG_EXTENDED_SELF_TEST, NULL);
-}
-
-
-UINT8 scsiSmartShortCapSelfTest (int device)
-{	
-	return senddiagnostic (device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL);
-}
-
-
-UINT8 scsiSmartExtendCapSelfTest (int device)
-{
-	return senddiagnostic (device, SCSI_DIAG_FG_EXTENDED_SELF_TEST, NULL);
-}
-
-
-UINT8 scsiSmartSelfTestAbort (int device)
-{
-	return senddiagnostic (device, SCSI_DIAG_ABORT_SELF_TEST, NULL);
-}
+//  $Id: scsicmds.c,v 1.5 2002/10/12 11:10:01 ballen4705 Exp $
+
+/*
+ * scsicmds.c
+ *
+ * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+#include <scsi/scsi.h>
+#include "scsicmds.h"
+
+
+
+
+UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf)
+{
+  struct cdb10hdr *ioctlhdr;
+  UINT8 tBuf[1024 + CDB_12_HDR_SIZE];
+  UINT8 status;
+
+  
+  memset ( &tBuf, 0, 255);
+    
+  ioctlhdr = (struct cdb10hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 1024;
+   
+  ioctlhdr->cdb[0] = LOG_SENSE;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = 0x40 | pagenum;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  ioctlhdr->cdb[6] = 0x00;
+  ioctlhdr->cdb[7] = 0x04;
+  ioctlhdr->cdb[8] = 0x00;
+  ioctlhdr->cdb[9] = 0x00;
+
+  status =  ioctl( device, 1 , &tBuf);
+
+	
+  memcpy ( pBuf, &tBuf[8], 1024); 
+
+  return status;
+  
+}
+
+
+
+
+UINT8 modesense (int device,  UINT8 pagenum, UINT8 *pBuf)
+{
+  
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = MODE_SENSE;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = pagenum;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  
+  status =  ioctl( device, 1 , &tBuf);
+  
+  memcpy ( pBuf, &tBuf[8], 256); 
+
+  return status;
+
+}
+
+
+
+
+UINT8 modeselect (int device,  UINT8 pagenum, UINT8 *pBuf)
+{
+  struct cdb6hdr *ioctlhdr;
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = pBuf[0] + 1;
+  ioctlhdr->outbufsize = 0;
+  
+  
+  ioctlhdr->cdb[0] = MODE_SELECT;
+  ioctlhdr->cdb[1] = 0x11;
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = pBuf[0] + 1;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  tBuf[CDB_6_HDR_SIZE + 3]  = 0x08;
+  tBuf[CDB_6_HDR_SIZE + 10] = 0x02;
+  
+    
+  memcpy ( &tBuf[ CDB_6_HDR_SIZE + MODE_DATA_HDR_SIZE],
+			 pBuf +  MODE_DATA_HDR_SIZE,
+			pBuf[0] - MODE_DATA_HDR_SIZE + 1);
+
+  tBuf[26] &= 0x3f;		
+ 
+  status = ioctl( device, 1 , &tBuf);
+
+  return status;
+
+}
+
+
+
+
+UINT8 modesense10 (int device, UINT8 pagenum, UINT8 *pBuf)
+{
+  
+    struct cdb10hdr *ioctlhdr;
+  UINT8 tBuf[1024];
+  UINT8 status;
+	
+  memset ( &tBuf, 0, 1024);
+    
+  ioctlhdr = (struct cdb10hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = MODE_SELECT_10;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = 0x11;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  ioctlhdr->cdb[6] = 0x00;
+  ioctlhdr->cdb[7] = 0x00;
+  ioctlhdr->cdb[8] = 0xff;
+  ioctlhdr->cdb[9] = 0x00;
+
+  status =  ioctl( device, 1 , &tBuf);
+ 
+  memcpy ( pBuf, &tBuf[8], 0xff); 
+  
+  return status;
+
+}
+
+
+
+
+UINT8 modeselect10 (int device,  UINT8 pagenum, UINT8 *pBuf)
+{
+  struct cdb10hdr *ioctlhdr;
+  UINT8 tBuf[CDB_10_MAX_DATA_SIZE + CDB_10_HDR_SIZE ];
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_10_MAX_DATA_SIZE + CDB_10_HDR_SIZE );
+
+  ioctlhdr = (struct cdb10hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = pBuf[0] + 1;
+  ioctlhdr->outbufsize = 0;
+  
+  ioctlhdr->cdb[0] = MODE_SELECT_10;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = pagenum;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  ioctlhdr->cdb[6] = 0x00;
+  ioctlhdr->cdb[7] = 0x00;
+  ioctlhdr->cdb[8] = pBuf[0] + 1;
+  ioctlhdr->cdb[9] = 0x00;
+  
+  tBuf[CDB_10_HDR_SIZE + 3]  = 0x08;
+  tBuf[CDB_10_HDR_SIZE + 10] = 0x02;
+  
+    
+  memcpy ( &tBuf[ CDB_10_HDR_SIZE + MODE_DATA_HDR_SIZE],
+			 pBuf +  MODE_DATA_HDR_SIZE,
+			pBuf[0] - MODE_DATA_HDR_SIZE + 1);
+
+  tBuf[26] &= 0x3f;		
+ 
+  status = ioctl( device, 1 , &tBuf);
+
+  return status;
+
+}
+
+
+
+
+UINT8 stdinquiry ( int device, UINT8 *pBuf)
+{
+ 
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = CDB_6_MAX_DATA_SIZE;
+   
+  ioctlhdr->cdb[0] = INQUIRY;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  
+  status =  ioctl( device, 1, &tBuf );
+  
+  memcpy ( pBuf, &tBuf[8], 255); 
+
+  return status;
+
+}
+
+
+
+
+UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf)
+{
+ 
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = INQUIRY;
+  ioctlhdr->cdb[1] = 0x01;
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = pagenum;
+  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  
+  status =  ioctl( device, 6 , &tBuf);
+  /*status =  ioctl( device, 1 , &tBuf);*/
+  
+  memcpy ( pBuf, &tBuf[8], 255); 
+
+  return status;
+
+}
+
+
+
+
+UINT8 requestsense (int device, UINT8 *pBuf)
+{
+    
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = REQUEST_SENSE;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  
+  status =  ioctl( device, 1 , &tBuf);
+  
+  memcpy ( pBuf, &tBuf[8], 255); 
+
+  return status;
+}
+
+
+UINT8 senddiagnostic (int device, UINT8 functioncode,  UINT8 *pBuf)
+{
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = SEND_DIAGNOSTIC;
+  
+  if (functioncode != SCSI_DIAG_SELF_TEST)
+	ioctlhdr->cdb[1] = ( functioncode <<5 ) | 0x10;
+  
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  if (pBuf != NULL)
+  {
+	  ioctlhdr->inbufsize = pBuf[0];	
+      ioctlhdr->cdb[4] = pBuf[0];
+	  memcpy ( &tBuf[CDB_6_HDR_SIZE],
+				pBuf + 1,
+				pBuf[0]);
+  }
+
+  status =  ioctl( device, 1 , &tBuf);
+  
+  if (pBuf != NULL)
+  	memcpy ( pBuf, &tBuf[8], 256); 
+
+  return status;
+
+}
+
+
+
+UINT8 receivediagnostic (int device, UINT8 pagenum,  UINT8 *pBuf)
+{
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = RECEIVE_DIAGNOSTIC;
+  
+  ioctlhdr->cdb[1] = 0x01;
+  
+  ioctlhdr->cdb[2] = pagenum;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  
+
+  status =  ioctl( device, 1 , &tBuf);
+  
+  memcpy ( pBuf, &tBuf[8], 256); 
+
+  return status;
+
+}
+
+
+UINT8 testunitready (int device)
+{
+  return ioctl( device, 2 , NULL);
+
+}
+
+
+
+
+/* ModePage1C Handler */
+
+#define SMART_SUPPORT	0x00	
+
+UINT8 scsiSmartModePage1CHandler (int device, UINT8 setting, UINT8 *retval)
+{
+	char tBuf[CDB_6_MAX_DATA_SIZE];
+	
+	if (modesense ( device, 0x1c, (UINT8 *) &tBuf) != 0)
+	{
+		return 1;
+	}
+	
+	switch (setting)
+	{
+		case DEXCPT_DISABLE:
+ 			tBuf[14] &= 0xf7;
+			tBuf[15] = 0x04;
+			break;
+		case DEXCPT_ENABLE:
+			tBuf[14] |= 0x08;
+			break;
+		case EWASC_ENABLE:
+			tBuf[14] |= 0x10;
+			break;
+		case EWASC_DISABLE:
+			tBuf[14] &= 0xef;
+			break;
+		case SMART_SUPPORT:
+			*retval = tBuf[14] & 0x08;
+			return 0;
+			break;
+		default:
+			return 1;
+	}
+			
+	if (modeselect ( device, 0x1c, (UINT8 *) &tBuf ) != 0)
+	{
+		return 1;
+	}
+	
+	return 0;
+}
+
+
+
+
+UINT8 scsiSmartSupport (int device, UINT8 *retval)
+{
+	return scsiSmartModePage1CHandler( device, SMART_SUPPORT, retval);
+}
+
+
+
+
+UINT8 scsiSmartEWASCEnable (int device)
+{
+	return scsiSmartModePage1CHandler( device, EWASC_ENABLE, NULL);
+}
+
+
+
+
+UINT8 scsiSmartEWASCDisable (int device)
+{
+	return scsiSmartModePage1CHandler( device, EWASC_DISABLE, NULL);
+}
+
+
+
+
+UINT8 scsiSmartDEXCPTEnable (int device)
+{
+	return scsiSmartModePage1CHandler( device, DEXCPT_ENABLE, NULL);
+}
+
+
+
+
+UINT8 scsiSmartDEXCPTDisable (int device)
+{
+	return scsiSmartModePage1CHandler( device, DEXCPT_DISABLE, NULL);
+}
+
+UINT8 scsiGetTemp ( int device, UINT8 *currenttemp, UINT8 *triptemp)
+{
+    
+   UINT8 tBuf[1024];
+
+  if (logsense ( device , TEMPERATURE_PAGE, (UINT8 *) &tBuf) != 0)
+  {
+     perror ( "Log Sense failed");
+     exit (1);
+  }
+  *currenttemp = tBuf[9];
+  *triptemp = tBuf[15];
+  return 0;
+}
+
+UINT8 scsiCheckSmart(int device, UINT8 method, UINT8 *retval,
+                     UINT8 *currenttemp, UINT8 *triptemp)
+{
+   UINT8 tBuf[1024];
+   UINT8 asc;
+   UINT8 ascq;
+   unsigned short pagesize;
+ 
+   *currenttemp = *triptemp = 0;
+  
+   if ( method == CHECK_SMART_BY_LGPG_2F)
+   {
+      if (logsense ( device , SMART_PAGE, (UINT8 *) &tBuf) != 0)
+      {
+	perror ( "Log Sense failed");
+	exit (1);
+      }
+
+      pagesize = (unsigned short) (tBuf[2] << 8) | tBuf[3];
+
+      if ( !pagesize )
+      {
+	/* failed read of page 2F\n */
+	return 1;
+      } 
+
+      asc  = tBuf[8]; 
+      ascq = tBuf[9];
+
+      if ( pagesize == 8 && (currenttemp != NULL) && (triptemp != NULL) )
+      {
+	*currenttemp = tBuf[10];
+	*triptemp =  tBuf[11];
+      }	
+
+   }
+   else
+   {
+      if (requestsense ( device , (UINT8 *) &tBuf) != 0)
+      {
+	perror ( "Request Sense failed");
+	exit (1);
+      }
+      
+      asc = tBuf[12]; 
+      ascq = tBuf[13];
+	
+   }
+
+   if ( asc == 0x5d )
+	*retval = ascq;
+   else
+         *retval = 0;
+
+   return 0;
+}
+
+
+char* scsiTapeAlertsTapeDevice ( unsigned short code)
+{
+
+#define NUMENTRIESINTAPEALERTSTABLE 54
+
+    char *TapeAlertsMessageTable[]=
+    {  " ",
+   "The tape drive is having problems reading data. No data has been lost, but there has been a reduction in the performance of the tape.",
+   "The tape drive is having problems writing data. No data has been lost, but there has been a reduction in the performance of the tape.",
+   "The operation has stopped because an error has occurred while reading or writing data which the drive cannot correct.",
+   "Your data is at risk:\n1. Copy any data you require from this tape. \n2. Do not use this tape again.\n3. Restart the operation with a different tape.",
+   "The tape is damaged or the drive is faulty. Call the tape drive supplier helpline.",
+   "The tape is from a faulty batch or the tape drive is faulty:\n1. Use a good tape to test the drive.\n2. If problem persists, call the tape drive supplier helpline.",
+   "The tape cartridge has reached the end of its calculated useful life: \n1. Copy data you need to another tape.\n2. Discard the old tape.",
+   "The tape cartridge is not data-grade. Any data you back up to the tape is at risk. Replace the cartridge with a data-grade tape.",
+   "You are trying to write to a write-protected cartridge. Remove the write-protection or use another tape.",
+   "You cannot eject the cartridge because the tape drive is in use. Wait until the operation is complete before ejecting the cartridge.",
+   "The tape in the drive is a cleaning cartridge.",
+   "You have tried to load a cartridge of a type which is not supported by this drive.",
+   "The operation has failed because the tape in the drive has snapped:\n1. Discard the old tape.\n2. Restart the operation with a different tape.",
+   "The operation has failed because the tape in the drive has snapped:\n1. Do not attempt to extract the tape cartridge\n2. Call the tape drive supplier helpline.",
+   "The memory in the tape cartridge has failed, which reduces performance. Do not use the cartridge for further backup operations.",
+   "The operation has failed because the tape cartridge was manually ejected while the tape drive was actively writing or reading.",
+   "You have loaded of a type that is read-only in this drive. The cartridge will appear as write-protected.",
+   "The directory on the tape cartridge has been corrupted. File search performance will be degraded. The tape directory can be rebuilt by reading all the data on the cartridge.",
+   "The tape cartridge is nearing the end of its calculated life. It is recommended that you:\n1. Use another tape cartridge for your next backup.\n2.Store this tape in a safe place in case you need to restore data from it.",
+   "The tape drive needs cleaning:\n1. If the operation has stopped, eject the tape and clean the drive.\n2. If the operation has not stopped, wait for it ti finish and then clean the drive. Check the tape drive users manual for device specific cleaning instructions.",
+   "The tape drive is due for routine cleaning:\n1. Wait for the current operation to finish.\n2. The use a cleaning cartridge. Check the tape drive users manual for device specific cleaning instructions.",
+   "The last cleaning cartridge used in the tape drive has worn out:\n1. Discard the worn out cleaning cartridge.\n2. Wait for the current operation to finish.\n 3.Then use a new cleaning cartridge.",
+   "The last cleaning cartridge used in the tape drive was an invalid type:\n1. Do not use this cleaning cartridge in this drive.\n2. Wait for the current operation to finish.\n 3.Then use a new cleaning cartridge.",
+   "The tape drive has requested a retention operation",
+   "A redundant interface port on the tape drive has failed",
+   "A tape drive cooling fan has failed",
+   "A redundant power supply has failed inside the tape drive enclosure. Check the enclosure users manual for instructions on replacing the failed power supply.",
+   "The tape drive power consumption is outside the specified range.",
+   "Preventive maintenance of the tape drive is required. Check the tape drive users manual for device specific preventive maintenance tasks or call the tape drive supplier helpline.",
+   "The tape drive has a hardware fault:\n1. Eject the tape or magazine.\n2. Reset the drive.\n3. Restart the operation.",
+   "The tape drive has a hardware fault:\n1. Turn the tape drive off and then on again.\n2. Restart the operation.\n3. If the problem persists, call the tape drive supplier helpline.\n Check the tape drive users manual for device specific instructions on turning the device power in and off.",
+   "The tape drive has a problem with the host interface:\n1. Check the cables and cable connections.\n2. Restart the operation.",
+   "The operation has failed:\n1. Eject the tape or magazine.\n2. Insert the tape or magazine again.\n3. Restart the operation.",
+   "The firmware download has failed because you have tried to use the incorrect firmware for this tape drive. Obtain the correct firmware and try again.",
+   "Environmental conditions inside the tape drive are outside the specified humidity range.",
+   "Environmental conditions inside the tape drive are outside the specified temperature range.",
+   "The voltage supply to the tape drive is outside the specified range.",
+   "A hardware failure of the tape drive is predicted. Call the tape drive supplier helpline.",
+   "The tape drive may have a fault. Check for availability of diagnostic information and run extended diagnostics if applicable. Check the tape drive users manual for instruction on running extended diagnostic tests and retrieving diagnostic data",
+   "The changer mechanism is having difficulty communicating with the tape drive:\n1. Turn the autoloader off then on.\n2. Restart the operation.\n3. If problem persists, call the tape drive supplier helpline.",
+   "A tape has been left in the autoloader by a previous hardware fault:\n1. Insert an empty magazine to clear the fault.\n2. If the fault does not clear, turn the autoloader off and then on again.\n3. If the problem persists, call the tape drive supplier helpline.",
+   "There is a problem with the autoloader mechanism.",
+   "The operation has failed because the autoloader door is open:\n1. Clear any obstructions from the autoloader door.\n2. Eject the magazine and then insert it again.\n3. If the fault does not clear, turn the autoloader off and then on again.\n4. If the problem persists, call the tape drive supplier helpline.",
+   "The autoloader has a hardware fault:\n1. Turn the autoloader off and then on again.\n2. Restart the operation.\n3. If the problem persists, call the tape drive supplier helpline.\n Check the autoloader users manual for device specific instructions on turning the device power on and off.",
+   "The autoloader cannot operate without the magazine,\n1. Insert the magazine into the autoloader.\n 2. Restart the operation.",
+   "A hardware failure of the changer mechanism is predicted. Call the tape drive supplier helpline.",
+   " ",
+   " ",
+   " ",
+   "Media statistics have been lost at some time in the past",
+   "The tape directory on the tape cartridge just unloaded has been corrupted. File search performance will be degraded. The tape directory can be rebuilt by reading all the data.",
+   "The tape just unloaded could not write its system area successfully:\n1. Copy data to another tape cartridge.\n2. Discard the old cartridge.",
+   "The tape system are could not be read successfully at load time:\n1. Copy data to another tape cartridge.\n2. Discard the old cartridge.",
+   "The start or data could not be found on the tape:\n1. Check you are using the correct format tape.\n2. Discard the tape or return the tape to you supplier",
+    };
+            
+    return ( code > NUMENTRIESINTAPEALERTSTABLE)? "Unknown Alert" : TapeAlertsMessageTable[code];
+}
+
+
+char* scsiSmartGetSenseCode ( UINT8 ascq)
+{
+
+ char *smartsensetable [] =   {
+	"FAILURE PREDICTION THRESHOLD EXCEEDED",
+	"MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED",
+	"LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"HARDWARE IMPENDING FAILURE CONTROLLER DETECTED",
+	"HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED",
+	"CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED",
+	"DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"SERVO IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"SERVO IMPENDING FAILURE CONTROLLER DETECTED",
+	"SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"SPINDLE IMPENDING FAILURE CONTROLLER DETECTED",
+	"SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED",
+	"FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"};
+
+	if ( ascq == 0xff)
+		return "SMART Sense: False Alarm";
+	else if ( ascq <= SMART_SENSE_MAX_ENTRY)
+		return smartsensetable[ascq];
+	else
+		return "Unknown Failure";
+
+}
+
+
+
+
+UINT8 scsiSmartOfflineTest (int device)
+{	
+	UINT8 tBuf[256];
+	
+	memset ( &tBuf, 0, 256);
+
+	/* Build SMART Off-line Immediate Diag Header */
+	tBuf[0] = 8;    /* Buffer Length n-1 */
+	tBuf[1] = 0x80; /* Page Code */
+	tBuf[2] = 0x00; /* Reserved */
+	tBuf[3] = 0x00; /* Page Length MSB */
+	tBuf[4] = 0x04; /* Page Length LSB */
+	tBuf[5] = 0x03; /* SMART Revision */
+	tBuf[6] = 0x00; /* Reserved */
+	tBuf[7] = 0x00; /* Off-line Immediate Time MSB */
+	tBuf[8] = 0x00; /* Off-line Immediate Time LSB */
+
+	return senddiagnostic (device, SCSI_DIAG_NO_SELF_TEST, (UINT8 *) &tBuf);
+}
+
+
+UINT8 scsiSmartShortSelfTest (int device)
+{	
+	return senddiagnostic (device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL);
+}
+
+
+UINT8 scsiSmartExtendSelfTest (int device)
+{	
+	return senddiagnostic (device, SCSI_DIAG_BG_EXTENDED_SELF_TEST, NULL);
+}
+
+
+UINT8 scsiSmartShortCapSelfTest (int device)
+{	
+	return senddiagnostic (device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL);
+}
+
+
+UINT8 scsiSmartExtendCapSelfTest (int device)
+{
+	return senddiagnostic (device, SCSI_DIAG_FG_EXTENDED_SELF_TEST, NULL);
+}
+
+
+UINT8 scsiSmartSelfTestAbort (int device)
+{
+	return senddiagnostic (device, SCSI_DIAG_ABORT_SELF_TEST, NULL);
+}
diff --git a/sm5/scsicmds.cpp b/sm5/scsicmds.cpp
index c0c296e59..5f572a4c9 100644
--- a/sm5/scsicmds.cpp
+++ b/sm5/scsicmds.cpp
@@ -1,811 +1,811 @@
-//  $Id: scsicmds.cpp,v 1.4 2002/10/11 09:20:32 ballen4705 Exp $
-
-/*
- * scsicmds.c
- *
- * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <linux/hdreg.h>
-#include <scsi/scsi.h>
-#include "scsicmds.h"
-
-
-
-
-UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf)
-{
-  struct cdb10hdr *ioctlhdr;
-  UINT8 tBuf[1024 + CDB_12_HDR_SIZE];
-  UINT8 status;
-
-  
-  memset ( &tBuf, 0, 255);
-    
-  ioctlhdr = (struct cdb10hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 1024;
-   
-  ioctlhdr->cdb[0] = LOG_SENSE;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = 0x40 | pagenum;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  ioctlhdr->cdb[6] = 0x00;
-  ioctlhdr->cdb[7] = 0x04;
-  ioctlhdr->cdb[8] = 0x00;
-  ioctlhdr->cdb[9] = 0x00;
-
-  status =  ioctl( device, 1 , &tBuf);
-
-	
-  memcpy ( pBuf, &tBuf[8], 1024); 
-
-  return status;
-  
-}
-
-
-
-
-UINT8 modesense (int device,  UINT8 pagenum, UINT8 *pBuf)
-{
-  
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = MODE_SENSE;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = pagenum;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  
-  status =  ioctl( device, 1 , &tBuf);
-  
-  memcpy ( pBuf, &tBuf[8], 256); 
-
-  return status;
-
-}
-
-
-
-
-UINT8 modeselect (int device,  UINT8 pagenum, UINT8 *pBuf)
-{
-  struct cdb6hdr *ioctlhdr;
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = pBuf[0] + 1;
-  ioctlhdr->outbufsize = 0;
-  
-  
-  ioctlhdr->cdb[0] = MODE_SELECT;
-  ioctlhdr->cdb[1] = 0x11;
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = pBuf[0] + 1;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  tBuf[CDB_6_HDR_SIZE + 3]  = 0x08;
-  tBuf[CDB_6_HDR_SIZE + 10] = 0x02;
-  
-    
-  memcpy ( &tBuf[ CDB_6_HDR_SIZE + MODE_DATA_HDR_SIZE],
-			 pBuf +  MODE_DATA_HDR_SIZE,
-			pBuf[0] - MODE_DATA_HDR_SIZE + 1);
-
-  tBuf[26] &= 0x3f;		
- 
-  status = ioctl( device, 1 , &tBuf);
-
-  return status;
-
-}
-
-
-
-
-UINT8 modesense10 (int device, UINT8 pagenum, UINT8 *pBuf)
-{
-  
-    struct cdb10hdr *ioctlhdr;
-  UINT8 tBuf[1024];
-  UINT8 status;
-	
-  memset ( &tBuf, 0, 1024);
-    
-  ioctlhdr = (struct cdb10hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = MODE_SELECT_10;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = 0x11;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  ioctlhdr->cdb[6] = 0x00;
-  ioctlhdr->cdb[7] = 0x00;
-  ioctlhdr->cdb[8] = 0xff;
-  ioctlhdr->cdb[9] = 0x00;
-
-  status =  ioctl( device, 1 , &tBuf);
- 
-  memcpy ( pBuf, &tBuf[8], 0xff); 
-  
-  return status;
-
-}
-
-
-
-
-UINT8 modeselect10 (int device,  UINT8 pagenum, UINT8 *pBuf)
-{
-  struct cdb10hdr *ioctlhdr;
-  UINT8 tBuf[CDB_10_MAX_DATA_SIZE + CDB_10_HDR_SIZE ];
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_10_MAX_DATA_SIZE + CDB_10_HDR_SIZE );
-
-  ioctlhdr = (struct cdb10hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = pBuf[0] + 1;
-  ioctlhdr->outbufsize = 0;
-  
-  ioctlhdr->cdb[0] = MODE_SELECT_10;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = pagenum;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  ioctlhdr->cdb[6] = 0x00;
-  ioctlhdr->cdb[7] = 0x00;
-  ioctlhdr->cdb[8] = pBuf[0] + 1;
-  ioctlhdr->cdb[9] = 0x00;
-  
-  tBuf[CDB_10_HDR_SIZE + 3]  = 0x08;
-  tBuf[CDB_10_HDR_SIZE + 10] = 0x02;
-  
-    
-  memcpy ( &tBuf[ CDB_10_HDR_SIZE + MODE_DATA_HDR_SIZE],
-			 pBuf +  MODE_DATA_HDR_SIZE,
-			pBuf[0] - MODE_DATA_HDR_SIZE + 1);
-
-  tBuf[26] &= 0x3f;		
- 
-  status = ioctl( device, 1 , &tBuf);
-
-  return status;
-
-}
-
-
-
-
-UINT8 stdinquiry ( int device, UINT8 *pBuf)
-{
- 
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = CDB_6_MAX_DATA_SIZE;
-   
-  ioctlhdr->cdb[0] = INQUIRY;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  
-  status =  ioctl( device, 1, &tBuf );
-  
-  memcpy ( pBuf, &tBuf[8], 255); 
-
-  return status;
-
-}
-
-
-
-
-UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf)
-{
- 
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = INQUIRY;
-  ioctlhdr->cdb[1] = 0x01;
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = pagenum;
-  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  
-  status =  ioctl( device, 6 , &tBuf);
-  /*status =  ioctl( device, 1 , &tBuf);*/
-  
-  memcpy ( pBuf, &tBuf[8], 255); 
-
-  return status;
-
-}
-
-
-
-
-UINT8 requestsense (int device, UINT8 *pBuf)
-{
-    
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = REQUEST_SENSE;
-  ioctlhdr->cdb[1] = 0x00;
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  
-  status =  ioctl( device, 1 , &tBuf);
-  
-  memcpy ( pBuf, &tBuf[8], 255); 
-
-  return status;
-}
-
-
-UINT8 senddiagnostic (int device, UINT8 functioncode,  UINT8 *pBuf)
-{
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = SEND_DIAGNOSTIC;
-  
-  if (functioncode != SCSI_DIAG_SELF_TEST)
-	ioctlhdr->cdb[1] = ( functioncode <<5 ) | 0x10;
-  
-  ioctlhdr->cdb[2] = 0x00;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  
-  if (pBuf != NULL)
-  {
-	  ioctlhdr->inbufsize = pBuf[0];	
-      ioctlhdr->cdb[4] = pBuf[0];
-	  memcpy ( &tBuf[CDB_6_HDR_SIZE],
-				pBuf + 1,
-				pBuf[0]);
-  }
-
-  status =  ioctl( device, 1 , &tBuf);
-  
-  if (pBuf != NULL)
-  	memcpy ( pBuf, &tBuf[8], 256); 
-
-  return status;
-
-}
-
-
-
-UINT8 receivediagnostic (int device, UINT8 pagenum,  UINT8 *pBuf)
-{
-  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
- 
-  struct cdb6hdr *ioctlhdr;
-  	
-  UINT8 status;
-
-  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
-  
-  ioctlhdr = (struct cdb6hdr *) &tBuf;
-  
-  ioctlhdr->inbufsize = 0;
-  ioctlhdr->outbufsize = 0xff;
-   
-  ioctlhdr->cdb[0] = RECEIVE_DIAGNOSTIC;
-  
-  ioctlhdr->cdb[1] = 0x01;
-  
-  ioctlhdr->cdb[2] = pagenum;
-  ioctlhdr->cdb[3] = 0x00;
-  ioctlhdr->cdb[4] = 0x00;
-  ioctlhdr->cdb[5] = 0x00;
-  
-
-  status =  ioctl( device, 1 , &tBuf);
-  
-  memcpy ( pBuf, &tBuf[8], 256); 
-
-  return status;
-
-}
-
-
-UINT8 testunitready (int device)
-{
-  return ioctl( device, 2 , NULL);
-
-}
-
-
-
-
-/* ModePage1C Handler */
-
-#define SMART_SUPPORT	0x00	
-
-UINT8 scsiSmartModePage1CHandler (int device, UINT8 setting, UINT8 *retval)
-{
-	char tBuf[CDB_6_MAX_DATA_SIZE];
-	
-	if (modesense ( device, 0x1c, (UINT8 *) &tBuf) != 0)
-	{
-		return 1;
-	}
-	
-	switch (setting)
-	{
-		case DEXCPT_DISABLE:
- 			tBuf[14] &= 0xf7;
-			tBuf[15] = 0x04;
-			break;
-		case DEXCPT_ENABLE:
-			tBuf[14] |= 0x08;
-			break;
-		case EWASC_ENABLE:
-			tBuf[14] |= 0x10;
-			break;
-		case EWASC_DISABLE:
-			tBuf[14] &= 0xef;
-			break;
-		case SMART_SUPPORT:
-			*retval = tBuf[14] & 0x08;
-			return 0;
-			break;
-		default:
-			return 1;
-	}
-			
-	if (modeselect ( device, 0x1c, (UINT8 *) &tBuf ) != 0)
-	{
-		return 1;
-	}
-	
-	return 0;
-}
-
-
-
-
-UINT8 scsiSmartSupport (int device, UINT8 *retval)
-{
-	return scsiSmartModePage1CHandler( device, SMART_SUPPORT, retval);
-}
-
-
-
-
-UINT8 scsiSmartEWASCEnable (int device)
-{
-	return scsiSmartModePage1CHandler( device, EWASC_ENABLE, NULL);
-}
-
-
-
-
-UINT8 scsiSmartEWASCDisable (int device)
-{
-	return scsiSmartModePage1CHandler( device, EWASC_DISABLE, NULL);
-}
-
-
-
-
-UINT8 scsiSmartDEXCPTEnable (int device)
-{
-	return scsiSmartModePage1CHandler( device, DEXCPT_ENABLE, NULL);
-}
-
-
-
-
-UINT8 scsiSmartDEXCPTDisable (int device)
-{
-	return scsiSmartModePage1CHandler( device, DEXCPT_DISABLE, NULL);
-}
-
-UINT8 scsiGetTemp ( int device, UINT8 *currenttemp, UINT8 *triptemp)
-{
-    
-   UINT8 tBuf[1024];
-
-  if (logsense ( device , TEMPERATURE_PAGE, (UINT8 *) &tBuf) != 0)
-  {
-     perror ( "Log Sense failed");
-     exit (1);
-  }
-  *currenttemp = tBuf[9];
-  *triptemp = tBuf[15];
-  return 0;
-}
-
-UINT8 scsiCheckSmart(int device, UINT8 method, UINT8 *retval,
-                     UINT8 *currenttemp, UINT8 *triptemp)
-{
-   UINT8 tBuf[1024];
-   UINT8 asc;
-   UINT8 ascq;
-   unsigned short pagesize;
- 
-   *currenttemp = *triptemp = 0;
-  
-   if ( method == CHECK_SMART_BY_LGPG_2F)
-   {
-      if (logsense ( device , SMART_PAGE, (UINT8 *) &tBuf) != 0)
-      {
-	perror ( "Log Sense failed");
-	exit (1);
-      }
-
-      pagesize = (unsigned short) (tBuf[2] << 8) | tBuf[3];
-
-      if ( !pagesize )
-      {
-	/* failed read of page 2F\n */
-	return 1;
-      } 
-
-      asc  = tBuf[8]; 
-      ascq = tBuf[9];
-
-      if ( pagesize == 8 && (currenttemp != NULL) && (triptemp != NULL) )
-      {
-	*currenttemp = tBuf[10];
-	*triptemp =  tBuf[11];
-      }	
-
-   }
-   else
-   {
-      if (requestsense ( device , (UINT8 *) &tBuf) != 0)
-      {
-	perror ( "Request Sense failed");
-	exit (1);
-      }
-      
-      asc = tBuf[12]; 
-      ascq = tBuf[13];
-	
-   }
-
-   if ( asc == 0x5d )
-	*retval = ascq;
-   else
-         *retval = 0;
-
-   return 0;
-}
-
-
-char* scsiTapeAlertsTapeDevice ( unsigned short code)
-{
-
-#define NUMENTRIESINTAPEALERTSTABLE 54
-
-    char *TapeAlertsMessageTable[]=
-    {  " ",
-   "The tape drive is having problems reading data. No data has been lost, but there has been a reduction in the performance of the tape.",
-   "The tape drive is having problems writing data. No data has been lost, but there has been a reduction in the performance of the tape.",
-   "The operation has stopped because an error has occurred while reading or writing data which the drive cannot correct.",
-   "Your data is at risk:\n1. Copy any data you require from this tape. \n2. Do not use this tape again.\n3. Restart the operation with a different tape.",
-   "The tape is damaged or the drive is faulty. Call the tape drive supplier helpline.",
-   "The tape is from a faulty batch or the tape drive is faulty:\n1. Use a good tape to test the drive.\n2. If problem persists, call the tape drive supplier helpline.",
-   "The tape cartridge has reached the end of its calculated useful life: \n1. Copy data you need to another tape.\n2. Discard the old tape.",
-   "The tape cartridge is not data-grade. Any data you back up to the tape is at risk. Replace the cartridge with a data-grade tape.",
-   "You are trying to write to a write-protected cartridge. Remove the write-protection or use another tape.",
-   "You cannot eject the cartridge because the tape drive is in use. Wait until the operation is complete before ejecting the cartridge.",
-   "The tape in the drive is a cleaning cartridge.",
-   "You have tried to load a cartridge of a type which is not supported by this drive.",
-   "The operation has failed because the tape in the drive has snapped:\n1. Discard the old tape.\n2. Restart the operation with a different tape.",
-   "The operation has failed because the tape in the drive has snapped:\n1. Do not attempt to extract the tape cartridge\n2. Call the tape drive supplier helpline.",
-   "The memory in the tape cartridge has failed, which reduces performance. Do not use the cartridge for further backup operations.",
-   "The operation has failed because the tape cartridge was manually ejected while the tape drive was actively writing or reading.",
-   "You have loaded of a type that is read-only in this drive. The cartridge will appear as write-protected.",
-   "The directory on the tape cartridge has been corrupted. File search performance will be degraded. The tape directory can be rebuilt by reading all the data on the cartridge.",
-   "The tape cartridge is nearing the end of its calculated life. It is recommended that you:\n1. Use another tape cartridge for your next backup.\n2.Store this tape in a safe place in case you need to restore data from it.",
-   "The tape drive needs cleaning:\n1. If the operation has stopped, eject the tape and clean the drive.\n2. If the operation has not stopped, wait for it ti finish and then clean the drive. Check the tape drive users manual for device specific cleaning instructions.",
-   "The tape drive is due for routine cleaning:\n1. Wait for the current operation to finish.\n2. The use a cleaning cartridge. Check the tape drive users manual for device specific cleaning instructions.",
-   "The last cleaning cartridge used in the tape drive has worn out:\n1. Discard the worn out cleaning cartridge.\n2. Wait for the current operation to finish.\n 3.Then use a new cleaning cartridge.",
-   "The last cleaning cartridge used in the tape drive was an invalid type:\n1. Do not use this cleaning cartridge in this drive.\n2. Wait for the current operation to finish.\n 3.Then use a new cleaning cartridge.",
-   "The tape drive has requested a retention operation",
-   "A redundant interface port on the tape drive has failed",
-   "A tape drive cooling fan has failed",
-   "A redundant power supply has failed inside the tape drive enclosure. Check the enclosure users manual for instructions on replacing the failed power supply.",
-   "The tape drive power consumption is outside the specified range.",
-   "Preventive maintenance of the tape drive is required. Check the tape drive users manual for device specific preventive maintenance tasks or call the tape drive supplier helpline.",
-   "The tape drive has a hardware fault:\n1. Eject the tape or magazine.\n2. Reset the drive.\n3. Restart the operation.",
-   "The tape drive has a hardware fault:\n1. Turn the tape drive off and then on again.\n2. Restart the operation.\n3. If the problem persists, call the tape drive supplier helpline.\n Check the tape drive users manual for device specific instructions on turning the device power in and off.",
-   "The tape drive has a problem with the host interface:\n1. Check the cables and cable connections.\n2. Restart the operation.",
-   "The operation has failed:\n1. Eject the tape or magazine.\n2. Insert the tape or magazine again.\n3. Restart the operation.",
-   "The firmware download has failed because you have tried to use the incorrect firmware for this tape drive. Obtain the correct firmware and try again.",
-   "Environmental conditions inside the tape drive are outside the specified humidity range.",
-   "Environmental conditions inside the tape drive are outside the specified temperature range.",
-   "The voltage supply to the tape drive is outside the specified range.",
-   "A hardware failure of the tape drive is predicted. Call the tape drive supplier helpline.",
-   "The tape drive may have a fault. Check for availability of diagnostic information and run extended diagnostics if applicable. Check the tape drive users manual for instruction on running extended diagnostic tests and retrieving diagnostic data",
-   "The changer mechanism is having difficulty communicating with the tape drive:\n1. Turn the autoloader off then on.\n2. Restart the operation.\n3. If problem persists, call the tape drive supplier helpline.",
-   "A tape has been left in the autoloader by a previous hardware fault:\n1. Insert an empty magazine to clear the fault.\n2. If the fault does not clear, turn the autoloader off and then on again.\n3. If the problem persists, call the tape drive supplier helpline.",
-   "There is a problem with the autoloader mechanism.",
-   "The operation has failed because the autoloader door is open:\n1. Clear any obstructions from the autoloader door.\n2. Eject the magazine and then insert it again.\n3. If the fault does not clear, turn the autoloader off and then on again.\n4. If the problem persists, call the tape drive supplier helpline.",
-   "The autoloader has a hardware fault:\n1. Turn the autoloader off and then on again.\n2. Restart the operation.\n3. If the problem persists, call the tape drive supplier helpline.\n Check the autoloader users manual for device specific instructions on turning the device power on and off.",
-   "The autoloader cannot operate without the magazine,\n1. Insert the magazine into the autoloader.\n 2. Restart the operation.",
-   "A hardware failure of the changer mechanism is predicted. Call the tape drive supplier helpline.",
-   " ",
-   " ",
-   " ",
-   "Media statistics have been lost at some time in the past",
-   "The tape directory on the tape cartridge just unloaded has been corrupted. File search performance will be degraded. The tape directory can be rebuilt by reading all the data.",
-   "The tape just unloaded could not write its system area successfully:\n1. Copy data to another tape cartridge.\n2. Discard the old cartridge.",
-   "The tape system are could not be read successfully at load time:\n1. Copy data to another tape cartridge.\n2. Discard the old cartridge.",
-   "The start or data could not be found on the tape:\n1. Check you are using the correct format tape.\n2. Discard the tape or return the tape to you supplier",
-    };
-            
-    return ( code > NUMENTRIESINTAPEALERTSTABLE)? "Unknown Alert" : TapeAlertsMessageTable[code];
-}
-
-
-char* scsiSmartGetSenseCode ( UINT8 ascq)
-{
-
- char *smartsensetable [] =   {
-	"FAILURE PREDICTION THRESHOLD EXCEEDED",
-	"MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED",
-	"LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"HARDWARE IMPENDING FAILURE CONTROLLER DETECTED",
-	"HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED",
-	"CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED",
-	"DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"SERVO IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"SERVO IMPENDING FAILURE CONTROLLER DETECTED",
-	"SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"SPINDLE IMPENDING FAILURE CONTROLLER DETECTED",
-	"SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
-	"Unknown Failure",
-	"Unknown Failure",
-	"Unknown Failure",
-	"FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
-	"FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
-	"FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
-	"FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
-	"FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED",
-	"FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
-	"FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
-	"FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
-	"FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"};
-
-	if ( ascq == 0xff)
-		return "SMART Sense: False Alarm";
-	else if ( ascq <= SMART_SENSE_MAX_ENTRY)
-		return smartsensetable[ascq];
-	else
-		return "Unknown Failure";
-
-}
-
-
-
-
-UINT8 scsiSmartOfflineTest (int device)
-{	
-	UINT8 tBuf[256];
-	
-	memset ( &tBuf, 0, 256);
-
-	/* Build SMART Off-line Immediate Diag Header */
-	tBuf[0] = 8;    /* Buffer Length n-1 */
-	tBuf[1] = 0x80; /* Page Code */
-	tBuf[2] = 0x00; /* Reserved */
-	tBuf[3] = 0x00; /* Page Length MSB */
-	tBuf[4] = 0x04; /* Page Length LSB */
-	tBuf[5] = 0x03; /* SMART Revision */
-	tBuf[6] = 0x00; /* Reserved */
-	tBuf[7] = 0x00; /* Off-line Immediate Time MSB */
-	tBuf[8] = 0x00; /* Off-line Immediate Time LSB */
-
-	return senddiagnostic (device, SCSI_DIAG_NO_SELF_TEST, (UINT8 *) &tBuf);
-}
-
-
-UINT8 scsiSmartShortSelfTest (int device)
-{	
-	return senddiagnostic (device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL);
-}
-
-
-UINT8 scsiSmartExtendSelfTest (int device)
-{	
-	return senddiagnostic (device, SCSI_DIAG_BG_EXTENDED_SELF_TEST, NULL);
-}
-
-
-UINT8 scsiSmartShortCapSelfTest (int device)
-{	
-	return senddiagnostic (device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL);
-}
-
-
-UINT8 scsiSmartExtendCapSelfTest (int device)
-{
-	return senddiagnostic (device, SCSI_DIAG_FG_EXTENDED_SELF_TEST, NULL);
-}
-
-
-UINT8 scsiSmartSelfTestAbort (int device)
-{
-	return senddiagnostic (device, SCSI_DIAG_ABORT_SELF_TEST, NULL);
-}
+//  $Id: scsicmds.cpp,v 1.5 2002/10/12 11:10:01 ballen4705 Exp $
+
+/*
+ * scsicmds.c
+ *
+ * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+#include <scsi/scsi.h>
+#include "scsicmds.h"
+
+
+
+
+UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf)
+{
+  struct cdb10hdr *ioctlhdr;
+  UINT8 tBuf[1024 + CDB_12_HDR_SIZE];
+  UINT8 status;
+
+  
+  memset ( &tBuf, 0, 255);
+    
+  ioctlhdr = (struct cdb10hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 1024;
+   
+  ioctlhdr->cdb[0] = LOG_SENSE;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = 0x40 | pagenum;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  ioctlhdr->cdb[6] = 0x00;
+  ioctlhdr->cdb[7] = 0x04;
+  ioctlhdr->cdb[8] = 0x00;
+  ioctlhdr->cdb[9] = 0x00;
+
+  status =  ioctl( device, 1 , &tBuf);
+
+	
+  memcpy ( pBuf, &tBuf[8], 1024); 
+
+  return status;
+  
+}
+
+
+
+
+UINT8 modesense (int device,  UINT8 pagenum, UINT8 *pBuf)
+{
+  
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = MODE_SENSE;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = pagenum;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  
+  status =  ioctl( device, 1 , &tBuf);
+  
+  memcpy ( pBuf, &tBuf[8], 256); 
+
+  return status;
+
+}
+
+
+
+
+UINT8 modeselect (int device,  UINT8 pagenum, UINT8 *pBuf)
+{
+  struct cdb6hdr *ioctlhdr;
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = pBuf[0] + 1;
+  ioctlhdr->outbufsize = 0;
+  
+  
+  ioctlhdr->cdb[0] = MODE_SELECT;
+  ioctlhdr->cdb[1] = 0x11;
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = pBuf[0] + 1;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  tBuf[CDB_6_HDR_SIZE + 3]  = 0x08;
+  tBuf[CDB_6_HDR_SIZE + 10] = 0x02;
+  
+    
+  memcpy ( &tBuf[ CDB_6_HDR_SIZE + MODE_DATA_HDR_SIZE],
+			 pBuf +  MODE_DATA_HDR_SIZE,
+			pBuf[0] - MODE_DATA_HDR_SIZE + 1);
+
+  tBuf[26] &= 0x3f;		
+ 
+  status = ioctl( device, 1 , &tBuf);
+
+  return status;
+
+}
+
+
+
+
+UINT8 modesense10 (int device, UINT8 pagenum, UINT8 *pBuf)
+{
+  
+    struct cdb10hdr *ioctlhdr;
+  UINT8 tBuf[1024];
+  UINT8 status;
+	
+  memset ( &tBuf, 0, 1024);
+    
+  ioctlhdr = (struct cdb10hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = MODE_SELECT_10;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = 0x11;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  ioctlhdr->cdb[6] = 0x00;
+  ioctlhdr->cdb[7] = 0x00;
+  ioctlhdr->cdb[8] = 0xff;
+  ioctlhdr->cdb[9] = 0x00;
+
+  status =  ioctl( device, 1 , &tBuf);
+ 
+  memcpy ( pBuf, &tBuf[8], 0xff); 
+  
+  return status;
+
+}
+
+
+
+
+UINT8 modeselect10 (int device,  UINT8 pagenum, UINT8 *pBuf)
+{
+  struct cdb10hdr *ioctlhdr;
+  UINT8 tBuf[CDB_10_MAX_DATA_SIZE + CDB_10_HDR_SIZE ];
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_10_MAX_DATA_SIZE + CDB_10_HDR_SIZE );
+
+  ioctlhdr = (struct cdb10hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = pBuf[0] + 1;
+  ioctlhdr->outbufsize = 0;
+  
+  ioctlhdr->cdb[0] = MODE_SELECT_10;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = pagenum;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  ioctlhdr->cdb[6] = 0x00;
+  ioctlhdr->cdb[7] = 0x00;
+  ioctlhdr->cdb[8] = pBuf[0] + 1;
+  ioctlhdr->cdb[9] = 0x00;
+  
+  tBuf[CDB_10_HDR_SIZE + 3]  = 0x08;
+  tBuf[CDB_10_HDR_SIZE + 10] = 0x02;
+  
+    
+  memcpy ( &tBuf[ CDB_10_HDR_SIZE + MODE_DATA_HDR_SIZE],
+			 pBuf +  MODE_DATA_HDR_SIZE,
+			pBuf[0] - MODE_DATA_HDR_SIZE + 1);
+
+  tBuf[26] &= 0x3f;		
+ 
+  status = ioctl( device, 1 , &tBuf);
+
+  return status;
+
+}
+
+
+
+
+UINT8 stdinquiry ( int device, UINT8 *pBuf)
+{
+ 
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = CDB_6_MAX_DATA_SIZE;
+   
+  ioctlhdr->cdb[0] = INQUIRY;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  
+  status =  ioctl( device, 1, &tBuf );
+  
+  memcpy ( pBuf, &tBuf[8], 255); 
+
+  return status;
+
+}
+
+
+
+
+UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf)
+{
+ 
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = INQUIRY;
+  ioctlhdr->cdb[1] = 0x01;
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = pagenum;
+  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  
+  status =  ioctl( device, 6 , &tBuf);
+  /*status =  ioctl( device, 1 , &tBuf);*/
+  
+  memcpy ( pBuf, &tBuf[8], 255); 
+
+  return status;
+
+}
+
+
+
+
+UINT8 requestsense (int device, UINT8 *pBuf)
+{
+    
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = REQUEST_SENSE;
+  ioctlhdr->cdb[1] = 0x00;
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  
+  status =  ioctl( device, 1 , &tBuf);
+  
+  memcpy ( pBuf, &tBuf[8], 255); 
+
+  return status;
+}
+
+
+UINT8 senddiagnostic (int device, UINT8 functioncode,  UINT8 *pBuf)
+{
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = SEND_DIAGNOSTIC;
+  
+  if (functioncode != SCSI_DIAG_SELF_TEST)
+	ioctlhdr->cdb[1] = ( functioncode <<5 ) | 0x10;
+  
+  ioctlhdr->cdb[2] = 0x00;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  
+  if (pBuf != NULL)
+  {
+	  ioctlhdr->inbufsize = pBuf[0];	
+      ioctlhdr->cdb[4] = pBuf[0];
+	  memcpy ( &tBuf[CDB_6_HDR_SIZE],
+				pBuf + 1,
+				pBuf[0]);
+  }
+
+  status =  ioctl( device, 1 , &tBuf);
+  
+  if (pBuf != NULL)
+  	memcpy ( pBuf, &tBuf[8], 256); 
+
+  return status;
+
+}
+
+
+
+UINT8 receivediagnostic (int device, UINT8 pagenum,  UINT8 *pBuf)
+{
+  UINT8 tBuf[CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE ];
+ 
+  struct cdb6hdr *ioctlhdr;
+  	
+  UINT8 status;
+
+  memset ( &tBuf, 0, CDB_6_MAX_DATA_SIZE + CDB_6_HDR_SIZE );
+  
+  ioctlhdr = (struct cdb6hdr *) &tBuf;
+  
+  ioctlhdr->inbufsize = 0;
+  ioctlhdr->outbufsize = 0xff;
+   
+  ioctlhdr->cdb[0] = RECEIVE_DIAGNOSTIC;
+  
+  ioctlhdr->cdb[1] = 0x01;
+  
+  ioctlhdr->cdb[2] = pagenum;
+  ioctlhdr->cdb[3] = 0x00;
+  ioctlhdr->cdb[4] = 0x00;
+  ioctlhdr->cdb[5] = 0x00;
+  
+
+  status =  ioctl( device, 1 , &tBuf);
+  
+  memcpy ( pBuf, &tBuf[8], 256); 
+
+  return status;
+
+}
+
+
+UINT8 testunitready (int device)
+{
+  return ioctl( device, 2 , NULL);
+
+}
+
+
+
+
+/* ModePage1C Handler */
+
+#define SMART_SUPPORT	0x00	
+
+UINT8 scsiSmartModePage1CHandler (int device, UINT8 setting, UINT8 *retval)
+{
+	char tBuf[CDB_6_MAX_DATA_SIZE];
+	
+	if (modesense ( device, 0x1c, (UINT8 *) &tBuf) != 0)
+	{
+		return 1;
+	}
+	
+	switch (setting)
+	{
+		case DEXCPT_DISABLE:
+ 			tBuf[14] &= 0xf7;
+			tBuf[15] = 0x04;
+			break;
+		case DEXCPT_ENABLE:
+			tBuf[14] |= 0x08;
+			break;
+		case EWASC_ENABLE:
+			tBuf[14] |= 0x10;
+			break;
+		case EWASC_DISABLE:
+			tBuf[14] &= 0xef;
+			break;
+		case SMART_SUPPORT:
+			*retval = tBuf[14] & 0x08;
+			return 0;
+			break;
+		default:
+			return 1;
+	}
+			
+	if (modeselect ( device, 0x1c, (UINT8 *) &tBuf ) != 0)
+	{
+		return 1;
+	}
+	
+	return 0;
+}
+
+
+
+
+UINT8 scsiSmartSupport (int device, UINT8 *retval)
+{
+	return scsiSmartModePage1CHandler( device, SMART_SUPPORT, retval);
+}
+
+
+
+
+UINT8 scsiSmartEWASCEnable (int device)
+{
+	return scsiSmartModePage1CHandler( device, EWASC_ENABLE, NULL);
+}
+
+
+
+
+UINT8 scsiSmartEWASCDisable (int device)
+{
+	return scsiSmartModePage1CHandler( device, EWASC_DISABLE, NULL);
+}
+
+
+
+
+UINT8 scsiSmartDEXCPTEnable (int device)
+{
+	return scsiSmartModePage1CHandler( device, DEXCPT_ENABLE, NULL);
+}
+
+
+
+
+UINT8 scsiSmartDEXCPTDisable (int device)
+{
+	return scsiSmartModePage1CHandler( device, DEXCPT_DISABLE, NULL);
+}
+
+UINT8 scsiGetTemp ( int device, UINT8 *currenttemp, UINT8 *triptemp)
+{
+    
+   UINT8 tBuf[1024];
+
+  if (logsense ( device , TEMPERATURE_PAGE, (UINT8 *) &tBuf) != 0)
+  {
+     perror ( "Log Sense failed");
+     exit (1);
+  }
+  *currenttemp = tBuf[9];
+  *triptemp = tBuf[15];
+  return 0;
+}
+
+UINT8 scsiCheckSmart(int device, UINT8 method, UINT8 *retval,
+                     UINT8 *currenttemp, UINT8 *triptemp)
+{
+   UINT8 tBuf[1024];
+   UINT8 asc;
+   UINT8 ascq;
+   unsigned short pagesize;
+ 
+   *currenttemp = *triptemp = 0;
+  
+   if ( method == CHECK_SMART_BY_LGPG_2F)
+   {
+      if (logsense ( device , SMART_PAGE, (UINT8 *) &tBuf) != 0)
+      {
+	perror ( "Log Sense failed");
+	exit (1);
+      }
+
+      pagesize = (unsigned short) (tBuf[2] << 8) | tBuf[3];
+
+      if ( !pagesize )
+      {
+	/* failed read of page 2F\n */
+	return 1;
+      } 
+
+      asc  = tBuf[8]; 
+      ascq = tBuf[9];
+
+      if ( pagesize == 8 && (currenttemp != NULL) && (triptemp != NULL) )
+      {
+	*currenttemp = tBuf[10];
+	*triptemp =  tBuf[11];
+      }	
+
+   }
+   else
+   {
+      if (requestsense ( device , (UINT8 *) &tBuf) != 0)
+      {
+	perror ( "Request Sense failed");
+	exit (1);
+      }
+      
+      asc = tBuf[12]; 
+      ascq = tBuf[13];
+	
+   }
+
+   if ( asc == 0x5d )
+	*retval = ascq;
+   else
+         *retval = 0;
+
+   return 0;
+}
+
+
+char* scsiTapeAlertsTapeDevice ( unsigned short code)
+{
+
+#define NUMENTRIESINTAPEALERTSTABLE 54
+
+    char *TapeAlertsMessageTable[]=
+    {  " ",
+   "The tape drive is having problems reading data. No data has been lost, but there has been a reduction in the performance of the tape.",
+   "The tape drive is having problems writing data. No data has been lost, but there has been a reduction in the performance of the tape.",
+   "The operation has stopped because an error has occurred while reading or writing data which the drive cannot correct.",
+   "Your data is at risk:\n1. Copy any data you require from this tape. \n2. Do not use this tape again.\n3. Restart the operation with a different tape.",
+   "The tape is damaged or the drive is faulty. Call the tape drive supplier helpline.",
+   "The tape is from a faulty batch or the tape drive is faulty:\n1. Use a good tape to test the drive.\n2. If problem persists, call the tape drive supplier helpline.",
+   "The tape cartridge has reached the end of its calculated useful life: \n1. Copy data you need to another tape.\n2. Discard the old tape.",
+   "The tape cartridge is not data-grade. Any data you back up to the tape is at risk. Replace the cartridge with a data-grade tape.",
+   "You are trying to write to a write-protected cartridge. Remove the write-protection or use another tape.",
+   "You cannot eject the cartridge because the tape drive is in use. Wait until the operation is complete before ejecting the cartridge.",
+   "The tape in the drive is a cleaning cartridge.",
+   "You have tried to load a cartridge of a type which is not supported by this drive.",
+   "The operation has failed because the tape in the drive has snapped:\n1. Discard the old tape.\n2. Restart the operation with a different tape.",
+   "The operation has failed because the tape in the drive has snapped:\n1. Do not attempt to extract the tape cartridge\n2. Call the tape drive supplier helpline.",
+   "The memory in the tape cartridge has failed, which reduces performance. Do not use the cartridge for further backup operations.",
+   "The operation has failed because the tape cartridge was manually ejected while the tape drive was actively writing or reading.",
+   "You have loaded of a type that is read-only in this drive. The cartridge will appear as write-protected.",
+   "The directory on the tape cartridge has been corrupted. File search performance will be degraded. The tape directory can be rebuilt by reading all the data on the cartridge.",
+   "The tape cartridge is nearing the end of its calculated life. It is recommended that you:\n1. Use another tape cartridge for your next backup.\n2.Store this tape in a safe place in case you need to restore data from it.",
+   "The tape drive needs cleaning:\n1. If the operation has stopped, eject the tape and clean the drive.\n2. If the operation has not stopped, wait for it ti finish and then clean the drive. Check the tape drive users manual for device specific cleaning instructions.",
+   "The tape drive is due for routine cleaning:\n1. Wait for the current operation to finish.\n2. The use a cleaning cartridge. Check the tape drive users manual for device specific cleaning instructions.",
+   "The last cleaning cartridge used in the tape drive has worn out:\n1. Discard the worn out cleaning cartridge.\n2. Wait for the current operation to finish.\n 3.Then use a new cleaning cartridge.",
+   "The last cleaning cartridge used in the tape drive was an invalid type:\n1. Do not use this cleaning cartridge in this drive.\n2. Wait for the current operation to finish.\n 3.Then use a new cleaning cartridge.",
+   "The tape drive has requested a retention operation",
+   "A redundant interface port on the tape drive has failed",
+   "A tape drive cooling fan has failed",
+   "A redundant power supply has failed inside the tape drive enclosure. Check the enclosure users manual for instructions on replacing the failed power supply.",
+   "The tape drive power consumption is outside the specified range.",
+   "Preventive maintenance of the tape drive is required. Check the tape drive users manual for device specific preventive maintenance tasks or call the tape drive supplier helpline.",
+   "The tape drive has a hardware fault:\n1. Eject the tape or magazine.\n2. Reset the drive.\n3. Restart the operation.",
+   "The tape drive has a hardware fault:\n1. Turn the tape drive off and then on again.\n2. Restart the operation.\n3. If the problem persists, call the tape drive supplier helpline.\n Check the tape drive users manual for device specific instructions on turning the device power in and off.",
+   "The tape drive has a problem with the host interface:\n1. Check the cables and cable connections.\n2. Restart the operation.",
+   "The operation has failed:\n1. Eject the tape or magazine.\n2. Insert the tape or magazine again.\n3. Restart the operation.",
+   "The firmware download has failed because you have tried to use the incorrect firmware for this tape drive. Obtain the correct firmware and try again.",
+   "Environmental conditions inside the tape drive are outside the specified humidity range.",
+   "Environmental conditions inside the tape drive are outside the specified temperature range.",
+   "The voltage supply to the tape drive is outside the specified range.",
+   "A hardware failure of the tape drive is predicted. Call the tape drive supplier helpline.",
+   "The tape drive may have a fault. Check for availability of diagnostic information and run extended diagnostics if applicable. Check the tape drive users manual for instruction on running extended diagnostic tests and retrieving diagnostic data",
+   "The changer mechanism is having difficulty communicating with the tape drive:\n1. Turn the autoloader off then on.\n2. Restart the operation.\n3. If problem persists, call the tape drive supplier helpline.",
+   "A tape has been left in the autoloader by a previous hardware fault:\n1. Insert an empty magazine to clear the fault.\n2. If the fault does not clear, turn the autoloader off and then on again.\n3. If the problem persists, call the tape drive supplier helpline.",
+   "There is a problem with the autoloader mechanism.",
+   "The operation has failed because the autoloader door is open:\n1. Clear any obstructions from the autoloader door.\n2. Eject the magazine and then insert it again.\n3. If the fault does not clear, turn the autoloader off and then on again.\n4. If the problem persists, call the tape drive supplier helpline.",
+   "The autoloader has a hardware fault:\n1. Turn the autoloader off and then on again.\n2. Restart the operation.\n3. If the problem persists, call the tape drive supplier helpline.\n Check the autoloader users manual for device specific instructions on turning the device power on and off.",
+   "The autoloader cannot operate without the magazine,\n1. Insert the magazine into the autoloader.\n 2. Restart the operation.",
+   "A hardware failure of the changer mechanism is predicted. Call the tape drive supplier helpline.",
+   " ",
+   " ",
+   " ",
+   "Media statistics have been lost at some time in the past",
+   "The tape directory on the tape cartridge just unloaded has been corrupted. File search performance will be degraded. The tape directory can be rebuilt by reading all the data.",
+   "The tape just unloaded could not write its system area successfully:\n1. Copy data to another tape cartridge.\n2. Discard the old cartridge.",
+   "The tape system are could not be read successfully at load time:\n1. Copy data to another tape cartridge.\n2. Discard the old cartridge.",
+   "The start or data could not be found on the tape:\n1. Check you are using the correct format tape.\n2. Discard the tape or return the tape to you supplier",
+    };
+            
+    return ( code > NUMENTRIESINTAPEALERTSTABLE)? "Unknown Alert" : TapeAlertsMessageTable[code];
+}
+
+
+char* scsiSmartGetSenseCode ( UINT8 ascq)
+{
+
+ char *smartsensetable [] =   {
+	"FAILURE PREDICTION THRESHOLD EXCEEDED",
+	"MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED",
+	"LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"HARDWARE IMPENDING FAILURE CONTROLLER DETECTED",
+	"HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED",
+	"CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED",
+	"DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"SERVO IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"SERVO IMPENDING FAILURE CONTROLLER DETECTED",
+	"SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"SPINDLE IMPENDING FAILURE CONTROLLER DETECTED",
+	"SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
+	"Unknown Failure",
+	"Unknown Failure",
+	"Unknown Failure",
+	"FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
+	"FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
+	"FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
+	"FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
+	"FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED",
+	"FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
+	"FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
+	"FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
+	"FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"};
+
+	if ( ascq == 0xff)
+		return "SMART Sense: False Alarm";
+	else if ( ascq <= SMART_SENSE_MAX_ENTRY)
+		return smartsensetable[ascq];
+	else
+		return "Unknown Failure";
+
+}
+
+
+
+
+UINT8 scsiSmartOfflineTest (int device)
+{	
+	UINT8 tBuf[256];
+	
+	memset ( &tBuf, 0, 256);
+
+	/* Build SMART Off-line Immediate Diag Header */
+	tBuf[0] = 8;    /* Buffer Length n-1 */
+	tBuf[1] = 0x80; /* Page Code */
+	tBuf[2] = 0x00; /* Reserved */
+	tBuf[3] = 0x00; /* Page Length MSB */
+	tBuf[4] = 0x04; /* Page Length LSB */
+	tBuf[5] = 0x03; /* SMART Revision */
+	tBuf[6] = 0x00; /* Reserved */
+	tBuf[7] = 0x00; /* Off-line Immediate Time MSB */
+	tBuf[8] = 0x00; /* Off-line Immediate Time LSB */
+
+	return senddiagnostic (device, SCSI_DIAG_NO_SELF_TEST, (UINT8 *) &tBuf);
+}
+
+
+UINT8 scsiSmartShortSelfTest (int device)
+{	
+	return senddiagnostic (device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL);
+}
+
+
+UINT8 scsiSmartExtendSelfTest (int device)
+{	
+	return senddiagnostic (device, SCSI_DIAG_BG_EXTENDED_SELF_TEST, NULL);
+}
+
+
+UINT8 scsiSmartShortCapSelfTest (int device)
+{	
+	return senddiagnostic (device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL);
+}
+
+
+UINT8 scsiSmartExtendCapSelfTest (int device)
+{
+	return senddiagnostic (device, SCSI_DIAG_FG_EXTENDED_SELF_TEST, NULL);
+}
+
+
+UINT8 scsiSmartSelfTestAbort (int device)
+{
+	return senddiagnostic (device, SCSI_DIAG_ABORT_SELF_TEST, NULL);
+}
diff --git a/sm5/scsicmds.h b/sm5/scsicmds.h
index 37e9e92ea..bd91eaad2 100644
--- a/sm5/scsicmds.h
+++ b/sm5/scsicmds.h
@@ -1,271 +1,271 @@
-//  $Id: scsicmds.h,v 1.2 2002/10/11 09:20:32 ballen4705 Exp $
-/*
- * scsicmds.h
- *
- * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef SCSICMDS_H_
-#define SCSICMDS_H_
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <linux/hdreg.h>
-
-typedef unsigned char UINT8;
-typedef char INT8;
-typedef unsigned int UINT32;
-typedef int INT32;
-
-
-
-
-/* Command Descriptor Block for SCSI Commands 
- * There are three standard length 6, 10, and 12 bytes 
- * List below are standard forms of CDBs the are not listed
- * in structure because format can change within specific commands
- * these header include data buffer sizes. This is for used with ioctl
- * 
-*/
-/* 6-type CDB format */
-/*
-	cdb[0] is Opcode
-	cdb[1] bits 5-7 LUN
-	       bits 0-4 Logical Block (MSB)
-	cdb[2] is Logical Block
-	cdb[3] is Logical Block (LSB)
-	cdb[4] is Transfer Length
-	cdb[5] is Control Byte 
-*/
-#define CDB_6_HDR_SIZE			14
-#define CDB_6_MAX_DATA_SIZE		0xff
-
-struct cdb6hdr{
-	UINT32 inbufsize;
-	UINT32 outbufsize;
-	UINT8 cdb [6];
-} __attribute__ ((packed));
-
-
-
-/* 10-type CDB format */
-/*
-	cdb[0] is Opcode
-	cdb[1] bits 5-7 LUN
-	       bits 0-4 Reserved
-	cdb[2] is Logical Block (MSB)
-	cdb[3] is Logical Block
-	cdb[4] is Logical Block
-	cdb[5] is Logical Block (LSB)
-	cdb[6] is Reserved
-	cdb[7] is Transfer Length (MSB)
-	cdb[8] is Transfer Length (LSB)
-	cdb[9] is Control Byte 
-*/
-#define CDB_10_HDR_SIZE 14
-#define CDB_10_MAX_DATA_SIZE		0xffff
-
-struct cdb10hdr {
-	UINT32 inbufsize;
-	UINT32 outbufsize;
-	UINT8 cdb [10];
-} __attribute__ ((packed));
-
-
-
-/* 12-type CDB format */
-/*
-	cdb[0] is Opcode
-	cdb[1] bits 5-7 LUN
-	       bits 0-4 Reserved
-	cdb[2] is Logical Block (MSB)
-	cdb[3] is Logical Block
-	cdb[4] is Logical Block
-	cdb[5] is Logical Block (LSB)
-	cdb[6] is Transfer Length (MSB)
-	cdb[7] is Transfer Length
-	cdb[8] is Transfer Length
-	cdb[9] is Transfer Length (LSB)
-	cdb[10] is Reserved
-	cdb[11] is Control Byte 
-*/
-
-#define CDB_12_HDR_SIZE 14
-#define CDB_12_MAX_DATA_SIZE		0xffffffff
-
-struct cdb12hdr {
-	UINT32 inbufsize;
-	UINT32 outbufsize;
-	UINT8 cdb [12];
-} __attribute__ ((packed));
-
-
-
-/* Mode Select Data Header */
-
-#define MODE_DATA_HDR_SIZE	12
-
-struct modedatahdr {
-	UINT8 modedatalength;
-	UINT8 mediumtype;
-	UINT8 reserved2;
-	UINT8 blockdescriptor;
-	UINT8 numberofblocks[3];
-	UINT8 densitycode;
-	UINT8 blocklength[3];
-} ;
-
-
-
-/* ANSI SCSI-3 Log Sense Return Log Pages from device. */
-#define SUPPORT_LOG_PAGES				0x00
-#define BUFFER_OVERRUN_PAGE				0x01
-#define WRITE_ERROR_COUNTER_PAGE		0x02
-#define READ_ERROR_COUNTER_PAGE			0x03
-#define READ_REVERSE_ERROR_COUNTER_PAGE 0x04
-#define VERIFY_ERROR_COUNTER_PAGE		0x05
-#define NON_MEDIUM_ERROR_PAGE			0x06
-#define LAST_N_ERROR_PAGE				0x07
-#define FORMAT_STATUS_PAGE				0x08
-#define TEMPERATURE_PAGE				0x0d
-#define STARTSTOP_CYCLE_COUNTER_PAGE	0x0e
-#define APPLICATION_CLIENT_PAGE			0x0f
-#define SELFTEST_RESULTS_PAGE			0x10
-
-/* From IBM Documentation */
-/* See more information at http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
-#define TAPE_ALERTS_PAGE				0x2e
-#define SMART_PAGE						0x2f
-
-/* ANSI SCSI-3 Mode Pages */
-#define VENDOR_UNIQUE_PARAMETERS		     0x00
-#define READ_WRITE_ERROR_RECOVERY_PARAMETERS 0x01
-#define DISCONNECT_RECONNECT_PARAMETERS		 0x02
-#define FORMAT_DEVICE_PARAMETERS             0x03
-#define RIGID_DISK_DRIVE_GEOMETRY_PARAMETERS 0x04
-#define FLEXIBLE_DISK_PARAMETERS			 0x05
-#define VERIFY_ERROR_RECOVERY_PARAMETERS	 0x07
-#define CACHING_PARAMETERS					 0x08
-#define PERIPHERAL_DEVICE					 0x09
-#define XOR_CONTROL_MODE_PARAMETERS			 0x10
-#define CONTROL_MODE_PAGE_PARAMETERS		 0x0a
-#define MEDIUM_TYPES_SUPPORTED				 0x0b
-#define NOTCH_PARAMETERS					 0x0c
-#define POWER_CONDITION_PARAMETERS			 0x0d
-#define CD_DEVICE_PARAMETERS				 0x0d
-#define CD_AUDIO_CONTROL_PAGE				 0x0e
-#define DATA_COMPRESSION_PARAMETERS			 0x0f
-#define MEDIUM_PARTITION_MODE_PARAMTERES_1	 0x11
-#define MEDIUM_PARTITION_MODE_PARAMTERES_2	 0x12
-#define MEDIUM_PARTITION_MODE_PARAMTERES_3	 0x13
-#define MEDIUM_PARTITION_MODE_PARAMTERES_4	 0x14
-#define ENCLOSURE_SERVICES_MANAGEMENT		 0x14
-#define LUN_CONTROL							 0x18
-#define PORT_CONTROL						 0x19
-#define POWER_CONTROL						 0x1a
-#define LUN_MAPPING_PAGE					 0x1b
-#define INFORMATIONAL_EXCEPTIONS_CONTROL	 0x1c
-#define FAULT_FAILURE_REPORTING_PAGE		 0x1c
-#define ELEMENT_ADDRESS_ASSIGNMENT			 0x1d
-#define TIMEOUT_AND_PROTECT_PARAMETERS		 0x1d
-#define TRANSPORT_GEOMETRY_PARAMETERS		 0x1e
-#define DEVICE_CAPABILITIES					 0x1f
-#define CD_CAPABILITIES_AND_MECHANISM_STATUS 0x2a
-
-#define ALL_PARAMETERS						 0x3f
-
-
-/* defines for functioncode parameter in SENDDIAGNOSTIC function */
-
-#define SCSI_DIAG_NO_SELF_TEST			0x00
-#define SCSI_DIAG_SELF_TEST				0xff
-#define SCSI_DIAG_BG_SHORT_SELF_TEST	0x01
-#define SCSI_DIAG_BG_EXTENDED_SELF_TEST	0x02
-#define SCSI_DIAG_FG_SHORT_SELF_TEST	0x05
-#define SCSI_DIAG_FG_EXTENDED_SELF_TEST	0x06
-#define SCSI_DIAG_ABORT_SELF_TEST		0x04
-
-
-
-#define LOGPAGEHDRSIZE	4
-
-/* STANDARD SCSI Commands  */
-UINT8 testunitready (int device);
-
-UINT8 stdinquiry ( int device, UINT8 *pBuffer);
-
-UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf);
-
-UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuffer);
-
-UINT8 modesense ( int device, UINT8 pagenum, UINT8 *pBuffer);
-
-UINT8 modeselect ( int device, UINT8 pagenum, UINT8 *pBuffer);
-
-UINT8 modesense10 ( int device, UINT8 pagenum, UINT8 *pBuffer);
-
-UINT8 modeselect10 ( int device, UINT8 pagenum, UINT8 *pBuffer);
-
-UINT8 requestsense (int device,   UINT8 *pBuffer);
-
-UINT8 senddiagnostic (int device, UINT8 functioncode, UINT8 *pBuffer);
-
-UINT8 receivediagnostic (int device, UINT8 pagenum,  UINT8 *pBuf);
-/* S.M.A.R.T. specific commands */
-
-/*scsSmartSupport return value  can be masked with the following */
-/* Parsing response of ModePage 1c */
-#define DEXCPT_DISABLE  0xf7
-#define DEXCPT_ENABLE	0x08
-#define EWASC_ENABLE	0x10
-#define EWASC_DISABLE	0xef
-
-#define CHECK_SMART_BY_LGPG_2F  0x01
-#define CHECK_SMART_BY_REQSENSE 0x00
-
-#define SMART_SENSE_MAX_ENTRY	0x6c
-
-UINT8 scsiCheckSmart(int device, UINT8 method, UINT8 *retval, UINT8 *currenttemp, UINT8 *triptemp);
-
-UINT8 scsiSmartSupport (int device, UINT8 *retval);
-
-
-UINT8 scsiSmartEWASCEnable (int device);
-UINT8 scsiSmartEWASCDisable (int device);
-
-UINT8 scsiSmartDEXCPTEnable (int device);
-UINT8 scsiSmartDEXCPTDisable (int device);
-
-
-/* T10 Standard SMART Sense Code assignment taken from t10.org */
-
-char* scsiSmartGetSenseCode ( UINT8 ascq);
-UINT8 scsiGetTemp ( int device, UINT8 *currenttemp, UINT8 *triptemp);
-
-
-UINT8 scsiSmartOfflineTest (int device);
-UINT8 scsiSmartShortSelfTest (int device);
-UINT8 scsiSmartExtendSelfTest (int device);
-UINT8 scsiSmartShortCapSelfTest (int device);
-UINT8 scsiSmartExtendCapSelfTest (int device);
-UINT8 scsiSmartSelfTestAbort (int device);
-
-char* scsiTapeAlertsTapeDevice ( unsigned short code);
-#endif
-
+//  $Id: scsicmds.h,v 1.3 2002/10/12 11:10:01 ballen4705 Exp $
+/*
+ * scsicmds.h
+ *
+ * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef SCSICMDS_H_
+#define SCSICMDS_H_
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+
+typedef unsigned char UINT8;
+typedef char INT8;
+typedef unsigned int UINT32;
+typedef int INT32;
+
+
+
+
+/* Command Descriptor Block for SCSI Commands 
+ * There are three standard length 6, 10, and 12 bytes 
+ * List below are standard forms of CDBs the are not listed
+ * in structure because format can change within specific commands
+ * these header include data buffer sizes. This is for used with ioctl
+ * 
+*/
+/* 6-type CDB format */
+/*
+	cdb[0] is Opcode
+	cdb[1] bits 5-7 LUN
+	       bits 0-4 Logical Block (MSB)
+	cdb[2] is Logical Block
+	cdb[3] is Logical Block (LSB)
+	cdb[4] is Transfer Length
+	cdb[5] is Control Byte 
+*/
+#define CDB_6_HDR_SIZE			14
+#define CDB_6_MAX_DATA_SIZE		0xff
+
+struct cdb6hdr{
+	UINT32 inbufsize;
+	UINT32 outbufsize;
+	UINT8 cdb [6];
+} __attribute__ ((packed));
+
+
+
+/* 10-type CDB format */
+/*
+	cdb[0] is Opcode
+	cdb[1] bits 5-7 LUN
+	       bits 0-4 Reserved
+	cdb[2] is Logical Block (MSB)
+	cdb[3] is Logical Block
+	cdb[4] is Logical Block
+	cdb[5] is Logical Block (LSB)
+	cdb[6] is Reserved
+	cdb[7] is Transfer Length (MSB)
+	cdb[8] is Transfer Length (LSB)
+	cdb[9] is Control Byte 
+*/
+#define CDB_10_HDR_SIZE 14
+#define CDB_10_MAX_DATA_SIZE		0xffff
+
+struct cdb10hdr {
+	UINT32 inbufsize;
+	UINT32 outbufsize;
+	UINT8 cdb [10];
+} __attribute__ ((packed));
+
+
+
+/* 12-type CDB format */
+/*
+	cdb[0] is Opcode
+	cdb[1] bits 5-7 LUN
+	       bits 0-4 Reserved
+	cdb[2] is Logical Block (MSB)
+	cdb[3] is Logical Block
+	cdb[4] is Logical Block
+	cdb[5] is Logical Block (LSB)
+	cdb[6] is Transfer Length (MSB)
+	cdb[7] is Transfer Length
+	cdb[8] is Transfer Length
+	cdb[9] is Transfer Length (LSB)
+	cdb[10] is Reserved
+	cdb[11] is Control Byte 
+*/
+
+#define CDB_12_HDR_SIZE 14
+#define CDB_12_MAX_DATA_SIZE		0xffffffff
+
+struct cdb12hdr {
+	UINT32 inbufsize;
+	UINT32 outbufsize;
+	UINT8 cdb [12];
+} __attribute__ ((packed));
+
+
+
+/* Mode Select Data Header */
+
+#define MODE_DATA_HDR_SIZE	12
+
+struct modedatahdr {
+	UINT8 modedatalength;
+	UINT8 mediumtype;
+	UINT8 reserved2;
+	UINT8 blockdescriptor;
+	UINT8 numberofblocks[3];
+	UINT8 densitycode;
+	UINT8 blocklength[3];
+} ;
+
+
+
+/* ANSI SCSI-3 Log Sense Return Log Pages from device. */
+#define SUPPORT_LOG_PAGES				0x00
+#define BUFFER_OVERRUN_PAGE				0x01
+#define WRITE_ERROR_COUNTER_PAGE		0x02
+#define READ_ERROR_COUNTER_PAGE			0x03
+#define READ_REVERSE_ERROR_COUNTER_PAGE 0x04
+#define VERIFY_ERROR_COUNTER_PAGE		0x05
+#define NON_MEDIUM_ERROR_PAGE			0x06
+#define LAST_N_ERROR_PAGE				0x07
+#define FORMAT_STATUS_PAGE				0x08
+#define TEMPERATURE_PAGE				0x0d
+#define STARTSTOP_CYCLE_COUNTER_PAGE	0x0e
+#define APPLICATION_CLIENT_PAGE			0x0f
+#define SELFTEST_RESULTS_PAGE			0x10
+
+/* From IBM Documentation */
+/* See more information at http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
+#define TAPE_ALERTS_PAGE				0x2e
+#define SMART_PAGE						0x2f
+
+/* ANSI SCSI-3 Mode Pages */
+#define VENDOR_UNIQUE_PARAMETERS		     0x00
+#define READ_WRITE_ERROR_RECOVERY_PARAMETERS 0x01
+#define DISCONNECT_RECONNECT_PARAMETERS		 0x02
+#define FORMAT_DEVICE_PARAMETERS             0x03
+#define RIGID_DISK_DRIVE_GEOMETRY_PARAMETERS 0x04
+#define FLEXIBLE_DISK_PARAMETERS			 0x05
+#define VERIFY_ERROR_RECOVERY_PARAMETERS	 0x07
+#define CACHING_PARAMETERS					 0x08
+#define PERIPHERAL_DEVICE					 0x09
+#define XOR_CONTROL_MODE_PARAMETERS			 0x10
+#define CONTROL_MODE_PAGE_PARAMETERS		 0x0a
+#define MEDIUM_TYPES_SUPPORTED				 0x0b
+#define NOTCH_PARAMETERS					 0x0c
+#define POWER_CONDITION_PARAMETERS			 0x0d
+#define CD_DEVICE_PARAMETERS				 0x0d
+#define CD_AUDIO_CONTROL_PAGE				 0x0e
+#define DATA_COMPRESSION_PARAMETERS			 0x0f
+#define MEDIUM_PARTITION_MODE_PARAMTERES_1	 0x11
+#define MEDIUM_PARTITION_MODE_PARAMTERES_2	 0x12
+#define MEDIUM_PARTITION_MODE_PARAMTERES_3	 0x13
+#define MEDIUM_PARTITION_MODE_PARAMTERES_4	 0x14
+#define ENCLOSURE_SERVICES_MANAGEMENT		 0x14
+#define LUN_CONTROL							 0x18
+#define PORT_CONTROL						 0x19
+#define POWER_CONTROL						 0x1a
+#define LUN_MAPPING_PAGE					 0x1b
+#define INFORMATIONAL_EXCEPTIONS_CONTROL	 0x1c
+#define FAULT_FAILURE_REPORTING_PAGE		 0x1c
+#define ELEMENT_ADDRESS_ASSIGNMENT			 0x1d
+#define TIMEOUT_AND_PROTECT_PARAMETERS		 0x1d
+#define TRANSPORT_GEOMETRY_PARAMETERS		 0x1e
+#define DEVICE_CAPABILITIES					 0x1f
+#define CD_CAPABILITIES_AND_MECHANISM_STATUS 0x2a
+
+#define ALL_PARAMETERS						 0x3f
+
+
+/* defines for functioncode parameter in SENDDIAGNOSTIC function */
+
+#define SCSI_DIAG_NO_SELF_TEST			0x00
+#define SCSI_DIAG_SELF_TEST				0xff
+#define SCSI_DIAG_BG_SHORT_SELF_TEST	0x01
+#define SCSI_DIAG_BG_EXTENDED_SELF_TEST	0x02
+#define SCSI_DIAG_FG_SHORT_SELF_TEST	0x05
+#define SCSI_DIAG_FG_EXTENDED_SELF_TEST	0x06
+#define SCSI_DIAG_ABORT_SELF_TEST		0x04
+
+
+
+#define LOGPAGEHDRSIZE	4
+
+/* STANDARD SCSI Commands  */
+UINT8 testunitready (int device);
+
+UINT8 stdinquiry ( int device, UINT8 *pBuffer);
+
+UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf);
+
+UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuffer);
+
+UINT8 modesense ( int device, UINT8 pagenum, UINT8 *pBuffer);
+
+UINT8 modeselect ( int device, UINT8 pagenum, UINT8 *pBuffer);
+
+UINT8 modesense10 ( int device, UINT8 pagenum, UINT8 *pBuffer);
+
+UINT8 modeselect10 ( int device, UINT8 pagenum, UINT8 *pBuffer);
+
+UINT8 requestsense (int device,   UINT8 *pBuffer);
+
+UINT8 senddiagnostic (int device, UINT8 functioncode, UINT8 *pBuffer);
+
+UINT8 receivediagnostic (int device, UINT8 pagenum,  UINT8 *pBuf);
+/* S.M.A.R.T. specific commands */
+
+/*scsSmartSupport return value  can be masked with the following */
+/* Parsing response of ModePage 1c */
+#define DEXCPT_DISABLE  0xf7
+#define DEXCPT_ENABLE	0x08
+#define EWASC_ENABLE	0x10
+#define EWASC_DISABLE	0xef
+
+#define CHECK_SMART_BY_LGPG_2F  0x01
+#define CHECK_SMART_BY_REQSENSE 0x00
+
+#define SMART_SENSE_MAX_ENTRY	0x6c
+
+UINT8 scsiCheckSmart(int device, UINT8 method, UINT8 *retval, UINT8 *currenttemp, UINT8 *triptemp);
+
+UINT8 scsiSmartSupport (int device, UINT8 *retval);
+
+
+UINT8 scsiSmartEWASCEnable (int device);
+UINT8 scsiSmartEWASCDisable (int device);
+
+UINT8 scsiSmartDEXCPTEnable (int device);
+UINT8 scsiSmartDEXCPTDisable (int device);
+
+
+/* T10 Standard SMART Sense Code assignment taken from t10.org */
+
+char* scsiSmartGetSenseCode ( UINT8 ascq);
+UINT8 scsiGetTemp ( int device, UINT8 *currenttemp, UINT8 *triptemp);
+
+
+UINT8 scsiSmartOfflineTest (int device);
+UINT8 scsiSmartShortSelfTest (int device);
+UINT8 scsiSmartExtendSelfTest (int device);
+UINT8 scsiSmartShortCapSelfTest (int device);
+UINT8 scsiSmartExtendCapSelfTest (int device);
+UINT8 scsiSmartSelfTestAbort (int device);
+
+char* scsiTapeAlertsTapeDevice ( unsigned short code);
+#endif
+
diff --git a/sm5/scsiprint.h b/sm5/scsiprint.h
index b32422e25..210487cd5 100644
--- a/sm5/scsiprint.h
+++ b/sm5/scsiprint.h
@@ -1,28 +1,28 @@
-//  $Id: scsiprint.h,v 1.2 2002/10/11 09:20:32 ballen4705 Exp $
-/*
- * scsiprint.h
- *
- * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-/* scsismart version number */
-#ifndef SCSI_PRINT_H_
-#define SCSI_PRINT_H_
-
-
-void scsiPrintMain (int fd);
-
-
-
-#endif
+//  $Id: scsiprint.h,v 1.3 2002/10/12 11:10:01 ballen4705 Exp $
+/*
+ * scsiprint.h
+ *
+ * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/* scsismart version number */
+#ifndef SCSI_PRINT_H_
+#define SCSI_PRINT_H_
+
+
+void scsiPrintMain (int fd);
+
+
+
+#endif
diff --git a/sm5/smartctl.8 b/sm5/smartctl.8
index 4ce076dfd..3372a0a6a 100644
--- a/sm5/smartctl.8
+++ b/sm5/smartctl.8
@@ -1,6 +1,6 @@
 \# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 \#
-\# $Id: smartctl.8,v 1.6 2002/10/11 09:20:32 ballen4705 Exp $
+\# $Id: smartctl.8,v 1.7 2002/10/12 11:10:01 ballen4705 Exp $
 \# 
 \# This program is free software; you can redistribute it and/or modify it
 \# under the terms of the GNU General Public License as published by the Free
@@ -10,7 +10,7 @@
 \# You should have received a copy of the GNU General Public License (for
 \# example COPYING); if not, write to the Free Software Foundation, Inc., 675
 \# Mass Ave, Cambridge, MA 02139, USA.
-.TH SMARTCTL 8  "$Date: 2002/10/11 09:20:32 $" "smartmontools-5.0"
+.TH SMARTCTL 8  "$Date: 2002/10/12 11:10:01 $" "smartmontools-5.0"
 .SH NAME
 smartctl \- S.M.A.R.T. control utility 
 .SH SYNOPSIS
@@ -125,6 +125,13 @@ a
 All: Prints all parameters for c,i,g,v,t,l,L (for SCSI c,i).  This prints all
 S.M.A.R.T. information about the disk.
 .TP
+.B Vendor-specific Attribute Display Options:
+.TP
+m
+Minutes: The disk stores Raw Attribute number 9 (power on time) in
+minutes, rather than hours.  Divide by 60 before displaying it as "power
+on hours" when using '\-v' or other options that display Raw values.
+.TP
 .B Enable/Disable Options:
 .TP
 e 
@@ -225,6 +232,12 @@ init files.  You can issue this command on a running system.
 begin an extended self-test of drive /dev/hdc.  The results can be
 seen in the self-test log after the test has completed. You can issue
 this command on a running system.
+.PP
+.nf
+.B smartctl -vm /dev/hda
+.fi
+shows the vendor attributes, when the disk stores its power-on time
+internally in minutes rather than hours.
 
 .PP
 .SH AUTHOR
@@ -296,4 +309,4 @@ Please let us know if there is an on\-line source for this document.
 
 .SH
 CVS ID OF THIS PAGE:
-$Id: smartctl.8,v 1.6 2002/10/11 09:20:32 ballen4705 Exp $
+$Id: smartctl.8,v 1.7 2002/10/12 11:10:01 ballen4705 Exp $
diff --git a/sm5/smartctl.c b/sm5/smartctl.c
index cc09bf587..f590ae683 100644
--- a/sm5/smartctl.c
+++ b/sm5/smartctl.c
@@ -1,4 +1,4 @@
-//  $Id: smartctl.c,v 1.6 2002/10/11 12:15:50 ballen4705 Exp $
+//  $Id: smartctl.c,v 1.7 2002/10/12 11:10:01 ballen4705 Exp $
 /*
  * smartctl.c
  *
@@ -49,6 +49,7 @@ unsigned char smartautoofflinedisable = FALSE;
 unsigned char smartautosaveenable     = FALSE;
 unsigned char smartautosavedisable    = FALSE;
 unsigned char printcopyleft           = FALSE;
+unsigned char smart009minutes         = FALSE;
 
 
 /*  void Usage (void) 
@@ -59,48 +60,33 @@ unsigned char printcopyleft           = FALSE;
 void Usage ( void){
   printf( "usage: smartctl -[options] [device]\n");
   printf( "Read Only Options:\n");
-  printf( "\t\t%c\t\tPrint Copyright and License information\n", 
-	  PRINTCOPYLEFT);
-  printf( "\t\t%c\t\tShow All S.M.A.R.T. Information (ATA and SCSI)\n", 
-	  SMARTVERBOSEALL);
-  printf( "\t\t%c\t\tShow General S.M.A.R.T. Attributes (ATA Only)\n",
-	  GENERALSMARTVALUES);
-  printf( "\t\t%c\t\tShow Vendor S.M.A.R.T. Attributes (ATA Only)\n", 
-	  SMARTVENDORATTRIB);
-  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Error Log (ATA Only\n", 
-	  SMARTERRORLOG);
-  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Self Test Log (ATA Only)\n", 
-	  SMARTSELFTESTLOG);
-  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Info (ATA and SCSI)\n", DRIVEINFO);
-  printf( "\t\t%c\t\tCheck S.M.A.R.T. Status (ATA and SCSI)\n", CHECKSMART);
+  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);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Info      (ATA and SCSI)\n",  DRIVEINFO);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Status          (ATA and SCSI)\n",  CHECKSMART);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. General Attributes  (ATA Only)\n",  GENERALSMARTVALUES);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Vendor Attributes   (ATA Only)\n",  SMARTVENDORATTRIB);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Error Log     (ATA Only\n",   SMARTERRORLOG);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Self Test Log (ATA Only)\n",  SMARTSELFTESTLOG);
+  printf( "\n");
+  printf( "Vendor-specific Display Options:\n");
+  printf( "\t\t%c\t\tRaw Attribute 009 is minutes        (ATA Only)\n",  SMART009MINUTES);
   printf( "\n");
   printf( "Enable/Disable Options:\n");
-  printf( "\t\t%c\t\tEnable S.M.A.R.T. data collection (ATA and SCSI)\n", 
-	  SMARTENABLE);
-  printf( "\t\t%c\t\tDisable S.M.A.R.T.data collection (ATA and SCSI)\n", 
-	  SMARTDISABLE);
-  printf( "\t\t%c\t\tEnable S.M.A.R.T. Automatic Offline Test (ATA Only)\n", 
-	  SMARTAUTOOFFLINEENABLE);
-  printf( "\t\t%c\t\tDisable S.M.A.R.T. Automatic Offline Test (ATA Only)\n", 
-	  SMARTAUTOOFFLINEDISABLE);
-  printf( "\t\t%c\t\tEnable S.M.A.R.T. Attribute Autosave (ATA Only)\n", 
-	  SMARTAUTOSAVEENABLE);
-  printf( "\t\t%c\t\tDisable S.M.A.R.T. Attribute Autosave (ATA Only)\n", 
-	  SMARTAUTOSAVEDISABLE);
+  printf( "\t\t%c\t\tEnable  S.M.A.R.T. data collection    (ATA and SCSI)\n",SMARTENABLE);
+  printf( "\t\t%c\t\tDisable S.M.A.R.T. data collection    (ATA and SCSI)\n",SMARTDISABLE);
+  printf( "\t\t%c\t\tEnable  S.M.A.R.T. Automatic Offline Test (ATA Only)\n",SMARTAUTOOFFLINEENABLE);
+  printf( "\t\t%c\t\tDisable S.M.A.R.T. Automatic Offline Test (ATA Only)\n",SMARTAUTOOFFLINEDISABLE);
+  printf( "\t\t%c\t\tEnable  S.M.A.R.T. Attribute Autosave     (ATA Only)\n",SMARTAUTOSAVEENABLE);
+  printf( "\t\t%c\t\tDisable S.M.A.R.T. Attribute Autosave     (ATA Only)\n",SMARTAUTOSAVEDISABLE);
   printf( "\n");
   printf( "Test Options:\n");
-  printf( "\t\t%c\t\tExecute Off-line data collection (ATA Only)\n",
-	  SMARTEXEOFFIMMEDIATE);
-  printf( "\t\t%c\t\tExecute Short Self Test (ATA Only)\n", 
-	  SMARTSHORTSELFTEST );
-  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 Off-line data collection (ATA Only)\n",          SMARTEXEOFFIMMEDIATE);
+  printf( "\t\t%c\t\tExecute Short Self Test (ATA Only)\n",                   SMARTSHORTSELFTEST );
+  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( "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");
@@ -115,7 +101,7 @@ const char opts[] = {
   SMARTENABLE, SMARTAUTOOFFLINEENABLE, SMARTAUTOOFFLINEDISABLE,
   SMARTEXEOFFIMMEDIATE, SMARTSHORTSELFTEST, SMARTEXTENDSELFTEST, 
   SMARTSHORTCAPSELFTEST, SMARTEXTENDCAPSELFTEST, SMARTSELFTESTABORT,
-  SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,'\0'
+  SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES,'\0'
 };
 
 /*      Takes command options and sets features to be run */	
@@ -127,6 +113,9 @@ void ParseOpts (int argc, char** argv){
   opterr=1;
   while (-1 != (optchar = getopt(argc, argv, opts))) {
     switch (optchar){
+    case SMART009MINUTES:
+      smart009minutes=TRUE;
+      break;
     case PRINTCOPYLEFT :
       printcopyleft=TRUE;
       break;
@@ -215,7 +204,7 @@ 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 project is %s\n\n",PROJECTHOME);
+  printf("Home page of smartctl is %s\n\n",PROJECTHOME);
   
   // Part input arguments
   ParseOpts (argc,argv);
@@ -226,7 +215,7 @@ int main (int argc, char **argv){
     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.6 2002/10/11 12:15:50 ballen4705 Exp $");
+    printf("CVS version ID %s\n","$Id: smartctl.c,v 1.7 2002/10/12 11:10:01 ballen4705 Exp $");
     exit(0);
  }
 
diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp
index ee8bd2c80..65c5600db 100644
--- a/sm5/smartctl.cpp
+++ b/sm5/smartctl.cpp
@@ -1,4 +1,4 @@
-//  $Id: smartctl.cpp,v 1.6 2002/10/11 12:15:50 ballen4705 Exp $
+//  $Id: smartctl.cpp,v 1.7 2002/10/12 11:10:01 ballen4705 Exp $
 /*
  * smartctl.c
  *
@@ -49,6 +49,7 @@ unsigned char smartautoofflinedisable = FALSE;
 unsigned char smartautosaveenable     = FALSE;
 unsigned char smartautosavedisable    = FALSE;
 unsigned char printcopyleft           = FALSE;
+unsigned char smart009minutes         = FALSE;
 
 
 /*  void Usage (void) 
@@ -59,48 +60,33 @@ unsigned char printcopyleft           = FALSE;
 void Usage ( void){
   printf( "usage: smartctl -[options] [device]\n");
   printf( "Read Only Options:\n");
-  printf( "\t\t%c\t\tPrint Copyright and License information\n", 
-	  PRINTCOPYLEFT);
-  printf( "\t\t%c\t\tShow All S.M.A.R.T. Information (ATA and SCSI)\n", 
-	  SMARTVERBOSEALL);
-  printf( "\t\t%c\t\tShow General S.M.A.R.T. Attributes (ATA Only)\n",
-	  GENERALSMARTVALUES);
-  printf( "\t\t%c\t\tShow Vendor S.M.A.R.T. Attributes (ATA Only)\n", 
-	  SMARTVENDORATTRIB);
-  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Error Log (ATA Only\n", 
-	  SMARTERRORLOG);
-  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Self Test Log (ATA Only)\n", 
-	  SMARTSELFTESTLOG);
-  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Info (ATA and SCSI)\n", DRIVEINFO);
-  printf( "\t\t%c\t\tCheck S.M.A.R.T. Status (ATA and SCSI)\n", CHECKSMART);
+  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);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Info      (ATA and SCSI)\n",  DRIVEINFO);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Status          (ATA and SCSI)\n",  CHECKSMART);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. General Attributes  (ATA Only)\n",  GENERALSMARTVALUES);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Vendor Attributes   (ATA Only)\n",  SMARTVENDORATTRIB);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Error Log     (ATA Only\n",   SMARTERRORLOG);
+  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Self Test Log (ATA Only)\n",  SMARTSELFTESTLOG);
+  printf( "\n");
+  printf( "Vendor-specific Display Options:\n");
+  printf( "\t\t%c\t\tRaw Attribute 009 is minutes        (ATA Only)\n",  SMART009MINUTES);
   printf( "\n");
   printf( "Enable/Disable Options:\n");
-  printf( "\t\t%c\t\tEnable S.M.A.R.T. data collection (ATA and SCSI)\n", 
-	  SMARTENABLE);
-  printf( "\t\t%c\t\tDisable S.M.A.R.T.data collection (ATA and SCSI)\n", 
-	  SMARTDISABLE);
-  printf( "\t\t%c\t\tEnable S.M.A.R.T. Automatic Offline Test (ATA Only)\n", 
-	  SMARTAUTOOFFLINEENABLE);
-  printf( "\t\t%c\t\tDisable S.M.A.R.T. Automatic Offline Test (ATA Only)\n", 
-	  SMARTAUTOOFFLINEDISABLE);
-  printf( "\t\t%c\t\tEnable S.M.A.R.T. Attribute Autosave (ATA Only)\n", 
-	  SMARTAUTOSAVEENABLE);
-  printf( "\t\t%c\t\tDisable S.M.A.R.T. Attribute Autosave (ATA Only)\n", 
-	  SMARTAUTOSAVEDISABLE);
+  printf( "\t\t%c\t\tEnable  S.M.A.R.T. data collection    (ATA and SCSI)\n",SMARTENABLE);
+  printf( "\t\t%c\t\tDisable S.M.A.R.T. data collection    (ATA and SCSI)\n",SMARTDISABLE);
+  printf( "\t\t%c\t\tEnable  S.M.A.R.T. Automatic Offline Test (ATA Only)\n",SMARTAUTOOFFLINEENABLE);
+  printf( "\t\t%c\t\tDisable S.M.A.R.T. Automatic Offline Test (ATA Only)\n",SMARTAUTOOFFLINEDISABLE);
+  printf( "\t\t%c\t\tEnable  S.M.A.R.T. Attribute Autosave     (ATA Only)\n",SMARTAUTOSAVEENABLE);
+  printf( "\t\t%c\t\tDisable S.M.A.R.T. Attribute Autosave     (ATA Only)\n",SMARTAUTOSAVEDISABLE);
   printf( "\n");
   printf( "Test Options:\n");
-  printf( "\t\t%c\t\tExecute Off-line data collection (ATA Only)\n",
-	  SMARTEXEOFFIMMEDIATE);
-  printf( "\t\t%c\t\tExecute Short Self Test (ATA Only)\n", 
-	  SMARTSHORTSELFTEST );
-  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 Off-line data collection (ATA Only)\n",          SMARTEXEOFFIMMEDIATE);
+  printf( "\t\t%c\t\tExecute Short Self Test (ATA Only)\n",                   SMARTSHORTSELFTEST );
+  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( "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");
@@ -115,7 +101,7 @@ const char opts[] = {
   SMARTENABLE, SMARTAUTOOFFLINEENABLE, SMARTAUTOOFFLINEDISABLE,
   SMARTEXEOFFIMMEDIATE, SMARTSHORTSELFTEST, SMARTEXTENDSELFTEST, 
   SMARTSHORTCAPSELFTEST, SMARTEXTENDCAPSELFTEST, SMARTSELFTESTABORT,
-  SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,'\0'
+  SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES,'\0'
 };
 
 /*      Takes command options and sets features to be run */	
@@ -127,6 +113,9 @@ void ParseOpts (int argc, char** argv){
   opterr=1;
   while (-1 != (optchar = getopt(argc, argv, opts))) {
     switch (optchar){
+    case SMART009MINUTES:
+      smart009minutes=TRUE;
+      break;
     case PRINTCOPYLEFT :
       printcopyleft=TRUE;
       break;
@@ -215,7 +204,7 @@ 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 project is %s\n\n",PROJECTHOME);
+  printf("Home page of smartctl is %s\n\n",PROJECTHOME);
   
   // Part input arguments
   ParseOpts (argc,argv);
@@ -226,7 +215,7 @@ int main (int argc, char **argv){
     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.6 2002/10/11 12:15:50 ballen4705 Exp $");
+    printf("CVS version ID %s\n","$Id: smartctl.cpp,v 1.7 2002/10/12 11:10:01 ballen4705 Exp $");
     exit(0);
  }
 
diff --git a/sm5/smartctl.h b/sm5/smartctl.h
index c0ddc6254..19ceed382 100644
--- a/sm5/smartctl.h
+++ b/sm5/smartctl.h
@@ -1,4 +1,4 @@
-//  $Id: smartctl.h,v 1.3 2002/10/11 09:20:32 ballen4705 Exp $
+//  $Id: smartctl.h,v 1.4 2002/10/12 11:10:01 ballen4705 Exp $
 /*
  * smartctl.h
  *
@@ -39,6 +39,7 @@
 #define SMARTAUTOSAVEENABLE     'f'
 #define SMARTAUTOSAVEDISABLE    'F'
 #define PRINTCOPYLEFT           'p'
+#define SMART009MINUTES         'm'
 
 
 /* Boolean Values */
-- 
GitLab