summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2002-04-16 22:03:14 +0000
committerluigi <luigi@FreeBSD.org>2002-04-16 22:03:14 +0000
commit73a7e12af14a421104c3c5a8e10b94d1b14f8595 (patch)
tree2af4535149502f6b1f2ef2c60315c198d9f68be1 /sys/pci
parent4d82810dc3a5a742ebe17d8d5428fc2608f711d1 (diff)
downloadFreeBSD-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
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/if_rl.c76
-rw-r--r--sys/pci/if_rlreg.h3
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;
OpenPOWER on IntegriCloud