aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/bcm43xx/bcm43xx_main.c
diff options
context:
space:
mode:
authorMichael Buesch <mbuesch@freenet.de>2006-02-23 21:15:39 +0100
committerJohn W. Linville <linville@tuxdriver.com>2006-03-27 11:18:40 -0500
commitf398f02d12cdc372e16c5e86246b10acf7211abc (patch)
treee1f705974b5380e43e2308355d461197fa553468 /drivers/net/wireless/bcm43xx/bcm43xx_main.c
parent1d1a73ccdc618168f2a5c962aab250605c93e517 (diff)
[PATCH] bcm43xx: Move TX/RX related functions to its own file. Add basic RTS/CTS code.
Signed-off-by: Michael Buesch <mbuesch@freenet.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/bcm43xx/bcm43xx_main.c')
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c430
1 files changed, 1 insertions, 429 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 899c06fe0bf..f1ac9940f14 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -50,6 +50,7 @@
#include "bcm43xx_power.h"
#include "bcm43xx_wx.h"
#include "bcm43xx_ethtool.h"
+#include "bcm43xx_xmit.h"
MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
@@ -342,234 +343,6 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
}
-static u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp,
- const int ofdm_modulation)
-{
- u8 rate;
-
- if (ofdm_modulation) {
- switch (plcp->raw[0] & 0xF) {
- case 0xB:
- rate = IEEE80211_OFDM_RATE_6MB;
- break;
- case 0xF:
- rate = IEEE80211_OFDM_RATE_9MB;
- break;
- case 0xA:
- rate = IEEE80211_OFDM_RATE_12MB;
- break;
- case 0xE:
- rate = IEEE80211_OFDM_RATE_18MB;
- break;
- case 0x9:
- rate = IEEE80211_OFDM_RATE_24MB;
- break;
- case 0xD:
- rate = IEEE80211_OFDM_RATE_36MB;
- break;
- case 0x8:
- rate = IEEE80211_OFDM_RATE_48MB;
- break;
- case 0xC:
- rate = IEEE80211_OFDM_RATE_54MB;
- break;
- default:
- rate = 0;
- assert(0);
- }
- } else {
- switch (plcp->raw[0]) {
- case 0x0A:
- rate = IEEE80211_CCK_RATE_1MB;
- break;
- case 0x14:
- rate = IEEE80211_CCK_RATE_2MB;
- break;
- case 0x37:
- rate = IEEE80211_CCK_RATE_5MB;
- break;
- case 0x6E:
- rate = IEEE80211_CCK_RATE_11MB;
- break;
- default:
- rate = 0;
- assert(0);
- }
- }
-
- return rate;
-}
-
-static 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;
-}
-
-static 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,
- u16 octets, const u8 bitrate,
- const int ofdm_modulation)
-{
- __le32 *data = &(plcp->data);
- __u8 *raw = plcp->raw;
-
- /* Account for hardware-appended FCS. */
- octets += IEEE80211_FCS_LEN;
-
- 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);
- }
-
-//bcm43xx_printk_bitdump(raw, 4, 0, "PLCP");
-}
-
-void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
- struct bcm43xx_txhdr *txhdr,
- const unsigned char *fragment_data,
- 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_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data;
- const struct ieee80211_security *secinfo = &bcm->ieee->sec;
- u8 bitrate;
- int ofdm_modulation;
- u8 fallback_bitrate;
- int fallback_ofdm_modulation;
- u16 tmp;
- u16 encrypt_frame;
-
- /* Now construct the TX header. */
- memset(txhdr, 0, sizeof(*txhdr));
-
- //TODO: Some RTS/CTS stuff has to be done.
- //TODO: Encryption stuff.
- //TODO: others?
-
- bitrate = bcm->softmac->txrates.default_rate;
- ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
- fallback_bitrate = bcm->softmac->txrates.default_fallback;
- fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
-
- /* Set Frame Control from 80211 header. */
- txhdr->frame_control = wireless_header->frame_ctl;
- /* Copy address1 from 80211 header. */
- memcpy(txhdr->mac1, wireless_header->addr1, 6);
- /* Set the fallback duration ID. */
- //FIXME: We use the original durid for now.
- txhdr->fallback_dur_id = wireless_header->duration_id;
-
- /* Set the cookie (used as driver internal ID for the frame) */
- txhdr->cookie = cpu_to_le16(cookie);
-
- encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
- if (encrypt_frame && !bcm->ieee->host_encrypt) {
- const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
- if (fragment_len <= sizeof(struct ieee80211_hdr_3addr)+4) {
- dprintkl(KERN_ERR PFX "invalid packet with PROTECTED"
- "flag set discarded");
- return;
- }
- memcpy(txhdr->wep_iv, hdr->payload, 4);
- /* Hardware appends ICV. */
- fragment_len += 4;
- }
-
- /* Generate the PLCP header and the fallback PLCP header. */
- bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
- fragment_len,
- bitrate, ofdm_modulation);
- bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, fragment_len,
- fallback_bitrate, fallback_ofdm_modulation);
-
- /* Set the CONTROL field */
- tmp = 0;
- if (ofdm_modulation)
- tmp |= BCM43xx_TXHDRCTL_OFDM;
- if (bcm->short_preamble) //FIXME: could be the other way around, please test
- tmp |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
- tmp |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
- & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
- txhdr->control = cpu_to_le16(tmp);
-
- /* Set the FLAGS field */
- tmp = 0;
- if (!is_multicast_ether_addr(wireless_header->addr1) &&
- !is_broadcast_ether_addr(wireless_header->addr1))
- tmp |= BCM43xx_TXHDRFLAG_EXPECTACK;
- if (1 /* FIXME: PS poll?? */)
- tmp |= 0x10; // FIXME: unknown meaning.
- if (fallback_ofdm_modulation)
- tmp |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
- if (is_first_fragment)
- tmp |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
- txhdr->flags = cpu_to_le16(tmp);
-
- /* Set WSEC/RATE field */
- if (encrypt_frame && !bcm->ieee->host_encrypt) {
- tmp = (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
- & BCM43xx_TXHDR_WSEC_ALGO_MASK;
- tmp |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
- & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
- txhdr->wsec_rate = cpu_to_le16(tmp);
- }
-
-//bcm43xx_printk_bitdump((const unsigned char *)txhdr, sizeof(*txhdr), 1, "TX header");
-}
-
static
void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
u16 offset,
@@ -3773,207 +3546,6 @@ err_pci_disable:
goto out;
}
-static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
- u8 in_rssi, int ofdm,
- int adjust_2053, int adjust_2050)
-{
- s32 tmp;
-
- switch (bcm->current_core->radio->version) {
- case 0x2050:
- if (ofdm) {
- tmp = in_rssi;
- if (tmp > 127)
- tmp -= 256;
- tmp *= 73;
- tmp /= 64;
- if (adjust_2050)
- tmp += 25;
- else
- tmp -= 3;
- } else {
- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
- if (in_rssi > 63)
- in_rssi = 63;
- tmp = bcm->current_core->radio->nrssi_lt[in_rssi];
- tmp = 31 - tmp;
- tmp *= -131;
- tmp /= 128;
- tmp -= 57;
- } else {
- tmp = in_rssi;
- tmp = 31 - tmp;
- tmp *= -149;
- tmp /= 128;
- tmp -= 68;
- }
- if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G &&
- adjust_2050)
- tmp += 25;
- }
- break;
- case 0x2060:
- if (in_rssi > 127)
- tmp = in_rssi - 256;
- else
- tmp = in_rssi;
- break;
- default:
- tmp = in_rssi;
- tmp -= 11;
- tmp *= 103;
- tmp /= 64;
- if (adjust_2053)
- tmp -= 109;
- else
- tmp -= 83;
- }
-
- return (s8)tmp;
-}
-
-static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
- u8 in_rssi)
-{
- s8 ret;
-
- if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) {
- //TODO: Incomplete specs.
- ret = 0;
- } else
- ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
-
- return ret;
-}
-
-static inline
-int bcm43xx_rx_packet(struct bcm43xx_private *bcm,
- struct sk_buff *skb,
- struct ieee80211_rx_stats *stats)
-{
- int err;
-
- err = ieee80211_rx(bcm->ieee, skb, stats);
- if (unlikely(err == 0))
- return -EINVAL;
- return 0;
-}
-
-int bcm43xx_rx(struct bcm43xx_private *bcm,
- struct sk_buff *skb,
- struct bcm43xx_rxhdr *rxhdr)
-{
- struct bcm43xx_plcp_hdr4 *plcp;
- struct ieee80211_rx_stats stats;
- struct ieee80211_hdr_4addr *wlhdr;
- u16 frame_ctl;
- int is_packet_for_us = 0;
- int err = -EINVAL;
- const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
- const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
- const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
- const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
-
- if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
- plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
- /* Skip two unknown bytes and the PLCP header. */
- skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
- } else {
- plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
- /* Skip the PLCP header. */
- skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
- }
- /* The SKB contains the PAYLOAD (wireless header + data)
- * at this point. The FCS at the end is stripped.
- */
-
- memset(&stats, 0, sizeof(stats));
- stats.mac_time = le16_to_cpu(rxhdr->mactime);
- stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
- !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
- !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
- stats.signal = rxhdr->signal_quality; //FIXME
-//TODO stats.noise =
- stats.rate = bcm43xx_plcp_get_bitrate(plcp, is_ofdm);
-//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
- stats.received_channel = bcm->current_core->radio->channel;
-//TODO stats.control =
- stats.mask = IEEE80211_STATMASK_SIGNAL |
-//TODO IEEE80211_STATMASK_NOISE |
- IEEE80211_STATMASK_RATE |
- IEEE80211_STATMASK_RSSI;
- if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A)
- stats.freq = IEEE80211_52GHZ_BAND;
- else
- stats.freq = IEEE80211_24GHZ_BAND;
- stats.len = skb->len;
-
- bcm->stats.last_rx = jiffies;
- if (bcm->ieee->iw_mode == IW_MODE_MONITOR)
- return bcm43xx_rx_packet(bcm, skb, &stats);
-
- wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
-
- switch (bcm->ieee->iw_mode) {
- case IW_MODE_ADHOC:
- if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
- memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
- is_broadcast_ether_addr(wlhdr->addr1) ||
- is_multicast_ether_addr(wlhdr->addr1) ||
- bcm->net_dev->flags & IFF_PROMISC)
- is_packet_for_us = 1;
- break;
- case IW_MODE_INFRA:
- default:
- /* When receiving multicast or broadcast packets, filter out
- the packets we send ourself; we shouldn't see those */
- if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
- memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
- (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
- (is_broadcast_ether_addr(wlhdr->addr1) ||
- is_multicast_ether_addr(wlhdr->addr1) ||
- bcm->net_dev->flags & IFF_PROMISC)))
- is_packet_for_us = 1;
- break;
- }
-
- frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
- if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
- frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
- wlhdr->frame_ctl = cpu_to_le16(frame_ctl);
- /* trim IV and ICV */
- /* FIXME: this must be done only for WEP encrypted packets */
- if (skb->len < 32) {
- dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
- "set and length < 32)\n");
- return -EINVAL;
- } else {
- memmove(skb->data + 4, skb->data, 24);
- skb_pull(skb, 4);
- skb_trim(skb, skb->len - 4);
- stats.len -= 8;
- }
- wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
- }
-
- switch (WLAN_FC_GET_TYPE(frame_ctl)) {
- case IEEE80211_FTYPE_MGMT:
- ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
- break;
- case IEEE80211_FTYPE_DATA:
- if (is_packet_for_us)
- err = bcm43xx_rx_packet(bcm, skb, &stats);
- break;
- case IEEE80211_FTYPE_CTL:
- break;
- default:
- assert(0);
- return -EINVAL;
- }
-
- return err;
-}
-
/* Do the Hardware IO operations to send the txb */
static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
struct ieee80211_txb *txb)