[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>
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 899c06f..f1ac994 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -50,6 +50,7 @@
 #include "bcm43xx_power.h"
 #include "bcm43xx_wx.h"
 #include "bcm43xx_ethtool.h"
+#include "bcm43xx_xmit.h"
 
 
 MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
@@ -342,234 +343,6 @@
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
 }
 
-static u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp,
-				   const int ofdm_modulation)
-{
-	u8 rate;
-
-	if (ofdm_modulation) {
-		switch (plcp->raw[0] & 0xF) {
-		case 0xB:
-			rate = IEEE80211_OFDM_RATE_6MB;
-			break;
-		case 0xF:
-			rate = IEEE80211_OFDM_RATE_9MB;
-			break;
-		case 0xA:
-			rate = IEEE80211_OFDM_RATE_12MB;
-			break;
-		case 0xE:
-			rate = IEEE80211_OFDM_RATE_18MB;
-			break;
-		case 0x9:
-			rate = IEEE80211_OFDM_RATE_24MB;
-			break;
-		case 0xD:
-			rate = IEEE80211_OFDM_RATE_36MB;
-			break;
-		case 0x8:
-			rate = IEEE80211_OFDM_RATE_48MB;
-			break;
-		case 0xC:
-			rate = IEEE80211_OFDM_RATE_54MB;
-			break;
-		default:
-			rate = 0;
-			assert(0);
-		}
-	} else {
-		switch (plcp->raw[0]) {
-		case 0x0A:
-			rate = IEEE80211_CCK_RATE_1MB;
-			break;
-		case 0x14:
-			rate = IEEE80211_CCK_RATE_2MB;
-			break;
-		case 0x37:
-			rate = IEEE80211_CCK_RATE_5MB;
-			break;
-		case 0x6E:
-			rate = IEEE80211_CCK_RATE_11MB;
-			break;
-		default:
-			rate = 0;
-			assert(0);
-		}
-	}
-
-	return rate;
-}
-
-static u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
-{
-	switch (bitrate) {
-	case IEEE80211_CCK_RATE_1MB:
-		return 0x0A;
-	case IEEE80211_CCK_RATE_2MB:
-		return 0x14;
-	case IEEE80211_CCK_RATE_5MB:
-		return 0x37;
-	case IEEE80211_CCK_RATE_11MB:
-		return 0x6E;
-	}
-	assert(0);
-	return 0;
-}
-
-static u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
-{
-	switch (bitrate) {
-	case IEEE80211_OFDM_RATE_6MB:
-		return 0xB;
-	case IEEE80211_OFDM_RATE_9MB:
-		return 0xF;
-	case IEEE80211_OFDM_RATE_12MB:
-		return 0xA;
-	case IEEE80211_OFDM_RATE_18MB:
-		return 0xE;
-	case IEEE80211_OFDM_RATE_24MB:
-		return 0x9;
-	case IEEE80211_OFDM_RATE_36MB:
-		return 0xD;
-	case IEEE80211_OFDM_RATE_48MB:
-		return 0x8;
-	case IEEE80211_OFDM_RATE_54MB:
-		return 0xC;
-	}
-	assert(0);
-	return 0;
-}
-
-static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
-				      u16 octets, const u8 bitrate,
-				      const int ofdm_modulation)
-{
-	__le32 *data = &(plcp->data);
-	__u8 *raw = plcp->raw;
-
-	/* Account for hardware-appended FCS. */
-	octets += IEEE80211_FCS_LEN;
-
-	if (ofdm_modulation) {
-		*data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
-		assert(!(octets & 0xF000));
-		*data |= (octets << 5);
-		*data = cpu_to_le32(*data);
-	} else {
-		u32 plen;
-
-		plen = octets * 16 / bitrate;
-		if ((octets * 16 % bitrate) > 0) {
-			plen++;
-			if ((bitrate == IEEE80211_CCK_RATE_11MB)
-			    && ((octets * 8 % 11) < 4)) {
-				raw[1] = 0x84;
-			} else
-				raw[1] = 0x04;
-		} else
-			raw[1] = 0x04;
-		*data |= cpu_to_le32(plen << 16);
-		raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
-	}
-
-//bcm43xx_printk_bitdump(raw, 4, 0, "PLCP");
-}
-
-void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
-			    struct bcm43xx_txhdr *txhdr,
-			    const unsigned char *fragment_data,
-			    unsigned int fragment_len,
-			    const int is_first_fragment,
-			    const u16 cookie)
-{
-	const struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
-	const struct ieee80211_hdr_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data;
-	const struct ieee80211_security *secinfo = &bcm->ieee->sec;
-	u8 bitrate;
-	int ofdm_modulation;
-	u8 fallback_bitrate;
-	int fallback_ofdm_modulation;
-	u16 tmp;
-	u16 encrypt_frame;
-
-	/* Now construct the TX header. */
-	memset(txhdr, 0, sizeof(*txhdr));
-
-	//TODO: Some RTS/CTS stuff has to be done.
-	//TODO: Encryption stuff.
-	//TODO: others?
-
-	bitrate = bcm->softmac->txrates.default_rate;
-	ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
-	fallback_bitrate = bcm->softmac->txrates.default_fallback;
-	fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
-
-	/* Set Frame Control from 80211 header. */
-	txhdr->frame_control = wireless_header->frame_ctl;
-	/* Copy address1 from 80211 header. */
-	memcpy(txhdr->mac1, wireless_header->addr1, 6);
-	/* Set the fallback duration ID. */
-	//FIXME: We use the original durid for now.
-	txhdr->fallback_dur_id = wireless_header->duration_id;
-
-	/* Set the cookie (used as driver internal ID for the frame) */
-	txhdr->cookie = cpu_to_le16(cookie);
-
-	encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
-	if (encrypt_frame && !bcm->ieee->host_encrypt) {
-		const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
-		if (fragment_len <= sizeof(struct ieee80211_hdr_3addr)+4) {
-			dprintkl(KERN_ERR PFX "invalid packet with PROTECTED"
-					      "flag set discarded");
-			return;
-		}
-		memcpy(txhdr->wep_iv, hdr->payload, 4);
-		/* Hardware appends ICV. */
-		fragment_len += 4;
-	}
-
-	/* Generate the PLCP header and the fallback PLCP header. */
-	bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
-				  fragment_len,
-				  bitrate, ofdm_modulation);
-	bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, fragment_len,
-				  fallback_bitrate, fallback_ofdm_modulation);
-
-	/* Set the CONTROL field */
-	tmp = 0;
-	if (ofdm_modulation)
-		tmp |= BCM43xx_TXHDRCTL_OFDM;
-	if (bcm->short_preamble) //FIXME: could be the other way around, please test
-		tmp |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
-	tmp |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
-		& BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
-	txhdr->control = cpu_to_le16(tmp);
-
-	/* Set the FLAGS field */
-	tmp = 0;
-	if (!is_multicast_ether_addr(wireless_header->addr1) &&
-	    !is_broadcast_ether_addr(wireless_header->addr1))
-		tmp |= BCM43xx_TXHDRFLAG_EXPECTACK;
-	if (1 /* FIXME: PS poll?? */)
-		tmp |= 0x10; // FIXME: unknown meaning.
-	if (fallback_ofdm_modulation)
-		tmp |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
-	if (is_first_fragment)
-		tmp |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
-	txhdr->flags = cpu_to_le16(tmp);
-
-	/* Set WSEC/RATE field */
-	if (encrypt_frame && !bcm->ieee->host_encrypt) {
-		tmp = (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
-		       & BCM43xx_TXHDR_WSEC_ALGO_MASK;
-		tmp |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
-			& BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
-		txhdr->wsec_rate = cpu_to_le16(tmp);
-	}
-
-//bcm43xx_printk_bitdump((const unsigned char *)txhdr, sizeof(*txhdr), 1, "TX header");
-}
-
 static
 void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
 			   u16 offset,
