Exemplo n.º 1
0
static int
wi_pccard_probe(device_t dev)
{
	const struct pccard_product *pp;
	u_int32_t fcn = PCCARD_FUNCTION_UNSPEC;

	wlan_serialize_enter();

	/* Make sure we're a network driver */
	fcn = pccard_get_function_number(dev);
	if (fcn != PCCARD_FUNCTION_NETWORK) {
		wlan_serialize_exit();
		return ENXIO;
	}

	pp = pccard_product_lookup(dev, wi_pccard_products,
	    sizeof(wi_pccard_products[0]), NULL);
	if (pp != NULL) {
		if (pp->pp_name != NULL)
			device_set_desc(dev, pp->pp_name);
		wlan_serialize_exit();
		return 0;
	}
	wlan_serialize_exit();
	return ENXIO;
}
Exemplo n.º 2
0
static void
cac_timeout_callout(void *arg)
{
	struct ieee80211vap *vap = arg;
	struct ieee80211com *ic;
	struct ieee80211_dfs_state *dfs;
	int i;

	wlan_serialize_enter();
	ic = vap->iv_ic;
	dfs = &ic->ic_dfs;
	if (vap->iv_state != IEEE80211_S_CAC) {	/* NB: just in case */
		wlan_serialize_exit();
		return;
	}
	/*
	 * When radar is detected during a CAC we are woken
	 * up prematurely to switch to a new channel.
	 * Check the channel to decide how to act.
	 */
	if (IEEE80211_IS_CHAN_RADAR(ic->ic_curchan)) {
		ieee80211_notify_cac(ic, ic->ic_curchan,
		    IEEE80211_NOTIFY_CAC_RADAR);

		if_printf(vap->iv_ifp,
		    "CAC timer on channel %u (%u MHz) stopped due to radar\n",
		    ic->ic_curchan->ic_ieee, ic->ic_curchan->ic_freq);

		/* XXX clobbers any existing desired channel */
		/* NB: dfs->newchan may be NULL, that's ok */
		vap->iv_des_chan = dfs->newchan;
		/* XXX recursive lock need ieee80211_new_state_locked */
		ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
	} else {
		if_printf(vap->iv_ifp,
		    "CAC timer on channel %u (%u MHz) expired; "
		    "no radar detected\n",
		    ic->ic_curchan->ic_ieee, ic->ic_curchan->ic_freq);
		/*
		 * Mark all channels with the current frequency
		 * as having completed CAC; this keeps us from
		 * doing it again until we change channels.
		 */
		for (i = 0; i < ic->ic_nchans; i++) {
			struct ieee80211_channel *c = &ic->ic_channels[i];
			if (c->ic_freq == ic->ic_curchan->ic_freq)
				c->ic_state |= IEEE80211_CHANSTATE_CACDONE;
		}
		ieee80211_notify_cac(ic, ic->ic_curchan,
		    IEEE80211_NOTIFY_CAC_EXPIRE);
		ieee80211_cac_completeswitch(vap);
	}
	wlan_serialize_exit();
}
Exemplo n.º 3
0
/*
 * Module glue.
 */
static int
onoe_modevent(module_t mod, int type, void *unused)
{
       int error;

       wlan_serialize_enter();

       switch (type) {
       case MOD_LOAD:
	       if (bootverbose) {
		       kprintf("ath_rate: <Atsushi Onoe's rate "
			       "control algorithm>\n");
	       }
	       error = 0;
	       break;
       case MOD_UNLOAD:
	       error = 0;
	       break;
       default:
	       error = EINVAL;
	       break;
       }
       wlan_serialize_exit();

       return error;
}
Exemplo n.º 4
0
static int
ndisusb_detach(device_t self)
{
	int i, error;
	struct ndis_softc       *sc = device_get_softc(self);
	struct usb_attach_arg *uaa = device_get_ivars(self);

	wlan_serialize_enter();
	sc->ndisusb_status |= NDISUSB_STATUS_DETACH;

	for (i = 0; i < NDISUSB_ENDPT_MAX; i++) {
		if (sc->ndisusb_ep[i] == NULL)
			continue;

		usbd_abort_pipe(sc->ndisusb_ep[i]);
		usbd_close_pipe(sc->ndisusb_ep[i]);
		sc->ndisusb_ep[i] = NULL;
	}

	if (sc->ndisusb_iin_buf != NULL) {
		kfree(sc->ndisusb_iin_buf, M_USBDEV);
		sc->ndisusb_iin_buf = NULL;
	}

	ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED);

	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, uaa->device, self);

	error = ndis_detach(self);

	wlan_serialize_exit();
	return error;
}
Exemplo n.º 5
0
/*
 * Send a Root Annoucement (RANN) to find all the nodes on the mesh. We are
 * called when the vap is configured as a HWMP RANN root node.
 */
