1130f4520SKenneth D. Merry /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3bec9534dSPedro F. Giffuni * 4130f4520SKenneth D. Merry * Copyright (c) 2003-2009 Silicon Graphics International Corp. 5130f4520SKenneth D. Merry * Copyright (c) 2011 Spectra Logic Corporation 6648dfc1aSAlexander Motin * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> 7130f4520SKenneth D. Merry * All rights reserved. 8130f4520SKenneth D. Merry * 9130f4520SKenneth D. Merry * Redistribution and use in source and binary forms, with or without 10130f4520SKenneth D. Merry * modification, are permitted provided that the following conditions 11130f4520SKenneth D. Merry * are met: 12130f4520SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright 13130f4520SKenneth D. Merry * notice, this list of conditions, and the following disclaimer, 14130f4520SKenneth D. Merry * without modification. 15130f4520SKenneth D. Merry * 2. Redistributions in binary form must reproduce at minimum a disclaimer 16130f4520SKenneth D. Merry * substantially similar to the "NO WARRANTY" disclaimer below 17130f4520SKenneth D. Merry * ("Disclaimer") and any redistribution must be conditioned upon 18130f4520SKenneth D. Merry * including a substantially similar Disclaimer requirement for further 19130f4520SKenneth D. Merry * binary redistribution. 20130f4520SKenneth D. Merry * 21130f4520SKenneth D. Merry * NO WARRANTY 22130f4520SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23130f4520SKenneth D. Merry * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24130f4520SKenneth D. Merry * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 25130f4520SKenneth D. Merry * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26130f4520SKenneth D. Merry * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27130f4520SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28130f4520SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29130f4520SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30130f4520SKenneth D. Merry * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31130f4520SKenneth D. Merry * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32130f4520SKenneth D. Merry * POSSIBILITY OF SUCH DAMAGES. 33130f4520SKenneth D. Merry * 34130f4520SKenneth D. Merry * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_error.c#2 $ 35130f4520SKenneth D. Merry */ 36130f4520SKenneth D. Merry /* 37130f4520SKenneth D. Merry * CAM Target Layer error reporting routines. 38130f4520SKenneth D. Merry * 39130f4520SKenneth D. Merry * Author: Ken Merry <ken@FreeBSD.org> 40130f4520SKenneth D. Merry */ 41130f4520SKenneth D. Merry 42130f4520SKenneth D. Merry #include <sys/param.h> 43130f4520SKenneth D. Merry #include <sys/systm.h> 44130f4520SKenneth D. Merry #include <sys/kernel.h> 45130f4520SKenneth D. Merry #include <sys/types.h> 46130f4520SKenneth D. Merry #include <sys/malloc.h> 47130f4520SKenneth D. Merry #include <sys/lock.h> 48130f4520SKenneth D. Merry #include <sys/mutex.h> 49130f4520SKenneth D. Merry #include <sys/condvar.h> 50130f4520SKenneth D. Merry #include <sys/stddef.h> 51130f4520SKenneth D. Merry #include <sys/ctype.h> 52bf8f8f34SKenneth D. Merry #include <sys/sysctl.h> 53130f4520SKenneth D. Merry #include <machine/stdarg.h> 54130f4520SKenneth D. Merry 55130f4520SKenneth D. Merry #include <cam/scsi/scsi_all.h> 56130f4520SKenneth D. Merry #include <cam/scsi/scsi_da.h> 57130f4520SKenneth D. Merry #include <cam/ctl/ctl_io.h> 58130f4520SKenneth D. Merry #include <cam/ctl/ctl.h> 59130f4520SKenneth D. Merry #include <cam/ctl/ctl_frontend.h> 60130f4520SKenneth D. Merry #include <cam/ctl/ctl_backend.h> 61130f4520SKenneth D. Merry #include <cam/ctl/ctl_ioctl.h> 62130f4520SKenneth D. Merry #include <cam/ctl/ctl_error.h> 63130f4520SKenneth D. Merry #include <cam/ctl/ctl_ha.h> 64130f4520SKenneth D. Merry #include <cam/ctl/ctl_private.h> 65130f4520SKenneth D. Merry 66130f4520SKenneth D. Merry void 674fc0d1d7SAlexander Motin ctl_set_sense_data_va(struct scsi_sense_data *sense_data, u_int *sense_len, 684fc0d1d7SAlexander Motin void *lunptr, scsi_sense_data_type sense_format, int current_error, 69130f4520SKenneth D. Merry int sense_key, int asc, int ascq, va_list ap) 70130f4520SKenneth D. Merry { 71130f4520SKenneth D. Merry struct ctl_lun *lun; 72130f4520SKenneth D. Merry 73130f4520SKenneth D. Merry lun = (struct ctl_lun *)lunptr; 74130f4520SKenneth D. Merry 75130f4520SKenneth D. Merry /* 76130f4520SKenneth D. Merry * Determine whether to return fixed or descriptor format sense 77130f4520SKenneth D. Merry * data. 78130f4520SKenneth D. Merry */ 79130f4520SKenneth D. Merry if (sense_format == SSD_TYPE_NONE) { 80130f4520SKenneth D. Merry /* 8168035f63SAlexander Motin * SPC-3 and up require some UAs to be returned as fixed. 8268035f63SAlexander Motin */ 8368035f63SAlexander Motin if (asc == 0x29 || (asc == 0x2A && ascq == 0x01)) 8468035f63SAlexander Motin sense_format = SSD_TYPE_FIXED; 8568035f63SAlexander Motin else 8668035f63SAlexander Motin /* 87130f4520SKenneth D. Merry * If the format isn't specified, we only return descriptor 88130f4520SKenneth D. Merry * sense if the LUN exists and descriptor sense is turned 89130f4520SKenneth D. Merry * on for that LUN. 90130f4520SKenneth D. Merry */ 9111887875SAlexander Motin if ((lun != NULL) && (lun->MODE_CTRL.rlec & SCP_DSENSE)) 92130f4520SKenneth D. Merry sense_format = SSD_TYPE_DESC; 93130f4520SKenneth D. Merry else 94130f4520SKenneth D. Merry sense_format = SSD_TYPE_FIXED; 95130f4520SKenneth D. Merry } 96130f4520SKenneth D. Merry 974fc0d1d7SAlexander Motin /* 984fc0d1d7SAlexander Motin * Determine maximum sense data length to return. 994fc0d1d7SAlexander Motin */ 1004fc0d1d7SAlexander Motin if (*sense_len == 0) { 1014fc0d1d7SAlexander Motin if ((lun != NULL) && (lun->MODE_CTRLE.max_sense != 0)) 1024fc0d1d7SAlexander Motin *sense_len = lun->MODE_CTRLE.max_sense; 1034fc0d1d7SAlexander Motin else 1044fc0d1d7SAlexander Motin *sense_len = SSD_FULL_SIZE; 1054fc0d1d7SAlexander Motin } 1064fc0d1d7SAlexander Motin 1074fc0d1d7SAlexander Motin scsi_set_sense_data_va(sense_data, sense_len, sense_format, 1084fc0d1d7SAlexander Motin current_error, sense_key, asc, ascq, ap); 109130f4520SKenneth D. Merry } 110130f4520SKenneth D. Merry 111130f4520SKenneth D. Merry void 1124fc0d1d7SAlexander Motin ctl_set_sense_data(struct scsi_sense_data *sense_data, u_int *sense_len, 1134fc0d1d7SAlexander Motin void *lunptr, scsi_sense_data_type sense_format, int current_error, 114130f4520SKenneth D. Merry int sense_key, int asc, int ascq, ...) 115130f4520SKenneth D. Merry { 116130f4520SKenneth D. Merry va_list ap; 117130f4520SKenneth D. Merry 118130f4520SKenneth D. Merry va_start(ap, ascq); 1194fc0d1d7SAlexander Motin ctl_set_sense_data_va(sense_data, sense_len, lunptr, sense_format, 1204fc0d1d7SAlexander Motin current_error, sense_key, asc, ascq, ap); 121130f4520SKenneth D. Merry va_end(ap); 122130f4520SKenneth D. Merry } 123130f4520SKenneth D. Merry 124130f4520SKenneth D. Merry void 125130f4520SKenneth D. Merry ctl_set_sense(struct ctl_scsiio *ctsio, int current_error, int sense_key, 126130f4520SKenneth D. Merry int asc, int ascq, ...) 127130f4520SKenneth D. Merry { 128130f4520SKenneth D. Merry va_list ap; 129130f4520SKenneth D. Merry struct ctl_lun *lun; 1304fc0d1d7SAlexander Motin u_int sense_len; 131130f4520SKenneth D. Merry 132130f4520SKenneth D. Merry /* 133130f4520SKenneth D. Merry * The LUN can't go away until all of the commands have been 134130f4520SKenneth D. Merry * completed. Therefore we can safely access the LUN structure and 135130f4520SKenneth D. Merry * flags without the lock. 136130f4520SKenneth D. Merry */ 1379cbbfd2fSAlexander Motin lun = CTL_LUN(ctsio); 138130f4520SKenneth D. Merry 139130f4520SKenneth D. Merry va_start(ap, ascq); 1404fc0d1d7SAlexander Motin sense_len = 0; 1414fc0d1d7SAlexander Motin ctl_set_sense_data_va(&ctsio->sense_data, &sense_len, 142130f4520SKenneth D. Merry lun, 143130f4520SKenneth D. Merry SSD_TYPE_NONE, 144130f4520SKenneth D. Merry current_error, 145130f4520SKenneth D. Merry sense_key, 146130f4520SKenneth D. Merry asc, 147130f4520SKenneth D. Merry ascq, 148130f4520SKenneth D. Merry ap); 149130f4520SKenneth D. Merry va_end(ap); 150130f4520SKenneth D. Merry 151130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_CHECK_COND; 1524fc0d1d7SAlexander Motin ctsio->sense_len = sense_len; 153130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SCSI_ERROR | CTL_AUTOSENSE; 154130f4520SKenneth D. Merry } 155130f4520SKenneth D. Merry 156130f4520SKenneth D. Merry /* 157130f4520SKenneth D. Merry * Transform fixed sense data into descriptor sense data. 158130f4520SKenneth D. Merry * 159130f4520SKenneth D. Merry * For simplicity's sake, we assume that both sense structures are 160130f4520SKenneth D. Merry * SSD_FULL_SIZE. Otherwise, the logic gets more complicated. 161130f4520SKenneth D. Merry */ 162130f4520SKenneth D. Merry void 163130f4520SKenneth D. Merry ctl_sense_to_desc(struct scsi_sense_data_fixed *sense_src, 164130f4520SKenneth D. Merry struct scsi_sense_data_desc *sense_dest) 165130f4520SKenneth D. Merry { 166130f4520SKenneth D. Merry struct scsi_sense_stream stream_sense; 167130f4520SKenneth D. Merry int current_error; 1684fc0d1d7SAlexander Motin u_int sense_len; 169130f4520SKenneth D. Merry uint8_t stream_bits; 170130f4520SKenneth D. Merry 171130f4520SKenneth D. Merry bzero(sense_dest, sizeof(*sense_dest)); 172130f4520SKenneth D. Merry 173130f4520SKenneth D. Merry if ((sense_src->error_code & SSD_ERRCODE) == SSD_DEFERRED_ERROR) 174130f4520SKenneth D. Merry current_error = 0; 175130f4520SKenneth D. Merry else 176130f4520SKenneth D. Merry current_error = 1; 177130f4520SKenneth D. Merry 178130f4520SKenneth D. Merry bzero(&stream_sense, sizeof(stream_sense)); 179130f4520SKenneth D. Merry 180130f4520SKenneth D. Merry /* 181130f4520SKenneth D. Merry * Check to see whether any of the tape-specific bits are set. If 182130f4520SKenneth D. Merry * so, we'll need a stream sense descriptor. 183130f4520SKenneth D. Merry */ 184130f4520SKenneth D. Merry if (sense_src->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK)) 185130f4520SKenneth D. Merry stream_bits = sense_src->flags & ~SSD_KEY; 186130f4520SKenneth D. Merry else 187130f4520SKenneth D. Merry stream_bits = 0; 188130f4520SKenneth D. Merry 189130f4520SKenneth D. Merry /* 190130f4520SKenneth D. Merry * Utilize our sense setting routine to do the transform. If a 191130f4520SKenneth D. Merry * value is set in the fixed sense data, set it in the descriptor 192130f4520SKenneth D. Merry * data. Otherwise, skip it. 193130f4520SKenneth D. Merry */ 1944fc0d1d7SAlexander Motin sense_len = SSD_FULL_SIZE; 1954fc0d1d7SAlexander Motin ctl_set_sense_data((struct scsi_sense_data *)sense_dest, &sense_len, 196130f4520SKenneth D. Merry /*lun*/ NULL, 197130f4520SKenneth D. Merry /*sense_format*/ SSD_TYPE_DESC, 198130f4520SKenneth D. Merry current_error, 199130f4520SKenneth D. Merry /*sense_key*/ sense_src->flags & SSD_KEY, 200130f4520SKenneth D. Merry /*asc*/ sense_src->add_sense_code, 201130f4520SKenneth D. Merry /*ascq*/ sense_src->add_sense_code_qual, 202130f4520SKenneth D. Merry 203130f4520SKenneth D. Merry /* Information Bytes */ 20432920cbfSAlexander Motin (sense_src->error_code & SSD_ERRCODE_VALID) ? 205130f4520SKenneth D. Merry SSD_ELEM_INFO : SSD_ELEM_SKIP, 206130f4520SKenneth D. Merry sizeof(sense_src->info), 207130f4520SKenneth D. Merry sense_src->info, 208130f4520SKenneth D. Merry 209130f4520SKenneth D. Merry /* Command specific bytes */ 210130f4520SKenneth D. Merry (scsi_4btoul(sense_src->cmd_spec_info) != 0) ? 211130f4520SKenneth D. Merry SSD_ELEM_COMMAND : SSD_ELEM_SKIP, 212130f4520SKenneth D. Merry sizeof(sense_src->cmd_spec_info), 213130f4520SKenneth D. Merry sense_src->cmd_spec_info, 214130f4520SKenneth D. Merry 215130f4520SKenneth D. Merry /* FRU */ 216130f4520SKenneth D. Merry (sense_src->fru != 0) ? 217130f4520SKenneth D. Merry SSD_ELEM_FRU : SSD_ELEM_SKIP, 218130f4520SKenneth D. Merry sizeof(sense_src->fru), 219130f4520SKenneth D. Merry &sense_src->fru, 220130f4520SKenneth D. Merry 221130f4520SKenneth D. Merry /* Sense Key Specific */ 222130f4520SKenneth D. Merry (sense_src->sense_key_spec[0] & SSD_SCS_VALID) ? 223130f4520SKenneth D. Merry SSD_ELEM_SKS : SSD_ELEM_SKIP, 224130f4520SKenneth D. Merry sizeof(sense_src->sense_key_spec), 225130f4520SKenneth D. Merry sense_src->sense_key_spec, 226130f4520SKenneth D. Merry 227130f4520SKenneth D. Merry /* Tape bits */ 228130f4520SKenneth D. Merry (stream_bits != 0) ? 229130f4520SKenneth D. Merry SSD_ELEM_STREAM : SSD_ELEM_SKIP, 230130f4520SKenneth D. Merry sizeof(stream_bits), 231130f4520SKenneth D. Merry &stream_bits, 232130f4520SKenneth D. Merry 233130f4520SKenneth D. Merry SSD_ELEM_NONE); 234130f4520SKenneth D. Merry } 235130f4520SKenneth D. Merry 236130f4520SKenneth D. Merry /* 237130f4520SKenneth D. Merry * Transform descriptor format sense data into fixed sense data. 238130f4520SKenneth D. Merry * 239130f4520SKenneth D. Merry * Some data may be lost in translation, because there are descriptors 240130f4520SKenneth D. Merry * thant can't be represented as fixed sense data. 241130f4520SKenneth D. Merry * 242130f4520SKenneth D. Merry * For simplicity's sake, we assume that both sense structures are 243130f4520SKenneth D. Merry * SSD_FULL_SIZE. Otherwise, the logic gets more complicated. 244130f4520SKenneth D. Merry */ 245130f4520SKenneth D. Merry void 246130f4520SKenneth D. Merry ctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src, 247130f4520SKenneth D. Merry struct scsi_sense_data_fixed *sense_dest) 248130f4520SKenneth D. Merry { 249130f4520SKenneth D. Merry int current_error; 250130f4520SKenneth D. Merry uint8_t *info_ptr = NULL, *cmd_ptr = NULL, *fru_ptr = NULL; 251130f4520SKenneth D. Merry uint8_t *sks_ptr = NULL, *stream_ptr = NULL; 252130f4520SKenneth D. Merry int info_size = 0, cmd_size = 0, fru_size = 0; 253130f4520SKenneth D. Merry int sks_size = 0, stream_size = 0; 254130f4520SKenneth D. Merry int pos; 2554fc0d1d7SAlexander Motin u_int sense_len; 256130f4520SKenneth D. Merry 257130f4520SKenneth D. Merry if ((sense_src->error_code & SSD_ERRCODE) == SSD_DESC_CURRENT_ERROR) 258130f4520SKenneth D. Merry current_error = 1; 259130f4520SKenneth D. Merry else 260130f4520SKenneth D. Merry current_error = 0; 261130f4520SKenneth D. Merry 262130f4520SKenneth D. Merry for (pos = 0; pos < (int)(sense_src->extra_len - 1);) { 263130f4520SKenneth D. Merry struct scsi_sense_desc_header *header; 264130f4520SKenneth D. Merry 265130f4520SKenneth D. Merry header = (struct scsi_sense_desc_header *) 266130f4520SKenneth D. Merry &sense_src->sense_desc[pos]; 267130f4520SKenneth D. Merry 268130f4520SKenneth D. Merry /* 269130f4520SKenneth D. Merry * See if this record goes past the end of the sense data. 270130f4520SKenneth D. Merry * It shouldn't, but check just in case. 271130f4520SKenneth D. Merry */ 272130f4520SKenneth D. Merry if ((pos + header->length + sizeof(*header)) > 273130f4520SKenneth D. Merry sense_src->extra_len) 274130f4520SKenneth D. Merry break; 275130f4520SKenneth D. Merry 276130f4520SKenneth D. Merry switch (sense_src->sense_desc[pos]) { 277130f4520SKenneth D. Merry case SSD_DESC_INFO: { 278130f4520SKenneth D. Merry struct scsi_sense_info *info; 279130f4520SKenneth D. Merry 280130f4520SKenneth D. Merry info = (struct scsi_sense_info *)header; 281130f4520SKenneth D. Merry 282130f4520SKenneth D. Merry info_ptr = info->info; 283130f4520SKenneth D. Merry info_size = sizeof(info->info); 284130f4520SKenneth D. Merry 285130f4520SKenneth D. Merry pos += info->length + 286130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 287130f4520SKenneth D. Merry break; 288130f4520SKenneth D. Merry } 289130f4520SKenneth D. Merry case SSD_DESC_COMMAND: { 290130f4520SKenneth D. Merry struct scsi_sense_command *cmd; 291130f4520SKenneth D. Merry 292130f4520SKenneth D. Merry cmd = (struct scsi_sense_command *)header; 293130f4520SKenneth D. Merry cmd_ptr = cmd->command_info; 294130f4520SKenneth D. Merry cmd_size = sizeof(cmd->command_info); 295130f4520SKenneth D. Merry 296130f4520SKenneth D. Merry pos += cmd->length + 297130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 298130f4520SKenneth D. Merry break; 299130f4520SKenneth D. Merry } 300130f4520SKenneth D. Merry case SSD_DESC_FRU: { 301130f4520SKenneth D. Merry struct scsi_sense_fru *fru; 302130f4520SKenneth D. Merry 303130f4520SKenneth D. Merry fru = (struct scsi_sense_fru *)header; 304130f4520SKenneth D. Merry fru_ptr = &fru->fru; 305130f4520SKenneth D. Merry fru_size = sizeof(fru->fru); 306130f4520SKenneth D. Merry pos += fru->length + 307130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 308130f4520SKenneth D. Merry break; 309130f4520SKenneth D. Merry } 310130f4520SKenneth D. Merry case SSD_DESC_SKS: { 311130f4520SKenneth D. Merry struct scsi_sense_sks *sks; 312130f4520SKenneth D. Merry 313130f4520SKenneth D. Merry sks = (struct scsi_sense_sks *)header; 314130f4520SKenneth D. Merry sks_ptr = sks->sense_key_spec; 315130f4520SKenneth D. Merry sks_size = sizeof(sks->sense_key_spec); 316130f4520SKenneth D. Merry 317130f4520SKenneth D. Merry pos = sks->length + 318130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 319130f4520SKenneth D. Merry break; 320130f4520SKenneth D. Merry } 321130f4520SKenneth D. Merry case SSD_DESC_STREAM: { 322130f4520SKenneth D. Merry struct scsi_sense_stream *stream_sense; 323130f4520SKenneth D. Merry 324130f4520SKenneth D. Merry stream_sense = (struct scsi_sense_stream *)header; 325130f4520SKenneth D. Merry stream_ptr = &stream_sense->byte3; 326130f4520SKenneth D. Merry stream_size = sizeof(stream_sense->byte3); 327130f4520SKenneth D. Merry pos = stream_sense->length + 328130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 329130f4520SKenneth D. Merry break; 330130f4520SKenneth D. Merry } 331130f4520SKenneth D. Merry default: 332130f4520SKenneth D. Merry /* 333130f4520SKenneth D. Merry * We don't recognize this particular sense 334130f4520SKenneth D. Merry * descriptor type, so just skip it. 335130f4520SKenneth D. Merry */ 336130f4520SKenneth D. Merry pos += sizeof(*header) + header->length; 337130f4520SKenneth D. Merry break; 338130f4520SKenneth D. Merry } 339130f4520SKenneth D. Merry } 340130f4520SKenneth D. Merry 3414fc0d1d7SAlexander Motin sense_len = SSD_FULL_SIZE; 3424fc0d1d7SAlexander Motin ctl_set_sense_data((struct scsi_sense_data *)sense_dest, &sense_len, 343130f4520SKenneth D. Merry /*lun*/ NULL, 344130f4520SKenneth D. Merry /*sense_format*/ SSD_TYPE_FIXED, 345130f4520SKenneth D. Merry current_error, 346130f4520SKenneth D. Merry /*sense_key*/ sense_src->sense_key & SSD_KEY, 347130f4520SKenneth D. Merry /*asc*/ sense_src->add_sense_code, 348130f4520SKenneth D. Merry /*ascq*/ sense_src->add_sense_code_qual, 349130f4520SKenneth D. Merry 350130f4520SKenneth D. Merry /* Information Bytes */ 351130f4520SKenneth D. Merry (info_ptr != NULL) ? SSD_ELEM_INFO : SSD_ELEM_SKIP, 352130f4520SKenneth D. Merry info_size, 353130f4520SKenneth D. Merry info_ptr, 354130f4520SKenneth D. Merry 355130f4520SKenneth D. Merry /* Command specific bytes */ 356130f4520SKenneth D. Merry (cmd_ptr != NULL) ? SSD_ELEM_COMMAND : SSD_ELEM_SKIP, 357130f4520SKenneth D. Merry cmd_size, 358130f4520SKenneth D. Merry cmd_ptr, 359130f4520SKenneth D. Merry 360130f4520SKenneth D. Merry /* FRU */ 361130f4520SKenneth D. Merry (fru_ptr != NULL) ? SSD_ELEM_FRU : SSD_ELEM_SKIP, 362130f4520SKenneth D. Merry fru_size, 363130f4520SKenneth D. Merry fru_ptr, 364130f4520SKenneth D. Merry 365130f4520SKenneth D. Merry /* Sense Key Specific */ 366130f4520SKenneth D. Merry (sks_ptr != NULL) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 367130f4520SKenneth D. Merry sks_size, 368130f4520SKenneth D. Merry sks_ptr, 369130f4520SKenneth D. Merry 370130f4520SKenneth D. Merry /* Tape bits */ 371130f4520SKenneth D. Merry (stream_ptr != NULL) ? SSD_ELEM_STREAM : SSD_ELEM_SKIP, 372130f4520SKenneth D. Merry stream_size, 373130f4520SKenneth D. Merry stream_ptr, 374130f4520SKenneth D. Merry 375130f4520SKenneth D. Merry SSD_ELEM_NONE); 376130f4520SKenneth D. Merry } 377130f4520SKenneth D. Merry 378130f4520SKenneth D. Merry void 379130f4520SKenneth D. Merry ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq) 380130f4520SKenneth D. Merry { 381130f4520SKenneth D. Merry ctl_set_sense(ctsio, 382130f4520SKenneth D. Merry /*current_error*/ 1, 383130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_UNIT_ATTENTION, 384130f4520SKenneth D. Merry asc, 385130f4520SKenneth D. Merry ascq, 386130f4520SKenneth D. Merry SSD_ELEM_NONE); 387130f4520SKenneth D. Merry } 388130f4520SKenneth D. Merry 389ceff31dcSAlexander Motin static void 390c329b295SAlexander Motin ctl_ua_to_ascq(struct ctl_lun *lun, ctl_ua_type ua_to_build, int *asc, 39162138827SAlexander Motin int *ascq, ctl_ua_type *ua_to_clear, uint8_t **info) 392ceff31dcSAlexander Motin { 393ceff31dcSAlexander Motin 394ceff31dcSAlexander Motin switch (ua_to_build) { 395ceff31dcSAlexander Motin case CTL_UA_POWERON: 396ceff31dcSAlexander Motin /* 29h/01h POWER ON OCCURRED */ 397ceff31dcSAlexander Motin *asc = 0x29; 398ceff31dcSAlexander Motin *ascq = 0x01; 399ceff31dcSAlexander Motin *ua_to_clear = ~0; 400ceff31dcSAlexander Motin break; 401ceff31dcSAlexander Motin case CTL_UA_BUS_RESET: 402ceff31dcSAlexander Motin /* 29h/02h SCSI BUS RESET OCCURRED */ 403ceff31dcSAlexander Motin *asc = 0x29; 404ceff31dcSAlexander Motin *ascq = 0x02; 405ceff31dcSAlexander Motin *ua_to_clear = ~0; 406ceff31dcSAlexander Motin break; 407ceff31dcSAlexander Motin case CTL_UA_TARG_RESET: 408ceff31dcSAlexander Motin /* 29h/03h BUS DEVICE RESET FUNCTION OCCURRED*/ 409ceff31dcSAlexander Motin *asc = 0x29; 410ceff31dcSAlexander Motin *ascq = 0x03; 411ceff31dcSAlexander Motin *ua_to_clear = ~0; 412ceff31dcSAlexander Motin break; 413ceff31dcSAlexander Motin case CTL_UA_I_T_NEXUS_LOSS: 414ceff31dcSAlexander Motin /* 29h/07h I_T NEXUS LOSS OCCURRED */ 415ceff31dcSAlexander Motin *asc = 0x29; 416ceff31dcSAlexander Motin *ascq = 0x07; 417ceff31dcSAlexander Motin *ua_to_clear = ~0; 418ceff31dcSAlexander Motin break; 419ceff31dcSAlexander Motin case CTL_UA_LUN_RESET: 420ceff31dcSAlexander Motin /* 29h/00h POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */ 421ceff31dcSAlexander Motin /* 422ceff31dcSAlexander Motin * Since we don't have a specific ASC/ASCQ pair for a LUN 423ceff31dcSAlexander Motin * reset, just return the generic reset code. 424ceff31dcSAlexander Motin */ 425ceff31dcSAlexander Motin *asc = 0x29; 426ceff31dcSAlexander Motin *ascq = 0x00; 427ceff31dcSAlexander Motin break; 428ceff31dcSAlexander Motin case CTL_UA_LUN_CHANGE: 429ceff31dcSAlexander Motin /* 3Fh/0Eh REPORTED LUNS DATA HAS CHANGED */ 430ceff31dcSAlexander Motin *asc = 0x3F; 431ceff31dcSAlexander Motin *ascq = 0x0E; 432ceff31dcSAlexander Motin break; 433ceff31dcSAlexander Motin case CTL_UA_MODE_CHANGE: 434ceff31dcSAlexander Motin /* 2Ah/01h MODE PARAMETERS CHANGED */ 435ceff31dcSAlexander Motin *asc = 0x2A; 436ceff31dcSAlexander Motin *ascq = 0x01; 437ceff31dcSAlexander Motin break; 438ceff31dcSAlexander Motin case CTL_UA_LOG_CHANGE: 439ceff31dcSAlexander Motin /* 2Ah/02h LOG PARAMETERS CHANGED */ 440ceff31dcSAlexander Motin *asc = 0x2A; 441ceff31dcSAlexander Motin *ascq = 0x02; 442ceff31dcSAlexander Motin break; 443ceff31dcSAlexander Motin case CTL_UA_INQ_CHANGE: 444ceff31dcSAlexander Motin /* 3Fh/03h INQUIRY DATA HAS CHANGED */ 445ceff31dcSAlexander Motin *asc = 0x3F; 446ceff31dcSAlexander Motin *ascq = 0x03; 447ceff31dcSAlexander Motin break; 448ceff31dcSAlexander Motin case CTL_UA_RES_PREEMPT: 449ceff31dcSAlexander Motin /* 2Ah/03h RESERVATIONS PREEMPTED */ 450ceff31dcSAlexander Motin *asc = 0x2A; 451ceff31dcSAlexander Motin *ascq = 0x03; 452ceff31dcSAlexander Motin break; 453ceff31dcSAlexander Motin case CTL_UA_RES_RELEASE: 454ceff31dcSAlexander Motin /* 2Ah/04h RESERVATIONS RELEASED */ 455ceff31dcSAlexander Motin *asc = 0x2A; 456ceff31dcSAlexander Motin *ascq = 0x04; 457ceff31dcSAlexander Motin break; 458ceff31dcSAlexander Motin case CTL_UA_REG_PREEMPT: 459ceff31dcSAlexander Motin /* 2Ah/05h REGISTRATIONS PREEMPTED */ 460ceff31dcSAlexander Motin *asc = 0x2A; 461ceff31dcSAlexander Motin *ascq = 0x05; 462ceff31dcSAlexander Motin break; 463ceff31dcSAlexander Motin case CTL_UA_ASYM_ACC_CHANGE: 464ceff31dcSAlexander Motin /* 2Ah/06h ASYMMETRIC ACCESS STATE CHANGED */ 465ceff31dcSAlexander Motin *asc = 0x2A; 466ceff31dcSAlexander Motin *ascq = 0x06; 467ceff31dcSAlexander Motin break; 468648dfc1aSAlexander Motin case CTL_UA_CAPACITY_CHANGE: 469ceff31dcSAlexander Motin /* 2Ah/09h CAPACITY DATA HAS CHANGED */ 470ceff31dcSAlexander Motin *asc = 0x2A; 471ceff31dcSAlexander Motin *ascq = 0x09; 472ceff31dcSAlexander Motin break; 473ceff31dcSAlexander Motin case CTL_UA_THIN_PROV_THRES: 474ceff31dcSAlexander Motin /* 38h/07h THIN PROVISIONING SOFT THRESHOLD REACHED */ 475ceff31dcSAlexander Motin *asc = 0x38; 476ceff31dcSAlexander Motin *ascq = 0x07; 47762138827SAlexander Motin *info = lun->ua_tpt_info; 478ceff31dcSAlexander Motin break; 479648dfc1aSAlexander Motin case CTL_UA_MEDIUM_CHANGE: 480648dfc1aSAlexander Motin /* 28h/00h NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */ 481648dfc1aSAlexander Motin *asc = 0x28; 482648dfc1aSAlexander Motin *ascq = 0x00; 483648dfc1aSAlexander Motin break; 484d9ba4eefSAlexander Motin case CTL_UA_IE: 485d9ba4eefSAlexander Motin /* Informational exception */ 486d9ba4eefSAlexander Motin *asc = lun->ie_asc; 487d9ba4eefSAlexander Motin *ascq = lun->ie_ascq; 488d9ba4eefSAlexander Motin break; 489ceff31dcSAlexander Motin default: 490ceff31dcSAlexander Motin panic("%s: Unknown UA %x", __func__, ua_to_build); 491ceff31dcSAlexander Motin } 492ceff31dcSAlexander Motin } 493ceff31dcSAlexander Motin 494ceff31dcSAlexander Motin ctl_ua_type 495ceff31dcSAlexander Motin ctl_build_qae(struct ctl_lun *lun, uint32_t initidx, uint8_t *resp) 496ceff31dcSAlexander Motin { 497ceff31dcSAlexander Motin ctl_ua_type ua; 498ceff31dcSAlexander Motin ctl_ua_type ua_to_build, ua_to_clear; 49962138827SAlexander Motin uint8_t *info; 500ceff31dcSAlexander Motin int asc, ascq; 501ceff31dcSAlexander Motin uint32_t p, i; 502ceff31dcSAlexander Motin 503ceff31dcSAlexander Motin mtx_assert(&lun->lun_lock, MA_OWNED); 504ceff31dcSAlexander Motin p = initidx / CTL_MAX_INIT_PER_PORT; 505ceff31dcSAlexander Motin i = initidx % CTL_MAX_INIT_PER_PORT; 506ceff31dcSAlexander Motin if (lun->pending_ua[p] == NULL) 507ceff31dcSAlexander Motin ua = CTL_UA_POWERON; 508ceff31dcSAlexander Motin else 509ceff31dcSAlexander Motin ua = lun->pending_ua[p][i]; 510ceff31dcSAlexander Motin if (ua == CTL_UA_NONE) 511ceff31dcSAlexander Motin return (CTL_UA_NONE); 512ceff31dcSAlexander Motin 513ceff31dcSAlexander Motin ua_to_build = (1 << (ffs(ua) - 1)); 514ceff31dcSAlexander Motin ua_to_clear = ua_to_build; 51562138827SAlexander Motin info = NULL; 516c329b295SAlexander Motin ctl_ua_to_ascq(lun, ua_to_build, &asc, &ascq, &ua_to_clear, &info); 517ceff31dcSAlexander Motin 518ceff31dcSAlexander Motin resp[0] = SSD_KEY_UNIT_ATTENTION; 519ceff31dcSAlexander Motin if (ua_to_build == ua) 520ceff31dcSAlexander Motin resp[0] |= 0x10; 521ceff31dcSAlexander Motin else 522ceff31dcSAlexander Motin resp[0] |= 0x20; 523ceff31dcSAlexander Motin resp[1] = asc; 524ceff31dcSAlexander Motin resp[2] = ascq; 5254fc0d1d7SAlexander Motin return (ua_to_build); 526ceff31dcSAlexander Motin } 527ceff31dcSAlexander Motin 528130f4520SKenneth D. Merry ctl_ua_type 5299e525653SAlexander Motin ctl_build_ua(struct ctl_lun *lun, uint32_t initidx, 5304fc0d1d7SAlexander Motin struct scsi_sense_data *sense, u_int *sense_len, 5314fc0d1d7SAlexander Motin scsi_sense_data_type sense_format) 532130f4520SKenneth D. Merry { 5339e525653SAlexander Motin ctl_ua_type *ua; 5348f07b2d5SAlexander Motin ctl_ua_type ua_to_build, ua_to_clear; 53562138827SAlexander Motin uint8_t *info; 5368f07b2d5SAlexander Motin int asc, ascq; 5379e525653SAlexander Motin uint32_t p, i; 538130f4520SKenneth D. Merry 5399e525653SAlexander Motin mtx_assert(&lun->lun_lock, MA_OWNED); 54033e7ba9cSAlexander Motin mtx_assert(&lun->ctl_softc->ctl_lock, MA_NOTOWNED); 5419e525653SAlexander Motin p = initidx / CTL_MAX_INIT_PER_PORT; 5429e525653SAlexander Motin if ((ua = lun->pending_ua[p]) == NULL) { 5439e525653SAlexander Motin mtx_unlock(&lun->lun_lock); 5449e525653SAlexander Motin ua = malloc(sizeof(ctl_ua_type) * CTL_MAX_INIT_PER_PORT, 5459e525653SAlexander Motin M_CTL, M_WAITOK); 5469e525653SAlexander Motin mtx_lock(&lun->lun_lock); 5479e525653SAlexander Motin if (lun->pending_ua[p] == NULL) { 5489e525653SAlexander Motin lun->pending_ua[p] = ua; 5499e525653SAlexander Motin for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++) 5509e525653SAlexander Motin ua[i] = CTL_UA_POWERON; 5519e525653SAlexander Motin } else { 5529e525653SAlexander Motin free(ua, M_CTL); 5539e525653SAlexander Motin ua = lun->pending_ua[p]; 5549e525653SAlexander Motin } 5559e525653SAlexander Motin } 5569e525653SAlexander Motin i = initidx % CTL_MAX_INIT_PER_PORT; 5579e525653SAlexander Motin if (ua[i] == CTL_UA_NONE) 5588f07b2d5SAlexander Motin return (CTL_UA_NONE); 559130f4520SKenneth D. Merry 5609e525653SAlexander Motin ua_to_build = (1 << (ffs(ua[i]) - 1)); 5618f07b2d5SAlexander Motin ua_to_clear = ua_to_build; 56262138827SAlexander Motin info = NULL; 563c329b295SAlexander Motin ctl_ua_to_ascq(lun, ua_to_build, &asc, &ascq, &ua_to_clear, &info); 564130f4520SKenneth D. Merry 5654fc0d1d7SAlexander Motin ctl_set_sense_data(sense, sense_len, lun, sense_format, 1, 56662138827SAlexander Motin /*sense_key*/ SSD_KEY_UNIT_ATTENTION, asc, ascq, 56762138827SAlexander Motin ((info != NULL) ? SSD_ELEM_INFO : SSD_ELEM_SKIP), 8, info, 568130f4520SKenneth D. Merry SSD_ELEM_NONE); 569130f4520SKenneth D. Merry 5708f07b2d5SAlexander Motin /* We're reporting this UA, so clear it */ 5719e525653SAlexander Motin ua[i] &= ~ua_to_clear; 5728f07b2d5SAlexander Motin 57333e7ba9cSAlexander Motin if (ua_to_build == CTL_UA_LUN_CHANGE) { 57433e7ba9cSAlexander Motin mtx_unlock(&lun->lun_lock); 57533e7ba9cSAlexander Motin mtx_lock(&lun->ctl_softc->ctl_lock); 57633e7ba9cSAlexander Motin ctl_clr_ua_allluns(lun->ctl_softc, initidx, ua_to_build); 57733e7ba9cSAlexander Motin mtx_unlock(&lun->ctl_softc->ctl_lock); 57833e7ba9cSAlexander Motin mtx_lock(&lun->lun_lock); 57933e7ba9cSAlexander Motin } else if (ua_to_build == CTL_UA_THIN_PROV_THRES && 58033e7ba9cSAlexander Motin (lun->MODE_LBP.main.flags & SLBPP_SITUA) != 0) { 58133e7ba9cSAlexander Motin ctl_clr_ua_all(lun, -1, ua_to_build); 58233e7ba9cSAlexander Motin } 58333e7ba9cSAlexander Motin 584130f4520SKenneth D. Merry return (ua_to_build); 585130f4520SKenneth D. Merry } 586130f4520SKenneth D. Merry 587130f4520SKenneth D. Merry void 588130f4520SKenneth D. Merry ctl_set_overlapped_cmd(struct ctl_scsiio *ctsio) 589130f4520SKenneth D. Merry { 590130f4520SKenneth D. Merry /* OVERLAPPED COMMANDS ATTEMPTED */ 591130f4520SKenneth D. Merry ctl_set_sense(ctsio, 592130f4520SKenneth D. Merry /*current_error*/ 1, 593130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 594130f4520SKenneth D. Merry /*asc*/ 0x4E, 595130f4520SKenneth D. Merry /*ascq*/ 0x00, 596130f4520SKenneth D. Merry SSD_ELEM_NONE); 597130f4520SKenneth D. Merry } 598130f4520SKenneth D. Merry 599130f4520SKenneth D. Merry void 600130f4520SKenneth D. Merry ctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag) 601130f4520SKenneth D. Merry { 602130f4520SKenneth D. Merry /* TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG) */ 603130f4520SKenneth D. Merry ctl_set_sense(ctsio, 604130f4520SKenneth D. Merry /*current_error*/ 1, 605130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 606130f4520SKenneth D. Merry /*asc*/ 0x4D, 607130f4520SKenneth D. Merry /*ascq*/ tag, 608130f4520SKenneth D. Merry SSD_ELEM_NONE); 609130f4520SKenneth D. Merry } 610130f4520SKenneth D. Merry 611130f4520SKenneth D. Merry /* 612130f4520SKenneth D. Merry * Tell the user that there was a problem with the command or data he sent. 613130f4520SKenneth D. Merry */ 614130f4520SKenneth D. Merry void 615130f4520SKenneth D. Merry ctl_set_invalid_field(struct ctl_scsiio *ctsio, int sks_valid, int command, 616130f4520SKenneth D. Merry int field, int bit_valid, int bit) 617130f4520SKenneth D. Merry { 618130f4520SKenneth D. Merry uint8_t sks[3]; 619130f4520SKenneth D. Merry int asc; 620130f4520SKenneth D. Merry 621130f4520SKenneth D. Merry if (command != 0) { 622130f4520SKenneth D. Merry /* "Invalid field in CDB" */ 623130f4520SKenneth D. Merry asc = 0x24; 624130f4520SKenneth D. Merry } else { 625130f4520SKenneth D. Merry /* "Invalid field in parameter list" */ 626130f4520SKenneth D. Merry asc = 0x26; 627130f4520SKenneth D. Merry } 628130f4520SKenneth D. Merry 629130f4520SKenneth D. Merry if (sks_valid) { 630130f4520SKenneth D. Merry sks[0] = SSD_SCS_VALID; 631130f4520SKenneth D. Merry if (command) 632130f4520SKenneth D. Merry sks[0] |= SSD_FIELDPTR_CMD; 633130f4520SKenneth D. Merry scsi_ulto2b(field, &sks[1]); 634130f4520SKenneth D. Merry 635130f4520SKenneth D. Merry if (bit_valid) 636130f4520SKenneth D. Merry sks[0] |= SSD_BITPTR_VALID | bit; 637130f4520SKenneth D. Merry } 638130f4520SKenneth D. Merry 639130f4520SKenneth D. Merry ctl_set_sense(ctsio, 640130f4520SKenneth D. Merry /*current_error*/ 1, 641130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 642130f4520SKenneth D. Merry asc, 643130f4520SKenneth D. Merry /*ascq*/ 0x00, 644130f4520SKenneth D. Merry /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 645130f4520SKenneth D. Merry /*size*/ sizeof(sks), 646130f4520SKenneth D. Merry /*data*/ sks, 647130f4520SKenneth D. Merry SSD_ELEM_NONE); 648130f4520SKenneth D. Merry } 649eb6ac6f9SAlexander Motin void 650eb6ac6f9SAlexander Motin ctl_set_invalid_field_ciu(struct ctl_scsiio *ctsio) 651eb6ac6f9SAlexander Motin { 652eb6ac6f9SAlexander Motin 653eb6ac6f9SAlexander Motin /* "Invalid field in command information unit" */ 654eb6ac6f9SAlexander Motin ctl_set_sense(ctsio, 655eb6ac6f9SAlexander Motin /*current_error*/ 1, 656eb6ac6f9SAlexander Motin /*sense_key*/ SSD_KEY_ABORTED_COMMAND, 657eb6ac6f9SAlexander Motin /*ascq*/ 0x0E, 658eb6ac6f9SAlexander Motin /*ascq*/ 0x03, 659eb6ac6f9SAlexander Motin SSD_ELEM_NONE); 660eb6ac6f9SAlexander Motin } 661130f4520SKenneth D. Merry 662130f4520SKenneth D. Merry void 663130f4520SKenneth D. Merry ctl_set_invalid_opcode(struct ctl_scsiio *ctsio) 664130f4520SKenneth D. Merry { 665130f4520SKenneth D. Merry uint8_t sks[3]; 666130f4520SKenneth D. Merry 667130f4520SKenneth D. Merry sks[0] = SSD_SCS_VALID | SSD_FIELDPTR_CMD; 668130f4520SKenneth D. Merry scsi_ulto2b(0, &sks[1]); 669130f4520SKenneth D. Merry 670130f4520SKenneth D. Merry /* "Invalid command operation code" */ 671130f4520SKenneth D. Merry ctl_set_sense(ctsio, 672130f4520SKenneth D. Merry /*current_error*/ 1, 673130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 674130f4520SKenneth D. Merry /*asc*/ 0x20, 675130f4520SKenneth D. Merry /*ascq*/ 0x00, 676130f4520SKenneth D. Merry /*type*/ SSD_ELEM_SKS, 677130f4520SKenneth D. Merry /*size*/ sizeof(sks), 678130f4520SKenneth D. Merry /*data*/ sks, 679130f4520SKenneth D. Merry SSD_ELEM_NONE); 680130f4520SKenneth D. Merry } 681130f4520SKenneth D. Merry 682130f4520SKenneth D. Merry void 683130f4520SKenneth D. Merry ctl_set_param_len_error(struct ctl_scsiio *ctsio) 684130f4520SKenneth D. Merry { 685130f4520SKenneth D. Merry /* "Parameter list length error" */ 686130f4520SKenneth D. Merry ctl_set_sense(ctsio, 687130f4520SKenneth D. Merry /*current_error*/ 1, 688130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 689130f4520SKenneth D. Merry /*asc*/ 0x1a, 690130f4520SKenneth D. Merry /*ascq*/ 0x00, 691130f4520SKenneth D. Merry SSD_ELEM_NONE); 692130f4520SKenneth D. Merry } 693130f4520SKenneth D. Merry 694130f4520SKenneth D. Merry void 695130f4520SKenneth D. Merry ctl_set_already_locked(struct ctl_scsiio *ctsio) 696130f4520SKenneth D. Merry { 697130f4520SKenneth D. Merry /* Vendor unique "Somebody already is locked" */ 698130f4520SKenneth D. Merry ctl_set_sense(ctsio, 699130f4520SKenneth D. Merry /*current_error*/ 1, 700130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 701130f4520SKenneth D. Merry /*asc*/ 0x81, 702130f4520SKenneth D. Merry /*ascq*/ 0x00, 703130f4520SKenneth D. Merry SSD_ELEM_NONE); 704130f4520SKenneth D. Merry } 705130f4520SKenneth D. Merry 706130f4520SKenneth D. Merry void 707130f4520SKenneth D. Merry ctl_set_unsupported_lun(struct ctl_scsiio *ctsio) 708130f4520SKenneth D. Merry { 709130f4520SKenneth D. Merry /* "Logical unit not supported" */ 710130f4520SKenneth D. Merry ctl_set_sense(ctsio, 711130f4520SKenneth D. Merry /*current_error*/ 1, 712130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 713130f4520SKenneth D. Merry /*asc*/ 0x25, 714130f4520SKenneth D. Merry /*ascq*/ 0x00, 715130f4520SKenneth D. Merry SSD_ELEM_NONE); 716130f4520SKenneth D. Merry } 717130f4520SKenneth D. Merry 718130f4520SKenneth D. Merry void 719130f4520SKenneth D. Merry ctl_set_internal_failure(struct ctl_scsiio *ctsio, int sks_valid, 720130f4520SKenneth D. Merry uint16_t retry_count) 721130f4520SKenneth D. Merry { 722130f4520SKenneth D. Merry uint8_t sks[3]; 723130f4520SKenneth D. Merry 724130f4520SKenneth D. Merry if (sks_valid) { 725130f4520SKenneth D. Merry sks[0] = SSD_SCS_VALID; 726130f4520SKenneth D. Merry sks[1] = (retry_count >> 8) & 0xff; 727130f4520SKenneth D. Merry sks[2] = retry_count & 0xff; 728130f4520SKenneth D. Merry } 729130f4520SKenneth D. Merry 730130f4520SKenneth D. Merry /* "Internal target failure" */ 731130f4520SKenneth D. Merry ctl_set_sense(ctsio, 732130f4520SKenneth D. Merry /*current_error*/ 1, 733130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_HARDWARE_ERROR, 734130f4520SKenneth D. Merry /*asc*/ 0x44, 735130f4520SKenneth D. Merry /*ascq*/ 0x00, 736130f4520SKenneth D. Merry /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 737130f4520SKenneth D. Merry /*size*/ sizeof(sks), 738130f4520SKenneth D. Merry /*data*/ sks, 739130f4520SKenneth D. Merry SSD_ELEM_NONE); 740130f4520SKenneth D. Merry } 741130f4520SKenneth D. Merry 742130f4520SKenneth D. Merry void 7437f7bb97aSAlexander Motin ctl_set_medium_error(struct ctl_scsiio *ctsio, int read) 744130f4520SKenneth D. Merry { 7457f7bb97aSAlexander Motin if (read) { 746130f4520SKenneth D. Merry /* "Unrecovered read error" */ 747130f4520SKenneth D. Merry ctl_set_sense(ctsio, 748130f4520SKenneth D. Merry /*current_error*/ 1, 749130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 750130f4520SKenneth D. Merry /*asc*/ 0x11, 751130f4520SKenneth D. Merry /*ascq*/ 0x00, 752130f4520SKenneth D. Merry SSD_ELEM_NONE); 753130f4520SKenneth D. Merry } else { 754130f4520SKenneth D. Merry /* "Write error - auto reallocation failed" */ 755130f4520SKenneth D. Merry ctl_set_sense(ctsio, 756130f4520SKenneth D. Merry /*current_error*/ 1, 757130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 758130f4520SKenneth D. Merry /*asc*/ 0x0C, 759130f4520SKenneth D. Merry /*ascq*/ 0x02, 760130f4520SKenneth D. Merry SSD_ELEM_NONE); 761130f4520SKenneth D. Merry } 762130f4520SKenneth D. Merry } 763130f4520SKenneth D. Merry 764130f4520SKenneth D. Merry void 765130f4520SKenneth D. Merry ctl_set_aborted(struct ctl_scsiio *ctsio) 766130f4520SKenneth D. Merry { 767130f4520SKenneth D. Merry ctl_set_sense(ctsio, 768130f4520SKenneth D. Merry /*current_error*/ 1, 769130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ABORTED_COMMAND, 770130f4520SKenneth D. Merry /*asc*/ 0x45, 771130f4520SKenneth D. Merry /*ascq*/ 0x00, 772130f4520SKenneth D. Merry SSD_ELEM_NONE); 773130f4520SKenneth D. Merry } 774130f4520SKenneth D. Merry 775130f4520SKenneth D. Merry void 77632920cbfSAlexander Motin ctl_set_lba_out_of_range(struct ctl_scsiio *ctsio, uint64_t lba) 777130f4520SKenneth D. Merry { 77832920cbfSAlexander Motin uint8_t info[8]; 77932920cbfSAlexander Motin 78032920cbfSAlexander Motin scsi_u64to8b(lba, info); 78132920cbfSAlexander Motin 782130f4520SKenneth D. Merry /* "Logical block address out of range" */ 783130f4520SKenneth D. Merry ctl_set_sense(ctsio, 784130f4520SKenneth D. Merry /*current_error*/ 1, 785130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 786130f4520SKenneth D. Merry /*asc*/ 0x21, 787130f4520SKenneth D. Merry /*ascq*/ 0x00, 78832920cbfSAlexander Motin /*type*/ (lba != 0) ? SSD_ELEM_INFO : SSD_ELEM_SKIP, 78932920cbfSAlexander Motin /*size*/ sizeof(info), /*data*/ &info, 790130f4520SKenneth D. Merry SSD_ELEM_NONE); 791130f4520SKenneth D. Merry } 792130f4520SKenneth D. Merry 793130f4520SKenneth D. Merry void 794130f4520SKenneth D. Merry ctl_set_lun_stopped(struct ctl_scsiio *ctsio) 795130f4520SKenneth D. Merry { 796130f4520SKenneth D. Merry /* "Logical unit not ready, initializing cmd. required" */ 797130f4520SKenneth D. Merry ctl_set_sense(ctsio, 798130f4520SKenneth D. Merry /*current_error*/ 1, 799130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 800130f4520SKenneth D. Merry /*asc*/ 0x04, 801130f4520SKenneth D. Merry /*ascq*/ 0x02, 802130f4520SKenneth D. Merry SSD_ELEM_NONE); 803130f4520SKenneth D. Merry } 804130f4520SKenneth D. Merry 805130f4520SKenneth D. Merry void 806648dfc1aSAlexander Motin ctl_set_lun_int_reqd(struct ctl_scsiio *ctsio) 807130f4520SKenneth D. Merry { 808130f4520SKenneth D. Merry /* "Logical unit not ready, manual intervention required" */ 809130f4520SKenneth D. Merry ctl_set_sense(ctsio, 810130f4520SKenneth D. Merry /*current_error*/ 1, 811130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 812130f4520SKenneth D. Merry /*asc*/ 0x04, 813eebb09cfSAlexander Motin /*ascq*/ 0x03, 814130f4520SKenneth D. Merry SSD_ELEM_NONE); 815130f4520SKenneth D. Merry } 816130f4520SKenneth D. Merry 817130f4520SKenneth D. Merry void 818648dfc1aSAlexander Motin ctl_set_lun_ejected(struct ctl_scsiio *ctsio) 819648dfc1aSAlexander Motin { 820648dfc1aSAlexander Motin /* "Medium not present - tray open" */ 821648dfc1aSAlexander Motin ctl_set_sense(ctsio, 822648dfc1aSAlexander Motin /*current_error*/ 1, 823648dfc1aSAlexander Motin /*sense_key*/ SSD_KEY_NOT_READY, 824648dfc1aSAlexander Motin /*asc*/ 0x3A, 825648dfc1aSAlexander Motin /*ascq*/ 0x02, 826648dfc1aSAlexander Motin SSD_ELEM_NONE); 827648dfc1aSAlexander Motin } 828648dfc1aSAlexander Motin 829648dfc1aSAlexander Motin void 830648dfc1aSAlexander Motin ctl_set_lun_no_media(struct ctl_scsiio *ctsio) 831648dfc1aSAlexander Motin { 832648dfc1aSAlexander Motin /* "Medium not present - tray closed" */ 833648dfc1aSAlexander Motin ctl_set_sense(ctsio, 834648dfc1aSAlexander Motin /*current_error*/ 1, 835648dfc1aSAlexander Motin /*sense_key*/ SSD_KEY_NOT_READY, 836648dfc1aSAlexander Motin /*asc*/ 0x3A, 837648dfc1aSAlexander Motin /*ascq*/ 0x01, 838648dfc1aSAlexander Motin SSD_ELEM_NONE); 839648dfc1aSAlexander Motin } 840648dfc1aSAlexander Motin 841648dfc1aSAlexander Motin void 842130f4520SKenneth D. Merry ctl_set_illegal_pr_release(struct ctl_scsiio *ctsio) 843130f4520SKenneth D. Merry { 844130f4520SKenneth D. Merry /* "Invalid release of persistent reservation" */ 845130f4520SKenneth D. Merry ctl_set_sense(ctsio, 846130f4520SKenneth D. Merry /*current_error*/ 1, 847130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 848130f4520SKenneth D. Merry /*asc*/ 0x26, 849130f4520SKenneth D. Merry /*ascq*/ 0x04, 850130f4520SKenneth D. Merry SSD_ELEM_NONE); 851130f4520SKenneth D. Merry } 852130f4520SKenneth D. Merry 853130f4520SKenneth D. Merry void 8547ac58230SAlexander Motin ctl_set_lun_transit(struct ctl_scsiio *ctsio) 8557ac58230SAlexander Motin { 8567ac58230SAlexander Motin /* "Logical unit not ready, asymmetric access state transition" */ 8577ac58230SAlexander Motin ctl_set_sense(ctsio, 8587ac58230SAlexander Motin /*current_error*/ 1, 8597ac58230SAlexander Motin /*sense_key*/ SSD_KEY_NOT_READY, 8607ac58230SAlexander Motin /*asc*/ 0x04, 8617ac58230SAlexander Motin /*ascq*/ 0x0a, 8627ac58230SAlexander Motin SSD_ELEM_NONE); 8637ac58230SAlexander Motin } 8647ac58230SAlexander Motin 8657ac58230SAlexander Motin void 866130f4520SKenneth D. Merry ctl_set_lun_standby(struct ctl_scsiio *ctsio) 867130f4520SKenneth D. Merry { 868130f4520SKenneth D. Merry /* "Logical unit not ready, target port in standby state" */ 869130f4520SKenneth D. Merry ctl_set_sense(ctsio, 870130f4520SKenneth D. Merry /*current_error*/ 1, 871130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 872130f4520SKenneth D. Merry /*asc*/ 0x04, 873130f4520SKenneth D. Merry /*ascq*/ 0x0b, 874130f4520SKenneth D. Merry SSD_ELEM_NONE); 875130f4520SKenneth D. Merry } 876130f4520SKenneth D. Merry 877130f4520SKenneth D. Merry void 8787ac58230SAlexander Motin ctl_set_lun_unavail(struct ctl_scsiio *ctsio) 8797ac58230SAlexander Motin { 8807ac58230SAlexander Motin /* "Logical unit not ready, target port in unavailable state" */ 8817ac58230SAlexander Motin ctl_set_sense(ctsio, 8827ac58230SAlexander Motin /*current_error*/ 1, 8837ac58230SAlexander Motin /*sense_key*/ SSD_KEY_NOT_READY, 8847ac58230SAlexander Motin /*asc*/ 0x04, 8857ac58230SAlexander Motin /*ascq*/ 0x0c, 8867ac58230SAlexander Motin SSD_ELEM_NONE); 8877ac58230SAlexander Motin } 8887ac58230SAlexander Motin 8897ac58230SAlexander Motin void 890130f4520SKenneth D. Merry ctl_set_medium_format_corrupted(struct ctl_scsiio *ctsio) 891130f4520SKenneth D. Merry { 892130f4520SKenneth D. Merry /* "Medium format corrupted" */ 893130f4520SKenneth D. Merry ctl_set_sense(ctsio, 894130f4520SKenneth D. Merry /*current_error*/ 1, 895130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 896130f4520SKenneth D. Merry /*asc*/ 0x31, 897130f4520SKenneth D. Merry /*ascq*/ 0x00, 898130f4520SKenneth D. Merry SSD_ELEM_NONE); 899130f4520SKenneth D. Merry } 900130f4520SKenneth D. Merry 901130f4520SKenneth D. Merry void 902130f4520SKenneth D. Merry ctl_set_medium_magazine_inaccessible(struct ctl_scsiio *ctsio) 903130f4520SKenneth D. Merry { 904130f4520SKenneth D. Merry /* "Medium magazine not accessible" */ 905130f4520SKenneth D. Merry ctl_set_sense(ctsio, 906130f4520SKenneth D. Merry /*current_error*/ 1, 907130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 908130f4520SKenneth D. Merry /*asc*/ 0x3b, 909130f4520SKenneth D. Merry /*ascq*/ 0x11, 910130f4520SKenneth D. Merry SSD_ELEM_NONE); 911130f4520SKenneth D. Merry } 912130f4520SKenneth D. Merry 913130f4520SKenneth D. Merry void 914130f4520SKenneth D. Merry ctl_set_data_phase_error(struct ctl_scsiio *ctsio) 915130f4520SKenneth D. Merry { 916130f4520SKenneth D. Merry /* "Data phase error" */ 917130f4520SKenneth D. Merry ctl_set_sense(ctsio, 918130f4520SKenneth D. Merry /*current_error*/ 1, 919130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 920130f4520SKenneth D. Merry /*asc*/ 0x4b, 921130f4520SKenneth D. Merry /*ascq*/ 0x00, 922130f4520SKenneth D. Merry SSD_ELEM_NONE); 923130f4520SKenneth D. Merry } 924130f4520SKenneth D. Merry 925130f4520SKenneth D. Merry void 926130f4520SKenneth D. Merry ctl_set_reservation_conflict(struct ctl_scsiio *ctsio) 927130f4520SKenneth D. Merry { 928130f4520SKenneth D. Merry 929130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT; 930130f4520SKenneth D. Merry ctsio->sense_len = 0; 931130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SCSI_ERROR; 932130f4520SKenneth D. Merry } 933130f4520SKenneth D. Merry 934130f4520SKenneth D. Merry void 935130f4520SKenneth D. Merry ctl_set_queue_full(struct ctl_scsiio *ctsio) 936130f4520SKenneth D. Merry { 937130f4520SKenneth D. Merry 938130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_QUEUE_FULL; 939130f4520SKenneth D. Merry ctsio->sense_len = 0; 940130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SCSI_ERROR; 941130f4520SKenneth D. Merry } 942130f4520SKenneth D. Merry 943130f4520SKenneth D. Merry void 944130f4520SKenneth D. Merry ctl_set_busy(struct ctl_scsiio *ctsio) 945130f4520SKenneth D. Merry { 946130f4520SKenneth D. Merry 947130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_BUSY; 948130f4520SKenneth D. Merry ctsio->sense_len = 0; 949130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SCSI_ERROR; 950130f4520SKenneth D. Merry } 951130f4520SKenneth D. Merry 952130f4520SKenneth D. Merry void 953b33b96e3SAlexander Motin ctl_set_task_aborted(struct ctl_scsiio *ctsio) 954b33b96e3SAlexander Motin { 955b33b96e3SAlexander Motin 956b33b96e3SAlexander Motin ctsio->scsi_status = SCSI_STATUS_TASK_ABORTED; 957b33b96e3SAlexander Motin ctsio->sense_len = 0; 958b33b96e3SAlexander Motin ctsio->io_hdr.status = CTL_CMD_ABORTED; 959b33b96e3SAlexander Motin } 960b33b96e3SAlexander Motin 961b33b96e3SAlexander Motin void 9626187d472SAlexander Motin ctl_set_hw_write_protected(struct ctl_scsiio *ctsio) 9636187d472SAlexander Motin { 9646187d472SAlexander Motin /* "Hardware write protected" */ 9656187d472SAlexander Motin ctl_set_sense(ctsio, 9666187d472SAlexander Motin /*current_error*/ 1, 9676187d472SAlexander Motin /*sense_key*/ SSD_KEY_DATA_PROTECT, 9686187d472SAlexander Motin /*asc*/ 0x27, 9696187d472SAlexander Motin /*ascq*/ 0x01, 9706187d472SAlexander Motin SSD_ELEM_NONE); 9716187d472SAlexander Motin } 9726187d472SAlexander Motin 9736187d472SAlexander Motin void 9744fc18ff9SAlexander Motin ctl_set_space_alloc_fail(struct ctl_scsiio *ctsio) 9754fc18ff9SAlexander Motin { 9764fc18ff9SAlexander Motin /* "Space allocation failed write protect" */ 9774fc18ff9SAlexander Motin ctl_set_sense(ctsio, 9784fc18ff9SAlexander Motin /*current_error*/ 1, 9794fc18ff9SAlexander Motin /*sense_key*/ SSD_KEY_DATA_PROTECT, 9804fc18ff9SAlexander Motin /*asc*/ 0x27, 9814fc18ff9SAlexander Motin /*ascq*/ 0x07, 9824fc18ff9SAlexander Motin SSD_ELEM_NONE); 9834fc18ff9SAlexander Motin } 9844fc18ff9SAlexander Motin 9854fc18ff9SAlexander Motin void 986130f4520SKenneth D. Merry ctl_set_success(struct ctl_scsiio *ctsio) 987130f4520SKenneth D. Merry { 988130f4520SKenneth D. Merry 989130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_OK; 990130f4520SKenneth D. Merry ctsio->sense_len = 0; 991130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SUCCESS; 992130f4520SKenneth D. Merry } 993*75577946SJohn Baldwin 994*75577946SJohn Baldwin void 995*75577946SJohn Baldwin ctl_nvme_set_error(struct ctl_nvmeio *ctnio, uint8_t sc_type, 996*75577946SJohn Baldwin uint8_t sc_status) 997*75577946SJohn Baldwin { 998*75577946SJohn Baldwin uint16_t status; 999*75577946SJohn Baldwin 1000*75577946SJohn Baldwin memset(&ctnio->cpl, 0, sizeof(ctnio->cpl)); 1001*75577946SJohn Baldwin status = NVMEF(NVME_STATUS_SCT, sc_type) | 1002*75577946SJohn Baldwin NVMEF(NVME_STATUS_SC, sc_status); 1003*75577946SJohn Baldwin ctnio->cpl.status = htole16(status); 1004*75577946SJohn Baldwin ctnio->io_hdr.status = CTL_NVME_ERROR; 1005*75577946SJohn Baldwin } 1006*75577946SJohn Baldwin 1007*75577946SJohn Baldwin void 1008*75577946SJohn Baldwin ctl_nvme_set_generic_error(struct ctl_nvmeio *ctnio, uint8_t sc_status) 1009*75577946SJohn Baldwin { 1010*75577946SJohn Baldwin ctl_nvme_set_error(ctnio, NVME_SCT_GENERIC, sc_status); 1011*75577946SJohn Baldwin } 1012*75577946SJohn Baldwin 1013*75577946SJohn Baldwin void 1014*75577946SJohn Baldwin ctl_nvme_set_invalid_opcode(struct ctl_nvmeio *ctnio) 1015*75577946SJohn Baldwin { 1016*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_INVALID_OPCODE); 1017*75577946SJohn Baldwin } 1018*75577946SJohn Baldwin 1019*75577946SJohn Baldwin void 1020*75577946SJohn Baldwin ctl_nvme_set_invalid_field(struct ctl_nvmeio *ctnio) 1021*75577946SJohn Baldwin { 1022*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_INVALID_FIELD); 1023*75577946SJohn Baldwin } 1024*75577946SJohn Baldwin 1025*75577946SJohn Baldwin void 1026*75577946SJohn Baldwin ctl_nvme_set_data_transfer_error(struct ctl_nvmeio *ctnio) 1027*75577946SJohn Baldwin { 1028*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_DATA_TRANSFER_ERROR); 1029*75577946SJohn Baldwin } 1030*75577946SJohn Baldwin 1031*75577946SJohn Baldwin void 1032*75577946SJohn Baldwin ctl_nvme_set_internal_error(struct ctl_nvmeio *ctnio) 1033*75577946SJohn Baldwin { 1034*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_INTERNAL_DEVICE_ERROR); 1035*75577946SJohn Baldwin } 1036*75577946SJohn Baldwin 1037*75577946SJohn Baldwin void 1038*75577946SJohn Baldwin ctl_nvme_set_invalid_namespace(struct ctl_nvmeio *ctnio) 1039*75577946SJohn Baldwin { 1040*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 1041*75577946SJohn Baldwin } 1042*75577946SJohn Baldwin 1043*75577946SJohn Baldwin void 1044*75577946SJohn Baldwin ctl_nvme_set_command_aborted(struct ctl_nvmeio *ctnio) 1045*75577946SJohn Baldwin { 1046*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_COMMAND_ABORTED_BY_HOST); 1047*75577946SJohn Baldwin } 1048*75577946SJohn Baldwin 1049*75577946SJohn Baldwin void 1050*75577946SJohn Baldwin ctl_nvme_set_failed_fused_command(struct ctl_nvmeio *ctnio) 1051*75577946SJohn Baldwin { 1052*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_ABORTED_FAILED_FUSED); 1053*75577946SJohn Baldwin } 1054*75577946SJohn Baldwin 1055*75577946SJohn Baldwin void 1056*75577946SJohn Baldwin ctl_nvme_set_missing_fused_command(struct ctl_nvmeio *ctnio) 1057*75577946SJohn Baldwin { 1058*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_ABORTED_MISSING_FUSED); 1059*75577946SJohn Baldwin } 1060*75577946SJohn Baldwin 1061*75577946SJohn Baldwin void 1062*75577946SJohn Baldwin ctl_nvme_set_namespace_is_write_protected(struct ctl_nvmeio *ctnio) 1063*75577946SJohn Baldwin { 1064*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_NAMESPACE_IS_WRITE_PROTECTED); 1065*75577946SJohn Baldwin } 1066*75577946SJohn Baldwin 1067*75577946SJohn Baldwin void 1068*75577946SJohn Baldwin ctl_nvme_set_lba_out_of_range(struct ctl_nvmeio *ctnio) 1069*75577946SJohn Baldwin { 1070*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_LBA_OUT_OF_RANGE); 1071*75577946SJohn Baldwin } 1072*75577946SJohn Baldwin 1073*75577946SJohn Baldwin void 1074*75577946SJohn Baldwin ctl_nvme_set_namespace_not_ready(struct ctl_nvmeio *ctnio) 1075*75577946SJohn Baldwin { 1076*75577946SJohn Baldwin ctl_nvme_set_generic_error(ctnio, NVME_SC_NAMESPACE_NOT_READY); 1077*75577946SJohn Baldwin } 1078*75577946SJohn Baldwin 1079*75577946SJohn Baldwin void 1080*75577946SJohn Baldwin ctl_nvme_set_write_fault(struct ctl_nvmeio *ctnio) 1081*75577946SJohn Baldwin { 1082*75577946SJohn Baldwin ctl_nvme_set_error(ctnio, NVME_SCT_MEDIA_ERROR, 1083*75577946SJohn Baldwin NVME_SC_WRITE_FAULTS); 1084*75577946SJohn Baldwin } 1085*75577946SJohn Baldwin 1086*75577946SJohn Baldwin void 1087*75577946SJohn Baldwin ctl_nvme_set_unrecoverable_read_error(struct ctl_nvmeio *ctnio) 1088*75577946SJohn Baldwin { 1089*75577946SJohn Baldwin ctl_nvme_set_error(ctnio, NVME_SCT_MEDIA_ERROR, 1090*75577946SJohn Baldwin NVME_SC_UNRECOVERED_READ_ERROR); 1091*75577946SJohn Baldwin } 1092*75577946SJohn Baldwin 1093*75577946SJohn Baldwin void 1094*75577946SJohn Baldwin ctl_nvme_set_compare_failure(struct ctl_nvmeio *ctnio) 1095*75577946SJohn Baldwin { 1096*75577946SJohn Baldwin ctl_nvme_set_error(ctnio, NVME_SCT_MEDIA_ERROR, 1097*75577946SJohn Baldwin NVME_SC_COMPARE_FAILURE); 1098*75577946SJohn Baldwin } 1099*75577946SJohn Baldwin 1100*75577946SJohn Baldwin void 1101*75577946SJohn Baldwin ctl_nvme_set_space_alloc_fail(struct ctl_nvmeio *ctnio) 1102*75577946SJohn Baldwin { 1103*75577946SJohn Baldwin ctl_nvme_set_error(ctnio, NVME_SCT_MEDIA_ERROR, 1104*75577946SJohn Baldwin NVME_SC_DEALLOCATED_OR_UNWRITTEN); 1105*75577946SJohn Baldwin } 1106*75577946SJohn Baldwin 1107*75577946SJohn Baldwin void 1108*75577946SJohn Baldwin ctl_nvme_set_success(struct ctl_nvmeio *ctnio) 1109*75577946SJohn Baldwin { 1110*75577946SJohn Baldwin memset(&ctnio->cpl, 0, sizeof(ctnio->cpl)); 1111*75577946SJohn Baldwin ctnio->io_hdr.status = CTL_SUCCESS; 1112*75577946SJohn Baldwin } 1113*75577946SJohn Baldwin 1114*75577946SJohn Baldwin void 1115*75577946SJohn Baldwin ctl_io_set_invalid_opcode(union ctl_io *io) 1116*75577946SJohn Baldwin { 1117*75577946SJohn Baldwin switch (io->io_hdr.io_type) { 1118*75577946SJohn Baldwin case CTL_IO_SCSI: 1119*75577946SJohn Baldwin ctl_set_invalid_opcode(&io->scsiio); 1120*75577946SJohn Baldwin break; 1121*75577946SJohn Baldwin case CTL_IO_NVME: 1122*75577946SJohn Baldwin ctl_nvme_set_invalid_opcode(&io->nvmeio); 1123*75577946SJohn Baldwin break; 1124*75577946SJohn Baldwin default: 1125*75577946SJohn Baldwin __assert_unreachable(); 1126*75577946SJohn Baldwin } 1127*75577946SJohn Baldwin } 1128*75577946SJohn Baldwin 1129*75577946SJohn Baldwin void 1130*75577946SJohn Baldwin ctl_io_set_hw_write_protected(union ctl_io *io) 1131*75577946SJohn Baldwin { 1132*75577946SJohn Baldwin switch (io->io_hdr.io_type) { 1133*75577946SJohn Baldwin case CTL_IO_SCSI: 1134*75577946SJohn Baldwin ctl_set_hw_write_protected(&io->scsiio); 1135*75577946SJohn Baldwin break; 1136*75577946SJohn Baldwin case CTL_IO_NVME: 1137*75577946SJohn Baldwin ctl_nvme_set_namespace_is_write_protected(&io->nvmeio); 1138*75577946SJohn Baldwin break; 1139*75577946SJohn Baldwin default: 1140*75577946SJohn Baldwin __assert_unreachable(); 1141*75577946SJohn Baldwin } 1142*75577946SJohn Baldwin } 1143*75577946SJohn Baldwin 1144*75577946SJohn Baldwin void 1145*75577946SJohn Baldwin ctl_io_set_busy(union ctl_io *io) 1146*75577946SJohn Baldwin { 1147*75577946SJohn Baldwin switch (io->io_hdr.io_type) { 1148*75577946SJohn Baldwin case CTL_IO_SCSI: 1149*75577946SJohn Baldwin ctl_set_busy(&io->scsiio); 1150*75577946SJohn Baldwin break; 1151*75577946SJohn Baldwin case CTL_IO_NVME: 1152*75577946SJohn Baldwin ctl_nvme_set_namespace_not_ready(&io->nvmeio); 1153*75577946SJohn Baldwin break; 1154*75577946SJohn Baldwin default: 1155*75577946SJohn Baldwin __assert_unreachable(); 1156*75577946SJohn Baldwin } 1157*75577946SJohn Baldwin } 1158*75577946SJohn Baldwin 1159*75577946SJohn Baldwin void 1160*75577946SJohn Baldwin ctl_io_set_compare_failure(union ctl_io *io, uint64_t offset) 1161*75577946SJohn Baldwin { 1162*75577946SJohn Baldwin uint8_t info[8]; 1163*75577946SJohn Baldwin 1164*75577946SJohn Baldwin switch (io->io_hdr.io_type) { 1165*75577946SJohn Baldwin case CTL_IO_SCSI: 1166*75577946SJohn Baldwin scsi_u64to8b(offset, info); 1167*75577946SJohn Baldwin ctl_set_sense(&io->scsiio, /*current_error*/ 1, 1168*75577946SJohn Baldwin /*sense_key*/ SSD_KEY_MISCOMPARE, 1169*75577946SJohn Baldwin /*asc*/ 0x1D, /*ascq*/ 0x00, 1170*75577946SJohn Baldwin /*type*/ SSD_ELEM_INFO, 1171*75577946SJohn Baldwin /*size*/ sizeof(info), /*data*/ &info, 1172*75577946SJohn Baldwin /*type*/ SSD_ELEM_NONE); 1173*75577946SJohn Baldwin break; 1174*75577946SJohn Baldwin case CTL_IO_NVME: 1175*75577946SJohn Baldwin ctl_nvme_set_compare_failure(&io->nvmeio); 1176*75577946SJohn Baldwin break; 1177*75577946SJohn Baldwin default: 1178*75577946SJohn Baldwin __assert_unreachable(); 1179*75577946SJohn Baldwin } 1180*75577946SJohn Baldwin } 1181*75577946SJohn Baldwin 1182*75577946SJohn Baldwin void 1183*75577946SJohn Baldwin ctl_io_set_space_alloc_fail(union ctl_io *io) 1184*75577946SJohn Baldwin { 1185*75577946SJohn Baldwin switch (io->io_hdr.io_type) { 1186*75577946SJohn Baldwin case CTL_IO_SCSI: 1187*75577946SJohn Baldwin ctl_set_space_alloc_fail(&io->scsiio); 1188*75577946SJohn Baldwin break; 1189*75577946SJohn Baldwin case CTL_IO_NVME: 1190*75577946SJohn Baldwin ctl_nvme_set_space_alloc_fail(&io->nvmeio); 1191*75577946SJohn Baldwin break; 1192*75577946SJohn Baldwin default: 1193*75577946SJohn Baldwin __assert_unreachable(); 1194*75577946SJohn Baldwin } 1195*75577946SJohn Baldwin } 1196*75577946SJohn Baldwin 1197*75577946SJohn Baldwin void 1198*75577946SJohn Baldwin ctl_io_set_success(union ctl_io *io) 1199*75577946SJohn Baldwin { 1200*75577946SJohn Baldwin switch (io->io_hdr.io_type) { 1201*75577946SJohn Baldwin case CTL_IO_SCSI: 1202*75577946SJohn Baldwin ctl_set_success(&io->scsiio); 1203*75577946SJohn Baldwin break; 1204*75577946SJohn Baldwin case CTL_IO_NVME: 1205*75577946SJohn Baldwin case CTL_IO_NVME_ADMIN: 1206*75577946SJohn Baldwin ctl_nvme_set_success(&io->nvmeio); 1207*75577946SJohn Baldwin break; 1208*75577946SJohn Baldwin default: 1209*75577946SJohn Baldwin __assert_unreachable(); 1210*75577946SJohn Baldwin } 1211*75577946SJohn Baldwin } 1212