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

📄 main.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  Broadcom B43 wireless driver  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>  Copyright (c) 2005 Stefano Brivio <st3@riseup.net>  Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>  Some parts of the code in this file are derived from the ipw2200  driver  Copyright(c) 2003 - 2004 Intel Corporation.  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 2 of the License, or  (at your option) any later version.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; see the file COPYING.  If not, write to  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,  Boston, MA 02110-1301, USA.*/#include <linux/delay.h>#include <linux/init.h>#include <linux/moduleparam.h>#include <linux/if_arp.h>#include <linux/etherdevice.h>#include <linux/version.h>#include <linux/firmware.h>#include <linux/wireless.h>#include <linux/workqueue.h>#include <linux/skbuff.h>#include <linux/dma-mapping.h>#include <asm/unaligned.h>#include "b43.h"#include "main.h"#include "debugfs.h"#include "phy.h"#include "dma.h"#include "pio.h"#include "sysfs.h"#include "xmit.h"#include "lo.h"#include "pcmcia.h"MODULE_DESCRIPTION("Broadcom B43 wireless driver");MODULE_AUTHOR("Martin Langer");MODULE_AUTHOR("Stefano Brivio");MODULE_AUTHOR("Michael Buesch");MODULE_LICENSE("GPL");extern char *nvram_get(char *name);#if defined(CONFIG_B43_DMA) && defined(CONFIG_B43_PIO)static int modparam_pio;module_param_named(pio, modparam_pio, int, 0444);MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");#elif defined(CONFIG_B43_DMA)# define modparam_pio	0#elif defined(CONFIG_B43_PIO)# define modparam_pio	1#endifstatic int modparam_bad_frames_preempt;module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);MODULE_PARM_DESC(bad_frames_preempt,		 "enable(1) / disable(0) Bad Frames Preemption");static int modparam_short_retry = B43_DEFAULT_SHORT_RETRY_LIMIT;module_param_named(short_retry, modparam_short_retry, int, 0444);MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");static int modparam_long_retry = B43_DEFAULT_LONG_RETRY_LIMIT;module_param_named(long_retry, modparam_long_retry, int, 0444);MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");static char modparam_fwpostfix[16];module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load.");static int modparam_hwpctl;module_param_named(hwpctl, modparam_hwpctl, int, 0444);MODULE_PARM_DESC(hwpctl, "Enable hardware-side power control (default off)");static int modparam_nohwcrypt;module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");static const struct ssb_device_id b43_ssb_tbl[] = {	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 7),	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9),	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13),	SSB_DEVTABLE_END};MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);/* Channel and ratetables are shared for all devices. * They can't be const, because ieee80211 puts some precalculated * data in there. This data is the same for all devices, so we don't * get concurrency issues */#define RATETAB_ENT(_rateid, _flags) \	{							\		.rate	= B43_RATE_TO_BASE100KBPS(_rateid),	\		.val	= (_rateid),				\		.val2	= (_rateid),				\		.flags	= (_flags),				\	}static struct ieee80211_rate __b43_ratetable[] = {	RATETAB_ENT(B43_CCK_RATE_1MB, IEEE80211_RATE_CCK),	RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),	RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),	RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),	RATETAB_ENT(B43_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),	RATETAB_ENT(B43_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),	RATETAB_ENT(B43_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),	RATETAB_ENT(B43_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),	RATETAB_ENT(B43_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),	RATETAB_ENT(B43_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),	RATETAB_ENT(B43_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),	RATETAB_ENT(B43_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),};#define b43_a_ratetable		(__b43_ratetable + 4)#define b43_a_ratetable_size	8#define b43_b_ratetable		(__b43_ratetable + 0)#define b43_b_ratetable_size	4#define b43_g_ratetable		(__b43_ratetable + 0)#define b43_g_ratetable_size	12#define CHANTAB_ENT(_chanid, _freq) \	{							\		.chan	= (_chanid),				\		.freq	= (_freq),				\		.val	= (_chanid),				\		.flag	= IEEE80211_CHAN_W_SCAN |		\			  IEEE80211_CHAN_W_ACTIVE_SCAN |	\			  IEEE80211_CHAN_W_IBSS,		\		.power_level	= 0xFF,				\		.antenna_max	= 0xFF,				\	}static struct ieee80211_channel b43_bg_chantable[] = {	CHANTAB_ENT(1, 2412),	CHANTAB_ENT(2, 2417),	CHANTAB_ENT(3, 2422),	CHANTAB_ENT(4, 2427),	CHANTAB_ENT(5, 2432),	CHANTAB_ENT(6, 2437),	CHANTAB_ENT(7, 2442),	CHANTAB_ENT(8, 2447),	CHANTAB_ENT(9, 2452),	CHANTAB_ENT(10, 2457),	CHANTAB_ENT(11, 2462),	CHANTAB_ENT(12, 2467),	CHANTAB_ENT(13, 2472),	CHANTAB_ENT(14, 2484),};#define b43_bg_chantable_size	ARRAY_SIZE(b43_bg_chantable)static struct ieee80211_channel b43_a_chantable[] = {	CHANTAB_ENT(36, 5180),	CHANTAB_ENT(40, 5200),	CHANTAB_ENT(44, 5220),	CHANTAB_ENT(48, 5240),	CHANTAB_ENT(52, 5260),	CHANTAB_ENT(56, 5280),	CHANTAB_ENT(60, 5300),	CHANTAB_ENT(64, 5320),	CHANTAB_ENT(149, 5745),	CHANTAB_ENT(153, 5765),	CHANTAB_ENT(157, 5785),	CHANTAB_ENT(161, 5805),	CHANTAB_ENT(165, 5825),};#define b43_a_chantable_size	ARRAY_SIZE(b43_a_chantable)static void b43_wireless_core_exit(struct b43_wldev *dev);static int b43_wireless_core_init(struct b43_wldev *dev);static void b43_wireless_core_stop(struct b43_wldev *dev);static int b43_wireless_core_start(struct b43_wldev *dev);static int b43_ratelimit(struct b43_wl *wl){	if (!wl || !wl->current_dev)		return 1;	if (b43_status(wl->current_dev) < B43_STAT_STARTED)		return 1;	/* We are up and running.	 * Ratelimit the messages to avoid DoS over the net. */	return net_ratelimit();}void b43info(struct b43_wl *wl, const char *fmt, ...){	va_list args;	if (!b43_ratelimit(wl))		return;	va_start(args, fmt);	printk(KERN_INFO "b43-%s: ",	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");	vprintk(fmt, args);	va_end(args);}void b43err(struct b43_wl *wl, const char *fmt, ...){	va_list args;	if (!b43_ratelimit(wl))		return;	va_start(args, fmt);	printk(KERN_ERR "b43-%s ERROR: ",	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");	vprintk(fmt, args);	va_end(args);}void b43warn(struct b43_wl *wl, const char *fmt, ...){	va_list args;	if (!b43_ratelimit(wl))		return;	va_start(args, fmt);	printk(KERN_WARNING "b43-%s warning: ",	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");	vprintk(fmt, args);	va_end(args);}#if B43_DEBUGvoid b43dbg(struct b43_wl *wl, const char *fmt, ...){	va_list args;	va_start(args, fmt);	printk(KERN_DEBUG "b43-%s debug: ",	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");	vprintk(fmt, args);	va_end(args);}#endif /* DEBUG */static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val){	u32 macctl;	B43_WARN_ON(offset % 4 != 0);	macctl = b43_read32(dev, B43_MMIO_MACCTL);	if (macctl & B43_MACCTL_BE)		val = swab32(val);	b43_write32(dev, B43_MMIO_RAM_CONTROL, offset);	mmiowb();	b43_write32(dev, B43_MMIO_RAM_DATA, val);}static inline    void b43_shm_control_word(struct b43_wldev *dev, u16 routing, u16 offset){	u32 control;	/* "offset" is the WORD offset. */	control = routing;	control <<= 16;	control |= offset;	b43_write32(dev, B43_MMIO_SHM_CONTROL, control);}u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset){	u32 ret;	if (routing == B43_SHM_SHARED) {		B43_WARN_ON(offset & 0x0001);		if (offset & 0x0003) {			/* Unaligned access */			b43_shm_control_word(dev, routing, offset >> 2);			ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);			ret <<= 16;			b43_shm_control_word(dev, routing, (offset >> 2) + 1);			ret |= b43_read16(dev, B43_MMIO_SHM_DATA);			return ret;		}		offset >>= 2;	}	b43_shm_control_word(dev, routing, offset);	ret = b43_read32(dev, B43_MMIO_SHM_DATA);	return ret;}u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset){	u16 ret;	if (routing == B43_SHM_SHARED) {		B43_WARN_ON(offset & 0x0001);		if (offset & 0x0003) {			/* Unaligned access */			b43_shm_control_word(dev, routing, offset >> 2);			ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);			return ret;		}		offset >>= 2;	}	b43_shm_control_word(dev, routing, offset);	ret = b43_read16(dev, B43_MMIO_SHM_DATA);	return ret;}void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value){	if (routing == B43_SHM_SHARED) {		B43_WARN_ON(offset & 0x0001);		if (offset & 0x0003) {			/* Unaligned access */			b43_shm_control_word(dev, routing, offset >> 2);			mmiowb();			b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED,				    (value >> 16) & 0xffff);			mmiowb();			b43_shm_control_word(dev, routing, (offset >> 2) + 1);			mmiowb();			b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff);			return;		}		offset >>= 2;	}	b43_shm_control_word(dev, routing, offset);	mmiowb();	b43_write32(dev, B43_MMIO_SHM_DATA, value);}void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value){	if (routing == B43_SHM_SHARED) {		B43_WARN_ON(offset & 0x0001);		if (offset & 0x0003) {			/* Unaligned access */			b43_shm_control_word(dev, routing, offset >> 2);			mmiowb();			b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value);			return;		}		offset >>= 2;	}	b43_shm_control_word(dev, routing, offset);	mmiowb();	b43_write16(dev, B43_MMIO_SHM_DATA, value);}/* Read HostFlags */u32 b43_hf_read(struct b43_wldev * dev){	u32 ret;	ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI);	ret <<= 16;	ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO);	return ret;}/* Write HostFlags */void b43_hf_write(struct b43_wldev *dev, u32 value){	b43_shm_write16(dev, B43_SHM_SHARED,			B43_SHM_SH_HOSTFLO, (value & 0x0000FFFF));	b43_shm_write16(dev, B43_SHM_SHARED,			B43_SHM_SH_HOSTFHI, ((value & 0xFFFF0000) >> 16));}void b43_tsf_read(struct b43_wldev *dev, u64 * tsf){	/* We need to be careful. As we read the TSF from multiple	 * registers, we should take care of register overflows.	 * In theory, the whole tsf read process should be atomic.	 * We try to be atomic here, by restaring the read process,	 * if any of the high registers changed (overflew).	 */	if (dev->dev->id.revision >= 3) {		u32 low, high, high2;		do {			high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);			low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW);			high2 = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);		} while (unlikely(high != high2));		*tsf = high;		*tsf <<= 32;		*tsf |= low;	} else {		u64 tmp;		u16 v0, v1, v2, v3;		u16 test1, test2, test3;		do {			v3 = b43_read16(dev, B43_MMIO_TSF_3);			v2 = b43_read16(dev, B43_MMIO_TSF_2);			v1 = b43_read16(dev, B43_MMIO_TSF_1);			v0 = b43_read16(dev, B43_MMIO_TSF_0);			test3 = b43_read16(dev, B43_MMIO_TSF_3);			test2 = b43_read16(dev, B43_MMIO_TSF_2);			test1 = b43_read16(dev, B43_MMIO_TSF_1);		} while (v3 != test3 || v2 != test2 || v1 != test1);		*tsf = v3;		*tsf <<= 48;		tmp = v2;		tmp <<= 32;		*tsf |= tmp;		tmp = v1;		tmp <<= 16;		*tsf |= tmp;		*tsf |= v0;	}}static void b43_time_lock(struct b43_wldev *dev){	u32 macctl;	macctl = b43_read32(dev, B43_MMIO_MACCTL);	macctl |= B43_MACCTL_TBTTHOLD;	b43_write32(dev, B43_MMIO_MACCTL, macctl);	/* Commit the write */	b43_read32(dev, B43_MMIO_MACCTL);}static void b43_time_unlock(struct b43_wldev *dev){	u32 macctl;	macctl = b43_read32(dev, B43_MMIO_MACCTL);	macctl &= ~B43_MACCTL_TBTTHOLD;	b43_write32(dev, B43_MMIO_MACCTL, macctl);	/* Commit the write */	b43_read32(dev, B43_MMIO_MACCTL);}static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf){	/* Be careful with the in-progress timer.	 * First zero out the low register, so we have a full	 * register-overflow duration to complete the operation.	 */	if (dev->dev->id.revision >= 3) {		u32 lo = (tsf & 0x00000000FFFFFFFFULL);		u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;		b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, 0);		mmiowb();		b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, hi);		mmiowb();		b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, lo);	} else {		u16 v0 = (tsf & 0x000000000000FFFFULL);		u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;		u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;		u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;		b43_write16(dev, B43_MMIO_TSF_0, 0);		mmiowb();		b43_write16(dev, B43_MMIO_TSF_3, v3);		mmiowb();		b43_write16(dev, B43_MMIO_TSF_2, v2);		mmiowb();		b43_write16(dev, B43_MMIO_TSF_1, v1);		mmiowb();

⌨️ 快捷键说明

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