static void
hwmp_rootmode_rann_callout(void *arg)
{
	struct ieee80211vap *vap = (struct ieee80211vap *)arg;
	struct ieee80211_hwmp_state *hs;
	struct ieee80211_mesh_state *ms;
	struct ieee80211_meshrann_ie rann;

	wlan_serialize_enter();
	hs = vap->iv_hwmp;
	ms = vap->iv_mesh;
	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss,
	    "%s", "send broadcast RANN");

	rann.rann_flags = 0;
	if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
		rann.rann_flags |= IEEE80211_MESHRANN_FLAGS_PR;
	rann.rann_hopcount = 0;
	rann.rann_ttl = ms->ms_ttl;
	IEEE80211_ADDR_COPY(rann.rann_addr, vap->iv_myaddr);
	rann.rann_seq = ++hs->hs_seq;
	rann.rann_metric = IEEE80211_MESHLMETRIC_INITIALVAL;

	vap->iv_stats.is_hwmp_rootrann++;
	hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &rann);
	hwmp_rootmode_setup(vap);
	wlan_serialize_exit();
}
Exemplo n.º 6
0
/*
 * Module glue.
 */
static int
null_dfs_modevent(module_t mod, int type, void *unused)
{
        int error;

        wlan_serialize_enter();

        switch (type) {
        case MOD_LOAD:
                if (bootverbose) {
                        kprintf("ath_dfs: WTF module\n");
                }
                error = 0;
                break;
        case MOD_UNLOAD:
                error = 0;
                break;
        default:
                error = EINVAL;
                break;
        }
        wlan_serialize_exit();

        return error;
}
Exemplo n.º 7
0
static void
scan_signal_callout(void *arg)
{
	struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;

	wlan_serialize_enter();
	scan_signal(ss);
	wlan_serialize_exit();
}
Exemplo n.º 8
0
static void
ath_led_done(void *arg)
{
	struct ath_softc *sc = arg;

	wlan_serialize_enter();
	sc->sc_blinking = 0;
	wlan_serialize_exit();
}
Exemplo n.º 9
0
static int
ndis_detach_pccard(device_t dev)
{
	int error = 0;

	wlan_serialize_enter();
	error = ndis_detach(dev);
	wlan_serialize_exit();
	return(error);
}
Exemplo n.º 10
0
/*
 * Turn the LED off: flip the pin and then set a timer so no
 * update will happen for the specified duration.
 */
static void
ath_led_off(void *arg)
{
	struct ath_softc *sc = arg;

	wlan_serialize_enter();
	ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon);
	callout_reset(&sc->sc_ledtimer, sc->sc_ledoff, ath_led_done, sc);
	wlan_serialize_exit();
}
Exemplo n.º 11
0
static int
wi_pci_suspend(device_t dev)
{
	struct wi_softc	*sc = device_get_softc(dev);

	wlan_serialize_enter();
	wi_stop(sc, 1);
	wlan_serialize_exit();
	
	return (0);
}
Exemplo n.º 12
0
/*
 * Blink the LED according to the specified on/off times.
 */
