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

📄 if_ath.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/*- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer, *    without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any *    redistribution must be conditioned upon including a substantially *    similar Disclaimer requirement for further binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names *    of any contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $Id: if_ath.c 1680 2006-07-08 06:47:19Z proski $ *//* * Driver for the Atheros Wireless LAN controller. * * This software is derived from work of Atsushi Onoe; his contribution * is greatly appreciated. */#include "opt_ah.h"#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/init.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/random.h>#include <linux/delay.h>#include <linux/cache.h>#include <linux/sysctl.h>#include <linux/proc_fs.h>#include <linux/if_arp.h>#include <linux/rtnetlink.h>#include <asm/uaccess.h>#include "if_ethersubr.h"		/* for ETHER_IS_MULTICAST */#include "if_media.h"#include "if_llc.h"#include <net80211/ieee80211_radiotap.h>#include <net80211/ieee80211_var.h>#include <net80211/ieee80211_monitor.h>#ifdef USE_HEADERLEN_RESV#include <net80211/if_llc.h>#endif#define	AR_DEBUG#include "if_athrate.h"#include "net80211/if_athproto.h"#include "if_athvar.h"#include "ah_desc.h"#include "ah_devid.h"			/* XXX to identify IBM cards */#ifdef ATH_PCI		/* PCI BUS */#include "if_ath_pci.h"#endif			/* PCI BUS */#ifdef ATH_AHB		/* AHB BUS */#include "if_ath_ahb.h"#endif			/* AHB BUS */#ifdef ATH_TX99_DIAG#include "ath_tx99.h"#endif/* unaligned little endian access */#define LE_READ_2(p)							\	((u_int16_t)							\	 ((((u_int8_t *)(p))[0]      ) | (((u_int8_t *)(p))[1] <<  8)))#define LE_READ_4(p)							\	((u_int32_t)							\	 ((((u_int8_t *)(p))[0]      ) | (((u_int8_t *)(p))[1] <<  8) |	\	  (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24)))enum {	ATH_LED_TX,	ATH_LED_RX,	ATH_LED_POLL,};static struct ieee80211vap *ath_vap_create(struct ieee80211com *,	const char *, int, int, int, struct net_device *);static void ath_vap_delete(struct ieee80211vap *);static int ath_init(struct net_device *);static int ath_set_ack_bitrate(struct ath_softc *, int);static int ath_reset(struct net_device *);static void ath_fatal_tasklet(TQUEUE_ARG);static void ath_rxorn_tasklet(TQUEUE_ARG);static void ath_bmiss_tasklet(TQUEUE_ARG);static void ath_bstuck_tasklet(TQUEUE_ARG);static void ath_radar_task(TQUEUE_ARG);static void ath_dfs_test_return(unsigned long);static int ath_stop_locked(struct net_device *);static int ath_stop(struct net_device *);#if 0static void ath_initkeytable(struct ath_softc *);#endifstatic int ath_key_alloc(struct ieee80211vap *, const struct ieee80211_key *);static int ath_key_delete(struct ieee80211vap *, const struct ieee80211_key *,	struct ieee80211_node *);static int ath_key_set(struct ieee80211vap *, const struct ieee80211_key *,	const u_int8_t mac[IEEE80211_ADDR_LEN]);static void ath_key_update_begin(struct ieee80211vap *);static void ath_key_update_end(struct ieee80211vap *);static void ath_mode_init(struct net_device *);static void ath_setslottime(struct ath_softc *);static void ath_updateslot(struct net_device *);static int ath_beaconq_setup(struct ath_hal *);static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *);#ifdef ATH_SUPERG_DYNTURBOstatic void ath_beacon_dturbo_update(struct ieee80211vap *, int *, u_int8_t);static void ath_beacon_dturbo_config(struct ieee80211vap *, u_int32_t);static void ath_turbo_switch_mode(unsigned long);static int ath_check_beacon_done(struct ath_softc *);#endifstatic void ath_beacon_send(struct ath_softc *, int *);static void ath_beacon_start_adhoc(struct ath_softc *, struct ieee80211vap *);static void ath_beacon_return(struct ath_softc *, struct ath_buf *);static void ath_beacon_free(struct ath_softc *);static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *);static int ath_desc_alloc(struct ath_softc *);static void ath_desc_free(struct ath_softc *);static void ath_desc_swap(struct ath_desc *);static struct ieee80211_node *ath_node_alloc(struct ieee80211_node_table *,	struct ieee80211vap *);static void ath_node_cleanup(struct ieee80211_node *);static void ath_node_free(struct ieee80211_node *);static u_int8_t ath_node_getrssi(const struct ieee80211_node *);static int ath_rxbuf_init(struct ath_softc *, struct ath_buf *);static void ath_recv_mgmt(struct ieee80211_node *, struct sk_buff *, int,	int, u_int32_t);static void ath_setdefantenna(struct ath_softc *, u_int);static struct ath_txq *ath_txq_setup(struct ath_softc *, int, int);static void ath_rx_tasklet(TQUEUE_ARG);static int ath_hardstart(struct sk_buff *, struct net_device *);static int ath_mgtstart(struct ieee80211com *, struct sk_buff *);#ifdef ATH_SUPERG_COMPstatic u_int32_t ath_get_icvlen(struct ieee80211_key *);static u_int32_t ath_get_ivlen(struct ieee80211_key *);static void ath_setup_comp(struct ieee80211_node *, int);static void ath_comp_set(struct ieee80211vap *, struct ieee80211_node *, int);	#endifstatic int ath_tx_setup(struct ath_softc *, int, int);static int ath_wme_update(struct ieee80211com *);static void ath_uapsd_flush(struct ieee80211_node *);static void ath_tx_cleanupq(struct ath_softc *, struct ath_txq *);static void ath_tx_cleanup(struct ath_softc *);static void ath_tx_uapsdqueue(struct ath_softc *, struct ath_node *,	struct ath_buf *);static int ath_tx_start(struct net_device *, struct ieee80211_node *,	struct ath_buf *, struct sk_buff *, int);static void ath_tx_tasklet_q0(TQUEUE_ARG);static void ath_tx_tasklet_q0123(TQUEUE_ARG);static void ath_tx_tasklet(TQUEUE_ARG);static void ath_tx_timeout(struct net_device *);static void ath_tx_draintxq(struct ath_softc *, struct ath_txq *);static int ath_chan_set(struct ath_softc *, struct ieee80211_channel *);static void ath_draintxq(struct ath_softc *);static __inline void ath_tx_txqaddbuf(struct ath_softc *, struct ieee80211_node *,	struct ath_txq *, struct ath_buf *, struct ath_desc *, int);static void ath_stoprecv(struct ath_softc *);static int ath_startrecv(struct ath_softc *);static void ath_flushrecv(struct ath_softc *);static void ath_chan_change(struct ath_softc *, struct ieee80211_channel *);static void ath_calibrate(unsigned long);static int ath_newstate(struct ieee80211vap *, enum ieee80211_state, int);static void ath_scan_start(struct ieee80211com *);static void ath_scan_end(struct ieee80211com *);static void ath_set_channel(struct ieee80211com *);static void ath_set_coverageclass(struct ieee80211com *);static u_int ath_mhz2ieee(struct ieee80211com *, u_int, u_int);#ifdef ATH_SUPERG_FFstatic int athff_can_aggregate(struct ath_softc *, struct ether_header *,	struct ath_node *, struct sk_buff *, u_int16_t, int *);#endifstatic struct net_device_stats *ath_getstats(struct net_device *);static void ath_setup_stationkey(struct ieee80211_node *);static void ath_setup_stationwepkey(struct ieee80211_node *);static void ath_setup_keycacheslot(struct ath_softc *, struct ieee80211_node *);static void ath_newassoc(struct ieee80211_node *, int);static int ath_getchannels(struct net_device *, u_int, HAL_BOOL, HAL_BOOL);static void ath_led_event(struct ath_softc *, int);static void ath_update_txpow(struct ath_softc *);static int ath_set_mac_address(struct net_device *, void *);static int ath_change_mtu(struct net_device *, int);static int ath_ioctl(struct net_device *, struct ifreq *, int);static int ath_rate_setup(struct net_device *, u_int);static void ath_setup_subrates(struct net_device *);#ifdef ATH_SUPERG_XRstatic int ath_xr_rate_setup(struct net_device *);static void ath_grppoll_txq_setup(struct ath_softc *, int, int);static void ath_grppoll_start(struct ieee80211vap *, int);static void ath_grppoll_stop(struct ieee80211vap *);static u_int8_t ath_node_move_data(const struct ieee80211_node *);static void ath_grppoll_txq_update(struct ath_softc *, int);static void ath_grppoll_period_update(struct ath_softc *);#endifstatic void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);#ifdef CONFIG_SYSCTLstatic void ath_dynamic_sysctl_register(struct ath_softc *);static void ath_dynamic_sysctl_unregister(struct ath_softc *);#endif /* CONFIG_SYSCTL */static void ath_announce(struct net_device *);static int ath_descdma_setup(struct ath_softc *, struct ath_descdma *,	ath_bufhead *, const char *, int, int);static void ath_descdma_cleanup(struct ath_softc *, struct ath_descdma *,	ath_bufhead *, int);static void ath_check_dfs_clear(unsigned long);static const char *ath_get_hal_status_desc(HAL_STATUS status);static int ath_rcv_dev_event(struct notifier_block *, unsigned long, void *);	static int ath_calinterval = ATH_SHORT_CALINTERVAL;		/*								 * calibrate every 30 secs in steady state								 * but check every second at first.								 */static int ath_countrycode = CTRY_DEFAULT;	/* country code */static int ath_outdoor = AH_FALSE;		/* enable outdoor use */static int ath_xchanmode = AH_TRUE;		/* enable extended channels */static char *autocreate = NULL;static int rfkill = -1;static int countrycode = -1;static int outdoor = -1;static int xchanmode = -1;static const char *hal_status_desc[] = {	"No error",	"No hardware present or device not yet supported",	"Memory allocation failed",	"Hardware didn't respond as expected",	"EEPROM magic number invalid",	"EEPROM version invalid",	"EEPROM unreadable",	"EEPROM checksum invalid",	"EEPROM read problem",	"EEPROM mac address invalid",	"EEPROM size not supported",	"Attempt to change write-locked EEPROM",	"Invalid parameter to function",	"Hardware revision not supported",	"Hardware self-test failed",	"Operation incomplete"};static struct notifier_block ath_event_block = {        .notifier_call = ath_rcv_dev_event};#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))MODULE_PARM(countrycode, "i");MODULE_PARM(outdoor, "i");MODULE_PARM(xchanmode, "i");MODULE_PARM(rfkill, "i");MODULE_PARM(autocreate, "s");#else#include <linux/moduleparam.h>module_param(countrycode, int, 0);module_param(outdoor, int, 0);module_param(xchanmode, int, 0);module_param(rfkill, int, 0);module_param(autocreate, charp, 0);#endifMODULE_PARM_DESC(countrycode, "Override default country code");MODULE_PARM_DESC(outdoor, "Enable/disable outdoor use");MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode");MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability");MODULE_PARM_DESC(autocreate, "Create ath device in [sta|ap|wds|adhoc|ahdemo|monitor] mode. defaults to sta, use 'none' to disable");static int	ath_debug = 0;#ifdef AR_DEBUG#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))MODULE_PARM(ath_debug, "i");#elsemodule_param(ath_debug, int, 0);#endifMODULE_PARM_DESC(ath_debug, "Load-time debug output enable");#define	IFF_DUMPPKTS(sc, _m) \	((sc->sc_debug & _m))static void ath_printrxbuf(struct ath_buf *, int);static void ath_printtxbuf(struct ath_buf *, int);enum {	ATH_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */	ATH_DEBUG_XMIT_DESC	= 0x00000002,	/* xmit descriptors */	ATH_DEBUG_RECV		= 0x00000004,	/* basic recv operation */	ATH_DEBUG_RECV_DESC	= 0x00000008,	/* recv descriptors */	ATH_DEBUG_RATE		= 0x00000010,	/* rate control */	ATH_DEBUG_RESET		= 0x00000020,	/* reset processing */	/* 0x00000040 was ATH_DEBUG_MODE */	ATH_DEBUG_BEACON 	= 0x00000080,	/* beacon handling */	ATH_DEBUG_WATCHDOG 	= 0x00000100,	/* watchdog timeout */	ATH_DEBUG_INTR		= 0x00001000,	/* ISR */	ATH_DEBUG_TX_PROC	= 0x00002000,	/* tx ISR proc */	ATH_DEBUG_RX_PROC	= 0x00004000,	/* rx ISR proc */	ATH_DEBUG_BEACON_PROC	= 0x00008000,	/* beacon ISR proc */	ATH_DEBUG_CALIBRATE	= 0x00010000,	/* periodic calibration */	ATH_DEBUG_KEYCACHE	= 0x00020000,	/* key cache management */	ATH_DEBUG_STATE		= 0x00040000,	/* 802.11 state transitions */	ATH_DEBUG_NODE		= 0x00080000,	/* node management */	ATH_DEBUG_LED		= 0x00100000,	/* led management */	ATH_DEBUG_FF		= 0x00200000,	/* fast frames */	ATH_DEBUG_TURBO		= 0x00400000,	/* turbo/dynamice turbo */	ATH_DEBUG_UAPSD		= 0x00800000,	/* uapsd */	ATH_DEBUG_DOTH		= 0x01000000,	/* 11.h */	ATH_DEBUG_FATAL		= 0x80000000,	/* fatal errors */	ATH_DEBUG_ANY		= 0xffffffff};#define	DPRINTF(sc, _m, _fmt, ...) do {				\	if (sc->sc_debug & (_m))				\		printk(_fmt, __VA_ARGS__);			\} while (0)#define	KEYPRINTF(sc, ix, hk, mac) do {				\	if (sc->sc_debug & ATH_DEBUG_KEYCACHE)			\		ath_keyprint(__func__, ix, hk, mac);		\} while (0)#else /* defined(AR_DEBUG) */#define	IFF_DUMPPKTS(sc, _m)	netif_msg_dumppkts(&sc->sc_ic)#define	DPRINTF(sc, _m, _fmt, ...)#define	KEYPRINTF(sc, k, ix, mac)#endif /* defined(AR_DEBUG) */#define ATH_SETUP_XR_VAP(sc,vap,rfilt) \	do { \		if (sc->sc_curchan.privFlags & CHANNEL_4MS_LIMIT) \			vap->iv_fragthreshold = XR_4MS_FRAG_THRESHOLD; \		else \			vap->iv_fragthreshold = vap->iv_xrvap->iv_fragthreshold; \		if (!sc->sc_xrgrppoll) { \			ath_grppoll_txq_setup(sc, HAL_TX_QUEUE_DATA, GRP_POLL_PERIOD_NO_XR_STA(sc)); \			ath_grppoll_start(vap, sc->sc_xrpollcount); \			ath_hal_setrxfilter(sc->sc_ah, rfilt|HAL_RX_FILTER_XRPOLL); \		} \   	} while(0)/* * Define the scheme that we select MAC address for multiple BSS on the same radio. * The very first VAP will just use the MAC address from the EEPROM. * For the next 3 VAPs, we set the U/L bit (bit 1) in MAC address, * and use the next two bits as the index of the VAP. */#define ATH_SET_VAP_BSSID_MASK(bssid_mask)      ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02))#define ATH_GET_VAP_ID(bssid)                   ((bssid)[0] >> 2)#define ATH_SET_VAP_BSSID(bssid, id)            \    	do {                                    \		if (id)                            \            		(bssid)[0] |= (((id) << 2) | 0x02); \	} while(0)intath_attach(u_int16_t devid, struct net_device *dev){	struct ath_softc *sc = dev->priv;	struct ieee80211com *ic = &sc->sc_ic;	struct ath_hal *ah;	HAL_STATUS status;	int error = 0, i;	int autocreatemode = IEEE80211_M_STA;	u_int8_t csz;	sc->devid = devid;	sc->sc_debug = ath_debug;	DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);	/*	 * Cache line size is used to size and align various	 * structures used to communicate with the hardware.	 */	bus_read_cachesize(sc, &csz);	/* XXX assert csz is non-zero */	sc->sc_cachelsz = csz << 2;		/* convert to bytes */	ATH_LOCK_INIT(sc);	ATH_TXBUF_LOCK_INIT(sc);	ATH_RXBUF_LOCK_INIT(sc);	ATH_INIT_TQUEUE(&sc->sc_rxtq,	 ath_rx_tasklet,	dev);	ATH_INIT_TQUEUE(&sc->sc_txtq,	 ath_tx_tasklet,	dev);	ATH_INIT_TQUEUE(&sc->sc_bmisstq, ath_bmiss_tasklet,	dev);	ATH_INIT_TQUEUE(&sc->sc_bstucktq,ath_bstuck_tasklet,	dev);	ATH_INIT_TQUEUE(&sc->sc_rxorntq, ath_rxorn_tasklet,	dev);	ATH_INIT_TQUEUE(&sc->sc_fataltq, ath_fatal_tasklet,	dev);	ATH_INIT_SCHED_TASK(&sc->sc_radartask, ath_radar_task,	dev);	/*	 * Attach the hal and verify ABI compatibility by checking	 * the hal's ABI signature against the one the driver was	 * compiled with.  A mismatch indicates the driver was	 * built with an ah.h that does not correspond to the hal	 * module loaded in the kernel.	 */

⌨️ 快捷键说明

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