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