aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJustin T. Gibbs <gibbs@FreeBSD.org>1997-04-18 16:34:36 +0000
committerJustin T. Gibbs <gibbs@FreeBSD.org>1997-04-18 16:34:36 +0000
commitba5da3326507dda325e99ad0ae2f3e96edbeef70 (patch)
treed1ec65a7217e130d2314d378e3652760ddd389e8 /sys
parent7bde50c60497eb6fc7bbf74fef31f1d070728974 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/scsi/aic7xxx.c140
1 files changed, 62 insertions, 78 deletions
diff --git a/sys/i386/scsi/aic7xxx.c b/sys/i386/scsi/aic7xxx.c
index 52ca36fcafba..77a99810ae74 100644
--- a/sys/i386/scsi/aic7xxx.c
+++ b/sys/i386/scsi/aic7xxx.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.c,v 1.115 1997/04/10 19:14:58 gibbs Exp $
+ * $Id: aic7xxx.c,v 1.116 1997/04/14 02:27:50 gibbs Exp $
*/
/*
* TODO:
@@ -279,7 +279,7 @@ static void ahc_handle_seqint __P((struct ahc_softc *ahc, u_int8_t intstat));
static void ahc_handle_scsiint __P((struct ahc_softc *ahc,
u_int8_t intstat));
static void ahc_handle_devreset __P((struct ahc_softc *ahc,
- struct scb *scb));
+ int target, char channel));
static void ahc_loadseq __P((struct ahc_softc *ahc));
static struct patch *
ahc_next_patch __P((struct patch *cur_patch, int options,
@@ -896,14 +896,17 @@ ahc_handle_seqint(ahc, intstat)
*/
u_int8_t scb_index;
u_int8_t busy_scbid;
+ u_int8_t arg1;
busy_scbid = ahc_index_busy_target(ahc, target, channel,
/*unbusy*/FALSE);
- scb_index = ahc_inb(ahc, ARG_1);
+ arg1 = ahc_inb(ahc, ARG_1);
- if (scb_index == SCB_LIST_NULL)
+ if (arg1 == SCB_LIST_NULL)
/* Untagged Request */
scb_index = busy_scbid;
+ else
+ scb_index = arg1;
if (scb_index < ahc->scb_data->numscbs) {
scb = ahc->scb_data->scbarray[scb_index];
@@ -925,26 +928,16 @@ ahc_handle_seqint(ahc, intstat)
}
}
- /*
- * We expect a busfree to occur, so don't bother to interrupt
- * when it happens - we've already handled the error.
- */
- ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
-
- /*
- * XXX Don't know why this happened or which transaction
- * caused it, so we have to be pretty heavy handed. We should
- * probably modify the sequencer so we can issue a bus device
- * reset instead of an abort in this case.
- */
- ahc_reset_device(ahc, target, channel, ALL_LUNS, SCB_LIST_NULL,
- XS_TIMEOUT);
-
printf("%s:%c:%d: no active SCB for reconnecting "
- "target - issuing ABORT\n",
+ "target - issuing BUS DEVICE RESET\n",
ahc_name(ahc), channel, target);
- printf("SAVED_TCL == 0x%x\n",
- ahc_inb(ahc, SAVED_TCL));
+ printf("SAVED_TCL == 0x%x ARG_1 == 0x%x SEQADDR == 0x%x\n",
+ ahc_inb(ahc, SAVED_TCL), arg1,
+ (ahc_inb(ahc, SEQADDR1) << 8)
+ | ahc_inb(ahc, SEQADDR0));
+
+ ahc_handle_devreset(ahc, target, channel);
+
break;
}
case NO_MATCH_BUSY:
@@ -1586,51 +1579,49 @@ ahc_handle_scsiint(ahc, intstat)
* our abort requests.
*/
u_int8_t lastphase = ahc_inb(ahc, LASTPHASE);
- u_int8_t target = (ahc_inb(ahc, SCSIID) >> 4) & 0x0f;
- u_int8_t scbptr = ahc_inb(ahc, SCBPTR);
- u_int8_t scb_control = ahc_inb(ahc, SCB_CONTROL);
+ u_int8_t target = (ahc_inb(ahc, SAVED_TCL) >> 4) & 0x0f;
char channel = ahc_inb(ahc, SBLKCTL) & SELBUSB ? 'B': 'A';
int printerror = 1;
ahc_outb(ahc, SCSISEQ, 0);
- if (lastphase != P_BUSFREE) {
- u_int8_t flags = ahc_inb(ahc, SEQ_FLAGS)
- & (IDENTIFY_SEEN|RESELECTED);
+ if (lastphase == P_MESGOUT) {
+ u_int8_t sindex;
+ u_int8_t message;
- if (flags == 0 || flags == (IDENTIFY_SEEN|RESELECTED)) {
- /*
- * We have an SCB we have to clean up.
- */
- /* Did we ask for this?? */
- if ((lastphase == P_MESGOUT
- || lastphase == P_MESGIN) && scb != NULL) {
- if (scb->flags & SCB_DEVICE_RESET) {
- ahc_handle_devreset(ahc, scb);
- scb = NULL;
- printerror = 0;
- } else if (scb->flags & SCB_ABORT) {
- struct hardware_scb *hscb;
- u_int8_t tag;
+ sindex = ahc_inb(ahc, SINDEX);
+ message = ahc_inb(ahc, sindex - 1);
- hscb = scb->hscb;
- tag = SCB_LIST_NULL;
- sc_print_addr(scb->xs->sc_link);
- printf("SCB %d - Abort "
- "Completed.\n",
- scbptr);
- if (hscb->control & TAG_ENB)
- tag = scb->hscb->tag;
- ahc_reset_device(ahc,
- target,
- channel,
- SCB_LUN(scb),
- tag,
- XS_TIMEOUT);
- ahc_run_done_queue(ahc);
- scb = NULL;
- printerror = 0;
- }
- }
+ if (message == MSG_ABORT) {
+
+ sc_print_addr(scb->xs->sc_link);
+ printf("SCB %d - Abort Completed.\n",
+ scb->hscb->tag);
+ ahc_reset_device(ahc, target, channel,
+ SCB_LUN(scb),
+ SCB_LIST_NULL,
+ XS_TIMEOUT);
+ ahc_run_done_queue(ahc);
+ scb = NULL;
+ printerror = 0;
+ } else if (message == MSG_ABORT_TAG) {
+
+ sc_print_addr(scb->xs->sc_link);
+ printf("SCB %d - Abort Tag Completed.\n",
+ scb->hscb->tag);
+ ahc_reset_device(ahc,
+ target,
+ channel,
+ SCB_LUN(scb),
+ scb->hscb->tag,
+ XS_TIMEOUT);
+ ahc_run_done_queue(ahc);
+ scb = NULL;
+ printerror = 0;
+ } else if (message == MSG_BUS_DEV_RESET) {
+ ahc_handle_devreset(ahc, target,
+ channel);
+ scb = NULL;
+ printerror = 0;
}
}
if (printerror != 0) {
@@ -1812,16 +1803,14 @@ ahc_handle_scsiint(ahc, intstat)
}
static void
-ahc_handle_devreset(ahc, scb)
+ahc_handle_devreset(ahc, target, channel)
struct ahc_softc *ahc;
- struct scb *scb;
+ int target;
+ char channel;
{
u_int16_t targ_mask;
u_int8_t targ_scratch;
- int target = scb->xs->sc_link->target;
- int lun = scb->xs->sc_link->lun;
int scratch_offset = target;
- char channel = (scb->hscb->tcl & SELBUSB) ? 'B': 'A';
int found;
if (channel == 'B')
@@ -1838,10 +1827,10 @@ ahc_handle_devreset(ahc, scb)
targ_scratch = ahc_inb(ahc, TARG_SCRATCH + scratch_offset);
targ_scratch &= SXFR;
ahc_outb(ahc, TARG_SCRATCH + scratch_offset, targ_scratch);
- sc_print_addr(scb->xs->sc_link);
- found = ahc_reset_device(ahc, target, channel, lun,
+ found = ahc_reset_device(ahc, target, channel, ALL_LUNS,
SCB_LIST_NULL, XS_NOERROR);
- printf("Bus Device Reset delivered. %d SCBs aborted\n", found);
+ printf("%s: Bus Device Reset delivered. %d SCBs aborted\n",
+ ahc_name(ahc), found);
ahc_run_done_queue(ahc);
}
@@ -2580,12 +2569,7 @@ ahc_run_waiting_queue(ahc)
{
struct scb *scb;
- /*
- * On aic78X0 chips, we rely on Auto Access Pause (AAP)
- * instead of doing an explicit pause/unpause.
- */
- if ((ahc->type & AHC_AIC78X0) == 0)
- pause_sequencer(ahc);
+ pause_sequencer(ahc);
while ((scb = ahc->waiting_scbs.stqh_first) != NULL) {
@@ -2597,6 +2581,7 @@ ahc_run_waiting_queue(ahc)
}
STAILQ_REMOVE_HEAD(&ahc->waiting_scbs, links);
scb->flags &= ~SCB_WAITINGQ;
+
ahc_outb(ahc, QINFIFO, scb->hscb->tag);
if ((ahc->flags & AHC_PAGESCBS) != 0)
@@ -2607,8 +2592,7 @@ ahc_run_waiting_queue(ahc)
*/
ahc->curqincnt++;
}
- if ((ahc->type & AHC_AIC78X0) == 0)
- unpause_sequencer(ahc, /*Unpause always*/FALSE);
+ unpause_sequencer(ahc, /*Unpause always*/FALSE);
}
/*
@@ -3118,7 +3102,7 @@ bus_reset:
if (hscb_index == SCB_LIST_NULL) {
disconnected = TRUE;
linked_next = (scb->hscb->datalen >> 24)
- & 0xFF000000;
+ & 0xFF;
} else {
ahc_outb(ahc, SCBPTR, hscb_index);
if (ahc_inb(ahc, SCB_CONTROL) & DISCONNECTED)