]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/cam/ctl/ctl_error.c
Since contrib/libc++'s ancestry was never correct, subversion 1.8 and
[FreeBSD/FreeBSD.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_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/06n  ASYMMETRIC ACCESS STATE CHANGED */
466                 asc = 0x2A;
467                 ascq = 0x06;
468                 break;
469         case CTL_UA_CAPACITY_CHANGED:
470                 /* 2Ah/09n  CAPACITY DATA HAS CHANGED */
471                 asc = 0x2A;
472                 ascq = 0x09;
473                 break;
474         case CTL_UA_THIN_PROV_THRES:
475                 /* 38h/07n  THIN PROVISIONING SOFT THRESHOLD REACHED */
476                 asc = 0x38;
477                 ascq = 0x07;
478                 break;
479         default:
480                 panic("ctl_build_ua: Unknown UA %x", ua_to_build);
481         }
482
483         ctl_set_sense_data(sense,
484                            /*lun*/ NULL,
485                            sense_format,
486                            /*current_error*/ 1,
487                            /*sense_key*/ SSD_KEY_UNIT_ATTENTION,
488                            asc,
489                            ascq,
490                            SSD_ELEM_NONE);
491
492         /* We're reporting this UA, so clear it */
493         ua[i] &= ~ua_to_clear;
494
495         return (ua_to_build);
496 }
497
498 void
499 ctl_set_overlapped_cmd(struct ctl_scsiio *ctsio)
500 {
501         /* OVERLAPPED COMMANDS ATTEMPTED */
502         ctl_set_sense(ctsio,
503                       /*current_error*/ 1,
504                       /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
505                       /*asc*/ 0x4E,
506                       /*ascq*/ 0x00,
507                       SSD_ELEM_NONE);
508 }
509
510 void
511 ctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag)
512 {
513         /* TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG) */
514         ctl_set_sense(ctsio,
515                       /*current_error*/ 1,
516                       /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
517                       /*asc*/ 0x4D,
518                       /*ascq*/ tag,
519                       SSD_ELEM_NONE);
520 }
521
522 /*
523  * Tell the user that there was a problem with the command or data he sent.
524  */
525 void
526 ctl_set_invalid_field(struct ctl_scsiio *ctsio, int sks_valid, int command,
527                       int field, int bit_valid, int bit)
528 {
529         uint8_t sks[3];
530         int asc;
531
532         if (command != 0) {
533                 /* "Invalid field in CDB" */
534                 asc = 0x24;
535         } else {
536                 /* "Invalid field in parameter list" */
537                 asc = 0x26;
538         }
539
540         if (sks_valid) {
541                 sks[0] = SSD_SCS_VALID;
542                 if (command)
543                         sks[0] |= SSD_FIELDPTR_CMD;
544                 scsi_ulto2b(field, &sks[1]);
545
546                 if (bit_valid)
547                         sks[0] |= SSD_BITPTR_VALID | bit;
548         }
549
550         ctl_set_sense(ctsio,
551                       /*current_error*/ 1,
552                       /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
553                       asc,
554                       /*ascq*/ 0x00,
555                       /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP,
556                       /*size*/ sizeof(sks),
557                       /*data*/ sks,
558                       SSD_ELEM_NONE);
559 }
560
561 void
562 ctl_set_invalid_opcode(struct ctl_scsiio *ctsio)
563 {
564         struct scsi_sense_data *sense;
565         uint8_t sks[3];
566
567         sense = &ctsio->sense_data;
568
569         sks[0] = SSD_SCS_VALID | SSD_FIELDPTR_CMD;
570         scsi_ulto2b(0, &sks[1]);
571
572         /* "Invalid command operation code" */
573         ctl_set_sense(ctsio,
574                       /*current_error*/ 1,
575                       /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
576                       /*asc*/ 0x20,
577                       /*ascq*/ 0x00,
578                       /*type*/ SSD_ELEM_SKS,
579                       /*size*/ sizeof(sks),
580                       /*data*/ sks,
581                       SSD_ELEM_NONE);
582 }
583
584 void
585 ctl_set_param_len_error(struct ctl_scsiio *ctsio)
586 {
587         /* "Parameter list length error" */
588         ctl_set_sense(ctsio,
589                       /*current_error*/ 1,
590                       /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
591                       /*asc*/ 0x1a,
592                       /*ascq*/ 0x00,
593                       SSD_ELEM_NONE);
594 }
595
596 void
597 ctl_set_already_locked(struct ctl_scsiio *ctsio)
598 {
599         /* Vendor unique "Somebody already is locked" */
600         ctl_set_sense(ctsio,
601                       /*current_error*/ 1,
602                       /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
603                       /*asc*/ 0x81,
604                       /*ascq*/ 0x00,
605                       SSD_ELEM_NONE);
606 }
607
608 void
609 ctl_set_unsupported_lun(struct ctl_scsiio *ctsio)
610 {
611         /* "Logical unit not supported" */
612         ctl_set_sense(ctsio,
613                       /*current_error*/ 1,
614                       /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
615                       /*asc*/ 0x25,
616                       /*ascq*/ 0x00,
617                       SSD_ELEM_NONE);
618 }
619
620 void
621 ctl_set_internal_failure(struct ctl_scsiio *ctsio, int sks_valid,
622                          uint16_t retry_count)
623 {
624         uint8_t sks[3];
625
626         if (sks_valid) {
627                 sks[0] = SSD_SCS_VALID;
628                 sks[1] = (retry_count >> 8) & 0xff;
629                 sks[2] = retry_count & 0xff;
630         }
631
632         /* "Internal target failure" */
633         ctl_set_sense(ctsio,
634                       /*current_error*/ 1,
635                       /*sense_key*/ SSD_KEY_HARDWARE_ERROR,
636                       /*asc*/ 0x44,
637                       /*ascq*/ 0x00,
638                       /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP,
639                       /*size*/ sizeof(sks),
640                       /*data*/ sks,
641                       SSD_ELEM_NONE);
642 }
643
644 void
645 ctl_set_medium_error(struct ctl_scsiio *ctsio)
646 {
647         if ((ctsio->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) {
648                 /* "Unrecovered read error" */
649                 ctl_set_sense(ctsio,
650                               /*current_error*/ 1,
651                               /*sense_key*/ SSD_KEY_MEDIUM_ERROR,
652                               /*asc*/ 0x11,
653                               /*ascq*/ 0x00,
654                               SSD_ELEM_NONE);
655         } else {
656                 /* "Write error - auto reallocation failed" */
657                 ctl_set_sense(ctsio,
658                               /*current_error*/ 1,
659                               /*sense_key*/ SSD_KEY_MEDIUM_ERROR,
660                               /*asc*/ 0x0C,
661                               /*ascq*/ 0x02,
662                               SSD_ELEM_NONE);
663         }
664 }
665
666 void
667 ctl_set_aborted(struct ctl_scsiio *ctsio)
668 {
669         ctl_set_sense(ctsio,
670                       /*current_error*/ 1,
671                       /*sense_key*/ SSD_KEY_ABORTED_COMMAND,
672                       /*asc*/ 0x45,
673                       /*ascq*/ 0x00,
674                       SSD_ELEM_NONE);
675 }
676
677 void
678 ctl_set_lba_out_of_range(struct ctl_scsiio *ctsio)
679 {
680         /* "Logical block address out of range" */
681         ctl_set_sense(ctsio,
682                       /*current_error*/ 1,
683                       /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
684                       /*asc*/ 0x21,
685                       /*ascq*/ 0x00,
686                       SSD_ELEM_NONE);
687 }
688
689 void
690 ctl_set_lun_stopped(struct ctl_scsiio *ctsio)
691 {
692         /* "Logical unit not ready, initializing cmd. required" */
693         ctl_set_sense(ctsio,
694                       /*current_error*/ 1,
695                       /*sense_key*/ SSD_KEY_NOT_READY,
696                       /*asc*/ 0x04,
697                       /*ascq*/ 0x02,
698                       SSD_ELEM_NONE);
699 }
700
701 void
702 ctl_set_lun_not_ready(struct ctl_scsiio *ctsio)
703 {
704         /* "Logical unit not ready, manual intervention required" */
705         ctl_set_sense(ctsio,
706                       /*current_error*/ 1,
707                       /*sense_key*/ SSD_KEY_NOT_READY,
708                       /*asc*/ 0x04,
709                       /*ascq*/ 0x03,
710                       SSD_ELEM_NONE);
711 }
712
713 void
714 ctl_set_illegal_pr_release(struct ctl_scsiio *ctsio)
715 {
716         /* "Invalid release of persistent reservation" */
717         ctl_set_sense(ctsio,
718                       /*current_error*/ 1,
719                       /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
720                       /*asc*/ 0x26,
721                       /*ascq*/ 0x04,
722                       SSD_ELEM_NONE);
723 }
724
725 void
726 ctl_set_lun_transit(struct ctl_scsiio *ctsio)
727 {
728         /* "Logical unit not ready, asymmetric access state transition" */
729         ctl_set_sense(ctsio,
730                       /*current_error*/ 1,
731                       /*sense_key*/ SSD_KEY_NOT_READY,
732                       /*asc*/ 0x04,
733                       /*ascq*/ 0x0a,
734                       SSD_ELEM_NONE);
735 }
736
737 void
738 ctl_set_lun_standby(struct ctl_scsiio *ctsio)
739 {
740         /* "Logical unit not ready, target port in standby state" */
741         ctl_set_sense(ctsio,
742                       /*current_error*/ 1,
743                       /*sense_key*/ SSD_KEY_NOT_READY,
744                       /*asc*/ 0x04,
745                       /*ascq*/ 0x0b,
746                       SSD_ELEM_NONE);
747 }
748
749 void
750 ctl_set_lun_unavail(struct ctl_scsiio *ctsio)
751 {
752         /* "Logical unit not ready, target port in unavailable state" */
753         ctl_set_sense(ctsio,
754                       /*current_error*/ 1,
755                       /*sense_key*/ SSD_KEY_NOT_READY,
756                       /*asc*/ 0x04,
757                       /*ascq*/ 0x0c,
758                       SSD_ELEM_NONE);
759 }
760
761 void
762 ctl_set_medium_format_corrupted(struct ctl_scsiio *ctsio)
763 {
764         /* "Medium format corrupted" */
765         ctl_set_sense(ctsio,
766                       /*current_error*/ 1,
767                       /*sense_key*/ SSD_KEY_MEDIUM_ERROR,
768                       /*asc*/ 0x31,
769                       /*ascq*/ 0x00,
770                       SSD_ELEM_NONE);
771 }
772
773 void
774 ctl_set_medium_magazine_inaccessible(struct ctl_scsiio *ctsio)
775 {
776         /* "Medium magazine not accessible" */
777         ctl_set_sense(ctsio,
778                       /*current_error*/ 1,
779                       /*sense_key*/ SSD_KEY_NOT_READY,
780                       /*asc*/ 0x3b,
781                       /*ascq*/ 0x11,
782                       SSD_ELEM_NONE);
783 }
784
785 void
786 ctl_set_data_phase_error(struct ctl_scsiio *ctsio)
787 {
788         /* "Data phase error" */
789         ctl_set_sense(ctsio,
790                       /*current_error*/ 1,
791                       /*sense_key*/ SSD_KEY_NOT_READY,
792                       /*asc*/ 0x4b,
793                       /*ascq*/ 0x00,
794                       SSD_ELEM_NONE);
795 }
796
797 void
798 ctl_set_reservation_conflict(struct ctl_scsiio *ctsio)
799 {
800         struct scsi_sense_data *sense;
801
802         sense = &ctsio->sense_data;
803         memset(sense, 0, sizeof(*sense));
804         ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT;
805         ctsio->sense_len = 0;
806         ctsio->io_hdr.status = CTL_SCSI_ERROR;
807 }
808
809 void
810 ctl_set_queue_full(struct ctl_scsiio *ctsio)
811 {
812         struct scsi_sense_data *sense;
813
814         sense = &ctsio->sense_data;
815         memset(sense, 0, sizeof(*sense));
816         ctsio->scsi_status = SCSI_STATUS_QUEUE_FULL;
817         ctsio->sense_len = 0;
818         ctsio->io_hdr.status = CTL_SCSI_ERROR;
819 }
820
821 void
822 ctl_set_busy(struct ctl_scsiio *ctsio)
823 {
824         struct scsi_sense_data *sense;
825
826         sense = &ctsio->sense_data;
827         memset(sense, 0, sizeof(*sense));
828         ctsio->scsi_status = SCSI_STATUS_BUSY;
829         ctsio->sense_len = 0;
830         ctsio->io_hdr.status = CTL_SCSI_ERROR;
831 }
832
833 void
834 ctl_set_task_aborted(struct ctl_scsiio *ctsio)
835 {
836         struct scsi_sense_data *sense;
837
838         sense = &ctsio->sense_data;
839         memset(sense, 0, sizeof(*sense));
840         ctsio->scsi_status = SCSI_STATUS_TASK_ABORTED;
841         ctsio->sense_len = 0;
842         ctsio->io_hdr.status = CTL_CMD_ABORTED;
843 }
844
845 void
846 ctl_set_space_alloc_fail(struct ctl_scsiio *ctsio)
847 {
848         /* "Space allocation failed write protect" */
849         ctl_set_sense(ctsio,
850                       /*current_error*/ 1,
851                       /*sense_key*/ SSD_KEY_DATA_PROTECT,
852                       /*asc*/ 0x27,
853                       /*ascq*/ 0x07,
854                       SSD_ELEM_NONE);
855 }
856
857 void
858 ctl_set_success(struct ctl_scsiio *ctsio)
859 {
860         struct scsi_sense_data *sense;
861
862         sense = &ctsio->sense_data;
863         memset(sense, 0, sizeof(*sense));
864         ctsio->scsi_status = SCSI_STATUS_OK;
865         ctsio->sense_len = 0;
866         ctsio->io_hdr.status = CTL_SUCCESS;
867 }