summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>1998-12-19 23:33:21 +0000
committermjacob <mjacob@FreeBSD.org>1998-12-19 23:33:21 +0000
commitd71b9016dc9b0d904c58b6ce64145c4a7d3a2f72 (patch)
tree7e8317bb2bb617a471526abed6030725aa4fc096 /sys
parent9050cce8aade3e8abfaa72f35f003b9fb890812c (diff)
downloadFreeBSD-src-d71b9016dc9b0d904c58b6ce64145c4a7d3a2f72.zip
FreeBSD-src-d71b9016dc9b0d904c58b6ce64145c4a7d3a2f72.tar.gz
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.
Diffstat (limited to 'sys')
-rw-r--r--sys/cam/scsi/scsi_sa.c129
1 files changed, 89 insertions, 40 deletions
diff --git a/sys/cam/scsi/scsi_sa.c b/sys/cam/scsi/scsi_sa.c
index a8d6de4..7be1efb 100644
--- a/sys/cam/scsi/scsi_sa.c
+++ b/sys/cam/scsi/scsi_sa.c
@@ -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);
}
OpenPOWER on IntegriCloud