/*
 * tunclose - close the device - mark i/f down & delete
 * routing info
 */
int
tunclose(dev_t dev, int flag, int mode,
    struct lwp *l)
{
	int	s;
	struct tun_softc *tp;
	struct ifnet	*ifp;

	s = splnet();
	if ((tp = tun_find_zunit(minor(dev))) != NULL) {
		/* interface was "destroyed" before the close */
		seldestroy(&tp->tun_rsel);
		seldestroy(&tp->tun_wsel);
		softint_disestablish(tp->tun_osih);
		softint_disestablish(tp->tun_isih);
		mutex_destroy(&tp->tun_lock);
		free(tp, M_DEVBUF);
		goto out_nolock;
	}

	if ((tp = tun_find_unit(dev)) == NULL)
		goto out_nolock;

	ifp = &tp->tun_if;

	tp->tun_flags &= ~TUN_OPEN;

	tp->tun_pgid = 0;
	selnotify(&tp->tun_rsel, 0, 0);

	TUNDEBUG ("%s: closed\n", ifp->if_xname);
	mutex_exit(&tp->tun_lock);

	/*
	 * junk all pending output
	 */
	IFQ_PURGE(&ifp->if_snd);

	if (ifp->if_flags & IFF_UP) {
		if_down(ifp);
		if (ifp->if_flags & IFF_RUNNING) {
			/* find internet addresses and delete routes */
			struct ifaddr *ifa;
			IFADDR_FOREACH(ifa, ifp) {
#if defined(INET) || defined(INET6)
				if (ifa->ifa_addr->sa_family == AF_INET ||
				    ifa->ifa_addr->sa_family == AF_INET6) {
					rtinit(ifa, (int)RTM_DELETE,
					       tp->tun_flags & TUN_DSTADDR
							? RTF_HOST
							: 0);
				}
#endif
			}
		}
	}
Exemple #2
0
static int
tap_dev_close(struct tap_softc *sc)
{
	struct ifnet *ifp;
	int s;

	s = splnet();
	/* Let tap_start handle packets again */
	ifp = &sc->sc_ec.ec_if;
	ifp->if_flags &= ~IFF_OACTIVE;

	/* Purge output queue */
	if (!(IFQ_IS_EMPTY(&ifp->if_snd))) {
		struct mbuf *m;

		for (;;) {
			IFQ_DEQUEUE(&ifp->if_snd, m);
			if (m == NULL)
				break;

			ifp->if_opackets++;
			bpf_mtap(ifp, m);
			m_freem(m);
		}
	}
	splx(s);

	if (sc->sc_sih != NULL) {
		softint_disestablish(sc->sc_sih);
		sc->sc_sih = NULL;
	}
	sc->sc_flags &= ~(TAP_INUSE | TAP_ASYNCIO);

	return (0);
}
Exemple #3
0
/* This is necessary when dynamically changing SAIP configuration. */
int
sacom_detach(struct device *self, int flags)
{
    struct sacom_softc *sc = (struct sacom_softc *)self;
    int maj, mn;

    /* locate the major number */
    maj = cdevsw_lookup_major(&sacom_cdevsw);

    /* Nuke the vnodes for any open instances. */
    mn = device_unit(self);
    vdevgone(maj, mn, mn, VCHR);

    mn |= COMDIALOUT_MASK;
    vdevgone(maj, mn, mn, VCHR);

    /* Free the receive buffer. */
    free(sc->sc_rbuf, M_DEVBUF);

    /* Detach and free the tty. */
    tty_detach(sc->sc_tty);
    ttyfree(sc->sc_tty);

    /* Unhook the soft interrupt handler. */
    softint_disestablish(sc->sc_si);

#if NRND > 0 && defined(RND_COM)
    /* Unhook the entropy source. */
    rnd_detach_source(&sc->rnd_source);
#endif

    return 0;
}
Exemple #4
0
int
testcall(struct lwp *l, void *uap, register_t *retval)
{

	printf("test: initializing\n");

	mutex_init(&test_mutex, MUTEX_DEFAULT, IPL_NONE);
	cv_init(&test_cv, "testcv");
	test_sih = softint_establish(SOFTINT_MPSAFE | SOFTINT_SERIAL,
	    test_softint, NULL);
	callout_init(&test_ch, CALLOUT_MPSAFE);
	callout_setfunc(&test_ch, test_callout, NULL);

	printf("test: firing\n");
	callout_schedule(&test_ch, hz / 10);

	printf("test: waiting\n");
	mutex_enter(&test_mutex);
	while (!test_done) {
		cv_wait(&test_cv, &test_mutex);
	}
	mutex_exit(&test_mutex);

	printf("test: finished\n");

	callout_destroy(&test_ch);
	softint_disestablish(test_sih);
	mutex_destroy(&test_mutex);
	cv_destroy(&test_cv);

	return 0;
}
static int
tun_clone_destroy(struct ifnet *ifp)
{
	struct tun_softc *tp = (void *)ifp;
	int s, zombie = 0;

	IF_PURGE(&ifp->if_snd);
	ifp->if_flags &= ~IFF_RUNNING;

	s = splnet();
	simple_lock(&tun_softc_lock);
	mutex_enter(&tp->tun_lock);
	LIST_REMOVE(tp, tun_list);
	if (tp->tun_flags & TUN_OPEN) {
		/* Hang on to storage until last close */
		zombie = 1;
		tp->tun_flags &= ~TUN_INITED;
		LIST_INSERT_HEAD(&tunz_softc_list, tp, tun_list);
	}
	simple_unlock(&tun_softc_lock);

	if (tp->tun_flags & TUN_RWAIT) {
		tp->tun_flags &= ~TUN_RWAIT;
		wakeup((void *)tp);
	}
	selnotify(&tp->tun_rsel, 0, 0);

	mutex_exit(&tp->tun_lock);
	splx(s);

	if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
		fownsignal(tp->tun_pgid, SIGIO, POLL_HUP, 0, NULL);

	bpf_detach(ifp);
	if_detach(ifp);

	if (!zombie) {
		seldestroy(&tp->tun_rsel);
		seldestroy(&tp->tun_wsel);
		softint_disestablish(tp->tun_osih);
		softint_disestablish(tp->tun_isih);
		mutex_destroy(&tp->tun_lock);
		free(tp, M_DEVBUF);
	}

	return (0);
}
static void
free_pipe(struct umidi_endpoint *ep)
{
	DPRINTF(("%s: free_pipe %p\n", USBDEVNAME(ep->sc->sc_dev), ep));
	usbd_abort_pipe(ep->pipe);
	usbd_close_pipe(ep->pipe);
	usbd_free_xfer(ep->xfer);
	softint_disestablish(ep->solicit_cookie);
}
Exemple #7
0
int
lpt_detach_subr(device_t self, int flags)
{
	struct lpt_softc *sc = device_private(self);

	sc->sc_dev_ok = 0;
	softint_disestablish(sc->sc_sih);
	callout_destroy(&sc->sc_wakeup_ch);
	return 0;
}
Exemple #8
0
static int
btsco_detach(device_t self, int flags)
{
	struct btsco_softc *sc = device_private(self);

	DPRINTF("sc=%p\n", sc);

	pmf_device_deregister(self);

	mutex_enter(bt_lock);
	if (sc->sc_sco != NULL) {
		DPRINTF("sc_sco=%p\n", sc->sc_sco);
		sco_disconnect_pcb(sc->sc_sco, 0);
		sco_detach_pcb(&sc->sc_sco);
		sc->sc_sco = NULL;
	}

	if (sc->sc_sco_l != NULL) {
		DPRINTF("sc_sco_l=%p\n", sc->sc_sco_l);
		sco_detach_pcb(&sc->sc_sco_l);
		sc->sc_sco_l = NULL;
	}
	mutex_exit(bt_lock);

	if (sc->sc_audio != NULL) {
		DPRINTF("sc_audio=%p\n", sc->sc_audio);
		config_detach(sc->sc_audio, flags);
		sc->sc_audio = NULL;
	}

	if (sc->sc_intr != NULL) {
		softint_disestablish(sc->sc_intr);
		sc->sc_intr = NULL;
	}

	if (sc->sc_rx_mbuf != NULL) {
		m_freem(sc->sc_rx_mbuf);
		sc->sc_rx_mbuf = NULL;
	}

	if (sc->sc_tx_refcnt > 0) {
		aprint_error_dev(self, "tx_refcnt=%d!\n", sc->sc_tx_refcnt);

		if ((flags & DETACH_FORCE) == 0)
			return EAGAIN;
	}

	cv_destroy(&sc->sc_connect);
	mutex_destroy(&sc->sc_intr_lock);

	return 0;
}
int
mididetach(device_t self, int flags)
{
	struct midi_softc *sc = device_private(self);
	int maj, mn;

	DPRINTFN(2,("%s: sc=%p flags=%d\n", __func__, sc, flags));

	pmf_device_deregister(self);

	mutex_enter(sc->lock);
	sc->dying = 1;
	cv_broadcast(&sc->wchan);
	cv_broadcast(&sc->rchan);
	mutex_exit(sc->lock);

	/* locate the major number */
	maj = cdevsw_lookup_major(&midi_cdevsw);

	/*
	 * Nuke the vnodes for any open instances (calls close).
	 * Will wait until any activity on the device nodes has ceased.
	 *
	 * XXXAD NOT YET.
	 *
	 * XXXAD NEED TO PREVENT NEW REFERENCES THROUGH AUDIO_ENTER().
	 */
	mn = device_unit(self);
	vdevgone(maj, mn, mn, VCHR);
	
	if (!(sc->props & MIDI_PROP_NO_OUTPUT)) {
		evcnt_detach(&sc->xmt.bytesDiscarded);
		evcnt_detach(&sc->xmt.incompleteMessages);
	}
	if (sc->props & MIDI_PROP_CAN_INPUT) {
		evcnt_detach(&sc->rcv.bytesDiscarded);
		evcnt_detach(&sc->rcv.incompleteMessages);
	}

	if (sc->sih != NULL) {
		softint_disestablish(sc->sih);
		sc->sih = NULL;
	}

	cv_destroy(&sc->wchan);
	cv_destroy(&sc->rchan);

	return (0);
}
static int
xennet_xenbus_detach(device_t self, int flags)
{
	struct xennet_xenbus_softc *sc = device_private(self);
	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
	int s0, s1;
	RING_IDX i;

	DPRINTF(("%s: xennet_xenbus_detach\n", device_xname(self)));
	s0 = splnet();
	xennet_stop(ifp, 1);
	/* wait for pending TX to complete, and collect pending RX packets */
	xennet_handler(sc);
	while (sc->sc_tx_ring.sring->rsp_prod != sc->sc_tx_ring.rsp_cons) {
		tsleep(xennet_xenbus_detach, PRIBIO, "xnet_detach", hz/2);
		xennet_handler(sc);
	}
	xennet_free_rx_buffer(sc);

	s1 = splvm();
	for (i = 0; i < NET_RX_RING_SIZE; i++) {
		struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i];
		uvm_km_free(kernel_map, rxreq->rxreq_va, PAGE_SIZE,
		    UVM_KMF_WIRED);
	}
	splx(s1);
		
