smartmontools SVN Rev 5409
Utility to control and monitor storage systems with "S.M.A.R.T."
scsicmds.cpp
Go to the documentation of this file.
1/*
2 * scsicmds.cpp
3 *
4 * Home page of code is: https://www.smartmontools.org
5 *
6 * Copyright (C) 2002-8 Bruce Allen
7 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
8 * Copyright (C) 2003-18 Douglas Gilbert <dgilbert@interlog.com>
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
12 *
13 * In the SCSI world "SMART" is a dead or withdrawn standard. In recent
14 * SCSI standards (since SCSI-3) it goes under the awkward name of
15 * "Informational Exceptions" ["IE" or "IEC" (with the "C" for "control")].
16 * The relevant information is spread around several SCSI draft
17 * standards available at http://www.t10.org . Reference is made in the
18 * code to the following acronyms:
19 * - SAM [SCSI Architectural model, versions 2 or 3]
20 * - SPC [SCSI Primary commands, versions 2 or 3]
21 * - SBC [SCSI Block commands, versions 2]
22 *
23 * Some SCSI disk vendors have snippets of "SMART" information in their
24 * product manuals.
25 */
26
27#include <stdio.h>
28#include <string.h>
29#include <errno.h>
30#include <ctype.h>
31
32#include "config.h"
33
34#include "scsicmds.h"
35#include "dev_interface.h"
36#include "utility.h"
37#include "sg_unaligned.h"
38
39const char *scsicmds_c_cvsid="$Id: scsicmds.cpp 5397 2022-07-17 02:22:29Z dpgilbert $"
41
42static const char * logSenStr = "Log Sense";
43
44// Print SCSI debug messages?
45unsigned char scsi_debugmode = 0;
46
48
49
51{
52 unsigned char b[0xfc] = {}; /* pre SPC-3 INQUIRY max response size */
53
54 if (device && (0 == scsiInquiryVpd(device, SCSI_VPD_SUPPORTED_VPD_PAGES,
55 b, sizeof(b)))) {
57 int n = sizeof(pages);
58 if (num_valid > n)
59 num_valid = n;
60 memcpy(pages, b + 4, num_valid);
61 }
62}
63
64bool
65supported_vpd_pages::is_supported(int vpd_page_num) const
66{
67 /* Supported VPD pages numbers start at offset 4 and should be in
68 * ascending order but don't assume that. */
69 for (int k = 0; k < num_valid; ++k) {
70 if (vpd_page_num == pages[k])
71 return true;
72 }
73 return false;
74}
75
76/* output binary in ASCII hex and optionally ASCII. Uses pout() for output. */
77void
78dStrHex(const uint8_t * up, int len, int no_ascii)
79{
80 const uint8_t * p = up;
81 char buff[82];
82 int a = 0;
83 const int bpstart = 5;
84 const int cpstart = 60;
85 int cpos = cpstart;
86 int bpos = bpstart;
87 int i, k;
88
89 if (len <= 0) return;
90 memset(buff,' ',80);
91 buff[80]='\0';
92 k = snprintf(buff+1, sizeof(buff)-1, "%.2x", a);
93 buff[k + 1] = ' ';
94 if (bpos >= ((bpstart + (9 * 3))))
95 bpos++;
96
97 for(i = 0; i < len; i++)
98 {
99 uint8_t c = *p++;
100 bpos += 3;
101 if (bpos == (bpstart + (9 * 3)))
102 bpos++;
103 snprintf(buff+bpos, sizeof(buff)-bpos, "%.2x", (unsigned int)c);
104 buff[bpos + 2] = ' ';
105 if (no_ascii)
106 buff[cpos++] = ' ';
107 else {
108 if ((c < ' ') || (c >= 0x7f))
109 c='.';
110 buff[cpos++] = c;
111 }
112 if (cpos > (cpstart+15))
113 {
114 while (cpos > 0 && buff[cpos-1] == ' ')
115 cpos--;
116 buff[cpos] = 0;
117 pout("%s\n", buff);
118 bpos = bpstart;
119 cpos = cpstart;
120 a += 16;
121 memset(buff,' ',80);
122 k = snprintf(buff+1, sizeof(buff)-1, "%.2x", a);
123 buff[k + 1] = ' ';
124 }
125 }
126 if (cpos > cpstart)
127 {
128 while (cpos > 0 && buff[cpos-1] == ' ')
129 cpos--;
130 buff[cpos] = 0;
131 pout("%s\n", buff);
132 }
133}
134
135/* This is a heuristic that takes into account the command bytes and length
136 * to decide whether the presented unstructured sequence of bytes could be
137 * a SCSI command. If so it returns true otherwise false. Vendor specific
138 * SCSI commands (i.e. opcodes from 0xc0 to 0xff), if presented, are assumed
139 * to follow SCSI conventions (i.e. length of 6, 10, 12 or 16 bytes). The
140 * only SCSI commands considered above 16 bytes of length are the Variable
141 * Length Commands (opcode 0x7f) and the XCDB wrapped commands (opcode 0x7e).
142 * Both have an inbuilt length field which can be cross checked with clen.
143 * No NVMe commands (64 bytes long plus some extra added by some OSes) have
144 * opcodes 0x7e or 0x7f yet. ATA is register based but SATA has FIS
145 * structures that are sent across the wire. The FIS register structure is
146 * used to move a command from a SATA host to device, but the ATA 'command'
147 * is not the first byte. So it is harder to say what will happen if a
148 * FIS structure is presented as a SCSI command, hopefully there is a low
149 * probability this function will yield true in that case. */
150bool
151is_scsi_cdb(const uint8_t * cdbp, int clen)
152{
153 if (clen < 6)
154 return false;
155 uint8_t opcode = cdbp[0];
156 uint8_t top3bits = opcode >> 5;
157 if (0x3 == top3bits) { /* Opcodes 0x60 to 0x7f */
158 int ilen, sa;
159 if ((clen < 12) || (clen % 4))
160 return false; /* must be modulo 4 and 12 or more bytes */
161 switch (opcode) {
162 case 0x7e: /* Extended cdb (XCDB) */
163 ilen = 4 + sg_get_unaligned_be16(cdbp + 2);
164 return (ilen == clen);
165 case 0x7f: /* Variable Length cdb */
166 ilen = 8 + cdbp[7];
167 sa = sg_get_unaligned_be16(cdbp + 8);
168 /* service action (sa) 0x0 is reserved */
169 return ((ilen == clen) && sa);
170 default:
171 return false;
172 }
173 } else if (clen <= 16) {
174 switch (clen) {
175 case 6:
176 if (top3bits > 0x5) /* vendor */
177 return true;
178 return (0x0 == top3bits); /* 6 byte cdb */
179 case 10:
180 if (top3bits > 0x5) /* vendor */
181 return true;
182 return ((0x1 == top3bits) || (0x2 == top3bits)); /* 10 byte cdb */
183 case 16:
184 if (top3bits > 0x5) /* vendor */
185 return true;
186 return (0x4 == top3bits); /* 16 byte cdb */
187 case 12:
188 if (top3bits > 0x5) /* vendor */
189 return true;
190 return (0x5 == top3bits); /* 12 byte cdb */
191 default:
192 return false;
193 }
194 }
195 /* NVMe probably falls out here, clen > 16 and (opcode < 0x60 or
196 * opcode > 0x7f). */
197 return false;
198}
199
202 scsi_sa_b1b4n5, /* for cdb byte 1, bit 4, number 5 bits */
204};
205
207 uint8_t cdb0;
209};
210
211static struct scsi_sa_var_map sa_var_a[] = {
212 {0x3b, scsi_sa_b1b4n5}, /* Write buffer modes_s */
213 {0x3c, scsi_sa_b1b4n5}, /* Read buffer(10) modes_s */
214 {0x48, scsi_sa_b1b4n5}, /* Sanitize sa_s */
215 {0x5e, scsi_sa_b1b4n5}, /* Persistent reserve in sa_s */
216 {0x5f, scsi_sa_b1b4n5}, /* Persistent reserve out sa_s */
217 {0x7f, scsi_sa_b8b7n16}, /* Variable length commands */
218 {0x83, scsi_sa_b1b4n5}, /* Extended copy out/cmd sa_s */
219 {0x84, scsi_sa_b1b4n5}, /* Extended copy in sa_s */
220 {0x8c, scsi_sa_b1b4n5}, /* Read attribute sa_s */
221 {0x9b, scsi_sa_b1b4n5}, /* Read buffer(16) modes_s */
222 {0x9e, scsi_sa_b1b4n5}, /* Service action in (16) */
223 {0x9f, scsi_sa_b1b4n5}, /* Service action out (16) */
224 {0xa3, scsi_sa_b1b4n5}, /* Maintenance in */
225 {0xa4, scsi_sa_b1b4n5}, /* Maintenance out */
226 {0xa9, scsi_sa_b1b4n5}, /* Service action out (12) */
227 {0xab, scsi_sa_b1b4n5}, /* Service action in (12) */
228};
229
231 uint8_t opcode;
233 uint16_t sa;
234 const char * name;
235};
236
237/* Array assumed to be sorted by opcode then service action (sa) */
239 /* in ascending opcode order */
240 {TEST_UNIT_READY, false, 0, "test unit ready"}, /* 0x00 */
241 {REQUEST_SENSE, false, 0, "request sense"}, /* 0x03 */
242 {INQUIRY, false, 0, "inquiry"}, /* 0x12 */
243 {MODE_SELECT_6, false, 0, "mode select(6)"}, /* 0x15 */
244 {MODE_SENSE_6, false, 0, "mode sense(6)"}, /* 0x1a */
245 {START_STOP_UNIT, false, 0, "start stop unit"}, /* 0x1b */
246 {RECEIVE_DIAGNOSTIC, false, 0, "receive diagnostic"}, /* 0x1c */
247 {SEND_DIAGNOSTIC, false, 0, "send diagnostic"}, /* 0x1d */
248 {READ_CAPACITY_10, false, 0, "read capacity(10)"}, /* 0x25 */
249 {READ_DEFECT_10, false, 0, "read defect list(10)"}, /* 0x37 */
250 {LOG_SELECT, false, 0, "log select"}, /* 0x4c */
251 {LOG_SENSE, false, 0, "log sense"}, /* 0x4d */
252 {MODE_SELECT_10, false, 0, "mode select(10)"}, /* 0x55 */
253 {MODE_SENSE_10, false, 0, "mode sense(10)"}, /* 0x5a */
254 {SAT_ATA_PASSTHROUGH_16, false, 0, "ata pass-through(16)"}, /* 0x85 */
255 {SERVICE_ACTION_IN_16, true, SAI_READ_CAPACITY_16, "read capacity(16)"},
256 /* 0x9e,0x10 */
258 "get physical element status"}, /* 0x9e,0x17 */
259 {REPORT_LUNS, false, 0, "report luns"}, /* 0xa0 */
260 {SAT_ATA_PASSTHROUGH_12, false, 0, "ata pass-through(12)"}, /* 0xa1 */
262 "report supported operation codes"}, /* 0xa3,0xc */
263 {READ_DEFECT_12, false, 0, "read defect list(12)"}, /* 0xb7 */
264};
265
266static const char * vendor_specific = "<vendor specific>";
267
268/* Need to expand to take service action into account. For commands
269 * of interest the service action is in the 2nd command byte */
270const char *
271scsi_get_opcode_name(const uint8_t * cdbp)
272{
273 uint8_t opcode = cdbp[0];
274 uint8_t cdb0;
275 enum scsi_sa_t sa_var = scsi_sa_none;
276 bool sa_valid = false;
277 uint16_t sa = 0;
278 int k;
279 static const int sa_var_len = sizeof(sa_var_a) /
280 sizeof(sa_var_a[0]);
281 static const int len = sizeof(opcode_name_arr) /
282 sizeof(opcode_name_arr[0]);
283
284 if (opcode >= 0xc0)
285 return vendor_specific;
286 for (k = 0; k < sa_var_len; ++k) {
287 cdb0 = sa_var_a[k].cdb0;
288 if (opcode == cdb0) {
289 sa_var = sa_var_a[k].sa_var;
290 break;
291 }
292 if (opcode < cdb0)
293 break;
294 }
295 switch (sa_var) {
296 case scsi_sa_none:
297 break;
298 case scsi_sa_b1b4n5:
299 sa_valid = true;
300 sa = cdbp[1] & 0x1f;
301 break;
302 case scsi_sa_b8b7n16:
303 sa_valid = true;
304 sa = sg_get_unaligned_be16(cdbp + 8);
305 break;
306 }
307 for (k = 0; k < len; ++k) {
308 struct scsi_opcode_name * onp = &opcode_name_arr[k];
309
310 if (opcode == onp->opcode) {
311 if ((! sa_valid) && (! onp->sa_valid))
312 return onp->name;
313 if (sa_valid && onp->sa_valid) {
314 if (sa == onp->sa)
315 return onp->name;
316 }
317 /* should not see sa_valid and ! onp->sa_valid (or vice versa) */
318 } else if (opcode < onp->opcode)
319 return NULL;
320 }
321 return NULL;
322}
323
324void
325scsi_do_sense_disect(const struct scsi_cmnd_io * io_buf,
326 struct scsi_sense_disect * out)
327{
328 memset(out, 0, sizeof(struct scsi_sense_disect));
330 int resp_code = (io_buf->sensep[0] & 0x7f);
331 out->resp_code = resp_code;
332 if (resp_code >= 0x72) {
333 out->sense_key = (io_buf->sensep[1] & 0xf);
334 out->asc = io_buf->sensep[2];
335 out->ascq = io_buf->sensep[3];
336 } else if (resp_code >= 0x70) {
337 out->sense_key = (io_buf->sensep[2] & 0xf);
338 if (io_buf->resp_sense_len > 13) {
339 out->asc = io_buf->sensep[12];
340 out->ascq = io_buf->sensep[13];
341 }
342 }
343 }
344}
345
346int
348{
349 switch (sinfo->sense_key) {
350 case SCSI_SK_NO_SENSE:
353 return SIMPLE_NO_ERROR;
355 if (SCSI_ASC_NO_MEDIUM == sinfo->asc)
357 else if (SCSI_ASC_NOT_READY == sinfo->asc) {
358 if (0x1 == sinfo->ascq)
360 else
362 } else
368 if (SCSI_ASC_UNKNOWN_OPCODE == sinfo->asc)
370 else if (SCSI_ASC_INVALID_FIELD == sinfo->asc)
372 else if (SCSI_ASC_UNKNOWN_PARAM == sinfo->asc)
374 else
375 return SIMPLE_ERR_BAD_PARAM; /* all other illegal request */
384 default:
385 return SIMPLE_ERR_UNKNOWN;
386 }
387}
388
389const char *
390scsiErrString(int scsiErr)
391{
392 if (scsiErr < 0)
393 return strerror(-scsiErr);
394 switch (scsiErr) {
395 case SIMPLE_NO_ERROR:
396 return "no error";
398 return "device not ready";
400 return "unsupported scsi opcode";
402 return "unsupported field in scsi command";
404 return "badly formed scsi parameters";
406 return "scsi response fails sanity test";
408 return "no medium present";
410 return "device will be ready soon";
412 return "unit attention reported, try again";
414 return "medium or hardware error (serious)";
416 return "unknown error (unexpected sense key)";
418 return "aborted command";
420 return "data protection error";
422 return "miscompare";
423 default:
424 return "unknown error";
425 }
426}
427
428static const char * sense_key_desc[] = {
429 "No Sense", /* Filemark, ILI and/or EOM; progress
430 indication (during FORMAT); power
431 condition sensing (REQUEST SENSE) */
432 "Recovered Error", /* The last command completed successfully
433 but used error correction */
434 "Not Ready", /* The addressed target is not ready */
435 "Medium Error", /* Data error detected on the medium */
436 "Hardware Error", /* Controller or device failure */
437 "Illegal Request",
438 "Unit Attention", /* Removable medium was changed, or
439 the target has been reset */
440 "Data Protect", /* Access to the data is blocked */
441 "Blank Check", /* Reached unexpected written or unwritten
442 region of the medium */
443 "Vendor specific(9)", /* Vendor specific */
444 "Copy Aborted", /* COPY or COMPARE was aborted */
445 "Aborted Command", /* The target aborted the command */
446 "Equal", /* SEARCH DATA found data equal (obsolete) */
447 "Volume Overflow", /* Medium full with data to be written */
448 "Miscompare", /* Source data and data on the medium
449 do not agree */
450 "Completed" /* may occur for successful cmd (spc4r23) */
451};
452
453/* Yield string associated with sense_key value. Returns 'buff'. */
454char *
455scsi_get_sense_key_str(int sense_key, int buff_len, char * buff)
456{
457 if (1 == buff_len) {
458 buff[0] = '\0';
459 return buff;
460 }
461 if ((sense_key >= 0) && (sense_key < 16))
462 snprintf(buff, buff_len, "%s", sense_key_desc[sense_key]);
463 else
464 snprintf(buff, buff_len, "invalid value: 0x%x", sense_key);
465 return buff;
466}
467
468/* Iterates to next designation descriptor in the device identification
469 * VPD page. The 'initial_desig_desc' should point to start of first
470 * descriptor with 'page_len' being the number of valid bytes in that
471 * and following descriptors. To start, 'off' should point to a negative
472 * value, thereafter it should point to the value yielded by the previous
473 * call. If 0 returned then 'initial_desig_desc + *off' should be a valid
474 * descriptor; returns -1 if normal end condition and -2 for an abnormal
475 * termination. Matches association, designator_type and/or code_set when
476 * any of those values are greater than or equal to zero. */
477int
478scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc, int page_len,
479 int * off, int m_assoc, int m_desig_type, int m_code_set)
480{
481 const unsigned char * ucp;
482 int k;
483
484 for (k = *off, ucp = initial_desig_desc ; (k + 3) < page_len; ) {
485 k = (k < 0) ? 0 : (k + ucp[k + 3] + 4);
486 if ((k + 4) > page_len)
487 break;
488 int c_set = (ucp[k] & 0xf);
489 if ((m_code_set >= 0) && (m_code_set != c_set))
490 continue;
491 int assoc = ((ucp[k + 1] >> 4) & 0x3);
492 if ((m_assoc >= 0) && (m_assoc != assoc))
493 continue;
494 int desig_type = (ucp[k + 1] & 0xf);
495 if ((m_desig_type >= 0) && (m_desig_type != desig_type))
496 continue;
497 *off = k;
498 return 0;
499 }
500 return (k == page_len) ? -1 : -2;
501}
502
503/* Decode VPD page 0x83 logical unit designator into a string. If both
504 * numeric address and SCSI name string present, prefer the former.
505 * Returns 0 on success, -1 on error with error string in s. */
506int
507scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
508 int * transport)
509{
510 if (transport)
511 *transport = -1;
512 if (slen < 32) {
513 if (slen > 0)
514 s[0] = '\0';
515 return -1;
516 }
517
518 s[0] = '\0';
519 int si = 0;
520 int have_scsi_ns = 0;
521 int off = -1;
522 int u;
523 while ((u = scsi_vpd_dev_id_iter(b, blen, &off, -1, -1, -1)) == 0) {
524 const unsigned char * ucp = b + off;
525 int i_len = ucp[3];
526 if ((off + i_len + 4) > blen) {
527 snprintf(s+si, slen-si, "error: designator length");
528 return -1;
529 }
530 int assoc = ((ucp[1] >> 4) & 0x3);
531 if (transport && assoc && (ucp[1] & 0x80) && (*transport < 0))
532 *transport = (ucp[0] >> 4) & 0xf;
533 if (0 != assoc)
534 continue;
535 const unsigned char * ip = ucp + 4;
536 int c_set = (ucp[0] & 0xf);
537 int desig_type = (ucp[1] & 0xf);
538
539 int naa;
540 switch (desig_type) {
541 case 0: /* vendor specific */
542 case 1: /* T10 vendor identification */
543 break;
544 case 2: /* EUI-64 based */
545 if ((8 != i_len) && (12 != i_len) && (16 != i_len)) {
546 snprintf(s+si, slen-si, "error: EUI-64 length");
547 return -1;
548 }
549 if (have_scsi_ns)
550 si = 0;
551 si += snprintf(s+si, slen-si, "0x");
552 for (int m = 0; m < i_len; ++m)
553 si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
554 break;
555 case 3: /* NAA */
556 if (1 != c_set) {
557 snprintf(s+si, slen-si, "error: NAA bad code_set");
558 return -1;
559 }
560 naa = (ip[0] >> 4) & 0xff;
561 if ((naa < 2) || (naa > 6) || (4 == naa)) {
562 snprintf(s+si, slen-si, "error: unexpected NAA");
563 return -1;
564 }
565 if (have_scsi_ns)
566 si = 0;
567 if (2 == naa) { /* NAA IEEE Extended */
568 if (8 != i_len) {
569 snprintf(s+si, slen-si, "error: NAA 2 length");
570 return -1;
571 }
572 si += snprintf(s+si, slen-si, "0x");
573 for (int m = 0; m < 8; ++m)
574 si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
575 } else if ((3 == naa ) || (5 == naa)) {
576 /* NAA=3 Locally assigned; NAA=5 IEEE Registered */
577 if (8 != i_len) {
578 snprintf(s+si, slen-si, "error: NAA 3 or 5 length");
579 return -1;
580 }
581 si += snprintf(s+si, slen-si, "0x");
582 for (int m = 0; m < 8; ++m)
583 si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
584 } else if (6 == naa) { /* NAA IEEE Registered extended */
585 if (16 != i_len) {
586 snprintf(s+si, slen-si, "error: NAA 6 length");
587 return -1;
588 }
589 si += snprintf(s+si, slen-si, "0x");
590 for (int m = 0; m < 16; ++m)
591 si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
592 }
593 break;
594 case 4: /* Relative target port */
595 case 5: /* (primary) Target port group */
596 case 6: /* Logical unit group */
597 case 7: /* MD5 logical unit identifier */
598 break;
599 case 8: /* SCSI name string */
600 if (3 != c_set) {
601 snprintf(s+si, slen-si, "error: SCSI name string");
602 return -1;
603 }
604 /* does %s print out UTF-8 ok?? */
605 if (si == 0) {
606 si += snprintf(s+si, slen-si, "%s", (const char *)ip);
607 ++have_scsi_ns;
608 }
609 break;
610 default: /* reserved */
611 break;
612 }
613 }
614 if (-2 == u) {
615 snprintf(s+si, slen-si, "error: bad structure");
616 return -1;
617 }
618 return 0;
619}
620
621/* Sends LOG SENSE command. Returns 0 if ok, 1 if device NOT READY, 2 if
622 * command not supported, 3 if field (within command) not supported or
623 * returns negated errno. SPC-3 sections 6.6 and 7.2 (rec 22a).
624 * N.B. Sets PC==1 to fetch "current cumulative" log pages.
625 * If known_resp_len > 0 then a single fetch is done for this response
626 * length. If known_resp_len == 0 then twin fetches are performed, the
627 * first to deduce the response length, then send the same command again
628 * requesting the deduced response length. This protects certain fragile
629 * HBAs. The twin fetch technique should not be used with the TapeAlert
630 * log page since it clears its state flags after each fetch. If
631 * known_resp_len < 0 then does single fetch for BufLen bytes. */
632int
633scsiLogSense(scsi_device * device, int pagenum, int subpagenum, uint8_t *pBuf,
634 int bufLen, int known_resp_len)
635{
636 int pageLen;
637 struct scsi_cmnd_io io_hdr = {};
638 struct scsi_sense_disect sinfo;
639 uint8_t cdb[10] = {};
640 uint8_t sense[32];
641
642 if (known_resp_len > bufLen)
643 return -EIO;
644 if (known_resp_len > 0)
645 pageLen = known_resp_len;
646 else if (known_resp_len < 0)
647 pageLen = bufLen;
648 else { /* 0 == known_resp_len */
649 /* Starting twin fetch strategy: first fetch to find respone length */
650 pageLen = 4;
651 if (pageLen > bufLen)
652 return -EIO;
653 else
654 memset(pBuf, 0, pageLen);
655
657 io_hdr.dxfer_len = pageLen;
658 io_hdr.dxferp = pBuf;
659 cdb[0] = LOG_SENSE;
660 cdb[2] = 0x40 | (pagenum & 0x3f); /* Page control (PC)==1 */
661 cdb[3] = subpagenum; /* 0 for no sub-page */
662 sg_put_unaligned_be16(pageLen, cdb + 7);
663 io_hdr.cmnd = cdb;
664 io_hdr.cmnd_len = sizeof(cdb);
665 io_hdr.sensep = sense;
666 io_hdr.max_sense_len = sizeof(sense);
668
669 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
670 return -device->get_errno();
671 int res;
672 if ((res = scsiSimpleSenseFilter(&sinfo)))
673 return res;
674 /* sanity check on response */
675 if ((SUPPORTED_LPAGES != pagenum) && ((pBuf[0] & 0x3f) != pagenum))
676 return SIMPLE_ERR_BAD_RESP;
677 uint16_t u = sg_get_unaligned_be16(pBuf + 2);
678 if (0 == u)
679 return SIMPLE_ERR_BAD_RESP;
680 pageLen = u + 4;
681 /* some SCSI HBA don't like "odd" length transfers */
682 if (pageLen % 2)
683 pageLen += 1;
684 if (pageLen > bufLen)
685 pageLen = bufLen;
686 }
687 memset(pBuf, 0, 4);
688 memset(&io_hdr, 0, sizeof(io_hdr));
689 memset(cdb, 0, sizeof(cdb));
691 io_hdr.dxfer_len = pageLen;
692 io_hdr.dxferp = pBuf;
693 cdb[0] = LOG_SENSE;
694 cdb[2] = 0x40 | (pagenum & 0x3f); /* Page control (PC)==1 */
695 cdb[3] = subpagenum;
696 sg_put_unaligned_be16(pageLen, cdb + 7);
697 io_hdr.cmnd = cdb;
698 io_hdr.cmnd_len = sizeof(cdb);
699 io_hdr.sensep = sense;
700 io_hdr.max_sense_len = sizeof(sense);
702
703 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
704 return -device->get_errno();
705 int status = scsiSimpleSenseFilter(&sinfo);
706 if (0 != status)
707 return status;
708 /* sanity check on response */
709 if ((SUPPORTED_LPAGES != pagenum) && ((pBuf[0] & 0x3f) != pagenum))
710 return SIMPLE_ERR_BAD_RESP;
711 if (0 == sg_get_unaligned_be16(pBuf + 2))
712 return SIMPLE_ERR_BAD_RESP;
713 return 0;
714}
715
716/* Sends a LOG SELECT command. Can be used to set log page values
717 * or reset one log page (or all of them) to its defaults (typically zero).
718 * Returns 0 if ok, 1 if NOT READY, 2 if command not supported, * 3 if
719 * field in command not supported, * 4 if bad parameter to command or
720 * returns negated errno. SPC-4 sections 6.5 and 7.2 (rev 20) */
721int
722scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum,
723 int subpagenum, uint8_t *pBuf, int bufLen)
724{
725 struct scsi_cmnd_io io_hdr = {};
726 struct scsi_sense_disect sinfo;
727 uint8_t cdb[10] = {};
728 uint8_t sense[32];
729
730 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
731 io_hdr.dxfer_len = bufLen;
732 io_hdr.dxferp = pBuf;
733 cdb[0] = LOG_SELECT;
734 cdb[1] = (pcr ? 2 : 0) | (sp ? 1 : 0);
735 cdb[2] = ((pc << 6) & 0xc0) | (pagenum & 0x3f);
736 cdb[3] = (subpagenum & 0xff);
737 sg_put_unaligned_be16(bufLen, cdb + 7);
738 io_hdr.cmnd = cdb;
739 io_hdr.cmnd_len = sizeof(cdb);
740 io_hdr.sensep = sense;
741 io_hdr.max_sense_len = sizeof(sense);
743
744 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
745 return -device->get_errno();
746 return scsiSimpleSenseFilter(&sinfo);
747}
748
749/* Send MODE SENSE (6 byte) command. Returns 0 if ok, 1 if NOT READY,
750 * 2 if command not supported (then MODE SENSE(10) should be supported),
751 * 3 if field in command not supported or returns negated errno.
752 * SPC-3 sections 6.9 and 7.4 (rev 22a) [mode subpage==0] */
753int
754scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
755 uint8_t *pBuf, int bufLen)
756{
757 struct scsi_cmnd_io io_hdr = {};
758 struct scsi_sense_disect sinfo;
759 uint8_t cdb[6] = {};
760 uint8_t sense[32];
761
762 if ((bufLen < 0) || (bufLen > 255))
763 return -EINVAL;
765 io_hdr.dxfer_len = bufLen;
766 io_hdr.dxferp = pBuf;
767 cdb[0] = MODE_SENSE_6;
768 cdb[2] = (pc << 6) | (pagenum & 0x3f);
769 cdb[3] = subpagenum;
770 cdb[4] = bufLen;
771 io_hdr.cmnd = cdb;
772 io_hdr.cmnd_len = sizeof(cdb);
773 io_hdr.sensep = sense;
774 io_hdr.max_sense_len = sizeof(sense);
776
777 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
778 return -device->get_errno();
779 int status = scsiSimpleSenseFilter(&sinfo);
780 if ((0 == status) && (ALL_MODE_PAGES != pagenum)) {
781 int offset;
782
783 offset = scsiModePageOffset(pBuf, bufLen, 0);
784 if (offset < 0)
785 return SIMPLE_ERR_BAD_RESP;
786 else if (pagenum != (pBuf[offset] & 0x3f))
787 return SIMPLE_ERR_BAD_RESP;
788 }
789 return status;
790}
791
792/* Sends a 6 byte MODE SELECT command. Assumes given pBuf is the response
793 * from a corresponding 6 byte MODE SENSE command. Such a response should
794 * have a 4 byte header followed by 0 or more 8 byte block descriptors
795 * (normally 1) and then 1 mode page. Returns 0 if ok, 1 if NOT READY,
796 * 2 if command not supported (then MODE SELECT(10) may be supported),
797 * 3 if field in command not supported, 4 if bad parameter to command
798 * or returns negated errno. SPC-3 sections 6.7 and 7.4 (rev 22a) */
799int
800scsiModeSelect(scsi_device * device, int sp, uint8_t *pBuf, int bufLen)
801{
802 struct scsi_cmnd_io io_hdr = {};
803 struct scsi_sense_disect sinfo;
804 uint8_t cdb[6] = {};
805 uint8_t sense[32];
806 int pg_offset, pg_len, hdr_plus_1_pg;
807
808 pg_offset = 4 + pBuf[3];
809 if (pg_offset + 2 >= bufLen)
810 return -EINVAL;
811 pg_len = pBuf[pg_offset + 1] + 2;
812 hdr_plus_1_pg = pg_offset + pg_len;
813 if (hdr_plus_1_pg > bufLen)
814 return -EINVAL;
815 pBuf[0] = 0; /* Length of returned mode sense data reserved for SELECT */
816 pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */
817 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
818 io_hdr.dxfer_len = hdr_plus_1_pg;
819 io_hdr.dxferp = pBuf;
820 cdb[0] = MODE_SELECT_6;
821 cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */
822 cdb[4] = hdr_plus_1_pg; /* make sure only one page sent */
823 io_hdr.cmnd = cdb;
824 io_hdr.cmnd_len = sizeof(cdb);
825 io_hdr.sensep = sense;
826 io_hdr.max_sense_len = sizeof(sense);
828
829 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
830 return -device->get_errno();
831 return scsiSimpleSenseFilter(&sinfo);
832}
833
834/* MODE SENSE (10 byte). Returns 0 if ok, 1 if NOT READY, 2 if command
835 * not supported (then MODE SENSE(6) might be supported), 3 if field in
836 * command not supported or returns negated errno.
837 * SPC-3 sections 6.10 and 7.4 (rev 22a) [mode subpage==0] */
838int
839scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc,
840 uint8_t *pBuf, int bufLen)
841{
842 struct scsi_cmnd_io io_hdr = {};
843 struct scsi_sense_disect sinfo;
844 uint8_t cdb[10] = {};
845 uint8_t sense[32];
846
848 io_hdr.dxfer_len = bufLen;
849 io_hdr.dxferp = pBuf;
850 cdb[0] = MODE_SENSE_10;
851 cdb[2] = (pc << 6) | (pagenum & 0x3f);
852 cdb[3] = subpagenum;
853 sg_put_unaligned_be16(bufLen, cdb + 7);
854 io_hdr.cmnd = cdb;
855 io_hdr.cmnd_len = sizeof(cdb);
856 io_hdr.sensep = sense;
857 io_hdr.max_sense_len = sizeof(sense);
859
860 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
861 return -device->get_errno();
862 int status = scsiSimpleSenseFilter(&sinfo);
863 if ((0 == status) && (ALL_MODE_PAGES != pagenum)) {
864 int offset;
865
866 offset = scsiModePageOffset(pBuf, bufLen, 1);
867 if (offset < 0)
868 return SIMPLE_ERR_BAD_RESP;
869 else if (pagenum != (pBuf[offset] & 0x3f))
870 return SIMPLE_ERR_BAD_RESP;
871 }
872 return status;
873}
874
875/* Sends a 10 byte MODE SELECT command. Assumes given pBuf is the response
876 * from a corresponding 10 byte MODE SENSE command. Such a response should
877 * have a 8 byte header followed by 0 or more 8 byte block descriptors
878 * (normally 1) and then 1 mode page. Returns 0 if ok, 1 NOT REAFY, 2 if
879 * command not supported (then MODE SELECT(6) may be supported), 3 if field
880 * in command not supported, 4 if bad parameter to command or returns
881 * negated errno. SPC-3 sections 6.8 and 7.4 (rev 22a) */
882int
883scsiModeSelect10(scsi_device * device, int sp, uint8_t *pBuf, int bufLen)
884{
885 struct scsi_cmnd_io io_hdr = {};
886 struct scsi_sense_disect sinfo;
887 uint8_t cdb[10] = {};
888 uint8_t sense[32];
889 int pg_offset, pg_len, hdr_plus_1_pg;
890
891 pg_offset = 8 + sg_get_unaligned_be16(pBuf + 6);
892 if (pg_offset + 2 >= bufLen)
893 return -EINVAL;
894 pg_len = pBuf[pg_offset + 1] + 2;
895 hdr_plus_1_pg = pg_offset + pg_len;
896 if (hdr_plus_1_pg > bufLen)
897 return -EINVAL;
898 pBuf[0] = 0;
899 pBuf[1] = 0; /* Length of returned mode sense data reserved for SELECT */
900 pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */
901 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
902 io_hdr.dxfer_len = hdr_plus_1_pg;
903 io_hdr.dxferp = pBuf;
904 cdb[0] = MODE_SELECT_10;
905 cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */
906 /* make sure only one page sent */
907 sg_put_unaligned_be16(hdr_plus_1_pg, cdb + 7);
908 io_hdr.cmnd = cdb;
909 io_hdr.cmnd_len = sizeof(cdb);
910 io_hdr.sensep = sense;
911 io_hdr.max_sense_len = sizeof(sense);
913
914 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
915 return -device->get_errno();
916 return scsiSimpleSenseFilter(&sinfo);
917}
918
919/* Standard INQUIRY returns 0 for ok, anything else is a major problem.
920 * bufLen should be 36 for unsafe devices (like USB mass storage stuff)
921 * otherwise they can lock up! SPC-3 sections 6.4 and 7.6 (rev 22a) */
922int
923scsiStdInquiry(scsi_device * device, uint8_t *pBuf, int bufLen)
924{
925 struct scsi_sense_disect sinfo;
926 struct scsi_cmnd_io io_hdr = {};
927 int res;
928 uint8_t cdb[6] = {};
929 uint8_t sense[32];
930
931 if ((bufLen < 0) || (bufLen > 1023))
932 return -EINVAL;
933 if (bufLen >= 36) /* normal case */
934 memset(pBuf, 0, 36);
936 io_hdr.dxfer_len = bufLen;
937 io_hdr.dxferp = pBuf;
938 cdb[0] = INQUIRY;
939 sg_put_unaligned_be16(bufLen, cdb + 3);
940 io_hdr.cmnd = cdb;
941 io_hdr.cmnd_len = sizeof(cdb);
942 io_hdr.sensep = sense;
943 io_hdr.max_sense_len = sizeof(sense);
945
946 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
947 return -device->get_errno();
948 res = scsiSimpleSenseFilter(&sinfo);
949 if ((SIMPLE_NO_ERROR == res) && (! device->is_spc4_or_higher())) {
950 if (((bufLen - io_hdr.resid) >= 36) &&
951 (pBuf[2] >= 6) && /* VERSION field >= SPC-4 */
952 ((pBuf[3] & 0xf) == 2)) { /* RESPONSE DATA field == 2 */
953 uint8_t pdt = pBuf[0] & 0x1f;
954
955 if ((SCSI_PT_DIRECT_ACCESS == pdt) ||
956 (SCSI_PT_HOST_MANAGED == pdt) ||
957 (SCSI_PT_SEQUENTIAL_ACCESS == pdt) ||
958 (SCSI_PT_MEDIUM_CHANGER == pdt))
959 device->set_spc4_or_higher();
960 }
961 }
962 return res;
963}
964
965/* INQUIRY to fetch Vital Page Data. Returns 0 if ok, 1 if NOT READY
966 * (unlikely), 2 if command not supported, 3 if field in command not
967 * supported, 5 if response indicates that EVPD bit ignored or returns
968 * negated errno. SPC-3 section 6.4 and 7.6 (rev 22a) */
969int
970scsiInquiryVpd(scsi_device * device, int vpd_page, uint8_t *pBuf, int bufLen)
971{
972 struct scsi_cmnd_io io_hdr = {};
973 struct scsi_sense_disect sinfo;
974 uint8_t cdb[6] = {};
975 uint8_t sense[32];
976 int res;
977
978 /* Assume SCSI_VPD_SUPPORTED_VPD_PAGES is first VPD page fetched */
979 if ((SCSI_VPD_SUPPORTED_VPD_PAGES != vpd_page) &&
981 (! supported_vpd_pages_p->is_supported(vpd_page)))
982 return 3;
983
984 if ((bufLen < 0) || (bufLen > 1023))
985 return -EINVAL;
986try_again:
987 if (bufLen > 1)
988 pBuf[1] = 0x0;
990 io_hdr.dxfer_len = bufLen;
991 io_hdr.dxferp = pBuf;
992 cdb[0] = INQUIRY;
993 cdb[1] = 0x1; /* set EVPD bit (enable Vital Product Data) */
994 cdb[2] = vpd_page;
995 sg_put_unaligned_be16(bufLen, cdb + 3);
996 io_hdr.cmnd = cdb;
997 io_hdr.cmnd_len = sizeof(cdb);
998 io_hdr.sensep = sense;
999 io_hdr.max_sense_len = sizeof(sense);
1001
1002 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
1003 return -device->get_errno();
1004 if ((SCSI_STATUS_CHECK_CONDITION == io_hdr.scsi_status) &&
1006 (SCSI_ASC_INVALID_FIELD == sinfo.asc) &&
1007 (cdb[3] > 0)) {
1008 bufLen &= 0xff; /* make sure cdb[3] is 0 next time around */
1009 goto try_again;
1010 }
1011
1012 if ((res = scsiSimpleSenseFilter(&sinfo)))
1013 return res;
1014 /* Guard against devices that ignore EVPD bit and do standard INQUIRY */
1015 if (bufLen > 1) {
1016 if (vpd_page == pBuf[1]) {
1017 if ((0x80 == vpd_page) && (bufLen > 2) && (0x0 != pBuf[2]))
1018 return SIMPLE_ERR_BAD_RESP;
1019 } else
1020 return SIMPLE_ERR_BAD_RESP;
1021 }
1022 return 0;
1023}
1024
1025/* REQUEST SENSE command. Returns 0 if ok, anything else major problem.
1026 * SPC-3 section 6.27 (rev 22a) */
1027int
1028scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info)
1029{
1030 struct scsi_cmnd_io io_hdr = {};
1031 uint8_t cdb[6] = {};
1032 uint8_t sense[32];
1033 uint8_t buff[18] = {};
1034 bool ok;
1035 static const int sz_buff = sizeof(buff);
1036
1038 io_hdr.dxfer_len = sz_buff;
1039 io_hdr.dxferp = buff;
1040 cdb[0] = REQUEST_SENSE;
1041 cdb[4] = sz_buff;
1042 io_hdr.cmnd = cdb;
1043 io_hdr.cmnd_len = sizeof(cdb);
1044 io_hdr.sensep = sense;
1045 io_hdr.max_sense_len = sizeof(sense);
1047
1048 if (sense_info)
1049 ok = scsi_pass_through_yield_sense(device, &io_hdr, *sense_info);
1050 else {
1051 scsi_sense_disect dummy_sense;
1052 ok = scsi_pass_through_yield_sense(device, &io_hdr, dummy_sense);
1053 }
1054 if (! ok)
1055 return -device->get_errno();
1056 if (sense_info) {
1057 uint8_t resp_code = buff[0] & 0x7f;
1058 sense_info->resp_code = resp_code;
1059 sense_info->sense_key = buff[2] & 0xf;
1060 sense_info->asc = 0;
1061 sense_info->ascq = 0;
1062 if ((0x70 == resp_code) || (0x71 == resp_code)) {
1063 int len = buff[7] + 8;
1064 if (len > 13) {
1065 sense_info->asc = buff[12];
1066 sense_info->ascq = buff[13];
1067 }
1068 }
1069 // fill progress indicator, if available
1070 sense_info->progress = -1;
1071 switch (resp_code) {
1072 const unsigned char * ucp;
1073 int sk, sk_pr;
1074 case 0x70:
1075 case 0x71:
1076 sk = (buff[2] & 0xf);
1077 if (! ((SCSI_SK_NO_SENSE == sk) || (SCSI_SK_NOT_READY == sk))) {
1078 break;
1079 }
1080 if (buff[15] & 0x80) { /* SKSV bit set */
1081 sense_info->progress = sg_get_unaligned_be16(buff + 16);
1082 break;
1083 } else {
1084 break;
1085 }
1086 case 0x72:
1087 case 0x73:
1088 /* sense key specific progress (0x2) or progress descriptor (0xa) */
1089 sk = (buff[1] & 0xf);
1090 sk_pr = (SCSI_SK_NO_SENSE == sk) || (SCSI_SK_NOT_READY == sk);
1091 if (sk_pr && ((ucp = sg_scsi_sense_desc_find(buff, sz_buff, 2))) &&
1092 (0x6 == ucp[1]) && (0x80 & ucp[4])) {
1093 sense_info->progress = sg_get_unaligned_be16(ucp + 5);
1094 break;
1095 } else if (((ucp = sg_scsi_sense_desc_find(buff, sz_buff, 0xa))) &&
1096 ((0x6 == ucp[1]))) {
1097 sense_info->progress = sg_get_unaligned_be16(ucp + 6);
1098 break;
1099 } else
1100 break;
1101 default:
1102 return 0;
1103 }
1104 }
1105 return 0;
1106}
1107
1108/* Send Start Stop Unit command with power_condition setting and
1109 * Power condition command. Returns 0 if ok, anything else major problem.
1110 * If power_cond is 0, treat as SSU(START) as that is better than
1111 * SSU(STOP) which would be the case if byte 4 of the cdb was zero.
1112 * Ref: SBC-4 revision 22, section 4.20 SSU and power conditions.
1113 *
1114 * SCSI_POW_COND_ACTIVE 0x1
1115 * SCSI_POW_COND_IDLE 0x2
1116 * SCSI_POW_COND_STANDBY 0x3
1117 *
1118 */
1119
1120int
1121scsiSetPowerCondition(scsi_device * device, int power_cond, int pcond_modifier)
1122{
1123 struct scsi_cmnd_io io_hdr = {};
1124 struct scsi_sense_disect sinfo;
1125 uint8_t cdb[6] = {};
1126 uint8_t sense[32];
1127
1128 io_hdr.dxfer_dir = DXFER_NONE;
1129 cdb[0] = START_STOP_UNIT;
1130 /* IMMED bit (cdb[1] = 0x1) not set, therefore will wait */
1131 if (power_cond > 0) {
1132 cdb[3] = pcond_modifier & 0xf;
1133 cdb[4] = power_cond << 4;
1134 } else
1135 cdb[4] = 0x1; /* START */
1136 io_hdr.cmnd = cdb;
1137 io_hdr.cmnd_len = sizeof(cdb);
1138 io_hdr.sensep = sense;
1139 io_hdr.max_sense_len = sizeof(sense);
1141
1142 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
1143 return -device->get_errno();
1144
1145 return scsiSimpleSenseFilter(&sinfo);
1146}
1147
1148/* SEND DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if command
1149 * not supported, 3 if field in command not supported or returns negated
1150 * errno. SPC-3 section 6.28 (rev 22a) */
1151int
1152scsiSendDiagnostic(scsi_device * device, int functioncode, uint8_t *pBuf,
1153 int bufLen)
1154{
1155 struct scsi_cmnd_io io_hdr = {};
1156 struct scsi_sense_disect sinfo;
1157 uint8_t cdb[6] = {};
1158 uint8_t sense[32];
1159
1160 io_hdr.dxfer_dir = bufLen ? DXFER_TO_DEVICE: DXFER_NONE;
1161 io_hdr.dxfer_len = bufLen;
1162 io_hdr.dxferp = pBuf;
1163 cdb[0] = SEND_DIAGNOSTIC;
1164 if (SCSI_DIAG_DEF_SELF_TEST == functioncode)
1165 cdb[1] = 0x4; /* SelfTest bit */
1166 else if (SCSI_DIAG_NO_SELF_TEST != functioncode)
1167 cdb[1] = (functioncode & 0x7) << 5; /* SelfTest _code_ */
1168 else /* SCSI_DIAG_NO_SELF_TEST == functioncode */
1169 cdb[1] = 0x10; /* PF bit */
1170 sg_put_unaligned_be16(bufLen, cdb + 3);
1171 io_hdr.cmnd = cdb;
1172 io_hdr.cmnd_len = sizeof(cdb);
1173 io_hdr.sensep = sense;
1174 io_hdr.max_sense_len = sizeof(sense);
1175 /* worst case is an extended foreground self test on a big disk */
1177
1178 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
1179 return -device->get_errno();
1180 return scsiSimpleSenseFilter(&sinfo);
1181}
1182
1183/* TEST UNIT READY command. SPC-3 section 6.33 (rev 22a) */
1184static int
1186{
1187 struct scsi_cmnd_io io_hdr = {};
1188 bool ok;
1189 uint8_t cdb[6] = {};
1190 uint8_t sense[32];
1191
1192 io_hdr.dxfer_dir = DXFER_NONE;
1193 io_hdr.dxfer_len = 0;
1194 io_hdr.dxferp = NULL;
1195 cdb[0] = TEST_UNIT_READY;
1196 io_hdr.cmnd = cdb;
1197 io_hdr.cmnd_len = sizeof(cdb);
1198 io_hdr.sensep = sense;
1199 io_hdr.max_sense_len = sizeof(sense);
1201
1202 if (sinfop)
1203 ok = scsi_pass_through_yield_sense(device, &io_hdr, *sinfop);
1204 else {
1205 struct scsi_sense_disect dummy_si;
1206 ok = scsi_pass_through_yield_sense(device, &io_hdr, dummy_si);
1207 }
1208 if (! ok)
1209 return -device->get_errno();
1210 return 0;
1211}
1212
1213/* Returns 0 for device responds and media ready, 1 for device responds and
1214 media not ready, or returns a negated errno value */
1215int
1217{
1218 struct scsi_sense_disect sinfo;
1219 int status;
1220
1221 status = _testunitready(device, &sinfo);
1222 if (0 != status)
1223 return status;
1224 return scsiSimpleSenseFilter(&sinfo);
1225}
1226
1227/* READ DEFECT (10) command. Returns 0 if ok, 1 if NOT READY, 2 if
1228 * command not supported, 3 if field in command not supported, 101 if
1229 * defect list not found (e.g. SSD may not have defect list) or returns
1230 * negated errno. SBC-2 section 5.12 (rev 16) */
1231int
1232scsiReadDefect10(scsi_device * device, int req_plist, int req_glist,
1233 int dl_format, uint8_t *pBuf, int bufLen)
1234{
1235 struct scsi_cmnd_io io_hdr = {};
1236 struct scsi_sense_disect sinfo;
1237 uint8_t cdb[10] = {};
1238 uint8_t sense[32];
1239
1241 io_hdr.dxfer_len = bufLen;
1242 io_hdr.dxferp = pBuf;
1243 cdb[0] = READ_DEFECT_10;
1244 cdb[2] = (unsigned char)(((req_plist << 4) & 0x10) |
1245 ((req_glist << 3) & 0x8) | (dl_format & 0x7));
1246 sg_put_unaligned_be16(bufLen, cdb + 7);
1247 io_hdr.cmnd = cdb;
1248 io_hdr.cmnd_len = sizeof(cdb);
1249 io_hdr.sensep = sense;
1250 io_hdr.max_sense_len = sizeof(sense);
1252
1253 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
1254 return -device->get_errno();
1255 /* Look for "(Primary|Grown) defect list not found" */
1256 if ((sinfo.resp_code >= 0x70) && (0x1c == sinfo.asc))
1257 return 101;
1258 return scsiSimpleSenseFilter(&sinfo);
1259}
1260
1261/* READ DEFECT (12) command. Returns 0 if ok, 1 if NOT READY, 2 if
1262 * command not supported, 3 if field in command not supported, 101 if
1263 * defect list not found (e.g. SSD may not have defect list) or returns
1264 * negated errno. SBC-3 section 5.18 (rev 35; vale Mark Evans) */
1265int
1266scsiReadDefect12(scsi_device * device, int req_plist, int req_glist,
1267 int dl_format, int addrDescIndex, uint8_t *pBuf, int bufLen)
1268{
1269 struct scsi_cmnd_io io_hdr = {};
1270 struct scsi_sense_disect sinfo;
1271 uint8_t cdb[12] = {};
1272 uint8_t sense[32];
1273
1275 io_hdr.dxfer_len = bufLen;
1276 io_hdr.dxferp = pBuf;
1277 cdb[0] = READ_DEFECT_12;
1278 cdb[1] = (unsigned char)(((req_plist << 4) & 0x10) |
1279 ((req_glist << 3) & 0x8) | (dl_format & 0x7));
1280 sg_put_unaligned_be32(addrDescIndex, cdb + 2);
1281 sg_put_unaligned_be32(bufLen, cdb + 6);
1282 io_hdr.cmnd = cdb;
1283 io_hdr.cmnd_len = sizeof(cdb);
1284 io_hdr.sensep = sense;
1285 io_hdr.max_sense_len = sizeof(sense);
1287
1288 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
1289 return -device->get_errno();
1290 /* Look for "(Primary|Grown) defect list not found" */
1291 if ((sinfo.resp_code >= 0x70) && (0x1c == sinfo.asc))
1292 return 101;
1293 return scsiSimpleSenseFilter(&sinfo);
1294}
1295
1296/* Call scsi_pass_through, and retry only if a UNIT_ATTENTION (UA) is raised.
1297 * When false returned, the caller should invoke device->get_error().
1298 * When true returned, the caller should check sinfo.
1299 * All SCSI commands can receive pending Unit Attentions, apart from:
1300 * INQUIRY, REPORT LUNS, REQUEST SENSE and NOTIFY DATA TRANSFER DEVICE
1301 * (ADC-3 spec). The first three are the important ones. */
1302bool
1304 /* OUT param */ scsi_sense_disect & sinfo)
1305{
1306 int k;
1307 uint32_t opcode = (iop->cmnd_len > 0) ? iop->cmnd[0] : 0xffff;
1308
1309 if (scsi_debugmode > 2)
1310 pout("%s: opcode: 0x%x\n", __func__, opcode);
1311
1312 if (! device->scsi_pass_through(iop))
1313 return false; // this will be missing device, timeout, etc
1314
1315 scsi_do_sense_disect(iop, &sinfo);
1316
1317 switch (opcode) {
1318 case INQUIRY:
1319 case REPORT_LUNS:
1320 case REQUEST_SENSE:
1321 return true; /* in these cases, it shouldn't be a UA */
1322 default:
1323 break; /* continue on for all other SCSI commands to check for UA */
1324 }
1325
1326 /* There can be multiple UAs pending, allow for three */
1327 for (k = 0; (k < 3) && (SCSI_SK_UNIT_ATTENTION == sinfo.sense_key); ++k) {
1328 if (scsi_debugmode > 0)
1329 pout("%s Unit Attention %d: asc/ascq=0x%x,0x%x, retrying\n",
1330 __func__, k + 1, sinfo.asc, sinfo.ascq);
1331 if (! device->scsi_pass_through(iop))
1332 return false;
1333 scsi_do_sense_disect(iop, &sinfo);
1334 }
1335 return true;
1336}
1337
1338/* READ CAPACITY (10) command. Returns 0 if ok, 1 if NOT READY, 2 if
1339 * command not supported, 3 if field in command not supported or returns
1340 * negated errno. SBC-3 section 5.15 (rev 26) */
1341int
1342scsiReadCapacity10(scsi_device * device, unsigned int * last_lbap,
1343 unsigned int * lb_sizep)
1344{
1345 int res;
1346 struct scsi_cmnd_io io_hdr = {};
1347 struct scsi_sense_disect sinfo;
1348 uint8_t cdb[10] = {};
1349 uint8_t sense[32];
1350 uint8_t resp[8] = {};
1351
1353 io_hdr.dxfer_len = sizeof(resp);
1354 io_hdr.dxferp = resp;
1355 cdb[0] = READ_CAPACITY_10;
1356 io_hdr.cmnd = cdb;
1357 io_hdr.cmnd_len = sizeof(cdb);
1358 io_hdr.sensep = sense;
1359 io_hdr.max_sense_len = sizeof(sense);
1361
1362 if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
1363 return -device->get_errno();
1364 res = scsiSimpleSenseFilter(&sinfo);
1365 if (res)
1366 return res;
1367 if (last_lbap)
1368 *last_lbap = sg_get_unaligned_be32(resp + 0);
1369 if (lb_sizep)
1370 *lb_sizep = sg_get_unaligned_be32(resp + 4);
1371 return 0;
1372}
1373
1374/* READ CAPACITY (16) command. The bufLen argument should be 32. Returns 0
1375 * if ok, 1 if NOT READY, 2 if command not supported, 3 if field in command
1376 * not supported or returns negated errno. SBC-3 section 5.16 (rev 26) */
1377int
1378scsiReadCapacity16(scsi_device * device, uint8_t *pBuf, int bufLen)
1379{
1380 struct scsi_cmnd_io io_hdr = {};
1381 struct scsi_sense_disect sinfo;
1382 uint8_t cdb[16] = {};
1383 uint8_t sense[32];
1384
1386 io_hdr.dxfer_len = bufLen;
1387 io_hdr.dxferp = pBuf;
1390 sg_put_unaligned_be32(bufLen, cdb + 10);
1391 io_hdr.cmnd = cdb;
1392 io_hdr.cmnd_len = sizeof(cdb);
1393 io_hdr.sensep = sense;
1394 io_hdr.max_sense_len = sizeof(sense);
1396
1397 if (!scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
1398 return -device->get_errno();
1399 return scsiSimpleSenseFilter(&sinfo);
1400}
1401
1402/* REPORT SUPPORTED OPERATION CODES [RSOC] command. If SIMPLE_NO_ERROR is
1403 * returned then the response length is written to rspLen. */
1404int
1405scsiRSOCcmd(scsi_device * device, uint8_t *pBuf, int bufLen, int & rspLen)
1406{
1407 struct scsi_cmnd_io io_hdr = {};
1408 struct scsi_sense_disect sinfo;
1409 int res;
1410 uint8_t cdb[12] = {};
1411 uint8_t sense[32];
1412
1414 io_hdr.dxfer_len = bufLen;
1415 io_hdr.dxferp = pBuf;
1418 /* RCTD=0 (no timeout descriptors); REPORTING_OPTION=0 (all commands) */
1419 /* those settings imply response should contain 8 bytes per command */
1420 sg_put_unaligned_be32(bufLen, cdb + 6);
1421 io_hdr.cmnd = cdb;
1422 io_hdr.cmnd_len = sizeof(cdb);
1423 io_hdr.sensep = sense;
1424 io_hdr.max_sense_len = sizeof(sense);
1426
1427 if (!scsi_pass_through_yield_sense(device, &io_hdr, sinfo))
1428 return -device->get_errno();
1429 res = scsiSimpleSenseFilter(&sinfo);
1430 if (SIMPLE_NO_ERROR == res)
1431 rspLen = bufLen - io_hdr.resid;
1432 return res;
1433}
1434
1435/* Return number of bytes of storage in 'device' or 0 if error. If
1436 * successful and lb_sizep is not NULL then the logical block size in bytes
1437 * is written to the location pointed to by lb_sizep. If the 'Logical Blocks
1438 * per Physical Block Exponent' pointer (lb_per_pb_expp,) is non-null then
1439 * the value is written. If 'Protection information Intervals Exponent'*/
1440uint64_t
1441scsiGetSize(scsi_device * device, bool avoid_rcap16,
1442 struct scsi_readcap_resp * srrp)
1443{
1444 bool try_16 = false;
1445 bool try_12 = false;
1446 unsigned int last_lba = 0, lb_size = 0;
1447 int res;
1448 uint64_t ret_val = 0;
1449 uint8_t rc16resp[32];
1450
1451 if (avoid_rcap16) {
1452 res = scsiReadCapacity10(device, &last_lba, &lb_size);
1453 if (res) {
1454 if (scsi_debugmode)
1455 pout("%s: READ CAPACITY(10) failed, res=%d\n", __func__, res);
1456 try_16 = true;
1457 } else { /* rcap10 succeeded */
1458 if (0xffffffff == last_lba) {
1459 /* so number of blocks needs > 32 bits to represent */
1460 try_16 = true;
1461 device->set_rcap16_first();
1462 } else {
1463 ret_val = last_lba + 1;
1464 if (srrp) {
1465 memset(srrp, 0, sizeof(*srrp));
1466 srrp->num_lblocks = ret_val;
1467 srrp->lb_size = lb_size;
1468 }
1469 }
1470 }
1471 }
1472 if (try_16 || (! avoid_rcap16)) {
1473 res = scsiReadCapacity16(device, rc16resp, sizeof(rc16resp));
1474 if (res) {
1475 if (scsi_debugmode)
1476 pout("%s: READ CAPACITY(16) failed, res=%d\n", __func__, res);
1477 if (try_16) /* so already tried rcap10 */
1478 return 0;
1479 try_12 = true;
1480 } else { /* rcap16 succeeded */
1481 ret_val = sg_get_unaligned_be64(rc16resp + 0) + 1;
1482 lb_size = sg_get_unaligned_be32(rc16resp + 8);
1483 if (srrp) { /* writes to all fields */
1484 srrp->num_lblocks = ret_val;
1485 srrp->lb_size = lb_size;
1486 bool prot_en = !!(0x1 & rc16resp[12]);
1487 uint8_t p_type = ((rc16resp[12] >> 1) & 0x7);
1488 srrp->prot_type = prot_en ? (1 + p_type) : 0;
1489 srrp->p_i_exp = ((rc16resp[13] >> 4) & 0xf);
1490 srrp->lb_p_pb_exp = (rc16resp[13] & 0xf);
1491 srrp->lbpme = !!(0x80 & rc16resp[14]);
1492 srrp->lbprz = !!(0x40 & rc16resp[14]);
1493 srrp->l_a_lba = sg_get_unaligned_be16(rc16resp + 14) & 0x3fff;
1494 }
1495 }
1496 }
1497 if (try_12) { /* case where only rcap16 has been tried and failed */
1498 res = scsiReadCapacity10(device, &last_lba, &lb_size);
1499 if (res) {
1500 if (scsi_debugmode)
1501 pout("%s: 2nd READ CAPACITY(10) failed, res=%d\n", __func__,
1502 res);
1503 return 0;
1504 } else { /* rcap10 succeeded */
1505 ret_val = (uint64_t)last_lba + 1;
1506 if (srrp) {
1507 memset(srrp, 0, sizeof(*srrp));
1508 srrp->num_lblocks = ret_val;
1509 srrp->lb_size = lb_size;
1510 }
1511 }
1512 }
1513 return (ret_val * lb_size);
1514}
1515
1516/* Offset into mode sense (6 or 10 byte) response that actual mode page
1517 * starts at (relative to resp[0]). Returns -1 if problem */
1518int
1519scsiModePageOffset(const uint8_t * resp, int len, int modese_len)
1520{
1521 int offset = -1;
1522
1523 if (resp) {
1524 int resp_len, bd_len;
1525 if (10 == modese_len) {
1526 resp_len = sg_get_unaligned_be16(resp + 0) + 2;
1527 bd_len = sg_get_unaligned_be16(resp + 6);
1528 offset = bd_len + 8;
1529 } else {
1530 resp_len = resp[0] + 1;
1531 bd_len = resp[3];
1532 offset = bd_len + 4;
1533 }
1534 if ((offset + 2) > len) {
1535 pout("scsiModePageOffset: raw_curr too small, offset=%d "
1536 "resp_len=%d bd_len=%d\n", offset, resp_len, bd_len);
1537 offset = -1;
1538 } else if ((offset + 2) > resp_len) {
1539 if ((resp_len > 2) || scsi_debugmode)
1540 pout("scsiModePageOffset: response length too short, "
1541 "resp_len=%d offset=%d bd_len=%d\n", resp_len,
1542 offset, bd_len);
1543 offset = -1;
1544 }
1545 }
1546 return offset;
1547}
1548
1549/* IEC mode page byte 2 bit masks */
1550#define DEXCPT_ENABLE 0x08
1551#define EWASC_ENABLE 0x10
1552#define DEXCPT_DISABLE 0xf7
1553#define EWASC_DISABLE 0xef
1554#define TEST_DISABLE 0xfb
1555
1556/* Fetches the Informational Exceptions Control mode page. First tries
1557 * the 6 byte MODE SENSE command and if that fails with an illegal opcode
1558 * tries a 10 byte MODE SENSE command. Returns 0 if successful, a positive
1559 * number if a known error (see SIMPLE_ERR_ ...) or a negative errno
1560 * value. */
1561int
1563 int modese_len)
1564{
1565 int err = 0;
1566
1567 memset(iecp, 0, sizeof(*iecp));
1568 iecp->modese_len = modese_len;
1569 iecp->requestedCurrent = 1;
1570 if (iecp->modese_len <= 6) {
1573 iecp->raw_curr, sizeof(iecp->raw_curr)))) {
1574 if (SIMPLE_ERR_BAD_OPCODE == err)
1575 iecp->modese_len = 10;
1576 else {
1577 iecp->modese_len = 0;
1578 return err;
1579 }
1580 } else if (0 == iecp->modese_len)
1581 iecp->modese_len = 6;
1582 }
1583 if (10 == iecp->modese_len) {
1586 iecp->raw_curr, sizeof(iecp->raw_curr));
1587 if (err) {
1588 iecp->modese_len = 0;
1589 return err;
1590 }
1591 }
1592 iecp->gotCurrent = 1;
1593 iecp->requestedChangeable = 1;
1594 if (10 == iecp->modese_len)
1597 iecp->raw_chg, sizeof(iecp->raw_chg));
1598 else if (6 == iecp->modese_len)
1601 iecp->raw_chg, sizeof(iecp->raw_chg));
1602 if (err)
1603 return err;
1604 iecp->gotChangeable = 1;
1605 return 0;
1606}
1607
1608int
1610{
1611 if (iecp && iecp->gotCurrent) {
1612 int offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
1613 iecp->modese_len);
1614 if (offset >= 0)
1615 return (iecp->raw_curr[offset + 2] & DEXCPT_ENABLE) ? 0 : 1;
1616 else
1617 return 0;
1618 } else
1619 return 0;
1620}
1621
1622int
1624{
1625 if (iecp && iecp->gotCurrent) {
1626 int offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
1627 iecp->modese_len);
1628 if (offset >= 0)
1629 return (iecp->raw_curr[offset + 2] & EWASC_ENABLE) ? 1 : 0;
1630 else
1631 return 0;
1632 } else
1633 return 0;
1634}
1635
1636/* set EWASC and clear PERF, EBF, DEXCPT TEST and LOGERR */
1637#define SCSI_IEC_MP_BYTE2_ENABLED 0x10
1638#define SCSI_IEC_MP_BYTE2_TEST_MASK 0x4
1639/* exception/warning via an unrequested REQUEST SENSE command */
1640#define SCSI_IEC_MP_MRIE 6
1641#define SCSI_IEC_MP_INTERVAL_T 0
1642#define SCSI_IEC_MP_REPORT_COUNT 1
1643
1644/* Try to set (or clear) both Exception Control and Warning in the IE
1645 * mode page subject to the "changeable" mask. The object pointed to
1646 * by iecp is (possibly) inaccurate after this call, therefore
1647 * scsiFetchIECmpage() should be called again if the IEC mode page
1648 * is to be re-examined.
1649 * When -r ioctl is invoked 3 or more time on 'smartctl -s on ...'
1650 * then set the TEST bit (causes asc,ascq pair of 0x5d,0xff). */
1651int
1653 const struct scsi_iec_mode_page *iecp)
1654{
1655 int offset, resp_len;
1656 int err = 0;
1657 uint8_t rout[SCSI_IECMP_RAW_LEN];
1658
1659 if ((! iecp) || (! iecp->gotCurrent))
1660 return -EINVAL;
1661 offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr),
1662 iecp->modese_len);
1663 if (offset < 0)
1664 return -EINVAL;
1665 memcpy(rout, iecp->raw_curr, SCSI_IECMP_RAW_LEN);
1666 /* mask out DPOFUA device specific (disk) parameter bit */
1667 if (10 == iecp->modese_len) {
1668 resp_len = sg_get_unaligned_be16(rout + 0) + 2;
1669 rout[3] &= 0xef;
1670 } else {
1671 resp_len = rout[0] + 1;
1672 rout[2] &= 0xef;
1673 }
1674 int sp = !! (rout[offset] & 0x80); /* PS bit becomes 'SELECT's SP bit */
1675 if (enabled) {
1676 rout[offset + 2] = SCSI_IEC_MP_BYTE2_ENABLED;
1677 if (scsi_debugmode > 2)
1678 rout[offset + 2] |= SCSI_IEC_MP_BYTE2_TEST_MASK;
1679 rout[offset + 3] = SCSI_IEC_MP_MRIE;
1682 if (iecp->gotChangeable) {
1683 uint8_t chg2 = iecp->raw_chg[offset + 2];
1684
1685 rout[offset + 2] = chg2 ? (rout[offset + 2] & chg2) :
1686 iecp->raw_curr[offset + 2];
1687 for (int k = 3; k < 12; ++k) {
1688 if (0 == iecp->raw_chg[offset + k])
1689 rout[offset + k] = iecp->raw_curr[offset + k];
1690 }
1691 }
1692 if (0 == memcmp(&rout[offset + 2], &iecp->raw_chg[offset + 2], 10)) {
1693 if (scsi_debugmode > 0)
1694 pout("scsiSetExceptionControlAndWarning: already enabled\n");
1695 return 0;
1696 }
1697 } else { /* disabling Exception Control and (temperature) Warnings */
1698 int eCEnabled = (rout[offset + 2] & DEXCPT_ENABLE) ? 0 : 1;
1699 int wEnabled = (rout[offset + 2] & EWASC_ENABLE) ? 1 : 0;
1700 if ((! eCEnabled) && (! wEnabled)) {
1701 if (scsi_debugmode > 0)
1702 pout("scsiSetExceptionControlAndWarning: already disabled\n");
1703 return 0; /* nothing to do, leave other setting alone */
1704 }
1705 if (wEnabled)
1706 rout[offset + 2] &= EWASC_DISABLE;
1707 if (eCEnabled) {
1708 if (iecp->gotChangeable &&
1709 (iecp->raw_chg[offset + 2] & DEXCPT_ENABLE))
1710 rout[offset + 2] |= DEXCPT_ENABLE;
1711 rout[offset + 2] &= TEST_DISABLE; /* clear TEST bit for spec */
1712 }
1713 }
1714 if (10 == iecp->modese_len)
1715 err = scsiModeSelect10(device, sp, rout, resp_len);
1716 else if (6 == iecp->modese_len)
1717 err = scsiModeSelect(device, sp, rout, resp_len);
1718 return err;
1719}
1720
1721int
1722scsiGetTemp(scsi_device * device, uint8_t *currenttemp, uint8_t *triptemp)
1723{
1724 uint8_t tBuf[252] = {};
1725 int err;
1726
1727 if ((err = scsiLogSense(device, TEMPERATURE_LPAGE, 0, tBuf,
1728 sizeof(tBuf), 0))) {
1729 *currenttemp = 0;
1730 *triptemp = 0;
1731 pout("%s for temperature failed [%s]\n", logSenStr,
1732 scsiErrString(err));
1733 return err;
1734 }
1735 *currenttemp = tBuf[9];
1736 *triptemp = tBuf[15];
1737 return 0;
1738}
1739
1740/* Informational Exception conditions specified by spc6r06.pdf seem to be
1741 * associated with ASC values 0xb (warnings) and 0x5d (impending failures).
1742 * The asc/accq value 0x5d,0xff is reported in response to setting the TEST
1743 * bit in the Informationl Exception Control mode page. */
1744
1745/* Read informational exception log page or Request Sense response.
1746 * Fetching asc/ascq code potentially flagging an exception or warning.
1747 * Returns 0 if ok, else error number. A current temperature of 255
1748 * (Celsius) implies that the temperature not available. */
1749int
1750scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
1751 uint8_t *asc, uint8_t *ascq, uint8_t *currenttemp,
1752 uint8_t *triptemp)
1753{
1754 uint8_t tBuf[252] = {};
1755 struct scsi_sense_disect sense_info;
1756 int err;
1757 uint8_t currTemp, trTemp;
1758
1759 memset(&sense_info, 0, sizeof(sense_info));
1760 *asc = 0;
1761 *ascq = 0;
1762 *currenttemp = 0;
1763 *triptemp = 0;
1764 if (hasIELogPage) {
1765 if ((err = scsiLogSense(device, IE_LPAGE, 0, tBuf,
1766 sizeof(tBuf), 0))) {
1767 pout("%s failed, IE page [%s]\n", logSenStr, scsiErrString(err));
1768 return err;
1769 }
1770 // pull out page size from response, don't forget to add 4
1771 unsigned short pagesize = sg_get_unaligned_be16(tBuf + 2) + 4;
1772 if ((pagesize < 4) || tBuf[4] || tBuf[5]) {
1773 pout("%s failed, IE page, bad parameter code or length\n",
1774 logSenStr);
1775 return SIMPLE_ERR_BAD_PARAM;
1776 }
1777 if (tBuf[7] > 1) {
1778 sense_info.asc = tBuf[8];
1779 sense_info.ascq = tBuf[9];
1780 if (! hasTempLogPage) {
1781 if (tBuf[7] > 2)
1782 *currenttemp = tBuf[10];
1783 if (tBuf[7] > 3) /* IBM extension in SMART (IE) lpage */
1784 *triptemp = tBuf[11];
1785 }
1786 }
1787 }
1788 if (0 == sense_info.asc) {
1789 /* ties in with MRIE field of 6 in IEC mode page (0x1c) */
1790 if ((err = scsiRequestSense(device, &sense_info))) {
1791 pout("Request Sense failed, [%s]\n", scsiErrString(err));
1792 return err;
1793 }
1794 }
1795 *asc = sense_info.asc;
1796 *ascq = sense_info.ascq;
1797 if (hasTempLogPage) {
1798 if (0 == scsiGetTemp(device, &currTemp, &trTemp)) {
1799 *currenttemp = currTemp;
1800 *triptemp = trTemp;
1801 }
1802 }
1803 return 0;
1804}
1805
1806// The first character (W, C, I) tells the severity
1807static const char * TapeAlertsMessageTable[]= {
1808 " ",
1809 /* 0x01 */
1810 "W: The tape drive is having problems reading data. No data has been "
1811 "lost,\n"
1812 " but there has been a reduction in the performance of the tape.",
1813 /* 0x02 */
1814 "W: The tape drive is having problems writing data. No data has been "
1815 "lost,\n"
1816 " but there has been a reduction in the capacity of the tape.",
1817 /* 0x03 */
1818 "W: The operation has stopped because an error has occurred while "
1819 "reading\n"
1820 " or writing data that the drive cannot correct.",
1821 /* 0x04 */
1822 "C: Your data is at risk:\n"
1823 " 1. Copy any data you require from this tape. \n"
1824 " 2. Do not use this tape again.\n"
1825 " 3. Restart the operation with a different tape.",
1826 /* 0x05 */
1827 "C: The tape is damaged or the drive is faulty. Call the tape drive\n"
1828 " supplier helpline.",
1829 /* 0x06 */
1830 "C: The tape is from a faulty batch or the tape drive is faulty:\n"
1831 " 1. Use a good tape to test the drive.\n"
1832 " 2. If problem persists, call the tape drive supplier helpline.",
1833 /* 0x07 */
1834 "W: The tape cartridge has reached the end of its calculated useful "
1835 "life:\n"
1836 " 1. Copy data you need to another tape.\n"
1837 " 2. Discard the old tape.",
1838 /* 0x08 */
1839 "W: The tape cartridge is not data-grade. Any data you back up to the "
1840 "tape\n"
1841 " is at risk. Replace the cartridge with a data-grade tape.",
1842 /* 0x09 */
1843 "C: You are trying to write to a write-protected cartridge. Remove the\n"
1844 " write-protection or use another tape.",
1845 /* 0x0a */
1846 "I: You cannot eject the cartridge because the tape drive is in use. "
1847 "Wait\n"
1848 " until the operation is complete before ejecting the cartridge.",
1849 /* 0x0b */
1850 "I: The tape in the drive is a cleaning cartridge.",
1851 /* 0x0c */
1852 "I: You have tried to load a cartridge of a type which is not supported\n"
1853 " by this drive.",
1854 /* 0x0d */
1855 "C: The operation has failed because the tape in the drive has "
1856 "experienced\n"
1857 " a mechanical failure:\n"
1858 " 1. Discard the old tape.\n"
1859 " 2. Restart the operation with a different tape.",
1860 /* 0x0e */
1861 "C: The operation has failed because the tape in the drive has "
1862 "experienced\n"
1863 " a mechanical failure:\n"
1864 " 1. Do not attempt to extract the tape cartridge\n"
1865 " 2. Call the tape drive supplier helpline.",
1866 /* 0x0f */
1867 "W: The memory in the tape cartridge has failed, which reduces\n"
1868 " performance. Do not use the cartridge for further write "
1869 "operations.",
1870 /* 0x10 */
1871 "C: The operation has failed because the tape cartridge was manually\n"
1872 " de-mounted while the tape drive was actively writing or reading.",
1873 /* 0x11 */
1874 "W: You have loaded a cartridge of a type that is read-only in this "
1875 "drive.\n"
1876 " The cartridge will appear as write-protected.",
1877 /* 0x12 */
1878 "W: The tape directory on the tape cartridge has been corrupted. File\n"
1879 " search performance will be degraded. The tape directory can be "
1880 "rebuilt\n"
1881 " by reading all the data on the cartridge.",
1882 /* 0x13 */
1883 "I: The tape cartridge is nearing the end of its calculated life. It is\n"
1884 " recommended that you:\n"
1885 " 1. Use another tape cartridge for your next backup.\n"
1886 " 2. Store this tape in a safe place in case you need to restore "
1887 " data from it.",
1888 /* 0x14 */
1889 "C: The tape drive needs cleaning:\n"
1890 " 1. If the operation has stopped, eject the tape and clean the "
1891 "drive.\n"
1892 " 2. If the operation has not stopped, wait for it to finish and "
1893 "then\n"
1894 " clean the drive.\n"
1895 " Check the tape drive users manual for device specific cleaning "
1896 "instructions.",
1897 /* 0x15 */
1898 "W: The tape drive is due for routine cleaning:\n"
1899 " 1. Wait for the current operation to finish.\n"
1900 " 2. The use a cleaning cartridge.\n"
1901 " Check the tape drive users manual for device specific cleaning "
1902 "instructions.",
1903 /* 0x16 */
1904 "C: The last cleaning cartridge used in the tape drive has worn out:\n"
1905 " 1. Discard the worn out cleaning cartridge.\n"
1906 " 2. Wait for the current operation to finish.\n"
1907 " 3. Then use a new cleaning cartridge.",
1908 /* 0x17 */
1909 "C: The last cleaning cartridge used in the tape drive was an invalid\n"
1910 " type:\n"
1911 " 1. Do not use this cleaning cartridge in this drive.\n"
1912 " 2. Wait for the current operation to finish.\n"
1913 " 3. Then use a new cleaning cartridge.",
1914 /* 0x18 */
1915 "W: The tape drive has requested a retention operation",
1916 /* 0x19 */
1917 "W: A redundant interface port on the tape drive has failed",
1918 /* 0x1a */
1919 "W: A tape drive cooling fan has failed",
1920 /* 0x1b */
1921 "W: A redundant power supply has failed inside the tape drive enclosure.\n"
1922 " Check the enclosure users manual for instructions on replacing "
1923 "the\n"
1924 " failed power supply.",
1925 /* 0x1c */
1926 "W: The tape drive power consumption is outside the specified range.",
1927 /* 0x1d */
1928 "W: Preventive maintenance of the tape drive is required. Check the tape\n"
1929 " drive users manual for device specific preventive maintenance\n"
1930 " tasks or call the tape drive supplier helpline.",
1931 /* 0x1e */
1932 "C: The tape drive has a hardware fault:\n"
1933 " 1. Eject the tape or magazine.\n"
1934 " 2. Reset the drive.\n"
1935 " 3. Restart the operation.",
1936 /* 0x1f */
1937 "C: The tape drive has a hardware fault:\n"
1938 " 1. Turn the tape drive off and then on again.\n"
1939 " 2. Restart the operation.\n"
1940 " 3. If the problem persists, call the tape drive supplier helpline.",
1941 /* 0x20 */
1942 "W: The tape drive has a problem with the application client interface:\n"
1943 " 1. Check the cables and cable connections.\n"
1944 " 2. Restart the operation.",
1945 /* 0x21 */
1946 "C: The operation has failed:\n"
1947 " 1. Eject the tape or magazine.\n"
1948 " 2. Insert the tape or magazine again.\n"
1949 " 3. Restart the operation.",
1950 /* 0x22 */
1951 "W: The firmware download has failed because you have tried to use the\n"
1952 " incorrect firmware for this tape drive. Obtain the correct\n"
1953 " firmware and try again.",
1954 /* 0x23 */
1955 "W: Environmental conditions inside the tape drive are outside the\n"
1956 " specified humidity range.",
1957 /* 0x24 */
1958 "W: Environmental conditions inside the tape drive are outside the\n"
1959 " specified temperature range.",
1960 /* 0x25 */
1961 "W: The voltage supply to the tape drive is outside the specified range.",
1962 /* 0x26 */
1963 "C: A hardware failure of the tape drive is predicted. Call the tape\n"
1964 " drive supplier helpline.",
1965 /* 0x27 */
1966 "W: The tape drive may have a hardware fault. Run extended diagnostics to\n"
1967 " verify and diagnose the problem. Check the tape drive users manual "
1968 "for\n"
1969 " device specific instructions on running extended diagnostic tests.",
1970 /* 0x28 */
1971 "C: The changer mechanism is having difficulty communicating with the "
1972 "tape\n"
1973 " drive:\n"
1974 " 1. Turn the autoloader off then on.\n"
1975 " 2. Restart the operation.\n"
1976 " 3. If problem persists, call the tape drive supplier helpline.",
1977 /* 0x29 */
1978 "C: A tape has been left in the autoloader by a previous hardware fault:\n"
1979 " 1. Insert an empty magazine to clear the fault.\n"
1980 " 2. If the fault does not clear, turn the autoloader off and then\n"
1981 " on again.\n"
1982 " 3. If the problem persists, call the tape drive supplier helpline.",
1983 /* 0x2a */
1984 "W: There is a problem with the autoloader mechanism.",
1985 /* 0x2b */
1986 "C: The operation has failed because the autoloader door is open:\n"
1987 " 1. Clear any obstructions from the autoloader door.\n"
1988 " 2. Eject the magazine and then insert it again.\n"
1989 " 3. If the fault does not clear, turn the autoloader off and then\n"
1990 " on again.\n"
1991 " 4. If the problem persists, call the tape drive supplier helpline.",
1992 /* 0x2c */
1993 "C: The autoloader has a hardware fault:\n"
1994 " 1. Turn the autoloader off and then on again.\n"
1995 " 2. Restart the operation.\n"
1996 " 3. If the problem persists, call the tape drive supplier helpline.\n"
1997 " Check the autoloader users manual for device specific instructions\n"
1998 " on turning the device power on and off.",
1999 /* 0x2d */
2000 "C: The autoloader cannot operate without the magazine,\n"
2001 " 1. Insert the magazine into the autoloader.\n"
2002 " 2. Restart the operation.",
2003 /* 0x2e */
2004 "W: A hardware failure of the changer mechanism is predicted. Call the\n"
2005 " tape drive supplier helpline.",
2006 /* 0x2f */
2007 "I: Reserved.",
2008 /* 0x30 */
2009 "I: Reserved.",
2010 /* 0x31 */
2011 "I: Reserved.",
2012 /* 0x32 */
2013 "W: Media statistics have been lost at some time in the past",
2014 /* 0x33 */
2015 "W: The tape directory on the tape cartridge just unloaded has been\n"
2016 " corrupted. File search performance will be degraded. The tape\n"
2017 " directory can be rebuilt by reading all the data.",
2018 /* 0x34 */
2019 "C: The tape just unloaded could not write its system area successfully:\n"
2020 " 1. Copy data to another tape cartridge.\n"
2021 " 2. Discard the old cartridge.",
2022 /* 0x35 */
2023 "C: The tape system are could not be read successfully at load time:\n"
2024 " 1. Copy data to another tape cartridge.\n",
2025 /* 0x36 */
2026 "C: The start or data could not be found on the tape:\n"
2027 " 1. Check you are using the correct format tape.\n"
2028 " 2. Discard the tape or return the tape to your supplier",
2029 /* 0x37 */
2030 "C: The operation has failed because the media cannot be loaded\n"
2031 " and threaded.\n"
2032 " 1. Remove the cartridge, inspect it as specified in the product\n"
2033 " manual, and retry the operation.\n"
2034 " 2. If the problem persists, call the tape drive supplier help "
2035 "line.",
2036 /* 0x38 */
2037 "C: The operation has failed because the medium cannot be unloaded:\n"
2038 " 1. Do not attempt to extract the tape cartridge.\n"
2039 " 2. Call the tape driver supplier help line.",
2040 /* 0x39 */
2041 "C: The tape drive has a problem with the automation interface:\n"
2042 " 1. Check the power to the automation system.\n"
2043 " 2. Check the cables and cable connections.\n"
2044 " 3. Call the supplier help line if problem persists.",
2045 /* 0x3a */
2046 "W: The tape drive has reset itself due to a detected firmware\n"
2047 " fault. If problem persists, call the supplier help line.",
2048 };
2049
2050const char *
2051scsiTapeAlertsTapeDevice(unsigned short code)
2052{
2053 static const int num = sizeof(TapeAlertsMessageTable) /
2054 sizeof(TapeAlertsMessageTable[0]);
2055
2056 return (code < num) ? TapeAlertsMessageTable[code] : "Unknown Alert";
2057}
2058
2059// The first character (W, C, I) tells the severity
2060static const char * ChangerTapeAlertsMessageTable[]= {
2061 " ",
2062 /* 0x01 */
2063 "C: The library mechanism is having difficulty communicating with the\n"
2064 " drive:\n"
2065 " 1. Turn the library off then on.\n"
2066 " 2. Restart the operation.\n"
2067 " 3. If the problem persists, call the library supplier help line.",
2068 /* 0x02 */
2069 "W: There is a problem with the library mechanism. If problem persists,\n"
2070 " call the library supplier help line.",
2071 /* 0x03 */
2072 "C: The library has a hardware fault:\n"
2073 " 1. Reset the library.\n"
2074 " 2. Restart the operation.\n"
2075 " Check the library users manual for device specific instructions on "
2076 "resetting\n"
2077 " the device.",
2078 /* 0x04 */
2079 "C: The library has a hardware fault:\n"
2080 " 1. Turn the library off then on again.\n"
2081 " 2. Restart the operation.\n"
2082 " 3. If the problem persists, call the library supplier help line.\n"
2083 " Check the library users manual for device specific instructions on "
2084 "turning the\n"
2085 " device power on and off.",
2086 /* 0x05 */
2087 "W: The library mechanism may have a hardware fault.\n"
2088 " Run extended diagnostics to verify and diagnose the problem. "
2089 "Check the library\n"
2090 " users manual for device specific instructions on running extended "
2091 "diagnostic\n"
2092 " tests.",
2093 /* 0x06 */
2094 "C: The library has a problem with the host interface:\n"
2095 " 1. Check the cables and connections.\n"
2096 " 2. Restart the operation.",
2097 /* 0x07 */
2098 "W: A hardware failure of the library is predicted. Call the library\n"
2099 " supplier help line.",
2100 /* 0x08 */
2101 "W: Preventive maintenance of the library is required.\n"
2102 " Check the library users manual for device specific preventative "
2103 "maintenance\n"
2104 " tasks, or call your library supplier help line.",
2105 /* 0x09 */
2106 "C: General environmental conditions inside the library are outside the\n"
2107 " specified humidity range.",
2108 /* 0x0a */
2109 "C: General environmental conditions inside the library are outside the\n"
2110 " specified temperature range.",
2111 /* 0x0b */
2112 "C: The voltage supply to the library is outside the specified range.\n"
2113 " There is a potential problem with the power supply or failure of\n"
2114 " a redundant power supply.",
2115 /* 0x0c */
2116 "C: A cartridge has been left inside the library by a previous hardware\n"
2117 " fault:\n"
2118 " 1. Insert an empty magazine to clear the fault.\n"
2119 " 2. If the fault does not clear, turn the library off and then on "
2120 "again.\n"
2121 " 3. If the problem persists, call the library supplier help line.",
2122 /* 0x0d */
2123 "W: There is a potential problem with the drive ejecting cartridges or\n"
2124 " with the library mechanism picking a cartridge from a slot.\n"
2125 " 1. No action needs to be taken at this time.\n"
2126 " 2. If the problem persists, call the library supplier help line.",
2127 /* 0x0e */
2128 "W: There is a potential problem with the library mechanism placing a\n"
2129 " cartridge into a slot.\n"
2130 " 1. No action needs to be taken at this time.\n"
2131 " 2. If the problem persists, call the library supplier help line.",
2132 /* 0x0f */
2133 "W: There is a potential problem with the drive or the library mechanism\n"
2134 " loading cartridges, or an incompatible cartridge.",
2135 /* 0x10 */
2136 "C: The library has failed because the door is open:\n"
2137 " 1. Clear any obstructions from the library door.\n"
2138 " 2. Close the library door.\n"
2139 " 3. If the problem persists, call the library supplier help line.",
2140 /* 0x11 */
2141 "C: There is a mechanical problem with the library media import/export\n"
2142 " mailslot.",
2143 /* 0x12 */
2144 "C: The library cannot operate without the magazine.\n"
2145 " 1. Insert the magazine into the library.\n"
2146 " 2. Restart the operation.",
2147 /* 0x13 */
2148 "W: Library security has been compromised.",
2149 /* 0x14 */
2150 "I: The library security mode has been changed.\n"
2151 " The library has either been put into secure mode, or the library "
2152 "has exited\n"
2153 " the secure mode.\n"
2154 " This is for information purposes only. No action is required.",
2155 /* 0x15 */
2156 "I: The library has been manually turned offline and is unavailable for "
2157 "use.",
2158 /* 0x16 */
2159 "I: A drive inside the library has been taken offline.\n"
2160 " This is for information purposes only. No action is required.",
2161 /* 0x17 */
2162 "W: There is a potential problem with the bar code label or the scanner\n"
2163 " hardware in the library mechanism.\n"
2164 " 1. No action needs to be taken at this time.\n"
2165 " 2. If the problem persists, call the library supplier help line.",
2166 /* 0x18 */
2167 "C: The library has detected an inconsistency in its inventory.\n"
2168 " 1. Redo the library inventory to correct inconsistency.\n"
2169 " 2. Restart the operation.\n"
2170 " Check the applications users manual or the hardware users manual "
2171 "for\n"
2172 " specific instructions on redoing the library inventory.",
2173 /* 0x19 */
2174 "W: A library operation has been attempted that is invalid at this time.",
2175 /* 0x1a */
2176 "W: A redundant interface port on the library has failed.",
2177 /* 0x1b */
2178 "W: A library cooling fan has failed.",
2179 /* 0x1c */
2180 "W: A redundant power supply has failed inside the library. Check the\n"
2181 " library users manual for instructions on replacing the failed "
2182 "power supply.",
2183 /* 0x1d */
2184 "W: The library power consumption is outside the specified range.",
2185 /* 0x1e */
2186 "C: A failure has occurred in the cartridge pass-through mechanism "
2187 "between\n"
2188 " two library modules.",
2189 /* 0x1f */
2190 "C: A cartridge has been left in the pass-through mechanism from a\n"
2191 " previous hardware fault. Check the library users guide for "
2192 "instructions on\n"
2193 " clearing this fault.",
2194 /* 0x20 */
2195 "I: The library was unable to read the bar code on a cartridge.",
2196};
2197
2198const char *
2200{
2201 static const int num = sizeof(ChangerTapeAlertsMessageTable) /
2203
2204 return (code < num) ? ChangerTapeAlertsMessageTable[code] :
2205 "Unknown Alert";
2206}
2207
2208int
2210{
2211 int res;
2212
2213 res = scsiSendDiagnostic(device, SCSI_DIAG_DEF_SELF_TEST, NULL, 0);
2214 if (res)
2215 pout("Default self test failed [%s]\n", scsiErrString(res));
2216 return res;
2217}
2218
2219int
2221{
2222 int res;
2223
2224 res = scsiSendDiagnostic(device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL, 0);
2225 if (res)
2226 pout("Short offline self test failed [%s]\n", scsiErrString(res));
2227 return res;
2228}
2229
2230int
2232{
2233 int res;
2234
2236 if (res)
2237 pout("Long (extended) offline self test failed [%s]\n",
2238 scsiErrString(res));
2239 return res;
2240}
2241
2242int
2244{
2245 int res;
2246
2247 res = scsiSendDiagnostic(device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL, 0);
2248 if (res)
2249 pout("Short foreground self test failed [%s]\n", scsiErrString(res));
2250 return res;
2251}
2252
2253int
2255{
2256 int res;
2257
2259 if (res)
2260 pout("Long (extended) foreground self test failed [%s]\n",
2261 scsiErrString(res));
2262 return res;
2263}
2264
2265int
2267{
2268 int res;
2269
2270 res = scsiSendDiagnostic(device, SCSI_DIAG_ABORT_SELF_TEST, NULL, 0);
2271 if (res)
2272 pout("Abort self test failed [%s]\n", scsiErrString(res));
2273 return res;
2274}
2275
2276/* Returns 0 and the expected duration of an extended self test (in seconds)
2277 if successful; any other return value indicates a failure. */
2278int
2279scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec,
2280 int modese_len)
2281{
2282 int err, offset;
2283 uint8_t buff[64] = {};
2284
2285 if (modese_len <= 6) {
2286 if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0,
2288 buff, sizeof(buff)))) {
2289 if (SIMPLE_ERR_BAD_OPCODE == err)
2290 modese_len = 10;
2291 else
2292 return err;
2293 } else if (0 == modese_len)
2294 modese_len = 6;
2295 }
2296 if (10 == modese_len) {
2297 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
2299 buff, sizeof(buff));
2300 if (err)
2301 return err;
2302 }
2303 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
2304 if (offset < 0)
2305 return -EINVAL;
2306 if (buff[offset + 1] >= 0xa) {
2307 int res = sg_get_unaligned_be16(buff + offset + 10);
2308
2309 if (res < 0xffff) {
2310 *durationSec = res;
2311 return 0;
2312 }
2313 /* The value 0xffff (all bits set in 16 bit field) indicates that
2314 * the Extended Inquiry VPD page should be consulted, it has a
2315 * similarly named 16 bit field, but the unit is minutes. */
2316 uint8_t b[64];
2317
2319 b, sizeof(b))) &&
2320 ((sg_get_unaligned_be16(b + 2)) > 11)) {
2321 res = sg_get_unaligned_be16(b + 10);
2322 *durationSec = res * 60; /* VPD field is in minutes */
2323 return 0;
2324 } else
2325 return -EINVAL;
2326 } else
2327 return -EINVAL;
2328}
2329
2330void
2331scsiDecodeErrCounterPage(unsigned char * resp, struct scsiErrorCounter *ecp)
2332{
2333 memset(ecp, 0, sizeof(*ecp));
2334 int num = sg_get_unaligned_be16(resp + 2);
2335 unsigned char * ucp = &resp[0] + 4;
2336 while (num > 3) {
2337 int pc = sg_get_unaligned_be16(ucp + 0);
2338 int pl = ucp[3] + 4;
2339 uint64_t * ullp;
2340 switch (pc) {
2341 case 0:
2342 case 1:
2343 case 2:
2344 case 3:
2345 case 4:
2346 case 5:
2347 case 6:
2348 ecp->gotPC[pc] = 1;
2349 ullp = &ecp->counter[pc];
2350 break;
2351 default:
2352 ecp->gotExtraPC = 1;
2353 ullp = &ecp->counter[7];
2354 break;
2355 }
2356 int k = pl - 4;
2357 unsigned char * xp = ucp + 4;
2358 if (k > (int)sizeof(*ullp)) {
2359 xp += (k - sizeof(*ullp));
2360 k = sizeof(*ullp);
2361 }
2362 *ullp = sg_get_unaligned_be(k, xp);
2363 num -= pl;
2364 ucp += pl;
2365 }
2366}
2367
2368void
2369scsiDecodeNonMediumErrPage(unsigned char *resp,
2370 struct scsiNonMediumError *nmep)
2371{
2372 memset(nmep, 0, sizeof(*nmep));
2373 int num = sg_get_unaligned_be16(resp + 2);
2374 unsigned char * ucp = &resp[0] + 4;
2375 static int szof = sizeof(nmep->counterPC0);
2376 while (num > 3) {
2377 int pc = sg_get_unaligned_be16(ucp + 0);
2378 int pl = ucp[3] + 4;
2379 int k;
2380 unsigned char * xp;
2381 switch (pc) {
2382 case 0:
2383 nmep->gotPC0 = 1;
2384 k = pl - 4;
2385 xp = ucp + 4;
2386 if (k > szof) {
2387 xp += (k - szof);
2388 k = szof;
2389 }
2390 nmep->counterPC0 = sg_get_unaligned_be(k, xp + 0);
2391 break;
2392 case 0x8009:
2393 nmep->gotTFE_H = 1;
2394 k = pl - 4;
2395 xp = ucp + 4;
2396 if (k > szof) {
2397 xp += (k - szof);
2398 k = szof;
2399 }
2400 nmep->counterTFE_H = sg_get_unaligned_be(k, xp + 0);
2401 break;
2402 case 0x8015:
2403 nmep->gotPE_H = 1;
2404 k = pl - 4;
2405 xp = ucp + 4;
2406 if (k > szof) {
2407 xp += (k - szof);
2408 k = szof;
2409 }
2410 nmep->counterPE_H = sg_get_unaligned_be(k, xp + 0);
2411 break;
2412 default:
2413 nmep->gotExtraPC = 1;
2414 break;
2415 }
2416 num -= pl;
2417 ucp += pl;
2418 }
2419}
2420
2421/* Counts number of failed self-tests. Also encodes the poweron_hour
2422 of the most recent failed self-test. Return value is negative if
2423 this function has a problem (typically -1), otherwise the bottom 8
2424 bits are the number of failed self tests and the 16 bits above that
2425 are the poweron hour of the most recent failure. Note: aborted self
2426 tests (typically by the user) and self tests in progress are not
2427 considered failures. See Working Draft SCSI Primary Commands - 3
2428 (SPC-3) section 7.2.10 T10/1416-D (rev 22a) */
2429int
2431{
2432 int num, k, err, fails, fail_hour;
2433 uint8_t * ucp;
2434 unsigned char resp[LOG_RESP_SELF_TEST_LEN];
2435
2436 if ((err = scsiLogSense(fd, SELFTEST_RESULTS_LPAGE, 0, resp,
2438 if (noisy)
2439 pout("scsiCountSelfTests Failed [%s]\n", scsiErrString(err));
2440 return -1;
2441 }
2442 if ((resp[0] & 0x3f) != SELFTEST_RESULTS_LPAGE) {
2443 if (noisy)
2444 pout("Self-test %s Failed, page mismatch\n", logSenStr);
2445 return -1;
2446 }
2447 // compute page length
2448 num = sg_get_unaligned_be16(resp + 2);
2449 // Log sense page length 0x190 bytes
2450 if (num != 0x190) {
2451 if (noisy)
2452 pout("Self-test %s length is 0x%x not 0x190 bytes\n", logSenStr,
2453 num);
2454 return -1;
2455 }
2456 fails = 0;
2457 fail_hour = 0;
2458 // loop through the twenty possible entries
2459 for (k = 0, ucp = resp + 4; k < 20; ++k, ucp += 20 ) {
2460
2461 // timestamp in power-on hours (or zero if test in progress)
2462 int n = sg_get_unaligned_be16(ucp + 6);
2463
2464 // The spec says "all 20 bytes will be zero if no test" but
2465 // DG has found otherwise. So this is a heuristic.
2466 if ((0 == n) && (0 == ucp[4]))
2467 break;
2468 int res = ucp[4] & 0xf;
2469 if ((res > 2) && (res < 8)) {
2470 fails++;
2471 if (1 == fails)
2472 fail_hour = sg_get_unaligned_be16(ucp + 6);
2473 }
2474 }
2475 return (fail_hour << 8) + fails;
2476}
2477
2478/* Returns 0 if able to read self test log page; then outputs 1 into
2479 *inProgress if self test still in progress, else outputs 0. */
2480int
2482{
2483 int num;
2484 uint8_t * ucp;
2485 unsigned char resp[LOG_RESP_SELF_TEST_LEN];
2486
2487 if (scsiLogSense(fd, SELFTEST_RESULTS_LPAGE, 0, resp,
2489 return -1;
2490 if (resp[0] != SELFTEST_RESULTS_LPAGE)
2491 return -1;
2492 // compute page length
2493 num = sg_get_unaligned_be16(resp + 2);
2494 // Log sense page length 0x190 bytes
2495 if (num != 0x190) {
2496 return -1;
2497 }
2498 ucp = resp + 4;
2499 if (inProgress)
2500 *inProgress = (0xf == (ucp[4] & 0xf)) ? 1 : 0;
2501 return 0;
2502}
2503
2504/* Returns a negative value if failed to fetch Control mode page or it was
2505 malformed. Returns 0 if GLTSD bit is zero and returns 1 if the GLTSD
2506 bit is set. Examines default mode page when current==0 else examines
2507 current mode page. */
2508int
2510{
2511 int err, offset;
2512 uint8_t buff[64] = {};
2513 int pc = current ? MPAGE_CONTROL_CURRENT : MPAGE_CONTROL_DEFAULT;
2514
2515 if (modese_len <= 6) {
2516 if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0, pc,
2517 buff, sizeof(buff)))) {
2518 if (SIMPLE_ERR_BAD_OPCODE == err)
2519 modese_len = 10;
2520 else
2521 return -EINVAL;
2522 } else if (0 == modese_len)
2523 modese_len = 6;
2524 }
2525 if (10 == modese_len) {
2526 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0, pc,
2527 buff, sizeof(buff));
2528 if (err)
2529 return -EINVAL;
2530 }
2531 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
2532 if ((offset >= 0) && (buff[offset + 1] >= 0xa))
2533 return (buff[offset + 2] & 2) ? 1 : 0;
2534 return -EINVAL;
2535}
2536
2537/* Returns a negative value on error, 0 if unknown and 1 if SSD,
2538 * otherwise the positive returned value is the speed in rpm. First checks
2539 * the Block Device Characteristics VPD page and if that fails it tries the
2540 * RIGID_DISK_DRIVE_GEOMETRY_PAGE mode page.
2541 * In SBC-4 the 2 bit ZONED field in this VPD page is written to *haw_zbcp
2542 * if haw_zbcp is non-NULL. In SBC-5 the ZONED field is now obsolete,
2543 * the Zoned block device characteristics VPD page should be used instead. */
2544
2545int
2546scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp,
2547 int * haw_zbcp)
2548{
2549 int err, offset;
2550 uint8_t buff[64] = {};
2551 int pc = MPAGE_CONTROL_DEFAULT;
2552
2554 buff, sizeof(buff))) &&
2555 ((sg_get_unaligned_be16(buff + 2)) > 2)) {
2556 int speed = sg_get_unaligned_be16(buff + 4);
2557 if (form_factorp)
2558 *form_factorp = buff[7] & 0xf;
2559 if (haw_zbcp)
2560 *haw_zbcp = (buff[8] >> 4) & 0x3;
2561 return speed;
2562 }
2563 if (form_factorp)
2564 *form_factorp = 0;
2565 if (haw_zbcp)
2566 *haw_zbcp = 0;
2567 if (modese_len <= 6) {
2568 if ((err = scsiModeSense(device, RIGID_DISK_DRIVE_GEOMETRY_PAGE, 0, pc,
2569 buff, sizeof(buff)))) {
2570 if (SIMPLE_ERR_BAD_OPCODE == err)
2571 modese_len = 10;
2572 else
2573 return -EINVAL;
2574 } else if (0 == modese_len)
2575 modese_len = 6;
2576 }
2577 if (10 == modese_len) {
2579 buff, sizeof(buff));
2580 if (err)
2581 return -EINVAL;
2582 }
2583 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
2584 return sg_get_unaligned_be16(buff + offset + 20);
2585}
2586
2587/* Returns a non-zero value in case of error, wcep/rcdp == -1 - get value,
2588 0 - clear bit, 1 - set bit */
2589
2590int
2591scsiGetSetCache(scsi_device * device, int modese_len, short int * wcep,
2592 short int * rcdp)
2593{
2594 int err, offset, resp_len, sp;
2595 uint8_t buff[64] = {};
2596 uint8_t ch_buff[64];
2597 short set_wce = *wcep;
2598 short set_rcd = *rcdp;
2599
2600 if (modese_len <= 6) {
2602 buff, sizeof(buff));
2603 if (err) {
2604 if (SIMPLE_ERR_BAD_OPCODE == err)
2605 modese_len = 10;
2606 else {
2607 device->set_err(EINVAL, "SCSI MODE SENSE failed");
2608 return -EINVAL;
2609 }
2610 } else if (0 == modese_len)
2611 modese_len = 6;
2612 }
2613
2614 if (10 == modese_len) {
2616 buff, sizeof(buff));
2617 if (err) {
2618 device->set_err(EINVAL, "SCSI MODE SENSE failed");
2619 return -EINVAL;
2620 }
2621 }
2622 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
2623 if ((offset < 0) || (buff[offset + 1] < 0xa)) {
2624 device->set_err(EINVAL, "Bad response");
2625 return SIMPLE_ERR_BAD_RESP;
2626 }
2627
2628 *wcep = ((buff[offset + 2] & 0x04) != 0);
2629 *rcdp = ((buff[offset + 2] & 0x01) != 0);
2630
2631 if((*wcep == set_wce || set_wce == -1)
2632 && ((*rcdp == set_rcd) || set_rcd == -1))
2633 return 0; // no changes needed or nothing to set
2634
2635 if (modese_len == 6)
2636 err = scsiModeSense(device, CACHING_PAGE, 0,
2638 ch_buff, sizeof(ch_buff));
2639 else
2640 err = scsiModeSense10(device, CACHING_PAGE, 0,
2642 ch_buff, sizeof(ch_buff));
2643 if (err) {
2644 device->set_err(EINVAL, "WCE/RCD bits not changeable");
2645 return err;
2646 }
2647
2648 // set WCE bit
2649 if(set_wce >= 0 && *wcep != set_wce) {
2650 if (0 == (ch_buff[offset + 2] & 0x04)) {
2651 device->set_err(EINVAL, "WCE bit not changeable");
2652 return 1;
2653 }
2654 if(set_wce)
2655 buff[offset + 2] |= 0x04; // set bit
2656 else
2657 buff[offset + 2] &= 0xfb; // clear bit
2658 }
2659 // set RCD bit
2660 if(set_rcd >= 0 && *rcdp != set_rcd) {
2661 if (0 == (ch_buff[offset + 2] & 0x01)) {
2662 device->set_err(EINVAL, "RCD bit not changeable");
2663 return 1;
2664 }
2665 if(set_rcd)
2666 buff[offset + 2] |= 0x01; // set bit
2667 else
2668 buff[offset + 2] &= 0xfe; // clear bit
2669 }
2670
2671 /* mask out DPOFUA device specific (disk) parameter bit */
2672 if (10 == modese_len) {
2673 resp_len = sg_get_unaligned_be16(buff + 0) + 2;
2674 buff[3] &= 0xef;
2675 } else {
2676 resp_len = buff[0] + 1;
2677 buff[2] &= 0xef;
2678 }
2679 sp = 0; /* Do not change saved values */
2680 if (10 == modese_len)
2681 err = scsiModeSelect10(device, sp, buff, resp_len);
2682 else if (6 == modese_len)
2683 err = scsiModeSelect(device, sp, buff, resp_len);
2684 if(err)
2685 device->set_err(EINVAL, "MODE SELECT command failed");
2686 return err;
2687}
2688
2689
2690/* Attempts to set or clear GLTSD bit in Control mode page. If enabled is
2691 0 attempts to clear GLTSD otherwise it attempts to set it. Returns 0 if
2692 successful, negative if low level error, > 0 if higher level error (e.g.
2693 SIMPLE_ERR_BAD_PARAM if GLTSD bit is not changeable). */
2694int
2695scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len)
2696{
2697 int err, offset, resp_len, sp;
2698 uint8_t buff[64] = {};
2699 uint8_t ch_buff[64];
2700
2701 if (modese_len <= 6) {
2702 if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0,
2704 buff, sizeof(buff)))) {
2705 if (SIMPLE_ERR_BAD_OPCODE == err)
2706 modese_len = 10;
2707 else
2708 return err;
2709 } else if (0 == modese_len)
2710 modese_len = 6;
2711 }
2712 if (10 == modese_len) {
2713 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
2715 buff, sizeof(buff));
2716 if (err)
2717 return err;
2718 }
2719 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
2720 if ((offset < 0) || (buff[offset + 1] < 0xa))
2721 return SIMPLE_ERR_BAD_RESP;
2722
2723 if (enabled)
2724 enabled = 2;
2725 if (enabled == (buff[offset + 2] & 2))
2726 return 0; /* GLTSD already in wanted state so nothing to do */
2727
2728 if (modese_len == 6)
2729 err = scsiModeSense(device, CONTROL_MODE_PAGE, 0,
2731 ch_buff, sizeof(ch_buff));
2732 else
2733 err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
2735 ch_buff, sizeof(ch_buff));
2736 if (err)
2737 return err;
2738 if (0 == (ch_buff[offset + 2] & 2))
2739 return SIMPLE_ERR_BAD_PARAM; /* GLTSD bit not changeable */
2740
2741 /* mask out DPOFUA device specific (disk) parameter bit */
2742 if (10 == modese_len) {
2743 resp_len = sg_get_unaligned_be16(buff + 0) + 2;
2744 buff[3] &= 0xef;
2745 } else {
2746 resp_len = buff[0] + 1;
2747 buff[2] &= 0xef;
2748 }
2749 sp = (buff[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */
2750 if (enabled)
2751 buff[offset + 2] |= 0x2; /* set GLTSD bit */
2752 else
2753 buff[offset + 2] &= 0xfd; /* clear GLTSD bit */
2754 if (10 == modese_len)
2755 err = scsiModeSelect10(device, sp, buff, resp_len);
2756 else if (6 == modese_len)
2757 err = scsiModeSelect(device, sp, buff, resp_len);
2758 return err;
2759}
2760
2761/* Returns a negative value if failed to fetch Protocol specific port mode
2762 page or it was malformed. Returns transport protocol identifier when
2763 value >= 0 . */
2764int
2766{
2767 int err, offset;
2768 uint8_t buff[64] {};
2769
2770 if (modese_len <= 6) {
2771 if ((err = scsiModeSense(device, PROTOCOL_SPECIFIC_PORT_PAGE, 0,
2773 buff, sizeof(buff)))) {
2774 if (SIMPLE_ERR_BAD_OPCODE == err)
2775 modese_len = 10;
2776 else
2777 return -EINVAL;
2778 } else if (0 == modese_len)
2779 modese_len = 6;
2780 }
2781 if (10 == modese_len) {
2784 buff, sizeof(buff));
2785 if (err)
2786 return -EINVAL;
2787 }
2788 offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
2789 if ((offset >= 0) && (buff[offset + 1] > 1)) {
2790 if ((0 == (buff[offset] & 0x40)) && /* SPF==0 */
2791 (PROTOCOL_SPECIFIC_PORT_PAGE == (buff[offset] & 0x3f)))
2792 return (buff[offset + 2] & 0xf);
2793 }
2794 return -EINVAL;
2795}
2796
2797const unsigned char *
2798sg_scsi_sense_desc_find(const unsigned char * sensep, int sense_len,
2799 int desc_type)
2800{
2801 int add_sen_len;
2802 const unsigned char * descp;
2803
2804 if ((sense_len < 8) || (0 == (add_sen_len = sensep[7])))
2805 return NULL;
2806 if ((sensep[0] < 0x72) || (sensep[0] > 0x73))
2807 return NULL;
2808 add_sen_len = (add_sen_len < (sense_len - 8)) ?
2809 add_sen_len : (sense_len - 8);
2810 descp = &sensep[8];
2811 for (int desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
2812 descp += desc_len;
2813 int add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
2814 desc_len = add_len + 2;
2815 if (descp[0] == desc_type)
2816 return descp;
2817 if (add_len < 0) /* short descriptor ?? */
2818 break;
2819 }
2820 return NULL;
2821}
2822
2823// Convenience function for formatting strings from SCSI identify
2824void
2825scsi_format_id_string(char * out, const uint8_t * in, int n)
2826{
2827 char tmp[65];
2828 n = n > 64 ? 64 : n;
2829 strncpy(tmp, (const char *)in, n);
2830 tmp[n] = '\0';
2831
2832 // Find the first non-space character (maybe none).
2833 int first = -1;
2834 int i;
2835 for (i = 0; tmp[i]; i++)
2836 if (!isspace((int)tmp[i])) {
2837 first = i;
2838 break;
2839 }
2840
2841 if (first == -1) {
2842 // There are only space characters.
2843 out[0] = '\0';
2844 return;
2845 }
2846
2847 // Find the last non-space character.
2848 for (i = strlen(tmp)-1; i >= first && isspace((int)tmp[i]); i--);
2849 int last = i;
2850
2851 strncpy(out, tmp+first, last-first+1);
2852 out[last-first+1] = '\0';
2853}
2854
2855static const char * wn = "Warning";
2856
2857static const char * wn1_9[] = {
2858 "specified temperature exceeded",
2859 "enclosure degraded",
2860 "background self-test failed",
2861 "background pre-scan detected medium error",
2862 "background medium scan detected medium error",
2863 "non-volatile cache now volatile",
2864 "degraded power to non-volatile cache",
2865 "power loss expected",
2866 "device statistics notification active",
2867};
2868
2869static const char * five_d_t[] = {
2870 "Hardware",
2871 "Controller",
2872 "Data channel",
2873 "Servo",
2874 "Spindle",
2875 "Firmware",
2876};
2877
2878static const char * impfail = "impending failure";
2879
2880static const char * impending0_c[] = {
2881 "general hard drive failure",
2882 "drive error rate too high",
2883 "data error rate too high",
2884 "seek error rate too high",
2885 "too many block reassigns",
2886 "access times too high",
2887 "start unit times too high",
2888 "channel parametrics",
2889 "controller detected",
2890 "throughput performance",
2891 "seek time performance",
2892 "spin-up retry count",
2893 "drive calibration retry count",
2894};
2895
2896static const char * pred = "prediction threshold exceeded";
2897
2898/* The SCSI Informational Exceptions log page and various other mechanisms
2899 * yield an additional sense code (and its qualifier) [asc and ascq] when
2900 * triggered. It seems only two asc values are involved: 0xb and 0xd.
2901 * If asc,ascq strings are known (in spc6r06.pdf) for asc 0xb and 0x5d
2902 * then a pointer to that string is returned, else NULL is returned. The
2903 * caller provides a buffer (b) and its length (blen) that a string (if
2904 * found) is placed in. So if a match is found b is returned. */
2905char *
2906scsiGetIEString(uint8_t asc, uint8_t ascq, char * b, int blen)
2907{
2908 if (asc == 0xb) {
2909 switch (ascq) {
2910 case 0:
2911 snprintf(b, blen, "%s", wn);
2912 return b;
2913 case 0x1:
2914 case 0x2:
2915 case 0x3:
2916 case 0x4:
2917 case 0x5:
2918 case 0x6:
2919 case 0x7:
2920 case 0x8:
2921 case 0x9:
2922 snprintf(b, blen, "%s - %s", wn, wn1_9[ascq - 1]);
2923 return b;
2924 case 0x12:
2925 snprintf(b, blen, "%s - microcode security at risk", wn);
2926 return b;
2927 case 0x13:
2928 snprintf(b, blen, "%s - microcode digital signature validation "
2929 "failure", wn);
2930 return b;
2931 case 0x14:
2932 snprintf(b, blen, "%s - physical element status change", wn);
2933 return b;
2934 default:
2935 if ((ascq >= 0xa) && (ascq <= 0x11)) {
2936 uint8_t q = ascq - 0xa;
2937
2938 snprintf(b, blen, "%s - %s %s %s limit exceeded", wn,
2939 (((q % 2) == 0) ? "high" : "low"),
2940 ((((q / 2) % 2) == 0) ? "critical" : "operating"),
2941 ((((q / 4) % 2) == 0) ? "temperature" : "humidity"));
2942 return b;
2943 } else
2944 return NULL;
2945 }
2946 } else if (asc == 0x5d) {
2947 switch (ascq) {
2948 case 0:
2949 snprintf(b, blen, "Failure %s", pred);
2950 return b;
2951 case 1:
2952 snprintf(b, blen, "Media failure %s", pred);
2953 return b;
2954 case 2:
2955 snprintf(b, blen, "Logical unit failure %s", pred);
2956 return b;
2957 case 3:
2958 snprintf(b, blen, "spare area exhaustion failure %s", pred);
2959 return b;
2960 case 0x1d:
2961 snprintf(b, blen, "%s %s power loss protection circuit area "
2962 "exhaustion failure", five_d_t[0], impfail);
2963 return b;
2964 case 0x73:
2965 snprintf(b, blen, "Media %s endurance limit met", impfail);
2966 return b;
2967 case 0xff:
2968 snprintf(b, blen, "Failure %s (false)", pred);
2969 return b;
2970 default:
2971 if ((ascq >= 0x10) && (ascq <= 0x6c)) {
2972 uint8_t q = ascq - 0x10;
2973 uint8_t rem = q % 0x10;
2974
2975 if (rem <= 0xc) {
2976 snprintf(b, blen, "%s %s %s", five_d_t[q / 0x10], impfail,
2977 impending0_c[rem]);
2978 return b;
2979 } else
2980 return NULL;
2981 } else
2982 return NULL;
2983 }
2984 } else
2985 return NULL;
2986}
SCSI device access.
bool is_spc4_or_higher() const
void set_rcap16_first()
Always try READ CAPACITY(10) (rcap10) first but once we know rcap16 is needed, use it instead.
virtual bool scsi_pass_through(scsi_cmnd_io *iop)=0
SCSI pass through.
void set_spc4_or_higher()
int get_errno() const
Get last error number.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
bool is_supported(int vpd_page_num) const
Definition: scsicmds.cpp:65
unsigned char pages[256]
Definition: scsicmds.h:393
supported_vpd_pages(scsi_device *device)
Definition: scsicmds.cpp:50
u8 sense_len
Definition: megaraid.h:2
uint8_t opcode
Definition: megaraid.h:0
u8 cdb[16]
Definition: megaraid.h:21
u8 b[12]
Definition: megaraid.h:17
u16 s[6]
Definition: megaraid.h:18
int scsiSetPowerCondition(scsi_device *device, int power_cond, int pcond_modifier)
Definition: scsicmds.cpp:1121
int scsiReadDefect12(scsi_device *device, int req_plist, int req_glist, int dl_format, int addrDescIndex, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:1266
int scsiFetchExtendedSelfTestTime(scsi_device *device, int *durationSec, int modese_len)
Definition: scsicmds.cpp:2279
int scsiModeSelect(scsi_device *device, int sp, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:800
int scsiSimpleSenseFilter(const struct scsi_sense_disect *sinfo)
Definition: scsicmds.cpp:347
#define SCSI_IEC_MP_BYTE2_ENABLED
Definition: scsicmds.cpp:1637
int scsiSetExceptionControlAndWarning(scsi_device *device, int enabled, const struct scsi_iec_mode_page *iecp)
Definition: scsicmds.cpp:1652
static struct scsi_sa_var_map sa_var_a[]
Definition: scsicmds.cpp:211
int scsiSmartExtendCapSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2254
static const char * TapeAlertsMessageTable[]
Definition: scsicmds.cpp:1807
void scsiDecodeErrCounterPage(unsigned char *resp, struct scsiErrorCounter *ecp)
Definition: scsicmds.cpp:2331
int scsiFetchIECmpage(scsi_device *device, struct scsi_iec_mode_page *iecp, int modese_len)
Definition: scsicmds.cpp:1562
int scsiGetTemp(scsi_device *device, uint8_t *currenttemp, uint8_t *triptemp)
Definition: scsicmds.cpp:1722
static const char * pred
Definition: scsicmds.cpp:2896
int scsiSmartShortCapSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2243
int scsiSmartSelfTestAbort(scsi_device *device)
Definition: scsicmds.cpp:2266
char * scsi_get_sense_key_str(int sense_key, int buff_len, char *buff)
Definition: scsicmds.cpp:455
static const char * ChangerTapeAlertsMessageTable[]
Definition: scsicmds.cpp:2060
static const char * wn
Definition: scsicmds.cpp:2855
static const char * impfail
Definition: scsicmds.cpp:2878
const char * scsiTapeAlertsTapeDevice(unsigned short code)
Definition: scsicmds.cpp:2051
int scsiFetchTransportProtocol(scsi_device *device, int modese_len)
Definition: scsicmds.cpp:2765
int scsi_decode_lu_dev_id(const unsigned char *b, int blen, char *s, int slen, int *transport)
Definition: scsicmds.cpp:507
bool is_scsi_cdb(const uint8_t *cdbp, int clen)
Definition: scsicmds.cpp:151
static const char * wn1_9[]
Definition: scsicmds.cpp:2857
int scsiTestUnitReady(scsi_device *device)
Definition: scsicmds.cpp:1216
int scsiModeSense10(scsi_device *device, int pagenum, int subpagenum, int pc, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:839
int scsiModePageOffset(const uint8_t *resp, int len, int modese_len)
Definition: scsicmds.cpp:1519
void scsi_do_sense_disect(const struct scsi_cmnd_io *io_buf, struct scsi_sense_disect *out)
Definition: scsicmds.cpp:325
int scsiInquiryVpd(scsi_device *device, int vpd_page, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:970
#define SCSI_IEC_MP_REPORT_COUNT
Definition: scsicmds.cpp:1642
int scsiSmartExtendSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2231
int scsiRequestSense(scsi_device *device, struct scsi_sense_disect *sense_info)
Definition: scsicmds.cpp:1028
int scsiCheckIE(scsi_device *device, int hasIELogPage, int hasTempLogPage, uint8_t *asc, uint8_t *ascq, uint8_t *currenttemp, uint8_t *triptemp)
Definition: scsicmds.cpp:1750
const char * scsicmds_c_cvsid
Definition: scsicmds.cpp:39
uint64_t scsiGetSize(scsi_device *device, bool avoid_rcap16, struct scsi_readcap_resp *srrp)
Definition: scsicmds.cpp:1441
int scsiSelfTestInProgress(scsi_device *fd, int *inProgress)
Definition: scsicmds.cpp:2481
static const char * sense_key_desc[]
Definition: scsicmds.cpp:428
#define DEXCPT_ENABLE
Definition: scsicmds.cpp:1550
char * scsiGetIEString(uint8_t asc, uint8_t ascq, char *b, int blen)
Definition: scsicmds.cpp:2906
static const char * vendor_specific
Definition: scsicmds.cpp:266
int scsiGetSetCache(scsi_device *device, int modese_len, short int *wcep, short int *rcdp)
Definition: scsicmds.cpp:2591
#define SCSI_IEC_MP_INTERVAL_T
Definition: scsicmds.cpp:1641
supported_vpd_pages * supported_vpd_pages_p
Definition: scsicmds.cpp:47
bool scsi_pass_through_yield_sense(scsi_device *device, scsi_cmnd_io *iop, scsi_sense_disect &sinfo)
Definition: scsicmds.cpp:1303
int scsiGetRPM(scsi_device *device, int modese_len, int *form_factorp, int *haw_zbcp)
Definition: scsicmds.cpp:2546
void scsi_format_id_string(char *out, const uint8_t *in, int n)
Definition: scsicmds.cpp:2825
#define EWASC_ENABLE
Definition: scsicmds.cpp:1551
int scsiReadCapacity16(scsi_device *device, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:1378
int scsiStdInquiry(scsi_device *device, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:923
#define SCSI_IEC_MP_MRIE
Definition: scsicmds.cpp:1640
scsi_sa_t
Definition: scsicmds.cpp:200
@ scsi_sa_b8b7n16
Definition: scsicmds.cpp:203
@ scsi_sa_b1b4n5
Definition: scsicmds.cpp:202
@ scsi_sa_none
Definition: scsicmds.cpp:201
int scsiModeSelect10(scsi_device *device, int sp, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:883
const unsigned char * sg_scsi_sense_desc_find(const unsigned char *sensep, int sense_len, int desc_type)
Definition: scsicmds.cpp:2798
static const char * logSenStr
Definition: scsicmds.cpp:42
#define SCSI_IEC_MP_BYTE2_TEST_MASK
Definition: scsicmds.cpp:1638
void scsiDecodeNonMediumErrPage(unsigned char *resp, struct scsiNonMediumError *nmep)
Definition: scsicmds.cpp:2369
int scsiSmartDefaultSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2209
static int _testunitready(scsi_device *device, struct scsi_sense_disect *sinfop)
Definition: scsicmds.cpp:1185
void dStrHex(const uint8_t *up, int len, int no_ascii)
Definition: scsicmds.cpp:78
int scsiSendDiagnostic(scsi_device *device, int functioncode, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:1152
const char * scsiErrString(int scsiErr)
Definition: scsicmds.cpp:390
const char * scsiTapeAlertsChangerDevice(unsigned short code)
Definition: scsicmds.cpp:2199
int scsiReadCapacity10(scsi_device *device, unsigned int *last_lbap, unsigned int *lb_sizep)
Definition: scsicmds.cpp:1342
int scsiFetchControlGLTSD(scsi_device *device, int modese_len, int current)
Definition: scsicmds.cpp:2509
int scsiRSOCcmd(scsi_device *device, uint8_t *pBuf, int bufLen, int &rspLen)
Definition: scsicmds.cpp:1405
static struct scsi_opcode_name opcode_name_arr[]
Definition: scsicmds.cpp:238
int scsiModeSense(scsi_device *device, int pagenum, int subpagenum, int pc, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:754
int scsiCountFailedSelfTests(scsi_device *fd, int noisy)
Definition: scsicmds.cpp:2430
int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
Definition: scsicmds.cpp:1623
int scsiSetControlGLTSD(scsi_device *device, int enabled, int modese_len)
Definition: scsicmds.cpp:2695
int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
Definition: scsicmds.cpp:1609
#define TEST_DISABLE
Definition: scsicmds.cpp:1554
int scsiSmartShortSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2220
int scsiLogSense(scsi_device *device, int pagenum, int subpagenum, uint8_t *pBuf, int bufLen, int known_resp_len)
Definition: scsicmds.cpp:633
unsigned char scsi_debugmode
Definition: scsicmds.cpp:45
#define EWASC_DISABLE
Definition: scsicmds.cpp:1553
const char * scsi_get_opcode_name(const uint8_t *cdbp)
Definition: scsicmds.cpp:271
int scsiLogSelect(scsi_device *device, int pcr, int sp, int pc, int pagenum, int subpagenum, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:722
static const char * five_d_t[]
Definition: scsicmds.cpp:2869
int scsiReadDefect10(scsi_device *device, int req_plist, int req_glist, int dl_format, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:1232
static const char * impending0_c[]
Definition: scsicmds.cpp:2880
int scsi_vpd_dev_id_iter(const unsigned char *initial_desig_desc, int page_len, int *off, int m_assoc, int m_desig_type, int m_code_set)
Definition: scsicmds.cpp:478
#define REPORT_LUNS
Definition: scsicmds.h:76
#define SIMPLE_ERR_BECOMING_READY
Definition: scsicmds.h:347
#define SCSI_SK_MEDIUM_ERROR
Definition: scsicmds.h:319
#define SIMPLE_ERR_MEDIUM_HARDWARE
Definition: scsicmds.h:349
#define START_STOP_UNIT
Definition: scsicmds.h:73
#define MPAGE_CONTROL_CURRENT
Definition: scsicmds.h:294
#define SAI_READ_CAPACITY_16
Definition: scsicmds.h:85
#define SCSI_ASC_UNKNOWN_OPCODE
Definition: scsicmds.h:331
#define MODE_SENSE_6
Definition: scsicmds.h:43
#define SIMPLE_ERR_BAD_FIELD
Definition: scsicmds.h:343
#define SAI_GET_PHY_ELEM_STATUS
Definition: scsicmds.h:88
#define INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE
Definition: scsicmds.h:285
#define READ_CAPACITY_10
Definition: scsicmds.h:79
#define MAINTENANCE_IN_12
Definition: scsicmds.h:91
#define SCSI_DIAG_DEF_SELF_TEST
Definition: scsicmds.h:358
#define SCSI_SK_UNIT_ATTENTION
Definition: scsicmds.h:322
#define MI_REP_SUP_OPCODES
Definition: scsicmds.h:94
#define SAT_ATA_PASSTHROUGH_12
Definition: scsicmds.h:98
#define DXFER_NONE
Definition: scsicmds.h:105
#define SCSICMDS_H_CVSID
Definition: scsicmds.h:22
#define SIMPLE_NO_ERROR
Definition: scsicmds.h:340
#define SEND_DIAGNOSTIC
Definition: scsicmds.h:64
#define SIMPLE_ERR_NOT_READY
Definition: scsicmds.h:341
#define RIGID_DISK_DRIVE_GEOMETRY_PAGE
Definition: scsicmds.h:269
#define SCSI_DIAG_BG_SHORT_SELF_TEST
Definition: scsicmds.h:359
#define SIMPLE_ERR_ABORTED_COMMAND
Definition: scsicmds.h:351
#define READ_DEFECT_12
Definition: scsicmds.h:70
#define SCSI_VPD_BLOCK_DEVICE_CHARACTERISTICS
Definition: scsicmds.h:308
#define READ_DEFECT_10
Definition: scsicmds.h:67
#define SCSI_DIAG_BG_EXTENDED_SELF_TEST
Definition: scsicmds.h:360
#define SIMPLE_ERR_TRY_AGAIN
Definition: scsicmds.h:348
#define SIMPLE_ERR_NO_MEDIUM
Definition: scsicmds.h:346
#define RECEIVE_DIAGNOSTIC
Definition: scsicmds.h:61
#define SCSI_ASC_INVALID_FIELD
Definition: scsicmds.h:332
#define CACHING_PAGE
Definition: scsicmds.h:272
#define SELFTEST_RESULTS_LPAGE
Definition: scsicmds.h:229
#define MODE_SELECT_10
Definition: scsicmds.h:52
#define LOG_SENSE
Definition: scsicmds.h:40
#define SIMPLE_ERR_PROTECTION
Definition: scsicmds.h:352
#define DXFER_FROM_DEVICE
Definition: scsicmds.h:106
#define SCSI_SK_ILLEGAL_REQUEST
Definition: scsicmds.h:321
#define SCSI_TIMEOUT_DEFAULT
Definition: scsicmds.h:372
#define SCSI_SK_ABORTED_COMMAND
Definition: scsicmds.h:324
#define SCSI_IECMP_RAW_LEN
Definition: scsicmds.h:140
#define SCSI_DIAG_ABORT_SELF_TEST
Definition: scsicmds.h:363
#define MODE_SELECT_6
Definition: scsicmds.h:49
#define SUPPORTED_LPAGES
Definition: scsicmds.h:215
#define SCSI_SK_COMPLETED
Definition: scsicmds.h:326
#define SAT_ATA_PASSTHROUGH_16
Definition: scsicmds.h:101
#define SCSI_DIAG_FG_SHORT_SELF_TEST
Definition: scsicmds.h:361
#define SIMPLE_ERR_BAD_OPCODE
Definition: scsicmds.h:342
#define SCSI_PT_MEDIUM_CHANGER
Definition: scsicmds.h:193
#define SCSI_ASC_UNKNOWN_PARAM
Definition: scsicmds.h:333
#define DXFER_TO_DEVICE
Definition: scsicmds.h:107
#define SCSI_PT_SEQUENTIAL_ACCESS
Definition: scsicmds.h:189
#define SCSI_SK_HARDWARE_ERROR
Definition: scsicmds.h:320
#define SCSI_STATUS_CHECK_CONDITION
Definition: scsicmds.h:313
#define MODE_SENSE_10
Definition: scsicmds.h:46
#define LOG_SELECT
Definition: scsicmds.h:37
#define SIMPLE_ERR_BAD_PARAM
Definition: scsicmds.h:344
#define SCSI_PT_HOST_MANAGED
Definition: scsicmds.h:196
#define MPAGE_CONTROL_DEFAULT
Definition: scsicmds.h:296
#define SCSI_VPD_EXTENDED_INQUIRY_DATA
Definition: scsicmds.h:303
#define SCSI_DIAG_NO_SELF_TEST
Definition: scsicmds.h:357
#define LOG_RESP_SELF_TEST_LEN
Definition: scsicmds.h:258
#define SCSI_VPD_SUPPORTED_VPD_PAGES
Definition: scsicmds.h:300
#define TEST_UNIT_READY
Definition: scsicmds.h:34
#define SIMPLE_ERR_MISCOMPARE
Definition: scsicmds.h:353
#define TEMPERATURE_LPAGE
Definition: scsicmds.h:226
#define MPAGE_CONTROL_CHANGEABLE
Definition: scsicmds.h:295
#define SIMPLE_ERR_BAD_RESP
Definition: scsicmds.h:345
#define SCSI_PT_DIRECT_ACCESS
Definition: scsicmds.h:188
#define SERVICE_ACTION_IN_16
Definition: scsicmds.h:82
#define SCSI_ASC_NOT_READY
Definition: scsicmds.h:329
#define SIMPLE_ERR_UNKNOWN
Definition: scsicmds.h:350
#define SCSI_SK_NO_SENSE
Definition: scsicmds.h:316
#define IE_LPAGE
Definition: scsicmds.h:238
#define ALL_MODE_PAGES
Definition: scsicmds.h:291
#define INQUIRY
Definition: scsicmds.h:55
#define SCSI_SK_RECOVERED_ERR
Definition: scsicmds.h:317
#define SCSI_SK_NOT_READY
Definition: scsicmds.h:318
#define REQUEST_SENSE
Definition: scsicmds.h:58
#define CONTROL_MODE_PAGE
Definition: scsicmds.h:275
#define SCSI_SK_DATA_PROTECT
Definition: scsicmds.h:323
#define SCSI_SK_MISCOMPARE
Definition: scsicmds.h:325
#define SCSI_DIAG_FG_EXTENDED_SELF_TEST
Definition: scsicmds.h:362
#define SCSI_TIMEOUT_SELF_TEST
Definition: scsicmds.h:375
#define SCSI_ASC_NO_MEDIUM
Definition: scsicmds.h:330
#define PROTOCOL_SPECIFIC_PORT_PAGE
Definition: scsicmds.h:283
static int modese_len
Definition: scsiprint.cpp:78
static void sg_put_unaligned_be32(uint32_t val, void *p)
Definition: sg_unaligned.h:279
static void sg_put_unaligned_be16(uint16_t val, void *p)
Definition: sg_unaligned.h:273
static uint64_t sg_get_unaligned_be64(const void *p)
Definition: sg_unaligned.h:267
static uint64_t sg_get_unaligned_be(int num_bytes, const void *p)
Definition: sg_unaligned.h:350
static uint16_t sg_get_unaligned_be16(const void *p)
Definition: sg_unaligned.h:256
static uint32_t sg_get_unaligned_be32(const void *p)
Definition: sg_unaligned.h:261
for(char *p=buf, *q;p &&*p;p=q)
Definition: smartd.cpp:1306
void pout(const char *fmt,...)
Definition: smartd.cpp:1326
uint8_t gotPC[7]
Definition: scsicmds.h:153
uint64_t counter[8]
Definition: scsicmds.h:155
uint8_t gotExtraPC
Definition: scsicmds.h:154
uint64_t counterTFE_H
Definition: scsicmds.h:164
uint64_t counterPE_H
Definition: scsicmds.h:166
uint8_t gotTFE_H
Definition: scsicmds.h:163
uint8_t gotExtraPC
Definition: scsicmds.h:161
uint64_t counterPC0
Definition: scsicmds.h:162
uint8_t * sensep
Definition: scsicmds.h:120
uint8_t * dxferp
Definition: scsicmds.h:118
int dxfer_dir
Definition: scsicmds.h:116
size_t cmnd_len
Definition: scsicmds.h:115
size_t resp_sense_len
Definition: scsicmds.h:124
size_t dxfer_len
Definition: scsicmds.h:119
size_t max_sense_len
Definition: scsicmds.h:122
uint8_t scsi_status
Definition: scsicmds.h:125
uint8_t * cmnd
Definition: scsicmds.h:114
unsigned timeout
Definition: scsicmds.h:123
uint8_t gotChangeable
Definition: scsicmds.h:145
uint8_t gotCurrent
Definition: scsicmds.h:143
uint8_t modese_len
Definition: scsicmds.h:146
uint8_t raw_curr[SCSI_IECMP_RAW_LEN]
Definition: scsicmds.h:147
uint8_t raw_chg[SCSI_IECMP_RAW_LEN]
Definition: scsicmds.h:148
uint8_t requestedChangeable
Definition: scsicmds.h:144
uint8_t requestedCurrent
Definition: scsicmds.h:142
const char * name
Definition: scsicmds.cpp:234
uint16_t l_a_lba
Definition: scsicmds.h:179
uint8_t lb_p_pb_exp
Definition: scsicmds.h:176
uint8_t prot_type
Definition: scsicmds.h:173
uint8_t p_i_exp
Definition: scsicmds.h:175
uint32_t lb_size
Definition: scsicmds.h:171
uint64_t num_lblocks
Definition: scsicmds.h:170
enum scsi_sa_t sa_var
Definition: scsicmds.cpp:208
uint8_t resp_code
Definition: scsicmds.h:132
uint8_t sense_key
Definition: scsicmds.h:133