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