From 6ab8768830549559d533989b7dc9bbd4df0b1f52 Mon Sep 17 00:00:00 2001 From: marius Date: Mon, 13 Feb 2006 11:30:40 +0000 Subject: [PATCH] MFC: sys/dev/le/am7990.c 1.1, sys/dev/le/am79900.c 1.1, sys/dev/le/am79900reg.h 1.1, sys/dev/le/am79900var.h 1.1, sys/dev/le/am7990reg.h 1.1, sys/dev/le/am7990var.h 1.1, sys/dev/le/if_le_ledma.c 1.1, sys/dev/le/if_le_pci.c 1.1, sys/dev/le/lance.c 1.1, sys/dev/le/lancereg.h 1.1, sys/dev/le/lancevar.h 1.1 Add le(4), a driver for AMD Am7900 LANCE and Am79C9xx PCnet NICs, ported from NetBSD. This version differs from HEAD in that if_le_ledma.c inlines lsi64854_enet_intr() from rev. 1.8 of sys/sparc64/sbus/lsi64854.c in le_dma_hwintr() in order to not break the API of the LSI64854 driver in RELENG_6. Approved by: re (scottl) --- sys/dev/le/if_le_ledma.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/sys/dev/le/if_le_ledma.c b/sys/dev/le/if_le_ledma.c index ccc95c0f4086..4d2ae48c18fc 100644 --- a/sys/dev/le/if_le_ledma.c +++ b/sys/dev/le/if_le_ledma.c @@ -91,6 +91,7 @@ struct le_dma_softc { bus_addr_t sc_laddr; /* LANCE DMA address */ struct lsi64854_softc *sc_dma; /* pointer to DMA engine */ + int sc_dodrain; }; static device_probe_t le_dma_probe; @@ -258,7 +259,46 @@ le_dma_hwintr(struct lance_softc *sc) struct le_dma_softc *lesc = (struct le_dma_softc *)sc; struct lsi64854_softc *dma = lesc->sc_dma; +#if 0 return (DMA_INTR(dma)); +#else + /* + * Inlined version of lsi64854_enet_intr() from rev. 1.8 of + * sys/sparc64/sbus/lsi64854.c in order to not break the API + * of the LSI64854 driver in RELENG_6. + */ + uint32_t csr; + int i, rv; + + csr = L64854_GCSR(dma); + + /* If the DMA logic shows an interrupt, claim it */ + rv = ((csr & E_INT_PEND) != 0) ? 1 : 0; + + if (csr & (E_ERR_PEND|E_SLAVE_ERR)) { + device_printf(dma->sc_dev, "error: csr=%b\n", csr, + EDMACSR_BITS); + csr &= ~L64854_EN_DMA; /* Stop DMA */ + /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */ + csr |= E_INVALIDATE|E_SLAVE_ERR; + L64854_SCSR(dma, csr); + /* Will be drained with the LE_C0_IDON interrupt. */ + lesc->sc_dodrain = 1; + return (-1); + } + + /* XXX - is this necessary with E_DSBL_WR_INVAL on? */ + if (lesc->sc_dodrain) { + i = 10; + csr |= E_DRAIN; + L64854_SCSR(dma, csr); + while (i-- > 0 && (L64854_GCSR(dma) & E_DRAINING)) + DELAY(1); + lesc->sc_dodrain = 0; + } + + return (rv); +#endif } static void