static void
ath_led_blink(struct ath_softc *sc, int on, int off)
{
	DPRINTF(sc, ATH_DEBUG_LED, "%s: on %u off %u\n", __func__, on, off);
	wlan_serialize_enter();
	ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, sc->sc_ledon);
	sc->sc_blinking = 1;
	sc->sc_ledoff = off;
	callout_reset(&sc->sc_ledtimer, on, ath_led_off, sc);
	wlan_serialize_exit();
}
Exemplo n.º 13
0
static int
wi_pci_probe(device_t dev)
{
	struct wi_softc		*sc;
	int i;

	wlan_serialize_enter();
	sc = device_get_softc(dev);
	for(i=0; pci_ids[i].vendor != 0; i++) {
		if ((pci_get_vendor(dev) == pci_ids[i].vendor) &&
			(pci_get_device(dev) == pci_ids[i].device)) {
			sc->wi_bus_type = pci_ids[i].bus_type;
			device_set_desc(dev, pci_ids[i].desc);
			wlan_serialize_exit();
			return (BUS_PROBE_DEFAULT);
		}
	}
	wlan_serialize_exit();
	return(ENXIO);
}
Exemplo n.º 14
0
static int
wi_pci_resume(device_t dev)
{
	struct wi_softc	*sc = device_get_softc(dev);
	struct ifnet *ifp = sc->sc_ifp;

	wlan_serialize_enter();
	if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
		wlan_serialize_exit();
		return (0);
	}

	if (ifp->if_flags & IFF_UP) {
		ifp->if_init(ifp->if_softc);
		if (ifp->if_flags & IFF_RUNNING)
			if_devstart(ifp);
	}
	wlan_serialize_exit();

	return (0);
}
Exemplo n.º 15
0
static void
dfs_timeout_callout(void *arg)
{
	struct ieee80211com *ic = arg;
	struct ieee80211_dfs_state *dfs = &ic->ic_dfs;
	struct ieee80211_channel *c;
	int i, oldest, now;

	wlan_serialize_enter();
	now = oldest = ticks;
	for (i = 0; i < ic->ic_nchans; i++) {
		c = &ic->ic_channels[i];
		if (IEEE80211_IS_CHAN_RADAR(c)) {
			if (time_after_eq(now, dfs->nol_event[i]+NOL_TIMEOUT)) {
				c->ic_state &= ~IEEE80211_CHANSTATE_RADAR;
				if (c->ic_state & IEEE80211_CHANSTATE_NORADAR) {
					/*
					 * NB: do this here so we get only one
					 * msg instead of one for every channel
					 * table entry.
					 */
					if_printf(ic->ic_ifp, "radar on channel"
					    " %u (%u MHz) cleared after timeout\n",
					    c->ic_ieee, c->ic_freq);
					/* notify user space */
					c->ic_state &=
					    ~IEEE80211_CHANSTATE_NORADAR;
					ieee80211_notify_radar(ic, c);
				}
			} else if (dfs->nol_event[i] < oldest)
				oldest = dfs->nol_event[i];
		}
	}
	if (oldest != now) {
		/* arrange to process next channel up for a status change */
		callout_reset(&dfs->nol_timer, oldest + NOL_TIMEOUT - now,
		    dfs_timeout_callout, ic);
	}
	wlan_serialize_exit();
}
Exemplo n.º 16
0
/*
 * Module glue.
 */
