Use TCL_CHANNEL/SCSI_ID/etc. macros in more locations.

Don't mess with the IRQMS bit in the host control register unless
we are an aic7770 chip.

Use calling context to determine if the card is already paused when
we update the target message request bit field in controller scratch
ram.  Looking at the paused bit in the HCNTRL register opened up a
race condition.

Insert delays in the target message request update routine as a temporary
work around for what looks like a chip bug.  I'm still investigating this
one.

Fix the Abort/Abort Tag/BDR handler to pull its message from the message
buffer in our softc instead of attempting to get it from a register on
the controller.  The message is never recorded by the controller in the
new message scheme.

Don't rely on having an SCB when a BDR occurs.  We can issue these during
invalid reconnects to.

Fix a few cases where we were restarting the sequencer but then still
falling out of a switch statement to unpause the sequencer again.
This could cause us to mess up sequencer state if it generated another
pausing interrupt between the time of the restart and unpause.

Kill the 'transceiver settle' loop during card initialization.  I
failed to realize that a controller that is not connected to any
cables will never settle or enable the SCSI transceivers at all.
The correct solution is to monitor the IOERR interrupt which indicates
that the transceiver state has changed (UW<->LVD).

Modify the aic7xxx assembler to properly echo input when stdin is not
a tty.
This commit is contained in:
Justin T. Gibbs 1999-03-23 07:24:29 +00:00
parent b847980f15
commit e287abc83c
4 changed files with 55 additions and 41 deletions

View File

