1 /* $OpenBSD: ch.c,v 1.46 2011/06/17 00:00:51 matthew Exp $ */ 2 /* $NetBSD: ch.c,v 1.26 1997/02/21 22:06:52 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1996, 1997 Jason R. Thorpe <thorpej@and.com> 6 * All rights reserved. 7 * 8 * Partially based on an autochanger driver written by Stefan Grefen 9 * and on an autochanger driver written by the Systems Programming Group 10 * at the University of Utah Computer Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgements: 22 * This product includes software developed by Jason R. Thorpe 23 * for And Communications, http://www.and.com/ 24 * 4. The name of the author may not be used to endorse or promote products 25 * derived from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 34 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 35 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/errno.h> 43 #include <sys/ioctl.h> 44 #include <sys/buf.h> 45 #include <sys/proc.h> 46 #include <sys/chio.h> 47 #include <sys/device.h> 48 #include <sys/malloc.h> 49 #include <sys/pool.h> 50 #include <sys/conf.h> 51 #include <sys/fcntl.h> 52 53 #include <scsi/scsi_all.h> 54 #include <scsi/scsi_changer.h> 55 #include <scsi/scsiconf.h> 56 57 #define CHRETRIES 2 58 #define CHUNIT(x) (minor((x))) 59 60 struct ch_softc { 61 struct device sc_dev; /* generic device info */ 62 struct scsi_link *sc_link; /* link in the SCSI bus */ 63 64 int sc_picker; /* current picker */ 65 66 /* 67 * The following information is obtained from the 68 * element address assignment page. 69 */ 70 int sc_firsts[4]; /* firsts, indexed by CHET_* */ 71 int sc_counts[4]; /* counts, indexed by CHET_* */ 72 73 /* 74 * The following mask defines the legal combinations 75 * of elements for the MOVE MEDIUM command. 76 */ 77 u_int8_t sc_movemask[4]; 78 79 /* 80 * As above, but for EXCHANGE MEDIUM. 81 */ 82 u_int8_t sc_exchangemask[4]; 83 84 int flags; /* misc. info */ 85 86 /* 87 * Quirks; see below. 88 */ 89 int sc_settledelay; /* delay for settle */ 90 91 }; 92 93 /* sc_flags */ 94 #define CHF_ROTATE 0x01 /* picker can rotate */ 95 96 /* Autoconfiguration glue */ 97 int chmatch(struct device *, void *, void *); 98 void chattach(struct device *, struct device *, void *); 99 100 struct cfattach ch_ca = { 101 sizeof(struct ch_softc), chmatch, chattach 102 }; 103 104 struct cfdriver ch_cd = { 105 NULL, "ch", DV_DULL 106 }; 107 108 const struct scsi_inquiry_pattern ch_patterns[] = { 109 {T_CHANGER, T_REMOV, 110 "", "", ""}, 111 }; 112 113 int ch_move(struct ch_softc *, struct changer_move *); 114 int ch_exchange(struct ch_softc *, struct changer_exchange *); 115 int ch_position(struct ch_softc *, struct changer_position *); 116 int ch_usergetelemstatus(struct ch_softc *, 117 struct changer_element_status_request *); 118 int ch_getelemstatus(struct ch_softc *, int, int, caddr_t, size_t, int); 119 int ch_get_params(struct ch_softc *, int); 120 int ch_interpret_sense(struct scsi_xfer *xs); 121 void ch_get_quirks(struct ch_softc *, struct scsi_inquiry_data *); 122 123 /* 124 * SCSI changer quirks. 125 */ 126 struct chquirk { 127 struct scsi_inquiry_pattern cq_match; /* device id pattern */ 128 int cq_settledelay; /* settle delay, in seconds */ 129 }; 130 131 struct chquirk chquirks[] = { 132 {{T_CHANGER, T_REMOV, 133 "SPECTRA", "9000", "0200"}, 134 75}, 135 }; 136 137 int 138 chmatch(struct device *parent, void *match, void *aux) 139 { 140 struct scsi_attach_args *sa = aux; 141 int priority; 142 143 (void)scsi_inqmatch(sa->sa_inqbuf, 144 ch_patterns, nitems(ch_patterns), 145 sizeof(ch_patterns[0]), &priority); 146 147 return (priority); 148 } 149 150 void 151 chattach(struct device *parent, struct device *self, void *aux) 152 { 153 struct ch_softc *sc = (struct ch_softc *)self; 154 struct scsi_attach_args *sa = aux; 155 struct scsi_link *link = sa->sa_sc_link; 156 157 /* Glue into the SCSI bus */ 158 sc->sc_link = link; 159 link->interpret_sense = ch_interpret_sense; 160 link->device_softc = sc; 161 link->openings = 1; 162 163 printf("\n"); 164 165 /* 166 * Store our our device's quirks. 167 */ 168 ch_get_quirks(sc, sa->sa_inqbuf); 169 170 } 171 172 int 173 chopen(dev_t dev, int flags, int fmt, struct proc *p) 174 { 175 struct ch_softc *sc; 176 int oldcounts[4]; 177 int i, unit, error = 0; 178 179 unit = CHUNIT(dev); 180 if ((unit >= ch_cd.cd_ndevs) || 181 ((sc = ch_cd.cd_devs[unit]) == NULL)) 182 return (ENXIO); 183 184 /* 185 * Only allow one open at a time. 186 */ 187 if (sc->sc_link->flags & SDEV_OPEN) 188 return (EBUSY); 189 190 sc->sc_link->flags |= SDEV_OPEN; 191 192 /* 193 * Absorb any unit attention errors. We must notice 194 * "Not ready" errors as a changer will report "In the 195 * process of getting ready" any time it must rescan 196 * itself to determine the state of the changer. 197 */ 198 error = scsi_test_unit_ready(sc->sc_link, TEST_READY_RETRIES, 199 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); 200 if (error) 201 goto bad; 202 203 /* 204 * Get information about the device. Save old information 205 * so we can decide whether to be verbose about new parameters. 206 */ 207 for (i = 0; i < 4; i++) { 208 oldcounts[i] = sc->sc_counts[i]; 209 } 210 error = ch_get_params(sc, scsi_autoconf); 211 if (error) 212 goto bad; 213 214 for (i = 0; i < 4; i++) { 215 if (oldcounts[i] != sc->sc_counts[i]) { 216 break; 217 } 218 } 219 if (i < 4) { 220 #ifdef CHANGER_DEBUG 221 #define PLURAL(c) (c) == 1 ? "" : "s" 222 printf("%s: %d slot%s, %d drive%s, %d picker%s, %d portal%s\n", 223 sc->sc_dev.dv_xname, 224 sc->sc_counts[CHET_ST], PLURAL(sc->sc_counts[CHET_ST]), 225 sc->sc_counts[CHET_DT], PLURAL(sc->sc_counts[CHET_DT]), 226 sc->sc_counts[CHET_MT], PLURAL(sc->sc_counts[CHET_MT]), 227 sc->sc_counts[CHET_IE], PLURAL(sc->sc_counts[CHET_IE])); 228 #undef PLURAL 229 printf("%s: move mask: 0x%x 0x%x 0x%x 0x%x\n", 230 sc->sc_dev.dv_xname, 231 sc->sc_movemask[CHET_MT], sc->sc_movemask[CHET_ST], 232 sc->sc_movemask[CHET_IE], sc->sc_movemask[CHET_DT]); 233 printf("%s: exchange mask: 0x%x 0x%x 0x%x 0x%x\n", 234 sc->sc_dev.dv_xname, 235 sc->sc_exchangemask[CHET_MT], sc->sc_exchangemask[CHET_ST], 236 sc->sc_exchangemask[CHET_IE], sc->sc_exchangemask[CHET_DT]); 237 #endif /* CHANGER_DEBUG */ 238 } 239 240 /* Default the current picker. */ 241 sc->sc_picker = sc->sc_firsts[CHET_MT]; 242 243 return (0); 244 245 bad: 246 sc->sc_link->flags &= ~SDEV_OPEN; 247 return (error); 248 } 249 250 int 251 chclose(dev_t dev, int flags, int fmt, struct proc *p) 252 { 253 struct ch_softc *sc = ch_cd.cd_devs[CHUNIT(dev)]; 254 255 sc->sc_link->flags &= ~SDEV_OPEN; 256 return (0); 257 } 258 259 int 260 chioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 261 { 262 struct ch_softc *sc = ch_cd.cd_devs[CHUNIT(dev)]; 263 int error = 0; 264 265 /* 266 * If this command can change the device's state, we must 267 * have the device open for writing. 268 */ 269 switch (cmd) { 270 case CHIOGPICKER: 271 case CHIOGPARAMS: 272 case CHIOGSTATUS: 273 break; 274 275 default: 276 if ((flags & FWRITE) == 0) 277 return (EBADF); 278 } 279 280 switch (cmd) { 281 case CHIOMOVE: 282 error = ch_move(sc, (struct changer_move *)data); 283 break; 284 285 case CHIOEXCHANGE: 286 error = ch_exchange(sc, (struct changer_exchange *)data); 287 break; 288 289 case CHIOPOSITION: 290 error = ch_position(sc, (struct changer_position *)data); 291 break; 292 293 case CHIOGPICKER: 294 *(int *)data = sc->sc_picker - sc->sc_firsts[CHET_MT]; 295 break; 296 297 case CHIOSPICKER: { 298 int new_picker = *(int *)data; 299 300 if (new_picker > (sc->sc_counts[CHET_MT] - 1)) 301 return (EINVAL); 302 sc->sc_picker = sc->sc_firsts[CHET_MT] + new_picker; 303 break; } 304 305 case CHIOGPARAMS: { 306 struct changer_params *cp = (struct changer_params *)data; 307 308 cp->cp_curpicker = sc->sc_picker - sc->sc_firsts[CHET_MT]; 309 cp->cp_npickers = sc->sc_counts[CHET_MT]; 310 cp->cp_nslots = sc->sc_counts[CHET_ST]; 311 cp->cp_nportals = sc->sc_counts[CHET_IE]; 312 cp->cp_ndrives = sc->sc_counts[CHET_DT]; 313 break; } 314 315 case CHIOGSTATUS: { 316 struct changer_element_status_request *cesr = 317 (struct changer_element_status_request *)data; 318 319 error = ch_usergetelemstatus(sc, cesr); 320 break; } 321 322 /* Implement prevent/allow? */ 323 324 default: 325 error = scsi_do_ioctl(sc->sc_link, cmd, data, flags); 326 break; 327 } 328 329 return (error); 330 } 331 332 int 333 ch_move(struct ch_softc *sc, struct changer_move *cm) 334 { 335 struct scsi_move_medium *cmd; 336 struct scsi_xfer *xs; 337 int error; 338 u_int16_t fromelem, toelem; 339 340 /* 341 * Check arguments. 342 */ 343 if ((cm->cm_fromtype > CHET_DT) || (cm->cm_totype > CHET_DT)) 344 return (EINVAL); 345 if ((cm->cm_fromunit > (sc->sc_counts[cm->cm_fromtype] - 1)) || 346 (cm->cm_tounit > (sc->sc_counts[cm->cm_totype] - 1))) 347 return (ENODEV); 348 349 /* 350 * Check the request against the changer's capabilities. 351 */ 352 if ((sc->sc_movemask[cm->cm_fromtype] & (1 << cm->cm_totype)) == 0) 353 return (EINVAL); 354 355 /* 356 * Calculate the source and destination elements. 357 */ 358 fromelem = sc->sc_firsts[cm->cm_fromtype] + cm->cm_fromunit; 359 toelem = sc->sc_firsts[cm->cm_totype] + cm->cm_tounit; 360 361 /* 362 * Build the SCSI command. 363 */ 364 xs = scsi_xs_get(sc->sc_link, 0); 365 if (xs == NULL) 366 return (ENOMEM); 367 xs->cmdlen = sizeof(*cmd); 368 xs->retries = CHRETRIES; 369 xs->timeout = 100000; 370 371 cmd = (struct scsi_move_medium *)xs->cmd; 372 cmd->opcode = MOVE_MEDIUM; 373 _lto2b(sc->sc_picker, cmd->tea); 374 _lto2b(fromelem, cmd->src); 375 _lto2b(toelem, cmd->dst); 376 if (cm->cm_flags & CM_INVERT) 377 cmd->flags |= MOVE_MEDIUM_INVERT; 378 379 error = scsi_xs_sync(xs); 380 scsi_xs_put(xs); 381 382 return (error); 383 } 384 385 int 386 ch_exchange(struct ch_softc *sc, struct changer_exchange *ce) 387 { 388 struct scsi_exchange_medium *cmd; 389 struct scsi_xfer *xs; 390 int error; 391 u_int16_t src, dst1, dst2; 392 393 /* 394 * Check arguments. 395 */ 396 if ((ce->ce_srctype > CHET_DT) || (ce->ce_fdsttype > CHET_DT) || 397 (ce->ce_sdsttype > CHET_DT)) 398 return (EINVAL); 399 if ((ce->ce_srcunit > (sc->sc_counts[ce->ce_srctype] - 1)) || 400 (ce->ce_fdstunit > (sc->sc_counts[ce->ce_fdsttype] - 1)) || 401 (ce->ce_sdstunit > (sc->sc_counts[ce->ce_sdsttype] - 1))) 402 return (ENODEV); 403 404 /* 405 * Check the request against the changer's capabilities. 406 */ 407 if (((sc->sc_exchangemask[ce->ce_srctype] & 408 (1 << ce->ce_fdsttype)) == 0) || 409 ((sc->sc_exchangemask[ce->ce_fdsttype] & 410 (1 << ce->ce_sdsttype)) == 0)) 411 return (EINVAL); 412 413 /* 414 * Calculate the source and destination elements. 415 */ 416 src = sc->sc_firsts[ce->ce_srctype] + ce->ce_srcunit; 417 dst1 = sc->sc_firsts[ce->ce_fdsttype] + ce->ce_fdstunit; 418 dst2 = sc->sc_firsts[ce->ce_sdsttype] + ce->ce_sdstunit; 419 420 /* 421 * Build the SCSI command. 422 */ 423 xs = scsi_xs_get(sc->sc_link, 0); 424 if (xs == NULL) 425 return (ENOMEM); 426 xs->cmdlen = sizeof(*cmd); 427 xs->retries = CHRETRIES; 428 xs->timeout = 100000; 429 430 cmd = (struct scsi_exchange_medium *)xs->cmd; 431 cmd->opcode = EXCHANGE_MEDIUM; 432 _lto2b(sc->sc_picker, cmd->tea); 433 _lto2b(src, cmd->src); 434 _lto2b(dst1, cmd->fdst); 435 _lto2b(dst2, cmd->sdst); 436 if (ce->ce_flags & CE_INVERT1) 437 cmd->flags |= EXCHANGE_MEDIUM_INV1; 438 if (ce->ce_flags & CE_INVERT2) 439 cmd->flags |= EXCHANGE_MEDIUM_INV2; 440 441 error = scsi_xs_sync(xs); 442 scsi_xs_put(xs); 443 444 return (error); 445 } 446 447 int 448 ch_position(struct ch_softc *sc, struct changer_position *cp) 449 { 450 struct scsi_position_to_element *cmd; 451 struct scsi_xfer *xs; 452 int error; 453 u_int16_t dst; 454 455 /* 456 * Check arguments. 457 */ 458 if (cp->cp_type > CHET_DT) 459 return (EINVAL); 460 if (cp->cp_unit > (sc->sc_counts[cp->cp_type] - 1)) 461 return (ENODEV); 462 463 /* 464 * Calculate the destination element. 465 */ 466 dst = sc->sc_firsts[cp->cp_type] + cp->cp_unit; 467 468 /* 469 * Build the SCSI command. 470 */ 471 xs = scsi_xs_get(sc->sc_link, 0); 472 if (xs == NULL) 473 return (ENOMEM); 474 xs->cmdlen = sizeof(*cmd); 475 xs->retries = CHRETRIES; 476 xs->timeout = 100000; 477 478 cmd = (struct scsi_position_to_element *)xs->cmd; 479 cmd->opcode = POSITION_TO_ELEMENT; 480 _lto2b(sc->sc_picker, cmd->tea); 481 _lto2b(dst, cmd->dst); 482 if (cp->cp_flags & CP_INVERT) 483 cmd->flags |= POSITION_TO_ELEMENT_INVERT; 484 485 error = scsi_xs_sync(xs); 486 scsi_xs_put(xs); 487 488 return (error); 489 } 490 491 /* 492 * Copy a volume tag to a volume_tag struct, converting SCSI byte order 493 * to host native byte order in the volume serial number. The volume 494 * label as returned by the changer is transferred to user mode as 495 * nul-terminated string. Volume labels are truncated at the first 496 * space, as suggested by SCSI-2. 497 */ 498 static void 499 copy_voltag(struct changer_voltag *uvoltag, struct volume_tag *voltag) 500 { 501 int i; 502 503 for (i=0; i<CH_VOLTAG_MAXLEN; i++) { 504 char c = voltag->vif[i]; 505 if (c && c != ' ') 506 uvoltag->cv_volid[i] = c; 507 else 508 break; 509 } 510 uvoltag->cv_volid[i] = '\0'; 511 uvoltag->cv_serial = _2btol(voltag->vsn); 512 } 513 514 /* 515 * Copy an an element status descriptor to a user-mode 516 * changer_element_status structure. 517 */ 518 static void 519 copy_element_status(int flags, struct read_element_status_descriptor *desc, 520 struct changer_element_status *ces) 521 { 522 ces->ces_flags = desc->flags1; 523 524 if (flags & READ_ELEMENT_STATUS_PVOLTAG) 525 copy_voltag(&ces->ces_pvoltag, &desc->pvoltag); 526 if (flags & READ_ELEMENT_STATUS_AVOLTAG) 527 copy_voltag(&ces->ces_avoltag, &desc->avoltag); 528 } 529 530 /* 531 * Perform a READ ELEMENT STATUS on behalf of the user, and return to 532 * the user only the data the user is interested in (i.e. an array of 533 * changer_element_status structures) 534 */ 535 int 536 ch_usergetelemstatus(struct ch_softc *sc, 537 struct changer_element_status_request *cesr) 538 { 539 struct changer_element_status *user_data = NULL; 540 struct read_element_status_header *st_hdr; 541 struct read_element_status_page_header *pg_hdr; 542 caddr_t desc; 543 caddr_t data = NULL; 544 size_t size, desclen, udsize; 545 int chet = cesr->cesr_type; 546 int avail, i, error = 0; 547 int want_voltags = (cesr->cesr_flags & CESR_VOLTAGS) ? 1 : 0; 548 549 /* 550 * If there are no elements of the requested type in the changer, 551 * the request is invalid. 552 */ 553 if (sc->sc_counts[chet] == 0) 554 return (EINVAL); 555 556 /* 557 * Request one descriptor for the given element type. This 558 * is used to determine the size of the descriptor so that 559 * we can allocate enough storage for all of them. We assume 560 * that the first one can fit into 1k. 561 */ 562 size = 1024; 563 data = dma_alloc(size, PR_WAITOK); 564 error = ch_getelemstatus(sc, sc->sc_firsts[chet], 1, data, size, 565 want_voltags); 566 if (error) 567 goto done; 568 569 st_hdr = (struct read_element_status_header *)data; 570 pg_hdr = (struct read_element_status_page_header *) (st_hdr + 1); 571 desclen = _2btol(pg_hdr->edl); 572 573 dma_free(data, size); 574 575 /* 576 * Reallocate storage for descriptors and get them from the 577 * device. 578 */ 579 size = sizeof(struct read_element_status_header) + 580 sizeof(struct read_element_status_page_header) + 581 (desclen * sc->sc_counts[chet]); 582 data = dma_alloc(size, PR_WAITOK); 583 error = ch_getelemstatus(sc, sc->sc_firsts[chet], 584 sc->sc_counts[chet], data, size, want_voltags); 585 if (error) 586 goto done; 587 588 /* 589 * Fill in the user status array. 590 */ 591 st_hdr = (struct read_element_status_header *)data; 592 pg_hdr = (struct read_element_status_page_header *) (st_hdr + 1); 593 594 avail = _2btol(st_hdr->count); 595 if (avail != sc->sc_counts[chet]) { 596 error = EINVAL; 597 goto done; 598 } 599 udsize = avail * sizeof(struct changer_element_status); 600 601 user_data = malloc(udsize, M_DEVBUF, M_WAITOK | M_ZERO); 602 603 desc = (caddr_t)(pg_hdr + 1); 604 for (i = 0; i < avail; ++i) { 605 struct changer_element_status *ces = &(user_data[i]); 606 copy_element_status(pg_hdr->flags, 607 (struct read_element_status_descriptor *)desc, ces); 608 desc += desclen; 609 } 610 611 /* Copy array out to userspace. */ 612 error = copyout(user_data, cesr->cesr_data, udsize); 613 614 done: 615 if (data != NULL) 616 dma_free(data, size); 617 if (user_data != NULL) 618 free(user_data, M_DEVBUF); 619 return (error); 620 } 621 622 int 623 ch_getelemstatus(struct ch_softc *sc, int first, int count, caddr_t data, 624 size_t datalen, int voltag) 625 { 626 struct scsi_read_element_status *cmd; 627 struct scsi_xfer *xs; 628 int error; 629 630 /* 631 * Build SCSI command. 632 */ 633 xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN); 634 if (xs == NULL) 635 return (ENOMEM); 636 xs->cmdlen = sizeof(*cmd); 637 xs->data = data; 638 xs->datalen = datalen; 639 xs->retries = CHRETRIES; 640 xs->timeout = 100000; 641 642 cmd = (struct scsi_read_element_status *)xs->cmd; 643 cmd->opcode = READ_ELEMENT_STATUS; 644 _lto2b(first, cmd->sea); 645 _lto2b(count, cmd->count); 646 _lto3b(datalen, cmd->len); 647 if (voltag) 648 cmd->byte2 |= READ_ELEMENT_STATUS_VOLTAG; 649 650 error = scsi_xs_sync(xs); 651 scsi_xs_put(xs); 652 653 return (error); 654 } 655 656 /* 657 * Ask the device about itself and fill in the parameters in our 658 * softc. 659 */ 660 int 661 ch_get_params(struct ch_softc *sc, int flags) 662 { 663 union scsi_mode_sense_buf *data; 664 struct page_element_address_assignment *ea; 665 struct page_device_capabilities *cap; 666 int error, from; 667 u_int8_t *moves, *exchanges; 668 669 data = dma_alloc(sizeof(*data), PR_NOWAIT); 670 if (data == NULL) 671 return (ENOMEM); 672 673 /* 674 * Grab info from the element address assignment page (0x1d). 675 */ 676 error = scsi_do_mode_sense(sc->sc_link, 0x1d, data, 677 (void **)&ea, NULL, NULL, NULL, sizeof(*ea), flags, NULL); 678 if (error == 0 && ea == NULL) 679 error = EIO; 680 if (error != 0) { 681 #ifdef CHANGER_DEBUG 682 printf("%s: could not sense element address page\n", 683 sc->sc_dev.dv_xname); 684 #endif 685 dma_free(data, sizeof(*data)); 686 return (error); 687 } 688 689 sc->sc_firsts[CHET_MT] = _2btol(ea->mtea); 690 sc->sc_counts[CHET_MT] = _2btol(ea->nmte); 691 sc->sc_firsts[CHET_ST] = _2btol(ea->fsea); 692 sc->sc_counts[CHET_ST] = _2btol(ea->nse); 693 sc->sc_firsts[CHET_IE] = _2btol(ea->fieea); 694 sc->sc_counts[CHET_IE] = _2btol(ea->niee); 695 sc->sc_firsts[CHET_DT] = _2btol(ea->fdtea); 696 sc->sc_counts[CHET_DT] = _2btol(ea->ndte); 697 698 /* XXX Ask for transport geometry page. */ 699 700 /* 701 * Grab info from the capabilities page (0x1f). 702 */ 703 error = scsi_do_mode_sense(sc->sc_link, 0x1f, data, 704 (void **)&cap, NULL, NULL, NULL, sizeof(*cap), flags, NULL); 705 if (cap == NULL) 706 error = EIO; 707 if (error != 0) { 708 #ifdef CHANGER_DEBUG 709 printf("%s: could not sense capabilities page\n", 710 sc->sc_dev.dv_xname); 711 #endif 712 dma_free(data, sizeof(*data)); 713 return (error); 714 } 715 716 bzero(sc->sc_movemask, sizeof(sc->sc_movemask)); 717 bzero(sc->sc_exchangemask, sizeof(sc->sc_exchangemask)); 718 moves = &cap->move_from_mt; 719 exchanges = &cap->exchange_with_mt; 720 for (from = CHET_MT; from <= CHET_DT; ++from) { 721 sc->sc_movemask[from] = moves[from]; 722 sc->sc_exchangemask[from] = exchanges[from]; 723 } 724 725 sc->sc_link->flags |= SDEV_MEDIA_LOADED; 726 dma_free(data, sizeof(*data)); 727 return (0); 728 } 729 730 void 731 ch_get_quirks(struct ch_softc *sc, struct scsi_inquiry_data *inqbuf) 732 { 733 const struct chquirk *match; 734 int priority; 735 736 sc->sc_settledelay = 0; 737 738 match = (const struct chquirk *)scsi_inqmatch(inqbuf, 739 (caddr_t)chquirks, 740 sizeof(chquirks) / sizeof(chquirks[0]), 741 sizeof(chquirks[0]), &priority); 742 if (priority != 0) { 743 sc->sc_settledelay = match->cq_settledelay; 744 } 745 } 746 747 /* 748 * Look at the returned sense and act on the error and detirmine 749 * The unix error number to pass back... (0 = report no error) 750 * (-1 = continue processing) 751 */ 752 int 753 ch_interpret_sense(struct scsi_xfer *xs) 754 { 755 struct scsi_sense_data *sense = &xs->sense; 756 struct scsi_link *sc_link = xs->sc_link; 757 u_int8_t serr = sense->error_code & SSD_ERRCODE; 758 u_int8_t skey = sense->flags & SSD_KEY; 759 760 if (((sc_link->flags & SDEV_OPEN) == 0) || 761 (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED)) 762 return (scsi_interpret_sense(xs)); 763 764 switch (skey) { 765 766 /* 767 * We do custom processing in ch for the unit becoming ready case. 768 * in this case we do not allow xs->retries to be decremented 769 * only on the "Unit Becoming Ready" case. This is because tape 770 * changers report "Unit Becoming Ready" when they rescan their 771 * state (i.e. when the door got opened) and can take a long time 772 * for large units. Rather than having a massive timeout for 773 * all operations (which would cause other problems) we allow 774 * changers to wait (but be interruptable with Ctrl-C) forever 775 * as long as they are reporting that they are becoming ready. 776 * all other cases are handled as per the default. 777 */ 778 case SKEY_NOT_READY: 779 if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0) 780 return (0); 781 switch (ASC_ASCQ(sense)) { 782 case SENSE_NOT_READY_BECOMING_READY: 783 SC_DEBUG(sc_link, SDEV_DB1, ("not ready: busy (%#x)\n", 784 sense->add_sense_code_qual)); 785 /* don't count this as a retry */ 786 xs->retries++; 787 return (scsi_delay(xs, 1)); 788 default: 789 return (scsi_interpret_sense(xs)); 790 } 791 default: 792 return (scsi_interpret_sense(xs)); 793 } 794 } 795