aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcm43xx
diff options
context:
space:
mode:
authorMichael Buesch <mbuesch@freenet.de>2006-02-23 15:15:39 -0500
committerJohn W. Linville <linville@tuxdriver.com>2006-03-27 11:18:40 -0500
commitf398f02d12cdc372e16c5e86246b10acf7211abc (patch)
treee1f705974b5380e43e2308355d461197fa553468 /drivers/net/wireless/bcm43xx
parent1d1a73ccdc618168f2a5c962aab250605c93e517 (diff)
[PATCH] bcm43xx: Move TX/RX related functions to its own file. Add basic RTS/CTS code.
Signed-off-by: Michael Buesch <mbuesch@freenet.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/bcm43xx')
-rw-r--r--drivers/net/wireless/bcm43xx/Makefile1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h23
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.c1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c430
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.h131
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.c1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.c579
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.h156
9 files changed, 746 insertions, 577 deletions
diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile
index c87c1525b39..2962b5f9e3e 100644
--- a/drivers/net/wireless/bcm43xx/Makefile
+++ b/drivers/net/wireless/bcm43xx/Makefile
@@ -8,4 +8,5 @@ bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \
8 bcm43xx_radio.o bcm43xx_phy.o \ 8 bcm43xx_radio.o bcm43xx_phy.o \
9 bcm43xx_power.o bcm43xx_wx.o \ 9 bcm43xx_power.o bcm43xx_wx.o \
10 bcm43xx_leds.o bcm43xx_ethtool.o \ 10 bcm43xx_leds.o bcm43xx_ethtool.o \
11 bcm43xx_xmit.o \
11 $(bcm43xx-obj-y) 12 $(bcm43xx-obj-y)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 848717513b5..21c75cae14b 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -314,23 +314,6 @@
314/* Initial default iw_mode */ 314/* Initial default iw_mode */
315#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA 315#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA
316 316
317/* Values/Masks for the device TX header */
318#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001
319#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008
320#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020
321#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100
322#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800
323
324#define BCM43xx_TXHDRCTL_OFDM 0x0001
325#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010
326#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030
327#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8
328
329#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0
330#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4
331#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003
332#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0
333
334/* Bus type PCI. */ 317/* Bus type PCI. */
335#define BCM43xx_BUSTYPE_PCI 0 318#define BCM43xx_BUSTYPE_PCI 0
336/* Bus type Silicone Backplane Bus. */ 319/* Bus type Silicone Backplane Bus. */
@@ -952,4 +935,10 @@ int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 valu
952 __value; \ 935 __value; \
953 }) 936 })
954 937
938/** Helpers to print MAC addresses. */
939#define BCM43xx_MACFMT "%02x:%02x:%02x:%02x:%02x:%02x"
940#define BCM43xx_MACARG(x) ((u8*)(x))[0], ((u8*)(x))[1], \
941 ((u8*)(x))[2], ((u8*)(x))[3], \
942 ((u8*)(x))[4], ((u8*)(x))[5]
943
955#endif /* BCM43xx_H_ */ 944#endif /* BCM43xx_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index 5a7dc43cd67..0bae0be4be2 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -37,6 +37,7 @@
37#include "bcm43xx_debugfs.h" 37#include "bcm43xx_debugfs.h"
38#include "bcm43xx_dma.h" 38#include "bcm43xx_dma.h"
39#include "bcm43xx_pio.h" 39#include "bcm43xx_pio.h"
40#include "bcm43xx_xmit.h"
40 41
41#define REALLY_BIG_BUFFER_SIZE (1024*256) 42#define REALLY_BIG_BUFFER_SIZE (1024*256)
42 43
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index af5c27f9bfd..e20fbaf29e0 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -32,6 +32,7 @@
32#include "bcm43xx_main.h" 32#include "bcm43xx_main.h"
33#include "bcm43xx_debugfs.h" 33#include "bcm43xx_debugfs.h"
34#include "bcm43xx_power.h" 34#include "bcm43xx_power.h"
35#include "bcm43xx_xmit.h"
35 36
36#include <linux/dmapool.h> 37#include <linux/dmapool.h>
37#include <linux/pci.h> 38#include <linux/pci.h>
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 899c06fe0bf..f1ac9940f14 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -50,6 +50,7 @@
50#include "bcm43xx_power.h" 50#include "bcm43xx_power.h"
51#include "bcm43xx_wx.h" 51#include "bcm43xx_wx.h"
52#include "bcm43xx_ethtool.h" 52#include "bcm43xx_ethtool.h"
53#include "bcm43xx_xmit.h"
53 54
54 55
55MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); 56MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
@@ -342,234 +343,6 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
342 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); 343 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
343} 344}
344 345
345static u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp,
346 const int ofdm_modulation)
347{
348 u8 rate;
349
350 if (ofdm_modulation) {
351 switch (plcp->raw[0] & 0xF) {
352 case 0xB:
353 rate = IEEE80211_OFDM_RATE_6MB;
354 break;
355 case 0xF:
356 rate = IEEE80211_OFDM_RATE_9MB;
357 break;
358 case 0xA:
359 rate = IEEE80211_OFDM_RATE_12MB;
360 break;
361 case 0xE:
362 rate = IEEE80211_OFDM_RATE_18MB;
363 break;
364 case 0x9:
365 rate = IEEE80211_OFDM_RATE_24MB;
366 break;
367 case 0xD:
368 rate = IEEE80211_OFDM_RATE_36MB;
369 break;
370 case 0x8:
371 rate = IEEE80211_OFDM_RATE_48MB;
372 break;
373 case 0xC:
374 rate = IEEE80211_OFDM_RATE_54MB;
375 break;
376 default:
377 rate = 0;
378 assert(0);
379 }
380 } else {
381 switch (plcp->raw[0]) {
382 case 0x0A:
383 rate = IEEE80211_CCK_RATE_1MB;
384 break;
385 case 0x14:
386 rate = IEEE80211_CCK_RATE_2MB;
387 break;
388 case 0x37:
389 rate = IEEE80211_CCK_RATE_5MB;
390 break;
391 case 0x6E:
392 rate = IEEE80211_CCK_RATE_11MB;
393 break;
394 default:
395 rate = 0;
396 assert(0);
397 }
398 }
399
400 return rate;
401}
402
403static u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
404{
405 switch (bitrate) {
406 case IEEE80211_CCK_RATE_1MB:
407 return 0x0A;
408 case IEEE80211_CCK_RATE_2MB:
409 return 0x14;
410 case IEEE80211_CCK_RATE_5MB:
411 return 0x37;
412 case IEEE80211_CCK_RATE_11MB:
413 return 0x6E;
414 }
415 assert(0);
416 return 0;
417}
418
419static u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
420{
421 switch (bitrate) {
422 case IEEE80211_OFDM_RATE_6MB:
423 return 0xB;
424 case IEEE80211_OFDM_RATE_9MB:
425 return 0xF;
426 case IEEE80211_OFDM_RATE_12MB:
427 return 0xA;
428 case IEEE80211_OFDM_RATE_18MB:
429 return 0xE;
430 case IEEE80211_OFDM_RATE_24MB:
431 return 0x9;
432 case IEEE80211_OFDM_RATE_36MB:
433 return 0xD;
434 case IEEE80211_OFDM_RATE_48MB:
435 return 0x8;
436 case IEEE80211_OFDM_RATE_54MB:
437 return 0xC;
438 }
439 assert(0);
440 return 0;
441}
442
443static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
444 u16 octets, const u8 bitrate,
445 const int ofdm_modulation)
446{
447 __le32 *data = &(plcp->data);
448 __u8 *raw = plcp->raw;
449
450 /* Account for hardware-appended FCS. */
451 octets += IEEE80211_FCS_LEN;
452
453 if (ofdm_modulation) {
454 *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
455 assert(!(octets & 0xF000));
456 *data |= (octets << 5);
457 *data = cpu_to_le32(*data);
458 } else {
459 u32 plen;
460
461 plen = octets * 16 / bitrate;
462 if ((octets * 16 % bitrate) > 0) {
463 plen++;
464 if ((bitrate == IEEE80211_CCK_RATE_11MB)
465 && ((octets * 8 % 11) < 4)) {
466 raw[1] = 0x84;
467 } else
468 raw[1] = 0x04;
469 } else
470 raw[1] = 0x04;
471 *data |= cpu_to_le32(plen << 16);
472 raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
473 }
474
475//bcm43xx_printk_bitdump(raw, 4, 0, "PLCP");
476}
477
478void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
479 struct bcm43xx_txhdr *txhdr,
480 const unsigned char *fragment_data,
481 unsigned int fragment_len,
482 const int is_first_fragment,
483 const u16 cookie)
484{
485 const struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
486 const struct ieee80211_hdr_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data;
487 const struct ieee80211_security *secinfo = &bcm->ieee->sec;
488 u8 bitrate;
489 int ofdm_modulation;
490 u8 fallback_bitrate;
491 int fallback_ofdm_modulation;
492 u16 tmp;
493 u16 encrypt_frame;
494
495 /* Now construct the TX header. */
496 memset(txhdr, 0, sizeof(*txhdr));
497
498 //TODO: Some RTS/CTS stuff has to be done.
499 //TODO: Encryption stuff.
500 //TODO: others?
501
502 bitrate = bcm->softmac->txrates.default_rate;
503 ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
504 fallback_bitrate = bcm->softmac->txrates.default_fallback;
505 fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
506
507 /* Set Frame Control from 80211 header. */
508 txhdr->frame_control = wireless_header->frame_ctl;
509 /* Copy address1 from 80211 header. */
510 memcpy(txhdr->mac1, wireless_header->addr1, 6);
511 /* Set the fallback duration ID. */
512 //FIXME: We use the original durid for now.
513 txhdr->fallback_dur_id = wireless_header->duration_id;
514
515 /* Set the cookie (used as driver internal ID for the frame) */
516 txhdr->cookie = cpu_to_le16(cookie);
517
518 encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
519 if (encrypt_frame && !bcm->ieee->host_encrypt) {
520 const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
521 if (fragment_len <= sizeof(struct ieee80211_hdr_3addr)+4) {
522 dprintkl(KERN_ERR PFX "invalid packet with PROTECTED"
523 "flag set discarded");
524 return;
525 }
526 memcpy(txhdr->wep_iv, hdr->payload, 4);
527 /* Hardware appends ICV. */
528 fragment_len += 4;
529 }
530
531 /* Generate the PLCP header and the fallback PLCP header. */
532 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
533 fragment_len,
534 bitrate, ofdm_modulation);
535 bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, fragment_len,
536 fallback_bitrate, fallback_ofdm_modulation);
537
538 /* Set the CONTROL field */
539 tmp = 0;
540 if (ofdm_modulation)
541 tmp |= BCM43xx_TXHDRCTL_OFDM;
542 if (bcm->short_preamble) //FIXME: could be the other way around, please test
543 tmp |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
544 tmp |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
545 & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
546 txhdr->control = cpu_to_le16(tmp);
547
548 /* Set the FLAGS field */
549 tmp = 0;
550 if (!is_multicast_ether_addr(wireless_header->addr1) &&
551 !is_broadcast_ether_addr(wireless_header->addr1))
552 tmp |= BCM43xx_TXHDRFLAG_EXPECTACK;
553 if (1 /* FIXME: PS poll?? */)
554 tmp |= 0x10; // FIXME: unknown meaning.
555 if (fallback_ofdm_modulation)
556 tmp |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
557 if (is_first_fragment)
558 tmp |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
559 txhdr->flags = cpu_to_le16(tmp);
560
561 /* Set WSEC/RATE field */
562 if (encrypt_frame && !bcm->ieee->host_encrypt) {
563 tmp = (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
564 & BCM43xx_TXHDR_WSEC_ALGO_MASK;
565 tmp |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
566 & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
567 txhdr->wsec_rate = cpu_to_le16(tmp);
568 }
569
570//bcm43xx_printk_bitdump((const unsigned char *)txhdr, sizeof(*txhdr), 1, "TX header");
571}
572
573static 346static
574void bcm43xx_macfilter_set(struct bcm43xx_private *bcm, 347void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
575 u16 offset, 348 u16 offset,
@@ -3773,207 +3546,6 @@ err_pci_disable:
3773 goto out; 3546 goto out;
3774} 3547}
3775 3548
3776static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
3777 u8 in_rssi, int ofdm,
3778 int adjust_2053, int adjust_2050)
3779{
3780 s32 tmp;
3781
3782 switch (bcm->current_core->radio->version) {
3783 case 0x2050:
3784 if (ofdm) {
3785 tmp = in_rssi;
3786 if (tmp > 127)
3787 tmp -= 256;
3788 tmp *= 73;
3789 tmp /= 64;
3790 if (adjust_2050)
3791 tmp += 25;
3792 else
3793 tmp -= 3;
3794 } else {
3795 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
3796 if (in_rssi > 63)
3797 in_rssi = 63;
3798 tmp = bcm->current_core->radio->nrssi_lt[in_rssi];
3799 tmp = 31 - tmp;
3800 tmp *= -131;
3801 tmp /= 128;
3802 tmp -= 57;
3803 } else {
3804 tmp = in_rssi;
3805 tmp = 31 - tmp;
3806 tmp *= -149;
3807 tmp /= 128;
3808 tmp -= 68;
3809 }
3810 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G &&
3811 adjust_2050)
3812 tmp += 25;
3813 }
3814 break;
3815 case 0x2060:
3816 if (in_rssi > 127)
3817 tmp = in_rssi - 256;
3818 else
3819 tmp = in_rssi;
3820 break;
3821 default:
3822 tmp = in_rssi;
3823 tmp -= 11;
3824 tmp *= 103;
3825 tmp /= 64;
3826 if (adjust_2053)
3827 tmp -= 109;
3828 else
3829 tmp -= 83;
3830 }
3831
3832 return (s8)tmp;
3833}
3834
3835static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
3836 u8 in_rssi)
3837{
3838 s8 ret;
3839
3840 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) {
3841 //TODO: Incomplete specs.
3842 ret = 0;
3843 } else
3844 ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
3845
3846 return ret;
3847}
3848
3849static inline
3850int bcm43xx_rx_packet(struct bcm43xx_private *bcm,
3851 struct sk_buff *skb,
3852 struct ieee80211_rx_stats *stats)
3853{
3854 int err;
3855
3856 err = ieee80211_rx(bcm->ieee, skb, stats);
3857 if (unlikely(err == 0))
3858 return -EINVAL;
3859 return 0;
3860}
3861
3862int bcm43xx_rx(struct bcm43xx_private *bcm,
3863 struct sk_buff *skb,
3864 struct bcm43xx_rxhdr *rxhdr)
3865{
3866 struct bcm43xx_plcp_hdr4 *plcp;
3867 struct ieee80211_rx_stats stats;
3868 struct ieee80211_hdr_4addr *wlhdr;
3869 u16 frame_ctl;
3870 int is_packet_for_us = 0;
3871 int err = -EINVAL;
3872 const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
3873 const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
3874 const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
3875 const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
3876
3877 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
3878 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
3879 /* Skip two unknown bytes and the PLCP header. */
3880 skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
3881 } else {
3882 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
3883 /* Skip the PLCP header. */
3884 skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
3885 }
3886 /* The SKB contains the PAYLOAD (wireless header + data)
3887 * at this point. The FCS at the end is stripped.
3888 */
3889
3890 memset(&stats, 0, sizeof(stats));
3891 stats.mac_time = le16_to_cpu(rxhdr->mactime);
3892 stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
3893 !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
3894 !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
3895 stats.signal = rxhdr->signal_quality; //FIXME
3896//TODO stats.noise =
3897 stats.rate = bcm43xx_plcp_get_bitrate(plcp, is_ofdm);
3898//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
3899 stats.received_channel = bcm->current_core->radio->channel;
3900//TODO stats.control =
3901 stats.mask = IEEE80211_STATMASK_SIGNAL |
3902//TODO IEEE80211_STATMASK_NOISE |
3903 IEEE80211_STATMASK_RATE |
3904 IEEE80211_STATMASK_RSSI;
3905 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A)
3906 stats.freq = IEEE80211_52GHZ_BAND;
3907 else
3908 stats.freq = IEEE80211_24GHZ_BAND;
3909 stats.len = skb->len;
3910
3911 bcm->stats.last_rx = jiffies;
3912 if (bcm->ieee->iw_mode == IW_MODE_MONITOR)
3913 return bcm43xx_rx_packet(bcm, skb, &stats);
3914
3915 wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
3916
3917 switch (bcm->ieee->iw_mode) {
3918 case IW_MODE_ADHOC:
3919 if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
3920 memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
3921 is_broadcast_ether_addr(wlhdr->addr1) ||
3922 is_multicast_ether_addr(wlhdr->addr1) ||
3923 bcm->net_dev->flags & IFF_PROMISC)
3924 is_packet_for_us = 1;
3925 break;
3926 case IW_MODE_INFRA:
3927 default:
3928 /* When receiving multicast or broadcast packets, filter out
3929 the packets we send ourself; we shouldn't see those */
3930 if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
3931 memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
3932 (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
3933 (is_broadcast_ether_addr(wlhdr->addr1) ||
3934 is_multicast_ether_addr(wlhdr->addr1) ||
3935 bcm->net_dev->flags & IFF_PROMISC)))
3936 is_packet_for_us = 1;
3937 break;
3938 }
3939
3940 frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
3941 if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
3942 frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
3943 wlhdr->frame_ctl = cpu_to_le16(frame_ctl);
3944 /* trim IV and ICV */
3945 /* FIXME: this must be done only for WEP encrypted packets */
3946 if (skb->len < 32) {
3947 dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
3948 "set and length < 32)\n");
3949 return -EINVAL;
3950 } else {
3951 memmove(skb->data + 4, skb->data, 24);
3952 skb_pull(skb, 4);
3953 skb_trim(skb, skb->len - 4);
3954 stats.len -= 8;
3955 }
3956 wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
3957 }
3958
3959 switch (WLAN_FC_GET_TYPE(frame_ctl)) {
3960 case IEEE80211_FTYPE_MGMT:
3961 ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
3962 break;
3963 case IEEE80211_FTYPE_DATA:
3964 if (is_packet_for_us)
3965 err = bcm43xx_rx_packet(bcm, skb, &stats);
3966 break;
3967 case IEEE80211_FTYPE_CTL:
3968 break;
3969 default:
3970 assert(0);
3971 return -EINVAL;
3972 }
3973
3974 return err;
3975}
3976
3977/* Do the Hardware IO operations to send the txb */ 3549/* Do the Hardware IO operations to send the txb */
3978static inline int bcm43xx_tx(struct bcm43xx_private *bcm, 3550static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
3979 struct ieee80211_txb *txb) 3551 struct ieee80211_txb *txb)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
index d460393ed34..086136c3d01 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -52,134 +52,12 @@ static inline void e_aton(char *str, char *dest)
52} 52}
53#endif 53#endif
54 54
55
56#define _bcm43xx_declare_plcp_hdr(size) \
57 struct bcm43xx_plcp_hdr##size { \
58 union { \
59 __le32 data; \
60 __u8 raw[size]; \
61 } __attribute__((__packed__)); \
62 } __attribute__((__packed__))
63
64/* struct bcm43xx_plcp_hdr4 */
65_bcm43xx_declare_plcp_hdr(4);
66/* struct bcm430c_plcp_hdr6 */
67_bcm43xx_declare_plcp_hdr(6);
68
69#undef _bcm43xx_declare_plcp_hdr
70
71
72#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] 55#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
73#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) 56#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
74/* Magic helper macro to pad structures. Ignore those above. It's magic. */ 57/* Magic helper macro to pad structures. Ignore those above. It's magic. */
75#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) 58#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
76 59
77 60
78/* Device specific TX header. To be prepended to TX frames. */
79struct bcm43xx_txhdr {
80 union {
81 struct {
82 u16 flags;
83 u16 wsec_rate;
84 u16 frame_control;
85 u16 unknown_zeroed_0;
86 u16 control;
87 unsigned char wep_iv[10];
88 unsigned char unknown_wsec_tkip_data[3]; //FIXME
89 PAD_BYTES(3);
90 unsigned char mac1[6];
91 u16 unknown_zeroed_1;
92 struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
93 u16 rts_cts_dur_fallback;
94 struct bcm43xx_plcp_hdr4 fallback_plcp;
95 u16 fallback_dur_id;
96 PAD_BYTES(2);
97 u16 cookie;
98 u16 unknown_scb_stuff; //FIXME
99 struct bcm43xx_plcp_hdr6 rts_cts_plcp;
100 u16 rts_cts_frame_type;
101 u16 rts_cts_dur;
102 unsigned char rts_cts_mac1[6];
103 unsigned char rts_cts_mac2[6];
104 PAD_BYTES(2);
105 struct bcm43xx_plcp_hdr6 plcp;
106 } __attribute__((__packed__));
107
108 unsigned char raw[82];
109 } __attribute__((__packed__));
110} __attribute__((__packed__));
111
112struct sk_buff;
113
114void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
115 struct bcm43xx_txhdr *txhdr,
116 const unsigned char *fragment_data,
117 const unsigned int fragment_len,
118 const int is_first_fragment,
119 const u16 cookie);
120
121/* RX header as received from the hardware. */
122struct bcm43xx_rxhdr {
123 /* Frame Length. Must be generated explicitely in PIO mode. */
124 __le16 frame_length;
125 PAD_BYTES(2);
126 /* Flags field 1 */
127 __le16 flags1;
128 u8 rssi;
129 u8 signal_quality;
130 PAD_BYTES(2);
131 /* Flags field 3 */
132 __le16 flags3;
133 /* Flags field 2 */
134 __le16 flags2;
135 /* Lower 16bits of the TSF at the time the frame started. */
136 __le16 mactime;
137 PAD_BYTES(14);
138} __attribute__((__packed__));
139
140#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0)
141/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */
142#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7)
143#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14)
144
145#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0)
146#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2)
147/*FIXME: WEP related flags */
148
149#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10)
150
151/* Transmit Status as received from the hardware. */
152struct bcm43xx_hwxmitstatus {
153 PAD_BYTES(4);
154 __le16 cookie;
155 u8 flags;
156 u8 cnt1:4,
157 cnt2:4;
158 PAD_BYTES(2);
159 __le16 seq;
160 __le16 unknown; //FIXME
161} __attribute__((__packed__));
162
163/* Transmit Status in CPU byteorder. */
164struct bcm43xx_xmitstatus {
165 u16 cookie;
166 u8 flags;
167 u8 cnt1:4,
168 cnt2:4;
169 u16 seq;
170 u16 unknown; //FIXME
171};
172
173#define BCM43xx_TXSTAT_FLAG_ACK 0x01
174//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02
175//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04
176//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08
177//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10
178#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20
179//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40
180//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80
181
182
183/* Lightweight function to convert a frequency (in Mhz) to a channel number. */ 61/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
184static inline 62static inline
185u8 bcm43xx_freq_to_channel_a(int freq) 63u8 bcm43xx_freq_to_channel_a(int freq)
@@ -259,10 +137,6 @@ int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
259void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); 137void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
260void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); 138void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
261 139
262int bcm43xx_rx(struct bcm43xx_private *bcm,
263 struct sk_buff *skb,
264 struct bcm43xx_rxhdr *rxhdr);
265
266void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, 140void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
267 int iw_mode); 141 int iw_mode);
268 142
@@ -283,11 +157,6 @@ int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *ne
283 157
284void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); 158void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
285 159
286int bcm43xx_pci_read_config_16(struct pci_dev *pdev, u16 offset, u16 *val);
287int bcm43xx_pci_read_config_32(struct pci_dev *pdev, u16 offset, u32 *val);
288int bcm43xx_pci_write_config_16(struct pci_dev *pdev, int offset, u16 val);
289int bcm43xx_pci_write_config_32(struct pci_dev *pdev, int offset, u32 val);
290
291void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); 160void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
292void bcm43xx_mac_enable(struct bcm43xx_private *bcm); 161void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
293 162
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
index 0bf4b3e26f9..7b45fa1314c 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -26,6 +26,7 @@
26#include "bcm43xx.h" 26#include "bcm43xx.h"
27#include "bcm43xx_pio.h" 27#include "bcm43xx_pio.h"
28#include "bcm43xx_main.h" 28#include "bcm43xx_main.h"
29#include "bcm43xx_xmit.h"
29 30
30#include <linux/delay.h> 31#include <linux/delay.h>
31 32
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
new file mode 100644
index 00000000000..5ee572e79f6
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -0,0 +1,579 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Transmission (TX/RX) related functions.
6
7 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
8 Stefano Brivio <st3@riseup.net>
9 Michael Buesch <mbuesch@freenet.de>
10 Danny van Dyk <kugelfang@gentoo.org>
11 Andreas Jaggi <andreas.jaggi@waterwave.ch>
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; see the file COPYING. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
26 Boston, MA 02110-1301, USA.
27
28*/
29
30#include "bcm43xx_xmit.h"
31
32#include <linux/etherdevice.h>
33
34
35/* Extract the bitrate out of a CCK PLCP header. */
36static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
37{
38 switch (plcp->raw[0]) {
39 case 0x0A:
40 return IEEE80211_CCK_RATE_1MB;
41 case 0x14:
42 return IEEE80211_CCK_RATE_2MB;
43 case 0x37:
44 return IEEE80211_CCK_RATE_5MB;
45 case 0x6E:
46 return IEEE80211_CCK_RATE_11MB;
47 }
48 assert(0);
49 return 0;
50}
51
52/* Extract the bitrate out of an OFDM PLCP header. */
53static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
54{
55 switch (plcp->raw[0] & 0xF) {
56 case 0xB:
57 return IEEE80211_OFDM_RATE_6MB;
58 case 0xF:
59 return IEEE80211_OFDM_RATE_9MB;
60 case 0xA:
61 return IEEE80211_OFDM_RATE_12MB;
62 case 0xE:
63 return IEEE80211_OFDM_RATE_18MB;
64 case 0x9:
65 return IEEE80211_OFDM_RATE_24MB;
66 case 0xD:
67 return IEEE80211_OFDM_RATE_36MB;
68 case 0x8:
69 return IEEE80211_OFDM_RATE_48MB;
70 case 0xC:
71 return IEEE80211_OFDM_RATE_54MB;
72 }
73 assert(0);
74 return 0;
75}
76
77u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
78{
79 switch (bitrate) {
80 case IEEE80211_CCK_RATE_1MB:
81 return 0x0A;
82 case IEEE80211_CCK_RATE_2MB:
83 return 0x14;
84 case IEEE80211_CCK_RATE_5MB:
85 return 0x37;
86 case IEEE80211_CCK_RATE_11MB:
87 return 0x6E;
88 }
89 assert(0);
90 return 0;
91}
92
93u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
94{
95 switch (bitrate) {
96 case IEEE80211_OFDM_RATE_6MB:
97 return 0xB;
98 case IEEE80211_OFDM_RATE_9MB:
99 return 0xF;
100 case IEEE80211_OFDM_RATE_12MB:
101 return 0xA;
102 case IEEE80211_OFDM_RATE_18MB:
103 return 0xE;
104 case IEEE80211_OFDM_RATE_24MB:
105 return 0x9;
106 case IEEE80211_OFDM_RATE_36MB:
107 return 0xD;
108 case IEEE80211_OFDM_RATE_48MB:
109 return 0x8;
110 case IEEE80211_OFDM_RATE_54MB:
111 return 0xC;
112 }
113 assert(0);
114 return 0;
115}
116
117static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
118 const u16 octets, const u8 bitrate,
119 const int ofdm_modulation)
120{
121 __le32 *data = &(plcp->data);
122 __u8 *raw = plcp->raw;
123
124 if (ofdm_modulation) {
125 *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
126 assert(!(octets & 0xF000));
127 *data |= (octets << 5);
128 *data = cpu_to_le32(*data);
129 } else {
130 u32 plen;
131
132 plen = octets * 16 / bitrate;
133 if ((octets * 16 % bitrate) > 0) {
134 plen++;
135 if ((bitrate == IEEE80211_CCK_RATE_11MB)
136 && ((octets * 8 % 11) < 4)) {
137 raw[1] = 0x84;
138 } else
139 raw[1] = 0x04;
140 } else
141 raw[1] = 0x04;
142 *data |= cpu_to_le32(plen << 16);
143 raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
144 }
145}
146
147static u8 bcm43xx_calc_fallback_rate(u8 bitrate)
148{
149 switch (bitrate) {
150 case IEEE80211_CCK_RATE_1MB:
151 return IEEE80211_CCK_RATE_1MB;
152 case IEEE80211_CCK_RATE_2MB:
153 return IEEE80211_CCK_RATE_1MB;
154 case IEEE80211_CCK_RATE_5MB:
155 return IEEE80211_CCK_RATE_2MB;
156 case IEEE80211_CCK_RATE_11MB:
157 return IEEE80211_CCK_RATE_5MB;
158 case IEEE80211_OFDM_RATE_6MB:
159 return IEEE80211_CCK_RATE_5MB;
160 case IEEE80211_OFDM_RATE_9MB:
161 return IEEE80211_OFDM_RATE_6MB;
162 case IEEE80211_OFDM_RATE_12MB:
163 return IEEE80211_OFDM_RATE_9MB;
164 case IEEE80211_OFDM_RATE_18MB:
165 return IEEE80211_OFDM_RATE_12MB;
166 case IEEE80211_OFDM_RATE_24MB:
167 return IEEE80211_OFDM_RATE_18MB;
168 case IEEE80211_OFDM_RATE_36MB:
169 return IEEE80211_OFDM_RATE_24MB;
170 case IEEE80211_OFDM_RATE_48MB:
171 return IEEE80211_OFDM_RATE_36MB;
172 case IEEE80211_OFDM_RATE_54MB:
173 return IEEE80211_OFDM_RATE_48MB;
174 }
175 assert(0);
176 return 0;
177}
178
179static
180__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,
181 u8 bitrate)
182{
183 const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);
184 __le16 duration_id = wireless_header->duration_id;
185
186 switch (WLAN_FC_GET_TYPE(frame_ctl)) {
187 case IEEE80211_FTYPE_DATA:
188 case IEEE80211_FTYPE_MGMT:
189 //TODO: Steal the code from ieee80211, once it is completed there.
190 break;
191 case IEEE80211_FTYPE_CTL:
192 /* Use the original duration/id. */
193 break;
194 default:
195 assert(0);
196 }
197
198 return duration_id;
199}
200
201static inline
202u16 ceiling_div(u16 dividend, u16 divisor)
203{
204 return ((dividend + divisor - 1) / divisor);
205}
206
207static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,
208 struct bcm43xx_txhdr *txhdr,
209 u16 *flags,
210 u8 bitrate,
211 const struct ieee80211_hdr_4addr *wlhdr)
212{
213 u16 fctl;
214 u16 dur;
215 u8 fallback_bitrate;
216 int ofdm_modulation;
217 int fallback_ofdm_modulation;
218 u8 *sa, *da;
219 u16 flen;
220
221//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);
222//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);
223 fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
224 ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
225 fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
226
227 flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,
228 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),
229 flen, bitrate,
230 !ieee80211_is_cck_rate(bitrate));
231 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),
232 flen, fallback_bitrate,
233 !ieee80211_is_cck_rate(fallback_bitrate));
234 fctl = IEEE80211_FTYPE_CTL;
235 fctl |= IEEE80211_STYPE_RTS;
236 dur = le16_to_cpu(wlhdr->duration_id);
237/*FIXME: should we test for dur==0 here and let it unmodified in this case?
238 * The following assert checks for this case...
239 */
240assert(dur);
241/*FIXME: The duration calculation is not really correct.
242 * I am not 100% sure which bitrate to use. We use the RTS rate here,
243 * but this is likely to be wrong.
244 */
245 if (phy->type == BCM43xx_PHYTYPE_A) {
246 /* Three times SIFS */
247 dur += 16 * 3;
248 /* Add ACK duration. */
249 dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
250 bitrate * 4);
251 /* Add CTS duration. */
252 dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
253 bitrate * 4);
254 } else {
255 /* Three times SIFS */
256 dur += 10 * 3;
257 /* Add ACK duration. */
258 dur += ceiling_div(8 * (14 /*bytes*/) * 10,
259 bitrate);
260 /* Add CTS duration. */
261 dur += ceiling_div(8 * (14 /*bytes*/) * 10,
262 bitrate);
263 }
264
265 txhdr->rts_cts_frame_control = cpu_to_le16(fctl);
266 txhdr->rts_cts_dur = cpu_to_le16(dur);
267//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));
268//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));
269 memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!
270 memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);
271
272 *flags |= BCM43xx_TXHDRFLAG_RTSCTS;
273 *flags |= BCM43xx_TXHDRFLAG_RTS;
274 if (ofdm_modulation)
275 *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;
276 if (fallback_ofdm_modulation)
277 *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;
278}
279
280void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
281 struct bcm43xx_txhdr *txhdr,
282 const unsigned char *fragment_data,
283 const unsigned int fragment_len,
284 const int is_first_fragment,
285 const u16 cookie)
286{
287 const struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
288 const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;
289 const struct ieee80211_security *secinfo = &bcm->ieee->sec;
290 u8 bitrate;
291 u8 fallback_bitrate;
292 int ofdm_modulation;
293 int fallback_ofdm_modulation;
294 u16 plcp_fragment_len = fragment_len;
295 u16 flags = 0;
296 u16 control = 0;
297 u16 wsec_rate = 0;
298 u16 encrypt_frame;
299
300 /* Now construct the TX header. */
301 memset(txhdr, 0, sizeof(*txhdr));
302
303 bitrate = bcm->softmac->txrates.default_rate;
304 ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
305 fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
306 fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
307
308 /* Set Frame Control from 80211 header. */
309 txhdr->frame_control = wireless_header->frame_ctl;
310 /* Copy address1 from 80211 header. */
311 memcpy(txhdr->mac1, wireless_header->addr1, 6);
312 /* Set the fallback duration ID. */
313 txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header,
314 fallback_bitrate);
315 /* Set the cookie (used as driver internal ID for the frame) */
316 txhdr->cookie = cpu_to_le16(cookie);
317
318 /* Hardware appends FCS. */
319 plcp_fragment_len += IEEE80211_FCS_LEN;
320
321 /* Hardware encryption. */
322 encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
323 if (encrypt_frame && !bcm->ieee->host_encrypt) {
324 const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
325 memcpy(txhdr->wep_iv, hdr->payload, 4);
326 /* Hardware appends ICV. */
327 plcp_fragment_len += 4;
328
329 wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
330 & BCM43xx_TXHDR_WSEC_ALGO_MASK;
331 wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
332 & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
333 }
334
335 /* Generate the PLCP header and the fallback PLCP header. */
336 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
337 plcp_fragment_len,
338 bitrate, ofdm_modulation);
339 bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
340 fallback_bitrate, fallback_ofdm_modulation);
341
342 /* Set the CONTROL field */
343 if (ofdm_modulation)
344 control |= BCM43xx_TXHDRCTL_OFDM;
345 if (bcm->short_preamble) //FIXME: could be the other way around, please test
346 control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
347 control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
348 & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
349
350 /* Set the FLAGS field */
351 if (!is_multicast_ether_addr(wireless_header->addr1) &&
352 !is_broadcast_ether_addr(wireless_header->addr1))
353 flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
354 if (1 /* FIXME: PS poll?? */)
355 flags |= 0x10; // FIXME: unknown meaning.
356 if (fallback_ofdm_modulation)
357 flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
358 if (is_first_fragment)
359 flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
360
361 /* Set WSEC/RATE field */
362 wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
363 & BCM43xx_TXHDR_RATE_MASK;
364
365 /* Generate the RTS/CTS packet, if required. */
366 /* FIXME: We should first try with CTS-to-self,
367 * if we are on 80211g. If we get too many
368 * failures (hidden nodes), we should switch back to RTS/CTS.
369 */
370 if (0/*FIXME txctl->use_rts_cts*/) {
371 bcm43xx_generate_rts(phy, txhdr, &flags,
372 0/*FIXME txctl->rts_cts_rate*/,
373 wireless_header);
374 }
375
376 txhdr->flags = cpu_to_le16(flags);
377 txhdr->control = cpu_to_le16(control);
378 txhdr->wsec_rate = cpu_to_le16(wsec_rate);
379}
380
381static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
382 u8 in_rssi, int ofdm,
383 int adjust_2053, int adjust_2050)
384{
385 struct bcm43xx_radioinfo *radio = bcm->current_core->radio;
386 struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
387 s32 tmp;
388
389 switch (radio->version) {
390 case 0x2050:
391 if (ofdm) {
392 tmp = in_rssi;
393 if (tmp > 127)
394 tmp -= 256;
395 tmp *= 73;
396 tmp /= 64;
397 if (adjust_2050)
398 tmp += 25;
399 else
400 tmp -= 3;
401 } else {
402 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
403 if (in_rssi > 63)
404 in_rssi = 63;
405 tmp = radio->nrssi_lt[in_rssi];
406 tmp = 31 - tmp;
407 tmp *= -131;
408 tmp /= 128;
409 tmp -= 57;
410 } else {
411 tmp = in_rssi;
412 tmp = 31 - tmp;
413 tmp *= -149;
414 tmp /= 128;
415 tmp -= 68;
416 }
417 if (phy->type == BCM43xx_PHYTYPE_G &&
418 adjust_2050)
419 tmp += 25;
420 }
421 break;
422 case 0x2060:
423 if (in_rssi > 127)
424 tmp = in_rssi - 256;
425 else
426 tmp = in_rssi;
427 break;
428 default:
429 tmp = in_rssi;
430 tmp -= 11;
431 tmp *= 103;
432 tmp /= 64;
433 if (adjust_2053)
434 tmp -= 109;
435 else
436 tmp -= 83;
437 }
438
439 return (s8)tmp;
440}
441
442static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
443 u8 in_rssi)
444{
445 struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
446 s8 ret;
447
448 if (phy->type == BCM43xx_PHYTYPE_A) {
449 //TODO: Incomplete specs.
450 ret = 0;
451 } else
452 ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
453
454 return ret;
455}
456
457int bcm43xx_rx(struct bcm43xx_private *bcm,
458 struct sk_buff *skb,
459 struct bcm43xx_rxhdr *rxhdr)
460{
461 struct bcm43xx_plcp_hdr4 *plcp;
462 struct ieee80211_rx_stats stats;
463 struct ieee80211_hdr_4addr *wlhdr;
464 u16 frame_ctl;
465 int is_packet_for_us = 0;
466 int err = -EINVAL;
467 const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
468 const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
469 const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
470 const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
471
472 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
473 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
474 /* Skip two unknown bytes and the PLCP header. */
475 skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
476 } else {
477 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
478 /* Skip the PLCP header. */
479 skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
480 }
481 /* The SKB contains the PAYLOAD (wireless header + data)
482 * at this point. The FCS at the end is stripped.
483 */
484
485 memset(&stats, 0, sizeof(stats));
486 stats.mac_time = le16_to_cpu(rxhdr->mactime);
487 stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
488 !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
489 !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
490 stats.signal = rxhdr->signal_quality; //FIXME
491//TODO stats.noise =
492 if (is_ofdm)
493 stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
494 else
495 stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
496//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
497 stats.received_channel = bcm->current_core->radio->channel;
498//TODO stats.control =
499 stats.mask = IEEE80211_STATMASK_SIGNAL |
500//TODO IEEE80211_STATMASK_NOISE |
501 IEEE80211_STATMASK_RATE |
502 IEEE80211_STATMASK_RSSI;
503 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A)
504 stats.freq = IEEE80211_52GHZ_BAND;
505 else
506 stats.freq = IEEE80211_24GHZ_BAND;
507 stats.len = skb->len;
508
509 bcm->stats.last_rx = jiffies;
510 if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
511 err = ieee80211_rx(bcm->ieee, skb, &stats);
512 return (err == 0) ? -EINVAL : 0;
513 }
514
515 wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
516
517 switch (bcm->ieee->iw_mode) {
518 case IW_MODE_ADHOC:
519 if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
520 memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
521 is_broadcast_ether_addr(wlhdr->addr1) ||
522 is_multicast_ether_addr(wlhdr->addr1) ||
523 bcm->net_dev->flags & IFF_PROMISC)
524 is_packet_for_us = 1;
525 break;
526 case IW_MODE_INFRA:
527 default:
528 /* When receiving multicast or broadcast packets, filter out
529 the packets we send ourself; we shouldn't see those */
530 if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
531 memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
532 (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
533 (is_broadcast_ether_addr(wlhdr->addr1) ||
534 is_multicast_ether_addr(wlhdr->addr1) ||
535 bcm->net_dev->flags & IFF_PROMISC)))
536 is_packet_for_us = 1;
537 break;
538 }
539
540 frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
541 if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
542 frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
543 wlhdr->frame_ctl = cpu_to_le16(frame_ctl);
544 /* trim IV and ICV */
545 /* FIXME: this must be done only for WEP encrypted packets */
546 if (skb->len < 32) {
547 dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
548 "set and length < 32)\n");
549 return -EINVAL;
550 } else {
551 memmove(skb->data + 4, skb->data, 24);
552 skb_pull(skb, 4);
553 skb_trim(skb, skb->len - 4);
554 stats.len -= 8;
555 }
556 wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
557 }
558
559 switch (WLAN_FC_GET_TYPE(frame_ctl)) {
560 case IEEE80211_FTYPE_MGMT:
561 ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
562 break;
563 case IEEE80211_FTYPE_DATA:
564 if (is_packet_for_us) {
565 err = ieee80211_rx(bcm->ieee, skb, &stats);
566 err = (err == 0) ? -EINVAL : 0;
567 }
568 break;
569 case IEEE80211_FTYPE_CTL:
570 break;
571 default:
572 assert(0);
573 return -EINVAL;
574 }
575
576 return err;
577}
578
579/* vim: set ts=8 sw=8 sts=8: */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
new file mode 100644
index 00000000000..2aed19e35c7
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
@@ -0,0 +1,156 @@
1#ifndef BCM43xx_XMIT_H_
2#define BCM43xx_XMIT_H_
3
4#include "bcm43xx_main.h"
5
6
7#define _bcm43xx_declare_plcp_hdr(size) \
8 struct bcm43xx_plcp_hdr##size { \
9 union { \
10 __le32 data; \
11 __u8 raw[size]; \
12 } __attribute__((__packed__)); \
13 } __attribute__((__packed__))
14
15/* struct bcm43xx_plcp_hdr4 */
16_bcm43xx_declare_plcp_hdr(4);
17/* struct bcm43xx_plcp_hdr6 */
18_bcm43xx_declare_plcp_hdr(6);
19
20#undef _bcm43xx_declare_plcp_hdr
21
22/* Device specific TX header. To be prepended to TX frames. */
23struct bcm43xx_txhdr {
24 union {
25 struct {
26 __le16 flags;
27 __le16 wsec_rate;
28 __le16 frame_control;
29 u16 unknown_zeroed_0;
30 __le16 control;
31 u8 wep_iv[10];
32 u8 unknown_wsec_tkip_data[3]; //FIXME
33 PAD_BYTES(3);
34 u8 mac1[6];
35 u16 unknown_zeroed_1;
36 struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
37 __le16 rts_cts_dur_fallback;
38 struct bcm43xx_plcp_hdr4 fallback_plcp;
39 __le16 fallback_dur_id;
40 PAD_BYTES(2);
41 __le16 cookie;
42 __le16 unknown_scb_stuff; //FIXME
43 struct bcm43xx_plcp_hdr6 rts_cts_plcp;
44 __le16 rts_cts_frame_control;
45 __le16 rts_cts_dur;
46 u8 rts_cts_mac1[6];
47 u8 rts_cts_mac2[6];
48 PAD_BYTES(2);
49 struct bcm43xx_plcp_hdr6 plcp;
50 } __attribute__((__packed__));
51 u8 raw[82];
52 } __attribute__((__packed__));
53} __attribute__((__packed__));
54
55/* Values/Masks for the device TX header */
56#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001
57#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002
58#define BCM43xx_TXHDRFLAG_RTS 0x0004
59#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008
60#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020
61#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080
62#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100
63#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200
64#define BCM43xx_TXHDRFLAG_CTS 0x0400
65#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800
66
67#define BCM43xx_TXHDRCTL_OFDM 0x0001
68#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010
69#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030
70#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8
71
72#define BCM43xx_TXHDR_RATE_MASK 0x0F00
73#define BCM43xx_TXHDR_RATE_SHIFT 8
74#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000
75#define BCM43xx_TXHDR_RTSRATE_SHIFT 12
76#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0
77#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4
78#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003
79#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0
80
81void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
82 struct bcm43xx_txhdr *txhdr,
83 const unsigned char *fragment_data,
84 const unsigned int fragment_len,
85 const int is_first_fragment,
86 const u16 cookie);
87
88/* RX header as received from the hardware. */
89struct bcm43xx_rxhdr {
90 /* Frame Length. Must be generated explicitely in PIO mode. */
91 __le16 frame_length;
92 PAD_BYTES(2);
93 /* Flags field 1 */
94 __le16 flags1;
95 u8 rssi;
96 u8 signal_quality;
97 PAD_BYTES(2);
98 /* Flags field 3 */
99 __le16 flags3;
100 /* Flags field 2 */
101 __le16 flags2;
102 /* Lower 16bits of the TSF at the time the frame started. */
103 __le16 mactime;
104 PAD_BYTES(14);
105} __attribute__((__packed__));
106
107#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0)
108/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */
109#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7)
110#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14)
111
112#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0)
113#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2)
114/*FIXME: WEP related flags */
115
116#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10)
117
118/* Transmit Status as received from the hardware. */
119struct bcm43xx_hwxmitstatus {
120 PAD_BYTES(4);
121 __le16 cookie;
122 u8 flags;
123 u8 cnt1:4,
124 cnt2:4;
125 PAD_BYTES(2);
126 __le16 seq;
127 __le16 unknown; //FIXME
128} __attribute__((__packed__));
129
130/* Transmit Status in CPU byteorder. */
131struct bcm43xx_xmitstatus {
132 u16 cookie;
133 u8 flags;
134 u8 cnt1:4,
135 cnt2:4;
136 u16 seq;
137 u16 unknown; //FIXME
138};
139
140#define BCM43xx_TXSTAT_FLAG_ACK 0x01
141//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02
142//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04
143//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08
144//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10
145#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20
146//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40
147//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80
148
149u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
150u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
151
152int bcm43xx_rx(struct bcm43xx_private *bcm,
153 struct sk_buff *skb,
154 struct bcm43xx_rxhdr *rxhdr);
155
156#endif /* BCM43xx_XMIT_H_ */