📄 ataprint.cpp
字号:
if (data->smart_capability == 0x00) { pout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n"); } else { pout( "%s\n", (data->smart_capability & 0x01)? "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.": "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode."); if ( data->smart_capability & 0x02 ) { pout("\t\t\t\t\tSupports SMART auto save timer.\n"); } }}void PrintSmartErrorLogCapability (struct ata_smart_values *data, struct ata_identify_device *identity){ pout("Error logging capability: "); if ( isSmartErrorLogCapable(data, identity) ) { pout(" (0x%02x)\tError logging supported.\n", (int)data->errorlog_capability); } else { pout(" (0x%02x)\tError logging NOT supported.\n", (int)data->errorlog_capability); }}void PrintSmartShortSelfTestPollingTime(struct ata_smart_values *data){ pout("Short self-test routine \n"); if (isSupportSelfTest(data)) pout("recommended polling time: \t (%4d) minutes.\n", (int)data->short_test_completion_time); else pout("recommended polling time: \t Not Supported.\n");}void PrintSmartExtendedSelfTestPollingTime(struct ata_smart_values *data){ pout("Extended self-test routine\n"); if (isSupportSelfTest(data)) pout("recommended polling time: \t (%4d) minutes.\n", (int)data->extend_test_completion_time); else pout("recommended polling time: \t Not Supported.\n");}void PrintSmartConveyanceSelfTestPollingTime(struct ata_smart_values *data){ pout("Conveyance self-test routine\n"); if (isSupportConveyanceSelfTest(data)) pout("recommended polling time: \t (%4d) minutes.\n", (int)data->conveyance_test_completion_time); else pout("recommended polling time: \t Not Supported.\n");}// onlyfailed=0 : print all attribute values// onlyfailed=1: just ones that are currently failed and have prefailure bit set// onlyfailed=2: ones that are failed, or have failed with or without prefailure bit setvoid PrintSmartAttribWithThres (struct ata_smart_values *data, struct ata_smart_thresholds_pvt *thresholds, int onlyfailed){ int i; int needheader=1; char rawstring[64]; // step through all vendor attributes for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ char *status; struct ata_smart_attribute *disk=data->vendor_attributes+i; struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i; // consider only valid attributes (allowing some screw-ups in the // thresholds page data to slip by) if (disk->id){ const char *type, *update; int failednow,failedever; char attributename[64]; failednow = (disk->current <= thre->threshold); failedever= (disk->worst <= thre->threshold); // These break out of the loop if we are only printing certain entries... if (onlyfailed==1 && (!ATTRIBUTE_FLAGS_PREFAILURE(disk->flags) || !failednow)) continue; if (onlyfailed==2 && !failedever) continue; // print header only if needed if (needheader){ if (!onlyfailed){ pout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber); pout("Vendor Specific SMART Attributes with Thresholds:\n"); } pout("ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n"); needheader=0; } // is this Attribute currently failed, or has it ever failed? if (failednow) status="FAILING_NOW"; else if (failedever) status="In_the_past"; else status=" -"; // Print name of attribute ataPrintSmartAttribName(attributename,disk->id, con->attributedefs); pout("%-28s",attributename); // printing line for each valid attribute type=ATTRIBUTE_FLAGS_PREFAILURE(disk->flags)?"Pre-fail":"Old_age"; update=ATTRIBUTE_FLAGS_ONLINE(disk->flags)?"Always":"Offline"; pout("0x%04x %.3d %.3d %.3d %-10s%-9s%-12s", (int)disk->flags, (int)disk->current, (int)disk->worst, (int)thre->threshold, type, update, status); // print raw value of attribute ataPrintSmartAttribRawValue(rawstring, disk, con->attributedefs); pout("%s\n", rawstring); // print a warning if there is inconsistency here! if (disk->id != thre->id){ char atdat[64],atthr[64]; ataPrintSmartAttribName(atdat, disk->id, con->attributedefs); ataPrintSmartAttribName(atthr, thre->id, con->attributedefs); pout("%-28s<== Data Page | WARNING: PREVIOUS ATTRIBUTE HAS TWO\n",atdat); pout("%-28s<== Threshold Page | INCONSISTENT IDENTITIES IN THE DATA\n",atthr); } } } if (!needheader) pout("\n");}// Print SMART related SCT capabilitiesstatic void ataPrintSCTCapability(const ata_identify_device *drive){ unsigned short sctcaps = drive->words088_255[206-88]; if (!(sctcaps & 0x01)) return; pout("SCT capabilities: \t (0x%04x)\tSCT Status supported.\n", sctcaps); if (sctcaps & 0x10) pout("\t\t\t\t\tSCT Feature Control supported.\n"); if (sctcaps & 0x20) pout("\t\t\t\t\tSCT Data Table supported.\n");}void ataPrintGeneralSmartValues(struct ata_smart_values *data, struct ata_identify_device *drive){ pout("General SMART Values:\n"); PrintSmartOfflineStatus(data); if (isSupportSelfTest(data)){ PrintSmartSelfExecStatus (data); } PrintSmartTotalTimeCompleteOffline(data); PrintSmartOfflineCollectCap(data); PrintSmartCapability(data); PrintSmartErrorLogCapability(data, drive); pout( "\t\t\t\t\t%s\n", isGeneralPurposeLoggingCapable(drive)? "General Purpose Logging supported.": "No General Purpose Logging support."); if (isSupportSelfTest(data)){ PrintSmartShortSelfTestPollingTime (data); PrintSmartExtendedSelfTestPollingTime (data); } if (isSupportConveyanceSelfTest(data)) PrintSmartConveyanceSelfTestPollingTime (data); ataPrintSCTCapability(drive); pout("\n");}int ataPrintLogDirectory(struct ata_smart_log_directory *data){ int i; char *name; pout("SMART Log Directory Logging Version %d%s\n", data->logversion, data->logversion==1?" [multi-sector log support]":""); for (i=0; i<=255; i++){ int numsect; // Directory log length numsect = i? data->entry[i-1].numsectors : 1; // If the log is not empty, what is it's name if (numsect){ switch (i) { case 0: name="Log Directory"; break; case 1: name="Summary SMART error log"; break; case 2: name="Comprehensive SMART error log"; break; case 3: name="Extended Comprehensive SMART error log"; break; case 6: name="SMART self-test log"; break; case 7: name="Extended self-test log"; break; case 9: name="Selective self-test log"; break; case 0x20: name="Streaming performance log"; break; case 0x21: name="Write stream error log"; break; case 0x22: name="Read stream error log"; break; case 0x23: name="Delayed sector log"; break; default: if (0xa0<=i && i<=0xbf) name="Device vendor specific log"; else if (0x80<=i && i<=0x9f) name="Host vendor specific log"; else name="Reserved log"; break; } // print name and length of log pout("Log at address 0x%02x has %03d sectors [%s]\n", i, numsect, name); } } return 0;}// returns number of errorsint ataPrintSmartErrorlog(struct ata_smart_errorlog *data){ int k; pout("SMART Error Log Version: %d\n", (int)data->revnumber); // if no errors logged, return if (!data->error_log_pointer){ pout("No Errors Logged\n\n"); return 0; } PRINT_ON(con); // If log pointer out of range, return if (data->error_log_pointer>5){ pout("Invalid Error Log index = 0x%02x (T13/1321D rev 1c " "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n\n", (int)data->error_log_pointer); return 0; } // Some internal consistency checking of the data structures if ((data->ata_error_count-data->error_log_pointer)%5 && con->fixfirmwarebug != FIX_SAMSUNG2) { pout("Warning: ATA error count %d inconsistent with error log pointer %d\n\n", data->ata_error_count,data->error_log_pointer); } // starting printing error log info if (data->ata_error_count<=5) pout( "ATA Error Count: %d\n", (int)data->ata_error_count); else pout( "ATA Error Count: %d (device log contains only the most recent five errors)\n", (int)data->ata_error_count); PRINT_OFF(con); pout("\tCR = Command Register [HEX]\n" "\tFR = Features Register [HEX]\n" "\tSC = Sector Count Register [HEX]\n" "\tSN = Sector Number Register [HEX]\n" "\tCL = Cylinder Low Register [HEX]\n" "\tCH = Cylinder High Register [HEX]\n" "\tDH = Device/Head Register [HEX]\n" "\tDC = Device Command Register [HEX]\n" "\tER = Error register [HEX]\n" "\tST = Status register [HEX]\n" "Powered_Up_Time is measured from power on, and printed as\n" "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n" "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n"); // now step through the five error log data structures (table 39 of spec) for (k = 4; k >= 0; k-- ) { char *st_er_desc; // The error log data structure entries are a circular buffer int j, i=(data->error_log_pointer+k)%5; struct ata_smart_errorlog_struct *elog=data->errorlog_struct+i; struct ata_smart_errorlog_error_struct *summary=&(elog->error_struct); // Spec says: unused error log structures shall be zero filled if (nonempty((unsigned char*)elog,sizeof(*elog))){ // Table 57 of T13/1532D Volume 1 Revision 3 char *msgstate; int bits=summary->state & 0x0f; int days = (int)summary->timestamp/24; switch (bits){ case 0x00: msgstate="in an unknown state";break; case 0x01: msgstate="sleeping"; break; case 0x02: msgstate="in standby mode"; break; case 0x03: msgstate="active or idle"; break; case 0x04: msgstate="doing SMART Offline or Self-test"; break; default: if (bits<0x0b) msgstate="in a reserved state"; else msgstate="in a vendor specific state"; } // See table 42 of ATA5 spec PRINT_ON(con); pout("Error %d occurred at disk power-on lifetime: %d hours (%d days + %d hours)\n", (int)(data->ata_error_count+k-4), (int)summary->timestamp, days, (int)(summary->timestamp-24*days)); PRINT_OFF(con); pout(" When the command that caused the error occurred, the device was %s.\n\n",msgstate); pout(" After command completion occurred, registers were:\n" " ER ST SC SN CL CH DH\n" " -- -- -- -- -- -- --\n" " %02x %02x %02x %02x %02x %02x %02x", (int)summary->error_register, (int)summary->status, (int)summary->sector_count, (int)summary->sector_number, (int)summary->cylinder_low, (int)summary->cylinder_high, (int)summary->drive_head); // Add a description of the contents of the status and error registers // if possible st_er_desc = construct_st_er_desc(elog); if (st_er_desc) { pout(" %s", st_er_desc); free(st_er_desc); } pout("\n\n"); pout(" Commands leading to the command that caused the error were:\n" " CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name\n" " -- -- -- -- -- -- -- -- ---------------- --------------------\n"); for ( j = 4; j >= 0; j--){ struct ata_smart_errorlog_command_struct *thiscommand=elog->commands+j; // Spec says: unused data command structures shall be zero filled if (nonempty((unsigned char*)thiscommand,sizeof(*thiscommand))) { char timestring[32]; // Convert integer milliseconds to a text-format string MsecToText(thiscommand->timestamp, timestring); pout(" %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n", (int)thiscommand->commandreg, (int)thiscommand->featuresreg, (int)thiscommand->sector_count, (int)thiscommand->sector_number, (int)thiscommand->cylinder_low, (int)thiscommand->cylinder_high, (int)thiscommand->drive_head, (int)thiscommand->devicecontrolreg, timestring, look_up_ata_command(thiscommand->commandreg, thiscommand->featuresreg)); } } pout("\n"); } } PRINT_ON(con); if (con->printing_switchable) pout("\n"); PRINT_OFF(con); return data->ata_error_count; }void ataPrintSelectiveSelfTestLog(struct ata_selective_self_test_log *log, struct ata_smart_values *sv) { int i,field1,field2; char *msg; char tmp[64]; uint64_t maxl=0,maxr=0; uint64_t current=log->currentlba; uint64_t currentend=current+65535;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -