Fix a problem that will reboot the system with no message as to what the

problem was.  A collision between a select and reselect would leave TC
non-zero from the command-out DMA count, which could later be considered
a fatal condition, causing a reboot.  The message for that error was
only displayed with DEBUG.  Fixed by clearing TC on a reselect.  The
non-zero TC detection won't occur in this case, so unconditionally
display the message if it occurs.

Workaround for another problem that resulted from an "Illegal Command"
status from the 53c94 which would get ignored and result in a timeout
(which also reboots the system).  Added the missing check for the
illegal command status, and add the workaround of resending the "accept
message" command to the 53c94.  Correct fix will be to determine why the
message wasn't sent in the first place.  Abort if the resending the
command doesn't work.

Correctly detect a spurious interrupt and ignore it.  This was taken
from a newer Mach driver, but did not get the check converted for the
design difference between the current NetBSD driver and the Mach driver.
This commit is contained in:
mhitch 1998-05-08 15:39:01 +00:00
parent c85dd6f9e1
commit b3f9a74326

View File

@ -1,4 +1,4 @@
/* $NetBSD: asc.c,v 1.45 1998/03/26 00:49:03 thorpej Exp $ */ /* $NetBSD: asc.c,v 1.46 1998/05/08 15:39:01 mhitch Exp $ */
/*- /*-
* Copyright (c) 1992, 1993 * Copyright (c) 1992, 1993
@ -825,6 +825,7 @@ asc_intr(sc)
register script_t *scpt; register script_t *scpt;
register int ss, ir, status; register int ss, ir, status;
register unsigned char cmd_was; register unsigned char cmd_was;
static int ill_cmd_count = 0; /* XXX */
/* collect ephemeral information */ /* collect ephemeral information */
status = regs->asc_status; status = regs->asc_status;
@ -901,7 +902,8 @@ again:
state = &asc->st[asc->target]; state = &asc->st[asc->target];
switch (ASC_PHASE(status)) { switch (ASC_PHASE(status)) {
case SCSI_PHASE_DATAI: case SCSI_PHASE_DATAI:
if ((asc->script - asc_scripts) == SCRIPT_GET_STATUS) { if ((asc->script - asc_scripts) == SCRIPT_DATA_IN + 1 ||
(asc->script - asc_scripts) == SCRIPT_CONTINUE_IN) {
/* /*
* From the Mach driver: * From the Mach driver:
* After a reconnect and restart dma in, we * After a reconnect and restart dma in, we
@ -1049,11 +1051,8 @@ again:
state->script = asc->script; state->script = asc->script;
} else if (state->flags & DMA_IN) { } else if (state->flags & DMA_IN) {
if (len) { if (len) {
#ifdef DEBUG printf("asc_intr: 1: len %d (fifo %d)\n",
printf("asc_intr: 1: bn %d len %d (fifo %d)\n", len, fifo); /* XXX */
asc_debug_bn, len, fifo); /* XXX */
#endif
goto abort;
} }
/* setup state to resume to */ /* setup state to resume to */
if (state->flags & DMA_IN_PROGRESS) { if (state->flags & DMA_IN_PROGRESS) {
@ -1196,6 +1195,30 @@ again:
/* Should process reselect? */ /* Should process reselect? */
} }
/* check for illegal command */
if (ir & ASC_INT_ILL) {
#ifdef ASC_DIAGNOSTIC
printf("asc_intr: Illegal command status %x ir %x cmd %x ? %x\n",
status, ir, regs->asc_cmd, asc_scripts[SCRIPT_MSG_IN].command);
#endif
/*
* On a 5000/200, I see this frequently when using an RD52
* CDROM. The 53c94 doesn't seem to get the Message Accept
* command, and generates an "Illegal Command" interrupt.
* Re-issuing the Message Accept at this point seems to keep
* things going. Don't allow this too many times in a row,
* just to make sure we don't get hung up. mhitch
*/
if (ill_cmd_count++ != 3) { /* XXX */
regs->asc_cmd = ASC_CMD_MSG_ACPT; /* XXX */
readback(regs->asc_cmd); /* XXX */
goto done; /* XXX */
} /* XXX */
printf("asc_intr: Illegal command tgt %d\n", asc->target);
goto abort; /* XXX */
}
ill_cmd_count = 0; /* XXX */
/* check for reselect */ /* check for reselect */
if (ir & ASC_INT_RESEL) { if (ir & ASC_INT_RESEL) {
unsigned fifo, id, msg; unsigned fifo, id, msg;
@ -1219,6 +1242,11 @@ again:
else else
asc_logp[-1].msg = msg; asc_logp[-1].msg = msg;
#endif #endif
/*
* TC may have been initialized during a selection attempt.
* Clear it to prevent possible confusion later.
*/
ASC_TC_PUT(regs,0); /* ensure TC clear */
asc->state = ASC_STATE_BUSY; asc->state = ASC_STATE_BUSY;
asc->target = id; asc->target = id;
state = &asc->st[id]; state = &asc->st[id];