static int
ath_hal_modevent(module_t mod, int type, void *unused)
{
	int error;

	wlan_serialize_enter();

	switch (type) {
	case MOD_LOAD:
		error = 0;
		break;
	case MOD_UNLOAD:
		error = 0;
		break;
	default:
		error = EINVAL;
		break;
	}
	wlan_serialize_exit();

	return error;
}
Exemplo n.º 17
0
static void
hwmp_rootmode_callout(void *arg)
{
	struct ieee80211vap *vap = (struct ieee80211vap *)arg;
	struct ieee80211_hwmp_state *hs;
	struct ieee80211_mesh_state *ms;
	struct ieee80211_meshpreq_ie preq;

	wlan_serialize_enter();
	hs = vap->iv_hwmp;
	ms = vap->iv_mesh;

	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss,
	    "%s", "send broadcast PREQ");

	preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM;
	if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
		preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PR;
	if (hs->hs_rootmode == IEEE80211_HWMP_ROOTMODE_PROACTIVE)
		preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PP;
	preq.preq_hopcount = 0;
	preq.preq_ttl = ms->ms_ttl;
	preq.preq_id = ++hs->hs_preqid;
	IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr);
	preq.preq_origseq = ++hs->hs_seq;
	preq.preq_lifetime = ticks_to_msecs(ieee80211_hwmp_roottimeout);
	preq.preq_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
	preq.preq_tcount = 1;
	IEEE80211_ADDR_COPY(PREQ_TADDR(0), broadcastaddr);
	PREQ_TFLAGS(0) = IEEE80211_MESHPREQ_TFLAGS_TO |
	    IEEE80211_MESHPREQ_TFLAGS_RF;
	PREQ_TSEQ(0) = 0;
	vap->iv_stats.is_hwmp_rootreqs++;
	hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq);
	hwmp_rootmode_setup(vap);
	wlan_serialize_exit();
}
Exemplo n.º 18
0
static int
wi_pccard_attach(device_t dev)
{
	struct wi_softc	*sc;
	int error;

	wlan_serialize_enter();
	sc = device_get_softc(dev);
	sc->wi_gone = 0;
	sc->wi_bus_type = WI_BUS_PCCARD;

	error = wi_alloc(dev, 0);
	if (error == 0) {
		/* Make sure interrupts are disabled. */
		CSR_WRITE_2(sc, WI_INT_EN, 0);
		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);

		error = wi_attach(dev);
		if (error != 0)
			wi_free(dev);
	}
	wlan_serialize_exit();
	return error;
}
Exemplo n.º 19
0
static void
scan_task(void *arg, int pending)
{
#define	ISCAN_REP	(ISCAN_MINDWELL | ISCAN_DISCARD)
	struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
	struct ieee80211vap *vap;
	struct ieee80211com *ic;
	struct ieee80211_channel *chan;
	unsigned long maxdwell, scanend;
	int scandone = 0;

	wlan_serialize_enter();
	vap = ss->ss_vap;
	ic = ss->ss_ic;

	if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
	    (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)) {
		/* Cancelled before we started */
		goto done;
	}

	if (ss->ss_next == ss->ss_last) {
		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
			"%s: no channels to scan\n", __func__);
		goto done;
	}

	if (vap->iv_opmode == IEEE80211_M_STA &&
	    vap->iv_state == IEEE80211_S_RUN) {
		if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
			/* Enable station power save mode */
			ieee80211_sta_pwrsave(vap, 1);
			/*
			 * Use an 1ms delay so the null data frame has a chance
			 * to go out.  Minimum one tick.
			 * XXX Should use M_TXCB mechanism to eliminate this.
			 */
			wlan_cv_timedwait(&SCAN_PRIVATE(ss)->ss_scan_cv,
					  hz / 1000 + 1);
			if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
				goto done;
		}
	}

	scanend = ticks + SCAN_PRIVATE(ss)->ss_duration;
	ic->ic_scan_start(ic);		/* notify driver */

	for (;;) {
		scandone = (ss->ss_next >= ss->ss_last) ||
		    (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0;
		if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
		    (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) ||
		     time_after(ticks + ss->ss_mindwell, scanend))
			break;

		chan = ss->ss_chans[ss->ss_next++];

		/*
		 * Watch for truncation due to the scan end time.
		 */
		if (time_after(ticks + ss->ss_maxdwell, scanend))
			maxdwell = scanend - ticks;
		else
			maxdwell = ss->ss_maxdwell;

		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
		    "%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n",
		    __func__,
		    ieee80211_chan2ieee(ic, ic->ic_curchan),
		        channel_type(ic->ic_curchan),
		    ieee80211_chan2ieee(ic, chan), channel_type(chan),
		    (ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
			(chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ?
			"active" : "passive",
		    ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell));

		/*
		 * Potentially change channel and phy mode.
		 */
		ic->ic_curchan = chan;
		ic->ic_rt = ieee80211_get_ratetable(chan);
		/*
		 * Perform the channel change and scan unlocked so the driver
		 * may sleep. Once set_channel returns the hardware has
		 * completed the channel change.
		 */
		ic->ic_set_channel(ic);
		ieee80211_radiotap_chan_change(ic);

		/*
		 * Scan curchan.  Drivers for "intelligent hardware"
		 * override ic_scan_curchan to tell the device to do
		 * the work.  Otherwise we manage the work outselves;
		 * sending a probe request (as needed), and arming the
		 * timeout to switch channels after maxdwell ticks.
		 *
		 * scan_curchan should only pause for the time required to
		 * prepare/initiate the hardware for the scan (if at all), the
		 * below condvar is used to sleep for the channels dwell time
		 * and allows it to be signalled for abort.
		 */
		ic->ic_scan_curchan(ss, maxdwell);

		SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell;
		/* clear mindwell lock and initial channel change flush */
		SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;

		if ((SCAN_PRIVATE(ss)->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT)))
			continue;

		/* Wait to be signalled to scan the next channel */
		wlan_cv_wait(&SCAN_PRIVATE(ss)->ss_scan_cv);
	}
	if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
		goto done;

	ic->ic_scan_end(ic);		/* notify driver */

	/*
	 * Record scan complete time.  Note that we also do
	 * this when canceled so any background scan will
	 * not be restarted for a while.
	 */
	if (scandone)
		ic->ic_lastscan = ticks;
	/* return to the bss channel */
	if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
	    ic->ic_curchan != ic->ic_bsschan) {
		ieee80211_setupcurchan(ic, ic->ic_bsschan);
		ic->ic_set_channel(ic);
		ieee80211_radiotap_chan_change(ic);
	}
	/* clear internal flags and any indication of a pick */
	SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
	ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK;

	/*
	 * If not canceled and scan completed, do post-processing.
	 * If the callback function returns 0, then it wants to
	 * continue/restart scanning.  Unfortunately we needed to
	 * notify the driver to end the scan above to avoid having
	 * rx frames alter the scan candidate list.
	 */
	if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0 &&
	    !ss->ss_ops->scan_end(ss, vap) &&
	    (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 &&
	    time_before(ticks + ss->ss_mindwell, scanend)) {
		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
		    "%s: done, restart "
		    "[ticks %u, dwell min %lu scanend %lu]\n",
		    __func__,
		    ticks, ss->ss_mindwell, scanend);
		ss->ss_next = 0;	/* reset to begining */
		if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
			vap->iv_stats.is_scan_active++;
		else
			vap->iv_stats.is_scan_passive++;

		ss->ss_ops->scan_restart(ss, vap);	/* XXX? */
		ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
		goto done2;
	}

	/* past here, scandone is ``true'' if not in bg mode */
	if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0)
		scandone = 1;

	IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
	    "%s: %s, [ticks %u, dwell min %lu scanend %lu]\n",
	    __func__, scandone ? "done" : "stopped",
	    ticks, ss->ss_mindwell, scanend);

	/*
	 * Clear the SCAN bit first in case frames are
	 * pending on the station power save queue.  If
	 * we defer this then the dispatch of the frames
	 * may generate a request to cancel scanning.
	 */
