Add the ability to report file number/block number. From Matt Jacob.
This commit is contained in:
parent
748ed9bd8f
commit
e5160e810e
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue