From c1617f14340ddfc5868202f703541707ce9690c4 Mon Sep 17 00:00:00 2001
From: ballen4705 <ballen4705@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Mon, 21 Oct 2002 15:07:48 +0000
Subject: [PATCH] Fixed possible error in determining ATA version if no
 minor_version field in DEVICE ID. Detect -EIO if sending a captive self-test
 command and do not generate error message.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@72 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/CHANGELOG   | 11 +++++++++--
 sm5/atacmds.c   | 26 +++++++++++++++++---------
 sm5/atacmds.cpp | 26 +++++++++++++++++---------
 3 files changed, 43 insertions(+), 20 deletions(-)

diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index 8f3699c7a..1cb6e4c26 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.10 2002/10/21 08:49:23 ballen4705 Exp $
+$Id: CHANGELOG,v 1.11 2002/10/21 15:07:47 ballen4705 Exp $
 
 Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
@@ -29,8 +29,15 @@ NOTES FOR NEXT RELEASE:
 
 smartmontools-5.0-11
 
+    when starting self-tests in captive mode ioctl returns EIO because
+    the drive has been busied out.  Detect this and don't return an eror
+    in this case.  Check this this is correct (or how to fix it?)
+ 
+    fixed possible error in how to determine ATA standard support
+    for devices with no ATA minor revision number.
+
     device opened only in read-only not read-write mode.  Don't need R/W 
-    access to get smart data.
+    access to get smart data. Check this with Andre.
 
     smartctl now handles all possible choices of "multiple options"
     gracefully.  It goes through the following phases of operation,