done:
	ic->ic_flags &= ~IEEE80211_F_SCAN;
	/*
	 * Drop out of power save mode when a scan has
	 * completed.  If this scan was prematurely terminated
	 * because it is a background scan then don't notify
	 * the ap; we'll either return to scanning after we
	 * receive the beacon frame or we'll drop out of power
	 * save mode because the beacon indicates we have frames
	 * waiting for us.
	 */
	if (scandone) {
		ieee80211_sta_pwrsave(vap, 0);
		if (ss->ss_next >= ss->ss_last) {
			ieee80211_notify_scan_done(vap);
			ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
		}
	}
	SCAN_PRIVATE(ss)->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT);
	ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST);
done2:
	wlan_serialize_exit();
#undef ISCAN_REP
}
Exemplo n.º 20
0
/* 
 * Tear down vap state and reclaim the ifnet.
 * The driver is assumed to have prepared for
 * this; e.g. by turning off interrupts for the
 * underlying device.
 */
void
ieee80211_vap_detach(struct ieee80211vap *vap)
{
	struct ieee80211com *ic = vap->iv_ic;
	struct ifnet *ifp = vap->iv_ifp;

	IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s parent %s\n",
	    __func__, ieee80211_opmode_name[vap->iv_opmode],
	    ic->ic_ifp->if_xname);

	/*
	 * NB: bpfdetach is called by ether_ifdetach and claims all taps
	 *
	 * ether_ifdetach() must be called without the serializer held.
	 */
	wlan_assert_serialized();
	wlan_serialize_exit();	/* exit to block */
	ether_ifdetach(ifp);

	wlan_serialize_enter();	/* then reenter */
	ieee80211_stop(vap);

	/*
	 * Flush any deferred vap tasks.
	 */
	wlan_serialize_exit();	/* exit to block */
	ieee80211_draintask(ic, &vap->iv_nstate_task);
	ieee80211_draintask(ic, &vap->iv_swbmiss_task);
	wlan_serialize_enter();	/* then reenter */

