1 /* 2 * Implementation of SCSI Sequential Access Peripheral driver for CAM. 3 * 4 * Copyright (c) 1997 Justin T. Gibbs 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions, and the following disclaimer, 12 * without modification, immediately at the beginning of the file. 13 * 2. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $Id: scsi_sa.c,v 1.3 1998/10/15 17:46:26 ken Exp $ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/queue.h> 33 #ifdef KERNEL 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #endif 37 #include <sys/types.h> 38 #include <sys/buf.h> 39 #include <sys/malloc.h> 40 #include <sys/mtio.h> 41 #include <sys/conf.h> 42 #include <sys/buf.h> 43 #include <sys/devicestat.h> 44 #include <machine/limits.h> 45 46 #ifndef KERNEL 47 #include <stdio.h> 48 #include <string.h> 49 #endif 50 51 #include <cam/cam.h> 52 #include <cam/cam_ccb.h> 53 #include <cam/cam_extend.h> 54 #include <cam/cam_periph.h> 55 #include <cam/cam_xpt_periph.h> 56 #include <cam/cam_debug.h> 57 58 #include <cam/scsi/scsi_all.h> 59 #include <cam/scsi/scsi_message.h> 60 #include <cam/scsi/scsi_sa.h> 61 62 #ifdef KERNEL 63 64 #include <opt_sa.h> 65 66 #ifndef SA_SPACE_TIMEOUT 67 #define SA_SPACE_TIMEOUT 1 * 60 68 #endif 69 #ifndef SA_REWIND_TIMEOUT 70 #define SA_REWIND_TIMEOUT 2 * 60 71 #endif 72 #ifndef SA_ERASE_TIMEOUT 73 #define SA_ERASE_TIMEOUT 4 * 60 74 #endif 75 76 #define SAUNIT(DEV) ((minor(DEV)&0xF0) >> 4) /* 4 bit unit. */ 77 #define SASETUNIT(DEV, U) makedev(major(DEV), ((U) << 4)) 78 79 typedef enum { 80 SA_STATE_NORMAL 81 } sa_state; 82 83 typedef enum { 84 SA_CCB_BUFFER_IO, 85 SA_CCB_WAITING 86 } sa_ccb_types; 87 88 #define ccb_type ppriv_field0 89 #define ccb_bp ppriv_ptr1 90 91 typedef enum { 92 SA_FLAG_OPEN = 0x0001, 93 SA_FLAG_FIXED = 0x0002, 94 SA_FLAG_TAPE_LOCKED = 0x0004, 95 SA_FLAG_TAPE_MOUNTED = 0x0008, 96 SA_FLAG_TAPE_WP = 0x0010, 97 SA_FLAG_TAPE_WRITTEN = 0x0020, 98 SA_FLAG_2FM_AT_EOD = 0x0040, 99 SA_FLAG_EOM_PENDING = 0x0080, 100 SA_FLAG_EIO_PENDING = 0x0100, 101 SA_FLAG_EOF_PENDING = 0x0200, 102 SA_FLAG_ERR_PENDING = (SA_FLAG_EOM_PENDING|SA_FLAG_EIO_PENDING| 103 SA_FLAG_EOF_PENDING), 104 SA_FLAG_INVALID = 0x0400, 105 SA_FLAG_COMP_ENABLED = 0x0800, 106 SA_FLAG_COMP_UNSUPP = 0x1000 107 } sa_flags; 108 109 typedef enum { 110 SA_MODE_REWIND = 0x00, 111 SA_MODE_NOREWIND = 0x01, 112 SA_MODE_OFFLINE = 0x02 113 } sa_mode; 114 115 typedef enum { 116 SA_PARAM_NONE = 0x00, 117 SA_PARAM_BLOCKSIZE = 0x01, 118 SA_PARAM_DENSITY = 0x02, 119 SA_PARAM_COMPRESSION = 0x04, 120 SA_PARAM_BUFF_MODE = 0x08, 121 SA_PARAM_NUMBLOCKS = 0x10, 122 SA_PARAM_WP = 0x20, 123 SA_PARAM_SPEED = 0x40, 124 SA_PARAM_ALL = 0x7f 125 } sa_params; 126 127 typedef enum { 128 SA_QUIRK_NONE = 0x00, 129 SA_QUIRK_NOCOMP = 0x01 130 } sa_quirks; 131 132 struct sa_softc { 133 sa_state state; 134 sa_flags flags; 135 sa_quirks quirks; 136 struct buf_queue_head buf_queue; 137 struct devstat device_stats; 138 int blk_gran; 139 int blk_mask; 140 int blk_shift; 141 u_int32_t max_blk; 142 u_int32_t min_blk; 143 u_int8_t media_density; 144 u_int32_t media_blksize; 145 u_int32_t media_numblks; 146 u_int32_t comp_algorithm; 147 u_int32_t saved_comp_algorithm; 148 u_int8_t speed; 149 int buffer_mode; 150 int filemarks; 151 union ccb saved_ccb; 152 }; 153 154 struct sa_quirk_entry { 155 struct scsi_inquiry_pattern inq_pat; 156 sa_quirks quirks; 157 }; 158 159 static struct sa_quirk_entry sa_quirk_table[] = 160 { 161 { 162 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE", 163 "Python 25601*", "*"}, /*quirks*/SA_QUIRK_NOCOMP 164 } 165 }; 166 167 static d_open_t saopen; 168 static d_read_t saread; 169 static d_write_t sawrite; 170 static d_close_t saclose; 171 static d_strategy_t sastrategy; 172 static d_ioctl_t saioctl; 173 static periph_init_t sainit; 174 static periph_ctor_t saregister; 175 static periph_oninv_t saoninvalidate; 176 static periph_dtor_t sacleanup; 177 static periph_start_t sastart; 178 static void saasync(void *callback_arg, u_int32_t code, 179 struct cam_path *path, void *arg); 180 static void sadone(struct cam_periph *periph, 181 union ccb *start_ccb); 182 static int saerror(union ccb *ccb, u_int32_t cam_flags, 183 u_int32_t sense_flags); 184 static int sacheckeod(struct cam_periph *periph); 185 static int sagetparams(struct cam_periph *periph, 186 sa_params params_to_get, 187 u_int32_t *blocksize, u_int8_t *density, 188 u_int32_t *numblocks, int *buff_mode, 189 u_int8_t *write_protect, u_int8_t *speed, 190 int *comp_supported, int *comp_enabled, 191 u_int32_t *comp_algorithm, 192 struct scsi_data_compression_page *comp_page); 193 static int sasetparams(struct cam_periph *periph, 194 sa_params params_to_set, 195 u_int32_t blocksize, u_int8_t density, 196 u_int32_t comp_algorithm); 197 static void saprevent(struct cam_periph *periph, int action); 198 static int sarewind(struct cam_periph *periph); 199 static int saspace(struct cam_periph *periph, int count, 200 scsi_space_code code); 201 static int samount(struct cam_periph *periph); 202 static int saretension(struct cam_periph *periph); 203 static int sareservereleaseunit(struct cam_periph *periph, 204 int reserve); 205 static int saloadunload(struct cam_periph *periph, int load); 206 static int saerase(struct cam_periph *periph, int longerase); 207 static int sawritefilemarks(struct cam_periph *periph, 208 int nmarks, int setmarks); 209 210 static struct periph_driver sadriver = 211 { 212 sainit, "sa", 213 TAILQ_HEAD_INITIALIZER(sadriver.units), /* generation */ 0 214 }; 215 216 DATA_SET(periphdriver_set, sadriver); 217 218 #define SAUNIT(DEV) ((minor(DEV)&0xF0) >> 4) /* 4 bit unit. */ 219 #define SASETUNIT(DEV, U) makedev(major(DEV), ((U) << 4)) 220 221 #define SAMODE(z) ((minor(z) & 0x03)) 222 #define SADENSITY(z) (((minor(z) >> 2) & 0x03)) 223 224 /* For 2.2-stable support */ 225 #ifndef D_TAPE 226 #define D_TAPE 0 227 #endif 228 229 #define CTLMODE 3 230 #define SA_CDEV_MAJOR 14 231 #define SA_BDEV_MAJOR 5 232 233 static struct cdevsw sa_cdevsw = 234 { 235 /*d_open*/ saopen, 236 /*d_close*/ saclose, 237 /*d_read*/ saread, 238 /*d_write*/ sawrite, 239 /*d_ioctl*/ saioctl, 240 /*d_stop*/ nostop, 241 /*d_reset*/ noreset, 242 /*d_devtotty*/ nodevtotty, 243 /*d_poll*/ seltrue, 244 /*d_mmap*/ nommap, 245 /*d_strategy*/ sastrategy, 246 /*d_name*/ "sa", 247 /*d_spare*/ NULL, 248 /*d_maj*/ -1, 249 /*d_dump*/ nodump, 250 /*d_psize*/ nopsize, 251 /*d_flags*/ D_TAPE, 252 /*d_maxio*/ 0, 253 /*b_maj*/ -1 254 }; 255 256 static struct extend_array *saperiphs; 257 258 static int 259 saopen(dev_t dev, int flags, int fmt, struct proc *p) 260 { 261 struct cam_periph *periph; 262 struct sa_softc *softc; 263 int unit; 264 int mode; 265 int density; 266 int error; 267 int s; 268 269 unit = SAUNIT(dev); 270 mode = SAMODE(dev); 271 density = SADENSITY(dev); 272 273 periph = cam_extend_get(saperiphs, unit); 274 if (periph == NULL) 275 return (ENXIO); 276 277 softc = (struct sa_softc *)periph->softc; 278 279 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 280 ("saaopen: dev=0x%x (unit %d , mode %d, density %d)\n", dev, 281 unit, mode, density)); 282 283 s = splsoftcam(); 284 if (softc->flags & SA_FLAG_INVALID) { 285 splx(s); 286 return(ENXIO); 287 } 288 splx(s); 289 290 if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) { 291 return (error); /* error code from tsleep */ 292 } 293 294 if ((softc->flags & SA_FLAG_OPEN) == 0) { 295 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 296 return(ENXIO); 297 298 if ((error = sareservereleaseunit(periph, TRUE)) != 0) { 299 cam_periph_unlock(periph); 300 cam_periph_release(periph); 301 return(error); 302 } 303 } 304 305 if (error == 0) { 306 if ((softc->flags & SA_FLAG_OPEN) != 0) { 307 error = EBUSY; 308 } 309 310 if (error == 0) { 311 error = samount(periph); 312 } 313 /* Perform other checking... */ 314 } 315 316 if (error == 0) { 317 saprevent(periph, PR_PREVENT); 318 softc->flags |= SA_FLAG_OPEN; 319 } 320 321 cam_periph_unlock(periph); 322 return (error); 323 } 324 325 static int 326 saclose(dev_t dev, int flag, int fmt, struct proc *p) 327 { 328 struct cam_periph *periph; 329 struct sa_softc *softc; 330 int unit; 331 int mode; 332 int error; 333 334 unit = SAUNIT(dev); 335 mode = SAMODE(dev); 336 periph = cam_extend_get(saperiphs, unit); 337 if (periph == NULL) 338 return (ENXIO); 339 340 softc = (struct sa_softc *)periph->softc; 341 342 if ((error = cam_periph_lock(periph, PRIBIO)) != 0) { 343 return (error); /* error code from tsleep */ 344 } 345 346 sacheckeod(periph); 347 348 saprevent(periph, PR_ALLOW); 349 350 switch (mode) { 351 case SA_MODE_REWIND: 352 sarewind(periph); 353 break; 354 case SA_MODE_OFFLINE: 355 sarewind(periph); 356 saloadunload(periph, /*load*/FALSE); 357 break; 358 case SA_MODE_NOREWIND: 359 default: 360 break; 361 } 362 363 softc->flags &= ~SA_FLAG_OPEN; 364 365 /* release the device */ 366 sareservereleaseunit(periph, FALSE); 367 368 cam_periph_unlock(periph); 369 cam_periph_release(periph); 370 371 return (0); 372 } 373 374 static int 375 saread(dev_t dev, struct uio *uio, int ioflag) 376 { 377 return(physio(sastrategy, NULL, dev, 1, minphys, uio)); 378 } 379 380 static int 381 sawrite(dev_t dev, struct uio *uio, int ioflag) 382 { 383 return(physio(sastrategy, NULL, dev, 0, minphys, uio)); 384 } 385 386 /* 387 * Actually translate the requested transfer into one the physical driver 388 * can understand. The transfer is described by a buf and will include 389 * only one physical transfer. 390 */ 391 static void 392 sastrategy(struct buf *bp) 393 { 394 struct cam_periph *periph; 395 struct sa_softc *softc; 396 u_int unit; 397 int s; 398 399 unit = SAUNIT(bp->b_dev); 400 periph = cam_extend_get(saperiphs, unit); 401 if (periph == NULL) { 402 bp->b_error = ENXIO; 403 goto bad; 404 } 405 softc = (struct sa_softc *)periph->softc; 406 407 s = splsoftcam(); 408 409 if (softc->flags & SA_FLAG_INVALID) { 410 splx(s); 411 bp->b_error = ENXIO; 412 goto bad; 413 } 414 415 splx(s); 416 417 /* 418 * If it's a null transfer, return immediatly 419 */ 420 if (bp->b_bcount == 0) 421 goto done; 422 423 /* valid request? */ 424 if (softc->flags & SA_FLAG_FIXED) { 425 /* 426 * Fixed block device. The byte count must 427 * be a multiple of our block size. 428 */ 429 if (((softc->blk_mask != ~0) 430 && ((bp->b_bcount & softc->blk_mask) != 0)) 431 || ((softc->blk_mask == ~0) 432 && ((bp->b_bcount % softc->min_blk) != 0))) { 433 xpt_print_path(periph->path); 434 printf("Invalid request. Fixed block device " 435 "requests must be a multiple " 436 "of %d bytes\n", softc->min_blk); 437 bp->b_error = EINVAL; 438 goto bad; 439 } 440 } else if ((bp->b_bcount > softc->max_blk) 441 || (bp->b_bcount < softc->min_blk) 442 || (bp->b_bcount & softc->blk_mask) != 0) { 443 444 xpt_print_path(periph->path); 445 printf("Invalid request. Variable block device " 446 "requests must be "); 447 if (softc->blk_mask != 0) { 448 printf("a multiple of %d ", 449 (0x1 << softc->blk_gran)); 450 } 451 printf("between %d and %d bytes\n", 452 softc->min_blk, softc->max_blk); 453 bp->b_error = EINVAL; 454 goto bad; 455 } 456 457 /* 458 * Mask interrupts so that the pack cannot be invalidated until 459 * after we are in the queue. Otherwise, we might not properly 460 * clean up one of the buffers. 461 */ 462 s = splbio(); 463 464 /* 465 * Place it in the queue of disk activities for this disk 466 */ 467 bufq_insert_tail(&softc->buf_queue, bp); 468 469 splx(s); 470 471 /* 472 * Schedule ourselves for performing the work. 473 */ 474 xpt_schedule(periph, /* XXX priority */1); 475 476 return; 477 bad: 478 bp->b_flags |= B_ERROR; 479 done: 480 481 /* 482 * Correctly set the buf to indicate a completed xfer 483 */ 484 bp->b_resid = bp->b_bcount; 485 biodone(bp); 486 } 487 488 static int 489 saioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) 490 { 491 struct cam_periph *periph; 492 struct sa_softc *softc; 493 int unit; 494 int mode; 495 int density; 496 int error; 497 498 unit = SAUNIT(dev); 499 mode = SAMODE(dev); 500 density = SADENSITY(dev); 501 502 periph = cam_extend_get(saperiphs, unit); 503 if (periph == NULL) 504 return (ENXIO); 505 506 softc = (struct sa_softc *)periph->softc; 507 508 /* 509 * Find the device that the user is talking about 510 */ 511 switch (cmd) { 512 case MTIOCGET: 513 { 514 struct mtget *g = (struct mtget *)arg; 515 516 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 517 ("saioctl: MTIOGET\n")); 518 519 bzero(g, sizeof(struct mtget)); 520 g->mt_type = 0x7; /* Ultrix compat *//*? */ 521 g->mt_density = softc->media_density; 522 g->mt_blksiz = softc->media_blksize; 523 if (softc->flags & SA_FLAG_COMP_UNSUPP) { 524 g->mt_comp = MT_COMP_UNSUPP; 525 g->mt_comp0 = MT_COMP_UNSUPP; 526 g->mt_comp1 = MT_COMP_UNSUPP; 527 g->mt_comp2 = MT_COMP_UNSUPP; 528 g->mt_comp3 = MT_COMP_UNSUPP; 529 } else if ((softc->flags & SA_FLAG_COMP_ENABLED) == 0) { 530 g->mt_comp = MT_COMP_DISABLED; 531 g->mt_comp0 = MT_COMP_DISABLED; 532 g->mt_comp1 = MT_COMP_DISABLED; 533 g->mt_comp2 = MT_COMP_DISABLED; 534 g->mt_comp3 = MT_COMP_DISABLED; 535 } else { 536 g->mt_comp = softc->comp_algorithm; 537 g->mt_comp0 = softc->comp_algorithm; 538 g->mt_comp1 = softc->comp_algorithm; 539 g->mt_comp2 = softc->comp_algorithm; 540 g->mt_comp3 = softc->comp_algorithm; 541 } 542 g->mt_density0 = softc->media_density; 543 g->mt_density1 = softc->media_density; 544 g->mt_density2 = softc->media_density; 545 g->mt_density3 = softc->media_density; 546 g->mt_blksiz0 = softc->media_blksize; 547 g->mt_blksiz1 = softc->media_blksize; 548 g->mt_blksiz2 = softc->media_blksize; 549 g->mt_blksiz3 = softc->media_blksize; 550 error = 0; 551 break; 552 } 553 case MTIOCTOP: 554 { 555 struct mtop *mt; 556 int count; 557 558 mt = (struct mtop *)arg; 559 560 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 561 ("saioctl: op=0x%x count=0x%x\n", 562 mt->mt_op, mt->mt_count)); 563 564 count = mt->mt_count; 565 switch (mt->mt_op) { 566 case MTWEOF: /* write an end-of-file record */ 567 error = sawritefilemarks(periph, count, 568 /*setmarks*/FALSE); 569 break; 570 case MTBSR: /* backward space record */ 571 case MTFSR: /* forward space record */ 572 case MTBSF: /* backward space file */ 573 case MTFSF: /* forward space file */ 574 case MTEOD: /* space to end of recorded medium */ 575 { 576 int nmarks; 577 scsi_space_code spaceop; 578 579 nmarks = softc->filemarks; 580 error = sacheckeod(periph); 581 nmarks -= softc->filemarks; 582 583 if ((mt->mt_op == MTBSR) || (mt->mt_op == MTBSF)) 584 count = -count; 585 586 if ((mt->mt_op == MTBSF) || (mt->mt_op == MTFSF)) 587 spaceop = SS_FILEMARKS; 588 else if ((mt->mt_op == MTBSR) || (mt->mt_op == MTFSR)) 589 spaceop = SS_BLOCKS; 590 else { 591 spaceop = SS_EOD; 592 count = 0; 593 nmarks = 0; 594 } 595 596 nmarks = softc->filemarks; 597 error = sacheckeod(periph); 598 nmarks -= softc->filemarks; 599 if (error == 0) 600 error = saspace(periph, count - nmarks, 601 spaceop); 602 break; 603 } 604 case MTREW: /* rewind */ 605 error = sarewind(periph); 606 break; 607 case MTERASE: /* erase */ 608 error = saerase(periph, count); 609 break; 610 case MTRETENS: /* re-tension tape */ 611 error = saretension(periph); 612 break; 613 case MTOFFL: /* rewind and put the drive offline */ 614 /* 615 * Be sure to allow media removal before 616 * attempting the eject. 617 */ 618 saprevent(periph, PR_ALLOW); 619 error = sarewind(periph); 620 621 if (error == 0) 622 error = saloadunload(periph, /*load*/FALSE); 623 else 624 break; 625 626 /* XXX KDM */ 627 softc->flags &= ~SA_FLAG_TAPE_LOCKED; 628 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 629 break; 630 case MTNOP: /* no operation, sets status only */ 631 case MTCACHE: /* enable controller cache */ 632 case MTNOCACHE: /* disable controller cache */ 633 error = 0; 634 break; 635 case MTSETBSIZ: /* Set block size for device */ 636 637 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, count, 638 0, 0); 639 break; 640 case MTSETDNSTY: /* Set density for device and mode */ 641 if (count > UCHAR_MAX) { 642 error = EINVAL; 643 break; 644 } else { 645 error = sasetparams(periph, SA_PARAM_DENSITY, 646 0, count, 0); 647 } 648 break; 649 case MTCOMP: /* enable compression */ 650 /* 651 * Some devices don't support compression, and 652 * don't like it if you ask them for the 653 * compression page. 654 */ 655 if ((softc->quirks & SA_QUIRK_NOCOMP) 656 || (softc->flags & SA_FLAG_COMP_UNSUPP)) { 657 error = ENODEV; 658 break; 659 } 660 error = sasetparams(periph, SA_PARAM_COMPRESSION, 661 0, 0, count); 662 break; 663 default: 664 error = EINVAL; 665 } 666 break; 667 } 668 case MTIOCIEOT: 669 case MTIOCEEOT: 670 error = 0; 671 break; 672 default: 673 error = cam_periph_ioctl(periph, cmd, arg, saerror); 674 break; 675 } 676 return (error); 677 } 678 679 static void 680 sainit(void) 681 { 682 cam_status status; 683 struct cam_path *path; 684 685 /* 686 * Create our extend array for storing the devices we attach to. 687 */ 688 saperiphs = cam_extend_new(); 689 if (saperiphs == NULL) { 690 printf("sa: Failed to alloc extend array!\n"); 691 return; 692 } 693 694 /* 695 * Install a global async callback. 696 */ 697 status = xpt_create_path(&path, NULL, CAM_XPT_PATH_ID, 698 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 699 700 if (status == CAM_REQ_CMP) { 701 /* Register the async callbacks of interrest */ 702 struct ccb_setasync csa; /* 703 * This is an immediate CCB, 704 * so using the stack is OK 705 */ 706 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 707 csa.ccb_h.func_code = XPT_SASYNC_CB; 708 csa.event_enable = AC_FOUND_DEVICE; 709 csa.callback = saasync; 710 csa.callback_arg = NULL; 711 xpt_action((union ccb *)&csa); 712 status = csa.ccb_h.status; 713 xpt_free_path(path); 714 } 715 716 if (status != CAM_REQ_CMP) { 717 printf("sa: Failed to attach master async callback " 718 "due to status 0x%x!\n", status); 719 } else { 720 /* If we were successfull, register our devsw */ 721 cdevsw_add_generic(SA_BDEV_MAJOR, SA_CDEV_MAJOR, &sa_cdevsw); 722 } 723 } 724 725 static void 726 saoninvalidate(struct cam_periph *periph) 727 { 728 struct sa_softc *softc; 729 struct buf *q_bp; 730 struct ccb_setasync csa; 731 int s; 732 733 softc = (struct sa_softc *)periph->softc; 734 735 /* 736 * De-register any async callbacks. 737 */ 738 xpt_setup_ccb(&csa.ccb_h, periph->path, 739 /* priority */ 5); 740 csa.ccb_h.func_code = XPT_SASYNC_CB; 741 csa.event_enable = 0; 742 csa.callback = saasync; 743 csa.callback_arg = periph; 744 xpt_action((union ccb *)&csa); 745 746 softc->flags |= SA_FLAG_INVALID; 747 748 /* 749 * Although the oninvalidate() routines are always called at 750 * splsoftcam, we need to be at splbio() here to keep the buffer 751 * queue from being modified while we traverse it. 752 */ 753 s = splbio(); 754 755 /* 756 * Return all queued I/O with ENXIO. 757 * XXX Handle any transactions queued to the card 758 * with XPT_ABORT_CCB. 759 */ 760 while ((q_bp = bufq_first(&softc->buf_queue)) != NULL){ 761 bufq_remove(&softc->buf_queue, q_bp); 762 q_bp->b_resid = q_bp->b_bcount; 763 q_bp->b_error = ENXIO; 764 q_bp->b_flags |= B_ERROR; 765 biodone(q_bp); 766 } 767 splx(s); 768 769 xpt_print_path(periph->path); 770 printf("lost device\n"); 771 772 } 773 774 static void 775 sacleanup(struct cam_periph *periph) 776 { 777 struct sa_softc *softc; 778 779 softc = (struct sa_softc *)periph->softc; 780 781 devstat_remove_entry(&softc->device_stats); 782 cam_extend_release(saperiphs, periph->unit_number); 783 xpt_print_path(periph->path); 784 printf("removing device entry\n"); 785 free(softc, M_DEVBUF); 786 } 787 788 static void 789 saasync(void *callback_arg, u_int32_t code, 790 struct cam_path *path, void *arg) 791 { 792 struct cam_periph *periph; 793 794 periph = (struct cam_periph *)callback_arg; 795 switch (code) { 796 case AC_FOUND_DEVICE: 797 { 798 struct ccb_getdev *cgd; 799 cam_status status; 800 801 cgd = (struct ccb_getdev *)arg; 802 803 if (cgd->pd_type != T_SEQUENTIAL) 804 break; 805 806 /* 807 * Allocate a peripheral instance for 808 * this device and start the probe 809 * process. 810 */ 811 status = cam_periph_alloc(saregister, saoninvalidate, 812 sacleanup, sastart, 813 "sa", CAM_PERIPH_BIO, cgd->ccb_h.path, 814 saasync, AC_FOUND_DEVICE, cgd); 815 816 if (status != CAM_REQ_CMP 817 && status != CAM_REQ_INPROG) 818 printf("saasync: Unable to probe new device " 819 "due to status 0x%x\n", status); 820 break; 821 } 822 case AC_LOST_DEVICE: 823 cam_periph_invalidate(periph); 824 break; 825 case AC_TRANSFER_NEG: 826 case AC_SENT_BDR: 827 case AC_SCSI_AEN: 828 case AC_UNSOL_RESEL: 829 case AC_BUS_RESET: 830 default: 831 break; 832 } 833 } 834 835 static cam_status 836 saregister(struct cam_periph *periph, void *arg) 837 { 838 struct sa_softc *softc; 839 struct ccb_setasync csa; 840 struct ccb_getdev *cgd; 841 caddr_t match; 842 843 cgd = (struct ccb_getdev *)arg; 844 if (periph == NULL) { 845 printf("saregister: periph was NULL!!\n"); 846 return(CAM_REQ_CMP_ERR); 847 } 848 849 if (cgd == NULL) { 850 printf("saregister: no getdev CCB, can't register device\n"); 851 return(CAM_REQ_CMP_ERR); 852 } 853 854 softc = (struct sa_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT); 855 856 if (softc == NULL) { 857 printf("saregister: Unable to probe new device. " 858 "Unable to allocate softc\n"); 859 return(CAM_REQ_CMP_ERR); 860 } 861 862 bzero(softc, sizeof(*softc)); 863 softc->state = SA_STATE_NORMAL; 864 bufq_init(&softc->buf_queue); 865 periph->softc = softc; 866 cam_extend_set(saperiphs, periph->unit_number, periph); 867 868 /* 869 * See if this device has any quirks. 870 */ 871 match = cam_quirkmatch((caddr_t)&cgd->inq_data, 872 (caddr_t)sa_quirk_table, 873 sizeof(sa_quirk_table)/sizeof(*sa_quirk_table), 874 sizeof(*sa_quirk_table), scsi_inquiry_match); 875 876 if (match != NULL) 877 softc->quirks = ((struct sa_quirk_entry *)match)->quirks; 878 else 879 softc->quirks = SA_QUIRK_NONE; 880 881 /* 882 * The SA driver supports a blocksize, but we don't know the 883 * blocksize until we sense the media. So, set a flag to 884 * indicate that the blocksize is unavailable right now. 885 * We'll clear the flag as soon as we've done a read capacity. 886 */ 887 devstat_add_entry(&softc->device_stats, "sa", 888 periph->unit_number, 0, 889 DEVSTAT_BS_UNAVAILABLE, 890 cgd->pd_type | DEVSTAT_TYPE_IF_SCSI); 891 892 /* 893 * Add an async callback so that we get 894 * notified if this device goes away. 895 */ 896 xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5); 897 csa.ccb_h.func_code = XPT_SASYNC_CB; 898 csa.event_enable = AC_LOST_DEVICE; 899 csa.callback = saasync; 900 csa.callback_arg = periph; 901 xpt_action((union ccb *)&csa); 902 903 xpt_announce_periph(periph, NULL); 904 905 return(CAM_REQ_CMP); 906 } 907 908 static void 909 sastart(struct cam_periph *periph, union ccb *start_ccb) 910 { 911 struct sa_softc *softc; 912 913 softc = (struct sa_softc *)periph->softc; 914 915 916 switch (softc->state) { 917 case SA_STATE_NORMAL: 918 { 919 /* Pull a buffer from the queue and get going on it */ 920 struct buf *bp; 921 int s; 922 923 /* 924 * See if there is a buf with work for us to do.. 925 */ 926 s = splbio(); 927 bp = bufq_first(&softc->buf_queue); 928 if (periph->immediate_priority <= periph->pinfo.priority) { 929 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, 930 ("queuing for immediate ccb\n")); 931 start_ccb->ccb_h.ccb_type = SA_CCB_WAITING; 932 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 933 periph_links.sle); 934 periph->immediate_priority = CAM_PRIORITY_NONE; 935 splx(s); 936 wakeup(&periph->ccb_list); 937 } else if (bp == NULL) { 938 splx(s); 939 xpt_release_ccb(start_ccb); 940 } else if ((softc->flags & SA_FLAG_ERR_PENDING) != 0) { 941 942 bufq_remove(&softc->buf_queue, bp); 943 bp->b_resid = bp->b_bcount; 944 bp->b_flags |= B_ERROR; 945 if ((softc->flags & SA_FLAG_EOM_PENDING) != 0) { 946 if ((bp->b_flags & B_READ) == 0) 947 bp->b_error = ENOSPC; 948 } 949 if ((softc->flags & SA_FLAG_EIO_PENDING) != 0) { 950 bp->b_error = EIO; 951 } 952 softc->flags &= ~SA_FLAG_ERR_PENDING; 953 bp = bufq_first(&softc->buf_queue); 954 splx(s); 955 biodone(bp); 956 } else { 957 u_int32_t length; 958 959 bufq_remove(&softc->buf_queue, bp); 960 961 if ((softc->flags & SA_FLAG_FIXED) != 0) { 962 if (softc->blk_shift != 0) { 963 length = 964 bp->b_bcount >> softc->blk_shift; 965 } else { 966 length = 967 bp->b_bcount / softc->min_blk; 968 } 969 } else { 970 length = bp->b_bcount; 971 } 972 973 devstat_start_transaction(&softc->device_stats); 974 975 /* 976 * XXX - Perhaps we should... 977 * suppress illegal length indication if we are 978 * running in variable block mode so that we don't 979 * have to request sense every time our requested 980 * block size is larger than the written block. 981 * The residual information from the ccb allows 982 * us to identify this situation anyway. The only 983 * problem with this is that we will not get 984 * information about blocks that are larger than 985 * our read buffer unless we set the block size 986 * in the mode page to something other than 0. 987 */ 988 scsi_sa_read_write(&start_ccb->csio, 989 /*retries*/4, 990 sadone, 991 MSG_SIMPLE_Q_TAG, 992 bp->b_flags & B_READ, 993 /*SILI*/FALSE, 994 softc->flags & SA_FLAG_FIXED, 995 length, 996 bp->b_data, 997 bp->b_bcount, 998 SSD_FULL_SIZE, 999 120 * 60 * 1000); /* 2min */ 1000 start_ccb->ccb_h.ccb_type = SA_CCB_BUFFER_IO; 1001 start_ccb->ccb_h.ccb_bp = bp; 1002 bp = bufq_first(&softc->buf_queue); 1003 splx(s); 1004 1005 xpt_action(start_ccb); 1006 } 1007 1008 if (bp != NULL) { 1009 /* Have more work to do, so ensure we stay scheduled */ 1010 xpt_schedule(periph, /* XXX priority */1); 1011 } 1012 break; 1013 } 1014 } 1015 } 1016 1017 1018 static void 1019 sadone(struct cam_periph *periph, union ccb *done_ccb) 1020 { 1021 struct sa_softc *softc; 1022 struct ccb_scsiio *csio; 1023 1024 softc = (struct sa_softc *)periph->softc; 1025 csio = &done_ccb->csio; 1026 switch (csio->ccb_h.ccb_type) { 1027 case SA_CCB_BUFFER_IO: 1028 { 1029 struct buf *bp; 1030 int error; 1031 1032 bp = (struct buf *)done_ccb->ccb_h.ccb_bp; 1033 error = 0; 1034 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1035 1036 if ((error = saerror(done_ccb, 0, 0)) == ERESTART) { 1037 /* 1038 * A retry was scheuled, so 1039 * just return. 1040 */ 1041 return; 1042 } 1043 } 1044 1045 if (error == EIO) { 1046 int s; 1047 struct buf *q_bp; 1048 1049 /* 1050 * Catastrophic error. Mark our pack as invalid, 1051 * return all queued I/O with EIO, and unfreeze 1052 * our queue so that future transactions that 1053 * attempt to fix this problem can get to the 1054 * device. 1055 * 1056 */ 1057 1058 s = splbio(); 1059 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 1060 1061 while ((q_bp = bufq_first(&softc->buf_queue)) != NULL) { 1062 bufq_remove(&softc->buf_queue, q_bp); 1063 q_bp->b_resid = q_bp->b_bcount; 1064 q_bp->b_error = EIO; 1065 q_bp->b_flags |= B_ERROR; 1066 biodone(q_bp); 1067 } 1068 splx(s); 1069 } 1070 if (error != 0) { 1071 bp->b_resid = bp->b_bcount; 1072 bp->b_error = error; 1073 bp->b_flags |= B_ERROR; 1074 cam_release_devq(done_ccb->ccb_h.path, 1075 /*relsim_flags*/0, 1076 /*reduction*/0, 1077 /*timeout*/0, 1078 /*getcount_only*/0); 1079 } else { 1080 bp->b_resid = csio->resid; 1081 bp->b_error = 0; 1082 if (csio->resid != 0) { 1083 bp->b_flags |= B_ERROR; 1084 } 1085 if ((bp->b_flags & B_READ) == 0) { 1086 softc->flags |= SA_FLAG_TAPE_WRITTEN; 1087 softc->filemarks = 0; 1088 } 1089 } 1090 1091 devstat_end_transaction(&softc->device_stats, 1092 bp->b_bcount - bp->b_resid, 1093 done_ccb->csio.tag_action & 0xf, 1094 (bp->b_flags & B_READ) ? DEVSTAT_READ 1095 : DEVSTAT_WRITE); 1096 biodone(bp); 1097 break; 1098 } 1099 case SA_CCB_WAITING: 1100 { 1101 /* Caller will release the CCB */ 1102 wakeup(&done_ccb->ccb_h.cbfcnp); 1103 return; 1104 } 1105 } 1106 xpt_release_ccb(done_ccb); 1107 } 1108 1109 static int 1110 samount(struct cam_periph *periph) 1111 { 1112 struct sa_softc *softc; 1113 union ccb *ccb; 1114 struct ccb_scsiio *csio; 1115 int error; 1116 1117 softc = (struct sa_softc *)periph->softc; 1118 ccb = cam_periph_getccb(periph, /* priority */1); 1119 csio = &ccb->csio; 1120 error = 0; 1121 1122 /* 1123 * Determine if something has happend since the last 1124 * open/mount that would invalidate a mount. This 1125 * will also eat any pending UAs. 1126 */ 1127 scsi_test_unit_ready(csio, 1128 /*retries*/1, 1129 sadone, 1130 MSG_SIMPLE_Q_TAG, 1131 SSD_FULL_SIZE, 1132 /*timeout*/5000); 1133 1134 cam_periph_runccb(ccb, /*error handler*/NULL, /*cam_flags*/0, 1135 /*sense_flags*/0, &softc->device_stats); 1136 1137 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1138 cam_release_devq(ccb->ccb_h.path, 1139 /*relsim_flags*/0, 1140 /*reduction*/0, 1141 /*timeout*/0, 1142 /*getcount_only*/0); 1143 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 1144 } 1145 1146 if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) { 1147 struct scsi_read_block_limits_data *rblim; 1148 int comp_enabled, comp_supported; 1149 u_int8_t write_protect; 1150 1151 /* 1152 * Clear out old state. 1153 */ 1154 softc->flags &= ~(SA_FLAG_TAPE_WP|SA_FLAG_TAPE_WRITTEN| 1155 SA_FLAG_ERR_PENDING|SA_FLAG_COMP_ENABLED| 1156 SA_FLAG_COMP_UNSUPP); 1157 softc->filemarks = 0; 1158 1159 /* 1160 * First off, determine block limits. 1161 */ 1162 rblim = (struct scsi_read_block_limits_data *) 1163 malloc(sizeof(*rblim), M_TEMP, M_WAITOK); 1164 1165 scsi_read_block_limits(csio, 1166 /*retries*/1, 1167 sadone, 1168 MSG_SIMPLE_Q_TAG, 1169 rblim, 1170 SSD_FULL_SIZE, 1171 /*timeout*/5000); 1172 1173 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 1174 /*sense_flags*/SF_RETRY_UA, 1175 &softc->device_stats); 1176 1177 xpt_release_ccb(ccb); 1178 1179 if (error != 0) 1180 goto exit; 1181 1182 softc->blk_gran = RBL_GRAN(rblim); 1183 softc->max_blk = scsi_3btoul(rblim->maximum); 1184 softc->min_blk = scsi_2btoul(rblim->minimum); 1185 if (softc->max_blk == softc->min_blk) { 1186 softc->flags |= SA_FLAG_FIXED; 1187 if (powerof2(softc->min_blk)) { 1188 softc->blk_mask = softc->min_blk - 1; 1189 softc->blk_shift = 0; 1190 softc->blk_shift = ffs(softc->min_blk) - 1; 1191 } else { 1192 softc->blk_mask = ~0; 1193 softc->blk_shift = 0; 1194 } 1195 } else { 1196 /* 1197 * SCSI-III spec allows 0 1198 * to mean "unspecified" 1199 */ 1200 if (softc->max_blk == 0) { 1201 softc->max_blk = ~0; 1202 } 1203 softc->blk_shift = 0; 1204 if (softc->blk_gran != 0) { 1205 softc->blk_mask = softc->blk_gran - 1; 1206 } else { 1207 softc->blk_mask = 0; 1208 } 1209 } 1210 1211 /* 1212 * Next, perform a mode sense to determine 1213 * current density, blocksize, compression etc. 1214 */ 1215 error = sagetparams(periph, SA_PARAM_ALL, 1216 &softc->media_blksize, 1217 &softc->media_density, 1218 &softc->media_numblks, 1219 &softc->buffer_mode, &write_protect, 1220 &softc->speed, &comp_supported, 1221 &comp_enabled, &softc->comp_algorithm, 1222 NULL); 1223 1224 if (error != 0) 1225 goto exit; 1226 1227 if (write_protect) 1228 softc->flags |= SA_FLAG_TAPE_WP; 1229 1230 if (comp_supported) { 1231 if (comp_enabled) { 1232 softc->flags |= SA_FLAG_COMP_ENABLED; 1233 1234 if (softc->saved_comp_algorithm == 0) 1235 softc->saved_comp_algorithm = 1236 softc->comp_algorithm; 1237 } 1238 } else 1239 softc->flags |= SA_FLAG_COMP_UNSUPP; 1240 1241 if (softc->buffer_mode != SMH_SA_BUF_MODE_NOBUF) 1242 goto exit; 1243 1244 error = sasetparams(periph, SA_PARAM_BUFF_MODE, 0, 0, 0); 1245 1246 if (error == 0) 1247 softc->buffer_mode = SMH_SA_BUF_MODE_SIBUF; 1248 exit: 1249 if (rblim != NULL) 1250 free(rblim, M_TEMP); 1251 1252 if (error != 0) { 1253 cam_release_devq(ccb->ccb_h.path, 1254 /*relsim_flags*/0, 1255 /*reduction*/0, 1256 /*timeout*/0, 1257 /*getcount_only*/0); 1258 } 1259 } else 1260 xpt_release_ccb(ccb); 1261 1262 return (error); 1263 } 1264 1265 static int 1266 sacheckeod(struct cam_periph *periph) 1267 { 1268 int error; 1269 int markswanted; 1270 struct sa_softc *softc; 1271 1272 softc = (struct sa_softc *)periph->softc; 1273 markswanted = 0; 1274 1275 if ((softc->flags & SA_FLAG_TAPE_WRITTEN) != 0) { 1276 markswanted++; 1277 1278 if ((softc->flags & SA_FLAG_2FM_AT_EOD) != 0) 1279 markswanted++; 1280 } 1281 1282 if (softc->filemarks < markswanted) { 1283 markswanted -= softc->filemarks; 1284 error = sawritefilemarks(periph, markswanted, 1285 /*setmarks*/FALSE); 1286 } else { 1287 error = 0; 1288 } 1289 return (error); 1290 } 1291 1292 static int 1293 saerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 1294 { 1295 struct cam_periph *periph; 1296 struct sa_softc *softc; 1297 struct ccb_scsiio *csio; 1298 struct scsi_sense_data *sense; 1299 int error_code, sense_key, asc, ascq; 1300 int error; 1301 1302 periph = xpt_path_periph(ccb->ccb_h.path); 1303 softc = (struct sa_softc *)periph->softc; 1304 csio = &ccb->csio; 1305 sense = &csio->sense_data; 1306 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq); 1307 error = 0; 1308 1309 if (((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) 1310 && ((sense->flags & (SSD_EOM|SSD_FILEMARK|SSD_ILI)) != 0) 1311 && ((sense_key == SSD_KEY_NO_SENSE) 1312 || (sense_key == SSD_KEY_BLANK_CHECK))) { 1313 u_int32_t info; 1314 u_int32_t resid; 1315 int defer_action; 1316 1317 /* 1318 * Filter out some sense codes of interest. 1319 */ 1320 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) { 1321 info = scsi_4btoul(sense->info); 1322 resid = info; 1323 if ((softc->flags & SA_FLAG_FIXED) != 0) 1324 resid *= softc->media_blksize; 1325 } else { 1326 resid = csio->dxfer_len; 1327 info = resid; 1328 if ((softc->flags & SA_FLAG_FIXED) != 0) 1329 info /= softc->media_blksize; 1330 } 1331 if ((resid > 0 && resid < csio->dxfer_len) 1332 && (softc->flags & SA_FLAG_FIXED) != 0) 1333 defer_action = TRUE; 1334 else 1335 defer_action = FALSE; 1336 1337 if ((sense->flags & SSD_EOM) != 0 1338 || (sense_key == 0x8 /* BLANK CHECK*/)) { 1339 csio->resid = resid; 1340 if (defer_action) { 1341 softc->flags |= SA_FLAG_EOM_PENDING; 1342 } else { 1343 if (csio->cdb_io.cdb_bytes[0] == SA_WRITE) 1344 error = ENOSPC; 1345 } 1346 } 1347 if ((sense->flags & SSD_FILEMARK) != 0) { 1348 csio->resid = resid; 1349 if (defer_action) 1350 softc->flags |= SA_FLAG_EOF_PENDING; 1351 } 1352 if (sense->flags & SSD_ILI) { 1353 if (info < 0) { 1354 /* 1355 * The record was too big. 1356 */ 1357 xpt_print_path(csio->ccb_h.path); 1358 printf("%d-byte tape record bigger " 1359 "than suplied read buffer\n", 1360 csio->dxfer_len - info); 1361 csio->resid = csio->dxfer_len; 1362 error = EIO; 1363 } else { 1364 csio->resid = resid; 1365 if ((softc->flags & SA_FLAG_FIXED) != 0) { 1366 if (defer_action) 1367 softc->flags |= 1368 SA_FLAG_EIO_PENDING; 1369 else 1370 error = EIO; 1371 } 1372 } 1373 } 1374 } 1375 if (error == 0) 1376 error = cam_periph_error(ccb, cam_flags, sense_flags, 1377 &softc->saved_ccb); 1378 1379 return (error); 1380 } 1381 1382 static int 1383 sagetparams(struct cam_periph *periph, sa_params params_to_get, 1384 u_int32_t *blocksize, u_int8_t *density, u_int32_t *numblocks, 1385 int *buff_mode, u_int8_t *write_protect, u_int8_t *speed, 1386 int *comp_supported, int *comp_enabled, u_int32_t *comp_algorithm, 1387 struct scsi_data_compression_page *comp_page) 1388 { 1389 union ccb *ccb; 1390 void *mode_buffer; 1391 struct scsi_mode_header_6 *mode_hdr; 1392 struct scsi_mode_blk_desc *mode_blk; 1393 struct scsi_data_compression_page *ncomp_page; 1394 int mode_buffer_len; 1395 struct sa_softc *softc; 1396 int error; 1397 cam_status status; 1398 1399 softc = (struct sa_softc *)periph->softc; 1400 1401 ccb = cam_periph_getccb(periph, /*priority*/ 1); 1402 1403 retry: 1404 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk); 1405 1406 if (params_to_get & SA_PARAM_COMPRESSION) { 1407 if (softc->quirks & SA_QUIRK_NOCOMP) { 1408 *comp_supported = FALSE; 1409 params_to_get &= ~SA_PARAM_COMPRESSION; 1410 } else 1411 mode_buffer_len += 1412 sizeof(struct scsi_data_compression_page); 1413 } 1414 1415 mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK); 1416 1417 bzero(mode_buffer, mode_buffer_len); 1418 1419 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer; 1420 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1]; 1421 1422 if (params_to_get & SA_PARAM_COMPRESSION) 1423 ncomp_page = (struct scsi_data_compression_page *)&mode_blk[1]; 1424 else 1425 ncomp_page = NULL; 1426 1427 scsi_mode_sense(&ccb->csio, 1428 /*retries*/ 1, 1429 /*cbfcnp*/ sadone, 1430 /*tag_action*/ MSG_SIMPLE_Q_TAG, 1431 /*dbd*/ FALSE, 1432 /*page_code*/ SMS_PAGE_CTRL_CURRENT, 1433 /*page*/ (params_to_get & SA_PARAM_COMPRESSION) ? 1434 SA_DATA_COMPRESSION_PAGE : 1435 SMS_VENDOR_SPECIFIC_PAGE, 1436 /*param_buf*/ mode_buffer, 1437 /*param_len*/ mode_buffer_len, 1438 /*sense_len*/ SSD_FULL_SIZE, 1439 /*timeout*/ 5000); 1440 1441 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/ 0, 1442 /*sense_flags*/SF_NO_PRINT, 1443 &softc->device_stats); 1444 1445 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1446 cam_release_devq(ccb->ccb_h.path, 1447 /* relsim_flags */0, 1448 /* opening_reduction */0, 1449 /* timeout */0, 1450 /* getcount_only */ FALSE); 1451 1452 status = ccb->ccb_h.status & CAM_STATUS_MASK; 1453 1454 if (error == EINVAL 1455 && (params_to_get & SA_PARAM_COMPRESSION) != 0) { 1456 /* 1457 * Most likely doesn't support the compression 1458 * page. Remeber this for the future and attempt 1459 * the request without asking for compression info. 1460 */ 1461 softc->quirks |= SA_QUIRK_NOCOMP; 1462 free(mode_buffer, M_TEMP); 1463 goto retry; 1464 } else if (error == 0) { 1465 struct scsi_data_compression_page *temp_comp_page; 1466 1467 temp_comp_page = NULL; 1468 1469 /* 1470 * If the user only wants the compression information, and 1471 * the device doesn't send back the block descriptor, it's 1472 * no big deal. If the user wants more than just 1473 * compression, though, and the device doesn't pass back the 1474 * block descriptor, we need to send another mode sense to 1475 * get the block descriptor. 1476 */ 1477 if ((mode_hdr->blk_desc_len == 0) 1478 && (params_to_get & SA_PARAM_COMPRESSION) 1479 && ((params_to_get & ~(SA_PARAM_COMPRESSION)) != 0)) { 1480 1481 /* 1482 * Decrease the mode buffer length by the size of 1483 * the compression page, to make sure the data 1484 * there doesn't get overwritten. 1485 */ 1486 mode_buffer_len -= sizeof(*ncomp_page); 1487 1488 /* 1489 * Now move the compression page that we presumably 1490 * got back down the memory chunk a little bit so 1491 * it doesn't get spammed. 1492 */ 1493 temp_comp_page = 1494 (struct scsi_data_compression_page *)&mode_hdr[1]; 1495 bcopy(temp_comp_page, ncomp_page, sizeof(*ncomp_page)); 1496 1497 /* 1498 * Now, we issue another mode sense and just ask 1499 * for the block descriptor, etc. 1500 */ 1501 scsi_mode_sense(&ccb->csio, 1502 /*retries*/ 1, 1503 /*cbfcnp*/ sadone, 1504 /*tag_action*/ MSG_SIMPLE_Q_TAG, 1505 /*dbd*/ FALSE, 1506 /*page_code*/ SMS_PAGE_CTRL_CURRENT, 1507 /*page*/ SMS_VENDOR_SPECIFIC_PAGE, 1508 /*param_buf*/ mode_buffer, 1509 /*param_len*/ mode_buffer_len, 1510 /*sense_len*/ SSD_FULL_SIZE, 1511 /*timeout*/ 5000); 1512 1513 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/ 0, 1514 /*sense_flags*/ 0, 1515 &softc->device_stats); 1516 1517 if (error != 0) 1518 goto sagetparamsexit; 1519 1520 } 1521 1522 if (params_to_get & SA_PARAM_BLOCKSIZE) 1523 *blocksize = scsi_3btoul(mode_blk->blklen); 1524 1525 if (params_to_get & SA_PARAM_NUMBLOCKS) 1526 *numblocks = scsi_3btoul(mode_blk->nblocks); 1527 1528 if (params_to_get & SA_PARAM_BUFF_MODE) 1529 *buff_mode = mode_hdr->dev_spec & SMH_SA_BUF_MODE_MASK; 1530 1531 if (params_to_get & SA_PARAM_DENSITY) 1532 *density = mode_blk->density; 1533 1534 if (params_to_get & SA_PARAM_WP) 1535 *write_protect = (mode_hdr->dev_spec & SMH_SA_WP) ? 1536 TRUE : FALSE; 1537 if (params_to_get & SA_PARAM_SPEED) 1538 *speed = mode_hdr->dev_spec & SMH_SA_SPEED_MASK; 1539 1540 if (params_to_get & SA_PARAM_COMPRESSION) { 1541 *comp_supported =(ncomp_page->dce_and_dcc & SA_DCP_DCC)? 1542 TRUE : FALSE; 1543 *comp_enabled = (ncomp_page->dce_and_dcc & SA_DCP_DCE)? 1544 TRUE : FALSE; 1545 *comp_algorithm = 1546 scsi_4btoul(ncomp_page->comp_algorithm); 1547 if (comp_page != NULL) 1548 bcopy(ncomp_page, comp_page,sizeof(*comp_page)); 1549 } 1550 1551 } else if (status == CAM_SCSI_STATUS_ERROR) { 1552 /* Tell the user about the fatal error. */ 1553 scsi_sense_print(&ccb->csio); 1554 } 1555 1556 sagetparamsexit: 1557 1558 xpt_release_ccb(ccb); 1559 free(mode_buffer, M_TEMP); 1560 return(error); 1561 } 1562 1563 /* 1564 * The purpose of this function is to set one of four different parameters 1565 * for a tape drive: 1566 * - blocksize 1567 * - density 1568 * - compression / compression algorithm 1569 * - buffering mode 1570 * 1571 * The assumption is that this will be called from saioctl(), and therefore 1572 * from a process context. Thus the waiting malloc calls below. If that 1573 * assumption ever changes, the malloc calls should be changed to be 1574 * NOWAIT mallocs. 1575 * 1576 * Any or all of the four parameters may be set when this function is 1577 * called. It should handle setting more than one parameter at once. 1578 */ 1579 static int 1580 sasetparams(struct cam_periph *periph, sa_params params_to_set, 1581 u_int32_t blocksize, u_int8_t density, u_int32_t comp_algorithm) 1582 { 1583 struct sa_softc *softc; 1584 u_int32_t current_blocksize; 1585 u_int32_t current_comp_algorithm; 1586 u_int8_t current_density; 1587 u_int8_t current_speed; 1588 int comp_enabled, comp_supported; 1589 void *mode_buffer; 1590 int mode_buffer_len; 1591 struct scsi_mode_header_6 *mode_hdr; 1592 struct scsi_mode_blk_desc *mode_blk; 1593 struct scsi_data_compression_page *comp_page; 1594 struct scsi_data_compression_page *current_comp_page; 1595 int buff_mode; 1596 union ccb *ccb; 1597 int error; 1598 1599 softc = (struct sa_softc *)periph->softc; 1600 1601 /* silence the compiler */ 1602 ccb = NULL; 1603 1604 current_comp_page = malloc(sizeof(*current_comp_page),M_TEMP, M_WAITOK); 1605 1606 /* 1607 * Since it doesn't make sense to set the number of blocks, or 1608 * write protection, we won't try to get the current value. We 1609 * always want to get the blocksize, so we can set it back to the 1610 * proper value. 1611 */ 1612 error = sagetparams(periph, params_to_set | SA_PARAM_BLOCKSIZE | 1613 SA_PARAM_SPEED, ¤t_blocksize, 1614 ¤t_density, NULL, &buff_mode, NULL, 1615 ¤t_speed, &comp_supported, &comp_enabled, 1616 ¤t_comp_algorithm, current_comp_page); 1617 1618 if (error != 0) { 1619 free(current_comp_page, M_TEMP); 1620 return(error); 1621 } 1622 1623 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk); 1624 if (params_to_set & SA_PARAM_COMPRESSION) 1625 mode_buffer_len += sizeof(struct scsi_data_compression_page); 1626 1627 mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK); 1628 1629 bzero(mode_buffer, mode_buffer_len); 1630 1631 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer; 1632 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1]; 1633 1634 if (params_to_set & SA_PARAM_COMPRESSION) { 1635 comp_page = (struct scsi_data_compression_page *)&mode_blk[1]; 1636 bcopy(current_comp_page, comp_page, sizeof(*comp_page)); 1637 } else 1638 comp_page = NULL; 1639 1640 /* 1641 * If the caller wants us to set the blocksize, use the one they 1642 * pass in. Otherwise, use the blocksize we got back from the 1643 * mode select above. 1644 */ 1645 if (params_to_set & SA_PARAM_BLOCKSIZE) 1646 scsi_ulto3b(blocksize, mode_blk->blklen); 1647 else 1648 scsi_ulto3b(current_blocksize, mode_blk->blklen); 1649 1650 /* 1651 * 0x7f means "same as before" 1652 */ 1653 if (params_to_set & SA_PARAM_DENSITY) 1654 mode_blk->density = density; 1655 else 1656 mode_blk->density = 0x7f; 1657 1658 /* 1659 * For mode selects, these two fields must be zero. 1660 */ 1661 mode_hdr->data_length = 0; 1662 mode_hdr->medium_type = 0; 1663 1664 /* set the speed to the current value */ 1665 mode_hdr->dev_spec = current_speed; 1666 1667 /* set single-initiator buffering mode */ 1668 mode_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF; 1669 1670 mode_hdr->blk_desc_len = sizeof(struct scsi_mode_blk_desc); 1671 1672 /* 1673 * First, if the user wants us to set the compression algorithm or 1674 * just turn compression on, check to make sure that this drive 1675 * supports compression. 1676 */ 1677 if ((params_to_set & SA_PARAM_COMPRESSION) 1678 && (current_comp_page->dce_and_dcc & SA_DCP_DCC)) { 1679 1680 /* 1681 * If the compression algorithm is 0, disable compression. 1682 * If the compression algorithm is non-zero, enable 1683 * compression and set the compression type to the 1684 * specified compression algorithm, unless the algorithm is 1685 * MT_COMP_ENABLE. In that case, we look at the 1686 * compression algorithm that is currently set and if it is 1687 * non-zero, we leave it as-is. If it is zero, and we have 1688 * saved a compression algorithm from a time when 1689 * compression was enabled before, set the compression to 1690 * the saved value. 1691 */ 1692 if (comp_algorithm == 0) { 1693 /* disable compression */ 1694 comp_page->dce_and_dcc &= ~SA_DCP_DCE; 1695 } else { 1696 /* enable compression */ 1697 comp_page->dce_and_dcc |= SA_DCP_DCE; 1698 1699 /* enable decompression */ 1700 comp_page->dde_and_red |= SA_DCP_DDE; 1701 1702 if (comp_algorithm != MT_COMP_ENABLE) { 1703 /* set the compression algorithm */ 1704 scsi_ulto4b(comp_algorithm, 1705 comp_page->comp_algorithm); 1706 1707 } else if ((scsi_4btoul(comp_page->comp_algorithm) == 0) 1708 && (softc->saved_comp_algorithm != 0)) { 1709 scsi_ulto4b(softc->saved_comp_algorithm, 1710 comp_page->comp_algorithm); 1711 } 1712 } 1713 } else if (params_to_set & SA_PARAM_COMPRESSION) { 1714 /* 1715 * The drive doesn't support compression, so turn off the 1716 * set compression bit. 1717 */ 1718 params_to_set &= ~SA_PARAM_COMPRESSION; 1719 1720 /* 1721 * Should probably do something other than a printf...like 1722 * set a flag in the softc saying that this drive doesn't 1723 * support compression. 1724 */ 1725 xpt_print_path(periph->path); 1726 printf("sasetparams: device does not support compression\n"); 1727 1728 /* 1729 * If that was the only thing the user wanted us to set, 1730 * clean up allocated resources and return with 'operation 1731 * not supported'. 1732 */ 1733 if (params_to_set == SA_PARAM_NONE) { 1734 free(mode_buffer, M_TEMP); 1735 return(ENODEV); 1736 } 1737 1738 /* 1739 * That wasn't the only thing the user wanted us to set. 1740 * So, decrease the stated mode buffer length by the size 1741 * of the compression mode page. 1742 */ 1743 mode_buffer_len -= sizeof(*comp_page); 1744 } 1745 1746 ccb = cam_periph_getccb(periph, /*priority*/ 1); 1747 1748 scsi_mode_select(&ccb->csio, 1749 /*retries*/1, 1750 /*cbfcnp*/ sadone, 1751 /*tag_action*/ MSG_SIMPLE_Q_TAG, 1752 /*scsi_page_fmt*/(params_to_set & SA_PARAM_COMPRESSION)? 1753 TRUE : FALSE, 1754 /*save_pages*/ FALSE, 1755 /*param_buf*/ mode_buffer, 1756 /*param_len*/ mode_buffer_len, 1757 /*sense_len*/ SSD_FULL_SIZE, 1758 /*timeout*/ 5000); 1759 1760 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/ 0, 1761 /*sense_flags*/ 0, &softc->device_stats); 1762 1763 if (error == 0) { 1764 xpt_release_ccb(ccb); 1765 } else { 1766 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1767 cam_release_devq(ccb->ccb_h.path, 1768 /*relsim_flags*/0, 1769 /*reduction*/0, 1770 /*timeout*/0, 1771 /*getcount_only*/0); 1772 /* 1773 * If we were setting the blocksize, and that failed, we 1774 * want to set it to its original value. If we weren't 1775 * setting the blocksize, we don't want to change it. 1776 */ 1777 scsi_ulto3b(current_blocksize, mode_blk->blklen); 1778 1779 /* 1780 * 0x7f means "same as before". 1781 */ 1782 if (params_to_set & SA_PARAM_DENSITY) 1783 mode_blk->density = current_density; 1784 else 1785 mode_blk->density = 0x7f; 1786 1787 if (params_to_set & SA_PARAM_COMPRESSION) 1788 bcopy(current_comp_page, comp_page, 1789 sizeof(struct scsi_data_compression_page)); 1790 1791 /* 1792 * The retry count is the only CCB field that might have been 1793 * changed that we care about, so reset it back to 1. 1794 */ 1795 ccb->ccb_h.retry_count = 1; 1796 cam_periph_runccb(ccb, saerror, /*cam_flags*/ 0, 1797 /*sense_flags*/ 0, &softc->device_stats); 1798 1799 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1800 cam_release_devq(ccb->ccb_h.path, 1801 /*relsim_flags*/0, 1802 /*reduction*/0, 1803 /*timeout*/0, 1804 /*getcount_only*/0); 1805 1806 xpt_release_ccb(ccb); 1807 } 1808 1809 if (params_to_set & SA_PARAM_COMPRESSION) 1810 free(current_comp_page, M_TEMP); 1811 1812 free(mode_buffer, M_TEMP); 1813 return(error); 1814 } 1815 1816 static void 1817 saprevent(struct cam_periph *periph, int action) 1818 { 1819 struct sa_softc *softc; 1820 union ccb *ccb; 1821 int error; 1822 1823 softc = (struct sa_softc *)periph->softc; 1824 1825 if (((action == PR_ALLOW) 1826 && (softc->flags & SA_FLAG_TAPE_LOCKED) == 0) 1827 || ((action == PR_PREVENT) 1828 && (softc->flags & SA_FLAG_TAPE_LOCKED) != 0)) { 1829 return; 1830 } 1831 1832 ccb = cam_periph_getccb(periph, /*priority*/1); 1833 1834 scsi_prevent(&ccb->csio, 1835 /*retries*/0, 1836 /*cbcfp*/sadone, 1837 MSG_SIMPLE_Q_TAG, 1838 action, 1839 SSD_FULL_SIZE, 1840 60000); 1841 1842 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 1843 /*sense_flags*/0, &softc->device_stats); 1844 1845 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1846 cam_release_devq(ccb->ccb_h.path, 1847 /*relsim_flags*/0, 1848 /*reduction*/0, 1849 /*timeout*/0, 1850 /*getcount_only*/0); 1851 1852 1853 if (error == 0) { 1854 if (action == PR_ALLOW) 1855 softc->flags &= ~SA_FLAG_TAPE_LOCKED; 1856 else 1857 softc->flags |= SA_FLAG_TAPE_LOCKED; 1858 } 1859 1860 xpt_release_ccb(ccb); 1861 } 1862 1863 static int 1864 sarewind(struct cam_periph *periph) 1865 { 1866 union ccb *ccb; 1867 struct sa_softc *softc; 1868 int error; 1869 1870 softc = (struct sa_softc *)periph->softc; 1871 1872 ccb = cam_periph_getccb(periph, /*priority*/1); 1873 1874 scsi_rewind(&ccb->csio, 1875 /*retries*/1, 1876 /*cbcfp*/sadone, 1877 MSG_SIMPLE_Q_TAG, 1878 /*immediate*/FALSE, 1879 SSD_FULL_SIZE, 1880 (SA_REWIND_TIMEOUT) * 60 * 1000); 1881 1882 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 1883 /*sense_flags*/0, &softc->device_stats); 1884 1885 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1886 cam_release_devq(ccb->ccb_h.path, 1887 /*relsim_flags*/0, 1888 /*reduction*/0, 1889 /*timeout*/0, 1890 /*getcount_only*/0); 1891 1892 xpt_release_ccb(ccb); 1893 1894 return (error); 1895 } 1896 1897 static int 1898 saspace(struct cam_periph *periph, int count, scsi_space_code code) 1899 { 1900 union ccb *ccb; 1901 struct sa_softc *softc; 1902 int error; 1903 1904 softc = (struct sa_softc *)periph->softc; 1905 1906 ccb = cam_periph_getccb(periph, /*priority*/1); 1907 1908 scsi_space(&ccb->csio, 1909 /*retries*/1, 1910 /*cbcfp*/sadone, 1911 MSG_SIMPLE_Q_TAG, 1912 code, count, 1913 SSD_FULL_SIZE, 1914 (SA_SPACE_TIMEOUT) * 60 * 1000); 1915 1916 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 1917 /*sense_flags*/0, &softc->device_stats); 1918 1919 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1920 cam_release_devq(ccb->ccb_h.path, 1921 /*relsim_flags*/0, 1922 /*reduction*/0, 1923 /*timeout*/0, 1924 /*getcount_only*/0); 1925 1926 xpt_release_ccb(ccb); 1927 1928 return (error); 1929 } 1930 1931 static int 1932 sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks) 1933 { 1934 union ccb *ccb; 1935 struct sa_softc *softc; 1936 int error; 1937 1938 softc = (struct sa_softc *)periph->softc; 1939 1940 ccb = cam_periph_getccb(periph, /*priority*/1); 1941 1942 scsi_write_filemarks(&ccb->csio, 1943 /*retries*/1, 1944 /*cbcfp*/sadone, 1945 MSG_SIMPLE_Q_TAG, 1946 /*immediate*/FALSE, 1947 setmarks, 1948 nmarks, 1949 SSD_FULL_SIZE, 1950 60000); 1951 1952 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 1953 /*sense_flags*/0, &softc->device_stats); 1954 1955 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1956 cam_release_devq(ccb->ccb_h.path, 1957 /*relsim_flags*/0, 1958 /*reduction*/0, 1959 /*timeout*/0, 1960 /*getcount_only*/0); 1961 1962 if (error == 0) { 1963 struct sa_softc *softc; 1964 1965 softc = (struct sa_softc *)periph->softc; 1966 softc->filemarks += nmarks; 1967 } 1968 1969 xpt_release_ccb(ccb); 1970 1971 return (error); 1972 } 1973 1974 static int 1975 saretension(struct cam_periph *periph) 1976 { 1977 union ccb *ccb; 1978 struct sa_softc *softc; 1979 int error; 1980 1981 softc = (struct sa_softc *)periph->softc; 1982 1983 ccb = cam_periph_getccb(periph, /*priority*/1); 1984 1985 scsi_load_unload(&ccb->csio, 1986 /*retries*/ 1, 1987 /*cbfcnp*/ sadone, 1988 MSG_SIMPLE_Q_TAG, 1989 /*immediate*/ FALSE, 1990 /*eot*/ FALSE, 1991 /*reten*/ TRUE, 1992 /*load*/ TRUE, 1993 SSD_FULL_SIZE, 1994 60000); 1995 1996 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 1997 /*sense_flags*/0, &softc->device_stats); 1998 1999 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2000 cam_release_devq(ccb->ccb_h.path, 2001 /*relsim_flags*/0, 2002 /*reduction*/0, 2003 /*timeout*/0, 2004 /*getcount_only*/0); 2005 2006 xpt_release_ccb(ccb); 2007 2008 return(error); 2009 } 2010 2011 static int 2012 sareservereleaseunit(struct cam_periph *periph, int reserve) 2013 { 2014 union ccb *ccb; 2015 struct sa_softc *softc; 2016 int error; 2017 2018 softc = (struct sa_softc *)periph->softc; 2019 2020 ccb = cam_periph_getccb(periph, /*priority*/ 1); 2021 2022 scsi_reserve_release_unit(&ccb->csio, 2023 /*retries*/ 1, 2024 /*cbfcnp*/ sadone, 2025 /*tag_action*/ MSG_SIMPLE_Q_TAG, 2026 /*third_party*/ FALSE, 2027 /*third_party_id*/ 0, 2028 /*sense_len*/ SSD_FULL_SIZE, 2029 /*timeout*/ 5000, 2030 reserve); 2031 2032 /* 2033 * We set SF_RETRY_UA, since this is often the first command run 2034 * when a tape device is opened, and there may be a unit attention 2035 * condition pending. 2036 */ 2037 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2038 /*sense_flags*/SF_RETRY_UA, 2039 &softc->device_stats); 2040 2041 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2042 cam_release_devq(ccb->ccb_h.path, 2043 /*relsim_flags*/0, 2044 /*reduction*/0, 2045 /*timeout*/0, 2046 /*getcount_only*/0); 2047 2048 xpt_release_ccb(ccb); 2049 2050 return (error); 2051 } 2052 2053 static int 2054 saloadunload(struct cam_periph *periph, int load) 2055 { 2056 union ccb *ccb; 2057 struct sa_softc *softc; 2058 int error; 2059 2060 softc = (struct sa_softc *)periph->softc; 2061 2062 ccb = cam_periph_getccb(periph, /*priority*/1); 2063 2064 scsi_load_unload(&ccb->csio, 2065 /*retries*/1, 2066 /*cbfcnp*/sadone, 2067 MSG_SIMPLE_Q_TAG, 2068 /*immediate*/FALSE, 2069 /*eot*/FALSE, 2070 /*reten*/FALSE, 2071 load, 2072 SSD_FULL_SIZE, 2073 60000); 2074 2075 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2076 /*sense_flags*/0, &softc->device_stats); 2077 2078 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2079 cam_release_devq(ccb->ccb_h.path, 2080 /*relsim_flags*/0, 2081 /*reduction*/0, 2082 /*timeout*/0, 2083 /*getcount_only*/0); 2084 2085 xpt_release_ccb(ccb); 2086 2087 return (error); 2088 } 2089 2090 static int 2091 saerase(struct cam_periph *periph, int longerase) 2092 { 2093 2094 union ccb *ccb; 2095 struct sa_softc *softc; 2096 int error; 2097 2098 softc = (struct sa_softc *)periph->softc; 2099 2100 ccb = cam_periph_getccb(periph, /*priority*/ 1); 2101 2102 scsi_erase(&ccb->csio, 2103 /*retries*/ 1, 2104 /*cbfcnp*/ sadone, 2105 /*tag_action*/ MSG_SIMPLE_Q_TAG, 2106 /*immediate*/ FALSE, 2107 /*long_erase*/ longerase, 2108 /*sense_len*/ SSD_FULL_SIZE, 2109 /*timeout*/ (SA_ERASE_TIMEOUT) * 60 * 1000); 2110 2111 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2112 /*sense_flags*/0, &softc->device_stats); 2113 2114 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2115 cam_release_devq(ccb->ccb_h.path, 2116 /*relsim_flags*/0, 2117 /*reduction*/0, 2118 /*timeout*/0, 2119 /*getcount_only*/0); 2120 2121 xpt_release_ccb(ccb); 2122 2123 return (error); 2124 } 2125 2126 #endif /* KERNEL */ 2127 2128 /* 2129 * Read tape block limits command. 2130 */ 2131 void 2132 scsi_read_block_limits(struct ccb_scsiio *csio, u_int32_t retries, 2133 void (*cbfcnp)(struct cam_periph *, union ccb *), 2134 u_int8_t tag_action, 2135 struct scsi_read_block_limits_data *rlimit_buf, 2136 u_int8_t sense_len, u_int32_t timeout) 2137 { 2138 struct scsi_read_block_limits *scsi_cmd; 2139 2140 cam_fill_csio(csio, 2141 retries, 2142 cbfcnp, 2143 /*flags*/CAM_DIR_IN, 2144 tag_action, 2145 /*data_ptr*/(u_int8_t *)rlimit_buf, 2146 /*dxfer_len*/sizeof(*rlimit_buf), 2147 sense_len, 2148 sizeof(*scsi_cmd), 2149 timeout); 2150 2151 scsi_cmd = (struct scsi_read_block_limits *)&csio->cdb_io.cdb_bytes; 2152 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2153 scsi_cmd->opcode = READ_BLOCK_LIMITS; 2154 } 2155 2156 void 2157 scsi_sa_read_write(struct ccb_scsiio *csio, u_int32_t retries, 2158 void (*cbfcnp)(struct cam_periph *, union ccb *), 2159 u_int8_t tag_action, int readop, int sli, 2160 int fixed, u_int32_t length, u_int8_t *data_ptr, 2161 u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout) 2162 { 2163 struct scsi_sa_rw *scsi_cmd; 2164 2165 scsi_cmd = (struct scsi_sa_rw *)&csio->cdb_io.cdb_bytes; 2166 scsi_cmd->opcode = readop ? SA_READ : SA_WRITE; 2167 scsi_cmd->sli_fixed = 0; 2168 if (sli && readop) 2169 scsi_cmd->sli_fixed |= SAR_SLI; 2170 if (fixed) 2171 scsi_cmd->sli_fixed |= SARW_FIXED; 2172 scsi_ulto3b(length, scsi_cmd->length); 2173 scsi_cmd->control = 0; 2174 2175 cam_fill_csio(csio, 2176 retries, 2177 cbfcnp, 2178 /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT, 2179 tag_action, 2180 data_ptr, 2181 dxfer_len, 2182 sense_len, 2183 sizeof(*scsi_cmd), 2184 timeout); 2185 } 2186 2187 void 2188 scsi_load_unload(struct ccb_scsiio *csio, u_int32_t retries, 2189 void (*cbfcnp)(struct cam_periph *, union ccb *), 2190 u_int8_t tag_action, int immediate, int eot, 2191 int reten, int load, u_int8_t sense_len, 2192 u_int32_t timeout) 2193 { 2194 struct scsi_load_unload *scsi_cmd; 2195 2196 scsi_cmd = (struct scsi_load_unload *)&csio->cdb_io.cdb_bytes; 2197 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2198 scsi_cmd->opcode = LOAD_UNLOAD; 2199 if (immediate) 2200 scsi_cmd->immediate = SLU_IMMED; 2201 if (eot) 2202 scsi_cmd->eot_reten_load |= SLU_EOT; 2203 if (reten) 2204 scsi_cmd->eot_reten_load |= SLU_RETEN; 2205 if (load) 2206 scsi_cmd->eot_reten_load |= SLU_LOAD; 2207 2208 cam_fill_csio(csio, 2209 retries, 2210 cbfcnp, 2211 /*flags*/CAM_DIR_NONE, 2212 tag_action, 2213 /*data_ptr*/NULL, 2214 /*dxfer_len*/0, 2215 sense_len, 2216 sizeof(*scsi_cmd), 2217 timeout); 2218 } 2219 2220 void 2221 scsi_rewind(struct ccb_scsiio *csio, u_int32_t retries, 2222 void (*cbfcnp)(struct cam_periph *, union ccb *), 2223 u_int8_t tag_action, int immediate, u_int8_t sense_len, 2224 u_int32_t timeout) 2225 { 2226 struct scsi_rewind *scsi_cmd; 2227 2228 scsi_cmd = (struct scsi_rewind *)&csio->cdb_io.cdb_bytes; 2229 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2230 scsi_cmd->opcode = REWIND; 2231 if (immediate) 2232 scsi_cmd->immediate = SREW_IMMED; 2233 2234 cam_fill_csio(csio, 2235 retries, 2236 cbfcnp, 2237 /*flags*/CAM_DIR_NONE, 2238 tag_action, 2239 /*data_ptr*/NULL, 2240 /*dxfer_len*/0, 2241 sense_len, 2242 sizeof(*scsi_cmd), 2243 timeout); 2244 } 2245 2246 void 2247 scsi_space(struct ccb_scsiio *csio, u_int32_t retries, 2248 void (*cbfcnp)(struct cam_periph *, union ccb *), 2249 u_int8_t tag_action, scsi_space_code code, 2250 u_int32_t count, u_int8_t sense_len, u_int32_t timeout) 2251 { 2252 struct scsi_space *scsi_cmd; 2253 2254 scsi_cmd = (struct scsi_space *)&csio->cdb_io.cdb_bytes; 2255 scsi_cmd->opcode = SPACE; 2256 scsi_cmd->code = code; 2257 scsi_ulto3b(count, scsi_cmd->count); 2258 scsi_cmd->control = 0; 2259 2260 cam_fill_csio(csio, 2261 retries, 2262 cbfcnp, 2263 /*flags*/CAM_DIR_NONE, 2264 tag_action, 2265 /*data_ptr*/NULL, 2266 /*dxfer_len*/0, 2267 sense_len, 2268 sizeof(*scsi_cmd), 2269 timeout); 2270 } 2271 2272 void 2273 scsi_write_filemarks(struct ccb_scsiio *csio, u_int32_t retries, 2274 void (*cbfcnp)(struct cam_periph *, union ccb *), 2275 u_int8_t tag_action, int immediate, int setmark, 2276 u_int32_t num_marks, u_int8_t sense_len, 2277 u_int32_t timeout) 2278 { 2279 struct scsi_write_filemarks *scsi_cmd; 2280 2281 scsi_cmd = (struct scsi_write_filemarks *)&csio->cdb_io.cdb_bytes; 2282 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2283 scsi_cmd->opcode = WRITE_FILEMARKS; 2284 if (immediate) 2285 scsi_cmd->byte2 |= SWFMRK_IMMED; 2286 if (setmark) 2287 scsi_cmd->byte2 |= SWFMRK_WSMK; 2288 2289 scsi_ulto3b(num_marks, scsi_cmd->num_marks); 2290 2291 cam_fill_csio(csio, 2292 retries, 2293 cbfcnp, 2294 /*flags*/CAM_DIR_NONE, 2295 tag_action, 2296 /*data_ptr*/NULL, 2297 /*dxfer_len*/0, 2298 sense_len, 2299 sizeof(*scsi_cmd), 2300 timeout); 2301 } 2302 2303 /* 2304 * The reserve and release unit commands differ only by their opcodes. 2305 */ 2306 void 2307 scsi_reserve_release_unit(struct ccb_scsiio *csio, u_int32_t retries, 2308 void (*cbfcnp)(struct cam_periph *, union ccb *), 2309 u_int8_t tag_action, int third_party, 2310 int third_party_id, u_int8_t sense_len, 2311 u_int32_t timeout, int reserve) 2312 { 2313 struct scsi_reserve_release_unit *scsi_cmd; 2314 2315 scsi_cmd = (struct scsi_reserve_release_unit *)&csio->cdb_io.cdb_bytes; 2316 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2317 2318 if (reserve) 2319 scsi_cmd->opcode = RESERVE_UNIT; 2320 else 2321 scsi_cmd->opcode = RELEASE_UNIT; 2322 2323 if (third_party) { 2324 scsi_cmd->lun_thirdparty |= SRRU_3RD_PARTY; 2325 scsi_cmd->lun_thirdparty |= 2326 ((third_party_id << SRRU_3RD_SHAMT) & SRRU_3RD_MASK); 2327 } 2328 2329 cam_fill_csio(csio, 2330 retries, 2331 cbfcnp, 2332 /*flags*/ CAM_DIR_NONE, 2333 tag_action, 2334 /*data_ptr*/ NULL, 2335 /*dxfer_len*/ 0, 2336 sense_len, 2337 sizeof(*scsi_cmd), 2338 timeout); 2339 } 2340 2341 void 2342 scsi_erase(struct ccb_scsiio *csio, u_int32_t retries, 2343 void (*cbfcnp)(struct cam_periph *, union ccb *), 2344 u_int8_t tag_action, int immediate, int long_erase, 2345 u_int8_t sense_len, u_int32_t timeout) 2346 { 2347 struct scsi_erase *scsi_cmd; 2348 2349 scsi_cmd = (struct scsi_erase *)&csio->cdb_io.cdb_bytes; 2350 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2351 2352 scsi_cmd->opcode = ERASE; 2353 2354 if (immediate) 2355 scsi_cmd->lun_imm_long |= SE_IMMED; 2356 2357 if (long_erase) 2358 scsi_cmd->lun_imm_long |= SE_LONG; 2359 2360 cam_fill_csio(csio, 2361 retries, 2362 cbfcnp, 2363 /*flags*/ CAM_DIR_NONE, 2364 tag_action, 2365 /*data_ptr*/ NULL, 2366 /*dxfer_len*/ 0, 2367 sense_len, 2368 sizeof(*scsi_cmd), 2369 timeout); 2370 } 2371