summaryrefslogtreecommitdiffstats
path: root/sys/i386/scsi
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1995-02-03 17:15:12 +0000
committergibbs <gibbs@FreeBSD.org>1995-02-03 17:15:12 +0000
commitc1786c1d98fe7e369818e9fb713432c6cc118876 (patch)
treee0058cc699a8d196f8b3ef7e5bf236af25d9cbbe /sys/i386/scsi
parent74f933a4ff197325fc1328384988f204e783c0a1 (diff)
downloadFreeBSD-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.c37
-rw-r--r--sys/i386/scsi/aic7xxx.h4
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;
OpenPOWER on IntegriCloud