scsi_sa.c revision 41918
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.8 1998/12/17 18:56:23 mjacob 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#ifndef UNUSED_PARAMETER 80#define UNUSED_PARAMETER(x) x = x 81#endif 82 83typedef enum { 84 SA_STATE_NORMAL 85} sa_state; 86 87typedef enum { 88 SA_CCB_BUFFER_IO, 89 SA_CCB_WAITING 90} sa_ccb_types; 91 92#define ccb_type ppriv_field0 93#define ccb_bp ppriv_ptr1 94 95typedef enum { 96 SA_FLAG_OPEN = 0x0001, 97 SA_FLAG_FIXED = 0x0002, 98 SA_FLAG_TAPE_LOCKED = 0x0004, 99 SA_FLAG_TAPE_MOUNTED = 0x0008, 100 SA_FLAG_TAPE_WP = 0x0010, 101 SA_FLAG_TAPE_WRITTEN = 0x0020, 102 SA_FLAG_EOM_PENDING = 0x0040, 103 SA_FLAG_EIO_PENDING = 0x0080, 104 SA_FLAG_EOF_PENDING = 0x0100, 105 SA_FLAG_ERR_PENDING = (SA_FLAG_EOM_PENDING|SA_FLAG_EIO_PENDING| 106 SA_FLAG_EOF_PENDING), 107 SA_FLAG_INVALID = 0x0200, 108 SA_FLAG_COMP_ENABLED = 0x0400, 109 SA_FLAG_COMP_UNSUPP = 0x0800 110} sa_flags; 111 112typedef enum { 113 SA_MODE_REWIND = 0x00, 114 SA_MODE_NOREWIND = 0x01, 115 SA_MODE_OFFLINE = 0x02 116} sa_mode; 117 118typedef enum { 119 SA_PARAM_NONE = 0x00, 120 SA_PARAM_BLOCKSIZE = 0x01, 121 SA_PARAM_DENSITY = 0x02, 122 SA_PARAM_COMPRESSION = 0x04, 123 SA_PARAM_BUFF_MODE = 0x08, 124 SA_PARAM_NUMBLOCKS = 0x10, 125 SA_PARAM_WP = 0x20, 126 SA_PARAM_SPEED = 0x40, 127 SA_PARAM_ALL = 0x7f 128} sa_params; 129 130typedef enum { 131 SA_QUIRK_NONE = 0x00, 132 SA_QUIRK_NOCOMP = 0x01, /* can't deal with compression at all */ 133 SA_QUIRK_FIXED = 0x02, /* force fixed mode */ 134 SA_QUIRK_VARIABLE = 0x04, /* force variable mode */ 135 SA_QUIRK_2FM = 0x05 /* Two File Marks at EOD */ 136} sa_quirks; 137 138struct sa_softc { 139 sa_state state; 140 sa_flags flags; 141 sa_quirks quirks; 142 struct buf_queue_head buf_queue; 143 struct devstat device_stats; 144 int blk_gran; 145 int blk_mask; 146 int blk_shift; 147 u_int32_t max_blk; 148 u_int32_t min_blk; 149 u_int32_t comp_algorithm; 150 u_int32_t saved_comp_algorithm; 151 u_int32_t media_blksize; 152 u_int32_t last_media_blksize; 153 u_int32_t media_numblks; 154 u_int8_t media_density; 155 u_int8_t speed; 156 u_int8_t scsi_rev; 157 int buffer_mode; 158 int filemarks; 159 union ccb saved_ccb; 160}; 161 162struct sa_quirk_entry { 163 struct scsi_inquiry_pattern inq_pat; 164 sa_quirks quirks; 165}; 166 167static struct sa_quirk_entry sa_quirk_table[] = 168{ 169 { 170 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE", 171 "Python 25601*", "*"}, SA_QUIRK_NOCOMP 172 }, 173 { 174 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 175 " TDC 3600", "U07:"}, SA_QUIRK_NOCOMP 176 } 177}; 178 179static d_open_t saopen; 180static d_read_t saread; 181static d_write_t sawrite; 182static d_close_t saclose; 183static d_strategy_t sastrategy; 184static d_ioctl_t saioctl; 185static periph_init_t sainit; 186static periph_ctor_t saregister; 187static periph_oninv_t saoninvalidate; 188static periph_dtor_t sacleanup; 189static periph_start_t sastart; 190static void saasync(void *callback_arg, u_int32_t code, 191 struct cam_path *path, void *arg); 192static void sadone(struct cam_periph *periph, 193 union ccb *start_ccb); 194static int saerror(union ccb *ccb, u_int32_t cam_flags, 195 u_int32_t sense_flags); 196static int sacheckeod(struct cam_periph *periph); 197static int sagetparams(struct cam_periph *periph, 198 sa_params params_to_get, 199 u_int32_t *blocksize, u_int8_t *density, 200 u_int32_t *numblocks, int *buff_mode, 201 u_int8_t *write_protect, u_int8_t *speed, 202 int *comp_supported, int *comp_enabled, 203 u_int32_t *comp_algorithm, 204 struct scsi_data_compression_page *comp_page); 205static int sasetparams(struct cam_periph *periph, 206 sa_params params_to_set, 207 u_int32_t blocksize, u_int8_t density, 208 u_int32_t comp_algorithm); 209static void saprevent(struct cam_periph *periph, int action); 210static int sarewind(struct cam_periph *periph); 211static int saspace(struct cam_periph *periph, int count, 212 scsi_space_code code); 213static int samount(struct cam_periph *, int, dev_t); 214static int saretension(struct cam_periph *periph); 215static int sareservereleaseunit(struct cam_periph *periph, 216 int reserve); 217static int saloadunload(struct cam_periph *periph, int load); 218static int saerase(struct cam_periph *periph, int longerase); 219static int sawritefilemarks(struct cam_periph *periph, 220 int nmarks, int setmarks); 221static int sardpos(struct cam_periph *periph, int, u_int32_t *); 222static int sasetpos(struct cam_periph *periph, int, u_int32_t *); 223 224 225static struct periph_driver sadriver = 226{ 227 sainit, "sa", 228 TAILQ_HEAD_INITIALIZER(sadriver.units), /* generation */ 0 229}; 230 231DATA_SET(periphdriver_set, sadriver); 232 233#define SAUNIT(DEV) ((minor(DEV)&0xF0) >> 4) /* 4 bit unit. */ 234#define SASETUNIT(DEV, U) makedev(major(DEV), ((U) << 4)) 235 236#define SAMODE(z) ((minor(z) & 0x03)) 237#define SADENSITY(z) (((minor(z) >> 2) & 0x03)) 238 239/* For 2.2-stable support */ 240#ifndef D_TAPE 241#define D_TAPE 0 242#endif 243 244#define CTLMODE 3 245#define SA_CDEV_MAJOR 14 246#define SA_BDEV_MAJOR 5 247 248static struct cdevsw sa_cdevsw = 249{ 250 /*d_open*/ saopen, 251 /*d_close*/ saclose, 252 /*d_read*/ saread, 253 /*d_write*/ sawrite, 254 /*d_ioctl*/ saioctl, 255 /*d_stop*/ nostop, 256 /*d_reset*/ noreset, 257 /*d_devtotty*/ nodevtotty, 258 /*d_poll*/ seltrue, 259 /*d_mmap*/ nommap, 260 /*d_strategy*/ sastrategy, 261 /*d_name*/ "sa", 262 /*d_spare*/ NULL, 263 /*d_maj*/ -1, 264 /*d_dump*/ nodump, 265 /*d_psize*/ nopsize, 266 /*d_flags*/ D_TAPE, 267 /*d_maxio*/ 0, 268 /*b_maj*/ -1 269}; 270 271static struct extend_array *saperiphs; 272 273static int 274saopen(dev_t dev, int flags, int fmt, struct proc *p) 275{ 276 struct cam_periph *periph; 277 struct sa_softc *softc; 278 int unit; 279 int mode; 280 int density; 281 int error; 282 int s; 283 284 unit = SAUNIT(dev); 285 mode = SAMODE(dev); 286 density = SADENSITY(dev); 287 288 periph = cam_extend_get(saperiphs, unit); 289 if (periph == NULL) 290 return (ENXIO); 291 292 softc = (struct sa_softc *)periph->softc; 293 294 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 295 ("saaopen: dev=0x%x (unit %d , mode %d, density %d)\n", dev, 296 unit, mode, density)); 297 298 s = splsoftcam(); 299 if (softc->flags & SA_FLAG_INVALID) { 300 splx(s); 301 return(ENXIO); 302 } 303 304 if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) { 305 splx(s); 306 return (error); /* error code from tsleep */ 307 } 308 309 splx(s); 310 311 if ((softc->flags & SA_FLAG_OPEN) == 0) { 312 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 313 return(ENXIO); 314 315 if ((error = sareservereleaseunit(periph, TRUE)) != 0) { 316 cam_periph_unlock(periph); 317 cam_periph_release(periph); 318 return(error); 319 } 320 } 321 322 if (error == 0) { 323 if ((softc->flags & SA_FLAG_OPEN) != 0) { 324 error = EBUSY; 325 } 326 327 if (error == 0) 328 error = samount(periph, flags, dev); 329 /* Perform other checking... */ 330 } 331 332 if (error == 0) { 333 saprevent(periph, PR_PREVENT); 334 softc->flags |= SA_FLAG_OPEN; 335 } 336 337 cam_periph_unlock(periph); 338 return (error); 339} 340 341static int 342saclose(dev_t dev, int flag, int fmt, struct proc *p) 343{ 344 struct cam_periph *periph; 345 struct sa_softc *softc; 346 int unit; 347 int mode; 348 int error; 349 350 unit = SAUNIT(dev); 351 mode = SAMODE(dev); 352 periph = cam_extend_get(saperiphs, unit); 353 if (periph == NULL) 354 return (ENXIO); 355 356 softc = (struct sa_softc *)periph->softc; 357 358 if ((error = cam_periph_lock(periph, PRIBIO)) != 0) { 359 return (error); /* error code from tsleep */ 360 } 361 362 /* 363 * See whether or not we need to write filemarks... 364 */ 365 error = sacheckeod(periph); 366 if (error) { 367 xpt_print_path(periph->path); 368 printf("failure at writing filemarks - opting for safety\n"); 369 mode = SA_MODE_OFFLINE; 370 } 371 372 /* 373 * Whatever we end up doing, allow users to eject tapes from here on. 374 */ 375 saprevent(periph, PR_ALLOW); 376 377 /* 378 * Decide how to end... 379 */ 380 switch (mode) { 381 default: 382 xpt_print_path(periph->path); 383 printf("unknown close mode %x- opting for safety\n", mode); 384 /* FALLTHROUGH */ 385 case SA_MODE_OFFLINE: 386 sarewind(periph); 387 saloadunload(periph, /*load*/FALSE); 388 break; 389 case SA_MODE_REWIND: 390 sarewind(periph); 391 break; 392 case SA_MODE_NOREWIND: 393 /* 394 * If we're not rewinding/unloading the tape, find out 395 * whether we need to back up over one of two filemarks 396 * we wrote (if we wrote two filemarks) so that appends 397 * from this point on will be sane. 398 */ 399 if ((softc->quirks & SA_QUIRK_2FM) && 400 (softc->flags & SA_FLAG_TAPE_WRITTEN)) { 401 error = saspace(periph, -1, SS_FILEMARKS); 402 if (error) { 403 xpt_print_path(periph->path); 404 printf("unable to backspace over one of double" 405 " filemarks at EOD- opting for safety\n"); 406 sarewind(periph); 407 saloadunload(periph, FALSE); 408 } 409 } 410 break; 411 } 412 413 /* 414 * We wish to note here that there are no filemarks written. 415 */ 416 softc->filemarks = 0; 417 418 /* 419 * And we are no longer open for business. 420 */ 421 422 softc->flags &= ~SA_FLAG_OPEN; 423 424 /* release the device */ 425 sareservereleaseunit(periph, FALSE); 426 427 cam_periph_unlock(periph); 428 cam_periph_release(periph); 429 430 return (0); 431} 432 433static int 434saread(dev_t dev, struct uio *uio, int ioflag) 435{ 436 return(physio(sastrategy, NULL, dev, 1, minphys, uio)); 437} 438 439static int 440sawrite(dev_t dev, struct uio *uio, int ioflag) 441{ 442 return(physio(sastrategy, NULL, dev, 0, minphys, uio)); 443} 444 445/* 446 * Actually translate the requested transfer into one the physical driver 447 * can understand. The transfer is described by a buf and will include 448 * only one physical transfer. 449 */ 450static void 451sastrategy(struct buf *bp) 452{ 453 struct cam_periph *periph; 454 struct sa_softc *softc; 455 u_int unit; 456 int s; 457 458 unit = SAUNIT(bp->b_dev); 459 periph = cam_extend_get(saperiphs, unit); 460 if (periph == NULL) { 461 bp->b_error = ENXIO; 462 goto bad; 463 } 464 softc = (struct sa_softc *)periph->softc; 465 466 s = splsoftcam(); 467 468 if (softc->flags & SA_FLAG_INVALID) { 469 splx(s); 470 bp->b_error = ENXIO; 471 goto bad; 472 } 473 474 splx(s); 475 476 /* 477 * If it's a null transfer, return immediatly 478 */ 479 if (bp->b_bcount == 0) 480 goto done; 481 482 /* valid request? */ 483 if (softc->flags & SA_FLAG_FIXED) { 484 /* 485 * Fixed block device. The byte count must 486 * be a multiple of our block size. 487 */ 488 if (((softc->blk_mask != ~0) 489 && ((bp->b_bcount & softc->blk_mask) != 0)) 490 || ((softc->blk_mask == ~0) 491 && ((bp->b_bcount % softc->min_blk) != 0))) { 492 xpt_print_path(periph->path); 493 printf("Invalid request. Fixed block device " 494 "requests must be a multiple " 495 "of %d bytes\n", softc->min_blk); 496 bp->b_error = EINVAL; 497 goto bad; 498 } 499 } else if ((bp->b_bcount > softc->max_blk) 500 || (bp->b_bcount < softc->min_blk) 501 || (bp->b_bcount & softc->blk_mask) != 0) { 502 503 xpt_print_path(periph->path); 504 printf("Invalid request. Variable block device " 505 "requests must be "); 506 if (softc->blk_mask != 0) { 507 printf("a multiple of %d ", 508 (0x1 << softc->blk_gran)); 509 } 510 printf("between %d and %d bytes\n", 511 softc->min_blk, softc->max_blk); 512 bp->b_error = EINVAL; 513 goto bad; 514 } 515 516 /* 517 * Mask interrupts so that the pack cannot be invalidated until 518 * after we are in the queue. Otherwise, we might not properly 519 * clean up one of the buffers. 520 */ 521 s = splbio(); 522 523 /* 524 * Place it in the queue of disk activities for this disk 525 */ 526 bufq_insert_tail(&softc->buf_queue, bp); 527 528 splx(s); 529 530 /* 531 * Schedule ourselves for performing the work. 532 */ 533 xpt_schedule(periph, /* XXX priority */1); 534 535 return; 536bad: 537 bp->b_flags |= B_ERROR; 538done: 539 540 /* 541 * Correctly set the buf to indicate a completed xfer 542 */ 543 bp->b_resid = bp->b_bcount; 544 biodone(bp); 545} 546 547static int 548saioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) 549{ 550 struct cam_periph *periph; 551 struct sa_softc *softc; 552 int unit; 553 int mode; 554 int density; 555 int error; 556 557 unit = SAUNIT(dev); 558 mode = SAMODE(dev); 559 density = SADENSITY(dev); 560 561 periph = cam_extend_get(saperiphs, unit); 562 if (periph == NULL) 563 return (ENXIO); 564 565 softc = (struct sa_softc *)periph->softc; 566 567 /* 568 * Find the device that the user is talking about 569 */ 570 switch (cmd) { 571 case MTIOCGET: 572 { 573 struct mtget *g = (struct mtget *)arg; 574 575 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 576 ("saioctl: MTIOGET\n")); 577 578 bzero(g, sizeof(struct mtget)); 579 g->mt_type = MT_ISAR; /* Don't ask */ 580 g->mt_density = softc->media_density; 581 g->mt_blksiz = softc->media_blksize; 582 if (softc->flags & SA_FLAG_COMP_UNSUPP) { 583 g->mt_comp = MT_COMP_UNSUPP; 584 g->mt_comp0 = MT_COMP_UNSUPP; 585 g->mt_comp1 = MT_COMP_UNSUPP; 586 g->mt_comp2 = MT_COMP_UNSUPP; 587 g->mt_comp3 = MT_COMP_UNSUPP; 588 } else if ((softc->flags & SA_FLAG_COMP_ENABLED) == 0) { 589 g->mt_comp = MT_COMP_DISABLED; 590 g->mt_comp0 = MT_COMP_DISABLED; 591 g->mt_comp1 = MT_COMP_DISABLED; 592 g->mt_comp2 = MT_COMP_DISABLED; 593 g->mt_comp3 = MT_COMP_DISABLED; 594 } else { 595 g->mt_comp = softc->comp_algorithm; 596 g->mt_comp0 = softc->comp_algorithm; 597 g->mt_comp1 = softc->comp_algorithm; 598 g->mt_comp2 = softc->comp_algorithm; 599 g->mt_comp3 = softc->comp_algorithm; 600 } 601 g->mt_density0 = softc->media_density; 602 g->mt_density1 = softc->media_density; 603 g->mt_density2 = softc->media_density; 604 g->mt_density3 = softc->media_density; 605 g->mt_blksiz0 = softc->media_blksize; 606 g->mt_blksiz1 = softc->media_blksize; 607 g->mt_blksiz2 = softc->media_blksize; 608 g->mt_blksiz3 = softc->media_blksize; 609 error = 0; 610 break; 611 } 612 case MTIOCTOP: 613 { 614 struct mtop *mt; 615 int count; 616 617 mt = (struct mtop *)arg; 618 619 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 620 ("saioctl: op=0x%x count=0x%x\n", 621 mt->mt_op, mt->mt_count)); 622 623 count = mt->mt_count; 624 switch (mt->mt_op) { 625 case MTWEOF: /* write an end-of-file marker */ 626 error = sawritefilemarks(periph, count, FALSE); 627 break; 628 case MTBSR: /* backward space record */ 629 case MTFSR: /* forward space record */ 630 case MTBSF: /* backward space file */ 631 case MTFSF: /* forward space file */ 632 case MTEOD: /* space to end of recorded medium */ 633 { 634 int nmarks; 635 scsi_space_code spaceop; 636 637 nmarks = softc->filemarks; 638 error = sacheckeod(periph); 639 if (error) { 640 xpt_print_path(periph->path); 641 printf("EOD check prior to spacing failed\n"); 642 softc->flags |= SA_FLAG_EIO_PENDING; 643 break; 644 } 645 nmarks -= softc->filemarks; 646 /* 647 * XXX: This very interestingly treats filemarks as 648 * XXX: marks we can just BSR over if the op is indeed 649 * XXX: a MTBSR. 650 */ 651 if ((mt->mt_op == MTBSR) || (mt->mt_op == MTBSF)) 652 count = -count; 653 654 if ((mt->mt_op == MTBSF) || (mt->mt_op == MTFSF)) 655 spaceop = SS_FILEMARKS; 656 else if ((mt->mt_op == MTBSR) || (mt->mt_op == MTFSR)) 657 spaceop = SS_BLOCKS; 658 else { 659 spaceop = SS_EOD; 660 count = 0; 661 nmarks = 0; 662 } 663 664 nmarks = softc->filemarks; 665 error = sacheckeod(periph); 666 nmarks -= softc->filemarks; 667 if (error == 0) 668 error = saspace(periph, count - nmarks, 669 spaceop); 670 /* 671 * At this point, clear that we've written the tape 672 * and that we've written any filemarks. We really 673 * don't know what the applications wishes to do next- 674 * the sacheckeod's will make sure we terminated the 675 * tape correctly if we'd been writing, but the next 676 * action the user application takes will set again 677 * whether we need to write filemarks. 678 */ 679 softc->flags &= ~SA_FLAG_TAPE_WRITTEN; 680 softc->filemarks = 0; 681 break; 682 } 683 case MTREW: /* rewind */ 684 (void) sacheckeod(periph); 685 error = sarewind(periph); 686 /* see above */ 687 softc->flags &= ~SA_FLAG_TAPE_WRITTEN; 688 softc->filemarks = 0; 689 break; 690 case MTERASE: /* erase */ 691 error = saerase(periph, count); 692 break; 693 case MTRETENS: /* re-tension tape */ 694 error = saretension(periph); 695 break; 696 case MTOFFL: /* rewind and put the drive offline */ 697 698 (void) sacheckeod(periph); 699 /* see above */ 700 softc->flags &= ~SA_FLAG_TAPE_WRITTEN; 701 softc->filemarks = 0; 702 703 /* 704 * Be sure to allow media removal before 705 * attempting the eject. 706 */ 707 saprevent(periph, PR_ALLOW); 708 error = sarewind(periph); 709 710 if (error == 0) 711 error = saloadunload(periph, /*load*/FALSE); 712 else 713 break; 714 715 softc->flags &= ~SA_FLAG_TAPE_LOCKED; 716 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 717 break; 718 case MTNOP: /* no operation, sets status only */ 719 case MTCACHE: /* enable controller cache */ 720 case MTNOCACHE: /* disable controller cache */ 721 error = 0; 722 break; 723 case MTSETBSIZ: /* Set block size for device */ 724 725 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, count, 726 0, 0); 727 if (error == 0) { 728 softc->last_media_blksize = 729 softc->media_blksize; 730 softc->media_blksize = count; 731 if (count) { 732 softc->flags |= SA_FLAG_FIXED; 733 if (powerof2(count)) { 734 softc->blk_shift = 735 ffs(count) - 1; 736 softc->blk_mask = count - 1; 737 } else { 738 softc->blk_mask = ~0; 739 softc->blk_shift = 0; 740 } 741 /* 742 * Make the user's desire 'persistent'. 743 */ 744 softc->quirks &= ~SA_QUIRK_VARIABLE; 745 softc->quirks |= SA_QUIRK_FIXED; 746 } else { 747 softc->flags &= ~SA_FLAG_FIXED; 748 if (softc->max_blk == 0) { 749 softc->max_blk = ~0; 750 } 751 softc->blk_shift = 0; 752 if (softc->blk_gran != 0) { 753 softc->blk_mask = 754 softc->blk_gran - 1; 755 } else { 756 softc->blk_mask = 0; 757 } 758 /* 759 * Make the user's desire 'persistent'. 760 */ 761 softc->quirks |= SA_QUIRK_VARIABLE; 762 softc->quirks &= ~SA_QUIRK_FIXED; 763 } 764 } 765 break; 766 case MTSETDNSTY: /* Set density for device and mode */ 767 if (count > UCHAR_MAX) { 768 error = EINVAL; 769 break; 770 } else { 771 error = sasetparams(periph, SA_PARAM_DENSITY, 772 0, count, 0); 773 } 774 break; 775 case MTCOMP: /* enable compression */ 776 /* 777 * Some devices don't support compression, and 778 * don't like it if you ask them for the 779 * compression page. 780 */ 781 if ((softc->quirks & SA_QUIRK_NOCOMP) 782 || (softc->flags & SA_FLAG_COMP_UNSUPP)) { 783 error = ENODEV; 784 break; 785 } 786 error = sasetparams(periph, SA_PARAM_COMPRESSION, 787 0, 0, count); 788 break; 789 default: 790 error = EINVAL; 791 } 792 break; 793 } 794 case MTIOCIEOT: 795 case MTIOCEEOT: 796 error = 0; 797 break; 798 case MTIOCRDSPOS: 799 error = sardpos(periph, 0, (u_int32_t *) arg); 800 break; 801 case MTIOCRDHPOS: 802 error = sardpos(periph, 1, (u_int32_t *) arg); 803 break; 804 case MTIOCSLOCATE: 805 error = sasetpos(periph, 0, (u_int32_t *) arg); 806 break; 807 case MTIOCHLOCATE: 808 error = sasetpos(periph, 1, (u_int32_t *) arg); 809 break; 810 default: 811 error = cam_periph_ioctl(periph, cmd, arg, saerror); 812 break; 813 } 814 return (error); 815} 816 817static void 818sainit(void) 819{ 820 cam_status status; 821 struct cam_path *path; 822 823 /* 824 * Create our extend array for storing the devices we attach to. 825 */ 826 saperiphs = cam_extend_new(); 827 if (saperiphs == NULL) { 828 printf("sa: Failed to alloc extend array!\n"); 829 return; 830 } 831 832 /* 833 * Install a global async callback. 834 */ 835 status = xpt_create_path(&path, NULL, CAM_XPT_PATH_ID, 836 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 837 838 if (status == CAM_REQ_CMP) { 839 /* Register the async callbacks of interrest */ 840 struct ccb_setasync csa; /* 841 * This is an immediate CCB, 842 * so using the stack is OK 843 */ 844 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 845 csa.ccb_h.func_code = XPT_SASYNC_CB; 846 csa.event_enable = AC_FOUND_DEVICE; 847 csa.callback = saasync; 848 csa.callback_arg = NULL; 849 xpt_action((union ccb *)&csa); 850 status = csa.ccb_h.status; 851 xpt_free_path(path); 852 } 853 854 if (status != CAM_REQ_CMP) { 855 printf("sa: Failed to attach master async callback " 856 "due to status 0x%x!\n", status); 857 } else { 858 /* If we were successfull, register our devsw */ 859 cdevsw_add_generic(SA_BDEV_MAJOR, SA_CDEV_MAJOR, &sa_cdevsw); 860 } 861} 862 863static void 864saoninvalidate(struct cam_periph *periph) 865{ 866 struct sa_softc *softc; 867 struct buf *q_bp; 868 struct ccb_setasync csa; 869 int s; 870 871 softc = (struct sa_softc *)periph->softc; 872 873 /* 874 * De-register any async callbacks. 875 */ 876 xpt_setup_ccb(&csa.ccb_h, periph->path, 877 /* priority */ 5); 878 csa.ccb_h.func_code = XPT_SASYNC_CB; 879 csa.event_enable = 0; 880 csa.callback = saasync; 881 csa.callback_arg = periph; 882 xpt_action((union ccb *)&csa); 883 884 softc->flags |= SA_FLAG_INVALID; 885 886 /* 887 * Although the oninvalidate() routines are always called at 888 * splsoftcam, we need to be at splbio() here to keep the buffer 889 * queue from being modified while we traverse it. 890 */ 891 s = splbio(); 892 893 /* 894 * Return all queued I/O with ENXIO. 895 * XXX Handle any transactions queued to the card 896 * with XPT_ABORT_CCB. 897 */ 898 while ((q_bp = bufq_first(&softc->buf_queue)) != NULL){ 899 bufq_remove(&softc->buf_queue, q_bp); 900 q_bp->b_resid = q_bp->b_bcount; 901 q_bp->b_error = ENXIO; 902 q_bp->b_flags |= B_ERROR; 903 biodone(q_bp); 904 } 905 splx(s); 906 907 xpt_print_path(periph->path); 908 printf("lost device\n"); 909 910} 911 912static void 913sacleanup(struct cam_periph *periph) 914{ 915 struct sa_softc *softc; 916 917 softc = (struct sa_softc *)periph->softc; 918 919 devstat_remove_entry(&softc->device_stats); 920 cam_extend_release(saperiphs, periph->unit_number); 921 xpt_print_path(periph->path); 922 printf("removing device entry\n"); 923 free(softc, M_DEVBUF); 924} 925 926static void 927saasync(void *callback_arg, u_int32_t code, 928 struct cam_path *path, void *arg) 929{ 930 struct cam_periph *periph; 931 932 periph = (struct cam_periph *)callback_arg; 933 switch (code) { 934 case AC_FOUND_DEVICE: 935 { 936 struct ccb_getdev *cgd; 937 cam_status status; 938 939 cgd = (struct ccb_getdev *)arg; 940 941 if (cgd->pd_type != T_SEQUENTIAL) 942 break; 943 944 /* 945 * Allocate a peripheral instance for 946 * this device and start the probe 947 * process. 948 */ 949 status = cam_periph_alloc(saregister, saoninvalidate, 950 sacleanup, sastart, 951 "sa", CAM_PERIPH_BIO, cgd->ccb_h.path, 952 saasync, AC_FOUND_DEVICE, cgd); 953 954 if (status != CAM_REQ_CMP 955 && status != CAM_REQ_INPROG) 956 printf("saasync: Unable to probe new device " 957 "due to status 0x%x\n", status); 958 break; 959 } 960 case AC_LOST_DEVICE: 961 cam_periph_invalidate(periph); 962 break; 963 case AC_TRANSFER_NEG: 964 case AC_SENT_BDR: 965 case AC_SCSI_AEN: 966 case AC_UNSOL_RESEL: 967 case AC_BUS_RESET: 968 default: 969 break; 970 } 971} 972 973static cam_status 974saregister(struct cam_periph *periph, void *arg) 975{ 976 struct sa_softc *softc; 977 struct ccb_setasync csa; 978 struct ccb_getdev *cgd; 979 caddr_t match; 980 981 cgd = (struct ccb_getdev *)arg; 982 if (periph == NULL) { 983 printf("saregister: periph was NULL!!\n"); 984 return(CAM_REQ_CMP_ERR); 985 } 986 987 if (cgd == NULL) { 988 printf("saregister: no getdev CCB, can't register device\n"); 989 return(CAM_REQ_CMP_ERR); 990 } 991 992 softc = (struct sa_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT); 993 994 if (softc == NULL) { 995 printf("saregister: Unable to probe new device. " 996 "Unable to allocate softc\n"); 997 return(CAM_REQ_CMP_ERR); 998 } 999 1000 bzero(softc, sizeof(*softc)); 1001 softc->scsi_rev = SID_ANSI_REV(&cgd->inq_data); 1002 softc->state = SA_STATE_NORMAL; 1003 bufq_init(&softc->buf_queue); 1004 periph->softc = softc; 1005 cam_extend_set(saperiphs, periph->unit_number, periph); 1006 1007 /* 1008 * See if this device has any quirks. 1009 */ 1010 match = cam_quirkmatch((caddr_t)&cgd->inq_data, 1011 (caddr_t)sa_quirk_table, 1012 sizeof(sa_quirk_table)/sizeof(*sa_quirk_table), 1013 sizeof(*sa_quirk_table), scsi_inquiry_match); 1014 1015 if (match != NULL) 1016 softc->quirks = ((struct sa_quirk_entry *)match)->quirks; 1017 else 1018 softc->quirks = SA_QUIRK_NONE; 1019 1020 /* 1021 * The SA driver supports a blocksize, but we don't know the 1022 * blocksize until we sense the media. So, set a flag to 1023 * indicate that the blocksize is unavailable right now. 1024 * We'll clear the flag as soon as we've done a read capacity. 1025 */ 1026 devstat_add_entry(&softc->device_stats, "sa", 1027 periph->unit_number, 0, 1028 DEVSTAT_BS_UNAVAILABLE, 1029 cgd->pd_type | DEVSTAT_TYPE_IF_SCSI); 1030 1031 /* 1032 * Add an async callback so that we get 1033 * notified if this device goes away. 1034 */ 1035 xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5); 1036 csa.ccb_h.func_code = XPT_SASYNC_CB; 1037 csa.event_enable = AC_LOST_DEVICE; 1038 csa.callback = saasync; 1039 csa.callback_arg = periph; 1040 xpt_action((union ccb *)&csa); 1041 1042 xpt_announce_periph(periph, NULL); 1043 1044 return(CAM_REQ_CMP); 1045} 1046 1047static void 1048sastart(struct cam_periph *periph, union ccb *start_ccb) 1049{ 1050 struct sa_softc *softc; 1051 1052 softc = (struct sa_softc *)periph->softc; 1053 1054 1055 switch (softc->state) { 1056 case SA_STATE_NORMAL: 1057 { 1058 /* Pull a buffer from the queue and get going on it */ 1059 struct buf *bp; 1060 int s; 1061 1062 /* 1063 * See if there is a buf with work for us to do.. 1064 */ 1065 s = splbio(); 1066 bp = bufq_first(&softc->buf_queue); 1067 if (periph->immediate_priority <= periph->pinfo.priority) { 1068 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, 1069 ("queuing for immediate ccb\n")); 1070 start_ccb->ccb_h.ccb_type = SA_CCB_WAITING; 1071 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 1072 periph_links.sle); 1073 periph->immediate_priority = CAM_PRIORITY_NONE; 1074 splx(s); 1075 wakeup(&periph->ccb_list); 1076 } else if (bp == NULL) { 1077 splx(s); 1078 xpt_release_ccb(start_ccb); 1079 } else if ((softc->flags & SA_FLAG_ERR_PENDING) != 0) { 1080 1081 bufq_remove(&softc->buf_queue, bp); 1082 bp->b_resid = bp->b_bcount; 1083 bp->b_flags |= B_ERROR; 1084 if ((softc->flags & SA_FLAG_EOM_PENDING) != 0) { 1085 if ((bp->b_flags & B_READ) == 0) 1086 bp->b_error = ENOSPC; 1087 } 1088 if ((softc->flags & SA_FLAG_EIO_PENDING) != 0) { 1089 bp->b_error = EIO; 1090 } 1091 softc->flags &= ~SA_FLAG_ERR_PENDING; 1092 bp = bufq_first(&softc->buf_queue); 1093 splx(s); 1094 biodone(bp); 1095 } else { 1096 u_int32_t length; 1097 1098 bufq_remove(&softc->buf_queue, bp); 1099 1100 if ((softc->flags & SA_FLAG_FIXED) != 0) { 1101 if (softc->blk_shift != 0) { 1102 length = 1103 bp->b_bcount >> softc->blk_shift; 1104 } else { 1105 if (softc->media_blksize == 0) { 1106 bp->b_error = EIO; 1107 xpt_print_path(periph->path); 1108 printf("zero blocksize for " 1109 "FIXED length writes?\n"); 1110 splx(s); 1111 biodone(bp); 1112 break; 1113 } 1114 length = 1115 bp->b_bcount / softc->media_blksize; 1116 } 1117 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1118 ("Fixed Record Count is %d\n", length)); 1119 } else { 1120 length = bp->b_bcount; 1121 CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO, 1122 ("Variable Record Count is %d\n", length)); 1123 } 1124 1125 devstat_start_transaction(&softc->device_stats); 1126 1127 /* 1128 * Some people have theorized that we should 1129 * suppress illegal length indication if we are 1130 * running in variable block mode so that we don't 1131 * have to request sense every time our requested 1132 * block size is larger than the written block. 1133 * The residual information from the ccb allows 1134 * us to identify this situation anyway. The only 1135 * problem with this is that we will not get 1136 * information about blocks that are larger than 1137 * our read buffer unless we set the block size 1138 * in the mode page to something other than 0. 1139 * 1140 * I believe that this is a non-issue. If user apps 1141 * don't adjust their read size to match our record 1142 * size, that's just life. Anyway, the typical usage 1143 * would be to issue, e.g., 64KB reads and occasionally 1144 * have to do deal with 512 byte or 1KB intermediate 1145 * records. 1146 */ 1147 scsi_sa_read_write(&start_ccb->csio, 1148 /*retries*/4, 1149 sadone, 1150 MSG_SIMPLE_Q_TAG, 1151 bp->b_flags & B_READ, 1152 /*SILI*/FALSE, 1153 softc->flags & SA_FLAG_FIXED, 1154 length, 1155 bp->b_data, 1156 bp->b_bcount, 1157 SSD_FULL_SIZE, 1158 120 * 60 * 1000); /* 2min */ 1159 start_ccb->ccb_h.ccb_type = SA_CCB_BUFFER_IO; 1160 start_ccb->ccb_h.ccb_bp = bp; 1161 bp = bufq_first(&softc->buf_queue); 1162 splx(s); 1163 1164 xpt_action(start_ccb); 1165 } 1166 1167 if (bp != NULL) { 1168 /* Have more work to do, so ensure we stay scheduled */ 1169 xpt_schedule(periph, /* XXX priority */1); 1170 } 1171 break; 1172 } 1173 } 1174} 1175 1176 1177static void 1178sadone(struct cam_periph *periph, union ccb *done_ccb) 1179{ 1180 struct sa_softc *softc; 1181 struct ccb_scsiio *csio; 1182 1183 softc = (struct sa_softc *)periph->softc; 1184 csio = &done_ccb->csio; 1185 switch (csio->ccb_h.ccb_type) { 1186 case SA_CCB_BUFFER_IO: 1187 { 1188 struct buf *bp; 1189 int error; 1190 1191 bp = (struct buf *)done_ccb->ccb_h.ccb_bp; 1192 error = 0; 1193 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1194 if ((error = saerror(done_ccb, 0, 0)) == ERESTART) { 1195 /* 1196 * A retry was scheuled, so 1197 * just return. 1198 */ 1199 return; 1200 } 1201 } 1202 1203 if (error == EIO) { 1204 int s; 1205 struct buf *q_bp; 1206 1207 /* 1208 * Catastrophic error. Mark our pack as invalid, 1209 * return all queued I/O with EIO, and unfreeze 1210 * our queue so that future transactions that 1211 * attempt to fix this problem can get to the 1212 * device. 1213 * 1214 */ 1215 1216 s = splbio(); 1217 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 1218 1219 while ((q_bp = bufq_first(&softc->buf_queue)) != NULL) { 1220 bufq_remove(&softc->buf_queue, q_bp); 1221 q_bp->b_resid = q_bp->b_bcount; 1222 q_bp->b_error = EIO; 1223 q_bp->b_flags |= B_ERROR; 1224 biodone(q_bp); 1225 } 1226 splx(s); 1227 } 1228 if (error != 0) { 1229 bp->b_resid = bp->b_bcount; 1230 bp->b_error = error; 1231 bp->b_flags |= B_ERROR; 1232 cam_release_devq(done_ccb->ccb_h.path, 1233 /*relsim_flags*/0, 1234 /*reduction*/0, 1235 /*timeout*/0, 1236 /*getcount_only*/0); 1237 } else { 1238 bp->b_resid = csio->resid; 1239 bp->b_error = 0; 1240 if (csio->resid != 0) { 1241 bp->b_flags |= B_ERROR; 1242 } 1243 if ((bp->b_flags & B_READ) == 0) { 1244 softc->flags |= SA_FLAG_TAPE_WRITTEN; 1245 softc->filemarks = 0; 1246 } 1247 } 1248#ifdef CAMDEBUG 1249 if (error || bp->b_resid) { 1250 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1251 ("error %d resid %ld count %ld\n", error, 1252 bp->b_resid, bp->b_bcount)); 1253 } 1254#endif 1255 1256 devstat_end_transaction(&softc->device_stats, 1257 bp->b_bcount - bp->b_resid, 1258 done_ccb->csio.tag_action & 0xf, 1259 (bp->b_flags & B_READ) ? DEVSTAT_READ 1260 : DEVSTAT_WRITE); 1261 biodone(bp); 1262 break; 1263 } 1264 case SA_CCB_WAITING: 1265 { 1266 /* Caller will release the CCB */ 1267 wakeup(&done_ccb->ccb_h.cbfcnp); 1268 return; 1269 } 1270 } 1271 xpt_release_ccb(done_ccb); 1272} 1273 1274 1275/* 1276 * Mount the tape (make sure it's ready for I/O). 1277 */ 1278static int 1279samount(struct cam_periph *periph, int oflags, dev_t dev) 1280{ 1281 struct sa_softc *softc; 1282 union ccb *ccb; 1283 struct ccb_scsiio *csio; 1284 int error; 1285 1286 /* 1287 * oflags can be checked for 'kind' of open (read-only check) - later 1288 * dev can be checked for a control-mode or compression open - later 1289 */ 1290 UNUSED_PARAMETER(oflags); 1291 UNUSED_PARAMETER(dev); 1292 1293 1294 softc = (struct sa_softc *)periph->softc; 1295 ccb = cam_periph_getccb(periph, /* priority */1); 1296 csio = &ccb->csio; 1297 error = 0; 1298 1299 /* 1300 * Determine if something has happend since the last 1301 * open/mount that would invalidate a mount. This 1302 * will also eat any pending UAs. 1303 */ 1304 scsi_test_unit_ready(csio, 1305 /*retries*/1, 1306 sadone, 1307 MSG_SIMPLE_Q_TAG, 1308 SSD_FULL_SIZE, 1309 /*timeout*/5000); 1310 1311 cam_periph_runccb(ccb, /*error handler*/NULL, /*cam_flags*/0, 1312 /*sense_flags*/0, &softc->device_stats); 1313 1314 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1315 cam_release_devq(ccb->ccb_h.path, 1316 /*relsim_flags*/0, 1317 /*reduction*/0, 1318 /*timeout*/0, 1319 /*getcount_only*/0); 1320 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 1321 } 1322 1323 if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) { 1324 struct scsi_read_block_limits_data *rblim; 1325 int comp_enabled, comp_supported; 1326 u_int8_t write_protect, guessing = 0; 1327 1328 /* 1329 * Clear out old state. 1330 */ 1331 softc->flags &= ~(SA_FLAG_TAPE_WP|SA_FLAG_TAPE_WRITTEN| 1332 SA_FLAG_ERR_PENDING|SA_FLAG_COMP_ENABLED| 1333 SA_FLAG_COMP_UNSUPP); 1334 softc->filemarks = 0; 1335 1336 /* 1337 * First off, determine block limits. 1338 */ 1339 rblim = (struct scsi_read_block_limits_data *) 1340 malloc(sizeof(*rblim), M_TEMP, M_WAITOK); 1341 1342 scsi_read_block_limits(csio, 1343 /*retries*/1, 1344 sadone, 1345 MSG_SIMPLE_Q_TAG, 1346 rblim, 1347 SSD_FULL_SIZE, 1348 /*timeout*/5000); 1349 1350 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 1351 /*sense_flags*/SF_RETRY_UA, 1352 &softc->device_stats); 1353 1354 xpt_release_ccb(ccb); 1355 1356 if (error != 0) { 1357 /* 1358 * If it's less than SCSI-2, READ BLOCK LIMITS is not 1359 * a MANDATORY command. Anyway- it doesn't matter- 1360 * we can proceed anyway. 1361 */ 1362 softc->blk_gran = 0; 1363 softc->max_blk = ~0; 1364 softc->min_blk = 0; 1365 } else { 1366 if (softc->scsi_rev >= SCSI_REV_3) { 1367 softc->blk_gran = RBL_GRAN(rblim); 1368 } else { 1369 softc->blk_gran = 0; 1370 } 1371 /* 1372 * We take max_blk == min_blk to mean a default to 1373 * fixed mode- but note that whatever we get out of 1374 * sagetparams below will actually determine whether 1375 * we are actually *in* fixed mode. 1376 */ 1377 softc->max_blk = scsi_3btoul(rblim->maximum); 1378 softc->min_blk = scsi_2btoul(rblim->minimum); 1379 1380 1381 } 1382 /* 1383 * Next, perform a mode sense to determine 1384 * current density, blocksize, compression etc. 1385 */ 1386 error = sagetparams(periph, SA_PARAM_ALL, 1387 &softc->media_blksize, 1388 &softc->media_density, 1389 &softc->media_numblks, 1390 &softc->buffer_mode, &write_protect, 1391 &softc->speed, &comp_supported, 1392 &comp_enabled, &softc->comp_algorithm, 1393 NULL); 1394 1395 if (error != 0) { 1396 /* 1397 * We could work a little harder here. We could 1398 * adjust our attempts to get information. It 1399 * might be an ancient tape drive. If someone 1400 * nudges us, we'll do that. 1401 */ 1402 goto exit; 1403 } 1404 1405 /* 1406 * If no quirk has determined that this is a device that is 1407 * preferred to be in fixed or variable mode, now is the time 1408 * to find out. 1409 */ 1410 if ((softc->quirks & (SA_QUIRK_FIXED|SA_QUIRK_VARIABLE)) == 0) { 1411 guessing = 1; 1412 switch (softc->media_density) { 1413 case SCSI_DENSITY_QIC_11_4TRK: 1414 case SCSI_DENSITY_QIC_11_9TRK: 1415 case SCSI_DENSITY_QIC_24: 1416 case SCSI_DENSITY_QIC_120: 1417 case SCSI_DENSITY_QIC_150: 1418 softc->quirks |= SA_QUIRK_FIXED; 1419 softc->last_media_blksize = 512; 1420 break; 1421 default: 1422 softc->last_media_blksize = 1423 softc->media_blksize; 1424 softc->quirks |= SA_QUIRK_VARIABLE; 1425 break; 1426 } 1427 } 1428 /* 1429 * If no quirk has determined that this is a device that needs 1430 * to have 2 Filemarks at EOD, now is the time to find out. 1431 */ 1432 if ((softc->quirks & SA_QUIRK_2FM) != 0) { 1433 switch (softc->media_density) { 1434 case SCSI_DENSITY_HALFINCH_800: 1435 case SCSI_DENSITY_HALFINCH_1600: 1436 case SCSI_DENSITY_HALFINCH_6250: 1437 case SCSI_DENSITY_HALFINCH_6250C: 1438 case SCSI_DENSITY_HALFINCH_PE: 1439 softc->quirks |= SA_QUIRK_2FM; 1440 break; 1441 default: 1442 break; 1443 } 1444 } 1445 1446 /* 1447 * Now validate that some info we got makes sense. 1448 */ 1449 1450 if ((softc->max_blk < softc->media_blksize) || 1451 (softc->min_blk > softc->media_blksize && 1452 softc->media_blksize)) { 1453 xpt_print_path(ccb->ccb_h.path); 1454 printf("BLOCK LIMITS (%d..%d) could not match current " 1455 "block settings (%d)- adjusting\n", softc->min_blk, 1456 softc->max_blk, softc->media_blksize); 1457 softc->max_blk = softc->min_blk = 1458 softc->media_blksize; 1459 } 1460 1461 /* 1462 * Now put ourselves into the right frame of mind based 1463 * upon quirks... 1464 */ 1465tryagain: 1466 if ((softc->quirks & SA_QUIRK_FIXED) && 1467 (softc->media_blksize == 0)) { 1468 softc->media_blksize = softc->last_media_blksize; 1469 if (softc->media_blksize == 0) { 1470 softc->media_blksize = BLKDEV_IOSIZE; 1471 if (softc->media_blksize < softc->min_blk) { 1472 softc->media_blksize = softc->min_blk; 1473 } 1474 } 1475 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, 1476 softc->media_blksize, 0, 0); 1477 if (error) { 1478 xpt_print_path(ccb->ccb_h.path); 1479 printf("unable to set fixed blocksize to %d\n", 1480 softc->media_blksize); 1481 goto exit; 1482 } 1483 } 1484 1485 if ((softc->quirks & SA_QUIRK_VARIABLE) && 1486 (softc->media_blksize != 0)) { 1487 softc->last_media_blksize = softc->media_blksize; 1488 softc->media_blksize = 0; 1489 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, 1490 0, 0, 0); 1491 if (error) { 1492 /* 1493 * If this fails and we were guessing, just 1494 * assume that we got it wrong and go try 1495 * fixed block mode... 1496 */ 1497 xpt_print_path(ccb->ccb_h.path); 1498 if (guessing && softc->media_density == 1499 SCSI_DEFAULT_DENSITY) { 1500 softc->quirks &= ~SA_QUIRK_VARIABLE; 1501 softc->quirks |= SA_QUIRK_FIXED; 1502 if (softc->last_media_blksize == 0) 1503 softc->last_media_blksize = 512; 1504 goto tryagain; 1505 } 1506 printf("unable to set variable blocksize\n"); 1507 goto exit; 1508 } 1509 } 1510 1511 /* 1512 * Now that we have the current block size, 1513 * set up some parameters for sastart's usage. 1514 */ 1515 if (softc->media_blksize) { 1516 softc->flags |= SA_FLAG_FIXED; 1517 if (powerof2(softc->media_blksize)) { 1518 softc->blk_shift = 1519 ffs(softc->media_blksize) - 1; 1520 softc->blk_mask = softc->media_blksize - 1; 1521 } else { 1522 softc->blk_mask = ~0; 1523 softc->blk_shift = 0; 1524 } 1525 } else { 1526 /* 1527 * The SCSI-3 spec allows 0 to mean "unspecified". 1528 * The SCSI-1 spec allows 0 to mean 'infinite'. 1529 * 1530 * Either works here. 1531 */ 1532 if (softc->max_blk == 0) { 1533 softc->max_blk = ~0; 1534 } 1535 softc->blk_shift = 0; 1536 if (softc->blk_gran != 0) { 1537 softc->blk_mask = softc->blk_gran - 1; 1538 } else { 1539 softc->blk_mask = 0; 1540 } 1541 } 1542 1543 if (write_protect) 1544 softc->flags |= SA_FLAG_TAPE_WP; 1545 1546 if (comp_supported) { 1547 if (comp_enabled) { 1548 softc->flags |= SA_FLAG_COMP_ENABLED; 1549 1550 if (softc->saved_comp_algorithm == 0) 1551 softc->saved_comp_algorithm = 1552 softc->comp_algorithm; 1553 } 1554 } else 1555 softc->flags |= SA_FLAG_COMP_UNSUPP; 1556 1557 if (softc->buffer_mode == SMH_SA_BUF_MODE_NOBUF) { 1558 error = sasetparams(periph, SA_PARAM_BUFF_MODE, 0, 1559 0, 0); 1560 if (error == 0) 1561 softc->buffer_mode = SMH_SA_BUF_MODE_SIBUF; 1562 } 1563 1564 1565 if (error == 0) 1566 softc->flags |= SA_FLAG_TAPE_MOUNTED; 1567exit: 1568 if (rblim != NULL) 1569 free(rblim, M_TEMP); 1570 1571 if (error != 0) { 1572 cam_release_devq(ccb->ccb_h.path, 1573 /*relsim_flags*/0, 1574 /*reduction*/0, 1575 /*timeout*/0, 1576 /*getcount_only*/0); 1577 } 1578 } else 1579 xpt_release_ccb(ccb); 1580 1581 return (error); 1582} 1583 1584static int 1585sacheckeod(struct cam_periph *periph) 1586{ 1587 int error; 1588 int markswanted; 1589 struct sa_softc *softc; 1590 1591 softc = (struct sa_softc *)periph->softc; 1592 markswanted = 0; 1593 1594 if ((softc->flags & SA_FLAG_TAPE_WRITTEN) != 0) { 1595 markswanted++; 1596 if ((softc->quirks & SA_QUIRK_2FM) != 0) 1597 markswanted++; 1598 } 1599 1600 if (softc->filemarks < markswanted) { 1601 markswanted -= softc->filemarks; 1602 error = sawritefilemarks(periph, markswanted, FALSE); 1603 } else { 1604 error = 0; 1605 } 1606 return (error); 1607} 1608 1609static int 1610saerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 1611{ 1612 struct cam_periph *periph; 1613 struct sa_softc *softc; 1614 struct ccb_scsiio *csio; 1615 struct scsi_sense_data *sense; 1616 int error_code, sense_key, asc, ascq; 1617 int error; 1618 1619 periph = xpt_path_periph(ccb->ccb_h.path); 1620 softc = (struct sa_softc *)periph->softc; 1621 csio = &ccb->csio; 1622 sense = &csio->sense_data; 1623 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq); 1624 error = 0; 1625 1626 if (((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) 1627 && ((sense->flags & (SSD_EOM|SSD_FILEMARK|SSD_ILI)) != 0) 1628 && ((sense_key == SSD_KEY_NO_SENSE) 1629 || (sense_key == SSD_KEY_BLANK_CHECK))) { 1630 u_int32_t info; 1631 u_int32_t resid; 1632 int defer_action; 1633 1634 /* 1635 * Filter out some sense codes of interest. 1636 */ 1637 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) { 1638 info = scsi_4btoul(sense->info); 1639 resid = info; 1640 if ((softc->flags & SA_FLAG_FIXED) != 0) 1641 resid *= softc->media_blksize; 1642 } else { 1643 resid = csio->dxfer_len; 1644 info = resid; 1645 if ((softc->flags & SA_FLAG_FIXED) != 0) { 1646 if (softc->media_blksize) 1647 info /= softc->media_blksize; 1648 } 1649 } 1650 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1651 ("Key 0x%x ASC/ASCQ 0x%x 0x%x flags 0x%x resid %d " 1652 "dxfer_len %d\n", sense_key, asc, ascq, 1653 sense->flags & ~SSD_KEY_RESERVED, resid, csio->dxfer_len)); 1654 1655 if ((resid > 0 && resid < csio->dxfer_len) 1656 && (softc->flags & SA_FLAG_FIXED) != 0) 1657 defer_action = TRUE; 1658 else 1659 defer_action = FALSE; 1660 1661 if ((sense->flags & SSD_EOM) != 0 1662 || (sense_key == 0x8 /* BLANK CHECK*/)) { 1663 csio->resid = resid; 1664 if (defer_action) { 1665 softc->flags |= SA_FLAG_EOM_PENDING; 1666 } else { 1667 if (csio->cdb_io.cdb_bytes[0] == SA_WRITE) 1668 error = ENOSPC; 1669 } 1670 } 1671 if ((sense->flags & SSD_FILEMARK) != 0) { 1672 csio->resid = resid; 1673 if (defer_action) 1674 softc->flags |= SA_FLAG_EOF_PENDING; 1675 } 1676 if (sense->flags & SSD_ILI) { 1677 if (info < 0) { 1678 /* 1679 * The record was too big. 1680 */ 1681 xpt_print_path(csio->ccb_h.path); 1682 printf("%d-byte tape record bigger " 1683 "than suplied read buffer\n", 1684 csio->dxfer_len - info); 1685 csio->resid = csio->dxfer_len; 1686 error = EIO; 1687 } else { 1688 csio->resid = resid; 1689 if ((softc->flags & SA_FLAG_FIXED) != 0) { 1690 if (defer_action) 1691 softc->flags |= 1692 SA_FLAG_EIO_PENDING; 1693 else 1694 error = EIO; 1695 } 1696 } 1697 } 1698 } 1699 if (error == 0) 1700 error = cam_periph_error(ccb, cam_flags, sense_flags, 1701 &softc->saved_ccb); 1702 1703 return (error); 1704} 1705 1706static int 1707sagetparams(struct cam_periph *periph, sa_params params_to_get, 1708 u_int32_t *blocksize, u_int8_t *density, u_int32_t *numblocks, 1709 int *buff_mode, u_int8_t *write_protect, u_int8_t *speed, 1710 int *comp_supported, int *comp_enabled, u_int32_t *comp_algorithm, 1711 struct scsi_data_compression_page *comp_page) 1712{ 1713 union ccb *ccb; 1714 void *mode_buffer; 1715 struct scsi_mode_header_6 *mode_hdr; 1716 struct scsi_mode_blk_desc *mode_blk; 1717 struct scsi_data_compression_page *ncomp_page; 1718 int mode_buffer_len; 1719 struct sa_softc *softc; 1720 int error; 1721 cam_status status; 1722 1723 softc = (struct sa_softc *)periph->softc; 1724 1725 ccb = cam_periph_getccb(periph, /*priority*/ 1); 1726 1727retry: 1728 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk); 1729 1730 if (params_to_get & SA_PARAM_COMPRESSION) { 1731 if (softc->quirks & SA_QUIRK_NOCOMP) { 1732 *comp_supported = FALSE; 1733 params_to_get &= ~SA_PARAM_COMPRESSION; 1734 } else 1735 mode_buffer_len += 1736 sizeof(struct scsi_data_compression_page); 1737 } 1738 1739 mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK); 1740 1741 bzero(mode_buffer, mode_buffer_len); 1742 1743 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer; 1744 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1]; 1745 1746 if (params_to_get & SA_PARAM_COMPRESSION) 1747 ncomp_page = (struct scsi_data_compression_page *)&mode_blk[1]; 1748 else 1749 ncomp_page = NULL; 1750 1751 scsi_mode_sense(&ccb->csio, 1752 /*retries*/ 1, 1753 /*cbfcnp*/ sadone, 1754 /*tag_action*/ MSG_SIMPLE_Q_TAG, 1755 /*dbd*/ FALSE, 1756 /*page_code*/ SMS_PAGE_CTRL_CURRENT, 1757 /*page*/ (params_to_get & SA_PARAM_COMPRESSION) ? 1758 SA_DATA_COMPRESSION_PAGE : 1759 SMS_VENDOR_SPECIFIC_PAGE, 1760 /*param_buf*/ mode_buffer, 1761 /*param_len*/ mode_buffer_len, 1762 /*sense_len*/ SSD_FULL_SIZE, 1763 /*timeout*/ 5000); 1764 1765 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/ 0, 1766 /*sense_flags*/SF_NO_PRINT, 1767 &softc->device_stats); 1768 1769 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1770 cam_release_devq(ccb->ccb_h.path, 1771 /* relsim_flags */0, 1772 /* opening_reduction */0, 1773 /* timeout */0, 1774 /* getcount_only */ FALSE); 1775 1776 status = ccb->ccb_h.status & CAM_STATUS_MASK; 1777 1778 if (error == EINVAL 1779 && (params_to_get & SA_PARAM_COMPRESSION) != 0) { 1780 /* 1781 * Most likely doesn't support the compression 1782 * page. Remember this for the future and attempt 1783 * the request without asking for compression info. 1784 */ 1785 softc->quirks |= SA_QUIRK_NOCOMP; 1786 free(mode_buffer, M_TEMP); 1787 goto retry; 1788 } else if (error == 0) { 1789 struct scsi_data_compression_page *temp_comp_page; 1790 1791 temp_comp_page = NULL; 1792 1793 /* 1794 * If the user only wants the compression information, and 1795 * the device doesn't send back the block descriptor, it's 1796 * no big deal. If the user wants more than just 1797 * compression, though, and the device doesn't pass back the 1798 * block descriptor, we need to send another mode sense to 1799 * get the block descriptor. 1800 */ 1801 if ((mode_hdr->blk_desc_len == 0) 1802 && (params_to_get & SA_PARAM_COMPRESSION) 1803 && ((params_to_get & ~(SA_PARAM_COMPRESSION)) != 0)) { 1804 1805 /* 1806 * Decrease the mode buffer length by the size of 1807 * the compression page, to make sure the data 1808 * there doesn't get overwritten. 1809 */ 1810 mode_buffer_len -= sizeof(*ncomp_page); 1811 1812 /* 1813 * Now move the compression page that we presumably 1814 * got back down the memory chunk a little bit so 1815 * it doesn't get spammed. 1816 */ 1817 temp_comp_page = 1818 (struct scsi_data_compression_page *)&mode_hdr[1]; 1819 bcopy(temp_comp_page, ncomp_page, sizeof(*ncomp_page)); 1820 1821 /* 1822 * Now, we issue another mode sense and just ask 1823 * for the block descriptor, etc. 1824 */ 1825 scsi_mode_sense(&ccb->csio, 1826 /*retries*/ 1, 1827 /*cbfcnp*/ sadone, 1828 /*tag_action*/ MSG_SIMPLE_Q_TAG, 1829 /*dbd*/ FALSE, 1830 /*page_code*/ SMS_PAGE_CTRL_CURRENT, 1831 /*page*/ SMS_VENDOR_SPECIFIC_PAGE, 1832 /*param_buf*/ mode_buffer, 1833 /*param_len*/ mode_buffer_len, 1834 /*sense_len*/ SSD_FULL_SIZE, 1835 /*timeout*/ 5000); 1836 1837 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/ 0, 1838 /*sense_flags*/ 0, 1839 &softc->device_stats); 1840 1841 if (error != 0) 1842 goto sagetparamsexit; 1843 1844 } 1845 1846 if (params_to_get & SA_PARAM_BLOCKSIZE) 1847 *blocksize = scsi_3btoul(mode_blk->blklen); 1848 1849 if (params_to_get & SA_PARAM_NUMBLOCKS) 1850 *numblocks = scsi_3btoul(mode_blk->nblocks); 1851 1852 if (params_to_get & SA_PARAM_BUFF_MODE) 1853 *buff_mode = mode_hdr->dev_spec & SMH_SA_BUF_MODE_MASK; 1854 1855 if (params_to_get & SA_PARAM_DENSITY) 1856 *density = mode_blk->density; 1857 1858 if (params_to_get & SA_PARAM_WP) 1859 *write_protect = (mode_hdr->dev_spec & SMH_SA_WP) ? 1860 TRUE : FALSE; 1861 if (params_to_get & SA_PARAM_SPEED) 1862 *speed = mode_hdr->dev_spec & SMH_SA_SPEED_MASK; 1863 1864 if (params_to_get & SA_PARAM_COMPRESSION) { 1865 *comp_supported =(ncomp_page->dce_and_dcc & SA_DCP_DCC)? 1866 TRUE : FALSE; 1867 *comp_enabled = (ncomp_page->dce_and_dcc & SA_DCP_DCE)? 1868 TRUE : FALSE; 1869 *comp_algorithm = 1870 scsi_4btoul(ncomp_page->comp_algorithm); 1871 if (comp_page != NULL) 1872 bcopy(ncomp_page, comp_page,sizeof(*comp_page)); 1873 } 1874 1875 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) { 1876 int idx; 1877 char *xyz = mode_buffer; 1878 xpt_print_path(periph->path); 1879 printf("Mode Sense Data="); 1880 for (idx = 0; idx < mode_buffer_len; idx++) 1881 printf(" 0x%02x", xyz[idx]); 1882 printf("\n"); 1883 } 1884 } else if (status == CAM_SCSI_STATUS_ERROR) { 1885 /* Tell the user about the fatal error. */ 1886 scsi_sense_print(&ccb->csio); 1887 } 1888 1889sagetparamsexit: 1890 1891 xpt_release_ccb(ccb); 1892 free(mode_buffer, M_TEMP); 1893 return(error); 1894} 1895 1896/* 1897 * The purpose of this function is to set one of four different parameters 1898 * for a tape drive: 1899 * - blocksize 1900 * - density 1901 * - compression / compression algorithm 1902 * - buffering mode 1903 * 1904 * The assumption is that this will be called from saioctl(), and therefore 1905 * from a process context. Thus the waiting malloc calls below. If that 1906 * assumption ever changes, the malloc calls should be changed to be 1907 * NOWAIT mallocs. 1908 * 1909 * Any or all of the four parameters may be set when this function is 1910 * called. It should handle setting more than one parameter at once. 1911 */ 1912static int 1913sasetparams(struct cam_periph *periph, sa_params params_to_set, 1914 u_int32_t blocksize, u_int8_t density, u_int32_t comp_algorithm) 1915{ 1916 struct sa_softc *softc; 1917 u_int32_t current_blocksize; 1918 u_int32_t current_comp_algorithm; 1919 u_int8_t current_density; 1920 u_int8_t current_speed; 1921 int comp_enabled, comp_supported; 1922 void *mode_buffer; 1923 int mode_buffer_len; 1924 struct scsi_mode_header_6 *mode_hdr; 1925 struct scsi_mode_blk_desc *mode_blk; 1926 struct scsi_data_compression_page *comp_page; 1927 struct scsi_data_compression_page *current_comp_page; 1928 int buff_mode; 1929 union ccb *ccb; 1930 int error; 1931 1932 softc = (struct sa_softc *)periph->softc; 1933 1934 /* silence the compiler */ 1935 ccb = NULL; 1936 1937 current_comp_page = malloc(sizeof(*current_comp_page),M_TEMP, M_WAITOK); 1938 1939 /* 1940 * Since it doesn't make sense to set the number of blocks, or 1941 * write protection, we won't try to get the current value. We 1942 * always want to get the blocksize, so we can set it back to the 1943 * proper value. 1944 */ 1945 error = sagetparams(periph, params_to_set | SA_PARAM_BLOCKSIZE | 1946 SA_PARAM_SPEED, ¤t_blocksize, 1947 ¤t_density, NULL, &buff_mode, NULL, 1948 ¤t_speed, &comp_supported, &comp_enabled, 1949 ¤t_comp_algorithm, current_comp_page); 1950 1951 if (error != 0) { 1952 free(current_comp_page, M_TEMP); 1953 return(error); 1954 } 1955 1956 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk); 1957 if (params_to_set & SA_PARAM_COMPRESSION) 1958 mode_buffer_len += sizeof(struct scsi_data_compression_page); 1959 1960 mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK); 1961 1962 bzero(mode_buffer, mode_buffer_len); 1963 1964 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer; 1965 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1]; 1966 1967 if (params_to_set & SA_PARAM_COMPRESSION) { 1968 comp_page = (struct scsi_data_compression_page *)&mode_blk[1]; 1969 bcopy(current_comp_page, comp_page, sizeof(*comp_page)); 1970 } else 1971 comp_page = NULL; 1972 1973 /* 1974 * If the caller wants us to set the blocksize, use the one they 1975 * pass in. Otherwise, use the blocksize we got back from the 1976 * mode select above. 1977 */ 1978 if (params_to_set & SA_PARAM_BLOCKSIZE) 1979 scsi_ulto3b(blocksize, mode_blk->blklen); 1980 else 1981 scsi_ulto3b(current_blocksize, mode_blk->blklen); 1982 1983 /* 1984 * Set density if requested, else preserve old density. 1985 * SCSI_SAME_DENSITY only applies to SCSI-2 or better 1986 * devices, else density we've latched up in our softc. 1987 */ 1988 if (params_to_set & SA_PARAM_DENSITY) { 1989 mode_blk->density = density; 1990 } else if (softc->scsi_rev > SCSI_REV_CCS) { 1991 mode_blk->density = SCSI_SAME_DENSITY; 1992 } else { 1993 mode_blk->density = softc->media_density; 1994 } 1995 1996 /* 1997 * For mode selects, these two fields must be zero. 1998 */ 1999 mode_hdr->data_length = 0; 2000 mode_hdr->medium_type = 0; 2001 2002 /* set the speed to the current value */ 2003 mode_hdr->dev_spec = current_speed; 2004 2005 /* set single-initiator buffering mode */ 2006 mode_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF; 2007 2008 mode_hdr->blk_desc_len = sizeof(struct scsi_mode_blk_desc); 2009 2010 /* 2011 * First, if the user wants us to set the compression algorithm or 2012 * just turn compression on, check to make sure that this drive 2013 * supports compression. 2014 */ 2015 if ((params_to_set & SA_PARAM_COMPRESSION) 2016 && (current_comp_page->dce_and_dcc & SA_DCP_DCC)) { 2017 2018 /* 2019 * If the compression algorithm is 0, disable compression. 2020 * If the compression algorithm is non-zero, enable 2021 * compression and set the compression type to the 2022 * specified compression algorithm, unless the algorithm is 2023 * MT_COMP_ENABLE. In that case, we look at the 2024 * compression algorithm that is currently set and if it is 2025 * non-zero, we leave it as-is. If it is zero, and we have 2026 * saved a compression algorithm from a time when 2027 * compression was enabled before, set the compression to 2028 * the saved value. 2029 */ 2030 if (comp_algorithm == 0) { 2031 /* disable compression */ 2032 comp_page->dce_and_dcc &= ~SA_DCP_DCE; 2033 } else { 2034 /* enable compression */ 2035 comp_page->dce_and_dcc |= SA_DCP_DCE; 2036 2037 /* enable decompression */ 2038 comp_page->dde_and_red |= SA_DCP_DDE; 2039 2040 if (comp_algorithm != MT_COMP_ENABLE) { 2041 /* set the compression algorithm */ 2042 scsi_ulto4b(comp_algorithm, 2043 comp_page->comp_algorithm); 2044 2045 } else if ((scsi_4btoul(comp_page->comp_algorithm) == 0) 2046 && (softc->saved_comp_algorithm != 0)) { 2047 scsi_ulto4b(softc->saved_comp_algorithm, 2048 comp_page->comp_algorithm); 2049 } 2050 } 2051 } else if (params_to_set & SA_PARAM_COMPRESSION) { 2052 /* 2053 * The drive doesn't support compression, so turn off the 2054 * set compression bit. 2055 */ 2056 params_to_set &= ~SA_PARAM_COMPRESSION; 2057 2058 /* 2059 * Should probably do something other than a printf...like 2060 * set a flag in the softc saying that this drive doesn't 2061 * support compression. 2062 */ 2063 xpt_print_path(periph->path); 2064 printf("sasetparams: device does not support compression\n"); 2065 2066 /* 2067 * If that was the only thing the user wanted us to set, 2068 * clean up allocated resources and return with 'operation 2069 * not supported'. 2070 */ 2071 if (params_to_set == SA_PARAM_NONE) { 2072 free(mode_buffer, M_TEMP); 2073 return(ENODEV); 2074 } 2075 2076 /* 2077 * That wasn't the only thing the user wanted us to set. 2078 * So, decrease the stated mode buffer length by the size 2079 * of the compression mode page. 2080 */ 2081 mode_buffer_len -= sizeof(*comp_page); 2082 } 2083 2084 ccb = cam_periph_getccb(periph, /*priority*/ 1); 2085 2086 2087 scsi_mode_select(&ccb->csio, 2088 /*retries*/1, 2089 /*cbfcnp*/ sadone, 2090 /*tag_action*/ MSG_SIMPLE_Q_TAG, 2091 /*scsi_page_fmt*/(params_to_set & SA_PARAM_COMPRESSION)? 2092 TRUE : FALSE, 2093 /*save_pages*/ FALSE, 2094 /*param_buf*/ mode_buffer, 2095 /*param_len*/ mode_buffer_len, 2096 /*sense_len*/ SSD_FULL_SIZE, 2097 /*timeout*/ 5000); 2098 2099 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) { 2100 int idx; 2101 char *xyz = mode_buffer; 2102 xpt_print_path(periph->path); 2103 printf("Mode Select Data="); 2104 for (idx = 0; idx < mode_buffer_len; idx++) 2105 printf(" 0x%02x", xyz[idx]); 2106 printf("\n"); 2107 } 2108 2109 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/ 0, 2110 /*sense_flags*/ 0, &softc->device_stats); 2111 2112 if (error == 0) { 2113 xpt_release_ccb(ccb); 2114 } else { 2115 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2116 cam_release_devq(ccb->ccb_h.path, 2117 /*relsim_flags*/0, 2118 /*reduction*/0, 2119 /*timeout*/0, 2120 /*getcount_only*/0); 2121 /* 2122 * If we were setting the blocksize, and that failed, we 2123 * want to set it to its original value. If we weren't 2124 * setting the blocksize, we don't want to change it. 2125 */ 2126 scsi_ulto3b(current_blocksize, mode_blk->blklen); 2127 2128 /* 2129 * Set density if requested, else preserve old density. 2130 * SCSI_SAME_DENSITY only applies to SCSI-2 or better 2131 * devices, else density we've latched up in our softc. 2132 */ 2133 if (params_to_set & SA_PARAM_DENSITY) { 2134 mode_blk->density = current_density; 2135 } else if (softc->scsi_rev > SCSI_REV_CCS) { 2136 mode_blk->density = SCSI_SAME_DENSITY; 2137 } else { 2138 mode_blk->density = softc->media_density; 2139 } 2140 2141 if (params_to_set & SA_PARAM_COMPRESSION) 2142 bcopy(current_comp_page, comp_page, 2143 sizeof(struct scsi_data_compression_page)); 2144 2145 /* 2146 * The retry count is the only CCB field that might have been 2147 * changed that we care about, so reset it back to 1. 2148 */ 2149 ccb->ccb_h.retry_count = 1; 2150 cam_periph_runccb(ccb, saerror, /*cam_flags*/ 0, 2151 /*sense_flags*/ 0, &softc->device_stats); 2152 2153 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2154 cam_release_devq(ccb->ccb_h.path, 2155 /*relsim_flags*/0, 2156 /*reduction*/0, 2157 /*timeout*/0, 2158 /*getcount_only*/0); 2159 2160 xpt_release_ccb(ccb); 2161 } 2162 2163 if (params_to_set & SA_PARAM_COMPRESSION) 2164 free(current_comp_page, M_TEMP); 2165 2166 free(mode_buffer, M_TEMP); 2167 return(error); 2168} 2169 2170static void 2171saprevent(struct cam_periph *periph, int action) 2172{ 2173 struct sa_softc *softc; 2174 union ccb *ccb; 2175 int error; 2176 2177 softc = (struct sa_softc *)periph->softc; 2178 2179 if (((action == PR_ALLOW) 2180 && (softc->flags & SA_FLAG_TAPE_LOCKED) == 0) 2181 || ((action == PR_PREVENT) 2182 && (softc->flags & SA_FLAG_TAPE_LOCKED) != 0)) { 2183 return; 2184 } 2185 2186 ccb = cam_periph_getccb(periph, /*priority*/1); 2187 2188 scsi_prevent(&ccb->csio, 2189 /*retries*/0, 2190 /*cbcfp*/sadone, 2191 MSG_SIMPLE_Q_TAG, 2192 action, 2193 SSD_FULL_SIZE, 2194 60000); 2195 2196 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2197 /*sense_flags*/0, &softc->device_stats); 2198 2199 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2200 cam_release_devq(ccb->ccb_h.path, 2201 /*relsim_flags*/0, 2202 /*reduction*/0, 2203 /*timeout*/0, 2204 /*getcount_only*/0); 2205 2206 2207 if (error == 0) { 2208 if (action == PR_ALLOW) 2209 softc->flags &= ~SA_FLAG_TAPE_LOCKED; 2210 else 2211 softc->flags |= SA_FLAG_TAPE_LOCKED; 2212 } 2213 2214 xpt_release_ccb(ccb); 2215} 2216 2217static int 2218sarewind(struct cam_periph *periph) 2219{ 2220 union ccb *ccb; 2221 struct sa_softc *softc; 2222 int error; 2223 2224 softc = (struct sa_softc *)periph->softc; 2225 2226 ccb = cam_periph_getccb(periph, /*priority*/1); 2227 2228 scsi_rewind(&ccb->csio, 2229 /*retries*/1, 2230 /*cbcfp*/sadone, 2231 MSG_SIMPLE_Q_TAG, 2232 /*immediate*/FALSE, 2233 SSD_FULL_SIZE, 2234 (SA_REWIND_TIMEOUT) * 60 * 1000); 2235 2236 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2237 /*sense_flags*/0, &softc->device_stats); 2238 2239 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2240 cam_release_devq(ccb->ccb_h.path, 2241 /*relsim_flags*/0, 2242 /*reduction*/0, 2243 /*timeout*/0, 2244 /*getcount_only*/0); 2245 xpt_release_ccb(ccb); 2246 return (error); 2247} 2248 2249static int 2250saspace(struct cam_periph *periph, int count, scsi_space_code code) 2251{ 2252 union ccb *ccb; 2253 struct sa_softc *softc; 2254 int error; 2255 2256 softc = (struct sa_softc *)periph->softc; 2257 2258 ccb = cam_periph_getccb(periph, /*priority*/1); 2259 2260 scsi_space(&ccb->csio, 2261 /*retries*/1, 2262 /*cbcfp*/sadone, 2263 MSG_SIMPLE_Q_TAG, 2264 code, count, 2265 SSD_FULL_SIZE, 2266 (SA_SPACE_TIMEOUT) * 60 * 1000); 2267 2268 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2269 /*sense_flags*/0, &softc->device_stats); 2270 2271 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2272 cam_release_devq(ccb->ccb_h.path, 2273 /*relsim_flags*/0, 2274 /*reduction*/0, 2275 /*timeout*/0, 2276 /*getcount_only*/0); 2277 xpt_release_ccb(ccb); 2278 return (error); 2279} 2280 2281static int 2282sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks) 2283{ 2284 union ccb *ccb; 2285 struct sa_softc *softc; 2286 int error; 2287 2288 softc = (struct sa_softc *)periph->softc; 2289 2290 ccb = cam_periph_getccb(periph, /*priority*/1); 2291 2292 scsi_write_filemarks(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, 2293 FALSE, setmarks, nmarks, SSD_FULL_SIZE, 60000); 2294 2295 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2296 2297 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2298 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 2299 2300 /* 2301 * XXXX: Actually, we need to get back the actual number of filemarks 2302 * XXXX: written (there can be a residual). 2303 */ 2304 if (error == 0 && nmarks) { 2305 struct sa_softc *softc = (struct sa_softc *)periph->softc; 2306 softc->filemarks += nmarks; 2307 } 2308 xpt_release_ccb(ccb); 2309 return (error); 2310} 2311 2312static int 2313sardpos(struct cam_periph *periph, int hard, u_int32_t *blkptr) 2314{ 2315 struct scsi_tape_position_data loc; 2316 union ccb *ccb; 2317 struct sa_softc *softc; 2318 int error; 2319 2320 /* 2321 * First flush any pending writes... 2322 */ 2323 error = sawritefilemarks(periph, 0, 0); 2324 2325 /* 2326 * The latter case is for 'write protected' tapes 2327 * which are too stupid to recognize a zero count 2328 * for writing filemarks as a no-op. 2329 */ 2330 if (error != 0 && error != EACCES) 2331 return (error); 2332 2333 softc = (struct sa_softc *)periph->softc; 2334 ccb = cam_periph_getccb(periph, /*priority*/1); 2335 2336 scsi_read_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, 2337 hard, &loc, SSD_FULL_SIZE, 5000); 2338 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2339 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2340 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 2341 2342 if (error == 0) { 2343 if (loc.flags & SA_RPOS_UNCERTAIN) { 2344 error = EINVAL; /* nothing is certain */ 2345 } else { 2346 *blkptr = scsi_4btoul(loc.firstblk); 2347 } 2348 } 2349 2350 xpt_release_ccb(ccb); 2351 return (error); 2352} 2353 2354static int 2355sasetpos(struct cam_periph *periph, int hard, u_int32_t *blkptr) 2356{ 2357 union ccb *ccb; 2358 struct sa_softc *softc; 2359 int error; 2360 2361 /* 2362 * First flush any pending writes... 2363 */ 2364 error = sawritefilemarks(periph, 0, 0); 2365 2366 /* 2367 * The latter case is for 'write protected' tapes 2368 * which are too stupid to recognize a zero count 2369 * for writing filemarks as a no-op. 2370 */ 2371 if (error != 0 && error != EACCES) 2372 return (error); 2373 2374 softc = (struct sa_softc *)periph->softc; 2375 ccb = cam_periph_getccb(periph, /*priority*/1); 2376 2377 scsi_set_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, 2378 hard, *blkptr, SSD_FULL_SIZE, 60 * 60 * 1000); 2379 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2380 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2381 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 2382 xpt_release_ccb(ccb); 2383 /* 2384 * XXX: Note relative file && block number position now unknown (if 2385 * XXX: these things ever start being maintained in this driver). 2386 */ 2387 return (error); 2388} 2389 2390 2391static int 2392saretension(struct cam_periph *periph) 2393{ 2394 union ccb *ccb; 2395 struct sa_softc *softc; 2396 int error; 2397 2398 softc = (struct sa_softc *)periph->softc; 2399 2400 ccb = cam_periph_getccb(periph, /*priority*/1); 2401 2402 scsi_load_unload(&ccb->csio, 2403 /*retries*/ 1, 2404 /*cbfcnp*/ sadone, 2405 MSG_SIMPLE_Q_TAG, 2406 /*immediate*/ FALSE, 2407 /*eot*/ FALSE, 2408 /*reten*/ TRUE, 2409 /*load*/ TRUE, 2410 SSD_FULL_SIZE, 2411 60000); 2412 2413 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2414 /*sense_flags*/0, &softc->device_stats); 2415 2416 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2417 cam_release_devq(ccb->ccb_h.path, 2418 /*relsim_flags*/0, 2419 /*reduction*/0, 2420 /*timeout*/0, 2421 /*getcount_only*/0); 2422 xpt_release_ccb(ccb); 2423 return(error); 2424} 2425 2426static int 2427sareservereleaseunit(struct cam_periph *periph, int reserve) 2428{ 2429 union ccb *ccb; 2430 struct sa_softc *softc; 2431 int error, sflags; 2432 2433 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) 2434 sflags = SF_RETRY_UA; 2435 else 2436 sflags = SF_RETRY_UA|SF_QUIET_IR; 2437 2438 softc = (struct sa_softc *)periph->softc; 2439 2440 ccb = cam_periph_getccb(periph, /*priority*/ 1); 2441 2442 scsi_reserve_release_unit(&ccb->csio, 2443 /*retries*/ 1, 2444 /*cbfcnp*/ sadone, 2445 /*tag_action*/ MSG_SIMPLE_Q_TAG, 2446 /*third_party*/ FALSE, 2447 /*third_party_id*/ 0, 2448 /*sense_len*/ SSD_FULL_SIZE, 2449 /*timeout*/ 5000, 2450 reserve); 2451 2452 /* 2453 * We set SF_RETRY_UA, since this is often the first command run 2454 * when a tape device is opened, and there may be a unit attention 2455 * condition pending. 2456 */ 2457 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2458 /*sense_flags*/sflags, 2459 &softc->device_stats); 2460 2461 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2462 cam_release_devq(ccb->ccb_h.path, 2463 /*relsim_flags*/0, 2464 /*reduction*/0, 2465 /*timeout*/0, 2466 /*getcount_only*/0); 2467 2468 xpt_release_ccb(ccb); 2469 2470 /* 2471 * If the error was Illegal Request, then the device doesn't support 2472 * RESERVE/RELEASE. This is not an error. 2473 */ 2474 if (error == EINVAL) 2475 error = 0; 2476 2477 return (error); 2478} 2479 2480static int 2481saloadunload(struct cam_periph *periph, int load) 2482{ 2483 union ccb *ccb; 2484 struct sa_softc *softc; 2485 int error; 2486 2487 softc = (struct sa_softc *)periph->softc; 2488 2489 ccb = cam_periph_getccb(periph, /*priority*/1); 2490 2491 scsi_load_unload(&ccb->csio, 2492 /*retries*/1, 2493 /*cbfcnp*/sadone, 2494 MSG_SIMPLE_Q_TAG, 2495 /*immediate*/FALSE, 2496 /*eot*/FALSE, 2497 /*reten*/FALSE, 2498 load, 2499 SSD_FULL_SIZE, 2500 60000); 2501 2502 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2503 /*sense_flags*/0, &softc->device_stats); 2504 2505 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2506 cam_release_devq(ccb->ccb_h.path, 2507 /*relsim_flags*/0, 2508 /*reduction*/0, 2509 /*timeout*/0, 2510 /*getcount_only*/0); 2511 xpt_release_ccb(ccb); 2512 return (error); 2513} 2514 2515static int 2516saerase(struct cam_periph *periph, int longerase) 2517{ 2518 2519 union ccb *ccb; 2520 struct sa_softc *softc; 2521 int error; 2522 2523 softc = (struct sa_softc *)periph->softc; 2524 2525 ccb = cam_periph_getccb(periph, /*priority*/ 1); 2526 2527 scsi_erase(&ccb->csio, 2528 /*retries*/ 1, 2529 /*cbfcnp*/ sadone, 2530 /*tag_action*/ MSG_SIMPLE_Q_TAG, 2531 /*immediate*/ FALSE, 2532 /*long_erase*/ longerase, 2533 /*sense_len*/ SSD_FULL_SIZE, 2534 /*timeout*/ (SA_ERASE_TIMEOUT) * 60 * 1000); 2535 2536 error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, 2537 /*sense_flags*/0, &softc->device_stats); 2538 2539 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2540 cam_release_devq(ccb->ccb_h.path, 2541 /*relsim_flags*/0, 2542 /*reduction*/0, 2543 /*timeout*/0, 2544 /*getcount_only*/0); 2545 xpt_release_ccb(ccb); 2546 return (error); 2547} 2548 2549#endif /* KERNEL */ 2550 2551/* 2552 * Read tape block limits command. 2553 */ 2554void 2555scsi_read_block_limits(struct ccb_scsiio *csio, u_int32_t retries, 2556 void (*cbfcnp)(struct cam_periph *, union ccb *), 2557 u_int8_t tag_action, 2558 struct scsi_read_block_limits_data *rlimit_buf, 2559 u_int8_t sense_len, u_int32_t timeout) 2560{ 2561 struct scsi_read_block_limits *scsi_cmd; 2562 2563 cam_fill_csio(csio, 2564 retries, 2565 cbfcnp, 2566 /*flags*/CAM_DIR_IN, 2567 tag_action, 2568 /*data_ptr*/(u_int8_t *)rlimit_buf, 2569 /*dxfer_len*/sizeof(*rlimit_buf), 2570 sense_len, 2571 sizeof(*scsi_cmd), 2572 timeout); 2573 2574 scsi_cmd = (struct scsi_read_block_limits *)&csio->cdb_io.cdb_bytes; 2575 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2576 scsi_cmd->opcode = READ_BLOCK_LIMITS; 2577} 2578 2579void 2580scsi_sa_read_write(struct ccb_scsiio *csio, u_int32_t retries, 2581 void (*cbfcnp)(struct cam_periph *, union ccb *), 2582 u_int8_t tag_action, int readop, int sli, 2583 int fixed, u_int32_t length, u_int8_t *data_ptr, 2584 u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout) 2585{ 2586 struct scsi_sa_rw *scsi_cmd; 2587 2588 scsi_cmd = (struct scsi_sa_rw *)&csio->cdb_io.cdb_bytes; 2589 scsi_cmd->opcode = readop ? SA_READ : SA_WRITE; 2590 scsi_cmd->sli_fixed = 0; 2591 if (sli && readop) 2592 scsi_cmd->sli_fixed |= SAR_SLI; 2593 if (fixed) 2594 scsi_cmd->sli_fixed |= SARW_FIXED; 2595 scsi_ulto3b(length, scsi_cmd->length); 2596 scsi_cmd->control = 0; 2597 2598 cam_fill_csio(csio, 2599 retries, 2600 cbfcnp, 2601 /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT, 2602 tag_action, 2603 data_ptr, 2604 dxfer_len, 2605 sense_len, 2606 sizeof(*scsi_cmd), 2607 timeout); 2608} 2609 2610void 2611scsi_load_unload(struct ccb_scsiio *csio, u_int32_t retries, 2612 void (*cbfcnp)(struct cam_periph *, union ccb *), 2613 u_int8_t tag_action, int immediate, int eot, 2614 int reten, int load, u_int8_t sense_len, 2615 u_int32_t timeout) 2616{ 2617 struct scsi_load_unload *scsi_cmd; 2618 2619 scsi_cmd = (struct scsi_load_unload *)&csio->cdb_io.cdb_bytes; 2620 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2621 scsi_cmd->opcode = LOAD_UNLOAD; 2622 if (immediate) 2623 scsi_cmd->immediate = SLU_IMMED; 2624 if (eot) 2625 scsi_cmd->eot_reten_load |= SLU_EOT; 2626 if (reten) 2627 scsi_cmd->eot_reten_load |= SLU_RETEN; 2628 if (load) 2629 scsi_cmd->eot_reten_load |= SLU_LOAD; 2630 2631 cam_fill_csio(csio, 2632 retries, 2633 cbfcnp, 2634 /*flags*/CAM_DIR_NONE, 2635 tag_action, 2636 /*data_ptr*/NULL, 2637 /*dxfer_len*/0, 2638 sense_len, 2639 sizeof(*scsi_cmd), 2640 timeout); 2641} 2642 2643void 2644scsi_rewind(struct ccb_scsiio *csio, u_int32_t retries, 2645 void (*cbfcnp)(struct cam_periph *, union ccb *), 2646 u_int8_t tag_action, int immediate, u_int8_t sense_len, 2647 u_int32_t timeout) 2648{ 2649 struct scsi_rewind *scsi_cmd; 2650 2651 scsi_cmd = (struct scsi_rewind *)&csio->cdb_io.cdb_bytes; 2652 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2653 scsi_cmd->opcode = REWIND; 2654 if (immediate) 2655 scsi_cmd->immediate = SREW_IMMED; 2656 2657 cam_fill_csio(csio, 2658 retries, 2659 cbfcnp, 2660 /*flags*/CAM_DIR_NONE, 2661 tag_action, 2662 /*data_ptr*/NULL, 2663 /*dxfer_len*/0, 2664 sense_len, 2665 sizeof(*scsi_cmd), 2666 timeout); 2667} 2668 2669void 2670scsi_space(struct ccb_scsiio *csio, u_int32_t retries, 2671 void (*cbfcnp)(struct cam_periph *, union ccb *), 2672 u_int8_t tag_action, scsi_space_code code, 2673 u_int32_t count, u_int8_t sense_len, u_int32_t timeout) 2674{ 2675 struct scsi_space *scsi_cmd; 2676 2677 scsi_cmd = (struct scsi_space *)&csio->cdb_io.cdb_bytes; 2678 scsi_cmd->opcode = SPACE; 2679 scsi_cmd->code = code; 2680 scsi_ulto3b(count, scsi_cmd->count); 2681 scsi_cmd->control = 0; 2682 2683 cam_fill_csio(csio, 2684 retries, 2685 cbfcnp, 2686 /*flags*/CAM_DIR_NONE, 2687 tag_action, 2688 /*data_ptr*/NULL, 2689 /*dxfer_len*/0, 2690 sense_len, 2691 sizeof(*scsi_cmd), 2692 timeout); 2693} 2694 2695void 2696scsi_write_filemarks(struct ccb_scsiio *csio, u_int32_t retries, 2697 void (*cbfcnp)(struct cam_periph *, union ccb *), 2698 u_int8_t tag_action, int immediate, int setmark, 2699 u_int32_t num_marks, u_int8_t sense_len, 2700 u_int32_t timeout) 2701{ 2702 struct scsi_write_filemarks *scsi_cmd; 2703 2704 scsi_cmd = (struct scsi_write_filemarks *)&csio->cdb_io.cdb_bytes; 2705 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2706 scsi_cmd->opcode = WRITE_FILEMARKS; 2707 if (immediate) 2708 scsi_cmd->byte2 |= SWFMRK_IMMED; 2709 if (setmark) 2710 scsi_cmd->byte2 |= SWFMRK_WSMK; 2711 2712 scsi_ulto3b(num_marks, scsi_cmd->num_marks); 2713 2714 cam_fill_csio(csio, 2715 retries, 2716 cbfcnp, 2717 /*flags*/CAM_DIR_NONE, 2718 tag_action, 2719 /*data_ptr*/NULL, 2720 /*dxfer_len*/0, 2721 sense_len, 2722 sizeof(*scsi_cmd), 2723 timeout); 2724} 2725 2726/* 2727 * The reserve and release unit commands differ only by their opcodes. 2728 */ 2729void 2730scsi_reserve_release_unit(struct ccb_scsiio *csio, u_int32_t retries, 2731 void (*cbfcnp)(struct cam_periph *, union ccb *), 2732 u_int8_t tag_action, int third_party, 2733 int third_party_id, u_int8_t sense_len, 2734 u_int32_t timeout, int reserve) 2735{ 2736 struct scsi_reserve_release_unit *scsi_cmd; 2737 2738 scsi_cmd = (struct scsi_reserve_release_unit *)&csio->cdb_io.cdb_bytes; 2739 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2740 2741 if (reserve) 2742 scsi_cmd->opcode = RESERVE_UNIT; 2743 else 2744 scsi_cmd->opcode = RELEASE_UNIT; 2745 2746 if (third_party) { 2747 scsi_cmd->lun_thirdparty |= SRRU_3RD_PARTY; 2748 scsi_cmd->lun_thirdparty |= 2749 ((third_party_id << SRRU_3RD_SHAMT) & SRRU_3RD_MASK); 2750 } 2751 2752 cam_fill_csio(csio, 2753 retries, 2754 cbfcnp, 2755 /*flags*/ CAM_DIR_NONE, 2756 tag_action, 2757 /*data_ptr*/ NULL, 2758 /*dxfer_len*/ 0, 2759 sense_len, 2760 sizeof(*scsi_cmd), 2761 timeout); 2762} 2763 2764void 2765scsi_erase(struct ccb_scsiio *csio, u_int32_t retries, 2766 void (*cbfcnp)(struct cam_periph *, union ccb *), 2767 u_int8_t tag_action, int immediate, int long_erase, 2768 u_int8_t sense_len, u_int32_t timeout) 2769{ 2770 struct scsi_erase *scsi_cmd; 2771 2772 scsi_cmd = (struct scsi_erase *)&csio->cdb_io.cdb_bytes; 2773 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2774 2775 scsi_cmd->opcode = ERASE; 2776 2777 if (immediate) 2778 scsi_cmd->lun_imm_long |= SE_IMMED; 2779 2780 if (long_erase) 2781 scsi_cmd->lun_imm_long |= SE_LONG; 2782 2783 cam_fill_csio(csio, 2784 retries, 2785 cbfcnp, 2786 /*flags*/ CAM_DIR_NONE, 2787 tag_action, 2788 /*data_ptr*/ NULL, 2789 /*dxfer_len*/ 0, 2790 sense_len, 2791 sizeof(*scsi_cmd), 2792 timeout); 2793} 2794 2795/* 2796 * Read Tape Position command. 2797 */ 2798void 2799scsi_read_position(struct ccb_scsiio *csio, u_int32_t retries, 2800 void (*cbfcnp)(struct cam_periph *, union ccb *), 2801 u_int8_t tag_action, int hardsoft, 2802 struct scsi_tape_position_data *sbp, 2803 u_int8_t sense_len, u_int32_t timeout) 2804{ 2805 struct scsi_tape_read_position *scmd; 2806 2807 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action, 2808 (u_int8_t *)sbp, sizeof (*sbp), sense_len, sizeof(*scmd), timeout); 2809 scmd = (struct scsi_tape_read_position *)&csio->cdb_io.cdb_bytes; 2810 bzero(scmd, sizeof(*scmd)); 2811 scmd->opcode = READ_POSITION; 2812 scmd->byte1 = hardsoft; 2813} 2814 2815/* 2816 * Set Tape Position command. 2817 */ 2818void 2819scsi_set_position(struct ccb_scsiio *csio, u_int32_t retries, 2820 void (*cbfcnp)(struct cam_periph *, union ccb *), 2821 u_int8_t tag_action, int hardsoft, u_int32_t blkno, 2822 u_int8_t sense_len, u_int32_t timeout) 2823{ 2824 struct scsi_tape_locate *scmd; 2825 2826 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, 2827 (u_int8_t *)NULL, 0, sense_len, sizeof(*scmd), timeout); 2828 scmd = (struct scsi_tape_locate *)&csio->cdb_io.cdb_bytes; 2829 bzero(scmd, sizeof(*scmd)); 2830 scmd->opcode = LOCATE; 2831 if (hardsoft) 2832 scmd->byte1 |= SA_SPOS_BT; 2833 scsi_ulto4b(blkno, scmd->blkaddr); 2834} 2835