예제 #1
0
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);
}
예제 #2
0
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;
		}
	}
}
예제 #3
0
파일: if_smsc.c 프로젝트: ryoon/netbsd-xhci
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;
}