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