Remove the bus settle delay after reset code. It could cause an infinite
loop. Perform a "-Wall" cleanup which actually exposed two real bugs having to do with operator precedence.
This commit is contained in:
parent
a6696ae844
commit
61e13f4498
@ -39,7 +39,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.c,v 1.120 1997/07/20 16:21:34 bde Exp $
|
||||
* $Id: aic7xxx.c,v 1.121 1997/08/13 17:02:43 gibbs Exp $
|
||||
*/
|
||||
/*
|
||||
* TODO:
|
||||
@ -182,18 +182,7 @@ static inline void unpause_sequencer __P((struct ahc_softc *ahc,
|
||||
int unpause_always));
|
||||
static inline void restart_sequencer __P((struct ahc_softc *ahc));
|
||||
|
||||
static int timeouts_work; /*
|
||||
* Boolean that lets the driver know
|
||||
* that it can safely use timeouts
|
||||
* for event scheduling. Timeouts
|
||||
* don't work early in the boot
|
||||
* process.
|
||||
*/
|
||||
|
||||
#define AHC_BUSRESET_DELAY 1000 /* Reset delay in us */
|
||||
#define AHC_BUSSETTLE_DELAY (100 * 1000)/* Delay before taking commands
|
||||
* after a reset in us
|
||||
*/
|
||||
|
||||
static struct scsi_adapter ahc_switch =
|
||||
{
|
||||
@ -323,15 +312,6 @@ static timeout_t
|
||||
static void ahc_timeout __P((void *));
|
||||
#endif
|
||||
|
||||
static timeout_t
|
||||
ahc_first_timeout;
|
||||
|
||||
static timeout_t
|
||||
ahc_busreset_complete;
|
||||
|
||||
static timeout_t
|
||||
ahc_busreset_settle_complete;
|
||||
|
||||
static u_int8_t ahc_index_busy_target __P((struct ahc_softc *ahc, int target,
|
||||
char channel, int unbusy));
|
||||
|
||||
@ -495,11 +475,6 @@ ahc_construct(ahc, bc, ioh, maddr, type, flags)
|
||||
ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
|
||||
ahc->pause = ahc->unpause | PAUSE;
|
||||
|
||||
ahc->busreset_args.ahc = ahc;
|
||||
ahc->busreset_args.bus = 'A';
|
||||
ahc->busreset_args_b.ahc = ahc;
|
||||
ahc->busreset_args_b.bus = 'B';
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
return (ahc);
|
||||
#endif
|
||||
@ -609,7 +584,7 @@ ahc_scsirate(ahc, scsirate, period, offset, channel, target )
|
||||
ultra_enb_addr++;
|
||||
ultra_enb = ahc_inb(ahc, ultra_enb_addr);
|
||||
sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
|
||||
if (*scsirate != 0 && ahc_syncrates[i].sxfr & ULTRA_SXFR) {
|
||||
if (*scsirate != 0 && (ahc_syncrates[i].sxfr & ULTRA_SXFR)) {
|
||||
ultra_enb |= 0x01 << (target & 0x07);
|
||||
sxfrctl0 |= FAST20;
|
||||
} else {
|
||||
@ -698,7 +673,7 @@ ahc_attach(ahc)
|
||||
scbus = NULL; /* Upper-level SCSI code owns this now */
|
||||
|
||||
if (ahc->type & AHC_TWIN) {
|
||||
scbus = scsi_alloc_bus();
|
||||
scbus = scsi_alloc_bus();
|
||||
if (!scbus)
|
||||
return 0;
|
||||
scbus->adapter_link = (ahc->flags & AHC_CHANNEL_B_PRIMARY) ?
|
||||
@ -784,7 +759,7 @@ ahc_intr(arg)
|
||||
int int_cleared;
|
||||
|
||||
int_cleared = 0;
|
||||
while (qoutcnt = (ahc_inb(ahc, QOUTCNT) & ahc->qcntmask)) {
|
||||
while ((qoutcnt = (ahc_inb(ahc, QOUTCNT) & ahc->qcntmask)) != 0) {
|
||||
ahc->cmdoutcnt += qoutcnt;
|
||||
for (; qoutcnt > 0; qoutcnt--) {
|
||||
scb_index = ahc_inb(ahc, QOUTFIFO);
|
||||
@ -971,7 +946,6 @@ ahc_handle_seqint(ahc, intstat)
|
||||
* to happen.
|
||||
*/
|
||||
u_int8_t scb_index;
|
||||
u_int8_t busy_scbindex;
|
||||
|
||||
scb_index = ahc_inb(ahc, CUR_SCBID);
|
||||
scb = ahc->scb_data->scbarray[scb_index];
|
||||
@ -1944,7 +1918,7 @@ ahc_done(ahc, scb)
|
||||
}
|
||||
}
|
||||
#endif /* AHC_TAGENABLE */
|
||||
if ((scb->flags & SCB_MSGOUT_WDTR|SCB_MSGOUT_SDTR) != 0) {
|
||||
if ((scb->flags & (SCB_MSGOUT_WDTR|SCB_MSGOUT_SDTR)) != 0) {
|
||||
/*
|
||||
* Turn off the pending flags for any DTR messages
|
||||
* regardless of whether they completed successfully
|
||||
@ -2284,7 +2258,7 @@ ahc_init(ahc)
|
||||
|
||||
if (ahc->scb_data->hscbs == NULL) {
|
||||
printf("%s: unable to allocate hardware SCB array. "
|
||||
"Failing attach\n");
|
||||
"Failing attach\n", ahc_name(ahc));
|
||||
return (-1);
|
||||
}
|
||||
/* At least the control byte of each hscb needs to be zeroed */
|
||||
@ -2352,9 +2326,6 @@ ahc_init(ahc)
|
||||
|
||||
unpause_sequencer(ahc, /*unpause_always*/TRUE);
|
||||
|
||||
/* Notify us when the system can handle timeouts */
|
||||
timeout(ahc_first_timeout, NULL, 0);
|
||||
|
||||
/*
|
||||
* Note that we are going and return (to probe)
|
||||
*/
|
||||
@ -2403,23 +2374,6 @@ ahc_scsi_cmd(xs)
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n"));
|
||||
flags = xs->flags;
|
||||
|
||||
if (ahc->in_reset != 0) {
|
||||
/*
|
||||
* If we are still in a reset, send the transaction
|
||||
* back indicating that it was aborted due to a
|
||||
* reset.
|
||||
*/
|
||||
if ((IS_SCSIBUS_B(ahc, xs->sc_link)
|
||||
&& (ahc->in_reset & CHANNEL_B_RESET) != 0)
|
||||
|| (!IS_SCSIBUS_B(ahc, xs->sc_link)
|
||||
&& (ahc->in_reset & CHANNEL_A_RESET) != 0)) {
|
||||
/* Ick, but I don't want it to abort this */
|
||||
xs->retries++;
|
||||
xs->error = XS_BUSY;
|
||||
return(COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get an scb to use. If the transfer
|
||||
* is from a buf (possibly from interrupt time)
|
||||
@ -2918,19 +2872,6 @@ ahc_poll(ahc, wait)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler to register that the system is capable of
|
||||
* delivering timeouts. We register this timeout in
|
||||
* ahc_init and it should go off as soon as we're through
|
||||
* the boot process.
|
||||
*/
|
||||
static void
|
||||
ahc_first_timeout(arg)
|
||||
void *arg;
|
||||
{
|
||||
timeouts_work = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ahc_timeout(arg)
|
||||
void *arg;
|
||||
@ -3335,13 +3276,19 @@ ahc_reset_device(ahc, target, channel, lun, tag, xs_error)
|
||||
break;
|
||||
case ALL_CHANNELS:
|
||||
min_target = 0;
|
||||
max_target = ahc->type & AHC_WIDE|AHC_TWIN
|
||||
? 15 : 7;
|
||||
max_target = ahc->type & (AHC_WIDE|AHC_TWIN)
|
||||
? 15 : 7;
|
||||
break;
|
||||
default:
|
||||
/* Shutup warning */
|
||||
min_target = 0;
|
||||
max_target = 0;
|
||||
panic("ahc_reset_device: Bogus Channel");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
} else {
|
||||
min_target = max_target = target
|
||||
+ channel == 'B' ? 8 : 0;
|
||||
min_target = max_target
|
||||
= target + (channel == 'B' ? 8 : 0);
|
||||
}
|
||||
|
||||
for (i = min_target; i <= max_target; i++) {
|
||||
@ -3569,8 +3516,6 @@ ahc_abort_wscb (ahc, scbp, scbpos, prev, xs_error)
|
||||
u_int32_t xs_error;
|
||||
{
|
||||
u_int8_t curscb, next;
|
||||
int target = ((scbp->hscb->tcl >> 4) & 0x0f);
|
||||
char channel = (scbp->hscb->tcl & SELBUSB) ? 'B' : 'A';
|
||||
/*
|
||||
* Select the SCB we want to abort and
|
||||
* pull the next pointer out of it.
|
||||
@ -3643,7 +3588,6 @@ ahc_busy_target(ahc, target, channel, scbid)
|
||||
{
|
||||
u_int8_t active_scb;
|
||||
u_int8_t info_scb;
|
||||
u_int8_t busy_scbid;
|
||||
u_int32_t scb_offset;
|
||||
|
||||
info_scb = target / 4;
|
||||
@ -3674,104 +3618,21 @@ ahc_reset_current_bus(ahc)
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
u_int8_t scsiseq;
|
||||
u_int8_t sblkctl;
|
||||
|
||||
|
||||
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST);
|
||||
scsiseq = ahc_inb(ahc, SCSISEQ);
|
||||
scsiseq = ahc_inb(ahc, SCSISEQ);
|
||||
ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
|
||||
if (timeouts_work != 0) {
|
||||
struct ahc_busreset_args *args;
|
||||
|
||||
sblkctl = ahc_inb(ahc, SBLKCTL);
|
||||
args = (sblkctl & SELBUSB) ? &ahc->busreset_args_b
|
||||
: &ahc->busreset_args;
|
||||
ahc->in_reset |= (args->bus == 'A' ? CHANNEL_A_RESET
|
||||
: CHANNEL_B_RESET);
|
||||
timeout(ahc_busreset_complete, args,
|
||||
MAX((AHC_BUSRESET_DELAY * hz) / 1000000, 1));
|
||||
} else {
|
||||
DELAY(AHC_BUSRESET_DELAY);
|
||||
/* Turn off the bus reset */
|
||||
ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
|
||||
|
||||
ahc_clear_intstat(ahc);
|
||||
|
||||
/* Re-enable reset interrupts */
|
||||
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
|
||||
|
||||
/* Wait a minimal bus settle delay */
|
||||
DELAY(AHC_BUSSETTLE_DELAY);
|
||||
|
||||
ahc_run_done_queue(ahc);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ahc_busreset_complete(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct ahc_busreset_args *args;
|
||||
struct ahc_softc *ahc;
|
||||
int s;
|
||||
u_int8_t scsiseq;
|
||||
u_int8_t sblkctl;
|
||||
|
||||
args = (struct ahc_busreset_args *)arg;
|
||||
ahc = (struct ahc_softc *)args->ahc;
|
||||
|
||||
s = splbio();
|
||||
pause_sequencer(ahc);
|
||||
|
||||
/* Save the current block control state */
|
||||
sblkctl = ahc_inb(ahc, SBLKCTL);
|
||||
|
||||
/* Switch to the right bus */
|
||||
if (args->bus == 'A')
|
||||
ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB);
|
||||
else
|
||||
ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB);
|
||||
|
||||
|
||||
DELAY(AHC_BUSRESET_DELAY);
|
||||
/* Turn off the bus reset */
|
||||
printf("Clearing bus reset\n");
|
||||
scsiseq = ahc_inb(ahc, SCSISEQ);
|
||||
ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
|
||||
|
||||
|
||||
ahc_clear_intstat(ahc);
|
||||
|
||||
|
||||
/* Re-enable reset interrupts */
|
||||
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
|
||||
|
||||
/*
|
||||
* Set a 100ms timeout to clear our in_reset flag.
|
||||
* It will be *at-least* that long before any targets
|
||||
* respond to real commands on the bus.
|
||||
*/
|
||||
timeout(ahc_busreset_settle_complete, args,
|
||||
(AHC_BUSSETTLE_DELAY * hz) / 1000000);
|
||||
|
||||
/* Restore the original channel */
|
||||
ahc_outb(ahc, SBLKCTL, sblkctl);
|
||||
unpause_sequencer(ahc, /*unpause_always*/FALSE);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static void
|
||||
ahc_busreset_settle_complete(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct ahc_busreset_args *args;
|
||||
struct ahc_softc *ahc;
|
||||
int s;
|
||||
|
||||
args = (struct ahc_busreset_args *)arg;
|
||||
ahc = (struct ahc_softc *)args->ahc;
|
||||
/* Clear the reset flag */
|
||||
s = splbio();
|
||||
printf("Clearing 'in-reset' flag\n");
|
||||
ahc->in_reset &= (args->bus == 'A' ? ~CHANNEL_A_RESET
|
||||
: ~CHANNEL_B_RESET);
|
||||
ahc_run_done_queue(ahc);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -3783,7 +3644,6 @@ ahc_reset_channel(ahc, channel, xs_error, initiate_reset)
|
||||
{
|
||||
u_int32_t offset, offset_max;
|
||||
int found;
|
||||
int target;
|
||||
u_int8_t sblkctl;
|
||||
char cur_channel;
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.h,v 1.41 1997/06/27 19:39:20 gibbs Exp $
|
||||
* $Id: aic7xxx.h,v 1.42 1997/08/13 17:02:47 gibbs Exp $
|
||||
*/
|
||||
|
||||
#ifndef _AIC7XXX_H_
|
||||
@ -256,8 +256,6 @@ struct ahc_softc {
|
||||
#endif
|
||||
volatile u_int8_t *maddr;
|
||||
struct scb_data *scb_data;
|
||||
struct ahc_busreset_args busreset_args;
|
||||
struct ahc_busreset_args busreset_args_b;
|
||||
struct scsi_link sc_link;
|
||||
struct scsi_link sc_link_b; /* Second bus for Twin channel cards */
|
||||
STAILQ_HEAD(, scb) waiting_scbs;/*
|
||||
@ -301,9 +299,6 @@ struct ahc_softc {
|
||||
u_int8_t unpause;
|
||||
u_int8_t pause;
|
||||
u_int8_t in_timeout;
|
||||
u_int8_t in_reset;
|
||||
#define CHANNEL_A_RESET 0x01
|
||||
#define CHANNEL_B_RESET 0x02
|
||||
};
|
||||
|
||||
struct full_ahc_softc {
|
||||
|
Loading…
Reference in New Issue
Block a user