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  * 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

Cache object: 6d787237a63c5a6142753a443d6f7ee2


[ 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.