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

📄 ipw2200.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.  802.11 status code portion of this file from ethereal-0.10.6:    Copyright 2000, Axis Communications AB    Ethereal - Network traffic analyzer    By Gerald Combs <gerald@ethereal.com>    Copyright 1998 Gerald Combs  This program is free software; you can redistribute it and/or modify it  under the terms of version 2 of the GNU General Public License as  published by the Free Software Foundation.  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; if not, write to the Free Software Foundation, Inc., 59  Temple Place - Suite 330, Boston, MA  02111-1307, USA.  The full GNU General Public License is included in this distribution in the  file called LICENSE.  Contact Information:  James P. Ketrenos <ipw2100-admin@linux.intel.com>  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497******************************************************************************/#include "ipw2200.h"#include <linux/version.h>#define IPW2200_VERSION "git-1.0.8"#define DRV_DESCRIPTION	"Intel(R) PRO/Wireless 2200/2915 Network Driver"#define DRV_COPYRIGHT	"Copyright(c) 2003-2005 Intel Corporation"#define DRV_VERSION     IPW2200_VERSION#define ETH_P_80211_STATS (ETH_P_80211_RAW + 1)MODULE_DESCRIPTION(DRV_DESCRIPTION);MODULE_VERSION(DRV_VERSION);MODULE_AUTHOR(DRV_COPYRIGHT);MODULE_LICENSE("GPL");static int cmdlog = 0;static int debug = 0;static int channel = 0;static int mode = 0;static u32 ipw_debug_level;static int associate = 1;static int auto_create = 1;static int led = 0;static int disable = 0;static int hwcrypto = 1;static const char ipw_modes[] = {	'a', 'b', 'g', '?'};#ifdef CONFIG_IPW_QOSstatic int qos_enable = 0;static int qos_burst_enable = 0;static int qos_no_ack_mask = 0;static int burst_duration_CCK = 0;static int burst_duration_OFDM = 0;static struct ieee80211_qos_parameters def_qos_parameters_OFDM = {	{QOS_TX0_CW_MIN_OFDM, QOS_TX1_CW_MIN_OFDM, QOS_TX2_CW_MIN_OFDM,	 QOS_TX3_CW_MIN_OFDM},	{QOS_TX0_CW_MAX_OFDM, QOS_TX1_CW_MAX_OFDM, QOS_TX2_CW_MAX_OFDM,	 QOS_TX3_CW_MAX_OFDM},	{QOS_TX0_AIFS, QOS_TX1_AIFS, QOS_TX2_AIFS, QOS_TX3_AIFS},	{QOS_TX0_ACM, QOS_TX1_ACM, QOS_TX2_ACM, QOS_TX3_ACM},	{QOS_TX0_TXOP_LIMIT_OFDM, QOS_TX1_TXOP_LIMIT_OFDM,	 QOS_TX2_TXOP_LIMIT_OFDM, QOS_TX3_TXOP_LIMIT_OFDM}};static struct ieee80211_qos_parameters def_qos_parameters_CCK = {	{QOS_TX0_CW_MIN_CCK, QOS_TX1_CW_MIN_CCK, QOS_TX2_CW_MIN_CCK,	 QOS_TX3_CW_MIN_CCK},	{QOS_TX0_CW_MAX_CCK, QOS_TX1_CW_MAX_CCK, QOS_TX2_CW_MAX_CCK,	 QOS_TX3_CW_MAX_CCK},	{QOS_TX0_AIFS, QOS_TX1_AIFS, QOS_TX2_AIFS, QOS_TX3_AIFS},	{QOS_TX0_ACM, QOS_TX1_ACM, QOS_TX2_ACM, QOS_TX3_ACM},	{QOS_TX0_TXOP_LIMIT_CCK, QOS_TX1_TXOP_LIMIT_CCK, QOS_TX2_TXOP_LIMIT_CCK,	 QOS_TX3_TXOP_LIMIT_CCK}};static struct ieee80211_qos_parameters def_parameters_OFDM = {	{DEF_TX0_CW_MIN_OFDM, DEF_TX1_CW_MIN_OFDM, DEF_TX2_CW_MIN_OFDM,	 DEF_TX3_CW_MIN_OFDM},	{DEF_TX0_CW_MAX_OFDM, DEF_TX1_CW_MAX_OFDM, DEF_TX2_CW_MAX_OFDM,	 DEF_TX3_CW_MAX_OFDM},	{DEF_TX0_AIFS, DEF_TX1_AIFS, DEF_TX2_AIFS, DEF_TX3_AIFS},	{DEF_TX0_ACM, DEF_TX1_ACM, DEF_TX2_ACM, DEF_TX3_ACM},	{DEF_TX0_TXOP_LIMIT_OFDM, DEF_TX1_TXOP_LIMIT_OFDM,	 DEF_TX2_TXOP_LIMIT_OFDM, DEF_TX3_TXOP_LIMIT_OFDM}};static struct ieee80211_qos_parameters def_parameters_CCK = {	{DEF_TX0_CW_MIN_CCK, DEF_TX1_CW_MIN_CCK, DEF_TX2_CW_MIN_CCK,	 DEF_TX3_CW_MIN_CCK},	{DEF_TX0_CW_MAX_CCK, DEF_TX1_CW_MAX_CCK, DEF_TX2_CW_MAX_CCK,	 DEF_TX3_CW_MAX_CCK},	{DEF_TX0_AIFS, DEF_TX1_AIFS, DEF_TX2_AIFS, DEF_TX3_AIFS},	{DEF_TX0_ACM, DEF_TX1_ACM, DEF_TX2_ACM, DEF_TX3_ACM},	{DEF_TX0_TXOP_LIMIT_CCK, DEF_TX1_TXOP_LIMIT_CCK, DEF_TX2_TXOP_LIMIT_CCK,	 DEF_TX3_TXOP_LIMIT_CCK}};static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };static int from_priority_to_tx_queue[] = {	IPW_TX_QUEUE_1, IPW_TX_QUEUE_2, IPW_TX_QUEUE_2, IPW_TX_QUEUE_1,	IPW_TX_QUEUE_3, IPW_TX_QUEUE_3, IPW_TX_QUEUE_4, IPW_TX_QUEUE_4};static u32 ipw_qos_get_burst_duration(struct ipw_priv *priv);static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters				       *qos_param);static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element				     *qos_param);#endif				/* CONFIG_IPW_QOS */static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev);static void ipw_remove_current_network(struct ipw_priv *priv);static void ipw_rx(struct ipw_priv *priv);static int ipw_queue_tx_reclaim(struct ipw_priv *priv,				struct clx2_tx_queue *txq, int qindex);static int ipw_queue_reset(struct ipw_priv *priv);static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf,			     int len, int sync);static void ipw_tx_queue_free(struct ipw_priv *);static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *);static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *);static void ipw_rx_queue_replenish(void *);static int ipw_up(struct ipw_priv *);static void ipw_bg_up(void *);static void ipw_down(struct ipw_priv *);static void ipw_bg_down(void *);static int ipw_config(struct ipw_priv *);static int init_supported_rates(struct ipw_priv *priv,				struct ipw_supported_rates *prates);static void ipw_set_hwcrypto_keys(struct ipw_priv *);static void ipw_send_wep_keys(struct ipw_priv *, int);static int ipw_is_valid_channel(struct ieee80211_device *, u8);static int ipw_channel_to_index(struct ieee80211_device *, u8);static u8 ipw_freq_to_channel(struct ieee80211_device *, u32);static int ipw_set_geo(struct ieee80211_device *, const struct ieee80211_geo *);static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *);static int snprint_line(char *buf, size_t count,			const u8 * data, u32 len, u32 ofs){	int out, i, j, l;	char c;	out = snprintf(buf, count, "%08X", ofs);	for (l = 0, i = 0; i < 2; i++) {		out += snprintf(buf + out, count - out, " ");		for (j = 0; j < 8 && l < len; j++, l++)			out += snprintf(buf + out, count - out, "%02X ",					data[(i * 8 + j)]);		for (; j < 8; j++)			out += snprintf(buf + out, count - out, "   ");	}	out += snprintf(buf + out, count - out, " ");	for (l = 0, i = 0; i < 2; i++) {		out += snprintf(buf + out, count - out, " ");		for (j = 0; j < 8 && l < len; j++, l++) {			c = data[(i * 8 + j)];			if (!isascii(c) || !isprint(c))				c = '.';			out += snprintf(buf + out, count - out, "%c", c);		}		for (; j < 8; j++)			out += snprintf(buf + out, count - out, " ");	}	return out;}static void printk_buf(int level, const u8 * data, u32 len){	char line[81];	u32 ofs = 0;	if (!(ipw_debug_level & level))		return;	while (len) {		snprint_line(line, sizeof(line), &data[ofs],			     min(len, 16U), ofs);		printk(KERN_DEBUG "%s\n", line);		ofs += 16;		len -= min(len, 16U);	}}static int snprintk_buf(u8 * output, size_t size, const u8 * data, size_t len){	size_t out = size;	u32 ofs = 0;	int total = 0;	while (size && len) {		out = snprint_line(output, size, &data[ofs],				   min_t(size_t, len, 16U), ofs);		ofs += 16;		output += out;		size -= out;		len -= min_t(size_t, len, 16U);		total += out;	}	return total;}static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg);#define ipw_read_reg32(a, b) _ipw_read_reg32(a, b)static u8 _ipw_read_reg8(struct ipw_priv *ipw, u32 reg);#define ipw_read_reg8(a, b) _ipw_read_reg8(a, b)static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value);static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c){	IPW_DEBUG_IO("%s %d: write_indirect8(0x%08X, 0x%08X)\n", __FILE__,		     __LINE__, (u32) (b), (u32) (c));	_ipw_write_reg8(a, b, c);}static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value);static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c){	IPW_DEBUG_IO("%s %d: write_indirect16(0x%08X, 0x%08X)\n", __FILE__,		     __LINE__, (u32) (b), (u32) (c));	_ipw_write_reg16(a, b, c);}static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value);static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c){	IPW_DEBUG_IO("%s %d: write_indirect32(0x%08X, 0x%08X)\n", __FILE__,		     __LINE__, (u32) (b), (u32) (c));	_ipw_write_reg32(a, b, c);}#define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs))#define ipw_write8(ipw, ofs, val) \ IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ _ipw_write8(ipw, ofs, val)#define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs))#define ipw_write16(ipw, ofs, val) \ IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ _ipw_write16(ipw, ofs, val)#define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs))#define ipw_write32(ipw, ofs, val) \ IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ _ipw_write32(ipw, ofs, val)#define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs))static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs){	IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs));	return _ipw_read8(ipw, ofs);}#define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs)#define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs))static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs){	IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs));	return _ipw_read16(ipw, ofs);}#define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs)#define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs))static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs){	IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs));	return _ipw_read32(ipw, ofs);}#define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs)static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int);static inline void __ipw_read_indirect(const char *f, int l,				       struct ipw_priv *a, u32 b, u8 * c, int d){	IPW_DEBUG_IO("%s %d: read_indirect(0x%08X) %d bytes\n", f, l, (u32) (b),		     d);	_ipw_read_indirect(a, b, c, d);}#define ipw_read_indirect(a, b, c, d) __ipw_read_indirect(__FILE__, __LINE__, a, b, c, d)static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data,				int num);#define ipw_write_indirect(a, b, c, d) \	IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \	_ipw_write_indirect(a, b, c, d)/* indirect write s */static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value){	IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value);	_ipw_write32(priv, IPW_INDIRECT_ADDR, reg);	_ipw_write32(priv, IPW_INDIRECT_DATA, value);}static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value){	IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);	_ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK);	_ipw_write8(priv, IPW_INDIRECT_DATA, value);}static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value){	IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);	_ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK);	_ipw_write16(priv, IPW_INDIRECT_DATA, value);}/* indirect read s */static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg){	u32 word;	_ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK);	IPW_DEBUG_IO(" reg = 0x%8X : \n", reg);	word = _ipw_read32(priv, IPW_INDIRECT_DATA);	return (word >> ((reg & 0x3) * 8)) & 0xff;}static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg){	u32 value;	IPW_DEBUG_IO("%p : reg = 0x%08x\n", priv, reg);	_ipw_write32(priv, IPW_INDIRECT_ADDR, reg);	value = _ipw_read32(priv, IPW_INDIRECT_DATA);	IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value);	return value;}/* iterative/auto-increment 32 bit reads and writes */static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,			       int num){	u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK;	u32 dif_len = addr - aligned_addr;	u32 i;	IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num);	if (num <= 0) {		return;	}	/* Read the first nibble byte by byte */	if (unlikely(dif_len)) {		_ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);		/* Start reading at aligned_addr + dif_len */		for (i = dif_len; ((i < 4) && (num > 0)); i++, num--)			*buf++ = _ipw_read8(priv, IPW_INDIRECT_DATA + i);		aligned_addr += 4;	}	_ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr);	for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4)		*(u32 *) buf = _ipw_read32(priv, IPW_AUTOINC_DATA);	/* Copy the last nibble */	if (unlikely(num)) {		_ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);		for (i = 0; num > 0; i++, num--)			*buf++ = ipw_read8(priv, IPW_INDIRECT_DATA + i);	}}static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,				int num){	u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK;	u32 dif_len = addr - aligned_addr;	u32 i;	IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num);	if (num <= 0) {		return;	}	/* Write the first nibble byte by byte */	if (unlikely(dif_len)) {		_ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);		/* Start reading at aligned_addr + dif_len */		for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++)			_ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf);		aligned_addr += 4;	}	_ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr);	for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4)		_ipw_write32(priv, IPW_AUTOINC_DATA, *(u32 *) buf);	/* Copy the last nibble */	if (unlikely(num)) {		_ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);		for (i = 0; num > 0; i++, num--, buf++)			_ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf);	}}static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf,			     int num){	memcpy_toio((priv->hw_base + addr), buf, num);}static inline void ipw_set_bit(struct ipw_priv *priv, u32 reg, u32 mask){	ipw_write32(priv, reg, ipw_read32(priv, reg) | mask);}static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask){	ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask);}static inline void ipw_enable_interrupts(struct ipw_priv *priv){	if (priv->status & STATUS_INT_ENABLED)		return;	priv->status |= STATUS_INT_ENABLED;	ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL);}static inline void ipw_disable_interrupts(struct ipw_priv *priv){	if (!(priv->status & STATUS_INT_ENABLED))		return;	priv->status &= ~STATUS_INT_ENABLED;	ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL);}#ifdef CONFIG_IPW_DEBUGstatic char *ipw_error_desc(u32 val){	switch (val) {	case IPW_FW_ERROR_OK:		return "ERROR_OK";	case IPW_FW_ERROR_FAIL:		return "ERROR_FAIL";	case IPW_FW_ERROR_MEMORY_UNDERFLOW:		return "MEMORY_UNDERFLOW";	case IPW_FW_ERROR_MEMORY_OVERFLOW:		return "MEMORY_OVERFLOW";	case IPW_FW_ERROR_BAD_PARAM:		return "BAD_PARAM";	case IPW_FW_ERROR_BAD_CHECKSUM:		return "BAD_CHECKSUM";	case IPW_FW_ERROR_NMI_INTERRUPT:		return "NMI_INTERRUPT";	case IPW_FW_ERROR_BAD_DATABASE:		return "BAD_DATABASE";	case IPW_FW_ERROR_ALLOC_FAIL:		return "ALLOC_FAIL";	case IPW_FW_ERROR_DMA_UNDERRUN:		return "DMA_UNDERRUN";

⌨️ 快捷键说明

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