📄 scsiprint.cpp
字号:
int k, j, num, pl, pc, err, len; unsigned char * ucp; unsigned char * xp; uint64_t ull; if ((err = scsiLogSense(device, SEAGATE_CACHE_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) { PRINT_ON(con); pout("Seagate Cache Log Sense Failed: %s\n", scsiErrString(err)); PRINT_OFF(con); return; } if ((gBuf[0] & 0x3f) != SEAGATE_CACHE_LPAGE) { PRINT_ON(con); pout("Seagate Cache Log Sense Failed, page mismatch\n"); PRINT_OFF(con); return; } len = ((gBuf[2] << 8) | gBuf[3]) + 4; num = len - 4; ucp = &gBuf[0] + 4; while (num > 3) { pc = (ucp[0] << 8) | ucp[1]; pl = ucp[3] + 4; switch (pc) { case 0: case 1: case 2: case 3: case 4: break; default: if (con->reportscsiioctl > 0) { PRINT_ON(con); pout("Vendor (Seagate) cache lpage has unexpected parameter" ", skip\n"); PRINT_OFF(con); } return; } num -= pl; ucp += pl; } pout("Vendor (Seagate) cache information\n"); num = len - 4; ucp = &gBuf[0] + 4; while (num > 3) { pc = (ucp[0] << 8) | ucp[1]; pl = ucp[3] + 4; switch (pc) { case 0: pout(" Blocks sent to initiator"); break; case 1: pout(" Blocks received from initiator"); break; case 2: pout(" Blocks read from cache and sent to initiator"); break; case 3: pout(" Number of read and write commands whose size " "<= segment size"); break; case 4: pout(" Number of read and write commands whose size " "> segment size"); break; default: pout(" Unknown Seagate parameter code [0x%x]", pc); break; } k = pl - 4; xp = ucp + 4; if (k > (int)sizeof(ull)) { xp += (k - (int)sizeof(ull)); k = (int)sizeof(ull); } ull = 0; for (j = 0; j < k; ++j) { if (j > 0) ull <<= 8; ull |= xp[j]; } pout(" = %"PRIu64"\n", ull); num -= pl; ucp += pl; }}static void scsiPrintSeagateFactoryLPage(int device){ int k, j, num, pl, pc, len, err, good, bad; unsigned char * ucp; unsigned char * xp; uint64_t ull; if ((err = scsiLogSense(device, SEAGATE_FACTORY_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) { PRINT_ON(con); pout("scsiPrintSeagateFactoryLPage Failed [%s]\n", scsiErrString(err)); PRINT_OFF(con); return; } if ((gBuf[0] & 0x3f) != SEAGATE_FACTORY_LPAGE) { PRINT_ON(con); pout("Seagate/Hitachi Factory Log Sense Failed, page mismatch\n"); PRINT_OFF(con); return; } len = ((gBuf[2] << 8) | gBuf[3]) + 4; num = len - 4; ucp = &gBuf[0] + 4; good = 0; bad = 0; while (num > 3) { pc = (ucp[0] << 8) | ucp[1]; pl = ucp[3] + 4; switch (pc) { case 0: case 8: ++good; break; default: ++bad; break; } num -= pl; ucp += pl; } if ((good < 2) || (bad > 4)) { /* heuristic */ if (con->reportscsiioctl > 0) { PRINT_ON(con); pout("\nVendor (Seagate/Hitachi) factory lpage has too many " "unexpected parameters, skip\n"); PRINT_OFF(con); } return; } pout("Vendor (Seagate/Hitachi) factory information\n"); num = len - 4; ucp = &gBuf[0] + 4; while (num > 3) { pc = (ucp[0] << 8) | ucp[1]; pl = ucp[3] + 4; good = 0; switch (pc) { case 0: pout(" number of hours powered up"); good = 1; break; case 8: pout(" number of minutes until next internal SMART test"); good = 1; break; default: if (con->reportscsiioctl > 0) { PRINT_ON(con); pout("Vendor (Seagate/Hitachi) factory lpage: " "unknown parameter code [0x%x]\n", pc); PRINT_OFF(con); } break; } if (good) { k = pl - 4; xp = ucp + 4; if (k > (int)sizeof(ull)) { xp += (k - (int)sizeof(ull)); k = (int)sizeof(ull); } ull = 0; for (j = 0; j < k; ++j) { if (j > 0) ull <<= 8; ull |= xp[j]; } if (0 == pc) pout(" = %.2f\n", uint64_to_double(ull) / 60.0 ); else pout(" = %"PRIu64"\n", ull); } num -= pl; ucp += pl; }}static void scsiPrintErrorCounterLog(int device){ struct scsiErrorCounter errCounterArr[3]; struct scsiErrorCounter * ecp; struct scsiNonMediumError nme; int found[3] = {0, 0, 0}; const char * pageNames[3] = {"read: ", "write: ", "verify: "}; int k; double processed_gb; if (gReadECounterLPage && (0 == scsiLogSense(device, READ_ERROR_COUNTER_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) { scsiDecodeErrCounterPage(gBuf, &errCounterArr[0]); found[0] = 1; } if (gWriteECounterLPage && (0 == scsiLogSense(device, WRITE_ERROR_COUNTER_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) { scsiDecodeErrCounterPage(gBuf, &errCounterArr[1]); found[1] = 1; } if (gVerifyECounterLPage && (0 == scsiLogSense(device, VERIFY_ERROR_COUNTER_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) { scsiDecodeErrCounterPage(gBuf, &errCounterArr[2]); ecp = &errCounterArr[2]; for (k = 0; k < 7; ++k) { if (ecp->gotPC[k] && ecp->counter[k]) { found[2] = 1; break; } } } if (found[0] || found[1] || found[2]) { pout("\nError counter log:\n"); pout(" Errors Corrected by Total " "Correction Gigabytes Total\n"); pout(" ECC rereads/ errors " "algorithm processed uncorrected\n"); pout(" fast | delayed rewrites corrected " "invocations [10^9 bytes] errors\n"); for (k = 0; k < 3; ++k) { if (! found[k]) continue; ecp = &errCounterArr[k]; pout("%s%8"PRIu64" %8"PRIu64" %8"PRIu64" %8"PRIu64" %8"PRIu64, pageNames[k], ecp->counter[0], ecp->counter[1], ecp->counter[2], ecp->counter[3], ecp->counter[4]); processed_gb = uint64_to_double(ecp->counter[5]) / 1000000000.0; pout(" %12.3f %8"PRIu64"\n", processed_gb, ecp->counter[6]); } } else pout("\nError Counter logging not supported\n"); if (gNonMediumELPage && (0 == scsiLogSense(device, NON_MEDIUM_ERROR_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) { scsiDecodeNonMediumErrPage(gBuf, &nme); if (nme.gotPC0) pout("\nNon-medium error count: %8"PRIu64"\n", nme.counterPC0); if (nme.gotTFE_H) pout("Track following error count [Hitachi]: %8"PRIu64"\n", nme.counterTFE_H); if (nme.gotPE_H) pout("Positioning error count [Hitachi]: %8"PRIu64"\n", nme.counterPE_H); } if (gLastNErrorLPage && (0 == scsiLogSense(device, LAST_N_ERROR_LPAGE, 0, gBuf, LOG_RESP_LONG_LEN, 0))) { unsigned char * ucp; int num, k, pc, pl, truncated; num = (gBuf[2] << 8) + gBuf[3] + 4; truncated = (num > LOG_RESP_LONG_LEN) ? num : 0; if (truncated) num = LOG_RESP_LONG_LEN; ucp = gBuf + 4; num -= 4; if (num < 4) pout("\nNo error events logged\n"); else { pout("\nLast n error events log page\n"); for (k = num; k > 0; k -= pl, ucp += pl) { if (k < 3) { pout(" <<short Last n error events log page>>\n"); break; } pl = ucp[3] + 4; pc = (ucp[0] << 8) + ucp[1]; if (pl > 4) { if ((ucp[2] & 0x1) && (ucp[2] & 0x2)) { pout(" Error event %d:\n", pc); pout(" [binary]:\n"); dStrHex((const char *)ucp + 4, pl - 4, 1); } else if (ucp[2] & 0x1) { pout(" Error event %d:\n", pc); pout(" %.*s\n", pl - 4, (const char *)(ucp + 4)); } else { if (con->reportscsiioctl > 0) { pout(" Error event %d:\n", pc); pout(" [data counter??]:\n"); dStrHex((const char *)ucp + 4, pl - 4, 1); } } } } if (truncated) pout(" >>>> log truncated, fetched %d of %d available " "bytes\n", LOG_RESP_LONG_LEN, truncated); } }}static const char * self_test_code[] = { "Default ", "Background short", "Background long ", "Reserved(3) ", "Abort background", "Foreground short", "Foreground long ", "Reserved(7) "};static const char * self_test_result[] = { "Completed ", "Interrupted ('-X' switch)", "Interrupted (bus reset ?)", "Unknown error, incomplete", "Completed, segment failed", "Failed in first segment ", "Failed in second segment ", "Failed in segment --> ", "Reserved(8) ", "Reserved(9) ", "Reserved(10) ", "Reserved(11) ", "Reserved(12) ", "Reserved(13) ", "Reserved(14) ", "Self test in progress ..."};// See SCSI Primary Commands - 3 (SPC-3) rev 23 (draft) section 7.2.10 .// Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent// 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or// FAILSMART is returned.static int scsiPrintSelfTest(int device){ int num, k, n, res, err, durationSec; int noheader = 1; int retval = 0; UINT8 * ucp; uint64_t ull=0; if ((err = scsiLogSense(device, SELFTEST_RESULTS_LPAGE, 0, gBuf, LOG_RESP_SELF_TEST_LEN, 0))) { PRINT_ON(con); pout("scsiPrintSelfTest Failed [%s]\n", scsiErrString(err)); PRINT_OFF(con); return FAILSMART; } if ((gBuf[0] & 0x3f) != SELFTEST_RESULTS_LPAGE) { PRINT_ON(con); pout("Self-test Log Sense Failed, page mismatch\n"); PRINT_OFF(con); return FAILSMART; } // compute page length num = (gBuf[2] << 8) + gBuf[3]; // Log sense page length 0x190 bytes if (num != 0x190) { PRINT_ON(con); pout("Self-test Log Sense length is 0x%x not 0x190 bytes\n",num); PRINT_OFF(con); return FAILSMART; } // loop through the twenty possible entries for (k = 0, ucp = gBuf + 4; k < 20; ++k, ucp += 20 ) { int i; // timestamp in power-on hours (or zero if test in progress) n = (ucp[6] << 8) | ucp[7]; // The spec says "all 20 bytes will be zero if no test" but // DG has found otherwise. So this is a heuristic. if ((0 == n) && (0 == ucp[4]))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -