diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-01-28 17:47:41 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:09:50 -0500 |
commit | eb189d8bc9824bcb2187ffdab27d77ab469264c3 (patch) | |
tree | 612c6549f0d0261087b55b157dd5ca016386ddee /drivers/net/wireless/b43/xmit.c | |
parent | 243dcfcc1d4b33aa610f1bf3ec610dafdf4d7ff7 (diff) |
b43: Add support for new firmware
This patch adds support for new firmware.
Old firmware is still supported until July 2008.
To get new firmware, go to
ftp://ftp.linksys.com/opensourcecode/wrt150nv11/1.51.3/
and download the tarball. We don't have a smaller tarball, yet.
That will be fixed later.
You can extract firmware out of the "wl_ap.o" file contained
in this tarball using latest fwcutter. You must pass the option
--unsupported to fwcutter.
Fwcutter-010 with official support for a new firmware image will
be released soon.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/b43/xmit.c')
-rw-r--r-- | drivers/net/wireless/b43/xmit.c | 144 |
1 files changed, 94 insertions, 50 deletions
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 5014213b7752..3fc53e8b4416 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -177,13 +177,15 @@ static u8 b43_calc_fallback_rate(u8 bitrate) | |||
177 | return 0; | 177 | return 0; |
178 | } | 178 | } |
179 | 179 | ||
180 | static void generate_txhdr_fw4(struct b43_wldev *dev, | 180 | /* Generate a TX data header. */ |
181 | struct b43_txhdr_fw4 *txhdr, | 181 | void b43_generate_txhdr(struct b43_wldev *dev, |
182 | const unsigned char *fragment_data, | 182 | u8 *_txhdr, |
183 | unsigned int fragment_len, | 183 | const unsigned char *fragment_data, |
184 | const struct ieee80211_tx_control *txctl, | 184 | unsigned int fragment_len, |
185 | u16 cookie) | 185 | const struct ieee80211_tx_control *txctl, |
186 | u16 cookie) | ||
186 | { | 187 | { |
188 | struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; | ||
187 | const struct b43_phy *phy = &dev->phy; | 189 | const struct b43_phy *phy = &dev->phy; |
188 | const struct ieee80211_hdr *wlhdr = | 190 | const struct ieee80211_hdr *wlhdr = |
189 | (const struct ieee80211_hdr *)fragment_data; | 191 | (const struct ieee80211_hdr *)fragment_data; |
@@ -241,23 +243,30 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, | |||
241 | plcp_fragment_len += txctl->icv_len; | 243 | plcp_fragment_len += txctl->icv_len; |
242 | 244 | ||
243 | key_idx = b43_kidx_to_fw(dev, key_idx); | 245 | key_idx = b43_kidx_to_fw(dev, key_idx); |
244 | mac_ctl |= (key_idx << B43_TX4_MAC_KEYIDX_SHIFT) & | 246 | mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & |
245 | B43_TX4_MAC_KEYIDX; | 247 | B43_TXH_MAC_KEYIDX; |
246 | mac_ctl |= (key->algorithm << B43_TX4_MAC_KEYALG_SHIFT) & | 248 | mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & |
247 | B43_TX4_MAC_KEYALG; | 249 | B43_TXH_MAC_KEYALG; |
248 | wlhdr_len = ieee80211_get_hdrlen(fctl); | 250 | wlhdr_len = ieee80211_get_hdrlen(fctl); |
249 | iv_len = min((size_t) txctl->iv_len, | 251 | iv_len = min((size_t) txctl->iv_len, |
250 | ARRAY_SIZE(txhdr->iv)); | 252 | ARRAY_SIZE(txhdr->iv)); |
251 | memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); | 253 | memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); |
252 | } | 254 | } |
253 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp), | 255 | if (b43_is_old_txhdr_format(dev)) { |
254 | plcp_fragment_len, rate); | 256 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), |
257 | plcp_fragment_len, rate); | ||
258 | } else { | ||
259 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp), | ||
260 | plcp_fragment_len, rate); | ||
261 | } | ||
255 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), | 262 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), |
256 | plcp_fragment_len, rate_fb); | 263 | plcp_fragment_len, rate_fb); |
257 | 264 | ||
258 | /* Extra Frame Types */ | 265 | /* Extra Frame Types */ |
259 | if (rate_fb_ofdm) | 266 | if (rate_fb_ofdm) |
260 | extra_ft |= B43_TX4_EFT_FBOFDM; | 267 | extra_ft |= B43_TXH_EFT_FB_OFDM; |
268 | else | ||
269 | extra_ft |= B43_TXH_EFT_FB_CCK; | ||
261 | 270 | ||
262 | /* Set channel radio code. Note that the micrcode ORs 0x100 to | 271 | /* Set channel radio code. Note that the micrcode ORs 0x100 to |
263 | * this value before comparing it to the value in SHM, if this | 272 | * this value before comparing it to the value in SHM, if this |
@@ -267,19 +276,27 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, | |||
267 | 276 | ||
268 | /* PHY TX Control word */ | 277 | /* PHY TX Control word */ |
269 | if (rate_ofdm) | 278 | if (rate_ofdm) |
270 | phy_ctl |= B43_TX4_PHY_OFDM; | 279 | phy_ctl |= B43_TXH_PHY_ENC_OFDM; |
280 | else | ||
281 | phy_ctl |= B43_TXH_PHY_ENC_CCK; | ||
271 | if (dev->short_preamble) | 282 | if (dev->short_preamble) |
272 | phy_ctl |= B43_TX4_PHY_SHORTPRMBL; | 283 | phy_ctl |= B43_TXH_PHY_SHORTPRMBL; |
273 | 284 | ||
274 | switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) { | 285 | switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) { |
275 | case 0: /* Default */ | 286 | case 0: /* Default */ |
276 | phy_ctl |= B43_TX4_PHY_ANTLAST; | 287 | phy_ctl |= B43_TXH_PHY_ANT01AUTO; |
277 | break; | 288 | break; |
278 | case 1: /* Antenna 0 */ | 289 | case 1: /* Antenna 0 */ |
279 | phy_ctl |= B43_TX4_PHY_ANT0; | 290 | phy_ctl |= B43_TXH_PHY_ANT0; |
280 | break; | 291 | break; |
281 | case 2: /* Antenna 1 */ | 292 | case 2: /* Antenna 1 */ |
282 | phy_ctl |= B43_TX4_PHY_ANT1; | 293 | phy_ctl |= B43_TXH_PHY_ANT1; |
294 | break; | ||
295 | case 3: /* Antenna 2 */ | ||
296 | phy_ctl |= B43_TXH_PHY_ANT2; | ||
297 | break; | ||
298 | case 4: /* Antenna 3 */ | ||
299 | phy_ctl |= B43_TXH_PHY_ANT3; | ||
283 | break; | 300 | break; |
284 | default: | 301 | default: |
285 | B43_WARN_ON(1); | 302 | B43_WARN_ON(1); |
@@ -287,16 +304,16 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, | |||
287 | 304 | ||
288 | /* MAC control */ | 305 | /* MAC control */ |
289 | if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK)) | 306 | if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK)) |
290 | mac_ctl |= B43_TX4_MAC_ACK; | 307 | mac_ctl |= B43_TXH_MAC_ACK; |
291 | if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && | 308 | if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && |
292 | ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) | 309 | ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) |
293 | mac_ctl |= B43_TX4_MAC_HWSEQ; | 310 | mac_ctl |= B43_TXH_MAC_HWSEQ; |
294 | if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT) | 311 | if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT) |
295 | mac_ctl |= B43_TX4_MAC_STMSDU; | 312 | mac_ctl |= B43_TXH_MAC_STMSDU; |
296 | if (phy->type == B43_PHYTYPE_A) | 313 | if (phy->type == B43_PHYTYPE_A) |
297 | mac_ctl |= B43_TX4_MAC_5GHZ; | 314 | mac_ctl |= B43_TXH_MAC_5GHZ; |
298 | if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT) | 315 | if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT) |
299 | mac_ctl |= B43_TX4_MAC_LONGFRAME; | 316 | mac_ctl |= B43_TXH_MAC_LONGFRAME; |
300 | 317 | ||
301 | /* Generate the RTS or CTS-to-self frame */ | 318 | /* Generate the RTS or CTS-to-self frame */ |
302 | if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) || | 319 | if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) || |
@@ -305,6 +322,7 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, | |||
305 | struct ieee80211_hdr *hdr; | 322 | struct ieee80211_hdr *hdr; |
306 | int rts_rate, rts_rate_fb; | 323 | int rts_rate, rts_rate_fb; |
307 | int rts_rate_ofdm, rts_rate_fb_ofdm; | 324 | int rts_rate_ofdm, rts_rate_fb_ofdm; |
325 | struct b43_plcp_hdr6 *plcp; | ||
308 | 326 | ||
309 | rts_rate = txctl->rts_cts_rate; | 327 | rts_rate = txctl->rts_cts_rate; |
310 | rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); | 328 | rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); |
@@ -312,58 +330,84 @@ static void generate_txhdr_fw4(struct b43_wldev *dev, | |||
312 | rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); | 330 | rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); |
313 | 331 | ||
314 | if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { | 332 | if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { |
333 | struct ieee80211_cts *cts; | ||
334 | |||
335 | if (b43_is_old_txhdr_format(dev)) { | ||
336 | cts = (struct ieee80211_cts *) | ||
337 | (txhdr->old_format.rts_frame); | ||
338 | } else { | ||
339 | cts = (struct ieee80211_cts *) | ||
340 | (txhdr->new_format.rts_frame); | ||
341 | } | ||
315 | ieee80211_ctstoself_get(dev->wl->hw, txctl->vif, | 342 | ieee80211_ctstoself_get(dev->wl->hw, txctl->vif, |
316 | fragment_data, fragment_len, | 343 | fragment_data, fragment_len, |
317 | txctl, | 344 | txctl, cts); |
318 | (struct ieee80211_cts *)(txhdr-> | 345 | mac_ctl |= B43_TXH_MAC_SENDCTS; |
319 | rts_frame)); | ||
320 | mac_ctl |= B43_TX4_MAC_SENDCTS; | ||
321 | len = sizeof(struct ieee80211_cts); | 346 | len = sizeof(struct ieee80211_cts); |
322 | } else { | 347 | } else { |
348 | struct ieee80211_rts *rts; | ||
349 | |||
350 | if (b43_is_old_txhdr_format(dev)) { | ||
351 | rts = (struct ieee80211_rts *) | ||
352 | (txhdr->old_format.rts_frame); | ||
353 | } else { | ||
354 | rts = (struct ieee80211_rts *) | ||
355 | (txhdr->new_format.rts_frame); | ||
356 | } | ||
323 | ieee80211_rts_get(dev->wl->hw, txctl->vif, | 357 | ieee80211_rts_get(dev->wl->hw, txctl->vif, |
324 | fragment_data, fragment_len, txctl, | 358 | fragment_data, fragment_len, |
325 | (struct ieee80211_rts *)(txhdr-> | 359 | txctl, rts); |
326 | rts_frame)); | 360 | mac_ctl |= B43_TXH_MAC_SENDRTS; |
327 | mac_ctl |= B43_TX4_MAC_SENDRTS; | ||
328 | len = sizeof(struct ieee80211_rts); | 361 | len = sizeof(struct ieee80211_rts); |
329 | } | 362 | } |
330 | len += FCS_LEN; | 363 | len += FCS_LEN; |
331 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr-> | 364 | |
332 | rts_plcp), len, | 365 | /* Generate the PLCP headers for the RTS/CTS frame */ |
333 | rts_rate); | 366 | if (b43_is_old_txhdr_format(dev)) |
334 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr-> | 367 | plcp = &txhdr->old_format.rts_plcp; |
335 | rts_plcp_fb), | 368 | else |
369 | plcp = &txhdr->new_format.rts_plcp; | ||
370 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, | ||
371 | len, rts_rate); | ||
372 | plcp = &txhdr->rts_plcp_fb; | ||
373 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, | ||
336 | len, rts_rate_fb); | 374 | len, rts_rate_fb); |
337 | hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame); | 375 | |
376 | if (b43_is_old_txhdr_format(dev)) { | ||
377 | hdr = (struct ieee80211_hdr *) | ||
378 | (&txhdr->old_format.rts_frame); | ||
379 | } else { | ||
380 | hdr = (struct ieee80211_hdr *) | ||
381 | (&txhdr->new_format.rts_frame); | ||
382 | } | ||
338 | txhdr->rts_dur_fb = hdr->duration_id; | 383 | txhdr->rts_dur_fb = hdr->duration_id; |
384 | |||
339 | if (rts_rate_ofdm) { | 385 | if (rts_rate_ofdm) { |
340 | extra_ft |= B43_TX4_EFT_RTSOFDM; | 386 | extra_ft |= B43_TXH_EFT_RTS_OFDM; |
341 | txhdr->phy_rate_rts = | 387 | txhdr->phy_rate_rts = |
342 | b43_plcp_get_ratecode_ofdm(rts_rate); | 388 | b43_plcp_get_ratecode_ofdm(rts_rate); |
343 | } else | 389 | } else { |
390 | extra_ft |= B43_TXH_EFT_RTS_CCK; | ||
344 | txhdr->phy_rate_rts = | 391 | txhdr->phy_rate_rts = |
345 | b43_plcp_get_ratecode_cck(rts_rate); | 392 | b43_plcp_get_ratecode_cck(rts_rate); |
393 | } | ||
346 | if (rts_rate_fb_ofdm) | 394 | if (rts_rate_fb_ofdm) |
347 | extra_ft |= B43_TX4_EFT_RTSFBOFDM; | 395 | extra_ft |= B43_TXH_EFT_RTSFB_OFDM; |
396 | else | ||
397 | extra_ft |= B43_TXH_EFT_RTSFB_CCK; | ||
348 | } | 398 | } |
349 | 399 | ||
350 | /* Magic cookie */ | 400 | /* Magic cookie */ |
351 | txhdr->cookie = cpu_to_le16(cookie); | 401 | if (b43_is_old_txhdr_format(dev)) |
402 | txhdr->old_format.cookie = cpu_to_le16(cookie); | ||
403 | else | ||
404 | txhdr->new_format.cookie = cpu_to_le16(cookie); | ||
352 | 405 | ||
353 | /* Apply the bitfields */ | 406 | /* Apply the bitfields */ |
354 | txhdr->mac_ctl = cpu_to_le32(mac_ctl); | 407 | txhdr->mac_ctl = cpu_to_le32(mac_ctl); |
355 | txhdr->phy_ctl = cpu_to_le16(phy_ctl); | 408 | txhdr->phy_ctl = cpu_to_le16(phy_ctl); |
356 | txhdr->extra_ft = extra_ft; | 409 | txhdr->extra_ft = extra_ft; |
357 | } | ||
358 | 410 | ||
359 | void b43_generate_txhdr(struct b43_wldev *dev, | ||
360 | u8 * txhdr, | ||
361 | const unsigned char *fragment_data, | ||
362 | unsigned int fragment_len, | ||
363 | const struct ieee80211_tx_control *txctl, u16 cookie) | ||
364 | { | ||
365 | generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr, | ||
366 | fragment_data, fragment_len, txctl, cookie); | ||
367 | } | 411 | } |
368 | 412 | ||
369 | static s8 b43_rssi_postprocess(struct b43_wldev *dev, | 413 | static s8 b43_rssi_postprocess(struct b43_wldev *dev, |