📄 scsiprint.cpp
字号:
break; // only print header if needed if (noheader) { pout("\nSMART Self-test log\n"); pout("Num Test Status segment " "LifeTime LBA_first_err [SK ASC ASQ]\n"); pout(" Description number " "(hours)\n"); noheader=0; } // print parameter code (test number) & self-test code text pout("#%2d %s", (ucp[0] << 8) | ucp[1], self_test_code[(ucp[4] >> 5) & 0x7]); // check the self-test result nibble, using the self-test results // field table from T10/1416-D (SPC-3) Rev. 23, section 7.2.10: switch ((res = ucp[4] & 0xf)) { case 0x3: // an unknown error occurred while the device server // was processing the self-test and the device server // was unable to complete the self-test retval|=FAILSMART; break; case 0x4: // the self-test completed with a failure in a test // segment, and the test segment that failed is not // known retval|=FAILLOG; break; case 0x5: // the first segment of the self-test failed retval|=FAILLOG; break; case 0x6: // the second segment of the self-test failed retval|=FAILLOG; break; case 0x7: // another segment of the self-test failed and which // test is indicated by the contents of the SELF-TEST // NUMBER field retval|=FAILLOG; break; default: break; } pout(" %s", self_test_result[res]); // self-test number identifies test that failed and consists // of either the number of the segment that failed during // the test, or the number of the test that failed and the // number of the segment in which the test was run, using a // vendor-specific method of putting both numbers into a // single byte. if (ucp[5]) pout(" %3d", (int)ucp[5]); else pout(" -"); // print time that the self-test was completed if (n==0 && res==0xf) // self-test in progress pout(" NOW"); else pout(" %5d", n); // construct 8-byte integer address of first failure for (i = 0; i < 8; i++) { ull <<= 8; ull |= ucp[i+8]; } // print Address of First Failure, if sensible if ((~(uint64_t)0 != ull) && (res > 0) && (res < 0xf)) { char buff[32]; // was hex but change to decimal to conform with ATA snprintf(buff, sizeof(buff), "%"PRIu64, ull); // snprintf(buff, sizeof(buff), "0x%"PRIx64, ull); pout("%18s", buff); } else pout(" -"); // if sense key nonzero, then print it, along with // additional sense code and additional sense code qualifier if (ucp[16] & 0xf) pout(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]); else pout(" [- - -]\n"); } // if header never printed, then there was no output if (noheader) pout("No self-tests have been logged\n"); else pout("\n"); if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec, modese_len)) && (durationSec > 0)) { pout("Long (extended) Self Test duration: %d seconds " "[%.1f minutes]\n", durationSec, durationSec / 60.0); } return retval;}static const char * bms_status[] = { "no scans active", "scan is active", "pre-scan is active", "halted due to fatal error", "halted due to a vendor specific pattern of error", "halted due to medium formatted without P-List", "halted - vendor specific cause", "halted due to temperature out of range", "halted until BM interval timer expires", /* 8 */};static const char * reassign_status[] = { "No reassignment needed", "Require Reassign or Write command", "Successfully reassigned", "Reserved [0x3]", "Failed", "Recovered via rewrite in-place", "Reassigned by app, has valid data", "Reassigned by app, has no valid data", "Unsuccessfully reassigned by app", /* 8 */};// See SCSI Block Commands - 3 (SBC-3) rev 6 (draft) section 6.2.2 .// Returns 0 if ok else FAIL* bitmask. Note can have a status entry// and up to 2048 events (although would hope to have less). May set// FAILLOG if serious errors detected (in the future).static int scsiPrintBackgroundResults(int device){ int num, j, m, err, pc, pl, truncated; int noheader = 1; int firstresult = 1; int retval = 0; UINT8 * ucp; if ((err = scsiLogSense(device, BACKGROUND_RESULTS_LPAGE, 0, gBuf, LOG_RESP_LONG_LEN, 0))) { PRINT_ON(con); pout("scsiPrintBackgroundResults Failed [%s]\n", scsiErrString(err)); PRINT_OFF(con); return FAILSMART; } if ((gBuf[0] & 0x3f) != BACKGROUND_RESULTS_LPAGE) { PRINT_ON(con); pout("Background scan results Log Sense Failed, page mismatch\n"); PRINT_OFF(con); return FAILSMART; } // compute page length num = (gBuf[2] << 8) + gBuf[3] + 4; if (num < 20) { PRINT_ON(con); pout("Background scan results Log Sense length is %d, no scan " "status\n", num); PRINT_OFF(con); return FAILSMART; } truncated = (num > LOG_RESP_LONG_LEN) ? num : 0; if (truncated) num = LOG_RESP_LONG_LEN; ucp = gBuf + 4; num -= 4; while (num > 3) { pc = (ucp[0] << 8) | ucp[1]; // pcb = ucp[2]; pl = ucp[3] + 4; switch (pc) { case 0: if (noheader) { noheader = 0; pout("\nBackground scan results log\n"); } pout(" Status: "); if ((pl < 16) || (num < 16)) { pout("\n"); break; } j = ucp[9]; if (j < (int)(sizeof(bms_status) / sizeof(bms_status[0]))) pout("%s\n", bms_status[j]); else pout("unknown [0x%x] background scan status value\n", j); j = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7]; pout(" Accumulated power on time, hours:minutes %d:%02d " "[%d minutes]\n", (j / 60), (j % 60), j); pout(" Number of background scans performed: %d, ", (ucp[10] << 8) + ucp[11]); pout("scan progress: %.2f%%\n", (double)((ucp[12] << 8) + ucp[13]) * 100.0 / 65536.0); break; default: if (noheader) { noheader = 0; pout("\nBackground scan results log\n"); } if (firstresult) { firstresult = 0; pout("\n # when lba(hex) [sk,asc,ascq] " "reassign_status\n"); } pout(" %3d ", pc); if ((pl < 24) || (num < 24)) { if (pl < 24) pout("parameter length >= 24 expected, got %d\n", pl); break; } j = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7]; pout("%4d:%02d ", (j / 60), (j % 60)); for (m = 0; m < 8; ++m) pout("%02x", ucp[16 + m]); pout(" [%x,%x,%x] ", ucp[8] & 0xf, ucp[9], ucp[10]); j = (ucp[8] >> 4) & 0xf; if (j < (int)(sizeof(reassign_status) / sizeof(reassign_status[0]))) pout("%s\n", reassign_status[j]); else pout("Reassign status: reserved [0x%x]\n", j); break; } num -= pl; ucp += pl; } if (truncated) pout(" >>>> log truncated, fetched %d of %d available " "bytes\n", LOG_RESP_LONG_LEN, truncated); return retval;}static const char * peripheral_dt_arr[] = { "disk", "tape", "printer", "processor", "optical disk(4)", "CD/DVD", "scanner", "optical disk(7)", "medium changer", "communications", "graphics(10)", "graphics(11)", "storage array", "enclosure", "simplified disk", "optical card reader"};static const char * transport_proto_arr[] = { "Fibre channel (FCP-2)", "Parallel SCSI (SPI-4)", "SSA", "IEEE 1394 (SBP-2)", "RDMA (SRP)", "iSCSI", "SAS", "ADT", "0x8", "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf"};/* Returns 0 on success, 1 on general error and 2 for early, clean exit */static int scsiGetDriveInfo(int device, UINT8 * peripheral_type, int all){ char manufacturer[9]; char product[17]; char revision[5]; char timedatetz[DATEANDEPOCHLEN]; struct scsi_iec_mode_page iec; int err, iec_err, len, req_len, avail_len, val; int is_tape = 0; int peri_dt = 0; int returnval=0; memset(gBuf, 0, 96); req_len = 36; if ((err = scsiStdInquiry(device, gBuf, req_len))) { PRINT_ON(con); pout("Standard Inquiry (36 bytes) failed [%s]\n", scsiErrString(err)); pout("Retrying with a 64 byte Standard Inquiry\n"); PRINT_OFF(con); /* Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices */ req_len = 64; if ((err = scsiStdInquiry(device, gBuf, req_len))) { PRINT_ON(con); pout("Standard Inquiry (64 bytes) failed [%s]\n", scsiErrString(err)); PRINT_OFF(con); return 1; } } avail_len = gBuf[4] + 5; len = (avail_len < req_len) ? avail_len : req_len; peri_dt = gBuf[0] & 0x1f; if (peripheral_type) *peripheral_type = peri_dt; if (len < 36) { PRINT_ON(con); pout("Short INQUIRY response, skip product id\n"); PRINT_OFF(con); return 1; } memset(manufacturer, 0, sizeof(manufacturer)); strncpy(manufacturer, (char *)&gBuf[8], 8); memset(product, 0, sizeof(product)); strncpy(product, (char *)&gBuf[16], 16); memset(revision, 0, sizeof(revision)); strncpy(revision, (char *)&gBuf[32], 4); if (all && (0 != strncmp(manufacturer, "ATA", 3))) pout("Device: %s %s Version: %s\n", manufacturer, product, revision); if (0 == strncmp(manufacturer, "3ware", 5) || 0 == strncmp(manufacturer, "AMCC", 4) ) {#if defined(_WIN32) || defined(__CYGWIN__) pout("please try changing device to /dev/hdX,N\n");#else pout("please try adding '-d 3ware,N'\n"); pout("you may also need to change device to /dev/twaN or /dev/tweN\n");#endif return 2; } else if ((len >= 42) && (0 == strncmp((const char *)(gBuf + 36), "MVSATA", 6))) { pout("please try '-d marvell'\n"); return 2; } else if ((0 == con->controller_explicit) && (0 == strncmp(manufacturer, "ATA ", 8)) && has_sat_pass_through(device, 0)) { con->controller_type = CONTROLLER_SAT; if (con->reportscsiioctl > 0) { PRINT_ON(con); pout("Detected SAT interface, switch to device type 'sat'\n"); PRINT_OFF(con); } return 2; } else if ((0 == con->controller_explicit) && (0 == strncmp(manufacturer, "ATA", 3))) { pout("\nProbable ATA device behind a SAT layer\n" "Try an additional '-d ata' or '-d sat' argument.\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -