1) Fix some serious bugs (1 botch on my part which caused a filemark to be

written even it the tape was opened readonly- 2 botches in deferred error
handling for FIXED LENGTH mode which caused panic && hand resp.). Fixed
a memory leak in sa_mount.
2) Fixed an annoying bug when turning of compression to actually reflect
this for future status calls.
3) Implement the MTIOCERRSTAT call where latched control and I/O residuals
and sense data are returned to the application asking for them.
This commit is contained in:
Matt Jacob 1998-12-19 23:33:21 +00:00
parent 084b6a51f3
commit 990635d6e8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=41948

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: scsi_sa.c,v 1.8 1998/12/17 18:56:23 mjacob Exp $
* $Id: scsi_sa.c,v 1.9 1998/12/18 04:31:43 mjacob Exp $
*/
#include <sys/param.h>
@ -157,6 +157,13 @@ struct sa_softc {
int buffer_mode;
int filemarks;
union ccb saved_ccb;
/*
* Latched Error Info
*/
struct scsi_sense_data last_io_sense;
u_int32_t last_io_resid;
struct scsi_sense_data last_ctl_sense;
u_int32_t last_ctl_resid;
};
struct sa_quirk_entry {
@ -384,7 +391,7 @@ saclose(dev_t dev, int flag, int fmt, struct proc *p)
/* FALLTHROUGH */
case SA_MODE_OFFLINE:
sarewind(periph);
saloadunload(periph, /*load*/FALSE);
saloadunload(periph, FALSE);
break;
case SA_MODE_REWIND:
sarewind(periph);
@ -411,9 +418,10 @@ saclose(dev_t dev, int flag, int fmt, struct proc *p)
}
/*
* We wish to note here that there are no filemarks written.
* We wish to note here that there are no more filemarks to be written.
*/
softc->filemarks = 0;
softc->flags &= ~SA_FLAG_TAPE_WRITTEN;
/*
* And we are no longer open for business.
@ -573,10 +581,10 @@ saioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
struct mtget *g = (struct mtget *)arg;
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
("saioctl: MTIOGET\n"));
("saioctl: MTIOGET\n"));
bzero(g, sizeof(struct mtget));
g->mt_type = MT_ISAR; /* Don't ask */
g->mt_type = MT_ISAR;
g->mt_density = softc->media_density;
g->mt_blksiz = softc->media_blksize;
if (softc->flags & SA_FLAG_COMP_UNSUPP) {
@ -609,6 +617,30 @@ saioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
error = 0;
break;
}
case MTIOCERRSTAT:
{
struct scsi_tape_errors *sep =
&((union mterrstat *)arg)->scsi_errstat;
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
("saioctl: MTIOCERRSTAT\n"));
bzero(sep, sizeof(*sep));
sep->io_resid = softc->last_io_resid;
sep->ctl_resid = softc->last_ctl_resid;
bcopy((caddr_t) &softc->last_io_sense, sep->io_sense,
sizeof (sep->io_sense));
bcopy((caddr_t) &softc->last_ctl_sense, sep->ctl_sense,
sizeof (sep->ctl_sense));
softc->last_io_resid = 0;
softc->last_ctl_resid = 0;
bzero((caddr_t) &softc->last_io_sense,
sizeof (softc->last_io_sense));
bzero((caddr_t) &softc->last_ctl_sense,
sizeof (softc->last_ctl_sense));
error = 0;
break;
}
case MTIOCTOP:
{
struct mtop *mt;
@ -1051,6 +1083,7 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
softc = (struct sa_softc *)periph->softc;
CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("sastart"));
switch (softc->state) {
case SA_STATE_NORMAL:
@ -1077,7 +1110,10 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
splx(s);
xpt_release_ccb(start_ccb);
} else if ((softc->flags & SA_FLAG_ERR_PENDING) != 0) {
struct buf *done_bp;
CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
("sastart- coping with pending error %x\n",
softc->flags & SA_FLAG_ERR_PENDING));
bufq_remove(&softc->buf_queue, bp);
bp->b_resid = bp->b_bcount;
bp->b_flags |= B_ERROR;
@ -1085,13 +1121,17 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
if ((bp->b_flags & B_READ) == 0)
bp->b_error = ENOSPC;
}
if ((softc->flags & SA_FLAG_EOF_PENDING) != 0) {
bp->b_error = EIO;
}
if ((softc->flags & SA_FLAG_EIO_PENDING) != 0) {
bp->b_error = EIO;
}
softc->flags &= ~SA_FLAG_ERR_PENDING;
done_bp = bp;
bp = bufq_first(&softc->buf_queue);
splx(s);
biodone(bp);
biodone(done_bp);
} else {
u_int32_t length;
@ -1145,7 +1185,7 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
* records.
*/
scsi_sa_read_write(&start_ccb->csio,
/*retries*/4,
/* No Retries */0,
sadone,
MSG_SIMPLE_Q_TAG,
bp->b_flags & B_READ,
@ -1160,7 +1200,6 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
start_ccb->ccb_h.ccb_bp = bp;
bp = bufq_first(&softc->buf_queue);
splx(s);
xpt_action(start_ccb);
}
@ -1193,8 +1232,7 @@ sadone(struct cam_periph *periph, union ccb *done_ccb)
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if ((error = saerror(done_ccb, 0, 0)) == ERESTART) {
/*
* A retry was scheuled, so
* just return.
* A retry was scheduled, so just return.
*/
return;
}
@ -1252,7 +1290,6 @@ sadone(struct cam_periph *periph, union ccb *done_ccb)
bp->b_resid, bp->b_bcount));
}
#endif
devstat_end_transaction(&softc->device_stats,
bp->b_bcount - bp->b_resid,
done_ccb->csio.tag_action & 0xf,
@ -1613,6 +1650,7 @@ saerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
struct sa_softc *softc;
struct ccb_scsiio *csio;
struct scsi_sense_data *sense;
u_int32_t info, resid;
int error_code, sense_key, asc, ascq;
int error;
@ -1622,18 +1660,7 @@ saerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
sense = &csio->sense_data;
scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
error = 0;
if (((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
&& ((sense->flags & (SSD_EOM|SSD_FILEMARK|SSD_ILI)) != 0)
&& ((sense_key == SSD_KEY_NO_SENSE)
|| (sense_key == SSD_KEY_BLANK_CHECK))) {
u_int32_t info;
u_int32_t resid;
int defer_action;
/*
* Filter out some sense codes of interest.
*/
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) {
if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
info = scsi_4btoul(sense->info);
resid = info;
@ -1647,13 +1674,31 @@ saerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
info /= softc->media_blksize;
}
}
if (csio->ccb_h.ccb_type == SA_CCB_BUFFER_IO) {
bcopy((caddr_t) sense, (caddr_t) &softc->last_io_sense,
sizeof (struct scsi_sense_data));
softc->last_io_resid = resid;
} else {
bcopy((caddr_t) sense, (caddr_t) &softc->last_ctl_sense,
sizeof (struct scsi_sense_data));
softc->last_ctl_resid = resid;
}
}
if (((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
&& ((sense->flags & (SSD_EOM|SSD_FILEMARK|SSD_ILI)) != 0)
&& ((sense_key == SSD_KEY_NO_SENSE)
|| (sense_key == SSD_KEY_BLANK_CHECK))) {
int defer_action;
CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
("Key 0x%x ASC/ASCQ 0x%x 0x%x flags 0x%x resid %d "
"dxfer_len %d\n", sense_key, asc, ascq,
sense->flags & ~SSD_KEY_RESERVED, resid, csio->dxfer_len));
sense->flags & ~SSD_KEY_RESERVED, resid,
csio->dxfer_len));
if ((resid > 0 && resid < csio->dxfer_len)
&& (softc->flags & SA_FLAG_FIXED) != 0)
if (resid > 0 && resid < csio->dxfer_len &&
(softc->flags & SA_FLAG_FIXED) != 0)
defer_action = TRUE;
else
defer_action = FALSE;
@ -2055,6 +2100,7 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
*/
params_to_set &= ~SA_PARAM_COMPRESSION;
/*
* Should probably do something other than a printf...like
* set a flag in the softc saying that this drive doesn't
@ -2113,11 +2159,8 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
xpt_release_ccb(ccb);
} else {
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(ccb->ccb_h.path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
/*getcount_only*/0);
cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
/*
* If we were setting the blocksize, and that failed, we
* want to set it to its original value. If we weren't
@ -2147,22 +2190,28 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
* changed that we care about, so reset it back to 1.
*/
ccb->ccb_h.retry_count = 1;
cam_periph_runccb(ccb, saerror, /*cam_flags*/ 0,
/*sense_flags*/ 0, &softc->device_stats);
cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(ccb->ccb_h.path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
/*getcount_only*/0);
cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
xpt_release_ccb(ccb);
}
if (params_to_set & SA_PARAM_COMPRESSION)
if (current_comp_page != NULL)
free(current_comp_page, M_TEMP);
if (params_to_set & SA_PARAM_COMPRESSION) {
if (error) {
softc->flags &= ~SA_FLAG_COMP_ENABLED;
softc->saved_comp_algorithm = softc->comp_algorithm;
softc->comp_algorithm = 0;
} else {
softc->flags |= SA_FLAG_COMP_ENABLED;
softc->comp_algorithm = comp_algorithm;
}
}
free(mode_buffer, M_TEMP);
return(error);
}