diff options
| author | Luigi Rizzo <luigi@FreeBSD.org> | 2001-12-14 17:56:12 +0000 |
|---|---|---|
| committer | Luigi Rizzo <luigi@FreeBSD.org> | 2001-12-14 17:56:12 +0000 |
| commit | e4fc250c15768b8e203496ee908dedb37846ea4f (patch) | |
| tree | 4ea0e407bb3cf5815d6067507d1fdc39f76f58e6 /sys/dev | |
| parent | 99adc698c1889950d1ff2b747f52de00fd69a8b1 (diff) | |
Notes
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/dc/if_dc.c | 83 | ||||
| -rw-r--r-- | sys/dev/dc/if_dcreg.h | 7 | ||||
| -rw-r--r-- | sys/dev/fxp/if_fxp.c | 61 | ||||
| -rw-r--r-- | sys/dev/fxp/if_fxpvar.h | 4 |
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 |
