⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atacmds.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    if (smartcommandhandler(device, DISABLE, 0, NULL)){    syserror("Error SMART Disable failed");    return -1;  }    return 0;}int ataEnableAutoSave(int device){    if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){    syserror("Error SMART Enable Auto-save failed");    return -1;  }  return 0;}int ataDisableAutoSave(int device){    if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){    syserror("Error SMART Disable Auto-save failed");    return -1;  }  return 0;}// In *ALL* ATA standards the Enable/Disable AutoOffline command is// marked "OBSOLETE". It is defined in SFF-8035i Revision 2, and most// vendors still support it for backwards compatibility. IBM documents// it for some drives.int ataEnableAutoOffline (int device ){     /* timer hard coded to 4 hours */    if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){    syserror("Error SMART Enable Automatic Offline failed");    return -1;  }  return 0;}// Another Obsolete Command.  See comments directly above, associated// with the corresponding Enable command.int ataDisableAutoOffline (int device ){            if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){    syserror("Error SMART Disable Automatic Offline failed");    return -1;  }  return 0;}// If SMART is enabled, supported, and working, then this call is// guaranteed to return 1, else zero.  Note that it should return 1// regardless of whether the disk's SMART status is 'healthy' or// 'failing'.int ataDoesSmartWork(int device){  int retval=smartcommandhandler(device, STATUS, 0, NULL);  if (-1 == retval)    return 0;  return 1;}// This function uses a different interface (DRIVE_TASK) than the// other commands in this file.int ataSmartStatus2(int device){  return smartcommandhandler(device, STATUS_CHECK, 0, NULL);  }// This is the way to execute ALL tests: offline, short self-test,// extended self test, with and without captive mode, etc.int ataSmartTest(int device, int testtype, struct ata_smart_values *sv, uint64_t num_sectors){  char cmdmsg[128],*type,*captive;  int errornum, cap, retval, select=0;  // Boolean, if set, says test is captive  cap=testtype & CAPTIVE_MASK;  // Set up strings that describe the type of test  if (cap)    captive="captive";  else    captive="off-line";    if (testtype==OFFLINE_FULL_SCAN)    type="off-line";  else  if (testtype==SHORT_SELF_TEST || testtype==SHORT_CAPTIVE_SELF_TEST)    type="Short self-test";  else if (testtype==EXTEND_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST)    type="Extended self-test";  else if (testtype==CONVEYANCE_SELF_TEST || testtype==CONVEYANCE_CAPTIVE_SELF_TEST)    type="Conveyance self-test";  else if ((select=(testtype==SELECTIVE_SELF_TEST || testtype==SELECTIVE_CAPTIVE_SELF_TEST)))    type="Selective self-test";  else    type="[Unrecognized] self-test";    // If doing a selective self-test, first use WRITE_LOG to write the  // selective self-test log.  if (select && (retval=ataWriteSelectiveSelfTestLog(device, sv, num_sectors))) {    if (retval==-4)      pout("Can't start selective self-test without aborting current test: use '-X' option to smartctl.\n");    return retval;  }  //  Print ouf message that we are sending the command to test  if (testtype==ABORT_SELF_TEST)    sprintf(cmdmsg,"Abort SMART off-line mode self-test routine");  else    sprintf(cmdmsg,"Execute SMART %s routine immediately in %s mode",type,captive);  pout("Sending command: \"%s\".\n",cmdmsg);  if (select) {    int i;    pout("SPAN         STARTING_LBA           ENDING_LBA\n");    for (i = 0; i < con->smartselectivenumspans; i++)      pout("   %d %20"PRId64" %20"PRId64"\n", i,           con->smartselectivespan[i][0],           con->smartselectivespan[i][1]);  }    // Now send the command to test  errornum=smartcommandhandler(device, IMMEDIATE_OFFLINE, testtype, NULL);    if (errornum && !(cap && errno==EIO)){    char errormsg[128];    sprintf(errormsg,"Command \"%s\" failed",cmdmsg);     syserror(errormsg);    pout("\n");    return -1;  }    // Since the command succeeded, tell user  if (testtype==ABORT_SELF_TEST)    pout("Self-testing aborted!\n");  else    pout("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg);  return 0;}/* Test Time Functions */int TestTime(struct ata_smart_values *data,int testtype){  switch (testtype){  case OFFLINE_FULL_SCAN:    return (int) data->total_time_to_complete_off_line;  case SHORT_SELF_TEST:  case SHORT_CAPTIVE_SELF_TEST:    return (int) data->short_test_completion_time;  case EXTEND_SELF_TEST:  case EXTEND_CAPTIVE_SELF_TEST:    return (int) data->extend_test_completion_time;  case CONVEYANCE_SELF_TEST:  case CONVEYANCE_CAPTIVE_SELF_TEST:    return (int) data->conveyance_test_completion_time;  default:    return 0;  }}// This function tells you both about the ATA error log and the// self-test error log capability (introduced in ATA-5).  The bit is// poorly documented in the ATA/ATAPI standard.  Starting with ATA-6,// SMART error logging is also indicated in bit 0 of DEVICE IDENTIFY// word 84 and 87.  Top two bits must match the pattern 01. BEFORE// ATA-6 these top two bits still had to match the pattern 01, but the// remaining bits were reserved (==0).int isSmartErrorLogCapable (struct ata_smart_values *data, struct ata_identify_device *identity){  unsigned short word84=identity->command_set_extension;  unsigned short word87=identity->csf_default;  int isata6=identity->major_rev_num & (0x01<<6);  int isata7=identity->major_rev_num & (0x01<<7);  if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x01))    return 1;    if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x01))    return 1;    // otherwise we'll use the poorly documented capability bit  return data->errorlog_capability & 0x01;}// See previous function.  If the error log exists then the self-test// log should (must?) also exist.int isSmartTestLogCapable (struct ata_smart_values *data, struct ata_identify_device *identity){  unsigned short word84=identity->command_set_extension;  unsigned short word87=identity->csf_default;  int isata6=identity->major_rev_num & (0x01<<6);  int isata7=identity->major_rev_num & (0x01<<7);  if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x02))    return 1;    if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x02))    return 1;  // otherwise we'll use the poorly documented capability bit    return data->errorlog_capability & 0x01;}int isGeneralPurposeLoggingCapable(struct ata_identify_device *identity){  unsigned short word84=identity->command_set_extension;  unsigned short word87=identity->csf_default;  // If bit 14 of word 84 is set to one and bit 15 of word 84 is  // cleared to zero, the contents of word 84 contains valid support  // information. If not, support information is not valid in this  // word.  if ((word84>>14) == 0x01)    // If bit 5 of word 84 is set to one, the device supports the    // General Purpose Logging feature set.    return (word84 & (0x01 << 5));    // If bit 14 of word 87 is set to one and bit 15 of word 87 is  // cleared to zero, the contents of words (87:85) contain valid  // information. If not, information is not valid in these words.    if ((word87>>14) == 0x01)    // If bit 5 of word 87 is set to one, the device supports    // the General Purpose Logging feature set.    return (word87 & (0x01 << 5));  // not capable  return 0;}// SMART self-test capability is also indicated in bit 1 of DEVICE// IDENTIFY word 87 (if top two bits of word 87 match pattern 01).// However this was only introduced in ATA-6 (but self-test log was in// ATA-5).int isSupportExecuteOfflineImmediate(struct ata_smart_values *data){   return data->offline_data_collection_capability & 0x01;}// Note in the ATA-5 standard, the following bit is listed as "Vendor// Specific".  So it may not be reliable. The only use of this that I// have found is in IBM drives, where it is well-documented.  See for// example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX// hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.int isSupportAutomaticTimer(struct ata_smart_values *data){   return data->offline_data_collection_capability & 0x02;}int isSupportOfflineAbort(struct ata_smart_values *data){   return data->offline_data_collection_capability & 0x04;}int isSupportOfflineSurfaceScan(struct ata_smart_values *data){   return data->offline_data_collection_capability & 0x08;}int isSupportSelfTest (struct ata_smart_values *data){   return data->offline_data_collection_capability & 0x10;}int isSupportConveyanceSelfTest(struct ata_smart_values *data){   return data->offline_data_collection_capability & 0x20;}int isSupportSelectiveSelfTest(struct ata_smart_values *data){   return data->offline_data_collection_capability & 0x40;}// Loop over all valid attributes.  If they are prefailure attributes// and are at or below the threshold value, then return the ID of the// first failing attribute found.  Return 0 if all prefailure// attributes are in bounds.  The spec says "Bit 0// -Pre-failure/advisory - If the value of this bit equals zero, an// attribute value less than or equal to its corresponding attribute// threshold indicates an advisory condition where the usage or age of// the device has exceeded its intended design life period. If the// value of this bit equals one, an atribute value less than or equal// to its corresponding attribute threshold indicates a pre-failure// condition where imminent loss of data is being predicted."// onlyfailed=0 : are or were any age or prefailure attributes <= threshold// onlyfailed=1:  are any prefailure attributes <= threshold nowint ataCheckSmart(struct ata_smart_values *data,                  struct ata_smart_thresholds_pvt *thresholds,                  int onlyfailed){  int i;    // loop over all attributes  for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){    // pointers to disk's values and vendor's thresholds    struct ata_smart_attribute *disk=data->vendor_attributes+i;    struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i;     // consider only valid attributes    if (disk->id && thre->id){      int failednow,failedever;            failednow =disk->current <= thre->threshold;      failedever=disk->worst   <= thre->threshold;            if (!onlyfailed && failedever)        return disk->id;            if (onlyfailed && failednow && ATTRIBUTE_FLAGS_PREFAILURE(disk->flags))        return disk->id;          }  }  return 0;}// This checks the n'th attribute in the attribute list, NOT the// attribute with id==n.  If the attribute does not exist, or the// attribute is > threshold, then returns zero.  If the attribute is// <= threshold (failing) then we the attribute number if it is a// prefail attribute.  Else we return minus the attribute number if it// is a usage attribute.int ataCheckAttribute(struct ata_smart_values *data,                      struct ata_smart_thresholds_pvt *thresholds,                      int n){  struct ata_smart_attribute *disk;  struct ata_smart_threshold_entry *thre;    if (n<0 || n>=NUMBER_ATA_SMART_ATTRIBUTES || !data || !thresholds)    return 0;    // pointers to disk's values and vendor's thresholds  disk=data->vendor_attributes+n;  thre=thresholds->thres_entries+n;  if (!disk || !thre)    return 0;    // consider only valid attributes, check for failure  if (!disk->id || !thre->id || (disk->id != thre->id) || disk->current> thre->threshold)    return 0;    // We have found a failed attribute.  Return positive or negative?   if (ATTRIBUTE_FLAGS_PREFAILURE(disk->flags))    return disk->id;  else    return -1*(disk->id);}// Print temperature value and Min/Max value if presentstatic void ataPrintTemperatureValue(char *out, const unsigned char *raw, const unsigned *word){  out+=sprintf(out, "%u", word[0]);  if (!word[1] && !word[2])    return; // No Min/Max  unsigned lo = ~0, hi = ~0;  if (!raw[3]) {    // 00 HH 00 LL 00 TT (IBM)    hi = word[2]; lo = word[1];  }  else if (!word[2]) {    // 00 00 HH LL 00 TT (Maxtor)    hi = raw[3]; lo = raw[2];  }  if (lo > hi) {    unsigned t = lo; lo = hi; hi = t;  }  if (lo <= word[0] && word[0] <= hi)    sprintf(out, " (Lifetime Min/Max %u/%u)", lo, hi);  else    sprintf(out, " (%u %u %u %u)", raw[5], raw[4], raw[3], raw[2]);}// This routine prints the raw value of an attribute as a text string// into out. It also returns this 48-bit number as a long long.  The// array defs[] contains non-zero values if particular attributes have// non-default interpretations.int64_t ataPrintSmartAttribRawValue(char *out,                                     struct ata_smart_attribute *attribute,                                    unsigned char *defs){  int64_t rawvalue;  unsigned word[3];  int j;  unsigned char select;    // convert the six individual bytes to a long long (8 byte) integer.  // This is the value that we'll eventually return.  rawvalue = 0;  for (j=0; j<6; j++) {    // This looks a bit roundabout, but is necessary.  Don't    // succumb to the temptation to use raw[j]<<(8*j) since under    // the normal rules this will be promoted to the native type.    // On a 32 bit machine this might then overflow.    int64_t temp;    temp = attribute->raw[j];    temp <<= 8*j;    rawvalue |= temp;  }  // convert quantities to three two-byte words  for (j=0; j<3; j++){    word[j] = attribute->raw[2*j+1];    word[j] <<= 8;    word[j] |= attribute->raw[2*j];  }    // if no data array, Attributes have default interpretations  if (defs)    select=defs[attribute->id];  else    select=0;  // Print six one-byte quantities.  if (select==253){    for (j=0; j<5; j++)      out+=sprintf(out, "%d ", attribute->raw[5-j]);    out+=sprintf(out, "%d ", attribute->raw[0]);    return rawvalue;  }     // Print three two-byte quantities  if (select==254){    out+=sprintf(out, "%d %d %d", word[2], word[1], word[0]); 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -