Hardware/HDD/SMART.cs
changeset 233 c5139c236200
parent 231 30f5a06f5d8a
child 308 d882720734bf
     1.1 --- a/Hardware/HDD/SMART.cs	Sun Oct 17 19:13:26 2010 +0000
     1.2 +++ b/Hardware/HDD/SMART.cs	Sun Oct 17 19:25:50 2010 +0000
     1.3 @@ -81,72 +81,160 @@
     1.4        public static readonly AttributeID None = new AttributeID(0x00);
     1.5      }
     1.6  
     1.7 -    // Common SMART attributes
     1.8 -    public static class CommonAttributes {      
     1.9 -      public static readonly AttributeID 
    1.10 -        ReadErrorRate = new AttributeID(0x01);
    1.11 -      public static readonly AttributeID 
    1.12 -        ThroughputPerformance = new AttributeID(0x02);
    1.13 -      public static readonly AttributeID 
    1.14 -        SpinUpTime = new AttributeID(0x03);
    1.15 -      public static readonly AttributeID 
    1.16 -        StartStopCount = new AttributeID(0x04);
    1.17 -      public static readonly AttributeID 
    1.18 -        ReallocatedSectorsCount = new AttributeID(0x05);
    1.19 -      public static readonly AttributeID 
    1.20 -        ReadChannelMargin = new AttributeID(0x06);
    1.21 -      public static readonly AttributeID 
    1.22 -        SeekErrorRate = new AttributeID(0x07);
    1.23 -      public static readonly AttributeID 
    1.24 -        SeekTimePerformance = new AttributeID(0x08);
    1.25 -      public static readonly AttributeID 
    1.26 -        PowerOnHours = new AttributeID(0x09);
    1.27 -      public static readonly AttributeID 
    1.28 -        SpinRetryCount = new AttributeID(0x0A);
    1.29 -      public static readonly AttributeID 
    1.30 -        RecalibrationRetries = new AttributeID(0x0B);
    1.31 -      public static readonly AttributeID 
    1.32 -        PowerCycleCount = new AttributeID(0x0C);
    1.33 -      public static readonly AttributeID 
    1.34 -        SoftReadErrorRate = new AttributeID(0x0D);
    1.35 -      public static readonly AttributeID 
    1.36 -        AirflowTemperature = new AttributeID(0xBE);
    1.37 -      public static readonly AttributeID 
    1.38 -        Temperature = new AttributeID(0xC2);
    1.39 -      public static readonly AttributeID 
    1.40 -        HardwareECCRecovered = new AttributeID(0xC3);
    1.41 -      public static readonly AttributeID 
    1.42 -        ReallocationEventCount = new AttributeID(0xC4);
    1.43 -      public static readonly AttributeID 
    1.44 -        CurrentPendingSectorCount = new AttributeID(0xC5);
    1.45 -      public static readonly AttributeID 
    1.46 -        UncorrectableSectorCount = new AttributeID(0xC6);
    1.47 -      public static readonly AttributeID 
    1.48 -        UltraDMACRCErrorCount = new AttributeID(0xC7);
    1.49 -      public static readonly AttributeID 
    1.50 -        WriteErrorRate = new AttributeID(0xC8);
    1.51 -      public static readonly AttributeID 
    1.52 -        DriveTemperature = new AttributeID(0xE7);
    1.53 +    // These are the more-or-less standard S.M.A.R.T attributes
    1.54 +    // TODO: Filter out unused/obscure ones; some are interpreted differently
    1.55 +    // between manufacturers
    1.56 +    public static class CommonAttributes {
    1.57 +      public static readonly AttributeID
    1.58 +        ReadErrorRate = new AttributeID(0x01),
    1.59 +        ThroughputPerformance = new AttributeID(0x02),
    1.60 +        SpinUpTime = new AttributeID(0x03),
    1.61 +        StartStopCount = new AttributeID(0x04),
    1.62 +        ReallocatedSectorsCount = new AttributeID(0x05),
    1.63 +        ReadChannelMargin = new AttributeID(0x06),
    1.64 +        SeekErrorRate = new AttributeID(0x07),
    1.65 +        SeekTimePerformance = new AttributeID(0x08),
    1.66 +        PowerOnHours = new AttributeID(0x09),
    1.67 +        SpinRetryCount = new AttributeID(0x0A),
    1.68 +        RecalibrationRetries = new AttributeID(0x0B),
    1.69 +        PowerCycleCount = new AttributeID(0x0C),
    1.70 +        SoftReadErrorRate = new AttributeID(0x0D),
    1.71 +        SataDownshiftErrorCount = new AttributeID(0xB7),
    1.72 +        EndToEndError = new AttributeID(0xB8),
    1.73 +        HeadStability = new AttributeID(0xB9),
    1.74 +        InducedOpVibrationDetection = new AttributeID(0xBA),
    1.75 +        ReportedUncorrectableErrors = new AttributeID(0xBB),
    1.76 +        CommandTimeout = new AttributeID(0xBC),
    1.77 +        HighFlyWrites = new AttributeID(0xBD),
    1.78 +        AirflowTemperature = new AttributeID(0xBE),
    1.79 +        GSenseErrorRate = new AttributeID(0xBF),
    1.80 +        PowerOffRetractCount = new AttributeID(0xC0),
    1.81 +        LoadCycleCount = new AttributeID(0xC1),
    1.82 +        Temperature = new AttributeID(0xC2),
    1.83 +        HardwareEccRecovered = new AttributeID(0xC3),
    1.84 +        ReallocationEventCount = new AttributeID(0xC4),
    1.85 +        CurrentPendingSectorCount = new AttributeID(0xC5),
    1.86 +        UncorrectableSectorCount = new AttributeID(0xC6),
    1.87 +        UltraDmaCrcErrorCount = new AttributeID(0xC7),
    1.88 +        WriteErrorRate = new AttributeID(0xC8),
    1.89 +        DataAddressMarkerrors = new AttributeID(0xCA),
    1.90 +        RunOutCancel = new AttributeID(0xCB),
    1.91 +        SoftEccCorrection = new AttributeID(0xCC),
    1.92 +        ThermalAsperityRate = new AttributeID(0xCD),
    1.93 +        FlyingHeight = new AttributeID(0xCE),
    1.94 +        SpinHighCurrent = new AttributeID(0xCF),
    1.95 +        SpinBuzz = new AttributeID(0xD0),
    1.96 +        OfflineSeekPerformance = new AttributeID(0xD1),
    1.97 +        VibrationDuringWrite = new AttributeID(0xD3),
    1.98 +        ShockDuringWrite = new AttributeID(0xD4),
    1.99 +        DiskShift = new AttributeID(0xDC),
   1.100 +        GSenseErrorRateAlt = new AttributeID(0xDD), // Alternative to 0xBF
   1.101 +        LoadedHours = new AttributeID(0xDE),
   1.102 +        LoadUnloadRetryCount = new AttributeID(0xDF),
   1.103 +        LoadFriction = new AttributeID(0xE0),
   1.104 +        LoadUnloadCycleCount = new AttributeID(0xE1),
   1.105 +        LoadInTime = new AttributeID(0xE2),
   1.106 +        TorqueAmplificationCount = new AttributeID(0xE3),
   1.107 +        PowerOffRetractCycle = new AttributeID(0xE4),
   1.108 +        GMRHeadAmplitude = new AttributeID(0xE6),
   1.109 +        DriveTemperature = new AttributeID(0xE7),
   1.110 +        HeadFlyingHours = new AttributeID(0xF0),
   1.111 +        LBAsWrittenTotal = new AttributeID(0xF1),
   1.112 +        LBAsReadTotal = new AttributeID(0xF2),
   1.113 +        ReadErrorRetryRate = new AttributeID(0xFA),
   1.114 +        FreeFallProtection = new AttributeID(0xFE)
   1.115 +      ;
   1.116      }
   1.117  
   1.118      // Indilinx SSD SMART attributes
   1.119 -    public static class IndilinxAttributes {      
   1.120 -      public static readonly AttributeID RemainingLife = new AttributeID(0xD1);
   1.121 +    // TODO: Find out the purpose of attribute 0xD2
   1.122 +    // Seems to be unique to Indilinx drives, hence its name of UnknownUnique.
   1.123 +    public static class IndilinxAttributes {
   1.124 +      public static readonly AttributeID
   1.125 +        ReadErrorRate = CommonAttributes.ReadErrorRate,
   1.126 +        PowerOnHours = CommonAttributes.PowerOnHours,
   1.127 +        PowerCycleCount = CommonAttributes.PowerCycleCount,
   1.128 +        InitialBadBlockCount = new AttributeID(0xB8),
   1.129 +        RemainingLife = new AttributeID(0xD1),
   1.130 +        ProgramFailure = new AttributeID(0xC3),
   1.131 +        EraseFailure = new AttributeID(0xC4),
   1.132 +        ReadFailure = new AttributeID(0xC5),
   1.133 +        SectorsRead = new AttributeID(0xC6),
   1.134 +        SectorsWritten = new AttributeID(0xC7),
   1.135 +        ReadCommands = new AttributeID(0xC8),
   1.136 +        WriteCommands = new AttributeID(0xC9),
   1.137 +        BitErrors = new AttributeID(0xCA),
   1.138 +        CorrectedErrors = new AttributeID(0xCB),
   1.139 +        BadBlockFullFlag = new AttributeID(0xCC),
   1.140 +        MaxCellcycles = new AttributeID(0xCD),
   1.141 +        MinErase = new AttributeID(0xCE),
   1.142 +        MaxErase = new AttributeID(0xCF),
   1.143 +        AverageEraseCount = new AttributeID(0xD0),
   1.144 +        UnknownUnique = new AttributeID(0xD2),
   1.145 +        SataErrorCountCRC = new AttributeID(0xD3),
   1.146 +        SataErrorCountHandshake = new AttributeID(0xD4)
   1.147 +      ;
   1.148      }
   1.149  
   1.150      // Intel SSD SMART attributes
   1.151 -    public static class IntelAttributes {      
   1.152 -      public static readonly AttributeID RemainingLife = new AttributeID(0xE8);
   1.153 +    // TODO: Find out the meaning behind 0xE2, 0xE3 and 0xE4
   1.154 +    public static class IntelAttributes {
   1.155 +      public static readonly AttributeID
   1.156 +        ReadErrorRate = CommonAttributes.ReadErrorRate,
   1.157 +        SpinUpTime = CommonAttributes.SpinUpTime,
   1.158 +        StartStopCount = CommonAttributes.StartStopCount,
   1.159 +        ReallocatedSectorsCount = CommonAttributes.ReallocatedSectorsCount,
   1.160 +        PowerOnHours = CommonAttributes.PowerOnHours,
   1.161 +        PowerCycleCount = CommonAttributes.PowerCycleCount,
   1.162 +        EndToEndError = CommonAttributes.EndToEndError, // Only on G2 drives!
   1.163 +
   1.164 +        // Different from the common attribute PowerOffRetractCount, same ID
   1.165 +        UnsafeShutdownCount = new AttributeID(0xC0),
   1.166 +        HostWrites = new AttributeID(0xE1),
   1.167 +        RemainingLife = new AttributeID(0xE8),
   1.168 +        MediaWearOutIndicator = new AttributeID(0xE9)
   1.169 +      ;
   1.170      }
   1.171  
   1.172      // Samsung SSD SMART attributes
   1.173 -    public static class SamsungAttributes {      
   1.174 -      public static readonly AttributeID RemainingLife = new AttributeID(0xB4);
   1.175 +    // TODO: AF, B0, B1, B5, B6, BB, C3, C6, C7, E8, E9
   1.176 +    public static class SamsungAttributes {
   1.177 +      public static readonly AttributeID
   1.178 +        PowerOnHours = CommonAttributes.PowerOnHours,
   1.179 +        PowerCycleCount = CommonAttributes.PowerCycleCount,
   1.180 +        UsedReservedBlockCountChip = new AttributeID(0xB2), // Unique
   1.181 +        UsedReservedBlockCountTotal = new AttributeID(0xB3), // Unique
   1.182 +        RemainingLife = new AttributeID(0xB4), // Unique
   1.183 +        RuntimeBadBlockTotal = new AttributeID(0xB7)
   1.184 +      ;
   1.185      }
   1.186  
   1.187      // SandForce SSD SMART attributes
   1.188 -    public static class SandForceAttributes {      
   1.189 -      public static readonly AttributeID RemainingLife = new AttributeID(0xE7);
   1.190 +    // Note: 0xE9 and 0xEA are reserved attributes and unique
   1.191 +    public static class SandForceAttributes {
   1.192 +      public static readonly AttributeID
   1.193 +        ReadErrorRate = CommonAttributes.ReadErrorRate,
   1.194 +        RetiredBlockCount = new AttributeID(0x05),
   1.195 +        PowerOnHours = CommonAttributes.PowerOnHours,
   1.196 +        PowerCycleCount = CommonAttributes.PowerCycleCount,
   1.197 +        ProgramFailCount = new AttributeID(0xAB), // Unique
   1.198 +        EraseFailCount = new AttributeID(0xAC), // Unique
   1.199 +        UnexpectedPowerLossCount = new AttributeID(0xAE), // Unique
   1.200 +        WearRangeDelta = new AttributeID(0xB1), // Unique
   1.201 +        ProgramFailCountAlt = new AttributeID(0xB5), // Same as 0xAB
   1.202 +        EraseFailCountAlt = new AttributeID(0xB6), // Same as 0xAC
   1.203 +        ReportedUncorrectableErrors =
   1.204 +          CommonAttributes.ReportedUncorrectableErrors,
   1.205 +        
   1.206 +        Temperature = CommonAttributes.Temperature, // SF-1500 only!
   1.207 +        
   1.208 +        // Opposite of the common attribute HardwareECCRecovered
   1.209 +        UnrecoverableECC = new AttributeID(0xC3),
   1.210 +        ReallocationEventCount = new AttributeID(0xC4),
   1.211 +        RemainingLife = new AttributeID(0xE7),
   1.212 +        LifetimeWrites = new AttributeID(0xF1),
   1.213 +        LifetimeReads = new AttributeID(0xF2)
   1.214 +      ;
   1.215      }
   1.216  
   1.217      [StructLayout(LayoutKind.Sequential, Pack = 1)]
   1.218 @@ -329,7 +417,7 @@
   1.219          IntPtr.Zero);
   1.220      }
   1.221  
   1.222 -    public static List<DriveAttribute> ReadSmart(IntPtr handle,
   1.223 +    public static DriveAttribute[] ReadSmart(IntPtr handle,
   1.224        int driveNumber)
   1.225      {
   1.226        DriveCommandParameter parameter = new DriveCommandParameter();
   1.227 @@ -347,9 +435,7 @@
   1.228          out result, Marshal.SizeOf(typeof(DriveSmartReadResult)), 
   1.229          out bytesReturned, IntPtr.Zero);
   1.230  
   1.231 -      return (isValid)
   1.232 -        ? new List<DriveAttribute>(result.Attributes)
   1.233 -        : new List<DriveAttribute>();
   1.234 +      return (isValid) ? result.Attributes : new DriveAttribute[0];
   1.235      }
   1.236  
   1.237      public static string ReadName(IntPtr handle, int driveNumber) {