⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_ath.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	ic->ic_scan_start = ath_scan_start;	ic->ic_scan_end = ath_scan_end;	ic->ic_set_channel = ath_set_channel;	ic->ic_set_coverageclass = ath_set_coverageclass;	ic->ic_mhz2ieee = ath_mhz2ieee;	if (register_netdev(dev)) {		printk(KERN_ERR "%s: unable to register device\n", dev->name);		goto bad3;	}	/*	 * Attach dynamic MIB vars and announce support	 * now that we have a device name with unit number.	 */#ifdef CONFIG_SYSCTL	ath_dynamic_sysctl_register(sc);#endif /* CONFIG_SYSCTL */	ieee80211_announce(ic);	ath_announce(dev);#ifdef ATH_TX99_DIAG	printk("%s: TX99 support enabled\n", dev->name);#endif	sc->sc_invalid = 0;	if (autocreate) {		if (!strcmp(autocreate, "none"))			autocreatemode = -1;		else if (!strcmp(autocreate, "sta"))			autocreatemode = IEEE80211_M_STA;		else if (!strcmp(autocreate, "ap"))			autocreatemode = IEEE80211_M_HOSTAP;		else if (!strcmp(autocreate, "adhoc"))			autocreatemode = IEEE80211_M_IBSS;		else if (!strcmp(autocreate, "ahdemo"))			autocreatemode = IEEE80211_M_AHDEMO;		else if (!strcmp(autocreate, "wds"))			autocreatemode = IEEE80211_M_WDS;		else if (!strcmp(autocreate, "monitor"))			autocreatemode = IEEE80211_M_MONITOR;		else {			printk(KERN_INFO "Unknown autocreate mode: %s\n",				autocreate);			autocreatemode = -1;		}	}		if (autocreatemode != -1) {		rtnl_lock();		error = ieee80211_create_vap(ic, "ath%d", dev,				autocreatemode, IEEE80211_CLONE_BSSID);		rtnl_unlock();		if (error)			printk(KERN_ERR "%s: autocreation of vap failed: %d\n",				dev->name, error);	}	return 0;bad3:	ieee80211_ifdetach(ic);	ath_rate_detach(sc->sc_rc);bad2:	ath_tx_cleanup(sc);	ath_desc_free(sc);bad:	if (ah)		ath_hal_detach(ah);	ATH_TXBUF_LOCK_DESTROY(sc);	ATH_LOCK_DESTROY(sc);	sc->sc_invalid = 1;	return error;}intath_detach(struct net_device *dev){	struct ath_softc *sc = dev->priv;	struct ath_hal *ah = sc->sc_ah;	HAL_INT tmp;	DPRINTF(sc, ATH_DEBUG_ANY, "%s: flags %x\n", __func__, dev->flags);	ath_stop(dev);	ath_hal_setpower(sc->sc_ah, HAL_PM_AWAKE);	/* Flush the radar task if it's scheduled */	if (sc->sc_rtasksched == 1)		ATH_FLUSH_TASKS();	sc->sc_invalid = 1;	/*	 * NB: the order of these is important:	 * o call the 802.11 layer before detaching the hal to	 *   ensure callbacks into the driver to delete global	 *   key cache entries can be handled	 * o reclaim the tx queue data structures after calling	 *   the 802.11 layer as we'll get called back to reclaim	 *   node state and potentially want to use them	 * o to cleanup the tx queues the hal is called, so detach	 *   it last	 * Other than that, it's straightforward...	 */	ieee80211_ifdetach(&sc->sc_ic);	ath_hal_intrset(ah, 0);		/* disable further intr's */	ath_hal_getisr(ah, &tmp);	/* clear ISR */	if(dev->irq) {		free_irq(dev->irq, dev);		dev->irq = 0;	}#ifdef ATH_TX99_DIAG	if (sc->sc_tx99 != NULL)		sc->sc_tx99->detach(sc->sc_tx99);#endif	ath_rate_detach(sc->sc_rc);	ath_desc_free(sc);	ath_tx_cleanup(sc);	ath_hal_detach(ah);#ifdef CONFIG_SYSCTL	ath_dynamic_sysctl_unregister(sc);#endif /* CONFIG_SYSCTL */	ATH_LOCK_DESTROY(sc);	dev->stop = NULL; /* prevent calling ath_stop again */	unregister_netdev(dev);	return 0;}static struct ieee80211vap *ath_vap_create(struct ieee80211com *ic, const char *name, int unit,	int opmode, int flags, struct net_device *mdev){	struct ath_softc *sc = ic->ic_dev->priv;	struct net_device *dev;	struct ath_vap *avp;	struct ieee80211vap *vap;	int ic_opmode;	/* XXX ic unlocked and race against add */	switch (opmode) {	case IEEE80211_M_STA:	/* ap+sta for repeater application */		if (sc->sc_nstavaps != 0)  /* only one sta regardless */			return NULL;		if ((sc->sc_nvaps != 0) && (!(flags & IEEE80211_NO_STABEACONS)))			return NULL;   /* If using station beacons, must first up */		if (flags & IEEE80211_NO_STABEACONS) {			sc->sc_nostabeacons = 1;			ic_opmode = IEEE80211_M_HOSTAP;	/* Run with chip in AP mode */		} else 			ic_opmode = opmode;		break;	case IEEE80211_M_IBSS:		if (sc->sc_nvaps != 0)		/* only one */			return NULL;		ic_opmode = opmode;		break;	case IEEE80211_M_AHDEMO:	case IEEE80211_M_MONITOR:		if (sc->sc_nvaps != 0 && ic->ic_opmode != opmode) {			/* preserve existing mode */			ic_opmode = ic->ic_opmode;		} else			ic_opmode = opmode;		break;	case IEEE80211_M_HOSTAP:	case IEEE80211_M_WDS:		/* permit multiple ap's and/or wds links */		/* XXX sta+ap for repeater/bridge application */		if ((sc->sc_nvaps != 0) && (ic->ic_opmode == IEEE80211_M_STA))			return NULL;		/* XXX not right, beacon buffer is allocated on RUN trans */		if (opmode == IEEE80211_M_HOSTAP && STAILQ_EMPTY(&sc->sc_bbuf))			return NULL;		/*		 * XXX Not sure if this is correct when operating only		 * with WDS links.		 */		ic_opmode = IEEE80211_M_HOSTAP;		break;	default:		return NULL;	}	if (sc->sc_nvaps >= ATH_BCBUF) {		printk(KERN_WARNING "too many virtual ap's (already got %d)\n", sc->sc_nvaps);		return NULL;	}	dev = alloc_etherdev(sizeof(struct ath_vap) + sc->sc_rc->arc_vap_space);	if (dev == NULL) {		/* XXX msg */		return NULL;	}		avp = dev->priv;	ieee80211_vap_setup(ic, dev, name, unit, opmode, flags);	/* override with driver methods */	vap = &avp->av_vap;	avp->av_newstate = vap->iv_newstate;	vap->iv_newstate = ath_newstate;	vap->iv_key_alloc = ath_key_alloc;	vap->iv_key_delete = ath_key_delete;	vap->iv_key_set = ath_key_set;	vap->iv_key_update_begin = ath_key_update_begin;	vap->iv_key_update_end = ath_key_update_end;#ifdef ATH_SUPERG_COMP	vap->iv_comp_set = ath_comp_set;#endif	/* Let rate control register proc entries for the vap */	ath_rate_dynamic_proc_register(vap);	/*	 * Change the interface type for monitor mode.	 */	if (opmode == IEEE80211_M_MONITOR)		dev->type = ARPHRD_IEEE80211_PRISM;	if ((flags & IEEE80211_CLONE_BSSID) &&	    sc->sc_nvaps != 0 && opmode != IEEE80211_M_WDS && sc->sc_hasbmask) {		struct ieee80211vap *v;		int id_mask, id;				/*		 * Hardware supports the bssid mask and a unique		 * bssid was requested.  Assign a new mac address		 * and expand our bssid mask to cover the active		 * virtual ap's with distinct addresses.		 */				/* do a full search to mark all the allocated vaps */		id_mask = 0;		TAILQ_FOREACH(v, &ic->ic_vaps, iv_next)			id_mask |= (1 << ATH_GET_VAP_ID(v->iv_myaddr));				for (id = 0; id < ATH_BCBUF; id++) {			/* get the first available slot */			if ((id_mask & (1 << id)) == 0) {				ATH_SET_VAP_BSSID(vap->iv_myaddr, id);				break;			}		}	}	avp->av_bslot = -1;	STAILQ_INIT(&avp->av_mcastq.axq_q);	ATH_TXQ_LOCK_INIT(&avp->av_mcastq);	if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_IBSS) {		/*		 * Allocate beacon state for hostap/ibss.  We know		 * a buffer is available because of the check above.		 */		avp->av_bcbuf = STAILQ_FIRST(&sc->sc_bbuf);		STAILQ_REMOVE_HEAD(&sc->sc_bbuf, bf_list);		if (opmode == IEEE80211_M_HOSTAP || !sc->sc_hasveol) {			int slot;			/*			 * Assign the vap to a beacon xmit slot.  As			 * above, this cannot fail to find one.			 */			avp->av_bslot = 0;			for (slot = 0; slot < ATH_BCBUF; slot++)				if (sc->sc_bslot[slot] == NULL) {					/*					 * XXX hack, space out slots to better					 * deal with misses					 */					if (slot + 1 < ATH_BCBUF &&					    sc->sc_bslot[slot+1] == NULL) {						avp->av_bslot = slot + 1;						break;					}					avp->av_bslot = slot;					/* NB: keep looking for a double slot */				}			KASSERT(sc->sc_bslot[avp->av_bslot] == NULL,				("beacon slot %u not empty?", avp->av_bslot));			sc->sc_bslot[avp->av_bslot] = vap;			sc->sc_nbcnvaps++;		}		if (sc->sc_hastsfadd) {			/*			 * Multiple vaps are to transmit beacons and we			 * have h/w support for TSF adjusting; enable use			 * of staggered beacons.			 */			/* XXX check for beacon interval too small */			sc->sc_stagbeacons = 1;		}	}	if (sc->sc_hastsfadd)		ath_hal_settsfadjust(sc->sc_ah, sc->sc_stagbeacons);	SET_NETDEV_DEV(dev, mdev->class_dev.dev);	/* complete setup */	(void) ieee80211_vap_attach(vap,		ieee80211_media_change, ieee80211_media_status);	ic->ic_opmode = ic_opmode;		if (opmode != IEEE80211_M_WDS)		sc->sc_nvaps++;			if (opmode == IEEE80211_M_STA)		sc->sc_nstavaps++;	else if (opmode == IEEE80211_M_MONITOR)		sc->sc_nmonvaps++;	/*	 * Adhoc demo mode is a pseudo mode; to the hal it's	 * just ibss mode and the driver doesn't use management	 * frames.  Other modes carry over directly to the hal.	 */	if (ic->ic_opmode == IEEE80211_M_AHDEMO)		sc->sc_opmode = HAL_M_IBSS;	else		sc->sc_opmode = (HAL_OPMODE) ic->ic_opmode;	/* NB: compatible */#ifdef ATH_SUPERG_XR	if ( vap->iv_flags & IEEE80211_F_XR ) {		if (ath_descdma_setup(sc, &sc->sc_grppolldma, &sc->sc_grppollbuf,			"grppoll", (sc->sc_xrpollcount+1) * HAL_ANTENNA_MAX_MODE, 1) != 0)			printk("%s:grppoll Buf allocation failed \n",__func__);		if (!sc->sc_xrtxq)			sc->sc_xrtxq = ath_txq_setup(sc, HAL_TX_QUEUE_DATA, HAL_XR_DATA);		if (sc->sc_hasdiversity) {			/* Save current diversity state if user destroys XR vap */			sc->sc_olddiversity = sc->sc_diversity;			ath_hal_setdiversity(sc->sc_ah, 0);			sc->sc_diversity = 0;		}	}#endif	return vap;}static voidath_vap_delete(struct ieee80211vap *vap){	struct net_device *dev = vap->iv_ic->ic_dev;	struct ath_softc *sc = dev->priv;	struct ath_hal *ah = sc->sc_ah;	struct ath_vap *avp = ATH_VAP(vap);	int decrease = 1;	KASSERT(vap->iv_state == IEEE80211_S_INIT, ("vap not stopped"));	if (dev->flags & IFF_RUNNING) {		/*		 * Quiesce the hardware while we remove the vap.  In		 * particular we need to reclaim all references to the		 * vap state by any frames pending on the tx queues.		 *		 * XXX can we do this w/o affecting other vap's?		 */		ath_hal_intrset(ah, 0);		/* disable interrupts */		ath_draintxq(sc);		/* stop xmit side */		ath_stoprecv(sc);		/* stop recv side */	}	/*	 * Reclaim any pending mcast bufs on the vap.	 */	ath_tx_draintxq(sc, &avp->av_mcastq);	ATH_TXQ_LOCK_DESTROY(&avp->av_mcastq);	/*	 * Reclaim beacon state.  Note this must be done before	 * vap instance is reclaimed as we may have a reference	 * to it in the buffer for the beacon frame.	 */	if (avp->av_bcbuf != NULL) {		if (avp->av_bslot != -1) {			sc->sc_bslot[avp->av_bslot] = NULL;			sc->sc_nbcnvaps--;		}		ath_beacon_return(sc, avp->av_bcbuf);		avp->av_bcbuf = NULL;		if (sc->sc_nbcnvaps == 0)			sc->sc_stagbeacons = 0;	}	if (vap->iv_opmode == IEEE80211_M_STA) {		sc->sc_nstavaps--;		if (sc->sc_nostabeacons)			sc->sc_nostabeacons = 0;	} else if (vap->iv_opmode == IEEE80211_M_MONITOR) {		sc->sc_nmonvaps--;	} else if (vap->iv_opmode == IEEE80211_M_WDS) {		decrease = 0;	}	ieee80211_vap_detach(vap);	/* NB: memory is reclaimed through dev->destructor callback */	if (decrease)		sc->sc_nvaps--;#ifdef ATH_SUPERG_XR 	/*	 * if its an XR vap ,free the memory allocated explicitly.	 * since the XR vap is not registered , OS can not free the memory.	 */	if (vap->iv_flags & IEEE80211_F_XR) {		ath_grppoll_stop(vap);		ath_descdma_cleanup(sc, &sc->sc_grppolldma, &sc->sc_grppollbuf, BUS_DMA_FROMDEVICE);		memset(&sc->sc_grppollbuf, 0, sizeof(sc->sc_grppollbuf));		memset(&sc->sc_grppolldma, 0, sizeof(sc->sc_grppolldma));		if (vap->iv_xrvap)			vap->iv_xrvap->iv_xrvap = NULL;		kfree(vap->iv_dev);		ath_tx_cleanupq(sc,sc->sc_xrtxq);		sc->sc_xrtxq = NULL;		if (sc->sc_hasdiversity) {			/* Restore diversity setting to old diversity setting */			ath_hal_setdiversity(ah, sc->sc_olddiversity);			sc->sc_diversity = sc->sc_olddiversity;		}	}#endif	if (dev->flags & IFF_RUNNING) {		/*		 * Restart rx+tx machines if device is still running.		 */		if (ath_startrecv(sc) != 0)	/* restart recv */			printk("%s: %s: unable to start recv logic\n",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -