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