1130f4520SKenneth D. Merry /*- 2130f4520SKenneth D. Merry * Copyright (c) 2003-2009 Silicon Graphics International Corp. 3130f4520SKenneth D. Merry * Copyright (c) 2011 Spectra Logic Corporation 4648dfc1aSAlexander Motin * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> 5130f4520SKenneth D. Merry * All rights reserved. 6130f4520SKenneth D. Merry * 7130f4520SKenneth D. Merry * Redistribution and use in source and binary forms, with or without 8130f4520SKenneth D. Merry * modification, are permitted provided that the following conditions 9130f4520SKenneth D. Merry * are met: 10130f4520SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright 11130f4520SKenneth D. Merry * notice, this list of conditions, and the following disclaimer, 12130f4520SKenneth D. Merry * without modification. 13130f4520SKenneth D. Merry * 2. Redistributions in binary form must reproduce at minimum a disclaimer 14130f4520SKenneth D. Merry * substantially similar to the "NO WARRANTY" disclaimer below 15130f4520SKenneth D. Merry * ("Disclaimer") and any redistribution must be conditioned upon 16130f4520SKenneth D. Merry * including a substantially similar Disclaimer requirement for further 17130f4520SKenneth D. Merry * binary redistribution. 18130f4520SKenneth D. Merry * 19130f4520SKenneth D. Merry * NO WARRANTY 20130f4520SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21130f4520SKenneth D. Merry * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22130f4520SKenneth D. Merry * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 23130f4520SKenneth D. Merry * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24130f4520SKenneth D. Merry * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25130f4520SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26130f4520SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27130f4520SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28130f4520SKenneth D. Merry * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29130f4520SKenneth D. Merry * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30130f4520SKenneth D. Merry * POSSIBILITY OF SUCH DAMAGES. 31130f4520SKenneth D. Merry * 32130f4520SKenneth D. Merry * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_error.c#2 $ 33130f4520SKenneth D. Merry */ 34130f4520SKenneth D. Merry /* 35130f4520SKenneth D. Merry * CAM Target Layer error reporting routines. 36130f4520SKenneth D. Merry * 37130f4520SKenneth D. Merry * Author: Ken Merry <ken@FreeBSD.org> 38130f4520SKenneth D. Merry */ 39130f4520SKenneth D. Merry 40130f4520SKenneth D. Merry #include <sys/cdefs.h> 41130f4520SKenneth D. Merry __FBSDID("$FreeBSD$"); 42130f4520SKenneth D. Merry 43130f4520SKenneth D. Merry #include <sys/param.h> 44130f4520SKenneth D. Merry #include <sys/systm.h> 45130f4520SKenneth D. Merry #include <sys/kernel.h> 46130f4520SKenneth D. Merry #include <sys/types.h> 47130f4520SKenneth D. Merry #include <sys/malloc.h> 48130f4520SKenneth D. Merry #include <sys/lock.h> 49130f4520SKenneth D. Merry #include <sys/mutex.h> 50130f4520SKenneth D. Merry #include <sys/condvar.h> 51130f4520SKenneth D. Merry #include <sys/stddef.h> 52130f4520SKenneth D. Merry #include <sys/ctype.h> 53bf8f8f34SKenneth D. Merry #include <sys/sysctl.h> 54130f4520SKenneth D. Merry #include <machine/stdarg.h> 55130f4520SKenneth D. Merry 56130f4520SKenneth D. Merry #include <cam/scsi/scsi_all.h> 57130f4520SKenneth D. Merry #include <cam/scsi/scsi_da.h> 58130f4520SKenneth D. Merry #include <cam/ctl/ctl_io.h> 59130f4520SKenneth D. Merry #include <cam/ctl/ctl.h> 60130f4520SKenneth D. Merry #include <cam/ctl/ctl_frontend.h> 61130f4520SKenneth D. Merry #include <cam/ctl/ctl_backend.h> 62130f4520SKenneth D. Merry #include <cam/ctl/ctl_ioctl.h> 63130f4520SKenneth D. Merry #include <cam/ctl/ctl_error.h> 64130f4520SKenneth D. Merry #include <cam/ctl/ctl_ha.h> 65130f4520SKenneth D. Merry #include <cam/ctl/ctl_private.h> 66130f4520SKenneth D. Merry 67130f4520SKenneth D. Merry void 684fc0d1d7SAlexander Motin ctl_set_sense_data_va(struct scsi_sense_data *sense_data, u_int *sense_len, 694fc0d1d7SAlexander Motin void *lunptr, scsi_sense_data_type sense_format, int current_error, 70130f4520SKenneth D. Merry int sense_key, int asc, int ascq, va_list ap) 71130f4520SKenneth D. Merry { 72130f4520SKenneth D. Merry struct ctl_lun *lun; 73130f4520SKenneth D. Merry 74130f4520SKenneth D. Merry lun = (struct ctl_lun *)lunptr; 75130f4520SKenneth D. Merry 76130f4520SKenneth D. Merry /* 77130f4520SKenneth D. Merry * Determine whether to return fixed or descriptor format sense 78130f4520SKenneth D. Merry * data. 79130f4520SKenneth D. Merry */ 80130f4520SKenneth D. Merry if (sense_format == SSD_TYPE_NONE) { 81130f4520SKenneth D. Merry /* 82130f4520SKenneth D. Merry * If the format isn't specified, we only return descriptor 83130f4520SKenneth D. Merry * sense if the LUN exists and descriptor sense is turned 84130f4520SKenneth D. Merry * on for that LUN. 85130f4520SKenneth D. Merry */ 8611887875SAlexander Motin if ((lun != NULL) && (lun->MODE_CTRL.rlec & SCP_DSENSE)) 87130f4520SKenneth D. Merry sense_format = SSD_TYPE_DESC; 88130f4520SKenneth D. Merry else 89130f4520SKenneth D. Merry sense_format = SSD_TYPE_FIXED; 90130f4520SKenneth D. Merry } 91130f4520SKenneth D. Merry 924fc0d1d7SAlexander Motin /* 934fc0d1d7SAlexander Motin * Determine maximum sense data length to return. 944fc0d1d7SAlexander Motin */ 954fc0d1d7SAlexander Motin if (*sense_len == 0) { 964fc0d1d7SAlexander Motin if ((lun != NULL) && (lun->MODE_CTRLE.max_sense != 0)) 974fc0d1d7SAlexander Motin *sense_len = lun->MODE_CTRLE.max_sense; 984fc0d1d7SAlexander Motin else 994fc0d1d7SAlexander Motin *sense_len = SSD_FULL_SIZE; 1004fc0d1d7SAlexander Motin } 1014fc0d1d7SAlexander Motin 1024fc0d1d7SAlexander Motin scsi_set_sense_data_va(sense_data, sense_len, sense_format, 1034fc0d1d7SAlexander Motin current_error, sense_key, asc, ascq, ap); 104130f4520SKenneth D. Merry } 105130f4520SKenneth D. Merry 106130f4520SKenneth D. Merry void 1074fc0d1d7SAlexander Motin ctl_set_sense_data(struct scsi_sense_data *sense_data, u_int *sense_len, 1084fc0d1d7SAlexander Motin void *lunptr, scsi_sense_data_type sense_format, int current_error, 109130f4520SKenneth D. Merry int sense_key, int asc, int ascq, ...) 110130f4520SKenneth D. Merry { 111130f4520SKenneth D. Merry va_list ap; 112130f4520SKenneth D. Merry 113130f4520SKenneth D. Merry va_start(ap, ascq); 1144fc0d1d7SAlexander Motin ctl_set_sense_data_va(sense_data, sense_len, lunptr, sense_format, 1154fc0d1d7SAlexander Motin current_error, sense_key, asc, ascq, ap); 116130f4520SKenneth D. Merry va_end(ap); 117130f4520SKenneth D. Merry } 118130f4520SKenneth D. Merry 119130f4520SKenneth D. Merry void 120130f4520SKenneth D. Merry ctl_set_sense(struct ctl_scsiio *ctsio, int current_error, int sense_key, 121130f4520SKenneth D. Merry int asc, int ascq, ...) 122130f4520SKenneth D. Merry { 123130f4520SKenneth D. Merry va_list ap; 124130f4520SKenneth D. Merry struct ctl_lun *lun; 1254fc0d1d7SAlexander Motin u_int sense_len; 126130f4520SKenneth D. Merry 127130f4520SKenneth D. Merry /* 128130f4520SKenneth D. Merry * The LUN can't go away until all of the commands have been 129130f4520SKenneth D. Merry * completed. Therefore we can safely access the LUN structure and 130130f4520SKenneth D. Merry * flags without the lock. 131130f4520SKenneth D. Merry */ 132*9cbbfd2fSAlexander Motin lun = CTL_LUN(ctsio); 133130f4520SKenneth D. Merry 134130f4520SKenneth D. Merry va_start(ap, ascq); 1354fc0d1d7SAlexander Motin sense_len = 0; 1364fc0d1d7SAlexander Motin ctl_set_sense_data_va(&ctsio->sense_data, &sense_len, 137130f4520SKenneth D. Merry lun, 138130f4520SKenneth D. Merry SSD_TYPE_NONE, 139130f4520SKenneth D. Merry current_error, 140130f4520SKenneth D. Merry sense_key, 141130f4520SKenneth D. Merry asc, 142130f4520SKenneth D. Merry ascq, 143130f4520SKenneth D. Merry ap); 144130f4520SKenneth D. Merry va_end(ap); 145130f4520SKenneth D. Merry 146130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_CHECK_COND; 1474fc0d1d7SAlexander Motin ctsio->sense_len = sense_len; 148130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SCSI_ERROR | CTL_AUTOSENSE; 149130f4520SKenneth D. Merry } 150130f4520SKenneth D. Merry 151130f4520SKenneth D. Merry /* 152130f4520SKenneth D. Merry * Transform fixed sense data into descriptor sense data. 153130f4520SKenneth D. Merry * 154130f4520SKenneth D. Merry * For simplicity's sake, we assume that both sense structures are 155130f4520SKenneth D. Merry * SSD_FULL_SIZE. Otherwise, the logic gets more complicated. 156130f4520SKenneth D. Merry */ 157130f4520SKenneth D. Merry void 158130f4520SKenneth D. Merry ctl_sense_to_desc(struct scsi_sense_data_fixed *sense_src, 159130f4520SKenneth D. Merry struct scsi_sense_data_desc *sense_dest) 160130f4520SKenneth D. Merry { 161130f4520SKenneth D. Merry struct scsi_sense_stream stream_sense; 162130f4520SKenneth D. Merry int current_error; 1634fc0d1d7SAlexander Motin u_int sense_len; 164130f4520SKenneth D. Merry uint8_t stream_bits; 165130f4520SKenneth D. Merry 166130f4520SKenneth D. Merry bzero(sense_dest, sizeof(*sense_dest)); 167130f4520SKenneth D. Merry 168130f4520SKenneth D. Merry if ((sense_src->error_code & SSD_ERRCODE) == SSD_DEFERRED_ERROR) 169130f4520SKenneth D. Merry current_error = 0; 170130f4520SKenneth D. Merry else 171130f4520SKenneth D. Merry current_error = 1; 172130f4520SKenneth D. Merry 173130f4520SKenneth D. Merry bzero(&stream_sense, sizeof(stream_sense)); 174130f4520SKenneth D. Merry 175130f4520SKenneth D. Merry /* 176130f4520SKenneth D. Merry * Check to see whether any of the tape-specific bits are set. If 177130f4520SKenneth D. Merry * so, we'll need a stream sense descriptor. 178130f4520SKenneth D. Merry */ 179130f4520SKenneth D. Merry if (sense_src->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK)) 180130f4520SKenneth D. Merry stream_bits = sense_src->flags & ~SSD_KEY; 181130f4520SKenneth D. Merry else 182130f4520SKenneth D. Merry stream_bits = 0; 183130f4520SKenneth D. Merry 184130f4520SKenneth D. Merry /* 185130f4520SKenneth D. Merry * Utilize our sense setting routine to do the transform. If a 186130f4520SKenneth D. Merry * value is set in the fixed sense data, set it in the descriptor 187130f4520SKenneth D. Merry * data. Otherwise, skip it. 188130f4520SKenneth D. Merry */ 1894fc0d1d7SAlexander Motin sense_len = SSD_FULL_SIZE; 1904fc0d1d7SAlexander Motin ctl_set_sense_data((struct scsi_sense_data *)sense_dest, &sense_len, 191130f4520SKenneth D. Merry /*lun*/ NULL, 192130f4520SKenneth D. Merry /*sense_format*/ SSD_TYPE_DESC, 193130f4520SKenneth D. Merry current_error, 194130f4520SKenneth D. Merry /*sense_key*/ sense_src->flags & SSD_KEY, 195130f4520SKenneth D. Merry /*asc*/ sense_src->add_sense_code, 196130f4520SKenneth D. Merry /*ascq*/ sense_src->add_sense_code_qual, 197130f4520SKenneth D. Merry 198130f4520SKenneth D. Merry /* Information Bytes */ 19932920cbfSAlexander Motin (sense_src->error_code & SSD_ERRCODE_VALID) ? 200130f4520SKenneth D. Merry SSD_ELEM_INFO : SSD_ELEM_SKIP, 201130f4520SKenneth D. Merry sizeof(sense_src->info), 202130f4520SKenneth D. Merry sense_src->info, 203130f4520SKenneth D. Merry 204130f4520SKenneth D. Merry /* Command specific bytes */ 205130f4520SKenneth D. Merry (scsi_4btoul(sense_src->cmd_spec_info) != 0) ? 206130f4520SKenneth D. Merry SSD_ELEM_COMMAND : SSD_ELEM_SKIP, 207130f4520SKenneth D. Merry sizeof(sense_src->cmd_spec_info), 208130f4520SKenneth D. Merry sense_src->cmd_spec_info, 209130f4520SKenneth D. Merry 210130f4520SKenneth D. Merry /* FRU */ 211130f4520SKenneth D. Merry (sense_src->fru != 0) ? 212130f4520SKenneth D. Merry SSD_ELEM_FRU : SSD_ELEM_SKIP, 213130f4520SKenneth D. Merry sizeof(sense_src->fru), 214130f4520SKenneth D. Merry &sense_src->fru, 215130f4520SKenneth D. Merry 216130f4520SKenneth D. Merry /* Sense Key Specific */ 217130f4520SKenneth D. Merry (sense_src->sense_key_spec[0] & SSD_SCS_VALID) ? 218130f4520SKenneth D. Merry SSD_ELEM_SKS : SSD_ELEM_SKIP, 219130f4520SKenneth D. Merry sizeof(sense_src->sense_key_spec), 220130f4520SKenneth D. Merry sense_src->sense_key_spec, 221130f4520SKenneth D. Merry 222130f4520SKenneth D. Merry /* Tape bits */ 223130f4520SKenneth D. Merry (stream_bits != 0) ? 224130f4520SKenneth D. Merry SSD_ELEM_STREAM : SSD_ELEM_SKIP, 225130f4520SKenneth D. Merry sizeof(stream_bits), 226130f4520SKenneth D. Merry &stream_bits, 227130f4520SKenneth D. Merry 228130f4520SKenneth D. Merry SSD_ELEM_NONE); 229130f4520SKenneth D. Merry } 230130f4520SKenneth D. Merry 231130f4520SKenneth D. Merry /* 232130f4520SKenneth D. Merry * Transform descriptor format sense data into fixed sense data. 233130f4520SKenneth D. Merry * 234130f4520SKenneth D. Merry * Some data may be lost in translation, because there are descriptors 235130f4520SKenneth D. Merry * thant can't be represented as fixed sense data. 236130f4520SKenneth D. Merry * 237130f4520SKenneth D. Merry * For simplicity's sake, we assume that both sense structures are 238130f4520SKenneth D. Merry * SSD_FULL_SIZE. Otherwise, the logic gets more complicated. 239130f4520SKenneth D. Merry */ 240130f4520SKenneth D. Merry void 241130f4520SKenneth D. Merry ctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src, 242130f4520SKenneth D. Merry struct scsi_sense_data_fixed *sense_dest) 243130f4520SKenneth D. Merry { 244130f4520SKenneth D. Merry int current_error; 245130f4520SKenneth D. Merry uint8_t *info_ptr = NULL, *cmd_ptr = NULL, *fru_ptr = NULL; 246130f4520SKenneth D. Merry uint8_t *sks_ptr = NULL, *stream_ptr = NULL; 247130f4520SKenneth D. Merry int info_size = 0, cmd_size = 0, fru_size = 0; 248130f4520SKenneth D. Merry int sks_size = 0, stream_size = 0; 249130f4520SKenneth D. Merry int pos; 2504fc0d1d7SAlexander Motin u_int sense_len; 251130f4520SKenneth D. Merry 252130f4520SKenneth D. Merry if ((sense_src->error_code & SSD_ERRCODE) == SSD_DESC_CURRENT_ERROR) 253130f4520SKenneth D. Merry current_error = 1; 254130f4520SKenneth D. Merry else 255130f4520SKenneth D. Merry current_error = 0; 256130f4520SKenneth D. Merry 257130f4520SKenneth D. Merry for (pos = 0; pos < (int)(sense_src->extra_len - 1);) { 258130f4520SKenneth D. Merry struct scsi_sense_desc_header *header; 259130f4520SKenneth D. Merry 260130f4520SKenneth D. Merry header = (struct scsi_sense_desc_header *) 261130f4520SKenneth D. Merry &sense_src->sense_desc[pos]; 262130f4520SKenneth D. Merry 263130f4520SKenneth D. Merry /* 264130f4520SKenneth D. Merry * See if this record goes past the end of the sense data. 265130f4520SKenneth D. Merry * It shouldn't, but check just in case. 266130f4520SKenneth D. Merry */ 267130f4520SKenneth D. Merry if ((pos + header->length + sizeof(*header)) > 268130f4520SKenneth D. Merry sense_src->extra_len) 269130f4520SKenneth D. Merry break; 270130f4520SKenneth D. Merry 271130f4520SKenneth D. Merry switch (sense_src->sense_desc[pos]) { 272130f4520SKenneth D. Merry case SSD_DESC_INFO: { 273130f4520SKenneth D. Merry struct scsi_sense_info *info; 274130f4520SKenneth D. Merry 275130f4520SKenneth D. Merry info = (struct scsi_sense_info *)header; 276130f4520SKenneth D. Merry 277130f4520SKenneth D. Merry info_ptr = info->info; 278130f4520SKenneth D. Merry info_size = sizeof(info->info); 279130f4520SKenneth D. Merry 280130f4520SKenneth D. Merry pos += info->length + 281130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 282130f4520SKenneth D. Merry break; 283130f4520SKenneth D. Merry } 284130f4520SKenneth D. Merry case SSD_DESC_COMMAND: { 285130f4520SKenneth D. Merry struct scsi_sense_command *cmd; 286130f4520SKenneth D. Merry 287130f4520SKenneth D. Merry cmd = (struct scsi_sense_command *)header; 288130f4520SKenneth D. Merry cmd_ptr = cmd->command_info; 289130f4520SKenneth D. Merry cmd_size = sizeof(cmd->command_info); 290130f4520SKenneth D. Merry 291130f4520SKenneth D. Merry pos += cmd->length + 292130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 293130f4520SKenneth D. Merry break; 294130f4520SKenneth D. Merry } 295130f4520SKenneth D. Merry case SSD_DESC_FRU: { 296130f4520SKenneth D. Merry struct scsi_sense_fru *fru; 297130f4520SKenneth D. Merry 298130f4520SKenneth D. Merry fru = (struct scsi_sense_fru *)header; 299130f4520SKenneth D. Merry fru_ptr = &fru->fru; 300130f4520SKenneth D. Merry fru_size = sizeof(fru->fru); 301130f4520SKenneth D. Merry pos += fru->length + 302130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 303130f4520SKenneth D. Merry break; 304130f4520SKenneth D. Merry } 305130f4520SKenneth D. Merry case SSD_DESC_SKS: { 306130f4520SKenneth D. Merry struct scsi_sense_sks *sks; 307130f4520SKenneth D. Merry 308130f4520SKenneth D. Merry sks = (struct scsi_sense_sks *)header; 309130f4520SKenneth D. Merry sks_ptr = sks->sense_key_spec; 310130f4520SKenneth D. Merry sks_size = sizeof(sks->sense_key_spec); 311130f4520SKenneth D. Merry 312130f4520SKenneth D. Merry pos = sks->length + 313130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 314130f4520SKenneth D. Merry break; 315130f4520SKenneth D. Merry } 316130f4520SKenneth D. Merry case SSD_DESC_STREAM: { 317130f4520SKenneth D. Merry struct scsi_sense_stream *stream_sense; 318130f4520SKenneth D. Merry 319130f4520SKenneth D. Merry stream_sense = (struct scsi_sense_stream *)header; 320130f4520SKenneth D. Merry stream_ptr = &stream_sense->byte3; 321130f4520SKenneth D. Merry stream_size = sizeof(stream_sense->byte3); 322130f4520SKenneth D. Merry pos = stream_sense->length + 323130f4520SKenneth D. Merry sizeof(struct scsi_sense_desc_header); 324130f4520SKenneth D. Merry break; 325130f4520SKenneth D. Merry } 326130f4520SKenneth D. Merry default: 327130f4520SKenneth D. Merry /* 328130f4520SKenneth D. Merry * We don't recognize this particular sense 329130f4520SKenneth D. Merry * descriptor type, so just skip it. 330130f4520SKenneth D. Merry */ 331130f4520SKenneth D. Merry pos += sizeof(*header) + header->length; 332130f4520SKenneth D. Merry break; 333130f4520SKenneth D. Merry } 334130f4520SKenneth D. Merry } 335130f4520SKenneth D. Merry 3364fc0d1d7SAlexander Motin sense_len = SSD_FULL_SIZE; 3374fc0d1d7SAlexander Motin ctl_set_sense_data((struct scsi_sense_data *)sense_dest, &sense_len, 338130f4520SKenneth D. Merry /*lun*/ NULL, 339130f4520SKenneth D. Merry /*sense_format*/ SSD_TYPE_FIXED, 340130f4520SKenneth D. Merry current_error, 341130f4520SKenneth D. Merry /*sense_key*/ sense_src->sense_key & SSD_KEY, 342130f4520SKenneth D. Merry /*asc*/ sense_src->add_sense_code, 343130f4520SKenneth D. Merry /*ascq*/ sense_src->add_sense_code_qual, 344130f4520SKenneth D. Merry 345130f4520SKenneth D. Merry /* Information Bytes */ 346130f4520SKenneth D. Merry (info_ptr != NULL) ? SSD_ELEM_INFO : SSD_ELEM_SKIP, 347130f4520SKenneth D. Merry info_size, 348130f4520SKenneth D. Merry info_ptr, 349130f4520SKenneth D. Merry 350130f4520SKenneth D. Merry /* Command specific bytes */ 351130f4520SKenneth D. Merry (cmd_ptr != NULL) ? SSD_ELEM_COMMAND : SSD_ELEM_SKIP, 352130f4520SKenneth D. Merry cmd_size, 353130f4520SKenneth D. Merry cmd_ptr, 354130f4520SKenneth D. Merry 355130f4520SKenneth D. Merry /* FRU */ 356130f4520SKenneth D. Merry (fru_ptr != NULL) ? SSD_ELEM_FRU : SSD_ELEM_SKIP, 357130f4520SKenneth D. Merry fru_size, 358130f4520SKenneth D. Merry fru_ptr, 359130f4520SKenneth D. Merry 360130f4520SKenneth D. Merry /* Sense Key Specific */ 361130f4520SKenneth D. Merry (sks_ptr != NULL) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 362130f4520SKenneth D. Merry sks_size, 363130f4520SKenneth D. Merry sks_ptr, 364130f4520SKenneth D. Merry 365130f4520SKenneth D. Merry /* Tape bits */ 366130f4520SKenneth D. Merry (stream_ptr != NULL) ? SSD_ELEM_STREAM : SSD_ELEM_SKIP, 367130f4520SKenneth D. Merry stream_size, 368130f4520SKenneth D. Merry stream_ptr, 369130f4520SKenneth D. Merry 370130f4520SKenneth D. Merry SSD_ELEM_NONE); 371130f4520SKenneth D. Merry } 372130f4520SKenneth D. Merry 373130f4520SKenneth D. Merry void 374130f4520SKenneth D. Merry ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq) 375130f4520SKenneth D. Merry { 376130f4520SKenneth D. Merry ctl_set_sense(ctsio, 377130f4520SKenneth D. Merry /*current_error*/ 1, 378130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_UNIT_ATTENTION, 379130f4520SKenneth D. Merry asc, 380130f4520SKenneth D. Merry ascq, 381130f4520SKenneth D. Merry SSD_ELEM_NONE); 382130f4520SKenneth D. Merry } 383130f4520SKenneth D. Merry 384ceff31dcSAlexander Motin static void 385c329b295SAlexander Motin ctl_ua_to_ascq(struct ctl_lun *lun, ctl_ua_type ua_to_build, int *asc, 38662138827SAlexander Motin int *ascq, ctl_ua_type *ua_to_clear, uint8_t **info) 387ceff31dcSAlexander Motin { 388ceff31dcSAlexander Motin 389ceff31dcSAlexander Motin switch (ua_to_build) { 390ceff31dcSAlexander Motin case CTL_UA_POWERON: 391ceff31dcSAlexander Motin /* 29h/01h POWER ON OCCURRED */ 392ceff31dcSAlexander Motin *asc = 0x29; 393ceff31dcSAlexander Motin *ascq = 0x01; 394ceff31dcSAlexander Motin *ua_to_clear = ~0; 395ceff31dcSAlexander Motin break; 396ceff31dcSAlexander Motin case CTL_UA_BUS_RESET: 397ceff31dcSAlexander Motin /* 29h/02h SCSI BUS RESET OCCURRED */ 398ceff31dcSAlexander Motin *asc = 0x29; 399ceff31dcSAlexander Motin *ascq = 0x02; 400ceff31dcSAlexander Motin *ua_to_clear = ~0; 401ceff31dcSAlexander Motin break; 402ceff31dcSAlexander Motin case CTL_UA_TARG_RESET: 403ceff31dcSAlexander Motin /* 29h/03h BUS DEVICE RESET FUNCTION OCCURRED*/ 404ceff31dcSAlexander Motin *asc = 0x29; 405ceff31dcSAlexander Motin *ascq = 0x03; 406ceff31dcSAlexander Motin *ua_to_clear = ~0; 407ceff31dcSAlexander Motin break; 408ceff31dcSAlexander Motin case CTL_UA_I_T_NEXUS_LOSS: 409ceff31dcSAlexander Motin /* 29h/07h I_T NEXUS LOSS OCCURRED */ 410ceff31dcSAlexander Motin *asc = 0x29; 411ceff31dcSAlexander Motin *ascq = 0x07; 412ceff31dcSAlexander Motin *ua_to_clear = ~0; 413ceff31dcSAlexander Motin break; 414ceff31dcSAlexander Motin case CTL_UA_LUN_RESET: 415ceff31dcSAlexander Motin /* 29h/00h POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */ 416ceff31dcSAlexander Motin /* 417ceff31dcSAlexander Motin * Since we don't have a specific ASC/ASCQ pair for a LUN 418ceff31dcSAlexander Motin * reset, just return the generic reset code. 419ceff31dcSAlexander Motin */ 420ceff31dcSAlexander Motin *asc = 0x29; 421ceff31dcSAlexander Motin *ascq = 0x00; 422ceff31dcSAlexander Motin break; 423ceff31dcSAlexander Motin case CTL_UA_LUN_CHANGE: 424ceff31dcSAlexander Motin /* 3Fh/0Eh REPORTED LUNS DATA HAS CHANGED */ 425ceff31dcSAlexander Motin *asc = 0x3F; 426ceff31dcSAlexander Motin *ascq = 0x0E; 427ceff31dcSAlexander Motin break; 428ceff31dcSAlexander Motin case CTL_UA_MODE_CHANGE: 429ceff31dcSAlexander Motin /* 2Ah/01h MODE PARAMETERS CHANGED */ 430ceff31dcSAlexander Motin *asc = 0x2A; 431ceff31dcSAlexander Motin *ascq = 0x01; 432ceff31dcSAlexander Motin break; 433ceff31dcSAlexander Motin case CTL_UA_LOG_CHANGE: 434ceff31dcSAlexander Motin /* 2Ah/02h LOG PARAMETERS CHANGED */ 435ceff31dcSAlexander Motin *asc = 0x2A; 436ceff31dcSAlexander Motin *ascq = 0x02; 437ceff31dcSAlexander Motin break; 438ceff31dcSAlexander Motin case CTL_UA_INQ_CHANGE: 439ceff31dcSAlexander Motin /* 3Fh/03h INQUIRY DATA HAS CHANGED */ 440ceff31dcSAlexander Motin *asc = 0x3F; 441ceff31dcSAlexander Motin *ascq = 0x03; 442ceff31dcSAlexander Motin break; 443ceff31dcSAlexander Motin case CTL_UA_RES_PREEMPT: 444ceff31dcSAlexander Motin /* 2Ah/03h RESERVATIONS PREEMPTED */ 445ceff31dcSAlexander Motin *asc = 0x2A; 446ceff31dcSAlexander Motin *ascq = 0x03; 447ceff31dcSAlexander Motin break; 448ceff31dcSAlexander Motin case CTL_UA_RES_RELEASE: 449ceff31dcSAlexander Motin /* 2Ah/04h RESERVATIONS RELEASED */ 450ceff31dcSAlexander Motin *asc = 0x2A; 451ceff31dcSAlexander Motin *ascq = 0x04; 452ceff31dcSAlexander Motin break; 453ceff31dcSAlexander Motin case CTL_UA_REG_PREEMPT: 454ceff31dcSAlexander Motin /* 2Ah/05h REGISTRATIONS PREEMPTED */ 455ceff31dcSAlexander Motin *asc = 0x2A; 456ceff31dcSAlexander Motin *ascq = 0x05; 457ceff31dcSAlexander Motin break; 458ceff31dcSAlexander Motin case CTL_UA_ASYM_ACC_CHANGE: 459ceff31dcSAlexander Motin /* 2Ah/06h ASYMMETRIC ACCESS STATE CHANGED */ 460ceff31dcSAlexander Motin *asc = 0x2A; 461ceff31dcSAlexander Motin *ascq = 0x06; 462ceff31dcSAlexander Motin break; 463648dfc1aSAlexander Motin case CTL_UA_CAPACITY_CHANGE: 464ceff31dcSAlexander Motin /* 2Ah/09h CAPACITY DATA HAS CHANGED */ 465ceff31dcSAlexander Motin *asc = 0x2A; 466ceff31dcSAlexander Motin *ascq = 0x09; 467ceff31dcSAlexander Motin break; 468ceff31dcSAlexander Motin case CTL_UA_THIN_PROV_THRES: 469ceff31dcSAlexander Motin /* 38h/07h THIN PROVISIONING SOFT THRESHOLD REACHED */ 470ceff31dcSAlexander Motin *asc = 0x38; 471ceff31dcSAlexander Motin *ascq = 0x07; 47262138827SAlexander Motin *info = lun->ua_tpt_info; 473ceff31dcSAlexander Motin break; 474648dfc1aSAlexander Motin case CTL_UA_MEDIUM_CHANGE: 475648dfc1aSAlexander Motin /* 28h/00h NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */ 476648dfc1aSAlexander Motin *asc = 0x28; 477648dfc1aSAlexander Motin *ascq = 0x00; 478648dfc1aSAlexander Motin break; 479d9ba4eefSAlexander Motin case CTL_UA_IE: 480d9ba4eefSAlexander Motin /* Informational exception */ 481d9ba4eefSAlexander Motin *asc = lun->ie_asc; 482d9ba4eefSAlexander Motin *ascq = lun->ie_ascq; 483d9ba4eefSAlexander Motin break; 484ceff31dcSAlexander Motin default: 485ceff31dcSAlexander Motin panic("%s: Unknown UA %x", __func__, ua_to_build); 486ceff31dcSAlexander Motin } 487ceff31dcSAlexander Motin } 488ceff31dcSAlexander Motin 489ceff31dcSAlexander Motin ctl_ua_type 490ceff31dcSAlexander Motin ctl_build_qae(struct ctl_lun *lun, uint32_t initidx, uint8_t *resp) 491ceff31dcSAlexander Motin { 492ceff31dcSAlexander Motin ctl_ua_type ua; 493ceff31dcSAlexander Motin ctl_ua_type ua_to_build, ua_to_clear; 49462138827SAlexander Motin uint8_t *info; 495ceff31dcSAlexander Motin int asc, ascq; 496ceff31dcSAlexander Motin uint32_t p, i; 497ceff31dcSAlexander Motin 498ceff31dcSAlexander Motin mtx_assert(&lun->lun_lock, MA_OWNED); 499ceff31dcSAlexander Motin p = initidx / CTL_MAX_INIT_PER_PORT; 500ceff31dcSAlexander Motin i = initidx % CTL_MAX_INIT_PER_PORT; 501ceff31dcSAlexander Motin if (lun->pending_ua[p] == NULL) 502ceff31dcSAlexander Motin ua = CTL_UA_POWERON; 503ceff31dcSAlexander Motin else 504ceff31dcSAlexander Motin ua = lun->pending_ua[p][i]; 505ceff31dcSAlexander Motin if (ua == CTL_UA_NONE) 506ceff31dcSAlexander Motin return (CTL_UA_NONE); 507ceff31dcSAlexander Motin 508ceff31dcSAlexander Motin ua_to_build = (1 << (ffs(ua) - 1)); 509ceff31dcSAlexander Motin ua_to_clear = ua_to_build; 51062138827SAlexander Motin info = NULL; 511c329b295SAlexander Motin ctl_ua_to_ascq(lun, ua_to_build, &asc, &ascq, &ua_to_clear, &info); 512ceff31dcSAlexander Motin 513ceff31dcSAlexander Motin resp[0] = SSD_KEY_UNIT_ATTENTION; 514ceff31dcSAlexander Motin if (ua_to_build == ua) 515ceff31dcSAlexander Motin resp[0] |= 0x10; 516ceff31dcSAlexander Motin else 517ceff31dcSAlexander Motin resp[0] |= 0x20; 518ceff31dcSAlexander Motin resp[1] = asc; 519ceff31dcSAlexander Motin resp[2] = ascq; 5204fc0d1d7SAlexander Motin return (ua_to_build); 521ceff31dcSAlexander Motin } 522ceff31dcSAlexander Motin 523130f4520SKenneth D. Merry ctl_ua_type 5249e525653SAlexander Motin ctl_build_ua(struct ctl_lun *lun, uint32_t initidx, 5254fc0d1d7SAlexander Motin struct scsi_sense_data *sense, u_int *sense_len, 5264fc0d1d7SAlexander Motin scsi_sense_data_type sense_format) 527130f4520SKenneth D. Merry { 5289e525653SAlexander Motin ctl_ua_type *ua; 5298f07b2d5SAlexander Motin ctl_ua_type ua_to_build, ua_to_clear; 53062138827SAlexander Motin uint8_t *info; 5318f07b2d5SAlexander Motin int asc, ascq; 5329e525653SAlexander Motin uint32_t p, i; 533130f4520SKenneth D. Merry 5349e525653SAlexander Motin mtx_assert(&lun->lun_lock, MA_OWNED); 53533e7ba9cSAlexander Motin mtx_assert(&lun->ctl_softc->ctl_lock, MA_NOTOWNED); 5369e525653SAlexander Motin p = initidx / CTL_MAX_INIT_PER_PORT; 5379e525653SAlexander Motin if ((ua = lun->pending_ua[p]) == NULL) { 5389e525653SAlexander Motin mtx_unlock(&lun->lun_lock); 5399e525653SAlexander Motin ua = malloc(sizeof(ctl_ua_type) * CTL_MAX_INIT_PER_PORT, 5409e525653SAlexander Motin M_CTL, M_WAITOK); 5419e525653SAlexander Motin mtx_lock(&lun->lun_lock); 5429e525653SAlexander Motin if (lun->pending_ua[p] == NULL) { 5439e525653SAlexander Motin lun->pending_ua[p] = ua; 5449e525653SAlexander Motin for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++) 5459e525653SAlexander Motin ua[i] = CTL_UA_POWERON; 5469e525653SAlexander Motin } else { 5479e525653SAlexander Motin free(ua, M_CTL); 5489e525653SAlexander Motin ua = lun->pending_ua[p]; 5499e525653SAlexander Motin } 5509e525653SAlexander Motin } 5519e525653SAlexander Motin i = initidx % CTL_MAX_INIT_PER_PORT; 5529e525653SAlexander Motin if (ua[i] == CTL_UA_NONE) 5538f07b2d5SAlexander Motin return (CTL_UA_NONE); 554130f4520SKenneth D. Merry 5559e525653SAlexander Motin ua_to_build = (1 << (ffs(ua[i]) - 1)); 5568f07b2d5SAlexander Motin ua_to_clear = ua_to_build; 55762138827SAlexander Motin info = NULL; 558c329b295SAlexander Motin ctl_ua_to_ascq(lun, ua_to_build, &asc, &ascq, &ua_to_clear, &info); 559130f4520SKenneth D. Merry 5604fc0d1d7SAlexander Motin ctl_set_sense_data(sense, sense_len, lun, sense_format, 1, 56162138827SAlexander Motin /*sense_key*/ SSD_KEY_UNIT_ATTENTION, asc, ascq, 56262138827SAlexander Motin ((info != NULL) ? SSD_ELEM_INFO : SSD_ELEM_SKIP), 8, info, 563130f4520SKenneth D. Merry SSD_ELEM_NONE); 564130f4520SKenneth D. Merry 5658f07b2d5SAlexander Motin /* We're reporting this UA, so clear it */ 5669e525653SAlexander Motin ua[i] &= ~ua_to_clear; 5678f07b2d5SAlexander Motin 56833e7ba9cSAlexander Motin if (ua_to_build == CTL_UA_LUN_CHANGE) { 56933e7ba9cSAlexander Motin mtx_unlock(&lun->lun_lock); 57033e7ba9cSAlexander Motin mtx_lock(&lun->ctl_softc->ctl_lock); 57133e7ba9cSAlexander Motin ctl_clr_ua_allluns(lun->ctl_softc, initidx, ua_to_build); 57233e7ba9cSAlexander Motin mtx_unlock(&lun->ctl_softc->ctl_lock); 57333e7ba9cSAlexander Motin mtx_lock(&lun->lun_lock); 57433e7ba9cSAlexander Motin } else if (ua_to_build == CTL_UA_THIN_PROV_THRES && 57533e7ba9cSAlexander Motin (lun->MODE_LBP.main.flags & SLBPP_SITUA) != 0) { 57633e7ba9cSAlexander Motin ctl_clr_ua_all(lun, -1, ua_to_build); 57733e7ba9cSAlexander Motin } 57833e7ba9cSAlexander Motin 579130f4520SKenneth D. Merry return (ua_to_build); 580130f4520SKenneth D. Merry } 581130f4520SKenneth D. Merry 582130f4520SKenneth D. Merry void 583130f4520SKenneth D. Merry ctl_set_overlapped_cmd(struct ctl_scsiio *ctsio) 584130f4520SKenneth D. Merry { 585130f4520SKenneth D. Merry /* OVERLAPPED COMMANDS ATTEMPTED */ 586130f4520SKenneth D. Merry ctl_set_sense(ctsio, 587130f4520SKenneth D. Merry /*current_error*/ 1, 588130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 589130f4520SKenneth D. Merry /*asc*/ 0x4E, 590130f4520SKenneth D. Merry /*ascq*/ 0x00, 591130f4520SKenneth D. Merry SSD_ELEM_NONE); 592130f4520SKenneth D. Merry } 593130f4520SKenneth D. Merry 594130f4520SKenneth D. Merry void 595130f4520SKenneth D. Merry ctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag) 596130f4520SKenneth D. Merry { 597130f4520SKenneth D. Merry /* TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG) */ 598130f4520SKenneth D. Merry ctl_set_sense(ctsio, 599130f4520SKenneth D. Merry /*current_error*/ 1, 600130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 601130f4520SKenneth D. Merry /*asc*/ 0x4D, 602130f4520SKenneth D. Merry /*ascq*/ tag, 603130f4520SKenneth D. Merry SSD_ELEM_NONE); 604130f4520SKenneth D. Merry } 605130f4520SKenneth D. Merry 606130f4520SKenneth D. Merry /* 607130f4520SKenneth D. Merry * Tell the user that there was a problem with the command or data he sent. 608130f4520SKenneth D. Merry */ 609130f4520SKenneth D. Merry void 610130f4520SKenneth D. Merry ctl_set_invalid_field(struct ctl_scsiio *ctsio, int sks_valid, int command, 611130f4520SKenneth D. Merry int field, int bit_valid, int bit) 612130f4520SKenneth D. Merry { 613130f4520SKenneth D. Merry uint8_t sks[3]; 614130f4520SKenneth D. Merry int asc; 615130f4520SKenneth D. Merry 616130f4520SKenneth D. Merry if (command != 0) { 617130f4520SKenneth D. Merry /* "Invalid field in CDB" */ 618130f4520SKenneth D. Merry asc = 0x24; 619130f4520SKenneth D. Merry } else { 620130f4520SKenneth D. Merry /* "Invalid field in parameter list" */ 621130f4520SKenneth D. Merry asc = 0x26; 622130f4520SKenneth D. Merry } 623130f4520SKenneth D. Merry 624130f4520SKenneth D. Merry if (sks_valid) { 625130f4520SKenneth D. Merry sks[0] = SSD_SCS_VALID; 626130f4520SKenneth D. Merry if (command) 627130f4520SKenneth D. Merry sks[0] |= SSD_FIELDPTR_CMD; 628130f4520SKenneth D. Merry scsi_ulto2b(field, &sks[1]); 629130f4520SKenneth D. Merry 630130f4520SKenneth D. Merry if (bit_valid) 631130f4520SKenneth D. Merry sks[0] |= SSD_BITPTR_VALID | bit; 632130f4520SKenneth D. Merry } 633130f4520SKenneth D. Merry 634130f4520SKenneth D. Merry ctl_set_sense(ctsio, 635130f4520SKenneth D. Merry /*current_error*/ 1, 636130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 637130f4520SKenneth D. Merry asc, 638130f4520SKenneth D. Merry /*ascq*/ 0x00, 639130f4520SKenneth D. Merry /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 640130f4520SKenneth D. Merry /*size*/ sizeof(sks), 641130f4520SKenneth D. Merry /*data*/ sks, 642130f4520SKenneth D. Merry SSD_ELEM_NONE); 643130f4520SKenneth D. Merry } 644130f4520SKenneth D. Merry 645130f4520SKenneth D. Merry void 646130f4520SKenneth D. Merry ctl_set_invalid_opcode(struct ctl_scsiio *ctsio) 647130f4520SKenneth D. Merry { 648130f4520SKenneth D. Merry uint8_t sks[3]; 649130f4520SKenneth D. Merry 650130f4520SKenneth D. Merry sks[0] = SSD_SCS_VALID | SSD_FIELDPTR_CMD; 651130f4520SKenneth D. Merry scsi_ulto2b(0, &sks[1]); 652130f4520SKenneth D. Merry 653130f4520SKenneth D. Merry /* "Invalid command operation code" */ 654130f4520SKenneth D. Merry ctl_set_sense(ctsio, 655130f4520SKenneth D. Merry /*current_error*/ 1, 656130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 657130f4520SKenneth D. Merry /*asc*/ 0x20, 658130f4520SKenneth D. Merry /*ascq*/ 0x00, 659130f4520SKenneth D. Merry /*type*/ SSD_ELEM_SKS, 660130f4520SKenneth D. Merry /*size*/ sizeof(sks), 661130f4520SKenneth D. Merry /*data*/ sks, 662130f4520SKenneth D. Merry SSD_ELEM_NONE); 663130f4520SKenneth D. Merry } 664130f4520SKenneth D. Merry 665130f4520SKenneth D. Merry void 666130f4520SKenneth D. Merry ctl_set_param_len_error(struct ctl_scsiio *ctsio) 667130f4520SKenneth D. Merry { 668130f4520SKenneth D. Merry /* "Parameter list length error" */ 669130f4520SKenneth D. Merry ctl_set_sense(ctsio, 670130f4520SKenneth D. Merry /*current_error*/ 1, 671130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 672130f4520SKenneth D. Merry /*asc*/ 0x1a, 673130f4520SKenneth D. Merry /*ascq*/ 0x00, 674130f4520SKenneth D. Merry SSD_ELEM_NONE); 675130f4520SKenneth D. Merry } 676130f4520SKenneth D. Merry 677130f4520SKenneth D. Merry void 678130f4520SKenneth D. Merry ctl_set_already_locked(struct ctl_scsiio *ctsio) 679130f4520SKenneth D. Merry { 680130f4520SKenneth D. Merry /* Vendor unique "Somebody already is locked" */ 681130f4520SKenneth D. Merry ctl_set_sense(ctsio, 682130f4520SKenneth D. Merry /*current_error*/ 1, 683130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 684130f4520SKenneth D. Merry /*asc*/ 0x81, 685130f4520SKenneth D. Merry /*ascq*/ 0x00, 686130f4520SKenneth D. Merry SSD_ELEM_NONE); 687130f4520SKenneth D. Merry } 688130f4520SKenneth D. Merry 689130f4520SKenneth D. Merry void 690130f4520SKenneth D. Merry ctl_set_unsupported_lun(struct ctl_scsiio *ctsio) 691130f4520SKenneth D. Merry { 692130f4520SKenneth D. Merry /* "Logical unit not supported" */ 693130f4520SKenneth D. Merry ctl_set_sense(ctsio, 694130f4520SKenneth D. Merry /*current_error*/ 1, 695130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 696130f4520SKenneth D. Merry /*asc*/ 0x25, 697130f4520SKenneth D. Merry /*ascq*/ 0x00, 698130f4520SKenneth D. Merry SSD_ELEM_NONE); 699130f4520SKenneth D. Merry } 700130f4520SKenneth D. Merry 701130f4520SKenneth D. Merry void 702130f4520SKenneth D. Merry ctl_set_internal_failure(struct ctl_scsiio *ctsio, int sks_valid, 703130f4520SKenneth D. Merry uint16_t retry_count) 704130f4520SKenneth D. Merry { 705130f4520SKenneth D. Merry uint8_t sks[3]; 706130f4520SKenneth D. Merry 707130f4520SKenneth D. Merry if (sks_valid) { 708130f4520SKenneth D. Merry sks[0] = SSD_SCS_VALID; 709130f4520SKenneth D. Merry sks[1] = (retry_count >> 8) & 0xff; 710130f4520SKenneth D. Merry sks[2] = retry_count & 0xff; 711130f4520SKenneth D. Merry } 712130f4520SKenneth D. Merry 713130f4520SKenneth D. Merry /* "Internal target failure" */ 714130f4520SKenneth D. Merry ctl_set_sense(ctsio, 715130f4520SKenneth D. Merry /*current_error*/ 1, 716130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_HARDWARE_ERROR, 717130f4520SKenneth D. Merry /*asc*/ 0x44, 718130f4520SKenneth D. Merry /*ascq*/ 0x00, 719130f4520SKenneth D. Merry /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 720130f4520SKenneth D. Merry /*size*/ sizeof(sks), 721130f4520SKenneth D. Merry /*data*/ sks, 722130f4520SKenneth D. Merry SSD_ELEM_NONE); 723130f4520SKenneth D. Merry } 724130f4520SKenneth D. Merry 725130f4520SKenneth D. Merry void 7267f7bb97aSAlexander Motin ctl_set_medium_error(struct ctl_scsiio *ctsio, int read) 727130f4520SKenneth D. Merry { 7287f7bb97aSAlexander Motin if (read) { 729130f4520SKenneth D. Merry /* "Unrecovered read error" */ 730130f4520SKenneth D. Merry ctl_set_sense(ctsio, 731130f4520SKenneth D. Merry /*current_error*/ 1, 732130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 733130f4520SKenneth D. Merry /*asc*/ 0x11, 734130f4520SKenneth D. Merry /*ascq*/ 0x00, 735130f4520SKenneth D. Merry SSD_ELEM_NONE); 736130f4520SKenneth D. Merry } else { 737130f4520SKenneth D. Merry /* "Write error - auto reallocation failed" */ 738130f4520SKenneth D. Merry ctl_set_sense(ctsio, 739130f4520SKenneth D. Merry /*current_error*/ 1, 740130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 741130f4520SKenneth D. Merry /*asc*/ 0x0C, 742130f4520SKenneth D. Merry /*ascq*/ 0x02, 743130f4520SKenneth D. Merry SSD_ELEM_NONE); 744130f4520SKenneth D. Merry } 745130f4520SKenneth D. Merry } 746130f4520SKenneth D. Merry 747130f4520SKenneth D. Merry void 748130f4520SKenneth D. Merry ctl_set_aborted(struct ctl_scsiio *ctsio) 749130f4520SKenneth D. Merry { 750130f4520SKenneth D. Merry ctl_set_sense(ctsio, 751130f4520SKenneth D. Merry /*current_error*/ 1, 752130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ABORTED_COMMAND, 753130f4520SKenneth D. Merry /*asc*/ 0x45, 754130f4520SKenneth D. Merry /*ascq*/ 0x00, 755130f4520SKenneth D. Merry SSD_ELEM_NONE); 756130f4520SKenneth D. Merry } 757130f4520SKenneth D. Merry 758130f4520SKenneth D. Merry void 75932920cbfSAlexander Motin ctl_set_lba_out_of_range(struct ctl_scsiio *ctsio, uint64_t lba) 760130f4520SKenneth D. Merry { 76132920cbfSAlexander Motin uint8_t info[8]; 76232920cbfSAlexander Motin 76332920cbfSAlexander Motin scsi_u64to8b(lba, info); 76432920cbfSAlexander Motin 765130f4520SKenneth D. Merry /* "Logical block address out of range" */ 766130f4520SKenneth D. Merry ctl_set_sense(ctsio, 767130f4520SKenneth D. Merry /*current_error*/ 1, 768130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 769130f4520SKenneth D. Merry /*asc*/ 0x21, 770130f4520SKenneth D. Merry /*ascq*/ 0x00, 77132920cbfSAlexander Motin /*type*/ (lba != 0) ? SSD_ELEM_INFO : SSD_ELEM_SKIP, 77232920cbfSAlexander Motin /*size*/ sizeof(info), /*data*/ &info, 773130f4520SKenneth D. Merry SSD_ELEM_NONE); 774130f4520SKenneth D. Merry } 775130f4520SKenneth D. Merry 776130f4520SKenneth D. Merry void 777130f4520SKenneth D. Merry ctl_set_lun_stopped(struct ctl_scsiio *ctsio) 778130f4520SKenneth D. Merry { 779130f4520SKenneth D. Merry /* "Logical unit not ready, initializing cmd. required" */ 780130f4520SKenneth D. Merry ctl_set_sense(ctsio, 781130f4520SKenneth D. Merry /*current_error*/ 1, 782130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 783130f4520SKenneth D. Merry /*asc*/ 0x04, 784130f4520SKenneth D. Merry /*ascq*/ 0x02, 785130f4520SKenneth D. Merry SSD_ELEM_NONE); 786130f4520SKenneth D. Merry } 787130f4520SKenneth D. Merry 788130f4520SKenneth D. Merry void 789648dfc1aSAlexander Motin ctl_set_lun_int_reqd(struct ctl_scsiio *ctsio) 790130f4520SKenneth D. Merry { 791130f4520SKenneth D. Merry /* "Logical unit not ready, manual intervention required" */ 792130f4520SKenneth D. Merry ctl_set_sense(ctsio, 793130f4520SKenneth D. Merry /*current_error*/ 1, 794130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 795130f4520SKenneth D. Merry /*asc*/ 0x04, 796eebb09cfSAlexander Motin /*ascq*/ 0x03, 797130f4520SKenneth D. Merry SSD_ELEM_NONE); 798130f4520SKenneth D. Merry } 799130f4520SKenneth D. Merry 800130f4520SKenneth D. Merry void 801648dfc1aSAlexander Motin ctl_set_lun_ejected(struct ctl_scsiio *ctsio) 802648dfc1aSAlexander Motin { 803648dfc1aSAlexander Motin /* "Medium not present - tray open" */ 804648dfc1aSAlexander Motin ctl_set_sense(ctsio, 805648dfc1aSAlexander Motin /*current_error*/ 1, 806648dfc1aSAlexander Motin /*sense_key*/ SSD_KEY_NOT_READY, 807648dfc1aSAlexander Motin /*asc*/ 0x3A, 808648dfc1aSAlexander Motin /*ascq*/ 0x02, 809648dfc1aSAlexander Motin SSD_ELEM_NONE); 810648dfc1aSAlexander Motin } 811648dfc1aSAlexander Motin 812648dfc1aSAlexander Motin void 813648dfc1aSAlexander Motin ctl_set_lun_no_media(struct ctl_scsiio *ctsio) 814648dfc1aSAlexander Motin { 815648dfc1aSAlexander Motin /* "Medium not present - tray closed" */ 816648dfc1aSAlexander Motin ctl_set_sense(ctsio, 817648dfc1aSAlexander Motin /*current_error*/ 1, 818648dfc1aSAlexander Motin /*sense_key*/ SSD_KEY_NOT_READY, 819648dfc1aSAlexander Motin /*asc*/ 0x3A, 820648dfc1aSAlexander Motin /*ascq*/ 0x01, 821648dfc1aSAlexander Motin SSD_ELEM_NONE); 822648dfc1aSAlexander Motin } 823648dfc1aSAlexander Motin 824648dfc1aSAlexander Motin void 825130f4520SKenneth D. Merry ctl_set_illegal_pr_release(struct ctl_scsiio *ctsio) 826130f4520SKenneth D. Merry { 827130f4520SKenneth D. Merry /* "Invalid release of persistent reservation" */ 828130f4520SKenneth D. Merry ctl_set_sense(ctsio, 829130f4520SKenneth D. Merry /*current_error*/ 1, 830130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 831130f4520SKenneth D. Merry /*asc*/ 0x26, 832130f4520SKenneth D. Merry /*ascq*/ 0x04, 833130f4520SKenneth D. Merry SSD_ELEM_NONE); 834130f4520SKenneth D. Merry } 835130f4520SKenneth D. Merry 836130f4520SKenneth D. Merry void 8377ac58230SAlexander Motin ctl_set_lun_transit(struct ctl_scsiio *ctsio) 8387ac58230SAlexander Motin { 8397ac58230SAlexander Motin /* "Logical unit not ready, asymmetric access state transition" */ 8407ac58230SAlexander Motin ctl_set_sense(ctsio, 8417ac58230SAlexander Motin /*current_error*/ 1, 8427ac58230SAlexander Motin /*sense_key*/ SSD_KEY_NOT_READY, 8437ac58230SAlexander Motin /*asc*/ 0x04, 8447ac58230SAlexander Motin /*ascq*/ 0x0a, 8457ac58230SAlexander Motin SSD_ELEM_NONE); 8467ac58230SAlexander Motin } 8477ac58230SAlexander Motin 8487ac58230SAlexander Motin void 849130f4520SKenneth D. Merry ctl_set_lun_standby(struct ctl_scsiio *ctsio) 850130f4520SKenneth D. Merry { 851130f4520SKenneth D. Merry /* "Logical unit not ready, target port in standby state" */ 852130f4520SKenneth D. Merry ctl_set_sense(ctsio, 853130f4520SKenneth D. Merry /*current_error*/ 1, 854130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 855130f4520SKenneth D. Merry /*asc*/ 0x04, 856130f4520SKenneth D. Merry /*ascq*/ 0x0b, 857130f4520SKenneth D. Merry SSD_ELEM_NONE); 858130f4520SKenneth D. Merry } 859130f4520SKenneth D. Merry 860130f4520SKenneth D. Merry void 8617ac58230SAlexander Motin ctl_set_lun_unavail(struct ctl_scsiio *ctsio) 8627ac58230SAlexander Motin { 8637ac58230SAlexander Motin /* "Logical unit not ready, target port in unavailable state" */ 8647ac58230SAlexander Motin ctl_set_sense(ctsio, 8657ac58230SAlexander Motin /*current_error*/ 1, 8667ac58230SAlexander Motin /*sense_key*/ SSD_KEY_NOT_READY, 8677ac58230SAlexander Motin /*asc*/ 0x04, 8687ac58230SAlexander Motin /*ascq*/ 0x0c, 8697ac58230SAlexander Motin SSD_ELEM_NONE); 8707ac58230SAlexander Motin } 8717ac58230SAlexander Motin 8727ac58230SAlexander Motin void 873130f4520SKenneth D. Merry ctl_set_medium_format_corrupted(struct ctl_scsiio *ctsio) 874130f4520SKenneth D. Merry { 875130f4520SKenneth D. Merry /* "Medium format corrupted" */ 876130f4520SKenneth D. Merry ctl_set_sense(ctsio, 877130f4520SKenneth D. Merry /*current_error*/ 1, 878130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 879130f4520SKenneth D. Merry /*asc*/ 0x31, 880130f4520SKenneth D. Merry /*ascq*/ 0x00, 881130f4520SKenneth D. Merry SSD_ELEM_NONE); 882130f4520SKenneth D. Merry } 883130f4520SKenneth D. Merry 884130f4520SKenneth D. Merry void 885130f4520SKenneth D. Merry ctl_set_medium_magazine_inaccessible(struct ctl_scsiio *ctsio) 886130f4520SKenneth D. Merry { 887130f4520SKenneth D. Merry /* "Medium magazine not accessible" */ 888130f4520SKenneth D. Merry ctl_set_sense(ctsio, 889130f4520SKenneth D. Merry /*current_error*/ 1, 890130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 891130f4520SKenneth D. Merry /*asc*/ 0x3b, 892130f4520SKenneth D. Merry /*ascq*/ 0x11, 893130f4520SKenneth D. Merry SSD_ELEM_NONE); 894130f4520SKenneth D. Merry } 895130f4520SKenneth D. Merry 896130f4520SKenneth D. Merry void 897130f4520SKenneth D. Merry ctl_set_data_phase_error(struct ctl_scsiio *ctsio) 898130f4520SKenneth D. Merry { 899130f4520SKenneth D. Merry /* "Data phase error" */ 900130f4520SKenneth D. Merry ctl_set_sense(ctsio, 901130f4520SKenneth D. Merry /*current_error*/ 1, 902130f4520SKenneth D. Merry /*sense_key*/ SSD_KEY_NOT_READY, 903130f4520SKenneth D. Merry /*asc*/ 0x4b, 904130f4520SKenneth D. Merry /*ascq*/ 0x00, 905130f4520SKenneth D. Merry SSD_ELEM_NONE); 906130f4520SKenneth D. Merry } 907130f4520SKenneth D. Merry 908130f4520SKenneth D. Merry void 909130f4520SKenneth D. Merry ctl_set_reservation_conflict(struct ctl_scsiio *ctsio) 910130f4520SKenneth D. Merry { 911130f4520SKenneth D. Merry struct scsi_sense_data *sense; 912130f4520SKenneth D. Merry 913130f4520SKenneth D. Merry sense = &ctsio->sense_data; 914130f4520SKenneth D. Merry memset(sense, 0, sizeof(*sense)); 915130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT; 916130f4520SKenneth D. Merry ctsio->sense_len = 0; 917130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SCSI_ERROR; 918130f4520SKenneth D. Merry } 919130f4520SKenneth D. Merry 920130f4520SKenneth D. Merry void 921130f4520SKenneth D. Merry ctl_set_queue_full(struct ctl_scsiio *ctsio) 922130f4520SKenneth D. Merry { 923130f4520SKenneth D. Merry struct scsi_sense_data *sense; 924130f4520SKenneth D. Merry 925130f4520SKenneth D. Merry sense = &ctsio->sense_data; 926130f4520SKenneth D. Merry memset(sense, 0, sizeof(*sense)); 927130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_QUEUE_FULL; 928130f4520SKenneth D. Merry ctsio->sense_len = 0; 929130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SCSI_ERROR; 930130f4520SKenneth D. Merry } 931130f4520SKenneth D. Merry 932130f4520SKenneth D. Merry void 933130f4520SKenneth D. Merry ctl_set_busy(struct ctl_scsiio *ctsio) 934130f4520SKenneth D. Merry { 935130f4520SKenneth D. Merry struct scsi_sense_data *sense; 936130f4520SKenneth D. Merry 937130f4520SKenneth D. Merry sense = &ctsio->sense_data; 938130f4520SKenneth D. Merry memset(sense, 0, sizeof(*sense)); 939130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_BUSY; 940130f4520SKenneth D. Merry ctsio->sense_len = 0; 941130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SCSI_ERROR; 942130f4520SKenneth D. Merry } 943130f4520SKenneth D. Merry 944130f4520SKenneth D. Merry void 945b33b96e3SAlexander Motin ctl_set_task_aborted(struct ctl_scsiio *ctsio) 946b33b96e3SAlexander Motin { 947b33b96e3SAlexander Motin struct scsi_sense_data *sense; 948b33b96e3SAlexander Motin 949b33b96e3SAlexander Motin sense = &ctsio->sense_data; 950b33b96e3SAlexander Motin memset(sense, 0, sizeof(*sense)); 951b33b96e3SAlexander Motin ctsio->scsi_status = SCSI_STATUS_TASK_ABORTED; 952b33b96e3SAlexander Motin ctsio->sense_len = 0; 953b33b96e3SAlexander Motin ctsio->io_hdr.status = CTL_CMD_ABORTED; 954b33b96e3SAlexander Motin } 955b33b96e3SAlexander Motin 956b33b96e3SAlexander Motin void 9576187d472SAlexander Motin ctl_set_hw_write_protected(struct ctl_scsiio *ctsio) 9586187d472SAlexander Motin { 9596187d472SAlexander Motin /* "Hardware write protected" */ 9606187d472SAlexander Motin ctl_set_sense(ctsio, 9616187d472SAlexander Motin /*current_error*/ 1, 9626187d472SAlexander Motin /*sense_key*/ SSD_KEY_DATA_PROTECT, 9636187d472SAlexander Motin /*asc*/ 0x27, 9646187d472SAlexander Motin /*ascq*/ 0x01, 9656187d472SAlexander Motin SSD_ELEM_NONE); 9666187d472SAlexander Motin } 9676187d472SAlexander Motin 9686187d472SAlexander Motin void 9694fc18ff9SAlexander Motin ctl_set_space_alloc_fail(struct ctl_scsiio *ctsio) 9704fc18ff9SAlexander Motin { 9714fc18ff9SAlexander Motin /* "Space allocation failed write protect" */ 9724fc18ff9SAlexander Motin ctl_set_sense(ctsio, 9734fc18ff9SAlexander Motin /*current_error*/ 1, 9744fc18ff9SAlexander Motin /*sense_key*/ SSD_KEY_DATA_PROTECT, 9754fc18ff9SAlexander Motin /*asc*/ 0x27, 9764fc18ff9SAlexander Motin /*ascq*/ 0x07, 9774fc18ff9SAlexander Motin SSD_ELEM_NONE); 9784fc18ff9SAlexander Motin } 9794fc18ff9SAlexander Motin 9804fc18ff9SAlexander Motin void 981130f4520SKenneth D. Merry ctl_set_success(struct ctl_scsiio *ctsio) 982130f4520SKenneth D. Merry { 983130f4520SKenneth D. Merry struct scsi_sense_data *sense; 984130f4520SKenneth D. Merry 985130f4520SKenneth D. Merry sense = &ctsio->sense_data; 986130f4520SKenneth D. Merry memset(sense, 0, sizeof(*sense)); 987130f4520SKenneth D. Merry ctsio->scsi_status = SCSI_STATUS_OK; 988130f4520SKenneth D. Merry ctsio->sense_len = 0; 989130f4520SKenneth D. Merry ctsio->io_hdr.status = CTL_SUCCESS; 990130f4520SKenneth D. Merry } 991