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

Cache object: 099833709a8cb9f50725cca7a889fc7c


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