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

📄 if_ath.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
			 */			ath_hal_mibevent(ah, &sc->sc_halstats);			ath_hal_intrset(ah, sc->sc_imask);		}	}	if (needmark)		mark_bh(IMMEDIATE_BH);	return IRQ_HANDLED;}static voidath_radar_task(TQUEUE_ARG data){	struct net_device *dev = (struct net_device *)data;	struct ath_softc *sc = dev->priv;	struct ath_hal *ah = sc->sc_ah;	struct ieee80211com *ic = &sc->sc_ic;	struct ieee80211_channel ichan;	HAL_CHANNEL hchan;	sc->sc_rtasksched = 0;	if (ath_hal_procdfs(ah, &hchan)) {		/*		 * DFS was found, initiate channel change		 */		ichan.ic_ieee = ath_hal_mhz2ieee(ah, hchan.channel, hchan.channelFlags);		ichan.ic_freq = hchan.channel;		ichan.ic_flags = hchan.channelFlags;		if ((sc->sc_curchan.channel == hchan.channel) &&		    (sc->sc_curchan.channelFlags == hchan.channel)) {			if (hchan.privFlags & CHANNEL_INTERFERENCE)				sc->sc_curchan.privFlags |= CHANNEL_INTERFERENCE;		}		ieee80211_mark_dfs(ic, &ichan);		if (((ic->ic_flags_ext & IEEE80211_FEXT_MARKDFS) == 0) &&		    (ic->ic_opmode == IEEE80211_M_HOSTAP)) {			sc->sc_dfstest_ieeechan = ic->ic_curchan->ic_ieee;			sc->sc_dfstesttimer.function = ath_dfs_test_return;			sc->sc_dfstesttimer.expires = jiffies + (sc->sc_dfstesttime * HZ);			sc->sc_dfstesttimer.data = (unsigned long)sc;			if (sc->sc_dfstest == 0) {				sc->sc_dfstest = 1;				add_timer(&sc->sc_dfstesttimer);			}		}	}}static voidath_dfs_test_return(unsigned long data){	struct ath_softc *sc = (struct ath_softc *)data; 	struct ieee80211com *ic = &sc->sc_ic;	sc->sc_dfstest = 0;	ieee80211_dfs_test_return(ic, sc->sc_dfstest_ieeechan);}static voidath_fatal_tasklet(TQUEUE_ARG data){	struct net_device *dev = (struct net_device *)data;	printk("%s: hardware error; reseting\n", dev->name);	ath_reset(dev);}static voidath_rxorn_tasklet(TQUEUE_ARG data){	struct net_device *dev = (struct net_device *)data;	printk("%s: rx FIFO overrun; reseting\n", dev->name);	ath_reset(dev);}static voidath_bmiss_tasklet(TQUEUE_ARG data){	struct net_device *dev = (struct net_device *)data;	struct ath_softc *sc = dev->priv;	DPRINTF(sc, ATH_DEBUG_ANY, "%s\n", __func__);	ieee80211_beacon_miss(&sc->sc_ic);}static u_intath_chan2flags(struct ieee80211_channel *chan){	u_int flags;	static const u_int modeflags[] = {		0,		/* IEEE80211_MODE_AUTO    */		CHANNEL_A,	/* IEEE80211_MODE_11A     */		CHANNEL_B,	/* IEEE80211_MODE_11B     */		CHANNEL_PUREG,	/* IEEE80211_MODE_11G     */		0,		/* IEEE80211_MODE_FH      */		CHANNEL_108A,	/* IEEE80211_MODE_TURBO_A */		CHANNEL_108G,	/* IEEE80211_MODE_TURBO_G */	};	flags = modeflags[ieee80211_chan2mode(chan)];	if (IEEE80211_IS_CHAN_HALF(chan))		flags |= CHANNEL_HALF;	else if (IEEE80211_IS_CHAN_QUARTER(chan))		flags |= CHANNEL_QUARTER;	return flags;}/* * Context: process context */static intath_init(struct net_device *dev){	struct ath_softc *sc = dev->priv;	struct ieee80211com *ic = &sc->sc_ic;	struct ath_hal *ah = sc->sc_ah;	HAL_STATUS status;	int error = 0;	ATH_LOCK(sc);	DPRINTF(sc, ATH_DEBUG_RESET, "%s: mode %d\n", __func__, ic->ic_opmode);	/*	 * Stop anything previously setup.  This is safe	 * whether this is the first time through or not.	 */	ath_stop_locked(dev);#ifdef ATH_CAP_TPC	ath_hal_setcapability(sc->sc_ah, HAL_CAP_TPC, 0, 1, NULL);#endif	/* Whether we should enable h/w TKIP MIC */	if ((ic->ic_caps & IEEE80211_C_WME) == 0)		ath_hal_setcapability(sc->sc_ah, HAL_CAP_TKIP_MIC, 0, 0, NULL);	else {		if (((ic->ic_caps & IEEE80211_C_WME_TKIPMIC) == 0) &&		    (ic->ic_flags & IEEE80211_F_WME))			ath_hal_setcapability(sc->sc_ah, HAL_CAP_TKIP_MIC, 0, 0, NULL);		else			ath_hal_setcapability(sc->sc_ah, HAL_CAP_TKIP_MIC, 0, 1, NULL);	}			/*	 * Flush the skb's allocated for receive in case the rx	 * buffer size changes.  This could be optimized but for	 * now we do it each time under the assumption it does	 * not happen often.	 */	ath_flushrecv(sc);	/*	 * The basic interface to setting the hardware in a good	 * state is ``reset''.  On return the hardware is known to	 * be powered up and with interrupts disabled.  This must	 * be followed by initialization of the appropriate bits	 * and then setup of the interrupt mask.	 */	sc->sc_curchan.channel = ic->ic_curchan->ic_freq;	sc->sc_curchan.channelFlags = ath_chan2flags(ic->ic_curchan);	if (!ath_hal_reset(ah, sc->sc_opmode, &sc->sc_curchan, AH_FALSE, &status)) {		printk("%s: unable to reset hardware: '%s' (HAL status %u) "			"(freq %u flags 0x%x)\n", dev->name,			ath_get_hal_status_desc(status), status,			sc->sc_curchan.channel, sc->sc_curchan.channelFlags);		error = -EIO;		goto done;	}	if (sc->sc_softled)		ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);	/*	 * This is needed only to setup initial state	 * but it's best done after a reset.	 */	ath_update_txpow(sc);	/*	 * Setup the hardware after reset: the key cache	 * is filled as needed and the receive engine is	 * set going.  Frame transmit is handled entirely	 * in the frame output path; there's nothing to do	 * here except setup the interrupt mask.	 */#if 0	ath_initkeytable(sc);		/* XXX still needed? */#endif	if (ath_startrecv(sc) != 0) {		printk("%s: unable to start recv logic\n", dev->name);		error = -EIO;		goto done;	}	/*	 * Enable interrupts.	 */	sc->sc_imask = HAL_INT_RX | HAL_INT_TX		  | HAL_INT_RXEOL | HAL_INT_RXORN		  | HAL_INT_FATAL | HAL_INT_GLOBAL;	/*	 * Enable MIB interrupts when there are hardware phy counters.	 * Note we only do this (at the moment) for station mode.	 */	if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA)		sc->sc_imask |= HAL_INT_MIB;	ath_hal_intrset(ah, sc->sc_imask);	/*	 * The hardware should be ready to go now so it's safe	 * to kick the 802.11 state machine as it's likely to	 * immediately call back to us to send mgmt frames.	 */	ath_chan_change(sc, ic->ic_curchan);	ath_set_ack_bitrate(sc, sc->sc_ackrate);	dev->flags |= IFF_RUNNING;		/* we are ready to go */	ieee80211_start_running(ic);		/* start all vap's */#ifdef ATH_TX99_DIAG	if (sc->sc_tx99 != NULL)		sc->sc_tx99->start(sc->sc_tx99);#endifdone:	ATH_UNLOCK(sc);	return error;}/* Caller must lock ATH_LOCK  * * Context: softIRQ */ static intath_stop_locked(struct net_device *dev){	struct ath_softc *sc = dev->priv;	struct ieee80211com *ic = &sc->sc_ic;	struct ath_hal *ah = sc->sc_ah;	DPRINTF(sc, ATH_DEBUG_RESET, "%s: invalid %u flags 0x%x\n",		__func__, sc->sc_invalid, dev->flags);	if (dev->flags & IFF_RUNNING) {		/*		 * Shutdown the hardware and driver:		 *    stop output from above		 *    reset 802.11 state machine		 *	(sends station deassoc/deauth frames)		 *    turn off timers		 *    disable interrupts		 *    clear transmit machinery		 *    clear receive machinery		 *    turn off the radio		 *    reclaim beacon resources		 *		 * Note that some of this work is not possible if the		 * hardware is gone (invalid).		 */#ifdef ATH_TX99_DIAG		if (sc->sc_tx99 != NULL)			sc->sc_tx99->stop(sc->sc_tx99);#endif		netif_stop_queue(dev);	/* XXX re-enabled by ath_newstate */		dev->flags &= ~IFF_RUNNING;	/* NB: avoid recursion */		ieee80211_stop_running(ic);	/* stop all vap's */		if (!sc->sc_invalid) {			ath_hal_intrset(ah, 0);			if (sc->sc_softled) {				del_timer(&sc->sc_ledtimer);				ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon);				sc->sc_blinking = 0;				sc->sc_ledstate = 1;			}		}		ath_draintxq(sc);		if (!sc->sc_invalid) {			ath_stoprecv(sc);			ath_hal_phydisable(ah);		} else			sc->sc_rxlink = NULL;		ath_beacon_free(sc);		/* XXX needed? */	}	if (sc->sc_softled)		ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon);		return 0;}/* * Stop the device, grabbing the top-level lock to protect * against concurrent entry through ath_init (which can happen * if another thread does a system call and the thread doing the * stop is preempted). */static intath_stop(struct net_device *dev){	struct ath_softc *sc = dev->priv;	int error;	ATH_LOCK(sc);	if (!sc->sc_invalid)		ath_hal_setpower(sc->sc_ah, HAL_PM_AWAKE);	error = ath_stop_locked(dev);#if 0	if (error == 0 && !sc->sc_invalid) {		/*		 * Set the chip in full sleep mode.  Note that we are		 * careful to do this only when bringing the interface		 * completely to a stop.  When the chip is in this state		 * it must be carefully woken up or references to		 * registers in the PCI clock domain may freeze the bus		 * (and system).  This varies by chip and is mostly an		 * issue with newer parts that go to sleep more quickly.		 */		ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);	}#endif	ATH_UNLOCK(sc);	return error;}static int ar_device(int devid){	switch (devid) {	case AR5210_DEFAULT:	case AR5210_PROD:	case AR5210_AP:		return 5210;	case AR5211_DEFAULT:	case AR5311_DEVID:	case AR5211_LEGACY:	case AR5211_FPGA11B:		return 5211;	case AR5212_DEFAULT:	case AR5212_DEVID:	case AR5212_FPGA:	case AR5212_DEVID_IBM:	case AR5212_AR5312_REV2:	case AR5212_AR5312_REV7:	case AR5212_AR2313_REV8:	case AR5212_AR2315_REV6:	case AR5212_AR2315_REV7:	case AR5212_AR2317_REV1:	case AR5212_DEVID_0014:	case AR5212_DEVID_0015:	case AR5212_DEVID_0016:	case AR5212_DEVID_0017:	case AR5212_DEVID_0018:	case AR5212_DEVID_0019:	case AR5212_AR2413:	case AR5212_AR5413:	case AR5212_AR5424:	case AR5212_DEVID_FF19:		return 5212;	case AR5213_SREV_1_0:	case AR5213_SREV_REG:	case AR_SUBVENDOR_ID_NOG:	case AR_SUBVENDOR_ID_NEW_A:		return 5213;	default: 		return 0; /* unknown */	}}static int ath_set_ack_bitrate(struct ath_softc *sc, int high) {	struct ath_hal *ah = sc->sc_ah;	if (ar_device(sc->devid) == 5212 || ar_device(sc->devid) == 5213) {		/* set ack to be sent at low bit-rate */		/* registers taken from the openbsd 5212 hal */#define AR5K_AR5212_STA_ID1                     0x8004#define AR5K_AR5212_STA_ID1_ACKCTS_6MB          0x01000000#define AR5K_AR5212_STA_ID1_BASE_RATE_11B       0x02000000		u_int32_t v = AR5K_AR5212_STA_ID1_BASE_RATE_11B | AR5K_AR5212_STA_ID1_ACKCTS_6MB;		if (high) {			OS_REG_WRITE(ah, AR5K_AR5212_STA_ID1, OS_REG_READ(ah, AR5K_AR5212_STA_ID1) & ~v);		} else {			OS_REG_WRITE(ah, AR5K_AR5212_STA_ID1, OS_REG_READ(ah, AR5K_AR5212_STA_ID1) | v);		}		return 0;	}	return 1;}/* * Reset the hardware w/o losing operational state.  This is * basically a more efficient way of doing ath_stop, ath_init, * followed by state transitions to the current 802.11 * operational state.  Used to recover from errors rx overrun * and to reset the hardware when rf gain settings must be reset. */static intath_reset(struct net_device *dev){	struct ath_softc *sc = dev->priv;	struct ieee80211com *ic = &sc->sc_ic;	struct ath_hal *ah = sc->sc_ah;	struct ieee80211_channel *c;	HAL_STATUS status;	/*	 * Convert to a HAL channel description with the flags	 * constrained to reflect the current operating mode.	 */	c = ic->ic_curchan;	sc->sc_curchan.channel = c->ic_freq;	sc->sc_curchan.channelFlags = ath_chan2flags(c);	ath_hal_intrset(ah, 0);		/* disable interrupts */	ath_draintxq(sc);		/* stop xmit s

⌨️ 快捷键说明

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