Avoid 3/50 H/W bug (I hope)

This commit is contained in:
gwr 1996-02-12 05:19:09 +00:00
parent c0a9716f6e
commit 2e06ee143c
1 changed files with 38 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ncr_si.c,v 1.3 1996/01/01 22:51:26 thorpej Exp $ */
/* $NetBSD: ncr_si.c,v 1.4 1996/02/12 05:19:09 gwr Exp $ */
/*
* Copyright (c) 1995 David Jones, Gordon W. Ross
@ -153,7 +153,7 @@ struct si_softc {
};
/* Options. Interesting values are: 1,3,7 */
int si_options = 0;
int si_options = 3;
#define SI_ENABLE_DMA 1 /* Use DMA (maybe polled) */
#define SI_DMA_INTR 2 /* DMA completion interrupts */
#define SI_DO_RESELECT 4 /* Allow disconnect/reselect */
@ -297,7 +297,7 @@ si_attach(parent, self, args)
printf("unknown\n");
return;
}
printf("\n");
printf(": options=%d\n", si_options);
/*
* Fill in the prototype scsi_link.
@ -983,10 +983,10 @@ si_obio_udc_write(si, regnum, value)
volatile struct si_regs *si;
int regnum, value;
{
delay(UDC_WAIT_USEC);
si->udc_addr = regnum;
delay(UDC_WAIT_USEC);
si->udc_data = value;
delay(UDC_WAIT_USEC);
}
static __inline__ int
@ -994,10 +994,14 @@ si_obio_udc_read(si, regnum)
volatile struct si_regs *si;
int regnum;
{
delay(UDC_WAIT_USEC);
int value;
si->udc_addr = regnum;
delay(UDC_WAIT_USEC);
return (si->udc_data);
value = si->udc_data;
delay(UDC_WAIT_USEC);
return (value);
}
@ -1036,6 +1040,9 @@ si_obio_dma_setup(ncr_sc)
}
#endif
/* Reset the UDC. (In case not already reset?) */
si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET);
/* Reset the FIFO */
si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
si->si_csr |= SI_CSR_FIFO_RES;
@ -1050,6 +1057,19 @@ si_obio_dma_setup(ncr_sc)
/* Set the FIFO counter. */
si->fifo_count = xlen;
/*
* XXX: Reset DMA engine again! Comment from Sprite:
* Go through reset again becuase of the bug on the 3/50
* where bytes occasionally linger in the DMA fifo.
*/
/* Reset the UDC. */
si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET);
/* Reset the FIFO */
si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
si->si_csr |= SI_CSR_FIFO_RES;
#ifdef DEBUG
if ((si->fifo_count > xlen) || (si->fifo_count < (xlen - 1))) {
printf("si_dma_setup: fifo_count=0x%x, xlen=0x%x\n",
@ -1135,6 +1155,8 @@ si_obio_dma_start(ncr_sc)
/* Tell the chip to interrupt on error. */
si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_CIE);
/* XXX: Move all of the above to _setup? */
/* Finally, give the UDC a "start chain" command. */
si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_STRT_CHN);
@ -1241,6 +1263,7 @@ si_obio_dma_stop(ncr_sc)
}
#endif
/* XXX: Treat (ntrans==0) as a special, non-error case? */
if (ntrans < MIN_DMA_LEN) {
printf("si: fifo count: 0x%x\n", resid);
ncr_sc->sc_state |= NCR_ABORTING;
@ -1260,6 +1283,8 @@ si_obio_dma_stop(ncr_sc)
if ((dh->dh_flags & SIDH_OUT) == 0) {
/* If odd transfer count, grab last byte by hand. */
if (ntrans & 1) {
NCR_TRACE("si_dma_stop: leftover 1 at 0x%x\n",
(int) ncr_sc->sc_dataptr - 1);
ncr_sc->sc_dataptr[-1] =
(si->fifo_data & 0xff00) >> 8;
goto out;
@ -1267,6 +1292,8 @@ si_obio_dma_stop(ncr_sc)
/* UDC might not have transfered the last word. */
udc_cnt = si_obio_udc_read(si, UDC_ADR_COUNT);
if (((udc_cnt * 2) - resid) == 2) {
NCR_TRACE("si_dma_stop: leftover 2 at 0x%x\n",
(int) ncr_sc->sc_dataptr - 2);
ncr_sc->sc_dataptr[-2] =
(si->fifo_data & 0xff00) >> 8;
ncr_sc->sc_dataptr[-1] =
@ -1278,6 +1305,11 @@ out:
/* Reset the UDC. */
si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET);
si->fifo_count = 0;
si->si_csr &= ~SI_CSR_SEND;
/* Reset the FIFO */
si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
si->si_csr |= SI_CSR_FIFO_RES;
/* Put SBIC back in PIO mode. */
*ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);