[PATCH 7/24] RT2x00: Add RTS frame creation
From Ivo van Doorn [EMAIL PROTECTED] Support RTS. When rts is required, create the frame and send it out before the rest of the frames. Signed-off-by: Ivo van Doorn [EMAIL PROTECTED] --- diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c --- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-07-23 17:24:56.0 +0200 +++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-07-23 18:16:35.0 +0200 @@ -863,6 +863,36 @@ } /* + * RTS frame creation. + */ +static struct sk_buff* rt2400pci_create_rts(struct rt2x00_dev *rt2x00dev, + struct ieee80211_hdr *hdr, unsigned short duration) +{ + struct ieee80211_hdr *ieee80211hdr; + struct sk_buff *skb; + u16 temp; + + skb = dev_alloc_skb(IEEE80211_HEADER); + if (!skb) + return NULL; + + /* +* Copy the entire header over to RTS frame. +*/ + memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER); + ieee80211hdr = (struct ieee80211_hdr*)skb-data; + + temp = (WLAN_FC_TYPE_CTRL 2) | (WLAN_FC_STYPE_RTS 4); + ieee80211hdr-frame_control = cpu_to_le16(temp); + + ieee80211hdr-duration_id += cpu_to_le16(duration); + + ieee80211hdr-seq_ctrl = 0; + + return skb; +} + +/* * TX descriptor initialization */ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, @@ -876,15 +906,32 @@ u16 length_low; u16 signal; u16 service; + u16 frame_control; + u8 bitrate; + int tx_rate; + + /* +* Check which rate should be used for this frame. +*/ + frame_control = le16_to_cpu(ieee80211hdr-frame_control); + if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS + control-rts_cts_rate) + tx_rate = control-rts_cts_rate; + else + tx_rate = control-tx_rate; rt2x00_set_field32(txd-word0, TXD_W0_VALID, 1); rt2x00_set_field32(txd-word0, TXD_W0_ACK, !control-no_ack); /* -* TODO: IFS can be various values, where can we find -* which one we want to use? +* Set IFS to IFS_SIFS when the this is not the first fragment, +* or this fragment came after RTS/CTS. */ - rt2x00_set_field32(txd-word0, TXD_W0_IFS, 0); + if ((WLAN_GET_SEQ_FRAG(le16_to_cpu(ieee80211hdr-seq_ctrl)) 0) || + control-use_rts_cts) + rt2x00_set_field32(txd-word0, TXD_W0_IFS, IFS_SIFS); + else + rt2x00_set_field32(txd-word0, TXD_W0_IFS, IFS_BACKOFF); if (control-queue == IEEE80211_TX_QUEUE_BEACON) rt2x00_set_field32(txd-word0, TXD_W0_TIMESTAMP, 1); @@ -896,16 +943,15 @@ */ rt2x00_set_field32(txd-word0, TXD_W0_RETRY_MODE, 0); - if (ieee80211hdr-frame_control WLAN_FC_MOREFRAG) + if (frame_control WLAN_FC_MOREFRAG) rt2x00_set_field32(txd-word0, TXD_W0_MORE_FRAG, 1); else rt2x00_set_field32(txd-word0, TXD_W0_MORE_FRAG, 0); - /* -* TODO: Does this field mean device will send RTS, or that this -* frame is an RTS frame? -*/ - rt2x00_set_field32(txd-word0, TXD_W0_RTS, control-use_rts_cts); + if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS) + rt2x00_set_field32(txd-word10, TXD_W10_RTS, 1); + else + rt2x00_set_field32(txd-word10, TXD_W10_RTS, 0); rt2x00_set_field32(txd-word2, TXD_W2_DATABYTE_COUNT, skb-len); @@ -918,9 +964,9 @@ * Convert length to microseconds. */ residual = get_duration_res(length, - DEVICE_GET_RATE_FIELD(control-tx_rate, RATE)); + DEVICE_GET_RATE_FIELD(tx_rate, RATE)); length = get_duration(length, - DEVICE_GET_RATE_FIELD(control-tx_rate, RATE)); + DEVICE_GET_RATE_FIELD(tx_rate, RATE)); if (residual) length++; @@ -938,8 +984,8 @@ length_high = 0x8000 | 0x0700 | (length 8); length_low = 0x8000 | 0x0800 | (length 0xff); - signal = 0x8500 | DEVICE_GET_RATE_FIELD(control-tx_rate, PLCP); - if (DEVICE_GET_RATE_FIELD(control-tx_rate, PREAMBLE)) + signal = 0x8500 | DEVICE_GET_RATE_FIELD(tx_rate, PLCP); + if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) signal |= 0x0008; service = 0x0600 | 0x0004; @@ -1089,8 +1135,9 @@ entry-tx_status.retry_count = rt2x00_get_field32( txd-word0, TXD_W0_RETRY_COUNT); - ieee80211_tx_status(ring-net_dev, - entry-skb, entry-tx_status); + if (!GET_FLAG(entry, ENTRY_RTS_FRAME)) + ieee80211_tx_status(ring-net_dev, + entry-skb, entry-tx_status);
Re: [PATCH 7/24] RT2x00: Add RTS frame creation
From Ivo van Doorn [EMAIL PROTECTED] Support RTS. When rts is required, create the frame and send it out before the rest of the frames. Signed-off-by: Ivo van Doorn [EMAIL PROTECTED] diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c --- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-07-23 17:24:56.0 +0200 +++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-07-23 18:16:35.0 +0200 @@ -863,6 +863,36 @@ } /* + * RTS frame creation. + */ +static struct sk_buff* rt2400pci_create_rts(struct rt2x00_dev *rt2x00dev, + struct ieee80211_hdr *hdr, unsigned short duration) +{ + struct ieee80211_hdr *ieee80211hdr; + struct sk_buff *skb; + u16 temp; + + skb = dev_alloc_skb(IEEE80211_HEADER); + if (!skb) + return NULL; + + /* +* Copy the entire header over to RTS frame. +*/ + memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER); + ieee80211hdr = (struct ieee80211_hdr*)skb-data; + + temp = (WLAN_FC_TYPE_CTRL 2) | (WLAN_FC_STYPE_RTS 4); + ieee80211hdr-frame_control = cpu_to_le16(temp); + + ieee80211hdr-duration_id += cpu_to_le16(duration); + + ieee80211hdr-seq_ctrl = 0; + + return skb; +} + +/* * TX descriptor initialization */ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, @@ -876,15 +906,32 @@ u16 length_low; u16 signal; u16 service; + u16 frame_control; + u8 bitrate; + int tx_rate; + + /* +* Check which rate should be used for this frame. +*/ + frame_control = le16_to_cpu(ieee80211hdr-frame_control); + if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS + control-rts_cts_rate) + tx_rate = control-rts_cts_rate; + else + tx_rate = control-tx_rate; rt2x00_set_field32(txd-word0, TXD_W0_VALID, 1); rt2x00_set_field32(txd-word0, TXD_W0_ACK, !control-no_ack); /* -* TODO: IFS can be various values, where can we find -* which one we want to use? +* Set IFS to IFS_SIFS when the this is not the first fragment, +* or this fragment came after RTS/CTS. */ - rt2x00_set_field32(txd-word0, TXD_W0_IFS, 0); + if ((WLAN_GET_SEQ_FRAG(le16_to_cpu(ieee80211hdr-seq_ctrl)) 0) || + control-use_rts_cts) + rt2x00_set_field32(txd-word0, TXD_W0_IFS, IFS_SIFS); + else + rt2x00_set_field32(txd-word0, TXD_W0_IFS, IFS_BACKOFF); if (control-queue == IEEE80211_TX_QUEUE_BEACON) rt2x00_set_field32(txd-word0, TXD_W0_TIMESTAMP, 1); @@ -896,16 +943,15 @@ */ rt2x00_set_field32(txd-word0, TXD_W0_RETRY_MODE, 0); - if (ieee80211hdr-frame_control WLAN_FC_MOREFRAG) + if (frame_control WLAN_FC_MOREFRAG) rt2x00_set_field32(txd-word0, TXD_W0_MORE_FRAG, 1); else rt2x00_set_field32(txd-word0, TXD_W0_MORE_FRAG, 0); - /* -* TODO: Does this field mean device will send RTS, or that this -* frame is an RTS frame? -*/ - rt2x00_set_field32(txd-word0, TXD_W0_RTS, control-use_rts_cts); + if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS) + rt2x00_set_field32(txd-word10, TXD_W10_RTS, 1); + else + rt2x00_set_field32(txd-word10, TXD_W10_RTS, 0); rt2x00_set_field32(txd-word2, TXD_W2_DATABYTE_COUNT, skb-len); @@ -918,9 +964,9 @@ * Convert length to microseconds. */ residual = get_duration_res(length, - DEVICE_GET_RATE_FIELD(control-tx_rate, RATE)); + DEVICE_GET_RATE_FIELD(tx_rate, RATE)); length = get_duration(length, - DEVICE_GET_RATE_FIELD(control-tx_rate, RATE)); + DEVICE_GET_RATE_FIELD(tx_rate, RATE)); if (residual) length++; @@ -938,8 +984,8 @@ length_high = 0x8000 | 0x0700 | (length 8); length_low = 0x8000 | 0x0800 | (length 0xff); - signal = 0x8500 | DEVICE_GET_RATE_FIELD(control-tx_rate, PLCP); - if (DEVICE_GET_RATE_FIELD(control-tx_rate, PREAMBLE)) + signal = 0x8500 | DEVICE_GET_RATE_FIELD(tx_rate, PLCP); + if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) signal |= 0x0008; service = 0x0600 | 0x0004; @@ -1089,8 +1135,9 @@ entry-tx_status.retry_count = rt2x00_get_field32( txd-word0, TXD_W0_RETRY_COUNT); - ieee80211_tx_status(ring-net_dev, - entry-skb, entry-tx_status); + if (!GET_FLAG(entry, ENTRY_RTS_FRAME)) + ieee80211_tx_status(ring-net_dev, + entry-skb, entry-tx_status);