From 844b7c2d86004c04479f05d51fdb0fb0783db0ec Mon Sep 17 00:00:00 2001 From: "Justin T. Gibbs" Date: Sat, 5 Apr 1997 21:41:13 +0000 Subject: [PATCH] Fix a bug in the selection timeout handler that was introduced when the selection loop was merged with the poll_for_work loop. We cannot assume that the SCB for the selection timeout is the current SCB. Instead we must look at the SCB at the head of the waiting for selection list. This fixes part of a problem reported by David Malone, but does not explain why he was getting selection timeouts in the first place. --- sys/i386/scsi/aic7xxx.c | 90 ++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/sys/i386/scsi/aic7xxx.c b/sys/i386/scsi/aic7xxx.c index 7c7736b20631..08e82fb2d0b8 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.111 1997/04/04 04:21:43 gibbs Exp $ + * $Id: aic7xxx.c,v 1.112 1997/04/04 19:36:04 gibbs Exp $ */ /* * TODO: @@ -1663,6 +1663,57 @@ ahc_handle_scsiint(ahc, intstat) ahc_outb(ahc, CLRSINT1, CLRBUSFREE); restart_sequencer(ahc); ahc_outb(ahc, CLRINT, CLRSCSIINT); + } else if ((status & SELTO) != 0) { + struct scsi_xfer *xs; + u_int8_t scbptr; + u_int8_t nextscb; + + scbptr = ahc_inb(ahc, WAITING_SCBH); + ahc_outb(ahc, SCBPTR, scbptr); + scb_index = ahc_inb(ahc, SCB_TAG); + + if (scb_index < ahc->scb_data->numscbs) { + scb = ahc->scb_data->scbarray[scb_index]; + if ((scb->flags & SCB_ACTIVE) == 0) + scb = NULL; + } else + scb = NULL; + + if (scb == NULL) { + printf("%s: ahc_intr - referenced scb not " + "valid during SELTO scb(%d)\n", + ahc_name(ahc), scb_index); + } else { + /* + * XXX If we queued an abort tag, go clean up the + * disconnected list. + */ + xs = scb->xs; + xs->error = XS_SELTIMEOUT; + /* + * Clear any pending messages for the timed out + * target, and mark the target as free + */ + ahc_outb(ahc, MSG_LEN, 0); + ahc_index_busy_target(ahc, xs->sc_link->target, + IS_SCSIBUS_B(ahc, xs->sc_link) ? 'B' : 'A', + /*unbusy*/TRUE); + + ahc_outb(ahc, SCB_CONTROL, 0); + /* Shift the waiting Q forward. */ + nextscb = ahc_inb(ahc, SCB_NEXT); + ahc_outb(ahc, WAITING_SCBH, nextscb); + + ahc_add_curscb_to_free_list(ahc); + } + /* Stop the selection */ + ahc_outb(ahc, SCSISEQ, 0); + + ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE); + + ahc_outb(ahc, CLRINT, CLRSCSIINT); + + restart_sequencer(ahc); } else if (scb == NULL) { printf("%s: ahc_intr - referenced scb not " "valid during scsiint 0x%x scb(%d)\n" @@ -1741,43 +1792,6 @@ ahc_handle_scsiint(ahc, intstat) ahc_outb(ahc, CLRSINT1, CLRSCSIPERR); unpause_sequencer(ahc, /*unpause_always*/TRUE); ahc_outb(ahc, CLRINT, CLRSCSIINT); - } else if ((status & SELTO) != 0) { - struct scsi_xfer *xs; - u_int8_t scbptr; - u_int8_t nextscb; - - /* - * XXX If we queued an abort tag, go clean up the - * disconnected list. - */ - xs = scb->xs; - xs->error = XS_SELTIMEOUT; - /* - * Clear any pending messages for the timed out - * target, and mark the target as free - */ - ahc_outb(ahc, MSG_LEN, 0); - ahc_index_busy_target(ahc, xs->sc_link->target, - IS_SCSIBUS_B(ahc, xs->sc_link) ? 'B' : 'A', - /*unbusy*/TRUE); - /* Stop the selection */ - ahc_outb(ahc, SCSISEQ, 0); - - ahc_outb(ahc, SCB_CONTROL, 0); - - ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE); - - ahc_outb(ahc, CLRINT, CLRSCSIINT); - - /* Shift the waiting Q forward. */ - scbptr = ahc_inb(ahc, WAITING_SCBH); - ahc_outb(ahc, SCBPTR, scbptr); - nextscb = ahc_inb(ahc, SCB_NEXT); - ahc_outb(ahc, WAITING_SCBH, nextscb); - - ahc_add_curscb_to_free_list(ahc); - - restart_sequencer(ahc); } else { sc_print_addr(scb->xs->sc_link); printf("Unknown SCSIINT. Status = 0x%x\n", status);