Index: sys/pci/if_xl.c =================================================================== RCS file: /home/ncvs/src/sys/pci/if_xl.c,v retrieving revision 1.105 diff -u -r1.105 if_xl.c --- sys/pci/if_xl.c 2002/08/24 00:02:03 1.105 +++ sys/pci/if_xl.c 2002/08/31 04:45:17 @@ -1857,12 +1857,12 @@ xl_rxeof(sc) struct xl_softc *sc; { - struct ether_header *eh; - struct mbuf *m; - struct ifnet *ifp; + struct ether_header *eh; + struct mbuf *m; + struct ifnet *ifp; struct xl_chain_onefrag *cur_rx; - int total_len = 0; - u_int32_t rxstat; + int total_len = 0; + u_int32_t rxstat; ifp = &sc->arpcom.ac_if; @@ -1897,10 +1897,20 @@ continue; } +#ifdef DEVICE_POLLING + if (ifp->if_flags & IFF_POLLING) { + if (sc->rxcycles <= 0) + break; + sc->rxcycles--; + } +#endif /* DEVICE_POLLING */ + /* No errors; receive the packet. */ m = cur_rx->xl_mbuf; total_len = cur_rx->xl_ptr->xl_status & XL_RXSTAT_LENMASK; + + /* * Try to conjure up a new mbuf cluster. If that * fails, it means we have an out of memory condition and @@ -2058,6 +2068,92 @@ return; } +#ifdef DEVICE_POLLING +static poll_handler_t xl_poll; + +static void +xl_poll (struct ifnet *ifp, enum poll_cmd cmd, int count) +{ + struct xl_softc *sc = ifp->if_softc; + u_int16_t status; + int curpkts; + + XL_LOCK(sc); + + if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB|XL_INTRS); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS); +#if 0 + if (sc->xl_flags & XL_FLAG_FUNCREG) + bus_space_write_4(sc->xl_ftag, sc->xl_fhandle, 4, 0x8000); +#endif + goto done; + } + + sc->rxcycles = count; + xl_rxeof(sc); + xl_txeof(sc); + + if (ifp->if_snd.ifq_head != NULL) + (*ifp->if_start)(ifp); + + /* + * Check the Interrupt Status Register (ISR) + */ + if (cmd = POLL_AND_CHECK_STATUS) { /* also check status register */ + while ((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS && \ + status != 0xFFF && cmd == POLL_AND_CHECK_STATUS) { + + CSR_WRITE_2(sc, XL_COMMAND, + XL_CMD_INTR_ACK|(status & XL_INTRS)); + + /* Packet upload complete */ + if (status & XL_STAT_UP_COMPLETE) { + int curpkts; + curpkts = ifp->if_ipackets; + xl_rxeof(sc); + if (curpkts == ifp->if_ipackets) { + while (xl_rx_resync(sc)) + xl_rxeof(sc); + } + } + + /* Packet download complete */ + if (status & XL_STAT_DOWN_COMPLETE) { + if (sc->xl_type == XL_TYPE_905B) + xl_txeof_90xB(sc); + else + xl_txeof(sc); + } + + /* Transmit (TX) complete */ + if (status & XL_STAT_TX_COMPLETE) { + ifp->if_oerrors++; + xl_txeoc(sc); + } + + /* System failure */ + if (status & XL_STAT_ADFAIL) { + xl_reset(sc); + xl_init(sc); + } + + /* Status register overflow */ + if (status & XL_STAT_STATSOFLOW) { + sc->xl_stats_no_timeout = 1; + xl_stats_update(sc); + sc->xl_stats_no_timeout = 0; + } + } +#ifdef DEVICE_POLLING +done: +#endif /* DEVICE_POLLING */ + XL_UNLOCK(sc); + return; +} +#endif /* DEVICE_POLLING */ + /* * TX 'end of channel' interrupt handler. Actually, we should * only get a 'TX complete' interrupt if there's a transmit error, @@ -2140,8 +2236,15 @@ while((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS && status != 0xFFFF) { - CSR_WRITE_2(sc, XL_COMMAND, - XL_CMD_INTR_ACK|(status & XL_INTRS)); +#ifdef DEVICE_POLLING + if (ifp->if_ipending & IFF_POLLING) + goto done; + if (ether_poll_register(xl_poll, ifp)) { /* disable interrupts */ + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0); + xl_poll(ifp, 0, 1); + goto done; + } +#endif /* DEVICE_POLLING */ if (status & XL_STAT_UP_COMPLETE) { int curpkts; @@ -2181,8 +2284,10 @@ if (ifp->if_snd.ifq_head != NULL) (*ifp->if_start)(ifp); +#ifdef DEVICE_POLLING +done: +#endif XL_UNLOCK(sc); - return; } @@ -2746,7 +2851,15 @@ CSR_WRITE_2(sc, XL_W4_NET_DIAG, XL_NETDIAG_UPPER_BYTES_ENABLE); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_ENABLE); +#ifdef DEVICE_POLLING /* + * Disable interrupts if we are polling. + */ + if (ifp->if_ipending & IFF_POLLING) + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0); + else +#endif /* DEVICE_POLLING */ + /* * Enable interrupts. */ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF); @@ -3063,7 +3176,10 @@ sizeof(sc->xl_ldata->xl_tx_list)); ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - +#ifdef DEVICE_POLLING + ether_poll_deregister(ifp); +#endif /* DEVICE_POLLING */ + XL_UNLOCK(sc); return; Index: sys/pci/if_xlreg.h =================================================================== RCS file: /home/ncvs/src/sys/pci/if_xlreg.h,v retrieving revision 1.36 diff -u -r1.36 if_xlreg.h --- sys/pci/if_xlreg.h 2001/12/17 22:24:19 1.36 +++ sys/pci/if_xlreg.h 2002/08/31 04:45:17 @@ -586,6 +586,9 @@ struct resource *xl_fres; bus_space_handle_t xl_fhandle; bus_space_tag_t xl_ftag; +#ifdef DEVICE_POLLING + int rxcycles; +#endif struct mtx xl_mtx; };