--- embedaddon/smartmontools/atacmds.cpp 2012/02/21 16:32:16 1.1.1.1 +++ embedaddon/smartmontools/atacmds.cpp 2012/10/09 09:36:45 1.1.1.2 @@ -4,7 +4,7 @@ * Home page of code is: http://smartmontools.sourceforge.net * * Copyright (C) 2002-11 Bruce Allen - * Copyright (C) 2008-11 Christian Franke + * Copyright (C) 2008-12 Christian Franke * Copyright (C) 1999-2000 Michael Cornwell * Copyright (C) 2000 Andre Hedrick * @@ -36,7 +36,7 @@ #include "utility.h" #include "dev_ata_cmd_set.h" // for parsed_ata_device -const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp,v 1.1.1.1 2012/02/21 16:32:16 misho Exp $" +const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp,v 1.1.1.2 2012/10/09 09:36:45 misho Exp $" ATACMDS_H_CVSID; // Print ATA debug messages? @@ -212,10 +212,13 @@ const format_name_entry format_names[] = { {"raw16" , RAWFMT_RAW16}, {"raw48" , RAWFMT_RAW48}, {"hex48" , RAWFMT_HEX48}, + {"raw56" , RAWFMT_RAW56}, + {"hex56" , RAWFMT_HEX56}, {"raw64" , RAWFMT_RAW64}, {"hex64" , RAWFMT_HEX64}, {"raw16(raw16)" , RAWFMT_RAW16_OPT_RAW16}, {"raw16(avg16)" , RAWFMT_RAW16_OPT_AVG16}, + {"raw24(raw8)" , RAWFMT_RAW24_OPT_RAW8}, {"raw24/raw24" , RAWFMT_RAW24_DIV_RAW24}, {"raw24/raw32" , RAWFMT_RAW24_DIV_RAW32}, {"sec2hour" , RAWFMT_SEC2HOUR}, @@ -611,8 +614,19 @@ int smartcommandhandler(ata_device * device, smart_com in.direction==ata_cmd_in::data_out ? " OUT\n":"\n")); ata_cmd_out out; + + int64_t start_usec = -1; + if (ata_debugmode) + start_usec = smi()->get_timer_usec(); + bool ok = device->ata_pass_through(in, out); + if (start_usec >= 0) { + int64_t duration_usec = smi()->get_timer_usec() - start_usec; + if (duration_usec >= 500) + pout(" [Duration: %.3fs]\n", duration_usec / 1000000.0); + } + if (ata_debugmode && out.out_regs.is_set()) print_regs(" Output: ", out.out_regs); @@ -838,6 +852,31 @@ int ataCheckPowerMode(ata_device * device) { return (int)result; } +// Issue a no-data ATA command with optional sector count register value +bool ata_nodata_command(ata_device * device, unsigned char command, + int sector_count /* = -1 */) +{ + ata_cmd_in in; + in.in_regs.command = command; + if (sector_count >= 0) + in.in_regs.sector_count = sector_count; + + return device->ata_pass_through(in); +} + +// Issue SET FEATURES command with optional sector count register value +bool ata_set_features(ata_device * device, unsigned char features, + int sector_count /* = -1 */) +{ + ata_cmd_in in; + in.in_regs.command = ATA_SET_FEATURES; + in.in_regs.features = features; + if (sector_count >= 0) + in.in_regs.sector_count = sector_count; + + return device->ata_pass_through(in); +} + // Reads current Device Identity info (512 bytes) into buf. Returns 0 // if all OK. Returns -1 if no ATA Device identity can be // established. Returns >0 if Device is ATA Packet Device (not SMART @@ -1057,6 +1096,7 @@ int ataReadSmartValues(ata_device * device, struct ata swap2((char *)&(data->revnumber)); swap2((char *)&(data->total_time_to_complete_off_line)); swap2((char *)&(data->smart_capability)); + swapx(&data->extend_test_completion_time_w); for (i=0; ivendor_attributes+i; swap2((char *)&(x->flags)); @@ -1637,7 +1677,8 @@ int ataSmartStatus2(ata_device * device){ // This is the way to execute ALL tests: offline, short self-test, // extended self test, with and without captive mode, etc. // TODO: Move to ataprint.cpp ? -int ataSmartTest(ata_device * device, int testtype, const ata_selective_selftest_args & selargs, +int ataSmartTest(ata_device * device, int testtype, bool force, + const ata_selective_selftest_args & selargs, const ata_smart_values * sv, uint64_t num_sectors) { char cmdmsg[128]; const char *type, *captive; @@ -1664,7 +1705,20 @@ int ataSmartTest(ata_device * device, int testtype, co type="Selective self-test"; else type = 0; - + + // Check whether another test is already running + if (type && (sv->self_test_exec_status >> 4) == 0xf) { + if (!force) { + pout("Can't start self-test without aborting current test (%d0%% remaining),\n" + "%srun 'smartctl -X' to abort test.\n", + sv->self_test_exec_status & 0x0f, + (!select ? "add '-t force' option to override, or " : "")); + return -1; + } + } + else + force = false; + // If doing a selective self-test, first use WRITE_LOG to write the // selective self-test log. ata_selective_selftest_args selargs_io = selargs; // filled with info about actual spans @@ -1706,7 +1760,7 @@ int ataSmartTest(ata_device * device, int testtype, co else { pout("Drive command \"%s\" successful.\n", cmdmsg); if (type) - pout("Testing has begun.\n"); + pout("Testing has begun%s.\n", (force ? " (previous test aborted)" : "")); } return 0; } @@ -1722,7 +1776,12 @@ int TestTime(const ata_smart_values *data, int testtyp return (int) data->short_test_completion_time; case EXTEND_SELF_TEST: case EXTEND_CAPTIVE_SELF_TEST: - return (int) data->extend_test_completion_time; + if (data->extend_test_completion_time_b == 0xff + && data->extend_test_completion_time_w != 0x0000 + && data->extend_test_completion_time_w != 0xffff) + return data->extend_test_completion_time_w; // ATA-8 + else + return data->extend_test_completion_time_b; case CONVEYANCE_SELF_TEST: case CONVEYANCE_CAPTIVE_SELF_TEST: return (int) data->conveyance_test_completion_time; @@ -1903,6 +1962,9 @@ static ata_attr_raw_format get_default_raw_format(unsi case 196: // Reallocated event count return RAWFMT_RAW16_OPT_RAW16; + case 9: // Power on hours + return RAWFMT_RAW24_OPT_RAW8; + case 190: // Temperature case 194: return RAWFMT_TEMPMINMAX; @@ -1925,6 +1987,8 @@ uint64_t ata_get_attr_raw_value(const ata_smart_attrib case RAWFMT_RAW64: case RAWFMT_HEX64: byteorder = "543210wv"; break; + case RAWFMT_RAW56: + case RAWFMT_HEX56: case RAWFMT_RAW24_DIV_RAW32: case RAWFMT_MSEC24_HOUR32: byteorder = "r543210"; break; @@ -1994,6 +2058,7 @@ std::string ata_format_attr_raw_value(const ata_smart_ break; case RAWFMT_RAW48: + case RAWFMT_RAW56: case RAWFMT_RAW64: s = strprintf("%"PRIu64, rawvalue); break; @@ -2002,6 +2067,10 @@ std::string ata_format_attr_raw_value(const ata_smart_ s = strprintf("0x%012"PRIx64, rawvalue); break; + case RAWFMT_HEX56: + s = strprintf("0x%014"PRIx64, rawvalue); + break; + case RAWFMT_HEX64: s = strprintf("0x%016"PRIx64, rawvalue); break; @@ -2009,13 +2078,19 @@ std::string ata_format_attr_raw_value(const ata_smart_ case RAWFMT_RAW16_OPT_RAW16: s = strprintf("%u", word[0]); if (word[1] || word[2]) - s += strprintf(" (%u, %u)", word[2], word[1]); + s += strprintf(" (%u %u)", word[2], word[1]); break; case RAWFMT_RAW16_OPT_AVG16: s = strprintf("%u", word[0]); if (word[1]) s += strprintf(" (Average %u)", word[1]); + break; + + case RAWFMT_RAW24_OPT_RAW8: + s = strprintf("%u", (unsigned)(rawvalue & 0x00ffffffULL)); + if (raw[3] || raw[4] || raw[5]) + s += strprintf(" (%d %d %d)", raw[5], raw[4], raw[3]); break; case RAWFMT_RAW24_DIV_RAW24: