|
@@ -1,5 +1,5 @@
|
|
|
/* aoeping.c - userland aoe pinger
|
|
|
- * Copyright 2008, Coraid, Inc., and licensed under GPL v.2.
|
|
|
+ * Copyright 2009, CORAID, Inc., and licensed under GPL v.2.
|
|
|
*
|
|
|
* run without arguments for usage
|
|
|
*/
|
|
@@ -210,8 +210,20 @@ pp_idtext(char *prefix, unsigned char *p, size_t len)
|
|
|
putchar('\n');
|
|
|
}
|
|
|
|
|
|
+int smart_supported(unsigned char *p)
|
|
|
+{
|
|
|
+ u16 w;
|
|
|
+
|
|
|
+ p += 82 * 2; /* skip to word 82 */
|
|
|
+ w = *p++;
|
|
|
+ w |= *p << 8;
|
|
|
+
|
|
|
+ /* word 82 bit 0 is SMART support per ATA spec */
|
|
|
+ return !!(w & 1);
|
|
|
+}
|
|
|
+
|
|
|
void
|
|
|
-disk_identify(Conf *c, u32 tag)
|
|
|
+disk_identify(Conf *c, struct progopts *opts, int *smart)
|
|
|
{
|
|
|
int n;
|
|
|
uchar buf[1400];
|
|
@@ -219,7 +231,7 @@ disk_identify(Conf *c, u32 tag)
|
|
|
Ata *p;
|
|
|
struct hd_driveid *id;
|
|
|
|
|
|
- ata_prep(&a, c, tag);
|
|
|
+ ata_prep(&a, c, opts->tag);
|
|
|
a.sectors = 1;
|
|
|
a.cmd = ATAid_dev;
|
|
|
a.lba[3] = 0xa0;
|
|
@@ -229,15 +241,19 @@ disk_identify(Conf *c, u32 tag)
|
|
|
exit(EXIT_FAILURE);
|
|
|
}
|
|
|
|
|
|
- n = aoe_pkt_read(buf, sizeof buf, c, tag);
|
|
|
+ n = aoe_pkt_read(buf, sizeof buf, c, opts->tag);
|
|
|
p = (Ata *) buf;
|
|
|
|
|
|
- if (!opts.pp_ataid) {
|
|
|
+ *smart = smart_supported(p->data);
|
|
|
+
|
|
|
+ if (opts->ata_ident && !opts->pp_ataid) {
|
|
|
puts("device identify response:");
|
|
|
hex_print(stdout, p->data, 512, " ");
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+ if (!opts->pp_ataid)
|
|
|
+ return;
|
|
|
+
|
|
|
for (n = 0; n < 1024; n += 2) {
|
|
|
unsigned char ch;
|
|
|
ch = p->data[n];
|
|
@@ -281,9 +297,15 @@ smart_registers(Ata *a, char *opts, struct smartcmd *s)
|
|
|
a->lba[0] = strtol(opts, NULL, 0);
|
|
|
}
|
|
|
|
|
|
-void
|
|
|
+int
|
|
|
show_smart_regs(Ata *a)
|
|
|
{
|
|
|
+ if (a->err & ATAabrt) {
|
|
|
+ fputs("SMART command aborted on target.\n",
|
|
|
+ stderr);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
puts("ATA registers:");
|
|
|
char *names[] = {
|
|
|
"Features", "Sector Count",
|
|
@@ -299,6 +321,8 @@ show_smart_regs(Ata *a)
|
|
|
|
|
|
for (i = 0; i < sizeof regs / sizeof regs[0]; ++i)
|
|
|
printf("%20s: 0x%02x\n", names[i], regs[i]);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
void
|
|
@@ -335,7 +359,8 @@ smart(Conf *c, u32 tag, char *smart_cmd)
|
|
|
}
|
|
|
n = aoe_pkt_read(buf, sizeof buf, c, tag);
|
|
|
p = (Ata *) buf;
|
|
|
- show_smart_regs(p);
|
|
|
+ if (show_smart_regs(p) != 0)
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
if (s->data & SmartDataRet) {
|
|
|
puts("SMART data:");
|
|
|
hex_print(stdout, p->data, 512, " ");
|
|
@@ -416,6 +441,7 @@ int
|
|
|
main(int argc, char *argv[])
|
|
|
{
|
|
|
Conf c;
|
|
|
+ int smartable = 0;
|
|
|
|
|
|
opts = defaults;
|
|
|
progname = strrchr(argv[0], '/');
|
|
@@ -448,14 +474,20 @@ main(int argc, char *argv[])
|
|
|
fflush(stdout);
|
|
|
}
|
|
|
|
|
|
- if (opts.ata_ident) {
|
|
|
+ if (opts.ata_ident || opts.smart) {
|
|
|
alarm(opts.timeout);
|
|
|
- disk_identify(&c, opts.tag);
|
|
|
+ disk_identify(&c, &opts, &smartable);
|
|
|
alarm(0);
|
|
|
opts.tag += 1;
|
|
|
}
|
|
|
|
|
|
if (opts.smart) {
|
|
|
+ if (!smartable) {
|
|
|
+ fprintf(stderr,
|
|
|
+ "Error: e%d.%d does not support SMART\n",
|
|
|
+ ntohs(c.h.maj), c.h.min);
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ }
|
|
|
alarm(opts.timeout);
|
|
|
smart(&c, opts.tag, opts.smart);
|
|
|
alarm(0);
|