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

📄 bcm43xx_xmit.c

📁 博通的bcm43xx系列Minipci接口无线网卡驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  Broadcom BCM43xx wireless driver  Transmission (TX/RX) related functions.  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,                     Stefano Brivio <st3@riseup.net>                     Michael Buesch <mbuesch@freenet.de>                     Danny van Dyk <kugelfang@gentoo.org>                     Andreas Jaggi <andreas.jaggi@waterwave.ch>  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 "bcm43xx_xmit.h"#include <linux/etherdevice.h>/* Extract the bitrate out of a CCK PLCP header. */static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp){	switch (plcp->raw[0]) {	case 0x0A:		return IEEE80211_CCK_RATE_1MB;	case 0x14:		return IEEE80211_CCK_RATE_2MB;	case 0x37:		return IEEE80211_CCK_RATE_5MB;	case 0x6E:		return IEEE80211_CCK_RATE_11MB;	}	assert(0);	return 0;}/* Extract the bitrate out of an OFDM PLCP header. */static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp){	switch (plcp->raw[0] & 0xF) {	case 0xB:		return IEEE80211_OFDM_RATE_6MB;	case 0xF:		return IEEE80211_OFDM_RATE_9MB;	case 0xA:		return IEEE80211_OFDM_RATE_12MB;	case 0xE:		return IEEE80211_OFDM_RATE_18MB;	case 0x9:		return IEEE80211_OFDM_RATE_24MB;	case 0xD:		return IEEE80211_OFDM_RATE_36MB;	case 0x8:		return IEEE80211_OFDM_RATE_48MB;	case 0xC:		return IEEE80211_OFDM_RATE_54MB;	}	assert(0);	return 0;}u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate){	switch (bitrate) {	case IEEE80211_CCK_RATE_1MB:		return 0x0A;	case IEEE80211_CCK_RATE_2MB:		return 0x14;	case IEEE80211_CCK_RATE_5MB:		return 0x37;	case IEEE80211_CCK_RATE_11MB:		return 0x6E;	}	assert(0);	return 0;}u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate){	switch (bitrate) {	case IEEE80211_OFDM_RATE_6MB:		return 0xB;	case IEEE80211_OFDM_RATE_9MB:		return 0xF;	case IEEE80211_OFDM_RATE_12MB:		return 0xA;	case IEEE80211_OFDM_RATE_18MB:		return 0xE;	case IEEE80211_OFDM_RATE_24MB:		return 0x9;	case IEEE80211_OFDM_RATE_36MB:		return 0xD;	case IEEE80211_OFDM_RATE_48MB:		return 0x8;	case IEEE80211_OFDM_RATE_54MB:		return 0xC;	}	assert(0);	return 0;}static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,				      const u16 octets, const u8 bitrate,				      const int ofdm_modulation){	__le32 *data = &(plcp->data);	__u8 *raw = plcp->raw;	if (ofdm_modulation) {		*data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);		assert(!(octets & 0xF000));		*data |= (octets << 5);		*data = cpu_to_le32(*data);	} else {		u32 plen;		plen = octets * 16 / bitrate;		if ((octets * 16 % bitrate) > 0) {			plen++;			if ((bitrate == IEEE80211_CCK_RATE_11MB)			    && ((octets * 8 % 11) < 4)) {				raw[1] = 0x84;			} else				raw[1] = 0x04;		} else			raw[1] = 0x04;		*data |= cpu_to_le32(plen << 16);		raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);	}}static u8 bcm43xx_calc_fallback_rate(u8 bitrate){	switch (bitrate) {	case IEEE80211_CCK_RATE_1MB:		return IEEE80211_CCK_RATE_1MB;	case IEEE80211_CCK_RATE_2MB:		return IEEE80211_CCK_RATE_1MB;	case IEEE80211_CCK_RATE_5MB:		return IEEE80211_CCK_RATE_2MB;	case IEEE80211_CCK_RATE_11MB:		return IEEE80211_CCK_RATE_5MB;	case IEEE80211_OFDM_RATE_6MB:		return IEEE80211_CCK_RATE_5MB;	case IEEE80211_OFDM_RATE_9MB:		return IEEE80211_OFDM_RATE_6MB;	case IEEE80211_OFDM_RATE_12MB:		return IEEE80211_OFDM_RATE_9MB;	case IEEE80211_OFDM_RATE_18MB:		return IEEE80211_OFDM_RATE_12MB;	case IEEE80211_OFDM_RATE_24MB:		return IEEE80211_OFDM_RATE_18MB;	case IEEE80211_OFDM_RATE_36MB:		return IEEE80211_OFDM_RATE_24MB;	case IEEE80211_OFDM_RATE_48MB:		return IEEE80211_OFDM_RATE_36MB;	case IEEE80211_OFDM_RATE_54MB:		return IEEE80211_OFDM_RATE_48MB;	}	assert(0);	return 0;}static__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,				u8 bitrate){	const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);	__le16 duration_id = wireless_header->duration_id;	switch (WLAN_FC_GET_TYPE(frame_ctl)) {	case IEEE80211_FTYPE_DATA:	case IEEE80211_FTYPE_MGMT:		//TODO: Steal the code from ieee80211, once it is completed there.		break;	case IEEE80211_FTYPE_CTL:		/* Use the original duration/id. */		break;	default:		assert(0);	}	return duration_id;}static inlineu16 ceiling_div(u16 dividend, u16 divisor){	return ((dividend + divisor - 1) / divisor);}static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,				 struct bcm43xx_txhdr *txhdr,				 u16 *flags,				 u8 bitrate,				 const struct ieee80211_hdr_4addr *wlhdr){	u16 fctl;	u16 dur;	u8 fallback_bitrate;	int ofdm_modulation;	int fallback_ofdm_modulation;	u8 *sa, *da;	u16 flen;//FIXME	sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);//FIXME	da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);	fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);	ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));	fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));	flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,	bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),				  flen, bitrate,				  !ieee80211_is_cck_rate(bitrate));	bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),				  flen, fallback_bitrate,				  !ieee80211_is_cck_rate(fallback_bitrate));	fctl = IEEE80211_FTYPE_CTL;	fctl |= IEEE80211_STYPE_RTS;	dur = le16_to_cpu(wlhdr->duration_id);/*FIXME: should we test for dur==0 here and let it unmodified in this case? *       The following assert checks for this case... */assert(dur);/*FIXME: The duration calculation is not really correct. *       I am not 100% sure which bitrate to use. We use the RTS rate here, *       but this is likely to be wrong. */	if (phy->type == BCM43xx_PHYTYPE_A) {		/* Three times SIFS */		dur += 16 * 3;		/* Add ACK duration. */		dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,				   bitrate * 4);		/* Add CTS duration. */		dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,				   bitrate * 4);	} else {		/* Three times SIFS */		dur += 10 * 3;		/* Add ACK duration. */		dur += ceiling_div(8 * (14 /*bytes*/) * 10,				   bitrate);		/* Add CTS duration. */		dur += ceiling_div(8 * (14 /*bytes*/) * 10,				   bitrate);	}	txhdr->rts_cts_frame_control = cpu_to_le16(fctl);	txhdr->rts_cts_dur = cpu_to_le16(dur);//printk(BCM43xx_MACFMT "  " BCM43xx_MACFMT "  " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));//printk(BCM43xx_MACFMT "  " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));	memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!	memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);	*flags |= BCM43xx_TXHDRFLAG_RTSCTS;	*flags |= BCM43xx_TXHDRFLAG_RTS;	if (ofdm_modulation)		*flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;	if (fallback_ofdm_modulation)		*flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;}				 void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,			    struct bcm43xx_txhdr *txhdr,			    const unsigned char *fragment_data,			    const unsigned int fragment_len,			    const int is_first_fragment,			    const u16 cookie){	const struct bcm43xx_phyinfo *phy = bcm->current_core->phy;	const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;	const struct ieee80211_security *secinfo = &bcm->ieee->sec;	u8 bitrate;

⌨️ 快捷键说明

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