#ifdef __FreeBSD__
	/* XXX band-aid until ifnet handles this for us */
	taskqueue_drain(taskqueue_swi, &ifp->if_linktask);
#endif

	KASSERT(vap->iv_state == IEEE80211_S_INIT , ("vap still running"));
	TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
	ieee80211_syncflag_locked(ic, IEEE80211_F_WME);
#ifdef IEEE80211_SUPPORT_SUPERG
	ieee80211_syncflag_locked(ic, IEEE80211_F_TURBOP);
#endif
	ieee80211_syncflag_locked(ic, IEEE80211_F_PCF);
	ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
	ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_HT);
	ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
	/* NB: this handles the bpfdetach done below */
	ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_BPF);
	ieee80211_syncifflag_locked(ic, IFF_PROMISC);
	ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);

	ifmedia_removeall(&vap->iv_media);

	ieee80211_radiotap_vdetach(vap);
	ieee80211_regdomain_vdetach(vap);
	ieee80211_scan_vdetach(vap);
#ifdef IEEE80211_SUPPORT_SUPERG
	ieee80211_superg_vdetach(vap);
#endif
	ieee80211_ht_vdetach(vap);
	/* NB: must be before ieee80211_node_vdetach */
	ieee80211_proto_vdetach(vap);
	ieee80211_crypto_vdetach(vap);
	ieee80211_power_vdetach(vap);
	ieee80211_node_vdetach(vap);
	ieee80211_sysctl_vdetach(vap);

	if_free(ifp);
}
Exemplo n.º 21
0
static int
ndisusb_attach(device_t self)
{
	struct drvdb_ent	*db;
	struct ndisusb_softc *dummy = device_get_softc(self);
	struct usb_attach_arg *uaa = device_get_ivars(self);
	struct ndis_softc	*sc;
	struct ndis_usb_type	*t;
	driver_object		*drv;
	int			devidx = 0;
	usbd_status		status;

	wlan_serialize_enter();
	sc = (struct ndis_softc *)dummy;

	if (uaa->device == NULL) {
		wlan_serialize_exit();
		return ENXIO;
	}

	db = windrv_match((matchfuncptr)ndisusb_devcompare, self);
	if (db == NULL) {
		wlan_serialize_exit();
		return (ENXIO);
	}

	sc->ndis_dev = self;
	sc->ndis_dobj = db->windrv_object;
	sc->ndis_regvals = db->windrv_regvals;
	sc->ndis_iftype = PNPBus;

	/* Create PDO for this device instance */

	drv = windrv_lookup(0, "USB Bus");
	windrv_create_pdo(drv, self);

	status = usbd_set_config_no(uaa->device, NDISUSB_CONFIG_NO, 0);
	if (status != USBD_NORMAL_COMPLETION) {
		device_printf(self, "setting config no failed\n");
		wlan_serialize_exit();
		return (ENXIO);
	}

	/* Figure out exactly which device we matched. */

	t = db->windrv_devlist;

	while (t->ndis_name != NULL) {
		if ((uaa->vendor == t->ndis_vid) &&
		    (uaa->product == t->ndis_did)) {
			sc->ndis_devidx = devidx;
			break;
		}
		t++;
		devidx++;
	}

	if (ndis_attach(self) != 0) {
		wlan_serialize_exit();
		return ENXIO;
	}

	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, uaa->device, self);

	wlan_serialize_exit();
	return 0;
}
Exemplo n.º 22
0
static int
wi_pci_attach(device_t dev)
{
	struct wi_softc		*sc;
	u_int32_t		command, wanted;
	u_int16_t		reg;
	int			error;
	int			timeout;

	wlan_serialize_enter();
	sc = device_get_softc(dev);

	command = pci_read_config(dev, PCIR_COMMAND, 4);
	wanted = PCIM_CMD_PORTEN|PCIM_CMD_MEMEN;
	command |= wanted;
	pci_write_config(dev, PCIR_COMMAND, command, 4);
	command = pci_read_config(dev, PCIR_COMMAND, 4);
	if ((command & wanted) != wanted) {
		device_printf(dev, "wi_pci_attach() failed to enable pci!\n");
		wlan_serialize_exit();
		return (ENXIO);
	}

	if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
		error = wi_alloc(dev, WI_PCI_IORES);
		if (error) {
			wlan_serialize_exit();
			return (error);
		}

		/* Make sure interrupts are disabled. */
		CSR_WRITE_2(sc, WI_INT_EN, 0);
		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);

		/* We have to do a magic PLX poke to enable interrupts */
		sc->local_rid = WI_PCI_LOCALRES;
		sc->local = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
		    &sc->local_rid, RF_ACTIVE);
		sc->wi_localtag = rman_get_bustag(sc->local);
		sc->wi_localhandle = rman_get_bushandle(sc->local);
		command = bus_space_read_4(sc->wi_localtag, sc->wi_localhandle,
		    WI_LOCAL_INTCSR);
		command |= WI_LOCAL_INTEN;
		bus_space_write_4(sc->wi_localtag, sc->wi_localhandle,
		    WI_LOCAL_INTCSR, command);
		bus_release_resource(dev, SYS_RES_IOPORT, sc->local_rid,
		    sc->local);
		sc->local = NULL;

		sc->mem_rid = WI_PCI_MEMRES;
		sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
					&sc->mem_rid, RF_ACTIVE);
		if (sc->mem == NULL) {
			device_printf(dev, "couldn't allocate memory\n");
			wi_free(dev);
			wlan_serialize_exit();
			return (ENXIO);
		}
		sc->wi_bmemtag = rman_get_bustag(sc->mem);
		sc->wi_bmemhandle = rman_get_bushandle(sc->mem);

		/*
		 * Write COR to enable PC card
		 * This is a subset of the protocol that the pccard bus code
		 * would do.  In theory, we should parse the CIS to find the
		 * COR offset.  In practice, the COR_OFFSET is always 0x3e0.
		 */
		CSM_WRITE_1(sc, WI_COR_OFFSET, WI_COR_VALUE); 
		reg = CSM_READ_1(sc, WI_COR_OFFSET);
		if (reg != WI_COR_VALUE) {
			device_printf(dev, "CSM_READ_1(WI_COR_OFFSET) "
			    "wanted %d, got %d\n", WI_COR_VALUE, reg);
			wi_free(dev);
			wlan_serialize_exit();
			return (ENXIO);
		}
	} else {
		error = wi_alloc(dev, WI_PCI_LMEMRES);
		if (error) {
			wlan_serialize_exit();
			return (error);
		}

		CSR_WRITE_2(sc, WI_PCICOR_OFF, WI_PCICOR_RESET);
		DELAY(250000);

		CSR_WRITE_2(sc, WI_PCICOR_OFF, 0x0000);
		DELAY(500000);

		timeout=2000000;
		while ((--timeout > 0) &&
		    (CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
			DELAY(10);

		if (timeout == 0) {
			device_printf(dev, "couldn't reset prism pci core.\n");
			wi_free(dev);
			wlan_serialize_exit();
			return(ENXIO);
		}
	}

	CSR_WRITE_2(sc, WI_HFA384X_SWSUPPORT0_OFF, WI_PRISM2STA_MAGIC);
	reg = CSR_READ_2(sc, WI_HFA384X_SWSUPPORT0_OFF);
	if (reg != WI_PRISM2STA_MAGIC) {
		device_printf(dev,
		    "CSR_READ_2(WI_HFA384X_SWSUPPORT0_OFF) "
		    "wanted %d, got %d\n", WI_PRISM2STA_MAGIC, reg);
		wi_free(dev);
		wlan_serialize_exit();
		return (ENXIO);
	}

	error = wi_attach(dev);
	if (error != 0)
		wi_free(dev);
	wlan_serialize_exit();
	return (error);
}
Exemplo n.º 23
0
/*
 * Attach the interface. Allocate softc structures, do ifmedia
 * setup and ethernet/BPF attach.
 */
static int
ndis_attach_pccard(device_t dev)
{
	struct ndis_softc	*sc;
	int			unit, error = 0, rid;
	struct ndis_pccard_type	*t;
	int			devidx = 0;
	const char		*prodstr, *vendstr;
	struct drvdb_ent	*db;

	wlan_serialize_enter();
	sc = device_get_softc(dev);
	unit = device_get_unit(dev);
	sc->ndis_dev = dev;

	db = windrv_match((matchfuncptr)ndis_devcompare, dev);
	if (db == NULL) {
		wlan_serialize_exit();
		return (ENXIO);
	}
	sc->ndis_dobj = db->windrv_object;
	sc->ndis_regvals = db->windrv_regvals;
	resource_list_init(&sc->ndis_rl);

	sc->ndis_io_rid = 0;
	sc->ndis_res_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
	    &sc->ndis_io_rid, RF_ACTIVE);
	if (sc->ndis_res_io == NULL) {
		device_printf(dev,
		    "couldn't map iospace\n");
		error = ENXIO;
		goto fail;
	}
	sc->ndis_rescnt++;
	resource_list_add(&sc->ndis_rl, SYS_RES_IOPORT, rid,
	    rman_get_start(sc->ndis_res_io), rman_get_end(sc->ndis_res_io),
	    rman_get_size(sc->ndis_res_io), -1);

	rid = 0;
	sc->ndis_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->ndis_irq == NULL) {
		device_printf(dev,
		    "couldn't map interrupt\n");
		error = ENXIO;
		goto fail;
	}
	sc->ndis_rescnt++;
	resource_list_add(&sc->ndis_rl, SYS_RES_IRQ, rid,
	    rman_get_start(sc->ndis_irq), rman_get_start(sc->ndis_irq), 1,
	    rman_get_cpuid(sc->ndis_irq));

	sc->ndis_iftype = PCMCIABus;

	/* Figure out exactly which device we matched. */

	t = db->windrv_devlist;

	prodstr = pccard_get_product_str(dev);
	vendstr = pccard_get_vendor_str(dev);

	while(t->ndis_name != NULL) {
		if (strcasecmp(vendstr, t->ndis_vid) == 0 &&
		    strcasecmp(prodstr, t->ndis_did) == 0)
			break;
		t++;
		devidx++;
	}

	sc->ndis_devidx = devidx;

	error = ndis_attach(dev);

fail:
	wlan_serialize_exit();
	return(error);
}