Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Add ATA SMART reporting support from Ben Collver in kern/12787.
details: https://anonhg.NetBSD.org/src/rev/88849f8fca76
branches: trunk
changeset: 534889:88849f8fca76
user: soren <soren%NetBSD.org@localhost>
date: Mon Aug 05 23:29:27 2002 +0000
description:
Add ATA SMART reporting support from Ben Collver in kern/12787.
diffstat:
distrib/sets/lists/comp/mi | 3 +-
distrib/sets/lists/comp/obsolete.mi | 3 +-
sbin/atactl/atactl.8 | 54 ++++++++-
sbin/atactl/atactl.c | 215 +++++++++++++++++++++++++++++++++++-
sys/dev/ata/Makefile | 4 +-
sys/dev/ata/atareg.h | 3 +-
sys/dev/ata/atavar.h | 52 ++++++++-
sys/dev/ic/wdcreg.h | 7 +-
8 files changed, 328 insertions(+), 13 deletions(-)
diffs (truncated from 487 to 300 lines):
diff -r e53b65d81cee -r 88849f8fca76 distrib/sets/lists/comp/mi
--- a/distrib/sets/lists/comp/mi Mon Aug 05 20:58:35 2002 +0000
+++ b/distrib/sets/lists/comp/mi Mon Aug 05 23:29:27 2002 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.462 2002/08/04 01:07:21 gmcgarry Exp $
+# $NetBSD: mi,v 1.463 2002/08/05 23:29:27 soren Exp $
./sys comp-sysutil-root
./usr/bin/addr2line comp-debug-bin
./usr/bin/ar comp-util-bin
@@ -120,6 +120,7 @@
./usr/include/db.h comp-c-include
./usr/include/dev/ata comp-c-include
./usr/include/dev/ata/atareg.h comp-c-include
+./usr/include/dev/ata/atavar.h comp-c-include
./usr/include/dev/ccdvar.h comp-c-include
./usr/include/dev/dec comp-c-include
./usr/include/dev/dec/dec_boot.h comp-c-include
diff -r e53b65d81cee -r 88849f8fca76 distrib/sets/lists/comp/obsolete.mi
--- a/distrib/sets/lists/comp/obsolete.mi Mon Aug 05 20:58:35 2002 +0000
+++ b/distrib/sets/lists/comp/obsolete.mi Mon Aug 05 23:29:27 2002 +0000
@@ -1,11 +1,10 @@
-# $NetBSD: obsolete.mi,v 1.71 2002/07/14 10:40:54 wiz Exp $
+# $NetBSD: obsolete.mi,v 1.72 2002/08/05 23:29:29 soren Exp $
/usr/bin/genclass
/usr/bin/gettextize
/usr/include/bfd
/usr/include/bfd/ansidecl.h
/usr/include/bfd/bfd.h
/usr/include/bfd/libiberty.h
-/usr/include/dev/ata/atavar.h
/usr/include/dev/ata/wdvar.h
/usr/include/dev/auconv.h
/usr/include/dev/audio_if.h
diff -r e53b65d81cee -r 88849f8fca76 sbin/atactl/atactl.8
--- a/sbin/atactl/atactl.8 Mon Aug 05 20:58:35 2002 +0000
+++ b/sbin/atactl/atactl.8 Mon Aug 05 23:29:27 2002 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: atactl.8,v 1.9 2001/11/16 11:21:37 wiz Exp $
+.\" $NetBSD: atactl.8,v 1.10 2002/08/05 23:29:29 soren Exp $
.\"
.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -103,6 +103,58 @@
.Pp
Will print out if the device is in Active, Idle, or Standby power
management mode.
+.Pp
+.Cm smart
+.Ar [enable | disable | info]
+.Pp
+Controls SMART feature set of the specified device. SMART stands for
+Self-Monitoring, Analysis, and Reporting Technology. It provides an
+early warning system by comparing subtle operation characteristics to
+those determined in vendor testing to precede device failures.
+.Pp
+.Ar enable
+.Pp
+Enables access to SMART capabilities within the device. Prior to being
+enabled, a SMART capable device neither monitors nor saves SMART
+attribute values. The state of SMART, either enabled or disabled, will
+be preserved by the device across power cycles.
+.Pp
+.Ar disable
+.Pp
+Disables access to SMART capabilities within the device. Attribute values
+will be saved, and will no longer be monitored.
+.Pp
+.Ar info
+.Pp
+Reports whether SMART is supported by the device, and whether SMART is
+enabled on the device (can only be determined on ATA6 or better devices).
+If SMART is enabled, then a table of attribute information is printed.
+Attributes are the specific performance or calibration parameters that
+are used in analyzing the status of the device. The specific set of
+attributes being used and the identity of these attributes is vendor
+specific and proprietary.
+.Pp
+Attribute values are used to represent the relative reliability of
+individual performance or calibration parameters. The valid range of
+attribute values is from 1 to 253 decimal. Lower values indicate that the
+analysis algorithms being used by the device are predicting a higher
+probability of a degrading or faulty condition.
+.Pp
+Each attribute value has a corresponding threshold limit which is used for
+direct comparison to the attribute value to indicate the existence of a
+degrading or faulty conditon. The numerical value of the attribute
+thresholds are determined by the device manufacturer through design and
+reliability testing and analysis. Each attribute threshold represents the
+lowest limit to which its corresponding attribute value can equal while
+still retaining a positive reliability status.
+.Pp
+If the crit field is "yes" then negative reliability of this attribute
+predicts imminent data loss. Otherwise it merely indicates that the
+intended design life period of usage or age has been exceeded.
+The collect field indicates whether this attribute is updated while the
+device is online. The reliability field indicates whether the attribute
+value is within the acceptable threshold.
+.Pp
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr wd 4
diff -r e53b65d81cee -r 88849f8fca76 sbin/atactl/atactl.c
--- a/sbin/atactl/atactl.c Mon Aug 05 20:58:35 2002 +0000
+++ b/sbin/atactl/atactl.c Mon Aug 05 23:29:27 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: atactl.c,v 1.14 2001/09/07 16:33:50 simonb Exp $ */
+/* $NetBSD: atactl.c,v 1.15 2002/08/05 23:29:29 soren Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -52,6 +52,7 @@
#include <util.h>
#include <dev/ata/atareg.h>
+#include <dev/ata/atavar.h>
#include <dev/ic/wdcreg.h>
#include <sys/ataio.h>
@@ -70,6 +71,8 @@
void usage(void);
void ata_command(struct atareq *);
void print_bitinfo(const char *, const char *, u_int, struct bitinfo *);
+void print_smart_status(void *vbuf, void *tbuf);
+int is_smart(int silent);
int fd; /* file descriptor for device */
const char *dvname; /* device name */
@@ -81,6 +84,7 @@
void device_setidle(int, char *[]);
void device_idle(int, char *[]);
void device_checkpower(int, char *[]);
+void device_smart(int, char *[]);
struct command commands[] = {
{ "identify", "", device_identify },
@@ -90,6 +94,7 @@
{ "standby", "", device_idle },
{ "sleep", "", device_idle },
{ "checkpower", "", device_checkpower },
+ { "smart", "enable|disable|info", device_smart },
{ NULL, NULL, NULL },
};
@@ -263,6 +268,115 @@
}
/*
+ * Print out SMART attribute thresholds and values
+ */
+
+void
+print_smart_status(void *vbuf, void *tbuf)
+{
+ struct ata_smart_attributes *value_buf = vbuf;
+ struct ata_smart_thresholds *threshold_buf = tbuf;
+ int values[256];
+ int thresholds[256];
+ int flags[256];
+ int i;
+ int id;
+ int8_t checksum;
+
+ for (i = checksum = 0; i < 511; i++)
+ checksum += ((int8_t *) value_buf)[i];
+ checksum *= -1;
+ if (checksum != value_buf->checksum) {
+ fprintf(stderr, "SMART attribute values checksum error\n");
+ return;
+ }
+
+ for (i = checksum = 0; i < 511; i++)
+ checksum += ((int8_t *) threshold_buf)[i];
+ checksum *= -1;
+ if (checksum != threshold_buf->checksum) {
+ fprintf(stderr, "SMART attribute thresholds checksum error\n");
+ return;
+ }
+
+ memset(values, 0, sizeof(values));
+ memset(thresholds, 0, sizeof(thresholds));
+ memset(flags, 0, sizeof(flags));
+
+ for (i = 0; i < 30; i++) {
+ id = value_buf->attributes[i].id;
+ values[id] = value_buf->attributes[i].value;
+ flags[id] = value_buf->attributes[i].flags;
+ id = threshold_buf->thresholds[i].id;
+ thresholds[id] = threshold_buf->thresholds[i].value;
+ }
+
+ printf("id\tvalue\tthresh\tcrit\tcollect\treliability\n");
+ for (i = 0; i < 256; i++) {
+ if (values[i] != 00 && values[i] != 0xFE && values[i] != 0xFF) {
+ printf("%2d\t%3d\t%3d\t%s\t%sline\t%stive\n",
+ i, values[i], thresholds[i],
+ flags[i] & WDSM_ATTR_ADVISORY ? "yes" : "no",
+ flags[i] & WDSM_ATTR_COLLECTIVE ? "on" : "off",
+ values[i] > thresholds[i] ? "posi" : "nega");
+ }
+ }
+}
+
+/*
+ * is_smart:
+ *
+ * Detect whether device supports SMART and SMART is enabled.
+ */
+
+int
+is_smart(int silent)
+{
+ int retval = 0;
+ struct atareq req;
+ unsigned char inbuf[DEV_BSIZE];
+ struct ataparams *inqbuf;
+ char *status;
+
+ memset(&inbuf, 0, sizeof(inbuf));
+ memset(&req, 0, sizeof(req));
+
+ inqbuf = (struct ataparams *) inbuf;
+
+ req.flags = ATACMD_READ;
+ req.command = WDCC_IDENTIFY;
+ req.databuf = (caddr_t) inbuf;
+ req.datalen = sizeof(inbuf);
+ req.timeout = 1000;
+
+ ata_command(&req);
+
+ if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
+ if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) {
+ fprintf(stderr, "SMART unsupported\n");
+ } else {
+ if (inqbuf->atap_ata_major <= WDC_VER_ATA5 ||
+ inqbuf->atap_cmd_set2 == 0xffff ||
+ inqbuf->atap_cmd_set2 == 0x0000) {
+ status = "status unknown";
+ retval = 2;
+ } else {
+ if (inqbuf->atap_cmd_set2 & ATA_CMD2_SMART) {
+ status = "enabled";
+ retval = 1;
+ } else {
+ status = "disabled";
+ }
+ }
+ if (!silent || retval == 0) {
+ printf("SMART supported, SMART %s\n", status);
+ }
+ }
+ }
+ return retval;
+}
+
+/*
* DEVICE COMMANDS
*/
@@ -517,3 +631,102 @@
return;
}
+
+/*
+ * device_smart:
+ *
+ * Display SMART status
+ */
+void
+device_smart(int argc, char *argv[])
+{
+ struct atareq req;
+ unsigned char inbuf[DEV_BSIZE];
+ unsigned char inbuf2[DEV_BSIZE];
+
+ /* Only one argument */
+ if (argc != 1)
+ usage();
+
+ if (strcmp(argv[0], "enable") == 0) {
+ if (is_smart(1)) {
+ memset(&req, 0, sizeof(req));
+
+ req.features = WDSM_ENABLE_OPS;
+ req.command = WDCC_SMART;
+ req.cylinder = htole16(WDSMART_CYL);
+ req.timeout = 1000;
+
+ ata_command(&req);
+
+ is_smart(0);
+ }
+ } else if (strcmp(argv[0], "disable") == 0) {
+ if (is_smart(1)) {
+ memset(&req, 0, sizeof(req));
+
+ req.features = WDSM_DISABLE_OPS;
+ req.command = WDCC_SMART;
+ req.cylinder = htole16(WDSMART_CYL);
Home |
Main Index |
Thread Index |
Old Index