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) {