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