Esempio n. 1
0
/* detach */
int
url_detach(device_t self, int flags)
{
	struct url_softc *sc = device_private(self);
	struct ifnet *ifp = GET_IFP(sc);
	int s;

	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));

	/* Detached before attached finished */
	if (!sc->sc_attached)
		return (0);

	callout_stop(&sc->sc_stat_ch);

	/* Remove any pending tasks */
	usb_rem_task(sc->sc_udev, &sc->sc_tick_task);
	usb_rem_task(sc->sc_udev, &sc->sc_stop_task);

	s = splusb();

	if (--sc->sc_refcnt >= 0) {
		/* Wait for processes to go away */
		usb_detach_waitold(sc->sc_dev);
	}

	if (ifp->if_flags & IFF_RUNNING)
		url_stop(GET_IFP(sc), 1);

	rnd_detach_source(&sc->rnd_source);
	mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
	ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
	ether_ifdetach(ifp);
	if_detach(ifp);

#ifdef DIAGNOSTIC
	if (sc->sc_pipe_tx != NULL)
		aprint_debug_dev(self, "detach has active tx endpoint.\n");
	if (sc->sc_pipe_rx != NULL)
		aprint_debug_dev(self, "detach has active rx endpoint.\n");
	if (sc->sc_pipe_intr != NULL)
		aprint_debug_dev(self, "detach has active intr endpoint.\n");
#endif

	sc->sc_attached = 0;

	splx(s);

	rw_destroy(&sc->sc_mii_rwlock);
	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
			   sc->sc_dev);

	return (0);
}
Esempio n. 2
0
Static int
url_init(struct ifnet *ifp)
{
	struct url_softc *sc = ifp->if_softc;
	struct mii_data *mii = GET_MII(sc);
	u_char *eaddr;
	int i, s;

	DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));

	if (sc->sc_dying)
		return (EIO);

	s = splnet();

	/* Cancel pending I/O and free all TX/RX buffers */
	url_stop(ifp, 1);

#if defined(__OpenBSD__)
	eaddr = sc->sc_ac.ac_enaddr;
#elif defined(__NetBSD__)
	eaddr = LLADDR(ifp->if_sadl);
#endif
	for (i = 0; i < ETHER_ADDR_LEN; i++)
		url_csr_write_1(sc, URL_IDR0 + i, eaddr[i]);

	/* Init transmission control register */
	URL_CLRBIT(sc, URL_TCR,
		   URL_TCR_TXRR1 | URL_TCR_TXRR0 |
		   URL_TCR_IFG1 | URL_TCR_IFG0 |
		   URL_TCR_NOCRC);

	/* Init receive control register */
	URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL | URL_RCR_AD);
	if (ifp->if_flags & IFF_BROADCAST)
		URL_SETBIT2(sc, URL_RCR, URL_RCR_AB);
	else
		URL_CLRBIT2(sc, URL_RCR, URL_RCR_AB);

	/* If we want promiscuous mode, accept all physical frames. */
	if (ifp->if_flags & IFF_PROMISC)
		URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP);
	else
		URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP);


	/* Initialize transmit ring */
	if (url_tx_list_init(sc) == ENOBUFS) {
		printf("%s: tx list init failed\n", USBDEVNAME(sc->sc_dev));
		splx(s);
		return (EIO);
	}

	/* Initialize receive ring */
	if (url_rx_list_init(sc) == ENOBUFS) {
		printf("%s: rx list init failed\n", USBDEVNAME(sc->sc_dev));
		splx(s);
		return (EIO);
	}

	/* Load the multicast filter */
	url_setmulti(sc);

	/* Enable RX and TX */
	URL_SETBIT(sc, URL_CR, URL_CR_TE | URL_CR_RE);

	mii_mediachg(mii);

	if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) {
		if (url_openpipes(sc)) {
			splx(s);
			return (EIO);
		}
	}

	ifp->if_flags |= IFF_RUNNING;
	ifp->if_flags &= ~IFF_OACTIVE;

	splx(s);

	usb_callout(sc->sc_stat_ch, hz, url_tick, sc);

	return (0);
}
Esempio n. 3
0
Static void
url_stop_task(struct url_softc *sc)
{
	url_stop(GET_IFP(sc), 1);
}
Esempio n. 4
0
Static int
url_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
	struct url_softc *sc = ifp->if_softc;
	struct ifaddr *ifa = (struct ifaddr *)data;
	struct ifreq *ifr = (struct ifreq *)data;
	struct mii_data *mii;
	int s, error = 0;

	DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));

	if (sc->sc_dying)
		return (EIO);

	s = splnet();

	switch (cmd) {
	case SIOCSIFADDR:
		ifp->if_flags |= IFF_UP;
		url_init(ifp);

		switch (ifa->ifa_addr->sa_family) {
#ifdef INET
		case AF_INET:
			arp_ifinit(&sc->sc_ac, ifa);
			break;
#endif /* INET */
		}
		break;

	case SIOCSIFMTU:
		if (ifr->ifr_mtu > ETHERMTU)
			error = EINVAL;
		else
			ifp->if_mtu = ifr->ifr_mtu;
		break;

	case SIOCSIFFLAGS:
		if (ifp->if_flags & IFF_UP) {
			if (ifp->if_flags & IFF_RUNNING &&
			    ifp->if_flags & IFF_PROMISC) {
				URL_SETBIT2(sc, URL_RCR,
					    URL_RCR_AAM|URL_RCR_AAP);
			} else if (ifp->if_flags & IFF_RUNNING &&
				   !(ifp->if_flags & IFF_PROMISC)) {
				URL_CLRBIT2(sc, URL_RCR,
					    URL_RCR_AAM|URL_RCR_AAP);
			} else if (!(ifp->if_flags & IFF_RUNNING))
				url_init(ifp);
		} else {
			if (ifp->if_flags & IFF_RUNNING)
				url_stop(ifp, 1);
		}
		error = 0;
		break;
	case SIOCADDMULTI:
	case SIOCDELMULTI:
		error = (cmd == SIOCADDMULTI) ?
			ether_addmulti(ifr, &sc->sc_ac) :
			ether_delmulti(ifr, &sc->sc_ac);

		if (error == ENETRESET) {
			if (ifp->if_flags & IFF_RUNNING)
				url_setmulti(sc);
			error = 0;
		}
		break;
	case SIOCGIFMEDIA:
	case SIOCSIFMEDIA:
		mii = GET_MII(sc);
		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
		break;
	default:
		error = EINVAL;
		break;
	}

	splx(s);

	return (error);
}