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