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:
parent
c85dd6f9e1
commit
b3f9a74326
@ -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];
|
||||||
|
Loading…
Reference in New Issue
Block a user