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