xmit.c revision c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41d
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> 81f21ad2a4f7f66855dae600ddd635ff5fb299bbdStefano Brivio Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it> 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; 29774cfdba7ce7b601559a4bcdc9054baf1bdc6948dMichael Buesch if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT) 29874cfdba7ce7b601559a4bcdc9054baf1bdc6948dMichael Buesch mac_ctl |= B43_TX4_MAC_LONGFRAME; 299e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 300e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Generate the RTS or CTS-to-self frame */ 301e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) || 302e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) { 303e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int len; 304e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_hdr *hdr; 305e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rts_rate, rts_rate_fb; 306e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rts_rate_ofdm, rts_rate_fb_ofdm; 307e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 308e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate = txctl->rts_cts_rate; 309e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); 310e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_fb = b43_calc_fallback_rate(rts_rate); 311e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); 312e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 313e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { 314e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ieee80211_ctstoself_get(dev->wl->hw, dev->wl->if_id, 315e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fragment_data, fragment_len, 316e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txctl, 317e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (struct ieee80211_cts *)(txhdr-> 318e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_frame)); 319e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= B43_TX4_MAC_SENDCTS; 320e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len = sizeof(struct ieee80211_cts); 321e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 322e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ieee80211_rts_get(dev->wl->hw, dev->wl->if_id, 323e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fragment_data, fragment_len, txctl, 324e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (struct ieee80211_rts *)(txhdr-> 325e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_frame)); 326e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mac_ctl |= B43_TX4_MAC_SENDRTS; 327e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len = sizeof(struct ieee80211_rts); 328e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 329e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len += FCS_LEN; 330e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr-> 331e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_plcp), len, 332e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate); 333e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr-> 334e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_plcp_fb), 335e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len, rts_rate_fb); 336e4d6b7951812d98417feb10784e400e253caf633Michael Buesch hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame); 337e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->rts_dur_fb = hdr->duration_id; 338e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rts_rate_ofdm) { 339e4d6b7951812d98417feb10784e400e253caf633Michael Buesch extra_ft |= B43_TX4_EFT_RTSOFDM; 340e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate_rts = 341e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_plcp_get_ratecode_ofdm(rts_rate); 342e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 343e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate_rts = 344e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_plcp_get_ratecode_cck(rts_rate); 345e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rts_rate_fb_ofdm) 346e4d6b7951812d98417feb10784e400e253caf633Michael Buesch extra_ft |= B43_TX4_EFT_RTSFBOFDM; 347e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 348e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 349e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Magic cookie */ 350e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->cookie = cpu_to_le16(cookie); 351e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 352e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Apply the bitfields */ 353e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->mac_ctl = cpu_to_le32(mac_ctl); 354e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_ctl = cpu_to_le16(phy_ctl); 355e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->extra_ft = extra_ft; 356e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 357e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 358e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_txhdr(struct b43_wldev *dev, 359e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 * txhdr, 360e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const unsigned char *fragment_data, 361e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int fragment_len, 362e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct ieee80211_tx_control *txctl, u16 cookie) 363e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 364e4d6b7951812d98417feb10784e400e253caf633Michael Buesch generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr, 365e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fragment_data, fragment_len, txctl, cookie); 366e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 367e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 368e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssi_postprocess(struct b43_wldev *dev, 369e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 in_rssi, int ofdm, 370e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int adjust_2053, int adjust_2050) 371e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 372e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_phy *phy = &dev->phy; 373e4d6b7951812d98417feb10784e400e253caf633Michael Buesch s32 tmp; 374e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 375e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (phy->radio_ver) { 376e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x2050: 377e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (ofdm) { 378e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 379e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (tmp > 127) 380e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 256; 381e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= 73; 382e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 64; 383e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (adjust_2050) 384e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp += 25; 385e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 386e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 3; 387e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 38895de2841aad971867851b59c0c5253ecc2e19832Larry Finger if (dev->dev->bus->sprom. 389e4d6b7951812d98417feb10784e400e253caf633Michael Buesch boardflags_lo & B43_BFL_RSSI) { 390e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (in_rssi > 63) 391e4d6b7951812d98417feb10784e400e253caf633Michael Buesch in_rssi = 63; 392e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = phy->nrssi_lt[in_rssi]; 393e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = 31 - tmp; 394e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= -131; 395e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 128; 396e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 57; 397e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 398e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 399e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = 31 - tmp; 400e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= -149; 401e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 128; 402e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 68; 403e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 404e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_G && adjust_2050) 405e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp += 25; 406e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 407e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 408e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x2060: 409e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (in_rssi > 127) 410e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi - 256; 411e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 412e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 413e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 414e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 415e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 416e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 11; 417e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= 103; 418e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 64; 419e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (adjust_2053) 420e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 109; 421e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 422e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 83; 423e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 424e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 425e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return (s8) tmp; 426e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 427e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 428e4d6b7951812d98417feb10784e400e253caf633Michael Buesch//TODO 429e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0 430e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi) 431e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 432e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_phy *phy = &dev->phy; 433e4d6b7951812d98417feb10784e400e253caf633Michael Buesch s8 ret; 434e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 435e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_A) { 436e4d6b7951812d98417feb10784e400e253caf633Michael Buesch //TODO: Incomplete specs. 437e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ret = 0; 438e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 439e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1); 440e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 441e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return ret; 442e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 443e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif 444e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 445e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) 446e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 447e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_rx_status status; 448e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_plcp_hdr6 *plcp; 449e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_hdr *wlhdr; 450e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; 451e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 fctl; 452e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 phystat0, phystat3, chanstat, mactime; 453e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 macstat; 454e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 chanid; 455e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 jssi; 456e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int padding; 457e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 458e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memset(&status, 0, sizeof(status)); 459e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 460e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Get metadata about the frame from the header. */ 461e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phystat0 = le16_to_cpu(rxhdr->phy_status0); 462e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phystat3 = le16_to_cpu(rxhdr->phy_status3); 463e4d6b7951812d98417feb10784e400e253caf633Michael Buesch jssi = rxhdr->jssi; 464e4d6b7951812d98417feb10784e400e253caf633Michael Buesch macstat = le32_to_cpu(rxhdr->mac_status); 465e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mactime = le16_to_cpu(rxhdr->mac_time); 466e4d6b7951812d98417feb10784e400e253caf633Michael Buesch chanstat = le16_to_cpu(rxhdr->channel); 467e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 468e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_FCSERR) 469e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11FCSErrorCount++; 470e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_DECERR) { 471e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Decryption with the given key failed. 472e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * Drop the packet. We also won't be able to decrypt it with 473e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * the key in software. */ 474e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 475e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 476e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 477e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Skip PLCP and padding */ 478e4d6b7951812d98417feb10784e400e253caf633Michael Buesch padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0; 479e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) { 480e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet size underrun (1)\n"); 481e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 482e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 483e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp = (struct b43_plcp_hdr6 *)(skb->data + padding); 484e4d6b7951812d98417feb10784e400e253caf633Michael Buesch skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding); 485e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* The skb contains the Wireless Header + payload data now */ 486e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */ + FCS_LEN))) { 487e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet size underrun (2)\n"); 488e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 489e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 490e4d6b7951812d98417feb10784e400e253caf633Michael Buesch wlhdr = (struct ieee80211_hdr *)(skb->data); 491e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fctl = le16_to_cpu(wlhdr->frame_control); 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); 528c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville 529c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville /* 530c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville * If monitors are present get full 64-bit timestamp. This 531c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville * code assumes we get to process the packet within 16 bits 532c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville * of timestamp, i.e. about 65 milliseconds after the PHY 533c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville * received the first symbol. 534c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville */ 535c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville if (dev->wl->radiotap_enabled) { 536c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville u16 low_mactime_now; 537c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville 538c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville b43_tsf_read(dev, &status.mactime); 539c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville low_mactime_now = status.mactime; 540c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime = status.mactime & ~0xFFFFULL; 541c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime += mactime; 542c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville if (low_mactime_now <= mactime) 543c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime -= 0x10000; 544c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.flag |= RX_FLAG_TSFT; 545c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville } 546e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 547e4d6b7951812d98417feb10784e400e253caf633Michael Buesch chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; 548e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (chanstat & B43_RX_CHAN_PHYTYPE) { 549e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_PHYTYPE_A: 550e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.phymode = MODE_IEEE80211A; 551d987160b710c98997015832422a05e18d9f0f925Michael Buesch B43_WARN_ON(1); 552d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* FIXME: We don't really know which value the "chanid" contains. 553d987160b710c98997015832422a05e18d9f0f925Michael Buesch * So the following assignment might be wrong. */ 554d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.channel = chanid; 555d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.freq = b43_channel_to_freq_5ghz(status.channel); 556e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 557e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_PHYTYPE_G: 558e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.phymode = MODE_IEEE80211G; 559d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* chanid is the radio channel cookie value as used 560d987160b710c98997015832422a05e18d9f0f925Michael Buesch * to tune the radio. */ 561e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.freq = chanid + 2400; 562d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.channel = b43_freq_to_channel_2ghz(status.freq); 563d987160b710c98997015832422a05e18d9f0f925Michael Buesch break; 564d987160b710c98997015832422a05e18d9f0f925Michael Buesch case B43_PHYTYPE_N: 565d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/; 566d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* chanid is the SHM channel cookie. Which is the plain 567d987160b710c98997015832422a05e18d9f0f925Michael Buesch * channel number in b43. */ 568d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.channel = chanid; 569d987160b710c98997015832422a05e18d9f0f925Michael Buesch if (chanstat & B43_RX_CHAN_5GHZ) 570d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.freq = b43_freq_to_channel_5ghz(status.freq); 571d987160b710c98997015832422a05e18d9f0f925Michael Buesch else 572d987160b710c98997015832422a05e18d9f0f925Michael Buesch status.freq = b43_freq_to_channel_2ghz(status.freq); 573e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 574e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 575e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 576d987160b710c98997015832422a05e18d9f0f925Michael Buesch goto drop; 577e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 578e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 579e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->stats.last_rx = jiffies; 580e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ieee80211_rx_irqsafe(dev->wl->hw, skb, &status); 581e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 582e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 583e4d6b7951812d98417feb10784e400e253caf633Michael Bueschdrop: 584e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet dropped\n"); 585e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev_kfree_skb_any(skb); 586e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 587e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 588e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_txstatus(struct b43_wldev *dev, 589e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_txstatus *status) 590e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 591e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_debugfs_log_txstat(dev, status); 592e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 593e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->intermediate) 594e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 595e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->for_ampdu) 596e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 597e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (!status->acked) 598e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11ACKFailureCount++; 599e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->rts_count) { 600e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->rts_count == 0xF) //FIXME 601e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11RTSFailureCount++; 602e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 603e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11RTSSuccessCount++; 604e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 605e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 606e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (b43_using_pio(dev)) 607e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_pio_handle_txstatus(dev, status); 608e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 609e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_dma_handle_txstatus(dev, status); 610e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 611e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 612e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Handle TX status report as received through DMA/PIO queues */ 613e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_hwtxstatus(struct b43_wldev *dev, 614e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_hwtxstatus *hw) 615e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 616e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_txstatus status; 617e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 tmp; 618e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 619e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.cookie = le16_to_cpu(hw->cookie); 620e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.seq = le16_to_cpu(hw->seq); 621e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.phy_stat = hw->phy_stat; 622e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = hw->count; 623e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.frame_count = (tmp >> 4); 624e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.rts_count = (tmp & 0x0F); 625e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = hw->flags; 626e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.supp_reason = ((tmp & 0x1C) >> 2); 627e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.pm_indicated = !!(tmp & 0x80); 628e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.intermediate = !!(tmp & 0x40); 629e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.for_ampdu = !!(tmp & 0x20); 630e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.acked = !!(tmp & 0x02); 631e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 632e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_handle_txstatus(dev, &status); 633e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 634e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 635e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Stop any TX operation on the device (suspend the hardware queues) */ 636e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_suspend(struct b43_wldev *dev) 637e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 638e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (b43_using_pio(dev)) 639e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_pio_freeze_txqueues(dev); 640e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 641e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_dma_tx_suspend(dev); 642e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 643e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 644e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Resume any TX operation on the device (resume the hardware queues) */ 645e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_resume(struct b43_wldev *dev) 646e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 647e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (b43_using_pio(dev)) 648e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_pio_thaw_txqueues(dev); 649e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 650e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_dma_tx_resume(dev); 651e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 652e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 653e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0 654e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic void upload_qos_parms(struct b43_wldev *dev, 655e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const u16 * parms, u16 offset) 656e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 657e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int i; 658e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 659e4d6b7951812d98417feb10784e400e253caf633Michael Buesch for (i = 0; i < B43_NR_QOSPARMS; i++) { 660e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_shm_write16(dev, B43_SHM_SHARED, 661e4d6b7951812d98417feb10784e400e253caf633Michael Buesch offset + (i * 2), parms[i]); 662e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 663e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 664e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif 665e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 666e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Initialize the QoS parameters */ 667e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_qos_init(struct b43_wldev *dev) 668e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 669e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* FIXME: This function must probably be called from the mac80211 670e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * config callback. */ 671e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 672e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 673e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); 674e4d6b7951812d98417feb10784e400e253caf633Michael Buesch //FIXME kill magic 675e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4); 676e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 677e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /*TODO: We might need some stack support here to get the values. */ 678e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 679