@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aic7xxx.c,v 1.18 1999/03/05 23:35:46 gibbs Exp $
* $Id: aic7xxx.c,v 1.19 1999/03/08 22:42:52 gibbs Exp $
*/
/*
* A few notes on features of the driver.
@ -159,6 +159,8 @@
(0x01 << (SCB_TARGET_OFFSET(scb)))
#define TCL_CHANNEL(ahc, tcl) \
((((ahc)->features & AHC_TWIN) && ((tcl) & SELBUSB)) ? 'B' : 'A')
#define TCL_SCSI_ID(ahc, tcl) \
(TCL_CHANNEL((ahc), (tcl)) == 'B' ? (ahc)->our_id_b : (ahc)->our_id)
#define TCL_TARGET(tcl) (((tcl) & TID) >> TCL_TARGET_SHIFT)
#define TCL_LUN(tcl) ((tcl) & LID)
@ -308,7 +310,7 @@ static void ahc_validate_offset(struct ahc_softc *ahc,
static void ahc_update_target_msg_request(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
struct ahc_initiator_tinfo *tinfo,
int force);
int force, int paused);
static int ahc_create_path(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
struct cam_path **path);
@ -623,6 +625,9 @@ ahc_alloc(int unit, u_int32_t iobase, vm_offset_t maddr, ahc_chip chip,
ahc->features = features;
ahc->flags = flags;
ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
/* The IRQMS bit is only valid on VL and EISA chips */
if ((ahc->chip & AHC_PCI) != 0)
ahc->unpause &= ~IRQMS;
ahc->pause = ahc->unpause | PAUSE;
return (ahc);
@ -800,9 +805,8 @@ static void
ahc_update_target_msg_request(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
struct ahc_initiator_tinfo *tinfo,
int force)
int force, int paused)
{
int paused;
u_int targ_msg_req_orig;
targ_msg_req_orig = ahc->targ_msg_req;
@ -817,17 +821,19 @@ ahc_update_target_msg_request(struct ahc_softc *ahc,
if (ahc->targ_msg_req != targ_msg_req_orig) {
/* Update the message request bit for this target */
paused = sequencer_paused(ahc);
if (!paused)
if (!paused) {
pause_sequencer(ahc);
DELAY(1000);
}
ahc_outb(ahc, TARGET_MSG_REQUEST, ahc->targ_msg_req & 0xFF);
ahc_outb(ahc, TARGET_MSG_REQUEST + 1,
(ahc->targ_msg_req >> 8) & 0xFF);
if (!paused)
if (!paused) {
unpause_sequencer(ahc, /*unpause always*/FALSE);
DELAY(1000);
}
}
}
@ -852,10 +858,11 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
struct cam_path *path, struct ahc_syncrate *syncrate,
u_int period, u_int offset, u_int type)
{
struct ahc_initiator_tinfo *tinfo;
struct tmode_tstate *tstate;
u_int old_period;
u_int old_offset;
struct ahc_initiator_tinfo *tinfo;
struct tmode_tstate *tstate;
u_int old_period;
u_int old_offset;
int active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
if (syncrate == NULL) {
period = 0;
@ -881,7 +888,7 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
scsirate |= syncrate->sxfr_ultra2;
}
if ((type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE)
if (active)
ahc_outb(ahc, SCSIOFFSET, offset);
} else {
@ -899,7 +906,7 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
scsirate |= syncrate->sxfr & SXFR;
scsirate |= offset & SOFS;
}
if ((type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE) {
if (active) {
u_int sxfrctl0;
sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
@ -909,7 +916,7 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
ahc_outb(ahc, SXFRCTL0, sxfrctl0);
}
}
if ((type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE)
if (active)
ahc_outb(ahc, SCSIRATE, scsirate);
tinfo->scsirate = scsirate;
@ -972,7 +979,9 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
tinfo->user.offset = offset;
}
ahc_update_target_msg_request(ahc, devinfo, tinfo, /*force*/FALSE);
ahc_update_target_msg_request(ahc, devinfo, tinfo,
/*force*/FALSE,
/*paused*/active);
}
static void
@ -982,6 +991,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
struct ahc_initiator_tinfo *tinfo;
struct tmode_tstate *tstate;
u_int oldwidth;
int active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
devinfo->target, &tstate);
@ -998,7 +1008,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
tinfo->scsirate = scsirate;
if ((type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE)
if (active)
ahc_outb(ahc, SCSIRATE, scsirate);
tinfo->current.width = width;
@ -1038,7 +1048,8 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
if ((type & AHC_TRANS_USER) != 0)
tinfo->user.width = width;
ahc_update_target_msg_request(ahc, devinfo, tinfo, /*force*/FALSE);
ahc_update_target_msg_request(ahc, devinfo, tinfo,
/*force*/FALSE, /*paused*/active);
}
static void
@ -1767,6 +1778,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
printf("SAVED_TCL == 0x%x, ARG_1 == 0x%x, SEQ_FLAGS == 0x%x\n",
ahc_inb(ahc, SAVED_TCL), ahc_inb(ahc, ARG_1),
ahc_inb(ahc, SEQ_FLAGS));
ahc->msgout_buf[0] = MSG_BUS_DEV_RESET;
ahc->msgout_len = 1;
ahc->msgout_index = 0;
ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
ahc_outb(ahc, MSG_OUT, HOST_MSG);
ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, LASTPHASE) | ATNO);
break;
}
case SEND_REJECT:
@ -1797,7 +1814,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
printf("%s: Issued Channel %c Bus Reset. "
"%d SCBs aborted\n", ahc_name(ahc), devinfo.channel,
found);
break;
return;
}
case BAD_PHASE:
if (ahc_inb(ahc, LASTPHASE) == P_BUSFREE) {
@ -1928,7 +1945,8 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
&tstate);
ahc_update_target_msg_request(ahc, &devinfo,
tinfo,
/*force*/TRUE);
/*force*/TRUE,
/*paused*/TRUE);
hscb->status = 0;
hscb->SG_count = 1;
hscb->SG_pointer = scb->ahc_dmaphys;
@ -1956,7 +1974,6 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
/* Freeze the queue while the sense occurs. */
ahc_freeze_devq(ahc, scb->ccb->ccb_h.path);
ahc_freeze_ccb(scb->ccb);
break;
}
break;
case SCSI_STATUS_BUSY:
@ -2181,8 +2198,9 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
*/
u_int lastphase = ahc_inb(ahc, LASTPHASE);
u_int saved_tcl = ahc_inb(ahc, SAVED_TCL);
u_int target = (saved_tcl >> 4) & 0x0f;
char channel = saved_tcl & SELBUSB ? 'B': 'A';
u_int target = TCL_TARGET(saved_tcl);
u_int initiator_role_id = TCL_SCSI_ID(ahc, saved_tcl);
char channel = TCL_CHANNEL(ahc, saved_tcl);
int printerror = 1;
ahc_outb(ahc, SCSISEQ,
@ -2191,8 +2209,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
u_int message;
u_int tag;
message = ahc_inb(ahc, SINDEX);
message = ahc->msgout_buf[ahc->msgout_index - 1];
tag = SCB_LIST_NULL;
switch (message) {
case MSG_ABORT_TAG:
@ -2214,7 +2231,12 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
{
struct ahc_devinfo devinfo;
ahc_scb_devinfo(ahc, &devinfo, scb);
ahc_compile_devinfo(&devinfo,
initiator_role_id,
target,
TCL_LUN(saved_tcl),
channel,
ROLE_INITIATOR);
ahc_handle_devreset(ahc, &devinfo,
CAM_BDR_SENT, AC_SENT_BDR,
"Bus Device Reset",
@ -3577,17 +3599,6 @@ ahc_init(struct ahc_softc *ahc)
ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
if ((ahc->features & AHC_ULTRA2) != 0) {
/* Wait for our transceiver status to settle */
i = 1000000;
while (--i && ((ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0))
DELAY(100);
if (i == 0)
panic("%s: Transceiver state never settled\n",
ahc_name(ahc));
}
#if 0
if ((scsi_conf & RESET_SCSI) != 0
&& (ahc->flags & AHC_INITIATORMODE) != 0)

View File

@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aic7xxx.seq,v 1.85 1999/02/11 07:10:20 gibbs Exp $
* $Id: aic7xxx.seq,v 1.86 1999/03/05 23:35:48 gibbs Exp $
*/
#include <dev/aic7xxx/aic7xxx.reg>
@ -1308,7 +1308,6 @@ not_found_cleanup_scb:
call add_scb_to_free_list;
not_found:
mvi INTSTAT, NO_MATCH;
mvi MSG_BUS_DEV_RESET call mk_mesg;
jmp mesgin_done;
/*

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aicasm.c,v 1.19 1997/09/03 03:44:38 gibbs Exp $
* $Id: aicasm.c,v 1.20 1998/09/15 07:24:17 gibbs Exp $
*/
#include <sys/types.h>
#include <sys/mman.h>
@ -491,6 +491,8 @@ output_listing(FILE *listfile, char *ifilename)
break;
}
}
if (isatty(fileno(stdin)) == 0)
putchar(input);
}
fprintf(stdout, "\nThanks!\n");
}

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aicasm.c,v 1.19 1997/09/03 03:44:38 gibbs Exp $
* $Id: aicasm.c,v 1.20 1998/09/15 07:24:17 gibbs Exp $
*/
#include <sys/types.h>
#include <sys/mman.h>
@ -491,6 +491,8 @@ output_listing(FILE *listfile, char *ifilename)
break;
}
}
if (isatty(fileno(stdin)) == 0)
putchar(input);
}
fprintf(stdout, "\nThanks!\n");
}