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.
This commit is contained in:
Justin T. Gibbs 1997-04-05 21:41:13 +00:00
parent 583f1729d1
commit 844b7c2d86
1 changed files with 52 additions and 38 deletions

View File

@ -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);