- Remove several hacks that didn't do much but waste cycles.

- Disable interrupt-driven PDMA when writing (use polled PDMA instead).
- Be more careful about when to flag a transfer as completed.

The result of these changes is that interrupt-driven PDMA works well
enough to bring the system up.
This commit is contained in:
scottr 1996-04-25 06:18:41 +00:00
parent 74affdc8f8
commit 2e936aa8ff
1 changed files with 51 additions and 53 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ncr_sbc.c,v 1.7 1996/04/23 14:20:28 scottr Exp $ */ /* $NetBSD: ncr_sbc.c,v 1.8 1996/04/25 06:18:41 scottr Exp $ */
/* /*
* Copyright (c) 1996 Scott Reynolds * Copyright (c) 1996 Scott Reynolds
@ -99,7 +99,7 @@
#define SBC_DB_DMA 0x02 #define SBC_DB_DMA 0x02
#define SBC_DB_BREAK 0x04 #define SBC_DB_BREAK 0x04
int sbc_debug = SBC_DB_INTR | SBC_DB_DMA | SBC_DB_BREAK; int sbc_debug = 0 /* SBC_DB_INTR | SBC_DB_DMA */;
int sbc_link_flags = 0 /* | SDEV_DB2 */; int sbc_link_flags = 0 /* | SDEV_DB2 */;
#endif #endif
@ -111,7 +111,6 @@ struct sbc_pdma_handle {
#define SBC_DH_BUSY 0x01 /* This DH is in use */ #define SBC_DH_BUSY 0x01 /* This DH is in use */
#define SBC_DH_OUT 0x02 /* PDMA does data out (write) */ #define SBC_DH_OUT 0x02 /* PDMA does data out (write) */
#define SBC_DH_XFER 0x04 /* PDMA transfer not completed */ #define SBC_DH_XFER 0x04 /* PDMA transfer not completed */
#define SBC_DH_START 0x08 /* PDMA transfer not yet underway */
u_char *dh_addr; /* data buffer */ u_char *dh_addr; /* data buffer */
int dh_len; /* length of data buffer */ int dh_len; /* length of data buffer */
}; };
@ -129,9 +128,6 @@ struct sbc_softc {
volatile u_char *sc_iflag; volatile u_char *sc_iflag;
int sc_options; /* options for this instance. */ int sc_options; /* options for this instance. */
struct sbc_pdma_handle sc_pdma[SCI_OPENINGS]; struct sbc_pdma_handle sc_pdma[SCI_OPENINGS];
#ifdef SBC_DEBUG
char *sc_vstate;
#endif
}; };
/* /*
@ -467,7 +463,7 @@ sbc_irq_intr(p)
ncr_sc->sc_dev.dv_xname); ncr_sc->sc_dev.dv_xname);
# ifdef DDB # ifdef DDB
if (sbc_debug & SBC_DB_BREAK) if (sbc_debug & SBC_DB_BREAK)
Debugger(); /* XXX */ Debugger();
# endif # endif
} }
#endif #endif
@ -545,7 +541,8 @@ sbc_pdma_out(ncr_sc, phase, count, data)
return count - len; return count - len;
timeout: timeout:
printf("pdma_out: timeout len=%d count=%d\n", len, count); printf("%s: pdma_out: timeout len=%d count=%d\n",
ncr_sc->sc_dev.dv_xname, len, count);
if ((*ncr_sc->sci_csr & SCI_CSR_PHASE_MATCH) == 0) { if ((*ncr_sc->sci_csr & SCI_CSR_PHASE_MATCH) == 0) {
*ncr_sc->sci_icmd &= ~SCI_ICMD_DATA; *ncr_sc->sci_icmd &= ~SCI_ICMD_DATA;
--len; --len;
@ -655,7 +652,8 @@ sbc_pdma_in(ncr_sc, phase, count, data)
return count - len; return count - len;
timeout: timeout:
printf("pdma_in: timeout len=%d count=%d\n", len, count); printf("%s: pdma_in: timeout len=%d count=%d\n",
ncr_sc->sc_dev.dv_xname, len, count);
SCI_CLR_INTR(ncr_sc); SCI_CLR_INTR(ncr_sc);
*ncr_sc->sci_mode &= ~SCI_MODE_DMA; *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
@ -703,15 +701,14 @@ sbc_drq_intr(p)
/* /*
* If we're not ready to xfer data, or have no more, just return. * If we're not ready to xfer data, or have no more, just return.
*/ */
if ((*ncr_sc->sci_csr & SCI_CSR_DREQ) == 0 || dh->dh_len == 0) { if ((*ncr_sc->sci_csr & SCI_CSR_DREQ) == 0)
return;
if (dh->dh_len == 0) {
dh->dh_flags &= ~SBC_DH_XFER; dh->dh_flags &= ~SBC_DH_XFER;
return; return;
} }
dh->dh_flags &= ~SBC_DH_START;
#ifdef SBC_DEBUG #ifdef SBC_DEBUG
sc->sc_vstate = "got drq interrupt.";
if (sbc_debug & SBC_DB_INTR) if (sbc_debug & SBC_DB_INTR)
printf("%s: drq intr, dh_len=0x%x, dh_flags=0x%x\n", printf("%s: drq intr, dh_len=0x%x, dh_flags=0x%x\n",
ncr_sc->sc_dev.dv_xname, dh->dh_len, dh->dh_flags); ncr_sc->sc_dev.dv_xname, dh->dh_len, dh->dh_flags);
@ -730,20 +727,21 @@ sbc_drq_intr(p)
- (u_long) sc->sc_drq_addr); - (u_long) sc->sc_drq_addr);
if ((count < 0) || (count > dh->dh_len)) { if ((count < 0) || (count > dh->dh_len)) {
printf("%s: count = 0x%x (pending 0x%x)\n", printf("%s: complete=0x%x (pending 0x%x)\n",
ncr_sc->sc_dev.dv_xname, count, dh->dh_len); ncr_sc->sc_dev.dv_xname, count, dh->dh_len);
panic("something is wrong"); panic("something is wrong");
} }
#ifdef SBC_DEBUG
if (sbc_debug & SBC_DB_INTR)
printf("%s: drq /berr, pending=0x%x, complete=0x%x\n",
ncr_sc->sc_dev.dv_xname, dh->dh_len, count);
#endif
dh->dh_addr += count; dh->dh_addr += count;
dh->dh_len -= count; dh->dh_len -= count;
dh->dh_flags &= ~SBC_DH_XFER; if (dh->dh_len == 0)
dh->dh_flags &= ~SBC_DH_XFER;
mac68k_buserr_addr = 0; mac68k_buserr_addr = 0;
#if 0
/* Can we rely on a 5380 disconnect interrupt? */
ncr5380_intr(ncr_sc);
#endif
return; return;
} }
@ -826,7 +824,8 @@ sbc_drq_intr(p)
dh->dh_addr += (dcount - count); dh->dh_addr += (dcount - count);
dh->dh_len -= (dcount - count); dh->dh_len -= (dcount - count);
dh->dh_flags &= ~SBC_DH_XFER; if (dh->dh_len == 0)
dh->dh_flags &= ~SBC_DH_XFER;
return; return;
} }
R4; R4; R4; R4; R4; R4; R4; R4; R4; R4; R4; R4; R4; R4; R4; R4;
@ -869,11 +868,8 @@ sbc_drq_intr(p)
*/ */
nofault = (int *) 0; nofault = (int *) 0;
dh->dh_flags &= ~SBC_DH_XFER; if (dh->dh_len == 0)
dh->dh_flags &= ~SBC_DH_XFER;
#ifdef SBC_DEBUG
sc->sc_vstate = "done in xfer.";
#endif
} }
void void
@ -888,24 +884,30 @@ sbc_dma_alloc(ncr_sc)
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (sr->sr_dma_hand != NULL) if (sr->sr_dma_hand != NULL)
panic("sbc_dma_alloc: already have DMA handle"); panic("sbc_dma_alloc: already have PDMA handle");
#endif #endif
/* Polled transfers shouldn't allocate a DMA handle. */ /* Polled transfers shouldn't allocate a PDMA handle. */
if (sr->sr_flags & SR_IMMED) if (sr->sr_flags & SR_IMMED)
return; return;
/* XXX - we don't trust PDMA writes yet! */
if (xs->flags & SCSI_DATA_OUT)
return;
xlen = ncr_sc->sc_datalen; xlen = ncr_sc->sc_datalen;
/* Make sure our caller checked sc_min_dma_len. */ /* Make sure our caller checked sc_min_dma_len. */
if (xlen < MIN_DMA_LEN) if (xlen < MIN_DMA_LEN)
panic("sbc_dma_alloc: xlen=0x%x\n", xlen); panic("sbc_dma_alloc: len=0x%x\n", xlen);
/* XXX - should segment these instead */ /* XXX - should segment these instead */
if (xlen > MAX_DMA_LEN) { if (xlen > MAX_DMA_LEN) {
printf("sbc_dma_alloc: excessive xlen=0x%x\n", xlen); printf("%s: excessive dma len=0x%x\n",
ncr_sc->sc_dev.dv_xname, xlen);
#ifdef DDB #ifdef DDB
Debugger(); if (sbc_debug & SBC_DB_BREAK)
Debugger();
#endif #endif
ncr_sc->sc_datalen = xlen = MAX_DMA_LEN; ncr_sc->sc_datalen = xlen = MAX_DMA_LEN;
} }
@ -967,14 +969,6 @@ sbc_dma_poll(ncr_sc)
register int s; register int s;
register int timo; register int timo;
#if 0
/*
* If we haven't started the transfer yet, DO IT NOW!
*/
if (dh->dh_flags & SBC_DH_START)
sbc_drq_intr(ncr_sc);
#endif
timo = 50000; /* X100 = 5 sec. */ timo = 50000; /* X100 = 5 sec. */
for (;;) { for (;;) {
if ((dh->dh_flags & SBC_DH_XFER) == 0) if ((dh->dh_flags & SBC_DH_XFER) == 0)
@ -1011,22 +1005,20 @@ sbc_dma_start(ncr_sc)
struct sbc_pdma_handle *dh = sr->sr_dma_hand; struct sbc_pdma_handle *dh = sr->sr_dma_hand;
/* /*
* Match bus phase, set DMA mode, and assert data bus, * Match bus phase, set DMA mode, and assert data bus (for
* then start the transfer. * writing only), then start the transfer.
*/ */
if (dh->dh_flags & SBC_DH_OUT) { if (dh->dh_flags & SBC_DH_OUT) {
*ncr_sc->sci_tcmd = PHASE_DATA_OUT; *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
SCI_CLR_INTR(ncr_sc); SCI_CLR_INTR(ncr_sc);
*ncr_sc->sci_icmd |= SCI_ICMD_DATA;
*ncr_sc->sci_mode &= ~SCI_MODE_MONBSY; /* XXX */
*ncr_sc->sci_mode |= SCI_MODE_DMA; *ncr_sc->sci_mode |= SCI_MODE_DMA;
*ncr_sc->sci_icmd = SCI_ICMD_DATA;
*ncr_sc->sci_dma_send = 0; *ncr_sc->sci_dma_send = 0;
} else { } else {
*ncr_sc->sci_tcmd = PHASE_DATA_IN; *ncr_sc->sci_tcmd = PHASE_DATA_IN;
SCI_CLR_INTR(ncr_sc); SCI_CLR_INTR(ncr_sc);
*ncr_sc->sci_icmd = 0;
*ncr_sc->sci_mode &= ~SCI_MODE_MONBSY; /* XXX */
*ncr_sc->sci_mode |= SCI_MODE_DMA; *ncr_sc->sci_mode |= SCI_MODE_DMA;
*ncr_sc->sci_icmd = 0;
*ncr_sc->sci_irecv = 0; *ncr_sc->sci_irecv = 0;
} }
@ -1034,14 +1026,14 @@ sbc_dma_start(ncr_sc)
* Set the SBC_DH_XFER flag so that sbc_dma_poll() will wait * Set the SBC_DH_XFER flag so that sbc_dma_poll() will wait
* even if the SCSI DRQ service routine hasn't been serviced yet. * even if the SCSI DRQ service routine hasn't been serviced yet.
*/ */
dh->dh_flags |= (SBC_DH_XFER | SBC_DH_START);; dh->dh_flags |= SBC_DH_XFER;
ncr_sc->sc_state |= NCR_DOINGDMA; ncr_sc->sc_state |= NCR_DOINGDMA;
#ifdef SBC_DEBUG #ifdef SBC_DEBUG
if (sbc_debug & SBC_DB_DMA) if (sbc_debug & SBC_DB_DMA)
printf("sbc_dma_start: started, va=0x%lx, xlen=0x%x\n", printf("%s: PDMA started, va=%p, len=0x%x\n",
(long)dh->dh_addr, dh->dh_len); ncr_sc->sc_dev.dv_xname, dh->dh_addr, dh->dh_len);
#endif #endif
} }
@ -1063,7 +1055,9 @@ sbc_dma_stop(ncr_sc)
if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) { if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
#ifdef SBC_DEBUG #ifdef SBC_DEBUG
printf("sbc_dma_stop: DMA not running\n"); if (sbc_debug & SBC_DB_DMA)
printf("%s: dma_stop: DMA not running\n",
ncr_sc->sc_dev.dv_xname);
#endif #endif
return; return;
} }
@ -1074,7 +1068,8 @@ sbc_dma_stop(ncr_sc)
#ifdef SBC_DEBUG #ifdef SBC_DEBUG
if (sbc_debug & SBC_DB_DMA) if (sbc_debug & SBC_DB_DMA)
printf("sbc_dma_stop: ntrans=0x%x\n", ntrans); printf("%s: dma_stop: ntrans=0x%x\n",
ncr_sc->sc_dev.dv_xname, ntrans);
#endif #endif
if (ntrans > ncr_sc->sc_datalen) if (ntrans > ncr_sc->sc_datalen)
@ -1092,7 +1087,10 @@ sbc_dma_stop(ncr_sc)
*ncr_sc->sci_mode &= ~SCI_MODE_DMA; *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
*ncr_sc->sci_icmd = 0; *ncr_sc->sci_icmd = 0;
printf("%s: exit dma_stop, csr=0x%x, bus_csr=0x%x\n", #ifdef SBC_DEBUG
ncr_sc->sc_dev.dv_xname, *ncr_sc->sci_csr, if (sbc_debug & SBC_DB_DMA)
*ncr_sc->sci_bus_csr); printf("%s: exit dma_stop, csr=0x%x, bus_csr=0x%x\n",
ncr_sc->sc_dev.dv_xname, *ncr_sc->sci_csr,
*ncr_sc->sci_bus_csr);
#endif
} }