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

Cache object: e8f74e3380d50c4ea2e26812e4349812


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