aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorLuigi Rizzo <luigi@FreeBSD.org>2001-12-14 17:56:12 +0000
committerLuigi Rizzo <luigi@FreeBSD.org>2001-12-14 17:56:12 +0000
commite4fc250c15768b8e203496ee908dedb37846ea4f (patch)
tree4ea0e407bb3cf5815d6067507d1fdc39f76f58e6 /sys/dev
parent99adc698c1889950d1ff2b747f52de00fd69a8b1 (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/dc/if_dc.c83
-rw-r--r--sys/dev/dc/if_dcreg.h7
-rw-r--r--sys/dev/fxp/if_fxp.c61
-rw-r--r--sys/dev/fxp/if_fxpvar.h4
4 files changed, 153 insertions, 2 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index 139983bb089a..caee9d0d44cf 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -2473,6 +2473,13 @@ static void dc_rxeof(sc)
while(!(sc->dc_ldata->dc_rx_list[i].dc_status & DC_RXSTAT_OWN)) {
+#ifdef DEVICE_POLLING
+ if (ifp->if_ipending & IFF_POLLING) {
+ if (sc->rxcycles <= 0)
+ break;
+ sc->rxcycles--;
+ }
+#endif /* DEVICE_POLLING */
cur_rx = &sc->dc_ldata->dc_rx_list[i];
rxstat = cur_rx->dc_status;
m = sc->dc_cdata.dc_rx_chain[i];
@@ -2786,6 +2793,60 @@ static void dc_tx_underrun(sc)
return;
}
+#ifdef DEVICE_POLLING
+static poll_handler_t dc_poll;
+
+static void
+dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+ struct dc_softc *sc = ifp->if_softc;
+
+ if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
+ /* Re-enable interrupts. */
+ CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
+ return;
+ }
+ sc->rxcycles = count;
+ dc_rxeof(sc);
+ dc_txeof(sc);
+ if (ifp->if_snd.ifq_head != NULL && !(ifp->if_flags & IFF_OACTIVE))
+ dc_start(ifp);
+
+ if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
+ u_int32_t status;
+
+ status = CSR_READ_4(sc, DC_ISR);
+ status &= (DC_ISR_RX_WATDOGTIMEO|DC_ISR_RX_NOBUF|
+ DC_ISR_TX_NOBUF|DC_ISR_TX_IDLE|DC_ISR_TX_UNDERRUN|
+ DC_ISR_BUS_ERR);
+ if (!status)
+ return ;
+ /* ack what we have */
+ CSR_WRITE_4(sc, DC_ISR, status);
+
+ if (status & (DC_ISR_RX_WATDOGTIMEO|DC_ISR_RX_NOBUF) ) {
+ u_int32_t r = CSR_READ_4(sc, DC_FRAMESDISCARDED);
+ ifp->if_ierrors += (r & 0xffff) + ((r >> 17) & 0x7ff);
+
+ if (dc_rx_resync(sc))
+ dc_rxeof(sc);
+ }
+ /* restart transmit unit if necessary */
+ if (status & DC_ISR_TX_IDLE && sc->dc_cdata.dc_tx_cnt)
+ CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
+
+ if (status & DC_ISR_TX_UNDERRUN)
+ dc_tx_underrun(sc);
+
+ if (status & DC_ISR_BUS_ERR) {
+ printf("dc_poll: dc%d bus error\n", sc->dc_unit);
+ dc_reset(sc);
+ dc_init(sc);
+ }
+ }
+}
+#endif /* DEVICE_POLLING */
+
static void dc_intr(arg)
void *arg;
{
@@ -2800,6 +2861,14 @@ static void dc_intr(arg)
DC_LOCK(sc);
ifp = &sc->arpcom.ac_if;
+#ifdef DEVICE_POLLING
+ if (ifp->if_ipending & IFF_POLLING)
+ goto done;
+ if (ether_poll_register(dc_poll, ifp)) { /* ok, disable interrupts */
+ CSR_WRITE_4(sc, DC_IMR, 0x00000000);
+ goto done;
+ }
+#endif /* DEVICE_POLLING */
/* Suppress unwanted interrupts */
if (!(ifp->if_flags & IFF_UP)) {
@@ -2864,6 +2933,7 @@ static void dc_intr(arg)
if (ifp->if_snd.ifq_head != NULL)
dc_start(ifp);
+done:
DC_UNLOCK(sc);
return;
@@ -3163,6 +3233,16 @@ static void dc_init(xsc)
/*
* Enable interrupts.
*/
+#ifdef DEVICE_POLLING
+ /*
+ * ... but only if we are not polling, and make sure they are off in
+ * the case of polling. Some cards (e.g. fxp) turn interrupts on
+ * after a reset.
+ */
+ if (ifp->if_ipending & IFF_POLLING)
+ CSR_WRITE_4(sc, DC_IMR, 0x00000000);
+ else
+#endif
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
CSR_WRITE_4(sc, DC_ISR, 0xFFFFFFFF);
@@ -3378,6 +3458,9 @@ static void dc_stop(sc)
callout_stop(&sc->dc_stat_ch);
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+#ifdef DEVICE_POLLING
+ ether_poll_deregister(ifp);
+#endif
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON|DC_NETCFG_TX_ON));
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
diff --git a/sys/dev/dc/if_dcreg.h b/sys/dev/dc/if_dcreg.h
index 0052d33d9220..8980e4433d18 100644
--- a/sys/dev/dc/if_dcreg.h
+++ b/sys/dev/dc/if_dcreg.h
@@ -453,7 +453,11 @@ struct dc_desc {
#define DC_FILTER_HASHONLY 0x10400000
#define DC_MAXFRAGS 16
+#ifdef DEVICE_POLLING
+#define DC_RX_LIST_CNT 192
+#else
#define DC_RX_LIST_CNT 64
+#endif
#define DC_TX_LIST_CNT 256
#define DC_MIN_FRAMELEN 60
#define DC_RXLEN 1536
@@ -717,6 +721,9 @@ struct dc_softc {
int dc_srm_media;
#endif
struct mtx dc_mtx;
+#ifdef DEVICE_POLLING
+ int rxcycles; /* ... when polling */
+#endif
};
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index 840ed8701eb1..27b78432b391 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -1141,6 +1141,38 @@ tbdinit:
}
}
+static void fxp_intr_body(struct fxp_softc *sc, u_int8_t statack, int count);
+
+#ifdef DEVICE_POLLING
+static poll_handler_t fxp_poll;
+
+static void
+fxp_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+ struct fxp_softc *sc = ifp->if_softc;
+ u_int8_t statack ;
+
+ if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
+ CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, 0);
+ return;
+ }
+ statack = FXP_SCB_STATACK_CXTNO | FXP_SCB_STATACK_CNA |
+ FXP_SCB_STATACK_FR ;
+ if (cmd == POLL_AND_CHECK_STATUS) {
+ u_int8_t tmp ;
+ tmp = CSR_READ_1(sc, FXP_CSR_SCB_STATACK);
+ if (tmp == 0xff || tmp == 0)
+ return ; /* nothing to do */
+ tmp &= ~statack ;
+ /* ack what we can */
+ if (tmp != 0)
+ CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, tmp);
+ statack |= tmp ;
+ }
+ fxp_intr_body(sc, statack, count);
+}
+#endif /* DEVICE_POLLING */
+
/*
* Process interface interrupts.
*/
@@ -1148,9 +1180,21 @@ static void
fxp_intr(void *xsc)
{
struct fxp_softc *sc = xsc;
- struct ifnet *ifp = &sc->sc_if;
u_int8_t statack;
+#ifdef DEVICE_POLLING
+ struct ifnet *ifp = &sc->sc_if;
+
+ if (ifp->if_ipending & IFF_POLLING)
+ return ;
+ if (ether_poll_register(fxp_poll, ifp)) {
+ /* disable interrupts */
+ CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE);
+ fxp_poll(ifp, 0, 1);
+ return ;
+ }
+#endif
+
if (sc->suspended) {
return;
}
@@ -1169,6 +1213,14 @@ fxp_intr(void *xsc)
* First ACK all the interrupts in this pass.
*/
CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, statack);
+ fxp_intr_body(sc, statack, -1);
+ }
+}
+
+static void
+fxp_intr_body(struct fxp_softc *sc, u_int8_t statack, int count)
+{
+ struct ifnet *ifp = &sc->sc_if;
/*
* Free any finished transmit mbuf chains.
@@ -1220,6 +1272,9 @@ rcvloop:
rfa = (struct fxp_rfa *)(m->m_ext.ext_buf +
RFA_ALIGNMENT_FUDGE);
+#ifdef DEVICE_POLLING /* loop at most count times if count >=0 */
+ if (count < 0 || count-- > 0)
+#endif
if (rfa->rfa_status & FXP_RFA_STATUS_C) {
/*
* Remove first packet from the chain.
@@ -1276,7 +1331,6 @@ rcvloop:
fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START);
}
}
- }
}
/*
@@ -1404,6 +1458,9 @@ fxp_stop(struct fxp_softc *sc)
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
ifp->if_timer = 0;
+#ifdef DEVICE_POLLING
+ ether_poll_deregister(ifp);
+#endif
/*
* Cancel stats updater.
*/
diff --git a/sys/dev/fxp/if_fxpvar.h b/sys/dev/fxp/if_fxpvar.h
index 23fdaa43ded3..b2ae9b26bfaf 100644
--- a/sys/dev/fxp/if_fxpvar.h
+++ b/sys/dev/fxp/if_fxpvar.h
@@ -57,7 +57,11 @@
* Number of receive frame area buffers. These are large so chose
* wisely.
*/
+#ifdef DEVICE_POLLING
+#define FXP_NRFABUFS 192
+#else
#define FXP_NRFABUFS 64
+#endif
/*
* Maximum number of seconds that the receiver can be idle before we