mac80211.c
Go to the documentation of this file.
00001 #include <linux/types.h>
00002 
00003 #include "ath5k.h"
00004 #include "mac80211.h"
00005 
00013 static inline int ath5k_is_erp_rate(unsigned int mode, int rate)
00014 {
00015         if (mode == AR5K_MODE_11G) {
00016                 if (rate != 10 && rate != 20 &&
00017                     rate != 55 && rate != 110)
00018                         return 1;
00019         }
00020         return 0;
00021 }
00022 
00023 int ath5k_get_hdrlen(u16 fc)
00024 {
00025         int hdrlen = 24;
00026 
00027         switch (fc & IEEE80211_FCTL_FTYPE) {
00028         case IEEE80211_FTYPE_DATA:
00029                 if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
00030                         hdrlen = 30; /* Addr4 */
00031                 /*
00032                  * The QoS Control field is two bytes and its presence is
00033                  * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to
00034                  * hdrlen if that bit is set.
00035                  * This works by masking out the bit and shifting it to
00036                  * bit position 1 so the result has the value 0 or 2.
00037                  */
00038                 hdrlen += (fc & IEEE80211_STYPE_QOS_DATA) >> 6;
00039                 break;
00040         case IEEE80211_FTYPE_CTL:
00041                 /*
00042                  * ACK and CTS are 10 bytes, all others 16. To see how
00043                  * to get this condition consider
00044                  *   subtype mask:   0b0000000011110000 (0x00F0)
00045                  *   ACK subtype:    0b0000000011010000 (0x00D0)
00046                  *   CTS subtype:    0b0000000011000000 (0x00C0)
00047                  *   bits that matter:         ^^^      (0x00E0)
00048                  *   value of those: 0b0000000011000000 (0x00C0)
00049                  */
00050                 if ((fc & 0xE0) == 0xC0)
00051                         hdrlen = 10;
00052                 else
00053                         hdrlen = 16;
00054                 break;
00055         }
00056 
00057         return hdrlen;
00058 }
00059 
00060 int ath5k_get_hdrlen_from_skb(const struct sk_buff *skb)
00061 {
00062         const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) skb->data;
00063         int hdrlen;
00064 
00065         if (unlikely(skb->len < 10))
00066                 return 0;
00067         hdrlen = ath5k_get_hdrlen(le16_to_cpu(hdr->frame_control));
00068         if (unlikely(hdrlen > skb->len))
00069                 return 0;
00070         return hdrlen;
00071 }
00072 
00073 int ath5k_frame_duration(unsigned int mode, size_t len,
00074                              int rate, int erp, int short_preamble)
00075 {
00076         int dur;
00077 
00078         /* calculate duration (in microseconds, rounded up to next higher
00079          * integer if it includes a fractional microsecond) to send frame of
00080          * len bytes (does not include FCS) at the given rate. Duration will
00081          * also include SIFS.
00082          *
00083          * rate is in 100 kbps, so divident is multiplied by 10 in the
00084          * DIV_ROUND_UP() operations.
00085          */
00086 
00087         if (mode == AR5K_MODE_11A || erp) {
00088                 /*
00089                  * OFDM:
00090                  *
00091                  * N_DBPS = DATARATE x 4
00092                  * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS)
00093                  *      (16 = SIGNAL time, 6 = tail bits)
00094                  * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
00095                  *
00096                  * T_SYM = 4 usec
00097                  * 802.11a - 17.5.2: aSIFSTime = 16 usec
00098                  * 802.11g - 19.8.4: aSIFSTime = 10 usec +
00099                  *      signal ext = 6 usec
00100                  */
00101                 dur = 16; /* SIFS + signal ext */
00102                 dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */
00103                 dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */
00104                 dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
00105                                         4 * rate); /* T_SYM x N_SYM */
00106         } else {
00107                 /*
00108                  * 802.11b or 802.11g with 802.11b compatibility:
00109                  * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime +
00110                  * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0.
00111                  *
00112                  * 802.11 (DS): 15.3.3, 802.11b: 18.3.4
00113                  * aSIFSTime = 10 usec
00114                  * aPreambleLength = 144 usec or 72 usec with short preamble
00115                  * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
00116                  */
00117                 dur = 10; /* aSIFSTime = 10 usec */
00118                 dur += short_preamble ? (72 + 24) : (144 + 48);
00119 
00120                 dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate);
00121         }
00122 
00123         return dur;
00124 }
00125 
00126 /* Exported duration function for driver use */
00127 __le16 ath5k_generic_frame_duration(unsigned int mode,
00128                                                                                 bool short_preamble,
00129                                         size_t frame_len, int rate)
00130 {
00131         u16 dur;
00132         int erp;
00133 
00134         erp = ath5k_is_erp_rate(mode, rate);
00135         dur = ath5k_frame_duration(mode, frame_len, rate, erp, short_preamble);
00136 
00137         return cpu_to_le16(dur);
00138 }
00139 
00140 int ath5k_frequency_to_channel(int freq)
00141 {
00142         if (freq == 2484)
00143                 return 14;
00144 
00145         if (freq < 2484)
00146                 return (freq - 2407) / 5;
00147 
00148         /* FIXME: 802.11j 17.3.8.3.2 */
00149         return freq/5 - 1000;
00150 }
00151 


ros_rt_wmp
Author(s): Danilo Tardioli, dantard@unizar.es
autogenerated on Fri Jan 3 2014 12:07:55