@@ -3773,207 +3546,6 @@
 	goto out;
 }
 
-static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
-				   u8 in_rssi, int ofdm,
-				   int adjust_2053, int adjust_2050)
-{
-	s32 tmp;
-
-	switch (bcm->current_core->radio->version) {
-	case 0x2050:
-		if (ofdm) {
-			tmp = in_rssi;
-			if (tmp > 127)
-				tmp -= 256;
-			tmp *= 73;
-			tmp /= 64;
-			if (adjust_2050)
-				tmp += 25;
-			else
-				tmp -= 3;
-		} else {
-			if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
-				if (in_rssi > 63)
-					in_rssi = 63;
-				tmp = bcm->current_core->radio->nrssi_lt[in_rssi];
-				tmp = 31 - tmp;
-				tmp *= -131;
-				tmp /= 128;
-				tmp -= 57;
-			} else {
-				tmp = in_rssi;
-				tmp = 31 - tmp;
-				tmp *= -149;
-				tmp /= 128;
-				tmp -= 68;
-			}
-			if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G &&
-			    adjust_2050)
-				tmp += 25;
-		}
-		break;
-	case 0x2060:
-		if (in_rssi > 127)
-			tmp = in_rssi - 256;
-		else
-			tmp = in_rssi;
-		break;
-	default:
-		tmp = in_rssi;
-		tmp -= 11;
-		tmp *= 103;
-		tmp /= 64;
-		if (adjust_2053)
-			tmp -= 109;
-		else
-			tmp -= 83;
-	}
-
-	return (s8)tmp;
-}
-
-static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
-					u8 in_rssi)
-{
-	s8 ret;
-
-	if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) {
-		//TODO: Incomplete specs.
-		ret = 0;
-	} else
-		ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
-
-	return ret;
-}
-
-static inline
-int bcm43xx_rx_packet(struct bcm43xx_private *bcm,
-		      struct sk_buff *skb,
-		      struct ieee80211_rx_stats *stats)
-{
-	int err;
-
-	err = ieee80211_rx(bcm->ieee, skb, stats);
-	if (unlikely(err == 0))
-		return -EINVAL;
-	return 0;
-}
-
-int bcm43xx_rx(struct bcm43xx_private *bcm,
-	       struct sk_buff *skb,
-	       struct bcm43xx_rxhdr *rxhdr)
-{
-	struct bcm43xx_plcp_hdr4 *plcp;
-	struct ieee80211_rx_stats stats;
-	struct ieee80211_hdr_4addr *wlhdr;
-	u16 frame_ctl;
-	int is_packet_for_us = 0;
-	int err = -EINVAL;
-	const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
-	const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
-	const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
-	const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
-
-	if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
-		plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
-		/* Skip two unknown bytes and the PLCP header. */
-		skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
-	} else {
-		plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
-		/* Skip the PLCP header. */
-		skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
-	}
-	/* The SKB contains the PAYLOAD (wireless header + data)
-	 * at this point. The FCS at the end is stripped.
-	 */
-
-	memset(&stats, 0, sizeof(stats));
-	stats.mac_time = le16_to_cpu(rxhdr->mactime);
-	stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
-					      !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
-					      !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
-	stats.signal = rxhdr->signal_quality;	//FIXME
-//TODO	stats.noise = 
-	stats.rate = bcm43xx_plcp_get_bitrate(plcp, is_ofdm);
-//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
-	stats.received_channel = bcm->current_core->radio->channel;
-//TODO	stats.control = 
-	stats.mask = IEEE80211_STATMASK_SIGNAL |
-//TODO		     IEEE80211_STATMASK_NOISE |
-		     IEEE80211_STATMASK_RATE |
-		     IEEE80211_STATMASK_RSSI;
-	if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A)
-		stats.freq = IEEE80211_52GHZ_BAND;
-	else
-		stats.freq = IEEE80211_24GHZ_BAND;
-	stats.len = skb->len;
-
-	bcm->stats.last_rx = jiffies;
-	if (bcm->ieee->iw_mode == IW_MODE_MONITOR)
-		return bcm43xx_rx_packet(bcm, skb, &stats);
-
-	wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
-
-	switch (bcm->ieee->iw_mode) {
-	case IW_MODE_ADHOC:
-		if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
-		    memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
-		    is_broadcast_ether_addr(wlhdr->addr1) ||
-		    is_multicast_ether_addr(wlhdr->addr1) ||
-		    bcm->net_dev->flags & IFF_PROMISC)
-			is_packet_for_us = 1;
-		break;
-	case IW_MODE_INFRA:
-	default:
-		/* When receiving multicast or broadcast packets, filter out
-		   the packets we send ourself; we shouldn't see those */
-		if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
-		    memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
-		    (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
-		     (is_broadcast_ether_addr(wlhdr->addr1) ||
-		      is_multicast_ether_addr(wlhdr->addr1) ||
-		      bcm->net_dev->flags & IFF_PROMISC)))
-			is_packet_for_us = 1;
-		break;
-	}
-
-	frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
-	if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
-		frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
-		wlhdr->frame_ctl = cpu_to_le16(frame_ctl);		
-		/* trim IV and ICV */
-		/* FIXME: this must be done only for WEP encrypted packets */
-		if (skb->len < 32) {
-			dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
-					      "set and length < 32)\n");
-			return -EINVAL;
-		} else {		
-			memmove(skb->data + 4, skb->data, 24);
-			skb_pull(skb, 4);
-			skb_trim(skb, skb->len - 4);
-			stats.len -= 8;
-		}
-		wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
-	}
-	
-	switch (WLAN_FC_GET_TYPE(frame_ctl)) {
-	case IEEE80211_FTYPE_MGMT:
-		ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
-		break;
-	case IEEE80211_FTYPE_DATA:
-		if (is_packet_for_us)
-			err = bcm43xx_rx_packet(bcm, skb, &stats);
-		break;
-	case IEEE80211_FTYPE_CTL:
-		break;
-	default:
-		assert(0);
-		return -EINVAL;
-	}
-
-	return err;
-}
-
 /* Do the Hardware IO operations to send the txb */
 static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
 			     struct ieee80211_txb *txb)