This if file 10 of 10 of the port of the bcm43xx driver from softmac
to mac80211.
Signed-off-by: Larry Finger <[EMAIL PROTECTED]>
---
Index: linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
===================================================================
--- linux-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+++ linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -4,11 +4,12 @@
Transmission (TX/RX) related functions.
- Copyright (c) 2005 Martin Langer <[EMAIL PROTECTED]>,
- Stefano Brivio <[EMAIL PROTECTED]>
- Michael Buesch <[EMAIL PROTECTED]>
- Danny van Dyk <[EMAIL PROTECTED]>
- Andreas Jaggi <[EMAIL PROTECTED]>
+ Copyright (C) 2005 Martin Langer <[EMAIL PROTECTED]>
+ Copyright (C) 2005 Stefano Brivio <[EMAIL PROTECTED]>
+ Copyright (C) 2005, 2006 Michael Buesch <[EMAIL PROTECTED]>
+ Copyright (C) 2005 Danny van Dyk <[EMAIL PROTECTED]>
+ Copyright (C) 2005 Andreas Jaggi <[EMAIL PROTECTED]>
+ Copyright (C) 2007 Larry Finger <[EMAIL PROTECTED]>
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
@@ -27,103 +28,105 @@
*/
-#include "bcm43xx_xmit.h"
+#include <net/dst.h>
-#include <linux/etherdevice.h>
+#include "bcm43xx_xmit.h"
+#include "bcm43xx_phy.h"
+#include "bcm43xx_dma.h"
+#include "bcm43xx_pio.h"
/* Extract the bitrate out of a CCK PLCP header. */
-static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
+static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr6 *plcp)
{
switch (plcp->raw[0]) {
case 0x0A:
- return IEEE80211_CCK_RATE_1MB;
+ return BCM43xx_CCK_RATE_1MB;
case 0x14:
- return IEEE80211_CCK_RATE_2MB;
+ return BCM43xx_CCK_RATE_2MB;
case 0x37:
- return IEEE80211_CCK_RATE_5MB;
+ return BCM43xx_CCK_RATE_5MB;
case 0x6E:
- return IEEE80211_CCK_RATE_11MB;
+ return BCM43xx_CCK_RATE_11MB;
}
- assert(0);
+ BCM43xx_BUG_ON(1);
return 0;
}
/* Extract the bitrate out of an OFDM PLCP header. */
-static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
+static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr6 *plcp)
{
switch (plcp->raw[0] & 0xF) {
case 0xB:
- return IEEE80211_OFDM_RATE_6MB;
+ return BCM43xx_OFDM_RATE_6MB;
case 0xF:
- return IEEE80211_OFDM_RATE_9MB;
+ return BCM43xx_OFDM_RATE_9MB;
case 0xA:
- return IEEE80211_OFDM_RATE_12MB;
+ return BCM43xx_OFDM_RATE_12MB;
case 0xE:
- return IEEE80211_OFDM_RATE_18MB;
+ return BCM43xx_OFDM_RATE_18MB;
case 0x9:
- return IEEE80211_OFDM_RATE_24MB;
+ return BCM43xx_OFDM_RATE_24MB;
case 0xD:
- return IEEE80211_OFDM_RATE_36MB;
+ return BCM43xx_OFDM_RATE_36MB;
case 0x8:
- return IEEE80211_OFDM_RATE_48MB;
+ return BCM43xx_OFDM_RATE_48MB;
case 0xC:
- return IEEE80211_OFDM_RATE_54MB;
+ return BCM43xx_OFDM_RATE_54MB;
}
- assert(0);
+ BCM43xx_BUG_ON(1);
return 0;
}
u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
{
switch (bitrate) {
- case IEEE80211_CCK_RATE_1MB:
+ case BCM43xx_CCK_RATE_1MB:
return 0x0A;
- case IEEE80211_CCK_RATE_2MB:
+ case BCM43xx_CCK_RATE_2MB:
return 0x14;
- case IEEE80211_CCK_RATE_5MB:
+ case BCM43xx_CCK_RATE_5MB:
return 0x37;
- case IEEE80211_CCK_RATE_11MB:
+ case BCM43xx_CCK_RATE_11MB:
return 0x6E;
}
- assert(0);
+ BCM43xx_BUG_ON(1);
return 0;
}
u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
{
switch (bitrate) {
- case IEEE80211_OFDM_RATE_6MB:
+ case BCM43xx_OFDM_RATE_6MB:
return 0xB;
- case IEEE80211_OFDM_RATE_9MB:
+ case BCM43xx_OFDM_RATE_9MB:
return 0xF;
- case IEEE80211_OFDM_RATE_12MB:
+ case BCM43xx_OFDM_RATE_12MB:
return 0xA;
- case IEEE80211_OFDM_RATE_18MB:
+ case BCM43xx_OFDM_RATE_18MB:
return 0xE;
- case IEEE80211_OFDM_RATE_24MB:
+ case BCM43xx_OFDM_RATE_24MB:
return 0x9;
- case IEEE80211_OFDM_RATE_36MB:
+ case BCM43xx_OFDM_RATE_36MB:
return 0xD;
- case IEEE80211_OFDM_RATE_48MB:
+ case BCM43xx_OFDM_RATE_48MB:
return 0x8;
- case IEEE80211_OFDM_RATE_54MB:
+ case BCM43xx_OFDM_RATE_54MB:
return 0xC;
}
- assert(0);
+ BCM43xx_BUG_ON(1);
return 0;
}
-static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
- const u16 octets, const u8 bitrate,
- const int ofdm_modulation)
+void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
+ const u16 octets, const u8 bitrate)
{
__le32 *data = &(plcp->data);
__u8 *raw = plcp->raw;
- if (ofdm_modulation) {
+ if (bcm43xx_is_ofdm_rate(bitrate)) {
*data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
- assert(!(octets & 0xF000));
+ BCM43xx_WARN_ON(octets & 0xF000);
*data |= (octets << 5);
*data = cpu_to_le32(*data);
} else {
@@ -132,13 +135,14 @@ static void bcm43xx_generate_plcp_hdr(st
plen = octets * 16 / bitrate;
if ((octets * 16 % bitrate) > 0) {
plen++;
- if ((bitrate == IEEE80211_CCK_RATE_11MB)
- && ((octets * 8 % 11) < 4)) {
+ if ((bitrate == BCM43xx_CCK_RATE_11MB)
+ && ((octets * 8 % 11) < 4))
raw[1] = 0x84;
- } else
+ else
raw[1] = 0x04;
- } else
+ } else {
raw[1] = 0x04;
+ }
*data |= cpu_to_le32(plen << 16);
raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
}
@@ -147,249 +151,216 @@ static void bcm43xx_generate_plcp_hdr(st
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;
+ case BCM43xx_CCK_RATE_1MB:
+ return BCM43xx_CCK_RATE_1MB;
+ case BCM43xx_CCK_RATE_2MB:
+ return BCM43xx_CCK_RATE_1MB;
+ case BCM43xx_CCK_RATE_5MB:
+ return BCM43xx_CCK_RATE_2MB;
+ case BCM43xx_CCK_RATE_11MB:
+ return BCM43xx_CCK_RATE_5MB;
+ case BCM43xx_OFDM_RATE_6MB:
+ return BCM43xx_CCK_RATE_5MB;
+ case BCM43xx_OFDM_RATE_9MB:
+ return BCM43xx_OFDM_RATE_6MB;
+ case BCM43xx_OFDM_RATE_12MB:
+ return BCM43xx_OFDM_RATE_9MB;
+ case BCM43xx_OFDM_RATE_18MB:
+ return BCM43xx_OFDM_RATE_12MB;
+ case BCM43xx_OFDM_RATE_24MB:
+ return BCM43xx_OFDM_RATE_18MB;
+ case BCM43xx_OFDM_RATE_36MB:
+ return BCM43xx_OFDM_RATE_24MB;
+ case BCM43xx_OFDM_RATE_48MB:
+ return BCM43xx_OFDM_RATE_36MB;
+ case BCM43xx_OFDM_RATE_54MB:
+ return BCM43xx_OFDM_RATE_48MB;
}
- assert(0);
+ BCM43xx_BUG_ON(1);
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);
- }
+static void generate_txhdr_fw3(struct bcm43xx_wldev *dev,
+ struct bcm43xx_txhdr_fw3 *txhdr,
+ const unsigned char *fragment_data,
+ unsigned int fragment_len,
+ const struct ieee80211_tx_control *txctl,
+ u16 cookie)
+{
+ const struct ieee80211_hdr *wlhdr;
+ int use_encryption = ((!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
+ && (txctl->key_idx >= 0));
+ u16 fctl;
+ u8 rate;
+ u8 rate_fb;
+ int rate_ofdm;
+ int rate_fb_ofdm;
+ unsigned int plcp_fragment_len;
+ u32 mac_ctl = 0;
+ u16 phy_ctl = 0;
- return duration_id;
-}
+ wlhdr = (const struct ieee80211_hdr *)fragment_data;
+ fctl = le16_to_cpu(wlhdr->frame_control);
-static inline
-u16 ceiling_div(u16 dividend, u16 divisor)
-{
- return ((dividend + divisor - 1) / divisor);
-}
+ memset(txhdr, 0, sizeof(*txhdr));
-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);
+ rate = txctl->tx_rate;
+ rate_ofdm = bcm43xx_is_ofdm_rate(rate);
+ rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
+ rate_fb_ofdm = bcm43xx_is_ofdm_rate(rate_fb);
+
+ txhdr->mac_frame_ctl = wlhdr->frame_control;
+ memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
+
+ /* Calculate duration for fallback rate */
+ if ((rate_fb == rate) ||
+ (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
+ (wlhdr->duration_id == cpu_to_le16(0))) {
+ /* If the fallback rate equals the normal rate or the
+ * dur_id field contains an AID, CFP magic or 0,
+ * use the original dur_id field. */
+ txhdr->dur_fb = wlhdr->duration_id;
} 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 = bcm43xx_current_phy(bcm);
- const struct ieee80211_hdr_4addr *wireless_header = (const struct
ieee80211_hdr_4addr *)fragment_data;
- const struct ieee80211_security *secinfo = &bcm->ieee->sec;
- u8 bitrate;
- u8 fallback_bitrate;
- int ofdm_modulation;
- int fallback_ofdm_modulation;
- u16 plcp_fragment_len = fragment_len;
- u16 flags = 0;
- u16 control = 0;
- u16 wsec_rate = 0;
- u16 encrypt_frame;
- const u16 ftype =
WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl));
- const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT);
+ int fbrate_base100kbps = BCM43xx_RATE_TO_100KBPS(rate_fb);
+ txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
+ fragment_len,
+ fbrate_base100kbps);
+ }
+
+ plcp_fragment_len = fragment_len + FCS_LEN;
+ if (use_encryption) {
+ u8 key_idx = (u16)(txctl->key_idx);
+ struct bcm43xx_key *key;
+ int wlhdr_len;
+ size_t iv_len;
+
+ BCM43xx_WARN_ON(key_idx >= dev->max_nr_keys);
+ key = &(dev->key[key_idx]);
+
+ if (key->enabled) {
+ /* Hardware appends ICV. */
+ plcp_fragment_len += txctl->icv_len;
+
+ key_idx = bcm43xx_kidx_to_fw(dev, key_idx);
+ mac_ctl |= (key_idx << BCM43xx_TX4_MAC_KEYIDX_SHIFT) &
+ BCM43xx_TX4_MAC_KEYIDX;
+ mac_ctl |= (key->algorithm <<
+ BCM43xx_TX4_MAC_KEYALG_SHIFT) &
+ BCM43xx_TX4_MAC_KEYALG;
+ wlhdr_len = ieee80211_get_hdrlen(fctl);
+ iv_len = min((size_t)txctl->iv_len,
+ ARRAY_SIZE(txhdr->iv));
+ memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
+ }
+ }
+ bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
+ plcp_fragment_len, rate);
+ bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp_fb),
+ plcp_fragment_len, rate_fb);
+
+ /* PHY TX Control word */
+ if (rate_ofdm)
+ phy_ctl |= BCM43xx_TX4_PHY_OFDM;
+ if (dev->short_preamble)
+ phy_ctl |= BCM43xx_TX4_PHY_SHORTPRMBL;
+ switch (txctl->antenna_sel_tx) {
+ case 0:
+ phy_ctl |= BCM43xx_TX4_PHY_ANTLAST;
+ break;
+ case 1:
+ phy_ctl |= BCM43xx_TX4_PHY_ANT0;
+ break;
+ case 2:
+ phy_ctl |= BCM43xx_TX4_PHY_ANT1;
+ break;
+ default:
+ BCM43xx_BUG_ON(1);
+ }
- /* Now construct the TX header. */
- memset(txhdr, 0, sizeof(*txhdr));
+ /* MAC control */
+ if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK))
+ mac_ctl |= BCM43xx_TX4_MAC_ACK;
+ if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+ ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)))
+ mac_ctl |= BCM43xx_TX4_MAC_HWSEQ;
+ if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
+ mac_ctl |= BCM43xx_TX4_MAC_STMSDU;
+ if (rate_fb_ofdm)
+ mac_ctl |= BCM43xx_TX4_MAC_FALLBACKOFDM;
+
+ /* Generate the RTS or CTS-to-self frame */
+ if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
+ (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
+ unsigned int len;
+ struct ieee80211_hdr *hdr;
+ int rts_rate;
+ int rts_rate_fb;
+ int rts_rate_ofdm;
+ int rts_rate_fb_ofdm;
+
+ rts_rate = txctl->rts_cts_rate;
+ rts_rate_ofdm = bcm43xx_is_ofdm_rate(rts_rate);
+ rts_rate_fb = bcm43xx_calc_fallback_rate(rts_rate);
+ rts_rate_fb_ofdm = bcm43xx_is_ofdm_rate(rts_rate_fb);
+ if (rts_rate_fb_ofdm)
+ mac_ctl |= BCM43xx_TX4_MAC_CTSFALLBACKOFDM;
+
+ if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
+ ieee80211_ctstoself_get(dev->wl->hw,
+ fragment_data,
+ fragment_len, txctl,
+ (struct ieee80211_cts *)
+ (txhdr->rts_frame));
+ mac_ctl |= BCM43xx_TX4_MAC_SENDCTS;
+ len = sizeof(struct ieee80211_cts);
+ } else {
+ ieee80211_rts_get(dev->wl->hw,
+ fragment_data, fragment_len, txctl,
+ (struct ieee80211_rts *)
+ (txhdr->rts_frame));
+ mac_ctl |= BCM43xx_TX4_MAC_SENDRTS;
+ len = sizeof(struct ieee80211_rts);
+ }
+ len += FCS_LEN;
+ bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)
+ (&txhdr->rts_plcp),
+ len, rts_rate);
+ bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)
+ (&txhdr->rts_plcp_fb),
+ len, rts_rate_fb);
+ hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame);
+ txhdr->rts_dur_fb = hdr->duration_id;
+ mac_ctl |= BCM43xx_TX4_MAC_LONGFRAME;
+ }
- bitrate = ieee80211softmac_suggest_txrate(bcm->softmac,
- is_multicast_ether_addr(wireless_header->addr1), is_mgt);
- ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
- fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
- 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. */
- txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct
ieee80211_hdr *)wireless_header,
- fallback_bitrate);
- /* Set the cookie (used as driver internal ID for the frame) */
+ /* Magic cookie */
txhdr->cookie = cpu_to_le16(cookie);
- /* Hardware appends FCS. */
- plcp_fragment_len += IEEE80211_FCS_LEN;
-
- /* Hardware encryption. */
- 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;
- memcpy(txhdr->wep_iv, hdr->payload, 4);
- /* Hardware appends ICV. */
- plcp_fragment_len += 4;
-
- wsec_rate |= (bcm->key[secinfo->active_key].algorithm <<
BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
- & BCM43xx_TXHDR_WSEC_ALGO_MASK;
- wsec_rate |= (secinfo->active_key <<
BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
- & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
- }
+ /* Apply the bitfields */
+ txhdr->mac_ctl = cpu_to_le32(mac_ctl);
+ txhdr->phy_ctl = cpu_to_le16(phy_ctl);
+}
- /* Generate the PLCP header and the fallback PLCP header. */
- bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
- plcp_fragment_len,
- bitrate, ofdm_modulation);
- bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
- fallback_bitrate, fallback_ofdm_modulation);
-
- /* Set the CONTROL field */
- if (ofdm_modulation)
- control |= BCM43xx_TXHDRCTL_OFDM;
- if (bcm->short_preamble) //FIXME: could be the other way around, please
test
- control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
- control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
- & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
-
- /* Set the FLAGS field */
- if (!is_multicast_ether_addr(wireless_header->addr1) &&
- !is_broadcast_ether_addr(wireless_header->addr1))
- flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
- if (1 /* FIXME: PS poll?? */)
- flags |= 0x10; // FIXME: unknown meaning.
- if (fallback_ofdm_modulation)
- flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
- if (is_first_fragment)
- flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
-
- /* Set WSEC/RATE field */
- wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
- & BCM43xx_TXHDR_RATE_MASK;
-
- /* Generate the RTS/CTS packet, if required. */
- /* FIXME: We should first try with CTS-to-self,
- * if we are on 80211g. If we get too many
- * failures (hidden nodes), we should switch back to RTS/CTS.
- */
- if (0/*FIXME txctl->use_rts_cts*/) {
- bcm43xx_generate_rts(phy, txhdr, &flags,
- 0/*FIXME txctl->rts_cts_rate*/,
- wireless_header);
- }
-
- txhdr->flags = cpu_to_le16(flags);
- txhdr->control = cpu_to_le16(control);
- txhdr->wsec_rate = cpu_to_le16(wsec_rate);
+void bcm43xx_generate_txhdr(struct bcm43xx_wldev *dev,
+ u8 *txhdr,
+ const unsigned char *fragment_data,
+ unsigned int fragment_len,
+ const struct ieee80211_tx_control *txctl,
+ u16 cookie)
+{
+ generate_txhdr_fw3(dev, (struct bcm43xx_txhdr_fw3 *)txhdr,
+ fragment_data, fragment_len,
+ txctl, cookie);
}
-static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
+static s8 bcm43xx_rssi_postprocess(struct bcm43xx_wldev *dev,
u8 in_rssi, int ofdm,
int adjust_2053, int adjust_2050)
{
- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_phy *phy = &dev->phy;
s32 tmp;
- switch (radio->version) {
+ switch (phy->radio_ver) {
case 0x2050:
if (ofdm) {
tmp = in_rssi;
@@ -402,10 +373,11 @@ static s8 bcm43xx_rssi_postprocess(struc
else
tmp -= 3;
} else {
- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+ if (dev->dev->bus->sprom.r1.boardflags_lo
+ & BCM43xx_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
- tmp = radio->nrssi_lt[in_rssi];
+ tmp = phy->nrssi_lt[in_rssi];
tmp = 31 - tmp;
tmp *= -131;
tmp /= 128;
@@ -442,124 +414,221 @@ static s8 bcm43xx_rssi_postprocess(struc
return (s8)tmp;
}
-//TODO
-#if 0
-static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
- u8 in_rssi)
-{
- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
- s8 ret;
-
- if (phy->type == BCM43xx_PHYTYPE_A) {
- //TODO: Incomplete specs.
- ret = 0;
- } else
- ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
-
- return ret;
-}
-#endif
-
-int bcm43xx_rx(struct bcm43xx_private *bcm,
- struct sk_buff *skb,
- struct bcm43xx_rxhdr *rxhdr)
-{
- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
- 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 = rxhdr->rssi;
- stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
- !!(rxflags1 &
BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
- !!(rxflags3 &
BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
- stats.noise = bcm->stats.noise;
- if (is_ofdm)
- stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
- else
- stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
- stats.received_channel = radio->channel;
- stats.mask = IEEE80211_STATMASK_SIGNAL |
- IEEE80211_STATMASK_NOISE |
- IEEE80211_STATMASK_RATE |
- IEEE80211_STATMASK_RSSI;
- if (phy->type == BCM43xx_PHYTYPE_A)
- stats.freq = IEEE80211_52GHZ_BAND;
- else
- stats.freq = IEEE80211_24GHZ_BAND;
- stats.len = skb->len;
+void bcm43xx_rx(struct bcm43xx_wldev *dev,
+ struct sk_buff *skb,
+ const void *_rxhdr)
+{
+ struct ieee80211_rx_status status;
+ struct bcm43xx_plcp_hdr6 *plcp;
+ struct ieee80211_hdr *wlhdr;
+ const struct bcm43xx_rxhdr_fw3 *rxhdr = _rxhdr;
+ u16 fctl;
+ u16 phystat0;
+ u16 phystat3;
+ u16 chanstat;
+ u16 mactime;
+ u32 macstat;
+ u16 chanid;
+ u8 jssi;
+ int padding;
+
+ memset(&status, 0, sizeof(status));
+
+ /* Get metadata about the frame from the header. */
+ phystat0 = le16_to_cpu(rxhdr->phy_status0);
+ phystat3 = le16_to_cpu(rxhdr->phy_status3);
+ jssi = rxhdr->jssi;
+ macstat = le32_to_cpu(rxhdr->mac_status);
+ mactime = le16_to_cpu(rxhdr->mac_time);
+ chanstat = le16_to_cpu(rxhdr->channel);
+
+ if (macstat & BCM43xx_RX_MAC_FCSERR)
+ dev->wl->ieee_stats.dot11FCSErrorCount++;
+
+ /* Skip PLCP and padding */
+ padding = (macstat & BCM43xx_RX_MAC_PADDING) ? 2 : 0;
+ if (unlikely(skb->len < (sizeof(struct bcm43xx_plcp_hdr6) + padding))) {
+ bcmdbg(dev->wl, "RX: Packet size underrun (1)\n");
+ goto drop;
+ }
+ plcp = (struct bcm43xx_plcp_hdr6 *)(skb->data + padding);
+ skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6) + padding);
+ /* The skb contains the Wireless Header + payload data now */
+ if (unlikely(skb->len < (2+2+6/*minimum hdr*/ + FCS_LEN))) {
+ bcmdbg(dev->wl, "RX: Packet size underrun (2)\n");
+ goto drop;
+ }
+ wlhdr = (struct ieee80211_hdr *)(skb->data);
+ fctl = le16_to_cpu(wlhdr->frame_control);
+ skb_trim(skb, skb->len - FCS_LEN);
+
+ if ((macstat & BCM43xx_RX_MAC_DEC) &&
+ !(macstat & BCM43xx_RX_MAC_DECERR)) {
+ unsigned int keyidx;
+ int wlhdr_len;
+ int iv_len;
+ int icv_len;
+
+ keyidx = ((macstat & BCM43xx_RX_MAC_KEYIDX)
+ >> BCM43xx_RX_MAC_KEYIDX_SHIFT);
+ /* We must adjust the key index here. We want the "physical"
+ * key index, but the ucode passed it slightly different.
+ */
+ keyidx = bcm43xx_kidx_to_raw(dev, keyidx);
+ BCM43xx_WARN_ON(keyidx >= dev->max_nr_keys);
+
+ if (dev->key[keyidx].algorithm != BCM43xx_SEC_ALGO_NONE) {
+ /* Remove PROTECTED flag to mark it as decrypted. */
+ BCM43xx_WARN_ON(!(fctl & IEEE80211_FCTL_PROTECTED));
+ fctl &= ~IEEE80211_FCTL_PROTECTED;
+ wlhdr->frame_control = cpu_to_le16(fctl);
+
+ wlhdr_len = ieee80211_get_hdrlen(fctl);
+ if (unlikely(skb->len < (wlhdr_len + 3))) {
+ bcmdbg(dev->wl, "RX: Packet size underrun3\n");
+ goto drop;
+ }
+ if (skb->data[wlhdr_len + 3] & (1 << 5)) {
+ /* The Ext-IV Bit is set in the "KeyID"
+ * octet of the IV.
+ */
+ iv_len = 8;
+ icv_len = 8;
+ } else {
+ iv_len = 4;
+ icv_len = 4;
+ }
+ if (unlikely(skb->len < (wlhdr_len + iv_len +
+ icv_len))) {
+ bcmdbg(dev->wl, "RX: Packet size underrun4\n");
+ goto drop;
+ }
+ /* Remove the IV */
+ memmove(skb->data + iv_len, skb->data, wlhdr_len);
+ skb_pull(skb, iv_len);
+ /* Remove the ICV */
+ skb_trim(skb, skb->len - icv_len);
- bcm->stats.last_rx = jiffies;
- if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
- err = ieee80211_rx(bcm->ieee, skb, &stats);
- return (err == 0) ? -EINVAL : 0;
- }
-
- 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;
+ status.flag |= RX_FLAG_DECRYPTED;
+ }
}
- frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
- 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 = ieee80211_rx(bcm->ieee, skb, &stats);
- err = (err == 0) ? -EINVAL : 0;
- }
+ status.ssi = bcm43xx_rssi_postprocess(dev, jssi,
+ (phystat0 & BCM43xx_RX_PHYST0_OFDM),
+ (phystat0 & BCM43xx_RX_PHYST0_GAINCTL),
+ (phystat3 & BCM43xx_RX_PHYST3_TRSTATE));
+ status.noise = dev->stats.link_noise;
+ status.signal = jssi * 100 / BCM43xx_RX_MAX_SSI;
+ if (phystat0 & BCM43xx_RX_PHYST0_OFDM)
+ status.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
+ else
+ status.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
+ status.antenna = !!(phystat0 & BCM43xx_RX_PHYST0_ANT);
+ status.mactime = mactime;
+
+ chanid = (chanstat & BCM43xx_RX_CHAN_ID) >> BCM43xx_RX_CHAN_ID_SHIFT;
+ switch (chanstat & BCM43xx_RX_CHAN_PHYTYPE) {
+ case BCM43xx_PHYTYPE_B:
+ status.phymode = MODE_IEEE80211B;
+ status.freq = chanid + 2400;
+ status.channel = bcm43xx_freq_to_channel_bg(chanid + 2400);
break;
- case IEEE80211_FTYPE_CTL:
+ case BCM43xx_PHYTYPE_G:
+ status.phymode = MODE_IEEE80211G;
+ status.freq = chanid + 2400;
+ status.channel = bcm43xx_freq_to_channel_bg(chanid + 2400);
break;
default:
- assert(0);
- return -EINVAL;
+ bcmwarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
+ chanstat);
+ }
+
+ dev->stats.last_rx = jiffies;
+ ieee80211_rx_irqsafe(dev->wl->hw, skb, &status);
+
+ return;
+drop:
+ bcmdbg(dev->wl, "RX: Packet dropped\n");
+ dev_kfree_skb_any(skb);
+}
+
+void bcm43xx_handle_txstatus(struct bcm43xx_wldev *dev,
+ const struct bcm43xx_txstatus *status)
+{
+ bcm43xx_debugfs_log_txstat(dev, status);
+
+ if (status->intermediate)
+ return;
+ if (status->for_ampdu)
+ return;
+ if (!status->acked)
+ dev->wl->ieee_stats.dot11ACKFailureCount++;
+ if (status->rts_count) {
+ if (status->rts_count == 0xF) /* FIXME */
+ dev->wl->ieee_stats.dot11RTSFailureCount++;
+ else
+ dev->wl->ieee_stats.dot11RTSSuccessCount++;
}
- return err;
+ if (bcm43xx_using_pio(dev))
+ bcm43xx_pio_handle_txstatus(dev, status);
+ else
+ bcm43xx_dma_handle_txstatus(dev, status);
+}
+
+/* Handle TX status report as received through DMA/PIO queues */
+void bcm43xx_handle_hwtxstatus(struct bcm43xx_wldev *dev,
+ const struct bcm43xx_hwtxstatus *hw)
+{
+ struct bcm43xx_txstatus status;
+ u8 tmp;
+
+ status.cookie = le16_to_cpu(hw->cookie);
+ status.seq = le16_to_cpu(hw->seq);
+ status.phy_stat = hw->phy_stat;
+ tmp = hw->count;
+ status.frame_count = (tmp >> 4);
+ status.rts_count = (tmp & 0x0F);
+ tmp = hw->flags;
+ status.supp_reason = ((tmp & 0x1C) >> 2);
+ status.pm_indicated = !!(tmp & 0x80);
+ status.intermediate = !!(tmp & 0x40);
+ status.for_ampdu = !!(tmp & 0x20);
+ status.acked = !!(tmp & 0x02);
+
+ bcm43xx_handle_txstatus(dev, &status);
+}
+
+/* Stop any TX operation on the device (suspend the hardware queues) */
+void bcm43xx_tx_suspend(struct bcm43xx_wldev *dev)
+{
+ if (bcm43xx_using_pio(dev))
+ bcm43xx_pio_freeze_txqueues(dev);
+ else
+ bcm43xx_dma_tx_suspend(dev);
+}
+
+/* Resume any TX operation on the device (resume the hardware queues) */
+void bcm43xx_tx_resume(struct bcm43xx_wldev *dev)
+{
+ if (bcm43xx_using_pio(dev))
+ bcm43xx_pio_thaw_txqueues(dev);
+ else
+ bcm43xx_dma_tx_resume(dev);
+}
+
+/* Initialize the QoS parameters */
+void bcm43xx_qos_init(struct bcm43xx_wldev *dev)
+{
+ /* FIXME: This function must probably be called from the mac80211
+ * config callback. */
+return;
+
+ bcm43xx_hf_write(dev, bcm43xx_hf_read(dev) | BCM43xx_HF_EDCF);
+ /* FIXME kill magic */
+ bcm43xx_write16(dev, 0x688,
+ bcm43xx_read16(dev, 0x688) | 0x4);
+
+
+ /*TODO: We might need some stack support here to get the values. */
}
Index: linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
===================================================================
--- linux-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
+++ linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
@@ -19,132 +19,240 @@ _bcm43xx_declare_plcp_hdr(6);
#undef _bcm43xx_declare_plcp_hdr
-/* Device specific TX header. To be prepended to TX frames. */
-struct bcm43xx_txhdr {
- union {
- struct {
- __le16 flags;
- __le16 wsec_rate;
- __le16 frame_control;
- u16 unknown_zeroed_0;
- __le16 control;
- u8 wep_iv[10];
- u8 unknown_wsec_tkip_data[3]; //FIXME
- PAD_BYTES(3);
- u8 mac1[6];
- u16 unknown_zeroed_1;
- struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
- __le16 rts_cts_dur_fallback;
- struct bcm43xx_plcp_hdr4 fallback_plcp;
- __le16 fallback_dur_id;
- PAD_BYTES(2);
- __le16 cookie;
- __le16 unknown_scb_stuff; //FIXME
- struct bcm43xx_plcp_hdr6 rts_cts_plcp;
- __le16 rts_cts_frame_control;
- __le16 rts_cts_dur;
- u8 rts_cts_mac1[6];
- u8 rts_cts_mac2[6];
- PAD_BYTES(2);
- struct bcm43xx_plcp_hdr6 plcp;
- } __attribute__((__packed__));
- u8 raw[82];
- } __attribute__((__packed__));
-} __attribute__((__packed__));
-
-/* Values/Masks for the device TX header */
-#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001
-#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002
-#define BCM43xx_TXHDRFLAG_RTS 0x0004
-#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008
-#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020
-#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080
-#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100
-#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200
-#define BCM43xx_TXHDRFLAG_CTS 0x0400
-#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800
-
-#define BCM43xx_TXHDRCTL_OFDM 0x0001
-#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010
-#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030
-#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8
-
-#define BCM43xx_TXHDR_RATE_MASK 0x0F00
-#define BCM43xx_TXHDR_RATE_SHIFT 8
-#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000
-#define BCM43xx_TXHDR_RTSRATE_SHIFT 12
-#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0
-#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4
-#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003
-#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0
-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);
-
-/* RX header as received from the hardware. */
-struct bcm43xx_rxhdr {
- /* Frame Length. Must be generated explicitely in PIO mode. */
- __le16 frame_length;
+/* TX header for v3 firmware */
+struct bcm43xx_txhdr_fw3 {
+ __le32 mac_ctl; /* MAC TX control */
+ __le16 mac_frame_ctl; /* Copy of the FrameControl
field */
+ __le16 tx_fes_time_norm; /* TX FES Time Normal */
+ __le16 phy_ctl; /* PHY TX control */
+ __u8 iv[16]; /* Encryption IV */
+ __u8 tx_receiver[6]; /* TX Frame Receiver address */
+ __le16 tx_fes_time_fb; /* TX FES Time Fallback */
+ struct bcm43xx_plcp_hdr4 rts_plcp_fb; /* RTS fallback PLCP */
+ __le16 rts_dur_fb; /* RTS fallback duration */
+ struct bcm43xx_plcp_hdr4 plcp_fb; /* Fallback PLCP */
+ __le16 dur_fb; /* Fallback duration */
PAD_BYTES(2);
- /* Flags field 1 */
- __le16 flags1;
- u8 rssi;
- u8 signal_quality;
- PAD_BYTES(2);
- /* Flags field 3 */
- __le16 flags3;
- /* Flags field 2 */
- __le16 flags2;
- /* Lower 16bits of the TSF at the time the frame started. */
- __le16 mactime;
- PAD_BYTES(14);
+ __le16 cookie;
+ __le16 unknown_scb_stuff;
+ struct bcm43xx_plcp_hdr6 rts_plcp; /* RTS PLCP */
+ __u8 rts_frame[18]; /* The RTS frame (if used) */
+ struct bcm43xx_plcp_hdr6 plcp;
} __attribute__((__packed__));
-#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0)
-/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */
-#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7)
-#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14)
-
-#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0)
-#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2)
-/*FIXME: WEP related flags */
+/* MAC TX control */
+#define BCM43xx_TX4_MAC_KEYIDX 0x0FF00000 /* Security key index */
+#define BCM43xx_TX4_MAC_KEYIDX_SHIFT 20
+#define BCM43xx_TX4_MAC_KEYALG 0x00070000 /* Security key algorithm */
+#define BCM43xx_TX4_MAC_KEYALG_SHIFT 16
+#define BCM43xx_TX4_MAC_LIFETIME 0x00001000
+#define BCM43xx_TX4_MAC_FRAMEBURST 0x00000800
+#define BCM43xx_TX4_MAC_SENDCTS 0x00000400
+#define BCM43xx_TX4_MAC_AMPDU 0x00000300
+#define BCM43xx_TX4_MAC_AMPDU_SHIFT 8
+#define BCM43xx_TX4_MAC_CTSFALLBACKOFDM 0x00000200
+#define BCM43xx_TX4_MAC_FALLBACKOFDM 0x00000100
+#define BCM43xx_TX4_MAC_5GHZ 0x00000080
+#define BCM43xx_TX4_MAC_IGNPMQ 0x00000020
+#define BCM43xx_TX4_MAC_HWSEQ 0x00000010 /* Use Hardware Seq No */
+#define BCM43xx_TX4_MAC_STMSDU 0x00000008 /* Start MSDU */
+#define BCM43xx_TX4_MAC_SENDRTS 0x00000004
+#define BCM43xx_TX4_MAC_LONGFRAME 0x00000002
+#define BCM43xx_TX4_MAC_ACK 0x00000001
+
+/* Extra Frame Types */
+#define BCM43xx_TX4_EFT_FBOFDM 0x0001 /* Data frame fb rate type */
+#define BCM43xx_TX4_EFT_RTSOFDM 0x0004 /* RTS/CTS rate type */
+#define BCM43xx_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */
+
+/* PHY TX control word */
+#define BCM43xx_TX4_PHY_OFDM 0x0001 /* Data frame rate type */
+#define BCM43xx_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */
+#define BCM43xx_TX4_PHY_ANT 0x03C0 /* Antenna selection */
+#define BCM43xx_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */
+#define BCM43xx_TX4_PHY_ANT1 0x0100 /* Use antenna 1 */
+#define BCM43xx_TX4_PHY_ANTLAST 0x0300 /* Use last used antenna */
+
-#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10)
-/* Transmit Status as received from the hardware. */
-struct bcm43xx_hwxmitstatus {
+void bcm43xx_generate_txhdr(struct bcm43xx_wldev *dev,
+ u8 *txhdr,
+ const unsigned char *fragment_data,
+ unsigned int fragment_len,
+ const struct ieee80211_tx_control *txctl,
+ u16 cookie);
+
+
+/* Transmit Status */
+struct bcm43xx_txstatus {
+ u16 cookie; /* The cookie from the txhdr */
+ u16 seq; /* Sequence number */
+ u8 phy_stat; /* PHY TX status */
+ u8 frame_count; /* Frame transmit count */
+ u8 rts_count; /* RTS transmit count */
+ u8 supp_reason; /* Suppression reason */
+ /* flags */
+ u8 pm_indicated; /* PM mode indicated to AP */
+ u8 intermediate; /* Intermediate status notification */
+ u8 for_ampdu; /* Status is for an AMPDU (afterburner) */
+ u8 acked; /* Wireless ACK received */
+};
+
+/* txstatus supp_reason values */
+enum {
+ BCM43xx_TXST_SUPP_NONE, /* Not suppressed */
+ BCM43xx_TXST_SUPP_PMQ, /* Suppressed due to PMQ entry */
+ BCM43xx_TXST_SUPP_FLUSH, /* Suppressed due to flush request */
+ BCM43xx_TXST_SUPP_PREV, /* Previous fragment failed */
+ BCM43xx_TXST_SUPP_CHAN, /* Channel mismatch */
+ BCM43xx_TXST_SUPP_LIFE, /* Lifetime expired */
+ BCM43xx_TXST_SUPP_UNDER, /* Buffer underflow */
+ BCM43xx_TXST_SUPP_ABNACK, /* Afterburner NACK */
+};
+
+/* Transmit Status as received through DMA/PIO on old chips */
+struct bcm43xx_hwtxstatus {
PAD_BYTES(4);
__le16 cookie;
u8 flags;
- u8 cnt1:4,
- cnt2:4;
+ u8 count;
PAD_BYTES(2);
__le16 seq;
- __le16 unknown; //FIXME
+ u8 phy_stat;
+ PAD_BYTES(1);
} __attribute__((__packed__));
-/* Transmit Status in CPU byteorder. */
-struct bcm43xx_xmitstatus {
- u16 cookie;
- u8 flags;
- u8 cnt1:4,
- cnt2:4;
- u16 seq;
- u16 unknown; //FIXME
-};
-#define BCM43xx_TXSTAT_FLAG_AMPDU 0x10
-#define BCM43xx_TXSTAT_FLAG_INTER 0x20
+/* Receive header for v3 firmware. */
+struct bcm43xx_rxhdr_fw3 {
+ __le16 frame_len; /* Frame length */
+ PAD_BYTES(2);
+ __le16 phy_status0; /* PHY RX Status 0 */
+ __u8 jssi; /* PHY RX Status 1: JSSI */
+ __u8 sig_qual; /* PHY RX Status 1: Signal Quality */
+ PAD_BYTES(2); /* PHY RX Status 2 */
+ __le16 phy_status3; /* PHY RX Status 3 */
+ __le16 mac_status; /* MAC RX status */
+ __le16 mac_time;
+ __le16 channel;
+} __attribute__((__packed__));
+
+
+/* PHY RX Status 0 */
+#define BCM43xx_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */
+#define BCM43xx_RX_PHYST0_PLCPHCF 0x0200
+#define BCM43xx_RX_PHYST0_PLCPFV 0x0100
+#define BCM43xx_RX_PHYST0_SHORTPRMBL 0x0080 /* Recvd with Short Preamble */
+#define BCM43xx_RX_PHYST0_LCRS 0x0040
+#define BCM43xx_RX_PHYST0_ANT 0x0020 /* Antenna */
+#define BCM43xx_RX_PHYST0_UNSRATE 0x0010
+#define BCM43xx_RX_PHYST0_CLIP 0x000C
+#define BCM43xx_RX_PHYST0_CLIP_SHIFT 2
+#define BCM43xx_RX_PHYST0_FTYPE 0x0003 /* Frame type */
+#define BCM43xx_RX_PHYST0_CCK 0x0000 /* Frame type: CCK */
+#define BCM43xx_RX_PHYST0_OFDM 0x0001 /* Frame type: OFDM */
+#define BCM43xx_RX_PHYST0_PRE_N 0x0002 /* Pre-standard N-PHY frame */
+#define BCM43xx_RX_PHYST0_STD_N 0x0003 /* Standard N-PHY frame */
+
+/* PHY RX Status 2 */
+#define BCM43xx_RX_PHYST2_LNAG 0xC000 /* LNA Gain */
+#define BCM43xx_RX_PHYST2_LNAG_SHIFT 14
+#define BCM43xx_RX_PHYST2_PNAG 0x3C00 /* PNA Gain */
+#define BCM43xx_RX_PHYST2_PNAG_SHIFT 10
+#define BCM43xx_RX_PHYST2_FOFF 0x03FF /* F offset */
+
+/* PHY RX Status 3 */
+#define BCM43xx_RX_PHYST3_DIGG 0x1800 /* DIG Gain */
+#define BCM43xx_RX_PHYST3_DIGG_SHIFT 11
+#define BCM43xx_RX_PHYST3_TRSTATE 0x0400 /* TR state */
+
+/* MAC RX Status */
+#define BCM43xx_RX_MAC_BEACONSENT 0x00008000 /* Beacon send flag */
+#define BCM43xx_RX_MAC_KEYIDX 0x000007E0 /* Key index */
+#define BCM43xx_RX_MAC_KEYIDX_SHIFT 5
+#define BCM43xx_RX_MAC_DECERR 0x00000010 /* Decrypt error */
+#define BCM43xx_RX_MAC_DEC 0x00000008 /* Decryption attempted */
+#define BCM43xx_RX_MAC_PADDING 0x00000004 /* Pad bytes present */
+#define BCM43xx_RX_MAC_RESP 0x00000002 /* Response frame xmitted */
+#define BCM43xx_RX_MAC_FCSERR 0x00000001 /* FCS error */
+
+/* RX channel */
+#define BCM43xx_RX_CHAN_GAIN 0xFC00 /* Gain */
+#define BCM43xx_RX_CHAN_GAIN_SHIFT 10
+#define BCM43xx_RX_CHAN_ID 0x03FC /* Channel ID */
+#define BCM43xx_RX_CHAN_ID_SHIFT 2
+#define BCM43xx_RX_CHAN_PHYTYPE 0x0003 /* PHY type */
+
+
u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
-int bcm43xx_rx(struct bcm43xx_private *bcm,
- struct sk_buff *skb,
- struct bcm43xx_rxhdr *rxhdr);
+void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
+ const u16 octets, const u8 bitrate);
+
+void bcm43xx_rx(struct bcm43xx_wldev *dev,
+ struct sk_buff *skb,
+ const void *_rxhdr);
+
+void bcm43xx_handle_txstatus(struct bcm43xx_wldev *dev,
+ const struct bcm43xx_txstatus *status);
+
+void bcm43xx_handle_hwtxstatus(struct bcm43xx_wldev *dev,
+ const struct bcm43xx_hwtxstatus *hw);
+
+void bcm43xx_tx_suspend(struct bcm43xx_wldev *dev);
+void bcm43xx_tx_resume(struct bcm43xx_wldev *dev);
+
+
+#define BCM43xx_NR_QOSPARMS 22
+enum {
+ BCM43xx_QOSPARM_TXOP = 0,
+ BCM43xx_QOSPARM_CWMIN,
+ BCM43xx_QOSPARM_CWMAX,
+ BCM43xx_QOSPARM_CWCUR,
+ BCM43xx_QOSPARM_AIFS,
+ BCM43xx_QOSPARM_BSLOTS,
+ BCM43xx_QOSPARM_REGGAP,
+ BCM43xx_QOSPARM_STATUS,
+};
+void bcm43xx_qos_init(struct bcm43xx_wldev *dev);
+
+
+/* Helper functions for converting the key-table index from "firmware-format"
+ * to "raw-format" and back. The firmware API changed for this at some
revision.
+ * We need to account for that here. */
+static inline
+int bcm43xx_new_kidx_api(struct bcm43xx_wldev *dev)
+{
+ /* FIXME: Not sure the change was at rev 351 */
+ return (dev->fw.rev >= 351);
+}
+static inline
+u8 bcm43xx_kidx_to_fw(struct bcm43xx_wldev *dev, u8 raw_kidx)
+{
+ u8 firmware_kidx;
+ if (bcm43xx_new_kidx_api(dev)) {
+ firmware_kidx = raw_kidx;
+ } else {
+ if (raw_kidx >= 4) /* Is per STA key? */
+ firmware_kidx = raw_kidx - 4;
+ else
+ firmware_kidx = raw_kidx; /* TX default key */
+ }
+ return firmware_kidx;
+}
+static inline
+u8 bcm43xx_kidx_to_raw(struct bcm43xx_wldev *dev, u8 firmware_kidx)
+{
+ u8 raw_kidx;
+ if (bcm43xx_new_kidx_api(dev))
+ raw_kidx = firmware_kidx;
+ else
+ /* RX default keys or per STA keys */
+ raw_kidx = firmware_kidx + 4;
+ return raw_kidx;
+}
#endif /* BCM43xx_XMIT_H_ */
_______________________________________________
Bcm43xx-dev mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev