int smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct smsc_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct ifaddr *ifa = (struct ifaddr *)data; int s, error = 0; s = splnet(); switch(cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; if (!(ifp->if_flags & IFF_RUNNING)) smsc_init(sc); #ifdef INET if (ifa->ifa_addr->sa_family == AF_INET) arp_ifinit(&sc->sc_ac, ifa); #endif break; case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { if (ifp->if_flags & IFF_RUNNING) error = ENETRESET; else smsc_init(sc); } else { if (ifp->if_flags & IFF_RUNNING) smsc_stop(sc); } break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); break; default: error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); } if (error == ENETRESET) { if (ifp->if_flags & IFF_RUNNING) smsc_iff(sc); error = 0; } splx(s); return(error); }
int smsc_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct smsc_softc *sc = ifp->if_softc; struct ifreq /*const*/ *ifr = data; int s, error = 0; if (sc->sc_dying) return EIO; s = splnet(); switch(cmd) { case SIOCSIFFLAGS: if ((error = ifioctl_common(ifp, cmd, data)) != 0) break; switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { case IFF_RUNNING: smsc_stop(ifp, 1); break; case IFF_UP: smsc_init(ifp); break; case IFF_UP | IFF_RUNNING: if (ifp->if_flags & IFF_PROMISC && !(sc->sc_if_flags & IFF_PROMISC)) { sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS; smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr); smsc_setmulti(sc); } else if (!(ifp->if_flags & IFF_PROMISC) && sc->sc_if_flags & IFF_PROMISC) { sc->sc_mac_csr &= ~SMSC_MAC_CSR_PRMS; smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr); smsc_setmulti(sc); } else { smsc_init(ifp); } break; } sc->sc_if_flags = ifp->if_flags; break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); break; default: if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET) break; error = 0; if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI) smsc_setmulti(sc); } splx(s); return error; }
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); }
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; }