mac80211.c
Go to the documentation of this file.
00001 /*------------------------------------------------------------------------------
00002  *-------------------------        ATH5K Driver          -----------------------
00003  *------------------------------------------------------------------------------
00004  *                                                           V1.0  08/02/2010
00005  *
00006  *
00007  *  Feb 2010 - Samuel Cabrero <samuelcabrero@gmail.com>
00008  *              Initial release
00009  *
00010  *  ----------------------------------------------------------------------------
00011  *  Copyright (C) 2000-2010, Universidad de Zaragoza, SPAIN
00012  *
00013  *  Autors:
00014  *              Samuel Cabrero        <samuelcabrero@gmail.com>
00015  *              Danilo Tardioli       <dantard@unizar.es>
00016  *              Jose Luis Villarroel  <jlvilla@unizar.es>
00017  *
00018  *  This is a simplified version of the original ath5k driver. It should work 
00019  *  with all Atheros 5xxx WLAN cards. The 802.11 layer have been removed so it
00020  *  just send and receive frames over the air, as if it were an Ethernet bus
00021  *  interface.
00022  *
00023  *  Please read ath5k_interface.h for instructions.
00024  *
00025  *  This program is distributed under the terms of GPL version 2 and in the 
00026  *  hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 
00027  *  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00028  *  See the GNU General Public License for more details.
00029  *
00030  *----------------------------------------------------------------------------*/
00031 
00032 #include "ath5k.h"
00033 #include "mac80211.h"
00034 
00042 static inline int ath5k_is_erp_rate(unsigned int mode, int rate)
00043 {
00044         if (mode == AR5K_MODE_11G) {
00045                 if (rate != 10 && rate != 20 &&
00046                                 rate != 55 && rate != 110)
00047                         return 1;
00048         }
00049         return 0;
00050 }
00051 
00052 int ath5k_get_hdrlen(u16 fc)
00053 {
00054         int hdrlen = 24;
00055 
00056         switch (fc & IEEE80211_FCTL_FTYPE) {
00057                 case IEEE80211_FTYPE_DATA:
00058                         if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
00059                                 hdrlen = 30; /* Addr4 */
00060                         /*
00061                          * The QoS Control field is two bytes and its presence is
00062                          * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to
00063                          * hdrlen if that bit is set.
00064                          * This works by masking out the bit and shifting it to
00065                          * bit position 1 so the result has the value 0 or 2.
00066                          */
00067                         hdrlen += (fc & IEEE80211_STYPE_QOS_DATA) >> 6;
00068                         break;
00069                 case IEEE80211_FTYPE_CTL:
00070                         /*
00071                          * ACK and CTS are 10 bytes, all others 16. To see how
00072                          * to get this condition consider
00073                          *   subtype mask:   0b0000000011110000 (0x00F0)
00074                          *   ACK subtype:    0b0000000011010000 (0x00D0)
00075                          *   CTS subtype:    0b0000000011000000 (0x00C0)
00076                          *   bits that matter:         ^^^      (0x00E0)
00077                          *   value of those: 0b0000000011000000 (0x00C0)
00078                          */
00079                         if ((fc & 0xE0) == 0xC0)
00080                                 hdrlen = 10;
00081                         else
00082                                 hdrlen = 16;
00083                         break;
00084         }
00085 
00086         return hdrlen;
00087 }
00088 
00089 int ath5k_get_hdrlen_from_skb(const struct sk_buff *skb)
00090 {
00091         const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) skb->data;
00092         int hdrlen;
00093 
00094         if (unlikely(skb->len < 10))
00095                 return 0;
00096         hdrlen = ath5k_get_hdrlen(le16_to_cpu(hdr->frame_control));
00097         if (unlikely(hdrlen > skb->len))
00098                 return 0;
00099         return hdrlen;
00100 }
00101 
00102 int ath5k_frame_duration(unsigned int mode, size_t len,
00103                 int rate, int erp, int short_preamble)
00104 {
00105         int dur;
00106 
00107         /* calculate duration (in microseconds, rounded up to next higher
00108          * integer if it includes a fractional microsecond) to send frame of
00109          * len bytes (does not include FCS) at the given rate. Duration will
00110          * also include SIFS.
00111          *
00112          * rate is in 100 kbps, so divident is multiplied by 10 in the
00113          * DIV_ROUND_UP() operations.
00114          */
00115 
00116         if (mode == AR5K_MODE_11A || erp) {
00117                 /*
00118                  * OFDM:
00119                  *
00120                  * N_DBPS = DATARATE x 4
00121                  * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS)
00122                  *      (16 = SIGNAL time, 6 = tail bits)
00123                  * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
00124                  *
00125                  * T_SYM = 4 usec
00126                  * 802.11a - 17.5.2: aSIFSTime = 16 usec
00127                  * 802.11g - 19.8.4: aSIFSTime = 10 usec +
00128                  *      signal ext = 6 usec
00129                  */
00130                 dur = 16; /* SIFS + signal ext */
00131                 dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */
00132                 dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */
00133                 dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
00134                                 4 * rate); /* T_SYM x N_SYM */
00135         } else {
00136                 /*
00137                  * 802.11b or 802.11g with 802.11b compatibility:
00138                  * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime +
00139                  * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0.
00140                  *
00141                  * 802.11 (DS): 15.3.3, 802.11b: 18.3.4
00142                  * aSIFSTime = 10 usec
00143                  * aPreambleLength = 144 usec or 72 usec with short preamble
00144                  * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
00145                  */
00146                 dur = 10; /* aSIFSTime = 10 usec */
00147                 dur += short_preamble ? (72 + 24) : (144 + 48);
00148 
00149                 dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate);
00150         }
00151 
00152         return dur;
00153 }
00154 
00155 /* Exported duration function for driver use */
00156 __le16 ath5k_generic_frame_duration(unsigned int mode,
00157                 bool short_preamble,
00158                 size_t frame_len, int rate)
00159 {
00160         u16 dur;
00161         int erp;
00162 
00163         erp = ath5k_is_erp_rate(mode, rate);
00164         dur = ath5k_frame_duration(mode, frame_len, rate, erp, short_preamble);
00165 
00166         return cpu_to_le16(dur);
00167 }
00168 
00169 int ath5k_frequency_to_channel(int freq)
00170 {
00171         if (freq == 2484)
00172                 return 14;
00173 
00174         if (freq < 2484)
00175                 return (freq - 2407) / 5;
00176 
00177         /* FIXME: 802.11j 17.3.8.3.2 */
00178         return freq/5 - 1000;
00179 }
00180 


ros_rt_wmp
Author(s): Danilo Tardioli, dantard@unizar.es
autogenerated on Mon Oct 6 2014 08:27:10