The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net80211/ieee80211_phy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    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

Cache object: 6982370b56f2c118eb3b1a25468b8991


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.