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