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

📄 if_ath.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
		break;	case IEEE80211_M_IBSS:		if ((sc->sc_nvaps != 0) && (ic->ic_opmode == IEEE80211_M_STA))			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 APs 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_maxvaps) {		EPRINTF(sc, "Too many virtual APs (%d already exist).\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 = netdev_priv(dev);	ieee80211_vap_setup(ic, dev, name, 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;	if (sc->sc_default_ieee80211_debug) {		/* User specified defaults for new VAPs were provided, so		 * use those (only). */		vap->iv_debug = (sc->sc_default_ieee80211_debug & ~IEEE80211_MSG_IC);	}	else {		/* If no default VAP debug flags are passed, allow a few to		 * transfer down from the driver to new VAPs so we can have load		 * time debugging for VAPs too. */		vap->iv_debug = 0 |			((sc->sc_debug & ATH_DEBUG_RATE) ? IEEE80211_MSG_XRATE  : 0) | 			((sc->sc_debug & ATH_DEBUG_XMIT) ? IEEE80211_MSG_OUTPUT : 0) | 			((sc->sc_debug & ATH_DEBUG_RECV) ? IEEE80211_MSG_INPUT  : 0) |			0			;	}	ic->ic_debug = (sc->sc_default_ieee80211_debug & IEEE80211_MSG_IC);#ifdef ATH_SUPERG_COMP	vap->iv_comp_set = ath_comp_set;#endif	/* Let rate control register proc entries for the VAP */	if (sc->sc_rc->ops->dynamic_proc_register)		sc->sc_rc->ops->dynamic_proc_register(vap);	/* XXX: VAPs emulate ethernet - true/false/good/bad? */	dev->type = ARPHRD_ETHER;	if (opmode == IEEE80211_M_MONITOR)		/* Use RadioTAP interface type for monitor mode. */		dev->type = ARPHRD_IEEE80211_RADIOTAP;	if (flags & IEEE80211_CLONE_BSSID) {		if (sc->sc_hasbmask) {			struct ieee80211vap *v;			uint64_t id_mask = 0;			unsigned int 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 APs with distinct addresses. */			/* Do a full search to mark all the allocated VAPs. */			TAILQ_FOREACH(v, &ic->ic_vaps, iv_next)				id_mask |= (1 << ATH_GET_VAP_ID(v->iv_myaddr));			for (id = 1; id < ath_maxvaps; id++) {				/* Get the first available slot. */				if ((id_mask & (1 << id)) == 0) {					ATH_SET_VAP_BSSID(vap->iv_myaddr, id);					ATH_SET_VAP_BSSID(vap->iv_bssid, id);					break;				}			}		} else {			EPRINTF(sc, "Unique BSSID requested on HW that does"				"does not support the necessary features.");		}	}	avp->av_bslot = -1;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)	atomic_set(&avp->av_beacon_alloc, 0);#else		clear_bit(0, &avp->av_beacon_alloc);#endif	STAILQ_INIT(&avp->av_mcastq.axq_q);	ATH_TXQ_LOCK_INIT(&avp->av_mcastq);	if (IEEE80211_IS_MODE_BEACON(opmode)) {		unsigned int slot;		/* 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);				/* 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_maxvaps; slot++)			if (sc->sc_bslot[slot] == NULL) {				/* XXX: Hack, space out slots to better				 * deal with misses. */				if (slot + 1 < ath_maxvaps &&				    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 ((opmode == IEEE80211_M_HOSTAP) && (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 */			if (ath_maxvaps > 4) {				DPRINTF(sc, ATH_DEBUG_BEACON, 						"Staggered beacons are not "						"possible with maxvaps set "						"to %d.\n", ath_maxvaps);				sc->sc_stagbeacons = 0;			} else {				sc->sc_stagbeacons = 1;			}		}		DPRINTF(sc, ATH_DEBUG_BEACON, "sc->sc_stagbeacons %sabled\n", 				(sc->sc_stagbeacons ? "en" : "dis"));	}	if (sc->sc_hastsfadd)		ath_hal_settsfadjust(sc->sc_ah, sc->sc_stagbeacons);	SET_NETDEV_DEV(dev, ATH_GET_NETDEV_DEV(mdev));	/* 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)			EPRINTF(sc, "DMA setup failed\n");		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	if (ic->ic_dev->flags & IFF_RUNNING) {		/* restart hardware */		if (ath_startrecv(sc) != 0)	/* restart recv */			EPRINTF(sc, "Unable to start receive logic.\n");		if (sc->sc_beacons)			ath_beacon_config(sc, NULL);	/* restart beacons */		ath_hal_intrset(ah, sc->sc_imask);	}	return vap;}static voidath_vap_delete(struct ieee80211vap *vap){	struct net_device *dev = vap->iv_ic->ic_dev;	struct ath_softc *sc = netdev_priv(dev);	struct ath_hal *ah = sc->sc_ah;	struct ath_vap *avp = ATH_VAP(vap);	int decrease = 1;	unsigned int i;	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 VAPs?		 */		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--;		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 it's an XR VAP, free the memory allocated explicitly.	 * Since the XR VAP is not registered, OS cannot 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	for (i = 0; i < IEEE80211_APPIE_NUM_OF_FRAME; i++) {		if (vap->app_ie[i].ie != NULL) {			FREE(vap->app_ie[i].ie, M_DEVBUF);			vap->app_ie[i].ie = NULL;			vap->app_ie[i].length = 0;		}	}	if (dev->flags & IFF_RUNNING) {		/* Restart RX & TX machines if device is still running. */		if (ath_startrecv(sc) != 0)		/* restart recv. */			EPRINTF(sc, "Unable to start receive logic.\n");		if (sc->sc_beacons)			ath_beacon_config(sc, NULL);	/* restart beacons */		ath_hal_intrset(ah, sc->sc_imask);	}}voidath_suspend(struct net_device *dev){	DPRINTF(((struct ath_softc *)netdev_priv(dev)), ATH_DEBUG_ANY,		"flags=%x\n", dev->flags);	ath_stop(dev);}voidath_resume(struct net_device *dev){	DPRINTF(((struct ath_softc *)netdev_priv(dev)), ATH_DEBUG_ANY,		"flags=%x\n", dev->flags);	ath_init(dev);}/* NB: Int. mit. was not implemented so that it could be enabled/disabled, * and actually in 0.9.30.13 HAL it really can't even be disabled because * it will start adjusting registers even when we turn off the capability * in the HAL. * * NB: This helper function basically clobbers all the related registers * if we have disabled int. mit. cap, allowing us to turn it on and off and * work around the bug preventing it from being disabled. */static inline void ath_override_intmit_if_disabled(struct ath_softc *sc){	/* Restore int. mit. registers if they were turned off. */	if (sc->sc_hasintmit && !sc->sc_useintmit)		ath_hal_restore_default_intmit(sc->sc_ah);	/* Sanity check... remove later. */	if (!sc->sc_useintmit) {		ath_hal_verify_default_intmit(sc->sc_ah);		/* If we don't have int. mit. and we don't have DFS on channel,		 * it is safe to filter error packets. */		if (!ath_radar_is_dfs_required(sc, &sc->sc_curchan)) {			ath_hal_setrxfilter(sc->sc_ah,				ath_hal_getrxfilter(sc->sc_ah) & 				~HAL_RX_FILTER_PHYERR);		}	}	else {		/* Make sure that we have errors in RX filter because ANI needs		 * them. */		ath_hal_setrxfilter(sc->sc_ah, 			ath_hal_getrxfilter(sc->sc_ah) | HAL_RX_FILTER_PHYERR);	}}static inline HAL_BOOL ath_hw_puttxbuf(struct ath_softc *sc, u_int qnum,				u_int32_t txdp, const char *msg){	HAL_BOOL result;	u_int32_t txdp_2;	result = ath_hal_puttxbuf(sc->sc_ah, qnum, txdp);	if (!result) {		DPRINTF(sc, ATH_DEBUG_WATCHDOG,			"TXQ%d: BUG failed to set TXDP:%08x\n",			qnum, txdp);		ath_txq_check(sc, &sc->sc_txq[qnum], msg);		return result;	}	txdp_2 = ath_hal_gettxbuf(sc->sc_ah, qnum);	if (txdp_2 != txdp) {		DPRINTF(sc, ATH_DEBUG_WATCHDOG,			"TXQ%d: BUG failed to set TXDP:%08x (is %08x)\n",			qnum, txdp, txdp_2);		ath_txq_check(sc, &sc->sc_txq[qnum], msg);	}	return result;}/* If channel change is successful, sc->sc_curchan is updated with the new * channel */static HAL_BOOL ath_hw_reset(struct ath_softc *sc, HAL_OPMODE opmode,		HAL_CHANNEL *channel, HAL_BOOL bChannelChange,		HAL_STATUS *status){

⌨️ 快捷键说明

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