summaryrefslogtreecommitdiff
path: root/sys/dev/ic/aic7xxx_openbsd.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2004-01-17 14:40:56 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2004-01-17 14:40:56 +0000
commitce6c932e534ced3247e5faf28ff1c77eb9664764 (patch)
treefb56d657ea801967485048690762993ce6ee0b4d /sys/dev/ic/aic7xxx_openbsd.c
parentc565652eba846e8845339ef4e839de84cdc95944 (diff)
Major stability improvement. Fix a variety of systems and problems
by dealing with various error conditions. Testing by Marco Peereboom, Olivier Cherrier, Alex Holst, Daniel Lucq, deraadt@, beck@ and others. ok deraadt@.
Diffstat (limited to 'sys/dev/ic/aic7xxx_openbsd.c')
-rw-r--r--sys/dev/ic/aic7xxx_openbsd.c90
1 files changed, 53 insertions, 37 deletions
diff --git a/sys/dev/ic/aic7xxx_openbsd.c b/sys/dev/ic/aic7xxx_openbsd.c
index e1f8dd20c63..540ca9beb66 100644
--- a/sys/dev/ic/aic7xxx_openbsd.c
+++ b/sys/dev/ic/aic7xxx_openbsd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aic7xxx_openbsd.c,v 1.19 2004/01/17 04:56:33 krw Exp $ */
+/* $OpenBSD: aic7xxx_openbsd.c,v 1.20 2004/01/17 14:40:55 krw Exp $ */
/* $NetBSD: aic7xxx_osm.c,v 1.14 2003/11/02 11:07:44 wiz Exp $ */
/*
@@ -51,16 +51,14 @@
#endif
-int32_t ahc_action(struct scsi_xfer *);
-int ahc_execute_scb(void *, bus_dma_segment_t *, int);
-int ahc_poll(struct ahc_softc *, int);
-int ahc_setup_data(struct ahc_softc *, struct scsi_xfer *,
- struct scb *);
-void ahc_set_recoveryscb(struct ahc_softc *, struct scb *);
-
-static void ahc_minphys(struct buf *);
-void ahc_adapter_req_set_xfer_mode(struct ahc_softc *, struct scb *);
+int ahc_action(struct scsi_xfer *);
+int ahc_execute_scb(void *, bus_dma_segment_t *, int);
+int ahc_poll(struct ahc_softc *, int);
+int ahc_setup_data(struct ahc_softc *, struct scsi_xfer *, struct scb *);
+void ahc_set_recoveryscb(struct ahc_softc *, struct scb *);
+void ahc_minphys(struct buf *);
+void ahc_adapter_req_set_xfer_mode(struct ahc_softc *, struct scb *);
struct cfdriver ahc_cd = {
@@ -244,7 +242,32 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
switch (xs->error) {
case CAM_REQ_INPROG:
case CAM_REQ_CMP:
- xs->error = XS_NOERROR;
+ switch (xs->status) {
+ case SCSI_TASKSET_FULL:
+ /* SCSI Layer won't requeue, so we force infinite
+ * retries until queue space is available. XS_BUSY
+ * is dangerous because if the NOSLEEP flag is set
+ * it can cause the I/O to return EIO. XS_BUSY code
+ * falls through to XS_TIMEOUT anyway.
+ */
+ xs->error = XS_TIMEOUT;
+ xs->retries++;
+ break;
+ case SCSI_BUSY:
+ xs->error = XS_BUSY;
+ break;
+ case SCSI_CHECK:
+ case SCSI_TERMINATED:
+ if ((scb->flags & SCB_SENSE) == 0) {
+ /* CHECK on CHECK? */
+ xs->error = XS_DRIVER_STUFFUP;
+ } else
+ xs->error = XS_NOERROR;
+ break;
+ default:
+ xs->error = XS_NOERROR;
+ break;
+ }
break;
case CAM_BUSY:
xs->error = XS_BUSY;
@@ -254,8 +277,10 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
break;
case CAM_BDR_SENT:
case CAM_SCSI_BUS_RESET:
- case CAM_REQUEUE_REQ:
xs->error = XS_RESET;
+ case CAM_REQUEUE_REQ:
+ xs->error = XS_TIMEOUT;
+ xs->retries++;
break;
case CAM_SEL_TIMEOUT:
xs->error = XS_SELTIMEOUT;
@@ -296,7 +321,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
scsi_done(xs);
}
-static void
+void
ahc_minphys(bp)
struct buf *bp;
{
@@ -377,7 +402,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
struct ahc_tmode_tstate *tstate;
u_int mask;
- int s, target;
+ int s;
scb = (struct scb *)arg;
xs = scb->xs;
@@ -475,7 +500,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
}
if ((tstate->tagenable & mask) != 0)
- ahc_set_transaction_tag(scb, TRUE, MSG_SIMPLE_TASK);
+ scb->hscb->control |= TAG_ENB;
bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
0, ahc->scb_data->hscb_dmamap->dm_mapsize,
@@ -529,6 +554,17 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
}
if (!(xs->flags & SCSI_POLL)) {
+ if (ahc->inited_target[xs->sc_link->target] == 0) {
+ struct ahc_devinfo devinfo;
+
+ ahc_adapter_req_set_xfer_mode(ahc, scb);
+ ahc_scb_devinfo(ahc, &devinfo, scb);
+ ahc_update_neg_request(ahc, &devinfo, tstate, tinfo,
+ AHC_NEG_IF_NON_ASYNC);
+
+ ahc->inited_target[xs->sc_link->target] = 1;
+ }
+
ahc_unlock(ahc, &s);
return (SUCCESSFULLY_QUEUED);
}
@@ -539,23 +575,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
poll:
SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
- target = xs->sc_link->target;
- if (ahc->inited_target[target] == INITED_TARGET_INQUIRYOK) {
- struct ahc_initiator_tinfo *tinfo;
- struct ahc_tmode_tstate *tstate;
- struct ahc_devinfo devinfo;
-
- ahc_adapter_req_set_xfer_mode(ahc, scb);
-
- ahc_scb_devinfo(ahc, &devinfo, scb);
- tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
- devinfo.our_scsiid, devinfo.target, &tstate);
- ahc_update_neg_request(ahc, &devinfo, tstate, tinfo,
- AHC_NEG_IF_NON_ASYNC);
-
- ahc->inited_target[target] = INITED_TARGET_MODEOK;
- }
-
do {
if (ahc_poll(ahc, xs->timeout)) {
if (!(xs->flags & SCSI_SILENT))
@@ -565,11 +584,6 @@ poll:
}
} while (!(xs->flags & ITSDONE));
- if (ahc->inited_target[target] == INITED_TARGET_START) {
- if ((xs->cmd->opcode == INQUIRY) && (xs->error == XS_NOERROR))
- ahc->inited_target[target] = INITED_TARGET_INQUIRYOK;
- }
-
ahc_unlock(ahc, &s);
return (COMPLETE);
}
@@ -610,6 +624,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct scsi_xfer *xs,
ahc_lock(ahc, &s);
ahc_free_scb(ahc, scb);
ahc_unlock(ahc, &s);
+ xs->flags |= ITSDONE;
scsi_done(xs);
return (COMPLETE);
}
@@ -637,6 +652,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct scsi_xfer *xs,
ahc_name(ahc), error);
#endif
xs->error = XS_BUSY;
+ xs->flags |= ITSDONE;
scsi_done(xs);
return (TRY_AGAIN_LATER); /* XXX fvdl */
}