version 1.1, 2012/02/21 16:32:16
|
version 1.1.1.3, 2013/10/14 07:54:04
|
Line 7
|
Line 7
|
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> |
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> |
* |
* |
* Additional SCSI work: |
* Additional SCSI work: |
* Copyright (C) 2003-10 Douglas Gilbert <dgilbert@interlog.com> | * Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com> |
* |
* |
* This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* it under the terms of the GNU General Public License as published by |
Line 15
|
Line 15
|
* any later version. |
* any later version. |
* |
* |
* You should have received a copy of the GNU General Public License |
* You should have received a copy of the GNU General Public License |
* (for example COPYING); if not, write to the Free | * (for example COPYING); if not, write to the Free Software Foundation, |
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* |
* This code was originally developed as a Senior Thesis by Michael Cornwell |
* This code was originally developed as a Senior Thesis by Michael Cornwell |
* at the Concurrent Systems Laboratory (now part of the Storage Systems |
* at the Concurrent Systems Laboratory (now part of the Storage Systems |
Line 76 static int gIecMPage = 1; /* N.B. assume it until
|
Line 76 static int gIecMPage = 1; /* N.B. assume it until
|
/* Remember last successful mode sense/select command */ |
/* Remember last successful mode sense/select command */ |
static int modese_len = 0; |
static int modese_len = 0; |
|
|
static void scsiGetSupportedLogPages(scsi_device * device) | |
| static void |
| scsiGetSupportedLogPages(scsi_device * device) |
{ |
{ |
int i, err; |
int i, err; |
|
|
if ((err = scsiLogSense(device, SUPPORTED_LPAGES, 0, gBuf, |
if ((err = scsiLogSense(device, SUPPORTED_LPAGES, 0, gBuf, |
LOG_RESP_LEN, 0))) { |
LOG_RESP_LEN, 0))) { |
if (scsi_debugmode > 0) |
if (scsi_debugmode > 0) |
pout("Log Sense for supported pages failed [%s]\n", | pout("Log Sense for supported pages failed [%s]\n", |
scsiErrString(err)); | scsiErrString(err)); |
return; |
return; |
} | } |
|
|
for (i = 4; i < gBuf[3] + LOGPAGEHDRSIZE; i++) { |
for (i = 4; i < gBuf[3] + LOGPAGEHDRSIZE; i++) { |
switch (gBuf[i]) |
switch (gBuf[i]) |
Line 144 static void scsiGetSupportedLogPages(scsi_device * dev
|
Line 146 static void scsiGetSupportedLogPages(scsi_device * dev
|
|
|
/* Returns 0 if ok, -1 if can't check IE, -2 if can check and bad |
/* Returns 0 if ok, -1 if can't check IE, -2 if can check and bad |
(or at least something to report). */ |
(or at least something to report). */ |
static int scsiGetSmartData(scsi_device * device, bool attribs) | static int |
| scsiGetSmartData(scsi_device * device, bool attribs) |
{ |
{ |
UINT8 asc; |
UINT8 asc; |
UINT8 ascq; |
UINT8 ascq; |
Line 152 static int scsiGetSmartData(scsi_device * device, bool
|
Line 155 static int scsiGetSmartData(scsi_device * device, bool
|
UINT8 triptemp = 0; |
UINT8 triptemp = 0; |
const char * cp; |
const char * cp; |
int err = 0; |
int err = 0; |
|
|
print_on(); |
print_on(); |
if (scsiCheckIE(device, gSmartLPage, gTempLPage, &asc, &ascq, |
if (scsiCheckIE(device, gSmartLPage, gTempLPage, &asc, &ascq, |
¤ttemp, &triptemp)) { |
¤ttemp, &triptemp)) { |
Line 165 static int scsiGetSmartData(scsi_device * device, bool
|
Line 167 static int scsiGetSmartData(scsi_device * device, bool
|
if (cp) { |
if (cp) { |
err = -2; |
err = -2; |
print_on(); |
print_on(); |
pout("SMART Health Status: %s [asc=%x, ascq=%x]\n", cp, asc, ascq); | pout("SMART Health Status: %s [asc=%x, ascq=%x]\n", cp, asc, ascq); |
print_off(); |
print_off(); |
} else if (gIecMPage) |
} else if (gIecMPage) |
pout("SMART Health Status: OK\n"); |
pout("SMART Health Status: OK\n"); |
|
|
if (attribs && !gTempLPage) { |
if (attribs && !gTempLPage) { |
if (currenttemp || triptemp) |
|
pout("\n"); |
|
if (currenttemp) { |
if (currenttemp) { |
if (255 != currenttemp) |
if (255 != currenttemp) |
pout("Current Drive Temperature: %d C\n", currenttemp); |
pout("Current Drive Temperature: %d C\n", currenttemp); |
Line 182 static int scsiGetSmartData(scsi_device * device, bool
|
Line 182 static int scsiGetSmartData(scsi_device * device, bool
|
if (triptemp) |
if (triptemp) |
pout("Drive Trip Temperature: %d C\n", triptemp); |
pout("Drive Trip Temperature: %d C\n", triptemp); |
} |
} |
|
pout("\n"); |
return err; |
return err; |
} |
} |
|
|
Line 190 static int scsiGetSmartData(scsi_device * device, bool
|
Line 191 static int scsiGetSmartData(scsi_device * device, bool
|
// TapeAlerts fails |
// TapeAlerts fails |
static const char * const severities = "CWI"; |
static const char * const severities = "CWI"; |
|
|
static int scsiGetTapeAlertsData(scsi_device * device, int peripheral_type) | static int |
| scsiGetTapeAlertsData(scsi_device * device, int peripheral_type) |
{ |
{ |
unsigned short pagelength; |
unsigned short pagelength; |
unsigned short parametercode; |
unsigned short parametercode; |
Line 223 static int scsiGetTapeAlertsData(scsi_device * device,
|
Line 225 static int scsiGetTapeAlertsData(scsi_device * device,
|
scsiTapeAlertsTapeDevice(parametercode); |
scsiTapeAlertsTapeDevice(parametercode); |
if (*ts == *s) { |
if (*ts == *s) { |
if (!failures) |
if (!failures) |
pout("TapeAlert Errors (C=Critical, W=Warning, I=Informational):\n"); | pout("TapeAlert Errors (C=Critical, W=Warning, " |
| "I=Informational):\n"); |
pout("[0x%02x] %s\n", parametercode, ts); |
pout("[0x%02x] %s\n", parametercode, ts); |
failures += 1; | failures += 1; |
} |
} |
} |
} |
} |
} |
Line 238 static int scsiGetTapeAlertsData(scsi_device * device,
|
Line 241 static int scsiGetTapeAlertsData(scsi_device * device,
|
return failures; |
return failures; |
} |
} |
|
|
static void scsiGetStartStopData(scsi_device * device) | static void |
| scsiGetStartStopData(scsi_device * device) |
{ |
{ |
UINT32 u; |
UINT32 u; |
int err, len, k, extra, pc; |
int err, len, k, extra, pc; |
Line 312 static void scsiGetStartStopData(scsi_device * device)
|
Line 316 static void scsiGetStartStopData(scsi_device * device)
|
break; |
break; |
} |
} |
} |
} |
} | } |
|
|
static void scsiPrintGrownDefectListLen(scsi_device * device) | static void |
| scsiPrintGrownDefectListLen(scsi_device * device) |
{ |
{ |
int err, dl_format, dl_len, div; | int err, dl_format, got_rd12, generation; |
| unsigned int dl_len, div; |
|
|
memset(gBuf, 0, 4); | memset(gBuf, 0, 8); |
if ((err = scsiReadDefect10(device, 0 /* req_plist */, 1 /* req_glist */, | if ((err = scsiReadDefect12(device, 0 /* req_plist */, 1 /* req_glist */, |
4 /* bytes from index */, gBuf, 4))) { | 4 /* format: bytes from index */, |
if (scsi_debugmode > 0) { | 0 /* addr desc index */, gBuf, 8))) { |
| if (2 == err) { /* command not supported */ |
| if ((err = scsiReadDefect10(device, 0 /* req_plist */, 1 /* req_glist */, |
| 4 /* format: bytes from index */, gBuf, 4))) { |
| if (scsi_debugmode > 0) { |
| print_on(); |
| pout("Read defect list (10) Failed: %s\n", scsiErrString(err)); |
| print_off(); |
| } |
| return; |
| } else |
| got_rd12 = 0; |
| } else { |
| if (scsi_debugmode > 0) { |
| print_on(); |
| pout("Read defect list (12) Failed: %s\n", scsiErrString(err)); |
| print_off(); |
| } |
| return; |
| } |
| } else |
| got_rd12 = 1; |
| |
| if (got_rd12) { |
| generation = (gBuf[2] << 8) + gBuf[3]; |
| if ((generation > 1) && (scsi_debugmode > 0)) { |
print_on(); |
print_on(); |
pout("Read defect list (10) Failed: %s\n", scsiErrString(err)); | pout("Read defect list (12): generation=%d\n", generation); |
print_off(); |
print_off(); |
} |
} |
return; | dl_len = (gBuf[4] << 24) + (gBuf[5] << 16) + (gBuf[6] << 8) + gBuf[7]; |
| } else { |
| dl_len = (gBuf[2] << 8) + gBuf[3]; |
} |
} |
if (0x8 != (gBuf[1] & 0x18)) { |
if (0x8 != (gBuf[1] & 0x18)) { |
print_on(); |
print_on(); |
Line 340 static void scsiPrintGrownDefectListLen(scsi_device *
|
Line 373 static void scsiPrintGrownDefectListLen(scsi_device *
|
case 0: /* short block */ |
case 0: /* short block */ |
div = 4; |
div = 4; |
break; |
break; |
|
case 1: /* extended bytes from index */ |
|
case 2: /* extended physical sector */ |
|
/* extended = 1; # might use in future */ |
|
div = 8; |
|
break; |
case 3: /* long block */ |
case 3: /* long block */ |
case 4: /* bytes from index */ |
case 4: /* bytes from index */ |
case 5: /* physical sector */ |
case 5: /* physical sector */ |
Line 351 static void scsiPrintGrownDefectListLen(scsi_device *
|
Line 389 static void scsiPrintGrownDefectListLen(scsi_device *
|
print_off(); |
print_off(); |
break; |
break; |
} |
} |
dl_len = (gBuf[2] << 8) + gBuf[3]; |
|
if (0 == dl_len) |
if (0 == dl_len) |
pout("Elements in grown defect list: 0\n"); | pout("Elements in grown defect list: 0\n\n"); |
else { |
else { |
if (0 == div) |
if (0 == div) |
pout("Grown defect list length=%d bytes [unknown " | pout("Grown defect list length=%u bytes [unknown " |
"number of elements]\n", dl_len); | "number of elements]\n\n", dl_len); |
else |
else |
pout("Elements in grown defect list: %d\n", dl_len / div); | pout("Elements in grown defect list: %u\n\n", dl_len / div); |
} |
} |
} |
} |
|
|
static void scsiPrintSeagateCacheLPage(scsi_device * device) | static void |
| scsiPrintSeagateCacheLPage(scsi_device * device) |
{ |
{ |
int k, j, num, pl, pc, err, len; |
int k, j, num, pl, pc, err, len; |
unsigned char * ucp; |
unsigned char * ucp; |
Line 392 static void scsiPrintSeagateCacheLPage(scsi_device * d
|
Line 430 static void scsiPrintSeagateCacheLPage(scsi_device * d
|
switch (pc) { |
switch (pc) { |
case 0: case 1: case 2: case 3: case 4: |
case 0: case 1: case 2: case 3: case 4: |
break; |
break; |
default: | default: |
if (scsi_debugmode > 0) { |
if (scsi_debugmode > 0) { |
print_on(); |
print_on(); |
pout("Vendor (Seagate) cache lpage has unexpected parameter" |
pout("Vendor (Seagate) cache lpage has unexpected parameter" |
Line 436 static void scsiPrintSeagateCacheLPage(scsi_device * d
|
Line 474 static void scsiPrintSeagateCacheLPage(scsi_device * d
|
num -= pl; |
num -= pl; |
ucp += pl; |
ucp += pl; |
} |
} |
|
pout("\n"); |
} |
} |
|
|
static void scsiPrintSeagateFactoryLPage(scsi_device * device) | static void |
| scsiPrintSeagateFactoryLPage(scsi_device * device) |
{ |
{ |
int k, j, num, pl, pc, len, err, good, bad; |
int k, j, num, pl, pc, len, err, good, bad; |
unsigned char * ucp; |
unsigned char * ucp; |
Line 470 static void scsiPrintSeagateFactoryLPage(scsi_device *
|
Line 510 static void scsiPrintSeagateFactoryLPage(scsi_device *
|
case 0: case 8: |
case 0: case 8: |
++good; |
++good; |
break; |
break; |
default: | default: |
++bad; |
++bad; |
break; |
break; |
} |
} |
Line 530 static void scsiPrintSeagateFactoryLPage(scsi_device *
|
Line 570 static void scsiPrintSeagateFactoryLPage(scsi_device *
|
num -= pl; |
num -= pl; |
ucp += pl; |
ucp += pl; |
} |
} |
|
pout("\n"); |
} |
} |
|
|
static void scsiPrintErrorCounterLog(scsi_device * device) | static void |
| scsiPrintErrorCounterLog(scsi_device * device) |
{ |
{ |
struct scsiErrorCounter errCounterArr[3]; |
struct scsiErrorCounter errCounterArr[3]; |
struct scsiErrorCounter * ecp; |
struct scsiErrorCounter * ecp; |
Line 563 static void scsiPrintErrorCounterLog(scsi_device * dev
|
Line 605 static void scsiPrintErrorCounterLog(scsi_device * dev
|
} |
} |
} |
} |
if (found[0] || found[1] || found[2]) { |
if (found[0] || found[1] || found[2]) { |
pout("\nError counter log:\n"); | pout("Error counter log:\n"); |
pout(" Errors Corrected by Total " |
pout(" Errors Corrected by Total " |
"Correction Gigabytes Total\n"); |
"Correction Gigabytes Total\n"); |
pout(" ECC rereads/ errors " |
pout(" ECC rereads/ errors " |
Line 574 static void scsiPrintErrorCounterLog(scsi_device * dev
|
Line 616 static void scsiPrintErrorCounterLog(scsi_device * dev
|
if (! found[k]) |
if (! found[k]) |
continue; |
continue; |
ecp = &errCounterArr[k]; |
ecp = &errCounterArr[k]; |
pout("%s%8"PRIu64" %8"PRIu64" %8"PRIu64" %8"PRIu64" %8"PRIu64, | pout("%s%8"PRIu64" %8"PRIu64" %8"PRIu64" %8"PRIu64" %8"PRIu64, |
pageNames[k], ecp->counter[0], ecp->counter[1], | pageNames[k], ecp->counter[0], ecp->counter[1], |
ecp->counter[2], ecp->counter[3], ecp->counter[4]); |
ecp->counter[2], ecp->counter[3], ecp->counter[4]); |
processed_gb = ecp->counter[5] / 1000000000.0; |
processed_gb = ecp->counter[5] / 1000000000.0; |
pout(" %12.3f %8"PRIu64"\n", processed_gb, ecp->counter[6]); |
pout(" %12.3f %8"PRIu64"\n", processed_gb, ecp->counter[6]); |
} |
} |
} |
} |
else | else |
pout("\nError Counter logging not supported\n"); | pout("Error Counter logging not supported\n"); |
if (gNonMediumELPage && (0 == scsiLogSense(device, |
if (gNonMediumELPage && (0 == scsiLogSense(device, |
NON_MEDIUM_ERROR_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) { |
NON_MEDIUM_ERROR_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) { |
scsiDecodeNonMediumErrPage(gBuf, &nme); |
scsiDecodeNonMediumErrPage(gBuf, &nme); |
Line 636 static void scsiPrintErrorCounterLog(scsi_device * dev
|
Line 678 static void scsiPrintErrorCounterLog(scsi_device * dev
|
"bytes\n", LOG_RESP_LONG_LEN, truncated); |
"bytes\n", LOG_RESP_LONG_LEN, truncated); |
} |
} |
} |
} |
|
pout("\n"); |
} |
} |
|
|
static const char * self_test_code[] = { |
static const char * self_test_code[] = { |
"Default ", | "Default ", |
"Background short", | "Background short", |
"Background long ", | "Background long ", |
"Reserved(3) ", |
"Reserved(3) ", |
"Abort background", | "Abort background", |
"Foreground short", | "Foreground short", |
"Foreground long ", |
"Foreground long ", |
"Reserved(7) " |
"Reserved(7) " |
}; |
}; |
Line 658 static const char * self_test_result[] = {
|
Line 701 static const char * self_test_result[] = {
|
"Failed in first segment ", |
"Failed in first segment ", |
"Failed in second segment ", |
"Failed in second segment ", |
"Failed in segment --> ", |
"Failed in segment --> ", |
"Reserved(8) ", | "Reserved(8) ", |
"Reserved(9) ", | "Reserved(9) ", |
"Reserved(10) ", | "Reserved(10) ", |
"Reserved(11) ", | "Reserved(11) ", |
"Reserved(12) ", | "Reserved(12) ", |
"Reserved(13) ", | "Reserved(13) ", |
"Reserved(14) ", |
"Reserved(14) ", |
"Self test in progress ..." |
"Self test in progress ..." |
}; |
}; |
Line 672 static const char * self_test_result[] = {
|
Line 715 static const char * self_test_result[] = {
|
// Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent |
// 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 |
// 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or |
// FAILSMART is returned. |
// FAILSMART is returned. |
static int scsiPrintSelfTest(scsi_device * device) | static int |
| scsiPrintSelfTest(scsi_device * device) |
{ |
{ |
int num, k, n, res, err, durationSec; |
int num, k, n, res, err, durationSec; |
int noheader = 1; |
int noheader = 1; |
int retval = 0; |
int retval = 0; |
UINT8 * ucp; |
UINT8 * ucp; |
uint64_t ull=0; |
uint64_t ull=0; |
|
struct scsi_sense_disect sense_info; |
|
|
|
// check if test is running |
|
if (!scsiRequestSense(device, &sense_info) && |
|
(sense_info.asc == 0x04 && sense_info.ascq == 0x09 && |
|
sense_info.progress != -1)) { |
|
pout("Self-test execution status:\t\t%d%% of test remaining\n", |
|
100 - ((sense_info.progress * 100) / 65535)); |
|
} |
|
|
if ((err = scsiLogSense(device, SELFTEST_RESULTS_LPAGE, 0, gBuf, |
if ((err = scsiLogSense(device, SELFTEST_RESULTS_LPAGE, 0, gBuf, |
LOG_RESP_SELF_TEST_LEN, 0))) { |
LOG_RESP_SELF_TEST_LEN, 0))) { |
print_on(); |
print_on(); |
Line 716 static int scsiPrintSelfTest(scsi_device * device)
|
Line 769 static int scsiPrintSelfTest(scsi_device * device)
|
|
|
// only print header if needed |
// only print header if needed |
if (noheader) { |
if (noheader) { |
pout("\nSMART Self-test log\n"); | pout("SMART Self-test log\n"); |
pout("Num Test Status segment " |
pout("Num Test Status segment " |
"LifeTime LBA_first_err [SK ASC ASQ]\n"); |
"LifeTime LBA_first_err [SK ASC ASQ]\n"); |
pout(" Description number " |
pout(" Description number " |
Line 725 static int scsiPrintSelfTest(scsi_device * device)
|
Line 778 static int scsiPrintSelfTest(scsi_device * device)
|
} |
} |
|
|
// print parameter code (test number) & self-test code text |
// print parameter code (test number) & self-test code text |
pout("#%2d %s", (ucp[0] << 8) | ucp[1], | pout("#%2d %s", (ucp[0] << 8) | ucp[1], |
self_test_code[(ucp[4] >> 5) & 0x7]); |
self_test_code[(ucp[4] >> 5) & 0x7]); |
|
|
// check the self-test result nibble, using the self-test results |
// check the self-test result nibble, using the self-test results |
Line 777 static int scsiPrintSelfTest(scsi_device * device)
|
Line 830 static int scsiPrintSelfTest(scsi_device * device)
|
if (n==0 && res==0xf) |
if (n==0 && res==0xf) |
// self-test in progress |
// self-test in progress |
pout(" NOW"); |
pout(" NOW"); |
else | else |
pout(" %5d", n); |
pout(" %5d", n); |
| |
// construct 8-byte integer address of first failure |
// construct 8-byte integer address of first failure |
for (i = 0; i < 8; i++) { |
for (i = 0; i < 8; i++) { |
ull <<= 8; |
ull <<= 8; |
Line 808 static int scsiPrintSelfTest(scsi_device * device)
|
Line 861 static int scsiPrintSelfTest(scsi_device * device)
|
if (noheader) |
if (noheader) |
pout("No self-tests have been logged\n"); |
pout("No self-tests have been logged\n"); |
else |
else |
pout("\n"); |
|
if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec, |
if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec, |
modese_len)) && (durationSec > 0)) { |
modese_len)) && (durationSec > 0)) { |
pout("Long (extended) Self Test duration: %d seconds " |
pout("Long (extended) Self Test duration: %d seconds " |
"[%.1f minutes]\n", durationSec, durationSec / 60.0); |
"[%.1f minutes]\n", durationSec, durationSec / 60.0); |
} |
} |
|
pout("\n"); |
return retval; |
return retval; |
} |
} |
|
|
Line 845 static const char * reassign_status[] = {
|
Line 898 static const char * reassign_status[] = {
|
// Returns 0 if ok else FAIL* bitmask. Note can have a status entry |
// 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 |
// and up to 2048 events (although would hope to have less). May set |
// FAILLOG if serious errors detected (in the future). |
// FAILLOG if serious errors detected (in the future). |
static int scsiPrintBackgroundResults(scsi_device * device) | static int |
| scsiPrintBackgroundResults(scsi_device * device) |
{ |
{ |
int num, j, m, err, pc, pl, truncated; |
int num, j, m, err, pc, pl, truncated; |
int noheader = 1; |
int noheader = 1; |
Line 888 static int scsiPrintBackgroundResults(scsi_device * de
|
Line 942 static int scsiPrintBackgroundResults(scsi_device * de
|
case 0: |
case 0: |
if (noheader) { |
if (noheader) { |
noheader = 0; |
noheader = 0; |
pout("\nBackground scan results log\n"); | pout("Background scan results log\n"); |
} |
} |
pout(" Status: "); |
pout(" Status: "); |
if ((pl < 16) || (num < 16)) { |
if ((pl < 16) || (num < 16)) { |
Line 945 static int scsiPrintBackgroundResults(scsi_device * de
|
Line 999 static int scsiPrintBackgroundResults(scsi_device * de
|
if (truncated) |
if (truncated) |
pout(" >>>> log truncated, fetched %d of %d available " |
pout(" >>>> log truncated, fetched %d of %d available " |
"bytes\n", LOG_RESP_LONG_LEN, truncated); |
"bytes\n", LOG_RESP_LONG_LEN, truncated); |
|
pout("\n"); |
return retval; |
return retval; |
} |
} |
|
|
Line 952 static int scsiPrintBackgroundResults(scsi_device * de
|
Line 1007 static int scsiPrintBackgroundResults(scsi_device * de
|
// Returns 0 if ok else FAIL* bitmask. Note can have a status entry |
// 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 |
// and up to 2048 events (although would hope to have less). May set |
// FAILLOG if serious errors detected (in the future). |
// FAILLOG if serious errors detected (in the future). |
static int scsiPrintSSMedia(scsi_device * device) | static int |
| scsiPrintSSMedia(scsi_device * device) |
{ |
{ |
int num, err, pc, pl, truncated; |
int num, err, pc, pl, truncated; |
int retval = 0; |
int retval = 0; |
Line 990 static int scsiPrintSSMedia(scsi_device * device)
|
Line 1046 static int scsiPrintSSMedia(scsi_device * device)
|
pl = ucp[3] + 4; |
pl = ucp[3] + 4; |
switch (pc) { |
switch (pc) { |
case 1: |
case 1: |
if (pl < 8) { | if (pl < 8) { |
print_on(); |
print_on(); |
pout("Percentage used endurance indicator too short (pl=%d)\n", pl); |
pout("Percentage used endurance indicator too short (pl=%d)\n", pl); |
print_off(); |
print_off(); |
return FAILSMART; |
return FAILSMART; |
} | } |
pout("SS Media used endurance indicator: %d%%\n", ucp[7]); |
pout("SS Media used endurance indicator: %d%%\n", ucp[7]); |
default: /* ignore other parameter codes */ | default: /* ignore other parameter codes */ |
break; |
break; |
} |
} |
num -= pl; |
num -= pl; |
Line 1006 static int scsiPrintSSMedia(scsi_device * device)
|
Line 1062 static int scsiPrintSSMedia(scsi_device * device)
|
return retval; |
return retval; |
} |
} |
|
|
static void show_sas_phy_event_info(int peis, unsigned int val, | static void |
unsigned thresh_val) | show_sas_phy_event_info(int peis, unsigned int val, unsigned thresh_val) |
{ |
{ |
unsigned int u; |
unsigned int u; |
|
|
Line 1137 static void show_sas_phy_event_info(int peis, unsigned
|
Line 1193 static void show_sas_phy_event_info(int peis, unsigned
|
} |
} |
} |
} |
|
|
static void show_sas_port_param(unsigned char * ucp, int param_len) | static void |
| show_sas_port_param(unsigned char * ucp, int param_len) |
{ |
{ |
int j, m, n, nphys, t, sz, spld_len; |
int j, m, n, nphys, t, sz, spld_len; |
unsigned char * vcp; |
unsigned char * vcp; |
Line 1268 static void show_sas_port_param(unsigned char * ucp, i
|
Line 1325 static void show_sas_port_param(unsigned char * ucp, i
|
} |
} |
|
|
// Returns 1 if okay, 0 if non SAS descriptors |
// Returns 1 if okay, 0 if non SAS descriptors |
static int show_protocol_specific_page(unsigned char * resp, int len) | static int |
| show_protocol_specific_page(unsigned char * resp, int len) |
{ |
{ |
int k, num, param_len; |
int k, num, param_len; |
unsigned char * ucp; |
unsigned char * ucp; |
Line 1284 static int show_protocol_specific_page(unsigned char *
|
Line 1342 static int show_protocol_specific_page(unsigned char *
|
k += param_len; |
k += param_len; |
ucp += param_len; |
ucp += param_len; |
} |
} |
|
pout("\n"); |
return 1; |
return 1; |
} |
} |
|
|
Line 1294 static int show_protocol_specific_page(unsigned char *
|
Line 1353 static int show_protocol_specific_page(unsigned char *
|
// Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent |
// 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 |
// 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or |
// FAILSMART is returned. |
// FAILSMART is returned. |
static int scsiPrintSasPhy(scsi_device * device, int reset) | static int |
| scsiPrintSasPhy(scsi_device * device, int reset) |
{ |
{ |
int num, err; |
int num, err; |
|
|
if ((err = scsiLogSense(device, PROTOCOL_SPECIFIC_LPAGE, 0, gBuf, |
if ((err = scsiLogSense(device, PROTOCOL_SPECIFIC_LPAGE, 0, gBuf, |
LOG_RESP_LONG_LEN, 0))) { |
LOG_RESP_LONG_LEN, 0))) { |
print_on(); |
print_on(); |
pout("scsiPrintSasPhy Log Sense Failed [%s]\n", scsiErrString(err)); | pout("scsiPrintSasPhy Log Sense Failed [%s]\n\n", scsiErrString(err)); |
print_off(); |
print_off(); |
return FAILSMART; |
return FAILSMART; |
} |
} |
if ((gBuf[0] & 0x3f) != PROTOCOL_SPECIFIC_LPAGE) { |
if ((gBuf[0] & 0x3f) != PROTOCOL_SPECIFIC_LPAGE) { |
print_on(); |
print_on(); |
pout("Protocol specific Log Sense Failed, page mismatch\n"); | pout("Protocol specific Log Sense Failed, page mismatch\n\n"); |
print_off(); |
print_off(); |
return FAILSMART; |
return FAILSMART; |
} |
} |
Line 1315 static int scsiPrintSasPhy(scsi_device * device, int r
|
Line 1375 static int scsiPrintSasPhy(scsi_device * device, int r
|
num = (gBuf[2] << 8) + gBuf[3]; |
num = (gBuf[2] << 8) + gBuf[3]; |
if (1 != show_protocol_specific_page(gBuf, num + 4)) { |
if (1 != show_protocol_specific_page(gBuf, num + 4)) { |
print_on(); |
print_on(); |
pout("Only support protocol specific log page on SAS devices\n"); | pout("Only support protocol specific log page on SAS devices\n\n"); |
print_off(); |
print_off(); |
return FAILSMART; |
return FAILSMART; |
} |
} |
Line 1323 static int scsiPrintSasPhy(scsi_device * device, int r
|
Line 1383 static int scsiPrintSasPhy(scsi_device * device, int r
|
if ((err = scsiLogSelect(device, 1 /* pcr */, 0 /* sp */, 0 /* pc */, |
if ((err = scsiLogSelect(device, 1 /* pcr */, 0 /* sp */, 0 /* pc */, |
PROTOCOL_SPECIFIC_LPAGE, 0, NULL, 0))) { |
PROTOCOL_SPECIFIC_LPAGE, 0, NULL, 0))) { |
print_on(); |
print_on(); |
pout("scsiPrintSasPhy Log Select (reset) Failed [%s]\n", | pout("scsiPrintSasPhy Log Select (reset) Failed [%s]\n\n", |
scsiErrString(err)); |
scsiErrString(err)); |
print_off(); |
print_off(); |
return FAILSMART; |
return FAILSMART; |
Line 1372 static const char * transport_proto_arr[] = {
|
Line 1432 static const char * transport_proto_arr[] = {
|
}; |
}; |
|
|
/* Returns 0 on success, 1 on general error and 2 for early, clean exit */ |
/* Returns 0 on success, 1 on general error and 2 for early, clean exit */ |
static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all) | static int |
| scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all) |
{ |
{ |
char timedatetz[DATEANDEPOCHLEN]; |
char timedatetz[DATEANDEPOCHLEN]; |
struct scsi_iec_mode_page iec; |
struct scsi_iec_mode_page iec; |
int err, iec_err, len, req_len, avail_len; | int err, iec_err, len, req_len, avail_len, n; |
int is_tape = 0; |
int is_tape = 0; |
int peri_dt = 0; |
int peri_dt = 0; |
int returnval = 0; |
int returnval = 0; |
int transport = -1; |
int transport = -1; |
| int form_factor = 0; |
| int protect = 0; |
| |
memset(gBuf, 0, 96); |
memset(gBuf, 0, 96); |
req_len = 36; |
req_len = 36; |
if ((err = scsiStdInquiry(device, gBuf, req_len))) { |
if ((err = scsiStdInquiry(device, gBuf, req_len))) { |
Line 1411 static int scsiGetDriveInfo(scsi_device * device, UINT
|
Line 1474 static int scsiGetDriveInfo(scsi_device * device, UINT
|
print_off(); |
print_off(); |
return 1; |
return 1; |
} |
} |
|
|
if (all && (0 != strncmp((char *)&gBuf[8], "ATA", 3))) { |
if (all && (0 != strncmp((char *)&gBuf[8], "ATA", 3))) { |
pout("Vendor: %.8s\n", (char *)&gBuf[8]); | char vendor[8+1], product[16+1], revision[4+1]; |
pout("Product: %.16s\n", (char *)&gBuf[16]); | scsi_format_id_string(vendor, (const unsigned char *)&gBuf[8], 8); |
if (gBuf[32] >= ' ') | scsi_format_id_string(product, (const unsigned char *)&gBuf[16], 16); |
pout("Revision: %.4s\n", (char *)&gBuf[32]); | scsi_format_id_string(revision, (const unsigned char *)&gBuf[32], 4); |
| |
| pout("=== START OF INFORMATION SECTION ===\n"); |
| pout("Vendor: %.8s\n", vendor); |
| pout("Product: %.16s\n", product); |
| if (gBuf[32] >= ' ') |
| pout("Revision: %.4s\n", revision); |
} |
} |
|
|
if (!*device->get_req_type()/*no type requested*/ && |
if (!*device->get_req_type()/*no type requested*/ && |
Line 1427 static int scsiGetDriveInfo(scsi_device * device, UINT
|
Line 1497 static int scsiGetDriveInfo(scsi_device * device, UINT
|
if (! all) |
if (! all) |
return 0; |
return 0; |
|
|
unsigned int lb_size; | protect = gBuf[5] & 0x1; /* from and including SPC-3 */ |
char cap_str[64]; | |
char si_str[64]; | |
char lb_str[16]; | |
uint64_t capacity = scsiGetSize(device, &lb_size); | |
|
|
if (capacity) { | if (! is_tape) { /* only do this for disks */ |
format_with_thousands_sep(cap_str, sizeof(cap_str), capacity); | unsigned int lb_size = 0; |
format_capacity(si_str, sizeof(si_str), capacity); | unsigned char lb_prov_resp[8]; |
pout("User Capacity: %s bytes [%s]\n", cap_str, si_str); | char cap_str[64]; |
snprintf(lb_str, sizeof(lb_str) - 1, "%u", lb_size); | char si_str[64]; |
pout("Logical block size: %s bytes\n", lb_str); | char lb_str[16]; |
| int lb_per_pb_exp = 0; |
| uint64_t capacity = scsiGetSize(device, &lb_size, &lb_per_pb_exp); |
| |
| if (capacity) { |
| format_with_thousands_sep(cap_str, sizeof(cap_str), capacity); |
| format_capacity(si_str, sizeof(si_str), capacity); |
| pout("User Capacity: %s bytes [%s]\n", cap_str, si_str); |
| snprintf(lb_str, sizeof(lb_str) - 1, "%u", lb_size); |
| pout("Logical block size: %s bytes\n", lb_str); |
| } |
| int lbpme = -1; |
| int lbprz = -1; |
| if (protect || lb_per_pb_exp) { |
| unsigned char rc16_12[20] = {0, }; |
| |
| if (0 == scsiGetProtPBInfo(device, rc16_12)) { |
| lb_per_pb_exp = rc16_12[1] & 0xf; /* just in case */ |
| if (lb_per_pb_exp > 0) { |
| snprintf(lb_str, sizeof(lb_str) - 1, "%u", |
| (lb_size * (1 << lb_per_pb_exp))); |
| pout("Physical block size: %s bytes\n", lb_str); |
| n = ((rc16_12[2] & 0x3f) << 8) + rc16_12[3]; |
| pout("Lowest aligned LBA: %d\n", n); |
| } |
| if (rc16_12[0] & 0x1) { /* PROT_EN set */ |
| int p_type = ((rc16_12[0] >> 1) & 0x7); |
| |
| switch (p_type) { |
| case 0 : |
| pout("Formatted with type 1 protection\n"); |
| break; |
| case 1 : |
| pout("Formatted with type 2 protection\n"); |
| break; |
| case 2 : |
| pout("Formatted with type 3 protection\n"); |
| break; |
| default: |
| pout("Formatted with unknown protection type [%d]\n", |
| p_type); |
| break; |
| } |
| int p_i_exp = ((rc16_12[1] >> 4) & 0xf); |
| |
| if (p_i_exp > 0) |
| pout("%d protection information intervals per " |
| "logical block\n", (1 << p_i_exp)); |
| } |
| /* Pick up some LB provisioning info since its available */ |
| lbpme = !! (rc16_12[2] & 0x80); |
| lbprz = !! (rc16_12[2] & 0x40); |
| } |
| } |
| if (0 == scsiInquiryVpd(device, SCSI_VPD_LOGICAL_BLOCK_PROVISIONING, |
| lb_prov_resp, sizeof(lb_prov_resp))) { |
| int prov_type = lb_prov_resp[6] & 0x7; |
| |
| if (-1 == lbprz) |
| lbprz = !! (lb_prov_resp[5] & 0x4); |
| switch (prov_type) { |
| case 0: |
| pout("Logical block provisioning type unreported, " |
| "LBPME=%d, LBPRZ=%d\n", lbpme, lbprz); |
| break; |
| case 1: |
| pout("LU is resource provisioned, LBPRZ=%d\n", lbprz); |
| break; |
| case 2: |
| pout("LU is thin provisioned, LBPRZ=%d\n", lbprz); |
| break; |
| default: |
| pout("LU provisioning type reserved [%d], LBPRZ=%d\n", |
| prov_type, lbprz); |
| break; |
| } |
| } else if (1 == lbpme) |
| pout("Logical block provisioning enabled, LBPRZ=%d\n", lbprz); |
| |
| int rpm = scsiGetRPM(device, modese_len, &form_factor); |
| if (rpm > 0) { |
| if (1 == rpm) |
| pout("Rotation Rate: Solid State Device\n"); |
| else |
| pout("Rotation Rate: %d rpm\n", rpm); |
| } |
| if (form_factor > 0) { |
| const char * cp = NULL; |
| |
| switch (form_factor) { |
| case 1: |
| cp = "5.25"; |
| break; |
| case 2: |
| cp = "3.5"; |
| break; |
| case 3: |
| cp = "2.5"; |
| break; |
| case 4: |
| cp = "1.8"; |
| break; |
| case 5: |
| cp = "< 1.8"; |
| break; |
| } |
| if (cp) |
| pout("Form Factor: %s inches\n", cp); |
| } |
} |
} |
|
|
/* Do this here to try and detect badly conforming devices (some USB |
/* Do this here to try and detect badly conforming devices (some USB |
Line 1455 static int scsiGetDriveInfo(scsi_device * device, UINT
|
Line 1629 static int scsiGetDriveInfo(scsi_device * device, UINT
|
modese_len = iec.modese_len; |
modese_len = iec.modese_len; |
|
|
if (! dont_print_serial_number) { |
if (! dont_print_serial_number) { |
if (0 == (err = scsiInquiryVpd(device, 0x83, gBuf, 200))) { | if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_DEVICE_IDENTIFICATION, |
char s[256]; | gBuf, 252))) { |
| char s[256]; |
|
|
len = gBuf[3]; |
len = gBuf[3]; |
scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport); | scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport); |
if (strlen(s) > 0) | if (strlen(s) > 0) |
pout("Logical Unit id: %s\n", s); |
pout("Logical Unit id: %s\n", s); |
} else if (scsi_debugmode > 0) { |
} else if (scsi_debugmode > 0) { |
print_on(); |
print_on(); |
Line 1470 static int scsiGetDriveInfo(scsi_device * device, UINT
|
Line 1645 static int scsiGetDriveInfo(scsi_device * device, UINT
|
pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err); |
pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err); |
print_off(); |
print_off(); |
} |
} |
if (0 == (err = scsiInquiryVpd(device, 0x80, gBuf, 64))) { | if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_UNIT_SERIAL_NUMBER, |
| gBuf, 252))) { |
| char serial[256]; |
len = gBuf[3]; |
len = gBuf[3]; |
|
|
gBuf[4 + len] = '\0'; |
gBuf[4 + len] = '\0'; |
pout("Serial number: %s\n", &gBuf[4]); | scsi_format_id_string(serial, &gBuf[4], len); |
| pout("Serial number: %s\n", serial); |
} else if (scsi_debugmode > 0) { |
} else if (scsi_debugmode > 0) { |
print_on(); |
print_on(); |
if (SIMPLE_ERR_BAD_RESP == err) |
if (SIMPLE_ERR_BAD_RESP == err) |
Line 1485 static int scsiGetDriveInfo(scsi_device * device, UINT
|
Line 1664 static int scsiGetDriveInfo(scsi_device * device, UINT
|
} |
} |
|
|
// print SCSI peripheral device type |
// print SCSI peripheral device type |
if (peri_dt < (int)(sizeof(peripheral_dt_arr) / | if (peri_dt < (int)(sizeof(peripheral_dt_arr) / |
sizeof(peripheral_dt_arr[0]))) |
sizeof(peripheral_dt_arr[0]))) |
pout("Device type: %s\n", peripheral_dt_arr[peri_dt]); |
pout("Device type: %s\n", peripheral_dt_arr[peri_dt]); |
else |
else |
Line 1528 static int scsiGetDriveInfo(scsi_device * device, UINT
|
Line 1707 static int scsiGetDriveInfo(scsi_device * device, UINT
|
} |
} |
failuretest(MANDATORY_CMD, returnval|=FAILID); |
failuretest(MANDATORY_CMD, returnval|=FAILID); |
} |
} |
| |
if (iec_err) { |
if (iec_err) { |
if (!is_tape) { |
if (!is_tape) { |
print_on(); |
print_on(); |
pout("Device does not support SMART"); | pout("SMART support is: Unavailable - device lacks SMART capability.\n"); |
if (scsi_debugmode > 0) |
if (scsi_debugmode > 0) |
pout(" [%s]\n", scsiErrString(iec_err)); |
pout(" [%s]\n", scsiErrString(iec_err)); |
else |
|
pout("\n"); |
|
print_off(); |
print_off(); |
} |
} |
gIecMPage = 0; |
gIecMPage = 0; |
Line 1544 static int scsiGetDriveInfo(scsi_device * device, UINT
|
Line 1721 static int scsiGetDriveInfo(scsi_device * device, UINT
|
} |
} |
|
|
if (!is_tape) |
if (!is_tape) |
pout("Device supports SMART and is %s\n", | pout("SMART support is: Available - device has SMART capability.\n" |
| "SMART support is: %s\n", |
(scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled"); |
(scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled"); |
pout("%s\n", (scsi_IsWarningEnabled(&iec)) ? | pout("%s\n", (scsi_IsWarningEnabled(&iec)) ? |
"Temperature Warning Enabled" : | "Temperature Warning: Enabled" : |
"Temperature Warning Disabled or Not Supported"); | "Temperature Warning: Disabled or Not Supported"); |
return 0; |
return 0; |
} |
} |
|
|
static int scsiSmartEnable(scsi_device * device) | static int |
| scsiSmartEnable(scsi_device * device) |
{ |
{ |
struct scsi_iec_mode_page iec; |
struct scsi_iec_mode_page iec; |
int err; |
int err; |
|
|
if ((err = scsiFetchIECmpage(device, &iec, modese_len))) { |
if ((err = scsiFetchIECmpage(device, &iec, modese_len))) { |
print_on(); |
print_on(); |
pout("unable to fetch IEC (SMART) mode page [%s]\n", | pout("unable to fetch IEC (SMART) mode page [%s]\n", |
scsiErrString(err)); |
scsiErrString(err)); |
print_off(); |
print_off(); |
return 1; |
return 1; |
Line 1575 static int scsiSmartEnable(scsi_device * device)
|
Line 1754 static int scsiSmartEnable(scsi_device * device)
|
} |
} |
/* Need to refetch 'iec' since could be modified by previous call */ |
/* Need to refetch 'iec' since could be modified by previous call */ |
if ((err = scsiFetchIECmpage(device, &iec, modese_len))) { |
if ((err = scsiFetchIECmpage(device, &iec, modese_len))) { |
pout("unable to fetch IEC (SMART) mode page [%s]\n", | pout("unable to fetch IEC (SMART) mode page [%s]\n", |
scsiErrString(err)); |
scsiErrString(err)); |
return 1; |
return 1; |
} else |
} else |
Line 1587 static int scsiSmartEnable(scsi_device * device)
|
Line 1766 static int scsiSmartEnable(scsi_device * device)
|
scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled"); |
scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled"); |
return 0; |
return 0; |
} |
} |
| |
static int scsiSmartDisable(scsi_device * device) | static int |
| scsiSmartDisable(scsi_device * device) |
{ |
{ |
struct scsi_iec_mode_page iec; |
struct scsi_iec_mode_page iec; |
int err; |
int err; |
|
|
if ((err = scsiFetchIECmpage(device, &iec, modese_len))) { |
if ((err = scsiFetchIECmpage(device, &iec, modese_len))) { |
print_on(); |
print_on(); |
pout("unable to fetch IEC (SMART) mode page [%s]\n", | pout("unable to fetch IEC (SMART) mode page [%s]\n", |
scsiErrString(err)); |
scsiErrString(err)); |
print_off(); |
print_off(); |
return 1; |
return 1; |
Line 1611 static int scsiSmartDisable(scsi_device * device)
|
Line 1791 static int scsiSmartDisable(scsi_device * device)
|
} |
} |
/* Need to refetch 'iec' since could be modified by previous call */ |
/* Need to refetch 'iec' since could be modified by previous call */ |
if ((err = scsiFetchIECmpage(device, &iec, modese_len))) { |
if ((err = scsiFetchIECmpage(device, &iec, modese_len))) { |
pout("unable to fetch IEC (SMART) mode page [%s]\n", | pout("unable to fetch IEC (SMART) mode page [%s]\n", |
scsiErrString(err)); |
scsiErrString(err)); |
return 1; |
return 1; |
} else |
} else |
Line 1624 static int scsiSmartDisable(scsi_device * device)
|
Line 1804 static int scsiSmartDisable(scsi_device * device)
|
return 0; |
return 0; |
} |
} |
|
|
static void scsiPrintTemp(scsi_device * device) | static void |
| scsiPrintTemp(scsi_device * device) |
{ |
{ |
UINT8 temp = 0; |
UINT8 temp = 0; |
UINT8 trip = 0; |
UINT8 trip = 0; |
|
|
if (scsiGetTemp(device, &temp, &trip)) |
if (scsiGetTemp(device, &temp, &trip)) |
return; |
return; |
| |
if (temp) { |
if (temp) { |
if (255 != temp) |
if (255 != temp) |
pout("Current Drive Temperature: %d C\n", temp); |
pout("Current Drive Temperature: %d C\n", temp); |
Line 1640 static void scsiPrintTemp(scsi_device * device)
|
Line 1821 static void scsiPrintTemp(scsi_device * device)
|
} |
} |
if (trip) |
if (trip) |
pout("Drive Trip Temperature: %d C\n", trip); |
pout("Drive Trip Temperature: %d C\n", trip); |
|
if (temp || trip) |
|
pout("\n"); |
} |
} |
|
|
/* Main entry point used by smartctl command. Return 0 for success */ |
/* Main entry point used by smartctl command. Return 0 for success */ |
int scsiPrintMain(scsi_device * device, const scsi_print_options & options) | int |
| scsiPrintMain(scsi_device * device, const scsi_print_options & options) |
{ |
{ |
int checkedSupportedLogPages = 0; |
int checkedSupportedLogPages = 0; |
UINT8 peripheral_type = 0; |
UINT8 peripheral_type = 0; |
int returnval = 0; |
int returnval = 0; |
int res, durationSec; |
int res, durationSec; |
|
struct scsi_sense_disect sense_info; |
|
|
bool any_output = options.drive_info; |
bool any_output = options.drive_info; |
|
|
|
if (supported_vpd_pages_p) { |
|
delete supported_vpd_pages_p; |
|
supported_vpd_pages_p = NULL; |
|
} |
|
supported_vpd_pages_p = new supported_vpd_pages(device); |
|
|
res = scsiGetDriveInfo(device, &peripheral_type, options.drive_info); |
res = scsiGetDriveInfo(device, &peripheral_type, options.drive_info); |
if (res) { |
if (res) { |
if (2 == res) |
if (2 == res) |
return 0; |
return 0; |
else |
else |
failuretest(MANDATORY_CMD, returnval |= FAILID); |
failuretest(MANDATORY_CMD, returnval |= FAILID); |
any_output = true; | any_output = true; |
} |
} |
|
|
|
// Print read look-ahead status for disks |
|
short int wce = -1, rcd = -1; |
|
if (options.get_rcd || options.get_wce) { |
|
if (SCSI_PT_DIRECT_ACCESS == peripheral_type) |
|
res = scsiGetSetCache(device, modese_len, &wce, &rcd); |
|
else |
|
res = -1; // fetch for disks only |
|
any_output = true; |
|
} |
|
|
|
if (options.get_rcd) { |
|
pout("Read Cache is: %s\n", |
|
res ? "Unavailable" : // error |
|
rcd ? "Disabled" : "Enabled"); |
|
} |
|
|
|
if (options.get_wce) { |
|
pout("Writeback Cache is: %s\n", |
|
res ? "Unavailable" : // error |
|
!wce ? "Disabled" : "Enabled"); |
|
} |
|
if (options.drive_info) |
|
pout("\n"); |
|
|
|
// START OF THE ENABLE/DISABLE SECTION OF THE CODE |
|
if ( options.smart_disable || options.smart_enable |
|
|| options.smart_auto_save_disable || options.smart_auto_save_enable) |
|
pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n"); |
|
|
if (options.smart_enable) { |
if (options.smart_enable) { |
if (scsiSmartEnable(device)) |
if (scsiSmartEnable(device)) |
failuretest(MANDATORY_CMD, returnval |= FAILSMART); |
failuretest(MANDATORY_CMD, returnval |= FAILSMART); |
any_output = true; | any_output = true; |
} |
} |
|
|
if (options.smart_disable) { |
if (options.smart_disable) { |
if (scsiSmartDisable(device)) |
if (scsiSmartDisable(device)) |
failuretest(MANDATORY_CMD,returnval |= FAILSMART); |
failuretest(MANDATORY_CMD,returnval |= FAILSMART); |
any_output = true; | any_output = true; |
} |
} |
| |
if (options.smart_auto_save_enable) { |
if (options.smart_auto_save_enable) { |
if (scsiSetControlGLTSD(device, 0, modese_len)) { |
if (scsiSetControlGLTSD(device, 0, modese_len)) { |
pout("Enable autosave (clear GLTSD bit) failed\n"); |
pout("Enable autosave (clear GLTSD bit) failed\n"); |
failuretest(OPTIONAL_CMD,returnval |= FAILSMART); |
failuretest(OPTIONAL_CMD,returnval |= FAILSMART); |
} |
} |
|
else { |
|
pout("Autosave enabled (GLTSD bit set).\n"); |
|
} |
any_output = true; |
any_output = true; |
} |
} |
| |
| // Enable/Disable write cache |
| if (options.set_wce && SCSI_PT_DIRECT_ACCESS == peripheral_type) { |
| short int enable = wce = (options.set_wce > 0); |
| rcd = -1; |
| if (scsiGetSetCache(device, modese_len, &wce, &rcd)) { |
| pout("Write cache %sable failed: %s\n", (enable ? "en" : "dis"), |
| device->get_errmsg()); |
| failuretest(OPTIONAL_CMD,returnval |= FAILSMART); |
| } |
| else |
| pout("Write cache %sabled\n", (enable ? "en" : "dis")); |
| any_output = true; |
| } |
| |
| // Enable/Disable read cache |
| if (options.set_rcd && SCSI_PT_DIRECT_ACCESS == peripheral_type) { |
| short int enable = (options.set_rcd > 0); |
| rcd = !enable; |
| wce = -1; |
| if (scsiGetSetCache(device, modese_len, &wce, &rcd)) { |
| pout("Read cache %sable failed: %s\n", (enable ? "en" : "dis"), |
| device->get_errmsg()); |
| failuretest(OPTIONAL_CMD,returnval |= FAILSMART); |
| } |
| else |
| pout("Read cache %sabled\n", (enable ? "en" : "dis")); |
| any_output = true; |
| } |
| |
if (options.smart_auto_save_disable) { |
if (options.smart_auto_save_disable) { |
if (scsiSetControlGLTSD(device, 1, modese_len)) { |
if (scsiSetControlGLTSD(device, 1, modese_len)) { |
pout("Disable autosave (set GLTSD bit) failed\n"); |
pout("Disable autosave (set GLTSD bit) failed\n"); |
failuretest(OPTIONAL_CMD,returnval |= FAILSMART); |
failuretest(OPTIONAL_CMD,returnval |= FAILSMART); |
} |
} |
|
else { |
|
pout("Autosave disabled (GLTSD bit cleared).\n"); |
|
} |
any_output = true; |
any_output = true; |
} |
} |
| if ( options.smart_disable || options.smart_enable |
| || options.smart_auto_save_disable || options.smart_auto_save_enable) |
| pout("\n"); // END OF THE ENABLE/DISABLE SECTION OF THE CODE |
| |
| // START OF READ-ONLY OPTIONS APART FROM -V and -i |
| if ( options.smart_check_status || options.smart_ss_media_log |
| || options.smart_vendor_attrib || options.smart_error_log |
| || options.smart_selftest_log || options.smart_vendor_attrib |
| || options.smart_background_log || options.sasphy |
| ) |
| pout("=== START OF READ SMART DATA SECTION ===\n"); |
| |
if (options.smart_check_status) { |
if (options.smart_check_status) { |
scsiGetSupportedLogPages(device); |
scsiGetSupportedLogPages(device); |
checkedSupportedLogPages = 1; |
checkedSupportedLogPages = 1; |
Line 1711 int scsiPrintMain(scsi_device * device, const scsi_pri
|
Line 1977 int scsiPrintMain(scsi_device * device, const scsi_pri
|
} |
} |
} |
} |
any_output = true; |
any_output = true; |
} | } |
| |
if (options.smart_ss_media_log) { |
if (options.smart_ss_media_log) { |
if (! checkedSupportedLogPages) |
if (! checkedSupportedLogPages) |
scsiGetSupportedLogPages(device); |
scsiGetSupportedLogPages(device); |
Line 1726 int scsiPrintMain(scsi_device * device, const scsi_pri
|
Line 1993 int scsiPrintMain(scsi_device * device, const scsi_pri
|
if (! checkedSupportedLogPages) |
if (! checkedSupportedLogPages) |
scsiGetSupportedLogPages(device); |
scsiGetSupportedLogPages(device); |
if (gTempLPage) { |
if (gTempLPage) { |
if (options.smart_check_status) |
|
pout("\n"); |
|
scsiPrintTemp(device); |
scsiPrintTemp(device); |
} |
} |
if (gStartStopLPage) |
if (gStartStopLPage) |
Line 1790 int scsiPrintMain(scsi_device * device, const scsi_pri
|
Line 2055 int scsiPrintMain(scsi_device * device, const scsi_pri
|
pout("Short Foreground Self Test Successful\n"); |
pout("Short Foreground Self Test Successful\n"); |
any_output = true; |
any_output = true; |
} |
} |
|
// check if another test is running |
|
if (options.smart_short_selftest || options.smart_extend_selftest) { |
|
if (!scsiRequestSense(device, &sense_info) && |
|
(sense_info.asc == 0x04 && sense_info.ascq == 0x09)) { |
|
if (!options.smart_selftest_force) { |
|
pout("Can't start self-test without aborting current test"); |
|
if (sense_info.progress != -1) { |
|
pout(" (%d%% remaining)", |
|
100 - sense_info.progress * 100 / 65535); |
|
} |
|
pout(",\nadd '-t force' option to override, or run 'smartctl -X' " |
|
"to abort test.\n"); |
|
return -1; |
|
} |
|
else |
|
scsiSmartSelfTestAbort(device); |
|
} |
|
} |
if (options.smart_short_selftest) { |
if (options.smart_short_selftest) { |
if (scsiSmartShortSelfTest(device)) |
if (scsiSmartShortSelfTest(device)) |
return returnval | FAILSMART; |
return returnval | FAILSMART; |
Line 1806 int scsiPrintMain(scsi_device * device, const scsi_pri
|
Line 2089 int scsiPrintMain(scsi_device * device, const scsi_pri
|
time_t t = time(NULL); |
time_t t = time(NULL); |
|
|
t += durationSec; |
t += durationSec; |
pout("Please wait %d minutes for test to complete.\n", | pout("Please wait %d minutes for test to complete.\n", |
durationSec / 60); |
durationSec / 60); |
pout("Estimated completion time: %s\n", ctime(&t)); |
pout("Estimated completion time: %s\n", ctime(&t)); |
} |
} |
pout("Use smartctl -X to abort test\n"); | pout("Use smartctl -X to abort test\n"); |
any_output = true; |
any_output = true; |
} |
} |
if (options.smart_extend_cap_selftest) { |
if (options.smart_extend_cap_selftest) { |
Line 1823 int scsiPrintMain(scsi_device * device, const scsi_pri
|
Line 2106 int scsiPrintMain(scsi_device * device, const scsi_pri
|
return returnval | FAILSMART; |
return returnval | FAILSMART; |
pout("Self Test returned without error\n"); |
pout("Self Test returned without error\n"); |
any_output = true; |
any_output = true; |
} | } |
if (options.sasphy) { |
if (options.sasphy) { |
if (scsiPrintSasPhy(device, options.sasphy_reset)) |
if (scsiPrintSasPhy(device, options.sasphy_reset)) |
return returnval | FAILSMART; |
return returnval | FAILSMART; |
any_output = true; |
any_output = true; |
} | } |
|
|
if (!any_output) |
if (!any_output) |
pout("SCSI device successfully opened\n\n" |
pout("SCSI device successfully opened\n\n" |