summaryrefslogtreecommitdiffstats
path: root/sys/i386/scsi
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1995-03-17 23:58:27 +0000
committergibbs <gibbs@FreeBSD.org>1995-03-17 23:58:27 +0000
commit107fa9cbb1aa397116f7ea30a4d8455a34a1709e (patch)
tree3563bf7b132b5c34d0defe89d7402933a9ff5a8d /sys/i386/scsi
parent0be8d9c7f65ec73db22ba12b714bb9a1025102e5 (diff)
downloadFreeBSD-src-107fa9cbb1aa397116f7ea30a4d8455a34a1709e.zip
FreeBSD-src-107fa9cbb1aa397116f7ea30a4d8455a34a1709e.tar.gz
Increase the DELAY used in ahc_poll. This is only used during intial
probe of the device and shouldn't affect normal operation. It seems that some version of the aic7870 are extreamly slow in clearing their interrupt register so the added delay is required to ensure we don't poll a stale interrupt value. Clean up debugging printfs and stuff superflous output into #ifdef AHC_DEBUG. Ensure that sdtrpending and wdtrpending are cleared in all cases after we recieve an SDTR or WDTR message. With this commit, the 294x should work or at least be much closer to working properly.
Diffstat (limited to 'sys/i386/scsi')
-rw-r--r--sys/i386/scsi/aic7xxx.c114
1 files changed, 67 insertions, 47 deletions
diff --git a/sys/i386/scsi/aic7xxx.c b/sys/i386/scsi/aic7xxx.c
index 631f60a..cdcbf09 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.15 1995/02/22 01:43:24 gibbs Exp $
+ * $Id: aic7xxx.c,v 1.16 1995/03/07 08:59:28 gibbs Exp $
*/
/*
* TODO:
@@ -78,7 +78,7 @@ int ahc_unit = 0;
#define AHC_SHOWCMDS 0x0002
#define AHC_SHOWSCBS 0x0004
/*#define AHC_DEBUG*/
-int ahc_debug = AHC_SHOWCMDS;
+int ahc_debug = AHC_SHOWMISC;
/**** bit definitions for SCSIDEF ****/
#define HSCSIID 0x07 /* our SCSI ID */
@@ -543,7 +543,7 @@ ahc_print_active_scb(ahc)
int cur_scb_offset;
u_long iobase = ahc->baseport;
PAUSE_SEQUENCER(ahc);
- cur_scb_offset = inb(SCBPTR + port);
+ cur_scb_offset = inb(SCBPTR + iobase);
UNPAUSE_SEQUENCER(ahc);
ahc_print_scb(ahc->scbarray[cur_scb_offset]);
}
@@ -694,6 +694,7 @@ ahc_attach(unit)
ahc->sc_link.adapter_unit = unit;
ahc->sc_link.adapter_targ = ahc->our_id;
ahc->sc_link.adapter = &ahc_switch;
+ ahc->sc_link.opennings = 2;
ahc->sc_link.device = &ahc_dev;
ahc->sc_link.flags = DEBUGLEVEL;
ahc->sc_link.fordriver = 0;
@@ -859,22 +860,27 @@ ahcintr(unit)
/* See if we initiated Sync Negotiation */
if(ahc->sdtrpending & (0x01 << scsi_id))
{
- /*
- * Negate the flag and don't send
- * an SDTR back to the target
+ /*
+ * 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);
}
else{
/*
* Send our own SDTR in reply
*/
- printf("Sending SDTR!!\n");
+#ifdef AHC_DEBUG
+ if(ahc_debug & AHC_SHOWMISC)
+ printf("Sending SDTR!!\n");
+#endif
outb(HA_RETURN_1 + iobase, SEND_SDTR);
}
+ /*
+ * Negate the flags
+ */
+ ahc->needsdtr &= ~(0x01 << scsi_id);
+ ahc->sdtrpending &= ~(0x01 << scsi_id);
break;
}
case MSG_WDTR:
@@ -894,12 +900,9 @@ ahcintr(unit)
if(ahc->wdtrpending & (0x01 << scsi_id))
{
/*
- * Negate the flag and don't
- * send a WDTR back to the
+ * Don't send a WDTR back to the
* target, since we asked first.
*/
- ahc->needwdtr &= ~(0x01 << scsi_id);
- ahc->wdtrpending &= ~(0x01 << scsi_id);
outb(HA_RETURN_1 + iobase, 0);
switch(bus_width)
{
@@ -941,8 +944,10 @@ ahcintr(unit)
outb(HA_RETURN_1 + iobase,
bus_width | SEND_WDTR);
}
+ ahc->needwdtr &= ~(0x01 << scsi_id);
+ ahc->wdtrpending &= ~(0x01 << scsi_id);
outb(HA_TARG_SCRATCH + iobase + scsi_id, scratch);
- outb(SCSIRATE + iobase, scratch);
+ outb(SCSIRATE + iobase, scratch);
break;
}
case MSG_REJECT:
@@ -970,6 +975,7 @@ ahcintr(unit)
/* note 8bit xfers and clear flag */
targ_scratch &= 0x7f;
ahc->needwdtr &= ~mask;
+ ahc->wdtrpending &= ~mask;
printf("ahc%d: target %d refusing "
"WIDE negotiation. Using "
"8bit transfers\n",
@@ -979,16 +985,23 @@ ahcintr(unit)
/* note asynch xfers and clear flag */
targ_scratch &= 0xf0;
ahc->needsdtr &= ~mask;
+ ahc->sdtrpending &= ~mask;
printf("ahc%d: target %d refusing "
"syncronous negotiation. Using "
"asyncronous transfers\n",
unit, scsi_id);
}
- else
+ else {
/*
* Otherwise, we ignore it.
*/
+#ifdef AHC_DEBUG
+ if(ahc_debug & AHC_SHOWMISC)
+ printf("Ignored message "
+ "reject!!\n");
+#endif
break;
+ }
outb(HA_TARG_SCRATCH + iobase + scsi_id,
targ_scratch);
outb(SCSIRATE + iobase, targ_scratch);
@@ -1058,8 +1071,7 @@ ahcintr(unit)
#endif
bzero(scb, SCB_DOWN_SIZE);
scb->flags |= SCB_SENSE;
- scb->control = SCB_NEEDDMA |
- (control & SCB_TE);
+ scb->control = control & SCB_TE;
sc->op_code = REQUEST_SENSE;
sc->byte2 = xs->sc_link->lun << 5;
sc->length = sizeof(struct scsi_sense_data);
@@ -1124,22 +1136,22 @@ ahcintr(unit)
break;
}
clear:
- /*
- * Clear the upper byte that holds SEQINT status
- * codes and clear the SEQINT bit.
- */
- outb(CLRINT + iobase, CLRSEQINT);
-
- /*
- * The sequencer is paused immediately on
- * a SEQINT, so we should restart it when
- * we leave this section.
- */
- UNPAUSE_SEQUENCER(ahc);
+ /*
+ * Clear the upper byte that holds SEQINT status
+ * codes and clear the SEQINT bit.
+ */
+ outb(CLRINT + iobase, CLRSEQINT);
+
+ /*
+ * The sequencer is paused immediately on
+ * a SEQINT, so we should restart it when
+ * we leave this section.
+ */
+ UNPAUSE_SEQUENCER(ahc);
}
- if (intstat & SCSIINT) {
+ if (intstat & SCSIINT) {
int scb_index = inb(SCBPTR + iobase);
status = inb(SSTAT1 + iobase);
@@ -1211,7 +1223,6 @@ clear:
outb(CLRSINT1 + iobase, BUSFREE); /* CLRBUSFREE */
#endif
}
-
else {
printf("ahc%d: Unknown SCSIINT. Status = 0x%x\n",
unit, status);
@@ -1297,6 +1308,9 @@ ahc_done(unit, scb)
printf("ahc%d: target %d Tagged Queuing Device\n",
unit, xs->sc_link->target);
ahc->tagenable |= mask;
+#ifdef QUEUE_FULL_SUPPORTED
+ xs->sc_link->opennings += 2; */
+#endif
}
}
ahc_free_scb(unit, scb, xs->flags);
@@ -1312,7 +1326,7 @@ ahc_init(unit)
{
struct ahc_data *ahc = ahcdata[unit];
u_long iobase = ahc->baseport;
- u_char scsi_conf;
+ u_char scsi_conf, sblkctl;
int intdef, i;
/*
@@ -1354,21 +1368,18 @@ ahc_init(unit)
};
/* Determine channel configuration and who we are on the scsi bus. */
- switch ( inb(SBLKCTL + iobase) ) {
+ switch ( (sblkctl = inb(SBLKCTL + iobase) & 0x0f) ) {
case 0:
- case 0xc0: /* 294x Adaptors have the top two bits set */
ahc->our_id = (inb(HA_SCSICONF + iobase) & HSCSIID);
printf("Single Channel, SCSI Id=%d, ", ahc->our_id);
break;
case 2:
- case 0xc2:
ahc->our_id = (inb(HA_SCSICONF + 1 + iobase) & HWSCSIID);
printf("Wide Channel, SCSI Id=%d, ", ahc->our_id);
ahc->type |= AHC_WIDE;
outb(HA_FLAGS + iobase, WIDE_BUS);
break;
case 8:
- case 0xc8:
ahc->our_id = (inb(HA_SCSICONF + iobase) & HSCSIID);
ahc->our_id_b = (inb(HA_SCSICONF + 1 + iobase) & HSCSIID);
printf("Twin Channel, A SCSI Id=%d, B SCSI Id=%d, ",
@@ -1380,7 +1391,10 @@ ahc_init(unit)
printf(" Unsupported adapter type. Ignoring\n");
return(-1);
}
-
+ /*
+ * Take the bus led out of diagnostic mode
+ */
+ outb(SBLKCTL + iobase, sblkctl);
/*
* Number of SCBs that will be used. Rev E aic7770s and
* aic7870s have 16. The rest have 4.
@@ -1393,7 +1407,7 @@ ahc_init(unit)
* Anything below a Rev E will have a
* R/O autoflush diable configuration bit.
*/
- u_char sblkctl, sblkctl_orig;
+ u_char sblkctl_orig;
sblkctl_orig = inb(SBLKCTL + iobase);
sblkctl = sblkctl_orig ^ AUTOFLUSHDIS;
outb(SBLKCTL + iobase, sblkctl);
@@ -1415,9 +1429,9 @@ ahc_init(unit)
printf("aic7870, ");
printf("%d SCBs\n", ahc->maxscbs);
if(!(ahc->type & AHC_294)){
- /* The 294x cards are PCI, so we get their interrupt from the PCI
- * BIOS. It doesn't look like the ISA mapped interrupt is reported
- * correctly this way either.
+ /*
+ * The 294x cards are PCI, so we get their interrupt from the PCI
+ * BIOS.
*/
intdef = inb(INTDEF + iobase);
@@ -1508,6 +1522,11 @@ ahc_init(unit)
ahc->sdtrpending = 0;
ahc->wdtrpending = 0;
ahc->tagenable = 0;
+
+#ifdef AHC_DEBUG
+ printf("NEEDSDTR == 0x%x\nNEEDWDTR == 0x%x\n", ahc->needsdtr,
+ ahc->needwdtr);
+#endif
/*
* Set the number of availible SCBs
*/
@@ -1533,7 +1552,7 @@ ahc_init(unit)
/* Reset the bus */
outb(SCSISEQ + iobase, SCSIRSTO);
- DELAY(500);
+ DELAY(1000);
outb(SCSISEQ + iobase, 0);
UNPAUSE_SEQUENCER(ahc);
@@ -1615,7 +1634,6 @@ ahc_scsi_cmd(xs)
}
SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%x)\n", scb));
scb->xs = xs;
-
if (flags & SCSI_RESET) {
/* XXX: Needs Implementation */
printf("ahc0: SCSI_RESET called.\n");
@@ -1901,9 +1919,9 @@ ahc_poll(int unit, int wait)
u_long stport = INTSTAT + iobase;
while (--wait) {
+ DELAY(10000);
if (inb(stport) & INT_PEND)
break;
- DELAY(1000);
} if (wait == 0) {
printf("ahc%d: board not responding\n", unit);
return (EIO);
@@ -1996,7 +2014,7 @@ ahc_abort_scb( unit, ahc, scb )
/* Reset the bus */
outb(SCSISEQ + iobase, SCSIRSTO);
- DELAY(100);
+ DELAY(1000);
outb(SCSISEQ + iobase, 0);
goto done;
}
@@ -2034,9 +2052,11 @@ ahc_timeout(void *arg1)
,scb->xs->sc_link->device->name
,scb->xs->sc_link->dev_unit);
#ifdef AHC_DEBUG
+#ifdef SCSIDEBUG
if (ahc_debug & AHC_SHOWCMDS) {
- show_scsi_cmd(ecb->xs);
+ show_scsi_cmd(scb->xs);
}
+#endif
if (ahc_debug & AHC_SHOWSCBS)
ahc_print_active_scb(unit);
#endif /*AHC_DEBUG */
OpenPOWER on IntegriCloud