nrelease - fix/improve livecd
[dragonfly.git] / sys / netproto / 802_11 / wlan / ieee80211_phy.c
1 /*-
2  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 /*
30  * IEEE 802.11 PHY-related support.
31  */
32
33 #include "opt_inet.h"
34
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39
40 #include <sys/socket.h>
41
42 #include <net/if.h>
43 #include <net/if_var.h>
44 #include <net/if_media.h>
45
46 #include <net/ethernet.h>
47 #include <net/route.h>
48
49 #include <netproto/802_11/ieee80211_var.h>
50 #include <netproto/802_11/ieee80211_phy.h>
51
52 #ifdef notyet
53 struct ieee80211_ds_plcp_hdr {
54         uint8_t         i_signal;
55         uint8_t         i_service;
56         uint16_t        i_length;
57         uint16_t        i_crc;
58 } __packed;
59
60 #endif  /* notyet */
61
62 /* shorthands to compact tables for readability */
63 #define OFDM    IEEE80211_T_OFDM
64 #define CCK     IEEE80211_T_CCK
65 #define TURBO   IEEE80211_T_TURBO
66 #define HALF    IEEE80211_T_OFDM_HALF
67 #define QUART   IEEE80211_T_OFDM_QUARTER
68 #define HT      IEEE80211_T_HT
69 /* XXX the 11n and the basic rate flag are unfortunately overlapping. Grr. */
70 #define N(r)    (IEEE80211_RATE_MCS | r)
71 #define PBCC    (IEEE80211_T_OFDM_QUARTER+1)            /* XXX */
72 #define B(r)    (IEEE80211_RATE_BASIC | r)
73 #define Mb(x)   (x*1000)
74
75 static struct ieee80211_rate_table ieee80211_11b_table = {
76     .rateCount = 4,             /* XXX no PBCC */
77     .info = {
78 /*                                   short            ctrl  */
79 /*                                Preamble  dot11Rate Rate */
80      [0] = { .phy = CCK,     1000,    0x00,      B(2),   0 },/*   1 Mb */
81      [1] = { .phy = CCK,     2000,    0x04,      B(4),   1 },/*   2 Mb */
82      [2] = { .phy = CCK,     5500,    0x04,     B(11),   1 },/* 5.5 Mb */
83      [3] = { .phy = CCK,    11000,    0x04,     B(22),   1 },/*  11 Mb */
84      [4] = { .phy = PBCC,   22000,    0x04,        44,   3 } /*  22 Mb */
85     },
86 };
87
88 static struct ieee80211_rate_table ieee80211_11g_table = {
89     .rateCount = 12,
90     .info = {
91 /*                                   short            ctrl  */
92 /*                                Preamble  dot11Rate Rate */
93      [0] = { .phy = CCK,     1000,    0x00,      B(2),   0 },
94      [1] = { .phy = CCK,     2000,    0x04,      B(4),   1 },
95      [2] = { .phy = CCK,     5500,    0x04,     B(11),   2 },
96      [3] = { .phy = CCK,    11000,    0x04,     B(22),   3 },
97      [4] = { .phy = OFDM,    6000,    0x00,        12,   4 },
98      [5] = { .phy = OFDM,    9000,    0x00,        18,   4 },
99      [6] = { .phy = OFDM,   12000,    0x00,        24,   6 },
100      [7] = { .phy = OFDM,   18000,    0x00,        36,   6 },
101      [8] = { .phy = OFDM,   24000,    0x00,        48,   8 },
102      [9] = { .phy = OFDM,   36000,    0x00,        72,   8 },
103     [10] = { .phy = OFDM,   48000,    0x00,        96,   8 },
104     [11] = { .phy = OFDM,   54000,    0x00,       108,   8 }
105     },
106 };
107
108 static struct ieee80211_rate_table ieee80211_11a_table = {
109     .rateCount = 8,
110     .info = {
111 /*                                   short            ctrl  */
112 /*                                Preamble  dot11Rate Rate */
113      [0] = { .phy = OFDM,    6000,    0x00,     B(12),   0 },
114      [1] = { .phy = OFDM,    9000,    0x00,        18,   0 },
115      [2] = { .phy = OFDM,   12000,    0x00,     B(24),   2 },
116      [3] = { .phy = OFDM,   18000,    0x00,        36,   2 },
117      [4] = { .phy = OFDM,   24000,    0x00,     B(48),   4 },
118      [5] = { .phy = OFDM,   36000,    0x00,        72,   4 },
119      [6] = { .phy = OFDM,   48000,    0x00,        96,   4 },
120      [7] = { .phy = OFDM,   54000,    0x00,       108,   4 }
121     },
122 };
123
124 static struct ieee80211_rate_table ieee80211_half_table = {
125     .rateCount = 8,
126     .info = {
127 /*                                   short            ctrl  */
128 /*                                Preamble  dot11Rate Rate */
129      [0] = { .phy = HALF,    3000,    0x00,      B(6),   0 },
130      [1] = { .phy = HALF,    4500,    0x00,         9,   0 },
131      [2] = { .phy = HALF,    6000,    0x00,     B(12),   2 },
132      [3] = { .phy = HALF,    9000,    0x00,        18,   2 },
133      [4] = { .phy = HALF,   12000,    0x00,     B(24),   4 },
134      [5] = { .phy = HALF,   18000,    0x00,        36,   4 },
135      [6] = { .phy = HALF,   24000,    0x00,        48,   4 },
136      [7] = { .phy = HALF,   27000,    0x00,        54,   4 }
137     },
138 };
139
140 static struct ieee80211_rate_table ieee80211_quarter_table = {
141     .rateCount = 8,
142     .info = {
143 /*                                   short            ctrl  */
144 /*                                Preamble  dot11Rate Rate */
145      [0] = { .phy = QUART,   1500,    0x00,      B(3),   0 },
146      [1] = { .phy = QUART,   2250,    0x00,         4,   0 },
147      [2] = { .phy = QUART,   3000,    0x00,      B(9),   2 },
148      [3] = { .phy = QUART,   4500,    0x00,         9,   2 },
149      [4] = { .phy = QUART,   6000,    0x00,     B(12),   4 },
150      [5] = { .phy = QUART,   9000,    0x00,        18,   4 },
151      [6] = { .phy = QUART,  12000,    0x00,        24,   4 },
152      [7] = { .phy = QUART,  13500,    0x00,        27,   4 }
153     },
154 };
155
156 static struct ieee80211_rate_table ieee80211_turbog_table = {
157     .rateCount = 7,
158     .info = {
159 /*                                   short            ctrl  */
160 /*                                Preamble  dot11Rate Rate */
161      [0] = { .phy = TURBO,   12000,   0x00,     B(12),   0 },
162      [1] = { .phy = TURBO,   24000,   0x00,     B(24),   1 },
163      [2] = { .phy = TURBO,   36000,   0x00,        36,   1 },
164      [3] = { .phy = TURBO,   48000,   0x00,     B(48),   3 },
165      [4] = { .phy = TURBO,   72000,   0x00,        72,   3 },
166      [5] = { .phy = TURBO,   96000,   0x00,        96,   3 },
167      [6] = { .phy = TURBO,  108000,   0x00,       108,   3 }
168     },
169 };
170
171 static struct ieee80211_rate_table ieee80211_turboa_table = {
172     .rateCount = 8,
173     .info = {
174 /*                                   short            ctrl  */
175 /*                                Preamble  dot11Rate Rate */
176      [0] = { .phy = TURBO,   12000,   0x00,     B(12),   0 },
177      [1] = { .phy = TURBO,   18000,   0x00,        18,   0 },
178      [2] = { .phy = TURBO,   24000,   0x00,     B(24),   2 },
179      [3] = { .phy = TURBO,   36000,   0x00,        36,   2 },
180      [4] = { .phy = TURBO,   48000,   0x00,     B(48),   4 },
181      [5] = { .phy = TURBO,   72000,   0x00,        72,   4 },
182      [6] = { .phy = TURBO,   96000,   0x00,        96,   4 },
183      [7] = { .phy = TURBO,  108000,   0x00,       108,   4 }
184     },
185 };
186
187 static struct ieee80211_rate_table ieee80211_11ng_table = {
188     .rateCount = 36,
189     .info = {
190 /*                                   short            ctrl  */
191 /*                                Preamble  dot11Rate Rate */
192      [0] = { .phy = CCK,     1000,    0x00,      B(2),   0 },
193      [1] = { .phy = CCK,     2000,    0x04,      B(4),   1 },
194      [2] = { .phy = CCK,     5500,    0x04,     B(11),   2 },
195      [3] = { .phy = CCK,    11000,    0x04,     B(22),   3 },
196      [4] = { .phy = OFDM,    6000,    0x00,        12,   4 },
197      [5] = { .phy = OFDM,    9000,    0x00,        18,   4 },
198      [6] = { .phy = OFDM,   12000,    0x00,        24,   6 },
199      [7] = { .phy = OFDM,   18000,    0x00,        36,   6 },
200      [8] = { .phy = OFDM,   24000,    0x00,        48,   8 },
201      [9] = { .phy = OFDM,   36000,    0x00,        72,   8 },
202     [10] = { .phy = OFDM,   48000,    0x00,        96,   8 },
203     [11] = { .phy = OFDM,   54000,    0x00,       108,   8 },
204
205     [12] = { .phy = HT,      6500,    0x00,      N(0),   4 },
206     [13] = { .phy = HT,     13000,    0x00,      N(1),   6 },
207     [14] = { .phy = HT,     19500,    0x00,      N(2),   6 },
208     [15] = { .phy = HT,     26000,    0x00,      N(3),   8 },
209     [16] = { .phy = HT,     39000,    0x00,      N(4),   8 },
210     [17] = { .phy = HT,     52000,    0x00,      N(5),   8 },
211     [18] = { .phy = HT,     58500,    0x00,      N(6),   8 },
212     [19] = { .phy = HT,     65000,    0x00,      N(7),   8 },
213
214     [20] = { .phy = HT,     13000,    0x00,      N(8),   4 },
215     [21] = { .phy = HT,     26000,    0x00,      N(9),   6 },
216     [22] = { .phy = HT,     39000,    0x00,     N(10),   6 },
217     [23] = { .phy = HT,     52000,    0x00,     N(11),   8 },
218     [24] = { .phy = HT,     78000,    0x00,     N(12),   8 },
219     [25] = { .phy = HT,    104000,    0x00,     N(13),   8 },
220     [26] = { .phy = HT,    117000,    0x00,     N(14),   8 },
221     [27] = { .phy = HT,    130000,    0x00,     N(15),   8 },
222
223     [28] = { .phy = HT,     19500,    0x00,     N(16),   4 },
224     [29] = { .phy = HT,     39000,    0x00,     N(17),   6 },
225     [30] = { .phy = HT,     58500,    0x00,     N(18),   6 },
226     [31] = { .phy = HT,     78000,    0x00,     N(19),   8 },
227     [32] = { .phy = HT,    117000,    0x00,     N(20),   8 },
228     [33] = { .phy = HT,    156000,    0x00,     N(21),   8 },
229     [34] = { .phy = HT,    175500,    0x00,     N(22),   8 },
230     [35] = { .phy = HT,    195000,    0x00,     N(23),   8 },
231
232     },
233 };
234
235 static struct ieee80211_rate_table ieee80211_11na_table = {
236     .rateCount = 32,
237     .info = {
238 /*                                   short            ctrl  */
239 /*                                Preamble  dot11Rate Rate */
240      [0] = { .phy = OFDM,    6000,    0x00,     B(12),   0 },
241      [1] = { .phy = OFDM,    9000,    0x00,        18,   0 },
242      [2] = { .phy = OFDM,   12000,    0x00,     B(24),   2 },
243      [3] = { .phy = OFDM,   18000,    0x00,        36,   2 },
244      [4] = { .phy = OFDM,   24000,    0x00,     B(48),   4 },
245      [5] = { .phy = OFDM,   36000,    0x00,        72,   4 },
246      [6] = { .phy = OFDM,   48000,    0x00,        96,   4 },
247      [7] = { .phy = OFDM,   54000,    0x00,       108,   4 },
248
249      [8] = { .phy = HT,      6500,    0x00,      N(0),   0 },
250      [9] = { .phy = HT,     13000,    0x00,      N(1),   2 },
251     [10] = { .phy = HT,     19500,    0x00,      N(2),   2 },
252     [11] = { .phy = HT,     26000,    0x00,      N(3),   4 },
253     [12] = { .phy = HT,     39000,    0x00,      N(4),   4 },
254     [13] = { .phy = HT,     52000,    0x00,      N(5),   4 },
255     [14] = { .phy = HT,     58500,    0x00,      N(6),   4 },
256     [15] = { .phy = HT,     65000,    0x00,      N(7),   4 },
257
258     [16] = { .phy = HT,     13000,    0x00,      N(8),   0 },
259     [17] = { .phy = HT,     26000,    0x00,      N(9),   2 },
260     [18] = { .phy = HT,     39000,    0x00,     N(10),   2 },
261     [19] = { .phy = HT,     52000,    0x00,     N(11),   4 },
262     [20] = { .phy = HT,     78000,    0x00,     N(12),   4 },
263     [21] = { .phy = HT,    104000,    0x00,     N(13),   4 },
264     [22] = { .phy = HT,    117000,    0x00,     N(14),   4 },
265     [23] = { .phy = HT,    130000,    0x00,     N(15),   4 },
266
267     [24] = { .phy = HT,     19500,    0x00,     N(16),   0 },
268     [25] = { .phy = HT,     39000,    0x00,     N(17),   2 },
269     [26] = { .phy = HT,     58500,    0x00,     N(18),   2 },
270     [27] = { .phy = HT,     78000,    0x00,     N(19),   4 },
271     [28] = { .phy = HT,    117000,    0x00,     N(20),   4 },
272     [29] = { .phy = HT,    156000,    0x00,     N(21),   4 },
273     [30] = { .phy = HT,    175500,    0x00,     N(22),   4 },
274     [31] = { .phy = HT,    195000,    0x00,     N(23),   4 },
275
276     },
277 };
278
279 #undef  Mb
280 #undef  B
281 #undef  OFDM
282 #undef  HALF
283 #undef  QUART
284 #undef  CCK
285 #undef  TURBO
286 #undef  XR
287 #undef  HT
288 #undef  N
289
290 /*
291  * Setup a rate table's reverse lookup table and fill in
292  * ack durations.  The reverse lookup tables are assumed
293  * to be initialized to zero (or at least the first entry).
294  * We use this as a key that indicates whether or not
295  * we've previously setup the reverse lookup table.
296  *
297  * XXX not reentrant, but shouldn't matter
298  */
299 static void
300 ieee80211_setup_ratetable(struct ieee80211_rate_table *rt)
301 {
302 #define WLAN_CTRL_FRAME_SIZE \
303         (sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN)
304
305         int i;
306
307         for (i = 0; i < nitems(rt->rateCodeToIndex); i++)
308                 rt->rateCodeToIndex[i] = (uint8_t) -1;
309         for (i = 0; i < rt->rateCount; i++) {
310                 uint8_t code = rt->info[i].dot11Rate;
311                 uint8_t cix = rt->info[i].ctlRateIndex;
312                 uint8_t ctl_rate = rt->info[cix].dot11Rate;
313
314                 /*
315                  * Map without the basic rate bit.
316                  *
317                  * It's up to the caller to ensure that the basic
318                  * rate bit is stripped here.
319                  *
320                  * For HT, use the MCS rate bit.
321                  */
322                 code &= IEEE80211_RATE_VAL;
323                 if (rt->info[i].phy == IEEE80211_T_HT) {
324                         code |= IEEE80211_RATE_MCS;
325                 }
326
327                 /* XXX assume the control rate is non-MCS? */
328                 ctl_rate &= IEEE80211_RATE_VAL;
329                 rt->rateCodeToIndex[code] = i;
330
331                 /*
332                  * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
333                  *     depends on whether they are marked as basic rates;
334                  *     the static tables are setup with an 11b-compatible
335                  *     2Mb/s rate which will work but is suboptimal
336                  *
337                  * NB: Control rate is always less than or equal to the
338                  *     current rate, so control rate's reverse lookup entry
339                  *     has been installed and following call is safe.
340                  */
341                 rt->info[i].lpAckDuration = ieee80211_compute_duration(rt,
342                         WLAN_CTRL_FRAME_SIZE, ctl_rate, 0);
343                 rt->info[i].spAckDuration = ieee80211_compute_duration(rt,
344                         WLAN_CTRL_FRAME_SIZE, ctl_rate, IEEE80211_F_SHPREAMBLE);
345         }
346
347 #undef WLAN_CTRL_FRAME_SIZE
348 }
349
350 /* Setup all rate tables */
351 static void
352 ieee80211_phy_init(void)
353 {
354         static struct ieee80211_rate_table * const ratetables[] = {
355                 &ieee80211_half_table,
356                 &ieee80211_quarter_table,
357                 &ieee80211_11na_table,
358                 &ieee80211_11ng_table,
359                 &ieee80211_turbog_table,
360                 &ieee80211_turboa_table,
361                 &ieee80211_11a_table,
362                 &ieee80211_11g_table,
363                 &ieee80211_11b_table
364         };
365         int i;
366
367         for (i = 0; i < nitems(ratetables); ++i)
368                 ieee80211_setup_ratetable(ratetables[i]);
369
370 }
371 SYSINIT(wlan_phy, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_phy_init, NULL);
372
373 const struct ieee80211_rate_table *
374 ieee80211_get_ratetable(struct ieee80211_channel *c)
375 {
376         const struct ieee80211_rate_table *rt;
377
378         /* XXX HT */
379         if (IEEE80211_IS_CHAN_HALF(c))
380                 rt = &ieee80211_half_table;
381         else if (IEEE80211_IS_CHAN_QUARTER(c))
382                 rt = &ieee80211_quarter_table;
383         else if (IEEE80211_IS_CHAN_HTA(c))
384                 rt = &ieee80211_11na_table;
385         else if (IEEE80211_IS_CHAN_HTG(c))
386                 rt = &ieee80211_11ng_table;
387         else if (IEEE80211_IS_CHAN_108G(c))
388                 rt = &ieee80211_turbog_table;
389         else if (IEEE80211_IS_CHAN_ST(c))
390                 rt = &ieee80211_turboa_table;
391         else if (IEEE80211_IS_CHAN_TURBO(c))
392                 rt = &ieee80211_turboa_table;
393         else if (IEEE80211_IS_CHAN_A(c))
394                 rt = &ieee80211_11a_table;
395         else if (IEEE80211_IS_CHAN_ANYG(c))
396                 rt = &ieee80211_11g_table;
397         else if (IEEE80211_IS_CHAN_B(c))
398                 rt = &ieee80211_11b_table;
399         else {
400                 /* NB: should not get here */
401                 panic("%s: no rate table for channel; freq %u flags 0x%x\n",
402                       __func__, c->ic_freq, c->ic_flags);
403         }
404         return rt;
405 }
406
407 /*
408  * Convert PLCP signal/rate field to 802.11 rate (.5Mbits/s)
409  *
410  * Note we do no parameter checking; this routine is mainly
411  * used to derive an 802.11 rate for constructing radiotap
412  * header data for rx frames.
413  *
414  * XXX might be a candidate for inline
415  */
416 uint8_t
417 ieee80211_plcp2rate(uint8_t plcp, enum ieee80211_phytype type)
418 {
419         if (type == IEEE80211_T_OFDM) {
420                 static const uint8_t ofdm_plcp2rate[16] = {
421                         [0xb]   = 12,
422                         [0xf]   = 18,
423                         [0xa]   = 24,
424                         [0xe]   = 36,
425                         [0x9]   = 48,
426                         [0xd]   = 72,
427                         [0x8]   = 96,
428                         [0xc]   = 108
429                 };
430                 return ofdm_plcp2rate[plcp & 0xf];
431         }
432         if (type == IEEE80211_T_CCK) {
433                 static const uint8_t cck_plcp2rate[16] = {
434                         [0xa]   = 2,    /* 0x0a */
435                         [0x4]   = 4,    /* 0x14 */
436                         [0x7]   = 11,   /* 0x37 */
437                         [0xe]   = 22,   /* 0x6e */
438                         [0xc]   = 44,   /* 0xdc , actually PBCC */
439                 };
440                 return cck_plcp2rate[plcp & 0xf];
441         }
442         return 0;
443 }
444
445 /*
446  * Covert 802.11 rate to PLCP signal.
447  */
448 uint8_t
449 ieee80211_rate2plcp(int rate, enum ieee80211_phytype type)
450 {
451         /* XXX ignore type for now since rates are unique */
452         switch (rate) {
453         /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
454         case 12:        return 0xb;
455         case 18:        return 0xf;
456         case 24:        return 0xa;
457         case 36:        return 0xe;
458         case 48:        return 0x9;
459         case 72:        return 0xd;
460         case 96:        return 0x8;
461         case 108:       return 0xc;
462         /* CCK rates (IEEE Std 802.11b-1999 page 15, subclause 18.2.3.3) */
463         case 2:         return 10;
464         case 4:         return 20;
465         case 11:        return 55;
466         case 22:        return 110;
467         /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
468         case 44:        return 220;
469         }
470         return 0;               /* XXX unsupported/unknown rate */
471 }
472
473 #define CCK_SIFS_TIME           10
474 #define CCK_PREAMBLE_BITS       144
475 #define CCK_PLCP_BITS           48
476
477 #define OFDM_SIFS_TIME          16
478 #define OFDM_PREAMBLE_TIME      20
479 #define OFDM_PLCP_BITS          22
480 #define OFDM_SYMBOL_TIME        4
481
482 #define OFDM_HALF_SIFS_TIME     32
483 #define OFDM_HALF_PREAMBLE_TIME 40
484 #define OFDM_HALF_PLCP_BITS     22
485 #define OFDM_HALF_SYMBOL_TIME   8
486
487 #define OFDM_QUARTER_SIFS_TIME          64
488 #define OFDM_QUARTER_PREAMBLE_TIME      80
489 #define OFDM_QUARTER_PLCP_BITS          22
490 #define OFDM_QUARTER_SYMBOL_TIME        16
491
492 #define TURBO_SIFS_TIME         8
493 #define TURBO_PREAMBLE_TIME     14
494 #define TURBO_PLCP_BITS         22
495 #define TURBO_SYMBOL_TIME       4
496
497 /*
498  * Compute the time to transmit a frame of length frameLen bytes
499  * using the specified rate, phy, and short preamble setting.
500  * SIFS is included.
501  */
502 uint16_t
503 ieee80211_compute_duration(const struct ieee80211_rate_table *rt,
504         uint32_t frameLen, uint16_t rate, int isShortPreamble)
505 {
506         uint8_t rix = rt->rateCodeToIndex[rate];
507         uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
508         uint32_t kbps;
509
510         KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
511         kbps = rt->info[rix].rateKbps;
512         if (kbps == 0)                  /* XXX bandaid for channel changes */
513                 return 0;
514
515         switch (rt->info[rix].phy) {
516         case IEEE80211_T_CCK:
517                 phyTime         = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
518                 if (isShortPreamble && rt->info[rix].shortPreamble)
519                         phyTime >>= 1;
520                 numBits         = frameLen << 3;
521                 txTime          = CCK_SIFS_TIME + phyTime
522                                 + ((numBits * 1000)/kbps);
523                 break;
524         case IEEE80211_T_OFDM:
525                 bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME) / 1000;
526                 KASSERT(bitsPerSymbol != 0, ("full rate bps"));
527
528                 numBits         = OFDM_PLCP_BITS + (frameLen << 3);
529                 numSymbols      = howmany(numBits, bitsPerSymbol);
530                 txTime          = OFDM_SIFS_TIME
531                                 + OFDM_PREAMBLE_TIME
532                                 + (numSymbols * OFDM_SYMBOL_TIME);
533                 break;
534         case IEEE80211_T_OFDM_HALF:
535                 bitsPerSymbol   = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
536                 KASSERT(bitsPerSymbol != 0, ("1/4 rate bps"));
537
538                 numBits         = OFDM_PLCP_BITS + (frameLen << 3);
539                 numSymbols      = howmany(numBits, bitsPerSymbol);
540                 txTime          = OFDM_HALF_SIFS_TIME
541                                 + OFDM_HALF_PREAMBLE_TIME
542                                 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
543                 break;
544         case IEEE80211_T_OFDM_QUARTER:
545                 bitsPerSymbol   = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
546                 KASSERT(bitsPerSymbol != 0, ("1/2 rate bps"));
547
548                 numBits         = OFDM_PLCP_BITS + (frameLen << 3);
549                 numSymbols      = howmany(numBits, bitsPerSymbol);
550                 txTime          = OFDM_QUARTER_SIFS_TIME
551                                 + OFDM_QUARTER_PREAMBLE_TIME
552                                 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
553                 break;
554         case IEEE80211_T_TURBO:
555                 /* we still save OFDM rates in kbps - so double them */
556                 bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
557                 KASSERT(bitsPerSymbol != 0, ("turbo bps"));
558
559                 numBits       = TURBO_PLCP_BITS + (frameLen << 3);
560                 numSymbols    = howmany(numBits, bitsPerSymbol);
561                 txTime        = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME
562                               + (numSymbols * TURBO_SYMBOL_TIME);
563                 break;
564         default:
565                 panic("%s: unknown phy %u (rate %u)\n", __func__,
566                       rt->info[rix].phy, rate);
567                 break;
568         }
569         return txTime;
570 }
571
572 static const uint16_t ht20_bps[32] = {
573         26, 52, 78, 104, 156, 208, 234, 260,
574         52, 104, 156, 208, 312, 416, 468, 520,
575         78, 156, 234, 312, 468, 624, 702, 780,
576         104, 208, 312, 416, 624, 832, 936, 1040
577 };
578 static const uint16_t ht40_bps[32] = {
579         54, 108, 162, 216, 324, 432, 486, 540,
580         108, 216, 324, 432, 648, 864, 972, 1080,
581         162, 324, 486, 648, 972, 1296, 1458, 1620,
582         216, 432, 648, 864, 1296, 1728, 1944, 2160
583 };
584
585
586 #define OFDM_PLCP_BITS  22
587 #define HT_L_STF        8
588 #define HT_L_LTF        8
589 #define HT_L_SIG        4
590 #define HT_SIG          8
591 #define HT_STF          4
592 #define HT_LTF(n)       ((n) * 4)
593
594 #define HT_RC_2_MCS(_rc)        ((_rc) & 0x1f)
595 #define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
596 #define IS_HT_RATE(_rc)         ( (_rc) & IEEE80211_RATE_MCS)
597
598 /*
599  * Calculate the transmit duration of an 11n frame.
600  */
601 uint32_t
602 ieee80211_compute_duration_ht(uint32_t frameLen, uint16_t rate,
603     int streams, int isht40, int isShortGI)
604 {
605         uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
606
607         KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
608         KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate));
609
610         if (isht40)
611                 bitsPerSymbol = ht40_bps[rate & 0x1f];
612         else
613                 bitsPerSymbol = ht20_bps[rate & 0x1f];
614         numBits = OFDM_PLCP_BITS + (frameLen << 3);
615         numSymbols = howmany(numBits, bitsPerSymbol);
616         if (isShortGI)
617                 txTime = ((numSymbols * 18) + 4) / 5;   /* 3.6us */
618         else
619                 txTime = numSymbols * 4;                /* 4us */
620         return txTime + HT_L_STF + HT_L_LTF +
621             HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
622 }
623
624 #undef  IS_HT_RATE
625 #undef  HT_RC_2_STREAMS
626 #undef  HT_RC_2_MCS
627 #undef  HT_LTF
628 #undef  HT_STF
629 #undef  HT_SIG
630 #undef  HT_L_SIG
631 #undef  HT_L_LTF
632 #undef  HT_L_STF
633 #undef  OFDM_PLCP_BITS