1229997Sken/*- 2229997Sken * Copyright (c) 2003-2009 Silicon Graphics International Corp. 3229997Sken * Copyright (c) 2011 Spectra Logic Corporation 4229997Sken * All rights reserved. 5229997Sken * 6229997Sken * Redistribution and use in source and binary forms, with or without 7229997Sken * modification, are permitted provided that the following conditions 8229997Sken * are met: 9229997Sken * 1. Redistributions of source code must retain the above copyright 10229997Sken * notice, this list of conditions, and the following disclaimer, 11229997Sken * without modification. 12229997Sken * 2. Redistributions in binary form must reproduce at minimum a disclaimer 13229997Sken * substantially similar to the "NO WARRANTY" disclaimer below 14229997Sken * ("Disclaimer") and any redistribution must be conditioned upon 15229997Sken * including a substantially similar Disclaimer requirement for further 16229997Sken * binary redistribution. 17229997Sken * 18229997Sken * NO WARRANTY 19229997Sken * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20229997Sken * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21229997Sken * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 22229997Sken * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23229997Sken * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24229997Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25229997Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26229997Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27229997Sken * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28229997Sken * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29229997Sken * POSSIBILITY OF SUCH DAMAGES. 30229997Sken * 31229997Sken * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_error.c#2 $ 32229997Sken */ 33229997Sken/* 34229997Sken * CAM Target Layer error reporting routines. 35229997Sken * 36229997Sken * Author: Ken Merry <ken@FreeBSD.org> 37229997Sken */ 38229997Sken 39229997Sken#include <sys/cdefs.h> 40229997Sken__FBSDID("$FreeBSD$"); 41229997Sken 42229997Sken#include <sys/param.h> 43229997Sken#include <sys/systm.h> 44229997Sken#include <sys/kernel.h> 45229997Sken#include <sys/types.h> 46229997Sken#include <sys/malloc.h> 47229997Sken#include <sys/lock.h> 48229997Sken#include <sys/mutex.h> 49229997Sken#include <sys/condvar.h> 50229997Sken#include <sys/stddef.h> 51229997Sken#include <sys/ctype.h> 52233963Sken#include <sys/sysctl.h> 53229997Sken#include <machine/stdarg.h> 54229997Sken 55229997Sken#include <cam/scsi/scsi_all.h> 56229997Sken#include <cam/scsi/scsi_da.h> 57229997Sken#include <cam/ctl/ctl_io.h> 58229997Sken#include <cam/ctl/ctl.h> 59229997Sken#include <cam/ctl/ctl_frontend.h> 60229997Sken#include <cam/ctl/ctl_frontend_internal.h> 61229997Sken#include <cam/ctl/ctl_backend.h> 62229997Sken#include <cam/ctl/ctl_ioctl.h> 63229997Sken#include <cam/ctl/ctl_error.h> 64229997Sken#include <cam/ctl/ctl_ha.h> 65229997Sken#include <cam/ctl/ctl_private.h> 66229997Sken 67229997Skenvoid 68229997Skenctl_set_sense_data_va(struct scsi_sense_data *sense_data, void *lunptr, 69229997Sken scsi_sense_data_type sense_format, int current_error, 70229997Sken int sense_key, int asc, int ascq, va_list ap) 71229997Sken{ 72229997Sken struct ctl_lun *lun; 73229997Sken 74229997Sken lun = (struct ctl_lun *)lunptr; 75229997Sken 76229997Sken /* 77229997Sken * Determine whether to return fixed or descriptor format sense 78229997Sken * data. 79229997Sken */ 80229997Sken if (sense_format == SSD_TYPE_NONE) { 81229997Sken /* 82229997Sken * If the format isn't specified, we only return descriptor 83229997Sken * sense if the LUN exists and descriptor sense is turned 84229997Sken * on for that LUN. 85229997Sken */ 86229997Sken if ((lun != NULL) 87229997Sken && (lun->flags & CTL_LUN_SENSE_DESC)) 88229997Sken sense_format = SSD_TYPE_DESC; 89229997Sken else 90229997Sken sense_format = SSD_TYPE_FIXED; 91229997Sken } 92229997Sken 93229997Sken scsi_set_sense_data_va(sense_data, sense_format, current_error, 94229997Sken sense_key, asc, ascq, ap); 95229997Sken} 96229997Sken 97229997Skenvoid 98229997Skenctl_set_sense_data(struct scsi_sense_data *sense_data, void *lunptr, 99229997Sken scsi_sense_data_type sense_format, int current_error, 100229997Sken int sense_key, int asc, int ascq, ...) 101229997Sken{ 102229997Sken va_list ap; 103229997Sken 104229997Sken va_start(ap, ascq); 105229997Sken ctl_set_sense_data_va(sense_data, lunptr, sense_format, current_error, 106229997Sken sense_key, asc, ascq, ap); 107229997Sken va_end(ap); 108229997Sken} 109229997Sken 110229997Skenvoid 111229997Skenctl_set_sense(struct ctl_scsiio *ctsio, int current_error, int sense_key, 112229997Sken int asc, int ascq, ...) 113229997Sken{ 114229997Sken va_list ap; 115229997Sken struct ctl_lun *lun; 116229997Sken 117229997Sken /* 118229997Sken * The LUN can't go away until all of the commands have been 119229997Sken * completed. Therefore we can safely access the LUN structure and 120229997Sken * flags without the lock. 121229997Sken */ 122229997Sken lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 123229997Sken 124229997Sken va_start(ap, ascq); 125229997Sken ctl_set_sense_data_va(&ctsio->sense_data, 126229997Sken lun, 127229997Sken SSD_TYPE_NONE, 128229997Sken current_error, 129229997Sken sense_key, 130229997Sken asc, 131229997Sken ascq, 132229997Sken ap); 133229997Sken va_end(ap); 134229997Sken 135229997Sken ctsio->scsi_status = SCSI_STATUS_CHECK_COND; 136229997Sken ctsio->sense_len = SSD_FULL_SIZE; 137229997Sken ctsio->io_hdr.status = CTL_SCSI_ERROR | CTL_AUTOSENSE; 138229997Sken} 139229997Sken 140229997Sken/* 141229997Sken * Transform fixed sense data into descriptor sense data. 142229997Sken * 143229997Sken * For simplicity's sake, we assume that both sense structures are 144229997Sken * SSD_FULL_SIZE. Otherwise, the logic gets more complicated. 145229997Sken */ 146229997Skenvoid 147229997Skenctl_sense_to_desc(struct scsi_sense_data_fixed *sense_src, 148229997Sken struct scsi_sense_data_desc *sense_dest) 149229997Sken{ 150229997Sken struct scsi_sense_stream stream_sense; 151229997Sken int current_error; 152229997Sken uint8_t stream_bits; 153229997Sken 154229997Sken bzero(sense_dest, sizeof(*sense_dest)); 155229997Sken 156229997Sken if ((sense_src->error_code & SSD_ERRCODE) == SSD_DEFERRED_ERROR) 157229997Sken current_error = 0; 158229997Sken else 159229997Sken current_error = 1; 160229997Sken 161229997Sken bzero(&stream_sense, sizeof(stream_sense)); 162229997Sken 163229997Sken /* 164229997Sken * Check to see whether any of the tape-specific bits are set. If 165229997Sken * so, we'll need a stream sense descriptor. 166229997Sken */ 167229997Sken if (sense_src->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK)) 168229997Sken stream_bits = sense_src->flags & ~SSD_KEY; 169229997Sken else 170229997Sken stream_bits = 0; 171229997Sken 172229997Sken /* 173229997Sken * Utilize our sense setting routine to do the transform. If a 174229997Sken * value is set in the fixed sense data, set it in the descriptor 175229997Sken * data. Otherwise, skip it. 176229997Sken */ 177229997Sken ctl_set_sense_data((struct scsi_sense_data *)sense_dest, 178229997Sken /*lun*/ NULL, 179229997Sken /*sense_format*/ SSD_TYPE_DESC, 180229997Sken current_error, 181229997Sken /*sense_key*/ sense_src->flags & SSD_KEY, 182229997Sken /*asc*/ sense_src->add_sense_code, 183229997Sken /*ascq*/ sense_src->add_sense_code_qual, 184229997Sken 185229997Sken /* Information Bytes */ 186229997Sken (scsi_4btoul(sense_src->info) != 0) ? 187229997Sken SSD_ELEM_INFO : SSD_ELEM_SKIP, 188229997Sken sizeof(sense_src->info), 189229997Sken sense_src->info, 190229997Sken 191229997Sken /* Command specific bytes */ 192229997Sken (scsi_4btoul(sense_src->cmd_spec_info) != 0) ? 193229997Sken SSD_ELEM_COMMAND : SSD_ELEM_SKIP, 194229997Sken sizeof(sense_src->cmd_spec_info), 195229997Sken sense_src->cmd_spec_info, 196229997Sken 197229997Sken /* FRU */ 198229997Sken (sense_src->fru != 0) ? 199229997Sken SSD_ELEM_FRU : SSD_ELEM_SKIP, 200229997Sken sizeof(sense_src->fru), 201229997Sken &sense_src->fru, 202229997Sken 203229997Sken /* Sense Key Specific */ 204229997Sken (sense_src->sense_key_spec[0] & SSD_SCS_VALID) ? 205229997Sken SSD_ELEM_SKS : SSD_ELEM_SKIP, 206229997Sken sizeof(sense_src->sense_key_spec), 207229997Sken sense_src->sense_key_spec, 208229997Sken 209229997Sken /* Tape bits */ 210229997Sken (stream_bits != 0) ? 211229997Sken SSD_ELEM_STREAM : SSD_ELEM_SKIP, 212229997Sken sizeof(stream_bits), 213229997Sken &stream_bits, 214229997Sken 215229997Sken SSD_ELEM_NONE); 216229997Sken} 217229997Sken 218229997Sken/* 219229997Sken * Transform descriptor format sense data into fixed sense data. 220229997Sken * 221229997Sken * Some data may be lost in translation, because there are descriptors 222229997Sken * thant can't be represented as fixed sense data. 223229997Sken * 224229997Sken * For simplicity's sake, we assume that both sense structures are 225229997Sken * SSD_FULL_SIZE. Otherwise, the logic gets more complicated. 226229997Sken */ 227229997Skenvoid 228229997Skenctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src, 229229997Sken struct scsi_sense_data_fixed *sense_dest) 230229997Sken{ 231229997Sken int current_error; 232229997Sken uint8_t *info_ptr = NULL, *cmd_ptr = NULL, *fru_ptr = NULL; 233229997Sken uint8_t *sks_ptr = NULL, *stream_ptr = NULL; 234229997Sken int info_size = 0, cmd_size = 0, fru_size = 0; 235229997Sken int sks_size = 0, stream_size = 0; 236229997Sken int pos; 237229997Sken 238229997Sken if ((sense_src->error_code & SSD_ERRCODE) == SSD_DESC_CURRENT_ERROR) 239229997Sken current_error = 1; 240229997Sken else 241229997Sken current_error = 0; 242229997Sken 243229997Sken for (pos = 0; pos < (int)(sense_src->extra_len - 1);) { 244229997Sken struct scsi_sense_desc_header *header; 245229997Sken 246229997Sken header = (struct scsi_sense_desc_header *) 247229997Sken &sense_src->sense_desc[pos]; 248229997Sken 249229997Sken /* 250229997Sken * See if this record goes past the end of the sense data. 251229997Sken * It shouldn't, but check just in case. 252229997Sken */ 253229997Sken if ((pos + header->length + sizeof(*header)) > 254229997Sken sense_src->extra_len) 255229997Sken break; 256229997Sken 257229997Sken switch (sense_src->sense_desc[pos]) { 258229997Sken case SSD_DESC_INFO: { 259229997Sken struct scsi_sense_info *info; 260229997Sken 261229997Sken info = (struct scsi_sense_info *)header; 262229997Sken 263229997Sken info_ptr = info->info; 264229997Sken info_size = sizeof(info->info); 265229997Sken 266229997Sken pos += info->length + 267229997Sken sizeof(struct scsi_sense_desc_header); 268229997Sken break; 269229997Sken } 270229997Sken case SSD_DESC_COMMAND: { 271229997Sken struct scsi_sense_command *cmd; 272229997Sken 273229997Sken cmd = (struct scsi_sense_command *)header; 274229997Sken cmd_ptr = cmd->command_info; 275229997Sken cmd_size = sizeof(cmd->command_info); 276229997Sken 277229997Sken pos += cmd->length + 278229997Sken sizeof(struct scsi_sense_desc_header); 279229997Sken break; 280229997Sken } 281229997Sken case SSD_DESC_FRU: { 282229997Sken struct scsi_sense_fru *fru; 283229997Sken 284229997Sken fru = (struct scsi_sense_fru *)header; 285229997Sken fru_ptr = &fru->fru; 286229997Sken fru_size = sizeof(fru->fru); 287229997Sken pos += fru->length + 288229997Sken sizeof(struct scsi_sense_desc_header); 289229997Sken break; 290229997Sken } 291229997Sken case SSD_DESC_SKS: { 292229997Sken struct scsi_sense_sks *sks; 293229997Sken 294229997Sken sks = (struct scsi_sense_sks *)header; 295229997Sken sks_ptr = sks->sense_key_spec; 296229997Sken sks_size = sizeof(sks->sense_key_spec); 297229997Sken 298229997Sken pos = sks->length + 299229997Sken sizeof(struct scsi_sense_desc_header); 300229997Sken break; 301229997Sken } 302229997Sken case SSD_DESC_STREAM: { 303229997Sken struct scsi_sense_stream *stream_sense; 304229997Sken 305229997Sken stream_sense = (struct scsi_sense_stream *)header; 306229997Sken stream_ptr = &stream_sense->byte3; 307229997Sken stream_size = sizeof(stream_sense->byte3); 308229997Sken pos = stream_sense->length + 309229997Sken sizeof(struct scsi_sense_desc_header); 310229997Sken break; 311229997Sken } 312229997Sken default: 313229997Sken /* 314229997Sken * We don't recognize this particular sense 315229997Sken * descriptor type, so just skip it. 316229997Sken */ 317229997Sken pos += sizeof(*header) + header->length; 318229997Sken break; 319229997Sken } 320229997Sken } 321229997Sken 322229997Sken ctl_set_sense_data((struct scsi_sense_data *)sense_dest, 323229997Sken /*lun*/ NULL, 324229997Sken /*sense_format*/ SSD_TYPE_FIXED, 325229997Sken current_error, 326229997Sken /*sense_key*/ sense_src->sense_key & SSD_KEY, 327229997Sken /*asc*/ sense_src->add_sense_code, 328229997Sken /*ascq*/ sense_src->add_sense_code_qual, 329229997Sken 330229997Sken /* Information Bytes */ 331229997Sken (info_ptr != NULL) ? SSD_ELEM_INFO : SSD_ELEM_SKIP, 332229997Sken info_size, 333229997Sken info_ptr, 334229997Sken 335229997Sken /* Command specific bytes */ 336229997Sken (cmd_ptr != NULL) ? SSD_ELEM_COMMAND : SSD_ELEM_SKIP, 337229997Sken cmd_size, 338229997Sken cmd_ptr, 339229997Sken 340229997Sken /* FRU */ 341229997Sken (fru_ptr != NULL) ? SSD_ELEM_FRU : SSD_ELEM_SKIP, 342229997Sken fru_size, 343229997Sken fru_ptr, 344229997Sken 345229997Sken /* Sense Key Specific */ 346229997Sken (sks_ptr != NULL) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 347229997Sken sks_size, 348229997Sken sks_ptr, 349229997Sken 350229997Sken /* Tape bits */ 351229997Sken (stream_ptr != NULL) ? SSD_ELEM_STREAM : SSD_ELEM_SKIP, 352229997Sken stream_size, 353229997Sken stream_ptr, 354229997Sken 355229997Sken SSD_ELEM_NONE); 356229997Sken} 357229997Sken 358229997Skenvoid 359229997Skenctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq) 360229997Sken{ 361229997Sken ctl_set_sense(ctsio, 362229997Sken /*current_error*/ 1, 363229997Sken /*sense_key*/ SSD_KEY_UNIT_ATTENTION, 364229997Sken asc, 365229997Sken ascq, 366229997Sken SSD_ELEM_NONE); 367229997Sken} 368229997Sken 369229997Skenctl_ua_type 370229997Skenctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense, 371230334Sken scsi_sense_data_type sense_format) 372229997Sken{ 373229997Sken ctl_ua_type ua_to_build; 374229997Sken int i, asc, ascq; 375229997Sken 376229997Sken if (ua_type == CTL_UA_NONE) 377229997Sken return (ua_type); 378229997Sken 379229997Sken ua_to_build = CTL_UA_NONE; 380229997Sken 381229997Sken for (i = 0; i < (sizeof(ua_type) * 8); i++) { 382229997Sken if (ua_type & (1 << i)) { 383229997Sken ua_to_build = 1 << i; 384229997Sken break; 385229997Sken } 386229997Sken } 387229997Sken 388229997Sken switch (ua_to_build) { 389229997Sken case CTL_UA_POWERON: 390229997Sken /* 29h/01h POWER ON OCCURRED */ 391229997Sken asc = 0x29; 392229997Sken ascq = 0x01; 393229997Sken break; 394229997Sken case CTL_UA_BUS_RESET: 395229997Sken /* 29h/02h SCSI BUS RESET OCCURRED */ 396229997Sken asc = 0x29; 397229997Sken ascq = 0x02; 398229997Sken break; 399229997Sken case CTL_UA_TARG_RESET: 400229997Sken /* 29h/03h BUS DEVICE RESET FUNCTION OCCURRED*/ 401229997Sken asc = 0x29; 402229997Sken ascq = 0x03; 403229997Sken break; 404229997Sken case CTL_UA_LUN_RESET: 405229997Sken /* 29h/00h POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */ 406229997Sken /* 407229997Sken * Since we don't have a specific ASC/ASCQ pair for a LUN 408229997Sken * reset, just return the generic reset code. 409229997Sken */ 410229997Sken asc = 0x29; 411229997Sken ascq = 0x00; 412229997Sken break; 413229997Sken case CTL_UA_LUN_CHANGE: 414229997Sken /* 3Fh/0Eh REPORTED LUNS DATA HAS CHANGED */ 415229997Sken asc = 0x3F; 416229997Sken ascq = 0x0E; 417229997Sken break; 418229997Sken case CTL_UA_MODE_CHANGE: 419229997Sken /* 2Ah/01h MODE PARAMETERS CHANGED */ 420229997Sken asc = 0x2A; 421229997Sken ascq = 0x01; 422229997Sken break; 423229997Sken case CTL_UA_LOG_CHANGE: 424229997Sken /* 2Ah/02h LOG PARAMETERS CHANGED */ 425229997Sken asc = 0x2A; 426229997Sken ascq = 0x02; 427229997Sken break; 428229997Sken case CTL_UA_LVD: 429229997Sken /* 29h/06h TRANSCEIVER MODE CHANGED TO LVD */ 430229997Sken asc = 0x29; 431229997Sken ascq = 0x06; 432229997Sken break; 433229997Sken case CTL_UA_SE: 434229997Sken /* 29h/05h TRANSCEIVER MODE CHANGED TO SINGLE-ENDED */ 435229997Sken asc = 0x29; 436229997Sken ascq = 0x05; 437229997Sken break; 438229997Sken case CTL_UA_RES_PREEMPT: 439229997Sken /* 2Ah/03h RESERVATIONS PREEMPTED */ 440229997Sken asc = 0x2A; 441229997Sken ascq = 0x03; 442229997Sken break; 443229997Sken case CTL_UA_RES_RELEASE: 444229997Sken /* 2Ah/04h RESERVATIONS RELEASED */ 445229997Sken asc = 0x2A; 446229997Sken ascq = 0x04; 447229997Sken break; 448229997Sken case CTL_UA_REG_PREEMPT: 449229997Sken /* 2Ah/05h REGISTRATIONS PREEMPTED */ 450229997Sken asc = 0x2A; 451229997Sken ascq = 0x05; 452229997Sken break; 453229997Sken case CTL_UA_ASYM_ACC_CHANGE: 454229997Sken /* 2Ah/06n ASYMMETRIC ACCESS STATE CHANGED */ 455229997Sken asc = 0x2A; 456229997Sken ascq = 0x06; 457229997Sken break; 458232604Strasz case CTL_UA_CAPACITY_CHANGED: 459232604Strasz /* 2Ah/09n CAPACITY DATA HAS CHANGED */ 460232604Strasz asc = 0x2A; 461232604Strasz ascq = 0x09; 462232604Strasz break; 463229997Sken default: 464229997Sken ua_to_build = CTL_UA_NONE; 465229997Sken return (ua_to_build); 466229997Sken break; /* NOTREACHED */ 467229997Sken } 468229997Sken 469229997Sken ctl_set_sense_data(sense, 470229997Sken /*lun*/ NULL, 471229997Sken sense_format, 472229997Sken /*current_error*/ 1, 473229997Sken /*sense_key*/ SSD_KEY_UNIT_ATTENTION, 474229997Sken asc, 475229997Sken ascq, 476229997Sken SSD_ELEM_NONE); 477229997Sken 478229997Sken return (ua_to_build); 479229997Sken} 480229997Sken 481229997Skenvoid 482229997Skenctl_set_overlapped_cmd(struct ctl_scsiio *ctsio) 483229997Sken{ 484229997Sken /* OVERLAPPED COMMANDS ATTEMPTED */ 485229997Sken ctl_set_sense(ctsio, 486229997Sken /*current_error*/ 1, 487229997Sken /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 488229997Sken /*asc*/ 0x4E, 489229997Sken /*ascq*/ 0x00, 490229997Sken SSD_ELEM_NONE); 491229997Sken} 492229997Sken 493229997Skenvoid 494229997Skenctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag) 495229997Sken{ 496229997Sken /* TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG) */ 497229997Sken ctl_set_sense(ctsio, 498229997Sken /*current_error*/ 1, 499229997Sken /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 500229997Sken /*asc*/ 0x4D, 501229997Sken /*ascq*/ tag, 502229997Sken SSD_ELEM_NONE); 503229997Sken} 504229997Sken 505229997Sken/* 506229997Sken * Tell the user that there was a problem with the command or data he sent. 507229997Sken */ 508229997Skenvoid 509229997Skenctl_set_invalid_field(struct ctl_scsiio *ctsio, int sks_valid, int command, 510229997Sken int field, int bit_valid, int bit) 511229997Sken{ 512229997Sken uint8_t sks[3]; 513229997Sken int asc; 514229997Sken 515229997Sken if (command != 0) { 516229997Sken /* "Invalid field in CDB" */ 517229997Sken asc = 0x24; 518229997Sken } else { 519229997Sken /* "Invalid field in parameter list" */ 520229997Sken asc = 0x26; 521229997Sken } 522229997Sken 523229997Sken if (sks_valid) { 524229997Sken sks[0] = SSD_SCS_VALID; 525229997Sken if (command) 526229997Sken sks[0] |= SSD_FIELDPTR_CMD; 527229997Sken scsi_ulto2b(field, &sks[1]); 528229997Sken 529229997Sken if (bit_valid) 530229997Sken sks[0] |= SSD_BITPTR_VALID | bit; 531229997Sken } 532229997Sken 533229997Sken ctl_set_sense(ctsio, 534229997Sken /*current_error*/ 1, 535229997Sken /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 536229997Sken asc, 537229997Sken /*ascq*/ 0x00, 538229997Sken /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 539229997Sken /*size*/ sizeof(sks), 540229997Sken /*data*/ sks, 541229997Sken SSD_ELEM_NONE); 542229997Sken} 543229997Sken 544229997Skenvoid 545229997Skenctl_set_invalid_opcode(struct ctl_scsiio *ctsio) 546229997Sken{ 547229997Sken struct scsi_sense_data *sense; 548229997Sken uint8_t sks[3]; 549229997Sken 550229997Sken sense = &ctsio->sense_data; 551229997Sken 552229997Sken sks[0] = SSD_SCS_VALID | SSD_FIELDPTR_CMD; 553229997Sken scsi_ulto2b(0, &sks[1]); 554229997Sken 555229997Sken /* "Invalid command operation code" */ 556229997Sken ctl_set_sense(ctsio, 557229997Sken /*current_error*/ 1, 558229997Sken /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 559229997Sken /*asc*/ 0x20, 560229997Sken /*ascq*/ 0x00, 561229997Sken /*type*/ SSD_ELEM_SKS, 562229997Sken /*size*/ sizeof(sks), 563229997Sken /*data*/ sks, 564229997Sken SSD_ELEM_NONE); 565229997Sken} 566229997Sken 567229997Skenvoid 568229997Skenctl_set_param_len_error(struct ctl_scsiio *ctsio) 569229997Sken{ 570229997Sken /* "Parameter list length error" */ 571229997Sken ctl_set_sense(ctsio, 572229997Sken /*current_error*/ 1, 573229997Sken /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 574229997Sken /*asc*/ 0x1a, 575229997Sken /*ascq*/ 0x00, 576229997Sken SSD_ELEM_NONE); 577229997Sken} 578229997Sken 579229997Skenvoid 580229997Skenctl_set_already_locked(struct ctl_scsiio *ctsio) 581229997Sken{ 582229997Sken /* Vendor unique "Somebody already is locked" */ 583229997Sken ctl_set_sense(ctsio, 584229997Sken /*current_error*/ 1, 585229997Sken /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 586229997Sken /*asc*/ 0x81, 587229997Sken /*ascq*/ 0x00, 588229997Sken SSD_ELEM_NONE); 589229997Sken} 590229997Sken 591229997Skenvoid 592229997Skenctl_set_unsupported_lun(struct ctl_scsiio *ctsio) 593229997Sken{ 594229997Sken /* "Logical unit not supported" */ 595229997Sken ctl_set_sense(ctsio, 596229997Sken /*current_error*/ 1, 597229997Sken /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 598229997Sken /*asc*/ 0x25, 599229997Sken /*ascq*/ 0x00, 600229997Sken SSD_ELEM_NONE); 601229997Sken} 602229997Sken 603229997Skenvoid 604229997Skenctl_set_internal_failure(struct ctl_scsiio *ctsio, int sks_valid, 605229997Sken uint16_t retry_count) 606229997Sken{ 607229997Sken uint8_t sks[3]; 608229997Sken 609229997Sken if (sks_valid) { 610229997Sken sks[0] = SSD_SCS_VALID; 611229997Sken sks[1] = (retry_count >> 8) & 0xff; 612229997Sken sks[2] = retry_count & 0xff; 613229997Sken } 614229997Sken 615229997Sken /* "Internal target failure" */ 616229997Sken ctl_set_sense(ctsio, 617229997Sken /*current_error*/ 1, 618229997Sken /*sense_key*/ SSD_KEY_HARDWARE_ERROR, 619229997Sken /*asc*/ 0x44, 620229997Sken /*ascq*/ 0x00, 621229997Sken /*type*/ (sks_valid != 0) ? SSD_ELEM_SKS : SSD_ELEM_SKIP, 622229997Sken /*size*/ sizeof(sks), 623229997Sken /*data*/ sks, 624229997Sken SSD_ELEM_NONE); 625229997Sken} 626229997Sken 627229997Skenvoid 628229997Skenctl_set_medium_error(struct ctl_scsiio *ctsio) 629229997Sken{ 630229997Sken if ((ctsio->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) { 631229997Sken /* "Unrecovered read error" */ 632229997Sken ctl_set_sense(ctsio, 633229997Sken /*current_error*/ 1, 634229997Sken /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 635229997Sken /*asc*/ 0x11, 636229997Sken /*ascq*/ 0x00, 637229997Sken SSD_ELEM_NONE); 638229997Sken } else { 639229997Sken /* "Write error - auto reallocation failed" */ 640229997Sken ctl_set_sense(ctsio, 641229997Sken /*current_error*/ 1, 642229997Sken /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 643229997Sken /*asc*/ 0x0C, 644229997Sken /*ascq*/ 0x02, 645229997Sken SSD_ELEM_NONE); 646229997Sken } 647229997Sken} 648229997Sken 649229997Skenvoid 650229997Skenctl_set_aborted(struct ctl_scsiio *ctsio) 651229997Sken{ 652229997Sken ctl_set_sense(ctsio, 653229997Sken /*current_error*/ 1, 654229997Sken /*sense_key*/ SSD_KEY_ABORTED_COMMAND, 655229997Sken /*asc*/ 0x45, 656229997Sken /*ascq*/ 0x00, 657229997Sken SSD_ELEM_NONE); 658229997Sken} 659229997Sken 660229997Skenvoid 661229997Skenctl_set_lba_out_of_range(struct ctl_scsiio *ctsio) 662229997Sken{ 663229997Sken /* "Logical block address out of range" */ 664229997Sken ctl_set_sense(ctsio, 665229997Sken /*current_error*/ 1, 666229997Sken /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 667229997Sken /*asc*/ 0x21, 668229997Sken /*ascq*/ 0x00, 669229997Sken SSD_ELEM_NONE); 670229997Sken} 671229997Sken 672229997Skenvoid 673229997Skenctl_set_lun_stopped(struct ctl_scsiio *ctsio) 674229997Sken{ 675229997Sken /* "Logical unit not ready, initializing cmd. required" */ 676229997Sken ctl_set_sense(ctsio, 677229997Sken /*current_error*/ 1, 678229997Sken /*sense_key*/ SSD_KEY_NOT_READY, 679229997Sken /*asc*/ 0x04, 680229997Sken /*ascq*/ 0x02, 681229997Sken SSD_ELEM_NONE); 682229997Sken} 683229997Sken 684229997Skenvoid 685229997Skenctl_set_lun_not_ready(struct ctl_scsiio *ctsio) 686229997Sken{ 687229997Sken /* "Logical unit not ready, manual intervention required" */ 688229997Sken ctl_set_sense(ctsio, 689229997Sken /*current_error*/ 1, 690229997Sken /*sense_key*/ SSD_KEY_NOT_READY, 691229997Sken /*asc*/ 0x04, 692229997Sken /*ascq*/ 0x05, 693229997Sken SSD_ELEM_NONE); 694229997Sken} 695229997Sken 696229997Skenvoid 697229997Skenctl_set_illegal_pr_release(struct ctl_scsiio *ctsio) 698229997Sken{ 699229997Sken /* "Invalid release of persistent reservation" */ 700229997Sken ctl_set_sense(ctsio, 701229997Sken /*current_error*/ 1, 702229997Sken /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 703229997Sken /*asc*/ 0x26, 704229997Sken /*ascq*/ 0x04, 705229997Sken SSD_ELEM_NONE); 706229997Sken} 707229997Sken 708229997Skenvoid 709229997Skenctl_set_lun_standby(struct ctl_scsiio *ctsio) 710229997Sken{ 711229997Sken /* "Logical unit not ready, target port in standby state" */ 712229997Sken ctl_set_sense(ctsio, 713229997Sken /*current_error*/ 1, 714229997Sken /*sense_key*/ SSD_KEY_NOT_READY, 715229997Sken /*asc*/ 0x04, 716229997Sken /*ascq*/ 0x0b, 717229997Sken SSD_ELEM_NONE); 718229997Sken} 719229997Sken 720229997Skenvoid 721229997Skenctl_set_medium_format_corrupted(struct ctl_scsiio *ctsio) 722229997Sken{ 723229997Sken /* "Medium format corrupted" */ 724229997Sken ctl_set_sense(ctsio, 725229997Sken /*current_error*/ 1, 726229997Sken /*sense_key*/ SSD_KEY_MEDIUM_ERROR, 727229997Sken /*asc*/ 0x31, 728229997Sken /*ascq*/ 0x00, 729229997Sken SSD_ELEM_NONE); 730229997Sken} 731229997Sken 732229997Skenvoid 733229997Skenctl_set_medium_magazine_inaccessible(struct ctl_scsiio *ctsio) 734229997Sken{ 735229997Sken /* "Medium magazine not accessible" */ 736229997Sken ctl_set_sense(ctsio, 737229997Sken /*current_error*/ 1, 738229997Sken /*sense_key*/ SSD_KEY_NOT_READY, 739229997Sken /*asc*/ 0x3b, 740229997Sken /*ascq*/ 0x11, 741229997Sken SSD_ELEM_NONE); 742229997Sken} 743229997Sken 744229997Skenvoid 745229997Skenctl_set_data_phase_error(struct ctl_scsiio *ctsio) 746229997Sken{ 747229997Sken /* "Data phase error" */ 748229997Sken ctl_set_sense(ctsio, 749229997Sken /*current_error*/ 1, 750229997Sken /*sense_key*/ SSD_KEY_NOT_READY, 751229997Sken /*asc*/ 0x4b, 752229997Sken /*ascq*/ 0x00, 753229997Sken SSD_ELEM_NONE); 754229997Sken} 755229997Sken 756229997Skenvoid 757229997Skenctl_set_reservation_conflict(struct ctl_scsiio *ctsio) 758229997Sken{ 759229997Sken struct scsi_sense_data *sense; 760229997Sken 761229997Sken sense = &ctsio->sense_data; 762229997Sken memset(sense, 0, sizeof(*sense)); 763229997Sken ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT; 764229997Sken ctsio->sense_len = 0; 765229997Sken ctsio->io_hdr.status = CTL_SCSI_ERROR; 766229997Sken} 767229997Sken 768229997Skenvoid 769229997Skenctl_set_queue_full(struct ctl_scsiio *ctsio) 770229997Sken{ 771229997Sken struct scsi_sense_data *sense; 772229997Sken 773229997Sken sense = &ctsio->sense_data; 774229997Sken memset(sense, 0, sizeof(*sense)); 775229997Sken ctsio->scsi_status = SCSI_STATUS_QUEUE_FULL; 776229997Sken ctsio->sense_len = 0; 777229997Sken ctsio->io_hdr.status = CTL_SCSI_ERROR; 778229997Sken} 779229997Sken 780229997Skenvoid 781229997Skenctl_set_busy(struct ctl_scsiio *ctsio) 782229997Sken{ 783229997Sken struct scsi_sense_data *sense; 784229997Sken 785229997Sken sense = &ctsio->sense_data; 786229997Sken memset(sense, 0, sizeof(*sense)); 787229997Sken ctsio->scsi_status = SCSI_STATUS_BUSY; 788229997Sken ctsio->sense_len = 0; 789229997Sken ctsio->io_hdr.status = CTL_SCSI_ERROR; 790229997Sken} 791229997Sken 792229997Skenvoid 793229997Skenctl_set_success(struct ctl_scsiio *ctsio) 794229997Sken{ 795229997Sken struct scsi_sense_data *sense; 796229997Sken 797229997Sken sense = &ctsio->sense_data; 798229997Sken memset(sense, 0, sizeof(*sense)); 799229997Sken ctsio->scsi_status = SCSI_STATUS_OK; 800229997Sken ctsio->sense_len = 0; 801229997Sken ctsio->io_hdr.status = CTL_SUCCESS; 802229997Sken} 803