void smsc_init(void *xsc) { struct smsc_softc *sc = xsc; struct ifnet *ifp = &sc->sc_ac.ac_if; struct smsc_chain *c; usbd_status err; int s, i; s = splnet(); /* Cancel pending I/O */ smsc_stop(sc); /* Reset the ethernet interface. */ smsc_reset(sc); /* Init RX ring. */ if (smsc_rx_list_init(sc) == ENOBUFS) { printf("%s: rx list init failed\n", sc->sc_dev.dv_xname); splx(s); return; } /* Init TX ring. */ if (smsc_tx_list_init(sc) == ENOBUFS) { printf("%s: tx list init failed\n", sc->sc_dev.dv_xname); splx(s); return; } /* Program promiscuous mode and multicast filters. */ smsc_iff(sc); /* Open RX and TX pipes. */ err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_RX], USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_RX]); if (err) { printf("%s: open rx pipe failed: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); splx(s); return; } err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_TX], USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_TX]); if (err) { printf("%s: open tx pipe failed: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); splx(s); return; } /* Start up the receive pipe. */ for (i = 0; i < SMSC_RX_LIST_CNT; i++) { c = &sc->sc_cdata.rx_chain[i]; usbd_setup_xfer(c->sc_xfer, sc->sc_ep[SMSC_ENDPT_RX], c, c->sc_buf, sc->sc_bufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, smsc_rxeof); usbd_transfer(c->sc_xfer); } /* TCP/UDP checksum offload engines. */ smsc_sethwcsum(sc); /* Indicate we are up and running. */ ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; timeout_add_sec(&sc->sc_stat_ch, 1); splx(s); }
void smsc_stop(struct smsc_softc *sc) { usbd_status err; struct ifnet *ifp; int i; smsc_reset(sc); ifp = &sc->sc_ac.ac_if; ifp->if_timer = 0; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); timeout_del(&sc->sc_stat_ch); /* Stop transfers. */ if (sc->sc_ep[SMSC_ENDPT_RX] != NULL) { usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_RX]); err = usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_RX]); if (err) { printf("%s: close rx pipe failed: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); } sc->sc_ep[SMSC_ENDPT_RX] = NULL; } if (sc->sc_ep[SMSC_ENDPT_TX] != NULL) { usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_TX]); err = usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_TX]); if (err) { printf("%s: close tx pipe failed: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); } sc->sc_ep[SMSC_ENDPT_TX] = NULL; } if (sc->sc_ep[SMSC_ENDPT_INTR] != NULL) { usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_INTR]); err = usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_INTR]); if (err) { printf("%s: close intr pipe failed: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); } sc->sc_ep[SMSC_ENDPT_INTR] = NULL; } /* Free RX resources. */ for (i = 0; i < SMSC_RX_LIST_CNT; i++) { if (sc->sc_cdata.rx_chain[i].sc_mbuf != NULL) { m_freem(sc->sc_cdata.rx_chain[i].sc_mbuf); sc->sc_cdata.rx_chain[i].sc_mbuf = NULL; } if (sc->sc_cdata.rx_chain[i].sc_xfer != NULL) { usbd_free_xfer(sc->sc_cdata.rx_chain[i].sc_xfer); sc->sc_cdata.rx_chain[i].sc_xfer = NULL; } } /* Free TX resources. */ for (i = 0; i < SMSC_TX_LIST_CNT; i++) { if (sc->sc_cdata.tx_chain[i].sc_mbuf != NULL) { m_freem(sc->sc_cdata.tx_chain[i].sc_mbuf); sc->sc_cdata.tx_chain[i].sc_mbuf = NULL; } if (sc->sc_cdata.tx_chain[i].sc_xfer != NULL) { usbd_free_xfer(sc->sc_cdata.tx_chain[i].sc_xfer); sc->sc_cdata.tx_chain[i].sc_xfer = NULL; } } }
int smsc_init(struct ifnet *ifp) { struct smsc_softc *sc = ifp->if_softc; struct smsc_chain *c; usbd_status err; int s, i; if (sc->sc_dying) return EIO; s = splnet(); /* Cancel pending I/O */ if (ifp->if_flags & IFF_RUNNING) smsc_stop(ifp, 1); /* Reset the ethernet interface. */ smsc_reset(sc); /* Init RX ring. */ if (smsc_rx_list_init(sc) == ENOBUFS) { aprint_error_dev(sc->sc_dev, "rx list init failed\n"); splx(s); return EIO; } /* Init TX ring. */ if (smsc_tx_list_init(sc) == ENOBUFS) { aprint_error_dev(sc->sc_dev, "tx list init failed\n"); splx(s); return EIO; } /* Load the multicast filter. */ smsc_setmulti(sc); /* TCP/UDP checksum offload engines. */ smsc_sethwcsum(sc); /* Open RX and TX pipes. */ err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_RX], USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_RX]); if (err) { printf("%s: open rx pipe failed: %s\n", device_xname(sc->sc_dev), usbd_errstr(err)); splx(s); return EIO; } err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_TX], USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_TX]); if (err) { printf("%s: open tx pipe failed: %s\n", device_xname(sc->sc_dev), usbd_errstr(err)); splx(s); return EIO; } /* Start up the receive pipe. */ for (i = 0; i < SMSC_RX_LIST_CNT; i++) { c = &sc->sc_cdata.rx_chain[i]; usbd_setup_xfer(c->sc_xfer, sc->sc_ep[SMSC_ENDPT_RX], c, c->sc_buf, sc->sc_bufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, smsc_rxeof); usbd_transfer(c->sc_xfer); } /* Indicate we are up and running. */ ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; splx(s); callout_reset(&sc->sc_stat_ch, hz, smsc_tick, sc); return 0; }