diff options
author | luigi <luigi@FreeBSD.org> | 2002-04-16 22:03:14 +0000 |
---|---|---|
committer | luigi <luigi@FreeBSD.org> | 2002-04-16 22:03:14 +0000 |
commit | 73a7e12af14a421104c3c5a8e10b94d1b14f8595 (patch) | |
tree | 2af4535149502f6b1f2ef2c60315c198d9f68be1 | |
parent | 4d82810dc3a5a742ebe17d8d5428fc2608f711d1 (diff) | |
download | FreeBSD-src-73a7e12af14a421104c3c5a8e10b94d1b14f8595.zip FreeBSD-src-73a7e12af14a421104c3c5a8e10b94d1b14f8595.tar.gz |
Add DEVICE_POLLING support to the "rl" driver.
The diffs are very similar to the ones for the "sis" driver.
MFC After: 5 days
-rw-r--r-- | sys/pci/if_rl.c | 76 | ||||
-rw-r--r-- | sys/pci/if_rlreg.h | 3 |
2 files changed, 73 insertions, 6 deletions
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c index 198f802..2b69302 100644 --- a/sys/pci/if_rl.c +++ b/sys/pci/if_rl.c @@ -1183,6 +1183,13 @@ static void rl_rxeof(sc) max_bytes = limit - cur_rx; while((CSR_READ_1(sc, RL_COMMAND) & RL_CMD_EMPTY_RXBUF) == 0) { +#ifdef DEVICE_POLLING + if (ifp->if_ipending & IFF_POLLING) { + if (sc->rxcycles <= 0) + break; + sc->rxcycles--; + } +#endif /* DEVICE_POLLING */ rxbufpos = sc->rl_cdata.rl_rx_buf + cur_rx; rxstat = *(u_int32_t *)rxbufpos; @@ -1348,6 +1355,45 @@ static void rl_tick(xsc) return; } +#ifdef DEVICE_POLLING +static void +rl_poll (struct ifnet *ifp, enum poll_cmd cmd, int count) +{ + struct rl_softc *sc = ifp->if_softc; + + RL_LOCK(sc); + if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ + CSR_WRITE_2(sc, RL_IMR, RL_INTRS); + goto done; + } + + sc->rxcycles = count; + rl_rxeof(sc); + rl_txeof(sc); + if (ifp->if_snd.ifq_head != NULL) + rl_start(ifp); + + if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */ + u_int16_t status; + + status = CSR_READ_2(sc, RL_ISR); + if (status) + CSR_WRITE_2(sc, RL_ISR, status); + + /* + * XXX check behaviour on receiver stalls. + */ + + if (status & RL_ISR_SYSTEM_ERR) { + rl_reset(sc); + rl_init(sc); + } + } +done: + RL_UNLOCK(sc); +} +#endif /* DEVICE_POLLING */ + static void rl_intr(arg) void *arg; { @@ -1364,8 +1410,15 @@ static void rl_intr(arg) RL_LOCK(sc); ifp = &sc->arpcom.ac_if; - /* Disable interrupts. */ - CSR_WRITE_2(sc, RL_IMR, 0x0000); +#ifdef DEVICE_POLLING + if (ifp->if_ipending & IFF_POLLING) + goto done; + if (ether_poll_register(rl_poll, ifp)) { /* ok, disable interrupts */ + CSR_WRITE_2(sc, RL_IMR, 0x0000); + rl_poll(ifp, 0, 1); + goto done; + } +#endif /* DEVICE_POLLING */ for (;;) { @@ -1392,12 +1445,12 @@ static void rl_intr(arg) } - /* Re-enable interrupts. */ - CSR_WRITE_2(sc, RL_IMR, RL_INTRS); - if (ifp->if_snd.ifq_head != NULL) rl_start(ifp); +#ifdef DEVICE_POLLING +done: +#endif RL_UNLOCK(sc); return; @@ -1589,6 +1642,14 @@ static void rl_init(xsc) */ rl_setmulti(sc); +#ifdef DEVICE_POLLING + /* + * Disable interrupts if we are polling. + */ + if (ifp->if_ipending & IFF_POLLING) + CSR_WRITE_2(sc, RL_IMR, 0); + else /* otherwise ... */ +#endif /* DEVICE_POLLING */ /* * Enable interrupts. */ @@ -1732,6 +1793,10 @@ static void rl_stop(sc) ifp->if_timer = 0; untimeout(rl_tick, sc, sc->rl_stat_ch); + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); +#ifdef DEVICE_POLLING + ether_poll_deregister(ifp); +#endif /* DEVICE_POLLING */ CSR_WRITE_1(sc, RL_COMMAND, 0x00); CSR_WRITE_2(sc, RL_IMR, 0x0000); @@ -1752,7 +1817,6 @@ static void rl_stop(sc) } } - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); RL_UNLOCK(sc); return; } diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h index 2e4086c..8f7b544 100644 --- a/sys/pci/if_rlreg.h +++ b/sys/pci/if_rlreg.h @@ -378,6 +378,9 @@ struct rl_softc { struct callout_handle rl_stat_ch; struct mtx rl_mtx; int suspended; /* 0 = normal 1 = suspended */ +#ifdef DEVICE_POLLING + int rxcycles; +#endif u_int32_t saved_maps[5]; /* pci data */ u_int32_t saved_biosaddr; |