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