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