	ether_ifdetach(ifp);
	if_detach(ifp);
	while (xengnt_status(sc->sc_tx_ring_gntref)) {
		tsleep(xennet_xenbus_detach, PRIBIO, "xnet_txref", hz/2);
	}
	xengnt_revoke_access(sc->sc_tx_ring_gntref);
	uvm_km_free(kernel_map, (vaddr_t)sc->sc_tx_ring.sring, PAGE_SIZE,
	    UVM_KMF_WIRED);
	while (xengnt_status(sc->sc_rx_ring_gntref)) {
		tsleep(xennet_xenbus_detach, PRIBIO, "xnet_rxref", hz/2);
	}
	xengnt_revoke_access(sc->sc_rx_ring_gntref);
	uvm_km_free(kernel_map, (vaddr_t)sc->sc_rx_ring.sring, PAGE_SIZE,
	    UVM_KMF_WIRED);
	softint_disestablish(sc->sc_softintr);
	event_remove_handler(sc->sc_evtchn, &xennet_handler, sc);
	splx(s0);
	DPRINTF(("%s: xennet_xenbus_detach done\n", device_xname(self)));
	return 0;
}
void
gemini_ipm_deregister(void *ipmh)
{
	gemini_ipm_softc_t *sc = gemini_ipm_sc;
	ipm_dispatch_entry_t *disp = ipmh;
	int psw;

	if (sc == NULL)
		return;

	psw = disable_interrupts(I32_bit);
	memset(disp, 0, sizeof(*disp));
#ifdef NOTYET
	softint_disestablish(sc->sih);
#endif
	restore_interrupts(psw);
}
Exemple #12
0
/*
 * When detaching, we do the inverse of what is done in the attach
 * routine, in reversed order.
 */
