1 /*- 2 * Copyright (c) 2003 Silicon Graphics International Corp. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * substantially similar to the "NO WARRANTY" disclaimer below 13 * ("Disclaimer") and any redistribution must be conditioned upon 14 * including a substantially similar Disclaimer requirement for further 15 * binary redistribution. 16 * 17 * NO WARRANTY 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGES. 29 * 30 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_util.c#2 $ 31 */ 32 /* 33 * CAM Target Layer SCSI library 34 * 35 * Author: Ken Merry <ken@FreeBSD.org> 36 */ 37 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 #ifdef _KERNEL 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/types.h> 46 #include <sys/malloc.h> 47 #else /* __KERNEL__ */ 48 #include <sys/types.h> 49 #include <sys/time.h> 50 #include <stdint.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #endif /* __KERNEL__ */ 55 #include <sys/sbuf.h> 56 #include <sys/queue.h> 57 #include <sys/callout.h> 58 #include <cam/scsi/scsi_all.h> 59 #include <cam/ctl/ctl_io.h> 60 #include <cam/ctl/ctl_scsi_all.h> 61 #include <cam/ctl/ctl_util.h> 62 63 struct ctl_status_desc { 64 ctl_io_status status; 65 const char *description; 66 }; 67 68 struct ctl_task_desc { 69 ctl_task_type task_action; 70 const char *description; 71 }; 72 static struct ctl_status_desc ctl_status_table[] = { 73 {CTL_STATUS_NONE, "No Status"}, 74 {CTL_SUCCESS, "Command Completed Successfully"}, 75 {CTL_CMD_TIMEOUT, "Command Timed Out"}, 76 {CTL_SEL_TIMEOUT, "Selection Timeout"}, 77 {CTL_ERROR, "Command Failed"}, 78 {CTL_SCSI_ERROR, "SCSI Error"}, 79 {CTL_CMD_ABORTED, "Command Aborted"}, 80 }; 81 82 static struct ctl_task_desc ctl_task_table[] = { 83 {CTL_TASK_ABORT_TASK, "Abort Task"}, 84 {CTL_TASK_ABORT_TASK_SET, "Abort Task Set"}, 85 {CTL_TASK_CLEAR_ACA, "Clear ACA"}, 86 {CTL_TASK_CLEAR_TASK_SET, "Clear Task Set"}, 87 {CTL_TASK_LUN_RESET, "LUN Reset"}, 88 {CTL_TASK_TARGET_RESET, "Target Reset"}, 89 {CTL_TASK_BUS_RESET, "Bus Reset"}, 90 {CTL_TASK_PORT_LOGIN, "Port Login"}, 91 {CTL_TASK_PORT_LOGOUT, "Port Logout"} 92 }; 93 94 void 95 ctl_scsi_tur(union ctl_io *io, ctl_tag_type tag_type, uint8_t control) 96 { 97 struct ctl_scsiio *ctsio; 98 struct scsi_test_unit_ready *cdb; 99 100 ctl_scsi_zero_io(io); 101 102 io->io_hdr.io_type = CTL_IO_SCSI; 103 ctsio = &io->scsiio; 104 cdb = (struct scsi_test_unit_ready *)ctsio->cdb; 105 106 cdb->opcode = TEST_UNIT_READY; 107 cdb->control = control; 108 io->io_hdr.flags = CTL_FLAG_DATA_NONE; 109 ctsio->tag_type = tag_type; 110 ctsio->cdb_len = sizeof(*cdb); 111 ctsio->ext_data_len = 0; 112 ctsio->ext_data_ptr = NULL; 113 ctsio->ext_sg_entries = 0; 114 ctsio->ext_data_filled = 0; 115 ctsio->sense_len = SSD_FULL_SIZE; 116 } 117 118 void 119 ctl_scsi_inquiry(union ctl_io *io, uint8_t *data_ptr, int32_t data_len, 120 uint8_t byte2, uint8_t page_code, ctl_tag_type tag_type, 121 uint8_t control) 122 { 123 struct ctl_scsiio *ctsio; 124 struct scsi_inquiry *cdb; 125 126 ctl_scsi_zero_io(io); 127 128 io->io_hdr.io_type = CTL_IO_SCSI; 129 ctsio = &io->scsiio; 130 cdb = (struct scsi_inquiry *)ctsio->cdb; 131 132 cdb->opcode = INQUIRY; 133 cdb->byte2 = byte2; 134 cdb->page_code = page_code; 135 cdb->control = control; 136 scsi_ulto2b(data_len, cdb->length); 137 io->io_hdr.io_type = CTL_IO_SCSI; 138 io->io_hdr.flags = CTL_FLAG_DATA_IN; 139 ctsio->tag_type = tag_type; 140 ctsio->cdb_len = sizeof(*cdb); 141 ctsio->ext_data_len = data_len; 142 ctsio->ext_data_ptr = data_ptr; 143 ctsio->ext_sg_entries = 0; 144 ctsio->ext_data_filled = 0; 145 ctsio->sense_len = SSD_FULL_SIZE; 146 } 147 148 void 149 ctl_scsi_request_sense(union ctl_io *io, uint8_t *data_ptr, 150 int32_t data_len, uint8_t byte2, ctl_tag_type tag_type, 151 uint8_t control) 152 { 153 struct ctl_scsiio *ctsio; 154 struct scsi_request_sense *cdb; 155 156 ctl_scsi_zero_io(io); 157 158 io->io_hdr.io_type = CTL_IO_SCSI; 159 ctsio = &io->scsiio; 160 cdb = (struct scsi_request_sense *)ctsio->cdb; 161 162 cdb->opcode = REQUEST_SENSE; 163 cdb->byte2 = byte2; 164 cdb->control = control; 165 cdb->length = data_len; 166 io->io_hdr.io_type = CTL_IO_SCSI; 167 io->io_hdr.flags = CTL_FLAG_DATA_IN; 168 ctsio->tag_type = tag_type; 169 ctsio->cdb_len = sizeof(*cdb); 170 ctsio->ext_data_ptr = data_ptr; 171 ctsio->ext_data_len = data_len; 172 ctsio->ext_sg_entries = 0; 173 ctsio->ext_data_filled = 0; 174 ctsio->sense_len = SSD_FULL_SIZE; 175 } 176 177 void 178 ctl_scsi_report_luns(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, 179 uint8_t select_report, ctl_tag_type tag_type, 180 uint8_t control) 181 { 182 struct ctl_scsiio *ctsio; 183 struct scsi_report_luns *cdb; 184 185 ctl_scsi_zero_io(io); 186 187 io->io_hdr.io_type = CTL_IO_SCSI; 188 ctsio = &io->scsiio; 189 cdb = (struct scsi_report_luns *)ctsio->cdb; 190 191 cdb->opcode = REPORT_LUNS; 192 cdb->select_report = select_report; 193 scsi_ulto4b(data_len, cdb->length); 194 cdb->control = control; 195 io->io_hdr.io_type = CTL_IO_SCSI; 196 io->io_hdr.flags = CTL_FLAG_DATA_IN; 197 ctsio->tag_type = tag_type; 198 ctsio->cdb_len = sizeof(*cdb); 199 ctsio->ext_data_ptr = data_ptr; 200 ctsio->ext_data_len = data_len; 201 ctsio->ext_sg_entries = 0; 202 ctsio->ext_data_filled = 0; 203 ctsio->sense_len = SSD_FULL_SIZE; 204 } 205 206 void 207 ctl_scsi_read_write_buffer(union ctl_io *io, uint8_t *data_ptr, 208 uint32_t data_len, int read_buffer, uint8_t mode, 209 uint8_t buffer_id, uint32_t buffer_offset, 210 ctl_tag_type tag_type, uint8_t control) 211 { 212 struct ctl_scsiio *ctsio; 213 struct scsi_write_buffer *cdb; 214 215 ctl_scsi_zero_io(io); 216 217 io->io_hdr.io_type = CTL_IO_SCSI; 218 ctsio = &io->scsiio; 219 cdb = (struct scsi_write_buffer *)ctsio->cdb; 220 221 if (read_buffer != 0) 222 cdb->opcode = READ_BUFFER; 223 else 224 cdb->opcode = WRITE_BUFFER; 225 226 cdb->byte2 = mode & RWB_MODE; 227 cdb->buffer_id = buffer_id; 228 scsi_ulto3b(buffer_offset, cdb->offset); 229 scsi_ulto3b(data_len, cdb->length); 230 cdb->control = control; 231 io->io_hdr.io_type = CTL_IO_SCSI; 232 if (read_buffer != 0) 233 io->io_hdr.flags = CTL_FLAG_DATA_IN; 234 else 235 io->io_hdr.flags = CTL_FLAG_DATA_OUT; 236 ctsio->tag_type = tag_type; 237 ctsio->cdb_len = sizeof(*cdb); 238 ctsio->ext_data_ptr = data_ptr; 239 ctsio->ext_data_len = data_len; 240 ctsio->ext_sg_entries = 0; 241 ctsio->ext_data_filled = 0; 242 ctsio->sense_len = SSD_FULL_SIZE; 243 } 244 245 void 246 ctl_scsi_read_write(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, 247 int read_op, uint8_t byte2, int minimum_cdb_size, 248 uint64_t lba, uint32_t num_blocks, ctl_tag_type tag_type, 249 uint8_t control) 250 { 251 struct ctl_scsiio *ctsio; 252 253 ctl_scsi_zero_io(io); 254 255 io->io_hdr.io_type = CTL_IO_SCSI; 256 ctsio = &io->scsiio; 257 258 /* 259 * Pick out the smallest CDB that will hold the user's request. 260 * minimum_cdb_size allows cranking the CDB size up, even for 261 * requests that would not normally need a large CDB. This can be 262 * useful for testing (e.g. to make sure READ_16 support works without 263 * having an array larger than 2TB) and for compatibility -- e.g. 264 * if your device doesn't support READ_6. (ATAPI drives don't.) 265 */ 266 if ((minimum_cdb_size < 10) 267 && ((lba & 0x1fffff) == lba) 268 && ((num_blocks & 0xff) == num_blocks) 269 && (byte2 == 0)) { 270 struct scsi_rw_6 *cdb; 271 272 /* 273 * Note that according to SBC-2, the target should return 256 274 * blocks if the transfer length in a READ(6) or WRITE(6) CDB 275 * is set to 0. Since it's possible that some targets 276 * won't do the right thing, we only send a READ(6) or 277 * WRITE(6) for transfer sizes up to and including 255 blocks. 278 */ 279 cdb = (struct scsi_rw_6 *)ctsio->cdb; 280 281 cdb->opcode = (read_op) ? READ_6 : WRITE_6; 282 scsi_ulto3b(lba, cdb->addr); 283 cdb->length = num_blocks & 0xff; 284 cdb->control = control; 285 286 ctsio->cdb_len = sizeof(*cdb); 287 288 } else if ((minimum_cdb_size < 12) 289 && ((num_blocks & 0xffff) == num_blocks) 290 && ((lba & 0xffffffff) == lba)) { 291 struct scsi_rw_10 *cdb; 292 293 cdb = (struct scsi_rw_10 *)ctsio->cdb; 294 295 cdb->opcode = (read_op) ? READ_10 : WRITE_10; 296 cdb->byte2 = byte2; 297 scsi_ulto4b(lba, cdb->addr); 298 cdb->reserved = 0; 299 scsi_ulto2b(num_blocks, cdb->length); 300 cdb->control = control; 301 302 ctsio->cdb_len = sizeof(*cdb); 303 } else if ((minimum_cdb_size < 16) 304 && ((num_blocks & 0xffffffff) == num_blocks) 305 && ((lba & 0xffffffff) == lba)) { 306 struct scsi_rw_12 *cdb; 307 308 cdb = (struct scsi_rw_12 *)ctsio->cdb; 309 310 cdb->opcode = (read_op) ? READ_12 : WRITE_12; 311 cdb->byte2 = byte2; 312 scsi_ulto4b(lba, cdb->addr); 313 scsi_ulto4b(num_blocks, cdb->length); 314 cdb->reserved = 0; 315 cdb->control = control; 316 317 ctsio->cdb_len = sizeof(*cdb); 318 } else { 319 struct scsi_rw_16 *cdb; 320 321 cdb = (struct scsi_rw_16 *)ctsio->cdb; 322 323 cdb->opcode = (read_op) ? READ_16 : WRITE_16; 324 cdb->byte2 = byte2; 325 scsi_u64to8b(lba, cdb->addr); 326 scsi_ulto4b(num_blocks, cdb->length); 327 cdb->reserved = 0; 328 cdb->control = control; 329 330 ctsio->cdb_len = sizeof(*cdb); 331 } 332 333 io->io_hdr.io_type = CTL_IO_SCSI; 334 if (read_op != 0) 335 io->io_hdr.flags = CTL_FLAG_DATA_IN; 336 else 337 io->io_hdr.flags = CTL_FLAG_DATA_OUT; 338 ctsio->tag_type = tag_type; 339 ctsio->ext_data_ptr = data_ptr; 340 ctsio->ext_data_len = data_len; 341 ctsio->ext_sg_entries = 0; 342 ctsio->ext_data_filled = 0; 343 ctsio->sense_len = SSD_FULL_SIZE; 344 } 345 346 void 347 ctl_scsi_read_capacity(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, 348 uint32_t addr, int reladr, int pmi, 349 ctl_tag_type tag_type, uint8_t control) 350 { 351 struct scsi_read_capacity *cdb; 352 353 ctl_scsi_zero_io(io); 354 355 io->io_hdr.io_type = CTL_IO_SCSI; 356 cdb = (struct scsi_read_capacity *)io->scsiio.cdb; 357 358 cdb->opcode = READ_CAPACITY; 359 if (reladr) 360 cdb->byte2 = SRC_RELADR; 361 if (pmi) 362 cdb->pmi = SRC_PMI; 363 scsi_ulto4b(addr, cdb->addr); 364 cdb->control = control; 365 io->io_hdr.io_type = CTL_IO_SCSI; 366 io->io_hdr.flags = CTL_FLAG_DATA_IN; 367 io->scsiio.tag_type = tag_type; 368 io->scsiio.ext_data_ptr = data_ptr; 369 io->scsiio.ext_data_len = data_len; 370 io->scsiio.ext_sg_entries = 0; 371 io->scsiio.ext_data_filled = 0; 372 io->scsiio.sense_len = SSD_FULL_SIZE; 373 } 374 375 void 376 ctl_scsi_read_capacity_16(union ctl_io *io, uint8_t *data_ptr, 377 uint32_t data_len, uint64_t addr, int reladr, 378 int pmi, ctl_tag_type tag_type, uint8_t control) 379 { 380 struct scsi_read_capacity_16 *cdb; 381 382 ctl_scsi_zero_io(io); 383 384 io->io_hdr.io_type = CTL_IO_SCSI; 385 cdb = (struct scsi_read_capacity_16 *)io->scsiio.cdb; 386 387 cdb->opcode = SERVICE_ACTION_IN; 388 cdb->service_action = SRC16_SERVICE_ACTION; 389 if (reladr) 390 cdb->reladr |= SRC16_RELADR; 391 if (pmi) 392 cdb->reladr |= SRC16_PMI; 393 scsi_u64to8b(addr, cdb->addr); 394 scsi_ulto4b(data_len, cdb->alloc_len); 395 cdb->control = control; 396 397 io->io_hdr.io_type = CTL_IO_SCSI; 398 io->io_hdr.flags = CTL_FLAG_DATA_IN; 399 io->scsiio.tag_type = tag_type; 400 io->scsiio.ext_data_ptr = data_ptr; 401 io->scsiio.ext_data_len = data_len; 402 io->scsiio.ext_sg_entries = 0; 403 io->scsiio.ext_data_filled = 0; 404 io->scsiio.sense_len = SSD_FULL_SIZE; 405 } 406 407 void 408 ctl_scsi_mode_sense(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, 409 int dbd, int llbaa, uint8_t page_code, uint8_t pc, 410 uint8_t subpage, int minimum_cdb_size, 411 ctl_tag_type tag_type, uint8_t control) 412 { 413 ctl_scsi_zero_io(io); 414 415 if ((minimum_cdb_size < 10) 416 && (llbaa == 0) 417 && (data_len < 256)) { 418 struct scsi_mode_sense_6 *cdb; 419 420 cdb = (struct scsi_mode_sense_6 *)io->scsiio.cdb; 421 422 cdb->opcode = MODE_SENSE_6; 423 if (dbd) 424 cdb->byte2 |= SMS_DBD; 425 cdb->page = page_code | pc; 426 cdb->subpage = subpage; 427 cdb->length = data_len; 428 cdb->control = control; 429 } else { 430 struct scsi_mode_sense_10 *cdb; 431 432 cdb = (struct scsi_mode_sense_10 *)io->scsiio.cdb; 433 434 cdb->opcode = MODE_SENSE_10; 435 if (dbd) 436 cdb->byte2 |= SMS_DBD; 437 if (llbaa) 438 cdb->byte2 |= SMS10_LLBAA; 439 cdb->page = page_code | pc; 440 cdb->subpage = subpage; 441 scsi_ulto2b(data_len, cdb->length); 442 cdb->control = control; 443 } 444 445 io->io_hdr.io_type = CTL_IO_SCSI; 446 io->io_hdr.flags = CTL_FLAG_DATA_IN; 447 io->scsiio.tag_type = tag_type; 448 io->scsiio.ext_data_ptr = data_ptr; 449 io->scsiio.ext_data_len = data_len; 450 io->scsiio.ext_sg_entries = 0; 451 io->scsiio.ext_data_filled = 0; 452 io->scsiio.sense_len = SSD_FULL_SIZE; 453 } 454 455 void 456 ctl_scsi_start_stop(union ctl_io *io, int start, int load_eject, int immediate, 457 int power_conditions, int onoffline __unused, 458 ctl_tag_type tag_type, uint8_t control) 459 { 460 struct scsi_start_stop_unit *cdb; 461 462 cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb; 463 464 ctl_scsi_zero_io(io); 465 466 cdb->opcode = START_STOP_UNIT; 467 if (immediate) 468 cdb->byte2 |= SSS_IMMED; 469 #ifdef NEEDTOPORT 470 if (onoffline) 471 cdb->byte2 |= SSS_ONOFFLINE; 472 #endif 473 cdb->how = power_conditions; 474 if (load_eject) 475 cdb->how |= SSS_LOEJ; 476 if (start) 477 cdb->how |= SSS_START; 478 cdb->control = control; 479 io->io_hdr.io_type = CTL_IO_SCSI; 480 io->io_hdr.flags = CTL_FLAG_DATA_NONE; 481 io->scsiio.tag_type = tag_type; 482 io->scsiio.ext_data_ptr = NULL; 483 io->scsiio.ext_data_len = 0; 484 io->scsiio.ext_sg_entries = 0; 485 io->scsiio.ext_data_filled = 0; 486 io->scsiio.sense_len = SSD_FULL_SIZE; 487 } 488 489 void 490 ctl_scsi_sync_cache(union ctl_io *io, int immed, int reladr, 491 int minimum_cdb_size, uint64_t starting_lba, 492 uint32_t block_count, ctl_tag_type tag_type, 493 uint8_t control) 494 { 495 ctl_scsi_zero_io(io); 496 497 if ((minimum_cdb_size < 16) 498 && ((block_count & 0xffff) == block_count) 499 && ((starting_lba & 0xffffffff) == starting_lba)) { 500 struct scsi_sync_cache *cdb; 501 502 cdb = (struct scsi_sync_cache *)io->scsiio.cdb; 503 504 cdb->opcode = SYNCHRONIZE_CACHE; 505 if (reladr) 506 cdb->byte2 |= SSC_RELADR; 507 508 if (immed) 509 cdb->byte2 |= SSC_IMMED; 510 511 scsi_ulto4b(starting_lba, cdb->begin_lba); 512 scsi_ulto2b(block_count, cdb->lb_count); 513 cdb->control = control; 514 } else { 515 struct scsi_sync_cache_16 *cdb; 516 517 cdb = (struct scsi_sync_cache_16 *)io->scsiio.cdb; 518 519 cdb->opcode = SYNCHRONIZE_CACHE_16; 520 if (reladr) 521 cdb->byte2 |= SSC_RELADR; 522 523 if (immed) 524 cdb->byte2 |= SSC_IMMED; 525 526 scsi_u64to8b(starting_lba, cdb->begin_lba); 527 scsi_ulto4b(block_count, cdb->lb_count); 528 cdb->control = control; 529 } 530 io->io_hdr.io_type = CTL_IO_SCSI; 531 io->io_hdr.flags = CTL_FLAG_DATA_NONE; 532 io->scsiio.tag_type = tag_type; 533 io->scsiio.ext_data_ptr = NULL; 534 io->scsiio.ext_data_len = 0; 535 io->scsiio.ext_sg_entries = 0; 536 io->scsiio.ext_data_filled = 0; 537 io->scsiio.sense_len = SSD_FULL_SIZE; 538 } 539 540 void 541 ctl_scsi_persistent_res_in(union ctl_io *io, uint8_t *data_ptr, 542 uint32_t data_len, int action, 543 ctl_tag_type tag_type, uint8_t control) 544 { 545 546 struct scsi_per_res_in *cdb; 547 548 ctl_scsi_zero_io(io); 549 550 cdb = (struct scsi_per_res_in *)io->scsiio.cdb; 551 cdb->opcode = PERSISTENT_RES_IN; 552 cdb->action = action; 553 scsi_ulto2b(data_len, cdb->length); 554 cdb->control = control; 555 556 io->io_hdr.io_type = CTL_IO_SCSI; 557 io->io_hdr.flags = CTL_FLAG_DATA_IN; 558 io->scsiio.tag_type = tag_type; 559 io->scsiio.ext_data_ptr = data_ptr; 560 io->scsiio.ext_data_len = data_len; 561 io->scsiio.ext_sg_entries = 0; 562 io->scsiio.ext_data_filled = 0; 563 io->scsiio.sense_len = SSD_FULL_SIZE; 564 } 565 566 void 567 ctl_scsi_persistent_res_out(union ctl_io *io, uint8_t *data_ptr, 568 uint32_t data_len, int action, int type, 569 uint64_t key, uint64_t sa_key, 570 ctl_tag_type tag_type, uint8_t control) 571 { 572 573 struct scsi_per_res_out *cdb; 574 struct scsi_per_res_out_parms *params; 575 576 ctl_scsi_zero_io(io); 577 578 cdb = (struct scsi_per_res_out *)io->scsiio.cdb; 579 params = (struct scsi_per_res_out_parms *)data_ptr; 580 581 cdb->opcode = PERSISTENT_RES_OUT; 582 if (action == 5) 583 cdb->action = 6; 584 else 585 cdb->action = action; 586 switch(type) 587 { 588 case 0: 589 cdb->scope_type = 1; 590 break; 591 case 1: 592 cdb->scope_type = 3; 593 break; 594 case 2: 595 cdb->scope_type = 5; 596 break; 597 case 3: 598 cdb->scope_type = 6; 599 break; 600 case 4: 601 cdb->scope_type = 7; 602 break; 603 case 5: 604 cdb->scope_type = 8; 605 break; 606 } 607 scsi_ulto4b(data_len, cdb->length); 608 cdb->control = control; 609 610 scsi_u64to8b(key, params->res_key.key); 611 scsi_u64to8b(sa_key, params->serv_act_res_key); 612 613 io->io_hdr.io_type = CTL_IO_SCSI; 614 io->io_hdr.flags = CTL_FLAG_DATA_OUT; 615 io->scsiio.tag_type = tag_type; 616 io->scsiio.ext_data_ptr = data_ptr; 617 io->scsiio.ext_data_len = data_len; 618 io->scsiio.ext_sg_entries = 0; 619 io->scsiio.ext_data_filled = 0; 620 io->scsiio.sense_len = SSD_FULL_SIZE; 621 622 } 623 624 void 625 ctl_scsi_maintenance_in(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, 626 uint8_t action, ctl_tag_type tag_type, uint8_t control) 627 { 628 struct scsi_maintenance_in *cdb; 629 630 ctl_scsi_zero_io(io); 631 632 cdb = (struct scsi_maintenance_in *)io->scsiio.cdb; 633 cdb->opcode = MAINTENANCE_IN; 634 cdb->byte2 = action; 635 scsi_ulto4b(data_len, cdb->length); 636 cdb->control = control; 637 638 io->io_hdr.io_type = CTL_IO_SCSI; 639 io->io_hdr.flags = CTL_FLAG_DATA_IN; 640 io->scsiio.tag_type = tag_type; 641 io->scsiio.ext_data_ptr = data_ptr; 642 io->scsiio.ext_data_len = data_len; 643 io->scsiio.ext_sg_entries = 0; 644 io->scsiio.ext_data_filled = 0; 645 io->scsiio.sense_len = SSD_FULL_SIZE; 646 } 647 648 #ifndef _KERNEL 649 union ctl_io * 650 ctl_scsi_alloc_io(struct ctl_id initid) 651 { 652 union ctl_io *io; 653 654 io = (union ctl_io *)malloc(sizeof(*io)); 655 if (io == NULL) 656 goto bailout; 657 658 io->io_hdr.nexus.initid = initid; 659 660 bailout: 661 return (io); 662 } 663 664 void 665 ctl_scsi_free_io(union ctl_io *io) 666 { 667 free(io); 668 } 669 670 #endif /* !_KERNEL */ 671 void 672 ctl_scsi_zero_io(union ctl_io *io) 673 { 674 void *pool_ref; 675 676 if (io == NULL) 677 return; 678 679 pool_ref = io->io_hdr.pool; 680 681 memset(io, 0, sizeof(*io)); 682 683 io->io_hdr.pool = pool_ref; 684 } 685 686 const char * 687 ctl_scsi_task_string(struct ctl_taskio *taskio) 688 { 689 unsigned int i; 690 691 for (i = 0; i < (sizeof(ctl_task_table)/sizeof(ctl_task_table[0])); 692 i++) { 693 if (taskio->task_action == ctl_task_table[i].task_action) { 694 return (ctl_task_table[i].description); 695 } 696 } 697 698 return (NULL); 699 } 700 701 void 702 ctl_io_error_sbuf(union ctl_io *io, struct scsi_inquiry_data *inq_data, 703 struct sbuf *sb) 704 { 705 struct ctl_status_desc *status_desc; 706 char path_str[64]; 707 unsigned int i; 708 709 status_desc = NULL; 710 711 for (i = 0; i < (sizeof(ctl_status_table)/sizeof(ctl_status_table[0])); 712 i++) { 713 if ((io->io_hdr.status & CTL_STATUS_MASK) == 714 ctl_status_table[i].status) { 715 status_desc = &ctl_status_table[i]; 716 break; 717 } 718 } 719 720 ctl_scsi_path_string(io, path_str, sizeof(path_str)); 721 722 switch (io->io_hdr.io_type) { 723 case CTL_IO_SCSI: 724 sbuf_cat(sb, path_str); 725 726 ctl_scsi_command_string(&io->scsiio, NULL, sb); 727 728 sbuf_printf(sb, "\n"); 729 730 sbuf_printf(sb, "%sTag: 0x%04x, Type: %d\n", path_str, 731 io->scsiio.tag_num, io->scsiio.tag_type); 732 break; 733 case CTL_IO_TASK: { 734 const char *task_desc; 735 736 sbuf_cat(sb, path_str); 737 738 task_desc = ctl_scsi_task_string(&io->taskio); 739 740 if (task_desc == NULL) 741 sbuf_printf(sb, "Unknown Task Action %d (%#x)", 742 io->taskio.task_action, 743 io->taskio.task_action); 744 else 745 sbuf_printf(sb, "Task Action: %s", task_desc); 746 747 sbuf_printf(sb, "\n"); 748 749 switch (io->taskio.task_action) { 750 case CTL_TASK_ABORT_TASK: 751 case CTL_TASK_ABORT_TASK_SET: 752 case CTL_TASK_CLEAR_TASK_SET: 753 sbuf_printf(sb, "%sTag: 0x%04x, Type: %d\n", path_str, 754 io->taskio.tag_num, 755 io->taskio.tag_type); 756 break; 757 default: 758 break; 759 } 760 break; 761 } 762 default: 763 break; 764 } 765 766 sbuf_cat(sb, path_str); 767 if (status_desc == NULL) 768 sbuf_printf(sb, "CTL Status: Unknown status %#x\n", 769 io->io_hdr.status); 770 else 771 sbuf_printf(sb, "CTL Status: %s\n", status_desc->description); 772 773 if ((io->io_hdr.io_type == CTL_IO_SCSI) 774 && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SCSI_ERROR)) { 775 sbuf_cat(sb, path_str); 776 sbuf_printf(sb, "SCSI Status: %s\n", 777 ctl_scsi_status_string(&io->scsiio)); 778 779 if (io->scsiio.scsi_status == SCSI_STATUS_CHECK_COND) 780 ctl_scsi_sense_sbuf(&io->scsiio, inq_data, 781 sb, SSS_FLAG_NONE); 782 } 783 } 784 785 char * 786 ctl_io_error_string(union ctl_io *io, struct scsi_inquiry_data *inq_data, 787 char *str, int str_len) 788 { 789 struct sbuf sb; 790 791 sbuf_new(&sb, str, str_len, SBUF_FIXEDLEN); 792 793 ctl_io_error_sbuf(io, inq_data, &sb); 794 795 sbuf_finish(&sb); 796 797 return (sbuf_data(&sb)); 798 } 799 800 #ifdef _KERNEL 801 802 void 803 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data) 804 { 805 char str[512]; 806 #ifdef NEEDTOPORT 807 char *message; 808 char *line; 809 810 message = io_error_string(io, inq_data, str, sizeof(str)); 811 812 for (line = strsep(&message, "\n"); line != NULL; 813 line = strsep(&message, "\n")) { 814 csevent_log(CSC_CTL | CSC_SHELF_SW | CTL_ERROR_REPORT, 815 csevent_LogType_Trace, 816 csevent_Severity_Information, 817 csevent_AlertLevel_Green, 818 csevent_FRU_Firmware, 819 csevent_FRU_Unknown, "%s", line); 820 } 821 #else 822 printf("%s", ctl_io_error_string(io, inq_data, str, sizeof(str))); 823 #endif 824 825 } 826 827 #else /* _KERNEL */ 828 829 void 830 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data, 831 FILE *ofile) 832 { 833 char str[512]; 834 835 fprintf(ofile, "%s", ctl_io_error_string(io, inq_data, str, 836 sizeof(str))); 837 } 838 839 #endif /* _KERNEL */ 840 841 /* 842 * vim: ts=8 843 */ 844