diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-01-28 14:47:41 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 15:09:50 -0800 |
commit | eb189d8bc9824bcb2187ffdab27d77ab469264c3 (patch) | |
tree | 612c6549f0d0261087b55b157dd5ca016386ddee | |
parent | 243dcfcc1d4b33aa610f1bf3ec610dafdf4d7ff7 (diff) | |
download | linux-eb189d8bc9824bcb2187ffdab27d77ab469264c3.tar.gz linux-eb189d8bc9824bcb2187ffdab27d77ab469264c3.tar.bz2 linux-eb189d8bc9824bcb2187ffdab27d77ab469264c3.zip |
b43: Add support for new firmware
This patch adds support for new firmware.
Old firmware is still supported until July 2008.
To get new firmware, go to
ftp://ftp.linksys.com/opensourcecode/wrt150nv11/1.51.3/
and download the tarball. We don't have a smaller tarball, yet.
That will be fixed later.
You can extract firmware out of the "wl_ap.o" file contained
in this tarball using latest fwcutter. You must pass the option
--unsupported to fwcutter.
Fwcutter-010 with official support for a new firmware image will
be released soon.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | Documentation/feature-removal-schedule.txt | 9 | ||||
-rw-r--r-- | drivers/net/wireless/b43/dma.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 50 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/b43/xmit.c | 144 | ||||
-rw-r--r-- | drivers/net/wireless/b43/xmit.h | 200 |
6 files changed, 298 insertions, 129 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 166915df8d6a..181bff005167 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -345,3 +345,12 @@ What (Why): When: January 2009 or Linux 2.7.0, whichever comes first Why: Superseded by newer revisions or modules Who: Jan Engelhardt <jengelh@computergmbh.de> + +--------------------------- + +What: b43 support for firmware revision < 410 +When: July 2008 +Why: The support code for the old firmware hurts code readability/maintainability + and slightly hurts runtime performance. Bugfixes for the old firmware + are not provided by Broadcom anymore. +Who: Michael Buesch <mb@bu3sch.de> diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index cf92853a2180..3e73d2a523aa 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -807,7 +807,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, goto err_kfree_ring; if (for_tx) { ring->txhdr_cache = kcalloc(nr_slots, - sizeof(struct b43_txhdr_fw4), + b43_txhdr_size(dev), GFP_KERNEL); if (!ring->txhdr_cache) goto err_kfree_meta; @@ -815,22 +815,21 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, /* test for ability to dma to txhdr_cache */ dma_test = dma_map_single(dev->dev->dev, ring->txhdr_cache, - sizeof(struct b43_txhdr_fw4), + b43_txhdr_size(dev), DMA_TO_DEVICE); if (dma_mapping_error(dma_test)) { /* ugh realloc */ kfree(ring->txhdr_cache); ring->txhdr_cache = kcalloc(nr_slots, - sizeof(struct - b43_txhdr_fw4), + b43_txhdr_size(dev), GFP_KERNEL | GFP_DMA); if (!ring->txhdr_cache) goto err_kfree_meta; dma_test = dma_map_single(dev->dev->dev, ring->txhdr_cache, - sizeof(struct b43_txhdr_fw4), + b43_txhdr_size(dev), DMA_TO_DEVICE); if (dma_mapping_error(dma_test)) @@ -838,7 +837,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, } dma_unmap_single(dev->dev->dev, - dma_test, sizeof(struct b43_txhdr_fw4), + dma_test, b43_txhdr_size(dev), DMA_TO_DEVICE); } @@ -1122,6 +1121,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, struct b43_dmadesc_meta *meta_hdr; struct sk_buff *bounce_skb; u16 cookie; + size_t hdrsize = b43_txhdr_size(ring->dev); #define SLOTS_PER_PACKET 2 B43_WARN_ON(skb_shinfo(skb)->nr_frags); @@ -1131,17 +1131,17 @@ static int dma_tx_fragment(struct b43_dmaring *ring, desc = ops->idx2desc(ring, slot, &meta_hdr); memset(meta_hdr, 0, sizeof(*meta_hdr)); - header = &(ring->txhdr_cache[slot * sizeof(struct b43_txhdr_fw4)]); + header = &(ring->txhdr_cache[slot * hdrsize]); cookie = generate_cookie(ring, slot); b43_generate_txhdr(ring->dev, header, skb->data, skb->len, ctl, cookie); meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, - sizeof(struct b43_txhdr_fw4), 1); + hdrsize, 1); if (dma_mapping_error(meta_hdr->dmaaddr)) return -EIO; ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, - sizeof(struct b43_txhdr_fw4), 1, 0, 0); + hdrsize, 1, 0, 0); /* Get a slot for the payload. */ slot = request_slot(ring); @@ -1189,7 +1189,7 @@ out_free_bounce: dev_kfree_skb_any(skb); out_unmap_hdr: unmap_descbuffer(ring, meta_hdr->dmaaddr, - sizeof(struct b43_txhdr_fw4), 1); + hdrsize, 1); return err; } @@ -1298,7 +1298,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, 1); else unmap_descbuffer(ring, meta->dmaaddr, - sizeof(struct b43_txhdr_fw4), 1); + b43_txhdr_size(dev), 1); if (meta->is_last_fragment) { B43_WARN_ON(!meta->skb); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 481bc8238e7c..560d1421e679 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1569,11 +1569,17 @@ static void b43_release_firmware(struct b43_wldev *dev) dev->fw.initvals_band = NULL; } -static void b43_print_fw_helptext(struct b43_wl *wl) +static void b43_print_fw_helptext(struct b43_wl *wl, bool error) { - b43err(wl, "You must go to " + const char *text; + + text = "You must go to " "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware " - "and download the correct firmware (version 4).\n"); + "and download the latest firmware (version 4).\n"; + if (error) + b43err(wl, text); + else + b43warn(wl, text); } static int do_request_fw(struct b43_wldev *dev, @@ -1725,7 +1731,7 @@ static int b43_request_firmware(struct b43_wldev *dev) return 0; err_load: - b43_print_fw_helptext(dev->wl); + b43_print_fw_helptext(dev->wl, 1); goto error; err_no_ucode: @@ -1795,7 +1801,7 @@ static int b43_upload_microcode(struct b43_wldev *dev) i++; if (i >= 50) { b43err(dev->wl, "Microcode not responding\n"); - b43_print_fw_helptext(dev->wl); + b43_print_fw_helptext(dev->wl, 1); err = -ENODEV; goto out; } @@ -1813,7 +1819,7 @@ static int b43_upload_microcode(struct b43_wldev *dev) b43err(dev->wl, "YOUR FIRMWARE IS TOO OLD. Firmware from " "binary drivers older than version 4.x is unsupported. " "You must upgrade your firmware files.\n"); - b43_print_fw_helptext(dev->wl); + b43_print_fw_helptext(dev->wl, 1); b43_write32(dev, B43_MMIO_MACCTL, 0); err = -EOPNOTSUPP; goto out; @@ -1827,7 +1833,13 @@ static int b43_upload_microcode(struct b43_wldev *dev) dev->fw.rev = fwrev; dev->fw.patch = fwpatch; - out: + if (b43_is_old_txhdr_format(dev)) { + b43warn(dev->wl, "You are using an old firmware image. " + "Support for old firmware will be removed in July 2008.\n"); + b43_print_fw_helptext(dev->wl, 0); + } + +out: return err; } @@ -1887,7 +1899,7 @@ static int b43_write_initvals(struct b43_wldev *dev, err_format: b43err(dev->wl, "Initial Values Firmware file-format error.\n"); - b43_print_fw_helptext(dev->wl); + b43_print_fw_helptext(dev->wl, 1); return -EPROTO; } @@ -2149,13 +2161,19 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna) switch (antenna) { case B43_ANTENNA0: - ant |= B43_TX4_PHY_ANT0; + ant |= B43_TXH_PHY_ANT0; break; case B43_ANTENNA1: - ant |= B43_TX4_PHY_ANT1; + ant |= B43_TXH_PHY_ANT1; + break; + case B43_ANTENNA2: + ant |= B43_TXH_PHY_ANT2; + break; + case B43_ANTENNA3: + ant |= B43_TXH_PHY_ANT3; break; case B43_ANTENNA_AUTO: - ant |= B43_TX4_PHY_ANTLAST; + ant |= B43_TXH_PHY_ANT01AUTO; break; default: B43_WARN_ON(1); @@ -2165,15 +2183,15 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna) /* For Beacons */ tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); - tmp = (tmp & ~B43_TX4_PHY_ANT) | ant; + tmp = (tmp & ~B43_TXH_PHY_ANT) | ant; b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, tmp); /* For ACK/CTS */ tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL); - tmp = (tmp & ~B43_TX4_PHY_ANT) | ant; + tmp = (tmp & ~B43_TXH_PHY_ANT) | ant; b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, tmp); /* For Probe Resposes */ tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL); - tmp = (tmp & ~B43_TX4_PHY_ANT) | ant; + tmp = (tmp & ~B43_TXH_PHY_ANT) | ant; b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp); } @@ -2738,6 +2756,10 @@ static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna) return B43_ANTENNA0; case 2: /* Antenna 1 */ return B43_ANTENNA1; + case 3: /* Antenna 2 */ + return B43_ANTENNA2; + case 4: /* Antenna 3 */ + return B43_ANTENNA3; default: return B43_ANTENNA_DEFAULT; } diff --git a/drivers/net/wireless/b43/phy.h b/drivers/net/wireless/b43/phy.h index 31bd4d87b404..ab1e7f097022 100644 --- a/drivers/net/wireless/b43/phy.h +++ b/drivers/net/wireless/b43/phy.h @@ -180,6 +180,8 @@ enum { B43_ANTENNA1, /* Antenna 0 */ B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */ B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */ + B43_ANTENNA2, + B43_ANTENNA3 = 8, B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0, B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO, diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 5014213b7752..3fc53e8b4416 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -177,13 +177,15 @@ static u8 b43_calc_fallback_rate(u8 bitrate) return 0; } -static void generate_txhdr_fw4(struct b43_wldev *dev, - struct b43_txhdr_fw4 *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const struct ieee80211_tx_control *txctl, - u16 cookie) +/* Generate a TX data header. */ +void b43_generate_txhdr(struct b43_wldev *dev, + u8 *_txhdr, + const unsigned char *fragment_data, + unsigned int fragment_len, + const struct ieee80211_tx_control *txctl, + u16 cookie) { + struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; const struct b43_phy *phy = &dev->phy; const struct ieee80211_hdr *wlhdr = (const struct ieee80211_hdr *)fragment_data; @@ -241,23 +243,30 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, plcp_fragment_len += txctl->icv_len; key_idx = b43_kidx_to_fw(dev, key_idx); - mac_ctl |= (key_idx << B43_TX4_MAC_KEYIDX_SHIFT) & - B43_TX4_MAC_KEYIDX; - mac_ctl |= (key->algorithm << B43_TX4_MAC_KEYALG_SHIFT) & - B43_TX4_MAC_KEYALG; + mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & + B43_TXH_MAC_KEYIDX; + mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & + B43_TXH_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); } - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp), - plcp_fragment_len, rate); + if (b43_is_old_txhdr_format(dev)) { + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), + plcp_fragment_len, rate); + } else { + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp), + plcp_fragment_len, rate); + } b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), plcp_fragment_len, rate_fb); /* Extra Frame Types */ if (rate_fb_ofdm) - extra_ft |= B43_TX4_EFT_FBOFDM; + extra_ft |= B43_TXH_EFT_FB_OFDM; + else + extra_ft |= B43_TXH_EFT_FB_CCK; /* Set channel radio code. Note that the micrcode ORs 0x100 to * this value before comparing it to the value in SHM, if this @@ -267,19 +276,27 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, /* PHY TX Control word */ if (rate_ofdm) - phy_ctl |= B43_TX4_PHY_OFDM; + phy_ctl |= B43_TXH_PHY_ENC_OFDM; + else + phy_ctl |= B43_TXH_PHY_ENC_CCK; if (dev->short_preamble) - phy_ctl |= B43_TX4_PHY_SHORTPRMBL; + phy_ctl |= B43_TXH_PHY_SHORTPRMBL; switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) { case 0: /* Default */ - phy_ctl |= B43_TX4_PHY_ANTLAST; + phy_ctl |= B43_TXH_PHY_ANT01AUTO; break; case 1: /* Antenna 0 */ - phy_ctl |= B43_TX4_PHY_ANT0; + phy_ctl |= B43_TXH_PHY_ANT0; break; case 2: /* Antenna 1 */ - phy_ctl |= B43_TX4_PHY_ANT1; + phy_ctl |= B43_TXH_PHY_ANT1; + break; + case 3: /* Antenna 2 */ + phy_ctl |= B43_TXH_PHY_ANT2; + break; + case 4: /* Antenna 3 */ + phy_ctl |= B43_TXH_PHY_ANT3; break; default: B43_WARN_ON(1); @@ -287,16 +304,16 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, /* MAC control */ if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK)) - mac_ctl |= B43_TX4_MAC_ACK; + mac_ctl |= B43_TXH_MAC_ACK; if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) - mac_ctl |= B43_TX4_MAC_HWSEQ; + mac_ctl |= B43_TXH_MAC_HWSEQ; if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT) - mac_ctl |= B43_TX4_MAC_STMSDU; + mac_ctl |= B43_TXH_MAC_STMSDU; if (phy->type == B43_PHYTYPE_A) - mac_ctl |= B43_TX4_MAC_5GHZ; + mac_ctl |= B43_TXH_MAC_5GHZ; if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT) - mac_ctl |= B43_TX4_MAC_LONGFRAME; + mac_ctl |= B43_TXH_MAC_LONGFRAME; /* Generate the RTS or CTS-to-self frame */ if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) || @@ -305,6 +322,7 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, struct ieee80211_hdr *hdr; int rts_rate, rts_rate_fb; int rts_rate_ofdm, rts_rate_fb_ofdm; + struct b43_plcp_hdr6 *plcp; rts_rate = txctl->rts_cts_rate; rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); @@ -312,58 +330,84 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { + struct ieee80211_cts *cts; + + if (b43_is_old_txhdr_format(dev)) { + cts = (struct ieee80211_cts *) + (txhdr->old_format.rts_frame); + } else { + cts = (struct ieee80211_cts *) + (txhdr->new_format.rts_frame); + } ieee80211_ctstoself_get(dev->wl->hw, txctl->vif, fragment_data, fragment_len, - txctl, - (struct ieee80211_cts *)(txhdr-> - rts_frame)); - mac_ctl |= B43_TX4_MAC_SENDCTS; + txctl, cts); + mac_ctl |= B43_TXH_MAC_SENDCTS; len = sizeof(struct ieee80211_cts); } else { + struct ieee80211_rts *rts; + + if (b43_is_old_txhdr_format(dev)) { + rts = (struct ieee80211_rts *) + (txhdr->old_format.rts_frame); + } else { + rts = (struct ieee80211_rts *) + (txhdr->new_format.rts_frame); + } ieee80211_rts_get(dev->wl->hw, txctl->vif, - fragment_data, fragment_len, txctl, - (struct ieee80211_rts *)(txhdr-> - rts_frame)); - mac_ctl |= B43_TX4_MAC_SENDRTS; + fragment_data, fragment_len, + txctl, rts); + mac_ctl |= B43_TXH_MAC_SENDRTS; len = sizeof(struct ieee80211_rts); } len += FCS_LEN; - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr-> - rts_plcp), len, - rts_rate); - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr-> - rts_plcp_fb), + + /* Generate the PLCP headers for the RTS/CTS frame */ + if (b43_is_old_txhdr_format(dev)) + plcp = &txhdr->old_format.rts_plcp; + else + plcp = &txhdr->new_format.rts_plcp; + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, + len, rts_rate); + plcp = &txhdr->rts_plcp_fb; + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, len, rts_rate_fb); - hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame); + + if (b43_is_old_txhdr_format(dev)) { + hdr = (struct ieee80211_hdr *) + (&txhdr->old_format.rts_frame); + } else { + hdr = (struct ieee80211_hdr *) + (&txhdr->new_format.rts_frame); + } txhdr->rts_dur_fb = hdr->duration_id; + if (rts_rate_ofdm) { - extra_ft |= B43_TX4_EFT_RTSOFDM; + extra_ft |= B43_TXH_EFT_RTS_OFDM; txhdr->phy_rate_rts = b43_plcp_get_ratecode_ofdm(rts_rate); - } else + } else { + extra_ft |= B43_TXH_EFT_RTS_CCK; txhdr->phy_rate_rts = b43_plcp_get_ratecode_cck(rts_rate); + } if (rts_rate_fb_ofdm) - extra_ft |= B43_TX4_EFT_RTSFBOFDM; + extra_ft |= B43_TXH_EFT_RTSFB_OFDM; + else + extra_ft |= B43_TXH_EFT_RTSFB_CCK; } /* Magic cookie */ - txhdr->cookie = cpu_to_le16(cookie); + if (b43_is_old_txhdr_format(dev)) + txhdr->old_format.cookie = cpu_to_le16(cookie); + else + txhdr->new_format.cookie = cpu_to_le16(cookie); /* Apply the bitfields */ txhdr->mac_ctl = cpu_to_le32(mac_ctl); txhdr->phy_ctl = cpu_to_le16(phy_ctl); txhdr->extra_ft = extra_ft; -} -void b43_generate_txhdr(struct b43_wldev *dev, - u8 * txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const struct ieee80211_tx_control *txctl, u16 cookie) -{ - generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr, - fragment_data, fragment_len, txctl, cookie); } static s8 b43_rssi_postprocess(struct b43_wldev *dev, diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 6dc079382f7f..ca2a2ab8654c 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -19,68 +19,160 @@ _b43_declare_plcp_hdr(6); #undef _b43_declare_plcp_hdr /* TX header for v4 firmware */ -struct b43_txhdr_fw4 { - __le32 mac_ctl; /* MAC TX control */ - __le16 mac_frame_ctl; /* Copy of the FrameControl field */ +struct b43_txhdr { + __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 */ - __le16 phy_ctl_0; /* Unused */ - __le16 phy_ctl_1; /* Unused */ - __le16 phy_ctl_rts_0; /* Unused */ - __le16 phy_ctl_rts_1; /* Unused */ - __u8 phy_rate; /* PHY rate */ - __u8 phy_rate_rts; /* PHY rate for RTS/CTS */ - __u8 extra_ft; /* Extra Frame Types */ - __u8 chan_radio_code; /* Channel Radio Code */ - __u8 iv[16]; /* Encryption IV */ - __u8 tx_receiver[6]; /* TX Frame Receiver address */ - __le16 tx_fes_time_fb; /* TX FES Time Fallback */ - struct b43_plcp_hdr6 rts_plcp_fb; /* RTS fallback PLCP */ - __le16 rts_dur_fb; /* RTS fallback duration */ - struct b43_plcp_hdr6 plcp_fb; /* Fallback PLCP */ - __le16 dur_fb; /* Fallback duration */ - __le16 mm_dur_time; /* Unused */ - __le16 mm_dur_time_fb; /* Unused */ - __le32 time_stamp; /* Timestamp */ - PAD_BYTES(2); - __le16 cookie; /* TX frame cookie */ - __le16 tx_status; /* TX status */ - struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP */ - __u8 rts_frame[16]; /* The RTS frame (if used) */ - PAD_BYTES(2); - struct b43_plcp_hdr6 plcp; /* Main PLCP */ + __le16 phy_ctl; /* PHY TX control */ + __le16 phy_ctl1; /* PHY TX control word 1 */ + __le16 phy_ctl1_fb; /* PHY TX control word 1 for fallback rates */ + __le16 phy_ctl1_rts; /* PHY TX control word 1 RTS */ + __le16 phy_ctl1_rts_fb; /* PHY TX control word 1 RTS for fallback rates */ + __u8 phy_rate; /* PHY rate */ + __u8 phy_rate_rts; /* PHY rate for RTS/CTS */ + __u8 extra_ft; /* Extra Frame Types */ + __u8 chan_radio_code; /* Channel Radio Code */ + __u8 iv[16]; /* Encryption IV */ + __u8 tx_receiver[6]; /* TX Frame Receiver address */ + __le16 tx_fes_time_fb; /* TX FES Time Fallback */ + struct b43_plcp_hdr6 rts_plcp_fb; /* RTS fallback PLCP header */ + __le16 rts_dur_fb; /* RTS fallback duration */ + struct b43_plcp_hdr6 plcp_fb; /* Fallback PLCP header */ + __le16 dur_fb; /* Fallback duration */ + __le16 mimo_modelen; /* MIMO mode length */ + __le16 mimo_ratelen_fb; /* MIMO fallback rate length */ + __le32 timeout; /* Timeout */ + + union { + /* The new r410 format. */ + struct { + __le16 mimo_antenna; /* MIMO antenna select */ + __le16 preload_size; /* Preload size */ + PAD_BYTES(2); + __le16 cookie; /* TX frame cookie */ + __le16 tx_status; /* TX status */ + struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */ + __u8 rts_frame[16]; /* The RTS frame (if used) */ + PAD_BYTES(2); + struct b43_plcp_hdr6 plcp; /* Main PLCP header */ + } new_format __attribute__ ((__packed__)); + + /* The old r351 format. */ + struct { + PAD_BYTES(2); + __le16 cookie; /* TX frame cookie */ + __le16 tx_status; /* TX status */ + struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */ + __u8 rts_frame[16]; /* The RTS frame (if used) */ + PAD_BYTES(2); + struct b43_plcp_hdr6 plcp; /* Main PLCP header */ + } old_format __attribute__ ((__packed__)); + + } __attribute__ ((__packed__)); } __attribute__ ((__packed__)); /* MAC TX control */ -#define B43_TX4_MAC_KEYIDX 0x0FF00000 /* Security key index */ -#define B43_TX4_MAC_KEYIDX_SHIFT 20 -#define B43_TX4_MAC_KEYALG 0x00070000 /* Security key algorithm */ -#define B43_TX4_MAC_KEYALG_SHIFT 16 -#define B43_TX4_MAC_LIFETIME 0x00001000 -#define B43_TX4_MAC_FRAMEBURST 0x00000800 -#define B43_TX4_MAC_SENDCTS 0x00000400 -#define B43_TX4_MAC_AMPDU 0x00000300 -#define B43_TX4_MAC_AMPDU_SHIFT 8 -#define B43_TX4_MAC_5GHZ 0x00000080 -#define B43_TX4_MAC_IGNPMQ 0x00000020 -#define B43_TX4_MAC_HWSEQ 0x00000010 /* Use Hardware Sequence Number */ -#define B43_TX4_MAC_STMSDU 0x00000008 /* Start MSDU */ -#define B43_TX4_MAC_SENDRTS 0x00000004 -#define B43_TX4_MAC_LONGFRAME 0x00000002 -#define B43_TX4_MAC_ACK 0x00000001 +#define B43_TXH_MAC_USEFBR 0x10000000 /* Use fallback rate for this AMPDU */ +#define B43_TXH_MAC_KEYIDX 0x0FF00000 /* Security key index */ +#define B43_TXH_MAC_KEYIDX_SHIFT 20 +#define B43_TXH_MAC_KEYALG 0x00070000 /* Security key algorithm */ +#define B43_TXH_MAC_KEYALG_SHIFT 16 +#define B43_TXH_MAC_AMIC 0x00008000 /* AMIC */ +#define B43_TXH_MAC_RIFS 0x00004000 /* Use RIFS */ +#define B43_TXH_MAC_LIFETIME 0x00002000 /* Lifetime */ +#define B43_TXH_MAC_FRAMEBURST 0x00001000 /* Frameburst */ +#define B43_TXH_MAC_SENDCTS 0x00000800 /* Send CTS-to-self */ +#define B43_TXH_MAC_AMPDU 0x00000600 /* AMPDU status */ +#define B43_TXH_MAC_AMPDU_MPDU 0x00000000 /* Regular MPDU, not an AMPDU */ +#define B43_TXH_MAC_AMPDU_FIRST 0x00000200 /* First MPDU or AMPDU */ +#define B43_TXH_MAC_AMPDU_INTER 0x00000400 /* Intermediate MPDU or AMPDU */ +#define B43_TXH_MAC_AMPDU_LAST 0x00000600 /* Last (or only) MPDU of AMPDU */ +#define B43_TXH_MAC_40MHZ 0x00000100 /* Use 40 MHz bandwidth */ +#define B43_TXH_MAC_5GHZ 0x00000080 /* 5GHz band */ +#define B43_TXH_MAC_DFCS 0x00000040 /* DFCS */ +#define B43_TXH_MAC_IGNPMQ 0x00000020 /* Ignore PMQ */ +#define B43_TXH_MAC_HWSEQ 0x00000010 /* Use Hardware Sequence Number */ +#define B43_TXH_MAC_STMSDU 0x00000008 /* Start MSDU */ +#define B43_TXH_MAC_SENDRTS 0x00000004 /* Send RTS */ +#define B43_TXH_MAC_LONGFRAME 0x00000002 /* Long frame */ +#define B43_TXH_MAC_ACK 0x00000001 /* Immediate ACK */ /* Extra Frame Types */ -#define B43_TX4_EFT_FBOFDM 0x0001 /* Data frame fallback rate type */ -#define B43_TX4_EFT_RTSOFDM 0x0004 /* RTS/CTS rate type */ -#define B43_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */ +#define B43_TXH_EFT_FB 0x03 /* Data frame fallback encoding */ +#define B43_TXH_EFT_FB_CCK 0x00 /* CCK */ +#define B43_TXH_EFT_FB_OFDM 0x01 /* OFDM */ +#define B43_TXH_EFT_FB_EWC 0x02 /* EWC */ +#define B43_TXH_EFT_FB_N 0x03 /* N */ +#define B43_TXH_EFT_RTS 0x0C /* RTS/CTS encoding */ +#define B43_TXH_EFT_RTS_CCK 0x00 /* CCK */ +#define B43_TXH_EFT_RTS_OFDM 0x04 /* OFDM */ +#define B43_TXH_EFT_RTS_EWC 0x08 /* EWC */ +#define B43_TXH_EFT_RTS_N 0x0C /* N */ +#define B43_TXH_EFT_RTSFB 0x30 /* RTS/CTS fallback encoding */ +#define B43_TXH_EFT_RTSFB_CCK 0x00 /* CCK */ +#define B43_TXH_EFT_RTSFB_OFDM 0x10 /* OFDM */ +#define B43_TXH_EFT_RTSFB_EWC 0x20 /* EWC */ +#define B43_TXH_EFT_RTSFB_N 0x30 /* N */ /* PHY TX control word */ -#define B43_TX4_PHY_OFDM 0x0001 /* Data frame rate type */ -#define B43_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */ -#define B43_TX4_PHY_ANT 0x03C0 /* Antenna selection */ -#define B43_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */ -#define B43_TX4_PHY_ANT1 0x0100 /* Use antenna 1 */ -#define B43_TX4_PHY_ANTLAST 0x0300 /* Use last used antenna */ +#define B43_TXH_PHY_ENC 0x0003 /* Data frame encoding */ +#define B43_TXH_PHY_ENC_CCK 0x0000 /* CCK */ +#define B43_TXH_PHY_ENC_OFDM 0x0001 /* OFDM */ +#define B43_TXH_PHY_ENC_EWC 0x0002 /* EWC */ +#define B43_TXH_PHY_ENC_N 0x0003 /* N */ +#define B43_TXH_PHY_SHORTPRMBL 0x0010 /* Use short preamble */ +#define B43_TXH_PHY_ANT 0x03C0 /* Antenna selection */ +#define B43_TXH_PHY_ANT0 0x0000 /* Use antenna 0 */ +#define B43_TXH_PHY_ANT1 0x0040 /* Use antenna 1 */ +#define B43_TXH_PHY_ANT01AUTO 0x00C0 /* Use antenna 0/1 auto */ +#define B43_TXH_PHY_ANT2 0x0100 /* Use antenna 2 */ +#define B43_TXH_PHY_ANT3 0x0200 /* Use antenna 3 */ +#define B43_TXH_PHY_TXPWR 0xFC00 /* TX power */ +#define B43_TXH_PHY_TXPWR_SHIFT 10 + +/* PHY TX control word 1 */ +#define B43_TXH_PHY1_BW 0x0007 /* Bandwidth */ +#define B43_TXH_PHY1_BW_10 0x0000 /* 10 MHz */ +#define B43_TXH_PHY1_BW_10U 0x0001 /* 10 MHz upper */ +#define B43_TXH_PHY1_BW_20 0x0002 /* 20 MHz */ +#define B43_TXH_PHY1_BW_20U 0x0003 /* 20 MHz upper */ +#define B43_TXH_PHY1_BW_40 0x0004 /* 40 MHz */ +#define B43_TXH_PHY1_BW_40DUP 0x0005 /* 50 MHz duplicate */ +#define B43_TXH_PHY1_MODE 0x0038 /* Mode */ +#define B43_TXH_PHY1_MODE_SISO 0x0000 /* SISO */ +#define B43_TXH_PHY1_MODE_CDD 0x0008 /* CDD */ +#define B43_TXH_PHY1_MODE_STBC 0x0010 /* STBC */ +#define B43_TXH_PHY1_MODE_SDM 0x0018 /* SDM */ +#define B43_TXH_PHY1_CRATE 0x0700 /* Coding rate */ +#define B43_TXH_PHY1_CRATE_1_2 0x0000 /* 1/2 */ +#define B43_TXH_PHY1_CRATE_2_3 0x0100 /* 2/3 */ +#define B43_TXH_PHY1_CRATE_3_4 0x0200 /* 3/4 */ +#define B43_TXH_PHY1_CRATE_4_5 0x0300 /* 4/5 */ +#define B43_TXH_PHY1_CRATE_5_6 0x0400 /* 5/6 */ +#define B43_TXH_PHY1_CRATE_7_8 0x0600 /* 7/8 */ +#define B43_TXH_PHY1_MODUL 0x3800 /* Modulation scheme */ +#define B43_TXH_PHY1_MODUL_BPSK 0x0000 /* BPSK */ +#define B43_TXH_PHY1_MODUL_QPSK 0x0800 /* QPSK */ +#define B43_TXH_PHY1_MODUL_QAM16 0x1000 /* QAM16 */ +#define B43_TXH_PHY1_MODUL_QAM64 0x1800 /* QAM64 */ +#define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */ + + +/* r351 firmware compatibility stuff. */ +static inline +bool b43_is_old_txhdr_format(struct b43_wldev *dev) +{ + return (dev->fw.rev <= 351); +} + +static inline +size_t b43_txhdr_size(struct b43_wldev *dev) +{ + if (b43_is_old_txhdr_format(dev)) + return 100 + sizeof(struct b43_plcp_hdr6); + return 104 + sizeof(struct b43_plcp_hdr6); +} + void b43_generate_txhdr(struct b43_wldev *dev, u8 * txhdr, |