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