diff --git a/sm5/scsiprint.c b/sm5/scsiprint.c index a69e247c1e7f81e499aa2c51adc1427370bd2a9b..9f5aca7b076f95491f6045c3c0a8dcbee969e1e3 100644 --- a/sm5/scsiprint.c +++ b/sm5/scsiprint.c @@ -36,7 +36,7 @@ #define GBUF_SIZE 65535 -const char* CVSid4="$Id: scsiprint.c,v 1.14 2003/01/04 01:37:48 dpgilbert Exp $" +const char* CVSid4="$Id: scsiprint.c,v 1.15 2003/01/05 15:24:44 ballen4705 Exp $" CVSID3 CVSID4 CVSID5 CVSID6; // control block which points to external global control variables @@ -214,11 +214,13 @@ const char * self_test_result[] = { "Self test in progress ..." }; +// See Working Draft SCSI Primary Commands - 3 (SPC-3) pages 231-233 +// T10/1416-D Rev 10 void scsiPrintSelfTest(int device) { - int num, k, n, res; + int num, k, n, res, noheader=1; UINT8 * ucp; - unsigned long long ull; + unsigned long long ull=0; if (logsense(device, SELFTEST_RESULTS_PAGE, gBuf) != 0) { @@ -228,42 +230,100 @@ void scsiPrintSelfTest(int device) if (gBuf[0] != SELFTEST_RESULTS_PAGE) { printf("Self-test Log Sense Failed\n"); - exit(-1); + exit(1); } + + // compute page length num = (gBuf[2] << 8) + gBuf[3]; + + // how come not num != 0x190 log sense wrong length? if (num < 0x190) { printf("Self-test Log Sense too short\n"); - exit(-1); + exit(1); } - ucp = &gBuf[0] + 4; - printf(",\nSMART Self-test log\n"); - printf("Num Test Status segment " - "LifeTime LBA_first_err [SK ASC ASQ]\n"); - printf(" Description number " - "(hours)\n"); + + // start address of first self-test result + // not needed initialized later in for () statement + // ucp = &gBuf[0] + 4; + + // loop through the twenty possible entries for (k = 0, ucp = gBuf + 4; k < 20; ++k, ucp += 20 ) { - n = (ucp[6] << 8) | ucp[7]; - if ((0 == n) && (0 == ucp[4])) + int i; + + // timestamp in power-on hours (or zero if test in progress) + n = (ucp[6] << 8) | ucp[7]; + + // if no test was done, we are finished. Should we check + // that all 20 bytes are zero? + if ((0 == n) && (0 == ucp[4])) break; - printf("#%2d %s", (ucp[0] << 8) | ucp[1], - self_test_code[(ucp[4] >> 5) & 0x7]); - res = ucp[4] & 0xf; - printf(" %s", self_test_result[res]); - printf(" %3d", (int)ucp[5]); - printf(" %5d", n); - ull = ucp[8]; ull <<= 8; ull |= ucp[9]; ull <<= 8; ull |= ucp[10]; - ull <<= 8; ull |= ucp[11]; ull <<= 8; ull |= ucp[12]; - ull <<= 8; ull |= ucp[13]; ull <<= 8; ull |= ucp[14]; - ull <<= 8; ull |= ucp[14]; ull <<= 8; ull |= ucp[15]; - if ((0xffffffffffffffffULL != ull) && (res > 0) && ( res < 0xf)) - printf(" 0x%10llx", ull); - else - printf(" "); - if (ucp[16] & 0xf) - printf(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]); + + // only print header if needed + if (noheader){ + printf(",\nSMART Self-test log\n"); + printf("Num Test Status segment " + "LifeTime LBA_first_err [SK ASC ASQ]\n"); + printf(" Description number " + "(hours)\n"); + noheader=0; + } + + // are the 20-byte blocks stored in increasing order of + // parameter code? I think so.... this code assumes it. + + // print parameter code (test number) & self-test code text + printf("#%2d %s", (ucp[0] << 8) | ucp[1], + self_test_code[(ucp[4] >> 5) & 0x7]); + + // self-test result + res = ucp[4] & 0xf; + printf(" %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]) + printf(" %3d", (int)ucp[5]); + else + printf(" - "); + + // print time that the self-test was completed + if (n==0 && res==0xf) + // self-test in progress + printf(" NOW "); + else + printf(" %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 ((0xffffffffffffffffULL != ull) && (res > 0) && ( res < 0xf)) + printf(" 0x%10llx", ull); + else + printf(" - "); + + // if sense key nonzero, then print it, along with + // additional sense code and additional sense code qualifier + if (ucp[16] & 0xf) + printf(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]); + else + printf(" [- - -]\n"); + } + + // if header never printed, then there was no output + if (noheader) + printf("No self-tests have been logged\n\n"); else - printf("\n"); - } + printf("\n"); + + return; } void scsiGetDriveInfo ( int device) diff --git a/sm5/scsiprint.cpp b/sm5/scsiprint.cpp index 16576c958feeba7ec65b1556605f048c7bbdfedf..69b7ec3badc2c062a5949243cea74735dca30be4 100644 --- a/sm5/scsiprint.cpp +++ b/sm5/scsiprint.cpp @@ -36,7 +36,7 @@ #define GBUF_SIZE 65535 -const char* CVSid4="$Id: scsiprint.cpp,v 1.14 2003/01/04 01:37:48 dpgilbert Exp $" +const char* CVSid4="$Id: scsiprint.cpp,v 1.15 2003/01/05 15:24:44 ballen4705 Exp $" CVSID3 CVSID4 CVSID5 CVSID6; // control block which points to external global control variables @@ -214,11 +214,13 @@ const char * self_test_result[] = { "Self test in progress ..." }; +// See Working Draft SCSI Primary Commands - 3 (SPC-3) pages 231-233 +// T10/1416-D Rev 10 void scsiPrintSelfTest(int device) { - int num, k, n, res; + int num, k, n, res, noheader=1; UINT8 * ucp; - unsigned long long ull; + unsigned long long ull=0; if (logsense(device, SELFTEST_RESULTS_PAGE, gBuf) != 0) { @@ -228,42 +230,100 @@ void scsiPrintSelfTest(int device) if (gBuf[0] != SELFTEST_RESULTS_PAGE) { printf("Self-test Log Sense Failed\n"); - exit(-1); + exit(1); } + + // compute page length num = (gBuf[2] << 8) + gBuf[3]; + + // how come not num != 0x190 log sense wrong length? if (num < 0x190) { printf("Self-test Log Sense too short\n"); - exit(-1); + exit(1); } - ucp = &gBuf[0] + 4; - printf(",\nSMART Self-test log\n"); - printf("Num Test Status segment " - "LifeTime LBA_first_err [SK ASC ASQ]\n"); - printf(" Description number " - "(hours)\n"); + + // start address of first self-test result + // not needed initialized later in for () statement + // ucp = &gBuf[0] + 4; + + // loop through the twenty possible entries for (k = 0, ucp = gBuf + 4; k < 20; ++k, ucp += 20 ) { - n = (ucp[6] << 8) | ucp[7]; - if ((0 == n) && (0 == ucp[4])) + int i; + + // timestamp in power-on hours (or zero if test in progress) + n = (ucp[6] << 8) | ucp[7]; + + // if no test was done, we are finished. Should we check + // that all 20 bytes are zero? + if ((0 == n) && (0 == ucp[4])) break; - printf("#%2d %s", (ucp[0] << 8) | ucp[1], - self_test_code[(ucp[4] >> 5) & 0x7]); - res = ucp[4] & 0xf; - printf(" %s", self_test_result[res]); - printf(" %3d", (int)ucp[5]); - printf(" %5d", n); - ull = ucp[8]; ull <<= 8; ull |= ucp[9]; ull <<= 8; ull |= ucp[10]; - ull <<= 8; ull |= ucp[11]; ull <<= 8; ull |= ucp[12]; - ull <<= 8; ull |= ucp[13]; ull <<= 8; ull |= ucp[14]; - ull <<= 8; ull |= ucp[14]; ull <<= 8; ull |= ucp[15]; - if ((0xffffffffffffffffULL != ull) && (res > 0) && ( res < 0xf)) - printf(" 0x%10llx", ull); - else - printf(" "); - if (ucp[16] & 0xf) - printf(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]); + + // only print header if needed + if (noheader){ + printf(",\nSMART Self-test log\n"); + printf("Num Test Status segment " + "LifeTime LBA_first_err [SK ASC ASQ]\n"); + printf(" Description number " + "(hours)\n"); + noheader=0; + } + + // are the 20-byte blocks stored in increasing order of + // parameter code? I think so.... this code assumes it. + + // print parameter code (test number) & self-test code text + printf("#%2d %s", (ucp[0] << 8) | ucp[1], + self_test_code[(ucp[4] >> 5) & 0x7]); + + // self-test result + res = ucp[4] & 0xf; + printf(" %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]) + printf(" %3d", (int)ucp[5]); + else + printf(" - "); + + // print time that the self-test was completed + if (n==0 && res==0xf) + // self-test in progress + printf(" NOW "); + else + printf(" %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 ((0xffffffffffffffffULL != ull) && (res > 0) && ( res < 0xf)) + printf(" 0x%10llx", ull); + else + printf(" - "); + + // if sense key nonzero, then print it, along with + // additional sense code and additional sense code qualifier + if (ucp[16] & 0xf) + printf(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]); + else + printf(" [- - -]\n"); + } + + // if header never printed, then there was no output + if (noheader) + printf("No self-tests have been logged\n\n"); else - printf("\n"); - } + printf("\n"); + + return; } void scsiGetDriveInfo ( int device)