static int
tap_detach(device_t self, int flags)
{
	struct tap_softc *sc = device_private(self);
	struct ifnet *ifp = &sc->sc_ec.ec_if;
#if defined(COMPAT_40) || defined(MODULAR)
	int error;
#endif
	int s;

	sc->sc_flags |= TAP_GOING;
	s = splnet();
	tap_stop(ifp, 1);
	if_down(ifp);
	splx(s);

	if (sc->sc_sih != NULL) {
		softint_disestablish(sc->sc_sih);
		sc->sc_sih = NULL;
	}

#if defined(COMPAT_40) || defined(MODULAR)
	/*
	 * Destroying a single leaf is a very straightforward operation using
	 * sysctl_destroyv.  One should be sure to always end the path with
	 * CTL_EOL.
	 */
	if ((error = sysctl_destroyv(NULL, CTL_NET, AF_LINK, tap_node,
	    device_unit(sc->sc_dev), CTL_EOL)) != 0)
		aprint_error_dev(self,
		    "sysctl_destroyv returned %d, ignoring\n", error);
#endif
	ether_ifdetach(ifp);
	if_detach(ifp);
	ifmedia_delete_instance(&sc->sc_im, IFM_INST_ANY);
	seldestroy(&sc->sc_rsel);
	mutex_destroy(&sc->sc_rdlock);
	mutex_destroy(&sc->sc_kqlock);

	pmf_device_deregister(self);

	return (0);
}
Exemple #13
0
int
ucom_detach(device_t self, int flags)
{
	struct ucom_softc *sc = device_private(self);
	struct tty *tp = sc->sc_tty;
	int maj, mn;
	int s, i;

	DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n",
		 sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no));

	sc->sc_dying = 1;
	pmf_device_deregister(self);

	if (sc->sc_bulkin_pipe != NULL)
		usbd_abort_pipe(sc->sc_bulkin_pipe);
	if (sc->sc_bulkout_pipe != NULL)
		usbd_abort_pipe(sc->sc_bulkout_pipe);

	s = splusb();
	if (--sc->sc_refcnt >= 0) {
		/* Wake up anyone waiting */
		if (tp != NULL) {
			mutex_spin_enter(&tty_lock);
			CLR(tp->t_state, TS_CARR_ON);
			CLR(tp->t_cflag, CLOCAL | MDMBUF);
			ttyflush(tp, FREAD|FWRITE);
			mutex_spin_exit(&tty_lock);
		}
		/* Wait for processes to go away. */
		usb_detach_waitold(sc->sc_dev);
	}

	softint_disestablish(sc->sc_si);
	splx(s);

	/* locate the major number */
	maj = cdevsw_lookup_major(&ucom_cdevsw);

	/* Nuke the vnodes for any open instances. */
	mn = device_unit(self);
	DPRINTF(("ucom_detach: maj=%d mn=%d\n", maj, mn));
	vdevgone(maj, mn, mn, VCHR);
	vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR);
	vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR);

	/* Detach and free the tty. */
	if (tp != NULL) {
		tty_detach(tp);
		tty_free(tp);
		sc->sc_tty = NULL;
	}

	for (i = 0; i < UCOM_IN_BUFFS; i++) {
		if (sc->sc_ibuff[i].ub_xfer != NULL)
			usbd_free_xfer(sc->sc_ibuff[i].ub_xfer);
	}

	for (i = 0; i < UCOM_OUT_BUFFS; i++) {
		if (sc->sc_obuff[i].ub_xfer != NULL)
			usbd_free_xfer(sc->sc_obuff[i].ub_xfer);
	}

	/* Detach the random source */
	rnd_detach_source(&sc->sc_rndsource);

	return (0);
}
Exemple #14
0
static int
tap_dev_ioctl(int unit, u_long cmd, void *data, struct lwp *l)
{
	struct tap_softc *sc = device_lookup_private(&tap_cd, unit);

	if (sc == NULL)
		return ENXIO;

	switch (cmd) {
	case FIONREAD:
		{
			struct ifnet *ifp = &sc->sc_ec.ec_if;
			struct mbuf *m;
			int s;

			s = splnet();
			IFQ_POLL(&ifp->if_snd, m);

			if (m == NULL)
				*(int *)data = 0;
			else
				*(int *)data = m->m_pkthdr.len;
			splx(s);
			return 0;
		} 
	case TIOCSPGRP:
	case FIOSETOWN:
		return fsetown(&sc->sc_pgid, cmd, data);
	case TIOCGPGRP:
	case FIOGETOWN:
		return fgetown(sc->sc_pgid, cmd, data);
	case FIOASYNC:
		if (*(int *)data) {
			if (sc->sc_sih == NULL) {
				sc->sc_sih = softint_establish(SOFTINT_CLOCK,
				    tap_softintr, sc);
				if (sc->sc_sih == NULL)
					return EBUSY; /* XXX */
			}
			sc->sc_flags |= TAP_ASYNCIO;
		} else {
			sc->sc_flags &= ~TAP_ASYNCIO;
			if (sc->sc_sih != NULL) {
				softint_disestablish(sc->sc_sih);
				sc->sc_sih = NULL;
			}
		}
		return 0;
	case FIONBIO:
		if (*(int *)data)
			sc->sc_flags |= TAP_NBIO;
		else
			sc->sc_flags &= ~TAP_NBIO;
		return 0;
#ifdef OTAPGIFNAME
	case OTAPGIFNAME:
#endif
	case TAPGIFNAME:
		{
			struct ifreq *ifr = (struct ifreq *)data;
			struct ifnet *ifp = &sc->sc_ec.ec_if;

			strlcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
			return 0;
		}
	default:
		return ENOTTY;
	}
}