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.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) 2001 Atsushi Onoe
    3  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * Alternatively, this software may be distributed under the terms of the
   18  * GNU General Public License ("GPL") version 2 as published by the Free
   19  * Software Foundation.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 /*
   37  * IEEE 802.11 generic handler
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h> 
   42 #include <sys/kernel.h>
   43  
   44 #include <sys/socket.h>
   45 
   46 #include <net/if.h>
   47 #include <net/if_media.h>
   48 #include <net/ethernet.h>
   49 
   50 #include <net80211/ieee80211_var.h>
   51 
   52 #include <net/bpf.h>
   53 
   54 const char *ieee80211_phymode_name[] = {
   55         "auto",         /* IEEE80211_MODE_AUTO */
   56         "11a",          /* IEEE80211_MODE_11A */
   57         "11b",          /* IEEE80211_MODE_11B */
   58         "11g",          /* IEEE80211_MODE_11G */
   59         "FH",           /* IEEE80211_MODE_FH */
   60         "turboA",       /* IEEE80211_MODE_TURBO_A */
   61         "turboG",       /* IEEE80211_MODE_TURBO_G */
   62 };
   63 
   64 /*
   65  * Default supported rates for 802.11 operation (in IEEE .5Mb units).
   66  */
   67 #define B(r)    ((r) | IEEE80211_RATE_BASIC)
   68 static const struct ieee80211_rateset ieee80211_rateset_11a =
   69         { 8, { B(12), 18, B(24), 36, B(48), 72, 96, 108 } };
   70 static const struct ieee80211_rateset ieee80211_rateset_half =
   71         { 8, { B(6), 9, B(12), 18, B(24), 36, 48, 54 } };
   72 static const struct ieee80211_rateset ieee80211_rateset_quarter =
   73         { 8, { B(3), 4, B(6), 9, B(12), 18, 24, 27 } };
   74 static const struct ieee80211_rateset ieee80211_rateset_11b =
   75         { 4, { B(2), B(4), B(11), B(22) } };
   76 /* NB: OFDM rates are handled specially based on mode */
   77 static const struct ieee80211_rateset ieee80211_rateset_11g =
   78         { 12, { B(2), B(4), B(11), B(22), 12, 18, 24, 36, 48, 72, 96, 108 } };
   79 #undef B
   80 
   81 /* list of all instances */
   82 SLIST_HEAD(ieee80211_list, ieee80211com);
   83 static struct ieee80211_list ieee80211_list =
   84         SLIST_HEAD_INITIALIZER(ieee80211_list);
   85 static u_int8_t ieee80211_vapmap[32];           /* enough for 256 */
   86 static struct mtx ieee80211_vap_mtx;
   87 MTX_SYSINIT(ieee80211, &ieee80211_vap_mtx, "net80211 instances", MTX_DEF);
   88 
   89 static void
   90 ieee80211_add_vap(struct ieee80211com *ic)
   91 {
   92 #define N(a)    (sizeof(a)/sizeof(a[0]))
   93         int i;
   94         u_int8_t b;
   95 
   96         mtx_lock(&ieee80211_vap_mtx);
   97         ic->ic_vap = 0;
   98         for (i = 0; i < N(ieee80211_vapmap) && ieee80211_vapmap[i] == 0xff; i++)
   99                 ic->ic_vap += NBBY;
  100         if (i == N(ieee80211_vapmap))
  101                 panic("vap table full");
  102         for (b = ieee80211_vapmap[i]; b & 1; b >>= 1)
  103                 ic->ic_vap++;
  104         setbit(ieee80211_vapmap, ic->ic_vap);
  105         SLIST_INSERT_HEAD(&ieee80211_list, ic, ic_next);
  106         mtx_unlock(&ieee80211_vap_mtx);
  107 #undef N
  108 }
  109 
  110 static void
  111 ieee80211_remove_vap(struct ieee80211com *ic)
  112 {
  113         mtx_lock(&ieee80211_vap_mtx);
  114         SLIST_REMOVE(&ieee80211_list, ic, ieee80211com, ic_next);
  115         KASSERT(ic->ic_vap < sizeof(ieee80211_vapmap)*NBBY,
  116                 ("invalid vap id %d", ic->ic_vap));
  117         KASSERT(isset(ieee80211_vapmap, ic->ic_vap),
  118                 ("vap id %d not allocated", ic->ic_vap));
  119         clrbit(ieee80211_vapmap, ic->ic_vap);
  120         mtx_unlock(&ieee80211_vap_mtx);
  121 }
  122 
  123 /*
  124  * Default reset method for use with the ioctl support.  This
  125  * method is invoked after any state change in the 802.11
  126  * layer that should be propagated to the hardware but not
  127  * require re-initialization of the 802.11 state machine (e.g
  128  * rescanning for an ap).  We always return ENETRESET which
  129  * should cause the driver to re-initialize the device. Drivers
  130  * can override this method to implement more optimized support.
  131  */
  132 static int
  133 ieee80211_default_reset(struct ifnet *ifp)
  134 {
  135         return ENETRESET;
  136 }
  137 
  138 /*
  139  * Fill in 802.11 available channel set, mark
  140  * all available channels as active, and pick
  141  * a default channel if not already specified.
  142  */
  143 static void
  144 ieee80211_chan_init(struct ieee80211com *ic)
  145 {
  146 #define DEFAULTRATES(m, def) do { \
  147         if ((ic->ic_modecaps & (1<<m)) && ic->ic_sup_rates[m].rs_nrates == 0) \
  148                 ic->ic_sup_rates[m] = def; \
  149 } while (0)
  150         struct ifnet *ifp = ic->ic_ifp;
  151         struct ieee80211_channel *c;
  152         int i;
  153 
  154         memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
  155         ic->ic_modecaps = 1<<IEEE80211_MODE_AUTO;
  156         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
  157                 c = &ic->ic_channels[i];
  158                 if (c->ic_flags) {
  159                         /*
  160                          * Verify driver passed us valid data.
  161                          */
  162                         if (i != ieee80211_chan2ieee(ic, c)) {
  163                                 if_printf(ifp, "bad channel ignored; "
  164                                         "freq %u flags %x number %u\n",
  165                                         c->ic_freq, c->ic_flags, i);
  166                                 c->ic_flags = 0;        /* NB: remove */
  167                                 continue;
  168                         }
  169                         setbit(ic->ic_chan_avail, i);
  170                         /*
  171                          * Identify mode capabilities.
  172                          */
  173                         if (IEEE80211_IS_CHAN_A(c))
  174                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11A;
  175                         if (IEEE80211_IS_CHAN_B(c))
  176                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11B;
  177                         if (IEEE80211_IS_CHAN_ANYG(c))
  178                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11G;
  179                         if (IEEE80211_IS_CHAN_FHSS(c))
  180                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_FH;
  181                         if (IEEE80211_IS_CHAN_T(c))
  182                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO_A;
  183                         if (IEEE80211_IS_CHAN_108G(c))
  184                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO_G;
  185                         if (ic->ic_curchan == NULL) {
  186                                 /* arbitrarily pick the first channel */
  187                                 ic->ic_curchan = &ic->ic_channels[i];
  188                         }
  189                 }
  190         }
  191 
  192         /* fillin well-known rate sets if driver has not specified */
  193         DEFAULTRATES(IEEE80211_MODE_11B,         ieee80211_rateset_11b);
  194         DEFAULTRATES(IEEE80211_MODE_11G,         ieee80211_rateset_11g);
  195         DEFAULTRATES(IEEE80211_MODE_11A,         ieee80211_rateset_11a);
  196         DEFAULTRATES(IEEE80211_MODE_TURBO_A,     ieee80211_rateset_11a);
  197         DEFAULTRATES(IEEE80211_MODE_TURBO_G,     ieee80211_rateset_11g);
  198 
  199         /*
  200          * Set auto mode to reset active channel state and any desired channel.
  201          */
  202         (void) ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
  203 #undef DEFAULTRATES
  204 }
  205 
  206 void
  207 ieee80211_ifattach(struct ieee80211com *ic)
  208 {
  209         struct ifnet *ifp = ic->ic_ifp;
  210 
  211         ether_ifattach(ifp, ic->ic_myaddr);
  212         bpfattach2(ifp, DLT_IEEE802_11,
  213             sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf);
  214 
  215         ieee80211_crypto_attach(ic);
  216 
  217         ic->ic_des_chan = IEEE80211_CHAN_ANYC;
  218         /*
  219          * Fill in 802.11 available channel set, mark all
  220          * available channels as active, and pick a default
  221          * channel if not already specified.
  222          */
  223         ieee80211_chan_init(ic);
  224 #if 0
  225         /*
  226          * Enable WME by default if we're capable.
  227          */
  228         if (ic->ic_caps & IEEE80211_C_WME)
  229                 ic->ic_flags |= IEEE80211_F_WME;
  230 #endif
  231         if (ic->ic_caps & IEEE80211_C_BURST)
  232                 ic->ic_flags |= IEEE80211_F_BURST;
  233 
  234         ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT;
  235         ic->ic_bmissthreshold = IEEE80211_HWBMISS_DEFAULT;
  236         ic->ic_dtim_period = IEEE80211_DTIM_DEFAULT;
  237         IEEE80211_BEACON_LOCK_INIT(ic, "beacon");
  238 
  239         ic->ic_lintval = ic->ic_bintval;
  240         ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX;
  241 
  242         ieee80211_node_attach(ic);
  243         ieee80211_proto_attach(ic);
  244 
  245         ieee80211_add_vap(ic);
  246 
  247         ieee80211_sysctl_attach(ic);            /* NB: requires ic_vap */
  248 
  249         /*
  250          * Install a default reset method for the ioctl support.
  251          * The driver is expected to fill this in before calling us.
  252          */
  253         if (ic->ic_reset == NULL)
  254                 ic->ic_reset = ieee80211_default_reset;
  255 }
  256 
  257 void
  258 ieee80211_ifdetach(struct ieee80211com *ic)
  259 {
  260         struct ifnet *ifp = ic->ic_ifp;
  261 
  262         ieee80211_remove_vap(ic);
  263 
  264         ieee80211_sysctl_detach(ic);
  265         /* NB: must be called before ieee80211_node_detach */
  266         ieee80211_proto_detach(ic);
  267         ieee80211_crypto_detach(ic);
  268         ieee80211_node_detach(ic);
  269         ifmedia_removeall(&ic->ic_media);
  270 
  271         IEEE80211_BEACON_LOCK_DESTROY(ic);
  272 
  273         bpfdetach(ifp);
  274         ether_ifdetach(ifp);
  275 }
  276 
  277 static __inline int
  278 mapgsm(u_int freq, u_int flags)
  279 {
  280         freq *= 10;
  281         if (flags & IEEE80211_CHAN_QUARTER)
  282                 freq += 5;
  283         else if (flags & IEEE80211_CHAN_HALF)
  284                 freq += 10;
  285         else
  286                 freq += 20;
  287         /* NB: there is no 907/20 wide but leave room */
  288         return (freq - 906*10) / 5;
  289 }
  290 
  291 static __inline int
  292 mappsb(u_int freq, u_int flags)
  293 {
  294         return 37 + ((freq * 10) + ((freq % 5) == 2 ? 5 : 0) - 49400) / 5;
  295 }
  296 
  297 /*
  298  * Convert MHz frequency to IEEE channel number.
  299  */
  300 int
  301 ieee80211_mhz2ieee(u_int freq, u_int flags)
  302 {
  303 #define IS_FREQ_IN_PSB(_freq) ((_freq) > 4940 && (_freq) < 4990)
  304         if (flags & IEEE80211_CHAN_GSM)
  305                 return mapgsm(freq, flags);
  306         if (flags & IEEE80211_CHAN_2GHZ) {      /* 2GHz band */
  307                 if (freq == 2484)
  308                         return 14;
  309                 if (freq < 2484)
  310                         return ((int) freq - 2407) / 5;
  311                 else
  312                         return 15 + ((freq - 2512) / 20);
  313         } else if (flags & IEEE80211_CHAN_5GHZ) {       /* 5Ghz band */
  314                 if (freq <= 5000) {
  315                         if (IS_FREQ_IN_PSB(freq))
  316                                 return mappsb(freq, flags);
  317                         return (freq - 4000) / 5;
  318                 } else
  319                         return (freq - 5000) / 5;
  320         } else {                                /* either, guess */
  321                 if (freq == 2484)
  322                         return 14;
  323                 if (freq < 2484) {
  324                         if (907 <= freq && freq <= 922)
  325                                 return mapgsm(freq, flags);
  326                         return ((int) freq - 2407) / 5;
  327                 }
  328                 if (freq < 5000) {
  329                         if (IS_FREQ_IN_PSB(freq))
  330                                 return mappsb(freq, flags);
  331                         else if (freq > 4900)
  332                                 return (freq - 4000) / 5;
  333                         else
  334                                 return 15 + ((freq - 2512) / 20);
  335                 }
  336                 return (freq - 5000) / 5;
  337         }
  338 #undef IS_FREQ_IN_PSB
  339 }
  340 
  341 /*
  342  * Convert channel to IEEE channel number.
  343  */
  344 int
  345 ieee80211_chan2ieee(struct ieee80211com *ic, const struct ieee80211_channel *c)
  346 {
  347         if (ic->ic_channels <= c && c <= &ic->ic_channels[IEEE80211_CHAN_MAX])
  348                 return c - ic->ic_channels;
  349         else if (c == IEEE80211_CHAN_ANYC)
  350                 return IEEE80211_CHAN_ANY;
  351         else if (c != NULL) {
  352                 if_printf(ic->ic_ifp, "invalid channel freq %u flags %x\n",
  353                         c->ic_freq, c->ic_flags);
  354                 return 0;               /* XXX */
  355         } else {
  356                 if_printf(ic->ic_ifp, "invalid channel (NULL)\n");
  357                 return 0;               /* XXX */
  358         }
  359 }
  360 
  361 /*
  362  * Convert IEEE channel number to MHz frequency.
  363  */
  364 u_int
  365 ieee80211_ieee2mhz(u_int chan, u_int flags)
  366 {
  367         if (flags & IEEE80211_CHAN_GSM)
  368                 return 907 + 5 * (chan / 10);
  369         if (flags & IEEE80211_CHAN_2GHZ) {      /* 2GHz band */
  370                 if (chan == 14)
  371                         return 2484;
  372                 if (chan < 14)
  373                         return 2407 + chan*5;
  374                 else
  375                         return 2512 + ((chan-15)*20);
  376         } else if (flags & IEEE80211_CHAN_5GHZ) {/* 5Ghz band */
  377                 if (flags & (IEEE80211_CHAN_HALF|IEEE80211_CHAN_QUARTER)) {
  378                         chan -= 37;
  379                         return 4940 + chan*5 + (chan % 5 ? 2 : 0);
  380                 }
  381                 return 5000 + (chan*5);
  382         } else {                                /* either, guess */
  383                 /* XXX can't distinguish PSB+GSM channels */
  384                 if (chan == 14)
  385                         return 2484;
  386                 if (chan < 14)                  /* 0-13 */
  387                         return 2407 + chan*5;
  388                 if (chan < 27)                  /* 15-26 */
  389                         return 2512 + ((chan-15)*20);
  390                 return 5000 + (chan*5);
  391         }
  392 }
  393 
  394 /*
  395  * Setup the media data structures according to the channel and
  396  * rate tables.  This must be called by the driver after
  397  * ieee80211_attach and before most anything else.
  398  */
  399 void
  400 ieee80211_media_init(struct ieee80211com *ic,
  401         ifm_change_cb_t media_change, ifm_stat_cb_t media_stat)
  402 {
  403 #define ADD(_ic, _s, _o) \
  404         ifmedia_add(&(_ic)->ic_media, \
  405                 IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL)
  406         struct ifnet *ifp = ic->ic_ifp;
  407         struct ifmediareq imr;
  408         int i, j, mode, rate, maxrate, mword, mopt, r;
  409         struct ieee80211_rateset *rs;
  410         struct ieee80211_rateset allrates;
  411 
  412         /* NB: this works because the structure is initialized to zero */
  413         if (LIST_EMPTY(&ic->ic_media.ifm_list)) {
  414                 /*
  415                  * Do late attach work that must wait for any subclass
  416                  * (i.e. driver) work such as overriding methods.
  417                  */
  418                 ieee80211_node_lateattach(ic);
  419         } else {
  420                 /*
  421                  * We are re-initializing the channel list; clear
  422                  * the existing media state as the media routines
  423                  * don't suppress duplicates.
  424                  */
  425                 ifmedia_removeall(&ic->ic_media);
  426                 ieee80211_chan_init(ic);
  427         }
  428 
  429         /*
  430          * Fill in media characteristics.
  431          */
  432         ifmedia_init(&ic->ic_media, 0, media_change, media_stat);
  433         maxrate = 0;
  434         memset(&allrates, 0, sizeof(allrates));
  435         for (mode = IEEE80211_MODE_AUTO; mode < IEEE80211_MODE_MAX; mode++) {
  436                 static const u_int mopts[] = { 
  437                         IFM_AUTO,
  438                         IFM_IEEE80211_11A,
  439                         IFM_IEEE80211_11B,
  440                         IFM_IEEE80211_11G,
  441                         IFM_IEEE80211_FH,
  442                         IFM_IEEE80211_11A | IFM_IEEE80211_TURBO,
  443                         IFM_IEEE80211_11G | IFM_IEEE80211_TURBO,
  444                 };
  445                 if ((ic->ic_modecaps & (1<<mode)) == 0)
  446                         continue;
  447                 mopt = mopts[mode];
  448                 ADD(ic, IFM_AUTO, mopt);        /* e.g. 11a auto */
  449                 if (ic->ic_caps & IEEE80211_C_IBSS)
  450                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC);
  451                 if (ic->ic_caps & IEEE80211_C_HOSTAP)
  452                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);
  453                 if (ic->ic_caps & IEEE80211_C_AHDEMO)
  454                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0);
  455                 if (ic->ic_caps & IEEE80211_C_MONITOR)
  456                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);
  457                 if (mode == IEEE80211_MODE_AUTO)
  458                         continue;
  459                 rs = &ic->ic_sup_rates[mode];
  460                 for (i = 0; i < rs->rs_nrates; i++) {
  461                         rate = rs->rs_rates[i];
  462                         mword = ieee80211_rate2media(ic, rate, mode);
  463                         if (mword == 0)
  464                                 continue;
  465                         ADD(ic, mword, mopt);
  466                         if (ic->ic_caps & IEEE80211_C_IBSS)
  467                                 ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC);
  468                         if (ic->ic_caps & IEEE80211_C_HOSTAP)
  469                                 ADD(ic, mword, mopt | IFM_IEEE80211_HOSTAP);
  470                         if (ic->ic_caps & IEEE80211_C_AHDEMO)
  471                                 ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0);
  472                         if (ic->ic_caps & IEEE80211_C_MONITOR)
  473                                 ADD(ic, mword, mopt | IFM_IEEE80211_MONITOR);
  474                         /*
  475                          * Add rate to the collection of all rates.
  476                          */
  477                         r = rate & IEEE80211_RATE_VAL;
  478                         for (j = 0; j < allrates.rs_nrates; j++)
  479                                 if (allrates.rs_rates[j] == r)
  480                                         break;
  481                         if (j == allrates.rs_nrates) {
  482                                 /* unique, add to the set */
  483                                 allrates.rs_rates[j] = r;
  484                                 allrates.rs_nrates++;
  485                         }
  486                         rate = (rate & IEEE80211_RATE_VAL) / 2;
  487                         if (rate > maxrate)
  488                                 maxrate = rate;
  489                 }
  490         }
  491         for (i = 0; i < allrates.rs_nrates; i++) {
  492                 mword = ieee80211_rate2media(ic, allrates.rs_rates[i],
  493                                 IEEE80211_MODE_AUTO);
  494                 if (mword == 0)
  495                         continue;
  496                 mword = IFM_SUBTYPE(mword);     /* remove media options */
  497                 ADD(ic, mword, 0);
  498                 if (ic->ic_caps & IEEE80211_C_IBSS)
  499                         ADD(ic, mword, IFM_IEEE80211_ADHOC);
  500                 if (ic->ic_caps & IEEE80211_C_HOSTAP)
  501                         ADD(ic, mword, IFM_IEEE80211_HOSTAP);
  502                 if (ic->ic_caps & IEEE80211_C_AHDEMO)
  503                         ADD(ic, mword, IFM_IEEE80211_ADHOC | IFM_FLAG0);
  504                 if (ic->ic_caps & IEEE80211_C_MONITOR)
  505                         ADD(ic, mword, IFM_IEEE80211_MONITOR);
  506         }
  507         ieee80211_media_status(ifp, &imr);
  508         ifmedia_set(&ic->ic_media, imr.ifm_active);
  509 
  510         if (maxrate)
  511                 ifp->if_baudrate = IF_Mbps(maxrate);
  512 #undef ADD
  513 }
  514 
  515 const struct ieee80211_rateset *
  516 ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *c)
  517 {
  518         enum ieee80211_phymode mode = ieee80211_chan2mode(ic, c);
  519 
  520         if (IEEE80211_IS_CHAN_HALF(c))
  521                 return &ieee80211_rateset_half;
  522         if (IEEE80211_IS_CHAN_QUARTER(c))
  523                 return &ieee80211_rateset_quarter;
  524         return &ic->ic_sup_rates[mode];
  525 }
  526 
  527 void
  528 ieee80211_announce(struct ieee80211com *ic)
  529 {
  530         struct ifnet *ifp = ic->ic_ifp;
  531         int i, mode, rate, mword;
  532         struct ieee80211_rateset *rs;
  533 
  534         for (mode = IEEE80211_MODE_11A; mode < IEEE80211_MODE_MAX; mode++) {
  535                 if ((ic->ic_modecaps & (1<<mode)) == 0)
  536                         continue;
  537                 if_printf(ifp, "%s rates: ", ieee80211_phymode_name[mode]);
  538                 rs = &ic->ic_sup_rates[mode];
  539                 for (i = 0; i < rs->rs_nrates; i++) {
  540                         rate = rs->rs_rates[i];
  541                         mword = ieee80211_rate2media(ic, rate, mode);
  542                         if (mword == 0)
  543                                 continue;
  544                         printf("%s%d%sMbps", (i != 0 ? " " : ""),
  545                             (rate & IEEE80211_RATE_VAL) / 2,
  546                             ((rate & 0x1) != 0 ? ".5" : ""));
  547                 }
  548                 printf("\n");
  549         }
  550 }
  551 
  552 static int
  553 findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate)
  554 {
  555 #define IEEERATE(_ic,_m,_i) \
  556         ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
  557         int i, nrates = ic->ic_sup_rates[mode].rs_nrates;
  558         for (i = 0; i < nrates; i++)
  559                 if (IEEERATE(ic, mode, i) == rate)
  560                         return i;
  561         return -1;
  562 #undef IEEERATE
  563 }
  564 
  565 /*
  566  * Find an instance by it's mac address.
  567  */
  568 struct ieee80211com *
  569 ieee80211_find_vap(const u_int8_t mac[IEEE80211_ADDR_LEN])
  570 {
  571         struct ieee80211com *ic;
  572 
  573         /* XXX lock */
  574         SLIST_FOREACH(ic, &ieee80211_list, ic_next)
  575                 if (IEEE80211_ADDR_EQ(mac, ic->ic_myaddr))
  576                         return ic;
  577         return NULL;
  578 }
  579 
  580 static struct ieee80211com *
  581 ieee80211_find_instance(struct ifnet *ifp)
  582 {
  583         struct ieee80211com *ic;
  584 
  585         /* XXX lock */
  586         /* XXX not right for multiple instances but works for now */
  587         SLIST_FOREACH(ic, &ieee80211_list, ic_next)
  588                 if (ic->ic_ifp == ifp)
  589                         return ic;
  590         return NULL;
  591 }
  592 
  593 /*
  594  * Handle a media change request.
  595  */
  596 int
  597 ieee80211_media_change(struct ifnet *ifp)
  598 {
  599         struct ieee80211com *ic;
  600         struct ifmedia_entry *ime;
  601         enum ieee80211_opmode newopmode;
  602         enum ieee80211_phymode newphymode;
  603         int i, j, newrate, error = 0;
  604 
  605         ic = ieee80211_find_instance(ifp);
  606         if (!ic) {
  607                 if_printf(ifp, "%s: no 802.11 instance!\n", __func__);
  608                 return EINVAL;
  609         }
  610         ime = ic->ic_media.ifm_cur;
  611         /*
  612          * First, identify the phy mode.
  613          */
  614         switch (IFM_MODE(ime->ifm_media)) {
  615         case IFM_IEEE80211_11A:
  616                 newphymode = IEEE80211_MODE_11A;
  617                 break;
  618         case IFM_IEEE80211_11B:
  619                 newphymode = IEEE80211_MODE_11B;
  620                 break;
  621         case IFM_IEEE80211_11G:
  622                 newphymode = IEEE80211_MODE_11G;
  623                 break;
  624         case IFM_IEEE80211_FH:
  625                 newphymode = IEEE80211_MODE_FH;
  626                 break;
  627         case IFM_AUTO:
  628                 newphymode = IEEE80211_MODE_AUTO;
  629                 break;
  630         default:
  631                 return EINVAL;
  632         }
  633         /*
  634          * Turbo mode is an ``option''.
  635          * XXX does not apply to AUTO
  636          */
  637         if (ime->ifm_media & IFM_IEEE80211_TURBO) {
  638                 if (newphymode == IEEE80211_MODE_11A)
  639                         newphymode = IEEE80211_MODE_TURBO_A;
  640                 else if (newphymode == IEEE80211_MODE_11G)
  641                         newphymode = IEEE80211_MODE_TURBO_G;
  642                 else
  643                         return EINVAL;
  644         }
  645         /*
  646          * Validate requested mode is available.
  647          */
  648         if ((ic->ic_modecaps & (1<<newphymode)) == 0)
  649                 return EINVAL;
  650 
  651         /*
  652          * Next, the fixed/variable rate.
  653          */
  654         i = -1;
  655         if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) {
  656                 /*
  657                  * Convert media subtype to rate.
  658                  */
  659                 newrate = ieee80211_media2rate(ime->ifm_media);
  660                 if (newrate == 0)
  661                         return EINVAL;
  662                 /*
  663                  * Check the rate table for the specified/current phy.
  664                  */
  665                 if (newphymode == IEEE80211_MODE_AUTO) {
  666                         /*
  667                          * In autoselect mode search for the rate.
  668                          */
  669                         for (j = IEEE80211_MODE_11A;
  670                              j < IEEE80211_MODE_MAX; j++) {
  671                                 if ((ic->ic_modecaps & (1<<j)) == 0)
  672                                         continue;
  673                                 i = findrate(ic, j, newrate);
  674                                 if (i != -1) {
  675                                         /* lock mode too */
  676                                         newphymode = j;
  677                                         break;
  678                                 }
  679                         }
  680                 } else {
  681                         i = findrate(ic, newphymode, newrate);
  682                 }
  683                 if (i == -1)                    /* mode/rate mismatch */
  684                         return EINVAL;
  685         }
  686         /* NB: defer rate setting to later */
  687 
  688         /*
  689          * Deduce new operating mode but don't install it just yet.
  690          */
  691         if ((ime->ifm_media & (IFM_IEEE80211_ADHOC|IFM_FLAG0)) ==
  692             (IFM_IEEE80211_ADHOC|IFM_FLAG0))
  693                 newopmode = IEEE80211_M_AHDEMO;
  694         else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
  695                 newopmode = IEEE80211_M_HOSTAP;
  696         else if (ime->ifm_media & IFM_IEEE80211_ADHOC)
  697                 newopmode = IEEE80211_M_IBSS;
  698         else if (ime->ifm_media & IFM_IEEE80211_MONITOR)
  699                 newopmode = IEEE80211_M_MONITOR;
  700         else
  701                 newopmode = IEEE80211_M_STA;
  702 
  703         /*
  704          * Autoselect doesn't make sense when operating as an AP.
  705          * If no phy mode has been selected, pick one and lock it
  706          * down so rate tables can be used in forming beacon frames
  707          * and the like.
  708          */
  709         if (newopmode == IEEE80211_M_HOSTAP &&
  710             newphymode == IEEE80211_MODE_AUTO) {
  711                 for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++)
  712                         if (ic->ic_modecaps & (1<<j)) {
  713                                 newphymode = j;
  714                                 break;
  715                         }
  716         }
  717 
  718         /*
  719          * Handle phy mode change.
  720          */
  721         if (ic->ic_curmode != newphymode) {             /* change phy mode */
  722                 error = ieee80211_setmode(ic, newphymode);
  723                 if (error != 0)
  724                         return error;
  725                 error = ENETRESET;
  726         }
  727 
  728         /*
  729          * Committed to changes, install the rate setting.
  730          */
  731         if (ic->ic_fixed_rate != i) {
  732                 ic->ic_fixed_rate = i;                  /* set fixed tx rate */
  733                 error = ENETRESET;
  734         }
  735 
  736         /*
  737          * Handle operating mode change.
  738          */
  739         if (ic->ic_opmode != newopmode) {
  740                 ic->ic_opmode = newopmode;
  741                 switch (newopmode) {
  742                 case IEEE80211_M_AHDEMO:
  743                 case IEEE80211_M_HOSTAP:
  744                 case IEEE80211_M_STA:
  745                 case IEEE80211_M_MONITOR:
  746                         ic->ic_flags &= ~IEEE80211_F_IBSSON;
  747                         break;
  748                 case IEEE80211_M_IBSS:
  749                         ic->ic_flags |= IEEE80211_F_IBSSON;
  750                         break;
  751                 }
  752                 /*
  753                  * Yech, slot time may change depending on the
  754                  * operating mode so reset it to be sure everything
  755                  * is setup appropriately.
  756                  */
  757                 ieee80211_reset_erp(ic);
  758                 ieee80211_wme_initparams(ic);   /* after opmode change */
  759                 error = ENETRESET;
  760         }
  761 #ifdef notdef
  762         if (error == 0)
  763                 ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);
  764 #endif
  765         return error;
  766 }
  767 
  768 void
  769 ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
  770 {
  771         struct ieee80211com *ic;
  772         const struct ieee80211_rateset *rs;
  773 
  774         ic = ieee80211_find_instance(ifp);
  775         if (!ic) {
  776                 if_printf(ifp, "%s: no 802.11 instance!\n", __func__);
  777                 return;
  778         }
  779         imr->ifm_status = IFM_AVALID;
  780         imr->ifm_active = IFM_IEEE80211;
  781         if (ic->ic_state == IEEE80211_S_RUN)
  782                 imr->ifm_status |= IFM_ACTIVE;
  783         /*
  784          * Calculate a current rate if possible.
  785          */
  786         if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
  787                 /*
  788                  * A fixed rate is set, report that.
  789                  */
  790                 rs = ieee80211_get_suprates(ic, ic->ic_curchan);
  791                 imr->ifm_active |= ieee80211_rate2media(ic,
  792                         rs->rs_rates[ic->ic_fixed_rate], ic->ic_curmode);
  793         } else if (ic->ic_opmode == IEEE80211_M_STA) {
  794                 /*
  795                  * In station mode report the current transmit rate.
  796                  */
  797                 rs = &ic->ic_bss->ni_rates;
  798                 imr->ifm_active |= ieee80211_rate2media(ic,
  799                         rs->rs_rates[ic->ic_bss->ni_txrate], ic->ic_curmode);
  800         } else
  801                 imr->ifm_active |= IFM_AUTO;
  802         switch (ic->ic_opmode) {
  803         case IEEE80211_M_STA:
  804                 break;
  805         case IEEE80211_M_IBSS:
  806                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
  807                 break;
  808         case IEEE80211_M_AHDEMO:
  809                 /* should not come here */
  810                 break;
  811         case IEEE80211_M_HOSTAP:
  812                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
  813                 break;
  814         case IEEE80211_M_MONITOR:
  815                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
  816                 break;
  817         }
  818         switch (ic->ic_curmode) {
  819         case IEEE80211_MODE_11A:
  820                 imr->ifm_active |= IFM_IEEE80211_11A;
  821                 break;
  822         case IEEE80211_MODE_11B:
  823                 imr->ifm_active |= IFM_IEEE80211_11B;
  824                 break;
  825         case IEEE80211_MODE_11G:
  826                 imr->ifm_active |= IFM_IEEE80211_11G;
  827                 break;
  828         case IEEE80211_MODE_FH:
  829                 imr->ifm_active |= IFM_IEEE80211_FH;
  830                 break;
  831         case IEEE80211_MODE_TURBO_A:
  832                 imr->ifm_active |= IFM_IEEE80211_11A
  833                                 |  IFM_IEEE80211_TURBO;
  834                 break;
  835         case IEEE80211_MODE_TURBO_G:
  836                 imr->ifm_active |= IFM_IEEE80211_11G
  837                                 |  IFM_IEEE80211_TURBO;
  838                 break;
  839         }
  840 }
  841 
  842 void
  843 ieee80211_watchdog(struct ieee80211com *ic)
  844 {
  845         struct ieee80211_node_table *nt;
  846         int need_inact_timer = 0;
  847 
  848         if (ic->ic_state != IEEE80211_S_INIT) {
  849                 if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0)
  850                         ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
  851                 nt = &ic->ic_scan;
  852                 if (nt->nt_inact_timer) {
  853                         if (--nt->nt_inact_timer == 0)
  854                                 nt->nt_timeout(nt);
  855                         need_inact_timer += nt->nt_inact_timer;
  856                 }
  857                 nt = &ic->ic_sta;
  858                 if (nt->nt_inact_timer) {
  859                         if (--nt->nt_inact_timer == 0)
  860                                 nt->nt_timeout(nt);
  861                         need_inact_timer += nt->nt_inact_timer;
  862                 }
  863         }
  864         if (ic->ic_mgt_timer != 0 || need_inact_timer)
  865                 ic->ic_ifp->if_timer = 1;
  866 }
  867 
  868 /*
  869  * Set the current phy mode and recalculate the active channel
  870  * set based on the available channels for this mode.  Also
  871  * select a new default/current channel if the current one is
  872  * inappropriate for this mode.
  873  */
  874 int
  875 ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode)
  876 {
  877 #define N(a)    (sizeof(a) / sizeof(a[0]))
  878         static const u_int chanflags[] = {
  879                 0,                      /* IEEE80211_MODE_AUTO */
  880                 IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
  881                 IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
  882                 IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
  883                 IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */
  884                 IEEE80211_CHAN_T,       /* IEEE80211_MODE_TURBO_A */
  885                 IEEE80211_CHAN_108G,    /* IEEE80211_MODE_TURBO_G */
  886         };
  887         struct ieee80211_channel *c;
  888         u_int modeflags;
  889         int i;
  890 
  891         /* validate new mode */
  892         if ((ic->ic_modecaps & (1<<mode)) == 0) {
  893                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
  894                         "%s: mode %u not supported (caps 0x%x)\n",
  895                         __func__, mode, ic->ic_modecaps);
  896                 return EINVAL;
  897         }
  898 
  899         /*
  900          * Verify at least one channel is present in the available
  901          * channel list before committing to the new mode.
  902          */
  903         KASSERT(mode < N(chanflags), ("Unexpected mode %u", mode));
  904         modeflags = chanflags[mode];
  905         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
  906                 c = &ic->ic_channels[i];
  907                 if (c->ic_flags == 0)
  908                         continue;
  909                 if (mode == IEEE80211_MODE_AUTO) {
  910                         /* ignore static turbo channels for autoselect */
  911                         if (!IEEE80211_IS_CHAN_T(c))
  912                                 break;
  913                 } else {
  914                         if ((c->ic_flags & modeflags) == modeflags)
  915                                 break;
  916                 }
  917         }
  918         if (i > IEEE80211_CHAN_MAX) {
  919                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
  920                         "%s: no channels found for mode %u\n", __func__, mode);
  921                 return EINVAL;
  922         }
  923 
  924         /*
  925          * Calculate the active channel set.
  926          */
  927         memset(ic->ic_chan_active, 0, sizeof(ic->ic_chan_active));
  928         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
  929                 c = &ic->ic_channels[i];
  930                 if (c->ic_flags == 0)
  931                         continue;
  932                 if (mode == IEEE80211_MODE_AUTO) {
  933                         /* take anything but static turbo channels */
  934                         if (!IEEE80211_IS_CHAN_T(c))
  935                                 setbit(ic->ic_chan_active, i);
  936                 } else {
  937                         if ((c->ic_flags & modeflags) == modeflags)
  938                                 setbit(ic->ic_chan_active, i);
  939                 }
  940         }
  941         /*
  942          * If no current/default channel is setup or the current
  943          * channel is wrong for the mode then pick the first
  944          * available channel from the active list.  This is likely
  945          * not the right one.
  946          */
  947         if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ic->ic_curchan))) {
  948                 ic->ic_curchan = NULL;
  949                 for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
  950                         if (isset(ic->ic_chan_active, i)) {
  951                                 ic->ic_curchan = &ic->ic_channels[i];
  952                                 break;
  953                         }
  954                 KASSERT(ic->ic_curchan != NULL, ("no current channel"));
  955         }
  956         if (ic->ic_ibss_chan == NULL ||
  957             isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ic->ic_ibss_chan)))
  958                 ic->ic_ibss_chan = ic->ic_curchan;
  959         /*
  960          * If the desired channel is set but no longer valid then reset it.
  961          */
  962         if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
  963             isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ic->ic_des_chan)))
  964                 ic->ic_des_chan = IEEE80211_CHAN_ANYC;
  965 
  966         /*
  967          * Adjust basic rates in 11b/11g supported rate set.
  968          * Note that if operating on a hal/quarter rate channel
  969          * this is a noop as those rates sets are different
  970          * and used instead.
  971          */
  972         if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11B)
  973                 ieee80211_set11gbasicrates(&ic->ic_sup_rates[mode], mode);
  974 
  975         /*
  976          * Setup an initial rate set according to the
  977          * current/default channel selected above.  This
  978          * will be changed when scanning but must exist
  979          * now so driver have a consistent state of ic_ibss_chan.
  980          */
  981         if (ic->ic_bss != NULL) /* NB: can be called before lateattach */
  982                 ic->ic_bss->ni_rates = ic->ic_sup_rates[mode];
  983 
  984         ic->ic_curmode = mode;
  985         ieee80211_reset_erp(ic);        /* reset ERP state */
  986         ieee80211_wme_initparams(ic);   /* reset WME stat */
  987 
  988         return 0;
  989 #undef N
  990 }
  991 
  992 /*
  993  * Return the phy mode for with the specified channel so the
  994  * caller can select a rate set.  This is problematic for channels
  995  * where multiple operating modes are possible (e.g. 11g+11b).
  996  * In those cases we defer to the current operating mode when set.
  997  */
  998 enum ieee80211_phymode
  999 ieee80211_chan2mode(struct ieee80211com *ic, const struct ieee80211_channel *chan)
 1000 {
 1001         if (IEEE80211_IS_CHAN_T(chan)) {
 1002                 return IEEE80211_MODE_TURBO_A;
 1003         } else if (IEEE80211_IS_CHAN_5GHZ(chan)) {
 1004                 return IEEE80211_MODE_11A;
 1005         } else if (IEEE80211_IS_CHAN_FHSS(chan))
 1006                 return IEEE80211_MODE_FH;
 1007         else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN)) {
 1008                 /*
 1009                  * This assumes all 11g channels are also usable
 1010                  * for 11b, which is currently true.
 1011                  */
 1012                 if (ic->ic_curmode == IEEE80211_MODE_TURBO_G)
 1013                         return IEEE80211_MODE_TURBO_G;
 1014                 if (ic->ic_curmode == IEEE80211_MODE_11B)
 1015                         return IEEE80211_MODE_11B;
 1016                 return IEEE80211_MODE_11G;
 1017         } else
 1018                 return IEEE80211_MODE_11B;
 1019 }
 1020 
 1021 /*
 1022  * convert IEEE80211 rate value to ifmedia subtype.
 1023  * ieee80211 rate is in unit of 0.5Mbps.
 1024  */
 1025 int
 1026 ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode mode)
 1027 {
 1028 #define N(a)    (sizeof(a) / sizeof(a[0]))
 1029         static const struct {
 1030                 u_int   m;      /* rate + mode */
 1031                 u_int   r;      /* if_media rate */
 1032         } rates[] = {
 1033                 {   2 | IFM_IEEE80211_FH, IFM_IEEE80211_FH1 },
 1034                 {   4 | IFM_IEEE80211_FH, IFM_IEEE80211_FH2 },
 1035                 {   2 | IFM_IEEE80211_11B, IFM_IEEE80211_DS1 },
 1036                 {   4 | IFM_IEEE80211_11B, IFM_IEEE80211_DS2 },
 1037                 {  11 | IFM_IEEE80211_11B, IFM_IEEE80211_DS5 },
 1038                 {  22 | IFM_IEEE80211_11B, IFM_IEEE80211_DS11 },
 1039                 {  44 | IFM_IEEE80211_11B, IFM_IEEE80211_DS22 },
 1040                 {  12 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM6 },
 1041                 {  18 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM9 },
 1042                 {  24 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM12 },
 1043                 {  36 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM18 },
 1044                 {  48 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM24 },
 1045                 {  72 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM36 },
 1046                 {  96 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM48 },
 1047                 { 108 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM54 },
 1048                 {   2 | IFM_IEEE80211_11G, IFM_IEEE80211_DS1 },
 1049                 {   4 | IFM_IEEE80211_11G, IFM_IEEE80211_DS2 },
 1050                 {  11 | IFM_IEEE80211_11G, IFM_IEEE80211_DS5 },
 1051                 {  22 | IFM_IEEE80211_11G, IFM_IEEE80211_DS11 },
 1052                 {  12 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM6 },
 1053                 {  18 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM9 },
 1054                 {  24 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM12 },
 1055                 {  36 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM18 },
 1056                 {  48 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM24 },
 1057                 {  72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 },
 1058                 {  96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 },
 1059                 { 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 },
 1060                 {   6 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM3 },
 1061                 {   9 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM4 },
 1062                 {  54 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM27 },
 1063                 /* NB: OFDM72 doesn't realy exist so we don't handle it */
 1064         };
 1065         u_int mask, i;
 1066 
 1067         mask = rate & IEEE80211_RATE_VAL;
 1068         switch (mode) {
 1069         case IEEE80211_MODE_11A:
 1070         case IEEE80211_MODE_TURBO_A:
 1071                 mask |= IFM_IEEE80211_11A;
 1072                 break;
 1073         case IEEE80211_MODE_11B:
 1074                 mask |= IFM_IEEE80211_11B;
 1075                 break;
 1076         case IEEE80211_MODE_FH:
 1077                 mask |= IFM_IEEE80211_FH;
 1078                 break;
 1079         case IEEE80211_MODE_AUTO:
 1080                 /* NB: ic may be NULL for some drivers */
 1081                 if (ic && ic->ic_phytype == IEEE80211_T_FH) {
 1082                         mask |= IFM_IEEE80211_FH;
 1083                         break;
 1084                 }
 1085                 /* NB: hack, 11g matches both 11b+11a rates */
 1086                 /* fall thru... */
 1087         case IEEE80211_MODE_11G:
 1088         case IEEE80211_MODE_TURBO_G:
 1089                 mask |= IFM_IEEE80211_11G;
 1090                 break;
 1091         }
 1092         for (i = 0; i < N(rates); i++)
 1093                 if (rates[i].m == mask)
 1094                         return rates[i].r;
 1095         return IFM_AUTO;
 1096 #undef N
 1097 }
 1098 
 1099 int
 1100 ieee80211_media2rate(int mword)
 1101 {
 1102 #define N(a)    (sizeof(a) / sizeof(a[0]))
 1103         static const int ieeerates[] = {
 1104                 -1,             /* IFM_AUTO */
 1105                 0,              /* IFM_MANUAL */
 1106                 0,              /* IFM_NONE */
 1107                 2,              /* IFM_IEEE80211_FH1 */
 1108                 4,              /* IFM_IEEE80211_FH2 */
 1109                 2,              /* IFM_IEEE80211_DS1 */
 1110                 4,              /* IFM_IEEE80211_DS2 */
 1111                 11,             /* IFM_IEEE80211_DS5 */
 1112                 22,             /* IFM_IEEE80211_DS11 */
 1113                 44,             /* IFM_IEEE80211_DS22 */
 1114                 12,             /* IFM_IEEE80211_OFDM6 */
 1115                 18,             /* IFM_IEEE80211_OFDM9 */
 1116                 24,             /* IFM_IEEE80211_OFDM12 */
 1117                 36,             /* IFM_IEEE80211_OFDM18 */
 1118                 48,             /* IFM_IEEE80211_OFDM24 */
 1119                 72,             /* IFM_IEEE80211_OFDM36 */
 1120                 96,             /* IFM_IEEE80211_OFDM48 */
 1121                 108,            /* IFM_IEEE80211_OFDM54 */
 1122                 144,            /* IFM_IEEE80211_OFDM72 */
 1123                 0,              /* IFM_IEEE80211_DS354k */
 1124                 0,              /* IFM_IEEE80211_DS512k */
 1125                 6,              /* IFM_IEEE80211_OFDM3 */
 1126                 9,              /* IFM_IEEE80211_OFDM4 */
 1127                 54,             /* IFM_IEEE80211_OFDM27 */
 1128         };
 1129         return IFM_SUBTYPE(mword) < N(ieeerates) ?
 1130                 ieeerates[IFM_SUBTYPE(mword)] : 0;
 1131 #undef N
 1132 }

Cache object: 884f6b62b8f44ccfdfdd506ec7d5761b


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