xmit.c revision d987160b710c98997015832422a05e18d9f0f925
1e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* 2e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 3e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Broadcom B43 wireless driver 4e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 5e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Transmission (TX/RX) related functions. 6e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 7e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Copyright (C) 2005 Martin Langer <martin-langer@gmx.de> 8e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Copyright (C) 2005 Stefano Brivio <st3@riseup.net> 9e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de> 10e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org> 11e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> 12e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 13e4d6b7951812d98417feb10784e400e253caf633Michael Buesch This program is free software; you can redistribute it and/or modify 14e4d6b7951812d98417feb10784e400e253caf633Michael Buesch it under the terms of the GNU General Public License as published by 15e4d6b7951812d98417feb10784e400e253caf633Michael Buesch the Free Software Foundation; either version 2 of the License, or 16e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (at your option) any later version. 17e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 18e4d6b7951812d98417feb10784e400e253caf633Michael Buesch This program is distributed in the hope that it will be useful, 19e4d6b7951812d98417feb10784e400e253caf633Michael Buesch but WITHOUT ANY WARRANTY; without even the implied warranty of 20e4d6b7951812d98417feb10784e400e253caf633Michael Buesch MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21e4d6b7951812d98417feb10784e400e253caf633Michael Buesch GNU General Public License for more details. 22e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 23e4d6b7951812d98417feb10784e400e253caf633Michael Buesch You should have received a copy of the GNU General Public License 24e4d6b7951812d98417feb10784e400e253caf633Michael Buesch along with this program; see the file COPYING. If not, write to 25e4d6b7951812d98417feb10784e400e253caf633Michael Buesch the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 26e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Boston, MA 02110-1301, USA. 27e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 28e4d6b7951812d98417feb10784e400e253caf633Michael Buesch*/ 29e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 30e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#include "xmit.h" 31e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#include "phy.h" 32e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#include "dma.h" 33e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#include "pio.h" 34e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 35e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Extract the bitrate out of a CCK PLCP header. */ 36e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp) 37e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 38e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (plcp->raw[0]) { 39e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x0A: 40e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_1MB; 41e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x14: 42e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_2MB; 43e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x37: 44e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_5MB; 45e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x6E: 46e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_11MB; 47e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 48e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 49e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 50e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 51e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 52e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Extract the bitrate out of an OFDM PLCP header. */ 53e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp) 54e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 55e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (plcp->raw[0] & 0xF) { 56e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xB: 57e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_6MB; 58e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xF: 59e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_9MB; 60e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xA: 61e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_12MB; 62e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xE: 63e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_18MB; 64e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x9: 65e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_24MB; 66e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xD: 67e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_36MB; 68e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x8: 69e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_48MB; 70e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xC: 71e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_54MB; 72e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 73e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 74e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 75e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 76e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 77e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_cck(const u8 bitrate) 78e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 79e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (bitrate) { 80e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_1MB: 81e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x0A; 82e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_2MB: 83e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x14; 84e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_5MB: 85e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x37; 86e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_11MB: 87e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x6E; 88e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 89e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 90e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 91e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 92e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 93e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_ofdm(const u8 bitrate) 94e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 95e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (bitrate) { 96e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_6MB: 97e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xB; 98e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_9MB: 99e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xF; 100e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_12MB: 101e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xA; 102e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_18MB: 103e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xE; 104e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_24MB: 105e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x9; 106e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_36MB: 107e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xD; 108e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_48MB: 109e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x8; 110e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_54MB: 111e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xC; 112e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 113e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 114e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 115e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 116e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 117e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, 118e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const u16 octets, const u8 bitrate) 119e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 120e4d6b7951812d98417feb10784e400e253caf633Michael Buesch __le32 *data = &(plcp->data); 121e4d6b7951812d98417feb10784e400e253caf633Michael Buesch __u8 *raw = plcp->raw; 122e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 123e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (b43_is_ofdm_rate(bitrate)) { 1241a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch u32 d; 1251a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch 1261a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch d = b43_plcp_get_ratecode_ofdm(bitrate); 127e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(octets & 0xF000); 1281a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch d |= (octets << 5); 1291a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch *data = cpu_to_le32(d); 130e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 131e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 plen; 132e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 133e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plen = octets * 16 / bitrate; 134e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((octets * 16 % bitrate) > 0) { 135e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plen++; 136e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((bitrate == B43_CCK_RATE_11MB) 137e4d6b7951812d98417feb10784e400e253caf633Michael Buesch && ((octets * 8 % 11) < 4)) { 138e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[1] = 0x84; 139e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 140e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[1] = 0x04; 141e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 142e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[1] = 0x04; 143e4d6b7951812d98417feb10784e400e253caf633Michael Buesch *data |= cpu_to_le32(plen << 16); 144e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[0] = b43_plcp_get_ratecode_cck(bitrate); 145e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 146e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 147e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 148e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_calc_fallback_rate(u8 bitrate) 149e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 150e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (bitrate) { 151e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_1MB: 152e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_1MB; 153e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_2MB: 154e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_1MB; 155e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_5MB: 156e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_2MB; 157e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_11MB: 158e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_5MB; 159e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_6MB: 160e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_5MB; 161e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_9MB: 162e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_6MB; 163e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_12MB: 164e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_9MB; 165e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_18MB: 166e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_12MB; 167e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_24MB: 168e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_18MB; 169e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_36MB: 170e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_24MB; 171e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_48MB: 172e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_36MB; 173e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_54MB: 174e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_48MB; 175e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 176e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 177e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 178e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 179e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 180e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic void generate_txhdr_fw4(struct b43_wldev *dev, 181e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_txhdr_fw4 *txhdr, 182e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const unsigned char *fragment_data, 183e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int fragment_len, 184e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct ieee80211_tx_control *txctl, 185e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 cookie) 186e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 187e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_phy *phy = &dev->phy; 188e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct ieee80211_hdr *wlhdr = 189e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (const struct ieee80211_hdr *)fragment_data; 190e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)); 191e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 fctl = le16_to_cpu(wlhdr->frame_control); 192e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 rate, rate_fb; 193e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rate_ofdm, rate_fb_ofdm; 194e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int plcp_fragment_len; 195e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 mac_ctl = 0; 196e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 phy_ctl = 0; 197e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 extra_ft = 0; 198e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 199e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memset(txhdr, 0, sizeof(*txhdr)); 200e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 201e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rate = txctl->tx_rate; 202e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rate_ofdm = b43_is_ofdm_rate(rate); 203e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate; 204e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); 205e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 206e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rate_ofdm) 207e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate); 208e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 209e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate); 210e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->mac_frame_ctl = wlhdr->frame_control; 211e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); 212e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 213e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Calculate duration for fallback rate */ 214e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((rate_fb == rate) || 215e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (wlhdr->duration_id & cpu_to_le16(0x8000)) || 216e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (wlhdr->duration_id == cpu_to_le16(0))) { 217e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* If the fallback rate equals the normal rate or the 218e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * dur_id field contains an AID, CFP magic or 0, 219e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * use the original dur_id field. */ 220e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->dur_fb = wlhdr->duration_id; 221e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 222e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb); 223e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, 224e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->if_id, 225e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fragment_len, 226e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fbrate_base100kbps); 227e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 228e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 229e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp_fragment_len = fragment_len + FCS_LEN; 230e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (use_encryption) { 231e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 key_idx = (u16) (txctl->key_idx); 232e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_key *key; 233e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int wlhdr_len; 234e4d6b7951812d98417feb10784e400e253caf633Michael Buesch size_t iv_len; 235e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 236e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(key_idx >= dev->max_nr_keys); 237e4d6b7951812d98417feb10784e400e253caf633Michael Buesch key = &(dev->key[key_idx]); 238e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(!key->keyconf); 239e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 240e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Hardware appends ICV. */ 241e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp_fragment_len += txctl->icv_len; 242e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 243e4d6b7951812d98417feb10784e400e253caf633Michael Buesch key_idx = b43_kidx_to_fw(dev, key_idx); 244e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= (key_idx << B43_TX4_MAC_KEYIDX_SHIFT) & 245e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_TX4_MAC_KEYIDX; 246e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= (key->algorithm << B43_TX4_MAC_KEYALG_SHIFT) & 247e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_TX4_MAC_KEYALG; 248e4d6b7951812d98417feb10784e400e253caf633Michael Buesch wlhdr_len = ieee80211_get_hdrlen(fctl); 249e4d6b7951812d98417feb10784e400e253caf633Michael Buesch iv_len = min((size_t) txctl->iv_len, 250e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ARRAY_SIZE(txhdr->iv)); 251e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); 252e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 253e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp), 254e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp_fragment_len, rate); 255e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), 256e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp_fragment_len, rate_fb); 257e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 258e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Extra Frame Types */ 259e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rate_fb_ofdm) 260e4d6b7951812d98417feb10784e400e253caf633Michael Buesch extra_ft |= B43_TX4_EFT_FBOFDM; 261e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 262e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Set channel radio code. Note that the micrcode ORs 0x100 to 263e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * this value before comparing it to the value in SHM, if this 264e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * is a 5Ghz packet. 265e4d6b7951812d98417feb10784e400e253caf633Michael Buesch */ 266e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->chan_radio_code = phy->channel; 267e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 268e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* PHY TX Control word */ 269e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rate_ofdm) 270e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phy_ctl |= B43_TX4_PHY_OFDM; 271e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (dev->short_preamble) 272e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phy_ctl |= B43_TX4_PHY_SHORTPRMBL; 273e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (txctl->antenna_sel_tx) { 274e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0: 275e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phy_ctl |= B43_TX4_PHY_ANTLAST; 276e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 277e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 1: 278e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phy_ctl |= B43_TX4_PHY_ANT0; 279e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 280e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 2: 281e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phy_ctl |= B43_TX4_PHY_ANT1; 282e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 283e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 284e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 285e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 286e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 287e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* MAC control */ 288e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK)) 289e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= B43_TX4_MAC_ACK; 290e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && 291e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) 292e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= B43_TX4_MAC_HWSEQ; 293e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT) 294e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= B43_TX4_MAC_STMSDU; 295e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_A) 296e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= B43_TX4_MAC_5GHZ; 297e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 298e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Generate the RTS or CTS-to-self frame */ 299e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) || 300e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) { 301e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int len; 302e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_hdr *hdr; 303e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rts_rate, rts_rate_fb; 304e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rts_rate_ofdm, rts_rate_fb_ofdm; 305e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 306e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate = txctl->rts_cts_rate; 307e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); 308e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_fb = b43_calc_fallback_rate(rts_rate); 309e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); 310e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 311e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { 312e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ieee80211_ctstoself_get(dev->wl->hw, dev->wl->if_id, 313e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fragment_data, fragment_len, 314e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txctl, 315e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (struct ieee80211_cts *)(txhdr-> 316e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_frame)); 317e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= B43_TX4_MAC_SENDCTS; 318e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len = sizeof(struct ieee80211_cts); 319e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 320e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ieee80211_rts_get(dev->wl->hw, dev->wl->if_id, 321e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fragment_data, fragment_len, txctl, 322e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (struct ieee80211_rts *)(txhdr-> 323e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_frame)); 324e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= B43_TX4_MAC_SENDRTS; 325e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len = sizeof(struct ieee80211_rts); 326e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 327e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len += FCS_LEN; 328e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr-> 329e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_plcp), len, 330e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate); 331e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr-> 332e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_plcp_fb), 333e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len, rts_rate_fb); 334e4d6b7951812d98417feb10784e400e253caf633Michael Buesch hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame); 335e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->rts_dur_fb = hdr->duration_id; 336e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rts_rate_ofdm) { 337e4d6b7951812d98417feb10784e400e253caf633Michael Buesch extra_ft |= B43_TX4_EFT_RTSOFDM; 338e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate_rts = 339e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_plcp_get_ratecode_ofdm(rts_rate); 340e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 341e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate_rts = 342e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_plcp_get_ratecode_cck(rts_rate); 343e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rts_rate_fb_ofdm) 344e4d6b7951812d98417feb10784e400e253caf633Michael Buesch extra_ft |= B43_TX4_EFT_RTSFBOFDM; 345e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= B43_TX4_MAC_LONGFRAME; 346e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 347e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 348e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Magic cookie */ 349e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->cookie = cpu_to_le16(cookie); 350e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 351e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Apply the bitfields */ 352e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->mac_ctl = cpu_to_le32(mac_ctl); 353e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_ctl = cpu_to_le16(phy_ctl); 354e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->extra_ft = extra_ft; 355e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 356e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 357e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_txhdr(struct b43_wldev *dev, 358e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 * txhdr, 359e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const unsigned char *fragment_data, 360e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int fragment_len, 361e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct ieee80211_tx_control *txctl, u16 cookie) 362e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 363e4d6b7951812d98417feb10784e400e253caf633Michael Buesch generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr, 364e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fragment_data, fragment_len, txctl, cookie); 365e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 366e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 367e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssi_postprocess(struct b43_wldev *dev, 368e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 in_rssi, int ofdm, 369e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int adjust_2053, int adjust_2050) 370e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 371e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_phy *phy = &dev->phy; 372e4d6b7951812d98417feb10784e400e253caf633Michael Buesch s32 tmp; 373e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 374e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (phy->radio_ver) { 375e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x2050: 376e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (ofdm) { 377e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 378e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (tmp > 127) 379e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 256; 380e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= 73; 381e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 64; 382e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (adjust_2050) 383e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp += 25; 384e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 385e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 3; 386e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 387e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (dev->dev->bus->sprom.r1. 388e4d6b7951812d98417feb10784e400e253caf633Michael Buesch boardflags_lo & B43_BFL_RSSI) { 389e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (in_rssi > 63) 390e4d6b7951812d98417feb10784e400e253caf633Michael Buesch in_rssi = 63; 391e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = phy->nrssi_lt[in_rssi]; 392e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = 31 - tmp; 393e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= -131; 394e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 128; 395e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 57; 396e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 397e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 398e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = 31 - tmp; 399e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= -149; 400e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 128; 401e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 68; 402e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 403e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_G && adjust_2050) 404e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp += 25; 405e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 406e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 407e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x2060: 408e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (in_rssi > 127) 409e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi - 256; 410e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 411e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 412e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 413e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 414e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 415e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 11; 416e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= 103; 417e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 64; 418e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (adjust_2053) 419e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 109; 420e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 421e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 83; 422e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 423e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 424e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return (s8) tmp; 425e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 426e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 427e4d6b7951812d98417feb10784e400e253caf633Michael Buesch//TODO 428e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0 429e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi) 430e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 431e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_phy *phy = &dev->phy; 432e4d6b7951812d98417feb10784e400e253caf633Michael Buesch s8 ret; 433e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 434e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_A) { 435e4d6b7951812d98417feb10784e400e253caf633Michael Buesch //TODO: Incomplete specs. 436e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ret = 0; 437e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 438e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1); 439e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 440e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return ret; 441e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 442e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif 443e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 444e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) 445e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 446e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_rx_status status; 447e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_plcp_hdr6 *plcp; 448e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_hdr *wlhdr; 449e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; 450e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 fctl; 451e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 phystat0, phystat3, chanstat, mactime; 452e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 macstat; 453e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 chanid; 454e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 jssi; 455e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int padding; 456e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 457e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memset(&status, 0, sizeof(status)); 458e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 459e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Get metadata about the frame from the header. */ 460e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phystat0 = le16_to_cpu(rxhdr->phy_status0); 461e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phystat3 = le16_to_cpu(rxhdr->phy_status3); 462e4d6b7951812d98417feb10784e400e253caf633Michael Buesch jssi = rxhdr->jssi; 463e4d6b7951812d98417feb10784e400e253caf633Michael Buesch macstat = le32_to_cpu(rxhdr->mac_status); 464e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mactime = le16_to_cpu(rxhdr->mac_time); 465e4d6b7951812d98417feb10784e400e253caf633Michael Buesch chanstat = le16_to_cpu(rxhdr->channel); 466e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 467e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_FCSERR) 468e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11FCSErrorCount++; 469e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_DECERR) { 470e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Decryption with the given key failed. 471e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * Drop the packet. We also won't be able to decrypt it with 472e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * the key in software. */ 473e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 474e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 475e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 476e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Skip PLCP and padding */ 477e4d6b7951812d98417feb10784e400e253caf633Michael Buesch padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0; 478e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) { 479e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet size underrun (1)\n"); 480e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 481e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 482e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp = (struct b43_plcp_hdr6 *)(skb->data + padding); 483e4d6b7951812d98417feb10784e400e253caf633Michael Buesch skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding); 484e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* The skb contains the Wireless Header + payload data now */ 485e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */ + FCS_LEN))) { 486e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet size underrun (2)\n"); 487e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 488e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 489e4d6b7951812d98417feb10784e400e253caf633Michael Buesch wlhdr = (struct ieee80211_hdr *)(skb->data); 490e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fctl = le16_to_cpu(wlhdr->frame_control); 491e4d6b7951812d98417feb10784e400e253caf633Michael Buesch skb_trim(skb, skb->len - FCS_LEN); 492e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 493e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_DEC) { 494e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int keyidx; 495e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int wlhdr_len; 496e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 497e4d6b7951812d98417feb10784e400e253caf633Michael Buesch keyidx = ((macstat & B43_RX_MAC_KEYIDX) 498e4d6b7951812d98417feb10784e400e253caf633Michael Buesch >> B43_RX_MAC_KEYIDX_SHIFT); 499e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* We must adjust the key index here. We want the "physical" 500e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * key index, but the ucode passed it slightly different. 501e4d6b7951812d98417feb10784e400e253caf633Michael Buesch */ 502e4d6b7951812d98417feb10784e400e253caf633Michael Buesch keyidx = b43_kidx_to_raw(dev, keyidx); 503e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(keyidx >= dev->max_nr_keys); 504e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 505e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { 506e4d6b7951812d98417feb10784e400e253caf633Michael Buesch wlhdr_len = ieee80211_get_hdrlen(fctl); 507e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (wlhdr_len + 3))) { 508e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, 509e4d6b7951812d98417feb10784e400e253caf633Michael Buesch "RX: Packet size underrun (3)\n"); 510e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 511e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 512e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.flag |= RX_FLAG_DECRYPTED; 513e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 514e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 515e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 516e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.ssi = b43_rssi_postprocess(dev, jssi, 517e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (phystat0 & B43_RX_PHYST0_OFDM), 518e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (phystat0 & B43_RX_PHYST0_GAINCTL), 519e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (phystat3 & B43_RX_PHYST3_TRSTATE)); 520e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.noise = dev->stats.link_noise; 521e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* the next line looks wrong, but is what mac80211 wants */ 522e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.signal = (jssi * 100) / B43_RX_MAX_SSI; 523e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phystat0 & B43_RX_PHYST0_OFDM) 524e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.rate = b43_plcp_get_bitrate_ofdm(plcp); 525e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 526e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.rate = b43_plcp_get_bitrate_cck(plcp); 527e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); 528e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.mactime = mactime; 529e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 530e4d6b7951812d98417feb10784e400e253caf633Michael Buesch chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; 531e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (chanstat & B43_RX_CHAN_PHYTYPE) { 532e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_PHYTYPE_A: 533e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.phymode = MODE_IEEE80211A; 534d987160b710c98997015832422a05e18d9f0f925Michael Buesch B43_WARN_ON(1); 535d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* FIXME: We don't really know which value the "chanid" contains. 536d987160b710c98997015832422a05e18d9f0f925Michael Buesch * So the following assignment might be wrong. */ 537d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.channel = chanid; 538d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.freq = b43_channel_to_freq_5ghz(status.channel); 539e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 540e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_PHYTYPE_G: 541e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.phymode = MODE_IEEE80211G; 542d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* chanid is the radio channel cookie value as used 543d987160b710c98997015832422a05e18d9f0f925Michael Buesch * to tune the radio. */ 544e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.freq = chanid + 2400; 545d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.channel = b43_freq_to_channel_2ghz(status.freq); 546d987160b710c98997015832422a05e18d9f0f925Michael Buesch break; 547d987160b710c98997015832422a05e18d9f0f925Michael Buesch case B43_PHYTYPE_N: 548d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/; 549d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* chanid is the SHM channel cookie. Which is the plain 550d987160b710c98997015832422a05e18d9f0f925Michael Buesch * channel number in b43. */ 551d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.channel = chanid; 552d987160b710c98997015832422a05e18d9f0f925Michael Buesch if (chanstat & B43_RX_CHAN_5GHZ) 553d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.freq = b43_freq_to_channel_5ghz(status.freq); 554d987160b710c98997015832422a05e18d9f0f925Michael Buesch else 555d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.freq = b43_freq_to_channel_2ghz(status.freq); 556e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 557e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 558e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 559d987160b710c98997015832422a05e18d9f0f925Michael Buesch goto drop; 560e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 561e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 562e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->stats.last_rx = jiffies; 563e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ieee80211_rx_irqsafe(dev->wl->hw, skb, &status); 564e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 565e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 566e4d6b7951812d98417feb10784e400e253caf633Michael Bueschdrop: 567e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet dropped\n"); 568e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev_kfree_skb_any(skb); 569e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 570e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 571e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_txstatus(struct b43_wldev *dev, 572e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_txstatus *status) 573e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 574e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_debugfs_log_txstat(dev, status); 575e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 576e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->intermediate) 577e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 578e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->for_ampdu) 579e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 580e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (!status->acked) 581e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11ACKFailureCount++; 582e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->rts_count) { 583e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->rts_count == 0xF) //FIXME 584e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11RTSFailureCount++; 585e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 586e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11RTSSuccessCount++; 587e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 588e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 589e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (b43_using_pio(dev)) 590e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_pio_handle_txstatus(dev, status); 591e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 592e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_dma_handle_txstatus(dev, status); 593e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 594e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 595e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Handle TX status report as received through DMA/PIO queues */ 596e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_hwtxstatus(struct b43_wldev *dev, 597e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_hwtxstatus *hw) 598e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 599e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_txstatus status; 600e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 tmp; 601e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 602e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.cookie = le16_to_cpu(hw->cookie); 603e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.seq = le16_to_cpu(hw->seq); 604e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.phy_stat = hw->phy_stat; 605e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = hw->count; 606e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.frame_count = (tmp >> 4); 607e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.rts_count = (tmp & 0x0F); 608e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = hw->flags; 609e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.supp_reason = ((tmp & 0x1C) >> 2); 610e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.pm_indicated = !!(tmp & 0x80); 611e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.intermediate = !!(tmp & 0x40); 612e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.for_ampdu = !!(tmp & 0x20); 613e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.acked = !!(tmp & 0x02); 614e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 615e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_handle_txstatus(dev, &status); 616e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 617e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 618e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Stop any TX operation on the device (suspend the hardware queues) */ 619e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_suspend(struct b43_wldev *dev) 620e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 621e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (b43_using_pio(dev)) 622e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_pio_freeze_txqueues(dev); 623e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 624e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_dma_tx_suspend(dev); 625e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 626e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 627e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Resume any TX operation on the device (resume the hardware queues) */ 628e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_resume(struct b43_wldev *dev) 629e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 630e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (b43_using_pio(dev)) 631e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_pio_thaw_txqueues(dev); 632e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 633e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_dma_tx_resume(dev); 634e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 635e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 636e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0 637e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic void upload_qos_parms(struct b43_wldev *dev, 638e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const u16 * parms, u16 offset) 639e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 640e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int i; 641e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 642e4d6b7951812d98417feb10784e400e253caf633Michael Buesch for (i = 0; i < B43_NR_QOSPARMS; i++) { 643e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_shm_write16(dev, B43_SHM_SHARED, 644e4d6b7951812d98417feb10784e400e253caf633Michael Buesch offset + (i * 2), parms[i]); 645e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 646e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 647e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif 648e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 649e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Initialize the QoS parameters */ 650e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_qos_init(struct b43_wldev *dev) 651e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 652e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* FIXME: This function must probably be called from the mac80211 653e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * config callback. */ 654e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 655e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 656e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); 657e4d6b7951812d98417feb10784e400e253caf633Michael Buesch //FIXME kill magic 658e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4); 659e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 660e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /*TODO: We might need some stack support here to get the values. */ 661e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 662