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.
@ -57,7 +57,7 @@
*/
#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"
@ -689,6 +689,10 @@ stopen(dev, flags, mode, p)
goto bad;
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"));
return (0);
@ -740,6 +744,12 @@ stclose(dev, flags, mode, p)
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)) {
case NORMAL_MODE:
st_unmount(st, NOEJECT);
@ -886,14 +896,10 @@ st_mount_tape(dev, flags)
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_MOUNTED;
periph->periph_flags |= PERIPH_MEDIA_LOADED; /* move earlier? */
st->blkno = st->fileno = (daddr_t) 0;
return (0);
}
@ -933,10 +939,12 @@ st_unmount(st, eject)
st->sc_dev.dv_xname);
}
scsipi_prevent(periph, PR_ALLOW,
XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
if (eject)
if (eject) {
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);
periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
}
@ -1252,6 +1260,11 @@ ststart(periph)
} else
_lto3b(bp->b_bcount, cmd.len);
/*
* Clear 'position updated' indicator
*/
st->flags &= ~ST_POSUPDATED;
/*
* go ask the adapter to do all this for us
*/
@ -1281,6 +1294,19 @@ stdone(xs)
#if NRND > 0
rnd_add_uint32(&st->rnd_source, xs->bp->b_blkno);
#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[2] = st->modes[2].density;
g->mt_mdensity[3] = st->modes[3].density;
g->mt_fileno = st->fileno;
g->mt_blkno = st->blkno;
if (st->flags & ST_READONLY)
g->mt_dsreg |= MT_DS_RDONLY;
if (st->flags & ST_MOUNTED)
@ -1713,9 +1741,35 @@ st_space(st, number, what, flags)
cmd.byte2 = what;
_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),
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 number;
{
int error;
struct scsi_write_filemarks cmd;
/*
@ -1760,9 +1815,14 @@ st_write_filemarks(st, number, flags)
if ((st->quirks & ST_Q_NOFILEMARKS) == 0)
_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),
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) {
printf("%s: error %d trying to rewind\n",
st->sc_dev.dv_xname, error);
/* lost position */
st->fileno = st->blkno = -1;
} else {
st->fileno = st->blkno = 0;
}
return (error);
}
@ -1899,17 +1963,28 @@ st_rdpos(st, hard, blkptr)
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);
/*
* 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);
if (hard && (st->flags & ST_WRITTEN)) {
/*
* First flush any pending writes...
*/
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(&posdata, 0, sizeof(posdata));
@ -1947,19 +2022,14 @@ st_setpos(st, hard, blkptr)
struct scsi_tape_locate cmd;
/*
* First flush any pending writes. Strictly speaking,
* we're not supposed to have to worry about this,
* but let's be untrusting.
* We used to try and flush any buffered writes here.
* Now we push this onto user applications to either
* 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));
cmd.opcode = LOCATE;
@ -1970,9 +2040,10 @@ st_setpos(st, hard, blkptr)
(struct scsipi_generic *)&cmd, sizeof(cmd),
NULL, 0, ST_RETRIES, ST_SPC_TIME, NULL, 0);
/*
* XXX: Note file && block number position now unknown (if
* XXX: these things ever start being maintained in this driver)
* Note file && block number position now unknown (if
* these things ever start being maintained in this driver)
*/
st->fileno = st->blkno = -1;
return (error);
}
@ -2030,20 +2101,45 @@ st_interpret_sense(xs)
return (retval);
}
xs->resid = info;
if (st->flags & ST_FIXEDBLOCKS) {
xs->resid = info * st->blksize;
if (sense->flags & SSD_EOM) {
if (bp) {
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)
st->flags |= ST_EIO_PENDING;
st->flags |= ST_EOM_PENDING;
if (bp)
if (bp) {
#if 0
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) {
st->flags |= ST_AT_FILEMARK;
if (bp)
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) {
st->flags |= ST_EIO_PENDING;
@ -2064,6 +2160,13 @@ st_interpret_sense(xs)
if ((st->quirks & ST_Q_SENSE_HELP) &&
(periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
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
@ -2078,6 +2181,11 @@ st_interpret_sense(xs)
}
}
} 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) {
/*
* The current semantics of this
@ -2103,6 +2211,11 @@ st_interpret_sense(xs)
}
} else if (sense->flags & SSD_FILEMARK) {
retval = 0;
if (st->fileno != (daddr_t) -1) {
st->fileno++;
st->blkno = 0;
st->flags |= ST_POSUPDATED;
}
} else if (sense->flags & SSD_ILI) {
if (info < 0) {
/*
@ -2118,9 +2231,12 @@ st_interpret_sense(xs)
retval = EIO;
} else {
retval = 0;
if (st->blkno != (daddr_t) -1) {
st->blkno++;
st->flags |= ST_POSUPDATED;
}
}
}
xs->resid = info;
if (bp)
bp->b_resid = info;
}
@ -2148,6 +2264,8 @@ st_interpret_sense(xs)
/* return an EOF */
}
retval = 0;
/* lost position */
st->fileno = st->blkno = -1;
}
}
@ -2171,6 +2289,7 @@ st_interpret_sense(xs)
case SKEY_UNIT_ATTENTION:
case SKEY_WRITE_PROTECT:
break;
case SKEY_VOLUME_OVERFLOW:
case SKEY_BLANK_CHECK:
printf(", requested size: %d (decimal)", info);
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.
@ -114,6 +114,11 @@ struct st_softc {
u_int last_dsty; /* last density opened */
short mt_resid; /* last (short) resid */
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
u_int8_t asc; /* 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_EARLYWARN 0x2000 /* Do (deferred) EOM for variable mode */
#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 | \
ST_BLANK_READ)
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_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 *));
int stactivate __P((struct device *, enum devact));