📄 ataprint.cpp
字号:
if (uses_device_fault && (ST & (1 << 5))) { strcat(s, "Device Fault"); if (ST & 1) // Error flag strcat(s, "; "); } if (ST & 1) { // Error flag int count = 0; strcat(s, "Error: "); for (i = 7; i >= 0; i--) if ((ER & (1 << i)) && (error_flag[i])) { if (count++ > 0) strcat(s, ", "); strcat(s, error_flag[i]); } } // If the error was a READ or WRITE error, print the Logical Block // Address (LBA) at which the read or write failed. if (print_lba) { char tmp[128]; int lba; // bits 24-27: bits 0-3 of DH lba = 0xf & data->error_struct.drive_head; lba <<= 8; // bits 16-23: CH lba |= data->error_struct.cylinder_high; lba <<= 8; // bits 8-15: CL lba |= data->error_struct.cylinder_low; lba <<= 8; // bits 0-7: SN lba |= data->error_struct.sector_number; // print number of sectors, if known, and append to print string if (print_sector) { snprintf(tmp, 128, " %d sectors", print_sector); strcat(s, tmp); } // print LBA, and append to print string snprintf(tmp, 128, " at LBA = 0x%08x = %d", lba, lba); strcat(s, tmp); } return s;}// Get number of sectors from IDENTIFY sector. If the drive doesn't// support LBA addressing or has no user writable sectors// (eg, CDROM or DVD) then routine returns zero.static uint64_t get_num_sectors(const ata_identify_device *drive){ unsigned short command_set_2 = drive->command_set_2; unsigned short capabilities_0 = drive->words047_079[49-47]; unsigned short sects_16 = drive->words047_079[60-47]; unsigned short sects_32 = drive->words047_079[61-47]; unsigned short lba_16 = drive->words088_255[100-88]; unsigned short lba_32 = drive->words088_255[101-88]; unsigned short lba_48 = drive->words088_255[102-88]; unsigned short lba_64 = drive->words088_255[103-88]; // LBA support? if (!(capabilities_0 & 0x0200)) return 0; // No // if drive supports LBA addressing, determine 32-bit LBA capacity uint64_t lba32 = (unsigned int)sects_32 << 16 | (unsigned int)sects_16 << 0 ; uint64_t lba64 = 0; // if drive supports 48-bit addressing, determine THAT capacity if ((command_set_2 & 0xc000) == 0x4000 && (command_set_2 & 0x0400)) lba64 = (uint64_t)lba_64 << 48 | (uint64_t)lba_48 << 32 | (uint64_t)lba_32 << 16 | (uint64_t)lba_16 << 0 ; // return the larger of the two possible capacities return (lba32 > lba64 ? lba32 : lba64);}// This returns the capacity of a disk drive and also prints this into// a string, using comma separators to make it easier to read. If the// drive doesn't support LBA addressing or has no user writable// sectors (eg, CDROM or DVD) then routine returns zero.uint64_t determine_capacity(struct ata_identify_device *drive, char *pstring){ // get correct character to use as thousands separator char *separator=",";#ifdef HAVE_LOCALE_H struct lconv *currentlocale=NULL; setlocale (LC_ALL, ""); currentlocale=localeconv(); if (*(currentlocale->thousands_sep)) separator=(char *)currentlocale->thousands_sep;#endif // #ifdef HAVE_LOCALE_H // get #sectors and turn into bytes uint64_t capacity = get_num_sectors(drive) * 512; uint64_t retval = capacity; // print with locale-specific separators (default is comma) int started=0, k=1000000000; uint64_t power_of_ten = k; power_of_ten *= k; for (k=0; k<7; k++) { uint64_t threedigits = capacity/power_of_ten; capacity -= threedigits*power_of_ten; if (started) // we have already printed some digits pstring += sprintf(pstring, "%s%03"PRIu64, separator, threedigits); else if (threedigits || k==6) { // these are the first digits that we are printing pstring += sprintf(pstring, "%"PRIu64, threedigits); started = 1; } if (k!=6) power_of_ten /= 1000; } return retval;}int ataPrintDriveInfo (struct ata_identify_device *drive){ int version, drivetype; const char *description; char unknown[64], timedatetz[DATEANDEPOCHLEN]; unsigned short minorrev; char model[64], serial[64], firm[64], capacity[64]; // format drive information (with byte swapping as needed) format_ata_string(model, (char *)drive->model,40); format_ata_string(serial, (char *)drive->serial_no,20); format_ata_string(firm, (char *)drive->fw_rev,8); // print out model, serial # and firmware versions (byte-swap ASCI strings) drivetype=lookupdrive(model, firm); // Print model family if known if (drivetype>=0 && knowndrives[drivetype].modelfamily) pout("Model Family: %s\n", knowndrives[drivetype].modelfamily); pout("Device Model: %s\n", infofound(model)); if (!con->dont_print_serial) pout("Serial Number: %s\n", infofound(serial)); pout("Firmware Version: %s\n", infofound(firm)); if (determine_capacity(drive, capacity)) pout("User Capacity: %s bytes\n", capacity); // See if drive is recognized pout("Device is: %s\n", drivetype<0? "Not in smartctl database [for details use: -P showall]": "In smartctl database [for details use: -P show]"); // now get ATA version info version=ataVersionInfo(&description,drive, &minorrev); // unrecognized minor revision code if (!description){ if (!minorrev) sprintf(unknown, "Exact ATA specification draft version not indicated"); else sprintf(unknown,"Not recognized. Minor revision code: 0x%02hx", minorrev); description=unknown; } // SMART Support was first added into the ATA/ATAPI-3 Standard with // Revision 3 of the document, July 25, 1995. Look at the "Document // Status" revision commands at the beginning of // http://www.t13.org/project/d2008r6.pdf to see this. So it's not // enough to check if we are ATA-3. Version=-3 indicates ATA-3 // BEFORE Revision 3. pout("ATA Version is: %d\n",(int)abs(version)); pout("ATA Standard is: %s\n",description); // print current time and date and timezone dateandtimezone(timedatetz); pout("Local Time is: %s\n", timedatetz); // Print warning message, if there is one if (drivetype>=0 && knowndrives[drivetype].warningmsg) pout("\n==> WARNING: %s\n\n", knowndrives[drivetype].warningmsg); if (version>=3) return drivetype; pout("SMART is only available in ATA Version 3 Revision 3 or greater.\n"); pout("We will try to proceed in spite of this.\n"); return drivetype;}const char *OfflineDataCollectionStatus(unsigned char status_byte){ unsigned char stat=status_byte & 0x7f; switch(stat){ case 0x00: return "was never started"; case 0x02: return "was completed without error"; case 0x03: if (status_byte == 0x03) return "is in progress"; else return "is in a Reserved state"; case 0x04: return "was suspended by an interrupting command from host"; case 0x05: return "was aborted by an interrupting command from host"; case 0x06: return "was aborted by the device with a fatal error"; default: if (stat >= 0x40) return "is in a Vendor Specific state\n"; else return "is in a Reserved state\n"; }} /* prints verbose value Off-line data collection status byte */ void PrintSmartOfflineStatus(struct ata_smart_values *data){ pout("Offline data collection status: (0x%02x)\t", (int)data->offline_data_collection_status); // Off-line data collection status byte is not a reserved // or vendor specific value pout("Offline data collection activity\n" "\t\t\t\t\t%s.\n", OfflineDataCollectionStatus(data->offline_data_collection_status)); // Report on Automatic Data Collection Status. Only IBM documents // this bit. See SFF 8035i Revision 2 for details. if (data->offline_data_collection_status & 0x80) pout("\t\t\t\t\tAuto Offline Data Collection: Enabled.\n"); else pout("\t\t\t\t\tAuto Offline Data Collection: Disabled.\n"); return;}void PrintSmartSelfExecStatus(struct ata_smart_values *data){ pout("Self-test execution status: "); switch (data->self_test_exec_status >> 4) { case 0: pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n"); break; case 1: pout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("the host.\n"); break; case 2: pout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("by the host with a hard or soft reset.\n"); break; case 3: pout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("occurred while the device was executing\n\t\t\t\t\t"); pout("its self-test routine and the device \n\t\t\t\t\t"); pout("was unable to complete the self-test \n\t\t\t\t\t"); pout("routine.\n"); break; case 4: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("a test element that failed and the test\n\t\t\t\t\t"); pout("element that failed is not known.\n"); break; case 5: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("the electrical element of the test\n\t\t\t\t\t"); pout("failed.\n"); break; case 6: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("the servo (and/or seek) element of the \n\t\t\t\t\t"); pout("test failed.\n"); break; case 7: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("the read element of the test failed.\n"); break; case 8: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("a test element that failed and the\n\t\t\t\t\t"); pout("device is suspected of having handling\n\t\t\t\t\t"); pout("damage.\n"); break; case 15: if (con->fixfirmwarebug == FIX_SAMSUNG3 && data->self_test_exec_status == 0xf0) { pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("with unknown result or self-test in\n\t\t\t\t\t"); pout("progress with less than 10%% remaining.\n"); } else { pout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", (int)data->self_test_exec_status); pout("%1d0%% of test remaining.\n", (int)(data->self_test_exec_status & 0x0f)); } break; default: pout("(%4d)\tReserved.\n", (int)data->self_test_exec_status); break; } }void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values *data){ pout("Total time to complete Offline \n"); pout("data collection: \t\t (%4d) seconds.\n", (int)data->total_time_to_complete_off_line);}void PrintSmartOfflineCollectCap(struct ata_smart_values *data){ pout("Offline data collection\n"); pout("capabilities: \t\t\t (0x%02x) ", (int)data->offline_data_collection_capability); if (data->offline_data_collection_capability == 0x00){ pout("\tOffline data collection not supported.\n"); } else { pout( "%s\n", isSupportExecuteOfflineImmediate(data)? "SMART execute Offline immediate." : "No SMART execute Offline immediate."); pout( "\t\t\t\t\t%s\n", isSupportAutomaticTimer(data)? "Auto Offline data collection on/off support.": "No Auto Offline data collection support."); pout( "\t\t\t\t\t%s\n", isSupportOfflineAbort(data)? "Abort Offline collection upon new\n\t\t\t\t\tcommand.": "Suspend Offline collection upon new\n\t\t\t\t\tcommand."); pout( "\t\t\t\t\t%s\n", isSupportOfflineSurfaceScan(data)? "Offline surface scan supported.": "No Offline surface scan supported."); pout( "\t\t\t\t\t%s\n", isSupportSelfTest(data)? "Self-test supported.": "No Self-test supported."); pout( "\t\t\t\t\t%s\n", isSupportConveyanceSelfTest(data)? "Conveyance Self-test supported.": "No Conveyance Self-test supported."); pout( "\t\t\t\t\t%s\n", isSupportSelectiveSelfTest(data)? "Selective Self-test supported.": "No Selective Self-test supported."); }}void PrintSmartCapability ( struct ata_smart_values *data){ pout("SMART capabilities: "); pout("(0x%04x)\t", (int)data->smart_capability);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -