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