diff --git a/sm5/atacmds.c b/sm5/atacmds.c
index 75e030550..72a2cc03a 100644
--- a/sm5/atacmds.c
+++ b/sm5/atacmds.c
@@ -1,4 +1,4 @@
-//  $Id: atacmds.c,v 1.11 2002/10/21 08:49:23 ballen4705 Exp $
+//  $Id: atacmds.c,v 1.12 2002/10/21 15:07:48 ballen4705 Exp $
 /*
  * atacmds.c
  * 
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <syslog.h>
+#include <errno.h>
 #include "atacmds.h"
 
 // These Drive Identity tables are taken from hdparm 5.2, and are also
@@ -140,7 +141,8 @@ int ataReadHDIdentity (int device, struct hd_driveid *buf){
   unsigned char parms[HDIO_DRIVE_CMD_HDR_SIZE+sizeof(*buf)]=
   {WIN_IDENTIFY, 0, 0, 1,};
   
-  if (ioctl(device ,HDIO_DRIVE_CMD,parms)){ 
+  if (ioctl(device ,HDIO_DRIVE_CMD,parms)){
+    // See if device responds to packet command...
     parms[0]=WIN_PIDENTIFY;
     if (ioctl(device ,HDIO_DRIVE_CMD,parms)){
       perror ("ATA GET HD Identity Failed");
@@ -176,7 +178,7 @@ int ataReadHDIdentity (int device, struct hd_driveid *buf){
 // the version number.  See notes above.
 int ataVersionInfo (const char** description, struct hd_driveid drive){
   unsigned short major,minor;
-  int i,atavalue=0;
+  int i;
   
   // get major and minor ATA revision numbers
 #ifdef __NEW_HD_DRIVE_ID
@@ -205,11 +207,15 @@ int ataVersionInfo (const char** description, struct hd_driveid drive){
   // 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++ )
+  for (i=15; i>0; i--)
     if (major & (0x1<<i))
-      atavalue = i;
-  *description=NULL;
-  return atavalue;
+      break;
+  
+  *description=NULL; 
+  if (i==0)
+    return 1;
+  else
+    return i;;
 }
 
 // returns 1 if SMART supported, 0 if not supported or can't tell
@@ -512,6 +518,7 @@ int ataSmartStatus2(int device){
 int ataSmartTest(int device, int testtype){	
   unsigned char parms[4] = {WIN_SMART, 0, SMART_IMMEDIATE_OFFLINE};
   char cmdmsg[128],*type,*captive;
+  int errornum;
 
   parms[1]=testtype;
 
@@ -536,10 +543,11 @@ int ataSmartTest(int device, int testtype){
   printf("Sending command: \"%s\".\n",cmdmsg);
 
   // Now send the command to test
-  if (ioctl(device , HDIO_DRIVE_CMD, parms)){
+  if ((errornum=ioctl(device , HDIO_DRIVE_CMD, parms)) && errornum!=EIO){
     char errormsg[128];
-    sprintf(errormsg,"Command \"%s\" failed.\n\n",cmdmsg); 
+    sprintf(errormsg,"Command \"%s\" failed.",cmdmsg); 
     perror (errormsg);
+    fprintf(stderr,"\n");
     return -1;
   }
   
diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index 58ed944fa..2baefc106 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -1,4 +1,4 @@
-//  $Id: atacmds.cpp,v 1.11 2002/10/21 08:49:23 ballen4705 Exp $
+//  $Id: atacmds.cpp,v 1.12 2002/10/21 15:07:48 ballen4705 Exp $
 /*
  * atacmds.c
  * 
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <syslog.h>
+#include <errno.h>
 #include "atacmds.h"
 
 // These Drive Identity tables are taken from hdparm 5.2, and are also
@@ -140,7 +141,8 @@ int ataReadHDIdentity (int device, struct hd_driveid *buf){
   unsigned char parms[HDIO_DRIVE_CMD_HDR_SIZE+sizeof(*buf)]=
   {WIN_IDENTIFY, 0, 0, 1,};
   
-  if (ioctl(device ,HDIO_DRIVE_CMD,parms)){ 
+  if (ioctl(device ,HDIO_DRIVE_CMD,parms)){
+    // See if device responds to packet command...
     parms[0]=WIN_PIDENTIFY;
     if (ioctl(device ,HDIO_DRIVE_CMD,parms)){
       perror ("ATA GET HD Identity Failed");
@@ -176,7 +178,7 @@ int ataReadHDIdentity (int device, struct hd_driveid *buf){
 // the version number.  See notes above.
 int ataVersionInfo (const char** description, struct hd_driveid drive){
   unsigned short major,minor;
-  int i,atavalue=0;
+  int i;
   
   // get major and minor ATA revision numbers
 #ifdef __NEW_HD_DRIVE_ID
@@ -205,11 +207,15 @@ int ataVersionInfo (const char** description, struct hd_driveid drive){
   // 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++ )
+  for (i=15; i>0; i--)
     if (major & (0x1<<i))
-      atavalue = i;
-  *description=NULL;
-  return atavalue;
+      break;
+  
+  *description=NULL; 
+  if (i==0)
+    return 1;
+  else
+    return i;;
 }
 
 // returns 1 if SMART supported, 0 if not supported or can't tell
@@ -512,6 +518,7 @@ int ataSmartStatus2(int device){
 int ataSmartTest(int device, int testtype){	
   unsigned char parms[4] = {WIN_SMART, 0, SMART_IMMEDIATE_OFFLINE};
   char cmdmsg[128],*type,*captive;
+  int errornum;
 
   parms[1]=testtype;
 
@@ -536,10 +543,11 @@ int ataSmartTest(int device, int testtype){
   printf("Sending command: \"%s\".\n",cmdmsg);
 
   // Now send the command to test
-  if (ioctl(device , HDIO_DRIVE_CMD, parms)){
+  if ((errornum=ioctl(device , HDIO_DRIVE_CMD, parms)) && errornum!=EIO){
     char errormsg[128];
-    sprintf(errormsg,"Command \"%s\" failed.\n\n",cmdmsg); 
+    sprintf(errormsg,"Command \"%s\" failed.",cmdmsg); 
     perror (errormsg);
+    fprintf(stderr,"\n");
     return -1;
   }
   
-- 
GitLab