1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2003-2009 Silicon Graphics International Corp.
5 * Copyright (c) 2011 Spectra Logic Corporation
6 * Copyright (c) 2014-2015 Alexander Motin <[email protected]>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions, and the following disclaimer,
14 * without modification.
15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
16 * substantially similar to the "NO WARRANTY" disclaimer below
17 * ("Disclaimer") and any redistribution must be conditioned upon
18 * including a substantially similar Disclaimer requirement for further
19 * binary redistribution.
20 *
21 * NO WARRANTY
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
31 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGES.
33 *
34 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_error.c#2 $
35 */
36 /*
37 * CAM Target Layer error reporting routines.
38 *
39 * Author: Ken Merry <[email protected]>
40 */
41
42 #include <sys/cdefs.h>
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/types.h>
47 #include <sys/malloc.h>
48 #include <sys/lock.h>
49 #include <sys/mutex.h>
50 #include <sys/condvar.h>
51 #include <sys/stddef.h>
52 #include <sys/ctype.h>
53 #include <sys/sysctl.h>
54 #include <machine/stdarg.h>
55
56 #include <cam/scsi/scsi_all.h>
57 #include <cam/scsi/scsi_da.h>
58 #include <cam/ctl/ctl_io.h>
59 #include <cam/ctl/ctl.h>
60 #include <cam/ctl/ctl_frontend.h>
61 #include <cam/ctl/ctl_backend.h>
62 #include <cam/ctl/ctl_ioctl.h>
63 #include <cam/ctl/ctl_error.h>
64 #include <cam/ctl/ctl_ha.h>
65 #include <cam/ctl/ctl_private.h>
66
67 void
ctl_set_sense_data_va(struct scsi_sense_data * sense_data,u_int * sense_len,void * lunptr,scsi_sense_data_type sense_format,int current_error,int sense_key,int asc,int ascq,va_list ap)68 ctl_set_sense_data_va(struct scsi_sense_data *sense_data, u_int *sense_len,
69 void *lunptr, scsi_sense_data_type sense_format, int current_error,
70 int sense_key, int asc, int ascq, va_list ap)
71 {
72 struct ctl_lun *lun;
73
74 lun = (struct ctl_lun *)lunptr;
75
76 /*
77 * Determine whether to return fixed or descriptor format sense
78 * data.
79 */
80 if (sense_format == SSD_TYPE_NONE) {
81 /*
82 * SPC-3 and up require some UAs to be returned as fixed.
83 */
84 if (asc == 0x29 || (asc == 0x2A && ascq == 0x01))
85 sense_format = SSD_TYPE_FIXED;
86 else
87 /*
88 * If the format isn't specified, we only return descriptor
89 * sense if the LUN exists and descriptor sense is turned
90 * on for that LUN.
91 */
92 if ((lun != NULL) && (lun->MODE_CTRL.rlec & SCP_DSENSE))
93 sense_format = SSD_TYPE_DESC;
94 else
95 sense_format = SSD_TYPE_FIXED;
96 }
97
98 /*
99 * Determine maximum sense data length to return.
100 */
101 if (*sense_len == 0) {
102 if ((lun != NULL) && (lun->MODE_CTRLE.max_sense != 0))
103 *sense_len = lun->MODE_CTRLE.max_sense;
104 else
105 *sense_len = SSD_FULL_SIZE;
106 }
107
108 scsi_set_sense_data_va(sense_data, sense_len, sense_format,
109 current_error, sense_key, asc, ascq, ap);
110 }
111
112 void
ctl_set_sense_data(struct scsi_sense_data * sense_data,u_int * sense_len,void * lunptr,scsi_sense_data_type sense_format,int current_error,int sense_key,int asc,int ascq,...)113 ctl_set_sense_data(struct scsi_sense_data *sense_data, u_int *sense_len,
114 void *lunptr, scsi_sense_data_type sense_format, int current_error,
115 int sense_key, int asc, int ascq, ...)
116 {
117 va_list ap;
118
119 va_start(ap, ascq);
120 ctl_set_sense_data_va(sense_data, sense_len, lunptr, sense_format,
121 current_error, sense_key, asc, ascq, ap);
122 va_end(ap);
123 }
124
125 void
ctl_set_sense(struct ctl_scsiio * ctsio,int current_error,int sense_key,int asc,int ascq,...)126 ctl_set_sense(struct ctl_scsiio *ctsio, int current_error, int sense_key,
127 int asc, int ascq, ...)
128 {
129 va_list ap;
130 struct ctl_lun *lun;
131 u_int sense_len;
132
133 /*
134 * The LUN can't go away until all of the commands have been
135 * completed. Therefore we can safely access the LUN structure and
136 * flags without the lock.
137 */
138 lun = CTL_LUN(ctsio);
139
140 va_start(ap, ascq);
141 sense_len = 0;
142 ctl_set_sense_data_va(&ctsio->sense_data, &sense_len,
143 lun,
144 SSD_TYPE_NONE,
145 current_error,
146 sense_key,
147 asc,
148 ascq,
149 ap);
150 va_end(ap);
151
152 ctsio->scsi_status = SCSI_STATUS_CHECK_COND;
153 ctsio->sense_len = sense_len;
154 ctsio->io_hdr.status = CTL_SCSI_ERROR | CTL_AUTOSENSE;
155 }
156
157 /*
158 * Transform fixed sense data into descriptor sense data.
159 *
160 * For simplicity's sake, we assume that both sense structures are
161 * SSD_FULL_SIZE. Otherwise, the logic gets more complicated.
162 */
163 void
ctl_sense_to_desc(struct scsi_sense_data_fixed * sense_src,struct scsi_sense_data_desc * sense_dest)164 ctl_sense_to_desc(struct scsi_sense_data_fixed *sense_src,
165 struct scsi_sense_data_desc *sense_dest)
166 {
167 struct scsi_sense_stream stream_sense;
168 int current_error;
169 u_int sense_len;
170 uint8_t stream_bits;
171
172 bzero(sense_dest, sizeof(*sense_dest));
173
174 if ((sense_src->error_code & SSD_ERRCODE) == SSD_DEFERRED_ERROR)
175 current_error = 0;
176 else
177 current_error = 1;
178
179 bzero(&stream_sense, sizeof(stream_sense));
180
181 /*
182 * Check to see whether any of the tape-specific bits are set. If
183 * so, we'll need a stream sense descriptor.
184 */
185 if (sense_src->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK))
186 stream_bits = sense_src->flags & ~SSD_KEY;
187 else
188 stream_bits = 0;
189
190 /*
191 * Utilize our sense setting routine to do the transform. If a
192 * value is set in the fixed sense data, set it in the descriptor
193 * data. Otherwise, skip it.
194 */
195 sense_len = SSD_FULL_SIZE;
196 ctl_set_sense_data((struct scsi_sense_data *)sense_dest, &sense_len,
197 /*lun*/ NULL,
198 /*sense_format*/ SSD_TYPE_DESC,
199 current_error,
200 /*sense_key*/ sense_src->flags & SSD_KEY,
201 /*asc*/ sense_src->add_sense_code,
202 /*ascq*/ sense_src->add_sense_code_qual,
203
204 /* Information Bytes */
205 (sense_src->error_code & SSD_ERRCODE_VALID) ?
206 SSD_ELEM_INFO : SSD_ELEM_SKIP,
207 sizeof(sense_src->info),
208 sense_src->info,
209
210 /* Command specific bytes */
211 (scsi_4btoul(sense_src->cmd_spec_info) != 0) ?
212 SSD_ELEM_COMMAND : SSD_ELEM_SKIP,
213 sizeof(sense_src->cmd_spec_info),
214 sense_src->cmd_spec_info,
215
216 /* FRU */
217 (sense_src->fru != 0) ?
218 SSD_ELEM_FRU : SSD_ELEM_SKIP,
219 sizeof(sense_src->fru),
220 &sense_src->fru,
221
222 /* Sense Key Specific */
223 (sense_src->sense_key_spec[0] & SSD_SCS_VALID) ?
224 SSD_ELEM_SKS : SSD_ELEM_SKIP,
225 sizeof(sense_src->sense_key_spec),
226 sense_src->sense_key_spec,
227
228 /* Tape bits */
229 (stream_bits != 0) ?
230 SSD_ELEM_STREAM : SSD_ELEM_SKIP,
231 sizeof(stream_bits),
232 &stream_bits,
233
234 SSD_ELEM_NONE);
235 }
236
237 /*
238 * Transform descriptor format sense data into fixed sense data.
239 *
240 * Some data may be lost in translation, because there are descriptors
241 * thant can't be represented as fixed sense data.
242 *
243 * For simplicity's sake, we assume that both sense structures are
244 * SSD_FULL_SIZE. Otherwise, the logic gets more complicated.
245 */
246 void
ctl_sense_to_fixed(struct scsi_sense_data_desc * sense_src,struct scsi_sense_data_fixed * sense_dest)247 ctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src,
248 struct scsi_sense_data_fixed *sense_dest)
249 {
250 int current_error;
251 uint8_t *info_ptr = NULL, *cmd_ptr = NULL, *fru_ptr = NULL;
252 uint8_t *sks_ptr = NULL, *stream_ptr = NULL;
253 int info_size = 0, cmd_size = 0, fru_size = 0;
254 int sks_size = 0, stream_size = 0;
255 int pos;
256 u_int sense_len;
257
258 if ((sense_src->error_code & SSD_ERRCODE) == SSD_DESC_CURRENT_ERROR)
259 current_error = 1;
260 else
261 current_error = 0;
262
263 for (pos = 0; pos < (int)(sense_src->extra_len - 1);) {
264 struct scsi_sense_desc_header *header;
265
266 header = (struct scsi_sense_desc_header *)
267 &sense_src->sense_desc[pos];
268
269 /*
270 * See if this record goes past the end of the sense data.
271 * It shouldn't, but check just in case.
272 */
273 if ((pos + header->length + sizeof(*header)) >
274 sense_src->extra_len)
275 break;
276
277 switch (sense_src->sense_desc[pos]) {
278 case SSD_DESC_INFO: {
279 struct scsi_sense_info *info;
280
281 info = (struct scsi_sense_info *)header;
282
283 info_ptr = info->info;
284 info_size = sizeof(info->info);
285
286 pos += info->length +
287 sizeof(struct scsi_sense_desc_header);
288 break;
289 }
290 case SSD_DESC_COMMAND: {
291 struct scsi_sense_command *cmd;
292
293 cmd = (struct scsi_sense_command *)header;
294 cmd_ptr = cmd->command_info;
295 cmd_size = sizeof(cmd->command_info);
296
297 pos += cmd->length +
298 sizeof(struct scsi_sense_desc_header);
299 break;
300 }
301 case SSD_DESC_FRU: {
302 struct scsi_sense_fru *fru;
303
304 fru = (struct scsi_sense_fru *)header;
305 fru_ptr = &fru->fru;
306 fru_size = sizeof(fru->fru);
307 pos += fru->length +
308 sizeof(struct scsi_sense_desc_header);
309 break;
310 }
311 case SSD_DESC_SKS: {
312 struct scsi_sense_sks *sks;
313
314 sks = (struct scsi_sense_sks *)header;
315 sks_ptr = sks->sense_key_spec;
316 sks_size = sizeof(sks->sense_key_spec);
317
318 pos = sks->length +
319 sizeof(struct scsi_sense_desc_header);
320 break;
321 }
322 case SSD_DESC_STREAM: {
323 struct scsi_sense_stream *stream_sense;
324
325 stream_sense = (struct scsi_sense_stream *)header;
326 stream_ptr = &stream_sense->byte3;
327 stream_size = sizeof(stream_sense->byte3);
328 pos = stream_sense->length +
329 sizeof(struct scsi_sense_desc_header);
330 break;
331 }
332 default:
333 /*
334 * We don't recognize this particular sense
335 * descriptor type, so just skip it.
336 */
337 pos += sizeof(*header) + header->length;
338 break;
339 }
340 }
341
342 sense_len = SSD_FULL_SIZE;
343 ctl_set_sense_data((struct scsi_sense_data *)sense_dest, &sense_len,
344 /*lun*/ NULL,
345 /*sense_format*/ SSD_TYPE_FIXED,
346 current_error,
347 /*sense_key*/ sense_src->sense_key & SSD_KEY,
348 /*asc*/ sense_src->add_sense_code,
349 /*ascq*/ sense_src->add_sense_code_qual,
350
351 /* Information Bytes */
352 (info_ptr != NULL) ? SSD_ELEM_INFO : SSD_ELEM_SKIP,
353 info_size,
354 info_ptr,
355
356 /* Command specific bytes */
357 (cmd_ptr != NULL) ? SSD_ELEM_COMMAND : SSD_ELEM_SKIP,
358 cmd_size,
359 cmd_ptr,
360
361 /* FRU */
362 (fru_ptr != NULL) ? SSD_ELEM_FRU : SSD_ELEM_SKIP,
363 fru_size,
364 fru_ptr,
365
366 /* Sense Key Specific */
367 (sks_ptr != NULL) ? SSD_ELEM_SKS : SSD_ELEM_SKIP,
368 sks_size,
369 sks_ptr,
370
371 /* Tape bits */
372 (stream_ptr != NULL) ? SSD_ELEM_STREAM : SSD_ELEM_SKIP,
373 stream_size,
374 stream_ptr,
375
376 SSD_ELEM_NONE);
377 }
378
379 void
ctl_set_ua(struct ctl_scsiio * ctsio,int asc,int ascq)380 ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq)
381 {
382 ctl_set_sense(ctsio,
383 /*current_error*/ 1,
384 /*sense_key*/ SSD_KEY_UNIT_ATTENTION,
385 asc,
386 ascq,
387 SSD_ELEM_NONE);
388 }
389
390 static void
ctl_ua_to_ascq(struct ctl_lun * lun,ctl_ua_type ua_to_build,int * asc,int * ascq,ctl_ua_type * ua_to_clear,uint8_t ** info)391 ctl_ua_to_ascq(struct ctl_lun *lun, ctl_ua_type ua_to_build, int *asc,
392 int *ascq, ctl_ua_type *ua_to_clear, uint8_t **info)
393 {
394
395 switch (ua_to_build) {
396 case CTL_UA_POWERON:
397 /* 29h/01h POWER ON OCCURRED */
398 *asc = 0x29;
399 *ascq = 0x01;
400 *ua_to_clear = ~0;
401 break;
402 case CTL_UA_BUS_RESET:
403 /* 29h/02h SCSI BUS RESET OCCURRED */
404 *asc = 0x29;
405 *ascq = 0x02;
406 *ua_to_clear = ~0;
407 break;
408 case CTL_UA_TARG_RESET:
409 /* 29h/03h BUS DEVICE RESET FUNCTION OCCURRED*/
410 *asc = 0x29;
411 *ascq = 0x03;
412 *ua_to_clear = ~0;
413 break;
414 case CTL_UA_I_T_NEXUS_LOSS:
415 /* 29h/07h I_T NEXUS LOSS OCCURRED */
416 *asc = 0x29;
417 *ascq = 0x07;
418 *ua_to_clear = ~0;
419 break;
420 case CTL_UA_LUN_RESET:
421 /* 29h/00h POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
422 /*
423 * Since we don't have a specific ASC/ASCQ pair for a LUN
424 * reset, just return the generic reset code.
425 */
426 *asc = 0x29;
427 *ascq = 0x00;
428 break;
429 case CTL_UA_LUN_CHANGE:
430 /* 3Fh/0Eh REPORTED LUNS DATA HAS CHANGED */
431 *asc = 0x3F;
432 *ascq = 0x0E;
433 break;
434 case CTL_UA_MODE_CHANGE:
435 /* 2Ah/01h MODE PARAMETERS CHANGED */
436 *asc = 0x2A;
437 *ascq = 0x01;
438 break;
439 case CTL_UA_LOG_CHANGE:
440 /* 2Ah/02h LOG PARAMETERS CHANGED */
441 *asc = 0x2A;
442 *ascq = 0x02;
443 break;
444 case CTL_UA_INQ_CHANGE:
445 /* 3Fh/03h INQUIRY DATA HAS CHANGED */
446 *asc = 0x3F;
447 *ascq = 0x03;
448 break;
449 case CTL_UA_RES_PREEMPT:
450 /* 2Ah/03h RESERVATIONS PREEMPTED */
451 *asc = 0x2A;
452 *ascq = 0x03;
453 break;
454 case CTL_UA_RES_RELEASE:
455 /* 2Ah/04h RESERVATIONS RELEASED */
456 *asc = 0x2A;
457 *ascq = 0x04;
458 break;
459 case CTL_UA_REG_PREEMPT:
460 /* 2Ah/05h REGISTRATIONS PREEMPTED */
461 *asc = 0x2A;
462 *ascq = 0x05;
463 break;
464 case CTL_UA_ASYM_ACC_CHANGE:
465 /* 2Ah/06h ASYMMETRIC ACCESS STATE CHANGED */
466 *asc = 0x2A;
467 *ascq = 0x06;
468 break;
469 case CTL_UA_CAPACITY_CHANGE:
470 /* 2Ah/09h CAPACITY DATA HAS CHANGED */
471 *asc = 0x2A;
472 *ascq = 0x09;
473 break;
474 case CTL_UA_THIN_PROV_THRES:
475 /* 38h/07h THIN PROVISIONING SOFT THRESHOLD REACHED */
476 *asc = 0x38;
477 *ascq = 0x07;
478 *info = lun->ua_tpt_info;
479 break;
480 case CTL_UA_MEDIUM_CHANGE:
481 /* 28h/00h NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */
482 *asc = 0x28;
483 *ascq = 0x00;
484 break;
485 case CTL_UA_IE:
486 /* Informational exception */
487 *asc = lun->ie_asc;
488 *ascq = lun->ie_ascq;
489 break;
490 default:
491 panic("%s: Unknown UA %x", __func__, ua_to_build);
492 }
493 }
494
495 ctl_ua_type
ctl_build_qae(struct ctl_lun * lun,uint32_t initidx,uint8_t * resp)496 ctl_build_qae(struct ctl_lun *lun, uint32_t initidx, uint8_t *resp)
497 {
498 ctl_ua_type ua;
499 ctl_ua_type ua_to_build, ua_to_clear;
500 uint8_t *info;
501 int asc, ascq;
502 uint32_t p, i;
503
504 mtx_assert(&lun->lun_lock, MA_OWNED);
505 p = initidx / CTL_MAX_INIT_PER_PORT;
506 i = initidx % CTL_MAX_INIT_PER_PORT;
507 if (lun->pending_ua[p] == NULL)
508 ua = CTL_UA_POWERON;
509 else
510 ua = lun->pending_ua[p][i];
511 if (ua == CTL_UA_NONE)
512 return (CTL_UA_NONE);
513
514 ua_to_build = (1 << (ffs(ua) - 1));
515 ua_to_clear = ua_to_build;
516 info = NULL;
517 ctl_ua_to_ascq(lun, ua_to_build, &asc, &ascq, &ua_to_clear, &info);
518
519 resp[0] = SSD_KEY_UNIT_ATTENTION;
520 if (ua_to_build == ua)
521 resp[0] |= 0x10;
522 else
523 resp[0] |= 0x20;
524 resp[1] = asc;
525 resp[2] = ascq;
526 return (ua_to_build);
527 }
528
529 ctl_ua_type
ctl_build_ua(struct ctl_lun * lun,uint32_t initidx,struct scsi_sense_data * sense,u_int * sense_len,scsi_sense_data_type sense_format)530 ctl_build_ua(struct ctl_lun *lun, uint32_t initidx,
531 struct scsi_sense_data *sense, u_int *sense_len,
532 scsi_sense_data_type sense_format)
533 {
534 ctl_ua_type *ua;
535 ctl_ua_type ua_to_build, ua_to_clear;
536 uint8_t *info;
537 int asc, ascq;
538 uint32_t p, i;
539
540 mtx_assert(&lun->lun_lock, MA_OWNED);
541 mtx_assert(&lun->ctl_softc->ctl_lock, MA_NOTOWNED);
542 p = initidx / CTL_MAX_INIT_PER_PORT;
543 if ((ua = lun->pending_ua[p]) == NULL) {
544 mtx_unlock(&lun->lun_lock);
545 ua = malloc(sizeof(ctl_ua_type) * CTL_MAX_INIT_PER_PORT,
546 M_CTL, M_WAITOK);
547 mtx_lock(&lun->lun_lock);
548 if (lun->pending_ua[p] == NULL) {
549 lun->pending_ua[p] = ua;
550 for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++)
551 ua[i] = CTL_UA_POWERON;
552 } else {
553 free(ua, M_CTL);
554 ua = lun->pending_ua[p];
555 }
556 }
557 i = initidx % CTL_MAX_INIT_PER_PORT;
558 if (ua[i] == CTL_UA_NONE)
559 return (CTL_UA_NONE);
560
561 ua_to_build = (1 << (ffs(ua[i]) - 1));
562 ua_to_clear = ua_to_build;
563 info = NULL;
564 ctl_ua_to_ascq(lun, ua_to_build, &asc, &ascq, &ua_to_clear, &info);
565
566 ctl_set_sense_data(sense, sense_len, lun, sense_format, 1,
567 /*sense_key*/ SSD_KEY_UNIT_ATTENTION, asc, ascq,
568 ((info != NULL) ? SSD_ELEM_INFO : SSD_ELEM_SKIP), 8, info,
569 SSD_ELEM_NONE);
570
571 /* We're reporting this UA, so clear it */
572 ua[i] &= ~ua_to_clear;
573
574 if (ua_to_build == CTL_UA_LUN_CHANGE) {
575 mtx_unlock(&lun->lun_lock);
576 mtx_lock(&lun->ctl_softc->ctl_lock);
577 ctl_clr_ua_allluns(lun->ctl_softc, initidx, ua_to_build);
578 mtx_unlock(&lun->ctl_softc->ctl_lock);
579 mtx_lock(&lun->lun_lock);
580 } else if (ua_to_build == CTL_UA_THIN_PROV_THRES &&
581 (lun->MODE_LBP.main.flags & SLBPP_SITUA) != 0) {
582 ctl_clr_ua_all(lun, -1, ua_to_build);
583 }
584
585 return (ua_to_build);
586 }
587
588 void
ctl_set_overlapped_cmd(struct ctl_scsiio * ctsio)589 ctl_set_overlapped_cmd(struct ctl_scsiio *ctsio)
590 {
591 /* OVERLAPPED COMMANDS ATTEMPTED */
592 ctl_set_sense(ctsio,
593 /*current_error*/ 1,
594 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
595 /*asc*/ 0x4E,
596 /*ascq*/ 0x00,
597 SSD_ELEM_NONE);
598 }
599
600 void
ctl_set_overlapped_tag(struct ctl_scsiio * ctsio,uint8_t tag)601 ctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag)
602 {
603 /* TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG) */
604 ctl_set_sense(ctsio,
605 /*current_error*/ 1,
606 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
607 /*asc*/ 0x4D,
608 /*ascq*/ tag,
609 SSD_ELEM_NONE);
610 }
611
612 /*
613 * Tell the user that there was a problem with the command or data he sent.
614 */
615 void
ctl_set_invalid_field(struct ctl_scsiio * ctsio,int sks_valid,int command,int field,int bit_valid,int bit)616 ctl_set_invalid_field(struct ctl_scsiio *ctsio, int sks_valid, int command,
617 int field, int bit_valid, int bit)
618 {
619 uint8_t sks[3];
620 int asc;
621
622 if (command != 0) {
623 /* "Invalid field in CDB" */
624 asc = 0x24;
625 } else {
626 /* "Invalid field in parameter list" */
627 asc = 0x26;
628 }
629
630 if (sks_valid) {
631 sks[0] = SSD_SCS_VALID;
632 if (command)
633 sks[0] |= SSD_FIELDPTR_CMD;
634 scsi_ulto2b(field, &sks[1]);
635
636 if (bit_valid)
637 sks[0] |= SSD_BITPTR_VALID | bit;
638 }
639
640 ctl_set_sense(ctsio,
641 /*current_error*/ 1,
642 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
643 asc,
644 /*ascq*/ 0x00,
645 /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP,
646 /*size*/ sizeof(sks),
647 /*data*/ sks,
648 SSD_ELEM_NONE);
649 }
650 void
ctl_set_invalid_field_ciu(struct ctl_scsiio * ctsio)651 ctl_set_invalid_field_ciu(struct ctl_scsiio *ctsio)
652 {
653
654 /* "Invalid field in command information unit" */
655 ctl_set_sense(ctsio,
656 /*current_error*/ 1,
657 /*sense_key*/ SSD_KEY_ABORTED_COMMAND,
658 /*ascq*/ 0x0E,
659 /*ascq*/ 0x03,
660 SSD_ELEM_NONE);
661 }
662
663 void
ctl_set_invalid_opcode(struct ctl_scsiio * ctsio)664 ctl_set_invalid_opcode(struct ctl_scsiio *ctsio)
665 {
666 uint8_t sks[3];
667
668 sks[0] = SSD_SCS_VALID | SSD_FIELDPTR_CMD;
669 scsi_ulto2b(0, &sks[1]);
670
671 /* "Invalid command operation code" */
672 ctl_set_sense(ctsio,
673 /*current_error*/ 1,
674 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
675 /*asc*/ 0x20,
676 /*ascq*/ 0x00,
677 /*type*/ SSD_ELEM_SKS,
678 /*size*/ sizeof(sks),
679 /*data*/ sks,
680 SSD_ELEM_NONE);
681 }
682
683 void
ctl_set_param_len_error(struct ctl_scsiio * ctsio)684 ctl_set_param_len_error(struct ctl_scsiio *ctsio)
685 {
686 /* "Parameter list length error" */
687 ctl_set_sense(ctsio,
688 /*current_error*/ 1,
689 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
690 /*asc*/ 0x1a,
691 /*ascq*/ 0x00,
692 SSD_ELEM_NONE);
693 }
694
695 void
ctl_set_already_locked(struct ctl_scsiio * ctsio)696 ctl_set_already_locked(struct ctl_scsiio *ctsio)
697 {
698 /* Vendor unique "Somebody already is locked" */
699 ctl_set_sense(ctsio,
700 /*current_error*/ 1,
701 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
702 /*asc*/ 0x81,
703 /*ascq*/ 0x00,
704 SSD_ELEM_NONE);
705 }
706
707 void
ctl_set_unsupported_lun(struct ctl_scsiio * ctsio)708 ctl_set_unsupported_lun(struct ctl_scsiio *ctsio)
709 {
710 /* "Logical unit not supported" */
711 ctl_set_sense(ctsio,
712 /*current_error*/ 1,
713 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
714 /*asc*/ 0x25,
715 /*ascq*/ 0x00,
716 SSD_ELEM_NONE);
717 }
718
719 void
ctl_set_internal_failure(struct ctl_scsiio * ctsio,int sks_valid,uint16_t retry_count)720 ctl_set_internal_failure(struct ctl_scsiio *ctsio, int sks_valid,
721 uint16_t retry_count)
722 {
723 uint8_t sks[3];
724
725 if (sks_valid) {
726 sks[0] = SSD_SCS_VALID;
727 sks[1] = (retry_count >> 8) & 0xff;
728 sks[2] = retry_count & 0xff;
729 }
730
731 /* "Internal target failure" */
732 ctl_set_sense(ctsio,
733 /*current_error*/ 1,
734 /*sense_key*/ SSD_KEY_HARDWARE_ERROR,
735 /*asc*/ 0x44,
736 /*ascq*/ 0x00,
737 /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP,
738 /*size*/ sizeof(sks),
739 /*data*/ sks,
740 SSD_ELEM_NONE);
741 }
742
743 void
ctl_set_medium_error(struct ctl_scsiio * ctsio,int read)744 ctl_set_medium_error(struct ctl_scsiio *ctsio, int read)
745 {
746 if (read) {
747 /* "Unrecovered read error" */
748 ctl_set_sense(ctsio,
749 /*current_error*/ 1,
750 /*sense_key*/ SSD_KEY_MEDIUM_ERROR,
751 /*asc*/ 0x11,
752 /*ascq*/ 0x00,
753 SSD_ELEM_NONE);
754 } else {
755 /* "Write error - auto reallocation failed" */
756 ctl_set_sense(ctsio,
757 /*current_error*/ 1,
758 /*sense_key*/ SSD_KEY_MEDIUM_ERROR,
759 /*asc*/ 0x0C,
760 /*ascq*/ 0x02,
761 SSD_ELEM_NONE);
762 }
763 }
764
765 void
ctl_set_aborted(struct ctl_scsiio * ctsio)766 ctl_set_aborted(struct ctl_scsiio *ctsio)
767 {
768 ctl_set_sense(ctsio,
769 /*current_error*/ 1,
770 /*sense_key*/ SSD_KEY_ABORTED_COMMAND,
771 /*asc*/ 0x45,
772 /*ascq*/ 0x00,
773 SSD_ELEM_NONE);
774 }
775
776 void
ctl_set_lba_out_of_range(struct ctl_scsiio * ctsio,uint64_t lba)777 ctl_set_lba_out_of_range(struct ctl_scsiio *ctsio, uint64_t lba)
778 {
779 uint8_t info[8];
780
781 scsi_u64to8b(lba, info);
782
783 /* "Logical block address out of range" */
784 ctl_set_sense(ctsio,
785 /*current_error*/ 1,
786 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
787 /*asc*/ 0x21,
788 /*ascq*/ 0x00,
789 /*type*/ (lba != 0) ? SSD_ELEM_INFO : SSD_ELEM_SKIP,
790 /*size*/ sizeof(info), /*data*/ &info,
791 SSD_ELEM_NONE);
792 }
793
794 void
ctl_set_lun_stopped(struct ctl_scsiio * ctsio)795 ctl_set_lun_stopped(struct ctl_scsiio *ctsio)
796 {
797 /* "Logical unit not ready, initializing cmd. required" */
798 ctl_set_sense(ctsio,
799 /*current_error*/ 1,
800 /*sense_key*/ SSD_KEY_NOT_READY,
801 /*asc*/ 0x04,
802 /*ascq*/ 0x02,
803 SSD_ELEM_NONE);
804 }
805
806 void
ctl_set_lun_int_reqd(struct ctl_scsiio * ctsio)807 ctl_set_lun_int_reqd(struct ctl_scsiio *ctsio)
808 {
809 /* "Logical unit not ready, manual intervention required" */
810 ctl_set_sense(ctsio,
811 /*current_error*/ 1,
812 /*sense_key*/ SSD_KEY_NOT_READY,
813 /*asc*/ 0x04,
814 /*ascq*/ 0x03,
815 SSD_ELEM_NONE);
816 }
817
818 void
ctl_set_lun_ejected(struct ctl_scsiio * ctsio)819 ctl_set_lun_ejected(struct ctl_scsiio *ctsio)
820 {
821 /* "Medium not present - tray open" */
822 ctl_set_sense(ctsio,
823 /*current_error*/ 1,
824 /*sense_key*/ SSD_KEY_NOT_READY,
825 /*asc*/ 0x3A,
826 /*ascq*/ 0x02,
827 SSD_ELEM_NONE);
828 }
829
830 void
ctl_set_lun_no_media(struct ctl_scsiio * ctsio)831 ctl_set_lun_no_media(struct ctl_scsiio *ctsio)
832 {
833 /* "Medium not present - tray closed" */
834 ctl_set_sense(ctsio,
835 /*current_error*/ 1,
836 /*sense_key*/ SSD_KEY_NOT_READY,
837 /*asc*/ 0x3A,
838 /*ascq*/ 0x01,
839 SSD_ELEM_NONE);
840 }
841
842 void
ctl_set_illegal_pr_release(struct ctl_scsiio * ctsio)843 ctl_set_illegal_pr_release(struct ctl_scsiio *ctsio)
844 {
845 /* "Invalid release of persistent reservation" */
846 ctl_set_sense(ctsio,
847 /*current_error*/ 1,
848 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
849 /*asc*/ 0x26,
850 /*ascq*/ 0x04,
851 SSD_ELEM_NONE);
852 }
853
854 void
ctl_set_lun_transit(struct ctl_scsiio * ctsio)855 ctl_set_lun_transit(struct ctl_scsiio *ctsio)
856 {
857 /* "Logical unit not ready, asymmetric access state transition" */
858 ctl_set_sense(ctsio,
859 /*current_error*/ 1,
860 /*sense_key*/ SSD_KEY_NOT_READY,
861 /*asc*/ 0x04,
862 /*ascq*/ 0x0a,
863 SSD_ELEM_NONE);
864 }
865
866 void
ctl_set_lun_standby(struct ctl_scsiio * ctsio)867 ctl_set_lun_standby(struct ctl_scsiio *ctsio)
868 {
869 /* "Logical unit not ready, target port in standby state" */
870 ctl_set_sense(ctsio,
871 /*current_error*/ 1,
872 /*sense_key*/ SSD_KEY_NOT_READY,
873 /*asc*/ 0x04,
874 /*ascq*/ 0x0b,
875 SSD_ELEM_NONE);
876 }
877
878 void
ctl_set_lun_unavail(struct ctl_scsiio * ctsio)879 ctl_set_lun_unavail(struct ctl_scsiio *ctsio)
880 {
881 /* "Logical unit not ready, target port in unavailable state" */
882 ctl_set_sense(ctsio,
883 /*current_error*/ 1,
884 /*sense_key*/ SSD_KEY_NOT_READY,
885 /*asc*/ 0x04,
886 /*ascq*/ 0x0c,
887 SSD_ELEM_NONE);
888 }
889
890 void
ctl_set_medium_format_corrupted(struct ctl_scsiio * ctsio)891 ctl_set_medium_format_corrupted(struct ctl_scsiio *ctsio)
892 {
893 /* "Medium format corrupted" */
894 ctl_set_sense(ctsio,
895 /*current_error*/ 1,
896 /*sense_key*/ SSD_KEY_MEDIUM_ERROR,
897 /*asc*/ 0x31,
898 /*ascq*/ 0x00,
899 SSD_ELEM_NONE);
900 }
901
902 void
ctl_set_medium_magazine_inaccessible(struct ctl_scsiio * ctsio)903 ctl_set_medium_magazine_inaccessible(struct ctl_scsiio *ctsio)
904 {
905 /* "Medium magazine not accessible" */
906 ctl_set_sense(ctsio,
907 /*current_error*/ 1,
908 /*sense_key*/ SSD_KEY_NOT_READY,
909 /*asc*/ 0x3b,
910 /*ascq*/ 0x11,
911 SSD_ELEM_NONE);
912 }
913
914 void
ctl_set_data_phase_error(struct ctl_scsiio * ctsio)915 ctl_set_data_phase_error(struct ctl_scsiio *ctsio)
916 {
917 /* "Data phase error" */
918 ctl_set_sense(ctsio,
919 /*current_error*/ 1,
920 /*sense_key*/ SSD_KEY_NOT_READY,
921 /*asc*/ 0x4b,
922 /*ascq*/ 0x00,
923 SSD_ELEM_NONE);
924 }
925
926 void
ctl_set_reservation_conflict(struct ctl_scsiio * ctsio)927 ctl_set_reservation_conflict(struct ctl_scsiio *ctsio)
928 {
929
930 ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT;
931 ctsio->sense_len = 0;
932 ctsio->io_hdr.status = CTL_SCSI_ERROR;
933 }
934
935 void
ctl_set_queue_full(struct ctl_scsiio * ctsio)936 ctl_set_queue_full(struct ctl_scsiio *ctsio)
937 {
938
939 ctsio->scsi_status = SCSI_STATUS_QUEUE_FULL;
940 ctsio->sense_len = 0;
941 ctsio->io_hdr.status = CTL_SCSI_ERROR;
942 }
943
944 void
ctl_set_busy(struct ctl_scsiio * ctsio)945 ctl_set_busy(struct ctl_scsiio *ctsio)
946 {
947
948 ctsio->scsi_status = SCSI_STATUS_BUSY;
949 ctsio->sense_len = 0;
950 ctsio->io_hdr.status = CTL_SCSI_ERROR;
951 }
952
953 void
ctl_set_task_aborted(struct ctl_scsiio * ctsio)954 ctl_set_task_aborted(struct ctl_scsiio *ctsio)
955 {
956
957 ctsio->scsi_status = SCSI_STATUS_TASK_ABORTED;
958 ctsio->sense_len = 0;
959 ctsio->io_hdr.status = CTL_CMD_ABORTED;
960 }
961
962 void
ctl_set_hw_write_protected(struct ctl_scsiio * ctsio)963 ctl_set_hw_write_protected(struct ctl_scsiio *ctsio)
964 {
965 /* "Hardware write protected" */
966 ctl_set_sense(ctsio,
967 /*current_error*/ 1,
968 /*sense_key*/ SSD_KEY_DATA_PROTECT,
969 /*asc*/ 0x27,
970 /*ascq*/ 0x01,
971 SSD_ELEM_NONE);
972 }
973
974 void
ctl_set_space_alloc_fail(struct ctl_scsiio * ctsio)975 ctl_set_space_alloc_fail(struct ctl_scsiio *ctsio)
976 {
977 /* "Space allocation failed write protect" */
978 ctl_set_sense(ctsio,
979 /*current_error*/ 1,
980 /*sense_key*/ SSD_KEY_DATA_PROTECT,
981 /*asc*/ 0x27,
982 /*ascq*/ 0x07,
983 SSD_ELEM_NONE);
984 }
985
986 void
ctl_set_success(struct ctl_scsiio * ctsio)987 ctl_set_success(struct ctl_scsiio *ctsio)
988 {
989
990 ctsio->scsi_status = SCSI_STATUS_OK;
991 ctsio->sense_len = 0;
992 ctsio->io_hdr.status = CTL_SUCCESS;
993 }
994