]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - scsicmds.cpp
afb7bdb0e915b54425eeaa3283168703f1c21938
[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.91 2006/09/12 00:25:44 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"}, /* 0x15 */
120 {MODE_SENSE, "mode sense"}, /* 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_NOT_READY:
175 if (SCSI_ASC_NO_MEDIUM == sinfo->asc)
176 return SIMPLE_ERR_NO_MEDIUM;
177 else if (SCSI_ASC_NOT_READY == sinfo->asc) {
178 if (0x1 == sinfo->ascq)
179 return SIMPLE_ERR_BECOMING_READY;
180 else
181 return SIMPLE_ERR_NOT_READY;
182 } else
183 return SIMPLE_ERR_NOT_READY;
184 case SCSI_SK_MEDIUM_ERROR:
185 case SCSI_SK_HARDWARE_ERROR:
186 return SIMPLE_ERR_MEDIUM_HARDWARE;
187 case SCSI_SK_ILLEGAL_REQUEST:
188 if (SCSI_ASC_UNKNOWN_OPCODE == sinfo->asc)
189 return SIMPLE_ERR_BAD_OPCODE;
190 else if (SCSI_ASC_UNKNOWN_FIELD == sinfo->asc)
191 return SIMPLE_ERR_BAD_FIELD;
192 else if (SCSI_ASC_UNKNOWN_PARAM == sinfo->asc)
193 return SIMPLE_ERR_BAD_PARAM;
194 else
195 return SIMPLE_ERR_BAD_PARAM; /* all other illegal request */
196 case SCSI_SK_UNIT_ATTENTION:
197 return SIMPLE_ERR_TRY_AGAIN;
198 default:
199 return SIMPLE_NO_ERROR;
200 }
201 }
202
203 const char * scsiErrString(int scsiErr)
204 {
205 if (scsiErr < 0)
206 return strerror(-scsiErr);
207 switch (scsiErr) {
208 case SIMPLE_NO_ERROR:
209 return "no error";
210 case SIMPLE_ERR_NOT_READY:
211 return "device not ready";
212 case SIMPLE_ERR_BAD_OPCODE:
213 return "unsupported scsi opcode";
214 case SIMPLE_ERR_BAD_FIELD:
215 return "unsupported field in scsi command";
216 case SIMPLE_ERR_BAD_PARAM:
217 return "badly formed scsi parameters";
218 case SIMPLE_ERR_BAD_RESP:
219 return "scsi response fails sanity test";
220 case SIMPLE_ERR_NO_MEDIUM:
221 return "no medium present";
222 case SIMPLE_ERR_BECOMING_READY:
223 return "device will be ready soon";
224 case SIMPLE_ERR_TRY_AGAIN:
225 return "unit attention reported, try again";
226 case SIMPLE_ERR_MEDIUM_HARDWARE:
227 return "medium or hardware error (serious)";
228 default:
229 return "unknown error";
230 }
231 }
232
233 /* Sends LOG SENSE command. Returns 0 if ok, 1 if device NOT READY, 2 if
234 command not supported, 3 if field (within command) not supported or
235 returns negated errno. SPC-3 sections 6.6 and 7.2 (rec 22a).
236 N.B. Sets PC==1 to fetch "current cumulative" log pages.
237 If known_resp_len > 0 then a single fetch is done for this response
238 length. If known_resp_len == 0 then twin fetches are performed, the
239 first to deduce the response length, then send the same command again
240 requesting the deduced response length. This protects certain fragile
241 HBAs. The twin fetch technique should not be used with the TapeAlert
242 log page since it clears its state flags after each fetch. */
243 int scsiLogSense(int device, int pagenum, int subpagenum, UINT8 *pBuf,
244 int bufLen, int known_resp_len)
245 {
246 struct scsi_cmnd_io io_hdr;
247 struct scsi_sense_disect sinfo;
248 UINT8 cdb[10];
249 UINT8 sense[32];
250 int pageLen;
251 int status, res;
252
253 if (known_resp_len > bufLen)
254 return -EIO;
255 if (known_resp_len > 0)
256 pageLen = known_resp_len;
257 else {
258 /* Starting twin fetch strategy: first fetch to find respone length */
259 pageLen = 4;
260 if (pageLen > bufLen)
261 return -EIO;
262 else
263 memset(pBuf, 0, pageLen);
264
265 memset(&io_hdr, 0, sizeof(io_hdr));
266 memset(cdb, 0, sizeof(cdb));
267 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
268 io_hdr.dxfer_len = pageLen;
269 io_hdr.dxferp = pBuf;
270 cdb[0] = LOG_SENSE;
271 cdb[2] = 0x40 | (pagenum & 0x3f); /* Page control (PC)==1 */
272 cdb[3] = subpagenum;
273 cdb[7] = (pageLen >> 8) & 0xff;
274 cdb[8] = pageLen & 0xff;
275 io_hdr.cmnd = cdb;
276 io_hdr.cmnd_len = sizeof(cdb);
277 io_hdr.sensep = sense;
278 io_hdr.max_sense_len = sizeof(sense);
279 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
280
281 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
282 if (0 != status)
283 return status;
284 scsi_do_sense_disect(&io_hdr, &sinfo);
285 if ((res = scsiSimpleSenseFilter(&sinfo)))
286 return res;
287 /* sanity check on response */
288 if ((SUPPORTED_LPAGES != pagenum) && (pBuf[0] != pagenum))
289 return SIMPLE_ERR_BAD_RESP;
290 if (0 == ((pBuf[2] << 8) + pBuf[3]))
291 return SIMPLE_ERR_BAD_RESP;
292 pageLen = (pBuf[2] << 8) + pBuf[3] + 4;
293 /* some SCSI HBA don't like "odd" length transfers */
294 if (pageLen % 2)
295 pageLen += 1;
296 if (pageLen > bufLen)
297 pageLen = bufLen;
298 }
299 memset(pBuf, 0, 4);
300 memset(&io_hdr, 0, sizeof(io_hdr));
301 memset(cdb, 0, sizeof(cdb));
302 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
303 io_hdr.dxfer_len = pageLen;
304 io_hdr.dxferp = pBuf;
305 cdb[0] = LOG_SENSE;
306 cdb[2] = 0x40 | (pagenum & 0x3f); /* Page control (PC)==1 */
307 cdb[7] = (pageLen >> 8) & 0xff;
308 cdb[8] = pageLen & 0xff;
309 io_hdr.cmnd = cdb;
310 io_hdr.cmnd_len = sizeof(cdb);
311 io_hdr.sensep = sense;
312 io_hdr.max_sense_len = sizeof(sense);
313 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
314
315 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
316 if (0 != status)
317 return status;
318 scsi_do_sense_disect(&io_hdr, &sinfo);
319 status = scsiSimpleSenseFilter(&sinfo);
320 if (0 != status)
321 return status;
322 /* sanity check on response */
323 if ((SUPPORTED_LPAGES != pagenum) && (pBuf[0] != pagenum))
324 return SIMPLE_ERR_BAD_RESP;
325 if (0 == ((pBuf[2] << 8) + pBuf[3]))
326 return SIMPLE_ERR_BAD_RESP;
327 return 0;
328 }
329
330 /* Send MODE SENSE (6 byte) command. Returns 0 if ok, 1 if NOT READY,
331 * 2 if command not supported (then MODE SENSE(10) should be supported),
332 * 3 if field in command not supported or returns negated errno.
333 * SPC-3 sections 6.9 and 7.4 (rev 22a) [mode subpage==0] */
334 int scsiModeSense(int device, int pagenum, int subpagenum, int pc,
335 UINT8 *pBuf, int bufLen)
336 {
337 struct scsi_cmnd_io io_hdr;
338 struct scsi_sense_disect sinfo;
339 UINT8 cdb[6];
340 UINT8 sense[32];
341 int status;
342
343 if ((bufLen < 0) || (bufLen > 255))
344 return -EINVAL;
345 memset(&io_hdr, 0, sizeof(io_hdr));
346 memset(cdb, 0, sizeof(cdb));
347 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
348 io_hdr.dxfer_len = bufLen;
349 io_hdr.dxferp = pBuf;
350 cdb[0] = MODE_SENSE;
351 cdb[2] = (pc << 6) | (pagenum & 0x3f);
352 cdb[3] = subpagenum;
353 cdb[4] = bufLen;
354 io_hdr.cmnd = cdb;
355 io_hdr.cmnd_len = sizeof(cdb);
356 io_hdr.sensep = sense;
357 io_hdr.max_sense_len = sizeof(sense);
358 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
359
360 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
361 if (0 != status)
362 return status;
363 scsi_do_sense_disect(&io_hdr, &sinfo);
364 status = scsiSimpleSenseFilter(&sinfo);
365 if (SIMPLE_ERR_TRY_AGAIN == status) {
366 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
367 if (0 != status)
368 return status;
369 scsi_do_sense_disect(&io_hdr, &sinfo);
370 status = scsiSimpleSenseFilter(&sinfo);
371 }
372 if ((0 == status) && (ALL_MODE_PAGES != pagenum)) {
373 int offset;
374
375 offset = scsiModePageOffset(pBuf, bufLen, 0);
376 if (offset < 0)
377 return SIMPLE_ERR_BAD_RESP;
378 else if (pagenum != (pBuf[offset] & 0x3f))
379 return SIMPLE_ERR_BAD_RESP;
380 }
381 return status;
382 }
383
384 /* Sends a 6 byte MODE SELECT command. Assumes given pBuf is the response
385 * from a corresponding 6 byte MODE SENSE command. Such a response should
386 * have a 4 byte header followed by 0 or more 8 byte block descriptors
387 * (normally 1) and then 1 mode page. Returns 0 if ok, 1 if NOT READY,
388 * 2 if command not supported (then MODE SELECT(10) may be supported),
389 * 3 if field in command not supported, 4 if bad parameter to command
390 * or returns negated errno. SPC-3 sections 6.7 and 7.4 (rev 22a) */
391 int scsiModeSelect(int device, int sp, UINT8 *pBuf, int bufLen)
392 {
393 struct scsi_cmnd_io io_hdr;
394 struct scsi_sense_disect sinfo;
395 UINT8 cdb[6];
396 UINT8 sense[32];
397 int status, pg_offset, pg_len, hdr_plus_1_pg;
398
399 pg_offset = 4 + pBuf[3];
400 if (pg_offset + 2 >= bufLen)
401 return -EINVAL;
402 pg_len = pBuf[pg_offset + 1] + 2;
403 hdr_plus_1_pg = pg_offset + pg_len;
404 if (hdr_plus_1_pg > bufLen)
405 return -EINVAL;
406 pBuf[0] = 0; /* Length of returned mode sense data reserved for SELECT */
407 pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */
408 memset(&io_hdr, 0, sizeof(io_hdr));
409 memset(cdb, 0, sizeof(cdb));
410 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
411 io_hdr.dxfer_len = hdr_plus_1_pg;
412 io_hdr.dxferp = pBuf;
413 cdb[0] = MODE_SELECT;
414 cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */
415 cdb[4] = hdr_plus_1_pg; /* make sure only one page sent */
416 io_hdr.cmnd = cdb;
417 io_hdr.cmnd_len = sizeof(cdb);
418 io_hdr.sensep = sense;
419 io_hdr.max_sense_len = sizeof(sense);
420 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
421
422 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
423 if (0 != status)
424 return status;
425 scsi_do_sense_disect(&io_hdr, &sinfo);
426 return scsiSimpleSenseFilter(&sinfo);
427 }
428
429 /* MODE SENSE (10 byte). Returns 0 if ok, 1 if NOT READY, 2 if command
430 * not supported (then MODE SENSE(6) might be supported), 3 if field in
431 * command not supported or returns negated errno.
432 * SPC-3 sections 6.10 and 7.4 (rev 22a) [mode subpage==0] */
433 int scsiModeSense10(int device, int pagenum, int subpagenum, int pc,
434 UINT8 *pBuf, int bufLen)
435 {
436 struct scsi_cmnd_io io_hdr;
437 struct scsi_sense_disect sinfo;
438 UINT8 cdb[10];
439 UINT8 sense[32];
440 int status;
441
442 memset(&io_hdr, 0, sizeof(io_hdr));
443 memset(cdb, 0, sizeof(cdb));
444 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
445 io_hdr.dxfer_len = bufLen;
446 io_hdr.dxferp = pBuf;
447 cdb[0] = MODE_SENSE_10;
448 cdb[2] = (pc << 6) | (pagenum & 0x3f);
449 cdb[3] = subpagenum;
450 cdb[7] = (bufLen >> 8) & 0xff;
451 cdb[8] = bufLen & 0xff;
452 io_hdr.cmnd = cdb;
453 io_hdr.cmnd_len = sizeof(cdb);
454 io_hdr.sensep = sense;
455 io_hdr.max_sense_len = sizeof(sense);
456 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
457
458 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
459 if (0 != status)
460 return status;
461 scsi_do_sense_disect(&io_hdr, &sinfo);
462 status = scsiSimpleSenseFilter(&sinfo);
463 if (SIMPLE_ERR_TRY_AGAIN == status) {
464 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
465 if (0 != status)
466 return status;
467 scsi_do_sense_disect(&io_hdr, &sinfo);
468 status = scsiSimpleSenseFilter(&sinfo);
469 }
470 if ((0 == status) && (ALL_MODE_PAGES != pagenum)) {
471 int offset;
472
473 offset = scsiModePageOffset(pBuf, bufLen, 1);
474 if (offset < 0)
475 return SIMPLE_ERR_BAD_RESP;
476 else if (pagenum != (pBuf[offset] & 0x3f))
477 return SIMPLE_ERR_BAD_RESP;
478 }
479 return status;
480 }
481
482 /* Sends a 10 byte MODE SELECT command. Assumes given pBuf is the response
483 * from a corresponding 10 byte MODE SENSE command. Such a response should
484 * have a 8 byte header followed by 0 or more 8 byte block descriptors
485 * (normally 1) and then 1 mode page. Returns 0 if ok, 1 NOT REAFY, 2 if
486 * command not supported (then MODE SELECT(6) may be supported), 3 if field
487 * in command not supported, 4 if bad parameter to command or returns
488 * negated errno. SPC-3 sections 6.8 and 7.4 (rev 22a) */
489 int scsiModeSelect10(int device, int sp, UINT8 *pBuf, int bufLen)
490 {
491 struct scsi_cmnd_io io_hdr;
492 struct scsi_sense_disect sinfo;
493 UINT8 cdb[10];
494 UINT8 sense[32];
495 int status, pg_offset, pg_len, hdr_plus_1_pg;
496
497 pg_offset = 8 + (pBuf[6] << 8) + pBuf[7];
498 if (pg_offset + 2 >= bufLen)
499 return -EINVAL;
500 pg_len = pBuf[pg_offset + 1] + 2;
501 hdr_plus_1_pg = pg_offset + pg_len;
502 if (hdr_plus_1_pg > bufLen)
503 return -EINVAL;
504 pBuf[0] = 0;
505 pBuf[1] = 0; /* Length of returned mode sense data reserved for SELECT */
506 pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */
507 memset(&io_hdr, 0, sizeof(io_hdr));
508 memset(cdb, 0, sizeof(cdb));
509 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
510 io_hdr.dxfer_len = hdr_plus_1_pg;
511 io_hdr.dxferp = pBuf;
512 cdb[0] = MODE_SELECT_10;
513 cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */
514 cdb[8] = hdr_plus_1_pg; /* make sure only one page sent */
515 io_hdr.cmnd = cdb;
516 io_hdr.cmnd_len = sizeof(cdb);
517 io_hdr.sensep = sense;
518 io_hdr.max_sense_len = sizeof(sense);
519 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
520
521 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
522 if (0 != status)
523 return status;
524 scsi_do_sense_disect(&io_hdr, &sinfo);
525 return scsiSimpleSenseFilter(&sinfo);
526 }
527
528 /* Standard INQUIRY returns 0 for ok, anything else is a major problem.
529 * bufLen should be 36 for unsafe devices (like USB mass storage stuff)
530 * otherwise they can lock up! SPC-3 sections 6.4 and 7.6 (rev 22a) */
531 int scsiStdInquiry(int device, UINT8 *pBuf, int bufLen)
532 {
533 struct scsi_sense_disect sinfo;
534 struct scsi_cmnd_io io_hdr;
535 UINT8 cdb[6];
536 UINT8 sense[32];
537 int status;
538
539 if ((bufLen < 0) || (bufLen > 255))
540 return -EINVAL;
541 memset(&io_hdr, 0, sizeof(io_hdr));
542 memset(cdb, 0, sizeof(cdb));
543 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
544 io_hdr.dxfer_len = bufLen;
545 io_hdr.dxferp = pBuf;
546 cdb[0] = INQUIRY;
547 cdb[4] = bufLen;
548 io_hdr.cmnd = cdb;
549 io_hdr.cmnd_len = sizeof(cdb);
550 io_hdr.sensep = sense;
551 io_hdr.max_sense_len = sizeof(sense);
552 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
553
554 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
555 if (0 != status)
556 return status;
557 scsi_do_sense_disect(&io_hdr, &sinfo);
558 return scsiSimpleSenseFilter(&sinfo);
559 }
560
561 /* INQUIRY to fetch Vital Page Data. Returns 0 if ok, 1 if NOT READY
562 * (unlikely), 2 if command not supported, 3 if field in command not
563 * supported, 5 if response indicates that EVPD bit ignored or returns
564 * negated errno. SPC-3 section 6.4 and 7.6 (rev 22a) */
565 int scsiInquiryVpd(int device, int vpd_page, UINT8 *pBuf, int bufLen)
566 {
567 struct scsi_cmnd_io io_hdr;
568 struct scsi_sense_disect sinfo;
569 UINT8 cdb[6];
570 UINT8 sense[32];
571 int status, res;
572
573 if ((bufLen < 0) || (bufLen > 255))
574 return -EINVAL;
575 memset(&io_hdr, 0, sizeof(io_hdr));
576 memset(cdb, 0, sizeof(cdb));
577 if (bufLen > 1)
578 pBuf[1] = 0x0;
579 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
580 io_hdr.dxfer_len = bufLen;
581 io_hdr.dxferp = pBuf;
582 cdb[0] = INQUIRY;
583 cdb[1] = 0x1; /* set EVPD bit (enable Vital Product Data) */
584 cdb[2] = vpd_page;
585 cdb[4] = bufLen;
586 io_hdr.cmnd = cdb;
587 io_hdr.cmnd_len = sizeof(cdb);
588 io_hdr.sensep = sense;
589 io_hdr.max_sense_len = sizeof(sense);
590 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
591
592 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
593 if (0 != status)
594 return status;
595 scsi_do_sense_disect(&io_hdr, &sinfo);
596 if ((res = scsiSimpleSenseFilter(&sinfo)))
597 return res;
598 /* Guard against devices that ignore EVPD bit and do standard INQUIRY */
599 if (bufLen > 1) {
600 if (vpd_page == pBuf[1]) {
601 if ((0x80 == vpd_page) && (bufLen > 2) && (0x0 != pBuf[2]))
602 return SIMPLE_ERR_BAD_RESP;
603 } else
604 return SIMPLE_ERR_BAD_RESP;
605 }
606 return 0;
607 }
608
609 /* REQUEST SENSE command. Returns 0 if ok, anything else major problem.
610 * SPC-3 section 6.27 (rev 22a) */
611 int scsiRequestSense(int device, struct scsi_sense_disect * sense_info)
612 {
613 struct scsi_cmnd_io io_hdr;
614 UINT8 cdb[6];
615 UINT8 sense[32];
616 UINT8 buff[18];
617 int status, len;
618 UINT8 ecode;
619
620 memset(&io_hdr, 0, sizeof(io_hdr));
621 memset(cdb, 0, sizeof(cdb));
622 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
623 io_hdr.dxfer_len = sizeof(buff);
624 io_hdr.dxferp = buff;
625 cdb[0] = REQUEST_SENSE;
626 cdb[4] = sizeof(buff);
627 io_hdr.cmnd = cdb;
628 io_hdr.cmnd_len = sizeof(cdb);
629 io_hdr.sensep = sense;
630 io_hdr.max_sense_len = sizeof(sense);
631 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
632
633 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
634 if ((0 == status) && (sense_info)) {
635 ecode = buff[0] & 0x7f;
636 sense_info->error_code = ecode;
637 sense_info->sense_key = buff[2] & 0xf;
638 sense_info->asc = 0;
639 sense_info->ascq = 0;
640 if ((0x70 == ecode) || (0x71 == ecode)) {
641 len = buff[7] + 8;
642 if (len > 13) {
643 sense_info->asc = buff[12];
644 sense_info->ascq = buff[13];
645 }
646 }
647 }
648 return status;
649 }
650
651 /* SEND DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if command
652 * not supported, 3 if field in command not supported or returns negated
653 * errno. SPC-3 section 6.28 (rev 22a) */
654 int scsiSendDiagnostic(int device, int functioncode, UINT8 *pBuf, int bufLen)
655 {
656 struct scsi_cmnd_io io_hdr;
657 struct scsi_sense_disect sinfo;
658 UINT8 cdb[6];
659 UINT8 sense[32];
660 int status;
661
662 memset(&io_hdr, 0, sizeof(io_hdr));
663 memset(cdb, 0, sizeof(cdb));
664 io_hdr.dxfer_dir = bufLen ? DXFER_TO_DEVICE: DXFER_NONE;
665 io_hdr.dxfer_len = bufLen;
666 io_hdr.dxferp = pBuf;
667 cdb[0] = SEND_DIAGNOSTIC;
668 if (SCSI_DIAG_DEF_SELF_TEST == functioncode)
669 cdb[1] = 0x4; /* SelfTest bit */
670 else if (SCSI_DIAG_NO_SELF_TEST != functioncode)
671 cdb[1] = (functioncode & 0x7) << 5; /* SelfTest _code_ */
672 else /* SCSI_DIAG_NO_SELF_TEST == functioncode */
673 cdb[1] = 0x10; /* PF bit */
674 cdb[3] = (bufLen >> 8) & 0xff;
675 cdb[4] = bufLen & 0xff;
676 io_hdr.cmnd = cdb;
677 io_hdr.cmnd_len = sizeof(cdb);
678 io_hdr.sensep = sense;
679 io_hdr.max_sense_len = sizeof(sense);
680 /* worst case is an extended foreground self test on a big disk */
681 io_hdr.timeout = SCSI_TIMEOUT_SELF_TEST;
682
683 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
684 if (0 != status)
685 return status;
686 scsi_do_sense_disect(&io_hdr, &sinfo);
687 return scsiSimpleSenseFilter(&sinfo);
688 }
689
690 /* RECEIVE DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if
691 * command not supported, 3 if field in command not supported or returns
692 * negated errno. SPC-3 section 6.18 (rev 22a) */
693 int scsiReceiveDiagnostic(int device, int pcv, int pagenum, UINT8 *pBuf,
694 int bufLen)
695 {
696 struct scsi_cmnd_io io_hdr;
697 struct scsi_sense_disect sinfo;
698 UINT8 cdb[6];
699 UINT8 sense[32];
700 int status;
701
702 memset(&io_hdr, 0, sizeof(io_hdr));
703 memset(cdb, 0, sizeof(cdb));
704 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
705 io_hdr.dxfer_len = bufLen;
706 io_hdr.dxferp = pBuf;
707 cdb[0] = RECEIVE_DIAGNOSTIC;
708 cdb[1] = pcv;
709 cdb[2] = pagenum;
710 cdb[3] = (bufLen >> 8) & 0xff;
711 cdb[4] = bufLen & 0xff;
712 io_hdr.cmnd = cdb;
713 io_hdr.cmnd_len = sizeof(cdb);
714 io_hdr.sensep = sense;
715 io_hdr.max_sense_len = sizeof(sense);
716 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
717
718 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
719 if (0 != status)
720 return status;
721 scsi_do_sense_disect(&io_hdr, &sinfo);
722 return scsiSimpleSenseFilter(&sinfo);
723 }
724
725 /* TEST UNIT READY command. SPC-3 section 6.33 (rev 22a) */
726 static int _testunitready(int device, struct scsi_sense_disect * sinfo)
727 {
728 struct scsi_cmnd_io io_hdr;
729 UINT8 cdb[6];
730 UINT8 sense[32];
731 int status;
732
733 memset(&io_hdr, 0, sizeof(io_hdr));
734 memset(cdb, 0, sizeof(cdb));
735 io_hdr.dxfer_dir = DXFER_NONE;
736 io_hdr.dxfer_len = 0;
737 io_hdr.dxferp = NULL;
738 cdb[0] = TEST_UNIT_READY;
739 io_hdr.cmnd = cdb;
740 io_hdr.cmnd_len = sizeof(cdb);
741 io_hdr.sensep = sense;
742 io_hdr.max_sense_len = sizeof(sense);
743 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
744
745 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
746 if (0 != status)
747 return status;
748 scsi_do_sense_disect(&io_hdr, sinfo);
749 return 0;
750 }
751
752 /* Returns 0 for device responds and media ready, 1 for device responds and
753 media not ready, or returns a negated errno value */
754 int scsiTestUnitReady(int device)
755 {
756 struct scsi_sense_disect sinfo;
757 int status;
758
759 status = _testunitready(device, &sinfo);
760 if (0 != status)
761 return status;
762 status = scsiSimpleSenseFilter(&sinfo);
763 if (SIMPLE_ERR_TRY_AGAIN == status) {
764 /* power on reset, media changed, ok ... try again */
765 status = _testunitready(device, &sinfo);
766 if (0 != status)
767 return status;
768 status = scsiSimpleSenseFilter(&sinfo);
769 }
770 return status;
771 }
772
773 /* READ DEFECT (10) command. Returns 0 if ok, 1 if NOT READY, 2 if
774 * command not supported, 3 if field in command not supported or returns
775 * negated errno. SBC-2 section 5.12 (rev 16) */
776 int scsiReadDefect10(int device, int req_plist, int req_glist, int dl_format,
777 UINT8 *pBuf, int bufLen)
778 {
779 struct scsi_cmnd_io io_hdr;
780 struct scsi_sense_disect sinfo;
781 UINT8 cdb[10];
782 UINT8 sense[32];
783 int status;
784
785 memset(&io_hdr, 0, sizeof(io_hdr));
786 memset(cdb, 0, sizeof(cdb));
787 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
788 io_hdr.dxfer_len = bufLen;
789 io_hdr.dxferp = pBuf;
790 cdb[0] = READ_DEFECT_10;
791 cdb[2] = (unsigned char)(((req_plist << 4) & 0x10) |
792 ((req_glist << 3) & 0x8) | (dl_format & 0x7));
793 cdb[7] = (bufLen >> 8) & 0xff;
794 cdb[8] = bufLen & 0xff;
795 io_hdr.cmnd = cdb;
796 io_hdr.cmnd_len = sizeof(cdb);
797 io_hdr.sensep = sense;
798 io_hdr.max_sense_len = sizeof(sense);
799 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
800
801 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
802 if (0 != status)
803 return status;
804 scsi_do_sense_disect(&io_hdr, &sinfo);
805 return scsiSimpleSenseFilter(&sinfo);
806 }
807
808 /* Offset into mode sense (6 or 10 byte) response that actual mode page
809 * starts at (relative to resp[0]). Returns -1 if problem */
810 int scsiModePageOffset(const UINT8 * resp, int len, int modese_len)
811 {
812 int resp_len, bd_len;
813 int offset = -1;
814
815 if (resp) {
816 if (10 == modese_len) {
817 resp_len = (resp[0] << 8) + resp[1] + 2;
818 bd_len = (resp[6] << 8) + resp[7];
819 offset = bd_len + 8;
820 } else {
821 resp_len = resp[0] + 1;
822 bd_len = resp[3];
823 offset = bd_len + 4;
824 }
825 if ((offset + 2) > len) {
826 pout("scsiModePageOffset: raw_curr too small, offset=%d "
827 "resp_len=%d bd_len=%d\n", offset, resp_len, bd_len);
828 offset = -1;
829 } else if ((offset + 2) > resp_len) {
830 if ((resp_len > 2) || con->reportscsiioctl)
831 pout("scsiModePageOffset: response length too short, "
832 "resp_len=%d offset=%d bd_len=%d\n", resp_len,
833 offset, bd_len);
834 offset = -1;
835 }
836 }
837 return offset;
838 }
839
840 /* IEC mode page byte 2 bit masks */
841 #define DEXCPT_ENABLE 0x08
842 #define EWASC_ENABLE 0x10
843 #define DEXCPT_DISABLE 0xf7
844 #define EWASC_DISABLE 0xef
845 #define TEST_DISABLE 0xfb
846
847 /* Fetches the Informational Exceptions Control mode page. First tries
848 * the 6 byte MODE SENSE command and if that fails with an illegal opcode
849 * tries a 10 byte MODE SENSE command. Returns 0 if successful, a positive
850 * number if a known error (see SIMPLE_ERR_ ...) or a negative errno
851 * value. */
852 int scsiFetchIECmpage(int device, struct scsi_iec_mode_page *iecp, int modese_len)
853 {
854 int err = 0;
855
856 memset(iecp, 0, sizeof(*iecp));
857 iecp->modese_len = modese_len;
858 iecp->requestedCurrent = 1;
859 if (iecp->modese_len <= 6) {
860 if ((err = scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE,
861 0, MPAGE_CONTROL_CURRENT,
862 iecp->raw_curr, sizeof(iecp->raw_curr)))) {
863 if (SIMPLE_ERR_BAD_OPCODE == err)
864 iecp->modese_len = 10;
865 else {
866 iecp->modese_len = 0;
867 return err;
868 }
869 } else if (0 == iecp->modese_len)
870 iecp->modese_len = 6;
871 }
872 if (10 == iecp->modese_len) {
873 err = scsiModeSense10(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE,
874 0, MPAGE_CONTROL_CURRENT,
875 iecp->raw_curr, sizeof(iecp->raw_curr));
876 if (err) {
877 iecp->modese_len = 0;
878 return err;
879 }
880 }
881 iecp->gotCurrent = 1;
882 iecp->requestedChangeable = 1;
883 if (10 == iecp->modese_len)
884 err = scsiModeSense10(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE,
885 0, MPAGE_CONTROL_CHANGEABLE,
886 iecp->raw_chg, sizeof(iecp->raw_chg));
887 else if (6 == iecp->modese_len)
888 err = scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE,
889 0, MPAGE_CONTROL_CHANGEABLE,
890 iecp->raw_chg, sizeof(iecp->raw_chg));
891 if (err)
892 return err;
893 iecp->gotChangeable = 1;
894 return 0;
895 }
896
897 int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
898 {
899 int offset;
900
901 if (iecp && iecp->gotCurrent) {
902 offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
903 iecp->modese_len);
904 if (offset >= 0)
905 return (iecp->raw_curr[offset + 2] & DEXCPT_ENABLE) ? 0 : 1;
906 else
907 return 0;
908 } else
909 return 0;
910 }
911
912 int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
913 {
914 int offset;
915
916 if (iecp && iecp->gotCurrent) {
917 offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
918 iecp->modese_len);
919 if (offset >= 0)
920 return (iecp->raw_curr[offset + 2] & EWASC_ENABLE) ? 1 : 0;
921 else
922 return 0;
923 } else
924 return 0;
925 }
926
927 /* set EWASC and clear PERF, EBF, DEXCPT TEST and LOGERR */
928 #define SCSI_IEC_MP_BYTE2_ENABLED 0x10
929 #define SCSI_IEC_MP_BYTE2_TEST_MASK 0x4
930 /* exception/warning via an unrequested REQUEST SENSE command */
931 #define SCSI_IEC_MP_MRIE 6
932 #define SCSI_IEC_MP_INTERVAL_T 0
933 #define SCSI_IEC_MP_REPORT_COUNT 1
934
935 /* Try to set (or clear) both Exception Control and Warning in the IE
936 * mode page subject to the "changeable" mask. The object pointed to
937 * by iecp is (possibly) inaccurate after this call, therefore
938 * scsiFetchIECmpage() should be called again if the IEC mode page
939 * is to be re-examined.
940 * When -r ioctl is invoked 3 or more time on 'smartctl -s on ...'
941 * then set the TEST bit (causes asc,ascq pair of 0x5d,0xff). */
942 int scsiSetExceptionControlAndWarning(int device, int enabled,
943 const struct scsi_iec_mode_page *iecp)
944 {
945 int k, offset, resp_len;
946 int err = 0;
947 UINT8 rout[SCSI_IECMP_RAW_LEN];
948 int sp, eCEnabled, wEnabled;
949
950 if ((! iecp) || (! iecp->gotCurrent))
951 return -EINVAL;
952 offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
953 iecp->modese_len);
954 if (offset < 0)
955 return -EINVAL;
956 memcpy(rout, iecp->raw_curr, SCSI_IECMP_RAW_LEN);
957 if (10 == iecp->modese_len) {
958 resp_len = (rout[0] << 8) + rout[1] + 2;
959 rout[3] &= 0xef; /* for disks mask out DPOFUA bit */
960 } else {
961 resp_len = rout[0] + 1;
962 rout[2] &= 0xef; /* for disks mask out DPOFUA bit */
963 }
964 sp = (rout[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
965 if (enabled) {
966 rout[offset + 2] = SCSI_IEC_MP_BYTE2_ENABLED;
967 if (con->reportscsiioctl > 2)
968 rout[offset + 2] |= SCSI_IEC_MP_BYTE2_TEST_MASK;
969 rout[offset + 3] = SCSI_IEC_MP_MRIE;
970 rout[offset + 4] = (SCSI_IEC_MP_INTERVAL_T >> 24) & 0xff;
971 rout[offset + 5] = (SCSI_IEC_MP_INTERVAL_T >> 16) & 0xff;
972 rout[offset + 6] = (SCSI_IEC_MP_INTERVAL_T >> 8) & 0xff;
973 rout[offset + 7] = SCSI_IEC_MP_INTERVAL_T & 0xff;
974 rout[offset + 8] = (SCSI_IEC_MP_REPORT_COUNT >> 24) & 0xff;
975 rout[offset + 9] = (SCSI_IEC_MP_REPORT_COUNT >> 16) & 0xff;
976 rout[offset + 10] = (SCSI_IEC_MP_REPORT_COUNT >> 8) & 0xff;
977 rout[offset + 11] = SCSI_IEC_MP_REPORT_COUNT & 0xff;
978 if (iecp->gotChangeable) {
979 UINT8 chg2 = iecp->raw_chg[offset + 2];
980
981 rout[offset + 2] = chg2 ? (rout[offset + 2] & chg2) :
982 iecp->raw_curr[offset + 2];
983 for (k = 3; k < 12; ++k) {
984 if (0 == iecp->raw_chg[offset + k])
985 rout[offset + k] = iecp->raw_curr[offset + k];
986 }
987 }
988 if (0 == memcmp(&rout[offset + 2], &iecp->raw_chg[offset + 2], 10)) {
989 if (con->reportscsiioctl > 0)
990 pout("scsiSetExceptionControlAndWarning: already enabled\n");
991 return 0;
992 }
993 } else { /* disabling Exception Control and (temperature) Warnings */
994 eCEnabled = (rout[offset + 2] & DEXCPT_ENABLE) ? 0 : 1;
995 wEnabled = (rout[offset + 2] & EWASC_ENABLE) ? 1 : 0;
996 if ((! eCEnabled) && (! wEnabled)) {
997 if (con->reportscsiioctl > 0)
998 pout("scsiSetExceptionControlAndWarning: already disabled\n");
999 return 0; /* nothing to do, leave other setting alone */
1000 }
1001 if (wEnabled)
1002 rout[offset + 2] &= EWASC_DISABLE;
1003 if (eCEnabled) {
1004 if (iecp->gotChangeable &&
1005 (iecp->raw_chg[offset + 2] & DEXCPT_ENABLE))
1006 rout[offset + 2] |= DEXCPT_ENABLE;
1007 rout[offset + 2] &= TEST_DISABLE;/* clear TEST bit for spec */
1008 }
1009 }
1010 if (10 == iecp->modese_len)
1011 err = scsiModeSelect10(device, sp, rout, resp_len);
1012 else if (6 == iecp->modese_len)
1013 err = scsiModeSelect(device, sp, rout, resp_len);
1014 return err;
1015 }
1016
1017 int scsiGetTemp(int device, UINT8 *currenttemp, UINT8 *triptemp)
1018 {
1019 UINT8 tBuf[252];
1020 int err;
1021
1022 memset(tBuf, 0, sizeof(tBuf));
1023 if ((err = scsiLogSense(device, TEMPERATURE_LPAGE, 0, tBuf,
1024 sizeof(tBuf), 0))) {
1025 *currenttemp = 0;
1026 *triptemp = 0;
1027 pout("Log Sense for temperature failed [%s]\n", scsiErrString(err));
1028 return err;
1029 }
1030 *currenttemp = tBuf[9];
1031 *triptemp = tBuf[15];
1032 return 0;
1033 }
1034
1035 /* Read informational exception log page or Request Sense response.
1036 * Fetching asc/ascq code potentially flagging an exception or warning.
1037 * Returns 0 if ok, else error number. A current temperature of 255
1038 * (Celsius) implies that the temperature not available. */
1039 int scsiCheckIE(int device, int hasIELogPage, int hasTempLogPage,
1040 UINT8 *asc, UINT8 *ascq, UINT8 *currenttemp,
1041 UINT8 *triptemp)
1042 {
1043 UINT8 tBuf[252];
1044 struct scsi_sense_disect sense_info;
1045 int err;
1046 int temperatureSet = 0;
1047 unsigned short pagesize;
1048 UINT8 currTemp, trTemp;
1049
1050 *asc = 0;
1051 *ascq = 0;
1052 *currenttemp = 0;
1053 *triptemp = 0;
1054 memset(tBuf,0,sizeof(tBuf)); // need to clear stack space of junk
1055 memset(&sense_info, 0, sizeof(sense_info));
1056 if (hasIELogPage) {
1057 if ((err = scsiLogSense(device, IE_LPAGE, 0, tBuf,
1058 sizeof(tBuf), 0))) {
1059 pout("Log Sense failed, IE page [%s]\n", scsiErrString(err));
1060 return err;
1061 }
1062 // pull out page size from response, don't forget to add 4
1063 pagesize = (unsigned short) ((tBuf[2] << 8) | tBuf[3]) + 4;
1064 if ((pagesize < 4) || tBuf[4] || tBuf[5]) {
1065 pout("Log Sense failed, IE page, bad parameter code or length\n");
1066 return SIMPLE_ERR_BAD_PARAM;
1067 }
1068 if (tBuf[7] > 1) {
1069 sense_info.asc = tBuf[8];
1070 sense_info.ascq = tBuf[9];
1071 if (! hasTempLogPage) {
1072 if (tBuf[7] > 2)
1073 *currenttemp = tBuf[10];
1074 if (tBuf[7] > 3) /* IBM extension in SMART (IE) lpage */
1075 *triptemp = tBuf[11];
1076 }
1077 }
1078 }
1079 if (0 == sense_info.asc) {
1080 /* ties in with MRIE field of 6 in IEC mode page (0x1c) */
1081 if ((err = scsiRequestSense(device, &sense_info))) {
1082 pout("Request Sense failed, [%s]\n", scsiErrString(err));
1083 return err;
1084 }
1085 }
1086 *asc = sense_info.asc;
1087 *ascq = sense_info.ascq;
1088 if ((! temperatureSet) && hasTempLogPage) {
1089 if (0 == scsiGetTemp(device, &currTemp, &trTemp)) {
1090 *currenttemp = currTemp;
1091 *triptemp = trTemp;
1092 }
1093 }
1094 return 0;
1095 }
1096
1097 // The first character (W, C, I) tells the severity
1098 static const char * TapeAlertsMessageTable[]= {
1099 " ",
1100 /* 0x01 */
1101 "W: The tape drive is having problems reading data. No data has been lost,\n"
1102 " but there has been a reduction in the performance of the tape.",
1103 /* 0x02 */
1104 "W: The tape drive is having problems writing data. No data has been lost,\n"
1105 " but there has been a reduction in the capacity of the tape.",
1106 /* 0x03 */
1107 "W: The operation has stopped because an error has occurred while reading\n"
1108 " or writing data that the drive cannot correct.",
1109 /* 0x04 */
1110 "C: Your data is at risk:\n"
1111 " 1. Copy any data you require from this tape. \n"
1112 " 2. Do not use this tape again.\n"
1113 " 3. Restart the operation with a different tape.",
1114 /* 0x05 */
1115 "C: The tape is damaged or the drive is faulty. Call the tape drive\n"
1116 " supplier helpline.",
1117 /* 0x06 */
1118 "C: The tape is from a faulty batch or the tape drive is faulty:\n"
1119 " 1. Use a good tape to test the drive.\n"
1120 " 2. If problem persists, call the tape drive supplier helpline.",
1121 /* 0x07 */
1122 "W: The tape cartridge has reached the end of its calculated useful life:\n"
1123 " 1. Copy data you need to another tape.\n"
1124 " 2. Discard the old tape.",
1125 /* 0x08 */
1126 "W: The tape cartridge is not data-grade. Any data you back up to the tape\n"
1127 " is at risk. Replace the cartridge with a data-grade tape.",
1128 /* 0x09 */
1129 "C: You are trying to write to a write-protected cartridge. Remove the\n"
1130 " write-protection or use another tape.",
1131 /* 0x0a */
1132 "I: You cannot eject the cartridge because the tape drive is in use. Wait\n"
1133 " until the operation is complete before ejecting the cartridge.",
1134 /* 0x0b */
1135 "I: The tape in the drive is a cleaning cartridge.",
1136 /* 0x0c */
1137 "I: You have tried to load a cartridge of a type which is not supported\n"
1138 " by this drive.",
1139 /* 0x0d */
1140 "C: The operation has failed because the tape in the drive has experienced\n"
1141 " a mechanical failure:\n"
1142 " 1. Discard the old tape.\n"
1143 " 2. Restart the operation with a different tape.",
1144 /* 0x0e */
1145 "C: The operation has failed because the tape in the drive has experienced\n"
1146 " a mechanical failure:\n"
1147 " 1. Do not attempt to extract the tape cartridge\n"
1148 " 2. Call the tape drive supplier helpline.",
1149 /* 0x0f */
1150 "W: The memory in the tape cartridge has failed, which reduces\n"
1151 " performance. Do not use the cartridge for further write operations.",
1152 /* 0x10 */
1153 "C: The operation has failed because the tape cartridge was manually\n"
1154 " de-mounted while the tape drive was actively writing or reading.",
1155 /* 0x11 */
1156 "W: You have loaded a cartridge of a type that is read-only in this drive.\n"
1157 " The cartridge will appear as write-protected.",
1158 /* 0x12 */
1159 "W: The tape directory on the tape cartridge has been corrupted. File\n"
1160 " search performance will be degraded. The tape directory can be rebuilt\n"
1161 " by reading all the data on the cartridge.",
1162 /* 0x13 */
1163 "I: The tape cartridge is nearing the end of its calculated life. It is\n"
1164 " recommended that you:\n"
1165 " 1. Use another tape cartridge for your next backup.\n"
1166 " 2. Store this tape in a safe place in case you need to restore "
1167 " data from it.",
1168 /* 0x14 */
1169 "C: The tape drive needs cleaning:\n"
1170 " 1. If the operation has stopped, eject the tape and clean the drive.\n"
1171 " 2. If the operation has not stopped, wait for it to finish and then\n"
1172 " clean the drive.\n"
1173 " Check the tape drive users manual for device specific cleaning instructions.",
1174 /* 0x15 */
1175 "W: The tape drive is due for routine cleaning:\n"
1176 " 1. Wait for the current operation to finish.\n"
1177 " 2. The use a cleaning cartridge.\n"
1178 " Check the tape drive users manual for device specific cleaning instructions.",
1179 /* 0x16 */
1180 "C: The last cleaning cartridge used in the tape drive has worn out:\n"
1181 " 1. Discard the worn out cleaning cartridge.\n"
1182 " 2. Wait for the current operation to finish.\n"
1183 " 3. Then use a new cleaning cartridge.",
1184 /* 0x17 */
1185 "C: The last cleaning cartridge used in the tape drive was an invalid\n"
1186 " type:\n"
1187 " 1. Do not use this cleaning cartridge in this drive.\n"
1188 " 2. Wait for the current operation to finish.\n"
1189 " 3. Then use a new cleaning cartridge.",
1190 /* 0x18 */
1191 "W: The tape drive has requested a retention operation",
1192 /* 0x19 */
1193 "W: A redundant interface port on the tape drive has failed",
1194 /* 0x1a */
1195 "W: A tape drive cooling fan has failed",
1196 /* 0x1b */
1197 "W: A redundant power supply has failed inside the tape drive enclosure.\n"
1198 " Check the enclosure users manual for instructions on replacing the\n"
1199 " failed power supply.",
1200 /* 0x1c */
1201 "W: The tape drive power consumption is outside the specified range.",
1202 /* 0x1d */
1203 "W: Preventive maintenance of the tape drive is required. Check the tape\n"
1204 " drive users manual for device specific preventive maintenance\n"
1205 " tasks or call the tape drive supplier helpline.",
1206 /* 0x1e */
1207 "C: The tape drive has a hardware fault:\n"
1208 " 1. Eject the tape or magazine.\n"
1209 " 2. Reset the drive.\n"
1210 " 3. Restart the operation.",
1211 /* 0x1f */
1212 "C: The tape drive has a hardware fault:\n"
1213 " 1. Turn the tape drive off and then on again.\n"
1214 " 2. Restart the operation.\n"
1215 " 3. If the problem persists, call the tape drive supplier helpline.",
1216 /* 0x20 */
1217 "W: The tape drive has a problem with the application client interface:\n"
1218 " 1. Check the cables and cable connections.\n"
1219 " 2. Restart the operation.",
1220 /* 0x21 */
1221 "C: The operation has failed:\n"
1222 " 1. Eject the tape or magazine.\n"
1223 " 2. Insert the tape or magazine again.\n"
1224 " 3. Restart the operation.",
1225 /* 0x22 */
1226 "W: The firmware download has failed because you have tried to use the\n"
1227 " incorrect firmware for this tape drive. Obtain the correct\n"
1228 " firmware and try again.",
1229 /* 0x23 */
1230 "W: Environmental conditions inside the tape drive are outside the\n"
1231 " specified humidity range.",
1232 /* 0x24 */
1233 "W: Environmental conditions inside the tape drive are outside the\n"
1234 " specified temperature range.",
1235 /* 0x25 */
1236 "W: The voltage supply to the tape drive is outside the specified range.",
1237 /* 0x26 */
1238 "C: A hardware failure of the tape drive is predicted. Call the tape\n"
1239 " drive supplier helpline.",
1240 /* 0x27 */
1241 "W: The tape drive may have a hardware fault. Run extended diagnostics to\n"
1242 " verify and diagnose the problem. Check the tape drive users manual for\n"
1243 " device specific instructions on running extended diagnostic tests.",
1244 /* 0x28 */
1245 "C: The changer mechanism is having difficulty communicating with the tape\n"
1246 " drive:\n"
1247 " 1. Turn the autoloader off then on.\n"
1248 " 2. Restart the operation.\n"
1249 " 3. If problem persists, call the tape drive supplier helpline.",
1250 /* 0x29 */
1251 "C: A tape has been left in the autoloader by a previous hardware fault:\n"
1252 " 1. Insert an empty magazine to clear the fault.\n"
1253 " 2. If the fault does not clear, turn the autoloader off and then\n"
1254 " on again.\n"
1255 " 3. If the problem persists, call the tape drive supplier helpline.",
1256 /* 0x2a */
1257 "W: There is a problem with the autoloader mechanism.",
1258 /* 0x2b */
1259 "C: The operation has failed because the autoloader door is open:\n"
1260 " 1. Clear any obstructions from the autoloader door.\n"
1261 " 2. Eject the magazine and then insert it again.\n"
1262 " 3. If the fault does not clear, turn the autoloader off and then\n"
1263 " on again.\n"
1264 " 4. If the problem persists, call the tape drive supplier helpline.",
1265 /* 0x2c */
1266 "C: The autoloader has a hardware fault:\n"
1267 " 1. Turn the autoloader off and then on again.\n"
1268 " 2. Restart the operation.\n"
1269 " 3. If the problem persists, call the tape drive supplier helpline.\n"
1270 " Check the autoloader users manual for device specific instructions\n"
1271 " on turning the device power on and off.",
1272 /* 0x2d */
1273 "C: The autoloader cannot operate without the magazine,\n"
1274 " 1. Insert the magazine into the autoloader.\n"
1275 " 2. Restart the operation.",
1276 /* 0x2e */
1277 "W: A hardware failure of the changer mechanism is predicted. Call the\n"
1278 " tape drive supplier helpline.",
1279 /* 0x2f */
1280 "I: Reserved.",
1281 /* 0x30 */
1282 "I: Reserved.",
1283 /* 0x31 */
1284 "I: Reserved.",
1285 /* 0x32 */
1286 "W: Media statistics have been lost at some time in the past",
1287 /* 0x33 */
1288 "W: The tape directory on the tape cartridge just unloaded has been\n"
1289 " corrupted. File search performance will be degraded. The tape\n"
1290 " directory can be rebuilt by reading all the data.",
1291 /* 0x34 */
1292 "C: The tape just unloaded could not write its system area successfully:\n"
1293 " 1. Copy data to another tape cartridge.\n"
1294 " 2. Discard the old cartridge.",
1295 /* 0x35 */
1296 "C: The tape system are could not be read successfully at load time:\n"
1297 " 1. Copy data to another tape cartridge.\n",
1298 /* 0x36 */
1299 "C: The start or data could not be found on the tape:\n"
1300 " 1. Check you are using the correct format tape.\n"
1301 " 2. Discard the tape or return the tape to your supplier",
1302 /* 0x37 */
1303 "C: The operation has failed because the media cannot be loaded\n"
1304 " and threaded.\n"
1305 " 1. Remove the cartridge, inspect it as specified in the product\n"
1306 " manual, and retry the operation.\n"
1307 " 2. If the problem persists, call the tape drive supplier help line.",
1308 /* 0x38 */
1309 "C: The operation has failed because the medium cannot be unloaded:\n"
1310 " 1. Do not attempt to extract the tape cartridge.\n"
1311 " 2. Call the tape driver supplier help line.",
1312 /* 0x39 */
1313 "C: The tape drive has a problem with the automation interface:\n"
1314 " 1. Check the power to the automation system.\n"
1315 " 2. Check the cables and cable connections.\n"
1316 " 3. Call the supplier help line if problem persists.",
1317 /* 0x3a */
1318 "W: The tape drive has reset itself due to a detected firmware\n"
1319 " fault. If problem persists, call the supplier help line.",
1320 };
1321
1322 const char * scsiTapeAlertsTapeDevice(unsigned short code)
1323 {
1324 const int num = sizeof(TapeAlertsMessageTable) /
1325 sizeof(TapeAlertsMessageTable[0]);
1326
1327 return (code < num) ? TapeAlertsMessageTable[code] : "Unknown Alert";
1328 }
1329
1330 // The first character (W, C, I) tells the severity
1331 static const char * ChangerTapeAlertsMessageTable[]= {
1332 " ",
1333 /* 0x01 */
1334 "C: The library mechanism is having difficulty communicating with the\n"
1335 " drive:\n"
1336 " 1. Turn the library off then on.\n"
1337 " 2. Restart the operation.\n"
1338 " 3. If the problem persists, call the library supplier help line.",
1339 /* 0x02 */
1340 "W: There is a problem with the library mechanism. If problem persists,\n"
1341 " call the library supplier help line.",
1342 /* 0x03 */
1343 "C: The library has a hardware fault:\n"
1344 " 1. Reset the library.\n"
1345 " 2. Restart the operation.\n"
1346 " Check the library users manual for device specific instructions on resetting\n"
1347 " the device.",
1348 /* 0x04 */
1349 "C: The library has a hardware fault:\n"
1350 " 1. Turn the library off then on again.\n"
1351 " 2. Restart the operation.\n"
1352 " 3. If the problem persists, call the library supplier help line.\n"
1353 " Check the library users manual for device specific instructions on turning the\n"
1354 " device power on and off.",
1355 /* 0x05 */
1356 "W: The library mechanism may have a hardware fault.\n"
1357 " Run extended diagnostics to verify and diagnose the problem. Check the library\n"
1358 " users manual for device specific instructions on running extended diagnostic\n"
1359 " tests.",
1360 /* 0x06 */
1361 "C: The library has a problem with the host interface:\n"
1362 " 1. Check the cables and connections.\n"
1363 " 2. Restart the operation.",
1364 /* 0x07 */
1365 "W: A hardware failure of the library is predicted. Call the library\n"
1366 " supplier help line.",
1367 /* 0x08 */
1368 "W: Preventive maintenance of the library is required.\n"
1369 " Check the library users manual for device specific preventative maintenance\n"
1370 " tasks, or call your library supplier help line.",
1371 /* 0x09 */
1372 "C: General environmental conditions inside the library are outside the\n"
1373 " specified humidity range.",
1374 /* 0x0a */
1375 "C: General environmental conditions inside the library are outside the\n"
1376 " specified temperature range.",
1377 /* 0x0b */
1378 "C: The voltage supply to the library is outside the specified range.\n"
1379 " There is a potential problem with the power supply or failure of\n"
1380 " a redundant power supply.",
1381 /* 0x0c */
1382 "C: A cartridge has been left inside the library by a previous hardware\n"
1383 " fault:\n"
1384 " 1. Insert an empty magazine to clear the fault.\n"
1385 " 2. If the fault does not clear, turn the library off and then on again.\n"
1386 " 3. If the problem persists, call the library supplier help line.",
1387 /* 0x0d */
1388 "W: There is a potential problem with the drive ejecting cartridges or\n"
1389 " with the library mechanism picking a cartridge from a slot.\n"
1390 " 1. No action needs to be taken at this time.\n"
1391 " 2. If the problem persists, call the library supplier help line.",
1392 /* 0x0e */
1393 "W: There is a potential problem with the library mechanism placing a\n"
1394 " cartridge into a slot.\n"
1395 " 1. No action needs to be taken at this time.\n"
1396 " 2. If the problem persists, call the library supplier help line.",
1397 /* 0x0f */
1398 "W: There is a potential problem with the drive or the library mechanism\n"
1399 " loading cartridges, or an incompatible cartridge.",
1400 /* 0x10 */
1401 "C: The library has failed because the door is open:\n"
1402 " 1. Clear any obstructions from the library door.\n"
1403 " 2. Close the library door.\n"
1404 " 3. If the problem persists, call the library supplier help line.",
1405 /* 0x11 */
1406 "C: There is a mechanical problem with the library media import/export\n"
1407 " mailslot.",
1408 /* 0x12 */
1409 "C: The library cannot operate without the magazine.\n"
1410 " 1. Insert the magazine into the library.\n"
1411 " 2. Restart the operation.",
1412 /* 0x13 */
1413 "W: Library security has been compromised.",
1414 /* 0x14 */
1415 "I: The library security mode has been changed.\n"
1416 " The library has either been put into secure mode, or the library has exited\n"
1417 " the secure mode.\n"
1418 " This is for information purposes only. No action is required.",
1419 /* 0x15 */
1420 "I: The library has been manually turned offline and is unavailable for use.",
1421 /* 0x16 */
1422 "I: A drive inside the library has been taken offline.\n"
1423 " This is for information purposes only. No action is required.",
1424 /* 0x17 */
1425 "W: There is a potential problem with the bar code label or the scanner\n"
1426 " hardware in the library mechanism.\n"
1427 " 1. No action needs to be taken at this time.\n"
1428 " 2. If the problem persists, call the library supplier help line.",
1429 /* 0x18 */
1430 "C: The library has detected an inconsistency in its inventory.\n"
1431 " 1. Redo the library inventory to correct inconsistency.\n"
1432 " 2. Restart the operation.\n"
1433 " Check the applications users manual or the hardware users manual for\n"
1434 " specific instructions on redoing the library inventory.",
1435 /* 0x19 */
1436 "W: A library operation has been attempted that is invalid at this time.",
1437 /* 0x1a */
1438 "W: A redundant interface port on the library has failed.",
1439 /* 0x1b */
1440 "W: A library cooling fan has failed.",
1441 /* 0x1c */
1442 "W: A redundant power supply has failed inside the library. Check the\n"
1443 " library users manual for instructions on replacing the failed power supply.",
1444 /* 0x1d */
1445 "W: The library power consumption is outside the specified range.",
1446 /* 0x1e */
1447 "C: A failure has occurred in the cartridge pass-through mechanism between\n"
1448 " two library modules.",
1449 /* 0x1f */
1450 "C: A cartridge has been left in the pass-through mechanism from a\n"
1451 " previous hardware fault. Check the library users guide for instructions on\n"
1452 " clearing this fault.",
1453 /* 0x20 */
1454 "I: The library was unable to read the bar code on a cartridge.",
1455 };
1456
1457 const char * scsiTapeAlertsChangerDevice(unsigned short code)
1458 {
1459 const int num = sizeof(ChangerTapeAlertsMessageTable) /
1460 sizeof(ChangerTapeAlertsMessageTable[0]);
1461
1462 return (code < num) ? ChangerTapeAlertsMessageTable[code] : "Unknown Alert";
1463 }
1464
1465
1466 /* this is a subset of the SCSI additional sense code strings indexed
1467 * by "ascq" for the case when asc==SCSI_ASC_IMPENDING_FAILURE (0x5d)
1468 */
1469 static const char * strs_for_asc_5d[] = {
1470 /* 0x00 */ "FAILURE PREDICTION THRESHOLD EXCEEDED",
1471 "MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED",
1472 "LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED",
1473 "SPARE AREA EXHAUSTION PREDICTION THRESHOLD EXCEEDED",
1474 "",
1475 "",
1476 "",
1477 "",
1478 "",
1479 "",
1480 "",
1481 "",
1482 "",
1483 "",
1484 "",
1485 "",
1486 /* 0x10 */ "HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1487 "HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1488 "HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1489 "HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1490 "HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1491 "HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1492 "HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1493 "HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
1494 "HARDWARE IMPENDING FAILURE CONTROLLER DETECTED",
1495 "HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1496 "HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
1497 "HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
1498 "HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1499 "",
1500 "",
1501 "",
1502 /* 0x20 */ "CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1503 "CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1504 "CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1505 "CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1506 "CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1507 "CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1508 "CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1509 "CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS",
1510 "CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED",
1511 "CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1512 "CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE",
1513 "CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT",
1514 "CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1515 "",
1516 "",
1517 "",
1518 /* 0x30 */ "DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1519 "DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1520 "DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1521 "DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1522 "DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1523 "DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1524 "DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1525 "DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS",
1526 "DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED",
1527 "DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1528 "DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE",
1529 "DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT",
1530 "DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1531 "",
1532 "",
1533 "",
1534 /* 0x40 */ "SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1535 "SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1536 "SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1537 "SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1538 "SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1539 "SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1540 "SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1541 "SERVO IMPENDING FAILURE CHANNEL PARAMETRICS",
1542 "SERVO IMPENDING FAILURE CONTROLLER DETECTED",
1543 "SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1544 "SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE",
1545 "SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT",
1546 "SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1547 "",
1548 "",
1549 "",
1550 /* 0x50 */ "SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1551 "SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1552 "SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1553 "SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1554 "SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1555 "SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1556 "SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1557 "SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS",
1558 "SPINDLE IMPENDING FAILURE CONTROLLER DETECTED",
1559 "SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1560 "SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE",
1561 "SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT",
1562 "SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT",
1563 "",
1564 "",
1565 "",
1566 /* 0x60 */ "FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE",
1567 "FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH",
1568 "FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH",
1569 "FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH",
1570 "FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS",
1571 "FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH",
1572 "FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH",
1573 "FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS",
1574 "FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED",
1575 "FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE",
1576 "FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE",
1577 "FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT",
1578 /* 0x6c */ "FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"};
1579
1580
1581 /* this is a subset of the SCSI additional sense code strings indexed
1582 * * by "ascq" for the case when asc==SCSI_ASC_WARNING (0xb)
1583 * */
1584 static const char * strs_for_asc_b[] = {
1585 /* 0x00 */ "WARNING",
1586 "WARNING - SPECIFIED TEMPERATURE EXCEEDED",
1587 "WARNING - ENCLOSURE DEGRADED"};
1588
1589 static char spare_buff[128];
1590
1591 const char * scsiGetIEString(UINT8 asc, UINT8 ascq)
1592 {
1593 const char * rp;
1594
1595 if (SCSI_ASC_IMPENDING_FAILURE == asc) {
1596 if (ascq == 0xff)
1597 return "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)";
1598 else if (ascq <
1599 (sizeof(strs_for_asc_5d) / sizeof(strs_for_asc_5d[0]))) {
1600 rp = strs_for_asc_5d[ascq];
1601 if (strlen(rp) > 0)
1602 return rp;
1603 }
1604 snprintf(spare_buff, sizeof(spare_buff),
1605 "FAILURE PREDICTION THRESHOLD EXCEEDED: ascq=0x%x", ascq);
1606 return spare_buff;
1607 } else if (SCSI_ASC_WARNING == asc) {
1608 if (ascq < (sizeof(strs_for_asc_b) / sizeof(strs_for_asc_b[0]))) {
1609 rp = strs_for_asc_b[ascq];
1610 if (strlen(rp) > 0)
1611 return rp;
1612 }
1613 snprintf(spare_buff, sizeof(spare_buff), "WARNING: ascq=0x%x", ascq);
1614 return spare_buff;
1615 }
1616 return NULL; /* not a IE additional sense code */
1617 }
1618
1619
1620 /* This is not documented in t10.org, page 0x80 is vendor specific */
1621 /* Some IBM disks do an offline read-scan when they get this command. */
1622 int scsiSmartIBMOfflineTest(int device)
1623 {
1624 UINT8 tBuf[256];
1625 int res;
1626
1627 memset(tBuf, 0, sizeof(tBuf));
1628 /* Build SMART Off-line Immediate Diag Header */
1629 tBuf[0] = 0x80; /* Page Code */
1630 tBuf[1] = 0x00; /* Reserved */
1631 tBuf[2] = 0x00; /* Page Length MSB */
1632 tBuf[3] = 0x04; /* Page Length LSB */
1633 tBuf[4] = 0x03; /* SMART Revision */
1634 tBuf[5] = 0x00; /* Reserved */
1635 tBuf[6] = 0x00; /* Off-line Immediate Time MSB */
1636 tBuf[7] = 0x00; /* Off-line Immediate Time LSB */
1637 res = scsiSendDiagnostic(device, SCSI_DIAG_NO_SELF_TEST, tBuf, 8);
1638 if (res)
1639 pout("IBM offline test failed [%s]\n", scsiErrString(res));
1640 return res;
1641 }
1642
1643 int scsiSmartDefaultSelfTest(int device)
1644 {
1645 int res;
1646
1647 res = scsiSendDiagnostic(device, SCSI_DIAG_DEF_SELF_TEST, NULL, 0);
1648 if (res)
1649 pout("Default self test failed [%s]\n", scsiErrString(res));
1650 return res;
1651 }
1652
1653 int scsiSmartShortSelfTest(int device)
1654 {
1655 int res;
1656
1657 res = scsiSendDiagnostic(device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL, 0);
1658 if (res)
1659 pout("Short offline self test failed [%s]\n", scsiErrString(res));
1660 return res;
1661 }
1662
1663 int scsiSmartExtendSelfTest(int device)
1664 {
1665 int res;
1666
1667 res = scsiSendDiagnostic(device, SCSI_DIAG_BG_EXTENDED_SELF_TEST, NULL, 0);
1668 if (res)
1669 pout("Long (extended) offline self test failed [%s]\n",
1670 scsiErrString(res));
1671 return res;
1672 }
1673
1674 int scsiSmartShortCapSelfTest(int device)
1675 {
1676 int res;
1677
1678 res = scsiSendDiagnostic(device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL, 0);
1679 if (res)
1680 pout("Short foreground self test failed [%s]\n", scsiErrString(res));
1681 return res;
1682 }
1683
1684 int scsiSmartExtendCapSelfTest(int device)
1685 {
1686 int res;
1687
1688 res = scsiSendDiagnostic(device, SCSI_DIAG_FG_EXTENDED_SELF_TEST, NULL, 0);
1689 if (res)
1690 pout("Long (extended) foreground self test failed [%s]\n",
1691 scsiErrString(res));
1692 return res;
1693 }
1694
1695 int scsiSmartSelfTestAbort(int device)
1696 {
1697 int res;
1698
1699 res = scsiSendDiagnostic(device, SCSI_DIAG_ABORT_SELF_TEST, NULL, 0);
1700 if (res)
1701 pout("Abort self test failed [%s]\n", scsiErrString(res));
1702 return res;
1703 }
1704
1705 /* Returns 0 and the expected duration of an extended self test (in seconds)
1706 if successful; any other return value indicates a failure. */
1707 int scsiFetchExtendedSelfTestTime(int device, int * durationSec, int modese_len)
1708 {
1709 int err, offset, res;
1710 UINT8 buff[64];
1711
1712 memset(buff, 0, sizeof(buff));
1713 if (modese_len <= 6) {
1714 if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0,
1715 MPAGE_CONTROL_CURRENT,
1716 buff, sizeof(buff)))) {
1717 if (SIMPLE_ERR_BAD_OPCODE == err)
1718 modese_len = 10;
1719 else
1720 return err;
1721 } else if (0 == modese_len)
1722 modese_len = 6;
1723 }
1724 if (10 == modese_len) {
1725 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
1726 MPAGE_CONTROL_CURRENT,
1727 buff, sizeof(buff));
1728 if (err)
1729 return err;
1730 }
1731 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
1732 if (offset < 0)
1733 return -EINVAL;
1734 if (buff[offset + 1] >= 0xa) {
1735 res = (buff[offset + 10] << 8) | buff[offset + 11];
1736 *durationSec = res;
1737 return 0;
1738 }
1739 else
1740 return -EINVAL;
1741 }
1742
1743 void scsiDecodeErrCounterPage(unsigned char * resp,
1744 struct scsiErrorCounter *ecp)
1745 {
1746 int k, j, num, pl, pc;
1747 unsigned char * ucp;
1748 unsigned char * xp;
1749 uint64_t * ullp;
1750
1751 memset(ecp, 0, sizeof(*ecp));
1752 num = (resp[2] << 8) | resp[3];
1753 ucp = &resp[0] + 4;
1754 while (num > 3) {
1755 pc = (ucp[0] << 8) | ucp[1];
1756 pl = ucp[3] + 4;
1757 switch (pc) {
1758 case 0:
1759 case 1:
1760 case 2:
1761 case 3:
1762 case 4:
1763 case 5:
1764 case 6:
1765 ecp->gotPC[pc] = 1;
1766 ullp = &ecp->counter[pc];
1767 break;
1768 default:
1769 ecp->gotExtraPC = 1;
1770 ullp = &ecp->counter[7];
1771 break;
1772 }
1773 k = pl - 4;
1774 xp = ucp + 4;
1775 if (k > (int)sizeof(*ullp)) {
1776 xp += (k - sizeof(*ullp));
1777 k = sizeof(*ullp);
1778 }
1779 *ullp = 0;
1780 for (j = 0; j < k; ++j) {
1781 if (j > 0)
1782 *ullp <<= 8;
1783 *ullp |= xp[j];
1784 }
1785 num -= pl;
1786 ucp += pl;
1787 }
1788 }
1789
1790 void scsiDecodeNonMediumErrPage(unsigned char *resp,
1791 struct scsiNonMediumError *nmep)
1792 {
1793 int k, j, num, pl, pc, szof;
1794 unsigned char * ucp;
1795 unsigned char * xp;
1796
1797 memset(nmep, 0, sizeof(*nmep));
1798 num = (resp[2] << 8) | resp[3];
1799 ucp = &resp[0] + 4;
1800 szof = sizeof(nmep->counterPC0);
1801 while (num > 3) {
1802 pc = (ucp[0] << 8) | ucp[1];
1803 pl = ucp[3] + 4;
1804 switch (pc) {
1805 case 0:
1806 nmep->gotPC0 = 1;
1807 k = pl - 4;
1808 xp = ucp + 4;
1809 if (k > szof) {
1810 xp += (k - szof);
1811 k = szof;
1812 }
1813 nmep->counterPC0 = 0;
1814 for (j = 0; j < k; ++j) {
1815 if (j > 0)
1816 nmep->counterPC0 <<= 8;
1817 nmep->counterPC0 |= xp[j];
1818 }
1819 break;
1820 case 0x8009:
1821 nmep->gotTFE_H = 1;
1822 k = pl - 4;
1823 xp = ucp + 4;
1824 if (k > szof) {
1825 xp += (k - szof);
1826 k = szof;
1827 }
1828 nmep->counterTFE_H = 0;
1829 for (j = 0; j < k; ++j) {
1830 if (j > 0)
1831 nmep->counterTFE_H <<= 8;
1832 nmep->counterTFE_H |= xp[j];
1833 }
1834 break;
1835 case 0x8015:
1836 nmep->gotPE_H = 1;
1837 k = pl - 4;
1838 xp = ucp + 4;
1839 if (k > szof) {
1840 xp += (k - szof);
1841 k = szof;
1842 }
1843 nmep->counterPE_H = 0;
1844 for (j = 0; j < k; ++j) {
1845 if (j > 0)
1846 nmep->counterPE_H <<= 8;
1847 nmep->counterPE_H |= xp[j];
1848 }
1849 break;
1850 default:
1851 nmep->gotExtraPC = 1;
1852 break;
1853 }
1854 num -= pl;
1855 ucp += pl;
1856 }
1857 }
1858
1859 /* Counts number of failed self-tests. Also encodes the poweron_hour
1860 of the most recent failed self-test. Return value is negative if
1861 this function has a problem (typically -1), otherwise the bottom 8
1862 bits are the number of failed self tests and the 16 bits above that
1863 are the poweron hour of the most recent failure. Note: aborted self
1864 tests (typically by the user) and self tests in progress are not
1865 considered failures. See Working Draft SCSI Primary Commands - 3
1866 (SPC-3) section 7.2.10 T10/1416-D (rev 22a) */
1867 int scsiCountFailedSelfTests(int fd, int noisy)
1868 {
1869 int num, k, n, err, res, fails, fail_hour;
1870 UINT8 * ucp;
1871 unsigned char resp[LOG_RESP_SELF_TEST_LEN];
1872
1873 if ((err = scsiLogSense(fd, SELFTEST_RESULTS_LPAGE, 0, resp,
1874 LOG_RESP_SELF_TEST_LEN, 0))) {
1875 if (noisy)
1876 pout("scsiCountSelfTests Failed [%s]\n", scsiErrString(err));
1877 return -1;
1878 }
1879 if ((resp[0] & 0x3f) != SELFTEST_RESULTS_LPAGE) {
1880 if (noisy)
1881 pout("Self-test Log Sense Failed, page mismatch\n");
1882 return -1;
1883 }
1884 // compute page length
1885 num = (resp[2] << 8) + resp[3];
1886 // Log sense page length 0x190 bytes
1887 if (num != 0x190) {
1888 if (noisy)
1889 pout("Self-test Log Sense length is 0x%x not 0x190 bytes\n", num);
1890 return -1;
1891 }
1892 fails = 0;
1893 fail_hour = 0;
1894 // loop through the twenty possible entries
1895 for (k = 0, ucp = resp + 4; k < 20; ++k, ucp += 20 ) {
1896
1897 // timestamp in power-on hours (or zero if test in progress)
1898 n = (ucp[6] << 8) | ucp[7];
1899
1900 // The spec says "all 20 bytes will be zero if no test" but
1901 // DG has found otherwise. So this is a heuristic.
1902 if ((0 == n) && (0 == ucp[4]))
1903 break;
1904 res = ucp[4] & 0xf;
1905 if ((res > 2) && (res < 8)) {
1906 fails++;
1907 if (1 == fails)
1908 fail_hour = (ucp[6] << 8) + ucp[7];
1909 }
1910 }
1911 return (fail_hour << 8) + fails;
1912 }
1913
1914 /* Returns 0 if able to read self test log page; then outputs 1 into
1915 *inProgress if self test still in progress, else outputs 0. */
1916 int scsiSelfTestInProgress(int fd, int * inProgress)
1917 {
1918 int num;
1919 UINT8 * ucp;
1920 unsigned char resp[LOG_RESP_SELF_TEST_LEN];
1921
1922 if (scsiLogSense(fd, SELFTEST_RESULTS_LPAGE, 0, resp,
1923 LOG_RESP_SELF_TEST_LEN, 0))
1924 return -1;
1925 if (resp[0] != SELFTEST_RESULTS_LPAGE)
1926 return -1;
1927 // compute page length
1928 num = (resp[2] << 8) + resp[3];
1929 // Log sense page length 0x190 bytes
1930 if (num != 0x190) {
1931 return -1;
1932 }
1933 ucp = resp + 4;
1934 if (inProgress)
1935 *inProgress = (0xf == (ucp[4] & 0xf)) ? 1 : 0;
1936 return 0;
1937 }
1938
1939 /* Returns a negative value if failed to fetch Contol mode page or it was
1940 malformed. Returns 0 if GLTSD bit is zero and returns 1 if the GLTSD
1941 bit is set. Examines default mode page when current==0 else examines
1942 current mode page. */
1943 int scsiFetchControlGLTSD(int device, int modese_len, int current)
1944 {
1945 int err, offset;
1946 UINT8 buff[64];
1947 int pc = current ? MPAGE_CONTROL_CURRENT : MPAGE_CONTROL_DEFAULT;
1948
1949 memset(buff, 0, sizeof(buff));
1950 if (modese_len <= 6) {
1951 if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0, pc,
1952 buff, sizeof(buff)))) {
1953 if (SIMPLE_ERR_BAD_OPCODE == err)
1954 modese_len = 10;
1955 else
1956 return -EINVAL;
1957 } else if (0 == modese_len)
1958 modese_len = 6;
1959 }
1960 if (10 == modese_len) {
1961 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0, pc,
1962 buff, sizeof(buff));
1963 if (err)
1964 return -EINVAL;
1965 }
1966 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
1967 if ((offset >= 0) && (buff[offset + 1] >= 0xa))
1968 return (buff[offset + 2] & 2) ? 1 : 0;
1969 return -EINVAL;
1970 }
1971
1972 /* Attempts to set or clear GLTSD bit in Control mode page. If enabled is
1973 0 attempts to clear GLTSD otherwise it attempts to set it. Returns 0 if
1974 successful, negative if low level error, > 0 if higher level error (e.g.
1975 SIMPLE_ERR_BAD_PARAM if GLTSD bit is not changeable). */
1976 int scsiSetControlGLTSD(int device, int enabled, int modese_len)
1977 {
1978 int err, offset, resp_len, sp;
1979 UINT8 buff[64];
1980 UINT8 ch_buff[64];
1981
1982 memset(buff, 0, sizeof(buff));
1983 if (modese_len <= 6) {
1984 if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0,
1985 MPAGE_CONTROL_CURRENT,
1986 buff, sizeof(buff)))) {
1987 if (SIMPLE_ERR_BAD_OPCODE == err)
1988 modese_len = 10;
1989 else
1990 return err;
1991 } else if (0 == modese_len)
1992 modese_len = 6;
1993 }
1994 if (10 == modese_len) {
1995 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
1996 MPAGE_CONTROL_CURRENT,
1997 buff, sizeof(buff));
1998 if (err)
1999 return err;
2000 }
2001 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
2002 if ((offset < 0) || (buff[offset + 1] < 0xa))
2003 return SIMPLE_ERR_BAD_RESP;
2004
2005 if (enabled)
2006 enabled = 2;
2007 if (enabled == (buff[offset + 2] & 2))
2008 return 0; /* GLTSD already in wanted state so nothing to do */
2009
2010 if (modese_len == 6)
2011 err = scsiModeSense(device, CONTROL_MODE_PAGE, 0,
2012 MPAGE_CONTROL_CHANGEABLE,
2013 ch_buff, sizeof(ch_buff));
2014 else
2015 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
2016 MPAGE_CONTROL_CHANGEABLE,
2017 ch_buff, sizeof(ch_buff));
2018 if (err)
2019 return err;
2020 if (0 == (ch_buff[offset + 2] & 2))
2021 return SIMPLE_ERR_BAD_PARAM; /* GLTSD bit not chageable */
2022
2023 if (10 == modese_len) {
2024 resp_len = (buff[0] << 8) + buff[1] + 2;
2025 buff[3] &= 0xef; /* for disks mask out DPOFUA bit */
2026 } else {
2027 resp_len = buff[0] + 1;
2028 buff[2] &= 0xef; /* for disks mask out DPOFUA bit */
2029 }
2030 sp = (buff[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
2031 if (enabled)
2032 buff[offset + 2] |= 0x2; /* set GLTSD bit */
2033 else
2034 buff[offset + 2] &= 0xfd; /* clear GLTSD bit */
2035 if (10 == modese_len)
2036 err = scsiModeSelect10(device, sp, buff, resp_len);
2037 else if (6 == modese_len)
2038 err = scsiModeSelect(device, sp, buff, resp_len);
2039 return err;
2040 }
2041
2042 /* Returns a negative value if failed to fetch Protocol specific port mode
2043 page or it was malformed. Returns transport protocol identifier when
2044 value >= 0 . */
2045 int scsiFetchTransportProtocol(int device, int modese_len)
2046 {
2047 int err, offset;
2048 UINT8 buff[64];
2049
2050 memset(buff, 0, sizeof(buff));
2051 if (modese_len <= 6) {
2052 if ((err = scsiModeSense(device, PROTOCOL_SPECIFIC_PORT_PAGE, 0,
2053 MPAGE_CONTROL_CURRENT,
2054 buff, sizeof(buff)))) {
2055 if (SIMPLE_ERR_BAD_OPCODE == err)
2056 modese_len = 10;
2057 else
2058 return -EINVAL;
2059 } else if (0 == modese_len)
2060 modese_len = 6;
2061 }
2062 if (10 == modese_len) {
2063 err = scsiModeSense10(device, PROTOCOL_SPECIFIC_PORT_PAGE, 0,
2064 MPAGE_CONTROL_CURRENT,
2065 buff, sizeof(buff));
2066 if (err)
2067 return -EINVAL;
2068 }
2069 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
2070 if ((offset >= 0) && (buff[offset + 1] > 1)) {
2071 if ((0 == (buff[offset] & 0x40)) && /* SPF==0 */
2072 (PROTOCOL_SPECIFIC_PORT_PAGE == (buff[offset] & 0x3f)))
2073 return (buff[offset + 2] & 0xf);
2074 }
2075 return -EINVAL;
2076 }
2077
2078
2079 /* This is Linux specific code to look for the libata ATA-SCSI
2080 simulator in the vendor device identification page.
2081 Returns 1 if found else 0. */
2082 int isLinuxLibAta(unsigned char * vpd_di_buff, int len)
2083 {
2084 int k, id_len, c_set, assoc, id_type, i_len;
2085 unsigned char * ucp;
2086 unsigned char * ip;
2087 unsigned char buff1[20];
2088 unsigned char buff2[20];
2089
2090 if (len < 4) {
2091 /* Device identification VPD page length too short */
2092 return 0;
2093 }
2094 buff1[0] = '\0';
2095 buff2[0] = '\0';
2096 len -= 4;
2097 ucp = vpd_di_buff + 4;
2098 for (k = 0; k < len; k += id_len, ucp += id_len) {
2099 i_len = ucp[3];
2100 id_len = i_len + 4;
2101 if ((k + id_len) > len) {
2102 /* short descriptor, badly formed */
2103 return 0;
2104 }
2105 ip = ucp + 4;
2106 c_set = (ucp[0] & 0xf);
2107 assoc = ((ucp[1] >> 4) & 0x3);
2108 id_type = (ucp[1] & 0xf);
2109 if ((0 == id_type) && (2 == c_set) && (0 == assoc)) {
2110 /* assoc=lu, c_set=ascii, id_type=vendor */
2111 if (0 == strncmp((const char *)ip,
2112 "Linux ATA-SCSI simulator", i_len)) {
2113 /* until lk 2.6.16 */
2114 return 1;
2115 }
2116 memcpy(buff1, ip, sizeof(buff1));
2117 }
2118 if ((1 == id_type) && (2 == c_set) && (0 == assoc)) {
2119 /* assoc=lu, c_set=ascii, id_type=t10 vendor id */
2120 if (0 == strncmp((const char *)ip, "ATA", 3))
2121 memcpy(buff2, ip + 48, sizeof(buff2));
2122 }
2123 }
2124 if (buff1[0] && buff2[0]) {
2125 if (0 == memcmp(buff1, buff2, sizeof(buff1))) {
2126 /* after lk 2.6.16, look for serial number match */
2127 return 1;
2128 }
2129 }
2130 return 0;
2131 }