scsi_sa.c revision 51658
1/* 2 * $FreeBSD: head/sys/cam/scsi/scsi_sa.c 51658 1999-09-25 18:24:47Z phk $ 3 * 4 * Implementation of SCSI Sequential Access Peripheral driver for CAM. 5 * 6 * Copyright (c) 1997 Justin T. Gibbs 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions, and the following disclaimer, 14 * without modification, immediately at the beginning of the file. 15 * 2. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * 31 * Substantial subsequent modifications 32 * Copyright (c) 1999 Matthew Jacob 33 * NASA Ames Research Center, 34 * Feral Software 35 */ 36 37#include <sys/param.h> 38#include <sys/queue.h> 39#ifdef KERNEL 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#endif 43#include <sys/types.h> 44#include <sys/buf.h> 45#include <sys/malloc.h> 46#include <sys/mtio.h> 47#include <sys/conf.h> 48#include <sys/buf.h> 49#include <sys/devicestat.h> 50#include <machine/limits.h> 51 52#ifndef KERNEL 53#include <stdio.h> 54#include <string.h> 55#endif 56 57#include <cam/cam.h> 58#include <cam/cam_ccb.h> 59#include <cam/cam_extend.h> 60#include <cam/cam_periph.h> 61#include <cam/cam_xpt_periph.h> 62#include <cam/cam_debug.h> 63 64#include <cam/scsi/scsi_all.h> 65#include <cam/scsi/scsi_message.h> 66#include <cam/scsi/scsi_sa.h> 67 68#ifdef KERNEL 69 70#include <opt_sa.h> 71 72#ifndef SA_SPACE_TIMEOUT 73#define SA_SPACE_TIMEOUT 1 * 60 74#endif 75#ifndef SA_REWIND_TIMEOUT 76#define SA_REWIND_TIMEOUT 2 * 60 77#endif 78#ifndef SA_ERASE_TIMEOUT 79#define SA_ERASE_TIMEOUT 4 * 60 80#endif 81 82/* 83 * Default to old FreeBSD behaviour of 2 filemarks 84 * at EOD for all (except QIC) devices. 85 */ 86#ifndef SA_2FM_AT_EOD 87#define SA_2FM_AT_EOD 1 88#endif 89 90#ifndef UNUSED_PARAMETER 91#define UNUSED_PARAMETER(x) x = x 92#endif 93 94typedef enum { 95 SA_STATE_NORMAL, SA_STATE_ABNORMAL 96} sa_state; 97 98typedef enum { 99 SA_CCB_BUFFER_IO, 100 SA_CCB_WAITING 101} sa_ccb_types; 102 103#define ccb_type ppriv_field0 104#define ccb_bp ppriv_ptr1 105 106typedef enum { 107 SA_FLAG_OPEN = 0x0001, 108 SA_FLAG_FIXED = 0x0002, 109 SA_FLAG_TAPE_LOCKED = 0x0004, 110 SA_FLAG_TAPE_MOUNTED = 0x0008, 111 SA_FLAG_TAPE_WP = 0x0010, 112 SA_FLAG_TAPE_WRITTEN = 0x0020, 113 SA_FLAG_EOM_PENDING = 0x0040, 114 SA_FLAG_EIO_PENDING = 0x0080, 115 SA_FLAG_EOF_PENDING = 0x0100, 116 SA_FLAG_ERR_PENDING = (SA_FLAG_EOM_PENDING|SA_FLAG_EIO_PENDING| 117 SA_FLAG_EOF_PENDING), 118 SA_FLAG_INVALID = 0x0200, 119 SA_FLAG_COMP_ENABLED = 0x0400, 120 SA_FLAG_COMP_SUPP = 0x0800, 121 SA_FLAG_COMP_UNSUPP = 0x1000, 122 SA_FLAG_TAPE_FROZEN = 0x2000 123} sa_flags; 124 125typedef enum { 126 SA_MODE_REWIND = 0x00, 127 SA_MODE_NOREWIND = 0x01, 128 SA_MODE_OFFLINE = 0x02 129} sa_mode; 130 131typedef enum { 132 SA_PARAM_NONE = 0x00, 133 SA_PARAM_BLOCKSIZE = 0x01, 134 SA_PARAM_DENSITY = 0x02, 135 SA_PARAM_COMPRESSION = 0x04, 136 SA_PARAM_BUFF_MODE = 0x08, 137 SA_PARAM_NUMBLOCKS = 0x10, 138 SA_PARAM_WP = 0x20, 139 SA_PARAM_SPEED = 0x40, 140 SA_PARAM_ALL = 0x7f 141} sa_params; 142 143typedef enum { 144 SA_QUIRK_NONE = 0x00, 145 SA_QUIRK_NOCOMP = 0x01, /* can't deal with compression at all */ 146 SA_QUIRK_FIXED = 0x02, /* force fixed mode */ 147 SA_QUIRK_VARIABLE = 0x04, /* force variable mode */ 148 SA_QUIRK_2FM = 0x08, /* Needs Two File Marks at EOD */ 149 SA_QUIRK_1FM = 0x10 /* No more than 1 File Mark at EOD */ 150} sa_quirks; 151 152struct sa_softc { 153 sa_state state; 154 sa_flags flags; 155 sa_quirks quirks; 156 struct buf_queue_head buf_queue; 157 int queue_count; 158 struct devstat device_stats; 159 int blk_gran; 160 int blk_mask; 161 int blk_shift; 162 u_int32_t max_blk; 163 u_int32_t min_blk; 164 u_int32_t comp_algorithm; 165 u_int32_t saved_comp_algorithm; 166 u_int32_t media_blksize; 167 u_int32_t last_media_blksize; 168 u_int32_t media_numblks; 169 u_int8_t media_density; 170 u_int8_t speed; 171 u_int8_t scsi_rev; 172 u_int8_t dsreg; /* mtio mt_dsreg, redux */ 173 int buffer_mode; 174 int filemarks; 175 union ccb saved_ccb; 176 177 /* 178 * Relative to BOT Location. 179 */ 180 daddr_t fileno; 181 daddr_t blkno; 182 183 /* 184 * Latched Error Info 185 */ 186 struct { 187 struct scsi_sense_data _last_io_sense; 188 u_int32_t _last_io_resid; 189 u_int8_t _last_io_cdb[CAM_MAX_CDBLEN]; 190 struct scsi_sense_data _last_ctl_sense; 191 u_int32_t _last_ctl_resid; 192 u_int8_t _last_ctl_cdb[CAM_MAX_CDBLEN]; 193#define last_io_sense errinfo._last_io_sense 194#define last_io_resid errinfo._last_io_resid 195#define last_io_cdb errinfo._last_io_cdb 196#define last_ctl_sense errinfo._last_ctl_sense 197#define last_ctl_resid errinfo._last_ctl_resid 198#define last_ctl_cdb errinfo._last_ctl_cdb 199 } errinfo; 200 /* 201 * Misc other flags/state 202 */ 203 u_int32_t 204 : 31, 205 ctrl_mode : 1; /* control device open */ 206}; 207 208struct sa_quirk_entry { 209 struct scsi_inquiry_pattern inq_pat; /* matching pattern */ 210 sa_quirks quirks; /* specific quirk type */ 211 u_int32_t prefblk; /* preferred blocksize when in fixed mode */ 212}; 213 214static struct sa_quirk_entry sa_quirk_table[] = 215{ 216 { 217 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE", 218 "Python 25601*", "*"}, SA_QUIRK_NOCOMP, 0 219 }, 220 { 221 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE", 222 "VIPER 150*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512 223 }, 224 { 225 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE", 226 "VIPER 2525*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024 227 }, 228 { 229 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP", 230 "T20*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512 231 }, 232 { 233 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP", 234 "T4000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512 235 }, 236 { 237 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP", 238 "HP-88780*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0 239 }, 240 { 241 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY", 242 "*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0 243 }, 244 { 245 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "M4 DATA", 246 "123107 SCSI*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0 247 }, 248 { 249 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 250 " TDC 3600", "U07:"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512 251 }, 252 { 253 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 254 " TDC 3800", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512 255 }, 256 { 257 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 258 " TDC 4100", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512 259 }, 260 { 261 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 262 " TDC 4200", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512 263 }, 264 { 265 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 266 " SLR*", "*"}, SA_QUIRK_1FM, 0 267 }, 268 { 269 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK", 270 "5525ES*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512 271 }, 272 { 273 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK", 274 "51000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024 275 } 276}; 277 278static d_open_t saopen; 279static d_close_t saclose; 280static d_strategy_t sastrategy; 281static d_ioctl_t saioctl; 282static periph_init_t sainit; 283static periph_ctor_t saregister; 284static periph_oninv_t saoninvalidate; 285static periph_dtor_t sacleanup; 286static periph_start_t sastart; 287static void saasync(void *callback_arg, u_int32_t code, 288 struct cam_path *path, void *arg); 289static void sadone(struct cam_periph *periph, 290 union ccb *start_ccb); 291static int saerror(union ccb *ccb, u_int32_t cam_flags, 292 u_int32_t sense_flags); 293static int sacheckeod(struct cam_periph *periph); 294static int sagetparams(struct cam_periph *periph, 295 sa_params params_to_get, 296 u_int32_t *blocksize, u_int8_t *density, 297 u_int32_t *numblocks, int *buff_mode, 298 u_int8_t *write_protect, u_int8_t *speed, 299 int *comp_supported, int *comp_enabled, 300 u_int32_t *comp_algorithm, 301 sa_comp_t *comp_page); 302static int sasetparams(struct cam_periph *periph, 303 sa_params params_to_set, 304 u_int32_t blocksize, u_int8_t density, 305 u_int32_t comp_algorithm, 306 u_int32_t sense_flags); 307static void saprevent(struct cam_periph *periph, int action); 308static int sarewind(struct cam_periph *periph); 309static int saspace(struct cam_periph *periph, int count, 310 scsi_space_code code); 311static int samount(struct cam_periph *, int, dev_t); 312static int saretension(struct cam_periph *periph); 313static int sareservereleaseunit(struct cam_periph *periph, 314 int reserve); 315static int saloadunload(struct cam_periph *periph, int load); 316static int saerase(struct cam_periph *periph, int longerase); 317static int sawritefilemarks(struct cam_periph *periph, 318 int nmarks, int setmarks); 319static int sardpos(struct cam_periph *periph, int, u_int32_t *); 320static int sasetpos(struct cam_periph *periph, int, u_int32_t *); 321 322 323static struct periph_driver sadriver = 324{ 325 sainit, "sa", 326 TAILQ_HEAD_INITIALIZER(sadriver.units), /* generation */ 0 327}; 328 329DATA_SET(periphdriver_set, sadriver); 330 331/* units are bits 4-7, 16-21 (1024 units) */ 332#define SAUNIT(DEV) \ 333 (((minor(DEV) & 0xF0) >> 4) | ((minor(DEV) & 0x3f0000) >> 16)) 334 335#define SAMODE(z) ((minor(z) & 0x3)) 336#define SADENSITY(z) (((minor(z) >> 2) & 0x3)) 337#define SA_IS_CTRL(z) (minor(z) & (1 << 29)) 338 339/* For 2.2-stable support */ 340#ifndef D_TAPE 341#define D_TAPE 0 342#endif 343 344#define SA_CDEV_MAJOR 14 345 346static struct cdevsw sa_cdevsw = { 347 /* open */ saopen, 348 /* close */ saclose, 349 /* read */ physread, 350 /* write */ physwrite, 351 /* ioctl */ saioctl, 352 /* poll */ nopoll, 353 /* mmap */ nommap, 354 /* strategy */ sastrategy, 355 /* name */ "sa", 356 /* maj */ SA_CDEV_MAJOR, 357 /* dump */ nodump, 358 /* psize */ nopsize, 359 /* flags */ D_TAPE, 360 /* bmaj */ -1 361}; 362 363static struct extend_array *saperiphs; 364 365static int 366saopen(dev_t dev, int flags, int fmt, struct proc *p) 367{ 368 struct cam_periph *periph; 369 struct sa_softc *softc; 370 int unit; 371 int mode; 372 int density; 373 int error; 374 int s; 375 376 unit = SAUNIT(dev); 377 mode = SAMODE(dev); 378 density = SADENSITY(dev); 379 380 periph = cam_extend_get(saperiphs, unit); 381 if (periph == NULL) 382 return (ENXIO); 383 384 softc = (struct sa_softc *)periph->softc; 385 386 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO, 387 ("saopen(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags)); 388 389 s = splsoftcam(); 390 391 if (SA_IS_CTRL(dev)) { 392 softc->ctrl_mode = 1; 393 (void) splx(s); 394 return (0); 395 } 396 397 if (softc->flags & SA_FLAG_INVALID) { 398 splx(s); 399 return(ENXIO); 400 } 401 402 if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) { 403 splx(s); 404 return (error); /* error code from tsleep */ 405 } 406 407 splx(s); 408 409 if ((softc->flags & SA_FLAG_OPEN) == 0) { 410 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 411 return(ENXIO); 412 413 if ((error = sareservereleaseunit(periph, TRUE)) != 0) { 414 cam_periph_unlock(periph); 415 cam_periph_release(periph); 416 return(error); 417 } 418 } 419 420 if (error == 0) { 421 if ((softc->flags & SA_FLAG_OPEN) != 0) { 422 error = EBUSY; 423 } 424 425 if (error == 0) 426 error = samount(periph, flags, dev); 427 /* Perform other checking... */ 428 } 429 430 if (error == 0) { 431 saprevent(periph, PR_PREVENT); 432 softc->flags |= SA_FLAG_OPEN; 433 } 434 435 cam_periph_unlock(periph); 436 return (error); 437} 438 439static int 440saclose(dev_t dev, int flag, int fmt, struct proc *p) 441{ 442 struct cam_periph *periph; 443 struct sa_softc *softc; 444 int unit, mode, error, writing, tmp; 445 int closedbits = SA_FLAG_OPEN; 446 447 unit = SAUNIT(dev); 448 mode = SAMODE(dev); 449 periph = cam_extend_get(saperiphs, unit); 450 if (periph == NULL) 451 return (ENXIO); 452 453 softc = (struct sa_softc *)periph->softc; 454 455 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO, 456 ("saclose(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags)); 457 458 459 if (SA_IS_CTRL(dev)) { 460 softc->ctrl_mode = 0; 461 return (0); 462 } 463 464 if ((error = cam_periph_lock(periph, PRIBIO)) != 0) { 465 return (error); 466 } 467 468 /* 469 * Were we writing the tape? 470 */ 471 writing = (softc->flags & SA_FLAG_TAPE_WRITTEN) != 0; 472 473 /* 474 * See whether or not we need to write filemarks. If this 475 * fails, we probably have to assume we've lost tape 476 * position. 477 */ 478 error = sacheckeod(periph); 479 if (error) { 480 xpt_print_path(periph->path); 481 printf("failed to write terminating filemark(s)\n"); 482 softc->flags |= SA_FLAG_TAPE_FROZEN; 483 } 484 485 /* 486 * Whatever we end up doing, allow users to eject tapes from here on. 487 */ 488 saprevent(periph, PR_ALLOW); 489 490 /* 491 * Decide how to end... 492 */ 493 switch (mode) { 494 case SA_MODE_OFFLINE: 495 /* 496 * An 'offline' close is an unconditional release of 497 * frozen && mount conditions, irrespective of whether 498 * these operations succeeded. The reason for this is 499 * to allow at least some kind of programmatic way 500 * around our state getting all fouled up. If somebody 501 * issues an 'offline' command, that will be allowed 502 * to clear state. 503 */ 504 (void) sarewind(periph); 505 (void) saloadunload(periph, FALSE); 506 closedbits |= SA_FLAG_TAPE_MOUNTED|SA_FLAG_TAPE_FROZEN; 507 break; 508 case SA_MODE_REWIND: 509 /* 510 * If the rewind fails, return an error- if anyone cares, 511 * but not overwriting any previous error. 512 * 513 * We don't clear the notion of mounted here, but we do 514 * clear the notion of frozen if we successfully rewound. 515 */ 516 tmp = sarewind(periph); 517 if (tmp) { 518 if (error != 0) 519 error = tmp; 520 } else { 521 closedbits |= SA_FLAG_TAPE_FROZEN; 522 } 523 break; 524 case SA_MODE_NOREWIND: 525 /* 526 * If we're not rewinding/unloading the tape, find out 527 * whether we need to back up over one of two filemarks 528 * we wrote (if we wrote two filemarks) so that appends 529 * from this point on will be sane. 530 */ 531 if (error == 0 && writing && (softc->quirks & SA_QUIRK_2FM)) { 532 tmp = saspace(periph, -1, SS_FILEMARKS); 533 if (tmp) { 534 xpt_print_path(periph->path); 535 printf("unable to backspace over one of double" 536 " filemarks at end of tape\n"); 537 xpt_print_path(periph->path); 538 printf("it is possible that this device " 539 " needs a SA_QUIRK_1FM quirk set for it\n"); 540 softc->flags |= SA_FLAG_TAPE_FROZEN; 541 } 542 } 543 break; 544 default: 545 xpt_print_path(periph->path); 546 panic("unknown mode 0x%x in saclose\n", mode); 547 /* NOTREACHED */ 548 break; 549 } 550 551 /* 552 * We wish to note here that there are no more filemarks to be written. 553 */ 554 softc->filemarks = 0; 555 softc->flags &= ~SA_FLAG_TAPE_WRITTEN; 556 557 /* 558 * And we are no longer open for business. 559 */ 560 softc->flags &= ~closedbits; 561 562 /* 563 * Inform users if tape state if frozen.... 564 */ 565 if (softc->flags & SA_FLAG_TAPE_FROZEN) { 566 xpt_print_path(periph->path); 567 printf("tape is now frozen- use an OFFLINE, REWIND or MTEOM " 568 "command to clear this state.\n"); 569 } 570 571 /* release the device */ 572 sareservereleaseunit(periph, FALSE); 573 574 cam_periph_unlock(periph); 575 cam_periph_release(periph); 576 577 return (error); 578} 579 580/* 581 * Actually translate the requested transfer into one the physical driver 582 * can understand. The transfer is described by a buf and will include 583 * only one physical transfer. 584 */ 585static void 586sastrategy(struct buf *bp) 587{ 588 struct cam_periph *periph; 589 struct sa_softc *softc; 590 u_int unit; 591 int s; 592 593 if (SA_IS_CTRL(bp->b_dev)) { 594 bp->b_error = EINVAL; 595 goto bad; 596 } 597 unit = SAUNIT(bp->b_dev); 598 periph = cam_extend_get(saperiphs, unit); 599 if (periph == NULL) { 600 bp->b_error = ENXIO; 601 goto bad; 602 } 603 softc = (struct sa_softc *)periph->softc; 604 605 s = splsoftcam(); 606 607 if (softc->flags & SA_FLAG_INVALID) { 608 splx(s); 609 bp->b_error = ENXIO; 610 goto bad; 611 } 612 613 if (softc->flags & SA_FLAG_TAPE_FROZEN) { 614 splx(s); 615 bp->b_error = EPERM; 616 goto bad; 617 } 618 619 splx(s); 620 621 /* 622 * If it's a null transfer, return immediatly 623 */ 624 if (bp->b_bcount == 0) 625 goto done; 626 627 /* valid request? */ 628 if (softc->flags & SA_FLAG_FIXED) { 629 /* 630 * Fixed block device. The byte count must 631 * be a multiple of our block size. 632 */ 633 if (((softc->blk_mask != ~0) && 634 ((bp->b_bcount & softc->blk_mask) != 0)) || 635 ((softc->blk_mask == ~0) && 636 ((bp->b_bcount % softc->min_blk) != 0))) { 637 xpt_print_path(periph->path); 638 printf("Invalid request. Fixed block device " 639 "requests must be a multiple " 640 "of %d bytes\n", softc->min_blk); 641 bp->b_error = EINVAL; 642 goto bad; 643 } 644 } else if ((bp->b_bcount > softc->max_blk) || 645 (bp->b_bcount < softc->min_blk) || 646 (bp->b_bcount & softc->blk_mask) != 0) { 647 648 xpt_print_path(periph->path); 649 printf("Invalid request. Variable block device " 650 "requests must be "); 651 if (softc->blk_mask != 0) { 652 printf("a multiple of %d ", (0x1 << softc->blk_gran)); 653 } 654 printf("between %d and %d bytes\n", softc->min_blk, 655 softc->max_blk); 656 bp->b_error = EINVAL; 657 goto bad; 658 } 659 660 /* 661 * Mask interrupts so that the device cannot be invalidated until 662 * after we are in the queue. Otherwise, we might not properly 663 * clean up one of the buffers. 664 */ 665 s = splbio(); 666 667 /* 668 * Place it at the end of the queue. 669 */ 670 bufq_insert_tail(&softc->buf_queue, bp); 671 672 softc->queue_count++; 673 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("sastrategy: enqueuing a %d " 674 "%s byte %s queue count now %d\n", (int) bp->b_bcount, 675 (softc->flags & SA_FLAG_FIXED)? "fixed" : "variable", 676 (bp->b_flags & B_READ)? "read" : "write", softc->queue_count)); 677 678 splx(s); 679 680 /* 681 * Schedule ourselves for performing the work. 682 */ 683 xpt_schedule(periph, 1); 684 685 return; 686bad: 687 bp->b_flags |= B_ERROR; 688done: 689 690 /* 691 * Correctly set the buf to indicate a completed xfer 692 */ 693 bp->b_resid = bp->b_bcount; 694 biodone(bp); 695} 696 697static int 698saioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) 699{ 700 struct cam_periph *periph; 701 struct sa_softc *softc; 702 scsi_space_code spaceop; 703 int didlockperiph = 0; 704 int s; 705 int unit; 706 int mode; 707 int density; 708 int error; 709 710 unit = SAUNIT(dev); 711 mode = SAMODE(dev); 712 density = SADENSITY(dev); 713 error = 0; /* shut up gcc */ 714 spaceop = 0; /* shut up gcc */ 715 716 periph = cam_extend_get(saperiphs, unit); 717 if (periph == NULL) 718 return (ENXIO); 719 720 softc = (struct sa_softc *)periph->softc; 721 722 /* 723 * Check for control mode accesses. We allow MTIOCGET and 724 * MTIOCERRSTAT (but need to be the only one open in order 725 * to clear latched status), and MTSETBSIZE, MTSETDNSTY 726 * and MTCOMP (but need to be the only one accessing this 727 * device to run those). 728 */ 729 730 if (SA_IS_CTRL(dev)) { 731 switch (cmd) { 732 case MTIOCGETEOTMODEL: 733 case MTIOCGET: 734 break; 735 case MTIOCERRSTAT: 736 /* 737 * If the periph isn't already locked, lock it 738 * so our MTIOCERRSTAT can reset latched error stats. 739 * 740 * If the periph is already locked, skip it because 741 * we're just getting status and it'll be up to the 742 * other thread that has this device open to do 743 * an MTIOCERRSTAT that would clear latched status. 744 */ 745 s = splsoftcam(); 746 if ((periph->flags & CAM_PERIPH_LOCKED) == 0) { 747 error = cam_periph_lock(periph, PRIBIO|PCATCH); 748 if (error != 0) { 749 splx(s); 750 return (error); 751 } 752 didlockperiph = 1; 753 } 754 break; 755 756 case MTIOCSETEOTMODEL: 757 case MTSETBSIZ: 758 case MTSETDNSTY: 759 case MTCOMP: 760 /* 761 * We need to acquire the peripheral here rather 762 * than at open time because we are sharing writable 763 * access to data structures. 764 */ 765 s = splsoftcam(); 766 error = cam_periph_lock(periph, PRIBIO|PCATCH); 767 if (error != 0) { 768 splx(s); 769 return (error); 770 } 771 didlockperiph = 1; 772 break; 773 774 default: 775 return (EINVAL); 776 } 777 } 778 779 /* 780 * Find the device that the user is talking about 781 */ 782 switch (cmd) { 783 case MTIOCGET: 784 { 785 struct mtget *g = (struct mtget *)arg; 786 787 bzero(g, sizeof(struct mtget)); 788 g->mt_type = MT_ISAR; 789 if (softc->flags & SA_FLAG_COMP_UNSUPP) { 790 g->mt_comp = MT_COMP_UNSUPP; 791 g->mt_comp0 = MT_COMP_UNSUPP; 792 g->mt_comp1 = MT_COMP_UNSUPP; 793 g->mt_comp2 = MT_COMP_UNSUPP; 794 g->mt_comp3 = MT_COMP_UNSUPP; 795 } else { 796 if ((softc->flags & SA_FLAG_COMP_ENABLED) == 0) { 797 g->mt_comp = MT_COMP_DISABLED; 798 } else { 799 g->mt_comp = softc->comp_algorithm; 800 } 801 g->mt_comp0 = softc->comp_algorithm; 802 g->mt_comp1 = softc->comp_algorithm; 803 g->mt_comp2 = softc->comp_algorithm; 804 g->mt_comp3 = softc->comp_algorithm; 805 } 806 g->mt_density = softc->media_density; 807 g->mt_density0 = softc->media_density; 808 g->mt_density1 = softc->media_density; 809 g->mt_density2 = softc->media_density; 810 g->mt_density3 = softc->media_density; 811 g->mt_blksiz = softc->media_blksize; 812 g->mt_blksiz0 = softc->media_blksize; 813 g->mt_blksiz1 = softc->media_blksize; 814 g->mt_blksiz2 = softc->media_blksize; 815 g->mt_blksiz3 = softc->media_blksize; 816 g->mt_fileno = softc->fileno; 817 g->mt_blkno = softc->blkno; 818 g->mt_dsreg = (short) softc->dsreg; 819 error = 0; 820 break; 821 } 822 case MTIOCERRSTAT: 823 { 824 struct scsi_tape_errors *sep = 825 &((union mterrstat *)arg)->scsi_errstat; 826 827 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 828 ("saioctl: MTIOCERRSTAT\n")); 829 830 bzero(sep, sizeof(*sep)); 831 sep->io_resid = softc->last_io_resid; 832 bcopy((caddr_t) &softc->last_io_sense, sep->io_sense, 833 sizeof (sep->io_sense)); 834 bcopy((caddr_t) &softc->last_io_cdb, sep->io_cdb, 835 sizeof (sep->io_cdb)); 836 sep->ctl_resid = softc->last_ctl_resid; 837 bcopy((caddr_t) &softc->last_ctl_sense, sep->ctl_sense, 838 sizeof (sep->ctl_sense)); 839 bcopy((caddr_t) &softc->last_ctl_cdb, sep->ctl_cdb, 840 sizeof (sep->ctl_cdb)); 841 842 if (SA_IS_CTRL(dev) == 0 || didlockperiph) 843 bzero((caddr_t) &softc->errinfo, 844 sizeof (softc->errinfo)); 845 error = 0; 846 break; 847 } 848 case MTIOCTOP: 849 { 850 struct mtop *mt; 851 int count; 852 853 mt = (struct mtop *)arg; 854 855 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 856 ("saioctl: op=0x%x count=0x%x\n", 857 mt->mt_op, mt->mt_count)); 858 859 count = mt->mt_count; 860 switch (mt->mt_op) { 861 case MTWEOF: /* write an end-of-file marker */ 862 /* XXXX: NEED TO CLEAR SA_TAPE_WRITTEN */ 863 error = sawritefilemarks(periph, count, FALSE); 864 break; 865 case MTWSS: /* write a setmark */ 866 error = sawritefilemarks(periph, count, TRUE); 867 break; 868 case MTBSR: /* backward space record */ 869 case MTFSR: /* forward space record */ 870 case MTBSF: /* backward space file */ 871 case MTFSF: /* forward space file */ 872 case MTBSS: /* backward space setmark */ 873 case MTFSS: /* forward space setmark */ 874 case MTEOD: /* space to end of recorded medium */ 875 { 876 int nmarks; 877 878 spaceop = SS_FILEMARKS; 879 nmarks = softc->filemarks; 880 error = sacheckeod(periph); 881 if (error) { 882 xpt_print_path(periph->path); 883 printf("EOD check prior to spacing failed\n"); 884 softc->flags |= SA_FLAG_EIO_PENDING; 885 break; 886 } 887 nmarks -= softc->filemarks; 888 switch(mt->mt_op) { 889 case MTBSR: 890 count = -count; 891 /* FALLTHROUGH */ 892 case MTFSR: 893 spaceop = SS_BLOCKS; 894 break; 895 case MTBSF: 896 count = -count; 897 /* FALLTHROUGH */ 898 case MTFSF: 899 break; 900 case MTBSS: 901 count = -count; 902 /* FALLTHROUGH */ 903 case MTFSS: 904 spaceop = SS_SETMARKS; 905 break; 906 case MTEOD: 907 spaceop = SS_EOD; 908 count = 0; 909 nmarks = 0; 910 break; 911 default: 912 error = EINVAL; 913 break; 914 } 915 if (error) 916 break; 917 918 nmarks = softc->filemarks; 919 /* 920 * XXX: Why are we checking again? 921 */ 922 error = sacheckeod(periph); 923 if (error) 924 break; 925 nmarks -= softc->filemarks; 926 error = saspace(periph, count - nmarks, spaceop); 927 /* 928 * At this point, clear that we've written the tape 929 * and that we've written any filemarks. We really 930 * don't know what the applications wishes to do next- 931 * the sacheckeod's will make sure we terminated the 932 * tape correctly if we'd been writing, but the next 933 * action the user application takes will set again 934 * whether we need to write filemarks. 935 */ 936 softc->flags &= 937 ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN); 938 softc->filemarks = 0; 939 break; 940 } 941 case MTREW: /* rewind */ 942 (void) sacheckeod(periph); 943 error = sarewind(periph); 944 /* see above */ 945 softc->flags &= 946 ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN); 947 softc->filemarks = 0; 948 break; 949 case MTERASE: /* erase */ 950 error = saerase(periph, count); 951 softc->flags &= 952 ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN); 953 break; 954 case MTRETENS: /* re-tension tape */ 955 error = saretension(periph); 956 softc->flags &= 957 ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN); 958 break; 959 case MTOFFL: /* rewind and put the drive offline */ 960 961 (void) sacheckeod(periph); 962 /* see above */ 963 softc->flags &= ~SA_FLAG_TAPE_WRITTEN; 964 softc->filemarks = 0; 965 966 error = sarewind(periph); 967 968 /* 969 * Be sure to allow media removal before 970 * attempting the eject. 971 */ 972 973 saprevent(periph, PR_ALLOW); 974 if (error == 0) 975 error = saloadunload(periph, FALSE); 976 else 977 break; 978 softc->flags &= ~(SA_FLAG_TAPE_LOCKED| 979 SA_FLAG_TAPE_WRITTEN| SA_FLAG_TAPE_WRITTEN| 980 SA_FLAG_TAPE_FROZEN); 981 break; 982 983 case MTNOP: /* no operation, sets status only */ 984 case MTCACHE: /* enable controller cache */ 985 case MTNOCACHE: /* disable controller cache */ 986 error = 0; 987 break; 988 989 case MTSETBSIZ: /* Set block size for device */ 990 991 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, count, 992 0, 0, 0); 993 if (error == 0) { 994 softc->last_media_blksize = 995 softc->media_blksize; 996 softc->media_blksize = count; 997 if (count) { 998 softc->flags |= SA_FLAG_FIXED; 999 if (powerof2(count)) { 1000 softc->blk_shift = 1001 ffs(count) - 1; 1002 softc->blk_mask = count - 1; 1003 } else { 1004 softc->blk_mask = ~0; 1005 softc->blk_shift = 0; 1006 } 1007 /* 1008 * Make the user's desire 'persistent'. 1009 */ 1010 softc->quirks &= ~SA_QUIRK_VARIABLE; 1011 softc->quirks |= SA_QUIRK_FIXED; 1012 } else { 1013 softc->flags &= ~SA_FLAG_FIXED; 1014 if (softc->max_blk == 0) { 1015 softc->max_blk = ~0; 1016 } 1017 softc->blk_shift = 0; 1018 if (softc->blk_gran != 0) { 1019 softc->blk_mask = 1020 softc->blk_gran - 1; 1021 } else { 1022 softc->blk_mask = 0; 1023 } 1024 /* 1025 * Make the user's desire 'persistent'. 1026 */ 1027 softc->quirks |= SA_QUIRK_VARIABLE; 1028 softc->quirks &= ~SA_QUIRK_FIXED; 1029 } 1030 } 1031 break; 1032 case MTSETDNSTY: /* Set density for device and mode */ 1033 if (count > UCHAR_MAX) { 1034 error = EINVAL; 1035 break; 1036 } else { 1037 error = sasetparams(periph, SA_PARAM_DENSITY, 1038 0, count, 0, 0); 1039 } 1040 break; 1041 case MTCOMP: /* enable compression */ 1042 /* 1043 * Some devices don't support compression, and 1044 * don't like it if you ask them for the 1045 * compression page. 1046 */ 1047 if ((softc->quirks & SA_QUIRK_NOCOMP) || 1048 (softc->flags & SA_FLAG_COMP_UNSUPP)) { 1049 error = ENODEV; 1050 break; 1051 } 1052 error = sasetparams(periph, SA_PARAM_COMPRESSION, 1053 0, 0, count, 0); 1054 break; 1055 default: 1056 error = EINVAL; 1057 } 1058 break; 1059 } 1060 case MTIOCIEOT: 1061 case MTIOCEEOT: 1062 error = 0; 1063 break; 1064 case MTIOCRDSPOS: 1065 error = sardpos(periph, 0, (u_int32_t *) arg); 1066 break; 1067 case MTIOCRDHPOS: 1068 error = sardpos(periph, 1, (u_int32_t *) arg); 1069 break; 1070 case MTIOCSLOCATE: 1071 error = sasetpos(periph, 0, (u_int32_t *) arg); 1072 break; 1073 case MTIOCHLOCATE: 1074 error = sasetpos(periph, 1, (u_int32_t *) arg); 1075 break; 1076 case MTIOCGETEOTMODEL: 1077 error = 0; 1078 if (softc->quirks & SA_QUIRK_1FM) 1079 mode = 1; 1080 else 1081 mode = 2; 1082 *((u_int32_t *) arg) = mode; 1083 break; 1084 case MTIOCSETEOTMODEL: 1085 error = 0; 1086 switch (*((u_int32_t *) arg)) { 1087 case 1: 1088 softc->quirks &= ~SA_QUIRK_2FM; 1089 softc->quirks |= SA_QUIRK_1FM; 1090 break; 1091 case 2: 1092 softc->quirks &= ~SA_QUIRK_1FM; 1093 softc->quirks |= SA_QUIRK_2FM; 1094 break; 1095 default: 1096 error = EINVAL; 1097 break; 1098 } 1099 break; 1100 default: 1101 error = cam_periph_ioctl(periph, cmd, arg, saerror); 1102 break; 1103 } 1104 if (didlockperiph) { 1105 cam_periph_unlock(periph); 1106 } 1107 return (error); 1108} 1109 1110static void 1111sainit(void) 1112{ 1113 cam_status status; 1114 struct cam_path *path; 1115 1116 /* 1117 * Create our extend array for storing the devices we attach to. 1118 */ 1119 saperiphs = cam_extend_new(); 1120 if (saperiphs == NULL) { 1121 printf("sa: Failed to alloc extend array!\n"); 1122 return; 1123 } 1124 1125 /* 1126 * Install a global async callback. 1127 */ 1128 status = xpt_create_path(&path, NULL, CAM_XPT_PATH_ID, 1129 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 1130 1131 if (status == CAM_REQ_CMP) { 1132 /* Register the async callbacks of interrest */ 1133 struct ccb_setasync csa; /* 1134 * This is an immediate CCB, 1135 * so using the stack is OK 1136 */ 1137 xpt_setup_ccb(&csa.ccb_h, path, 5); 1138 csa.ccb_h.func_code = XPT_SASYNC_CB; 1139 csa.event_enable = AC_FOUND_DEVICE; 1140 csa.callback = saasync; 1141 csa.callback_arg = NULL; 1142 xpt_action((union ccb *)&csa); 1143 status = csa.ccb_h.status; 1144 xpt_free_path(path); 1145 } 1146 1147 if (status != CAM_REQ_CMP) { 1148 printf("sa: Failed to attach master async callback " 1149 "due to status 0x%x!\n", status); 1150 } else { 1151 /* If we were successfull, register our devsw */ 1152 cdevsw_add(&sa_cdevsw); 1153 } 1154} 1155 1156static void 1157saoninvalidate(struct cam_periph *periph) 1158{ 1159 struct sa_softc *softc; 1160 struct buf *q_bp; 1161 struct ccb_setasync csa; 1162 int s; 1163 1164 softc = (struct sa_softc *)periph->softc; 1165 1166 /* 1167 * De-register any async callbacks. 1168 */ 1169 xpt_setup_ccb(&csa.ccb_h, periph->path, 1170 /* priority */ 5); 1171 csa.ccb_h.func_code = XPT_SASYNC_CB; 1172 csa.event_enable = 0; 1173 csa.callback = saasync; 1174 csa.callback_arg = periph; 1175 xpt_action((union ccb *)&csa); 1176 1177 softc->flags |= SA_FLAG_INVALID; 1178 1179 /* 1180 * Although the oninvalidate() routines are always called at 1181 * splsoftcam, we need to be at splbio() here to keep the buffer 1182 * queue from being modified while we traverse it. 1183 */ 1184 s = splbio(); 1185 1186 /* 1187 * Return all queued I/O with ENXIO. 1188 * XXX Handle any transactions queued to the card 1189 * with XPT_ABORT_CCB. 1190 */ 1191 while ((q_bp = bufq_first(&softc->buf_queue)) != NULL){ 1192 bufq_remove(&softc->buf_queue, q_bp); 1193 q_bp->b_resid = q_bp->b_bcount; 1194 q_bp->b_error = ENXIO; 1195 q_bp->b_flags |= B_ERROR; 1196 biodone(q_bp); 1197 } 1198 softc->queue_count = 0; 1199 splx(s); 1200 1201 xpt_print_path(periph->path); 1202 printf("lost device\n"); 1203 1204} 1205 1206static void 1207sacleanup(struct cam_periph *periph) 1208{ 1209 struct sa_softc *softc; 1210 1211 softc = (struct sa_softc *)periph->softc; 1212 1213 devstat_remove_entry(&softc->device_stats); 1214 cam_extend_release(saperiphs, periph->unit_number); 1215 xpt_print_path(periph->path); 1216 printf("removing device entry\n"); 1217 free(softc, M_DEVBUF); 1218} 1219 1220static void 1221saasync(void *callback_arg, u_int32_t code, 1222 struct cam_path *path, void *arg) 1223{ 1224 struct cam_periph *periph; 1225 1226 periph = (struct cam_periph *)callback_arg; 1227 switch (code) { 1228 case AC_FOUND_DEVICE: 1229 { 1230 struct ccb_getdev *cgd; 1231 cam_status status; 1232 1233 cgd = (struct ccb_getdev *)arg; 1234 1235 if (cgd->pd_type != T_SEQUENTIAL) 1236 break; 1237 1238 /* 1239 * Allocate a peripheral instance for 1240 * this device and start the probe 1241 * process. 1242 */ 1243 status = cam_periph_alloc(saregister, saoninvalidate, 1244 sacleanup, sastart, 1245 "sa", CAM_PERIPH_BIO, cgd->ccb_h.path, 1246 saasync, AC_FOUND_DEVICE, cgd); 1247 1248 if (status != CAM_REQ_CMP 1249 && status != CAM_REQ_INPROG) 1250 printf("saasync: Unable to probe new device " 1251 "due to status 0x%x\n", status); 1252 break; 1253 } 1254 default: 1255 cam_periph_async(periph, code, path, arg); 1256 break; 1257 } 1258} 1259 1260static cam_status 1261saregister(struct cam_periph *periph, void *arg) 1262{ 1263 struct sa_softc *softc; 1264 struct ccb_setasync csa; 1265 struct ccb_getdev *cgd; 1266 caddr_t match; 1267 1268 cgd = (struct ccb_getdev *)arg; 1269 if (periph == NULL) { 1270 printf("saregister: periph was NULL!!\n"); 1271 return(CAM_REQ_CMP_ERR); 1272 } 1273 1274 if (cgd == NULL) { 1275 printf("saregister: no getdev CCB, can't register device\n"); 1276 return(CAM_REQ_CMP_ERR); 1277 } 1278 1279 softc = (struct sa_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT); 1280 1281 if (softc == NULL) { 1282 printf("saregister: Unable to probe new device. " 1283 "Unable to allocate softc\n"); 1284 return(CAM_REQ_CMP_ERR); 1285 } 1286 1287 bzero(softc, sizeof(*softc)); 1288 softc->scsi_rev = SID_ANSI_REV(&cgd->inq_data); 1289 softc->state = SA_STATE_NORMAL; 1290 softc->fileno = (daddr_t) -1; 1291 softc->blkno = (daddr_t) -1; 1292 1293 bufq_init(&softc->buf_queue); 1294 periph->softc = softc; 1295 cam_extend_set(saperiphs, periph->unit_number, periph); 1296 1297 /* 1298 * See if this device has any quirks. 1299 */ 1300 match = cam_quirkmatch((caddr_t)&cgd->inq_data, 1301 (caddr_t)sa_quirk_table, 1302 sizeof(sa_quirk_table)/sizeof(*sa_quirk_table), 1303 sizeof(*sa_quirk_table), scsi_inquiry_match); 1304 1305 if (match != NULL) { 1306 softc->quirks = ((struct sa_quirk_entry *)match)->quirks; 1307 softc->last_media_blksize = 1308 ((struct sa_quirk_entry *)match)->prefblk; 1309#ifdef CAMDEBUG 1310 xpt_print_path(periph->path); 1311 printf("found quirk entry %d\n", (int) 1312 (((struct sa_quirk_entry *) match) - sa_quirk_table)); 1313#endif 1314 } else 1315 softc->quirks = SA_QUIRK_NONE; 1316 1317 /* 1318 * The SA driver supports a blocksize, but we don't know the 1319 * blocksize until we media is inserted. So, set a flag to 1320 * indicate that the blocksize is unavailable right now. 1321 */ 1322 devstat_add_entry(&softc->device_stats, "sa", 1323 periph->unit_number, 0, 1324 DEVSTAT_BS_UNAVAILABLE, 1325 cgd->pd_type | DEVSTAT_TYPE_IF_SCSI, 1326 DEVSTAT_PRIORITY_SA); 1327 1328 /* 1329 * Add an async callback so that we get 1330 * notified if this device goes away. 1331 */ 1332 xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5); 1333 csa.ccb_h.func_code = XPT_SASYNC_CB; 1334 csa.event_enable = AC_LOST_DEVICE; 1335 csa.callback = saasync; 1336 csa.callback_arg = periph; 1337 xpt_action((union ccb *)&csa); 1338 1339 xpt_announce_periph(periph, NULL); 1340 1341 return(CAM_REQ_CMP); 1342} 1343 1344static void 1345sastart(struct cam_periph *periph, union ccb *start_ccb) 1346{ 1347 struct sa_softc *softc; 1348 1349 softc = (struct sa_softc *)periph->softc; 1350 1351 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("sastart")); 1352 1353 switch (softc->state) { 1354 case SA_STATE_NORMAL: 1355 { 1356 /* Pull a buffer from the queue and get going on it */ 1357 struct buf *bp; 1358 int s; 1359 1360 /* 1361 * See if there is a buf with work for us to do.. 1362 */ 1363 s = splbio(); 1364 bp = bufq_first(&softc->buf_queue); 1365 if (periph->immediate_priority <= periph->pinfo.priority) { 1366 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, 1367 ("queuing for immediate ccb\n")); 1368 start_ccb->ccb_h.ccb_type = SA_CCB_WAITING; 1369 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 1370 periph_links.sle); 1371 periph->immediate_priority = CAM_PRIORITY_NONE; 1372 splx(s); 1373 wakeup(&periph->ccb_list); 1374 } else if (bp == NULL) { 1375 splx(s); 1376 xpt_release_ccb(start_ccb); 1377 } else if ((softc->flags & SA_FLAG_ERR_PENDING) != 0) { 1378 struct buf *done_bp; 1379 softc->queue_count--; 1380 bufq_remove(&softc->buf_queue, bp); 1381 bp->b_resid = bp->b_bcount; 1382 bp->b_flags |= B_ERROR; 1383 if ((softc->flags & SA_FLAG_EOM_PENDING) != 0) { 1384 if ((bp->b_flags & B_READ) == 0) 1385 bp->b_error = ENOSPC; 1386 else 1387 bp->b_error = EIO; 1388 } 1389 if ((softc->flags & SA_FLAG_EOF_PENDING) != 0) { 1390 bp->b_error = EIO; 1391 } 1392 if ((softc->flags & SA_FLAG_EIO_PENDING) != 0) { 1393 bp->b_error = EIO; 1394 } 1395 done_bp = bp; 1396 bp = bufq_first(&softc->buf_queue); 1397 /* 1398 * Only if we have no other buffers queued up 1399 * do we clear the pending error flag. 1400 */ 1401 if (bp == NULL) 1402 softc->flags &= ~SA_FLAG_ERR_PENDING; 1403 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1404 ("sastart- ERR_PENDING now 0x%x, bp is %sNULL, " 1405 "%d more buffers queued up\n", 1406 (softc->flags & SA_FLAG_ERR_PENDING), 1407 (bp != NULL)? "not " : " ", softc->queue_count)); 1408 splx(s); 1409 xpt_release_ccb(start_ccb); 1410 biodone(done_bp); 1411 } else { 1412 u_int32_t length; 1413 1414 bufq_remove(&softc->buf_queue, bp); 1415 softc->queue_count--; 1416 1417 if ((softc->flags & SA_FLAG_FIXED) != 0) { 1418 if (softc->blk_shift != 0) { 1419 length = 1420 bp->b_bcount >> softc->blk_shift; 1421 } else if (softc->media_blksize != 0) { 1422 length = 1423 bp->b_bcount / softc->media_blksize; 1424 } else { 1425 bp->b_error = EIO; 1426 xpt_print_path(periph->path); 1427 printf("zero blocksize for " 1428 "FIXED length writes?\n"); 1429 splx(s); 1430 biodone(bp); 1431 break; 1432 } 1433 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1434 ("Fixed Record Count is %d\n", length)); 1435 } else { 1436 length = bp->b_bcount; 1437 CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO, 1438 ("Variable Record Count is %d\n", length)); 1439 } 1440 devstat_start_transaction(&softc->device_stats); 1441 /* 1442 * Some people have theorized that we should 1443 * suppress illegal length indication if we are 1444 * running in variable block mode so that we don't 1445 * have to request sense every time our requested 1446 * block size is larger than the written block. 1447 * The residual information from the ccb allows 1448 * us to identify this situation anyway. The only 1449 * problem with this is that we will not get 1450 * information about blocks that are larger than 1451 * our read buffer unless we set the block size 1452 * in the mode page to something other than 0. 1453 * 1454 * I believe that this is a non-issue. If user apps 1455 * don't adjust their read size to match our record 1456 * size, that's just life. Anyway, the typical usage 1457 * would be to issue, e.g., 64KB reads and occasionally 1458 * have to do deal with 512 byte or 1KB intermediate 1459 * records. 1460 */ 1461 softc->dsreg = (bp->b_flags & B_READ)? 1462 MTIO_DSREG_RD : MTIO_DSREG_WR; 1463 scsi_sa_read_write(&start_ccb->csio, 0, sadone, 1464 MSG_SIMPLE_Q_TAG, (bp->b_flags & B_READ) != 0, 1465 FALSE, (softc->flags & SA_FLAG_FIXED) != 0, 1466 length, bp->b_data, bp->b_bcount, SSD_FULL_SIZE, 1467 120 * 60 * 1000); 1468 start_ccb->ccb_h.ccb_type = SA_CCB_BUFFER_IO; 1469 start_ccb->ccb_h.ccb_bp = bp; 1470 bp = bufq_first(&softc->buf_queue); 1471 splx(s); 1472 xpt_action(start_ccb); 1473 } 1474 1475 if (bp != NULL) { 1476 /* Have more work to do, so ensure we stay scheduled */ 1477 xpt_schedule(periph, 1); 1478 } 1479 break; 1480 } 1481 case SA_STATE_ABNORMAL: 1482 default: 1483 panic("state 0x%x in sastart", softc->state); 1484 break; 1485 } 1486} 1487 1488 1489static void 1490sadone(struct cam_periph *periph, union ccb *done_ccb) 1491{ 1492 struct sa_softc *softc; 1493 struct ccb_scsiio *csio; 1494 1495 softc = (struct sa_softc *)periph->softc; 1496 csio = &done_ccb->csio; 1497 switch (csio->ccb_h.ccb_type) { 1498 case SA_CCB_BUFFER_IO: 1499 { 1500 struct buf *bp; 1501 int error; 1502 1503 softc->dsreg = MTIO_DSREG_REST; 1504 bp = (struct buf *)done_ccb->ccb_h.ccb_bp; 1505 error = 0; 1506 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1507 if ((error = saerror(done_ccb, 0, 0)) == ERESTART) { 1508 /* 1509 * A retry was scheduled, so just return. 1510 */ 1511 return; 1512 } 1513 } 1514 1515 if (error == EIO) { 1516 int s; 1517 struct buf *q_bp; 1518 1519 /* 1520 * Catastrophic error. Mark the tape as not mounted. 1521 * Return all queued I/O with EIO, and unfreeze 1522 * our queue so that future transactions that 1523 * attempt to fix this problem can get to the 1524 * device. 1525 * 1526 */ 1527 1528 s = splbio(); 1529 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 1530 while ((q_bp = bufq_first(&softc->buf_queue)) != NULL) { 1531 bufq_remove(&softc->buf_queue, q_bp); 1532 q_bp->b_resid = q_bp->b_bcount; 1533 q_bp->b_error = EIO; 1534 q_bp->b_flags |= B_ERROR; 1535 biodone(q_bp); 1536 } 1537 splx(s); 1538 } 1539 if (error != 0) { 1540 bp->b_resid = bp->b_bcount; 1541 bp->b_error = error; 1542 bp->b_flags |= B_ERROR; 1543 /* 1544 * In the error case, position is updated in saerror. 1545 */ 1546 } else { 1547 bp->b_resid = csio->resid; 1548 bp->b_error = 0; 1549 if (csio->resid != 0) { 1550 bp->b_flags |= B_ERROR; 1551 } 1552 if ((bp->b_flags & B_READ) == 0) { 1553 softc->flags |= SA_FLAG_TAPE_WRITTEN; 1554 softc->filemarks = 0; 1555 } 1556 if (softc->blkno != (daddr_t) -1) { 1557 if ((softc->flags & SA_FLAG_FIXED) != 0) { 1558 u_int32_t l; 1559 if (softc->blk_shift != 0) { 1560 l = bp->b_bcount >> 1561 softc->blk_shift; 1562 } else { 1563 l = bp->b_bcount / 1564 softc->media_blksize; 1565 } 1566 softc->blkno += (daddr_t) l; 1567 } else { 1568 softc->blkno++; 1569 } 1570 } 1571 } 1572 /* 1573 * If we had an error (immediate or pending), 1574 * release the device queue now. 1575 */ 1576 if (error || (softc->flags & SA_FLAG_ERR_PENDING)) 1577 cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0); 1578#ifdef CAMDEBUG 1579 if (error || bp->b_resid) { 1580 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1581 ("error %d resid %ld count %ld\n", error, 1582 bp->b_resid, bp->b_bcount)); 1583 } 1584#endif 1585 devstat_end_transaction(&softc->device_stats, 1586 bp->b_bcount - bp->b_resid, 1587 done_ccb->csio.tag_action & 0xf, 1588 (bp->b_flags & B_READ) ? DEVSTAT_READ 1589 : DEVSTAT_WRITE); 1590 biodone(bp); 1591 break; 1592 } 1593 case SA_CCB_WAITING: 1594 { 1595 /* Caller will release the CCB */ 1596 wakeup(&done_ccb->ccb_h.cbfcnp); 1597 return; 1598 } 1599 } 1600 xpt_release_ccb(done_ccb); 1601} 1602 1603/* 1604 * Mount the tape (make sure it's ready for I/O). 1605 */ 1606static int 1607samount(struct cam_periph *periph, int oflags, dev_t dev) 1608{ 1609 struct sa_softc *softc; 1610 union ccb *ccb; 1611 struct ccb_scsiio *csio; 1612 int error; 1613 1614 /* 1615 * oflags can be checked for 'kind' of open (read-only check) - later 1616 * dev can be checked for a control-mode or compression open - later 1617 */ 1618 UNUSED_PARAMETER(oflags); 1619 UNUSED_PARAMETER(dev); 1620 1621 1622 softc = (struct sa_softc *)periph->softc; 1623 ccb = cam_periph_getccb(periph, 1); 1624 csio = &ccb->csio; 1625 error = 0; 1626 1627 /* 1628 * This *should* determine if something has happend since the last 1629 * open/mount that would invalidate the mount, but is currently 1630 * broken. 1631 * 1632 * This will also eat any pending UAs. 1633 */ 1634 scsi_test_unit_ready(csio, 1, sadone, 1635 MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5 * 60 * 1000); 1636 1637 /* 1638 * Because we're not supplying a error routine, cam_periph_runccb 1639 * will unfreeze the queue if there was an error. 1640 */ 1641 cam_periph_runccb(ccb, NULL, 0, 0, &softc->device_stats); 1642 1643 1644 if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) { 1645 struct scsi_read_block_limits_data *rblim = NULL; 1646 int comp_enabled, comp_supported; 1647 u_int8_t write_protect, guessing = 0; 1648 1649 /* 1650 * Clear out old state. 1651 */ 1652 softc->flags &= ~(SA_FLAG_TAPE_WP|SA_FLAG_TAPE_WRITTEN| 1653 SA_FLAG_ERR_PENDING|SA_FLAG_COMP_ENABLED| 1654 SA_FLAG_COMP_SUPP|SA_FLAG_COMP_UNSUPP); 1655 softc->filemarks = 0; 1656 1657 /* 1658 * *Very* first off, make sure we're loaded to BOT. 1659 */ 1660 scsi_load_unload(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE, 1661 FALSE, FALSE, 1, SSD_FULL_SIZE, 60000); 1662 error = cam_periph_runccb(ccb, saerror, 0, SF_QUIET_IR, 1663 &softc->device_stats); 1664 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1665 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 1666 /* 1667 * In case this doesn't work, do a REWIND instead 1668 */ 1669 if (error) { 1670 scsi_rewind(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, 1671 FALSE, SSD_FULL_SIZE, 1672 (SA_REWIND_TIMEOUT) * 60 * 1000); 1673 error = cam_periph_runccb(ccb, saerror, 0, 0, 1674 &softc->device_stats); 1675 } 1676 if (error) { 1677 xpt_release_ccb(ccb); 1678 goto exit; 1679 } 1680 1681 /* 1682 * Next off, determine block limits. 1683 */ 1684 rblim = (struct scsi_read_block_limits_data *) 1685 malloc(sizeof(*rblim), M_TEMP, M_WAITOK); 1686 1687 /* it is safe to retry this */ 1688 scsi_read_block_limits(csio, 5, sadone, MSG_SIMPLE_Q_TAG, 1689 rblim, SSD_FULL_SIZE, 5000); 1690 1691 error = cam_periph_runccb(ccb, saerror, 0, 1692 SF_RETRY_UA | SF_RETRY_SELTO, &softc->device_stats); 1693 1694 xpt_release_ccb(ccb); 1695 1696 if (error != 0) { 1697 /* 1698 * If it's less than SCSI-2, READ BLOCK LIMITS is not 1699 * a MANDATORY command. Anyway- it doesn't matter- 1700 * we can proceed anyway. 1701 */ 1702 softc->blk_gran = 0; 1703 softc->max_blk = ~0; 1704 softc->min_blk = 0; 1705 } else { 1706 if (softc->scsi_rev >= SCSI_REV_3) { 1707 softc->blk_gran = RBL_GRAN(rblim); 1708 } else { 1709 softc->blk_gran = 0; 1710 } 1711 /* 1712 * We take max_blk == min_blk to mean a default to 1713 * fixed mode- but note that whatever we get out of 1714 * sagetparams below will actually determine whether 1715 * we are actually *in* fixed mode. 1716 */ 1717 softc->max_blk = scsi_3btoul(rblim->maximum); 1718 softc->min_blk = scsi_2btoul(rblim->minimum); 1719 1720 1721 } 1722 /* 1723 * Next, perform a mode sense to determine 1724 * current density, blocksize, compression etc. 1725 */ 1726 error = sagetparams(periph, SA_PARAM_ALL, 1727 &softc->media_blksize, 1728 &softc->media_density, 1729 &softc->media_numblks, 1730 &softc->buffer_mode, &write_protect, 1731 &softc->speed, &comp_supported, 1732 &comp_enabled, &softc->comp_algorithm, 1733 NULL); 1734 1735 if (error != 0) { 1736 /* 1737 * We could work a little harder here. We could 1738 * adjust our attempts to get information. It 1739 * might be an ancient tape drive. If someone 1740 * nudges us, we'll do that. 1741 */ 1742 goto exit; 1743 } 1744 1745 /* 1746 * If no quirk has determined that this is a device that is 1747 * preferred to be in fixed or variable mode, now is the time 1748 * to find out. 1749 */ 1750 if ((softc->quirks & (SA_QUIRK_FIXED|SA_QUIRK_VARIABLE)) == 0) { 1751 guessing = 1; 1752 /* 1753 * This could be expensive to find out. Luckily we 1754 * only need to do this once. If we start out in 1755 * 'default' mode, try and set ourselves to one 1756 * of the densities that would determine a wad 1757 * of other stuff. Go from highest to lowest. 1758 */ 1759 if (softc->media_density == SCSI_DEFAULT_DENSITY) { 1760 int i; 1761 static u_int8_t ctry[] = { 1762 SCSI_DENSITY_HALFINCH_PE, 1763 SCSI_DENSITY_HALFINCH_6250C, 1764 SCSI_DENSITY_HALFINCH_6250, 1765 SCSI_DENSITY_HALFINCH_1600, 1766 SCSI_DENSITY_HALFINCH_800, 1767 SCSI_DENSITY_QIC_4GB, 1768 SCSI_DENSITY_QIC_2GB, 1769 SCSI_DENSITY_QIC_525_320, 1770 SCSI_DENSITY_QIC_150, 1771 SCSI_DENSITY_QIC_120, 1772 SCSI_DENSITY_QIC_24, 1773 SCSI_DENSITY_QIC_11_9TRK, 1774 SCSI_DENSITY_QIC_11_4TRK, 1775 SCSI_DENSITY_QIC_1320, 1776 SCSI_DENSITY_QIC_3080, 1777 0 1778 }; 1779 for (i = 0; ctry[i]; i++) { 1780 error = sasetparams(periph, 1781 SA_PARAM_DENSITY, 0, ctry[i], 1782 0, SF_NO_PRINT); 1783 if (error == 0) { 1784 softc->media_density = ctry[i]; 1785 break; 1786 } 1787 } 1788 } 1789 switch (softc->media_density) { 1790 case SCSI_DENSITY_QIC_11_4TRK: 1791 case SCSI_DENSITY_QIC_11_9TRK: 1792 case SCSI_DENSITY_QIC_24: 1793 case SCSI_DENSITY_QIC_120: 1794 case SCSI_DENSITY_QIC_150: 1795 case SCSI_DENSITY_QIC_1320: 1796 case SCSI_DENSITY_QIC_3080: 1797 softc->quirks &= ~SA_QUIRK_2FM; 1798 softc->quirks |= SA_QUIRK_FIXED|SA_QUIRK_1FM; 1799 softc->last_media_blksize = 512; 1800 break; 1801 case SCSI_DENSITY_QIC_4GB: 1802 case SCSI_DENSITY_QIC_2GB: 1803 case SCSI_DENSITY_QIC_525_320: 1804 softc->quirks &= ~SA_QUIRK_2FM; 1805 softc->quirks |= SA_QUIRK_FIXED|SA_QUIRK_1FM; 1806 softc->last_media_blksize = 1024; 1807 break; 1808 default: 1809 softc->last_media_blksize = 1810 softc->media_blksize; 1811 softc->quirks |= SA_QUIRK_VARIABLE; 1812 break; 1813 } 1814 } 1815 1816 /* 1817 * If no quirk has determined that this is a device that needs 1818 * to have 2 Filemarks at EOD, now is the time to find out. 1819 */ 1820 1821 if ((softc->quirks & SA_QUIRK_2FM) == 0) { 1822 switch (softc->media_density) { 1823 case SCSI_DENSITY_HALFINCH_800: 1824 case SCSI_DENSITY_HALFINCH_1600: 1825 case SCSI_DENSITY_HALFINCH_6250: 1826 case SCSI_DENSITY_HALFINCH_6250C: 1827 case SCSI_DENSITY_HALFINCH_PE: 1828 softc->quirks &= ~SA_QUIRK_1FM; 1829 softc->quirks |= SA_QUIRK_2FM; 1830 break; 1831 default: 1832 break; 1833 } 1834 } 1835 1836 /* 1837 * Now validate that some info we got makes sense. 1838 */ 1839 if ((softc->max_blk < softc->media_blksize) || 1840 (softc->min_blk > softc->media_blksize && 1841 softc->media_blksize)) { 1842 xpt_print_path(ccb->ccb_h.path); 1843 printf("BLOCK LIMITS (%d..%d) could not match current " 1844 "block settings (%d)- adjusting\n", softc->min_blk, 1845 softc->max_blk, softc->media_blksize); 1846 softc->max_blk = softc->min_blk = 1847 softc->media_blksize; 1848 } 1849 1850 /* 1851 * Now put ourselves into the right frame of mind based 1852 * upon quirks... 1853 */ 1854tryagain: 1855 /* 1856 * If we want to be in FIXED mode and our current blocksize 1857 * is not equal to our last blocksize (if nonzero), try and 1858 * set ourselves to this last blocksize (as the 'preferred' 1859 * block size). The initial quirkmatch at registry sets the 1860 * initial 'last' blocksize. If, for whatever reason, this 1861 * 'last' blocksize is zero, set the blocksize to 512, 1862 * or min_blk if that's larger. 1863 */ 1864 if ((softc->quirks & SA_QUIRK_FIXED) && 1865 (softc->media_blksize != softc->last_media_blksize)) { 1866 softc->media_blksize = softc->last_media_blksize; 1867 if (softc->media_blksize == 0) { 1868 softc->media_blksize = 512; 1869 if (softc->media_blksize < softc->min_blk) { 1870 softc->media_blksize = softc->min_blk; 1871 } 1872 } 1873 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, 1874 softc->media_blksize, 0, 0, SF_NO_PRINT); 1875 if (error) { 1876 xpt_print_path(ccb->ccb_h.path); 1877 printf("unable to set fixed blocksize to %d\n", 1878 softc->media_blksize); 1879 goto exit; 1880 } 1881 } 1882 1883 if ((softc->quirks & SA_QUIRK_VARIABLE) && 1884 (softc->media_blksize != 0)) { 1885 softc->last_media_blksize = softc->media_blksize; 1886 softc->media_blksize = 0; 1887 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, 1888 0, 0, 0, SF_NO_PRINT); 1889 if (error) { 1890 /* 1891 * If this fails and we were guessing, just 1892 * assume that we got it wrong and go try 1893 * fixed block mode. Don't even check against 1894 * density code at this point. 1895 */ 1896 if (guessing) { 1897 softc->quirks &= ~SA_QUIRK_VARIABLE; 1898 softc->quirks |= SA_QUIRK_FIXED; 1899 if (softc->last_media_blksize == 0) 1900 softc->last_media_blksize = 512; 1901 goto tryagain; 1902 } 1903 xpt_print_path(ccb->ccb_h.path); 1904 printf("unable to set variable blocksize\n"); 1905 goto exit; 1906 } 1907 } 1908 1909 /* 1910 * Now that we have the current block size, 1911 * set up some parameters for sastart's usage. 1912 */ 1913 if (softc->media_blksize) { 1914 softc->flags |= SA_FLAG_FIXED; 1915 if (powerof2(softc->media_blksize)) { 1916 softc->blk_shift = 1917 ffs(softc->media_blksize) - 1; 1918 softc->blk_mask = softc->media_blksize - 1; 1919 } else { 1920 softc->blk_mask = ~0; 1921 softc->blk_shift = 0; 1922 } 1923 } else { 1924 /* 1925 * The SCSI-3 spec allows 0 to mean "unspecified". 1926 * The SCSI-1 spec allows 0 to mean 'infinite'. 1927 * 1928 * Either works here. 1929 */ 1930 if (softc->max_blk == 0) { 1931 softc->max_blk = ~0; 1932 } 1933 softc->blk_shift = 0; 1934 if (softc->blk_gran != 0) { 1935 softc->blk_mask = softc->blk_gran - 1; 1936 } else { 1937 softc->blk_mask = 0; 1938 } 1939 } 1940 1941 if (write_protect) 1942 softc->flags |= SA_FLAG_TAPE_WP; 1943 1944 if (comp_supported) { 1945 if (softc->saved_comp_algorithm == 0) 1946 softc->saved_comp_algorithm = 1947 softc->comp_algorithm; 1948 softc->flags |= SA_FLAG_COMP_SUPP; 1949 if (comp_enabled) 1950 softc->flags |= SA_FLAG_COMP_ENABLED; 1951 } else 1952 softc->flags |= SA_FLAG_COMP_UNSUPP; 1953 1954 if (softc->buffer_mode == SMH_SA_BUF_MODE_NOBUF) { 1955 error = sasetparams(periph, SA_PARAM_BUFF_MODE, 0, 1956 0, 0, SF_NO_PRINT); 1957 if (error == 0) 1958 softc->buffer_mode = SMH_SA_BUF_MODE_SIBUF; 1959 } 1960 1961 1962 if (error == 0) { 1963 softc->flags |= SA_FLAG_TAPE_MOUNTED; 1964 } 1965exit: 1966 if (rblim != NULL) 1967 free(rblim, M_TEMP); 1968 1969 if (error != 0) { 1970 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 1971 softc->dsreg = MTIO_DSREG_NIL; 1972 } else { 1973 softc->fileno = softc->blkno = 0; 1974 softc->dsreg = MTIO_DSREG_REST; 1975 } 1976#if SA_2FM_AT_EOD == 1 1977 if ((softc->quirks & SA_QUIRK_1FM) == 0) 1978 softc->quirks |= SA_QUIRK_2FM; 1979#else 1980 if ((softc->quirks & SA_QUIRK_2FM) == 0) 1981 softc->quirks |= SA_QUIRK_1FM; 1982#endif 1983 } else 1984 xpt_release_ccb(ccb); 1985 1986 return (error); 1987} 1988 1989static int 1990sacheckeod(struct cam_periph *periph) 1991{ 1992 int error; 1993 int markswanted; 1994 struct sa_softc *softc; 1995 1996 softc = (struct sa_softc *)periph->softc; 1997 markswanted = 0; 1998 1999 if ((softc->flags & SA_FLAG_TAPE_WRITTEN) != 0) { 2000 markswanted++; 2001 if (softc->quirks & SA_QUIRK_2FM) 2002 markswanted++; 2003 } 2004 2005 if (softc->filemarks < markswanted) { 2006 markswanted -= softc->filemarks; 2007 error = sawritefilemarks(periph, markswanted, FALSE); 2008 } else { 2009 error = 0; 2010 } 2011 return (error); 2012} 2013 2014static int 2015saerror(union ccb *ccb, u_int32_t cflgs, u_int32_t sflgs) 2016{ 2017 static const char *toobig = 2018 "%d-byte tape record bigger than suplied buffer\n"; 2019 struct cam_periph *periph; 2020 struct sa_softc *softc; 2021 struct ccb_scsiio *csio; 2022 struct scsi_sense_data *sense; 2023 u_int32_t resid; 2024 int32_t info; 2025 int error_code, sense_key, asc, ascq; 2026 int error, defer_action; 2027 2028 periph = xpt_path_periph(ccb->ccb_h.path); 2029 softc = (struct sa_softc *)periph->softc; 2030 csio = &ccb->csio; 2031 sense = &csio->sense_data; 2032 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq); 2033 error = 0; 2034 2035 /* 2036 * Calculate/latch up, any residuals... 2037 */ 2038 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) { 2039 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) { 2040 info = (int32_t) scsi_4btoul(sense->info); 2041 resid = info; 2042 if ((softc->flags & SA_FLAG_FIXED) != 0) 2043 resid *= softc->media_blksize; 2044 } else { 2045 resid = csio->dxfer_len; 2046 info = resid; 2047 if ((softc->flags & SA_FLAG_FIXED) != 0) { 2048 if (softc->media_blksize) 2049 info /= softc->media_blksize; 2050 } 2051 } 2052 if (csio->ccb_h.ccb_type == SA_CCB_BUFFER_IO) { 2053 bcopy((caddr_t) sense, (caddr_t) &softc->last_io_sense, 2054 sizeof (struct scsi_sense_data)); 2055 bcopy(csio->cdb_io.cdb_bytes, softc->last_io_cdb, 2056 (int) csio->cdb_len); 2057 softc->last_io_resid = resid; 2058 } else { 2059 bcopy((caddr_t) sense, (caddr_t) &softc->last_ctl_sense, 2060 sizeof (struct scsi_sense_data)); 2061 bcopy(csio->cdb_io.cdb_bytes, softc->last_ctl_cdb, 2062 (int) csio->cdb_len); 2063 softc->last_ctl_resid = resid; 2064 } 2065 } 2066 2067 /* 2068 * If it's neither a SCSI Check Condition Error nor a non-read/write 2069 * command, let the common code deal with it the error setting. 2070 */ 2071 if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR || 2072 (csio->ccb_h.ccb_type == SA_CCB_WAITING)) { 2073 return (cam_periph_error(ccb, cflgs, sflgs, &softc->saved_ccb)); 2074 } 2075 2076 /* 2077 * Calculate whether we'll defer action. 2078 */ 2079 2080 if (resid > 0 && resid < csio->dxfer_len && 2081 (softc->flags & SA_FLAG_FIXED) != 0) { 2082 defer_action = TRUE; 2083 } else { 2084 defer_action = FALSE; 2085 } 2086 2087 /* 2088 * Handle filemark, end of tape, mismatched record sizes.... 2089 * From this point out, we're only handling read/write cases. 2090 * Handle writes && reads differently. 2091 */ 2092 2093 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Key 0x%x ASC/ASCQ 0x%x " 2094 "0x%x flags 0x%x resid %d dxfer_len %d\n", sense_key, asc, ascq, 2095 sense->flags & ~SSD_KEY_RESERVED, resid, csio->dxfer_len)); 2096 2097 if (csio->cdb_io.cdb_bytes[0] == SA_WRITE) { 2098 if (sense->flags & SSD_FILEMARK) { 2099 xpt_print_path(csio->ccb_h.path); 2100 printf("filemark detected on write?\n"); 2101 if (softc->fileno != (daddr_t) -1) { 2102 softc->fileno++; 2103 softc->blkno = 0; 2104 } 2105 } 2106 if (sense->flags & SSD_EOM) { 2107 csio->resid = resid; 2108 if (defer_action) { 2109 error = -1; 2110 softc->flags |= SA_FLAG_EOM_PENDING; 2111 } else { 2112 error = ENOSPC; 2113 } 2114 } 2115 } else { 2116 if (sense_key == SSD_KEY_BLANK_CHECK) { 2117 csio->resid = resid; 2118 if (defer_action) { 2119 error = -1; 2120 softc->flags |= SA_FLAG_EOM_PENDING; 2121 } else { 2122 error = EIO; 2123 } 2124 } 2125 if (sense->flags & SSD_FILEMARK) { 2126 csio->resid = resid; 2127 if (defer_action) { 2128 error = -1; 2129 softc->flags |= SA_FLAG_EOF_PENDING; 2130 } 2131 /* 2132 * Unconditionally, if we detected a filemark on a read, 2133 * mark that we've run moved a file ahead. 2134 */ 2135 if (softc->fileno != (daddr_t) -1) { 2136 softc->fileno++; 2137 softc->blkno = 0; 2138 } 2139 } 2140 } 2141 /* 2142 * Incorrect Length usually applies to read, but can apply to writes. 2143 */ 2144 if (error == 0 && (sense->flags & SSD_ILI)) { 2145 if (info < 0) { 2146 xpt_print_path(csio->ccb_h.path); 2147 printf(toobig, csio->dxfer_len - info); 2148 csio->resid = csio->dxfer_len; 2149 error = EIO; 2150 } else { 2151 csio->resid = resid; 2152 if ((softc->flags & SA_FLAG_FIXED) != 0) { 2153 if (defer_action) 2154 softc->flags |= SA_FLAG_EIO_PENDING; 2155 else 2156 error = EIO; 2157 } 2158 /* 2159 * Bump the block number if we hadn't seen a filemark. 2160 * Do this independent of errors (we've moved anyway). 2161 */ 2162 if ((sense->flags & SSD_FILEMARK) == 0) { 2163 if (softc->blkno != (daddr_t) -1) { 2164 softc->blkno++; 2165 } 2166 } 2167 } 2168 } 2169 if (error == 0) 2170 return (cam_periph_error(ccb, cflgs, sflgs, &softc->saved_ccb)); 2171 2172 if (error == -1) 2173 return (0); 2174 else 2175 return (error); 2176} 2177 2178static int 2179sagetparams(struct cam_periph *periph, sa_params params_to_get, 2180 u_int32_t *blocksize, u_int8_t *density, u_int32_t *numblocks, 2181 int *buff_mode, u_int8_t *write_protect, u_int8_t *speed, 2182 int *comp_supported, int *comp_enabled, u_int32_t *comp_algorithm, 2183 sa_comp_t *tcs) 2184{ 2185 sa_comp_t *ntcs; 2186 struct scsi_data_compression_page *comp_page; 2187 union ccb *ccb; 2188 void *mode_buffer; 2189 struct scsi_mode_header_6 *mode_hdr; 2190 struct scsi_mode_blk_desc *mode_blk; 2191 int mode_buffer_len; 2192 struct sa_softc *softc; 2193 u_int8_t cpage; 2194 int error; 2195 cam_status status; 2196 2197 if (tcs) 2198 comp_page = &tcs->dcomp; 2199 else 2200 comp_page = NULL; 2201 2202 softc = (struct sa_softc *)periph->softc; 2203 2204 ccb = cam_periph_getccb(periph, 1); 2205 cpage = SA_DATA_COMPRESSION_PAGE; 2206 2207retry: 2208 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk); 2209 2210 if (params_to_get & SA_PARAM_COMPRESSION) { 2211 if (softc->quirks & SA_QUIRK_NOCOMP) { 2212 *comp_supported = FALSE; 2213 params_to_get &= ~SA_PARAM_COMPRESSION; 2214 } else 2215 mode_buffer_len += sizeof (sa_comp_t); 2216 } 2217 mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK); 2218 2219 bzero(mode_buffer, mode_buffer_len); 2220 2221 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer; 2222 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1]; 2223 2224 if (params_to_get & SA_PARAM_COMPRESSION) 2225 ntcs = (sa_comp_t *) &mode_blk[1]; 2226 else 2227 ntcs = NULL; 2228 2229 /* it is safe to retry this */ 2230 scsi_mode_sense(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE, 2231 SMS_PAGE_CTRL_CURRENT, (params_to_get & SA_PARAM_COMPRESSION) ? 2232 cpage : SMS_VENDOR_SPECIFIC_PAGE, mode_buffer, mode_buffer_len, 2233 SSD_FULL_SIZE, 5000); 2234 2235 error = cam_periph_runccb(ccb, saerror, 0, 2236 SF_NO_PRINT, &softc->device_stats); 2237 2238 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2239 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2240 2241 status = ccb->ccb_h.status & CAM_STATUS_MASK; 2242 2243 if (error == EINVAL && (params_to_get & SA_PARAM_COMPRESSION) != 0) { 2244 /* 2245 * Hmm. Let's see if we can try another page... 2246 * If we've already done that, give up on compression 2247 * for this device and remember this for the future 2248 * and attempt the request without asking for compression 2249 * info. 2250 */ 2251 if (cpage == SA_DATA_COMPRESSION_PAGE) { 2252 cpage = SA_DEVICE_CONFIGURATION_PAGE; 2253 goto retry; 2254 } 2255 softc->quirks |= SA_QUIRK_NOCOMP; 2256 free(mode_buffer, M_TEMP); 2257 goto retry; 2258 } else if (status == CAM_SCSI_STATUS_ERROR) { 2259 /* Tell the user about the fatal error. */ 2260 scsi_sense_print(&ccb->csio); 2261 goto sagetparamsexit; 2262 } 2263 2264 /* 2265 * If the user only wants the compression information, and 2266 * the device doesn't send back the block descriptor, it's 2267 * no big deal. If the user wants more than just 2268 * compression, though, and the device doesn't pass back the 2269 * block descriptor, we need to send another mode sense to 2270 * get the block descriptor. 2271 */ 2272 if ((mode_hdr->blk_desc_len == 0) && 2273 (params_to_get & SA_PARAM_COMPRESSION) && 2274 (params_to_get & ~(SA_PARAM_COMPRESSION))) { 2275 2276 /* 2277 * Decrease the mode buffer length by the size of 2278 * the compression page, to make sure the data 2279 * there doesn't get overwritten. 2280 */ 2281 mode_buffer_len -= sizeof (sa_comp_t); 2282 2283 /* 2284 * Now move the compression page that we presumably 2285 * got back down the memory chunk a little bit so 2286 * it doesn't get spammed. 2287 */ 2288 bcopy(&mode_hdr[1], ntcs, sizeof (sa_comp_t)); 2289 2290 /* 2291 * Now, we issue another mode sense and just ask 2292 * for the block descriptor, etc. 2293 */ 2294 2295 scsi_mode_sense(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE, 2296 SMS_PAGE_CTRL_CURRENT, SMS_VENDOR_SPECIFIC_PAGE, 2297 mode_buffer, mode_buffer_len, SSD_FULL_SIZE, 5000); 2298 2299 error = cam_periph_runccb(ccb, saerror, 0, 0, 2300 &softc->device_stats); 2301 2302 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2303 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2304 2305 if (error != 0) 2306 goto sagetparamsexit; 2307 } 2308 2309 if (params_to_get & SA_PARAM_BLOCKSIZE) 2310 *blocksize = scsi_3btoul(mode_blk->blklen); 2311 2312 if (params_to_get & SA_PARAM_NUMBLOCKS) 2313 *numblocks = scsi_3btoul(mode_blk->nblocks); 2314 2315 if (params_to_get & SA_PARAM_BUFF_MODE) 2316 *buff_mode = mode_hdr->dev_spec & SMH_SA_BUF_MODE_MASK; 2317 2318 if (params_to_get & SA_PARAM_DENSITY) 2319 *density = mode_blk->density; 2320 2321 if (params_to_get & SA_PARAM_WP) 2322 *write_protect = (mode_hdr->dev_spec & SMH_SA_WP)? TRUE : FALSE; 2323 2324 if (params_to_get & SA_PARAM_SPEED) 2325 *speed = mode_hdr->dev_spec & SMH_SA_SPEED_MASK; 2326 2327 if (params_to_get & SA_PARAM_COMPRESSION) { 2328 if (cpage == SA_DATA_COMPRESSION_PAGE) { 2329 struct scsi_data_compression_page *cp = &ntcs->dcomp; 2330 *comp_supported = 2331 (cp->dce_and_dcc & SA_DCP_DCC)? TRUE : FALSE; 2332 *comp_enabled = 2333 (cp->dce_and_dcc & SA_DCP_DCE)? TRUE : FALSE; 2334 *comp_algorithm = scsi_4btoul(cp->comp_algorithm); 2335 } else { 2336 struct scsi_dev_conf_page *cp = &ntcs->dconf; 2337 /* 2338 * We don't really know whether this device supports 2339 * Data Compression if the the algorithm field is 2340 * zero. Just say we do. 2341 */ 2342 *comp_supported = TRUE; 2343 *comp_enabled = 2344 (cp->sel_comp_alg != SA_COMP_NONE)? TRUE : FALSE; 2345 *comp_algorithm = cp->sel_comp_alg; 2346 } 2347 if (tcs != NULL) 2348 bcopy(ntcs, tcs , sizeof (sa_comp_t)); 2349 } 2350 2351 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) { 2352 int idx; 2353 char *xyz = mode_buffer; 2354 xpt_print_path(periph->path); 2355 printf("Mode Sense Data="); 2356 for (idx = 0; idx < mode_buffer_len; idx++) 2357 printf(" 0x%02x", xyz[idx] & 0xff); 2358 printf("\n"); 2359 } 2360 2361sagetparamsexit: 2362 2363 xpt_release_ccb(ccb); 2364 free(mode_buffer, M_TEMP); 2365 return(error); 2366} 2367 2368/* 2369 * The purpose of this function is to set one of four different parameters 2370 * for a tape drive: 2371 * - blocksize 2372 * - density 2373 * - compression / compression algorithm 2374 * - buffering mode 2375 * 2376 * The assumption is that this will be called from saioctl(), and therefore 2377 * from a process context. Thus the waiting malloc calls below. If that 2378 * assumption ever changes, the malloc calls should be changed to be 2379 * NOWAIT mallocs. 2380 * 2381 * Any or all of the four parameters may be set when this function is 2382 * called. It should handle setting more than one parameter at once. 2383 */ 2384static int 2385sasetparams(struct cam_periph *periph, sa_params params_to_set, 2386 u_int32_t blocksize, u_int8_t density, u_int32_t calg, 2387 u_int32_t sense_flags) 2388{ 2389 struct sa_softc *softc; 2390 u_int32_t current_blocksize; 2391 u_int32_t current_calg; 2392 u_int8_t current_density; 2393 u_int8_t current_speed; 2394 int comp_enabled, comp_supported; 2395 void *mode_buffer; 2396 int mode_buffer_len; 2397 struct scsi_mode_header_6 *mode_hdr; 2398 struct scsi_mode_blk_desc *mode_blk; 2399 sa_comp_t *ccomp, *cpage; 2400 int buff_mode; 2401 union ccb *ccb = NULL; 2402 int error; 2403 2404 softc = (struct sa_softc *)periph->softc; 2405 2406 ccomp = malloc(sizeof (sa_comp_t), M_TEMP, M_WAITOK); 2407 2408 /* 2409 * Since it doesn't make sense to set the number of blocks, or 2410 * write protection, we won't try to get the current value. We 2411 * always want to get the blocksize, so we can set it back to the 2412 * proper value. 2413 */ 2414 error = sagetparams(periph, 2415 params_to_set | SA_PARAM_BLOCKSIZE | SA_PARAM_SPEED, 2416 ¤t_blocksize, ¤t_density, NULL, &buff_mode, NULL, 2417 ¤t_speed, &comp_supported, &comp_enabled, 2418 ¤t_calg, ccomp); 2419 2420 if (error != 0) { 2421 free(ccomp, M_TEMP); 2422 return(error); 2423 } 2424 2425 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk); 2426 if (params_to_set & SA_PARAM_COMPRESSION) 2427 mode_buffer_len += sizeof (sa_comp_t); 2428 2429 mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK); 2430 bzero(mode_buffer, mode_buffer_len); 2431 2432 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer; 2433 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1]; 2434 2435 if (params_to_set & SA_PARAM_COMPRESSION) { 2436 cpage = (sa_comp_t *)&mode_blk[1]; 2437 bcopy(ccomp, cpage, sizeof (sa_comp_t)); 2438 } else 2439 cpage = NULL; 2440 2441 /* 2442 * If the caller wants us to set the blocksize, use the one they 2443 * pass in. Otherwise, use the blocksize we got back from the 2444 * mode select above. 2445 */ 2446 if (params_to_set & SA_PARAM_BLOCKSIZE) 2447 scsi_ulto3b(blocksize, mode_blk->blklen); 2448 else 2449 scsi_ulto3b(current_blocksize, mode_blk->blklen); 2450 2451 /* 2452 * Set density if requested, else preserve old density. 2453 * SCSI_SAME_DENSITY only applies to SCSI-2 or better 2454 * devices, else density we've latched up in our softc. 2455 */ 2456 if (params_to_set & SA_PARAM_DENSITY) { 2457 mode_blk->density = density; 2458 } else if (softc->scsi_rev > SCSI_REV_CCS) { 2459 mode_blk->density = SCSI_SAME_DENSITY; 2460 } else { 2461 mode_blk->density = softc->media_density; 2462 } 2463 2464 /* 2465 * For mode selects, these two fields must be zero. 2466 */ 2467 mode_hdr->data_length = 0; 2468 mode_hdr->medium_type = 0; 2469 2470 /* set the speed to the current value */ 2471 mode_hdr->dev_spec = current_speed; 2472 2473 /* set single-initiator buffering mode */ 2474 mode_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF; 2475 2476 mode_hdr->blk_desc_len = sizeof(struct scsi_mode_blk_desc); 2477 2478 /* 2479 * First, if the user wants us to set the compression algorithm or 2480 * just turn compression on, check to make sure that this drive 2481 * supports compression. 2482 */ 2483 if (params_to_set & SA_PARAM_COMPRESSION) { 2484 /* 2485 * If the compression algorithm is 0, disable compression. 2486 * If the compression algorithm is non-zero, enable 2487 * compression and set the compression type to the 2488 * specified compression algorithm, unless the algorithm is 2489 * MT_COMP_ENABLE. In that case, we look at the 2490 * compression algorithm that is currently set and if it is 2491 * non-zero, we leave it as-is. If it is zero, and we have 2492 * saved a compression algorithm from a time when 2493 * compression was enabled before, set the compression to 2494 * the saved value. 2495 */ 2496 switch (ccomp->hdr.pagecode) { 2497 case SA_DATA_COMPRESSION_PAGE: 2498 if (ccomp->dcomp.dce_and_dcc & SA_DCP_DCC) { 2499 struct scsi_data_compression_page *dcp = &cpage->dcomp; 2500 if (calg == 0) { 2501 /* disable compression */ 2502 dcp->dce_and_dcc &= ~SA_DCP_DCE; 2503 break; 2504 } 2505 /* enable compression */ 2506 dcp->dce_and_dcc |= SA_DCP_DCE; 2507 /* enable decompression */ 2508 dcp->dde_and_red |= SA_DCP_DDE; 2509 if (calg != MT_COMP_ENABLE) { 2510 scsi_ulto4b(calg, dcp->comp_algorithm); 2511 } else if (scsi_4btoul(dcp->comp_algorithm) == 0 && 2512 softc->saved_comp_algorithm != 0) { 2513 scsi_ulto4b(softc->saved_comp_algorithm, 2514 dcp->comp_algorithm); 2515 } 2516 break; 2517 } 2518 case SA_DEVICE_CONFIGURATION_PAGE: /* NOT YET */ 2519 { 2520 struct scsi_dev_conf_page *dcp = &cpage->dconf; 2521 if (calg == 0) { 2522 dcp->sel_comp_alg = SA_COMP_NONE; 2523 break; 2524 } 2525 if (calg != MT_COMP_ENABLE) { 2526 dcp->sel_comp_alg = calg; 2527 } else if (dcp->sel_comp_alg == SA_COMP_NONE && 2528 softc->saved_comp_algorithm != 0) { 2529 dcp->sel_comp_alg = softc->saved_comp_algorithm; 2530 } 2531 break; 2532 } 2533 default: 2534 /* 2535 * The drive doesn't support compression, 2536 * so turn off the set compression bit. 2537 */ 2538 params_to_set &= ~SA_PARAM_COMPRESSION; 2539 xpt_print_path(periph->path); 2540 printf("device does not support compression\n"); 2541 /* 2542 * If that was the only thing the user wanted us to set, 2543 * clean up allocated resources and return with 2544 * 'operation not supported'. 2545 */ 2546 if (params_to_set == SA_PARAM_NONE) { 2547 free(mode_buffer, M_TEMP); 2548 return(ENODEV); 2549 } 2550 2551 /* 2552 * That wasn't the only thing the user wanted us to set. 2553 * So, decrease the stated mode buffer length by the 2554 * size of the compression mode page. 2555 */ 2556 mode_buffer_len -= sizeof(sa_comp_t); 2557 } 2558 } 2559 2560 ccb = cam_periph_getccb(periph, 1); 2561 2562 /* It is safe to retry this operation */ 2563 scsi_mode_select(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, 2564 (params_to_set & SA_PARAM_COMPRESSION)? TRUE : FALSE, 2565 FALSE, mode_buffer, mode_buffer_len, SSD_FULL_SIZE, 5000); 2566 2567 error = cam_periph_runccb(ccb, saerror, 0, 2568 sense_flags, &softc->device_stats); 2569 2570 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) { 2571 int idx; 2572 char *xyz = mode_buffer; 2573 xpt_print_path(periph->path); 2574 printf("Err%d, Mode Select Data=", error); 2575 for (idx = 0; idx < mode_buffer_len; idx++) 2576 printf(" 0x%02x", xyz[idx] & 0xff); 2577 printf("\n"); 2578 } 2579 2580 2581 if (error == 0) { 2582 xpt_release_ccb(ccb); 2583 } else { 2584 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2585 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 2586 2587 /* 2588 * If we were setting the blocksize, and that failed, we 2589 * want to set it to its original value. If we weren't 2590 * setting the blocksize, we don't want to change it. 2591 */ 2592 scsi_ulto3b(current_blocksize, mode_blk->blklen); 2593 2594 /* 2595 * Set density if requested, else preserve old density. 2596 * SCSI_SAME_DENSITY only applies to SCSI-2 or better 2597 * devices, else density we've latched up in our softc. 2598 */ 2599 if (params_to_set & SA_PARAM_DENSITY) { 2600 mode_blk->density = current_density; 2601 } else if (softc->scsi_rev > SCSI_REV_CCS) { 2602 mode_blk->density = SCSI_SAME_DENSITY; 2603 } else { 2604 mode_blk->density = softc->media_density; 2605 } 2606 2607 if (params_to_set & SA_PARAM_COMPRESSION) 2608 bcopy(ccomp, cpage, sizeof (sa_comp_t)); 2609 2610 /* 2611 * The retry count is the only CCB field that might have been 2612 * changed that we care about, so reset it back to 1. 2613 */ 2614 ccb->ccb_h.retry_count = 1; 2615 cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2616 2617 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2618 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 2619 2620 xpt_release_ccb(ccb); 2621 } 2622 2623 if (ccomp != NULL) 2624 free(ccomp, M_TEMP); 2625 2626 if (params_to_set & SA_PARAM_COMPRESSION) { 2627 if (error) { 2628 softc->flags &= ~SA_FLAG_COMP_ENABLED; 2629 /* 2630 * Even if we get an error setting compression, 2631 * do not say that we don't support it. We could 2632 * have been wrong, or it may be media specific. 2633 * softc->flags &= ~SA_FLAG_COMP_SUPP; 2634 */ 2635 softc->saved_comp_algorithm = softc->comp_algorithm; 2636 softc->comp_algorithm = 0; 2637 } else { 2638 softc->flags |= SA_FLAG_COMP_ENABLED; 2639 softc->comp_algorithm = calg; 2640 } 2641 } 2642 2643 free(mode_buffer, M_TEMP); 2644 return(error); 2645} 2646 2647static void 2648saprevent(struct cam_periph *periph, int action) 2649{ 2650 struct sa_softc *softc; 2651 union ccb *ccb; 2652 int error, sf; 2653 2654 softc = (struct sa_softc *)periph->softc; 2655 2656 if ((action == PR_ALLOW) && (softc->flags & SA_FLAG_TAPE_LOCKED) == 0) 2657 return; 2658 if ((action == PR_PREVENT) && (softc->flags & SA_FLAG_TAPE_LOCKED) != 0) 2659 return; 2660 2661 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) 2662 sf = 0; 2663 else 2664 sf = SF_QUIET_IR; 2665 2666 ccb = cam_periph_getccb(periph, 1); 2667 2668 /* It is safe to retry this operation */ 2669 scsi_prevent(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, action, 2670 SSD_FULL_SIZE, 60000); 2671 2672 /* 2673 * We can be quiet about illegal requests. 2674 */ 2675 error = cam_periph_runccb(ccb, saerror, 0, sf, &softc->device_stats); 2676 2677 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2678 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2679 2680 if (error == 0) { 2681 if (action == PR_ALLOW) 2682 softc->flags &= ~SA_FLAG_TAPE_LOCKED; 2683 else 2684 softc->flags |= SA_FLAG_TAPE_LOCKED; 2685 } 2686 2687 xpt_release_ccb(ccb); 2688} 2689 2690static int 2691sarewind(struct cam_periph *periph) 2692{ 2693 union ccb *ccb; 2694 struct sa_softc *softc; 2695 int error; 2696 2697 softc = (struct sa_softc *)periph->softc; 2698 2699 ccb = cam_periph_getccb(periph, 1); 2700 2701 /* It is safe to retry this operation */ 2702 scsi_rewind(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE, 2703 SSD_FULL_SIZE, (SA_REWIND_TIMEOUT) * 60 * 1000); 2704 2705 softc->dsreg = MTIO_DSREG_REW; 2706 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2707 softc->dsreg = MTIO_DSREG_REST; 2708 2709 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2710 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2711 2712 xpt_release_ccb(ccb); 2713 if (error == 0) 2714 softc->fileno = softc->blkno = (daddr_t) 0; 2715 else 2716 softc->fileno = softc->blkno = (daddr_t) -1; 2717 return (error); 2718} 2719 2720static int 2721saspace(struct cam_periph *periph, int count, scsi_space_code code) 2722{ 2723 union ccb *ccb; 2724 struct sa_softc *softc; 2725 int error; 2726 2727 softc = (struct sa_softc *)periph->softc; 2728 2729 ccb = cam_periph_getccb(periph, 1); 2730 2731 /* This cannot be retried */ 2732 2733 scsi_space(&ccb->csio, 0, sadone, MSG_SIMPLE_Q_TAG, code, count, 2734 SSD_FULL_SIZE, (SA_SPACE_TIMEOUT) * 60 * 1000); 2735 2736 softc->dsreg = (count < 0)? MTIO_DSREG_REV : MTIO_DSREG_FWD; 2737 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2738 softc->dsreg = MTIO_DSREG_REST; 2739 2740 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2741 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2742 2743 xpt_release_ccb(ccb); 2744 2745 /* 2746 * If a spacing operation has failed, we need to invalidate 2747 * this mount. 2748 * 2749 * If the spacing operation was setmarks or to end of recorded data, 2750 * we no longer know our relative position. 2751 * 2752 * We are not managing residuals here (really). 2753 */ 2754 if (error) { 2755 softc->fileno = softc->blkno = (daddr_t) -1; 2756 } else if (code == SS_SETMARKS || code == SS_EOD) { 2757 softc->fileno = softc->blkno = (daddr_t) -1; 2758 } else if (code == SS_FILEMARKS && softc->fileno != (daddr_t) -1) { 2759 softc->fileno += count; 2760 softc->blkno = 0; 2761 } else if (code == SS_BLOCKS && softc->blkno != (daddr_t) -1) { 2762 softc->blkno += count; 2763 } 2764 return (error); 2765} 2766 2767static int 2768sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks) 2769{ 2770 union ccb *ccb; 2771 struct sa_softc *softc; 2772 int error; 2773 2774 softc = (struct sa_softc *)periph->softc; 2775 2776 ccb = cam_periph_getccb(periph, 1); 2777 2778 softc->dsreg = MTIO_DSREG_FMK; 2779 /* this *must* not be retried */ 2780 scsi_write_filemarks(&ccb->csio, 0, sadone, MSG_SIMPLE_Q_TAG, 2781 FALSE, setmarks, nmarks, SSD_FULL_SIZE, 60000); 2782 softc->dsreg = MTIO_DSREG_REST; 2783 2784 2785 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2786 2787 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2788 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2789 2790 /* 2791 * XXXX: Get back the actual number of filemarks written 2792 * XXXX: (there can be a residual). 2793 */ 2794 if (error == 0 && nmarks) { 2795 struct sa_softc *softc = (struct sa_softc *)periph->softc; 2796 softc->filemarks += nmarks; 2797 } 2798 xpt_release_ccb(ccb); 2799 2800 /* 2801 * Update relative positions (if we're doing that). 2802 */ 2803 if (error) { 2804 softc->fileno = softc->blkno = (daddr_t) -1; 2805 } else if (softc->fileno != (daddr_t) -1) { 2806 softc->fileno += nmarks; 2807 softc->blkno = 0; 2808 } 2809 return (error); 2810} 2811 2812static int 2813sardpos(struct cam_periph *periph, int hard, u_int32_t *blkptr) 2814{ 2815 struct scsi_tape_position_data loc; 2816 union ccb *ccb; 2817 struct sa_softc *softc = (struct sa_softc *)periph->softc; 2818 int error; 2819 2820 /* 2821 * We have to try and flush any buffered writes here if we were writing. 2822 * 2823 * The SCSI specification is vague enough about situations like 2824 * different sized blocks in a tape drive buffer as to make one 2825 * wary about trying to figure out the actual block location value 2826 * if data is in the tape drive buffer. 2827 */ 2828 ccb = cam_periph_getccb(periph, 1); 2829 2830 if (softc->flags & SA_FLAG_TAPE_WRITTEN) { 2831 error = sawritefilemarks(periph, 0, 0); 2832 if (error && error != EACCES) 2833 return (error); 2834 } 2835 2836 scsi_read_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, 2837 hard, &loc, SSD_FULL_SIZE, 5000); 2838 softc->dsreg = MTIO_DSREG_RBSY; 2839 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2840 softc->dsreg = MTIO_DSREG_REST; 2841 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2842 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 2843 2844 if (error == 0) { 2845 if (loc.flags & SA_RPOS_UNCERTAIN) { 2846 error = EINVAL; /* nothing is certain */ 2847 } else { 2848#if 0 2849 u_int32_t firstblk, lastblk, nbufblk, nbufbyte; 2850 2851 firstblk = scsi_4btoul(loc.firstblk); 2852 lastblk = scsi_4btoul(loc.lastblk); 2853 nbufblk = scsi_4btoul(loc.nbufblk); 2854 nbufbyte = scsi_4btoul(loc.nbufbyte); 2855 if (lastblk || nbufblk || nbufbyte) { 2856 xpt_print_path(periph->path); 2857 printf("rdpos firstblk 0x%x lastblk 0x%x bufblk" 2858 " 0x%x bufbyte 0x%x\n", firstblk, lastblk, 2859 nbufblk, nbufbyte); 2860 } 2861 *blkptr = firstblk; 2862#else 2863 *blkptr = scsi_4btoul(loc.firstblk); 2864#endif 2865 } 2866 } 2867 2868 xpt_release_ccb(ccb); 2869 return (error); 2870} 2871 2872static int 2873sasetpos(struct cam_periph *periph, int hard, u_int32_t *blkptr) 2874{ 2875 union ccb *ccb; 2876 struct sa_softc *softc; 2877 int error; 2878 2879 /* 2880 * We used to try and flush any buffered writes here. 2881 * Now we push this onto user applications to either 2882 * flush the pending writes themselves (via a zero count 2883 * WRITE FILEMARKS command) or they can trust their tape 2884 * drive to do this correctly for them. 2885 */ 2886 2887 softc = (struct sa_softc *)periph->softc; 2888 ccb = cam_periph_getccb(periph, 1); 2889 2890 2891 scsi_set_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, 2892 hard, *blkptr, SSD_FULL_SIZE, 60 * 60 * 1000); 2893 2894 softc->dsreg = MTIO_DSREG_POS; 2895 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2896 softc->dsreg = MTIO_DSREG_REST; 2897 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2898 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 2899 xpt_release_ccb(ccb); 2900 /* 2901 * Note relative file && block number position as now unknown. 2902 */ 2903 softc->fileno = softc->blkno = (daddr_t) -1; 2904 return (error); 2905} 2906 2907static int 2908saretension(struct cam_periph *periph) 2909{ 2910 union ccb *ccb; 2911 struct sa_softc *softc; 2912 int error; 2913 2914 softc = (struct sa_softc *)periph->softc; 2915 2916 ccb = cam_periph_getccb(periph, 1); 2917 2918 /* It is safe to retry this operation */ 2919 scsi_load_unload(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE, 2920 FALSE, TRUE, TRUE, SSD_FULL_SIZE, (SA_ERASE_TIMEOUT) * 60 * 1000); 2921 2922 softc->dsreg = MTIO_DSREG_TEN; 2923 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2924 softc->dsreg = MTIO_DSREG_REST; 2925 2926 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2927 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2928 xpt_release_ccb(ccb); 2929 if (error == 0) 2930 softc->fileno = softc->blkno = (daddr_t) 0; 2931 else 2932 softc->fileno = softc->blkno = (daddr_t) -1; 2933 return(error); 2934} 2935 2936static int 2937sareservereleaseunit(struct cam_periph *periph, int reserve) 2938{ 2939 union ccb *ccb; 2940 struct sa_softc *softc; 2941 int error, sflag; 2942 2943 softc = (struct sa_softc *)periph->softc; 2944 2945 /* 2946 * We set SF_RETRY_UA, since this is often the first command run 2947 * when a tape device is opened, and there may be a unit attention 2948 * condition pending. 2949 */ 2950 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) 2951 sflag = SF_RETRY_UA; 2952 else 2953 sflag = SF_RETRY_UA|SF_QUIET_IR; 2954 2955 sflag |= SF_RETRY_SELTO; 2956 2957 ccb = cam_periph_getccb(periph, 1); 2958 2959 /* It is safe to retry this operation */ 2960 scsi_reserve_release_unit(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, 2961 FALSE, 0, SSD_FULL_SIZE, 5000, reserve); 2962 2963 softc->dsreg = MTIO_DSREG_RBSY; 2964 error = cam_periph_runccb(ccb, saerror, 0, sflag, &softc->device_stats); 2965 softc->dsreg = MTIO_DSREG_REST; 2966 2967 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2968 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2969 2970 xpt_release_ccb(ccb); 2971 2972 /* 2973 * If the error was Illegal Request, then the device doesn't support 2974 * RESERVE/RELEASE. This is not an error. 2975 */ 2976 if (error == EINVAL) { 2977 error = 0; 2978 } 2979 2980 return (error); 2981} 2982 2983static int 2984saloadunload(struct cam_periph *periph, int load) 2985{ 2986 union ccb *ccb; 2987 struct sa_softc *softc; 2988 int error; 2989 2990 softc = (struct sa_softc *)periph->softc; 2991 2992 ccb = cam_periph_getccb(periph, 1); 2993 2994 /* It is safe to retry this operation */ 2995 scsi_load_unload(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE, 2996 FALSE, FALSE, load, SSD_FULL_SIZE, 60000); 2997 2998 softc->dsreg = (load)? MTIO_DSREG_LD : MTIO_DSREG_UNL; 2999 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 3000 softc->dsreg = MTIO_DSREG_REST; 3001 3002 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 3003 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 3004 xpt_release_ccb(ccb); 3005 3006 if (error || load == 0) 3007 softc->fileno = softc->blkno = (daddr_t) -1; 3008 else if (error == 0) 3009 softc->fileno = softc->blkno = (daddr_t) 0; 3010 return (error); 3011} 3012 3013static int 3014saerase(struct cam_periph *periph, int longerase) 3015{ 3016 3017 union ccb *ccb; 3018 struct sa_softc *softc; 3019 int error; 3020 3021 softc = (struct sa_softc *)periph->softc; 3022 3023 ccb = cam_periph_getccb(periph, 1); 3024 3025 scsi_erase(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, FALSE, longerase, 3026 SSD_FULL_SIZE, (SA_ERASE_TIMEOUT) * 60 * 1000); 3027 3028 softc->dsreg = MTIO_DSREG_ZER; 3029 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 3030 softc->dsreg = MTIO_DSREG_REST; 3031 3032 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 3033 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 3034 xpt_release_ccb(ccb); 3035 return (error); 3036} 3037 3038#endif /* KERNEL */ 3039 3040/* 3041 * Read tape block limits command. 3042 */ 3043void 3044scsi_read_block_limits(struct ccb_scsiio *csio, u_int32_t retries, 3045 void (*cbfcnp)(struct cam_periph *, union ccb *), 3046 u_int8_t tag_action, 3047 struct scsi_read_block_limits_data *rlimit_buf, 3048 u_int8_t sense_len, u_int32_t timeout) 3049{ 3050 struct scsi_read_block_limits *scsi_cmd; 3051 3052 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action, 3053 (u_int8_t *)rlimit_buf, sizeof(*rlimit_buf), sense_len, 3054 sizeof(*scsi_cmd), timeout); 3055 3056 scsi_cmd = (struct scsi_read_block_limits *)&csio->cdb_io.cdb_bytes; 3057 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3058 scsi_cmd->opcode = READ_BLOCK_LIMITS; 3059} 3060 3061void 3062scsi_sa_read_write(struct ccb_scsiio *csio, u_int32_t retries, 3063 void (*cbfcnp)(struct cam_periph *, union ccb *), 3064 u_int8_t tag_action, int readop, int sli, 3065 int fixed, u_int32_t length, u_int8_t *data_ptr, 3066 u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout) 3067{ 3068 struct scsi_sa_rw *scsi_cmd; 3069 3070 scsi_cmd = (struct scsi_sa_rw *)&csio->cdb_io.cdb_bytes; 3071 scsi_cmd->opcode = readop ? SA_READ : SA_WRITE; 3072 scsi_cmd->sli_fixed = 0; 3073 if (sli && readop) 3074 scsi_cmd->sli_fixed |= SAR_SLI; 3075 if (fixed) 3076 scsi_cmd->sli_fixed |= SARW_FIXED; 3077 scsi_ulto3b(length, scsi_cmd->length); 3078 scsi_cmd->control = 0; 3079 3080 cam_fill_csio(csio, retries, cbfcnp, readop ? CAM_DIR_IN : CAM_DIR_OUT, 3081 tag_action, data_ptr, dxfer_len, sense_len, 3082 sizeof(*scsi_cmd), timeout); 3083} 3084 3085void 3086scsi_load_unload(struct ccb_scsiio *csio, u_int32_t retries, 3087 void (*cbfcnp)(struct cam_periph *, union ccb *), 3088 u_int8_t tag_action, int immediate, int eot, 3089 int reten, int load, u_int8_t sense_len, 3090 u_int32_t timeout) 3091{ 3092 struct scsi_load_unload *scsi_cmd; 3093 3094 scsi_cmd = (struct scsi_load_unload *)&csio->cdb_io.cdb_bytes; 3095 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3096 scsi_cmd->opcode = LOAD_UNLOAD; 3097 if (immediate) 3098 scsi_cmd->immediate = SLU_IMMED; 3099 if (eot) 3100 scsi_cmd->eot_reten_load |= SLU_EOT; 3101 if (reten) 3102 scsi_cmd->eot_reten_load |= SLU_RETEN; 3103 if (load) 3104 scsi_cmd->eot_reten_load |= SLU_LOAD; 3105 3106 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, 3107 NULL, 0, sense_len, sizeof(*scsi_cmd), timeout); 3108} 3109 3110void 3111scsi_rewind(struct ccb_scsiio *csio, u_int32_t retries, 3112 void (*cbfcnp)(struct cam_periph *, union ccb *), 3113 u_int8_t tag_action, int immediate, u_int8_t sense_len, 3114 u_int32_t timeout) 3115{ 3116 struct scsi_rewind *scsi_cmd; 3117 3118 scsi_cmd = (struct scsi_rewind *)&csio->cdb_io.cdb_bytes; 3119 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3120 scsi_cmd->opcode = REWIND; 3121 if (immediate) 3122 scsi_cmd->immediate = SREW_IMMED; 3123 3124 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3125 0, sense_len, sizeof(*scsi_cmd), timeout); 3126} 3127 3128void 3129scsi_space(struct ccb_scsiio *csio, u_int32_t retries, 3130 void (*cbfcnp)(struct cam_periph *, union ccb *), 3131 u_int8_t tag_action, scsi_space_code code, 3132 u_int32_t count, u_int8_t sense_len, u_int32_t timeout) 3133{ 3134 struct scsi_space *scsi_cmd; 3135 3136 scsi_cmd = (struct scsi_space *)&csio->cdb_io.cdb_bytes; 3137 scsi_cmd->opcode = SPACE; 3138 scsi_cmd->code = code; 3139 scsi_ulto3b(count, scsi_cmd->count); 3140 scsi_cmd->control = 0; 3141 3142 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3143 0, sense_len, sizeof(*scsi_cmd), timeout); 3144} 3145 3146void 3147scsi_write_filemarks(struct ccb_scsiio *csio, u_int32_t retries, 3148 void (*cbfcnp)(struct cam_periph *, union ccb *), 3149 u_int8_t tag_action, int immediate, int setmark, 3150 u_int32_t num_marks, u_int8_t sense_len, 3151 u_int32_t timeout) 3152{ 3153 struct scsi_write_filemarks *scsi_cmd; 3154 3155 scsi_cmd = (struct scsi_write_filemarks *)&csio->cdb_io.cdb_bytes; 3156 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3157 scsi_cmd->opcode = WRITE_FILEMARKS; 3158 if (immediate) 3159 scsi_cmd->byte2 |= SWFMRK_IMMED; 3160 if (setmark) 3161 scsi_cmd->byte2 |= SWFMRK_WSMK; 3162 3163 scsi_ulto3b(num_marks, scsi_cmd->num_marks); 3164 3165 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3166 0, sense_len, sizeof(*scsi_cmd), timeout); 3167} 3168 3169/* 3170 * The reserve and release unit commands differ only by their opcodes. 3171 */ 3172void 3173scsi_reserve_release_unit(struct ccb_scsiio *csio, u_int32_t retries, 3174 void (*cbfcnp)(struct cam_periph *, union ccb *), 3175 u_int8_t tag_action, int third_party, 3176 int third_party_id, u_int8_t sense_len, 3177 u_int32_t timeout, int reserve) 3178{ 3179 struct scsi_reserve_release_unit *scsi_cmd; 3180 3181 scsi_cmd = (struct scsi_reserve_release_unit *)&csio->cdb_io.cdb_bytes; 3182 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3183 3184 if (reserve) 3185 scsi_cmd->opcode = RESERVE_UNIT; 3186 else 3187 scsi_cmd->opcode = RELEASE_UNIT; 3188 3189 if (third_party) { 3190 scsi_cmd->lun_thirdparty |= SRRU_3RD_PARTY; 3191 scsi_cmd->lun_thirdparty |= 3192 ((third_party_id << SRRU_3RD_SHAMT) & SRRU_3RD_MASK); 3193 } 3194 3195 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3196 0, sense_len, sizeof(*scsi_cmd), timeout); 3197} 3198 3199void 3200scsi_erase(struct ccb_scsiio *csio, u_int32_t retries, 3201 void (*cbfcnp)(struct cam_periph *, union ccb *), 3202 u_int8_t tag_action, int immediate, int long_erase, 3203 u_int8_t sense_len, u_int32_t timeout) 3204{ 3205 struct scsi_erase *scsi_cmd; 3206 3207 scsi_cmd = (struct scsi_erase *)&csio->cdb_io.cdb_bytes; 3208 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3209 3210 scsi_cmd->opcode = ERASE; 3211 3212 if (immediate) 3213 scsi_cmd->lun_imm_long |= SE_IMMED; 3214 3215 if (long_erase) 3216 scsi_cmd->lun_imm_long |= SE_LONG; 3217 3218 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3219 0, sense_len, sizeof(*scsi_cmd), timeout); 3220} 3221 3222/* 3223 * Read Tape Position command. 3224 */ 3225void 3226scsi_read_position(struct ccb_scsiio *csio, u_int32_t retries, 3227 void (*cbfcnp)(struct cam_periph *, union ccb *), 3228 u_int8_t tag_action, int hardsoft, 3229 struct scsi_tape_position_data *sbp, 3230 u_int8_t sense_len, u_int32_t timeout) 3231{ 3232 struct scsi_tape_read_position *scmd; 3233 3234 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action, 3235 (u_int8_t *)sbp, sizeof (*sbp), sense_len, sizeof(*scmd), timeout); 3236 scmd = (struct scsi_tape_read_position *)&csio->cdb_io.cdb_bytes; 3237 bzero(scmd, sizeof(*scmd)); 3238 scmd->opcode = READ_POSITION; 3239 scmd->byte1 = hardsoft; 3240} 3241 3242/* 3243 * Set Tape Position command. 3244 */ 3245void 3246scsi_set_position(struct ccb_scsiio *csio, u_int32_t retries, 3247 void (*cbfcnp)(struct cam_periph *, union ccb *), 3248 u_int8_t tag_action, int hardsoft, u_int32_t blkno, 3249 u_int8_t sense_len, u_int32_t timeout) 3250{ 3251 struct scsi_tape_locate *scmd; 3252 3253 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, 3254 (u_int8_t *)NULL, 0, sense_len, sizeof(*scmd), timeout); 3255 scmd = (struct scsi_tape_locate *)&csio->cdb_io.cdb_bytes; 3256 bzero(scmd, sizeof(*scmd)); 3257 scmd->opcode = LOCATE; 3258 if (hardsoft) 3259 scmd->byte1 |= SA_SPOS_BT; 3260 scsi_ulto4b(blkno, scmd->blkaddr); 3261} 3262