diff options
author | gibbs <gibbs@FreeBSD.org> | 1995-02-03 17:15:12 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1995-02-03 17:15:12 +0000 |
commit | c1786c1d98fe7e369818e9fb713432c6cc118876 (patch) | |
tree | e0058cc699a8d196f8b3ef7e5bf236af25d9cbbe /sys/i386/scsi | |
parent | 74f933a4ff197325fc1328384988f204e783c0a1 (diff) | |
download | FreeBSD-src-c1786c1d98fe7e369818e9fb713432c6cc118876.zip FreeBSD-src-c1786c1d98fe7e369818e9fb713432c6cc118876.tar.gz |
Keep track of when we actually are awaiting a reply to an SDTR or WDTR
message instead of relying on the fact that we are scheduled to send them.
The old method worked 99.9% of the time, but someone reported some periferals
that did MSG_REJECT at odd times (sometimes before we could send an SDTR
or WDTR) that we would construe as the response to an SDTR or WDTR message.
This also removes a possible race condition where after a bus reset (the
result of a command time out not during intial probe time), we might queue
two commands both requesting SDTR, WDTR or both.
Diffstat (limited to 'sys/i386/scsi')
-rw-r--r-- | sys/i386/scsi/aic7xxx.c | 37 | ||||
-rw-r--r-- | sys/i386/scsi/aic7xxx.h | 4 |
2 files changed, 31 insertions, 10 deletions
diff --git a/sys/i386/scsi/aic7xxx.c b/sys/i386/scsi/aic7xxx.c index 0b62719..1817f48 100644 --- a/sys/i386/scsi/aic7xxx.c +++ b/sys/i386/scsi/aic7xxx.c @@ -24,7 +24,7 @@ * * commenced: Sun Sep 27 18:14:01 PDT 1992 * - * $Id: aic7xxx.c,v 1.12 1995/01/22 00:48:39 gibbs Exp $ + * $Id: aic7xxx.c,v 1.13 1995/01/27 17:37:05 gibbs Exp $ */ /* * TODO: @@ -849,13 +849,14 @@ ahcintr(unit) outb(HA_TARG_SCRATCH + iobase + scsi_id, rate); outb(SCSIRATE + iobase, rate); /* See if we initiated Sync Negotiation */ - if(ahc->needsdtr & (0x01 << scsi_id)) + if(ahc->sdtrpending & (0x01 << scsi_id)) { /* * Negate the flag and don't send * an SDTR back to the target */ ahc->needsdtr &= ~(0x01 << scsi_id); + ahc->sdtrpending &= ~(0x01 << scsi_id); outb(HA_RETURN_1 + iobase, 0); } @@ -883,7 +884,7 @@ ahcintr(unit) scratch = inb(HA_TARG_SCRATCH + iobase + scsi_id); - if(ahc->needwdtr & (0x01 << scsi_id)) + if(ahc->wdtrpending & (0x01 << scsi_id)) { /* * Negate the flag and don't @@ -891,6 +892,7 @@ ahcintr(unit) * target, since we asked first. */ ahc->needwdtr &= ~(0x01 << scsi_id); + ahc->wdtrpending &= ~(0x01 << scsi_id); outb(HA_RETURN_1 + iobase, 0); switch(bus_width) { @@ -957,7 +959,7 @@ ahcintr(unit) + scsi_id); mask = (0x01 << scsi_id); - if(ahc->needwdtr & mask){ + if(ahc->wdtrpending & mask){ /* note 8bit xfers and clear flag */ targ_scratch &= 0x7f; ahc->needwdtr &= ~mask; @@ -966,7 +968,7 @@ ahcintr(unit) "8bit transfers\n", unit, scsi_id); } - else if(ahc->needsdtr & mask){ + else if(ahc->sdtrpending & mask){ /* note asynch xfers and clear flag */ targ_scratch &= 0xf0; ahc->needsdtr &= ~mask; @@ -1443,6 +1445,8 @@ ahc_init(unit) } ahc->needsdtr = ahc->needsdtr_orig; ahc->needwdtr = ahc->needwdtr_orig; + ahc->sdtrpending = 0; + ahc->wdtrpending = 0; /* * Set the number of availible SCBs */ @@ -1452,6 +1456,11 @@ ahc_init(unit) outb( HA_ACTIVE0 + iobase, 0 ); outb( HA_ACTIVE1 + iobase, 0 ); + /* Reset the bus */ + outb(SCSISEQ + iobase, SCSIRSTO); + DELAY(500); + outb(SCSISEQ + iobase, 0); + UNPAUSE_SEQUENCER(ahc); /* @@ -1540,10 +1549,16 @@ ahc_scsi_cmd(xs) * Put all the arguments for the xfer in the scb */ - if(ahc->needsdtr & mask) + if((ahc->needsdtr & mask) && !(ahc->sdtrpending & mask)) + { scb->control |= SCB_NEEDSDTR; - if(ahc->needwdtr & mask) + ahc->sdtrpending |= mask; + } + if((ahc->needwdtr & mask) && !(ahc->wdtrpending & mask)) + { scb->control |= SCB_NEEDWDTR; + ahc->wdtrpending |= mask; + } scb->target_channel_lun = ((xs->sc_link->target << 4) & 0xF0) | ((u_long)xs->sc_link->fordriver & 0x08) | xs->sc_link->lun & 0x07; @@ -1888,23 +1903,27 @@ ahc_abort_scb( unit, ahc, scb ) u_char flags; if(scb->target_channel_lun & 0x08){ ahc->needsdtr |= (ahc->needsdtr_orig & 0xff00); + ahc->sdtrpending &= 0x00ff; outb(HA_ACTIVE1, 0); } else if (ahc->type == AHC_274W || ahc->type == AHC_284W || ahc->type == AHC_294W){ ahc->needsdtr = ahc->needsdtr_orig; ahc->needwdtr = ahc->needwdtr_orig; + ahc->sdtrpending = 0; + ahc->wdtrpending = 0; outb(HA_ACTIVE0, 0); outb(HA_ACTIVE1, 0); } else{ - ahc->needsdtr = ahc->needsdtr_orig; + ahc->needsdtr |= (ahc->needsdtr_orig & 0x00ff); + ahc->sdtrpending &= 0xff00; outb(HA_ACTIVE0, 0); } /* Reset the bus */ outb(SCSISEQ + iobase, SCSIRSTO); - DELAY(50); + DELAY(100); outb(SCSISEQ + iobase, 0); goto done; } diff --git a/sys/i386/scsi/aic7xxx.h b/sys/i386/scsi/aic7xxx.h index c009abb..ce08cc4 100644 --- a/sys/i386/scsi/aic7xxx.h +++ b/sys/i386/scsi/aic7xxx.h @@ -20,7 +20,7 @@ * 4. Modifications may be freely made to this file if the above conditions * are met. * - * $Id$ + * $Id: aic7xxx.h,v 1.2 1995/01/16 16:33:47 gibbs Exp $ */ #ifndef _AIC7XXX_H_ @@ -136,6 +136,8 @@ struct ahc_data { u_short needwdtr_orig; /* Targets we initiate wide neg with */ u_short needsdtr; /* Current list of negotiated targets */ u_short needwdtr; /* Current list of negotiated targets */ + u_short sdtrpending; /* Pending SDTR to these targets */ + u_short wdtrpending; /* Pending WDTR to these targets */ int numscbs; u_char maxscbs; int unpause; |