- 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:
parent
74affdc8f8
commit
2e936aa8ff
|
@ -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;
|
||||||
|
if (dh->dh_len == 0)
|
||||||
dh->dh_flags &= ~SBC_DH_XFER;
|
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,6 +824,7 @@ sbc_drq_intr(p)
|
||||||
|
|
||||||
dh->dh_addr += (dcount - count);
|
dh->dh_addr += (dcount - count);
|
||||||
dh->dh_len -= (dcount - count);
|
dh->dh_len -= (dcount - count);
|
||||||
|
if (dh->dh_len == 0)
|
||||||
dh->dh_flags &= ~SBC_DH_XFER;
|
dh->dh_flags &= ~SBC_DH_XFER;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -869,11 +868,8 @@ sbc_drq_intr(p)
|
||||||
*/
|
*/
|
||||||
nofault = (int *) 0;
|
nofault = (int *) 0;
|
||||||
|
|
||||||
|
if (dh->dh_len == 0)
|
||||||
dh->dh_flags &= ~SBC_DH_XFER;
|
dh->dh_flags &= ~SBC_DH_XFER;
|
||||||
|
|
||||||
#ifdef SBC_DEBUG
|
|
||||||
sc->sc_vstate = "done in xfer.";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -888,23 +884,29 @@ 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
|
||||||
|
if (sbc_debug & SBC_DB_BREAK)
|
||||||
Debugger();
|
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;
|
||||||
|
|
||||||
|
#ifdef SBC_DEBUG
|
||||||
|
if (sbc_debug & SBC_DB_DMA)
|
||||||
printf("%s: exit dma_stop, csr=0x%x, bus_csr=0x%x\n",
|
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->sc_dev.dv_xname, *ncr_sc->sci_csr,
|
||||||
*ncr_sc->sci_bus_csr);
|
*ncr_sc->sci_bus_csr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue