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