Skip to content
Snippets Groups Projects
Select Git revision
  • ee53fc77e05372c8fb4d06ee283eb147b0ffdc41
  • master default protected
2 results

neighbors.cpp

Blame
  • ataprint.cpp 28.68 KiB
    //  $Id: ataprint.cpp,v 1.1 2002/10/09 17:56:58 ballen4705 Exp $
    /*
     * ataprint.c
     *
     * Copyright (C) 2002 Bruce Allen <ballen@uwm.edu>
     * 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 "ataprint.h"
    #include "smartctl.h"
    #include "extern.h"
    
    void ataPrintDriveInfo (struct hd_driveid drive)
    {
      printf ("Device: %.40s  Supports ATA Version %i\n", 
    	  drive.model, ataVersionInfo ( drive) );
      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);
    }
    
    
    /* void PrintSmartOfflineStatus ( struct ata_smart_values data) 
       prints verbose value Off-line data collection status byte */
    
    void PrintSmartOfflineStatus ( struct ata_smart_values data)
    {
       printf ("Off-line data collection status: ");	
       
       switch (data.offline_data_collection_status)
       {
          case 0x0: case 0x80:
              printf ("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t",
                      data.offline_data_collection_status);
              printf("never started\n");
              break;
          case 0x01: case 0x81:
              printf ("(0x%02x)\tReserved\n",
                      data.offline_data_collection_status);
              break;
          case 0x02: case 0x82:
              printf ("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t",
                      data.offline_data_collection_status);
              printf ("completed without error\n");
              break;
          case 0x03: case 0x83:
              printf ("(0x%02x)\tReserved\n",
                      data.offline_data_collection_status);
              break;
          case 0x04: case 0x84:
              printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
                      data.offline_data_collection_status);
              printf ("suspended by an interrupting command\n");
              break;
          case 0x05: case 0x85:
              printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
                      data.offline_data_collection_status);
              printf ("aborted by an interrupting command\n");
              break;
          case 0x06: case 0x86:
              printf ("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
                      data.offline_data_collection_status);
              printf ("aborted by the device with fatal error\n");
              break;
          default:
              if ( ((data.offline_data_collection_status >= 0x07) &&
                    (data.offline_data_collection_status <= 0x3f)) ||
                    ((data.offline_data_collection_status >= 0xc0) &&
                    (data.offline_data_collection_status <= 0xff)) )
              {
                  printf ("(0x%02x)\tVendor Specific\n",
                          data.offline_data_collection_status);
              } 
              else 
              {
                  printf ("(0x%02x)\tReserved\n",
                          data.offline_data_collection_status);
              }
       }
    }
    
    
    
    void PrintSmartSelfExecStatus ( struct ata_smart_values data)
    {
       printf ("Self-test execution status:      ");
       
       switch (data.self_test_exec_status >> 4)
       {
          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");
            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");
             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");
             break;
           case 3:
              printf ("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t",
                      data.self_test_exec_status);
              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");
              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");
              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");
              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");
              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");
              break;
           case 15:
              printf ("(%4d)\tSelf-test routine in progess\n\t\t\t\t\t",
                      data.self_test_exec_status);
              printf ("%1d0%% of test remaining\n", 
                      data.self_test_exec_status & 0x0f);
              break;
           default:
              printf ("(%4d)\tReserved\n",
                      data.self_test_exec_status);
              break;
       }
    	
    }
    
    
    
    void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values data)
    {
       printf ("Total time to complete off-line \n");
       printf ("data collection: \t\t (%4d) Seconds\n", 
               data.total_time_to_complete_off_line);
    }
    
    
    
    void PrintSmartOfflineCollectCap ( struct ata_smart_values data)
    {
       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");
       } 
       else 
       {
          printf( "%s\n", isSupportExecuteOfflineImmediate(data)?
                  "SMART EXECUTE OFF-LINE IMMEDIATE" :
                  "NO SMART EXECUTE OFF-LINE IMMEDIATE");
    
          printf( "\t\t\t\t\t%s\n", isSupportAutomaticTimer(data)? 
                  "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");
    
          printf( "\t\t\t\t\t%s\n", isSupportOfflineSurfaceScan(data)? 
                  "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");
        }
    }
    
    
    
    void PrintSmartCapability ( struct ata_smart_values data)
    {
       printf ("Smart Capablilities:           ");
       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");
       } 
       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");
    		
          if ( data.smart_capability & 0x02 )
          {
              printf ("\t\t\t\t\tSupports SMART auto save timer\n");
          }
       }
    }
    
    
    
    void PrintSmartErrorLogCapability ( struct ata_smart_values data)
    {
    
       printf ("Error logging capability:       ");
        
       if ( isSmartErrorLogCapable(data) )
       {
          printf (" (0x%02x)\tError logging supported\n",
                   data.errorlog_capability);
       }
       else {
           printf (" (0x%02x)\tError logging NOT supported\n",
                    data.errorlog_capability);
       }
    }
    
    
    
    void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data)
    {
       if ( isSupportSelfTest(data) )
       {
          printf ("Short self-test routine \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");
       }
    }
    
    
    void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data)
    {
       if ( isSupportSelfTest(data) )
       {
          printf ("Extended self-test routine \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");
       }
    }
    
    
    
    void PrintSmartAttribWithThres ( struct ata_smart_values data, 
                                     struct ata_smart_thresholds thresholds)
    {
       int i,j;
       long long rawvalue; 
       printf ("Vendor Specific SMART Attributes with Thresholds:\n");
       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("First: %u Second: %u Third: %u\n",
    		   data.vendor_attributes[i].raw[0],		   
    		   data.vendor_attributes[i].raw[2],
    		   data.vendor_attributes[i].raw[4]);
          }
       }
    }
    
    
    void ataPrintGeneralSmartValues  ( struct ata_smart_values data)
    {
       printf ("\nGeneral Smart Values: \n");
    
       PrintSmartOfflineStatus (data); 
       printf("\n");
    	
       if (isSupportSelfTest(data))
       {
           PrintSmartSelfExecStatus (data);
           printf("\n");
       }
    	
       PrintSmartTotalTimeCompleteOffline (data);
       printf("\n");
    	
       PrintSmartOfflineCollectCap (data);
       printf("\n");
    	
       PrintSmartCapability ( data);
       printf("\n");
    
       PrintSmartErrorLogCapability (data);
       printf ("\n");
    	
       if (isSupportSelfTest(data))
       {
          PrintSmartShortSelfTestPollingTime (data);
          printf ("\n");
    
          PrintSmartExtendedSelfTestPollingTime (data);
          printf ("\n");
       }
    
    }
    
    
    void ataPrintSmartThresholds (struct ata_smart_thresholds data)
    {
       int i;
    
       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)	
              printf ("Atrribute %3i threshold: %02x (%2i)\n", 
                       data.thres_entries[i].id, 
                       data.thres_entries[i].threshold, 
                       data.thres_entries[i].threshold);
    	
       }
    }
    
    
    // Returns nonzero if region of memory contains non-zero entries
    int nonempty(unsigned char *testarea,int n){
      int i;
      for (i=0;i<n;i++)
        if (testarea[i])
          return 1;
      return 0;
    }
      
    void ataPrintSmartErrorlog (struct ata_smart_errorlog data)
    {
      int i,j,k;
      
      printf ("\nSMART Error Log\n");
      printf ( "SMART Error Logging Version: %i\n", data.revnumber);
      
      // if no errors logged, return
      if ( ! data.error_log_pointer)
        {
          printf ("No Errors Logged\n");
          return;
        }
      
      // if log pointer out of range, return
      if ( data.error_log_pointer>5 ){
        printf("Invalid Error log index = %02x (T13/1321D rev 1c"
    	   "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n",
    	   data.error_log_pointer);
        return;
      }
      
      // starting printing error log info
      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(  "Acronyms used below:\n");
      printf(  "DCR = Device Control Register\n");
      printf(  "FR  = Features Register\n");
      printf(  "SC  = Sector Count Register\n");
      printf(  "SN  = Sector Number Register\n");
      printf(  "CL  = Cylinder Low Register\n");
      printf(  "CH  = Cylinder High Register\n");
      printf(  "D/H = Device/Head Register\n");
      printf(  "CR  = Content written to Command Register\n");
      printf(  "ER  = Error register\n");
      printf(  "STA = Status register\n\n");
      printf(  "Timestamp is time (in seconds) since the command that caused an error was accepted,\n");
      printf(  "measured from the time the disk was powered-on, during the session when the error occured.\n");
      printf(  "Note: timestamp \"wraps\" after 1193.046 hours = 49.710 days = 2^32 seconds.\n");
      
      // now step through the five error log data structures (table 39 of spec)
      for (k = 4; k >= 0; k-- ) {
        
        // The error log data structure entries are a circular buffer
        i=(data.error_log_pointer+k)%5;
        
        // Spec says: unused error log structures shall be zero filled
        if (nonempty((unsigned char*)&(data.errorlog_struct[i]),sizeof(data.errorlog_struct[i]))){
          char *msgstate;
          switch (data.errorlog_struct[i].error_struct.state){
          case 0x00: msgstate="in an unknown state";break;
          case 0x01: msgstate="sleeping"; break;
          case 0x02: msgstate="in standby mode"; break;
          case 0x03: msgstate="active or idle"; break;
          case 0x04: msgstate="doing SMART off-line or self test"; break;
          default:   msgstate="in a vendor specific or reserved state";
          }
          printf("\nError Log Structure %i:\n",5-k);
          // See table 42 of ATA5 spec
          printf("Error occured at disk power-on lifetime: %u hours\n",
    	     data.errorlog_struct[i].error_struct.timestamp);
          printf("When the command that caused the error occured, the  device was %s.\n",msgstate);
          printf("After command completion occured, registers were:\n");
          printf("ER:%02x SC:%02x SN:%02x CL:%02x CH:%02x D/H:%02x ST:%02x\n",
    	     data.errorlog_struct[i].error_struct.error_register,
    	     data.errorlog_struct[i].error_struct.sector_count,
    	     data.errorlog_struct[i].error_struct.sector_number,
    	     data.errorlog_struct[i].error_struct.cylinder_low,
    	     data.errorlog_struct[i].error_struct.cylinder_high,
    	     data.errorlog_struct[i].error_struct.drive_head,
    	     data.errorlog_struct[i].error_struct.status);
          printf("Sequence of commands leading to the command that caused the error were:\n");
          printf("DCR   FR   SC   SN   CL   CH   D/H   CR   Timestamp\n");
          for ( j = 4; j >= 0; j--){
    	struct ata_smart_errorlog_command_struct *thiscommand=&(data.errorlog_struct[i].commands[j]);
    	
    	// Spec says: unused data command structures shall be zero filled
    	if (nonempty((unsigned char*)thiscommand,sizeof(*thiscommand)))
    	  printf ( " %02x   %02x   %02x   %02x   %02x   %02x    %02x   %02x     %u.%03u\n", 
    		   thiscommand->devicecontrolreg,
    		   thiscommand->featuresreg,
    		   thiscommand->sector_count,
    		   thiscommand->sector_number,
    		   thiscommand->cylinder_low,
    		   thiscommand->cylinder_high,
    		   thiscommand->drive_head,
    		   thiscommand->commandreg,
    		   (unsigned int)(thiscommand->timestamp / 1000),
    		   (unsigned int)(thiscommand->timestamp % 1000)); 
          } 
        }
      }  
      return;  
    }
    
    
    void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data){
      int i,j;
    
      printf("\nSMART Self-test log, version number %u\n",data.revnumber);
      if (data.revnumber!=0x01)
        printf("Warning - structure revision number does not match spec!\n");
      
      if (data.mostrecenttest==0){
        printf("No self-test have been logged\n");
        return;
      }
    
      // print log      
      printf("\nNum  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error\n");
      for (i=20;i>=0;i--){
    
        struct ata_smart_selftestlog_struct *log;
        // log is a circular buffer
        j=(i+data.mostrecenttest)%21;
        log=&(data.selftest_struct[j]);
    
        if (nonempty((unsigned char*)log,sizeof(*log))){
          char *msgtest,*msgstat,percent[16],firstlba[16];
    
          // test name
          switch(log->selftestnumber){
          case   0: msgtest="Off-line           "; break;
          case   1: msgtest="Short off-line     "; break;
          case   2: msgtest="Extended off-line  "; break;
          case 127: msgtest="Abort off-line test"; break;
          case 129: msgtest="Short captive      "; break;
          case 130: msgtest="Extended captive   "; break;
          default:  msgtest="Unknown test       ";
          }
          
          // test status
          switch((log->selfteststatus)>>4){
          case  0:msgstat="Completed                    "; break;
          case  1:msgstat="Aborted by host              "; break;
          case  2:msgstat="Interrupted (host reset)     "; break;
          case  3:msgstat="Fatal or unknown error       "; break;
          case  4:msgstat="Completed: unknown failure   "; break;
          case  5:msgstat="Completed: electrical failure"; break;
          case  6:msgstat="Completed: servo/seek failure"; break;
          case  7:msgstat="Completed: read failure      "; break;
          case 15:msgstat="Test in progress             "; break;
          default:msgstat="Unknown test status          ";
          }
          
          sprintf(percent,"%1d0%%",(log->selfteststatus)&0xf);
          if (log->lbafirstfailure==0xffffffff || log->lbafirstfailure==0x00000000)
    	sprintf(firstlba,"%s","");
          else	
    	sprintf(firstlba,"0x%08x",log->lbafirstfailure);
          printf("#%2d  %s %s %s  %8u         %s\n",
    	     21-i,
    	     msgtest,
    	     msgstat,
    	     percent,
    	     log->timestamp,
    	     firstlba);
        }
        else
          return;
      }
      return;
    }
    
    void ataPsuedoCheckSmart ( struct ata_smart_values data, 
                               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;
          } 
    
       }
       
       printf("%s\n", ( failed )?
         "Please save all data and call drive manufacture immediately.":
         "Check S.M.A.R.T. Passed.");
    }
    
    void ataPrintSmartAttribName ( unsigned char id )
    {
       switch (id)
       {
    	
          case 1:
             printf("(  1)Raw Read Error Rate    ");
    	 break;
          case 2:
             printf("(  2)Throughput Performance ");
             break;
          case 3:
             printf("(  3)Spin Up Time           ");
             break;
          case 4:
             printf("(  4)Start Stop Count       ");
             break;
          case 5:
             printf("(  5)Reallocated Sector Ct  ");
    	 break;
          case 6:
             printf("(  6)Read Channel Margin    ");
    	 break;
          case 7:
             printf("(  7)Seek Error Rate        ");
             break;
          case 8:
             printf("(  8)Seek Time Preformance  ");
             break;
          case 9:
             printf("(  9)Power On Hours         ");
             break;
          case 10:
             printf("( 10)Spin Retry Count       ");
             break;
          case 11:
             printf("( 11)Calibration Retry Count");
             break;
          case 12:
             printf("( 12)Power Cycle Count      ");
             break;
          case 13:
             printf("( 13)Read Soft Error Rate   ");
             break;
          case 191:
             printf("(191)Gsense Error Rate      ");
             break;
          case 192:
             printf("(192)Power-Off Retract Count");
             break;
          case 193:
             printf("(193)Load Cycle Count       ");
             break;
          case 194:
             printf("(194)Temperature            ");
             break;
          case 195:
             printf("(195)Hardware ECC Recovered ");
             break;
          case 196:
             printf("(196)Reallocated Event Count");
             break;
          case 197:
             printf("(197)Current Pending Sector ");
             break;
          case 198:
             printf("(198)Offline Uncorrectable  ");
             break;
          case 199:
             printf("(199)UDMA CRC Error Count   ");
             break;
          default:
             printf("(%3d)Unknown Attribute      ", id);
             break;
      }
    }	
    
    /****
     Called by smartctl to access ataprint  
    **/
    
    void ataPrintMain ( int fd )
    {
       struct hd_driveid drive;
       struct ata_smart_values smartval;
       struct ata_smart_thresholds smartthres;
       struct ata_smart_errorlog smarterror;
       struct ata_smart_selftestlog smartselftest;
    
       if ( driveinfo )
       {
          if (  ataReadHDIdentity ( fd, &drive) != 0 )
          {
             printf("Smartctl: Hard Drive Identity Failed\n");
             exit(0);	
          } 
    		
          ataPrintDriveInfo(drive); 
    		
    
          if (ataSmartSupport(drive))
          {
              printf ("Drive supports S.M.A.R.T. and is ");
    	  
              if ( ataSmartStatus(fd) != 0) 
              {
                  printf( "disabled\n");
                  printf( "Use option -%c to enable\n", SMARTENABLE );
                  exit(0);
              }
              else { 
                  printf( "enabled\n");
              } 
          }
          else {
               printf("Drive does not support S.M.A.R.T.\n");
    	   exit (0);
          }
      }
    
      if ( smartdisable )
      {
    		
         if ( ataDisableSmart(fd) != 0) 
         {
    	printf( "Smartctl: Smart Enable Failed\n");
    	exit(-1);
         }
        
         printf("S.M.A.R.T. Disabled\n");
         exit (0);
    		
       }
    
       if ( smartenable )
       {
          if ( ataEnableSmart(fd) != 0) 
    	{
              printf( "Smartctl: Smart Enable Failed\n");
              exit(-1);
    	}
    
          if (ataSmartStatus(fd)==0)
    	printf("S.M.A.R.T. Enabled\n");
          else
    	printf( "Smartctl: Smart Enable Failed for unknown reasons\n");
       }
       
       
       if ( smartautosavedisable ){
         if (ataDisableAutoSave(fd) != 0)
           {
    	 printf( "Smartctl: Smart Disable Atribute Autosave Failed\n");
    	 exit(-1);
           }     
         printf("S.M.A.R.T. Atribute Autosave Disabled\n");
       }
    	
       if ( smartautosaveenable ){
         if (ataEnableAutoSave(fd) != 0)
           {
    	 printf( "Smartctl: Smart Enable Atribute Autosave Failed\n");
    	 exit(-1);
           } 
         printf("S.M.A.R.T. Atribute Autosave Enabled\n");
       }
    
       /* for everything else read values and thresholds 
       are needed */	
    
       if ( ataReadSmartValues ( fd, &smartval) != 0 )
       {
          printf("Smartctl: Smart Values Read Failed\n");
          exit (-1);
       }
    
       if ( ataReadSmartThresholds ( fd, &smartthres) != 0 )
       {
          printf("Smartctl: Smart THresholds Read Failed\n");
          exit (-1); 
       }
    	
       if ( checksmart )
       {
    	/* pseudo is used because linux does not support access to
    	   Task Fiule registers */
    
          ataPsuedoCheckSmart ( smartval , smartthres);
    
       }
    	
       if (  generalsmartvalues )
       {
          ataPrintGeneralSmartValues( smartval ); 
       }
    
       if ( smartvendorattrib )
       {
          PrintSmartAttribWithThres( smartval, smartthres);
       }
    	
       if ( smarterrorlog )
       {
          if ( isSmartErrorLogCapable(smartval) == 0)
          {
              printf("Device does not support Error Logging\n");
          } 
          else
          {
             if ( ataReadErrorLog ( fd, &smarterror) != 0 )
    	 {
                 printf("Smartctl: Smart Errorlog Read Failed\n");
             }
             else
             {
                 ataPrintSmartErrorlog ( smarterror); 
             }
          }
        }
    	
    
       if ( smartselftestlog )
       {
           if ( isSmartErrorLogCapable(smartval) == 0)
           {
               printf("Device does not support Self Test Logging\n");
           }
           else
           {
    	    if (  ataReadSelfTestLog( fd, &smartselftest) != 0 )
                {
                    printf("Smartctl: Smart Self Test log Read Failed\n");
                }
                else
                {
                     ataPrintSmartSelfTestlog (smartselftest); 
                }
            } 
        }
    
        if (  smartautoofflineenable  )
        {
            if ( !isSupportAutomaticTimer (smartval))
            {
                printf("Device does not support S.M.A.R.T. Automatic Timers\n");
                exit(-1);
            }
    
            if ( ataEnableAutoOffline (fd) != 0) 
            {
                printf( "Smartctl: Smart Enable Automatic Offline Failed\n");
                exit(-1);
            }
            
            printf ("S.M.A.R.T. 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");
                exit(-1);
            }
    			
            if ( ataDisableAutoOffline (fd) != 0) 
            {
                printf( "Smartctl: Smart Disable Automatic Offline Failed\n");
                exit(-1);
            }
             
            printf ("S.M.A.R.T. Automatic Offline Testing Disabled\n");
    
         }
    
    
         if ( smartexeoffimmediate )
         {
            if ( ataSmartOfflineTest (fd) != 0) 
    	{
                printf( "Smartctl: Smart Offline Failed\n");
                exit(-1);
            }
    
            printf ("Drive Command Successful offline test has begun\n");
            printf ("Please wait %d seconds for test to complete\n", 
                     isOfflineTestTime(smartval) );
            printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
    	exit (0);
         }
    
         if ( smartshortcapselftest )
         {
             if ( ! isSupportSelfTest(smartval) )
             {
                 printf (" ERROR: device does not support Self-Test function\n");
                 exit(-1);
             }
    		
             if ( ataSmartShortCapSelfTest (fd) != 0) 
             {
                  printf( "Smartctl: Smart Short Self Test Failed\n");
                  exit(-1);
             }
         
             printf ("Drive Command Successful offline test has begun\n");
             printf ("Please wait %d minutes for test to complete\n", 
                      isShortSelfTestTime (smartval) );
    	 printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
    	
             /* Make sure Offline testing is last thing done */
            exit (0);
         }
    
         if ( smartshortselftest )
         {
            if ( ! isSupportSelfTest(smartval) )
            {
                printf (" ERROR: device does not support Self-Test function\n");
                exit(-1);
            }
    		
            if ( ataSmartShortSelfTest (fd) != 0) 
            {
                printf( "Smartctl: Smart Short Self Test Failed\n");
                exit(-1);
            }
    
            printf ("Drive Command Successful offline test has begun\n");
            printf ("Please wait %d minutes for test to complete\n", 
                     isShortSelfTestTime (smartval) );
            printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
    		
    	/* Make sure Offline testing is last thing done */
    	exit (0);
         }
     
    	
         if ( smartextendselftest )
         {
            if ( ! isSupportSelfTest(smartval) )
            {
               printf (" ERROR: device does not support Self-Test function\n");
               exit(-1);
            }
    
            if ( ataSmartExtendSelfTest (fd) != 0) 
            {
               printf( "S.M.A.R.T. Extendend Self Test Failed\n");
               exit(-1);
            }
    		
            printf ("Drive Command Successful self test has begun\n");
            printf ("Please wait %d minutes for test to complete\n", 
                     isExtendedSelfTestTime(smartval) );
            printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
    	
            exit (0);
         }
    
    	
         if ( smartextendcapselftest )
         {
             if ( ! isSupportSelfTest(smartval) )
             {
                printf (" ERROR: device does not support self test function\n");
                exit(-1);
             }
    
             if ( ataSmartExtendCapSelfTest (fd) != 0) 
             {
                printf( "S.M.A.R.T. Extendend Self Test Failed\n");
                exit(-1);
             }
    		
                printf ("Drive Command Successful captive extended self test has begun\n");
                printf ("Please wait %d minutes for test to complete\n", 
                        isExtendedSelfTestTime(smartval) );
                printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);	
                exit (0);
         }
    
         if ( smartselftestabort )
         {
            if ( ! isSupportSelfTest(smartval) )
            {
                printf (" ERROR: device does not support Self-Test function\n");
                exit(-1);
            }
    
            if ( ataSmartSelfTestAbort (fd) != 0) 
            {
                printf( "S.M.A.R.T. Self Test Abort Failed\n");
                exit(-1);
            }
    		
            printf ("Drive Command Successful self test aborted\n");
        }		
    	
    }