Fix wrong test for (software) queue blocked condition.

This commit is contained in:
fvdl 2000-06-04 11:42:55 +00:00
parent bcb24bdd25
commit c8c1e5854f

View File

@ -1,4 +1,4 @@
/* $NetBSD: aic7xxx.c,v 1.54 2000/05/29 20:13:53 fvdl Exp $ */
/* $NetBSD: aic7xxx.c,v 1.55 2000/06/04 11:42:55 fvdl Exp $ */
/*
* Generic driver for the aic7xxx based adaptec SCSI controllers
@ -115,6 +115,8 @@
#include <dev/microcode/aic7xxx/aic7xxx_reg.h>
#include <dev/microcode/aic7xxx/aic7xxx_seq.h>
#define XS_STS_DEBUG 0x00000002
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define ALL_CHANNELS '\0'
@ -358,7 +360,7 @@ ahc_first_xs(struct ahc_softc *ahc)
while (xs != NULL) {
target = xs->sc_link->scsipi_scsi.target;
if (ahc->devqueue_blocked[target] == 0 &&
(!ahc_istagged_device(ahc, xs, 0) &&
(ahc_istagged_device(ahc, xs, 0) ||
ahc_index_busy_tcl(ahc, XS_TCL(ahc, xs), FALSE) ==
SCB_LIST_NULL))
break;
@ -1722,6 +1724,8 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
u_int scb_index;
struct hardware_scb *hscb;
struct scsipi_xfer *xs;
struct scb *scbp;
int todo, inqueue;
/*
* The sequencer will notify us when a command
* has an error that would be of interest to
@ -1890,10 +1894,34 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
case SCSI_STATUS_BUSY:
/*
* XXX middle layer doesn't handle XS_BUSY well.
* So, requeue this ourselves internally.
* So, requeue this ourselves internally. It will
* get its turn once all outstanding (tagged)
* commands have finished.
*/
xs->error = XS_BUSY;
xs->xs_status |= XS_STS_DEBUG;
scb->flags |= SCB_REQUEUE;
/*
* Walk through all pending SCBs for this target,
* incrementing the freeze count for the queue.
* When all of these have been completed, the
* queue will be available again.
*/
inqueue = todo = 0;
scbp = ahc->pending_ccbs.lh_first;
while (scbp != NULL) {
inqueue++;
if (ahc_match_scb(scbp, SCB_TARGET(scb),
SCB_CHANNEL(scb), SCB_LUN(scb),
SCB_LIST_NULL, ROLE_INITIATOR)) {
ahc_freeze_ccb(scbp);
todo++;
}
scbp = scbp->plinks.le_next;
}
scsi_print_addr(xs->sc_link);
printf("%d SCBs pending, %d to drain\n", inqueue, todo);
break;
}
break;
@ -3427,10 +3455,21 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
*/
int s;
if (xs->xs_status & XS_STS_DEBUG) {
scsi_print_addr(xs->sc_link);
printf("putting SCB that caused queue full back"
" in queue\n");
}
s = splbio();
TAILQ_INSERT_HEAD(&ahc->sc_q, xs, adapter_q);
splx(s);
} else {
if (xs->xs_status & XS_STS_DEBUG) {
xs->xs_status &= ~XS_STS_DEBUG;
scsi_print_addr(xs->sc_link);
printf("completed SCB that caused queue full\n");
}
xs->xs_status |= XS_STS_DONE;
ahc_check_tags(ahc, xs);
scsipi_done(xs);
@ -4059,6 +4098,11 @@ get_scb:
if ((tstate->discenable & mask) != 0)
hscb->control |= DISCENB;
if (xs->xs_status & XS_STS_DEBUG) {
scsi_print_addr(xs->sc_link);
printf("redoing command that caused queue full\n");
}
if (xs->xs_control & XS_CTL_RESET) {
hscb->cmdpointer = 0;
scb->flags |= SCB_DEVICE_RESET;