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