4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
7 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
9 * Additional SCSI work:
10 * Copyright (C) 2003-8 Douglas Gilbert <dougg@torque.net>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
17 * You should have received a copy of the GNU General Public License
18 * (for example COPYING); if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * This code was originally developed as a Senior Thesis by Michael Cornwell
22 * at the Concurrent Systems Laboratory (now part of the Storage Systems
23 * Research Center), Jack Baskin School of Engineering, University of
24 * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
27 * In the SCSI world "SMART" is a dead or withdrawn standard. In recent
28 * SCSI standards (since SCSI-3) it goes under the awkward name of
29 * "Informational Exceptions" ["IE" or "IEC" (with the "C" for "control")].
30 * The relevant information is spread around several SCSI draft
31 * standards available at http://www.t10.org . Reference is made in the
32 * code to the following acronyms:
33 * - SAM [SCSI Architectural model, versions 2 or 3]
34 * - SPC [SCSI Primary commands, versions 2 or 3]
35 * - SBC [SCSI Block commands, versions 2]
37 * Some SCSI disk vendors have snippets of "SMART" information in their
50 const char *scsicmds_c_cvsid
="$Id: scsicmds.cpp,v 1.96 2008/03/04 22:09:47 ballen4705 Exp $"
51 CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
53 /* for passing global control variables */
54 extern smartmonctrl
*con
;
56 /* output binary in hex and optionally ascii */
57 void dStrHex(const char* str
, int len
, int no_ascii
)
63 const int bpstart
= 5;
64 const int cpstart
= 60;
72 k
= sprintf(buff
+ 1, "%.2x", a
);
74 if (bpos
>= ((bpstart
+ (9 * 3))))
77 for(i
= 0; i
< len
; i
++)
81 if (bpos
== (bpstart
+ (9 * 3)))
83 sprintf(&buff
[bpos
], "%.2x", (int)(unsigned char)c
);
88 if ((c
< ' ') || (c
>= 0x7f))
92 if (cpos
> (cpstart
+15))
99 k
= sprintf(buff
+ 1, "%.2x", a
);
109 struct scsi_opcode_name
{
114 static struct scsi_opcode_name opcode_name_arr
[] = {
115 /* in ascending opcode order */
116 {TEST_UNIT_READY
, "test unit ready"}, /* 0x00 */
117 {REQUEST_SENSE
, "request sense"}, /* 0x03 */
118 {INQUIRY
, "inquiry"}, /* 0x12 */
119 {MODE_SELECT
, "mode select(6)"}, /* 0x15 */
120 {MODE_SENSE
, "mode sense(6)"}, /* 0x1a */
121 {RECEIVE_DIAGNOSTIC
, "receive diagnostic"}, /* 0x1c */
122 {SEND_DIAGNOSTIC
, "send diagnostic"}, /* 0x1d */
123 {READ_DEFECT_10
, "read defect list(10)"}, /* 0x37 */
124 {LOG_SENSE
, "log sense"}, /* 0x4d */
125 {MODE_SELECT_10
, "mode select(10)"}, /* 0x55 */
126 {MODE_SENSE_10
, "mode sense(10)"}, /* 0x5a */
127 {SAT_ATA_PASSTHROUGH_16
, "ata pass-through(16)"}, /* 0x85 */
128 {SAT_ATA_PASSTHROUGH_12
, "ata pass-through(12)"}, /* 0xa1 */
131 const char * scsi_get_opcode_name(UINT8 opcode
)
134 int len
= sizeof(opcode_name_arr
) / sizeof(opcode_name_arr
[0]);
135 struct scsi_opcode_name
* onp
;
137 for (k
= 0; k
< len
; ++k
) {
138 onp
= &opcode_name_arr
[k
];
139 if (opcode
== onp
->opcode
)
141 else if (opcode
< onp
->opcode
)
148 void scsi_do_sense_disect(const struct scsi_cmnd_io
* io_buf
,
149 struct scsi_sense_disect
* out
)
153 memset(out
, 0, sizeof(struct scsi_sense_disect
));
154 if (SCSI_STATUS_CHECK_CONDITION
== io_buf
->scsi_status
) {
155 resp_code
= (io_buf
->sensep
[0] & 0x7f);
156 out
->error_code
= resp_code
;
157 if (resp_code
>= 0x72) {
158 out
->sense_key
= (io_buf
->sensep
[1] & 0xf);
159 out
->asc
= io_buf
->sensep
[2];
160 out
->ascq
= io_buf
->sensep
[3];
161 } else if (resp_code
>= 0x70) {
162 out
->sense_key
= (io_buf
->sensep
[2] & 0xf);
163 if (io_buf
->resp_sense_len
> 13) {
164 out
->asc
= io_buf
->sensep
[12];
165 out
->ascq
= io_buf
->sensep
[13];
171 int scsiSimpleSenseFilter(const struct scsi_sense_disect
* sinfo
)
173 switch (sinfo
->sense_key
) {
174 case SCSI_SK_NO_SENSE
:
175 case SCSI_SK_RECOVERED_ERR
:
176 return SIMPLE_NO_ERROR
;
177 case SCSI_SK_NOT_READY
:
178 if (SCSI_ASC_NO_MEDIUM
== sinfo
->asc
)
179 return SIMPLE_ERR_NO_MEDIUM
;
180 else if (SCSI_ASC_NOT_READY
== sinfo
->asc
) {
181 if (0x1 == sinfo
->ascq
)
182 return SIMPLE_ERR_BECOMING_READY
;
184 return SIMPLE_ERR_NOT_READY
;
186 return SIMPLE_ERR_NOT_READY
;
187 case SCSI_SK_MEDIUM_ERROR
:
188 case SCSI_SK_HARDWARE_ERROR
:
189 return SIMPLE_ERR_MEDIUM_HARDWARE
;
190 case SCSI_SK_ILLEGAL_REQUEST
:
191 if (SCSI_ASC_UNKNOWN_OPCODE
== sinfo
->asc
)
192 return SIMPLE_ERR_BAD_OPCODE
;
193 else if (SCSI_ASC_UNKNOWN_FIELD
== sinfo
->asc
)
194 return SIMPLE_ERR_BAD_FIELD
;
195 else if (SCSI_ASC_UNKNOWN_PARAM
== sinfo
->asc
)
196 return SIMPLE_ERR_BAD_PARAM
;
198 return SIMPLE_ERR_BAD_PARAM
; /* all other illegal request */
199 case SCSI_SK_UNIT_ATTENTION
:
200 return SIMPLE_ERR_TRY_AGAIN
;
201 case SCSI_SK_ABORTED_COMMAND
:
202 return SIMPLE_ERR_ABORTED_COMMAND
;
204 return SIMPLE_ERR_UNKNOWN
;
208 const char * scsiErrString(int scsiErr
)
211 return strerror(-scsiErr
);
213 case SIMPLE_NO_ERROR
:
215 case SIMPLE_ERR_NOT_READY
:
216 return "device not ready";
217 case SIMPLE_ERR_BAD_OPCODE
:
218 return "unsupported scsi opcode";
219 case SIMPLE_ERR_BAD_FIELD
:
220 return "unsupported field in scsi command";
221 case SIMPLE_ERR_BAD_PARAM
:
222 return "badly formed scsi parameters";
223 case SIMPLE_ERR_BAD_RESP
:
224 return "scsi response fails sanity test";
225 case SIMPLE_ERR_NO_MEDIUM
:
226 return "no medium present";
227 case SIMPLE_ERR_BECOMING_READY
:
228 return "device will be ready soon";
229 case SIMPLE_ERR_TRY_AGAIN
:
230 return "unit attention reported, try again";
231 case SIMPLE_ERR_MEDIUM_HARDWARE
:
232 return "medium or hardware error (serious)";
233 case SIMPLE_ERR_UNKNOWN
:
234 return "unknown error (unexpected sense key)";
235 case SIMPLE_ERR_ABORTED_COMMAND
:
236 return "aborted command";
238 return "unknown error";
242 /* Sends LOG SENSE command. Returns 0 if ok, 1 if device NOT READY, 2 if
243 command not supported, 3 if field (within command) not supported or
244 returns negated errno. SPC-3 sections 6.6 and 7.2 (rec 22a).
245 N.B. Sets PC==1 to fetch "current cumulative" log pages.
246 If known_resp_len > 0 then a single fetch is done for this response
247 length. If known_resp_len == 0 then twin fetches are performed, the
248 first to deduce the response length, then send the same command again
249 requesting the deduced response length. This protects certain fragile
250 HBAs. The twin fetch technique should not be used with the TapeAlert
251 log page since it clears its state flags after each fetch. */
252 int scsiLogSense(int device
, int pagenum
, int subpagenum
, UINT8
*pBuf
,
253 int bufLen
, int known_resp_len
)
255 struct scsi_cmnd_io io_hdr
;
256 struct scsi_sense_disect sinfo
;
262 if (known_resp_len
> bufLen
)
264 if (known_resp_len
> 0)
265 pageLen
= known_resp_len
;
267 /* Starting twin fetch strategy: first fetch to find respone length */
269 if (pageLen
> bufLen
)
272 memset(pBuf
, 0, pageLen
);
274 memset(&io_hdr
, 0, sizeof(io_hdr
));
275 memset(cdb
, 0, sizeof(cdb
));
276 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
277 io_hdr
.dxfer_len
= pageLen
;
278 io_hdr
.dxferp
= pBuf
;
280 cdb
[2] = 0x40 | (pagenum
& 0x3f); /* Page control (PC)==1 */
282 cdb
[7] = (pageLen
>> 8) & 0xff;
283 cdb
[8] = pageLen
& 0xff;
285 io_hdr
.cmnd_len
= sizeof(cdb
);
286 io_hdr
.sensep
= sense
;
287 io_hdr
.max_sense_len
= sizeof(sense
);
288 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
290 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
293 scsi_do_sense_disect(&io_hdr
, &sinfo
);
294 if ((res
= scsiSimpleSenseFilter(&sinfo
)))
296 /* sanity check on response */
297 if ((SUPPORTED_LPAGES
!= pagenum
) && (pBuf
[0] != pagenum
))
298 return SIMPLE_ERR_BAD_RESP
;
299 if (0 == ((pBuf
[2] << 8) + pBuf
[3]))
300 return SIMPLE_ERR_BAD_RESP
;
301 pageLen
= (pBuf
[2] << 8) + pBuf
[3] + 4;
302 if (4 == pageLen
) /* why define a lpage with no payload? */
303 pageLen
= 252; /* some IBM tape drives don't like double fetch */
304 /* some SCSI HBA don't like "odd" length transfers */
307 if (pageLen
> bufLen
)
311 memset(&io_hdr
, 0, sizeof(io_hdr
));
312 memset(cdb
, 0, sizeof(cdb
));
313 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
314 io_hdr
.dxfer_len
= pageLen
;
315 io_hdr
.dxferp
= pBuf
;
317 cdb
[2] = 0x40 | (pagenum
& 0x3f); /* Page control (PC)==1 */
318 cdb
[7] = (pageLen
>> 8) & 0xff;
319 cdb
[8] = pageLen
& 0xff;
321 io_hdr
.cmnd_len
= sizeof(cdb
);
322 io_hdr
.sensep
= sense
;
323 io_hdr
.max_sense_len
= sizeof(sense
);
324 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
326 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
329 scsi_do_sense_disect(&io_hdr
, &sinfo
);
330 status
= scsiSimpleSenseFilter(&sinfo
);
333 /* sanity check on response */
334 if ((SUPPORTED_LPAGES
!= pagenum
) && (pBuf
[0] != pagenum
))
335 return SIMPLE_ERR_BAD_RESP
;
336 if (0 == ((pBuf
[2] << 8) + pBuf
[3]))
337 return SIMPLE_ERR_BAD_RESP
;
341 /* Send MODE SENSE (6 byte) command. Returns 0 if ok, 1 if NOT READY,
342 * 2 if command not supported (then MODE SENSE(10) should be supported),
343 * 3 if field in command not supported or returns negated errno.
344 * SPC-3 sections 6.9 and 7.4 (rev 22a) [mode subpage==0] */
345 int scsiModeSense(int device
, int pagenum
, int subpagenum
, int pc
,
346 UINT8
*pBuf
, int bufLen
)
348 struct scsi_cmnd_io io_hdr
;
349 struct scsi_sense_disect sinfo
;
354 if ((bufLen
< 0) || (bufLen
> 255))
356 memset(&io_hdr
, 0, sizeof(io_hdr
));
357 memset(cdb
, 0, sizeof(cdb
));
358 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
359 io_hdr
.dxfer_len
= bufLen
;
360 io_hdr
.dxferp
= pBuf
;
362 cdb
[2] = (pc
<< 6) | (pagenum
& 0x3f);
366 io_hdr
.cmnd_len
= sizeof(cdb
);
367 io_hdr
.sensep
= sense
;
368 io_hdr
.max_sense_len
= sizeof(sense
);
369 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
371 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
374 scsi_do_sense_disect(&io_hdr
, &sinfo
);
375 status
= scsiSimpleSenseFilter(&sinfo
);
376 if (SIMPLE_ERR_TRY_AGAIN
== status
) {
377 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
380 scsi_do_sense_disect(&io_hdr
, &sinfo
);
381 status
= scsiSimpleSenseFilter(&sinfo
);
383 if ((0 == status
) && (ALL_MODE_PAGES
!= pagenum
)) {
386 offset
= scsiModePageOffset(pBuf
, bufLen
, 0);
388 return SIMPLE_ERR_BAD_RESP
;
389 else if (pagenum
!= (pBuf
[offset
] & 0x3f))
390 return SIMPLE_ERR_BAD_RESP
;
395 /* Sends a 6 byte MODE SELECT command. Assumes given pBuf is the response
396 * from a corresponding 6 byte MODE SENSE command. Such a response should
397 * have a 4 byte header followed by 0 or more 8 byte block descriptors
398 * (normally 1) and then 1 mode page. Returns 0 if ok, 1 if NOT READY,
399 * 2 if command not supported (then MODE SELECT(10) may be supported),
400 * 3 if field in command not supported, 4 if bad parameter to command
401 * or returns negated errno. SPC-3 sections 6.7 and 7.4 (rev 22a) */
402 int scsiModeSelect(int device
, int sp
, UINT8
*pBuf
, int bufLen
)
404 struct scsi_cmnd_io io_hdr
;
405 struct scsi_sense_disect sinfo
;
408 int status
, pg_offset
, pg_len
, hdr_plus_1_pg
;
410 pg_offset
= 4 + pBuf
[3];
411 if (pg_offset
+ 2 >= bufLen
)
413 pg_len
= pBuf
[pg_offset
+ 1] + 2;
414 hdr_plus_1_pg
= pg_offset
+ pg_len
;
415 if (hdr_plus_1_pg
> bufLen
)
417 pBuf
[0] = 0; /* Length of returned mode sense data reserved for SELECT */
418 pBuf
[pg_offset
] &= 0x7f; /* Mask out PS bit from byte 0 of page data */
419 memset(&io_hdr
, 0, sizeof(io_hdr
));
420 memset(cdb
, 0, sizeof(cdb
));
421 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
422 io_hdr
.dxfer_len
= hdr_plus_1_pg
;
423 io_hdr
.dxferp
= pBuf
;
424 cdb
[0] = MODE_SELECT
;
425 cdb
[1] = 0x10 | (sp
& 1); /* set PF (page format) bit always */
426 cdb
[4] = hdr_plus_1_pg
; /* make sure only one page sent */
428 io_hdr
.cmnd_len
= sizeof(cdb
);
429 io_hdr
.sensep
= sense
;
430 io_hdr
.max_sense_len
= sizeof(sense
);
431 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
433 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
436 scsi_do_sense_disect(&io_hdr
, &sinfo
);
437 return scsiSimpleSenseFilter(&sinfo
);
440 /* MODE SENSE (10 byte). Returns 0 if ok, 1 if NOT READY, 2 if command
441 * not supported (then MODE SENSE(6) might be supported), 3 if field in
442 * command not supported or returns negated errno.
443 * SPC-3 sections 6.10 and 7.4 (rev 22a) [mode subpage==0] */
444 int scsiModeSense10(int device
, int pagenum
, int subpagenum
, int pc
,
445 UINT8
*pBuf
, int bufLen
)
447 struct scsi_cmnd_io io_hdr
;
448 struct scsi_sense_disect sinfo
;
453 memset(&io_hdr
, 0, sizeof(io_hdr
));
454 memset(cdb
, 0, sizeof(cdb
));
455 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
456 io_hdr
.dxfer_len
= bufLen
;
457 io_hdr
.dxferp
= pBuf
;
458 cdb
[0] = MODE_SENSE_10
;
459 cdb
[2] = (pc
<< 6) | (pagenum
& 0x3f);
461 cdb
[7] = (bufLen
>> 8) & 0xff;
462 cdb
[8] = bufLen
& 0xff;
464 io_hdr
.cmnd_len
= sizeof(cdb
);
465 io_hdr
.sensep
= sense
;
466 io_hdr
.max_sense_len
= sizeof(sense
);
467 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
469 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
472 scsi_do_sense_disect(&io_hdr
, &sinfo
);
473 status
= scsiSimpleSenseFilter(&sinfo
);
474 if (SIMPLE_ERR_TRY_AGAIN
== status
) {
475 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
478 scsi_do_sense_disect(&io_hdr
, &sinfo
);
479 status
= scsiSimpleSenseFilter(&sinfo
);
481 if ((0 == status
) && (ALL_MODE_PAGES
!= pagenum
)) {
484 offset
= scsiModePageOffset(pBuf
, bufLen
, 1);
486 return SIMPLE_ERR_BAD_RESP
;
487 else if (pagenum
!= (pBuf
[offset
] & 0x3f))
488 return SIMPLE_ERR_BAD_RESP
;
493 /* Sends a 10 byte MODE SELECT command. Assumes given pBuf is the response
494 * from a corresponding 10 byte MODE SENSE command. Such a response should
495 * have a 8 byte header followed by 0 or more 8 byte block descriptors
496 * (normally 1) and then 1 mode page. Returns 0 if ok, 1 NOT REAFY, 2 if
497 * command not supported (then MODE SELECT(6) may be supported), 3 if field
498 * in command not supported, 4 if bad parameter to command or returns
499 * negated errno. SPC-3 sections 6.8 and 7.4 (rev 22a) */
500 int scsiModeSelect10(int device
, int sp
, UINT8
*pBuf
, int bufLen
)
502 struct scsi_cmnd_io io_hdr
;
503 struct scsi_sense_disect sinfo
;
506 int status
, pg_offset
, pg_len
, hdr_plus_1_pg
;
508 pg_offset
= 8 + (pBuf
[6] << 8) + pBuf
[7];
509 if (pg_offset
+ 2 >= bufLen
)
511 pg_len
= pBuf
[pg_offset
+ 1] + 2;
512 hdr_plus_1_pg
= pg_offset
+ pg_len
;
513 if (hdr_plus_1_pg
> bufLen
)
516 pBuf
[1] = 0; /* Length of returned mode sense data reserved for SELECT */
517 pBuf
[pg_offset
] &= 0x7f; /* Mask out PS bit from byte 0 of page data */
518 memset(&io_hdr
, 0, sizeof(io_hdr
));
519 memset(cdb
, 0, sizeof(cdb
));
520 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
521 io_hdr
.dxfer_len
= hdr_plus_1_pg
;
522 io_hdr
.dxferp
= pBuf
;
523 cdb
[0] = MODE_SELECT_10
;
524 cdb
[1] = 0x10 | (sp
& 1); /* set PF (page format) bit always */
525 cdb
[8] = hdr_plus_1_pg
; /* make sure only one page sent */
527 io_hdr
.cmnd_len
= sizeof(cdb
);
528 io_hdr
.sensep
= sense
;
529 io_hdr
.max_sense_len
= sizeof(sense
);
530 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
532 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
535 scsi_do_sense_disect(&io_hdr
, &sinfo
);
536 return scsiSimpleSenseFilter(&sinfo
);
539 /* Standard INQUIRY returns 0 for ok, anything else is a major problem.
540 * bufLen should be 36 for unsafe devices (like USB mass storage stuff)
541 * otherwise they can lock up! SPC-3 sections 6.4 and 7.6 (rev 22a) */
542 int scsiStdInquiry(int device
, UINT8
*pBuf
, int bufLen
)
544 struct scsi_sense_disect sinfo
;
545 struct scsi_cmnd_io io_hdr
;
550 if ((bufLen
< 0) || (bufLen
> 255))
552 memset(&io_hdr
, 0, sizeof(io_hdr
));
553 memset(cdb
, 0, sizeof(cdb
));
554 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
555 io_hdr
.dxfer_len
= bufLen
;
556 io_hdr
.dxferp
= pBuf
;
560 io_hdr
.cmnd_len
= sizeof(cdb
);
561 io_hdr
.sensep
= sense
;
562 io_hdr
.max_sense_len
= sizeof(sense
);
563 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
565 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
568 scsi_do_sense_disect(&io_hdr
, &sinfo
);
569 return scsiSimpleSenseFilter(&sinfo
);
572 /* INQUIRY to fetch Vital Page Data. Returns 0 if ok, 1 if NOT READY
573 * (unlikely), 2 if command not supported, 3 if field in command not
574 * supported, 5 if response indicates that EVPD bit ignored or returns
575 * negated errno. SPC-3 section 6.4 and 7.6 (rev 22a) */
576 int scsiInquiryVpd(int device
, int vpd_page
, UINT8
*pBuf
, int bufLen
)
578 struct scsi_cmnd_io io_hdr
;
579 struct scsi_sense_disect sinfo
;
584 if ((bufLen
< 0) || (bufLen
> 255))
586 memset(&io_hdr
, 0, sizeof(io_hdr
));
587 memset(cdb
, 0, sizeof(cdb
));
590 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
591 io_hdr
.dxfer_len
= bufLen
;
592 io_hdr
.dxferp
= pBuf
;
594 cdb
[1] = 0x1; /* set EVPD bit (enable Vital Product Data) */
598 io_hdr
.cmnd_len
= sizeof(cdb
);
599 io_hdr
.sensep
= sense
;
600 io_hdr
.max_sense_len
= sizeof(sense
);
601 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
603 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
606 scsi_do_sense_disect(&io_hdr
, &sinfo
);
607 if ((res
= scsiSimpleSenseFilter(&sinfo
)))
609 /* Guard against devices that ignore EVPD bit and do standard INQUIRY */
611 if (vpd_page
== pBuf
[1]) {
612 if ((0x80 == vpd_page
) && (bufLen
> 2) && (0x0 != pBuf
[2]))
613 return SIMPLE_ERR_BAD_RESP
;
615 return SIMPLE_ERR_BAD_RESP
;
620 /* REQUEST SENSE command. Returns 0 if ok, anything else major problem.
621 * SPC-3 section 6.27 (rev 22a) */
622 int scsiRequestSense(int device
, struct scsi_sense_disect
* sense_info
)
624 struct scsi_cmnd_io io_hdr
;
631 memset(&io_hdr
, 0, sizeof(io_hdr
));
632 memset(cdb
, 0, sizeof(cdb
));
633 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
634 io_hdr
.dxfer_len
= sizeof(buff
);
635 io_hdr
.dxferp
= buff
;
636 cdb
[0] = REQUEST_SENSE
;
637 cdb
[4] = sizeof(buff
);
639 io_hdr
.cmnd_len
= sizeof(cdb
);
640 io_hdr
.sensep
= sense
;
641 io_hdr
.max_sense_len
= sizeof(sense
);
642 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
644 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
645 if ((0 == status
) && (sense_info
)) {
646 ecode
= buff
[0] & 0x7f;
647 sense_info
->error_code
= ecode
;
648 sense_info
->sense_key
= buff
[2] & 0xf;
650 sense_info
->ascq
= 0;
651 if ((0x70 == ecode
) || (0x71 == ecode
)) {
654 sense_info
->asc
= buff
[12];
655 sense_info
->ascq
= buff
[13];
662 /* SEND DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if command
663 * not supported, 3 if field in command not supported or returns negated
664 * errno. SPC-3 section 6.28 (rev 22a) */
665 int scsiSendDiagnostic(int device
, int functioncode
, UINT8
*pBuf
, int bufLen
)
667 struct scsi_cmnd_io io_hdr
;
668 struct scsi_sense_disect sinfo
;
673 memset(&io_hdr
, 0, sizeof(io_hdr
));
674 memset(cdb
, 0, sizeof(cdb
));
675 io_hdr
.dxfer_dir
= bufLen
? DXFER_TO_DEVICE
: DXFER_NONE
;
676 io_hdr
.dxfer_len
= bufLen
;
677 io_hdr
.dxferp
= pBuf
;
678 cdb
[0] = SEND_DIAGNOSTIC
;
679 if (SCSI_DIAG_DEF_SELF_TEST
== functioncode
)
680 cdb
[1] = 0x4; /* SelfTest bit */
681 else if (SCSI_DIAG_NO_SELF_TEST
!= functioncode
)
682 cdb
[1] = (functioncode
& 0x7) << 5; /* SelfTest _code_ */
683 else /* SCSI_DIAG_NO_SELF_TEST == functioncode */
684 cdb
[1] = 0x10; /* PF bit */
685 cdb
[3] = (bufLen
>> 8) & 0xff;
686 cdb
[4] = bufLen
& 0xff;
688 io_hdr
.cmnd_len
= sizeof(cdb
);
689 io_hdr
.sensep
= sense
;
690 io_hdr
.max_sense_len
= sizeof(sense
);
691 /* worst case is an extended foreground self test on a big disk */
692 io_hdr
.timeout
= SCSI_TIMEOUT_SELF_TEST
;
694 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
697 scsi_do_sense_disect(&io_hdr
, &sinfo
);
698 return scsiSimpleSenseFilter(&sinfo
);
701 /* RECEIVE DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if
702 * command not supported, 3 if field in command not supported or returns
703 * negated errno. SPC-3 section 6.18 (rev 22a) */
704 int scsiReceiveDiagnostic(int device
, int pcv
, int pagenum
, UINT8
*pBuf
,
707 struct scsi_cmnd_io io_hdr
;
708 struct scsi_sense_disect sinfo
;
713 memset(&io_hdr
, 0, sizeof(io_hdr
));
714 memset(cdb
, 0, sizeof(cdb
));
715 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
716 io_hdr
.dxfer_len
= bufLen
;
717 io_hdr
.dxferp
= pBuf
;
718 cdb
[0] = RECEIVE_DIAGNOSTIC
;
721 cdb
[3] = (bufLen
>> 8) & 0xff;
722 cdb
[4] = bufLen
& 0xff;
724 io_hdr
.cmnd_len
= sizeof(cdb
);
725 io_hdr
.sensep
= sense
;
726 io_hdr
.max_sense_len
= sizeof(sense
);
727 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
729 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
732 scsi_do_sense_disect(&io_hdr
, &sinfo
);
733 return scsiSimpleSenseFilter(&sinfo
);
736 /* TEST UNIT READY command. SPC-3 section 6.33 (rev 22a) */
737 static int _testunitready(int device
, struct scsi_sense_disect
* sinfo
)
739 struct scsi_cmnd_io io_hdr
;
744 memset(&io_hdr
, 0, sizeof(io_hdr
));
745 memset(cdb
, 0, sizeof(cdb
));
746 io_hdr
.dxfer_dir
= DXFER_NONE
;
747 io_hdr
.dxfer_len
= 0;
748 io_hdr
.dxferp
= NULL
;
749 cdb
[0] = TEST_UNIT_READY
;
751 io_hdr
.cmnd_len
= sizeof(cdb
);
752 io_hdr
.sensep
= sense
;
753 io_hdr
.max_sense_len
= sizeof(sense
);
754 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
756 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
759 scsi_do_sense_disect(&io_hdr
, sinfo
);
763 /* Returns 0 for device responds and media ready, 1 for device responds and
764 media not ready, or returns a negated errno value */
765 int scsiTestUnitReady(int device
)
767 struct scsi_sense_disect sinfo
;
770 status
= _testunitready(device
, &sinfo
);
773 status
= scsiSimpleSenseFilter(&sinfo
);
774 if (SIMPLE_ERR_TRY_AGAIN
== status
) {
775 /* power on reset, media changed, ok ... try again */
776 status
= _testunitready(device
, &sinfo
);
779 status
= scsiSimpleSenseFilter(&sinfo
);
784 /* READ DEFECT (10) command. Returns 0 if ok, 1 if NOT READY, 2 if
785 * command not supported, 3 if field in command not supported or returns
786 * negated errno. SBC-2 section 5.12 (rev 16) */
787 int scsiReadDefect10(int device
, int req_plist
, int req_glist
, int dl_format
,
788 UINT8
*pBuf
, int bufLen
)
790 struct scsi_cmnd_io io_hdr
;
791 struct scsi_sense_disect sinfo
;
796 memset(&io_hdr
, 0, sizeof(io_hdr
));
797 memset(cdb
, 0, sizeof(cdb
));
798 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
799 io_hdr
.dxfer_len
= bufLen
;
800 io_hdr
.dxferp
= pBuf
;
801 cdb
[0] = READ_DEFECT_10
;
802 cdb
[2] = (unsigned char)(((req_plist
<< 4) & 0x10) |
803 ((req_glist
<< 3) & 0x8) | (dl_format
& 0x7));
804 cdb
[7] = (bufLen
>> 8) & 0xff;
805 cdb
[8] = bufLen
& 0xff;
807 io_hdr
.cmnd_len
= sizeof(cdb
);
808 io_hdr
.sensep
= sense
;
809 io_hdr
.max_sense_len
= sizeof(sense
);
810 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
812 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
815 scsi_do_sense_disect(&io_hdr
, &sinfo
);
816 return scsiSimpleSenseFilter(&sinfo
);
819 /* Offset into mode sense (6 or 10 byte) response that actual mode page
820 * starts at (relative to resp[0]). Returns -1 if problem */
821 int scsiModePageOffset(const UINT8
* resp
, int len
, int modese_len
)
823 int resp_len
, bd_len
;
827 if (10 == modese_len
) {
828 resp_len
= (resp
[0] << 8) + resp
[1] + 2;
829 bd_len
= (resp
[6] << 8) + resp
[7];
832 resp_len
= resp
[0] + 1;
836 if ((offset
+ 2) > len
) {
837 pout("scsiModePageOffset: raw_curr too small, offset=%d "
838 "resp_len=%d bd_len=%d\n", offset
, resp_len
, bd_len
);
840 } else if ((offset
+ 2) > resp_len
) {
841 if ((resp_len
> 2) || con
->reportscsiioctl
)
842 pout("scsiModePageOffset: response length too short, "
843 "resp_len=%d offset=%d bd_len=%d\n", resp_len
,
851 /* IEC mode page byte 2 bit masks */
852 #define DEXCPT_ENABLE 0x08
853 #define EWASC_ENABLE 0x10
854 #define DEXCPT_DISABLE 0xf7
855 #define EWASC_DISABLE 0xef
856 #define TEST_DISABLE 0xfb
858 /* Fetches the Informational Exceptions Control mode page. First tries
859 * the 6 byte MODE SENSE command and if that fails with an illegal opcode
860 * tries a 10 byte MODE SENSE command. Returns 0 if successful, a positive
861 * number if a known error (see SIMPLE_ERR_ ...) or a negative errno
863 int scsiFetchIECmpage(int device
, struct scsi_iec_mode_page
*iecp
, int modese_len
)
867 memset(iecp
, 0, sizeof(*iecp
));
868 iecp
->modese_len
= modese_len
;
869 iecp
->requestedCurrent
= 1;
870 if (iecp
->modese_len
<= 6) {
871 if ((err
= scsiModeSense(device
, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE
,
872 0, MPAGE_CONTROL_CURRENT
,
873 iecp
->raw_curr
, sizeof(iecp
->raw_curr
)))) {
874 if (SIMPLE_ERR_BAD_OPCODE
== err
)
875 iecp
->modese_len
= 10;
877 iecp
->modese_len
= 0;
880 } else if (0 == iecp
->modese_len
)
881 iecp
->modese_len
= 6;
883 if (10 == iecp
->modese_len
) {
884 err
= scsiModeSense10(device
, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE
,
885 0, MPAGE_CONTROL_CURRENT
,
886 iecp
->raw_curr
, sizeof(iecp
->raw_curr
));
888 iecp
->modese_len
= 0;
892 iecp
->gotCurrent
= 1;
893 iecp
->requestedChangeable
= 1;
894 if (10 == iecp
->modese_len
)
895 err
= scsiModeSense10(device
, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE
,
896 0, MPAGE_CONTROL_CHANGEABLE
,
897 iecp
->raw_chg
, sizeof(iecp
->raw_chg
));
898 else if (6 == iecp
->modese_len
)
899 err
= scsiModeSense(device
, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE
,
900 0, MPAGE_CONTROL_CHANGEABLE
,
901 iecp
->raw_chg
, sizeof(iecp
->raw_chg
));
904 iecp
->gotChangeable
= 1;
908 int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page
*iecp
)
912 if (iecp
&& iecp
->gotCurrent
) {
913 offset
= scsiModePageOffset(iecp
->raw_curr
, sizeof(iecp
->raw_curr
),
916 return (iecp
->raw_curr
[offset
+ 2] & DEXCPT_ENABLE
) ? 0 : 1;
923 int scsi_IsWarningEnabled(const struct scsi_iec_mode_page
*iecp
)
927 if (iecp
&& iecp
->gotCurrent
) {
928 offset
= scsiModePageOffset(iecp
->raw_curr
, sizeof(iecp
->raw_curr
),
931 return (iecp
->raw_curr
[offset
+ 2] & EWASC_ENABLE
) ? 1 : 0;
938 /* set EWASC and clear PERF, EBF, DEXCPT TEST and LOGERR */
939 #define SCSI_IEC_MP_BYTE2_ENABLED 0x10
940 #define SCSI_IEC_MP_BYTE2_TEST_MASK 0x4
941 /* exception/warning via an unrequested REQUEST SENSE command */
942 #define SCSI_IEC_MP_MRIE 6
943 #define SCSI_IEC_MP_INTERVAL_T 0
944 #define SCSI_IEC_MP_REPORT_COUNT 1
946 /* Try to set (or clear) both Exception Control and Warning in the IE
947 * mode page subject to the "changeable" mask. The object pointed to
948 * by iecp is (possibly) inaccurate after this call, therefore
949 * scsiFetchIECmpage() should be called again if the IEC mode page
950 * is to be re-examined.
951 * When -r ioctl is invoked 3 or more time on 'smartctl -s on ...'
952 * then set the TEST bit (causes asc,ascq pair of 0x5d,0xff). */
953 int scsiSetExceptionControlAndWarning(int device
, int enabled
,
954 const struct scsi_iec_mode_page
*iecp
)
956 int k
, offset
, resp_len
;
958 UINT8 rout
[SCSI_IECMP_RAW_LEN
];
959 int sp
, eCEnabled
, wEnabled
;
961 if ((! iecp
) || (! iecp
->gotCurrent
))
963 offset
= scsiModePageOffset(iecp
->raw_curr
, sizeof(iecp
->raw_curr
),
967 memcpy(rout
, iecp
->raw_curr
, SCSI_IECMP_RAW_LEN
);
968 if (10 == iecp
->modese_len
) {
969 resp_len
= (rout
[0] << 8) + rout
[1] + 2;
970 rout
[3] &= 0xef; /* for disks mask out DPOFUA bit */
972 resp_len
= rout
[0] + 1;
973 rout
[2] &= 0xef; /* for disks mask out DPOFUA bit */
975 sp
= (rout
[offset
] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
977 rout
[offset
+ 2] = SCSI_IEC_MP_BYTE2_ENABLED
;
978 if (con
->reportscsiioctl
> 2)
979 rout
[offset
+ 2] |= SCSI_IEC_MP_BYTE2_TEST_MASK
;
980 rout
[offset
+ 3] = SCSI_IEC_MP_MRIE
;
981 rout
[offset
+ 4] = (SCSI_IEC_MP_INTERVAL_T
>> 24) & 0xff;
982 rout
[offset
+ 5] = (SCSI_IEC_MP_INTERVAL_T
>> 16) & 0xff;
983 rout
[offset
+ 6] = (SCSI_IEC_MP_INTERVAL_T
>> 8) & 0xff;
984 rout
[offset
+ 7] = SCSI_IEC_MP_INTERVAL_T
& 0xff;
985 rout
[offset
+ 8] = (SCSI_IEC_MP_REPORT_COUNT
>> 24) & 0xff;
986 rout
[offset
+ 9] = (SCSI_IEC_MP_REPORT_COUNT
>> 16) & 0xff;
987 rout
[offset
+ 10] = (SCSI_IEC_MP_REPORT_COUNT
>> 8) & 0xff;
988 rout
[offset
+ 11] = SCSI_IEC_MP_REPORT_COUNT
& 0xff;
989 if (iecp
->gotChangeable
) {
990 UINT8 chg2
= iecp
->raw_chg
[offset
+ 2];
992 rout
[offset
+ 2] = chg2
? (rout
[offset
+ 2] & chg2
) :
993 iecp
->raw_curr
[offset
+ 2];
994 for (k
= 3; k
< 12; ++k
) {
995 if (0 == iecp
->raw_chg
[offset
+ k
])
996 rout
[offset
+ k
] = iecp
->raw_curr
[offset
+ k
];
999 if (0 == memcmp(&rout
[offset
+ 2], &iecp
->raw_chg
[offset
+ 2], 10)) {
1000 if (con
->reportscsiioctl
> 0)
1001 pout("scsiSetExceptionControlAndWarning: already enabled\n");
1004 } else { /* disabling Exception Control and (temperature) Warnings */
1005 eCEnabled
= (rout
[offset
+ 2] & DEXCPT_ENABLE
) ? 0 : 1;
1006 wEnabled
= (rout
[offset
+ 2] & EWASC_ENABLE
) ? 1 : 0;
1007 if ((! eCEnabled
) && (! wEnabled
)) {
1008 if (con
->reportscsiioctl
> 0)
1009 pout("scsiSetExceptionControlAndWarning: already disabled\n");
1010 return 0; /* nothing to do, leave other setting alone */
1013 rout
[offset
+ 2] &= EWASC_DISABLE
;
1015 if (iecp
->gotChangeable
&&
1016 (iecp
->raw_chg
[offset
+ 2] & DEXCPT_ENABLE
))
1017 rout
[offset
+ 2] |= DEXCPT_ENABLE
;
1018 rout
[offset
+ 2] &= TEST_DISABLE
;/* clear TEST bit for spec */
1021 if (10 == iecp
->modese_len
)
1022 err
= scsiModeSelect10(device
, sp
, rout
, resp_len
);
1023 else if (6 == iecp
->modese_len
)
1024 err
= scsiModeSelect(device
, sp
, rout
, resp_len
);
1028 int scsiGetTemp(int device
, UINT8
*currenttemp
, UINT8
*triptemp
)
1033 memset(tBuf
, 0, sizeof(tBuf
));
1034 if ((err
= scsiLogSense(device
, TEMPERATURE_LPAGE
, 0, tBuf
,
1035 sizeof(tBuf
), 0))) {
1038 pout("Log Sense for temperature failed [%s]\n", scsiErrString(err
));
1041 *currenttemp
= tBuf
[9];
1042 *triptemp
= tBuf
[15];
1046 /* Read informational exception log page or Request Sense response.
1047 * Fetching asc/ascq code potentially flagging an exception or warning.
1048 * Returns 0 if ok, else error number. A current temperature of 255
1049 * (Celsius) implies that the temperature not available. */
1050 int scsiCheckIE(int device
, int hasIELogPage
, int hasTempLogPage
,
1051 UINT8
*asc
, UINT8
*ascq
, UINT8
*currenttemp
,
1055 struct scsi_sense_disect sense_info
;
1057 int temperatureSet
= 0;
1058 unsigned short pagesize
;
1059 UINT8 currTemp
, trTemp
;
1065 memset(tBuf
,0,sizeof(tBuf
)); // need to clear stack space of junk
1066 memset(&sense_info
, 0, sizeof(sense_info
));
1068 if ((err
= scsiLogSense(device
, IE_LPAGE
, 0, tBuf
,
1069 sizeof(tBuf
), 0))) {
1070 pout("Log Sense failed, IE page [%s]\n", scsiErrString(err
));
1073 // pull out page size from response, don't forget to add 4
1074 pagesize
= (unsigned short) ((tBuf
[2] << 8) | tBuf
[3]) + 4;
1075 if ((pagesize
< 4) || tBuf
[4] || tBuf
[5]) {
1076 pout("Log Sense failed, IE page, bad parameter code or length\n");
1077 return SIMPLE_ERR_BAD_PARAM
;
1080 sense_info
.asc
= tBuf
[8];
1081 sense_info
.ascq
= tBuf
[9];
1082 if (! hasTempLogPage
) {
1084 *currenttemp
= tBuf
[10];
1085 if (tBuf
[7] > 3) /* IBM extension in SMART (IE) lpage */
1086 *triptemp
= tBuf
[11];
1090 if (0 == sense_info
.asc
) {
1091 /* ties in with MRIE field of 6 in IEC mode page (0x1c) */
1092 if ((err
= scsiRequestSense(device
, &sense_info
))) {
1093 pout("Request Sense failed, [%s]\n", scsiErrString(err
));
1097 *asc
= sense_info
.asc
;
1098 *ascq
= sense_info
.ascq
;
1099 if ((! temperatureSet
) && hasTempLogPage
) {
1100 if (0 == scsiGetTemp(device
, &currTemp
, &trTemp
)) {
1101 *currenttemp
= currTemp
;
1108 // The first character (W, C, I) tells the severity
1109 static const char * TapeAlertsMessageTable
[]= {
1112 "W: The tape drive is having problems reading data. No data has been lost,\n"
1113 " but there has been a reduction in the performance of the tape.",
1115 "W: The tape drive is having problems writing data. No data has been lost,\n"
1116 " but there has been a reduction in the capacity of the tape.",
1118 "W: The operation has stopped because an error has occurred while reading\n"
1119 " or writing data that the drive cannot correct.",
1121 "C: Your data is at risk:\n"
1122 " 1. Copy any data you require from this tape. \n"
1123 " 2. Do not use this tape again.\n"
1124 " 3. Restart the operation with a different tape.",
1126 "C: The tape is damaged or the drive is faulty. Call the tape drive\n"
1127 " supplier helpline.",
1129 "C: The tape is from a faulty batch or the tape drive is faulty:\n"
1130 " 1. Use a good tape to test the drive.\n"
1131 " 2. If problem persists, call the tape drive supplier helpline.",
1133 "W: The tape cartridge has reached the end of its calculated useful life:\n"
1134 " 1. Copy data you need to another tape.\n"
1135 " 2. Discard the old tape.",
1137 "W: The tape cartridge is not data-grade. Any data you back up to the tape\n"
1138 " is at risk. Replace the cartridge with a data-grade tape.",
1140 "C: You are trying to write to a write-protected cartridge. Remove the\n"
1141 " write-protection or use another tape.",
1143 "I: You cannot eject the cartridge because the tape drive is in use. Wait\n"
1144 " until the operation is complete before ejecting the cartridge.",
1146 "I: The tape in the drive is a cleaning cartridge.",
1148 "I: You have tried to load a cartridge of a type which is not supported\n"
1151 "C: The operation has failed because the tape in the drive has experienced\n"
1152 " a mechanical failure:\n"
1153 " 1. Discard the old tape.\n"
1154 " 2. Restart the operation with a different tape.",
1156 "C: The operation has failed because the tape in the drive has experienced\n"
1157 " a mechanical failure:\n"
1158 " 1. Do not attempt to extract the tape cartridge\n"
1159 " 2. Call the tape drive supplier helpline.",
1161 "W: The memory in the tape cartridge has failed, which reduces\n"
1162 " performance. Do not use the cartridge for further write operations.",
1164 "C: The operation has failed because the tape cartridge was manually\n"
1165 " de-mounted while the tape drive was actively writing or reading.",
1167 "W: You have loaded a cartridge of a type that is read-only in this drive.\n"
1168 " The cartridge will appear as write-protected.",
1170 "W: The tape directory on the tape cartridge has been corrupted. File\n"
1171 " search performance will be degraded. The tape directory can be rebuilt\n"
1172 " by reading all the data on the cartridge.",
1174 "I: The tape cartridge is nearing the end of its calculated life. It is\n"
1175 " recommended that you:\n"
1176 " 1. Use another tape cartridge for your next backup.\n"
1177 " 2. Store this tape in a safe place in case you need to restore "
1180 "C: The tape drive needs cleaning:\n"
1181 " 1. If the operation has stopped, eject the tape and clean the drive.\n"
1182 " 2. If the operation has not stopped, wait for it to finish and then\n"
1183 " clean the drive.\n"
1184 " Check the tape drive users manual for device specific cleaning instructions.",
1186 "W: The tape drive is due for routine cleaning:\n"
1187 " 1. Wait for the current operation to finish.\n"
1188 " 2. The use a cleaning cartridge.\n"
1189 " Check the tape drive users manual for device specific cleaning instructions.",
1191 "C: The last cleaning cartridge used in the tape drive has worn out:\n"
1192 " 1. Discard the worn out cleaning cartridge.\n"
1193 " 2. Wait for the current operation to finish.\n"
1194 " 3. Then use a new cleaning cartridge.",
1196 "C: The last cleaning cartridge used in the tape drive was an invalid\n"
1198 " 1. Do not use this cleaning cartridge in this drive.\n"
1199 " 2. Wait for the current operation to finish.\n"
1200 " 3. Then use a new cleaning cartridge.",
1202 "W: The tape drive has requested a retention operation",
1204 "W: A redundant interface port on the tape drive has failed",
1206 "W: A tape drive cooling fan has failed",
1208 "W: A redundant power supply has failed inside the tape drive enclosure.\n"
1209 " Check the enclosure users manual for instructions on replacing the\n"
1210 " failed power supply.",
1212 "W: The tape drive power consumption is outside the specified range.",
1214 "W: Preventive maintenance of the tape drive is required. Check the tape\n"
1215 " drive users manual for device specific preventive maintenance\n"
1216 " tasks or call the tape drive supplier helpline.",
1218 "C: The tape drive has a hardware fault:\n"
1219 " 1. Eject the tape or magazine.\n"
1220 " 2. Reset the drive.\n"
1221 " 3. Restart the operation.",
1223 "C: The tape drive has a hardware fault:\n"
1224 " 1. Turn the tape drive off and then on again.\n"
1225 " 2. Restart the operation.\n"
1226 " 3. If the problem persists, call the tape drive supplier helpline.",
1228 "W: The tape drive has a problem with the application client interface:\n"
1229 " 1. Check the cables and cable connections.\n"
1230 " 2. Restart the operation.",
1232 "C: The operation has failed:\n"
1233 " 1. Eject the tape or magazine.\n"
1234 " 2. Insert the tape or magazine again.\n"
1235 " 3. Restart the operation.",
1237 "W: The firmware download has failed because you have tried to use the\n"
1238 " incorrect firmware for this tape drive. Obtain the correct\n"
1239 " firmware and try again.",
1241 "W: Environmental conditions inside the tape drive are outside the\n"
1242 " specified humidity range.",
1244 "W: Environmental conditions inside the tape drive are outside the\n"
1245 " specified temperature range.",
1247 "W: The voltage supply to the tape drive is outside the specified range.",
1249 "C: A hardware failure of the tape drive is predicted. Call the tape\n"
1250 " drive supplier helpline.",
1252 "W: The tape drive may have a hardware fault. Run extended diagnostics to\n"
1253 " verify and diagnose the problem. Check the tape drive users manual for\n"
1254 " device specific instructions on running extended diagnostic tests.",
1256 "C: The changer mechanism is having difficulty communicating with the tape\n"
1258 " 1. Turn the autoloader off then on.\n"
1259 " 2. Restart the operation.\n"
1260 " 3. If problem persists, call the tape drive supplier helpline.",
1262 "C: A tape has been left in the autoloader by a previous hardware fault:\n"
1263 " 1. Insert an empty magazine to clear the fault.\n"
1264 " 2. If the fault does not clear, turn the autoloader off and then\n"
1266 " 3. If the problem persists, call the tape drive supplier helpline.",
1268 "W: There is a problem with the autoloader mechanism.",
1270 "C: The operation has failed because the autoloader door is open:\n"
1271 " 1. Clear any obstructions from the autoloader door.\n"
1272 " 2. Eject the magazine and then insert it again.\n"
1273 " 3. If the fault does not clear, turn the autoloader off and then\n"
1275 " 4. If the problem persists, call the tape drive supplier helpline.",
1277 "C: The autoloader has a hardware fault:\n"
1278 " 1. Turn the autoloader off and then on again.\n"
1279 " 2. Restart the operation.\n"
1280 " 3. If the problem persists, call the tape drive supplier helpline.\n"
1281 " Check the autoloader users manual for device specific instructions\n"
1282 " on turning the device power on and off.",
1284 "C: The autoloader cannot operate without the magazine,\n"
1285 " 1. Insert the magazine into the autoloader.\n"
1286 " 2. Restart the operation.",
1288 "W: A hardware failure of the changer mechanism is predicted. Call the\n"
1289 " tape drive supplier helpline.",
1297 "W: Media statistics have been lost at some time in the past",
1299 "W: The tape directory on the tape cartridge just unloaded has been\n"
1300 " corrupted. File search performance will be degraded. The tape\n"
1301 " directory can be rebuilt by reading all the data.",
1303 "C: The tape just unloaded could not write its system area successfully:\n"
1304 " 1. Copy data to another tape cartridge.\n"
1305 " 2. Discard the old cartridge.",
1307 "C: The tape system are could not be read successfully at load time:\n"
1308 " 1. Copy data to another tape cartridge.\n",
1310 "C: The start or data could not be found on the tape:\n"
1311 " 1. Check you are using the correct format tape.\n"
1312 " 2. Discard the tape or return the tape to your supplier",
1314 "C: The operation has failed because the media cannot be loaded\n"
1316 " 1. Remove the cartridge, inspect it as specified in the product\n"
1317 " manual, and retry the operation.\n"
1318 " 2. If the problem persists, call the tape drive supplier help line.",
1320 "C: The operation has failed because the medium cannot be unloaded:\n"
1321 " 1. Do not attempt to extract the tape cartridge.\n"
1322 " 2. Call the tape driver supplier help line.",
1324 "C: The tape drive has a problem with the automation interface:\n"
1325 " 1. Check the power to the automation system.\n"
1326 " 2. Check the cables and cable connections.\n"
1327 " 3. Call the supplier help line if problem persists.",
1329 "W: The tape drive has reset itself due to a detected firmware\n"
1330 " fault. If problem persists, call the supplier help line.",
1333 const char * scsiTapeAlertsTapeDevice(unsigned short code
)
1335 const int num
= sizeof(TapeAlertsMessageTable
) /
1336 sizeof(TapeAlertsMessageTable
[0]);
1338 return (code
< num
) ? TapeAlertsMessageTable
[code
] : "Unknown Alert";
1341 // The first character (W, C, I) tells the severity
1342 static const char * ChangerTapeAlertsMessageTable
[]= {
1345 "C: The library mechanism is having difficulty communicating with the\n"
1347 " 1. Turn the library off then on.\n"
1348 " 2. Restart the operation.\n"
1349 " 3. If the problem persists, call the library supplier help line.",
1351 "W: There is a problem with the library mechanism. If problem persists,\n"
1352 " call the library supplier help line.",
1354 "C: The library has a hardware fault:\n"
1355 " 1. Reset the library.\n"
1356 " 2. Restart the operation.\n"
1357 " Check the library users manual for device specific instructions on resetting\n"
1360 "C: The library has a hardware fault:\n"
1361 " 1. Turn the library off then on again.\n"
1362 " 2. Restart the operation.\n"
1363 " 3. If the problem persists, call the library supplier help line.\n"
1364 " Check the library users manual for device specific instructions on turning the\n"
1365 " device power on and off.",
1367 "W: The library mechanism may have a hardware fault.\n"
1368 " Run extended diagnostics to verify and diagnose the problem. Check the library\n"
1369 " users manual for device specific instructions on running extended diagnostic\n"
1372 "C: The library has a problem with the host interface:\n"
1373 " 1. Check the cables and connections.\n"
1374 " 2. Restart the operation.",
1376 "W: A hardware failure of the library is predicted. Call the library\n"
1377 " supplier help line.",
1379 "W: Preventive maintenance of the library is required.\n"
1380 " Check the library users manual for device specific preventative maintenance\n"
1381 " tasks, or call your library supplier help line.",
1383 "C: General environmental conditions inside the library are outside the\n"
1384 " specified humidity range.",
1386 "C: General environmental conditions inside the library are outside the\n"
1387 " specified temperature range.",
1389 "C: The voltage supply to the library is outside the specified range.\n"
1390 " There is a potential problem with the power supply or failure of\n"
1391 " a redundant power supply.",
1393 "C: A cartridge has been left inside the library by a previous hardware\n"
1395 " 1. Insert an empty magazine to clear the fault.\n"
1396 " 2. If the fault does not clear, turn the library off and then on again.\n"
1397 " 3. If the problem persists, call the library supplier help line.",
1399 "W: There is a potential problem with the drive ejecting cartridges or\n"
1400 " with the library mechanism picking a cartridge from a slot.\n"
1401 " 1. No action needs to be taken at this time.\n"
1402 " 2. If the problem persists, call the library supplier help line.",
1404 "W: There is a potential problem with the library mechanism placing a\n"
1405 " cartridge into a slot.\n"
1406 " 1. No action needs to be taken at this time.\n"
1407 " 2. If the problem persists, call the library supplier help line.",
1409 "W: There is a potential problem with the drive or the library mechanism\n"
1410 " loading cartridges, or an incompatible cartridge.",
1412 "C: The library has failed because the door is open:\n"
1413 " 1. Clear any obstructions from the library door.\n"
1414 " 2. Close the library door.\n"
1415 " 3. If the problem persists, call the library supplier help line.",
1417 "C: There is a mechanical problem with the library media import/export\n"
1420 "C: The library cannot operate without the magazine.\n"
1421 " 1. Insert the magazine into the library.\n"
1422 " 2. Restart the operation.",
1424 "W: Library security has been compromised.",
1426 "I: The library security mode has been changed.\n"
1427 " The library has either been put into secure mode, or the library has exited\n"
1428 " the secure mode.\n"
1429 " This is for information purposes only. No action is required.",
1431 "I: The library has been manually turned offline and is unavailable for use.",
1433 "I: A drive inside the library has been taken offline.\n"
1434 " This is for information purposes only. No action is required.",
1436 "W: There is a potential problem with the bar code label or the scanner\n"
1437 " hardware in the library mechanism.\n"
1438 " 1. No action needs to be taken at this time.\n"
1439 " 2. If the problem persists, call the library supplier help line.",
1441 "C: The library has detected an inconsistency in its inventory.\n"
1442 " 1. Redo the library inventory to correct inconsistency.\n"
1443 " 2. Restart the operation.\n"
1444 " Check the applications users manual or the hardware users manual for\n"
1445 " specific instructions on redoing the library inventory.",
1447 "W: A library operation has been attempted that is invalid at this time.",
1449 "W: A redundant interface port on the library has failed.",
1451 "W: A library cooling fan has failed.",
1453 "W: A redundant power supply has failed inside the library. Check the\n"
1454 " library users manual for instructions on replacing the failed power supply.",
1456 "W: The library power consumption is outside the specified range.",
1458 "C: A failure has occurred in the cartridge pass-through mechanism between\n"
1459 " two library modules.",
1461 "C: A cartridge has been left in the pass-through mechanism from a\n"
1462 " previous hardware fault. Check the library users guide for instructions on\n"
1463 " clearing this fault.",
1465 "I: The library was unable to read the bar code on a cartridge.",
1468 const char * scsiTapeAlertsChangerDevice(unsigned short code
)
1470 const int num
= sizeof(ChangerTapeAlertsMessageTable
) /
1471 sizeof(ChangerTapeAlertsMessageTable
[0]);
1473 return (code
< num
) ? ChangerTapeAlertsMessageTable
[code
] : "Unknown Alert";
1477 /* this is a subset of the SCSI additional sense code strings indexed
1478 * by "ascq" for the case when asc==SCSI_ASC_IMPENDING_FAILURE (0x5d)
1480 static const char * strs_for_asc_5d
[] = {
1481 /* 0x00 */ "FAILURE PREDICTION THRESHOLD EXCEEDED",
1482 "MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED",
1483 "LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED",
1484 "SPARE AREA EXHAUSTION PREDICTION THRESHOLD EXCEEDED",
1497 /* 0x10 */ "HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1498 "HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1499 "HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1500 "HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1501 "HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1502 "HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1503 "HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1504 "HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
1505 "HARDWARE IMPENDING FAILURE CONTROLLER DETECTED",
1506 "HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1507 "HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
1508 "HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
1509 "HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1513 /* 0x20 */ "CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1514 "CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1515 "CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1516 "CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1517 "CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1518 "CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1519 "CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1520 "CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS",
1521 "CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED",
1522 "CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1523 "CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE",
1524 "CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT",
1525 "CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1529 /* 0x30 */ "DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1530 "DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1531 "DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1532 "DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1533 "DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1534 "DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1535 "DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1536 "DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS",
1537 "DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED",
1538 "DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1539 "DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE",
1540 "DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT",
1541 "DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1545 /* 0x40 */ "SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1546 "SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1547 "SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1548 "SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1549 "SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1550 "SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1551 "SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1552 "SERVO IMPENDING FAILURE CHANNEL PARAMETRICS",
1553 "SERVO IMPENDING FAILURE CONTROLLER DETECTED",
1554 "SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1555 "SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE",
1556 "SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT",
1557 "SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1561 /* 0x50 */ "SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1562 "SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1563 "SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1564 "SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1565 "SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1566 "SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1567 "SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1568 "SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS",
1569 "SPINDLE IMPENDING FAILURE CONTROLLER DETECTED",
1570 "SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1571 "SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE",
1572 "SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT",
1573 "SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1577 /* 0x60 */ "FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1578 "FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1579 "FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1580 "FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1581 "FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1582 "FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1583 "FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1584 "FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
1585 "FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED",
1586 "FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1587 "FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
1588 "FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
1589 /* 0x6c */ "FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"};
1592 /* this is a subset of the SCSI additional sense code strings indexed
1593 * * by "ascq" for the case when asc==SCSI_ASC_WARNING (0xb)
1595 static const char * strs_for_asc_b
[] = {
1596 /* 0x00 */ "WARNING",
1597 "WARNING - SPECIFIED TEMPERATURE EXCEEDED",
1598 "WARNING - ENCLOSURE DEGRADED"};
1600 static char spare_buff
[128];
1602 const char * scsiGetIEString(UINT8 asc
, UINT8 ascq
)
1606 if (SCSI_ASC_IMPENDING_FAILURE
== asc
) {
1608 return "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)";
1610 (sizeof(strs_for_asc_5d
) / sizeof(strs_for_asc_5d
[0]))) {
1611 rp
= strs_for_asc_5d
[ascq
];
1615 snprintf(spare_buff
, sizeof(spare_buff
),
1616 "FAILURE PREDICTION THRESHOLD EXCEEDED: ascq=0x%x", ascq
);
1618 } else if (SCSI_ASC_WARNING
== asc
) {
1619 if (ascq
< (sizeof(strs_for_asc_b
) / sizeof(strs_for_asc_b
[0]))) {
1620 rp
= strs_for_asc_b
[ascq
];
1624 snprintf(spare_buff
, sizeof(spare_buff
), "WARNING: ascq=0x%x", ascq
);
1627 return NULL
; /* not a IE additional sense code */
1631 /* This is not documented in t10.org, page 0x80 is vendor specific */
1632 /* Some IBM disks do an offline read-scan when they get this command. */
1633 int scsiSmartIBMOfflineTest(int device
)
1638 memset(tBuf
, 0, sizeof(tBuf
));
1639 /* Build SMART Off-line Immediate Diag Header */
1640 tBuf
[0] = 0x80; /* Page Code */
1641 tBuf
[1] = 0x00; /* Reserved */
1642 tBuf
[2] = 0x00; /* Page Length MSB */
1643 tBuf
[3] = 0x04; /* Page Length LSB */
1644 tBuf
[4] = 0x03; /* SMART Revision */
1645 tBuf
[5] = 0x00; /* Reserved */
1646 tBuf
[6] = 0x00; /* Off-line Immediate Time MSB */
1647 tBuf
[7] = 0x00; /* Off-line Immediate Time LSB */
1648 res
= scsiSendDiagnostic(device
, SCSI_DIAG_NO_SELF_TEST
, tBuf
, 8);
1650 pout("IBM offline test failed [%s]\n", scsiErrString(res
));
1654 int scsiSmartDefaultSelfTest(int device
)
1658 res
= scsiSendDiagnostic(device
, SCSI_DIAG_DEF_SELF_TEST
, NULL
, 0);
1660 pout("Default self test failed [%s]\n", scsiErrString(res
));
1664 int scsiSmartShortSelfTest(int device
)
1668 res
= scsiSendDiagnostic(device
, SCSI_DIAG_BG_SHORT_SELF_TEST
, NULL
, 0);
1670 pout("Short offline self test failed [%s]\n", scsiErrString(res
));
1674 int scsiSmartExtendSelfTest(int device
)
1678 res
= scsiSendDiagnostic(device
, SCSI_DIAG_BG_EXTENDED_SELF_TEST
, NULL
, 0);
1680 pout("Long (extended) offline self test failed [%s]\n",
1681 scsiErrString(res
));
1685 int scsiSmartShortCapSelfTest(int device
)
1689 res
= scsiSendDiagnostic(device
, SCSI_DIAG_FG_SHORT_SELF_TEST
, NULL
, 0);
1691 pout("Short foreground self test failed [%s]\n", scsiErrString(res
));
1695 int scsiSmartExtendCapSelfTest(int device
)
1699 res
= scsiSendDiagnostic(device
, SCSI_DIAG_FG_EXTENDED_SELF_TEST
, NULL
, 0);
1701 pout("Long (extended) foreground self test failed [%s]\n",
1702 scsiErrString(res
));
1706 int scsiSmartSelfTestAbort(int device
)
1710 res
= scsiSendDiagnostic(device
, SCSI_DIAG_ABORT_SELF_TEST
, NULL
, 0);
1712 pout("Abort self test failed [%s]\n", scsiErrString(res
));
1716 /* Returns 0 and the expected duration of an extended self test (in seconds)
1717 if successful; any other return value indicates a failure. */
1718 int scsiFetchExtendedSelfTestTime(int device
, int * durationSec
, int modese_len
)
1720 int err
, offset
, res
;
1723 memset(buff
, 0, sizeof(buff
));
1724 if (modese_len
<= 6) {
1725 if ((err
= scsiModeSense(device
, CONTROL_MODE_PAGE
, 0,
1726 MPAGE_CONTROL_CURRENT
,
1727 buff
, sizeof(buff
)))) {
1728 if (SIMPLE_ERR_BAD_OPCODE
== err
)
1732 } else if (0 == modese_len
)
1735 if (10 == modese_len
) {
1736 err
= scsiModeSense10(device
, CONTROL_MODE_PAGE
, 0,
1737 MPAGE_CONTROL_CURRENT
,
1738 buff
, sizeof(buff
));
1742 offset
= scsiModePageOffset(buff
, sizeof(buff
), modese_len
);
1745 if (buff
[offset
+ 1] >= 0xa) {
1746 res
= (buff
[offset
+ 10] << 8) | buff
[offset
+ 11];
1754 void scsiDecodeErrCounterPage(unsigned char * resp
,
1755 struct scsiErrorCounter
*ecp
)
1757 int k
, j
, num
, pl
, pc
;
1758 unsigned char * ucp
;
1762 memset(ecp
, 0, sizeof(*ecp
));
1763 num
= (resp
[2] << 8) | resp
[3];
1766 pc
= (ucp
[0] << 8) | ucp
[1];
1777 ullp
= &ecp
->counter
[pc
];
1780 ecp
->gotExtraPC
= 1;
1781 ullp
= &ecp
->counter
[7];
1786 if (k
> (int)sizeof(*ullp
)) {
1787 xp
+= (k
- sizeof(*ullp
));
1791 for (j
= 0; j
< k
; ++j
) {
1801 void scsiDecodeNonMediumErrPage(unsigned char *resp
,
1802 struct scsiNonMediumError
*nmep
)
1804 int k
, j
, num
, pl
, pc
, szof
;
1805 unsigned char * ucp
;
1808 memset(nmep
, 0, sizeof(*nmep
));
1809 num
= (resp
[2] << 8) | resp
[3];
1811 szof
= sizeof(nmep
->counterPC0
);
1813 pc
= (ucp
[0] << 8) | ucp
[1];
1824 nmep
->counterPC0
= 0;
1825 for (j
= 0; j
< k
; ++j
) {
1827 nmep
->counterPC0
<<= 8;
1828 nmep
->counterPC0
|= xp
[j
];
1839 nmep
->counterTFE_H
= 0;
1840 for (j
= 0; j
< k
; ++j
) {
1842 nmep
->counterTFE_H
<<= 8;
1843 nmep
->counterTFE_H
|= xp
[j
];
1854 nmep
->counterPE_H
= 0;
1855 for (j
= 0; j
< k
; ++j
) {
1857 nmep
->counterPE_H
<<= 8;
1858 nmep
->counterPE_H
|= xp
[j
];
1862 nmep
->gotExtraPC
= 1;
1870 /* Counts number of failed self-tests. Also encodes the poweron_hour
1871 of the most recent failed self-test. Return value is negative if
1872 this function has a problem (typically -1), otherwise the bottom 8
1873 bits are the number of failed self tests and the 16 bits above that
1874 are the poweron hour of the most recent failure. Note: aborted self
1875 tests (typically by the user) and self tests in progress are not
1876 considered failures. See Working Draft SCSI Primary Commands - 3
1877 (SPC-3) section 7.2.10 T10/1416-D (rev 22a) */
1878 int scsiCountFailedSelfTests(int fd
, int noisy
)
1880 int num
, k
, n
, err
, res
, fails
, fail_hour
;
1882 unsigned char resp
[LOG_RESP_SELF_TEST_LEN
];
1884 if ((err
= scsiLogSense(fd
, SELFTEST_RESULTS_LPAGE
, 0, resp
,
1885 LOG_RESP_SELF_TEST_LEN
, 0))) {
1887 pout("scsiCountSelfTests Failed [%s]\n", scsiErrString(err
));
1890 if ((resp
[0] & 0x3f) != SELFTEST_RESULTS_LPAGE
) {
1892 pout("Self-test Log Sense Failed, page mismatch\n");
1895 // compute page length
1896 num
= (resp
[2] << 8) + resp
[3];
1897 // Log sense page length 0x190 bytes
1900 pout("Self-test Log Sense length is 0x%x not 0x190 bytes\n", num
);
1905 // loop through the twenty possible entries
1906 for (k
= 0, ucp
= resp
+ 4; k
< 20; ++k
, ucp
+= 20 ) {
1908 // timestamp in power-on hours (or zero if test in progress)
1909 n
= (ucp
[6] << 8) | ucp
[7];
1911 // The spec says "all 20 bytes will be zero if no test" but
1912 // DG has found otherwise. So this is a heuristic.
1913 if ((0 == n
) && (0 == ucp
[4]))
1916 if ((res
> 2) && (res
< 8)) {
1919 fail_hour
= (ucp
[6] << 8) + ucp
[7];
1922 return (fail_hour
<< 8) + fails
;
1925 /* Returns 0 if able to read self test log page; then outputs 1 into
1926 *inProgress if self test still in progress, else outputs 0. */
1927 int scsiSelfTestInProgress(int fd
, int * inProgress
)
1931 unsigned char resp
[LOG_RESP_SELF_TEST_LEN
];
1933 if (scsiLogSense(fd
, SELFTEST_RESULTS_LPAGE
, 0, resp
,
1934 LOG_RESP_SELF_TEST_LEN
, 0))
1936 if (resp
[0] != SELFTEST_RESULTS_LPAGE
)
1938 // compute page length
1939 num
= (resp
[2] << 8) + resp
[3];
1940 // Log sense page length 0x190 bytes
1946 *inProgress
= (0xf == (ucp
[4] & 0xf)) ? 1 : 0;
1950 /* Returns a negative value if failed to fetch Contol mode page or it was
1951 malformed. Returns 0 if GLTSD bit is zero and returns 1 if the GLTSD
1952 bit is set. Examines default mode page when current==0 else examines
1953 current mode page. */
1954 int scsiFetchControlGLTSD(int device
, int modese_len
, int current
)
1958 int pc
= current
? MPAGE_CONTROL_CURRENT
: MPAGE_CONTROL_DEFAULT
;
1960 memset(buff
, 0, sizeof(buff
));
1961 if (modese_len
<= 6) {
1962 if ((err
= scsiModeSense(device
, CONTROL_MODE_PAGE
, 0, pc
,
1963 buff
, sizeof(buff
)))) {
1964 if (SIMPLE_ERR_BAD_OPCODE
== err
)
1968 } else if (0 == modese_len
)
1971 if (10 == modese_len
) {
1972 err
= scsiModeSense10(device
, CONTROL_MODE_PAGE
, 0, pc
,
1973 buff
, sizeof(buff
));
1977 offset
= scsiModePageOffset(buff
, sizeof(buff
), modese_len
);
1978 if ((offset
>= 0) && (buff
[offset
+ 1] >= 0xa))
1979 return (buff
[offset
+ 2] & 2) ? 1 : 0;
1983 /* Attempts to set or clear GLTSD bit in Control mode page. If enabled is
1984 0 attempts to clear GLTSD otherwise it attempts to set it. Returns 0 if
1985 successful, negative if low level error, > 0 if higher level error (e.g.
1986 SIMPLE_ERR_BAD_PARAM if GLTSD bit is not changeable). */
1987 int scsiSetControlGLTSD(int device
, int enabled
, int modese_len
)
1989 int err
, offset
, resp_len
, sp
;
1993 memset(buff
, 0, sizeof(buff
));
1994 if (modese_len
<= 6) {
1995 if ((err
= scsiModeSense(device
, CONTROL_MODE_PAGE
, 0,
1996 MPAGE_CONTROL_CURRENT
,
1997 buff
, sizeof(buff
)))) {
1998 if (SIMPLE_ERR_BAD_OPCODE
== err
)
2002 } else if (0 == modese_len
)
2005 if (10 == modese_len
) {
2006 err
= scsiModeSense10(device
, CONTROL_MODE_PAGE
, 0,
2007 MPAGE_CONTROL_CURRENT
,
2008 buff
, sizeof(buff
));
2012 offset
= scsiModePageOffset(buff
, sizeof(buff
), modese_len
);
2013 if ((offset
< 0) || (buff
[offset
+ 1] < 0xa))
2014 return SIMPLE_ERR_BAD_RESP
;
2018 if (enabled
== (buff
[offset
+ 2] & 2))
2019 return 0; /* GLTSD already in wanted state so nothing to do */
2021 if (modese_len
== 6)
2022 err
= scsiModeSense(device
, CONTROL_MODE_PAGE
, 0,
2023 MPAGE_CONTROL_CHANGEABLE
,
2024 ch_buff
, sizeof(ch_buff
));
2026 err
= scsiModeSense10(device
, CONTROL_MODE_PAGE
, 0,
2027 MPAGE_CONTROL_CHANGEABLE
,
2028 ch_buff
, sizeof(ch_buff
));
2031 if (0 == (ch_buff
[offset
+ 2] & 2))
2032 return SIMPLE_ERR_BAD_PARAM
; /* GLTSD bit not chageable */
2034 if (10 == modese_len
) {
2035 resp_len
= (buff
[0] << 8) + buff
[1] + 2;
2036 buff
[3] &= 0xef; /* for disks mask out DPOFUA bit */
2038 resp_len
= buff
[0] + 1;
2039 buff
[2] &= 0xef; /* for disks mask out DPOFUA bit */
2041 sp
= (buff
[offset
] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
2043 buff
[offset
+ 2] |= 0x2; /* set GLTSD bit */
2045 buff
[offset
+ 2] &= 0xfd; /* clear GLTSD bit */
2046 if (10 == modese_len
)
2047 err
= scsiModeSelect10(device
, sp
, buff
, resp_len
);
2048 else if (6 == modese_len
)
2049 err
= scsiModeSelect(device
, sp
, buff
, resp_len
);
2053 /* Returns a negative value if failed to fetch Protocol specific port mode
2054 page or it was malformed. Returns transport protocol identifier when
2056 int scsiFetchTransportProtocol(int device
, int modese_len
)
2061 memset(buff
, 0, sizeof(buff
));
2062 if (modese_len
<= 6) {
2063 if ((err
= scsiModeSense(device
, PROTOCOL_SPECIFIC_PORT_PAGE
, 0,
2064 MPAGE_CONTROL_CURRENT
,
2065 buff
, sizeof(buff
)))) {
2066 if (SIMPLE_ERR_BAD_OPCODE
== err
)
2070 } else if (0 == modese_len
)
2073 if (10 == modese_len
) {
2074 err
= scsiModeSense10(device
, PROTOCOL_SPECIFIC_PORT_PAGE
, 0,
2075 MPAGE_CONTROL_CURRENT
,
2076 buff
, sizeof(buff
));
2080 offset
= scsiModePageOffset(buff
, sizeof(buff
), modese_len
);
2081 if ((offset
>= 0) && (buff
[offset
+ 1] > 1)) {
2082 if ((0 == (buff
[offset
] & 0x40)) && /* SPF==0 */
2083 (PROTOCOL_SPECIFIC_PORT_PAGE
== (buff
[offset
] & 0x3f)))
2084 return (buff
[offset
+ 2] & 0xf);