1 /*- 2 * SPDX-License-Identifier: (BSD-2-Clause AND BSD-4-Clause) 3 * 4 * Copyright (c) 1997 Justin T. Gibbs. 5 * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions, and the following disclaimer, 13 * without modification, immediately at the beginning of the file. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /*- 31 * Copyright (c) 1996, 1997 Jason R. Thorpe <thorpej@and.com> 32 * All rights reserved. 33 * 34 * Partially based on an autochanger driver written by Stefan Grefen 35 * and on an autochanger driver written by the Systems Programming Group 36 * at the University of Utah Computer Science Department. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgements: 48 * This product includes software developed by Jason R. Thorpe 49 * for And Communications, http://www.and.com/ 50 * 4. The name of the author may not be used to endorse or promote products 51 * derived from this software without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 54 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 55 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 56 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 57 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 58 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 59 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 60 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 61 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * $NetBSD: ch.c,v 1.34 1998/08/31 22:28:06 cgd Exp $ 66 */ 67 68 #include <sys/param.h> 69 #include <sys/queue.h> 70 #include <sys/systm.h> 71 #include <sys/kernel.h> 72 #include <sys/types.h> 73 #include <sys/malloc.h> 74 #include <sys/fcntl.h> 75 #include <sys/conf.h> 76 #include <sys/chio.h> 77 #include <sys/errno.h> 78 #include <sys/devicestat.h> 79 80 #include <cam/cam.h> 81 #include <cam/cam_ccb.h> 82 #include <cam/cam_periph.h> 83 #include <cam/cam_xpt_periph.h> 84 #include <cam/cam_debug.h> 85 86 #include <cam/scsi/scsi_all.h> 87 #include <cam/scsi/scsi_message.h> 88 #include <cam/scsi/scsi_ch.h> 89 90 /* 91 * Timeout definitions for various changer related commands. They may 92 * be too short for some devices (especially the timeout for INITIALIZE 93 * ELEMENT STATUS). 94 */ 95 96 static const uint32_t CH_TIMEOUT_MODE_SENSE = 6000; 97 static const uint32_t CH_TIMEOUT_MOVE_MEDIUM = 15 * 60 * 1000; 98 static const uint32_t CH_TIMEOUT_EXCHANGE_MEDIUM = 15 * 60 * 1000; 99 static const uint32_t CH_TIMEOUT_POSITION_TO_ELEMENT = 15 * 60 * 1000; 100 static const uint32_t CH_TIMEOUT_READ_ELEMENT_STATUS = 5 * 60 * 1000; 101 static const uint32_t CH_TIMEOUT_SEND_VOLTAG = 10000; 102 static const uint32_t CH_TIMEOUT_INITIALIZE_ELEMENT_STATUS = 500000; 103 104 typedef enum { 105 CH_FLAG_INVALID = 0x001 106 } ch_flags; 107 108 typedef enum { 109 CH_STATE_PROBE, 110 CH_STATE_NORMAL 111 } ch_state; 112 113 typedef enum { 114 CH_CCB_PROBE 115 } ch_ccb_types; 116 117 typedef enum { 118 CH_Q_NONE = 0x00, 119 CH_Q_NO_DBD = 0x01, 120 CH_Q_NO_DVCID = 0x02 121 } ch_quirks; 122 123 #define CH_Q_BIT_STRING \ 124 "\020" \ 125 "\001NO_DBD" \ 126 "\002NO_DVCID" 127 128 #define ccb_state ppriv_field0 129 #define ccb_bp ppriv_ptr1 130 131 struct scsi_mode_sense_data { 132 struct scsi_mode_header_6 header; 133 struct scsi_mode_blk_desc blk_desc; 134 union { 135 struct page_element_address_assignment ea; 136 struct page_transport_geometry_parameters tg; 137 struct page_device_capabilities cap; 138 } pages; 139 }; 140 141 struct ch_softc { 142 ch_flags flags; 143 ch_state state; 144 ch_quirks quirks; 145 struct devstat *device_stats; 146 struct cdev *dev; 147 int open_count; 148 149 int sc_picker; /* current picker */ 150 151 /* 152 * The following information is obtained from the 153 * element address assignment page. 154 */ 155 int sc_firsts[CHET_MAX + 1]; /* firsts */ 156 int sc_counts[CHET_MAX + 1]; /* counts */ 157 158 /* 159 * The following mask defines the legal combinations 160 * of elements for the MOVE MEDIUM command. 161 */ 162 uint8_t sc_movemask[CHET_MAX + 1]; 163 164 /* 165 * As above, but for EXCHANGE MEDIUM. 166 */ 167 uint8_t sc_exchangemask[CHET_MAX + 1]; 168 169 /* 170 * Quirks; see below. XXX KDM not implemented yet 171 */ 172 int sc_settledelay; /* delay for settle */ 173 }; 174 175 static d_open_t chopen; 176 static d_close_t chclose; 177 static d_ioctl_t chioctl; 178 static periph_init_t chinit; 179 static periph_ctor_t chregister; 180 static periph_oninv_t choninvalidate; 181 static periph_dtor_t chcleanup; 182 static periph_start_t chstart; 183 static void chasync(void *callback_arg, uint32_t code, 184 struct cam_path *path, void *arg); 185 static void chdone(struct cam_periph *periph, 186 union ccb *done_ccb); 187 static int cherror(union ccb *ccb, uint32_t cam_flags, 188 uint32_t sense_flags); 189 static int chmove(struct cam_periph *periph, 190 struct changer_move *cm); 191 static int chexchange(struct cam_periph *periph, 192 struct changer_exchange *ce); 193 static int chposition(struct cam_periph *periph, 194 struct changer_position *cp); 195 static int chgetelemstatus(struct cam_periph *periph, 196 int scsi_version, u_long cmd, 197 struct changer_element_status_request *csr); 198 static int chsetvoltag(struct cam_periph *periph, 199 struct changer_set_voltag_request *csvr); 200 static int chielem(struct cam_periph *periph, 201 unsigned int timeout); 202 static int chgetparams(struct cam_periph *periph); 203 static int chscsiversion(struct cam_periph *periph); 204 205 static struct periph_driver chdriver = 206 { 207 chinit, "ch", 208 TAILQ_HEAD_INITIALIZER(chdriver.units), /* generation */ 0 209 }; 210 211 PERIPHDRIVER_DECLARE(ch, chdriver); 212 213 static struct cdevsw ch_cdevsw = { 214 .d_version = D_VERSION, 215 .d_flags = D_TRACKCLOSE, 216 .d_open = chopen, 217 .d_close = chclose, 218 .d_ioctl = chioctl, 219 .d_name = "ch", 220 }; 221 222 static MALLOC_DEFINE(M_SCSICH, "scsi_ch", "scsi_ch buffers"); 223 224 static void 225 chinit(void) 226 { 227 cam_status status; 228 229 /* 230 * Install a global async callback. This callback will 231 * receive async callbacks like "new device found". 232 */ 233 status = xpt_register_async(AC_FOUND_DEVICE, chasync, NULL, NULL); 234 235 if (status != CAM_REQ_CMP) { 236 printf("ch: Failed to attach master async callback " 237 "due to status 0x%x!\n", status); 238 } 239 } 240 241 static void 242 chdevgonecb(void *arg) 243 { 244 struct ch_softc *softc; 245 struct cam_periph *periph; 246 struct mtx *mtx; 247 int i; 248 249 periph = (struct cam_periph *)arg; 250 mtx = cam_periph_mtx(periph); 251 mtx_lock(mtx); 252 253 softc = (struct ch_softc *)periph->softc; 254 KASSERT(softc->open_count >= 0, ("Negative open count %d", 255 softc->open_count)); 256 257 /* 258 * When we get this callback, we will get no more close calls from 259 * devfs. So if we have any dangling opens, we need to release the 260 * reference held for that particular context. 261 */ 262 for (i = 0; i < softc->open_count; i++) 263 cam_periph_release_locked(periph); 264 265 softc->open_count = 0; 266 267 /* 268 * Release the reference held for the device node, it is gone now. 269 */ 270 cam_periph_release_locked(periph); 271 272 /* 273 * We reference the lock directly here, instead of using 274 * cam_periph_unlock(). The reason is that the final call to 275 * cam_periph_release_locked() above could result in the periph 276 * getting freed. If that is the case, dereferencing the periph 277 * with a cam_periph_unlock() call would cause a page fault. 278 */ 279 mtx_unlock(mtx); 280 } 281 282 static void 283 choninvalidate(struct cam_periph *periph) 284 { 285 struct ch_softc *softc; 286 287 softc = (struct ch_softc *)periph->softc; 288 289 /* 290 * De-register any async callbacks. 291 */ 292 xpt_register_async(0, chasync, periph, periph->path); 293 294 softc->flags |= CH_FLAG_INVALID; 295 296 /* 297 * Tell devfs this device has gone away, and ask for a callback 298 * when it has cleaned up its state. 299 */ 300 destroy_dev_sched_cb(softc->dev, chdevgonecb, periph); 301 } 302 303 static void 304 chcleanup(struct cam_periph *periph) 305 { 306 struct ch_softc *softc; 307 308 softc = (struct ch_softc *)periph->softc; 309 310 devstat_remove_entry(softc->device_stats); 311 312 free(softc, M_DEVBUF); 313 } 314 315 static void 316 chasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 317 { 318 struct cam_periph *periph; 319 320 periph = (struct cam_periph *)callback_arg; 321 322 switch(code) { 323 case AC_FOUND_DEVICE: 324 { 325 struct ccb_getdev *cgd; 326 cam_status status; 327 328 cgd = (struct ccb_getdev *)arg; 329 if (cgd == NULL) 330 break; 331 332 if (cgd->protocol != PROTO_SCSI) 333 break; 334 if (SID_QUAL(&cgd->inq_data) != SID_QUAL_LU_CONNECTED) 335 break; 336 if (SID_TYPE(&cgd->inq_data)!= T_CHANGER) 337 break; 338 339 /* 340 * Allocate a peripheral instance for 341 * this device and start the probe 342 * process. 343 */ 344 status = cam_periph_alloc(chregister, choninvalidate, 345 chcleanup, chstart, "ch", 346 CAM_PERIPH_BIO, path, 347 chasync, AC_FOUND_DEVICE, cgd); 348 349 if (status != CAM_REQ_CMP 350 && status != CAM_REQ_INPROG) 351 printf("chasync: Unable to probe new device " 352 "due to status 0x%x\n", status); 353 354 break; 355 } 356 default: 357 cam_periph_async(periph, code, path, arg); 358 break; 359 } 360 } 361 362 static cam_status 363 chregister(struct cam_periph *periph, void *arg) 364 { 365 struct ch_softc *softc; 366 struct ccb_getdev *cgd; 367 struct ccb_pathinq cpi; 368 struct make_dev_args args; 369 int error; 370 371 cgd = (struct ccb_getdev *)arg; 372 if (cgd == NULL) { 373 printf("chregister: no getdev CCB, can't register device\n"); 374 return(CAM_REQ_CMP_ERR); 375 } 376 377 softc = (struct ch_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT); 378 379 if (softc == NULL) { 380 printf("chregister: Unable to probe new device. " 381 "Unable to allocate softc\n"); 382 return(CAM_REQ_CMP_ERR); 383 } 384 385 bzero(softc, sizeof(*softc)); 386 softc->state = CH_STATE_PROBE; 387 periph->softc = softc; 388 softc->quirks = CH_Q_NONE; 389 390 /* 391 * The DVCID and CURDATA bits were not introduced until the SMC 392 * spec. If this device claims SCSI-2 or earlier support, then it 393 * very likely does not support these bits. 394 */ 395 if (cgd->inq_data.version <= SCSI_REV_2) 396 softc->quirks |= CH_Q_NO_DVCID; 397 398 xpt_path_inq(&cpi, periph->path); 399 400 /* 401 * Changers don't have a blocksize, and obviously don't support 402 * tagged queueing. 403 */ 404 cam_periph_unlock(periph); 405 softc->device_stats = devstat_new_entry("ch", 406 periph->unit_number, 0, 407 DEVSTAT_NO_BLOCKSIZE | DEVSTAT_NO_ORDERED_TAGS, 408 SID_TYPE(&cgd->inq_data) | 409 XPORT_DEVSTAT_TYPE(cpi.transport), 410 DEVSTAT_PRIORITY_OTHER); 411 412 /* 413 * Acquire a reference to the periph before we create the devfs 414 * instance for it. We'll release this reference once the devfs 415 * instance has been freed. 416 */ 417 if (cam_periph_acquire(periph) != 0) { 418 xpt_print(periph->path, "%s: lost periph during " 419 "registration!\n", __func__); 420 cam_periph_lock(periph); 421 return (CAM_REQ_CMP_ERR); 422 } 423 424 /* Register the device */ 425 make_dev_args_init(&args); 426 args.mda_devsw = &ch_cdevsw; 427 args.mda_unit = periph->unit_number; 428 args.mda_uid = UID_ROOT; 429 args.mda_gid = GID_OPERATOR; 430 args.mda_mode = 0600; 431 args.mda_si_drv1 = periph; 432 error = make_dev_s(&args, &softc->dev, "%s%d", periph->periph_name, 433 periph->unit_number); 434 cam_periph_lock(periph); 435 if (error != 0) { 436 cam_periph_release_locked(periph); 437 return (CAM_REQ_CMP_ERR); 438 } 439 440 /* 441 * Add an async callback so that we get 442 * notified if this device goes away. 443 */ 444 xpt_register_async(AC_LOST_DEVICE, chasync, periph, periph->path); 445 446 /* 447 * Lock this periph until we are setup. 448 * This first call can't block 449 */ 450 (void)cam_periph_hold(periph, PRIBIO); 451 xpt_schedule(periph, CAM_PRIORITY_DEV); 452 453 return(CAM_REQ_CMP); 454 } 455 456 static int 457 chopen(struct cdev *dev, int flags, int fmt, struct thread *td) 458 { 459 struct cam_periph *periph; 460 struct ch_softc *softc; 461 int error; 462 463 periph = (struct cam_periph *)dev->si_drv1; 464 if (cam_periph_acquire(periph) != 0) 465 return (ENXIO); 466 467 softc = (struct ch_softc *)periph->softc; 468 469 cam_periph_lock(periph); 470 471 if (softc->flags & CH_FLAG_INVALID) { 472 cam_periph_release_locked(periph); 473 cam_periph_unlock(periph); 474 return(ENXIO); 475 } 476 477 if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) { 478 cam_periph_unlock(periph); 479 cam_periph_release(periph); 480 return (error); 481 } 482 483 /* 484 * Load information about this changer device into the softc. 485 */ 486 if ((error = chgetparams(periph)) != 0) { 487 cam_periph_unhold(periph); 488 cam_periph_release_locked(periph); 489 cam_periph_unlock(periph); 490 return(error); 491 } 492 493 cam_periph_unhold(periph); 494 495 softc->open_count++; 496 497 cam_periph_unlock(periph); 498 499 return(error); 500 } 501 502 static int 503 chclose(struct cdev *dev, int flag, int fmt, struct thread *td) 504 { 505 struct cam_periph *periph; 506 struct ch_softc *softc; 507 struct mtx *mtx; 508 509 periph = (struct cam_periph *)dev->si_drv1; 510 mtx = cam_periph_mtx(periph); 511 mtx_lock(mtx); 512 513 softc = (struct ch_softc *)periph->softc; 514 softc->open_count--; 515 516 cam_periph_release_locked(periph); 517 518 /* 519 * We reference the lock directly here, instead of using 520 * cam_periph_unlock(). The reason is that the call to 521 * cam_periph_release_locked() above could result in the periph 522 * getting freed. If that is the case, dereferencing the periph 523 * with a cam_periph_unlock() call would cause a page fault. 524 * 525 * cam_periph_release() avoids this problem using the same method, 526 * but we're manually acquiring and dropping the lock here to 527 * protect the open count and avoid another lock acquisition and 528 * release. 529 */ 530 mtx_unlock(mtx); 531 532 return(0); 533 } 534 535 static void 536 chstart(struct cam_periph *periph, union ccb *start_ccb) 537 { 538 struct ch_softc *softc; 539 540 softc = (struct ch_softc *)periph->softc; 541 542 switch (softc->state) { 543 case CH_STATE_NORMAL: 544 { 545 xpt_release_ccb(start_ccb); 546 break; 547 } 548 case CH_STATE_PROBE: 549 { 550 int mode_buffer_len; 551 void *mode_buffer; 552 553 /* 554 * Include the block descriptor when calculating the mode 555 * buffer length, 556 */ 557 mode_buffer_len = sizeof(struct scsi_mode_header_6) + 558 sizeof(struct scsi_mode_blk_desc) + 559 sizeof(struct page_element_address_assignment); 560 561 mode_buffer = malloc(mode_buffer_len, M_SCSICH, M_NOWAIT); 562 563 if (mode_buffer == NULL) { 564 printf("chstart: couldn't malloc mode sense data\n"); 565 break; 566 } 567 bzero(mode_buffer, mode_buffer_len); 568 569 /* 570 * Get the element address assignment page. 571 */ 572 scsi_mode_sense(&start_ccb->csio, 573 /* retries */ 1, 574 /* cbfcnp */ chdone, 575 /* tag_action */ MSG_SIMPLE_Q_TAG, 576 /* dbd */ (softc->quirks & CH_Q_NO_DBD) ? 577 FALSE : TRUE, 578 /* pc */ SMS_PAGE_CTRL_CURRENT, 579 /* page */ CH_ELEMENT_ADDR_ASSIGN_PAGE, 580 /* param_buf */ (uint8_t *)mode_buffer, 581 /* param_len */ mode_buffer_len, 582 /* sense_len */ SSD_FULL_SIZE, 583 /* timeout */ CH_TIMEOUT_MODE_SENSE); 584 585 start_ccb->ccb_h.ccb_bp = NULL; 586 start_ccb->ccb_h.ccb_state = CH_CCB_PROBE; 587 xpt_action(start_ccb); 588 break; 589 } 590 } 591 } 592 593 static void 594 chdone(struct cam_periph *periph, union ccb *done_ccb) 595 { 596 struct ch_softc *softc; 597 struct ccb_scsiio *csio; 598 599 softc = (struct ch_softc *)periph->softc; 600 csio = &done_ccb->csio; 601 602 switch(done_ccb->ccb_h.ccb_state) { 603 case CH_CCB_PROBE: 604 { 605 struct scsi_mode_header_6 *mode_header; 606 struct page_element_address_assignment *ea; 607 char announce_buf[80]; 608 609 mode_header = (struct scsi_mode_header_6 *)csio->data_ptr; 610 611 ea = (struct page_element_address_assignment *) 612 find_mode_page_6(mode_header); 613 614 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP){ 615 616 softc->sc_firsts[CHET_MT] = scsi_2btoul(ea->mtea); 617 softc->sc_counts[CHET_MT] = scsi_2btoul(ea->nmte); 618 softc->sc_firsts[CHET_ST] = scsi_2btoul(ea->fsea); 619 softc->sc_counts[CHET_ST] = scsi_2btoul(ea->nse); 620 softc->sc_firsts[CHET_IE] = scsi_2btoul(ea->fieea); 621 softc->sc_counts[CHET_IE] = scsi_2btoul(ea->niee); 622 softc->sc_firsts[CHET_DT] = scsi_2btoul(ea->fdtea); 623 softc->sc_counts[CHET_DT] = scsi_2btoul(ea->ndte); 624 softc->sc_picker = softc->sc_firsts[CHET_MT]; 625 626 #define PLURAL(c) (c) == 1 ? "" : "s" 627 snprintf(announce_buf, sizeof(announce_buf), 628 "%d slot%s, %d drive%s, " 629 "%d picker%s, %d portal%s", 630 softc->sc_counts[CHET_ST], 631 PLURAL(softc->sc_counts[CHET_ST]), 632 softc->sc_counts[CHET_DT], 633 PLURAL(softc->sc_counts[CHET_DT]), 634 softc->sc_counts[CHET_MT], 635 PLURAL(softc->sc_counts[CHET_MT]), 636 softc->sc_counts[CHET_IE], 637 PLURAL(softc->sc_counts[CHET_IE])); 638 #undef PLURAL 639 if (announce_buf[0] != '\0') { 640 xpt_announce_periph(periph, announce_buf); 641 xpt_announce_quirks(periph, softc->quirks, 642 CH_Q_BIT_STRING); 643 } 644 } else { 645 int error; 646 647 error = cherror(done_ccb, CAM_RETRY_SELTO, 648 SF_RETRY_UA | SF_NO_PRINT); 649 /* 650 * Retry any UNIT ATTENTION type errors. They 651 * are expected at boot. 652 */ 653 if (error == ERESTART) { 654 /* 655 * A retry was scheduled, so 656 * just return. 657 */ 658 return; 659 } else if (error != 0) { 660 struct scsi_mode_sense_6 *sms; 661 int frozen, retry_scheduled; 662 663 sms = (struct scsi_mode_sense_6 *) 664 done_ccb->csio.cdb_io.cdb_bytes; 665 frozen = (done_ccb->ccb_h.status & 666 CAM_DEV_QFRZN) != 0; 667 668 /* 669 * Check to see if block descriptors were 670 * disabled. Some devices don't like that. 671 * We're taking advantage of the fact that 672 * the first few bytes of the 6 and 10 byte 673 * mode sense commands are the same. If 674 * block descriptors were disabled, enable 675 * them and re-send the command. 676 */ 677 if ((sms->byte2 & SMS_DBD) != 0 && 678 (periph->flags & CAM_PERIPH_INVALID) == 0) { 679 sms->byte2 &= ~SMS_DBD; 680 xpt_action(done_ccb); 681 softc->quirks |= CH_Q_NO_DBD; 682 retry_scheduled = 1; 683 } else 684 retry_scheduled = 0; 685 686 /* Don't wedge this device's queue */ 687 if (frozen) 688 cam_release_devq(done_ccb->ccb_h.path, 689 /*relsim_flags*/0, 690 /*reduction*/0, 691 /*timeout*/0, 692 /*getcount_only*/0); 693 694 if (retry_scheduled) 695 return; 696 697 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) 698 == CAM_SCSI_STATUS_ERROR) 699 scsi_sense_print(&done_ccb->csio); 700 else { 701 xpt_print(periph->path, 702 "got CAM status %#x\n", 703 done_ccb->ccb_h.status); 704 } 705 xpt_print(periph->path, "fatal error, failed " 706 "to attach to device\n"); 707 708 cam_periph_invalidate(periph); 709 } 710 } 711 softc->state = CH_STATE_NORMAL; 712 free(mode_header, M_SCSICH); 713 /* 714 * Since our peripheral may be invalidated by an error 715 * above or an external event, we must release our CCB 716 * before releasing the probe lock on the peripheral. 717 * The peripheral will only go away once the last lock 718 * is removed, and we need it around for the CCB release 719 * operation. 720 */ 721 xpt_release_ccb(done_ccb); 722 cam_periph_unhold(periph); 723 return; 724 } 725 default: 726 break; 727 } 728 xpt_release_ccb(done_ccb); 729 } 730 731 static int 732 cherror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags) 733 { 734 735 return (cam_periph_error(ccb, cam_flags, sense_flags)); 736 } 737 738 static int 739 chioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 740 { 741 struct cam_periph *periph; 742 struct ch_softc *softc; 743 int error; 744 745 periph = (struct cam_periph *)dev->si_drv1; 746 cam_periph_lock(periph); 747 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering chioctl\n")); 748 749 softc = (struct ch_softc *)periph->softc; 750 751 error = 0; 752 753 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 754 ("trying to do ioctl %#lx\n", cmd)); 755 756 /* 757 * If this command can change the device's state, we must 758 * have the device open for writing. 759 */ 760 switch (cmd) { 761 case CHIOGPICKER: 762 case CHIOGPARAMS: 763 case OCHIOGSTATUS: 764 case CHIOGSTATUS: 765 break; 766 767 default: 768 if ((flag & FWRITE) == 0) { 769 cam_periph_unlock(periph); 770 return (EBADF); 771 } 772 } 773 774 switch (cmd) { 775 case CHIOMOVE: 776 error = chmove(periph, (struct changer_move *)addr); 777 break; 778 779 case CHIOEXCHANGE: 780 error = chexchange(periph, (struct changer_exchange *)addr); 781 break; 782 783 case CHIOPOSITION: 784 error = chposition(periph, (struct changer_position *)addr); 785 break; 786 787 case CHIOGPICKER: 788 *(int *)addr = softc->sc_picker - softc->sc_firsts[CHET_MT]; 789 break; 790 791 case CHIOSPICKER: 792 { 793 int new_picker = *(int *)addr; 794 795 if (new_picker > (softc->sc_counts[CHET_MT] - 1)) { 796 error = EINVAL; 797 break; 798 } 799 softc->sc_picker = softc->sc_firsts[CHET_MT] + new_picker; 800 break; 801 } 802 case CHIOGPARAMS: 803 { 804 struct changer_params *cp = (struct changer_params *)addr; 805 806 cp->cp_npickers = softc->sc_counts[CHET_MT]; 807 cp->cp_nslots = softc->sc_counts[CHET_ST]; 808 cp->cp_nportals = softc->sc_counts[CHET_IE]; 809 cp->cp_ndrives = softc->sc_counts[CHET_DT]; 810 break; 811 } 812 case CHIOIELEM: 813 error = chielem(periph, *(unsigned int *)addr); 814 break; 815 816 case OCHIOGSTATUS: 817 { 818 error = chgetelemstatus(periph, SCSI_REV_2, cmd, 819 (struct changer_element_status_request *)addr); 820 break; 821 } 822 823 case CHIOGSTATUS: 824 { 825 int scsi_version; 826 827 scsi_version = chscsiversion(periph); 828 if (scsi_version >= SCSI_REV_0) { 829 error = chgetelemstatus(periph, scsi_version, cmd, 830 (struct changer_element_status_request *)addr); 831 } 832 else { /* unable to determine the SCSI version */ 833 cam_periph_unlock(periph); 834 return (ENXIO); 835 } 836 break; 837 } 838 839 case CHIOSETVOLTAG: 840 { 841 error = chsetvoltag(periph, 842 (struct changer_set_voltag_request *) addr); 843 break; 844 } 845 846 /* Implement prevent/allow? */ 847 848 default: 849 error = cam_periph_ioctl(periph, cmd, addr, cherror); 850 break; 851 } 852 853 cam_periph_unlock(periph); 854 return (error); 855 } 856 857 static int 858 chmove(struct cam_periph *periph, struct changer_move *cm) 859 { 860 struct ch_softc *softc; 861 uint16_t fromelem, toelem; 862 union ccb *ccb; 863 int error; 864 865 error = 0; 866 softc = (struct ch_softc *)periph->softc; 867 868 /* 869 * Check arguments. 870 */ 871 if ((cm->cm_fromtype > CHET_DT) || (cm->cm_totype > CHET_DT)) 872 return (EINVAL); 873 if ((cm->cm_fromunit > (softc->sc_counts[cm->cm_fromtype] - 1)) || 874 (cm->cm_tounit > (softc->sc_counts[cm->cm_totype] - 1))) 875 return (ENODEV); 876 877 /* 878 * Check the request against the changer's capabilities. 879 */ 880 if ((softc->sc_movemask[cm->cm_fromtype] & (1 << cm->cm_totype)) == 0) 881 return (ENODEV); 882 883 /* 884 * Calculate the source and destination elements. 885 */ 886 fromelem = softc->sc_firsts[cm->cm_fromtype] + cm->cm_fromunit; 887 toelem = softc->sc_firsts[cm->cm_totype] + cm->cm_tounit; 888 889 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 890 891 scsi_move_medium(&ccb->csio, 892 /* retries */ 1, 893 /* cbfcnp */ chdone, 894 /* tag_action */ MSG_SIMPLE_Q_TAG, 895 /* tea */ softc->sc_picker, 896 /* src */ fromelem, 897 /* dst */ toelem, 898 /* invert */ (cm->cm_flags & CM_INVERT) ? TRUE : FALSE, 899 /* sense_len */ SSD_FULL_SIZE, 900 /* timeout */ CH_TIMEOUT_MOVE_MEDIUM); 901 902 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/CAM_RETRY_SELTO, 903 /*sense_flags*/ SF_RETRY_UA, 904 softc->device_stats); 905 906 xpt_release_ccb(ccb); 907 908 return(error); 909 } 910 911 static int 912 chexchange(struct cam_periph *periph, struct changer_exchange *ce) 913 { 914 struct ch_softc *softc; 915 uint16_t src, dst1, dst2; 916 union ccb *ccb; 917 int error; 918 919 error = 0; 920 softc = (struct ch_softc *)periph->softc; 921 /* 922 * Check arguments. 923 */ 924 if ((ce->ce_srctype > CHET_DT) || (ce->ce_fdsttype > CHET_DT) || 925 (ce->ce_sdsttype > CHET_DT)) 926 return (EINVAL); 927 if ((ce->ce_srcunit > (softc->sc_counts[ce->ce_srctype] - 1)) || 928 (ce->ce_fdstunit > (softc->sc_counts[ce->ce_fdsttype] - 1)) || 929 (ce->ce_sdstunit > (softc->sc_counts[ce->ce_sdsttype] - 1))) 930 return (ENODEV); 931 932 /* 933 * Check the request against the changer's capabilities. 934 */ 935 if (((softc->sc_exchangemask[ce->ce_srctype] & 936 (1 << ce->ce_fdsttype)) == 0) || 937 ((softc->sc_exchangemask[ce->ce_fdsttype] & 938 (1 << ce->ce_sdsttype)) == 0)) 939 return (ENODEV); 940 941 /* 942 * Calculate the source and destination elements. 943 */ 944 src = softc->sc_firsts[ce->ce_srctype] + ce->ce_srcunit; 945 dst1 = softc->sc_firsts[ce->ce_fdsttype] + ce->ce_fdstunit; 946 dst2 = softc->sc_firsts[ce->ce_sdsttype] + ce->ce_sdstunit; 947 948 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 949 950 scsi_exchange_medium(&ccb->csio, 951 /* retries */ 1, 952 /* cbfcnp */ chdone, 953 /* tag_action */ MSG_SIMPLE_Q_TAG, 954 /* tea */ softc->sc_picker, 955 /* src */ src, 956 /* dst1 */ dst1, 957 /* dst2 */ dst2, 958 /* invert1 */ (ce->ce_flags & CE_INVERT1) ? 959 TRUE : FALSE, 960 /* invert2 */ (ce->ce_flags & CE_INVERT2) ? 961 TRUE : FALSE, 962 /* sense_len */ SSD_FULL_SIZE, 963 /* timeout */ CH_TIMEOUT_EXCHANGE_MEDIUM); 964 965 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/CAM_RETRY_SELTO, 966 /*sense_flags*/ SF_RETRY_UA, 967 softc->device_stats); 968 969 xpt_release_ccb(ccb); 970 971 return(error); 972 } 973 974 static int 975 chposition(struct cam_periph *periph, struct changer_position *cp) 976 { 977 struct ch_softc *softc; 978 uint16_t dst; 979 union ccb *ccb; 980 int error; 981 982 error = 0; 983 softc = (struct ch_softc *)periph->softc; 984 985 /* 986 * Check arguments. 987 */ 988 if (cp->cp_type > CHET_DT) 989 return (EINVAL); 990 if (cp->cp_unit > (softc->sc_counts[cp->cp_type] - 1)) 991 return (ENODEV); 992 993 /* 994 * Calculate the destination element. 995 */ 996 dst = softc->sc_firsts[cp->cp_type] + cp->cp_unit; 997 998 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 999 1000 scsi_position_to_element(&ccb->csio, 1001 /* retries */ 1, 1002 /* cbfcnp */ chdone, 1003 /* tag_action */ MSG_SIMPLE_Q_TAG, 1004 /* tea */ softc->sc_picker, 1005 /* dst */ dst, 1006 /* invert */ (cp->cp_flags & CP_INVERT) ? 1007 TRUE : FALSE, 1008 /* sense_len */ SSD_FULL_SIZE, 1009 /* timeout */ CH_TIMEOUT_POSITION_TO_ELEMENT); 1010 1011 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, 1012 /*sense_flags*/ SF_RETRY_UA, 1013 softc->device_stats); 1014 1015 xpt_release_ccb(ccb); 1016 1017 return(error); 1018 } 1019 1020 /* 1021 * Copy a volume tag to a volume_tag struct, converting SCSI byte order 1022 * to host native byte order in the volume serial number. The volume 1023 * label as returned by the changer is transferred to user mode as 1024 * nul-terminated string. Volume labels are truncated at the first 1025 * space, as suggested by SCSI-2. 1026 */ 1027 static void 1028 copy_voltag(struct changer_voltag *uvoltag, struct volume_tag *voltag) 1029 { 1030 int i; 1031 for (i=0; i<CH_VOLTAG_MAXLEN; i++) { 1032 char c = voltag->vif[i]; 1033 if (c && c != ' ') 1034 uvoltag->cv_volid[i] = c; 1035 else 1036 break; 1037 } 1038 uvoltag->cv_serial = scsi_2btoul(voltag->vsn); 1039 } 1040 1041 /* 1042 * Copy an element status descriptor to a user-mode 1043 * changer_element_status structure. 1044 */ 1045 static void 1046 copy_element_status(struct ch_softc *softc, 1047 uint16_t flags, 1048 struct read_element_status_descriptor *desc, 1049 struct changer_element_status *ces, 1050 int scsi_version) 1051 { 1052 uint16_t eaddr = scsi_2btoul(desc->eaddr); 1053 uint16_t et; 1054 struct volume_tag *pvol_tag = NULL, *avol_tag = NULL; 1055 struct read_element_status_device_id *devid = NULL; 1056 1057 ces->ces_int_addr = eaddr; 1058 /* set up logical address in element status */ 1059 for (et = CHET_MT; et <= CHET_DT; et++) { 1060 if ((softc->sc_firsts[et] <= eaddr) 1061 && ((softc->sc_firsts[et] + softc->sc_counts[et]) 1062 > eaddr)) { 1063 ces->ces_addr = eaddr - softc->sc_firsts[et]; 1064 ces->ces_type = et; 1065 break; 1066 } 1067 } 1068 1069 ces->ces_flags = desc->flags1; 1070 1071 ces->ces_sensecode = desc->sense_code; 1072 ces->ces_sensequal = desc->sense_qual; 1073 1074 if (desc->flags2 & READ_ELEMENT_STATUS_INVERT) 1075 ces->ces_flags |= CES_INVERT; 1076 1077 if (desc->flags2 & READ_ELEMENT_STATUS_SVALID) { 1078 eaddr = scsi_2btoul(desc->ssea); 1079 1080 /* convert source address to logical format */ 1081 for (et = CHET_MT; et <= CHET_DT; et++) { 1082 if ((softc->sc_firsts[et] <= eaddr) 1083 && ((softc->sc_firsts[et] + softc->sc_counts[et]) 1084 > eaddr)) { 1085 ces->ces_source_addr = 1086 eaddr - softc->sc_firsts[et]; 1087 ces->ces_source_type = et; 1088 ces->ces_flags |= CES_SOURCE_VALID; 1089 break; 1090 } 1091 } 1092 1093 if (!(ces->ces_flags & CES_SOURCE_VALID)) 1094 printf("ch: warning: could not map element source " 1095 "address %ud to a valid element type\n", 1096 eaddr); 1097 } 1098 1099 /* 1100 * pvoltag and avoltag are common between SCSI-2 and later versions 1101 */ 1102 if (flags & READ_ELEMENT_STATUS_PVOLTAG) 1103 pvol_tag = &desc->voltag_devid.pvoltag; 1104 if (flags & READ_ELEMENT_STATUS_AVOLTAG) 1105 avol_tag = (flags & READ_ELEMENT_STATUS_PVOLTAG) ? 1106 &desc->voltag_devid.voltag[1] :&desc->voltag_devid.pvoltag; 1107 /* 1108 * For SCSI-3 and later, element status can carry designator and 1109 * other information. 1110 */ 1111 if (scsi_version >= SCSI_REV_SPC) { 1112 if ((flags & READ_ELEMENT_STATUS_PVOLTAG) ^ 1113 (flags & READ_ELEMENT_STATUS_AVOLTAG)) 1114 devid = &desc->voltag_devid.pvol_and_devid.devid; 1115 else if (!(flags & READ_ELEMENT_STATUS_PVOLTAG) && 1116 !(flags & READ_ELEMENT_STATUS_AVOLTAG)) 1117 devid = &desc->voltag_devid.devid; 1118 else /* Have both PVOLTAG and AVOLTAG */ 1119 devid = &desc->voltag_devid.vol_tags_and_devid.devid; 1120 } 1121 1122 if (pvol_tag) 1123 copy_voltag(&(ces->ces_pvoltag), pvol_tag); 1124 if (avol_tag) 1125 copy_voltag(&(ces->ces_pvoltag), avol_tag); 1126 if (devid != NULL) { 1127 if (devid->designator_length > 0) { 1128 bcopy((void *)devid->designator, 1129 (void *)ces->ces_designator, 1130 devid->designator_length); 1131 ces->ces_designator_length = devid->designator_length; 1132 /* 1133 * Make sure we are always NUL terminated. The 1134 * This won't matter for the binary code set, 1135 * since the user will only pay attention to the 1136 * length field. 1137 */ 1138 ces->ces_designator[devid->designator_length]= '\0'; 1139 } 1140 if (devid->piv_assoc_designator_type & 1141 READ_ELEMENT_STATUS_PIV_SET) { 1142 ces->ces_flags |= CES_PIV; 1143 ces->ces_protocol_id = 1144 READ_ELEMENT_STATUS_PROTOCOL_ID( 1145 devid->prot_code_set); 1146 } 1147 ces->ces_code_set = 1148 READ_ELEMENT_STATUS_CODE_SET(devid->prot_code_set); 1149 ces->ces_assoc = READ_ELEMENT_STATUS_ASSOCIATION( 1150 devid->piv_assoc_designator_type); 1151 ces->ces_designator_type = READ_ELEMENT_STATUS_DESIGNATOR_TYPE( 1152 devid->piv_assoc_designator_type); 1153 } else if (scsi_version > SCSI_REV_2) { 1154 /* SCSI-SPC and No devid, no designator */ 1155 ces->ces_designator_length = 0; 1156 ces->ces_designator[0] = '\0'; 1157 ces->ces_protocol_id = CES_PROTOCOL_ID_FCP_4; 1158 } 1159 1160 if (scsi_version <= SCSI_REV_2) { 1161 if (desc->dt_or_obsolete.scsi_2.dt_scsi_flags & 1162 READ_ELEMENT_STATUS_DT_IDVALID) { 1163 ces->ces_flags |= CES_SCSIID_VALID; 1164 ces->ces_scsi_id = 1165 desc->dt_or_obsolete.scsi_2.dt_scsi_addr; 1166 } 1167 1168 if (desc->dt_or_obsolete.scsi_2.dt_scsi_addr & 1169 READ_ELEMENT_STATUS_DT_LUVALID) { 1170 ces->ces_flags |= CES_LUN_VALID; 1171 ces->ces_scsi_lun = 1172 desc->dt_or_obsolete.scsi_2.dt_scsi_flags & 1173 READ_ELEMENT_STATUS_DT_LUNMASK; 1174 } 1175 } 1176 } 1177 1178 static int 1179 chgetelemstatus(struct cam_periph *periph, int scsi_version, u_long cmd, 1180 struct changer_element_status_request *cesr) 1181 { 1182 struct read_element_status_header *st_hdr; 1183 struct read_element_status_page_header *pg_hdr; 1184 struct read_element_status_descriptor *desc; 1185 caddr_t data = NULL; 1186 size_t size, desclen; 1187 u_int avail, i; 1188 int curdata, dvcid, sense_flags; 1189 int try_no_dvcid = 0; 1190 struct changer_element_status *user_data = NULL; 1191 struct ch_softc *softc; 1192 union ccb *ccb; 1193 int chet = cesr->cesr_element_type; 1194 int error = 0; 1195 int want_voltags = (cesr->cesr_flags & CESR_VOLTAGS) ? 1 : 0; 1196 1197 softc = (struct ch_softc *)periph->softc; 1198 1199 /* perform argument checking */ 1200 1201 /* 1202 * Perform a range check on the cesr_element_{base,count} 1203 * request argument fields. 1204 */ 1205 if ((softc->sc_counts[chet] - cesr->cesr_element_base) <= 0 1206 || (cesr->cesr_element_base + cesr->cesr_element_count) 1207 > softc->sc_counts[chet]) 1208 return (EINVAL); 1209 1210 /* 1211 * Request one descriptor for the given element type. This 1212 * is used to determine the size of the descriptor so that 1213 * we can allocate enough storage for all of them. We assume 1214 * that the first one can fit into 1k. 1215 */ 1216 cam_periph_unlock(periph); 1217 data = (caddr_t)malloc(1024, M_DEVBUF, M_WAITOK); 1218 1219 cam_periph_lock(periph); 1220 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 1221 1222 sense_flags = SF_RETRY_UA; 1223 if (softc->quirks & CH_Q_NO_DVCID) { 1224 dvcid = 0; 1225 curdata = 0; 1226 } else { 1227 dvcid = 1; 1228 curdata = 1; 1229 /* 1230 * Don't print anything for an Illegal Request, because 1231 * these flags can cause some changers to complain. We'll 1232 * retry without them if we get an error. 1233 */ 1234 sense_flags |= SF_QUIET_IR; 1235 } 1236 1237 retry_einval: 1238 1239 scsi_read_element_status(&ccb->csio, 1240 /* retries */ 1, 1241 /* cbfcnp */ chdone, 1242 /* tag_action */ MSG_SIMPLE_Q_TAG, 1243 /* voltag */ want_voltags, 1244 /* sea */ softc->sc_firsts[chet], 1245 /* curdata */ curdata, 1246 /* dvcid */ dvcid, 1247 /* count */ 1, 1248 /* data_ptr */ data, 1249 /* dxfer_len */ 1024, 1250 /* sense_len */ SSD_FULL_SIZE, 1251 /* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS); 1252 1253 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, 1254 /*sense_flags*/ sense_flags, 1255 softc->device_stats); 1256 1257 /* 1258 * An Illegal Request sense key (only used if there is no asc/ascq) 1259 * or 0x24,0x00 for an ASC/ASCQ both map to EINVAL. If dvcid or 1260 * curdata are set (we set both or neither), try turning them off 1261 * and see if the command is successful. 1262 */ 1263 if ((error == EINVAL) 1264 && (dvcid || curdata)) { 1265 dvcid = 0; 1266 curdata = 0; 1267 error = 0; 1268 /* At this point we want to report any Illegal Request */ 1269 sense_flags &= ~SF_QUIET_IR; 1270 try_no_dvcid = 1; 1271 goto retry_einval; 1272 } 1273 1274 /* 1275 * In this case, we tried a read element status with dvcid and 1276 * curdata set, and it failed. We retried without those bits, and 1277 * it succeeded. Suggest to the user that he set a quirk, so we 1278 * don't go through the retry process the first time in the future. 1279 * This should only happen on changers that claim SCSI-3 or higher, 1280 * but don't support these bits. 1281 */ 1282 if ((try_no_dvcid != 0) 1283 && (error == 0)) 1284 softc->quirks |= CH_Q_NO_DVCID; 1285 1286 if (error) 1287 goto done; 1288 cam_periph_unlock(periph); 1289 1290 st_hdr = (struct read_element_status_header *)data; 1291 pg_hdr = (struct read_element_status_page_header *)((uintptr_t)st_hdr + 1292 sizeof(struct read_element_status_header)); 1293 desclen = scsi_2btoul(pg_hdr->edl); 1294 1295 size = sizeof(struct read_element_status_header) + 1296 sizeof(struct read_element_status_page_header) + 1297 (desclen * cesr->cesr_element_count); 1298 /* 1299 * Reallocate storage for descriptors and get them from the 1300 * device. 1301 */ 1302 free(data, M_DEVBUF); 1303 data = (caddr_t)malloc(size, M_DEVBUF, M_WAITOK); 1304 1305 cam_periph_lock(periph); 1306 scsi_read_element_status(&ccb->csio, 1307 /* retries */ 1, 1308 /* cbfcnp */ chdone, 1309 /* tag_action */ MSG_SIMPLE_Q_TAG, 1310 /* voltag */ want_voltags, 1311 /* sea */ softc->sc_firsts[chet] 1312 + cesr->cesr_element_base, 1313 /* curdata */ curdata, 1314 /* dvcid */ dvcid, 1315 /* count */ cesr->cesr_element_count, 1316 /* data_ptr */ data, 1317 /* dxfer_len */ size, 1318 /* sense_len */ SSD_FULL_SIZE, 1319 /* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS); 1320 1321 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, 1322 /*sense_flags*/ SF_RETRY_UA, 1323 softc->device_stats); 1324 1325 if (error) 1326 goto done; 1327 cam_periph_unlock(periph); 1328 1329 /* 1330 * Fill in the user status array. 1331 */ 1332 st_hdr = (struct read_element_status_header *)data; 1333 pg_hdr = (struct read_element_status_page_header *)((uintptr_t)st_hdr + 1334 sizeof(struct read_element_status_header)); 1335 avail = scsi_2btoul(st_hdr->count); 1336 1337 if (avail != cesr->cesr_element_count) { 1338 xpt_print(periph->path, 1339 "warning, READ ELEMENT STATUS avail != count\n"); 1340 } 1341 1342 user_data = (struct changer_element_status *) 1343 malloc(avail * sizeof(struct changer_element_status), 1344 M_DEVBUF, M_WAITOK | M_ZERO); 1345 1346 desc = (struct read_element_status_descriptor *)((uintptr_t)data + 1347 sizeof(struct read_element_status_header) + 1348 sizeof(struct read_element_status_page_header)); 1349 /* 1350 * Set up the individual element status structures 1351 */ 1352 for (i = 0; i < avail; ++i) { 1353 struct changer_element_status *ces; 1354 1355 /* 1356 * In the changer_element_status structure, fields from 1357 * the beginning to the field of ces_scsi_lun are common 1358 * between SCSI-2 and SCSI-3, while all the rest are new 1359 * from SCSI-3. In order to maintain backward compatibility 1360 * of the chio command, the ces pointer, below, is computed 1361 * such that it lines up with the structure boundary 1362 * corresponding to the SCSI version. 1363 */ 1364 ces = cmd == OCHIOGSTATUS ? 1365 (struct changer_element_status *) 1366 ((unsigned char *)user_data + i * 1367 (offsetof(struct changer_element_status,ces_scsi_lun)+1)): 1368 &user_data[i]; 1369 1370 copy_element_status(softc, pg_hdr->flags, desc, 1371 ces, scsi_version); 1372 1373 desc = (struct read_element_status_descriptor *) 1374 ((unsigned char *)desc + desclen); 1375 } 1376 1377 /* Copy element status structures out to userspace. */ 1378 if (cmd == OCHIOGSTATUS) 1379 error = copyout(user_data, 1380 cesr->cesr_element_status, 1381 avail* (offsetof(struct changer_element_status, 1382 ces_scsi_lun) + 1)); 1383 else 1384 error = copyout(user_data, 1385 cesr->cesr_element_status, 1386 avail * sizeof(struct changer_element_status)); 1387 1388 cam_periph_lock(periph); 1389 1390 done: 1391 xpt_release_ccb(ccb); 1392 1393 if (data != NULL) 1394 free(data, M_DEVBUF); 1395 if (user_data != NULL) 1396 free(user_data, M_DEVBUF); 1397 1398 return (error); 1399 } 1400 1401 static int 1402 chielem(struct cam_periph *periph, 1403 unsigned int timeout) 1404 { 1405 union ccb *ccb; 1406 struct ch_softc *softc; 1407 int error; 1408 1409 if (!timeout) { 1410 timeout = CH_TIMEOUT_INITIALIZE_ELEMENT_STATUS; 1411 } else { 1412 timeout *= 1000; 1413 } 1414 1415 error = 0; 1416 softc = (struct ch_softc *)periph->softc; 1417 1418 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 1419 1420 scsi_initialize_element_status(&ccb->csio, 1421 /* retries */ 1, 1422 /* cbfcnp */ chdone, 1423 /* tag_action */ MSG_SIMPLE_Q_TAG, 1424 /* sense_len */ SSD_FULL_SIZE, 1425 /* timeout */ timeout); 1426 1427 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, 1428 /*sense_flags*/ SF_RETRY_UA, 1429 softc->device_stats); 1430 1431 xpt_release_ccb(ccb); 1432 1433 return(error); 1434 } 1435 1436 static int 1437 chsetvoltag(struct cam_periph *periph, 1438 struct changer_set_voltag_request *csvr) 1439 { 1440 union ccb *ccb; 1441 struct ch_softc *softc; 1442 uint16_t ea; 1443 uint8_t sac; 1444 struct scsi_send_volume_tag_parameters ssvtp; 1445 int error; 1446 int i; 1447 1448 error = 0; 1449 softc = (struct ch_softc *)periph->softc; 1450 1451 bzero(&ssvtp, sizeof(ssvtp)); 1452 for (i=0; i<sizeof(ssvtp.vitf); i++) { 1453 ssvtp.vitf[i] = ' '; 1454 } 1455 1456 /* 1457 * Check arguments. 1458 */ 1459 if (csvr->csvr_type > CHET_DT) 1460 return EINVAL; 1461 if (csvr->csvr_addr > (softc->sc_counts[csvr->csvr_type] - 1)) 1462 return ENODEV; 1463 1464 ea = softc->sc_firsts[csvr->csvr_type] + csvr->csvr_addr; 1465 1466 if (csvr->csvr_flags & CSVR_ALTERNATE) { 1467 switch (csvr->csvr_flags & CSVR_MODE_MASK) { 1468 case CSVR_MODE_SET: 1469 sac = SEND_VOLUME_TAG_ASSERT_ALTERNATE; 1470 break; 1471 case CSVR_MODE_REPLACE: 1472 sac = SEND_VOLUME_TAG_REPLACE_ALTERNATE; 1473 break; 1474 case CSVR_MODE_CLEAR: 1475 sac = SEND_VOLUME_TAG_UNDEFINED_ALTERNATE; 1476 break; 1477 default: 1478 error = EINVAL; 1479 goto out; 1480 } 1481 } else { 1482 switch (csvr->csvr_flags & CSVR_MODE_MASK) { 1483 case CSVR_MODE_SET: 1484 sac = SEND_VOLUME_TAG_ASSERT_PRIMARY; 1485 break; 1486 case CSVR_MODE_REPLACE: 1487 sac = SEND_VOLUME_TAG_REPLACE_PRIMARY; 1488 break; 1489 case CSVR_MODE_CLEAR: 1490 sac = SEND_VOLUME_TAG_UNDEFINED_PRIMARY; 1491 break; 1492 default: 1493 error = EINVAL; 1494 goto out; 1495 } 1496 } 1497 1498 memcpy(ssvtp.vitf, csvr->csvr_voltag.cv_volid, 1499 min(strlen(csvr->csvr_voltag.cv_volid), sizeof(ssvtp.vitf))); 1500 scsi_ulto2b(csvr->csvr_voltag.cv_serial, ssvtp.minvsn); 1501 1502 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 1503 1504 scsi_send_volume_tag(&ccb->csio, 1505 /* retries */ 1, 1506 /* cbfcnp */ chdone, 1507 /* tag_action */ MSG_SIMPLE_Q_TAG, 1508 /* element_address */ ea, 1509 /* send_action_code */ sac, 1510 /* parameters */ &ssvtp, 1511 /* sense_len */ SSD_FULL_SIZE, 1512 /* timeout */ CH_TIMEOUT_SEND_VOLTAG); 1513 1514 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, 1515 /*sense_flags*/ SF_RETRY_UA, 1516 softc->device_stats); 1517 1518 xpt_release_ccb(ccb); 1519 1520 out: 1521 return error; 1522 } 1523 1524 static int 1525 chgetparams(struct cam_periph *periph) 1526 { 1527 union ccb *ccb; 1528 struct ch_softc *softc; 1529 void *mode_buffer; 1530 int mode_buffer_len; 1531 struct page_element_address_assignment *ea; 1532 struct page_device_capabilities *cap; 1533 int error, from, dbd; 1534 uint8_t *moves, *exchanges; 1535 1536 error = 0; 1537 1538 softc = (struct ch_softc *)periph->softc; 1539 1540 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 1541 1542 /* 1543 * The scsi_mode_sense_data structure is just a convenience 1544 * structure that allows us to easily calculate the worst-case 1545 * storage size of the mode sense buffer. 1546 */ 1547 mode_buffer_len = sizeof(struct scsi_mode_sense_data); 1548 1549 mode_buffer = malloc(mode_buffer_len, M_SCSICH, M_NOWAIT); 1550 1551 if (mode_buffer == NULL) { 1552 printf("chgetparams: couldn't malloc mode sense data\n"); 1553 xpt_release_ccb(ccb); 1554 return(ENOSPC); 1555 } 1556 1557 bzero(mode_buffer, mode_buffer_len); 1558 1559 if (softc->quirks & CH_Q_NO_DBD) 1560 dbd = FALSE; 1561 else 1562 dbd = TRUE; 1563 1564 /* 1565 * Get the element address assignment page. 1566 */ 1567 scsi_mode_sense(&ccb->csio, 1568 /* retries */ 1, 1569 /* cbfcnp */ chdone, 1570 /* tag_action */ MSG_SIMPLE_Q_TAG, 1571 /* dbd */ dbd, 1572 /* pc */ SMS_PAGE_CTRL_CURRENT, 1573 /* page */ CH_ELEMENT_ADDR_ASSIGN_PAGE, 1574 /* param_buf */ (uint8_t *)mode_buffer, 1575 /* param_len */ mode_buffer_len, 1576 /* sense_len */ SSD_FULL_SIZE, 1577 /* timeout */ CH_TIMEOUT_MODE_SENSE); 1578 1579 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, 1580 /* sense_flags */ SF_RETRY_UA|SF_NO_PRINT, 1581 softc->device_stats); 1582 1583 if (error) { 1584 if (dbd) { 1585 struct scsi_mode_sense_6 *sms; 1586 1587 sms = (struct scsi_mode_sense_6 *) 1588 ccb->csio.cdb_io.cdb_bytes; 1589 1590 sms->byte2 &= ~SMS_DBD; 1591 error = cam_periph_runccb(ccb, cherror, 1592 /*cam_flags*/ CAM_RETRY_SELTO, 1593 /*sense_flags*/ SF_RETRY_UA, 1594 softc->device_stats); 1595 } else { 1596 /* 1597 * Since we disabled sense printing above, print 1598 * out the sense here since we got an error. 1599 */ 1600 scsi_sense_print(&ccb->csio); 1601 } 1602 1603 if (error) { 1604 xpt_print(periph->path, 1605 "chgetparams: error getting element " 1606 "address page\n"); 1607 xpt_release_ccb(ccb); 1608 free(mode_buffer, M_SCSICH); 1609 return(error); 1610 } 1611 } 1612 1613 ea = (struct page_element_address_assignment *) 1614 find_mode_page_6((struct scsi_mode_header_6 *)mode_buffer); 1615 1616 softc->sc_firsts[CHET_MT] = scsi_2btoul(ea->mtea); 1617 softc->sc_counts[CHET_MT] = scsi_2btoul(ea->nmte); 1618 softc->sc_firsts[CHET_ST] = scsi_2btoul(ea->fsea); 1619 softc->sc_counts[CHET_ST] = scsi_2btoul(ea->nse); 1620 softc->sc_firsts[CHET_IE] = scsi_2btoul(ea->fieea); 1621 softc->sc_counts[CHET_IE] = scsi_2btoul(ea->niee); 1622 softc->sc_firsts[CHET_DT] = scsi_2btoul(ea->fdtea); 1623 softc->sc_counts[CHET_DT] = scsi_2btoul(ea->ndte); 1624 1625 bzero(mode_buffer, mode_buffer_len); 1626 1627 /* 1628 * Now get the device capabilities page. 1629 */ 1630 scsi_mode_sense(&ccb->csio, 1631 /* retries */ 1, 1632 /* cbfcnp */ chdone, 1633 /* tag_action */ MSG_SIMPLE_Q_TAG, 1634 /* dbd */ dbd, 1635 /* pc */ SMS_PAGE_CTRL_CURRENT, 1636 /* page */ CH_DEVICE_CAP_PAGE, 1637 /* param_buf */ (uint8_t *)mode_buffer, 1638 /* param_len */ mode_buffer_len, 1639 /* sense_len */ SSD_FULL_SIZE, 1640 /* timeout */ CH_TIMEOUT_MODE_SENSE); 1641 1642 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, 1643 /* sense_flags */ SF_RETRY_UA | SF_NO_PRINT, 1644 softc->device_stats); 1645 1646 if (error) { 1647 if (dbd) { 1648 struct scsi_mode_sense_6 *sms; 1649 1650 sms = (struct scsi_mode_sense_6 *) 1651 ccb->csio.cdb_io.cdb_bytes; 1652 1653 sms->byte2 &= ~SMS_DBD; 1654 error = cam_periph_runccb(ccb, cherror, 1655 /*cam_flags*/ CAM_RETRY_SELTO, 1656 /*sense_flags*/ SF_RETRY_UA, 1657 softc->device_stats); 1658 } else { 1659 /* 1660 * Since we disabled sense printing above, print 1661 * out the sense here since we got an error. 1662 */ 1663 scsi_sense_print(&ccb->csio); 1664 } 1665 1666 if (error) { 1667 xpt_print(periph->path, 1668 "chgetparams: error getting device " 1669 "capabilities page\n"); 1670 xpt_release_ccb(ccb); 1671 free(mode_buffer, M_SCSICH); 1672 return(error); 1673 } 1674 } 1675 1676 xpt_release_ccb(ccb); 1677 1678 cap = (struct page_device_capabilities *) 1679 find_mode_page_6((struct scsi_mode_header_6 *)mode_buffer); 1680 1681 bzero(softc->sc_movemask, sizeof(softc->sc_movemask)); 1682 bzero(softc->sc_exchangemask, sizeof(softc->sc_exchangemask)); 1683 moves = cap->move_from; 1684 exchanges = cap->exchange_with; 1685 for (from = CHET_MT; from <= CHET_MAX; ++from) { 1686 softc->sc_movemask[from] = moves[from]; 1687 softc->sc_exchangemask[from] = exchanges[from]; 1688 } 1689 1690 free(mode_buffer, M_SCSICH); 1691 1692 return(error); 1693 } 1694 1695 static int 1696 chscsiversion(struct cam_periph *periph) 1697 { 1698 struct scsi_inquiry_data *inq_data; 1699 struct ccb_getdev *cgd; 1700 int dev_scsi_version; 1701 1702 cam_periph_assert(periph, MA_OWNED); 1703 if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) == NULL) 1704 return (-1); 1705 /* 1706 * Get the device information. 1707 */ 1708 xpt_setup_ccb(&cgd->ccb_h, 1709 periph->path, 1710 CAM_PRIORITY_NORMAL); 1711 cgd->ccb_h.func_code = XPT_GDEV_TYPE; 1712 xpt_action((union ccb *)cgd); 1713 1714 if (cgd->ccb_h.status != CAM_REQ_CMP) { 1715 xpt_free_ccb((union ccb *)cgd); 1716 return -1; 1717 } 1718 1719 inq_data = &cgd->inq_data; 1720 dev_scsi_version = inq_data->version; 1721 xpt_free_ccb((union ccb *)cgd); 1722 1723 return dev_scsi_version; 1724 } 1725 1726 void 1727 scsi_move_medium(struct ccb_scsiio *csio, uint32_t retries, 1728 void (*cbfcnp)(struct cam_periph *, union ccb *), 1729 uint8_t tag_action, uint32_t tea, uint32_t src, 1730 uint32_t dst, int invert, uint8_t sense_len, 1731 uint32_t timeout) 1732 { 1733 struct scsi_move_medium *scsi_cmd; 1734 1735 scsi_cmd = (struct scsi_move_medium *)&csio->cdb_io.cdb_bytes; 1736 bzero(scsi_cmd, sizeof(*scsi_cmd)); 1737 1738 scsi_cmd->opcode = MOVE_MEDIUM; 1739 1740 scsi_ulto2b(tea, scsi_cmd->tea); 1741 scsi_ulto2b(src, scsi_cmd->src); 1742 scsi_ulto2b(dst, scsi_cmd->dst); 1743 1744 if (invert) 1745 scsi_cmd->invert |= MOVE_MEDIUM_INVERT; 1746 1747 cam_fill_csio(csio, 1748 retries, 1749 cbfcnp, 1750 /*flags*/ CAM_DIR_NONE, 1751 tag_action, 1752 /*data_ptr*/ NULL, 1753 /*dxfer_len*/ 0, 1754 sense_len, 1755 sizeof(*scsi_cmd), 1756 timeout); 1757 } 1758 1759 void 1760 scsi_exchange_medium(struct ccb_scsiio *csio, uint32_t retries, 1761 void (*cbfcnp)(struct cam_periph *, union ccb *), 1762 uint8_t tag_action, uint32_t tea, uint32_t src, 1763 uint32_t dst1, uint32_t dst2, int invert1, 1764 int invert2, uint8_t sense_len, uint32_t timeout) 1765 { 1766 struct scsi_exchange_medium *scsi_cmd; 1767 1768 scsi_cmd = (struct scsi_exchange_medium *)&csio->cdb_io.cdb_bytes; 1769 bzero(scsi_cmd, sizeof(*scsi_cmd)); 1770 1771 scsi_cmd->opcode = EXCHANGE_MEDIUM; 1772 1773 scsi_ulto2b(tea, scsi_cmd->tea); 1774 scsi_ulto2b(src, scsi_cmd->src); 1775 scsi_ulto2b(dst1, scsi_cmd->fdst); 1776 scsi_ulto2b(dst2, scsi_cmd->sdst); 1777 1778 if (invert1) 1779 scsi_cmd->invert |= EXCHANGE_MEDIUM_INV1; 1780 1781 if (invert2) 1782 scsi_cmd->invert |= EXCHANGE_MEDIUM_INV2; 1783 1784 cam_fill_csio(csio, 1785 retries, 1786 cbfcnp, 1787 /*flags*/ CAM_DIR_NONE, 1788 tag_action, 1789 /*data_ptr*/ NULL, 1790 /*dxfer_len*/ 0, 1791 sense_len, 1792 sizeof(*scsi_cmd), 1793 timeout); 1794 } 1795 1796 void 1797 scsi_position_to_element(struct ccb_scsiio *csio, uint32_t retries, 1798 void (*cbfcnp)(struct cam_periph *, union ccb *), 1799 uint8_t tag_action, uint32_t tea, uint32_t dst, 1800 int invert, uint8_t sense_len, uint32_t timeout) 1801 { 1802 struct scsi_position_to_element *scsi_cmd; 1803 1804 scsi_cmd = (struct scsi_position_to_element *)&csio->cdb_io.cdb_bytes; 1805 bzero(scsi_cmd, sizeof(*scsi_cmd)); 1806 1807 scsi_cmd->opcode = POSITION_TO_ELEMENT; 1808 1809 scsi_ulto2b(tea, scsi_cmd->tea); 1810 scsi_ulto2b(dst, scsi_cmd->dst); 1811 1812 if (invert) 1813 scsi_cmd->invert |= POSITION_TO_ELEMENT_INVERT; 1814 1815 cam_fill_csio(csio, 1816 retries, 1817 cbfcnp, 1818 /*flags*/ CAM_DIR_NONE, 1819 tag_action, 1820 /*data_ptr*/ NULL, 1821 /*dxfer_len*/ 0, 1822 sense_len, 1823 sizeof(*scsi_cmd), 1824 timeout); 1825 } 1826 1827 void 1828 scsi_read_element_status(struct ccb_scsiio *csio, uint32_t retries, 1829 void (*cbfcnp)(struct cam_periph *, union ccb *), 1830 uint8_t tag_action, int voltag, uint32_t sea, 1831 int curdata, int dvcid, 1832 uint32_t count, uint8_t *data_ptr, 1833 uint32_t dxfer_len, uint8_t sense_len, 1834 uint32_t timeout) 1835 { 1836 struct scsi_read_element_status *scsi_cmd; 1837 1838 scsi_cmd = (struct scsi_read_element_status *)&csio->cdb_io.cdb_bytes; 1839 bzero(scsi_cmd, sizeof(*scsi_cmd)); 1840 1841 scsi_cmd->opcode = READ_ELEMENT_STATUS; 1842 1843 scsi_ulto2b(sea, scsi_cmd->sea); 1844 scsi_ulto2b(count, scsi_cmd->count); 1845 scsi_ulto3b(dxfer_len, scsi_cmd->len); 1846 if (dvcid) 1847 scsi_cmd->flags |= READ_ELEMENT_STATUS_DVCID; 1848 if (curdata) 1849 scsi_cmd->flags |= READ_ELEMENT_STATUS_CURDATA; 1850 1851 if (voltag) 1852 scsi_cmd->byte2 |= READ_ELEMENT_STATUS_VOLTAG; 1853 1854 cam_fill_csio(csio, 1855 retries, 1856 cbfcnp, 1857 /*flags*/ CAM_DIR_IN, 1858 tag_action, 1859 data_ptr, 1860 dxfer_len, 1861 sense_len, 1862 sizeof(*scsi_cmd), 1863 timeout); 1864 } 1865 1866 void 1867 scsi_initialize_element_status(struct ccb_scsiio *csio, uint32_t retries, 1868 void (*cbfcnp)(struct cam_periph *, union ccb *), 1869 uint8_t tag_action, uint8_t sense_len, 1870 uint32_t timeout) 1871 { 1872 struct scsi_initialize_element_status *scsi_cmd; 1873 1874 scsi_cmd = (struct scsi_initialize_element_status *) 1875 &csio->cdb_io.cdb_bytes; 1876 bzero(scsi_cmd, sizeof(*scsi_cmd)); 1877 1878 scsi_cmd->opcode = INITIALIZE_ELEMENT_STATUS; 1879 1880 cam_fill_csio(csio, 1881 retries, 1882 cbfcnp, 1883 /*flags*/ CAM_DIR_NONE, 1884 tag_action, 1885 /* data_ptr */ NULL, 1886 /* dxfer_len */ 0, 1887 sense_len, 1888 sizeof(*scsi_cmd), 1889 timeout); 1890 } 1891 1892 void 1893 scsi_send_volume_tag(struct ccb_scsiio *csio, uint32_t retries, 1894 void (*cbfcnp)(struct cam_periph *, union ccb *), 1895 uint8_t tag_action, 1896 uint16_t element_address, 1897 uint8_t send_action_code, 1898 struct scsi_send_volume_tag_parameters *parameters, 1899 uint8_t sense_len, uint32_t timeout) 1900 { 1901 struct scsi_send_volume_tag *scsi_cmd; 1902 1903 scsi_cmd = (struct scsi_send_volume_tag *) &csio->cdb_io.cdb_bytes; 1904 bzero(scsi_cmd, sizeof(*scsi_cmd)); 1905 1906 scsi_cmd->opcode = SEND_VOLUME_TAG; 1907 scsi_ulto2b(element_address, scsi_cmd->ea); 1908 scsi_cmd->sac = send_action_code; 1909 scsi_ulto2b(sizeof(*parameters), scsi_cmd->pll); 1910 1911 cam_fill_csio(csio, 1912 retries, 1913 cbfcnp, 1914 /*flags*/ CAM_DIR_OUT, 1915 tag_action, 1916 /* data_ptr */ (uint8_t *) parameters, 1917 sizeof(*parameters), 1918 sense_len, 1919 sizeof(*scsi_cmd), 1920 timeout); 1921 } 1922