summaryrefslogtreecommitdiffstats
path: root/smart.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2008-06-30 22:51:55 +0200
committerLennart Poettering <lennart@poettering.net>2008-06-30 22:51:55 +0200
commitfbde61a065b5b1e74d181bf58145ad5a19b27a50 (patch)
tree1f8c50752ae794a94d447cb4465b21530fd7a23c /smart.c
parentffee9d06d5f95f799621deeffdfce2012275b211 (diff)
implement smart read status call
Diffstat (limited to 'smart.c')
-rw-r--r--smart.c61
1 files changed, 43 insertions, 18 deletions
diff --git a/smart.c b/smart.c
index 430785f..f0710c4 100644
--- a/smart.c
+++ b/smart.c
@@ -275,7 +275,7 @@ static int disk_passthrough_command(SkDisk *d, SkAtaCommand command, SkDirection
cdb[6] = bytes[3];
cdb[8] = bytes[9]; /* LBA LOW */
- cdb[10] = bytes[8]; /* LBA MED */
+ cdb[10] = bytes[8]; /* LBA MID */
cdb[12] = bytes[7]; /* LBA HIGH */
cdb[13] = bytes[10] & 0x4F; /* SELECT */
@@ -296,7 +296,7 @@ static int disk_passthrough_command(SkDisk *d, SkAtaCommand command, SkDirection
bytes[3] = desc[5];
bytes[9] = desc[7];
bytes[8] = desc[9];
- bytes[7] = desc[10];
+ bytes[7] = desc[11];
bytes[10] = desc[12];
bytes[11] = desc[13];
@@ -436,20 +436,38 @@ static int disk_smart_read_thresholds(SkDisk *d) {
return ret;
}
-/* int disk_smart_status(SkDisk *d, SmartLogAddress a, gboolean *b) { */
-/* guint16 cmd[6]; */
+int sk_disk_smart_status(SkDisk *d, gboolean *good) {
+ guint16 cmd[6];
+ int ret;
+
+ if (!disk_smart_is_available(d)) {
+ errno = ENOTSUP;
+ return -1;
+ }
-/* guint8 data[16]; */
+ memset(cmd, 0, sizeof(cmd));
+
+ cmd[0] = GUINT16_TO_BE(SK_SMART_COMMAND_RETURN_STATUS);
+ cmd[1] = GUINT16_TO_BE(0x0000U);
+ cmd[3] = GUINT16_TO_BE(0x00C2U);
+ cmd[4] = GUINT16_TO_BE(0x4F00U);
-/* cmd[0] = GUINT16_TO_BE(SMART_RETURN_STATUS); */
-/* cmd[1] = GUINT16_TO_BE(0x0000U); */
-/* cmd[3] = GUINT16_TO_BE(0x00C2U); */
-/* cmd[4] = GUINT16_TO_BE(0x4F00U | (guint16) a); */
+ if ((ret = disk_command(d, SK_ATA_COMMAND_SMART, SK_DIRECTION_NONE, cmd, NULL, 0)) < 0)
+ return ret;
-/* ret = disk_command(SK_ATA_SMART, cmd, sizeof(cmd), NULL, 0); */
+ if (cmd[3] == GUINT16_TO_BE(0x00C2U) &&
+ cmd[4] == GUINT16_TO_BE(0x4F00U))
+ *good = TRUE;
+ else if (cmd[3] == GUINT16_TO_BE(0x002CU) &&
+ cmd[4] == GUINT16_TO_BE(0xF400U))
+ *good = FALSE;
+ else {
+ errno = EIO;
+ return -1;
+ }
-/* return ret; */
-/* } */
+ return ret;
+}
int sk_disk_smart_self_test(SkDisk *d, SkSmartSelfTest test) {
guint16 cmd[6];
@@ -885,9 +903,9 @@ static void find_threshold(SkDisk *d, SkSmartAttributeParsedData *a) {
a->threshold = p[1];
a->threshold_valid = TRUE;
- a->bad =
- a->worst_value <= a->threshold ||
- a->current_value <= a->threshold;
+ a->good =
+ a->worst_value > a->threshold &&
+ a->current_value > a->threshold;
}
int sk_disk_smart_parse_attributes(SkDisk *d, SkSmartAttributeParseCallback cb, gpointer userdata) {
@@ -1025,7 +1043,7 @@ static void disk_dump_attributes(SkDisk *d, const SkSmartAttributeParsedData *a,
g_snprintf(t, sizeof(t), "%3u", a->threshold);
- if (a->bad && isatty(1))
+ if (!a->good && isatty(1))
fprintf(stderr, HIGHLIGHT);
g_print("%3u %-27s %3u %3u %-3s %-11s %-7s %-7s %-3s\n",
@@ -1037,9 +1055,9 @@ static void disk_dump_attributes(SkDisk *d, const SkSmartAttributeParsedData *a,
print_value(pretty, sizeof(pretty), a),
a->prefailure ? "prefail" : "old-age",
a->online ? "online" : "offline",
- yes_no(!a->bad));
+ yes_no(a->good));
- if (a->bad && isatty(1))
+ if (!a->good && isatty(1))
fprintf(stderr, ENDHIGHLIGHT);
}
@@ -1074,6 +1092,13 @@ int sk_disk_dump(SkDisk *d) {
if (disk_smart_is_available(d)) {
const SkSmartParsedData *spd;
+ gboolean good;
+
+ if ((ret = sk_disk_smart_status(d, &good)) < 0)
+ return ret;
+
+ g_print("Disk Health Good: %s\n",
+ yes_no(good));
if ((ret = sk_disk_smart_read_data(d)) < 0)
return ret;