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