diff options
author | simokawa <simokawa@FreeBSD.org> | 2002-11-06 15:50:32 +0000 |
---|---|---|
committer | simokawa <simokawa@FreeBSD.org> | 2002-11-06 15:50:32 +0000 |
commit | 131fe3293a00e11ceabd9867d8d9c613939fc186 (patch) | |
tree | f4d802d21c7b52af2066666d90ddf0b4a1e1a2ac | |
parent | e6dea8f6330af598cd10c616e7e30614449c8d75 (diff) | |
download | FreeBSD-src-131fe3293a00e11ceabd9867d8d9c613939fc186.zip FreeBSD-src-131fe3293a00e11ceabd9867d8d9c613939fc186.tar.gz |
Add support for DEVICE_POLLING.
PR: kern/44772
Submitted by: Takashi Oono <takashi@yha.att.ne.jp>
MFC after: 1 week
-rw-r--r-- | sys/dev/nge/if_nge.c | 76 | ||||
-rw-r--r-- | sys/dev/nge/if_ngereg.h | 3 |
2 files changed, 79 insertions, 0 deletions
diff --git a/sys/dev/nge/if_nge.c b/sys/dev/nge/if_nge.c index a99aea5..98f43f3 100644 --- a/sys/dev/nge/if_nge.c +++ b/sys/dev/nge/if_nge.c @@ -1340,6 +1340,14 @@ nge_rxeof(sc) struct mbuf *m0 = NULL; u_int32_t extsts; +#ifdef DEVICE_POLLING + if (ifp->if_ipending & IFF_POLLING) { + if (sc->rxcycles <= 0) + break; + sc->rxcycles--; + } +#endif /* DEVICE_POLLING */ + cur_rx = &sc->nge_ldata->nge_rx_list[i]; rxstat = cur_rx->nge_rxstat; extsts = cur_rx->nge_extsts; @@ -1545,6 +1553,52 @@ nge_tick(xsc) return; } +#ifdef DEVICE_POLLING +static poll_handler_t nge_poll; + +static void +nge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) +{ + struct nge_softc *sc = ifp->if_softc; + + if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ + CSR_WRITE_4(sc, NGE_IER, 1); + return; + } + + /* + * On the nge, reading the status register also clears it. + * So before returning to intr mode we must make sure that all + * possible pending sources of interrupts have been served. + * In practice this means run to completion the *eof routines, + * and then call the interrupt routine + */ + sc->rxcycles = count; + nge_rxeof(sc); + nge_txeof(sc); + if (ifp->if_snd.ifq_head != NULL) + nge_start(ifp); + + if (sc->rxcycles > 0 || cmd == POLL_AND_CHECK_STATUS) { + u_int32_t status; + + /* Reading the ISR register clears all interrupts. */ + status = CSR_READ_4(sc, NGE_ISR); + + if (status & (NGE_ISR_RX_ERR|NGE_ISR_RX_OFLOW)) + nge_rxeof(sc); + + if (status & (NGE_ISR_RX_IDLE)) + NGE_SETBIT(sc, NGE_CSR, NGE_CSR_RX_ENABLE); + + if (status & NGE_ISR_SYSERR) { + nge_reset(sc); + nge_init(sc); + } + } +} +#endif /* DEVICE_POLLING */ + static void nge_intr(arg) void *arg; @@ -1556,6 +1610,16 @@ nge_intr(arg) sc = arg; ifp = &sc->arpcom.ac_if; +#ifdef DEVICE_POLLING + if (ifp->if_ipending & IFF_POLLING) + return; + if (ether_poll_register(nge_poll, ifp)) { /* ok, disable interrupts */ + CSR_WRITE_4(sc, NGE_IER, 0); + nge_poll(ifp, 0, 1); + return; + } +#endif /* DEVICE_POLLING */ + /* Supress unwanted interrupts */ if (!(ifp->if_flags & IFF_UP)) { nge_stop(sc); @@ -1927,6 +1991,15 @@ nge_init(xsc) * Enable interrupts. */ CSR_WRITE_4(sc, NGE_IMR, NGE_INTRS); +#ifdef DEVICE_POLLING + /* + * ... only enable interrupts if we are not polling, make sure + * they are off otherwise. + */ + if (ifp->if_ipending & IFF_POLLING) + CSR_WRITE_4(sc, NGE_IER, 0); + else +#endif /* DEVICE_POLLING */ CSR_WRITE_4(sc, NGE_IER, 1); /* Enable receiver and transmitter. */ @@ -2183,6 +2256,9 @@ nge_stop(sc) } untimeout(nge_tick, sc, sc->nge_stat_ch); +#ifdef DEVICE_POLLING + ether_poll_deregister(ifp); +#endif CSR_WRITE_4(sc, NGE_IER, 0); CSR_WRITE_4(sc, NGE_IMR, 0); NGE_SETBIT(sc, NGE_CSR, NGE_CSR_TX_DISABLE|NGE_CSR_RX_DISABLE); diff --git a/sys/dev/nge/if_ngereg.h b/sys/dev/nge/if_ngereg.h index 13baa7b..27ea49a 100644 --- a/sys/dev/nge/if_ngereg.h +++ b/sys/dev/nge/if_ngereg.h @@ -659,6 +659,9 @@ struct nge_softc { struct mtx nge_mtx; u_int8_t nge_tbi; struct ifmedia nge_ifmedia; +#ifdef DEVICE_POLLING + int rxcycles; +#endif }; /* |