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
634