Add the ability to report file number/block number. From Matt Jacob.

This commit is contained in:
christos 2002-03-20 14:53:59 +00:00
parent 748ed9bd8f
commit e5160e810e
2 changed files with 169 additions and 44 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: st.c,v 1.149 2002/01/12 20:30:11 bouyer Exp $ */ /* $NetBSD: st.c,v 1.150 2002/03/20 14:53:59 christos Exp $ */
/*- /*-
* Copyright (c) 1998 The NetBSD Foundation, Inc. * Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -57,7 +57,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: st.c,v 1.149 2002/01/12 20:30:11 bouyer Exp $"); __KERNEL_RCSID(0, "$NetBSD: st.c,v 1.150 2002/03/20 14:53:59 christos Exp $");
#include "opt_scsi.h" #include "opt_scsi.h"
@ -689,6 +689,10 @@ stopen(dev, flags, mode, p)
goto bad; goto bad;
st->last_dsty = dsty; st->last_dsty = dsty;
} }
if (!(st->quirks & ST_Q_NOPREVENT)) {
scsipi_prevent(periph, PR_PREVENT,
XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
}
SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n")); SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n"));
return (0); return (0);
@ -740,6 +744,12 @@ stclose(dev, flags, mode, p)
error = st_check_eod(st, FALSE, &nm, 0); error = st_check_eod(st, FALSE, &nm, 0);
} }
/*
* Allow robots to eject tape if needed.
*/
scsipi_prevent(periph, PR_ALLOW,
XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
switch (STMODE(dev)) { switch (STMODE(dev)) {
case NORMAL_MODE: case NORMAL_MODE:
st_unmount(st, NOEJECT); st_unmount(st, NOEJECT);
@ -886,14 +896,10 @@ st_mount_tape(dev, flags)
return (error); return (error);
} }
} }
if (!(st->quirks & ST_Q_NOPREVENT)) {
scsipi_prevent(periph, PR_PREVENT,
XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
}
st->flags &= ~ST_NEW_MOUNT; st->flags &= ~ST_NEW_MOUNT;
st->flags |= ST_MOUNTED; st->flags |= ST_MOUNTED;
periph->periph_flags |= PERIPH_MEDIA_LOADED; /* move earlier? */ periph->periph_flags |= PERIPH_MEDIA_LOADED; /* move earlier? */
st->blkno = st->fileno = (daddr_t) 0;
return (0); return (0);
} }
@ -933,10 +939,12 @@ st_unmount(st, eject)
st->sc_dev.dv_xname); st->sc_dev.dv_xname);
} }
scsipi_prevent(periph, PR_ALLOW, if (eject) {
XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
if (eject)
st_load(st, LD_UNLOAD, XS_CTL_IGNORE_NOT_READY); st_load(st, LD_UNLOAD, XS_CTL_IGNORE_NOT_READY);
st->blkno = st->fileno = (daddr_t) -1;
} else {
st->blkno = st->fileno = (daddr_t) 0;
}
st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT); st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
periph->periph_flags &= ~PERIPH_MEDIA_LOADED; periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
} }
@ -1252,6 +1260,11 @@ ststart(periph)
} else } else
_lto3b(bp->b_bcount, cmd.len); _lto3b(bp->b_bcount, cmd.len);
/*
* Clear 'position updated' indicator
*/
st->flags &= ~ST_POSUPDATED;
/* /*
* go ask the adapter to do all this for us * go ask the adapter to do all this for us
*/ */
@ -1281,6 +1294,19 @@ stdone(xs)
#if NRND > 0 #if NRND > 0
rnd_add_uint32(&st->rnd_source, xs->bp->b_blkno); rnd_add_uint32(&st->rnd_source, xs->bp->b_blkno);
#endif #endif
if ((st->flags & ST_POSUPDATED) == 0) {
if (xs->bp->b_flags & B_ERROR) {
st->fileno = st->blkno = -1;
} else if (st->blkno != -1) {
if (st->flags & ST_FIXEDBLOCKS) {
st->blkno +=
(xs->bp->b_bcount / st->blksize);
} else {
st->blkno++;
}
}
}
} }
} }
@ -1369,6 +1395,8 @@ stioctl(dev, cmd, arg, flag, p)
g->mt_mdensity[1] = st->modes[1].density; g->mt_mdensity[1] = st->modes[1].density;
g->mt_mdensity[2] = st->modes[2].density; g->mt_mdensity[2] = st->modes[2].density;
g->mt_mdensity[3] = st->modes[3].density; g->mt_mdensity[3] = st->modes[3].density;
g->mt_fileno = st->fileno;
g->mt_blkno = st->blkno;
if (st->flags & ST_READONLY) if (st->flags & ST_READONLY)
g->mt_dsreg |= MT_DS_RDONLY; g->mt_dsreg |= MT_DS_RDONLY;
if (st->flags & ST_MOUNTED) if (st->flags & ST_MOUNTED)
@ -1713,9 +1741,35 @@ st_space(st, number, what, flags)
cmd.byte2 = what; cmd.byte2 = what;
_lto3b(number, cmd.number); _lto3b(number, cmd.number);
return (scsipi_command(st->sc_periph, st->flags &= ~ST_POSUPDATED;
st->last_ctl_resid = 0;
error = scsipi_command(st->sc_periph,
(struct scsipi_generic *)&cmd, sizeof(cmd), (struct scsipi_generic *)&cmd, sizeof(cmd),
0, 0, 0, ST_SPC_TIME, NULL, flags)); 0, 0, 0, ST_SPC_TIME, NULL, flags);
if (error == 0 && (st->flags & ST_POSUPDATED) == 0) {
number = number - st->last_ctl_resid;
if (what == SP_BLKS) {
if (st->blkno != -1) {
st->blkno += number;
}
} else if (what == SP_FILEMARKS) {
if (st->fileno != -1) {
st->fileno += number;
if (number > 0) {
st->blkno = 0;
} else if (number < 0) {
st->blkno = -1;
}
}
} else if (what == SP_EOM) {
/*
* This loses us relative position.
*/
st->fileno = st->blkno = -1;
}
}
return (error);
} }
/* /*
@ -1727,6 +1781,7 @@ st_write_filemarks(st, number, flags)
int flags; int flags;
int number; int number;
{ {
int error;
struct scsi_write_filemarks cmd; struct scsi_write_filemarks cmd;
/* /*
@ -1760,9 +1815,14 @@ st_write_filemarks(st, number, flags)
if ((st->quirks & ST_Q_NOFILEMARKS) == 0) if ((st->quirks & ST_Q_NOFILEMARKS) == 0)
_lto3b(number, cmd.number); _lto3b(number, cmd.number);
return (scsipi_command(st->sc_periph, /* XXX WE NEED TO BE ABLE TO GET A RESIDIUAL XXX */
error = scsipi_command(st->sc_periph,
(struct scsipi_generic *)&cmd, sizeof(cmd), (struct scsipi_generic *)&cmd, sizeof(cmd),
0, 0, 0, ST_IO_TIME * 4, NULL, flags)); 0, 0, 0, ST_IO_TIME * 4, NULL, flags);
if (error == 0 && st->fileno != -1) {
st->fileno += number;
}
return (error);
} }
/* /*
@ -1884,6 +1944,10 @@ st_rewind(st, immediate, flags)
if (error) { if (error) {
printf("%s: error %d trying to rewind\n", printf("%s: error %d trying to rewind\n",
st->sc_dev.dv_xname, error); st->sc_dev.dv_xname, error);
/* lost position */
st->fileno = st->blkno = -1;
} else {
st->fileno = st->blkno = 0;
} }
return (error); return (error);
} }
@ -1899,17 +1963,28 @@ st_rdpos(st, hard, blkptr)
struct scsi_tape_read_position cmd; struct scsi_tape_read_position cmd;
/* /*
* First flush any pending writes... * We try and flush any buffered writes here if we were writing
* and we're trying to get hardware block position. It eats
* up performance substantially, but I'm wary of drive firmware.
*
* I think that *logical* block position is probably okay-
* but hardware block position might have to wait for data
* to hit media to be valid. Caveat Emptor.
*/ */
error = st_write_filemarks(st, 0, XS_CTL_SILENT);
/* if (hard && (st->flags & ST_WRITTEN)) {
* The latter case is for 'write protected' tapes /*
* which are too stupid to recognize a zero count * First flush any pending writes...
* for writing filemarks as a no-op. */
*/ error = st_write_filemarks(st, 0, XS_CTL_SILENT);
if (error != 0 && error != EACCES && error != EROFS) /*
return (error); * The latter case is for 'write protected' tapes
* which are too stupid to recognize a zero count
* for writing filemarks as a no-op.
*/
if (error != 0 && error != EACCES && error != EROFS)
return (error);
}
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
memset(&posdata, 0, sizeof(posdata)); memset(&posdata, 0, sizeof(posdata));
@ -1947,19 +2022,14 @@ st_setpos(st, hard, blkptr)
struct scsi_tape_locate cmd; struct scsi_tape_locate cmd;
/* /*
* First flush any pending writes. Strictly speaking, * We used to try and flush any buffered writes here.
* we're not supposed to have to worry about this, * Now we push this onto user applications to either
* but let's be untrusting. * flush the pending writes themselves (via a zero count
* WRITE FILEMARKS command) or they can trust their tape
* drive to do this correctly for them.
*
* There are very ugly performance limitations otherwise.
*/ */
error = st_write_filemarks(st, 0, XS_CTL_SILENT);
/*
* The latter case is for 'write protected' tapes
* which are too stupid to recognize a zero count
* for writing filemarks as a no-op.
*/
if (error != 0 && error != EACCES && error != EROFS)
return (error);
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.opcode = LOCATE; cmd.opcode = LOCATE;
@ -1970,9 +2040,10 @@ st_setpos(st, hard, blkptr)
(struct scsipi_generic *)&cmd, sizeof(cmd), (struct scsipi_generic *)&cmd, sizeof(cmd),
NULL, 0, ST_RETRIES, ST_SPC_TIME, NULL, 0); NULL, 0, ST_RETRIES, ST_SPC_TIME, NULL, 0);
/* /*
* XXX: Note file && block number position now unknown (if * Note file && block number position now unknown (if
* XXX: these things ever start being maintained in this driver) * these things ever start being maintained in this driver)
*/ */
st->fileno = st->blkno = -1;
return (error); return (error);
} }
@ -2030,20 +2101,45 @@ st_interpret_sense(xs)
return (retval); return (retval);
} }
xs->resid = info;
if (st->flags & ST_FIXEDBLOCKS) { if (st->flags & ST_FIXEDBLOCKS) {
xs->resid = info * st->blksize; if (bp) {
if (sense->flags & SSD_EOM) { xs->resid *= st->blksize;
st->last_io_resid = xs->resid;
} else {
st->last_ctl_resid = xs->resid;
}
if (key == SKEY_VOLUME_OVERFLOW) {
st->flags |= ST_EIO_PENDING;
if (bp)
bp->b_resid = xs->resid;
} else if (sense->flags & SSD_EOM) {
if ((st->flags & ST_EARLYWARN) == 0) if ((st->flags & ST_EARLYWARN) == 0)
st->flags |= ST_EIO_PENDING; st->flags |= ST_EIO_PENDING;
st->flags |= ST_EOM_PENDING; st->flags |= ST_EOM_PENDING;
if (bp) if (bp) {
#if 0
bp->b_resid = xs->resid; bp->b_resid = xs->resid;
#else
/*
* Grotesque as it seems, the few times
* I've actually seen a non-zero resid,
* the tape drive actually lied and had
* written all the data!
*/
bp->b_resid = 0;
#endif
}
} }
if (sense->flags & SSD_FILEMARK) { if (sense->flags & SSD_FILEMARK) {
st->flags |= ST_AT_FILEMARK; st->flags |= ST_AT_FILEMARK;
if (bp) if (bp)
bp->b_resid = xs->resid; bp->b_resid = xs->resid;
if (st->fileno != (daddr_t) -1) {
st->fileno++;
st->blkno = 0;
st->flags |= ST_POSUPDATED;
}
} }
if (sense->flags & SSD_ILI) { if (sense->flags & SSD_ILI) {
st->flags |= ST_EIO_PENDING; st->flags |= ST_EIO_PENDING;
@ -2064,6 +2160,13 @@ st_interpret_sense(xs)
if ((st->quirks & ST_Q_SENSE_HELP) && if ((st->quirks & ST_Q_SENSE_HELP) &&
(periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
st->blksize -= 512; st->blksize -= 512;
else if ((st->flags & ST_POSUPDATED) == 0) {
if (st->blkno != (daddr_t) -1) {
st->blkno +=
(xs->datalen / st->blksize);
st->flags |= ST_POSUPDATED;
}
}
} }
/* /*
* If data wanted and no data was transferred, do it immediately * If data wanted and no data was transferred, do it immediately
@ -2078,6 +2181,11 @@ st_interpret_sense(xs)
} }
} }
} else { /* must be variable mode */ } else { /* must be variable mode */
if (bp) {
st->last_io_resid = xs->resid;
} else {
st->last_ctl_resid = xs->resid;
}
if (sense->flags & SSD_EOM) { if (sense->flags & SSD_EOM) {
/* /*
* The current semantics of this * The current semantics of this
@ -2103,6 +2211,11 @@ st_interpret_sense(xs)
} }
} else if (sense->flags & SSD_FILEMARK) { } else if (sense->flags & SSD_FILEMARK) {
retval = 0; retval = 0;
if (st->fileno != (daddr_t) -1) {
st->fileno++;
st->blkno = 0;
st->flags |= ST_POSUPDATED;
}
} else if (sense->flags & SSD_ILI) { } else if (sense->flags & SSD_ILI) {
if (info < 0) { if (info < 0) {
/* /*
@ -2118,9 +2231,12 @@ st_interpret_sense(xs)
retval = EIO; retval = EIO;
} else { } else {
retval = 0; retval = 0;
if (st->blkno != (daddr_t) -1) {
st->blkno++;
st->flags |= ST_POSUPDATED;
}
} }
} }
xs->resid = info;
if (bp) if (bp)
bp->b_resid = info; bp->b_resid = info;
} }
@ -2148,6 +2264,8 @@ st_interpret_sense(xs)
/* return an EOF */ /* return an EOF */
} }
retval = 0; retval = 0;
/* lost position */
st->fileno = st->blkno = -1;
} }
} }
@ -2171,6 +2289,7 @@ st_interpret_sense(xs)
case SKEY_UNIT_ATTENTION: case SKEY_UNIT_ATTENTION:
case SKEY_WRITE_PROTECT: case SKEY_WRITE_PROTECT:
break; break;
case SKEY_VOLUME_OVERFLOW:
case SKEY_BLANK_CHECK: case SKEY_BLANK_CHECK:
printf(", requested size: %d (decimal)", info); printf(", requested size: %d (decimal)", info);
break; break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: stvar.h,v 1.4 2001/12/07 11:26:31 yamt Exp $ */ /* $NetBSD: stvar.h,v 1.5 2002/03/20 14:54:00 christos Exp $ */
/*- /*-
* Copyright (c) 1998 The NetBSD Foundation, Inc. * Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -114,6 +114,11 @@ struct st_softc {
u_int last_dsty; /* last density opened */ u_int last_dsty; /* last density opened */
short mt_resid; /* last (short) resid */ short mt_resid; /* last (short) resid */
short mt_erreg; /* last error (sense key) seen */ short mt_erreg; /* last error (sense key) seen */
/* relative to BOT location */
daddr_t fileno;
daddr_t blkno;
int32_t last_io_resid;
int32_t last_ctl_resid;
#define mt_key mt_erreg #define mt_key mt_erreg
u_int8_t asc; /* last asc code seen */ u_int8_t asc; /* last asc code seen */
u_int8_t ascq; /* last asc code seen */ u_int8_t ascq; /* last asc code seen */
@ -167,12 +172,13 @@ struct st_softc {
#define ST_DONTBUFFER 0x1000 /* Disable buffering/caching */ #define ST_DONTBUFFER 0x1000 /* Disable buffering/caching */
#define ST_EARLYWARN 0x2000 /* Do (deferred) EOM for variable mode */ #define ST_EARLYWARN 0x2000 /* Do (deferred) EOM for variable mode */
#define ST_EOM_PENDING 0x4000 /* EOM reporting deferred until next op */ #define ST_EOM_PENDING 0x4000 /* EOM reporting deferred until next op */
#define ST_POSUPDATED 0x8000 /* tape position already updated */
#define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_EOM_PENDING | \ #define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_EOM_PENDING | \
ST_BLANK_READ) ST_BLANK_READ)
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \ #define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \ ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \
ST_2FM_AT_EOD | ST_PER_ACTION) ST_2FM_AT_EOD | ST_PER_ACTION | ST_POSUPDATED)
void stattach __P((struct device *, struct st_softc *, void *)); void stattach __P((struct device *, struct st_softc *, void *));
int stactivate __P((struct device *, enum devact)); int stactivate __P((struct device *, enum devact));