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