Annotation of sys/scsi/st.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: st.c,v 1.75 2007/06/06 17:15:14 deraadt Exp $ */
! 2: /* $NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1994 Charles Hannum. 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: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Charles Hannum.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: /*
! 34: * Originally written by Julian Elischer (julian@tfs.com)
! 35: * for TRW Financial Systems for use under the MACH(2.5) operating system.
! 36: *
! 37: * TRW Financial Systems, in accordance with their agreement with Carnegie
! 38: * Mellon University, makes this software available to CMU to distribute
! 39: * or use in any manner that they see fit as long as this message is kept with
! 40: * the software. For this reason TFS also grants any other persons or
! 41: * organisations permission to use or modify this software.
! 42: *
! 43: * TFS supplies this software to be publicly redistributed
! 44: * on the understanding that TFS is not responsible for the correct
! 45: * functioning of this software in any circumstances.
! 46: *
! 47: * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
! 48: * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993
! 49: */
! 50:
! 51: /*
! 52: * To do:
! 53: * work out some better way of guessing what a good timeout is going
! 54: * to be depending on whether we expect to retension or not.
! 55: */
! 56:
! 57: #include <sys/types.h>
! 58: #include <sys/param.h>
! 59: #include <sys/systm.h>
! 60: #include <sys/timeout.h>
! 61: #include <sys/fcntl.h>
! 62: #include <sys/errno.h>
! 63: #include <sys/ioctl.h>
! 64: #include <sys/stat.h>
! 65: #include <sys/malloc.h>
! 66: #include <sys/buf.h>
! 67: #include <sys/proc.h>
! 68: #include <sys/user.h>
! 69: #include <sys/mtio.h>
! 70: #include <sys/device.h>
! 71: #include <sys/conf.h>
! 72:
! 73: #include <scsi/scsi_all.h>
! 74: #include <scsi/scsi_tape.h>
! 75: #include <scsi/scsiconf.h>
! 76:
! 77: /* Defines for device specific stuff */
! 78: #define DEF_FIXED_BSIZE 512
! 79: #define ST_RETRIES 4 /* only on non IO commands */
! 80:
! 81: #define STMODE(z) ( minor(z) & 0x03)
! 82: #define STUNIT(z) ((minor(z) >> 4) )
! 83:
! 84: #define ST_IO_TIME (3 * 60 * 1000) /* 3 minutes */
! 85: #define ST_CTL_TIME (30 * 1000) /* 30 seconds */
! 86: #define ST_SPC_TIME (4 * 60 * 60 * 1000) /* 4 hours */
! 87:
! 88: /*
! 89: * Maximum density code allowed in SCSI spec (SSC2R08f, Section 8.3).
! 90: */
! 91: #define SCSI_MAX_DENSITY_CODE 0xff
! 92:
! 93: /*
! 94: * Define various devices that we know mis-behave in some way,
! 95: * and note how they are bad, so we can correct for them
! 96: */
! 97: struct modes {
! 98: u_int quirks; /* same definitions as in quirkdata */
! 99: int blksize;
! 100: u_int8_t density;
! 101: };
! 102:
! 103: struct quirkdata {
! 104: u_int quirks;
! 105: #define ST_Q_FORCE_BLKSIZE 0x0001
! 106: #define ST_Q_SENSE_HELP 0x0002 /* must do READ for good MODE SENSE */
! 107: #define ST_Q_IGNORE_LOADS 0x0004
! 108: #define ST_Q_BLKSIZE 0x0008 /* variable-block media_blksize > 0 */
! 109: #define ST_Q_UNIMODAL 0x0010 /* unimode drive rejects mode select */
! 110: struct modes modes;
! 111: };
! 112:
! 113: struct st_quirk_inquiry_pattern {
! 114: struct scsi_inquiry_pattern pattern;
! 115: struct quirkdata quirkdata;
! 116: };
! 117:
! 118: const struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
! 119: {{T_SEQUENTIAL, T_REMOV,
! 120: " ", " ", " "}, {0,
! 121: {ST_Q_FORCE_BLKSIZE, 512, 0}}}, /* minor 0-3 */
! 122: {{T_SEQUENTIAL, T_REMOV,
! 123: "TANDBERG", " TDC 3600 ", ""}, {0,
! 124: {0, 0, 0}}}, /* minor 0-3 */
! 125: {{T_SEQUENTIAL, T_REMOV,
! 126: "TANDBERG", " TDC 3800 ", ""}, {0,
! 127: {ST_Q_FORCE_BLKSIZE, 512, 0}}}, /* minor 0-3 */
! 128: /*
! 129: * At least -005 and -007 need this. I'll assume they all do unless I
! 130: * hear otherwise. - mycroft, 31MAR1994
! 131: */
! 132: {{T_SEQUENTIAL, T_REMOV,
! 133: "ARCHIVE ", "VIPER 2525 25462", ""}, {0,
! 134: {ST_Q_SENSE_HELP, 0, 0}}}, /* minor 0-3 */
! 135: /*
! 136: * One user reports that this works for his tape drive. It probably
! 137: * needs more work. - mycroft, 09APR1994
! 138: */
! 139: {{T_SEQUENTIAL, T_REMOV,
! 140: "SANKYO ", "CP525 ", ""}, {0,
! 141: {ST_Q_FORCE_BLKSIZE, 512, 0}}}, /* minor 0-3 */
! 142: {{T_SEQUENTIAL, T_REMOV,
! 143: "ANRITSU ", "DMT780 ", ""}, {0,
! 144: {ST_Q_FORCE_BLKSIZE, 512, 0}}}, /* minor 0-3 */
! 145: {{T_SEQUENTIAL, T_REMOV,
! 146: "ARCHIVE ", "VIPER 150 21247", ""}, {0,
! 147: {0, 0, 0}}}, /* minor 0-3 */
! 148: {{T_SEQUENTIAL, T_REMOV,
! 149: "ARCHIVE ", "VIPER 150 21531", ""}, {0,
! 150: {ST_Q_SENSE_HELP, 0, 0}}}, /* minor 0-3 */
! 151: {{T_SEQUENTIAL, T_REMOV,
! 152: "WANGTEK ", "5099ES SCSI", ""}, {0,
! 153: {ST_Q_FORCE_BLKSIZE, 512, 0}}}, /* minor 0-3 */
! 154: {{T_SEQUENTIAL, T_REMOV,
! 155: "WANGTEK ", "5150ES SCSI", ""}, {0,
! 156: {ST_Q_FORCE_BLKSIZE, 512, 0}}}, /* minor 0-3 */
! 157: {{T_SEQUENTIAL, T_REMOV,
! 158: "WANGTEK ", "5525ES SCSI REV7", ""}, {0,
! 159: {0, 0, 0}}}, /* minor 0-3 */
! 160: {{T_SEQUENTIAL, T_REMOV,
! 161: "WangDAT ", "Model 1300 ", ""}, {0,
! 162: {0, 0, 0}}}, /* minor 0-3 */
! 163: {{T_SEQUENTIAL, T_REMOV,
! 164: "EXABYTE ", "EXB-8200 ", "263H"}, {0,
! 165: {0, 0, 0}}}, /* minor 0-3 */
! 166: {{T_SEQUENTIAL, T_REMOV,
! 167: "HP ", "T4000s ", ""}, {ST_Q_UNIMODAL,
! 168: {0, 0, QIC_3095}}}, /* minor 0-3 */
! 169: #if 0
! 170: {{T_SEQUENTIAL, T_REMOV,
! 171: "EXABYTE ", "EXB-8200 ", ""}, {0,
! 172: {0, 0, 0}}}, /* minor 0-3 */
! 173: #endif
! 174: {{T_SEQUENTIAL, T_REMOV,
! 175: "WANGTEK ", "5150ES SCSI FA15\0""01 A", "????"}, {0,
! 176: {ST_Q_IGNORE_LOADS, 0, 0}}}, /* minor 0-3 */
! 177: {{T_SEQUENTIAL, T_REMOV,
! 178: "TEAC ", "MT-2ST/N50 ", ""}, {ST_Q_IGNORE_LOADS,
! 179: {0, 0, 0}}}, /* minor 0-3 */
! 180: };
! 181:
! 182: #define NOEJECT 0
! 183: #define EJECT 1
! 184:
! 185: #define NOREWIND 0
! 186: #define DOREWIND 1
! 187:
! 188: struct st_softc {
! 189: struct device sc_dev;
! 190: /*--------------------present operating parameters, flags etc.----------------*/
! 191: int flags; /* see below */
! 192: u_int quirks; /* quirks for the open mode */
! 193: int blksize; /* blksize we are using */
! 194: u_int8_t density; /* present density */
! 195: short mt_resid; /* last (short) resid */
! 196: short mt_erreg; /* last error (sense key) seen */
! 197: /*--------------------device/scsi parameters----------------------------------*/
! 198: struct scsi_link *sc_link; /* our link to the adpter etc. */
! 199: /*--------------------parameters reported by the device ----------------------*/
! 200: int blkmin; /* min blk size */
! 201: int blkmax; /* max blk size */
! 202: const struct quirkdata *quirkdata; /* if we have a rogue entry */
! 203: /*--------------------parameters reported by the device for this media--------*/
! 204: u_int64_t numblks; /* nominal blocks capacity */
! 205: u_int32_t media_blksize; /* 0 if not ST_FIXEDBLOCKS */
! 206: u_int32_t media_density; /* this is what it said when asked */
! 207: int media_fileno; /* relative to BOT. -1 means unknown. */
! 208: int media_blkno; /* relative to BOF. -1 means unknown. */
! 209: /*--------------------quirks for the whole drive------------------------------*/
! 210: u_int drive_quirks; /* quirks of this drive */
! 211: /*--------------------How we should set up when opening each minor device----*/
! 212: struct modes modes; /* plus more for each mode */
! 213: u_int8_t modeflags; /* flags for the modes */
! 214: #define DENSITY_SET_BY_USER 0x01
! 215: #define DENSITY_SET_BY_QUIRK 0x02
! 216: #define BLKSIZE_SET_BY_USER 0x04
! 217: #define BLKSIZE_SET_BY_QUIRK 0x08
! 218: /*--------------------storage for sense data returned by the drive------------*/
! 219: struct buf buf_queue; /* the queue of pending IO operations */
! 220: struct timeout sc_timeout;
! 221: };
! 222:
! 223:
! 224: int stmatch(struct device *, void *, void *);
! 225: void stattach(struct device *, struct device *, void *);
! 226: void st_identify_drive(struct st_softc *, struct scsi_inquiry_data *);
! 227: void st_loadquirks(struct st_softc *);
! 228: int st_mount_tape(dev_t, int);
! 229: void st_unmount(struct st_softc *, int, int);
! 230: int st_decide_mode(struct st_softc *, int);
! 231: void ststart(void *);
! 232: void strestart(void *);
! 233: int st_read(struct st_softc *, char *, int, int);
! 234: int st_read_block_limits(struct st_softc *, int);
! 235: int st_mode_sense(struct st_softc *, int);
! 236: int st_mode_select(struct st_softc *, int);
! 237: int st_space(struct st_softc *, int, u_int, int);
! 238: int st_write_filemarks(struct st_softc *, int, int);
! 239: int st_check_eod(struct st_softc *, int, int *, int);
! 240: int st_load(struct st_softc *, u_int, int);
! 241: int st_rewind(struct st_softc *, u_int, int);
! 242: int st_interpret_sense(struct scsi_xfer *);
! 243: int st_touch_tape(struct st_softc *);
! 244: int st_erase(struct st_softc *, int, int);
! 245:
! 246: struct cfattach st_ca = {
! 247: sizeof(struct st_softc), stmatch, stattach
! 248: };
! 249:
! 250: struct cfdriver st_cd = {
! 251: NULL, "st", DV_TAPE
! 252: };
! 253:
! 254: struct scsi_device st_switch = {
! 255: st_interpret_sense,
! 256: ststart,
! 257: NULL,
! 258: NULL,
! 259: };
! 260:
! 261: #define ST_INFO_VALID 0x0001
! 262: #define ST_BLOCK_SET 0x0002 /* block size, mode set by ioctl */
! 263: #define ST_WRITTEN 0x0004 /* data have been written, EOD needed */
! 264: #define ST_FIXEDBLOCKS 0x0008
! 265: #define ST_AT_FILEMARK 0x0010
! 266: #define ST_EIO_PENDING 0x0020 /* we couldn't report it then (had data) */
! 267: #define ST_READONLY 0x0080 /* st_mode_sense says write protected */
! 268: #define ST_FM_WRITTEN 0x0100 /*
! 269: * EOF file mark written -- used with
! 270: * ~ST_WRITTEN to indicate that multiple file
! 271: * marks have been written
! 272: */
! 273: #define ST_BLANK_READ 0x0200 /* BLANK CHECK encountered already */
! 274: #define ST_2FM_AT_EOD 0x0400 /* write 2 file marks at EOD */
! 275: #define ST_MOUNTED 0x0800 /* Device is presently mounted */
! 276: #define ST_DONTBUFFER 0x1000 /* Disable buffering/caching */
! 277:
! 278: #define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
! 279: #define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
! 280: ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \
! 281: ST_2FM_AT_EOD | ST_PER_ACTION)
! 282:
! 283: const struct scsi_inquiry_pattern st_patterns[] = {
! 284: {T_SEQUENTIAL, T_REMOV,
! 285: "", "", ""},
! 286: };
! 287:
! 288: int
! 289: stmatch(parent, match, aux)
! 290: struct device *parent;
! 291: void *match, *aux;
! 292: {
! 293: struct scsi_attach_args *sa = aux;
! 294: int priority;
! 295:
! 296: (void)scsi_inqmatch(sa->sa_inqbuf,
! 297: st_patterns, sizeof(st_patterns)/sizeof(st_patterns[0]),
! 298: sizeof(st_patterns[0]), &priority);
! 299: return (priority);
! 300: }
! 301:
! 302: /*
! 303: * The routine called by the low level scsi routine when it discovers
! 304: * A device suitable for this driver
! 305: */
! 306: void
! 307: stattach(parent, self, aux)
! 308: struct device *parent, *self;
! 309: void *aux;
! 310: {
! 311: struct st_softc *st = (void *)self;
! 312: struct scsi_attach_args *sa = aux;
! 313: struct scsi_link *sc_link = sa->sa_sc_link;
! 314:
! 315: SC_DEBUG(sc_link, SDEV_DB2, ("stattach:\n"));
! 316:
! 317: /*
! 318: * Store information needed to contact our base driver
! 319: */
! 320: st->sc_link = sc_link;
! 321: sc_link->device = &st_switch;
! 322: sc_link->device_softc = st;
! 323:
! 324: /*
! 325: * Check if the drive is a known criminal and take
! 326: * Any steps needed to bring it into line
! 327: */
! 328: st_identify_drive(st, sa->sa_inqbuf);
! 329: printf("\n");
! 330:
! 331: timeout_set(&st->sc_timeout, strestart, st);
! 332:
! 333: /*
! 334: * Set up the buf queue for this device
! 335: */
! 336: st->buf_queue.b_active = 0;
! 337: st->buf_queue.b_actf = 0;
! 338: st->buf_queue.b_actb = &st->buf_queue.b_actf;
! 339:
! 340: /* Start up with media position unknown. */
! 341: st->media_fileno = -1;
! 342: st->media_blkno = -1;
! 343:
! 344: /*
! 345: * Reset the media loaded flag, sometimes the data
! 346: * acquired at boot time is not quite accurate. This
! 347: * will be checked again at the first open.
! 348: */
! 349: sc_link->flags &= ~SDEV_MEDIA_LOADED;
! 350: }
! 351:
! 352: /*
! 353: * Use the inquiry routine in 'scsi_base' to get drive info so we can
! 354: * Further tailor our behaviour.
! 355: */
! 356: void
! 357: st_identify_drive(st, inqbuf)
! 358: struct st_softc *st;
! 359: struct scsi_inquiry_data *inqbuf;
! 360: {
! 361: const struct st_quirk_inquiry_pattern *finger;
! 362: int priority;
! 363:
! 364: finger = (const struct st_quirk_inquiry_pattern *)scsi_inqmatch(inqbuf,
! 365: st_quirk_patterns,
! 366: sizeof(st_quirk_patterns)/sizeof(st_quirk_patterns[0]),
! 367: sizeof(st_quirk_patterns[0]), &priority);
! 368: if (priority != 0) {
! 369: st->quirkdata = &finger->quirkdata;
! 370: st->drive_quirks = finger->quirkdata.quirks;
! 371: st->quirks = finger->quirkdata.quirks; /* start value */
! 372: st_loadquirks(st);
! 373: }
! 374: }
! 375:
! 376: /*
! 377: * initialise the subdevices to the default (QUIRK) state.
! 378: * this will remove any setting made by the system operator or previous
! 379: * operations.
! 380: */
! 381: void
! 382: st_loadquirks(st)
! 383: struct st_softc *st;
! 384: {
! 385: const struct modes *mode;
! 386: struct modes *mode2;
! 387:
! 388: mode = &st->quirkdata->modes;
! 389: mode2 = &st->modes;
! 390: bzero(mode2, sizeof(struct modes));
! 391: st->modeflags &= ~(BLKSIZE_SET_BY_QUIRK |
! 392: DENSITY_SET_BY_QUIRK | BLKSIZE_SET_BY_USER |
! 393: DENSITY_SET_BY_USER);
! 394: if ((mode->quirks | st->drive_quirks) & ST_Q_FORCE_BLKSIZE) {
! 395: mode2->blksize = mode->blksize;
! 396: st->modeflags |= BLKSIZE_SET_BY_QUIRK;
! 397: }
! 398: if (mode->density) {
! 399: mode2->density = mode->density;
! 400: st->modeflags |= DENSITY_SET_BY_QUIRK;
! 401: }
! 402: }
! 403:
! 404: /*
! 405: * open the device.
! 406: */
! 407: int
! 408: stopen(dev, flags, fmt, p)
! 409: dev_t dev;
! 410: int flags;
! 411: int fmt;
! 412: struct proc *p;
! 413: {
! 414: struct scsi_link *sc_link;
! 415: struct st_softc *st;
! 416: int error = 0, unit;
! 417:
! 418: unit = STUNIT(dev);
! 419: if (unit >= st_cd.cd_ndevs)
! 420: return (ENXIO);
! 421: st = st_cd.cd_devs[unit];
! 422: if (!st)
! 423: return (ENXIO);
! 424:
! 425: sc_link = st->sc_link;
! 426:
! 427: SC_DEBUG(sc_link, SDEV_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev,
! 428: unit, st_cd.cd_ndevs));
! 429:
! 430: /*
! 431: * Tape is an exclusive media. Only one open at a time.
! 432: */
! 433: if (sc_link->flags & SDEV_OPEN) {
! 434: SC_DEBUG(sc_link, SDEV_DB4, ("already open\n"));
! 435: return (EBUSY);
! 436: }
! 437:
! 438: /* Use st_interpret_sense() now. */
! 439: sc_link->flags |= SDEV_OPEN;
! 440:
! 441: /*
! 442: * Check the unit status. This clears any outstanding errors and
! 443: * will ensure that media is present.
! 444: */
! 445: error = scsi_test_unit_ready(sc_link, TEST_READY_RETRIES,
! 446: SCSI_SILENT | SCSI_IGNORE_MEDIA_CHANGE |
! 447: SCSI_IGNORE_ILLEGAL_REQUEST);
! 448:
! 449: /*
! 450: * Terminate any exising mount session if there is no media.
! 451: */
! 452: if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0)
! 453: st_unmount(st, NOEJECT, DOREWIND);
! 454:
! 455: if (error) {
! 456: sc_link->flags &= ~SDEV_OPEN;
! 457: return (error);
! 458: }
! 459:
! 460: if ((st->flags & ST_MOUNTED) == 0) {
! 461: error = st_mount_tape(dev, flags);
! 462: if (error) {
! 463: sc_link->flags &= ~SDEV_OPEN;
! 464: return (error);
! 465: }
! 466: }
! 467:
! 468: /*
! 469: * Make sure that a tape opened in write-only mode will have
! 470: * file marks written on it when closed, even if not written to.
! 471: * This is for SUN compatibility
! 472: */
! 473: if ((flags & O_ACCMODE) == FWRITE)
! 474: st->flags |= ST_WRITTEN;
! 475:
! 476: SC_DEBUG(sc_link, SDEV_DB2, ("open complete\n"));
! 477: return (0);
! 478: }
! 479:
! 480: /*
! 481: * close the device.. only called if we are the LAST
! 482: * occurence of an open device
! 483: */
! 484: int
! 485: stclose(dev, flags, mode, p)
! 486: dev_t dev;
! 487: int flags;
! 488: int mode;
! 489: struct proc *p;
! 490: {
! 491: struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
! 492:
! 493: SC_DEBUG(st->sc_link, SDEV_DB1, ("closing\n"));
! 494: if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
! 495: st_write_filemarks(st, 1, 0);
! 496: switch (STMODE(dev)) {
! 497: case 0: /* normal */
! 498: st_unmount(st, NOEJECT, DOREWIND);
! 499: break;
! 500: case 3: /* eject, no rewind */
! 501: st_unmount(st, EJECT, NOREWIND);
! 502: break;
! 503: case 1: /* no rewind */
! 504: /* leave mounted unless media seems to have been removed */
! 505: if (!(st->sc_link->flags & SDEV_MEDIA_LOADED))
! 506: st_unmount(st, NOEJECT, NOREWIND);
! 507: break;
! 508: case 2: /* rewind, eject */
! 509: st_unmount(st, EJECT, DOREWIND);
! 510: break;
! 511: }
! 512: st->sc_link->flags &= ~SDEV_OPEN;
! 513: timeout_del(&st->sc_timeout);
! 514:
! 515: return 0;
! 516: }
! 517:
! 518: /*
! 519: * Start a new mount session.
! 520: * Copy in all the default parameters from the selected device mode.
! 521: * and try guess any that seem to be defaulted.
! 522: */
! 523: int
! 524: st_mount_tape(dev, flags)
! 525: dev_t dev;
! 526: int flags;
! 527: {
! 528: int unit;
! 529: u_int mode;
! 530: struct st_softc *st;
! 531: struct scsi_link *sc_link;
! 532: int error = 0;
! 533:
! 534: unit = STUNIT(dev);
! 535: mode = STMODE(dev);
! 536: st = st_cd.cd_devs[unit];
! 537: sc_link = st->sc_link;
! 538:
! 539: if (st->flags & ST_MOUNTED)
! 540: return 0;
! 541:
! 542: SC_DEBUG(sc_link, SDEV_DB1, ("mounting\n"));
! 543: st->quirks = st->drive_quirks | st->modes.quirks;
! 544: /*
! 545: * If the media is new, then make sure we give it a chance to
! 546: * to do a 'load' instruction. (We assume it is new.)
! 547: */
! 548: if ((error = st_load(st, LD_LOAD, 0)) != 0)
! 549: return error;
! 550: /*
! 551: * Throw another dummy instruction to catch
! 552: * 'Unit attention' errors. Some drives appear to give
! 553: * these after doing a Load instruction.
! 554: * (noteably some DAT drives)
! 555: */
! 556: /* XXX */
! 557: scsi_test_unit_ready(sc_link, TEST_READY_RETRIES, SCSI_SILENT);
! 558:
! 559: /*
! 560: * Some devices can't tell you much until they have been
! 561: * asked to look at the media. This quirk does this.
! 562: */
! 563: if (st->quirks & ST_Q_SENSE_HELP)
! 564: if ((error = st_touch_tape(st)) != 0)
! 565: return error;
! 566: /*
! 567: * Load the physical device parameters
! 568: * loads: blkmin, blkmax
! 569: */
! 570: if (!(sc_link->flags & SDEV_ATAPI) &&
! 571: (error = st_read_block_limits(st, 0)) != 0) {
! 572: return error;
! 573: }
! 574:
! 575: /*
! 576: * Load the media dependent parameters
! 577: * includes: media_blksize,media_density,numblks
! 578: * As we have a tape in, it should be reflected here.
! 579: * If not you may need the "quirk" above.
! 580: */
! 581: if ((error = st_mode_sense(st, 0)) != 0)
! 582: return error;
! 583:
! 584: /*
! 585: * If we have gained a permanent density from somewhere,
! 586: * then use it in preference to the one supplied by
! 587: * default by the driver.
! 588: */
! 589: if (st->modeflags & (DENSITY_SET_BY_QUIRK | DENSITY_SET_BY_USER))
! 590: st->density = st->modes.density;
! 591: else
! 592: st->density = st->media_density;
! 593: /*
! 594: * If we have gained a permanent blocksize
! 595: * then use it in preference to the one supplied by
! 596: * default by the driver.
! 597: */
! 598: st->flags &= ~ST_FIXEDBLOCKS;
! 599: if (st->modeflags & (BLKSIZE_SET_BY_QUIRK | BLKSIZE_SET_BY_USER)) {
! 600: st->blksize = st->modes.blksize;
! 601: if (st->blksize)
! 602: st->flags |= ST_FIXEDBLOCKS;
! 603: } else {
! 604: if ((error = st_decide_mode(st, FALSE)) != 0)
! 605: return error;
! 606: }
! 607: if ((error = st_mode_select(st, 0)) != 0) {
! 608: printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname);
! 609: return error;
! 610: }
! 611: scsi_prevent(sc_link, PR_PREVENT,
! 612: SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
! 613: st->flags |= ST_MOUNTED;
! 614: sc_link->flags |= SDEV_MEDIA_LOADED; /* move earlier? */
! 615:
! 616: return 0;
! 617: }
! 618:
! 619: /*
! 620: * End the present mount session.
! 621: * Rewind, and optionally eject the tape.
! 622: * Reset various flags to indicate that all new
! 623: * operations require another mount operation
! 624: */
! 625: void
! 626: st_unmount(st, eject, rewind)
! 627: struct st_softc *st;
! 628: int eject, rewind;
! 629: {
! 630: struct scsi_link *sc_link = st->sc_link;
! 631: int nmarks;
! 632:
! 633: st->media_fileno = -1;
! 634: st->media_blkno = -1;
! 635:
! 636: if (!(st->flags & ST_MOUNTED))
! 637: return;
! 638: SC_DEBUG(sc_link, SDEV_DB1, ("unmounting\n"));
! 639: st_check_eod(st, FALSE, &nmarks, SCSI_IGNORE_NOT_READY);
! 640: if (rewind)
! 641: st_rewind(st, 0, SCSI_IGNORE_NOT_READY);
! 642: scsi_prevent(sc_link, PR_ALLOW,
! 643: SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
! 644: if (eject)
! 645: st_load(st, LD_UNLOAD, SCSI_IGNORE_NOT_READY);
! 646: st->flags &= ~ST_MOUNTED;
! 647: sc_link->flags &= ~SDEV_MEDIA_LOADED;
! 648: }
! 649:
! 650: /*
! 651: * Given all we know about the device, media, mode, 'quirks' and
! 652: * initial operation, make a decision as to how we should be set
! 653: * to run (regarding blocking and EOD marks)
! 654: */
! 655: int
! 656: st_decide_mode(st, first_read)
! 657: struct st_softc *st;
! 658: int first_read;
! 659: {
! 660: struct scsi_link *sc_link = st->sc_link;
! 661:
! 662: SC_DEBUG(sc_link, SDEV_DB2, ("starting block mode decision\n"));
! 663:
! 664: /* ATAPI tapes are always fixed blocksize. */
! 665: if (sc_link->flags & SDEV_ATAPI) {
! 666: st->flags |= ST_FIXEDBLOCKS;
! 667: if (st->media_blksize > 0)
! 668: st->blksize = st->media_blksize;
! 669: else
! 670: st->blksize = DEF_FIXED_BSIZE;
! 671: goto done;
! 672: }
! 673:
! 674: /*
! 675: * If the drive can only handle fixed-length blocks and only at
! 676: * one size, perhaps we should just do that.
! 677: */
! 678: if (st->blkmin && (st->blkmin == st->blkmax)) {
! 679: st->flags |= ST_FIXEDBLOCKS;
! 680: st->blksize = st->blkmin;
! 681: SC_DEBUG(sc_link, SDEV_DB3,
! 682: ("blkmin == blkmax of %d\n", st->blkmin));
! 683: goto done;
! 684: }
! 685: /*
! 686: * If the tape density mandates (or even suggests) use of fixed
! 687: * or variable-length blocks, comply.
! 688: */
! 689: switch (st->density) {
! 690: case HALFINCH_800:
! 691: case HALFINCH_1600:
! 692: case HALFINCH_6250:
! 693: case DDS:
! 694: st->flags &= ~ST_FIXEDBLOCKS;
! 695: st->blksize = 0;
! 696: SC_DEBUG(sc_link, SDEV_DB3, ("density specified variable\n"));
! 697: goto done;
! 698: case QIC_11:
! 699: case QIC_24:
! 700: case QIC_120:
! 701: case QIC_150:
! 702: case QIC_525:
! 703: case QIC_1320:
! 704: st->flags |= ST_FIXEDBLOCKS;
! 705: if (st->media_blksize > 0)
! 706: st->blksize = st->media_blksize;
! 707: else
! 708: st->blksize = DEF_FIXED_BSIZE;
! 709: SC_DEBUG(sc_link, SDEV_DB3, ("density specified fixed\n"));
! 710: goto done;
! 711: }
! 712: /*
! 713: * If we're about to read the tape, perhaps we should choose
! 714: * fixed or variable-length blocks and block size according to
! 715: * what the drive found on the tape.
! 716: */
! 717: if (first_read &&
! 718: (!(st->quirks & ST_Q_BLKSIZE) || (st->media_blksize == 0) ||
! 719: (st->media_blksize == DEF_FIXED_BSIZE) ||
! 720: (st->media_blksize == 1024))) {
! 721: if (st->media_blksize > 0)
! 722: st->flags |= ST_FIXEDBLOCKS;
! 723: else
! 724: st->flags &= ~ST_FIXEDBLOCKS;
! 725: st->blksize = st->media_blksize;
! 726: SC_DEBUG(sc_link, SDEV_DB3,
! 727: ("Used media_blksize of %d\n", st->media_blksize));
! 728: goto done;
! 729: }
! 730: /*
! 731: * We're getting no hints from any direction. Choose variable-
! 732: * length blocks arbitrarily.
! 733: */
! 734: st->flags &= ~ST_FIXEDBLOCKS;
! 735: st->blksize = 0;
! 736: SC_DEBUG(sc_link, SDEV_DB3,
! 737: ("Give up and default to variable mode\n"));
! 738:
! 739: done:
! 740: /*
! 741: * Decide whether or not to write two file marks to signify end-
! 742: * of-data. Make the decision as a function of density. If
! 743: * the decision is not to use a second file mark, the SCSI BLANK
! 744: * CHECK condition code will be recognized as end-of-data when
! 745: * first read.
! 746: * (I think this should be a by-product of fixed/variable..julian)
! 747: */
! 748: switch (st->density) {
! 749: /* case 8 mm: What is the SCSI density code for 8 mm, anyway? */
! 750: case QIC_11:
! 751: case QIC_24:
! 752: case QIC_120:
! 753: case QIC_150:
! 754: case QIC_525:
! 755: case QIC_1320:
! 756: st->flags &= ~ST_2FM_AT_EOD;
! 757: break;
! 758: default:
! 759: st->flags |= ST_2FM_AT_EOD;
! 760: }
! 761: return 0;
! 762: }
! 763:
! 764: /*
! 765: * Actually translate the requested transfer into
! 766: * one the physical driver can understand
! 767: * The transfer is described by a buf and will include
! 768: * only one physical transfer.
! 769: */
! 770: void
! 771: ststrategy(bp)
! 772: struct buf *bp;
! 773: {
! 774: struct st_softc *st = st_cd.cd_devs[STUNIT(bp->b_dev)];
! 775: struct buf *dp;
! 776: int s;
! 777:
! 778: SC_DEBUG(st->sc_link, SDEV_DB2, ("ststrategy: %ld bytes @ blk %d\n",
! 779: bp->b_bcount, bp->b_blkno));
! 780: /*
! 781: * If it's a null transfer, return immediately.
! 782: */
! 783: if (bp->b_bcount == 0)
! 784: goto done;
! 785: /*
! 786: * Odd sized request on fixed drives are verboten
! 787: */
! 788: if (st->flags & ST_FIXEDBLOCKS) {
! 789: if (bp->b_bcount % st->blksize) {
! 790: printf("%s: bad request, must be multiple of %d\n",
! 791: st->sc_dev.dv_xname, st->blksize);
! 792: bp->b_error = EIO;
! 793: goto bad;
! 794: }
! 795: }
! 796: /*
! 797: * as are out-of-range requests on variable drives.
! 798: */
! 799: else if (bp->b_bcount < st->blkmin ||
! 800: (st->blkmax && bp->b_bcount > st->blkmax)) {
! 801: printf("%s: bad request, must be between %d and %d\n",
! 802: st->sc_dev.dv_xname, st->blkmin, st->blkmax);
! 803: bp->b_error = EIO;
! 804: goto bad;
! 805: }
! 806: s = splbio();
! 807:
! 808: /*
! 809: * Place it in the queue of activities for this tape
! 810: * at the end (a bit silly because we only have on user..
! 811: * (but it could fork()))
! 812: */
! 813: dp = &st->buf_queue;
! 814: bp->b_actf = NULL;
! 815: bp->b_actb = dp->b_actb;
! 816: *dp->b_actb = bp;
! 817: dp->b_actb = &bp->b_actf;
! 818:
! 819: /*
! 820: * Tell the device to get going on the transfer if it's
! 821: * not doing anything, otherwise just wait for completion
! 822: * (All a bit silly if we're only allowing 1 open but..)
! 823: */
! 824: ststart(st);
! 825:
! 826: splx(s);
! 827: return;
! 828: bad:
! 829: bp->b_flags |= B_ERROR;
! 830: done:
! 831: /*
! 832: * Correctly set the buf to indicate a completed xfer
! 833: */
! 834: bp->b_resid = bp->b_bcount;
! 835: s = splbio();
! 836: biodone(bp);
! 837: splx(s);
! 838: }
! 839:
! 840: /*
! 841: * ststart looks to see if there is a buf waiting for the device
! 842: * and that the device is not already busy. If both are true,
! 843: * It dequeues the buf and creates a scsi command to perform the
! 844: * transfer required. The transfer request will call scsi_done
! 845: * on completion, which will in turn call this routine again
! 846: * so that the next queued transfer is performed.
! 847: * The bufs are queued by the strategy routine (ststrategy)
! 848: *
! 849: * This routine is also called after other non-queued requests
! 850: * have been made of the scsi driver, to ensure that the queue
! 851: * continues to be drained.
! 852: * ststart() is called at splbio from ststrategy, strestart and scsi_done()
! 853: */
! 854: void
! 855: ststart(v)
! 856: void *v;
! 857: {
! 858: struct st_softc *st = v;
! 859: struct scsi_link *sc_link = st->sc_link;
! 860: struct buf *bp, *dp;
! 861: struct scsi_rw_tape cmd;
! 862: int flags, error;
! 863:
! 864: SC_DEBUG(sc_link, SDEV_DB2, ("ststart\n"));
! 865:
! 866: splassert(IPL_BIO);
! 867:
! 868: /*
! 869: * See if there is a buf to do and we are not already
! 870: * doing one
! 871: */
! 872: while (sc_link->openings > 0) {
! 873: /* if a special awaits, let it proceed first */
! 874: if (sc_link->flags & SDEV_WAITING) {
! 875: sc_link->flags &= ~SDEV_WAITING;
! 876: wakeup((caddr_t)sc_link);
! 877: return;
! 878: }
! 879:
! 880: dp = &st->buf_queue;
! 881: if ((bp = dp->b_actf) == NULL)
! 882: return;
! 883: if ((dp = bp->b_actf) != NULL)
! 884: dp->b_actb = bp->b_actb;
! 885: else
! 886: st->buf_queue.b_actb = bp->b_actb;
! 887: *bp->b_actb = dp;
! 888:
! 889: /*
! 890: * if the device has been unmounted by the user
! 891: * then throw away all requests until done
! 892: */
! 893: if (!(st->flags & ST_MOUNTED) ||
! 894: !(sc_link->flags & SDEV_MEDIA_LOADED)) {
! 895: /* make sure that one implies the other.. */
! 896: sc_link->flags &= ~SDEV_MEDIA_LOADED;
! 897: bp->b_flags |= B_ERROR;
! 898: bp->b_resid = bp->b_bcount;
! 899: bp->b_error = EIO;
! 900: biodone(bp);
! 901: continue;
! 902: }
! 903: /*
! 904: * only FIXEDBLOCK devices have pending operations
! 905: */
! 906: if (st->flags & ST_FIXEDBLOCKS) {
! 907: /*
! 908: * If we are at a filemark but have not reported it yet
! 909: * then we should report it now
! 910: */
! 911: if (st->flags & ST_AT_FILEMARK) {
! 912: if ((bp->b_flags & B_READ) == B_WRITE) {
! 913: /*
! 914: * Handling of ST_AT_FILEMARK in
! 915: * st_space will fill in the right file
! 916: * mark count.
! 917: * Back up over filemark
! 918: */
! 919: if (st_space(st, 0, SP_FILEMARKS, 0)) {
! 920: bp->b_flags |= B_ERROR;
! 921: bp->b_resid = bp->b_bcount;
! 922: bp->b_error = EIO;
! 923: biodone(bp);
! 924: continue;
! 925: }
! 926: } else {
! 927: bp->b_resid = bp->b_bcount;
! 928: bp->b_error = 0;
! 929: bp->b_flags &= ~B_ERROR;
! 930: st->flags &= ~ST_AT_FILEMARK;
! 931: biodone(bp);
! 932: continue; /* seek more work */
! 933: }
! 934: }
! 935: /*
! 936: * If we are at EIO (e.g. EOM) but have not reported it
! 937: * yet then we should report it now
! 938: */
! 939: if (st->flags & ST_EIO_PENDING) {
! 940: bp->b_resid = bp->b_bcount;
! 941: bp->b_error = EIO;
! 942: bp->b_flags |= B_ERROR;
! 943: st->flags &= ~ST_EIO_PENDING;
! 944: biodone(bp);
! 945: continue; /* seek more work */
! 946: }
! 947: }
! 948:
! 949: /*
! 950: * Fill out the scsi command
! 951: */
! 952: bzero(&cmd, sizeof(cmd));
! 953: if ((bp->b_flags & B_READ) == B_WRITE) {
! 954: cmd.opcode = WRITE;
! 955: st->flags &= ~ST_FM_WRITTEN;
! 956: st->flags |= ST_WRITTEN;
! 957: flags = SCSI_DATA_OUT;
! 958: } else {
! 959: cmd.opcode = READ;
! 960: flags = SCSI_DATA_IN;
! 961: }
! 962:
! 963: /*
! 964: * Handle "fixed-block-mode" tape drives by using the
! 965: * block count instead of the length.
! 966: */
! 967: if (st->flags & ST_FIXEDBLOCKS) {
! 968: cmd.byte2 |= SRW_FIXED;
! 969: _lto3b(bp->b_bcount / st->blksize, cmd.len);
! 970: } else
! 971: _lto3b(bp->b_bcount, cmd.len);
! 972:
! 973: if (st->media_blkno != -1) {
! 974: /* Update block count now, errors will set it to -1. */
! 975: if (st->flags & ST_FIXEDBLOCKS)
! 976: st->media_blkno += _3btol(cmd.len);
! 977: else if (cmd.len != 0)
! 978: st->media_blkno++;
! 979: }
! 980:
! 981: /*
! 982: * go ask the adapter to do all this for us
! 983: */
! 984: error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd,
! 985: sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount, 0,
! 986: ST_IO_TIME, bp, flags | SCSI_NOSLEEP);
! 987: switch (error) {
! 988: case 0:
! 989: timeout_del(&st->sc_timeout);
! 990: break;
! 991: case EAGAIN:
! 992: /*
! 993: * The device can't start another i/o. Try again later.
! 994: */
! 995: dp->b_actf = bp;
! 996: timeout_add(&st->sc_timeout, 1);
! 997: return;
! 998: default:
! 999: printf("%s: not queued\n", st->sc_dev.dv_xname);
! 1000: break;
! 1001: }
! 1002: } /* go back and see if we can cram more work in.. */
! 1003: }
! 1004:
! 1005: void
! 1006: strestart(v)
! 1007: void *v;
! 1008: {
! 1009: int s;
! 1010:
! 1011: s = splbio();
! 1012: ststart(v);
! 1013: splx(s);
! 1014: }
! 1015:
! 1016: int
! 1017: stread(dev, uio, iomode)
! 1018: dev_t dev;
! 1019: struct uio *uio;
! 1020: int iomode;
! 1021: {
! 1022: struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
! 1023:
! 1024: return (physio(ststrategy, NULL, dev, B_READ,
! 1025: st->sc_link->adapter->scsi_minphys, uio));
! 1026: }
! 1027:
! 1028: int
! 1029: stwrite(dev, uio, iomode)
! 1030: dev_t dev;
! 1031: struct uio *uio;
! 1032: int iomode;
! 1033: {
! 1034: struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
! 1035:
! 1036: return (physio(ststrategy, NULL, dev, B_WRITE,
! 1037: st->sc_link->adapter->scsi_minphys, uio));
! 1038: }
! 1039:
! 1040: /*
! 1041: * Perform special action on behalf of the user;
! 1042: * knows about the internals of this device
! 1043: */
! 1044: int
! 1045: stioctl(dev, cmd, arg, flag, p)
! 1046: dev_t dev;
! 1047: u_long cmd;
! 1048: caddr_t arg;
! 1049: int flag;
! 1050: struct proc *p;
! 1051: {
! 1052: int error = 0;
! 1053: int unit;
! 1054: int nmarks;
! 1055: int flags;
! 1056: struct st_softc *st;
! 1057: int hold_blksize;
! 1058: u_int8_t hold_density;
! 1059: struct mtop *mt = (struct mtop *) arg;
! 1060: int number;
! 1061:
! 1062: /*
! 1063: * Find the device that the user is talking about
! 1064: */
! 1065: flags = 0; /* give error messages, act on errors etc. */
! 1066: unit = STUNIT(dev);
! 1067: st = st_cd.cd_devs[unit];
! 1068: hold_blksize = st->blksize;
! 1069: hold_density = st->density;
! 1070:
! 1071: switch (cmd) {
! 1072:
! 1073: case MTIOCGET: {
! 1074: struct mtget *g = (struct mtget *) arg;
! 1075:
! 1076: /*
! 1077: * (to get the current state of READONLY)
! 1078: */
! 1079: error = st_mode_sense(st, SCSI_SILENT);
! 1080: if (error)
! 1081: break;
! 1082:
! 1083: SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: get status]\n"));
! 1084: bzero(g, sizeof(struct mtget));
! 1085: g->mt_type = 0x7; /* Ultrix compat *//*? */
! 1086: g->mt_blksiz = st->blksize;
! 1087: g->mt_density = st->density;
! 1088: g->mt_mblksiz = st->modes.blksize;
! 1089: g->mt_mdensity = st->modes.density;
! 1090: if (st->flags & ST_READONLY)
! 1091: g->mt_dsreg |= MT_DS_RDONLY;
! 1092: if (st->flags & ST_MOUNTED)
! 1093: g->mt_dsreg |= MT_DS_MOUNTED;
! 1094: g->mt_resid = st->mt_resid;
! 1095: g->mt_erreg = st->mt_erreg;
! 1096: g->mt_fileno = st->media_fileno;
! 1097: g->mt_blkno = st->media_blkno;
! 1098: /*
! 1099: * clear latched errors.
! 1100: */
! 1101: st->mt_resid = 0;
! 1102: st->mt_erreg = 0;
! 1103: break;
! 1104: }
! 1105: case MTIOCTOP: {
! 1106:
! 1107: SC_DEBUG(st->sc_link, SDEV_DB1,
! 1108: ("[ioctl: op=0x%x count=0x%x]\n", mt->mt_op, mt->mt_count));
! 1109:
! 1110: number = mt->mt_count;
! 1111: switch (mt->mt_op) {
! 1112: case MTWEOF: /* write an end-of-file record */
! 1113: error = st_write_filemarks(st, number, flags);
! 1114: break;
! 1115: case MTBSF: /* backward space file */
! 1116: number = -number;
! 1117: case MTFSF: /* forward space file */
! 1118: error = st_check_eod(st, FALSE, &nmarks, flags);
! 1119: if (!error)
! 1120: error = st_space(st, number - nmarks,
! 1121: SP_FILEMARKS, flags);
! 1122: break;
! 1123: case MTBSR: /* backward space record */
! 1124: number = -number;
! 1125: case MTFSR: /* forward space record */
! 1126: error = st_check_eod(st, TRUE, &nmarks, flags);
! 1127: if (!error)
! 1128: error = st_space(st, number, SP_BLKS, flags);
! 1129: break;
! 1130: case MTREW: /* rewind */
! 1131: error = st_rewind(st, 0, flags);
! 1132: break;
! 1133: case MTOFFL: /* rewind and put the drive offline */
! 1134: st_unmount(st, EJECT, DOREWIND);
! 1135: break;
! 1136: case MTNOP: /* no operation, sets status only */
! 1137: break;
! 1138: case MTRETEN: /* retension the tape */
! 1139: error = st_load(st, LD_RETENSION, flags);
! 1140: if (!error)
! 1141: error = st_load(st, LD_LOAD, flags);
! 1142: break;
! 1143: case MTEOM: /* forward space to end of media */
! 1144: error = st_check_eod(st, FALSE, &nmarks, flags);
! 1145: if (!error)
! 1146: error = st_space(st, 1, SP_EOM, flags);
! 1147: break;
! 1148: case MTCACHE: /* enable controller cache */
! 1149: st->flags &= ~ST_DONTBUFFER;
! 1150: goto try_new_value;
! 1151: case MTNOCACHE: /* disable controller cache */
! 1152: st->flags |= ST_DONTBUFFER;
! 1153: goto try_new_value;
! 1154: case MTERASE: /* erase volume */
! 1155: error = st_erase(st, number, flags);
! 1156: break;
! 1157: case MTSETBSIZ: /* Set block size for device */
! 1158: if (number == 0) {
! 1159: st->flags &= ~ST_FIXEDBLOCKS;
! 1160: } else {
! 1161: if ((st->blkmin || st->blkmax) &&
! 1162: (number < st->blkmin ||
! 1163: number > st->blkmax)) {
! 1164: error = EINVAL;
! 1165: break;
! 1166: }
! 1167: st->flags |= ST_FIXEDBLOCKS;
! 1168: }
! 1169: st->blksize = number;
! 1170: st->flags |= ST_BLOCK_SET; /*XXX */
! 1171: goto try_new_value;
! 1172:
! 1173: case MTSETDNSTY: /* Set density for device and mode */
! 1174: if (number < 0 || number > SCSI_MAX_DENSITY_CODE) {
! 1175: error = EINVAL;
! 1176: break;
! 1177: } else
! 1178: st->density = number;
! 1179: goto try_new_value;
! 1180:
! 1181: default:
! 1182: error = EINVAL;
! 1183: }
! 1184: break;
! 1185: }
! 1186: case MTIOCIEOT:
! 1187: case MTIOCEEOT:
! 1188: break;
! 1189:
! 1190: #if 0
! 1191: case MTIOCRDSPOS:
! 1192: error = st_rdpos(st, 0, (u_int32_t *) arg);
! 1193: break;
! 1194:
! 1195: case MTIOCRDHPOS:
! 1196: error = st_rdpos(st, 1, (u_int32_t *) arg);
! 1197: break;
! 1198:
! 1199: case MTIOCSLOCATE:
! 1200: error = st_setpos(st, 0, (u_int32_t *) arg);
! 1201: break;
! 1202:
! 1203: case MTIOCHLOCATE:
! 1204: error = st_setpos(st, 1, (u_int32_t *) arg);
! 1205: break;
! 1206: #endif
! 1207:
! 1208: default:
! 1209: error = scsi_do_ioctl(st->sc_link, dev, cmd, arg, flag, p);
! 1210: break;
! 1211: }
! 1212: return error;
! 1213: /*-----------------------------*/
! 1214: try_new_value:
! 1215: /*
! 1216: * Check that the mode being asked for is aggreeable to the
! 1217: * drive. If not, put it back the way it was.
! 1218: */
! 1219: if ((error = st_mode_select(st, 0)) != 0) {/* put it back as it was */
! 1220: printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname);
! 1221: st->density = hold_density;
! 1222: st->blksize = hold_blksize;
! 1223: if (st->blksize)
! 1224: st->flags |= ST_FIXEDBLOCKS;
! 1225: else
! 1226: st->flags &= ~ST_FIXEDBLOCKS;
! 1227: return error;
! 1228: }
! 1229: /*
! 1230: * As the drive liked it, if we are setting a new default,
! 1231: * set it into the structures as such.
! 1232: */
! 1233: switch (mt->mt_op) {
! 1234: case MTSETBSIZ:
! 1235: st->modes.blksize = st->blksize;
! 1236: st->modeflags |= BLKSIZE_SET_BY_USER;
! 1237: break;
! 1238: case MTSETDNSTY:
! 1239: st->modes.density = st->density;
! 1240: st->modeflags |= DENSITY_SET_BY_USER;
! 1241: break;
! 1242: }
! 1243:
! 1244: return 0;
! 1245: }
! 1246:
! 1247: /*
! 1248: * Do a synchronous read.
! 1249: */
! 1250: int
! 1251: st_read(st, buf, size, flags)
! 1252: struct st_softc *st;
! 1253: int size;
! 1254: int flags;
! 1255: char *buf;
! 1256: {
! 1257: struct scsi_rw_tape cmd;
! 1258:
! 1259: /*
! 1260: * If it's a null transfer, return immediately
! 1261: */
! 1262: if (size == 0)
! 1263: return 0;
! 1264: bzero(&cmd, sizeof(cmd));
! 1265: cmd.opcode = READ;
! 1266: if (st->flags & ST_FIXEDBLOCKS) {
! 1267: cmd.byte2 |= SRW_FIXED;
! 1268: _lto3b(size / (st->blksize ? st->blksize : DEF_FIXED_BSIZE),
! 1269: cmd.len);
! 1270: } else
! 1271: _lto3b(size, cmd.len);
! 1272: return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
! 1273: sizeof(cmd), (u_char *) buf, size, 0, ST_IO_TIME, NULL,
! 1274: flags | SCSI_DATA_IN);
! 1275: }
! 1276:
! 1277: /*
! 1278: * Ask the drive what its min and max blk sizes are.
! 1279: */
! 1280: int
! 1281: st_read_block_limits(st, flags)
! 1282: struct st_softc *st;
! 1283: int flags;
! 1284: {
! 1285: struct scsi_block_limits cmd;
! 1286: struct scsi_block_limits_data block_limits;
! 1287: struct scsi_link *sc_link = st->sc_link;
! 1288: int error;
! 1289:
! 1290: /*
! 1291: * First check if we have it all loaded
! 1292: */
! 1293: if ((sc_link->flags & SDEV_MEDIA_LOADED))
! 1294: return 0;
! 1295:
! 1296: /*
! 1297: * do a 'Read Block Limits'
! 1298: */
! 1299: bzero(&cmd, sizeof(cmd));
! 1300: cmd.opcode = READ_BLOCK_LIMITS;
! 1301:
! 1302: /*
! 1303: * do the command, update the global values
! 1304: */
! 1305: error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd,
! 1306: sizeof(cmd), (u_char *) &block_limits, sizeof(block_limits),
! 1307: ST_RETRIES, ST_CTL_TIME, NULL, flags | SCSI_DATA_IN);
! 1308: if (error)
! 1309: return error;
! 1310:
! 1311: st->blkmin = _2btol(block_limits.min_length);
! 1312: st->blkmax = _3btol(block_limits.max_length);
! 1313:
! 1314: SC_DEBUG(sc_link, SDEV_DB3,
! 1315: ("(%d <= blksize <= %d)\n", st->blkmin, st->blkmax));
! 1316: return 0;
! 1317: }
! 1318:
! 1319: /*
! 1320: * Get the scsi driver to send a full inquiry to the
! 1321: * device and use the results to fill out the global
! 1322: * parameter structure.
! 1323: *
! 1324: * called from:
! 1325: * attach
! 1326: * open
! 1327: * ioctl (to reset original blksize)
! 1328: */
! 1329: int
! 1330: st_mode_sense(st, flags)
! 1331: struct st_softc *st;
! 1332: int flags;
! 1333: {
! 1334: union scsi_mode_sense_buf *data;
! 1335: struct scsi_link *sc_link = st->sc_link;
! 1336: u_int64_t block_count;
! 1337: u_int32_t density, block_size;
! 1338: u_char *page0 = NULL;
! 1339: u_int8_t dev_spec;
! 1340: int error, big;
! 1341:
! 1342: data = malloc(sizeof(*data), M_TEMP, M_NOWAIT);
! 1343: if (data == NULL)
! 1344: return (ENOMEM);
! 1345:
! 1346: /*
! 1347: * Ask for page 0 (vendor specific) mode sense data.
! 1348: */
! 1349: error = scsi_do_mode_sense(sc_link, 0, data, (void **)&page0,
! 1350: &density, &block_count, &block_size, 1, flags | SCSI_SILENT, &big);
! 1351: if (error != 0) {
! 1352: free(data, M_TEMP);
! 1353: return (error);
! 1354: }
! 1355:
! 1356: /* It is valid for no page0 to be available. */
! 1357:
! 1358: if (big)
! 1359: dev_spec = data->hdr_big.dev_spec;
! 1360: else
! 1361: dev_spec = data->hdr.dev_spec;
! 1362:
! 1363: if (dev_spec & SMH_DSP_WRITE_PROT)
! 1364: st->flags |= ST_READONLY;
! 1365: else
! 1366: st->flags &= ~ST_READONLY;
! 1367:
! 1368: st->numblks = block_count;
! 1369: st->media_blksize = block_size;
! 1370: st->media_density = density;
! 1371:
! 1372: SC_DEBUG(sc_link, SDEV_DB3,
! 1373: ("density code 0x%x, %d-byte blocks, write-%s, ",
! 1374: st->media_density, st->media_blksize,
! 1375: st->flags & ST_READONLY ? "protected" : "enabled"));
! 1376: SC_DEBUGN(sc_link, SDEV_DB3,
! 1377: ("%sbuffered\n", dev_spec & SMH_DSP_BUFF_MODE ? "" : "un"));
! 1378:
! 1379: sc_link->flags |= SDEV_MEDIA_LOADED;
! 1380:
! 1381: free(data, M_TEMP);
! 1382: return (0);
! 1383: }
! 1384:
! 1385: /*
! 1386: * Send a filled out parameter structure to the drive to
! 1387: * set it into the desire modes etc.
! 1388: */
! 1389: int
! 1390: st_mode_select(st, flags)
! 1391: struct st_softc *st;
! 1392: int flags;
! 1393: {
! 1394: union scsi_mode_sense_buf *inbuf, *outbuf;
! 1395: struct scsi_blk_desc general;
! 1396: struct scsi_link *sc_link = st->sc_link;
! 1397: u_int8_t *page0 = NULL;
! 1398: int error, big, page0_size;
! 1399:
! 1400: inbuf = malloc(sizeof(*inbuf), M_TEMP, M_NOWAIT);
! 1401: if (inbuf == NULL)
! 1402: return (ENOMEM);
! 1403: outbuf = malloc(sizeof(*outbuf), M_TEMP, M_NOWAIT);
! 1404: if (outbuf == NULL) {
! 1405: free(inbuf, M_TEMP);
! 1406: return (ENOMEM);
! 1407: }
! 1408:
! 1409: /*
! 1410: * This quirk deals with drives that have only one valid mode and think
! 1411: * this gives them license to reject all mode selects, even if the
! 1412: * selected mode is the one that is supported.
! 1413: */
! 1414: if (st->quirks & ST_Q_UNIMODAL) {
! 1415: SC_DEBUG(sc_link, SDEV_DB3,
! 1416: ("not setting density 0x%x blksize 0x%x\n",
! 1417: st->density, st->blksize));
! 1418: free(inbuf, M_TEMP);
! 1419: free(outbuf, M_TEMP);
! 1420: return (0);
! 1421: }
! 1422:
! 1423: if (sc_link->flags & SDEV_ATAPI) {
! 1424: free(inbuf, M_TEMP);
! 1425: free(outbuf, M_TEMP);
! 1426: return (0);
! 1427: }
! 1428:
! 1429: bzero(outbuf, sizeof(*outbuf));
! 1430: bzero(&general, sizeof(general));
! 1431:
! 1432: general.density = st->density;
! 1433: if (st->flags & ST_FIXEDBLOCKS)
! 1434: _lto3b(st->blksize, general.blklen);
! 1435:
! 1436: /*
! 1437: * Ask for page 0 (vendor specific) mode sense data.
! 1438: */
! 1439: error = scsi_do_mode_sense(sc_link, 0, inbuf, (void **)&page0, NULL,
! 1440: NULL, NULL, 1, flags | SCSI_SILENT, &big);
! 1441: if (error != 0) {
! 1442: free(inbuf, M_TEMP);
! 1443: free(outbuf, M_TEMP);
! 1444: return (error);
! 1445: }
! 1446:
! 1447: if (page0 == NULL) {
! 1448: page0_size = 0;
! 1449: } else if (big == 0) {
! 1450: page0_size = inbuf->hdr.data_length +
! 1451: sizeof(inbuf->hdr.data_length) - sizeof(inbuf->hdr) -
! 1452: inbuf->hdr.blk_desc_len;
! 1453: memcpy(&outbuf->buf[sizeof(outbuf->hdr)+ sizeof(general)],
! 1454: page0, page0_size);
! 1455: } else {
! 1456: page0_size = _2btol(inbuf->hdr_big.data_length) +
! 1457: sizeof(inbuf->hdr_big.data_length) -
! 1458: sizeof(inbuf->hdr_big) -
! 1459: _2btol(inbuf->hdr_big.blk_desc_len);
! 1460: memcpy(&outbuf->buf[sizeof(outbuf->hdr_big) + sizeof(general)],
! 1461: page0, page0_size);
! 1462: }
! 1463:
! 1464: /*
! 1465: * Set up for a mode select.
! 1466: */
! 1467: if (big == 0) {
! 1468: outbuf->hdr.data_length = sizeof(outbuf->hdr) +
! 1469: sizeof(general) + page0_size -
! 1470: sizeof(outbuf->hdr.data_length);
! 1471: if ((st->flags & ST_DONTBUFFER) == 0)
! 1472: outbuf->hdr.dev_spec = SMH_DSP_BUFF_MODE_ON;
! 1473: outbuf->hdr.blk_desc_len = sizeof(general);
! 1474: memcpy(&outbuf->buf[sizeof(outbuf->hdr)],
! 1475: &general, sizeof(general));
! 1476: error = scsi_mode_select(st->sc_link, 0, &outbuf->hdr,
! 1477: flags, ST_CTL_TIME);
! 1478: free(inbuf, M_TEMP);
! 1479: free(outbuf, M_TEMP);
! 1480: return (error);
! 1481: }
! 1482:
! 1483: /* MODE SENSE (10) header was returned, so use MODE SELECT (10). */
! 1484: _lto2b((sizeof(outbuf->hdr_big) + sizeof(general) + page0_size -
! 1485: sizeof(outbuf->hdr_big.data_length)), outbuf->hdr_big.data_length);
! 1486: if ((st->flags & ST_DONTBUFFER) == 0)
! 1487: outbuf->hdr_big.dev_spec = SMH_DSP_BUFF_MODE_ON;
! 1488: _lto2b(sizeof(general), outbuf->hdr_big.blk_desc_len);
! 1489: memcpy(&outbuf->buf[sizeof(outbuf->hdr_big)], &general,
! 1490: sizeof(general));
! 1491:
! 1492: error = scsi_mode_select_big(st->sc_link, 0, &outbuf->hdr_big,
! 1493: flags, ST_CTL_TIME);
! 1494: free(inbuf, M_TEMP);
! 1495: free(outbuf, M_TEMP);
! 1496: return (error);
! 1497: }
! 1498:
! 1499: /*
! 1500: * issue an erase command
! 1501: */
! 1502: int
! 1503: st_erase(st, full, flags)
! 1504: struct st_softc *st;
! 1505: int full, flags;
! 1506: {
! 1507: struct scsi_erase cmd;
! 1508: int tmo;
! 1509:
! 1510: /*
! 1511: * Full erase means set LONG bit in erase command, which asks
! 1512: * the drive to erase the entire unit. Without this bit, we're
! 1513: * asking the drive to write an erase gap.
! 1514: */
! 1515: bzero(&cmd, sizeof(cmd));
! 1516: cmd.opcode = ERASE;
! 1517: if (full) {
! 1518: cmd.byte2 = SE_IMMED|SE_LONG;
! 1519: tmo = ST_SPC_TIME;
! 1520: } else {
! 1521: cmd.byte2 = SE_IMMED;
! 1522: tmo = ST_IO_TIME;
! 1523: }
! 1524:
! 1525: /*
! 1526: * XXX We always do this asynchronously, for now. How long should
! 1527: * we wait if we want to (eventually) to it synchronously?
! 1528: */
! 1529: return (scsi_scsi_cmd(st->sc_link, (struct scsi_generic *)&cmd,
! 1530: sizeof(cmd), 0, 0, ST_RETRIES, tmo, NULL, flags));
! 1531: }
! 1532:
! 1533: /*
! 1534: * skip N blocks/filemarks/seq filemarks/eom
! 1535: */
! 1536: int
! 1537: st_space(st, number, what, flags)
! 1538: struct st_softc *st;
! 1539: u_int what;
! 1540: int flags;
! 1541: int number;
! 1542: {
! 1543: struct scsi_space cmd;
! 1544: int error;
! 1545:
! 1546: switch (what) {
! 1547: case SP_BLKS:
! 1548: if (st->flags & ST_PER_ACTION) {
! 1549: if (number > 0) {
! 1550: st->flags &= ~ST_PER_ACTION;
! 1551: return EIO;
! 1552: } else if (number < 0) {
! 1553: if (st->flags & ST_AT_FILEMARK) {
! 1554: /*
! 1555: * Handling of ST_AT_FILEMARK
! 1556: * in st_space will fill in the
! 1557: * right file mark count.
! 1558: */
! 1559: error = st_space(st, 0, SP_FILEMARKS,
! 1560: flags);
! 1561: if (error)
! 1562: return error;
! 1563: }
! 1564: if (st->flags & ST_BLANK_READ) {
! 1565: st->flags &= ~ST_BLANK_READ;
! 1566: return EIO;
! 1567: }
! 1568: st->flags &= ~ST_EIO_PENDING;
! 1569: }
! 1570: }
! 1571: break;
! 1572: case SP_FILEMARKS:
! 1573: if (st->flags & ST_EIO_PENDING) {
! 1574: if (number > 0) {
! 1575: /* pretend we just discovered the error */
! 1576: st->flags &= ~ST_EIO_PENDING;
! 1577: return EIO;
! 1578: } else if (number < 0) {
! 1579: /* back away from the error */
! 1580: st->flags &= ~ST_EIO_PENDING;
! 1581: }
! 1582: }
! 1583: if (st->flags & ST_AT_FILEMARK) {
! 1584: st->flags &= ~ST_AT_FILEMARK;
! 1585: number--;
! 1586: }
! 1587: if ((st->flags & ST_BLANK_READ) && (number < 0)) {
! 1588: /* back away from unwritten tape */
! 1589: st->flags &= ~ST_BLANK_READ;
! 1590: number++; /* XXX dubious */
! 1591: }
! 1592: break;
! 1593: case SP_EOM:
! 1594: if (st->flags & ST_EIO_PENDING) {
! 1595: /* pretend we just discovered the error */
! 1596: st->flags &= ~ST_EIO_PENDING;
! 1597: return EIO;
! 1598: }
! 1599: if (st->flags & ST_AT_FILEMARK)
! 1600: st->flags &= ~ST_AT_FILEMARK;
! 1601: break;
! 1602: }
! 1603: if (number == 0)
! 1604: return 0;
! 1605:
! 1606: bzero(&cmd, sizeof(cmd));
! 1607: cmd.opcode = SPACE;
! 1608: cmd.byte2 = what;
! 1609: _lto3b(number, cmd.number);
! 1610:
! 1611: error = scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
! 1612: sizeof(cmd), 0, 0, 0, ST_SPC_TIME, NULL, flags);
! 1613:
! 1614: if (error != 0) {
! 1615: st->media_fileno = -1;
! 1616: st->media_blkno = -1;
! 1617: } else {
! 1618: switch (what) {
! 1619: case SP_BLKS:
! 1620: if (st->media_blkno != -1) {
! 1621: st->media_blkno += number;
! 1622: if (st->media_blkno < 0)
! 1623: st->media_blkno = -1;
! 1624: }
! 1625: break;
! 1626: case SP_FILEMARKS:
! 1627: if (st->media_fileno != -1) {
! 1628: st->media_fileno += number;
! 1629: st->media_blkno = 0;
! 1630: }
! 1631: break;
! 1632: default:
! 1633: st->media_fileno = -1;
! 1634: st->media_blkno = -1;
! 1635: break;
! 1636: }
! 1637: }
! 1638:
! 1639: return (error);
! 1640: }
! 1641:
! 1642: /*
! 1643: * write N filemarks
! 1644: */
! 1645: int
! 1646: st_write_filemarks(st, number, flags)
! 1647: struct st_softc *st;
! 1648: int flags;
! 1649: int number;
! 1650: {
! 1651: struct scsi_write_filemarks cmd;
! 1652: int error;
! 1653:
! 1654: /*
! 1655: * It's hard to write a negative number of file marks.
! 1656: * Don't try.
! 1657: */
! 1658: if (number < 0)
! 1659: return EINVAL;
! 1660: switch (number) {
! 1661: case 0: /* really a command to sync the drive's buffers */
! 1662: break;
! 1663: case 1:
! 1664: if (st->flags & ST_FM_WRITTEN) /* already have one down */
! 1665: st->flags &= ~ST_WRITTEN;
! 1666: else
! 1667: st->flags |= ST_FM_WRITTEN;
! 1668: st->flags &= ~ST_PER_ACTION;
! 1669: break;
! 1670: default:
! 1671: st->flags &= ~(ST_PER_ACTION | ST_WRITTEN);
! 1672: }
! 1673:
! 1674: bzero(&cmd, sizeof(cmd));
! 1675: cmd.opcode = WRITE_FILEMARKS;
! 1676: _lto3b(number, cmd.number);
! 1677:
! 1678: error = scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
! 1679: sizeof(cmd), 0, 0, 0, ST_IO_TIME * 4, NULL, flags);
! 1680:
! 1681: if (error != 0) {
! 1682: st->media_fileno = -1;
! 1683: st->media_blkno = -1;
! 1684: } else if (st->media_fileno != -1) {
! 1685: st->media_fileno += number;
! 1686: st->media_blkno = 0;
! 1687: }
! 1688:
! 1689: return (error);
! 1690: }
! 1691:
! 1692: /*
! 1693: * Make sure the right number of file marks is on tape if the
! 1694: * tape has been written. If the position argument is true,
! 1695: * leave the tape positioned where it was originally.
! 1696: *
! 1697: * nmarks returns the number of marks to skip (or, if position
! 1698: * true, which were skipped) to get back original position.
! 1699: */
! 1700: int
! 1701: st_check_eod(st, position, nmarks, flags)
! 1702: struct st_softc *st;
! 1703: int position;
! 1704: int *nmarks;
! 1705: int flags;
! 1706: {
! 1707: int error;
! 1708:
! 1709: switch (st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD)) {
! 1710: default:
! 1711: *nmarks = 0;
! 1712: return 0;
! 1713: case ST_WRITTEN:
! 1714: case ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD:
! 1715: *nmarks = 1;
! 1716: break;
! 1717: case ST_WRITTEN | ST_2FM_AT_EOD:
! 1718: *nmarks = 2;
! 1719: }
! 1720: error = st_write_filemarks(st, *nmarks, flags);
! 1721: if (position && !error)
! 1722: error = st_space(st, -*nmarks, SP_FILEMARKS, flags);
! 1723: return error;
! 1724: }
! 1725:
! 1726: /*
! 1727: * load/unload/retension
! 1728: */
! 1729: int
! 1730: st_load(st, type, flags)
! 1731: struct st_softc *st;
! 1732: u_int type;
! 1733: int flags;
! 1734: {
! 1735: struct scsi_load cmd;
! 1736:
! 1737: st->media_fileno = -1;
! 1738: st->media_blkno = -1;
! 1739:
! 1740: if (type != LD_LOAD) {
! 1741: int error;
! 1742: int nmarks;
! 1743:
! 1744: error = st_check_eod(st, FALSE, &nmarks, flags);
! 1745: if (error)
! 1746: return error;
! 1747: }
! 1748: if (st->quirks & ST_Q_IGNORE_LOADS) {
! 1749: if (type == LD_LOAD) {
! 1750: /*
! 1751: * If we ignore loads, at least we should try a rewind.
! 1752: */
! 1753: return st_rewind(st, 0, flags);
! 1754: }
! 1755: return (0);
! 1756: }
! 1757:
! 1758:
! 1759: bzero(&cmd, sizeof(cmd));
! 1760: cmd.opcode = LOAD;
! 1761: cmd.how = type;
! 1762:
! 1763: return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
! 1764: sizeof(cmd), 0, 0, ST_RETRIES, ST_SPC_TIME, NULL, flags);
! 1765: }
! 1766:
! 1767: /*
! 1768: * Rewind the device
! 1769: */
! 1770: int
! 1771: st_rewind(st, immediate, flags)
! 1772: struct st_softc *st;
! 1773: u_int immediate;
! 1774: int flags;
! 1775: {
! 1776: struct scsi_rewind cmd;
! 1777: int error;
! 1778: int nmarks;
! 1779:
! 1780: error = st_check_eod(st, FALSE, &nmarks, flags);
! 1781: if (error)
! 1782: return error;
! 1783: st->flags &= ~ST_PER_ACTION;
! 1784:
! 1785: bzero(&cmd, sizeof(cmd));
! 1786: cmd.opcode = REWIND;
! 1787: cmd.byte2 = immediate;
! 1788:
! 1789: error = scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
! 1790: sizeof(cmd), 0, 0, ST_RETRIES,
! 1791: immediate ? ST_CTL_TIME: ST_SPC_TIME, NULL, flags);
! 1792:
! 1793: if (error == 0) {
! 1794: st->media_fileno = 0;
! 1795: st->media_blkno = 0;
! 1796: }
! 1797:
! 1798: return (error);
! 1799: }
! 1800:
! 1801: /*
! 1802: * Look at the returned sense and act on the error and detirmine
! 1803: * The unix error number to pass back... (0 = report no error)
! 1804: * (-1 = continue processing)
! 1805: */
! 1806: int
! 1807: st_interpret_sense(xs)
! 1808: struct scsi_xfer *xs;
! 1809: {
! 1810: struct scsi_sense_data *sense = &xs->sense;
! 1811: struct scsi_link *sc_link = xs->sc_link;
! 1812: struct st_softc *st = sc_link->device_softc;
! 1813: struct buf *bp = xs->bp;
! 1814: u_int8_t serr = sense->error_code & SSD_ERRCODE;
! 1815: u_int8_t skey = sense->flags & SSD_KEY;
! 1816: int32_t info;
! 1817:
! 1818: if (((sc_link->flags & SDEV_OPEN) == 0) ||
! 1819: (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED))
! 1820: return (EJUSTRETURN); /* let the generic code handle it */
! 1821:
! 1822: switch (skey) {
! 1823:
! 1824: /*
! 1825: * We do custom processing in st for the unit becoming ready case.
! 1826: * in this case we do not allow xs->retries to be decremented
! 1827: * only on the "Unit Becoming Ready" case. This is because tape
! 1828: * drives report "Unit Becoming Ready" when loading media, etc.
! 1829: * and can take a long time. Rather than having a massive timeout
! 1830: * for all operations (which would cause other problems) we allow
! 1831: * operations to wait (but be interruptable with Ctrl-C) forever
! 1832: * as long as the drive is reporting that it is becoming ready.
! 1833: * all other cases are handled as per the default.
! 1834: */
! 1835:
! 1836: case SKEY_NOT_READY:
! 1837: if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0)
! 1838: return (0);
! 1839: switch (ASC_ASCQ(sense)) {
! 1840: case SENSE_NOT_READY_BECOMING_READY:
! 1841: SC_DEBUG(sc_link, SDEV_DB1, ("not ready: busy (%#x)\n",
! 1842: sense->add_sense_code_qual));
! 1843: /* don't count this as a retry */
! 1844: xs->retries++;
! 1845: return (scsi_delay(xs, 1));
! 1846: default:
! 1847: return (EJUSTRETURN);
! 1848: }
! 1849: case SKEY_NO_SENSE:
! 1850: case SKEY_RECOVERED_ERROR:
! 1851: case SKEY_MEDIUM_ERROR:
! 1852: case SKEY_VOLUME_OVERFLOW:
! 1853: case SKEY_BLANK_CHECK:
! 1854: break;
! 1855: default:
! 1856: return (EJUSTRETURN);
! 1857: }
! 1858:
! 1859: /*
! 1860: * Get the sense fields and work out what code
! 1861: */
! 1862: if (sense->error_code & SSD_ERRCODE_VALID)
! 1863: info = _4btol(sense->info);
! 1864: else
! 1865: info = xs->datalen; /* bad choice if fixed blocks */
! 1866: if (st->flags & ST_FIXEDBLOCKS) {
! 1867: xs->resid = info * st->blksize;
! 1868: if (sense->flags & SSD_EOM) {
! 1869: st->flags |= ST_EIO_PENDING;
! 1870: if (bp)
! 1871: bp->b_resid = xs->resid;
! 1872: }
! 1873: if (sense->flags & SSD_FILEMARK) {
! 1874: st->flags |= ST_AT_FILEMARK;
! 1875: if (st->media_fileno != -1) {
! 1876: st->media_fileno++;
! 1877: st->media_blkno = 0;
! 1878: }
! 1879: if (bp)
! 1880: bp->b_resid = xs->resid;
! 1881: }
! 1882: if (sense->flags & SSD_ILI) {
! 1883: st->flags |= ST_EIO_PENDING;
! 1884: if (bp)
! 1885: bp->b_resid = xs->resid;
! 1886: if (sense->error_code & SSD_ERRCODE_VALID &&
! 1887: (xs->flags & SCSI_SILENT) == 0)
! 1888: printf("%s: block wrong size, %d blocks residual\n",
! 1889: st->sc_dev.dv_xname, info);
! 1890:
! 1891: /*
! 1892: * This quirk code helps the drive read
! 1893: * the first tape block, regardless of
! 1894: * format. That is required for these
! 1895: * drives to return proper MODE SENSE
! 1896: * information.
! 1897: */
! 1898: if ((st->quirks & ST_Q_SENSE_HELP) &&
! 1899: !(sc_link->flags & SDEV_MEDIA_LOADED))
! 1900: st->blksize -= 512;
! 1901: }
! 1902: /*
! 1903: * If no data was transferred, return immediately
! 1904: */
! 1905: if (xs->resid >= xs->datalen) {
! 1906: if (st->flags & ST_EIO_PENDING)
! 1907: return EIO;
! 1908: if (st->flags & ST_AT_FILEMARK) {
! 1909: if (bp)
! 1910: bp->b_resid = xs->resid;
! 1911: return 0;
! 1912: }
! 1913: }
! 1914: } else { /* must be variable mode */
! 1915: xs->resid = xs->datalen; /* to be sure */
! 1916: if (sense->flags & SSD_EOM)
! 1917: return EIO;
! 1918: if (sense->flags & SSD_FILEMARK) {
! 1919: if (st->media_fileno != -1) {
! 1920: st->media_fileno++;
! 1921: st->media_blkno = 0;
! 1922: }
! 1923: if (bp)
! 1924: bp->b_resid = bp->b_bcount;
! 1925: return 0;
! 1926: }
! 1927: if (sense->flags & SSD_ILI) {
! 1928: if (info < 0) {
! 1929: /*
! 1930: * the record was bigger than the read
! 1931: */
! 1932: if ((xs->flags & SCSI_SILENT) == 0)
! 1933: printf("%s: %d-byte record too big\n",
! 1934: st->sc_dev.dv_xname,
! 1935: xs->datalen - info);
! 1936: return (EIO);
! 1937: } else if (info > xs->datalen) {
! 1938: /*
! 1939: * huh? the residual is bigger than the request
! 1940: */
! 1941: if ((xs->flags & SCSI_SILENT) == 0) {
! 1942: printf(
! 1943: "%s: bad residual %d out of %d\n",
! 1944: st->sc_dev.dv_xname, info,
! 1945: xs->datalen);
! 1946: return (EIO);
! 1947: }
! 1948: }
! 1949: xs->resid = info;
! 1950: if (bp)
! 1951: bp->b_resid = info;
! 1952: return (0);
! 1953: }
! 1954: }
! 1955:
! 1956: if (skey == SKEY_BLANK_CHECK) {
! 1957: /*
! 1958: * This quirk code helps the drive read the first tape block,
! 1959: * regardless of format. That is required for these drives to
! 1960: * return proper MODE SENSE information.
! 1961: */
! 1962: if ((st->quirks & ST_Q_SENSE_HELP) &&
! 1963: !(sc_link->flags & SDEV_MEDIA_LOADED)) {
! 1964: /* still starting */
! 1965: st->blksize -= 512;
! 1966: } else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) {
! 1967: st->flags |= ST_BLANK_READ;
! 1968: xs->resid = xs->datalen;
! 1969: if (bp) {
! 1970: bp->b_resid = xs->resid;
! 1971: /* return an EOF */
! 1972: }
! 1973: return (0);
! 1974: }
! 1975: }
! 1976:
! 1977: return (EJUSTRETURN);
! 1978: }
! 1979:
! 1980: /*
! 1981: * The quirk here is that the drive returns some value to st_mode_sense
! 1982: * incorrectly until the tape has actually passed by the head.
! 1983: *
! 1984: * The method is to set the drive to large fixed-block state (user-specified
! 1985: * density and 1024-byte blocks), then read and rewind to get it to sense the
! 1986: * tape. If that doesn't work, try 512-byte fixed blocks. If that doesn't
! 1987: * work, as a last resort, try variable- length blocks. The result will be
! 1988: * the ability to do an accurate st_mode_sense.
! 1989: *
! 1990: * We know we can do a rewind because we just did a load, which implies rewind.
! 1991: * Rewind seems preferable to space backward if we have a virgin tape.
! 1992: *
! 1993: * The rest of the code for this quirk is in ILI processing and BLANK CHECK
! 1994: * error processing, both part of st_interpret_sense.
! 1995: */
! 1996: int
! 1997: st_touch_tape(st)
! 1998: struct st_softc *st;
! 1999: {
! 2000: char *buf;
! 2001: int readsize;
! 2002: int error;
! 2003:
! 2004: buf = malloc(1024, M_TEMP, M_NOWAIT);
! 2005: if (!buf)
! 2006: return ENOMEM;
! 2007:
! 2008: if ((error = st_mode_sense(st, 0)) != 0)
! 2009: goto bad;
! 2010: st->blksize = 1024;
! 2011: do {
! 2012: switch (st->blksize) {
! 2013: case 512:
! 2014: case 1024:
! 2015: readsize = st->blksize;
! 2016: st->flags |= ST_FIXEDBLOCKS;
! 2017: break;
! 2018: default:
! 2019: readsize = 1;
! 2020: st->flags &= ~ST_FIXEDBLOCKS;
! 2021: }
! 2022: if ((error = st_mode_select(st, 0)) != 0)
! 2023: goto bad;
! 2024: st_read(st, buf, readsize, SCSI_SILENT); /* XXX */
! 2025: if ((error = st_rewind(st, 0, 0)) != 0) {
! 2026: bad: free(buf, M_TEMP);
! 2027: return error;
! 2028: }
! 2029: } while (readsize != 1 && readsize > st->blksize);
! 2030:
! 2031: free(buf, M_TEMP);
! 2032: return 0;
! 2033: }
! 2034:
! 2035: int
! 2036: stdump(dev, blkno, va, size)
! 2037: dev_t dev;
! 2038: daddr64_t blkno;
! 2039: caddr_t va;
! 2040: size_t size;
! 2041: {
! 2042:
! 2043: /* Not implemented. */
! 2044: return ENXIO;
! 2045: }
CVSweb