]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - scsicmds.cpp
Imported upstream version 5.38~rc0
[mirror_smartmontools-debian.git] / scsicmds.cpp
1 /*
2 * scsicmds.cpp
3 *
4 * Home page of code is: http://smartmontools.sourceforge.net
5 *
6 * Copyright (C) 2002-6 Bruce Allen <smartmontools-support@lists.sourceforge.net>
7 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
8 *
9 * Additional SCSI work:
10 * Copyright (C) 2003-6 Douglas Gilbert <dougg@torque.net>
11 *
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)
15 * any later version.
16 *
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.
20 *
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/
25 *
26 *
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]
36 *
37 * Some SCSI disk vendors have snippets of "SMART" information in their
38 * product manuals.
39 */
40
41 #include <stdio.h>
42 #include <string.h>
43
44 #include "config.h"
45 #include "int64.h"
46 #include "extern.h"
47 #include "scsicmds.h"
48 #include "utility.h"
49
50 const char *scsicmds_c_cvsid="$Id: scsicmds.cpp,v 1.95 2007/12/03 02:14:20 dpgilbert Exp $"
51 CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
52
53 /* for passing global control variables */
54 extern smartmonctrl *con;
55
56 /* output binary in hex and optionally ascii */
57 void dStrHex(const char* str, int len, int no_ascii)
58 {
59 const char* p = str;
60 unsigned char c;
61 char buff[82];
62 int a = 0;
63 const int bpstart = 5;
64 const int cpstart = 60;
65 int cpos = cpstart;
66 int bpos = bpstart;
67 int i, k;
68
69 if (len <= 0) return;
70 memset(buff,' ',80);
71 buff[80]='\0';
72 k = sprintf(buff + 1, "%.2x", a);
73 buff[k + 1] = ' ';
74 if (bpos >= ((bpstart + (9 * 3))))
75 bpos++;
76
77 for(i = 0; i < len; i++)
78 {
79 c = *p++;
80 bpos += 3;
81 if (bpos == (bpstart + (9 * 3)))
82 bpos++;
83 sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c);
84 buff[bpos + 2] = ' ';
85 if (no_ascii)
86 buff[cpos++] = ' ';
87 else {
88 if ((c < ' ') || (c >= 0x7f))
89 c='.';
90 buff[cpos++] = c;
91 }
92 if (cpos > (cpstart+15))
93 {
94 pout("%s\n", buff);
95 bpos = bpstart;
96 cpos = cpstart;
97 a += 16;
98 memset(buff,' ',80);
99 k = sprintf(buff + 1, "%.2x", a);
100 buff[k + 1] = ' ';
101 }
102 }
103 if (cpos > cpstart)
104 {
105 pout("%s\n", buff);
106 }
107 }
108
109 struct scsi_opcode_name {
110 UINT8 opcode;
111 const char * name;
112 };
113
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 */
129 };
130
131 const char * scsi_get_opcode_name(UINT8 opcode)
132 {
133 int k;
134 int len = sizeof(opcode_name_arr) / sizeof(opcode_name_arr[0]);
135 struct scsi_opcode_name * onp;
136
137 for (k = 0; k < len; ++k) {
138 onp = &opcode_name_arr[k];
139 if (opcode == onp->opcode)
140 return onp->name;
141 else if (opcode < onp->opcode)
142 return NULL;
143 }
144 return NULL;
145 }
146
147
148 void scsi_do_sense_disect(const struct scsi_cmnd_io * io_buf,
149 struct scsi_sense_disect * out)
150 {
151 int resp_code;
152
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];
166 }
167 }
168 }
169 }
170
171 int scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo)
172 {
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;
183 else
184 return SIMPLE_ERR_NOT_READY;
185 } else
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;
197 else
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;
203 default:
204 return SIMPLE_ERR_UNKNOWN;
205 }
206 }
207
208 const char * scsiErrString(int scsiErr)
209 {
210 if (scsiErr < 0)
211 return strerror(-scsiErr);
212 switch (scsiErr) {
213 case SIMPLE_NO_ERROR:
214 return "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";
237 default:
238 return "unknown error";
239 }
240 }
241
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)
254 {
255 struct scsi_cmnd_io io_hdr;
256 struct scsi_sense_disect sinfo;
257 UINT8 cdb[10];
258 UINT8 sense[32];
259 int pageLen;
260 int status, res;
261
262 if (known_resp_len > bufLen)
263 return -EIO;
264 if (known_resp_len > 0)
265 pageLen = known_resp_len;
266 else {
267 /* Starting twin fetch strategy: first fetch to find respone length */
268 pageLen = 4;
269 if (pageLen > bufLen)
270 return -EIO;
271 else
272 memset(pBuf, 0, pageLen);
273
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;
279 cdb[0] = LOG_SENSE;
280 cdb[2] = 0x40 | (pagenum & 0x3f); /* Page control (PC)==1 */
281 cdb[3] = subpagenum;
282 cdb[7] = (pageLen >> 8) & 0xff;
283 cdb[8] = pageLen & 0xff;
284 io_hdr.cmnd = cdb;
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;
289
290 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
291 if (0 != status)
292 return status;
293 scsi_do_sense_disect(&io_hdr, &sinfo);
294 if ((res = scsiSimpleSenseFilter(&sinfo)))
295 return res;
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 */
305 if (pageLen % 2)
306 pageLen += 1;
307 if (pageLen > bufLen)
308 pageLen = bufLen;
309 }
310 memset(pBuf, 0, 4);
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;
316 cdb[0] = LOG_SENSE;
317 cdb[2] = 0x40 | (pagenum & 0x3f); /* Page control (PC)==1 */
318 cdb[7] = (pageLen >> 8) & 0xff;
319 cdb[8] = pageLen & 0xff;
320 io_hdr.cmnd = cdb;
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;
325
326 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
327 if (0 != status)
328 return status;
329 scsi_do_sense_disect(&io_hdr, &sinfo);
330 status = scsiSimpleSenseFilter(&sinfo);
331 if (0 != status)
332 return status;
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;
338 return 0;
339 }
340
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)
347 {
348 struct scsi_cmnd_io io_hdr;
349 struct scsi_sense_disect sinfo;
350 UINT8 cdb[6];
351 UINT8 sense[32];
352 int status;
353
354 if ((bufLen < 0) || (bufLen > 255))
355 return -EINVAL;
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;
361 cdb[0] = MODE_SENSE;
362 cdb[2] = (pc << 6) | (pagenum & 0x3f);
363 cdb[3] = subpagenum;
364 cdb[4] = bufLen;
365 io_hdr.cmnd = cdb;
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;
370
371 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
372 if (0 != status)
373 return status;
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);
378 if (0 != status)
379 return status;
380 scsi_do_sense_disect(&io_hdr, &sinfo);
381 status = scsiSimpleSenseFilter(&sinfo);
382 }
383 if ((0 == status) && (ALL_MODE_PAGES != pagenum)) {
384 int offset;
385
386 offset = scsiModePageOffset(pBuf, bufLen, 0);
387 if (offset < 0)
388 return SIMPLE_ERR_BAD_RESP;
389 else if (pagenum != (pBuf[offset] & 0x3f))
390 return SIMPLE_ERR_BAD_RESP;
391 }
392 return status;
393 }
394
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)
403 {
404 struct scsi_cmnd_io io_hdr;
405 struct scsi_sense_disect sinfo;
406 UINT8 cdb[6];
407 UINT8 sense[32];
408 int status, pg_offset, pg_len, hdr_plus_1_pg;
409
410 pg_offset = 4 + pBuf[3];
411 if (pg_offset + 2 >= bufLen)
412 return -EINVAL;
413 pg_len = pBuf[pg_offset + 1] + 2;
414 hdr_plus_1_pg = pg_offset + pg_len;
415 if (hdr_plus_1_pg > bufLen)
416 return -EINVAL;
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 */
427 io_hdr.cmnd = cdb;
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;
432
433 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
434 if (0 != status)
435 return status;
436 scsi_do_sense_disect(&io_hdr, &sinfo);
437 return scsiSimpleSenseFilter(&sinfo);
438 }
439
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)
446 {
447 struct scsi_cmnd_io io_hdr;
448 struct scsi_sense_disect sinfo;
449 UINT8 cdb[10];
450 UINT8 sense[32];
451 int status;
452
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);
460 cdb[3] = subpagenum;
461 cdb[7] = (bufLen >> 8) & 0xff;
462 cdb[8] = bufLen & 0xff;
463 io_hdr.cmnd = cdb;
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;
468
469 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
470 if (0 != status)
471 return status;
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);
476 if (0 != status)
477 return status;
478 scsi_do_sense_disect(&io_hdr, &sinfo);
479 status = scsiSimpleSenseFilter(&sinfo);
480 }
481 if ((0 == status) && (ALL_MODE_PAGES != pagenum)) {
482 int offset;
483
484 offset = scsiModePageOffset(pBuf, bufLen, 1);
485 if (offset < 0)
486 return SIMPLE_ERR_BAD_RESP;
487 else if (pagenum != (pBuf[offset] & 0x3f))
488 return SIMPLE_ERR_BAD_RESP;
489 }
490 return status;
491 }
492
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)
501 {
502 struct scsi_cmnd_io io_hdr;
503 struct scsi_sense_disect sinfo;
504 UINT8 cdb[10];
505 UINT8 sense[32];
506 int status, pg_offset, pg_len, hdr_plus_1_pg;
507
508 pg_offset = 8 + (pBuf[6] << 8) + pBuf[7];
509 if (pg_offset + 2 >= bufLen)
510 return -EINVAL;
511 pg_len = pBuf[pg_offset + 1] + 2;
512 hdr_plus_1_pg = pg_offset + pg_len;
513 if (hdr_plus_1_pg > bufLen)
514 return -EINVAL;
515 pBuf[0] = 0;
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 */
526 io_hdr.cmnd = cdb;
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;
531
532 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
533 if (0 != status)
534 return status;
535 scsi_do_sense_disect(&io_hdr, &sinfo);
536 return scsiSimpleSenseFilter(&sinfo);
537 }
538
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)
543 {
544 struct scsi_sense_disect sinfo;
545 struct scsi_cmnd_io io_hdr;
546 UINT8 cdb[6];
547 UINT8 sense[32];
548 int status;
549
550 if ((bufLen < 0) || (bufLen > 255))
551 return -EINVAL;
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;
557 cdb[0] = INQUIRY;
558 cdb[4] = bufLen;
559 io_hdr.cmnd = cdb;
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;
564
565 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
566 if (0 != status)
567 return status;
568 scsi_do_sense_disect(&io_hdr, &sinfo);
569 return scsiSimpleSenseFilter(&sinfo);
570 }
571
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)
577 {
578 struct scsi_cmnd_io io_hdr;
579 struct scsi_sense_disect sinfo;
580 UINT8 cdb[6];
581 UINT8 sense[32];
582 int status, res;
583
584 if ((bufLen < 0) || (bufLen > 255))
585 return -EINVAL;
586 memset(&io_hdr, 0, sizeof(io_hdr));
587 memset(cdb, 0, sizeof(cdb));
588 if (bufLen > 1)
589 pBuf[1] = 0x0;
590 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
591 io_hdr.dxfer_len = bufLen;
592 io_hdr.dxferp = pBuf;
593 cdb[0] = INQUIRY;
594 cdb[1] = 0x1; /* set EVPD bit (enable Vital Product Data) */
595 cdb[2] = vpd_page;
596 cdb[4] = bufLen;
597 io_hdr.cmnd = cdb;
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;
602
603 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
604 if (0 != status)
605 return status;
606 scsi_do_sense_disect(&io_hdr, &sinfo);
607 if ((res = scsiSimpleSenseFilter(&sinfo)))
608 return res;
609 /* Guard against devices that ignore EVPD bit and do standard INQUIRY */
610 if (bufLen > 1) {
611 if (vpd_page == pBuf[1]) {
612 if ((0x80 == vpd_page) && (bufLen > 2) && (0x0 != pBuf[2]))
613 return SIMPLE_ERR_BAD_RESP;
614 } else
615 return SIMPLE_ERR_BAD_RESP;
616 }
617 return 0;
618 }
619
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)
623 {
624 struct scsi_cmnd_io io_hdr;
625 UINT8 cdb[6];
626 UINT8 sense[32];
627 UINT8 buff[18];
628 int status, len;
629 UINT8 ecode;
630
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);
638 io_hdr.cmnd = cdb;
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;
643
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;
649 sense_info->asc = 0;
650 sense_info->ascq = 0;
651 if ((0x70 == ecode) || (0x71 == ecode)) {
652 len = buff[7] + 8;
653 if (len > 13) {
654 sense_info->asc = buff[12];
655 sense_info->ascq = buff[13];
656 }
657 }
658 }
659 return status;
660 }
661
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)
666 {
667 struct scsi_cmnd_io io_hdr;
668 struct scsi_sense_disect sinfo;
669 UINT8 cdb[6];
670 UINT8 sense[32];
671 int status;
672
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;
687 io_hdr.cmnd = cdb;
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;
693
694 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
695 if (0 != status)
696 return status;
697 scsi_do_sense_disect(&io_hdr, &sinfo);
698 return scsiSimpleSenseFilter(&sinfo);
699 }
700
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,
705 int bufLen)
706 {
707 struct scsi_cmnd_io io_hdr;
708 struct scsi_sense_disect sinfo;
709 UINT8 cdb[6];
710 UINT8 sense[32];
711 int status;
712
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;
719 cdb[1] = pcv;
720 cdb[2] = pagenum;
721 cdb[3] = (bufLen >> 8) & 0xff;
722 cdb[4] = bufLen & 0xff;
723 io_hdr.cmnd = cdb;
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;
728
729 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
730 if (0 != status)
731 return status;
732 scsi_do_sense_disect(&io_hdr, &sinfo);
733 return scsiSimpleSenseFilter(&sinfo);
734 }
735
736 /* TEST UNIT READY command. SPC-3 section 6.33 (rev 22a) */
737 static int _testunitready(int device, struct scsi_sense_disect * sinfo)
738 {
739 struct scsi_cmnd_io io_hdr;
740 UINT8 cdb[6];
741 UINT8 sense[32];
742 int status;
743
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;
750 io_hdr.cmnd = cdb;
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;
755
756 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
757 if (0 != status)
758 return status;
759 scsi_do_sense_disect(&io_hdr, sinfo);
760 return 0;
761 }
762
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)
766 {
767 struct scsi_sense_disect sinfo;
768 int status;
769
770 status = _testunitready(device, &sinfo);
771 if (0 != status)
772 return status;
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);
777 if (0 != status)
778 return status;
779 status = scsiSimpleSenseFilter(&sinfo);
780 }
781 return status;
782 }
783
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)
789 {
790 struct scsi_cmnd_io io_hdr;
791 struct scsi_sense_disect sinfo;
792 UINT8 cdb[10];
793 UINT8 sense[32];
794 int status;
795
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;
806 io_hdr.cmnd = cdb;
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;
811
812 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
813 if (0 != status)
814 return status;
815 scsi_do_sense_disect(&io_hdr, &sinfo);
816 return scsiSimpleSenseFilter(&sinfo);
817 }
818
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)
822 {
823 int resp_len, bd_len;
824 int offset = -1;
825
826 if (resp) {
827 if (10 == modese_len) {
828 resp_len = (resp[0] << 8) + resp[1] + 2;
829 bd_len = (resp[6] << 8) + resp[7];
830 offset = bd_len + 8;
831 } else {
832 resp_len = resp[0] + 1;
833 bd_len = resp[3];
834 offset = bd_len + 4;
835 }
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);
839 offset = -1;
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,
844 offset, bd_len);
845 offset = -1;
846 }
847 }
848 return offset;
849 }
850
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
857
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
862 * value. */
863 int scsiFetchIECmpage(int device, struct scsi_iec_mode_page *iecp, int modese_len)
864 {
865 int err = 0;
866
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;
876 else {
877 iecp->modese_len = 0;
878 return err;
879 }
880 } else if (0 == iecp->modese_len)
881 iecp->modese_len = 6;
882 }
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));
887 if (err) {
888 iecp->modese_len = 0;
889 return err;
890 }
891 }
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));
902 if (err)
903 return err;
904 iecp->gotChangeable = 1;
905 return 0;
906 }
907
908 int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
909 {
910 int offset;
911
912 if (iecp && iecp->gotCurrent) {
913 offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
914 iecp->modese_len);
915 if (offset >= 0)
916 return (iecp->raw_curr[offset + 2] & DEXCPT_ENABLE) ? 0 : 1;
917 else
918 return 0;
919 } else
920 return 0;
921 }
922
923 int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
924 {
925 int offset;
926
927 if (iecp && iecp->gotCurrent) {
928 offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
929 iecp->modese_len);
930 if (offset >= 0)
931 return (iecp->raw_curr[offset + 2] & EWASC_ENABLE) ? 1 : 0;
932 else
933 return 0;
934 } else
935 return 0;
936 }
937
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
945
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)
955 {
956 int k, offset, resp_len;
957 int err = 0;
958 UINT8 rout[SCSI_IECMP_RAW_LEN];
959 int sp, eCEnabled, wEnabled;
960
961 if ((! iecp) || (! iecp->gotCurrent))
962 return -EINVAL;
963 offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
964 iecp->modese_len);
965 if (offset < 0)
966 return -EINVAL;
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 */
971 } else {
972 resp_len = rout[0] + 1;
973 rout[2] &= 0xef; /* for disks mask out DPOFUA bit */
974 }
975 sp = (rout[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
976 if (enabled) {
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];
991
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];
997 }
998 }
999 if (0 == memcmp(&rout[offset + 2], &iecp->raw_chg[offset + 2], 10)) {
1000 if (con->reportscsiioctl > 0)
1001 pout("scsiSetExceptionControlAndWarning: already enabled\n");
1002 return 0;
1003 }
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 */
1011 }
1012 if (wEnabled)
1013 rout[offset + 2] &= EWASC_DISABLE;
1014 if (eCEnabled) {
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 */
1019 }
1020 }
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);
1025 return err;
1026 }
1027
1028 int scsiGetTemp(int device, UINT8 *currenttemp, UINT8 *triptemp)
1029 {
1030 UINT8 tBuf[252];
1031 int err;
1032
1033 memset(tBuf, 0, sizeof(tBuf));
1034 if ((err = scsiLogSense(device, TEMPERATURE_LPAGE, 0, tBuf,
1035 sizeof(tBuf), 0))) {
1036 *currenttemp = 0;
1037 *triptemp = 0;
1038 pout("Log Sense for temperature failed [%s]\n", scsiErrString(err));
1039 return err;
1040 }
1041 *currenttemp = tBuf[9];
1042 *triptemp = tBuf[15];
1043 return 0;
1044 }
1045
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,
1052 UINT8 *triptemp)
1053 {
1054 UINT8 tBuf[252];
1055 struct scsi_sense_disect sense_info;
1056 int err;
1057 int temperatureSet = 0;
1058 unsigned short pagesize;
1059 UINT8 currTemp, trTemp;
1060
1061 *asc = 0;
1062 *ascq = 0;
1063 *currenttemp = 0;
1064 *triptemp = 0;
1065 memset(tBuf,0,sizeof(tBuf)); // need to clear stack space of junk
1066 memset(&sense_info, 0, sizeof(sense_info));
1067 if (hasIELogPage) {
1068 if ((err = scsiLogSense(device, IE_LPAGE, 0, tBuf,
1069 sizeof(tBuf), 0))) {
1070 pout("Log Sense failed, IE page [%s]\n", scsiErrString(err));
1071 return err;
1072 }
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;
1078 }
1079 if (tBuf[7] > 1) {
1080 sense_info.asc = tBuf[8];
1081 sense_info.ascq = tBuf[9];
1082 if (! hasTempLogPage) {
1083 if (tBuf[7] > 2)
1084 *currenttemp = tBuf[10];
1085 if (tBuf[7] > 3) /* IBM extension in SMART (IE) lpage */
1086 *triptemp = tBuf[11];
1087 }
1088 }
1089 }
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));
1094 return err;
1095 }
1096 }
1097 *asc = sense_info.asc;
1098 *ascq = sense_info.ascq;
1099 if ((! temperatureSet) && hasTempLogPage) {
1100 if (0 == scsiGetTemp(device, &currTemp, &trTemp)) {
1101 *currenttemp = currTemp;
1102 *triptemp = trTemp;
1103 }
1104 }
1105 return 0;
1106 }
1107
1108 // The first character (W, C, I) tells the severity
1109 static const char * TapeAlertsMessageTable[]= {
1110 " ",
1111 /* 0x01 */
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.",
1114 /* 0x02 */
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.",
1117 /* 0x03 */
1118 "W: The operation has stopped because an error has occurred while reading\n"
1119 " or writing data that the drive cannot correct.",
1120 /* 0x04 */
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.",
1125 /* 0x05 */
1126 "C: The tape is damaged or the drive is faulty. Call the tape drive\n"
1127 " supplier helpline.",
1128 /* 0x06 */
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.",
1132 /* 0x07 */
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.",
1136 /* 0x08 */
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.",
1139 /* 0x09 */
1140 "C: You are trying to write to a write-protected cartridge. Remove the\n"
1141 " write-protection or use another tape.",
1142 /* 0x0a */
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.",
1145 /* 0x0b */
1146 "I: The tape in the drive is a cleaning cartridge.",
1147 /* 0x0c */
1148 "I: You have tried to load a cartridge of a type which is not supported\n"
1149 " by this drive.",
1150 /* 0x0d */
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.",
1155 /* 0x0e */
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.",
1160 /* 0x0f */
1161 "W: The memory in the tape cartridge has failed, which reduces\n"
1162 " performance. Do not use the cartridge for further write operations.",
1163 /* 0x10 */
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.",
1166 /* 0x11 */
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.",
1169 /* 0x12 */
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.",
1173 /* 0x13 */
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 "
1178 " data from it.",
1179 /* 0x14 */
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.",
1185 /* 0x15 */
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.",
1190 /* 0x16 */
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.",
1195 /* 0x17 */
1196 "C: The last cleaning cartridge used in the tape drive was an invalid\n"
1197 " type:\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.",
1201 /* 0x18 */
1202 "W: The tape drive has requested a retention operation",
1203 /* 0x19 */
1204 "W: A redundant interface port on the tape drive has failed",
1205 /* 0x1a */
1206 "W: A tape drive cooling fan has failed",
1207 /* 0x1b */
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.",
1211 /* 0x1c */
1212 "W: The tape drive power consumption is outside the specified range.",
1213 /* 0x1d */
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.",
1217 /* 0x1e */
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.",
1222 /* 0x1f */
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.",
1227 /* 0x20 */
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.",
1231 /* 0x21 */
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.",
1236 /* 0x22 */
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.",
1240 /* 0x23 */
1241 "W: Environmental conditions inside the tape drive are outside the\n"
1242 " specified humidity range.",
1243 /* 0x24 */
1244 "W: Environmental conditions inside the tape drive are outside the\n"
1245 " specified temperature range.",
1246 /* 0x25 */
1247 "W: The voltage supply to the tape drive is outside the specified range.",
1248 /* 0x26 */
1249 "C: A hardware failure of the tape drive is predicted. Call the tape\n"
1250 " drive supplier helpline.",
1251 /* 0x27 */
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.",
1255 /* 0x28 */
1256 "C: The changer mechanism is having difficulty communicating with the tape\n"
1257 " drive:\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.",
1261 /* 0x29 */
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"
1265 " on again.\n"
1266 " 3. If the problem persists, call the tape drive supplier helpline.",
1267 /* 0x2a */
1268 "W: There is a problem with the autoloader mechanism.",
1269 /* 0x2b */
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"
1274 " on again.\n"
1275 " 4. If the problem persists, call the tape drive supplier helpline.",
1276 /* 0x2c */
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.",
1283 /* 0x2d */
1284 "C: The autoloader cannot operate without the magazine,\n"
1285 " 1. Insert the magazine into the autoloader.\n"
1286 " 2. Restart the operation.",
1287 /* 0x2e */
1288 "W: A hardware failure of the changer mechanism is predicted. Call the\n"
1289 " tape drive supplier helpline.",
1290 /* 0x2f */
1291 "I: Reserved.",
1292 /* 0x30 */
1293 "I: Reserved.",
1294 /* 0x31 */
1295 "I: Reserved.",
1296 /* 0x32 */
1297 "W: Media statistics have been lost at some time in the past",
1298 /* 0x33 */
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.",
1302 /* 0x34 */
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.",
1306 /* 0x35 */
1307 "C: The tape system are could not be read successfully at load time:\n"
1308 " 1. Copy data to another tape cartridge.\n",
1309 /* 0x36 */
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",
1313 /* 0x37 */
1314 "C: The operation has failed because the media cannot be loaded\n"
1315 " and threaded.\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.",
1319 /* 0x38 */
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.",
1323 /* 0x39 */
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.",
1328 /* 0x3a */
1329 "W: The tape drive has reset itself due to a detected firmware\n"
1330 " fault. If problem persists, call the supplier help line.",
1331 };
1332
1333 const char * scsiTapeAlertsTapeDevice(unsigned short code)
1334 {
1335 const int num = sizeof(TapeAlertsMessageTable) /
1336 sizeof(TapeAlertsMessageTable[0]);
1337
1338 return (code < num) ? TapeAlertsMessageTable[code] : "Unknown Alert";
1339 }
1340
1341 // The first character (W, C, I) tells the severity
1342 static const char * ChangerTapeAlertsMessageTable[]= {
1343 " ",
1344 /* 0x01 */
1345 "C: The library mechanism is having difficulty communicating with the\n"
1346 " drive:\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.",
1350 /* 0x02 */
1351 "W: There is a problem with the library mechanism. If problem persists,\n"
1352 " call the library supplier help line.",
1353 /* 0x03 */
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"
1358 " the device.",
1359 /* 0x04 */
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.",
1366 /* 0x05 */
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"
1370 " tests.",
1371 /* 0x06 */
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.",
1375 /* 0x07 */
1376 "W: A hardware failure of the library is predicted. Call the library\n"
1377 " supplier help line.",
1378 /* 0x08 */
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.",
1382 /* 0x09 */
1383 "C: General environmental conditions inside the library are outside the\n"
1384 " specified humidity range.",
1385 /* 0x0a */
1386 "C: General environmental conditions inside the library are outside the\n"
1387 " specified temperature range.",
1388 /* 0x0b */
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.",
1392 /* 0x0c */
1393 "C: A cartridge has been left inside the library by a previous hardware\n"
1394 " fault:\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.",
1398 /* 0x0d */
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.",
1403 /* 0x0e */
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.",
1408 /* 0x0f */
1409 "W: There is a potential problem with the drive or the library mechanism\n"
1410 " loading cartridges, or an incompatible cartridge.",
1411 /* 0x10 */
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.",
1416 /* 0x11 */
1417 "C: There is a mechanical problem with the library media import/export\n"
1418 " mailslot.",
1419 /* 0x12 */
1420 "C: The library cannot operate without the magazine.\n"
1421 " 1. Insert the magazine into the library.\n"
1422 " 2. Restart the operation.",
1423 /* 0x13 */
1424 "W: Library security has been compromised.",
1425 /* 0x14 */
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.",
1430 /* 0x15 */
1431 "I: The library has been manually turned offline and is unavailable for use.",
1432 /* 0x16 */
1433 "I: A drive inside the library has been taken offline.\n"
1434 " This is for information purposes only. No action is required.",
1435 /* 0x17 */
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.",
1440 /* 0x18 */
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.",
1446 /* 0x19 */
1447 "W: A library operation has been attempted that is invalid at this time.",
1448 /* 0x1a */
1449 "W: A redundant interface port on the library has failed.",
1450 /* 0x1b */
1451 "W: A library cooling fan has failed.",
1452 /* 0x1c */
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.",
1455 /* 0x1d */
1456 "W: The library power consumption is outside the specified range.",
1457 /* 0x1e */
1458 "C: A failure has occurred in the cartridge pass-through mechanism between\n"
1459 " two library modules.",
1460 /* 0x1f */
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.",
1464 /* 0x20 */
1465 "I: The library was unable to read the bar code on a cartridge.",
1466 };
1467
1468 const char * scsiTapeAlertsChangerDevice(unsigned short code)
1469 {
1470 const int num = sizeof(ChangerTapeAlertsMessageTable) /
1471 sizeof(ChangerTapeAlertsMessageTable[0]);
1472
1473 return (code < num) ? ChangerTapeAlertsMessageTable[code] : "Unknown Alert";
1474 }
1475
1476
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)
1479 */
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",
1485 "",
1486 "",
1487 "",
1488 "",
1489 "",
1490 "",
1491 "",
1492 "",
1493 "",
1494 "",
1495 "",
1496 "",
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",
1510 "",
1511 "",
1512 "",
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",
1526 "",
1527 "",
1528 "",
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",
1542 "",
1543 "",
1544 "",
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",
1558 "",
1559 "",
1560 "",
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",
1574 "",
1575 "",
1576 "",
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"};
1590
1591
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)
1594 * */
1595 static const char * strs_for_asc_b[] = {
1596 /* 0x00 */ "WARNING",
1597 "WARNING - SPECIFIED TEMPERATURE EXCEEDED",
1598 "WARNING - ENCLOSURE DEGRADED"};
1599
1600 static char spare_buff[128];
1601
1602 const char * scsiGetIEString(UINT8 asc, UINT8 ascq)
1603 {
1604 const char * rp;
1605
1606 if (SCSI_ASC_IMPENDING_FAILURE == asc) {
1607 if (ascq == 0xff)
1608 return "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)";
1609 else if (ascq <
1610 (sizeof(strs_for_asc_5d) / sizeof(strs_for_asc_5d[0]))) {
1611 rp = strs_for_asc_5d[ascq];
1612 if (strlen(rp) > 0)
1613 return rp;
1614 }
1615 snprintf(spare_buff, sizeof(spare_buff),
1616 "FAILURE PREDICTION THRESHOLD EXCEEDED: ascq=0x%x", ascq);
1617 return spare_buff;
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];
1621 if (strlen(rp) > 0)
1622 return rp;
1623 }
1624 snprintf(spare_buff, sizeof(spare_buff), "WARNING: ascq=0x%x", ascq);
1625 return spare_buff;
1626 }
1627 return NULL; /* not a IE additional sense code */
1628 }
1629
1630
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)
1634 {
1635 UINT8 tBuf[256];
1636 int res;
1637
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);
1649 if (res)
1650 pout("IBM offline test failed [%s]\n", scsiErrString(res));
1651 return res;
1652 }
1653
1654 int scsiSmartDefaultSelfTest(int device)
1655 {
1656 int res;
1657
1658 res = scsiSendDiagnostic(device, SCSI_DIAG_DEF_SELF_TEST, NULL, 0);
1659 if (res)
1660 pout("Default self test failed [%s]\n", scsiErrString(res));
1661 return res;
1662 }
1663
1664 int scsiSmartShortSelfTest(int device)
1665 {
1666 int res;
1667
1668 res = scsiSendDiagnostic(device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL, 0);
1669 if (res)
1670 pout("Short offline self test failed [%s]\n", scsiErrString(res));
1671 return res;
1672 }
1673
1674 int scsiSmartExtendSelfTest(int device)
1675 {
1676 int res;
1677
1678 res = scsiSendDiagnostic(device, SCSI_DIAG_BG_EXTENDED_SELF_TEST, NULL, 0);
1679 if (res)
1680 pout("Long (extended) offline self test failed [%s]\n",
1681 scsiErrString(res));
1682 return res;
1683 }
1684
1685 int scsiSmartShortCapSelfTest(int device)
1686 {
1687 int res;
1688
1689 res = scsiSendDiagnostic(device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL, 0);
1690 if (res)
1691 pout("Short foreground self test failed [%s]\n", scsiErrString(res));
1692 return res;
1693 }
1694
1695 int scsiSmartExtendCapSelfTest(int device)
1696 {
1697 int res;
1698
1699 res = scsiSendDiagnostic(device, SCSI_DIAG_FG_EXTENDED_SELF_TEST, NULL, 0);
1700 if (res)
1701 pout("Long (extended) foreground self test failed [%s]\n",
1702 scsiErrString(res));
1703 return res;
1704 }
1705
1706 int scsiSmartSelfTestAbort(int device)
1707 {
1708 int res;
1709
1710 res = scsiSendDiagnostic(device, SCSI_DIAG_ABORT_SELF_TEST, NULL, 0);
1711 if (res)
1712 pout("Abort self test failed [%s]\n", scsiErrString(res));
1713 return res;
1714 }
1715
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)
1719 {
1720 int err, offset, res;
1721 UINT8 buff[64];
1722
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)
1729 modese_len = 10;
1730 else
1731 return err;
1732 } else if (0 == modese_len)
1733 modese_len = 6;
1734 }
1735 if (10 == modese_len) {
1736 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
1737 MPAGE_CONTROL_CURRENT,
1738 buff, sizeof(buff));
1739 if (err)
1740 return err;
1741 }
1742 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
1743 if (offset < 0)
1744 return -EINVAL;
1745 if (buff[offset + 1] >= 0xa) {
1746 res = (buff[offset + 10] << 8) | buff[offset + 11];
1747 *durationSec = res;
1748 return 0;
1749 }
1750 else
1751 return -EINVAL;
1752 }
1753
1754 void scsiDecodeErrCounterPage(unsigned char * resp,
1755 struct scsiErrorCounter *ecp)
1756 {
1757 int k, j, num, pl, pc;
1758 unsigned char * ucp;
1759 unsigned char * xp;
1760 uint64_t * ullp;
1761
1762 memset(ecp, 0, sizeof(*ecp));
1763 num = (resp[2] << 8) | resp[3];
1764 ucp = &resp[0] + 4;
1765 while (num > 3) {
1766 pc = (ucp[0] << 8) | ucp[1];
1767 pl = ucp[3] + 4;
1768 switch (pc) {
1769 case 0:
1770 case 1:
1771 case 2:
1772 case 3:
1773 case 4:
1774 case 5:
1775 case 6:
1776 ecp->gotPC[pc] = 1;
1777 ullp = &ecp->counter[pc];
1778 break;
1779 default:
1780 ecp->gotExtraPC = 1;
1781 ullp = &ecp->counter[7];
1782 break;
1783 }
1784 k = pl - 4;
1785 xp = ucp + 4;
1786 if (k > (int)sizeof(*ullp)) {
1787 xp += (k - sizeof(*ullp));
1788 k = sizeof(*ullp);
1789 }
1790 *ullp = 0;
1791 for (j = 0; j < k; ++j) {
1792 if (j > 0)
1793 *ullp <<= 8;
1794 *ullp |= xp[j];
1795 }
1796 num -= pl;
1797 ucp += pl;
1798 }
1799 }
1800
1801 void scsiDecodeNonMediumErrPage(unsigned char *resp,
1802 struct scsiNonMediumError *nmep)
1803 {
1804 int k, j, num, pl, pc, szof;
1805 unsigned char * ucp;
1806 unsigned char * xp;
1807
1808 memset(nmep, 0, sizeof(*nmep));
1809 num = (resp[2] << 8) | resp[3];
1810 ucp = &resp[0] + 4;
1811 szof = sizeof(nmep->counterPC0);
1812 while (num > 3) {
1813 pc = (ucp[0] << 8) | ucp[1];
1814 pl = ucp[3] + 4;
1815 switch (pc) {
1816 case 0:
1817 nmep->gotPC0 = 1;
1818 k = pl - 4;
1819 xp = ucp + 4;
1820 if (k > szof) {
1821 xp += (k - szof);
1822 k = szof;
1823 }
1824 nmep->counterPC0 = 0;
1825 for (j = 0; j < k; ++j) {
1826 if (j > 0)
1827 nmep->counterPC0 <<= 8;
1828 nmep->counterPC0 |= xp[j];
1829 }
1830 break;
1831 case 0x8009:
1832 nmep->gotTFE_H = 1;
1833 k = pl - 4;
1834 xp = ucp + 4;
1835 if (k > szof) {
1836 xp += (k - szof);
1837 k = szof;
1838 }
1839 nmep->counterTFE_H = 0;
1840 for (j = 0; j < k; ++j) {
1841 if (j > 0)
1842 nmep->counterTFE_H <<= 8;
1843 nmep->counterTFE_H |= xp[j];
1844 }
1845 break;
1846 case 0x8015:
1847 nmep->gotPE_H = 1;
1848 k = pl - 4;
1849 xp = ucp + 4;
1850 if (k > szof) {
1851 xp += (k - szof);
1852 k = szof;
1853 }
1854 nmep->counterPE_H = 0;
1855 for (j = 0; j < k; ++j) {
1856 if (j > 0)
1857 nmep->counterPE_H <<= 8;
1858 nmep->counterPE_H |= xp[j];
1859 }
1860 break;
1861 default:
1862 nmep->gotExtraPC = 1;
1863 break;
1864 }
1865 num -= pl;
1866 ucp += pl;
1867 }
1868 }
1869
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)
1879 {
1880 int num, k, n, err, res, fails, fail_hour;
1881 UINT8 * ucp;
1882 unsigned char resp[LOG_RESP_SELF_TEST_LEN];
1883
1884 if ((err = scsiLogSense(fd, SELFTEST_RESULTS_LPAGE, 0, resp,
1885 LOG_RESP_SELF_TEST_LEN, 0))) {
1886 if (noisy)
1887 pout("scsiCountSelfTests Failed [%s]\n", scsiErrString(err));
1888 return -1;
1889 }
1890 if ((resp[0] & 0x3f) != SELFTEST_RESULTS_LPAGE) {
1891 if (noisy)
1892 pout("Self-test Log Sense Failed, page mismatch\n");
1893 return -1;
1894 }
1895 // compute page length
1896 num = (resp[2] << 8) + resp[3];
1897 // Log sense page length 0x190 bytes
1898 if (num != 0x190) {
1899 if (noisy)
1900 pout("Self-test Log Sense length is 0x%x not 0x190 bytes\n", num);
1901 return -1;
1902 }
1903 fails = 0;
1904 fail_hour = 0;
1905 // loop through the twenty possible entries
1906 for (k = 0, ucp = resp + 4; k < 20; ++k, ucp += 20 ) {
1907
1908 // timestamp in power-on hours (or zero if test in progress)
1909 n = (ucp[6] << 8) | ucp[7];
1910
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]))
1914 break;
1915 res = ucp[4] & 0xf;
1916 if ((res > 2) && (res < 8)) {
1917 fails++;
1918 if (1 == fails)
1919 fail_hour = (ucp[6] << 8) + ucp[7];
1920 }
1921 }
1922 return (fail_hour << 8) + fails;
1923 }
1924
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)
1928 {
1929 int num;
1930 UINT8 * ucp;
1931 unsigned char resp[LOG_RESP_SELF_TEST_LEN];
1932
1933 if (scsiLogSense(fd, SELFTEST_RESULTS_LPAGE, 0, resp,
1934 LOG_RESP_SELF_TEST_LEN, 0))
1935 return -1;
1936 if (resp[0] != SELFTEST_RESULTS_LPAGE)
1937 return -1;
1938 // compute page length
1939 num = (resp[2] << 8) + resp[3];
1940 // Log sense page length 0x190 bytes
1941 if (num != 0x190) {
1942 return -1;
1943 }
1944 ucp = resp + 4;
1945 if (inProgress)
1946 *inProgress = (0xf == (ucp[4] & 0xf)) ? 1 : 0;
1947 return 0;
1948 }
1949
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)
1955 {
1956 int err, offset;
1957 UINT8 buff[64];
1958 int pc = current ? MPAGE_CONTROL_CURRENT : MPAGE_CONTROL_DEFAULT;
1959
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)
1965 modese_len = 10;
1966 else
1967 return -EINVAL;
1968 } else if (0 == modese_len)
1969 modese_len = 6;
1970 }
1971 if (10 == modese_len) {
1972 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0, pc,
1973 buff, sizeof(buff));
1974 if (err)
1975 return -EINVAL;
1976 }
1977 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
1978 if ((offset >= 0) && (buff[offset + 1] >= 0xa))
1979 return (buff[offset + 2] & 2) ? 1 : 0;
1980 return -EINVAL;
1981 }
1982
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)
1988 {
1989 int err, offset, resp_len, sp;
1990 UINT8 buff[64];
1991 UINT8 ch_buff[64];
1992
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)
1999 modese_len = 10;
2000 else
2001 return err;
2002 } else if (0 == modese_len)
2003 modese_len = 6;
2004 }
2005 if (10 == modese_len) {
2006 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
2007 MPAGE_CONTROL_CURRENT,
2008 buff, sizeof(buff));
2009 if (err)
2010 return err;
2011 }
2012 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
2013 if ((offset < 0) || (buff[offset + 1] < 0xa))
2014 return SIMPLE_ERR_BAD_RESP;
2015
2016 if (enabled)
2017 enabled = 2;
2018 if (enabled == (buff[offset + 2] & 2))
2019 return 0; /* GLTSD already in wanted state so nothing to do */
2020
2021 if (modese_len == 6)
2022 err = scsiModeSense(device, CONTROL_MODE_PAGE, 0,
2023 MPAGE_CONTROL_CHANGEABLE,
2024 ch_buff, sizeof(ch_buff));
2025 else
2026 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
2027 MPAGE_CONTROL_CHANGEABLE,
2028 ch_buff, sizeof(ch_buff));
2029 if (err)
2030 return err;
2031 if (0 == (ch_buff[offset + 2] & 2))
2032 return SIMPLE_ERR_BAD_PARAM; /* GLTSD bit not chageable */
2033
2034 if (10 == modese_len) {
2035 resp_len = (buff[0] << 8) + buff[1] + 2;
2036 buff[3] &= 0xef; /* for disks mask out DPOFUA bit */
2037 } else {
2038 resp_len = buff[0] + 1;
2039 buff[2] &= 0xef; /* for disks mask out DPOFUA bit */
2040 }
2041 sp = (buff[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
2042 if (enabled)
2043 buff[offset + 2] |= 0x2; /* set GLTSD bit */
2044 else
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);
2050 return err;
2051 }
2052
2053 /* Returns a negative value if failed to fetch Protocol specific port mode
2054 page or it was malformed. Returns transport protocol identifier when
2055 value >= 0 . */
2056 int scsiFetchTransportProtocol(int device, int modese_len)
2057 {
2058 int err, offset;
2059 UINT8 buff[64];
2060
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)
2067 modese_len = 10;
2068 else
2069 return -EINVAL;
2070 } else if (0 == modese_len)
2071 modese_len = 6;
2072 }
2073 if (10 == modese_len) {
2074 err = scsiModeSense10(device, PROTOCOL_SPECIFIC_PORT_PAGE, 0,
2075 MPAGE_CONTROL_CURRENT,
2076 buff, sizeof(buff));
2077 if (err)
2078 return -EINVAL;
2079 }
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);
2085 }
2086 return -EINVAL;
2087 }