Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
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;
}