Skip to content
Snippets Groups Projects
Commit fc9a5e5e authored by dpgilbert's avatar dpgilbert
Browse files

Add "-l selftest" capability for SCSI devices. Format of output is slightly

different from ATA's self test log (documented in smartctl.8 change).


git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@407 4ea69e1a-61f1-4043-bf83-b5c94c648137
parent 66c424e8
Branches
No related tags found
No related merge requests found
CHANGELOG for smartmontools CHANGELOG for smartmontools
$Id: CHANGELOG,v 1.79 2003/01/03 17:58:16 ballen4705 Exp $ $Id: CHANGELOG,v 1.80 2003/01/04 01:37:47 dpgilbert Exp $
Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
...@@ -38,6 +38,8 @@ CURRENT RELEASE (see VERSION file in this directory): ...@@ -38,6 +38,8 @@ CURRENT RELEASE (see VERSION file in this directory):
smartmontools-5.1.1 smartmontools-5.1.1
[DG] add '-l selftest' capability for SCSI devices (update smartctl.8)
[BA] smartd,smartctl: added additional Attribute modification option [BA] smartd,smartctl: added additional Attribute modification option
-v 220,temp and -v 9,temp. -v 220,temp and -v 9,temp.
......
...@@ -28,13 +28,33 @@ ...@@ -28,13 +28,33 @@
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
// We do NOT want to include the kernel SCSI header file, just user space one /* #include <scsi/scsi.h> bypass for now */
#define _LINUX_SCSI_H /* #include <scsi/scsi_ioctl.h> bypass for now */
#include <scsi/scsi.h>
#include "scsicmds.h" #include "scsicmds.h"
const char *CVSid3="$Id: scsicmds.c,v 1.16 2002/11/21 21:21:48 knan Exp $" CVSID4; const char *CVSid3="$Id: scsicmds.c,v 1.17 2003/01/04 01:37:48 dpgilbert Exp $" CVSID4;
static int send_scsi_cmd(int device, int cmnd_len, void * io_hdr)
{
int status;
#ifdef SCSI_DEBUG
{
int k;
const unsigned char * ucp = io_hdr;
ucp += 2 * sizeof(int);
fprintf(stderr, "cmnd: [");
for (k = 0; k < cmnd_len; ++k)
fprintf(stderr, "%02x ", ucp[k]);
}
#endif
status = ioctl(device, SCSI_IOCTL_SEND_COMMAND , io_hdr);
#ifdef SCSI_DEBUG
fprintf(stderr, "] status=0x%x\n", status);
#endif
return status;
}
UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf) UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf)
{ {
...@@ -61,8 +81,7 @@ UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -61,8 +81,7 @@ UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[8] = 0x00; ioctlhdr->cdb[8] = 0x00;
ioctlhdr->cdb[9] = 0x00; ioctlhdr->cdb[9] = 0x00;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 10, &tBuf);
memcpy ( pBuf, &tBuf[8], 1024); memcpy ( pBuf, &tBuf[8], 1024);
...@@ -96,8 +115,7 @@ UINT8 modesense (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -96,8 +115,7 @@ UINT8 modesense (int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE; ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = send_scsi_cmd(device, 6, &tBuf);
status = ioctl( device, 1 , &tBuf);
memcpy ( pBuf, &tBuf[8], 256); memcpy ( pBuf, &tBuf[8], 256);
...@@ -139,7 +157,7 @@ UINT8 modeselect (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -139,7 +157,7 @@ UINT8 modeselect (int device, UINT8 pagenum, UINT8 *pBuf)
tBuf[26] &= 0x3f; tBuf[26] &= 0x3f;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 6, &tBuf);
return status; return status;
...@@ -173,7 +191,7 @@ UINT8 modesense10 (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -173,7 +191,7 @@ UINT8 modesense10 (int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[8] = 0xff; ioctlhdr->cdb[8] = 0xff;
ioctlhdr->cdb[9] = 0x00; ioctlhdr->cdb[9] = 0x00;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 10, &tBuf);
memcpy ( pBuf, &tBuf[8], 0xff); memcpy ( pBuf, &tBuf[8], 0xff);
...@@ -218,7 +236,7 @@ UINT8 modeselect10 (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -218,7 +236,7 @@ UINT8 modeselect10 (int device, UINT8 pagenum, UINT8 *pBuf)
tBuf[26] &= 0x3f; tBuf[26] &= 0x3f;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 10, &tBuf);
return status; return status;
...@@ -251,7 +269,7 @@ UINT8 stdinquiry ( int device, UINT8 *pBuf) ...@@ -251,7 +269,7 @@ UINT8 stdinquiry ( int device, UINT8 *pBuf)
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = ioctl( device, 1, &tBuf ); status = send_scsi_cmd(device, 6, &tBuf);
memcpy ( pBuf, &tBuf[8], 255); memcpy ( pBuf, &tBuf[8], 255);
...@@ -286,8 +304,7 @@ UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -286,8 +304,7 @@ UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE; ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = send_scsi_cmd(device, 6, &tBuf);
status = ioctl( device, 1 , &tBuf);
memcpy ( pBuf, &tBuf[8], 255); memcpy ( pBuf, &tBuf[8], 255);
...@@ -321,8 +338,7 @@ UINT8 requestsense (int device, UINT8 *pBuf) ...@@ -321,8 +338,7 @@ UINT8 requestsense (int device, UINT8 *pBuf)
ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE; ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = send_scsi_cmd(device, 6, &tBuf);
status = ioctl( device, 1 , &tBuf);
memcpy ( pBuf, &tBuf[8], 255); memcpy ( pBuf, &tBuf[8], 255);
...@@ -364,7 +380,7 @@ UINT8 senddiagnostic (int device, UINT8 functioncode, UINT8 *pBuf) ...@@ -364,7 +380,7 @@ UINT8 senddiagnostic (int device, UINT8 functioncode, UINT8 *pBuf)
pBuf[0]); pBuf[0]);
} }
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 6, &tBuf);
if (pBuf != NULL) if (pBuf != NULL)
memcpy ( pBuf, &tBuf[8], 256); memcpy ( pBuf, &tBuf[8], 256);
...@@ -400,7 +416,7 @@ UINT8 receivediagnostic (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -400,7 +416,7 @@ UINT8 receivediagnostic (int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 6, &tBuf);
memcpy ( pBuf, &tBuf[8], 256); memcpy ( pBuf, &tBuf[8], 256);
...@@ -411,7 +427,7 @@ UINT8 receivediagnostic (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -411,7 +427,7 @@ UINT8 receivediagnostic (int device, UINT8 pagenum, UINT8 *pBuf)
// See if the device accepts IOCTLs at all... // See if the device accepts IOCTLs at all...
UINT8 testunitnotready (int device) UINT8 testunitnotready (int device)
{ {
return ioctl( device, 2 , NULL); return ioctl( device, SCSI_IOCTL_TEST_UNIT_READY , NULL);
} }
......
...@@ -28,13 +28,33 @@ ...@@ -28,13 +28,33 @@
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
// We do NOT want to include the kernel SCSI header file, just user space one /* #include <scsi/scsi.h> bypass for now */
#define _LINUX_SCSI_H /* #include <scsi/scsi_ioctl.h> bypass for now */
#include <scsi/scsi.h>
#include "scsicmds.h" #include "scsicmds.h"
const char *CVSid3="$Id: scsicmds.cpp,v 1.16 2002/11/21 21:21:48 knan Exp $" CVSID4; const char *CVSid3="$Id: scsicmds.cpp,v 1.17 2003/01/04 01:37:48 dpgilbert Exp $" CVSID4;
static int send_scsi_cmd(int device, int cmnd_len, void * io_hdr)
{
int status;
#ifdef SCSI_DEBUG
{
int k;
const unsigned char * ucp = io_hdr;
ucp += 2 * sizeof(int);
fprintf(stderr, "cmnd: [");
for (k = 0; k < cmnd_len; ++k)
fprintf(stderr, "%02x ", ucp[k]);
}
#endif
status = ioctl(device, SCSI_IOCTL_SEND_COMMAND , io_hdr);
#ifdef SCSI_DEBUG
fprintf(stderr, "] status=0x%x\n", status);
#endif
return status;
}
UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf) UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf)
{ {
...@@ -61,8 +81,7 @@ UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -61,8 +81,7 @@ UINT8 logsense (int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[8] = 0x00; ioctlhdr->cdb[8] = 0x00;
ioctlhdr->cdb[9] = 0x00; ioctlhdr->cdb[9] = 0x00;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 10, &tBuf);
memcpy ( pBuf, &tBuf[8], 1024); memcpy ( pBuf, &tBuf[8], 1024);
...@@ -96,8 +115,7 @@ UINT8 modesense (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -96,8 +115,7 @@ UINT8 modesense (int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE; ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = send_scsi_cmd(device, 6, &tBuf);
status = ioctl( device, 1 , &tBuf);
memcpy ( pBuf, &tBuf[8], 256); memcpy ( pBuf, &tBuf[8], 256);
...@@ -139,7 +157,7 @@ UINT8 modeselect (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -139,7 +157,7 @@ UINT8 modeselect (int device, UINT8 pagenum, UINT8 *pBuf)
tBuf[26] &= 0x3f; tBuf[26] &= 0x3f;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 6, &tBuf);
return status; return status;
...@@ -173,7 +191,7 @@ UINT8 modesense10 (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -173,7 +191,7 @@ UINT8 modesense10 (int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[8] = 0xff; ioctlhdr->cdb[8] = 0xff;
ioctlhdr->cdb[9] = 0x00; ioctlhdr->cdb[9] = 0x00;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 10, &tBuf);
memcpy ( pBuf, &tBuf[8], 0xff); memcpy ( pBuf, &tBuf[8], 0xff);
...@@ -218,7 +236,7 @@ UINT8 modeselect10 (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -218,7 +236,7 @@ UINT8 modeselect10 (int device, UINT8 pagenum, UINT8 *pBuf)
tBuf[26] &= 0x3f; tBuf[26] &= 0x3f;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 10, &tBuf);
return status; return status;
...@@ -251,7 +269,7 @@ UINT8 stdinquiry ( int device, UINT8 *pBuf) ...@@ -251,7 +269,7 @@ UINT8 stdinquiry ( int device, UINT8 *pBuf)
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = ioctl( device, 1, &tBuf ); status = send_scsi_cmd(device, 6, &tBuf);
memcpy ( pBuf, &tBuf[8], 255); memcpy ( pBuf, &tBuf[8], 255);
...@@ -286,8 +304,7 @@ UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -286,8 +304,7 @@ UINT8 inquiry ( int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE; ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = send_scsi_cmd(device, 6, &tBuf);
status = ioctl( device, 1 , &tBuf);
memcpy ( pBuf, &tBuf[8], 255); memcpy ( pBuf, &tBuf[8], 255);
...@@ -321,8 +338,7 @@ UINT8 requestsense (int device, UINT8 *pBuf) ...@@ -321,8 +338,7 @@ UINT8 requestsense (int device, UINT8 *pBuf)
ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE; ioctlhdr->cdb[4] = CDB_6_MAX_DATA_SIZE;
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = send_scsi_cmd(device, 6, &tBuf);
status = ioctl( device, 1 , &tBuf);
memcpy ( pBuf, &tBuf[8], 255); memcpy ( pBuf, &tBuf[8], 255);
...@@ -364,7 +380,7 @@ UINT8 senddiagnostic (int device, UINT8 functioncode, UINT8 *pBuf) ...@@ -364,7 +380,7 @@ UINT8 senddiagnostic (int device, UINT8 functioncode, UINT8 *pBuf)
pBuf[0]); pBuf[0]);
} }
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 6, &tBuf);
if (pBuf != NULL) if (pBuf != NULL)
memcpy ( pBuf, &tBuf[8], 256); memcpy ( pBuf, &tBuf[8], 256);
...@@ -400,7 +416,7 @@ UINT8 receivediagnostic (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -400,7 +416,7 @@ UINT8 receivediagnostic (int device, UINT8 pagenum, UINT8 *pBuf)
ioctlhdr->cdb[5] = 0x00; ioctlhdr->cdb[5] = 0x00;
status = ioctl( device, 1 , &tBuf); status = send_scsi_cmd(device, 6, &tBuf);
memcpy ( pBuf, &tBuf[8], 256); memcpy ( pBuf, &tBuf[8], 256);
...@@ -411,7 +427,7 @@ UINT8 receivediagnostic (int device, UINT8 pagenum, UINT8 *pBuf) ...@@ -411,7 +427,7 @@ UINT8 receivediagnostic (int device, UINT8 pagenum, UINT8 *pBuf)
// See if the device accepts IOCTLs at all... // See if the device accepts IOCTLs at all...
UINT8 testunitnotready (int device) UINT8 testunitnotready (int device)
{ {
return ioctl( device, 2 , NULL); return ioctl( device, SCSI_IOCTL_TEST_UNIT_READY , NULL);
} }
......
...@@ -27,9 +27,13 @@ ...@@ -27,9 +27,13 @@
#define SCSICMDS_H_ #define SCSICMDS_H_
#ifndef CVSID4 #ifndef CVSID4
#define CVSID4 "$Id: scsicmds.h,v 1.8 2002/11/17 05:30:11 ballen4705 Exp $\n" #define CVSID4 "$Id: scsicmds.h,v 1.9 2003/01/04 01:37:48 dpgilbert Exp $\n"
#endif #endif
/* #define SCSI_DEBUG 1 */ /* Comment out to disable command debugging */
/* Following conditional defines bypass inclusion of scsi/scsi.h and
* scsi/scsi_ioctl.h . Issue will be resolved later ... */
#ifndef LOG_SENSE #ifndef LOG_SENSE
#define LOG_SENSE 0x4d #define LOG_SENSE 0x4d
#endif #endif
...@@ -37,6 +41,9 @@ ...@@ -37,6 +41,9 @@
#ifndef MODE_SENSE #ifndef MODE_SENSE
#define MODE_SENSE 0x1a #define MODE_SENSE 0x1a
#endif #endif
#ifndef MODE_SENSE_10
#define MODE_SENSE_10 0x5a
#endif
#ifndef MODE_SELECT #ifndef MODE_SELECT
#define MODE_SELECT 0x15 #define MODE_SELECT 0x15
...@@ -62,6 +69,13 @@ ...@@ -62,6 +69,13 @@
#define SEND_DIAGNOSTIC 0x1d #define SEND_DIAGNOSTIC 0x1d
#endif #endif
#ifndef SCSI_IOCTL_SEND_COMMAND
#define SCSI_IOCTL_SEND_COMMAND 1
#endif
#ifndef SCSI_IOCTL_TEST_UNIT_READY
#define SCSI_IOCTL_TEST_UNIT_READY 2
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#define GBUF_SIZE 65535 #define GBUF_SIZE 65535
const char* CVSid4="$Id: scsiprint.c,v 1.13 2002/12/29 02:14:47 dpgilbert Exp $" const char* CVSid4="$Id: scsiprint.c,v 1.14 2003/01/04 01:37:48 dpgilbert Exp $"
CVSID3 CVSID4 CVSID5 CVSID6; CVSID3 CVSID4 CVSID5 CVSID6;
// control block which points to external global control variables // control block which points to external global control variables
...@@ -184,6 +184,87 @@ void scsiGetStartStopData ( int device) ...@@ -184,6 +184,87 @@ void scsiGetStartStopData ( int device)
printf("Recommended start stop count: %u times\n", recommendedStartStop); printf("Recommended start stop count: %u times\n", recommendedStartStop);
} }
const char * self_test_code[] = {
"Default ",
"Background short",
"Background long ",
"Reserved(3) ",
"Abort background",
"Foreground short",
"Foreground long ",
"Reserved(7) "
};
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 ..."
};
void scsiPrintSelfTest(int device)
{
int num, k, n, res;
UINT8 * ucp;
unsigned long long ull;
if (logsense(device, SELFTEST_RESULTS_PAGE, gBuf) != 0)
{
perror ( "scsiPrintSelfTest Failed");
exit (1);
}
if (gBuf[0] != SELFTEST_RESULTS_PAGE)
{
printf("Self-test Log Sense Failed\n");
exit(-1);
}
num = (gBuf[2] << 8) + gBuf[3];
if (num < 0x190) {
printf("Self-test Log Sense too short\n");
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");
for (k = 0, ucp = gBuf + 4; k < 20; ++k, ucp += 20 ) {
n = (ucp[6] << 8) | ucp[7];
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]);
else
printf("\n");
}
}
void scsiGetDriveInfo ( int device) void scsiGetDriveInfo ( int device)
{ {
...@@ -299,6 +380,7 @@ void scsiPrintStopStart ( int device ) ...@@ -299,6 +380,7 @@ void scsiPrintStopStart ( int device )
void scsiPrintMain (char *device, int fd) void scsiPrintMain (char *device, int fd)
{ {
int checkedsupportlogpages = 0;
// See if unit accepts SCSI commmands from us // See if unit accepts SCSI commmands from us
if (testunitnotready(fd)){ if (testunitnotready(fd)){
...@@ -318,6 +400,7 @@ void scsiPrintMain (char *device, int fd) ...@@ -318,6 +400,7 @@ void scsiPrintMain (char *device, int fd)
if (con->checksmart) if (con->checksmart)
{ {
scsiGetSupportPages (fd); scsiGetSupportPages (fd);
checkedsupportlogpages = 1;
if(gTapeAlertsPage) if(gTapeAlertsPage)
scsiGetTapeAlertsData (fd); scsiGetTapeAlertsData (fd);
else else
...@@ -330,6 +413,12 @@ void scsiPrintMain (char *device, int fd) ...@@ -330,6 +413,12 @@ void scsiPrintMain (char *device, int fd)
} }
} }
if (con->smartselftestlog) {
if (! checkedsupportlogpages)
scsiGetSupportPages(fd);
if (gSelfTestPage)
scsiPrintSelfTest(fd);
}
if ( con->smartexeoffimmediate ) if ( con->smartexeoffimmediate )
{ {
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#define GBUF_SIZE 65535 #define GBUF_SIZE 65535
const char* CVSid4="$Id: scsiprint.cpp,v 1.13 2002/12/29 02:14:47 dpgilbert Exp $" const char* CVSid4="$Id: scsiprint.cpp,v 1.14 2003/01/04 01:37:48 dpgilbert Exp $"
CVSID3 CVSID4 CVSID5 CVSID6; CVSID3 CVSID4 CVSID5 CVSID6;
// control block which points to external global control variables // control block which points to external global control variables
...@@ -184,6 +184,87 @@ void scsiGetStartStopData ( int device) ...@@ -184,6 +184,87 @@ void scsiGetStartStopData ( int device)
printf("Recommended start stop count: %u times\n", recommendedStartStop); printf("Recommended start stop count: %u times\n", recommendedStartStop);
} }
const char * self_test_code[] = {
"Default ",
"Background short",
"Background long ",
"Reserved(3) ",
"Abort background",
"Foreground short",
"Foreground long ",
"Reserved(7) "
};
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 ..."
};
void scsiPrintSelfTest(int device)
{
int num, k, n, res;
UINT8 * ucp;
unsigned long long ull;
if (logsense(device, SELFTEST_RESULTS_PAGE, gBuf) != 0)
{
perror ( "scsiPrintSelfTest Failed");
exit (1);
}
if (gBuf[0] != SELFTEST_RESULTS_PAGE)
{
printf("Self-test Log Sense Failed\n");
exit(-1);
}
num = (gBuf[2] << 8) + gBuf[3];
if (num < 0x190) {
printf("Self-test Log Sense too short\n");
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");
for (k = 0, ucp = gBuf + 4; k < 20; ++k, ucp += 20 ) {
n = (ucp[6] << 8) | ucp[7];
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]);
else
printf("\n");
}
}
void scsiGetDriveInfo ( int device) void scsiGetDriveInfo ( int device)
{ {
...@@ -299,6 +380,7 @@ void scsiPrintStopStart ( int device ) ...@@ -299,6 +380,7 @@ void scsiPrintStopStart ( int device )
void scsiPrintMain (char *device, int fd) void scsiPrintMain (char *device, int fd)
{ {
int checkedsupportlogpages = 0;
// See if unit accepts SCSI commmands from us // See if unit accepts SCSI commmands from us
if (testunitnotready(fd)){ if (testunitnotready(fd)){
...@@ -318,6 +400,7 @@ void scsiPrintMain (char *device, int fd) ...@@ -318,6 +400,7 @@ void scsiPrintMain (char *device, int fd)
if (con->checksmart) if (con->checksmart)
{ {
scsiGetSupportPages (fd); scsiGetSupportPages (fd);
checkedsupportlogpages = 1;
if(gTapeAlertsPage) if(gTapeAlertsPage)
scsiGetTapeAlertsData (fd); scsiGetTapeAlertsData (fd);
else else
...@@ -330,6 +413,12 @@ void scsiPrintMain (char *device, int fd) ...@@ -330,6 +413,12 @@ void scsiPrintMain (char *device, int fd)
} }
} }
if (con->smartselftestlog) {
if (! checkedsupportlogpages)
scsiGetSupportPages(fd);
if (gSelfTestPage)
scsiPrintSelfTest(fd);
}
if ( con->smartexeoffimmediate ) if ( con->smartexeoffimmediate )
{ {
......
\# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> \# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
\# \#
\# $Id: smartctl.8,v 1.34 2003/01/03 20:31:11 pjwilliams Exp $ \# $Id: smartctl.8,v 1.35 2003/01/04 01:37:48 dpgilbert Exp $
\# \#
\# This program is free software; you can redistribute it and/or modify it \# 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 the Free \# under the terms of the GNU General Public License as published by the Free
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
\# Research Center), Jack Baskin School of Engineering, University of \# Research Center), Jack Baskin School of Engineering, University of
\# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/
\# \#
.TH SMARTCTL 8 "$Date: 2003/01/03 20:31:11 $" "smartmontools-5.0" .TH SMARTCTL 8 "$Date: 2003/01/04 01:37:48 $" "smartmontools-5.0"
.SH NAME .SH NAME
smartctl \- S.M.A.R.T. control and monitor utility smartctl \- S.M.A.R.T. control and monitor utility
.SH SYNOPSIS .SH SYNOPSIS
...@@ -74,7 +74,7 @@ will execute the corresponding commands in the order: INFORMATION, ...@@ -74,7 +74,7 @@ will execute the corresponding commands in the order: INFORMATION,
ENABLE/DISABLE, DISPLAY DATA, RUN/ABORT TESTS. ENABLE/DISABLE, DISPLAY DATA, RUN/ABORT TESTS.
SCSI devices only accept the options SCSI devices only accept the options
.B \-h, \-?, \-V, \-i, \-a, \-d, \-s, \-H, \-t, \-C .B \-h, \-?, \-V, \-i, \-a, \-d, \-s, \-H, \-t, \-C \-l selftest
and and
.B \-X. .B \-X.
TapeAlerts devices only accept the options TapeAlerts devices only accept the options
...@@ -109,7 +109,7 @@ so, whether S.M.A.R.T. support is currently enabled or disabled. ...@@ -109,7 +109,7 @@ so, whether S.M.A.R.T. support is currently enabled or disabled.
.TP .TP
.B \-a, \-\-all .B \-a, \-\-all
Prints all S.M.A.R.T. information about the disk. This is equivalent to '\-H Prints all S.M.A.R.T. information about the disk. This is equivalent to '\-H
\-i \-c \-A \-l error \-l selftest' (for SCSI, '\-H \-i'). \-i \-c \-A \-l error \-l selftest' (for SCSI, '\-H \-i \-l selftest').
.TP .TP
.B RUN-TIME BEHAVIOR: .B RUN-TIME BEHAVIOR:
.TP .TP
...@@ -400,6 +400,18 @@ measured in hours of disk lifetime, is shown. If any errors were ...@@ -400,6 +400,18 @@ measured in hours of disk lifetime, is shown. If any errors were
detected, the Logical Block Address (LBA) of the first error is printed detected, the Logical Block Address (LBA) of the first error is printed
in hexadecimal notation. in hexadecimal notation.
.I selftest [SCSI]
\- the self-test log for a SCSI device has a slightly different format.
The log will show, for each of the most recent twenty self-tests, the type
of test and the status (final or in progress) of the test. SCSI standards
use the terms foreground and background (rather than ATA's captive and
off-line); and long (rather ATA's extended). The segment number column is
only relevant when a test fails in the third or later test segment. The
Logical Block Address (LBA) of the first error is printed in hexadecimal
notation. If provided, a SCSI sense key (SK), additional sense code (ASC)
and additional sense qualifier (ASQ) is output. The self tests can be
run using the '\-t' option described below (use ATA's test terminology).
.TP .TP
.B \-v N,OPTION, \-\-vendorattribute=N,OPTION .B \-v N,OPTION, \-\-vendorattribute=N,OPTION
Sets a vendor-specific display OPTION for Attribute N. Valid Sets a vendor-specific display OPTION for Attribute N. Valid
...@@ -653,4 +665,4 @@ Please let us know if there is an on\-line source for this document. ...@@ -653,4 +665,4 @@ Please let us know if there is an on\-line source for this document.
.SH .SH
CVS ID OF THIS PAGE: CVS ID OF THIS PAGE:
$Id: smartctl.8,v 1.34 2003/01/03 20:31:11 pjwilliams Exp $ $Id: smartctl.8,v 1.35 2003/01/04 01:37:48 dpgilbert Exp $
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment