ctl_error.c revision 274732
1248613Sdes/*- 2248613Sdes * Copyright (c) 2003-2009 Silicon Graphics International Corp. 3248613Sdes * Copyright (c) 2011 Spectra Logic Corporation 4248613Sdes * All rights reserved. 5248613Sdes * 6248613Sdes * Redistribution and use in source and binary forms, with or without 7248613Sdes * modification, are permitted provided that the following conditions 8248613Sdes * are met: 9248613Sdes * 1. Redistributions of source code must retain the above copyright 10248613Sdes * notice, this list of conditions, and the following disclaimer, 11248613Sdes * without modification. 12248613Sdes * 2. Redistributions in binary form must reproduce at minimum a disclaimer 13248613Sdes * substantially similar to the "NO WARRANTY" disclaimer below 14248613Sdes * ("Disclaimer") and any redistribution must be conditioned upon 15248613Sdes * including a substantially similar Disclaimer requirement for further 16248613Sdes * binary redistribution. 17296781Sdes * 18248613Sdes * NO WARRANTY 19248613Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20248613Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21295367Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 22248613Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23248613Sdes * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24248613Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25248613Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26248613Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27248613Sdes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28248613Sdes * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29248613Sdes * POSSIBILITY OF SUCH DAMAGES. 30248613Sdes * 31248613Sdes * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_error.c#2 $ 32248613Sdes */ 33295367Sdes/* 34295367Sdes * CAM Target Layer error reporting routines. 35295367Sdes * 36248613Sdes * Author: Ken Merry <ken@FreeBSD.org> 37248613Sdes */ 38248613Sdes 39295367Sdes#include <sys/cdefs.h> 40295367Sdes__FBSDID("$FreeBSD: stable/10/sys/cam/ctl/ctl_error.c 274732 2014-11-20 01:55:12Z mav $"); 41248613Sdes 42248613Sdes#include <sys/param.h> 43248613Sdes#include <sys/systm.h> 44248613Sdes#include <sys/kernel.h> 45248613Sdes#include <sys/types.h> 46248613Sdes#include <sys/malloc.h> 47248613Sdes#include <sys/lock.h> 48248613Sdes#include <sys/mutex.h> 49248613Sdes#include <sys/condvar.h> 50248613Sdes#include <sys/stddef.h> 51248613Sdes#include <sys/ctype.h> 52248613Sdes#include <sys/sysctl.h> 53248613Sdes#include <machine/stdarg.h> 54248613Sdes 55248613Sdes#include <cam/scsi/scsi_all.h> 56248613Sdes#include <cam/scsi/scsi_da.h> 57248613Sdes#include <cam/ctl/ctl_io.h> 58248613Sdes#include <cam/ctl/ctl.h> 59248613Sdes#include <cam/ctl/ctl_frontend.h> 60248613Sdes#include <cam/ctl/ctl_frontend_internal.h> 61248613Sdes#include <cam/ctl/ctl_backend.h> 62248613Sdes#include <cam/ctl/ctl_ioctl.h> 63248613Sdes#include <cam/ctl/ctl_error.h> 64248613Sdes#include <cam/ctl/ctl_ha.h> 65248613Sdes#include <cam/ctl/ctl_private.h> 66248613Sdes 67248613Sdesvoid 68248613Sdesctl_set_sense_data_va(struct scsi_sense_data *sense_data, void *lunptr, 69248613Sdes scsi_sense_data_type sense_format, int current_error, 70248613Sdes int sense_key, int asc, int ascq, va_list ap) 71248613Sdes{ 72248613Sdes struct ctl_lun *lun; 73248613Sdes 74248613Sdes lun = (struct ctl_lun *)lunptr; 75248613Sdes 76248613Sdes /* 77295367Sdes * Determine whether to return fixed or descriptor format sense 78248613Sdes * data. 79248613Sdes */ 80248613Sdes if (sense_format == SSD_TYPE_NONE) { 81248613Sdes /* 82248613Sdes * If the format isn't specified, we only return descriptor 83248613Sdes * sense if the LUN exists and descriptor sense is turned 84248613Sdes * on for that LUN. 85248613Sdes */ 86295367Sdes if ((lun != NULL) 87248613Sdes && (lun->flags & CTL_LUN_SENSE_DESC)) 88248613Sdes sense_format = SSD_TYPE_DESC; 89248613Sdes else 90248613Sdes sense_format = SSD_TYPE_FIXED; 91248613Sdes } 92248613Sdes 93248613Sdes scsi_set_sense_data_va(sense_data, sense_format, current_error, 94248613Sdes sense_key, asc, ascq, ap); 95248613Sdes} 96248613Sdes 97248613Sdesvoid 98248613Sdesctl_set_sense_data(struct scsi_sense_data *sense_data, void *lunptr, 99248613Sdes scsi_sense_data_type sense_format, int current_error, 100248613Sdes int sense_key, int asc, int ascq, ...) 101248613Sdes{ 102248613Sdes va_list ap; 103248613Sdes 104248613Sdes va_start(ap, ascq); 105248613Sdes ctl_set_sense_data_va(sense_data, lunptr, sense_format, current_error, 106248613Sdes sense_key, asc, ascq, ap); 107248613Sdes va_end(ap); 108248613Sdes} 109248613Sdes 110248613Sdesvoid 111248613Sdesctl_set_sense(struct ctl_scsiio *ctsio, int current_error, int sense_key, 112248613Sdes int asc, int ascq, ...) 113248613Sdes{ 114248613Sdes va_list ap; 115248613Sdes struct ctl_lun *lun; 116248613Sdes 117248613Sdes /* 118248613Sdes * The LUN can't go away until all of the commands have been 119248613Sdes * completed. Therefore we can safely access the LUN structure and 120248613Sdes * flags without the lock. 121248613Sdes */ 122248613Sdes lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 123248613Sdes 124248613Sdes va_start(ap, ascq); 125248613Sdes ctl_set_sense_data_va(&ctsio->sense_data, 126248613Sdes lun, 127248613Sdes SSD_TYPE_NONE, 128248613Sdes current_error, 129248613Sdes sense_key, 130248613Sdes asc, 131248613Sdes ascq, 132248613Sdes ap); 133248613Sdes va_end(ap); 134248613Sdes 135248613Sdes ctsio->scsi_status = SCSI_STATUS_CHECK_COND; 136248613Sdes ctsio->sense_len = SSD_FULL_SIZE; 137248613Sdes ctsio->io_hdr.status = CTL_SCSI_ERROR | CTL_AUTOSENSE; 138248613Sdes} 139248613Sdes 140248613Sdes/* 141248613Sdes * Transform fixed sense data into descriptor sense data. 142248613Sdes * 143248613Sdes * For simplicity's sake, we assume that both sense structures are 144248613Sdes * SSD_FULL_SIZE. Otherwise, the logic gets more complicated. 145248613Sdes */ 146248613Sdesvoid 147248613Sdesctl_sense_to_desc(struct scsi_sense_data_fixed *sense_src, 148248613Sdes struct scsi_sense_data_desc *sense_dest) 149248613Sdes{ 150248613Sdes struct scsi_sense_stream stream_sense; 151248613Sdes int current_error; 152248613Sdes uint8_t stream_bits; 153248613Sdes 154248613Sdes bzero(sense_dest, sizeof(*sense_dest)); 155248613Sdes 156248613Sdes if ((sense_src->error_code & SSD_ERRCODE) == SSD_DEFERRED_ERROR) 157248613Sdes current_error = 0; 158248613Sdes else 159295367Sdes current_error = 1; 160248613Sdes 161248613Sdes bzero(&stream_sense, sizeof(stream_sense)); 162248613Sdes 163248613Sdes /* 164248613Sdes * Check to see whether any of the tape-specific bits are set. If 165248613Sdes * so, we'll need a stream sense descriptor. 166248613Sdes */ 167248613Sdes if (sense_src->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK)) 168248613Sdes stream_bits = sense_src->flags & ~SSD_KEY; 169248613Sdes else 170248613Sdes stream_bits = 0; 171248613Sdes 172248613Sdes /* 173248613Sdes * Utilize our sense setting routine to do the transform. If a 174248613Sdes * value is set in the fixed sense data, set it in the descriptor 175248613Sdes * data. Otherwise, skip it. 176248613Sdes */ 177248613Sdes ctl_set_sense_data((struct scsi_sense_data *)sense_dest, 178248613Sdes /*lun*/ NULL, 179248613Sdes /*sense_format*/ SSD_TYPE_DESC, 180248613Sdes current_error, 181248613Sdes /*sense_key*/ sense_src->flags & SSD_KEY, 182248613Sdes /*asc*/ sense_src->add_sense_code, 183248613Sdes /*ascq*/ sense_src->add_sense_code_qual, 184248613Sdes 185248613Sdes /* Information Bytes */ 186248613Sdes (scsi_4btoul(sense_src->info) != 0) ? 187248613Sdes SSD_ELEM_INFO : SSD_ELEM_SKIP, 188248613Sdes sizeof(sense_src->info), 189248613Sdes sense_src->info, 190248613Sdes 191248613Sdes /* Command specific bytes */ 192248613Sdes (scsi_4btoul(sense_src->cmd_spec_info) != 0) ? 193248613Sdes SSD_ELEM_COMMAND : SSD_ELEM_SKIP, 194295367Sdes sizeof(sense_src->cmd_spec_info), 195248613Sdes sense_src->cmd_spec_info, 196248613Sdes 197248613Sdes /* FRU */ 198248613Sdes (sense_src->fru != 0) ? 199295367Sdes SSD_ELEM_FRU : SSD_ELEM_SKIP, 200295367Sdes sizeof(sense_src->fru), 201248613Sdes &sense_src->fru, 202248613Sdes 203248613Sdes /* Sense Key Specific */ 204248613Sdes (sense_src->sense_key_spec[0] & SSD_SCS_VALID) ? 205248613Sdes SSD_ELEM_SKS : SSD_ELEM_SKIP, 206248613Sdes sizeof(sense_src->sense_key_spec), 207248613Sdes sense_src->sense_key_spec, 208295367Sdes 209248613Sdes /* Tape bits */ 210248613Sdes (stream_bits != 0) ? 211248613Sdes SSD_ELEM_STREAM : SSD_ELEM_SKIP, 212295367Sdes sizeof(stream_bits), 213248613Sdes &stream_bits, 214248613Sdes 215248613Sdes SSD_ELEM_NONE); 216295367Sdes} 217295367Sdes 218248613Sdes/* 219248613Sdes * Transform descriptor format sense data into fixed sense data. 220248613Sdes * 221248613Sdes * Some data may be lost in translation, because there are descriptors 222248613Sdes * thant can't be represented as fixed sense data. 223248613Sdes * 224248613Sdes * For simplicity's sake, we assume that both sense structures are 225248613Sdes * SSD_FULL_SIZE. Otherwise, the logic gets more complicated. 226295367Sdes */ 227295367Sdesvoid 228295367Sdesctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src, 229295367Sdes struct scsi_sense_data_fixed *sense_dest) 230248613Sdes{ 231295367Sdes int current_error; 232248613Sdes uint8_t *info_ptr = NULL, *cmd_ptr = NULL, *fru_ptr = NULL; 233248613Sdes uint8_t *sks_ptr = NULL, *stream_ptr = NULL; 234248613Sdes int info_size = 0, cmd_size = 0, fru_size = 0; 235248613Sdes int sks_size = 0, stream_size = 0; 236295367Sdes int pos; 237295367Sdes 238248613Sdes if ((sense_src->error_code & SSD_ERRCODE) == SSD_DESC_CURRENT_ERROR) 239248613Sdes current_error = 1; 240248613Sdes else 241248613Sdes current_error = 0; 242248613Sdes 243248613Sdes for (pos = 0; pos < (int)(sense_src->extra_len - 1);) { 244248613Sdes struct scsi_sense_desc_header *header; 245248613Sdes 246248613Sdes header = (struct scsi_sense_desc_header *) 247248613Sdes &sense_src->sense_desc[pos]; 248264377Sdes 249248613Sdes /* 250248613Sdes * See if this record goes past the end of the sense data. 251248613Sdes * It shouldn't, but check just in case. 252248613Sdes */ 253248613Sdes if ((pos + header->length + sizeof(*header)) > 254248613Sdes sense_src->extra_len) 255295367Sdes break; 256248613Sdes 257248613Sdes switch (sense_src->sense_desc[pos]) { 258248613Sdes case SSD_DESC_INFO: { 259248613Sdes struct scsi_sense_info *info; 260248613Sdes 261248613Sdes info = (struct scsi_sense_info *)header; 262295367Sdes 263248613Sdes info_ptr = info->info; 264248613Sdes info_size = sizeof(info->info); 265248613Sdes 266248613Sdes pos += info->length + 267248613Sdes sizeof(struct scsi_sense_desc_header); 268248613Sdes break; 269248613Sdes } 270248613Sdes case SSD_DESC_COMMAND: { 271248613Sdes struct scsi_sense_command *cmd; 272248613Sdes 273248613Sdes cmd = (struct scsi_sense_command *)header; 274248613Sdes cmd_ptr = cmd->command_info; 275248613Sdes cmd_size = sizeof(cmd->command_info); 276248613Sdes 277295367Sdes pos += cmd->length + 278248613Sdes sizeof(struct scsi_sense_desc_header); 279248613Sdes break; 280248613Sdes } 281248613Sdes case SSD_DESC_FRU: { 282248613Sdes struct scsi_sense_fru *fru; 283248613Sdes 284248613Sdes fru = (struct scsi_sense_fru *)header; 285248613Sdes fru_ptr = &fru->fru; 286248613Sdes fru_size = sizeof(fru->fru); 287248613Sdes pos += fru->length + 288248613Sdes sizeof(struct scsi_sense_desc_header); 289248613Sdes break; 290248613Sdes } 291248613Sdes case SSD_DESC_SKS: { 292248613Sdes struct scsi_sense_sks *sks; 293248613Sdes 294248613Sdes sks = (struct scsi_sense_sks *)header; 295248613Sdes sks_ptr = sks->sense_key_spec; 296248613Sdes sks_size = sizeof(sks->sense_key_spec); 297248613Sdes 298248613Sdes pos = sks->length + 299248613Sdes sizeof(struct scsi_sense_desc_header); 300248613Sdes break; 301248613Sdes } 302248613Sdes case SSD_DESC_STREAM: { 303248613Sdes struct scsi_sense_stream *stream_sense; 304248613Sdes 305248613Sdes stream_sense = (struct scsi_sense_stream *)header; 306248613Sdes stream_ptr = &stream_sense->byte3; 307248613Sdes stream_size = sizeof(stream_sense->byte3); 308248613Sdes pos = stream_sense->length + 309248613Sdes sizeof(struct scsi_sense_desc_header); 310248613Sdes break; 311248613Sdes } 312248613Sdes default: 313248613Sdes /* 314248613Sdes * We don't recognize this particular sense 315248613Sdes * descriptor type, so just skip it. 316295367Sdes */ 317248613Sdes pos += sizeof(*header) + header->length; 318248613Sdes break; 319248613Sdes } 320248613Sdes } 321248613Sdes 322248613Sdes ctl_set_sense_data((struct scsi_sense_data *)sense_dest, 323295367Sdes /*lun*/ NULL, 324295367Sdes /*sense_format*/ SSD_TYPE_FIXED, 325248613Sdes current_error, 326248613Sdes /*sense_key*/ sense_src->sense_key & SSD_KEY, 327295367Sdes /*asc*/ sense_src->add_sense_code, 328248613Sdes /*ascq*/ sense_src->add_sense_code_qual, 329248613Sdes 330295367Sdes /* Information Bytes */ 331295367Sdes (info_ptr != NULL) ? SSD_ELEM_INFO : SSD_ELEM_SKIP, 332295367Sdes info_size, 333248613Sdes info_ptr, 334248613Sdes 335248613Sdes /* Command specific bytes */ 336248613Sdes (cmd_ptr != NULL) ? SSD_ELEM_COMMAND : SSD_ELEM_SKIP, 337295367Sdes cmd_size, 338248613Sdes cmd_ptr, 339248613Sdes 340248613Sdes /* FRU */ 341248613Sdes (fru_ptr != NULL) ? SSD_ELEM_FRU : SSD_ELEM_SKIP, 342295367Sdes fru_size, 343248613Sdes fru_ptr, 344295367Sdes 345295367Sdes /* Sense Key Specific */ 346248613Sdes (sks_ptr != NULL) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 347295367Sdes sks_size, 348248613Sdes sks_ptr, 349248613Sdes 350248613Sdes /* Tape bits */ 351295367Sdes (stream_ptr != NULL) ? SSD_ELEM_STREAM : SSD_ELEM_SKIP, 352248613Sdes stream_size, 353248613Sdes stream_ptr, 354248613Sdes 355248613Sdes SSD_ELEM_NONE); 356248613Sdes} 357248613Sdes 358248613Sdesvoid 359248613Sdesctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq) 360248613Sdes{ 361248613Sdes ctl_set_sense(ctsio, 362248613Sdes /*current_error*/ 1, 363295367Sdes /*sense_key*/ SSD_KEY_UNIT_ATTENTION, 364248613Sdes asc, 365295367Sdes ascq, 366248613Sdes SSD_ELEM_NONE); 367248613Sdes} 368295367Sdes 369295367Sdesctl_ua_type 370295367Sdesctl_build_ua(ctl_ua_type *ua_type, struct scsi_sense_data *sense, 371295367Sdes scsi_sense_data_type sense_format) 372295367Sdes{ 373295367Sdes ctl_ua_type ua_to_build, ua_to_clear; 374248613Sdes int asc, ascq; 375248613Sdes 376295367Sdes if (*ua_type == CTL_UA_NONE) 377295367Sdes return (CTL_UA_NONE); 378295367Sdes 379248613Sdes ua_to_build = (1 << (ffs(*ua_type) - 1)); 380248613Sdes ua_to_clear = ua_to_build; 381248613Sdes 382248613Sdes switch (ua_to_build) { 383295367Sdes case CTL_UA_POWERON: 384248613Sdes /* 29h/01h POWER ON OCCURRED */ 385248613Sdes asc = 0x29; 386248613Sdes ascq = 0x01; 387248613Sdes ua_to_clear = ~0; 388295367Sdes break; 389248613Sdes case CTL_UA_BUS_RESET: 390248613Sdes /* 29h/02h SCSI BUS RESET OCCURRED */ 391248613Sdes asc = 0x29; 392248613Sdes ascq = 0x02; 393248613Sdes ua_to_clear = ~0; 394248613Sdes break; 395248613Sdes case CTL_UA_TARG_RESET: 396248613Sdes /* 29h/03h BUS DEVICE RESET FUNCTION OCCURRED*/ 397248613Sdes asc = 0x29; 398248613Sdes ascq = 0x03; 399248613Sdes ua_to_clear = ~0; 400295367Sdes break; 401248613Sdes case CTL_UA_I_T_NEXUS_LOSS: 402248613Sdes /* 29h/07h I_T NEXUS LOSS OCCURRED */ 403295367Sdes asc = 0x29; 404295367Sdes ascq = 0x07; 405248613Sdes ua_to_clear = ~0; 406295367Sdes break; 407295367Sdes case CTL_UA_LUN_RESET: 408295367Sdes /* 29h/00h POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */ 409248613Sdes /* 410248613Sdes * Since we don't have a specific ASC/ASCQ pair for a LUN 411248613Sdes * reset, just return the generic reset code. 412248613Sdes */ 413295367Sdes asc = 0x29; 414248613Sdes ascq = 0x00; 415248613Sdes break; 416295367Sdes case CTL_UA_LUN_CHANGE: 417295367Sdes /* 3Fh/0Eh REPORTED LUNS DATA HAS CHANGED */ 418248613Sdes asc = 0x3F; 419295367Sdes ascq = 0x0E; 420295367Sdes break; 421295367Sdes case CTL_UA_MODE_CHANGE: 422295367Sdes /* 2Ah/01h MODE PARAMETERS CHANGED */ 423248613Sdes asc = 0x2A; 424248613Sdes ascq = 0x01; 425248613Sdes break; 426248613Sdes case CTL_UA_LOG_CHANGE: 427295367Sdes /* 2Ah/02h LOG PARAMETERS CHANGED */ 428248613Sdes asc = 0x2A; 429295367Sdes ascq = 0x02; 430248613Sdes break; 431248613Sdes case CTL_UA_LVD: 432295367Sdes /* 29h/06h TRANSCEIVER MODE CHANGED TO LVD */ 433248613Sdes asc = 0x29; 434248613Sdes ascq = 0x06; 435248613Sdes break; 436248613Sdes case CTL_UA_SE: 437248613Sdes /* 29h/05h TRANSCEIVER MODE CHANGED TO SINGLE-ENDED */ 438248613Sdes asc = 0x29; 439248613Sdes ascq = 0x05; 440248613Sdes break; 441248613Sdes case CTL_UA_RES_PREEMPT: 442248613Sdes /* 2Ah/03h RESERVATIONS PREEMPTED */ 443248613Sdes asc = 0x2A; 444295367Sdes ascq = 0x03; 445295367Sdes break; 446248613Sdes case CTL_UA_RES_RELEASE: 447248613Sdes /* 2Ah/04h RESERVATIONS RELEASED */ 448248613Sdes asc = 0x2A; 449248613Sdes ascq = 0x04; 450248613Sdes break; 451248613Sdes case CTL_UA_REG_PREEMPT: 452248613Sdes /* 2Ah/05h REGISTRATIONS PREEMPTED */ 453248613Sdes asc = 0x2A; 454248613Sdes ascq = 0x05; 455248613Sdes break; 456248613Sdes case CTL_UA_ASYM_ACC_CHANGE: 457248613Sdes /* 2Ah/06n ASYMMETRIC ACCESS STATE CHANGED */ 458248613Sdes asc = 0x2A; 459248613Sdes ascq = 0x06; 460248613Sdes break; 461248613Sdes case CTL_UA_CAPACITY_CHANGED: 462248613Sdes /* 2Ah/09n CAPACITY DATA HAS CHANGED */ 463248613Sdes asc = 0x2A; 464248613Sdes ascq = 0x09; 465248613Sdes break; 466248613Sdes case CTL_UA_THIN_PROV_THRES: 467248613Sdes /* 38h/07n THIN PROVISIONING SOFT THRESHOLD REACHED */ 468248613Sdes asc = 0x38; 469248613Sdes ascq = 0x07; 470248613Sdes break; 471248613Sdes default: 472248613Sdes panic("ctl_build_ua: Unknown UA %x", ua_to_build); 473248613Sdes } 474248613Sdes 475248613Sdes ctl_set_sense_data(sense, 476248613Sdes /*lun*/ NULL, 477248613Sdes sense_format, 478248613Sdes /*current_error*/ 1, 479248613Sdes /*sense_key*/ SSD_KEY_UNIT_ATTENTION, 480248613Sdes asc, 481248613Sdes ascq, 482248613Sdes SSD_ELEM_NONE); 483248613Sdes 484248613Sdes /* We're reporting this UA, so clear it */ 485248613Sdes *ua_type &= ~ua_to_clear; 486248613Sdes 487248613Sdes return (ua_to_build); 488248613Sdes} 489248613Sdes 490248613Sdesvoid 491248613Sdesctl_set_overlapped_cmd(struct ctl_scsiio *ctsio) 492248613Sdes{ 493248613Sdes /* OVERLAPPED COMMANDS ATTEMPTED */ 494248613Sdes ctl_set_sense(ctsio, 495248613Sdes /*current_error*/ 1, 496248613Sdes /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 497248613Sdes /*asc*/ 0x4E, 498248613Sdes /*ascq*/ 0x00, 499248613Sdes SSD_ELEM_NONE); 500248613Sdes} 501248613Sdes 502248613Sdesvoid 503248613Sdesctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag) 504248613Sdes{ 505248613Sdes /* TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG) */ 506248613Sdes ctl_set_sense(ctsio, 507248613Sdes /*current_error*/ 1, 508248613Sdes /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 509248613Sdes /*asc*/ 0x4D, 510248613Sdes /*ascq*/ tag, 511248613Sdes SSD_ELEM_NONE); 512248613Sdes} 513248613Sdes 514248613Sdes/* 515295367Sdes * Tell the user that there was a problem with the command or data he sent. 516248613Sdes */ 517255767Sdesvoid 518255767Sdesctl_set_invalid_field(struct ctl_scsiio *ctsio, int sks_valid, int command, 519255767Sdes int field, int bit_valid, int bit) 520255767Sdes{ 521255767Sdes uint8_t sks[3]; 522295367Sdes int asc; 523248613Sdes 524248613Sdes if (command != 0) { 525248613Sdes /* "Invalid field in CDB" */ 526295367Sdes asc = 0x24; 527295367Sdes } else { 528295367Sdes /* "Invalid field in parameter list" */ 529295367Sdes asc = 0x26; 530295367Sdes } 531295367Sdes 532295367Sdes if (sks_valid) { 533295367Sdes sks[0] = SSD_SCS_VALID; 534295367Sdes if (command) 535295367Sdes sks[0] |= SSD_FIELDPTR_CMD; 536295367Sdes scsi_ulto2b(field, &sks[1]); 537295367Sdes 538295367Sdes if (bit_valid) 539295367Sdes sks[0] |= SSD_BITPTR_VALID | bit; 540295367Sdes } 541295367Sdes 542295367Sdes ctl_set_sense(ctsio, 543295367Sdes /*current_error*/ 1, 544295367Sdes /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 545248613Sdes asc, 546248613Sdes /*ascq*/ 0x00, 547295367Sdes /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 548248613Sdes /*size*/ sizeof(sks), 549295367Sdes /*data*/ sks, 550248613Sdes SSD_ELEM_NONE); 551248613Sdes} 552248613Sdes 553248613Sdesvoid 554295367Sdesctl_set_invalid_opcode(struct ctl_scsiio *ctsio) 555295367Sdes{ 556248613Sdes struct scsi_sense_data *sense; 557295367Sdes uint8_t sks[3]; 558295367Sdes 559248613Sdes sense = &ctsio->sense_data; 560295367Sdes 561295367Sdes sks[0] = SSD_SCS_VALID | SSD_FIELDPTR_CMD; 562295367Sdes scsi_ulto2b(0, &sks[1]); 563295367Sdes 564295367Sdes /* "Invalid command operation code" */ 565295367Sdes ctl_set_sense(ctsio, 566295367Sdes /*current_error*/ 1, 567295367Sdes /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 568295367Sdes /*asc*/ 0x20, 569295367Sdes /*ascq*/ 0x00, 570248613Sdes /*type*/ SSD_ELEM_SKS, 571248613Sdes /*size*/ sizeof(sks), 572248613Sdes /*data*/ sks, 573248613Sdes SSD_ELEM_NONE); 574248613Sdes} 575295367Sdes 576255767Sdesvoid 577295367Sdesctl_set_param_len_error(struct ctl_scsiio *ctsio) 578248613Sdes{ 579248613Sdes /* "Parameter list length error" */ 580248613Sdes ctl_set_sense(ctsio, 581248613Sdes /*current_error*/ 1, 582248613Sdes /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 583248613Sdes /*asc*/ 0x1a, 584248613Sdes /*ascq*/ 0x00, 585248613Sdes SSD_ELEM_NONE); 586248613Sdes} 587248613Sdes 588248613Sdesvoid 589248613Sdesctl_set_already_locked(struct ctl_scsiio *ctsio) 590248613Sdes{ 591248613Sdes /* Vendor unique "Somebody already is locked" */ 592248613Sdes ctl_set_sense(ctsio, 593248613Sdes /*current_error*/ 1, 594248613Sdes /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 595295367Sdes /*asc*/ 0x81, 596248613Sdes /*ascq*/ 0x00, 597248613Sdes SSD_ELEM_NONE); 598248613Sdes} 599248613Sdes 600248613Sdesvoid 601295367Sdesctl_set_unsupported_lun(struct ctl_scsiio *ctsio) 602295367Sdes{ 603295367Sdes /* "Logical unit not supported" */ 604248613Sdes ctl_set_sense(ctsio, 605248613Sdes /*current_error*/ 1, 606248613Sdes /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 607295367Sdes /*asc*/ 0x25, 608295367Sdes /*ascq*/ 0x00, 609295367Sdes SSD_ELEM_NONE); 610295367Sdes} 611248613Sdes 612248613Sdesvoid 613248613Sdesctl_set_internal_failure(struct ctl_scsiio *ctsio, int sks_valid, 614248613Sdes uint16_t retry_count) 615295367Sdes{ 616295367Sdes uint8_t sks[3]; 617248613Sdes 618295367Sdes if (sks_valid) { 619248613Sdes sks[0] = SSD_SCS_VALID; 620248613Sdes sks[1] = (retry_count >> 8) & 0xff; 621248613Sdes sks[2] = retry_count & 0xff; 622248613Sdes } 623248613Sdes 624295367Sdes /* "Internal target failure" */ 625295367Sdes ctl_set_sense(ctsio, 626248613Sdes /*current_error*/ 1, 627295367Sdes /*sense_key*/ SSD_KEY_HARDWARE_ERROR, 628248613Sdes /*asc*/ 0x44, 629295367Sdes /*ascq*/ 0x00, 630295367Sdes /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 631295367Sdes /*size*/ sizeof(sks), 632248613Sdes /*data*/ sks, 633248613Sdes SSD_ELEM_NONE); 634248613Sdes} 635248613Sdes 636248613Sdesvoid 637248613Sdesctl_set_medium_error(struct ctl_scsiio *ctsio) 638248613Sdes{ 639295367Sdes if ((ctsio->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) { 640295367Sdes /* "Unrecovered read error" */ 641295367Sdes ctl_set_sense(ctsio, 642295367Sdes /*current_error*/ 1, 643248613Sdes /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 644248613Sdes /*asc*/ 0x11, 645295367Sdes /*ascq*/ 0x00, 646295367Sdes SSD_ELEM_NONE); 647295367Sdes } else { 648248613Sdes /* "Write error - auto reallocation failed" */ 649248613Sdes ctl_set_sense(ctsio, 650248613Sdes /*current_error*/ 1, 651248613Sdes /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 652248613Sdes /*asc*/ 0x0C, 653248613Sdes /*ascq*/ 0x02, 654248613Sdes SSD_ELEM_NONE); 655295367Sdes } 656295367Sdes} 657295367Sdes 658248613Sdesvoid 659295367Sdesctl_set_aborted(struct ctl_scsiio *ctsio) 660248613Sdes{ 661248613Sdes ctl_set_sense(ctsio, 662248613Sdes /*current_error*/ 1, 663248613Sdes /*sense_key*/ SSD_KEY_ABORTED_COMMAND, 664248613Sdes /*asc*/ 0x45, 665248613Sdes /*ascq*/ 0x00, 666248613Sdes SSD_ELEM_NONE); 667295367Sdes} 668295367Sdes 669248613Sdesvoid 670248613Sdesctl_set_lba_out_of_range(struct ctl_scsiio *ctsio) 671248613Sdes{ 672248613Sdes /* "Logical block address out of range" */ 673248613Sdes ctl_set_sense(ctsio, 674295367Sdes /*current_error*/ 1, 675295367Sdes /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 676295367Sdes /*asc*/ 0x21, 677248613Sdes /*ascq*/ 0x00, 678248613Sdes SSD_ELEM_NONE); 679248613Sdes} 680295367Sdes 681295367Sdesvoid 682295367Sdesctl_set_lun_stopped(struct ctl_scsiio *ctsio) 683248613Sdes{ 684295367Sdes /* "Logical unit not ready, initializing cmd. required" */ 685248613Sdes ctl_set_sense(ctsio, 686248613Sdes /*current_error*/ 1, 687295367Sdes /*sense_key*/ SSD_KEY_NOT_READY, 688248613Sdes /*asc*/ 0x04, 689295367Sdes /*ascq*/ 0x02, 690295367Sdes SSD_ELEM_NONE); 691295367Sdes} 692248613Sdes 693295367Sdesvoid 694295367Sdesctl_set_lun_not_ready(struct ctl_scsiio *ctsio) 695295367Sdes{ 696295367Sdes /* "Logical unit not ready, manual intervention required" */ 697248613Sdes ctl_set_sense(ctsio, 698248613Sdes /*current_error*/ 1, 699248613Sdes /*sense_key*/ SSD_KEY_NOT_READY, 700295367Sdes /*asc*/ 0x04, 701295367Sdes /*ascq*/ 0x03, 702248613Sdes SSD_ELEM_NONE); 703248613Sdes} 704248613Sdes 705248613Sdesvoid 706295367Sdesctl_set_illegal_pr_release(struct ctl_scsiio *ctsio) 707295367Sdes{ 708248613Sdes /* "Invalid release of persistent reservation" */ 709295367Sdes ctl_set_sense(ctsio, 710248613Sdes /*current_error*/ 1, 711248613Sdes /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 712295367Sdes /*asc*/ 0x26, 713295367Sdes /*ascq*/ 0x04, 714295367Sdes SSD_ELEM_NONE); 715248613Sdes} 716248613Sdes 717248613Sdesvoid 718248613Sdesctl_set_lun_standby(struct ctl_scsiio *ctsio) 719295367Sdes{ 720295367Sdes /* "Logical unit not ready, target port in standby state" */ 721248613Sdes ctl_set_sense(ctsio, 722248613Sdes /*current_error*/ 1, 723295367Sdes /*sense_key*/ SSD_KEY_NOT_READY, 724295367Sdes /*asc*/ 0x04, 725295367Sdes /*ascq*/ 0x0b, 726296781Sdes SSD_ELEM_NONE); 727295367Sdes} 728295367Sdes 729295367Sdesvoid 730295367Sdesctl_set_medium_format_corrupted(struct ctl_scsiio *ctsio) 731248613Sdes{ 732248613Sdes /* "Medium format corrupted" */ 733248613Sdes ctl_set_sense(ctsio, 734295367Sdes /*current_error*/ 1, 735295367Sdes /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 736248613Sdes /*asc*/ 0x31, 737295367Sdes /*ascq*/ 0x00, 738295367Sdes SSD_ELEM_NONE); 739295367Sdes} 740248613Sdes 741248613Sdesvoid 742248613Sdesctl_set_medium_magazine_inaccessible(struct ctl_scsiio *ctsio) 743295367Sdes{ 744248613Sdes /* "Medium magazine not accessible" */ 745295367Sdes ctl_set_sense(ctsio, 746295367Sdes /*current_error*/ 1, 747295367Sdes /*sense_key*/ SSD_KEY_NOT_READY, 748248613Sdes /*asc*/ 0x3b, 749295367Sdes /*ascq*/ 0x11, 750295367Sdes SSD_ELEM_NONE); 751295367Sdes} 752295367Sdes 753248613Sdesvoid 754295367Sdesctl_set_data_phase_error(struct ctl_scsiio *ctsio) 755248613Sdes{ 756295367Sdes /* "Data phase error" */ 757295367Sdes ctl_set_sense(ctsio, 758295367Sdes /*current_error*/ 1, 759248613Sdes /*sense_key*/ SSD_KEY_NOT_READY, 760295367Sdes /*asc*/ 0x4b, 761295367Sdes /*ascq*/ 0x00, 762295367Sdes SSD_ELEM_NONE); 763295367Sdes} 764295367Sdes 765248613Sdesvoid 766248613Sdesctl_set_reservation_conflict(struct ctl_scsiio *ctsio) 767248613Sdes{ 768295367Sdes struct scsi_sense_data *sense; 769295367Sdes 770295367Sdes sense = &ctsio->sense_data; 771295367Sdes memset(sense, 0, sizeof(*sense)); 772248613Sdes ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT; 773248613Sdes ctsio->sense_len = 0; 774295367Sdes ctsio->io_hdr.status = CTL_SCSI_ERROR; 775296781Sdes} 776248613Sdes 777295367Sdesvoid 778295367Sdesctl_set_queue_full(struct ctl_scsiio *ctsio) 779295367Sdes{ 780248613Sdes struct scsi_sense_data *sense; 781248613Sdes 782248613Sdes sense = &ctsio->sense_data; 783248613Sdes memset(sense, 0, sizeof(*sense)); 784248613Sdes ctsio->scsi_status = SCSI_STATUS_QUEUE_FULL; 785295367Sdes ctsio->sense_len = 0; 786248613Sdes ctsio->io_hdr.status = CTL_SCSI_ERROR; 787248613Sdes} 788248613Sdes 789248613Sdesvoid 790248613Sdesctl_set_busy(struct ctl_scsiio *ctsio) 791248613Sdes{ 792248613Sdes struct scsi_sense_data *sense; 793248613Sdes 794248613Sdes sense = &ctsio->sense_data; 795248613Sdes memset(sense, 0, sizeof(*sense)); 796248613Sdes ctsio->scsi_status = SCSI_STATUS_BUSY; 797295367Sdes ctsio->sense_len = 0; 798295367Sdes ctsio->io_hdr.status = CTL_SCSI_ERROR; 799295367Sdes} 800295367Sdes 801295367Sdesvoid 802295367Sdesctl_set_task_aborted(struct ctl_scsiio *ctsio) 803248613Sdes{ 804248613Sdes struct scsi_sense_data *sense; 805248613Sdes 806295367Sdes sense = &ctsio->sense_data; 807248613Sdes memset(sense, 0, sizeof(*sense)); 808295367Sdes ctsio->scsi_status = SCSI_STATUS_TASK_ABORTED; 809295367Sdes ctsio->sense_len = 0; 810295367Sdes ctsio->io_hdr.status = CTL_CMD_ABORTED; 811295367Sdes} 812295367Sdes 813248613Sdesvoid 814295367Sdesctl_set_space_alloc_fail(struct ctl_scsiio *ctsio) 815248613Sdes{ 816295367Sdes /* "Space allocation failed write protect" */ 817248613Sdes ctl_set_sense(ctsio, 818295367Sdes /*current_error*/ 1, 819295367Sdes /*sense_key*/ SSD_KEY_DATA_PROTECT, 820248613Sdes /*asc*/ 0x27, 821295367Sdes /*ascq*/ 0x07, 822295367Sdes SSD_ELEM_NONE); 823295367Sdes} 824248613Sdes 825295367Sdesvoid 826248613Sdesctl_set_success(struct ctl_scsiio *ctsio) 827248613Sdes{ 828295367Sdes struct scsi_sense_data *sense; 829296781Sdes 830296781Sdes sense = &ctsio->sense_data; 831295367Sdes memset(sense, 0, sizeof(*sense)); 832295367Sdes ctsio->scsi_status = SCSI_STATUS_OK; 833248613Sdes ctsio->sense_len = 0; 834295367Sdes ctsio->io_hdr.status = CTL_SUCCESS; 835295367Sdes} 836248613Sdes