Subject: IMPORTANT: bug in asc driver in 1.2 release
To: None <port-pmax@NetBSD.ORG>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: port-pmax
Date: 10/03/1996 21:06:44
The 1.2 release of the ASC driver for the NCR 53c94 chip used in
TurboChannel DECstations has a bug.
The following patch should be applied to the 1.2 source tree before
re-building a kernel. I am not sure what the official stance on
building an updated kernel, with this patch applied, is, given
that the release is now stepping out the door...
following
Index: src/sys/dev/tc/asc.c
*** 1.1 1996/08/03 11:42:43
--- asc.c 1996/09/29 01:22:04
***************
*** 128,133 ****
--- 128,134 ----
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/errno.h>
+ #include <sys/kernel.h>
#include <sys/device.h>
#include <sys/reboot.h>
***************
*** 198,203 ****
--- 199,205 ----
*/
static void asc_reset();
static void asc_startcmd();
+ static void asc_timeout();
#ifdef DEBUG
int asc_debug = 1;
***************
*** 734,739 ****
--- 736,747 ----
splx(s);
}
asc->cmd[sdp->sd_drive] = scsicmd;
+ /*
+ * Kludge: use a 60 second timeout if data is being transfered,
+ * otherwise use a 30 minute timeout.
+ */
+ timeout(asc_timeout, scsicmd, hz * (scsicmd->buflen == 0 ?
+ 1800 : 60));
asc_startcmd(asc, sdp->sd_drive);
splx(s);
}
***************
*** 1451,1456 ****
--- 1459,1465 ----
scsicmd = asc->cmd[target];
asc->cmd[target] = (ScsiCmd *)0;
state = &asc->st[target];
+ untimeout(asc_timeout, scsicmd);
#ifdef DEBUG
if (asc_debug > 1) {
***************
*** 1544,1556 ****
state->buflen -= len;
}
- #ifdef DEBUG
if (!(state->flags & DMA_IN_PROGRESS) &&
(regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 0) {
! printf("asc_dma_in: FIFO count %x flags %x\n",
! regs->asc_flags, state->flags);
}
- #endif
/* setup to start reading the next chunk */
len = state->buflen;
#ifdef DEBUG
--- 1553,1588 ----
state->buflen -= len;
}
if (!(state->flags & DMA_IN_PROGRESS) &&
(regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 0) {
! volatile int async_fifo_junk = 0;
!
! /*
! * If the target is asynchronous, the FIFO contains
! * a byte of garbage. (see the Mach mk84 53c94 driver,
! * where this occurs on tk-50s and exabytes.)
! * It also occurs on asynch disks like SCSI-1 disks.
! * Recover by reading the byte of junk from the fifo if,
! * and only if, the target is async. If the target is
! * synch, there is no junk, and reading the fifo
! * deadlocks our SCSI state machine.
! */
! if (state->sync_offset == 0)
! async_fifo_junk = regs->asc_fifo;
! #ifdef DEBUG
! printf("%s: asc_dma_in: FIFO count %x flags %x sync_offset %d",
! asc->sc_dev.dv_xname, regs->asc_flags,
! state->flags, state->sync_offset);
! if (state->sync_offset != 0)
! printf("\n");
! else
! printf(" unexpected fifo data %x\n", async_fifo_junk);
! #ifdef DIAGNOSTIC
! asc_DumpLog("asc_dma_in");
! #endif /* DIAGNOSTIC */
! #endif /* DEBUG */
!
}
/* setup to start reading the next chunk */
len = state->buflen;
#ifdef DEBUG
***************
*** 2245,2250 ****
--- 2277,2300 ----
}
}
}
+ }
+
+ void
+ asc_timeout(arg)
+ void *arg;
+ {
+ int s = splbio();
+ ScsiCmd *scsicmd = (ScsiCmd *) arg;
+
+ printf("asc_timeout: cmd %p drive %d\n", scsicmd, scsicmd->sd->sd_drive);
+ #ifdef DEBUG
+ asc_DumpLog("asc_timeout");
+ #endif
+ #if 0
+ panic("asc_timeout");
+ #else
+ boot(4); /* XXX */
+ #endif
}
#ifdef notdef