Home | History | Annotate | Download | only in net80211
      1   3147  xc151355 /*
      2  10266    Quaker  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
      3   3147  xc151355  * Use is subject to license terms.
      4   3147  xc151355  */
      5   3147  xc151355 
      6   3147  xc151355 /*
      7   3147  xc151355  * Copyright (c) 2001 Atsushi Onoe
      8   3147  xc151355  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
      9   3147  xc151355  * All rights reserved.
     10   3147  xc151355  *
     11   3147  xc151355  * Redistribution and use in source and binary forms, with or without
     12   3147  xc151355  * modification, are permitted provided that the following conditions
     13   3147  xc151355  * are met:
     14   3147  xc151355  * 1. Redistributions of source code must retain the above copyright
     15   3147  xc151355  *    notice, this list of conditions and the following disclaimer.
     16   3147  xc151355  * 2. Redistributions in binary form must reproduce the above copyright
     17   3147  xc151355  *    notice, this list of conditions and the following disclaimer in the
     18   3147  xc151355  *    documentation and/or other materials provided with the distribution.
     19   3147  xc151355  * 3. The name of the author may not be used to endorse or promote products
     20   3147  xc151355  *    derived from this software without specific prior written permission.
     21   3147  xc151355  *
     22   3147  xc151355  * Alternatively, this software may be distributed under the terms of the
     23   3147  xc151355  * GNU General Public License ("GPL") version 2 as published by the Free
     24   3147  xc151355  * Software Foundation.
     25   3147  xc151355  *
     26   3147  xc151355  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     27   3147  xc151355  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     28   3147  xc151355  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     29   3147  xc151355  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     30   3147  xc151355  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     31   3147  xc151355  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     32   3147  xc151355  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     33   3147  xc151355  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     34   3147  xc151355  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     35   3147  xc151355  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     36   3147  xc151355  */
     37   3147  xc151355 
     38   3147  xc151355 /*
     39   3147  xc151355  * IEEE 802.11 generic handler
     40   3147  xc151355  */
     41   3147  xc151355 
     42   3147  xc151355 #include <sys/param.h>
     43   3147  xc151355 #include <sys/types.h>
     44   3147  xc151355 #include <sys/cmn_err.h>
     45   3147  xc151355 #include <sys/modctl.h>
     46   4126  zf162725 #include <sys/stropts.h>
     47   4126  zf162725 #include <sys/door.h>
     48   8275      Eric #include <sys/mac_provider.h>
     49   3147  xc151355 #include "net80211_impl.h"
     50   3147  xc151355 
     51   3147  xc151355 uint32_t ieee80211_debug = 0x0;	/* debug msg flags */
     52   3147  xc151355 
     53   3147  xc151355 const char *ieee80211_phymode_name[] = {
     54   3147  xc151355 	"auto",		/* IEEE80211_MODE_AUTO */
     55   3147  xc151355 	"11a",		/* IEEE80211_MODE_11A */
     56   3147  xc151355 	"11b",		/* IEEE80211_MODE_11B */
     57   3147  xc151355 	"11g",		/* IEEE80211_MODE_11G */
     58   3147  xc151355 	"FH",		/* IEEE80211_MODE_FH */
     59   3147  xc151355 	"turboA",	/* IEEE80211_MODE_TURBO_A */
     60   3147  xc151355 	"turboG",	/* IEEE80211_MODE_TURBO_G */
     61  10266    Quaker 	"sturboA",	/* IEEE80211_MODE_STURBO_A */
     62  10266    Quaker 	"11na",		/* IEEE80211_MODE_11NA */
     63  10266    Quaker 	"11ng",		/* IEEE80211_MODE_11NG */
     64   3147  xc151355 };
     65   3147  xc151355 
     66   3147  xc151355 #define	IEEE80211_DPRINT(_level, _fmt)	do {	\
     67   3147  xc151355 		_NOTE(CONSTCOND)		\
     68   3147  xc151355 		va_list ap;			\
     69   3147  xc151355 		va_start(ap, (_fmt));		\
     70   3147  xc151355 		vcmn_err((_level), (_fmt), ap);	\
     71   3147  xc151355 		va_end(ap);			\
     72   3147  xc151355 		_NOTE(CONSTCOND)		\
     73   3147  xc151355 	} while (0)
     74   3147  xc151355 
     75   3147  xc151355 /*
     76   3147  xc151355  * Print error messages
     77   3147  xc151355  */
     78   3147  xc151355 void
     79   3147  xc151355 ieee80211_err(const int8_t *fmt, ...)
     80   3147  xc151355 {
     81   3147  xc151355 	IEEE80211_DPRINT(CE_WARN, fmt);
     82   3147  xc151355 }
     83   3147  xc151355 
     84   3147  xc151355 /*
     85   3147  xc151355  * Print debug messages
     86   3147  xc151355  */
     87   3147  xc151355 void
     88   3147  xc151355 ieee80211_dbg(uint32_t flag, const int8_t *fmt, ...)
     89   3147  xc151355 {
     90   3147  xc151355 	if (flag & ieee80211_debug)
     91   3147  xc151355 		IEEE80211_DPRINT(CE_CONT, fmt);
     92   4126  zf162725 }
     93   4126  zf162725 
     94   4126  zf162725 /*
     95   4126  zf162725  * Alloc memory, and save the size
     96   4126  zf162725  */
     97   4126  zf162725 void *
     98   4126  zf162725 ieee80211_malloc(size_t size)
     99   4126  zf162725 {
    100   4126  zf162725 	void *p = kmem_zalloc((size + 4), KM_SLEEP);
    101   4126  zf162725 	*(int *)p = size;
    102   4126  zf162725 	p = (char *)p + 4;
    103   4126  zf162725 
    104   4126  zf162725 	return (p);
    105   4126  zf162725 }
    106   4126  zf162725 
    107   4126  zf162725 void
    108   4126  zf162725 ieee80211_free(void *p)
    109   4126  zf162725 {
    110   4126  zf162725 	void *tp = (char *)p - 4;
    111   4126  zf162725 	kmem_free((char *)p - 4, *(int *)tp + 4);
    112   4126  zf162725 }
    113   4126  zf162725 
    114   4126  zf162725 void
    115   4126  zf162725 ieee80211_mac_update(ieee80211com_t *ic)
    116   4126  zf162725 {
    117   4126  zf162725 	wifi_data_t wd = { 0 };
    118   4126  zf162725 	ieee80211_node_t *in;
    119   4126  zf162725 
    120   4126  zf162725 	/*
    121   4126  zf162725 	 * We can send data now; update the fastpath with our
    122   4126  zf162725 	 * current associated BSSID and other relevant settings.
    123   4126  zf162725 	 */
    124   4126  zf162725 	in = ic->ic_bss;
    125   4126  zf162725 	wd.wd_secalloc = ieee80211_crypto_getciphertype(ic);
    126   4126  zf162725 	wd.wd_opmode = ic->ic_opmode;
    127   4126  zf162725 	IEEE80211_ADDR_COPY(wd.wd_bssid, in->in_bssid);
    128  10266    Quaker 	wd.wd_qospad = 0;
    129  10266    Quaker 	if (in->in_flags & (IEEE80211_NODE_QOS|IEEE80211_NODE_HT)) {
    130  10266    Quaker 		wd.wd_qospad = 2;
    131  10266    Quaker 		if (ic->ic_flags & IEEE80211_F_DATAPAD)
    132  10266    Quaker 			wd.wd_qospad = roundup(wd.wd_qospad, sizeof (uint32_t));
    133  10266    Quaker 	}
    134   4126  zf162725 	(void) mac_pdata_update(ic->ic_mach, &wd, sizeof (wd));
    135   4126  zf162725 	mac_tx_update(ic->ic_mach);
    136   4126  zf162725 	ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_mac_update"
    137   4126  zf162725 	    "(cipher = %d)\n", wd.wd_secalloc);
    138   4126  zf162725 }
    139   4126  zf162725 
    140   4126  zf162725 /*
    141   4126  zf162725  * ieee80211_event_thread
    142   4126  zf162725  * open door of wpa, send event to wpad service
    143   4126  zf162725  */
    144   4126  zf162725 static void
    145   4126  zf162725 ieee80211_event_thread(void *arg)
    146   4126  zf162725 {
    147   4126  zf162725 	ieee80211com_t *ic = arg;
    148   4126  zf162725 	door_handle_t event_door = NULL;	/* Door for upcalls */
    149   4126  zf162725 	wl_events_t ev;
    150   4126  zf162725 	door_arg_t darg;
    151   4126  zf162725 
    152   4126  zf162725 	mutex_enter(&ic->ic_doorlock);
    153   4126  zf162725 
    154   4126  zf162725 	ev.event = ic->ic_eventq[ic->ic_evq_head];
    155   4126  zf162725 	ic->ic_evq_head ++;
    156   4126  zf162725 	if (ic->ic_evq_head >= MAX_EVENT)
    157   4126  zf162725 		ic->ic_evq_head = 0;
    158   4126  zf162725 
    159   4126  zf162725 	ieee80211_dbg(IEEE80211_MSG_DEBUG, "ieee80211_event(%d)\n", ev.event);
    160   4126  zf162725 	/*
    161   4126  zf162725 	 * Locate the door used for upcalls
    162   4126  zf162725 	 */
    163   4126  zf162725 	if (door_ki_open(ic->ic_wpadoor, &event_door) != 0) {
    164   4126  zf162725 		ieee80211_err("ieee80211_event: door_ki_open(%s) failed\n",
    165   4126  zf162725 		    ic->ic_wpadoor);
    166   4126  zf162725 		goto out;
    167   4126  zf162725 	}
    168   4126  zf162725 
    169   4126  zf162725 	darg.data_ptr = (char *)&ev;
    170   4126  zf162725 	darg.data_size = sizeof (wl_events_t);
    171   4126  zf162725 	darg.desc_ptr = NULL;
    172   4126  zf162725 	darg.desc_num = 0;
    173   4126  zf162725 	darg.rbuf = NULL;
    174   4126  zf162725 	darg.rsize = 0;
    175   4126  zf162725 
    176   6997   jwadams 	if (door_ki_upcall_limited(event_door, &darg, NULL, SIZE_MAX, 0) != 0) {
    177   4126  zf162725 		ieee80211_err("ieee80211_event: door_ki_upcall() failed\n");
    178   4126  zf162725 	}
    179   4126  zf162725 
    180   4126  zf162725 	if (event_door) {	/* release our hold (if any) */
    181   4126  zf162725 		door_ki_rele(event_door);
    182   4126  zf162725 	}
    183   4126  zf162725 
    184   4126  zf162725 out:
    185   4126  zf162725 	mutex_exit(&ic->ic_doorlock);
    186   4126  zf162725 }
    187   4126  zf162725 
    188   4126  zf162725 /*
    189   4126  zf162725  * Notify state transition event message to WPA daemon
    190   4126  zf162725  */
    191   4126  zf162725 void
    192   4126  zf162725 ieee80211_notify(ieee80211com_t *ic, wpa_event_type event)
    193   4126  zf162725 {
    194   4126  zf162725 	if ((ic->ic_flags & IEEE80211_F_WPA) == 0)
    195   4126  zf162725 		return;		/* Not running on WPA mode */
    196   4126  zf162725 
    197   4126  zf162725 	ic->ic_eventq[ic->ic_evq_tail] = event;
    198   4126  zf162725 	ic->ic_evq_tail ++;
    199   4126  zf162725 	if (ic->ic_evq_tail >= MAX_EVENT) ic->ic_evq_tail = 0;
    200   4126  zf162725 
    201   4126  zf162725 	/* async */
    202   4126  zf162725 	(void) timeout(ieee80211_event_thread, (void *)ic, 0);
    203   3147  xc151355 }
    204   3147  xc151355 
    205   3147  xc151355 /*
    206   5296  zf162725  * Register WPA door
    207   5296  zf162725  */
    208   5296  zf162725 void
    209   5296  zf162725 ieee80211_register_door(ieee80211com_t *ic, const char *drvname, int inst)
    210   5296  zf162725 {
    211   5296  zf162725 	(void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d",
    212   5296  zf162725 	    WPA_DOOR, drvname, inst);
    213   5296  zf162725 }
    214   5296  zf162725 
    215   5296  zf162725 /*
    216   3147  xc151355  * Default reset method for use with the ioctl support.  This
    217   3147  xc151355  * method is invoked after any state change in the 802.11
    218   3147  xc151355  * layer that should be propagated to the hardware but not
    219   3147  xc151355  * require re-initialization of the 802.11 state machine (e.g
    220   3147  xc151355  * rescanning for an ap).  We always return ENETRESET which
    221   3147  xc151355  * should cause the driver to re-initialize the device. Drivers
    222   3147  xc151355  * can override this method to implement more optimized support.
    223   3147  xc151355  */
    224   3147  xc151355 /* ARGSUSED */
    225   3147  xc151355 static int
    226   3147  xc151355 ieee80211_default_reset(ieee80211com_t *ic)
    227   3147  xc151355 {
    228   3147  xc151355 	return (ENETRESET);
    229   3147  xc151355 }
    230   3147  xc151355 
    231   3147  xc151355 /*
    232   3147  xc151355  * Convert channel to IEEE channel number.
    233   3147  xc151355  */
    234   3147  xc151355 uint32_t
    235   3147  xc151355 ieee80211_chan2ieee(ieee80211com_t *ic, struct ieee80211_channel *ch)
    236   3147  xc151355 {
    237   3147  xc151355 	if ((ic->ic_sup_channels <= ch) &&
    238   3147  xc151355 	    (ch <= &ic->ic_sup_channels[IEEE80211_CHAN_MAX])) {
    239   3147  xc151355 		return (ch - ic->ic_sup_channels);
    240   3147  xc151355 	} else if (ch == IEEE80211_CHAN_ANYC) {
    241   3147  xc151355 		return (IEEE80211_CHAN_ANY);
    242   3147  xc151355 	} else if (ch != NULL) {
    243   3147  xc151355 		ieee80211_err("invalid channel freq %u flags %x\n",
    244   5296  zf162725 		    ch->ich_freq, ch->ich_flags);
    245   3147  xc151355 		return (0);
    246   3147  xc151355 	}
    247   3147  xc151355 	ieee80211_err("invalid channel (NULL)\n");	/* ch == NULL */
    248   3147  xc151355 	return (0);
    249   3147  xc151355 }
    250   3147  xc151355 
    251   3147  xc151355 /*
    252   3147  xc151355  * Convert IEEE channel number to MHz frequency.
    253   3147  xc151355  *    chan    IEEE channel number
    254   3147  xc151355  *    flags   specify whether the frequency is in the 2GHz ISM
    255   3147  xc151355  *            band or the 5GHz band
    256   3147  xc151355  *
    257   3147  xc151355  * 802.11b 2GHz: 14 channels, each 5 MHz wide. Channel 1 is placed
    258   3147  xc151355  * at 2.412 GHz, channel 2 at 2.417 GHz, and so on up to channel 13
    259   3147  xc151355  * at 2.472 GHz. Channel 14 was defined especially for operation in
    260   3147  xc151355  * Japan, and has a center frequency 2.484 GHz.
    261   3147  xc151355  * 802.11g 2GHz: adopts the frequency plan of 802.11b. Japan only
    262   3147  xc151355  * allows 802.11g operation in channels 1-13
    263   3147  xc151355  * 802.11a 5GHz: starting every 5 MHz
    264   3147  xc151355  * 802.11b/g channels 15-24 (2512-2692) are used by some implementation
    265   3147  xc151355  * (Atheros etc.)
    266   3147  xc151355  */
    267   3147  xc151355 uint32_t
    268   3147  xc151355 ieee80211_ieee2mhz(uint32_t chan, uint32_t flags)
    269   3147  xc151355 {
    270   3147  xc151355 	if (flags & IEEE80211_CHAN_2GHZ) {	/* 2GHz band */
    271   3147  xc151355 		if (chan == 14)
    272   3147  xc151355 			return (2484);
    273   3147  xc151355 		if (chan < 14)
    274   3147  xc151355 			return (2412 + (chan - 1) * 5);
    275   3147  xc151355 		else
    276   3147  xc151355 			return (2512 + ((chan - 15) * 20));
    277   3147  xc151355 	} else if (flags & IEEE80211_CHAN_5GHZ) {	/* 5Ghz band */
    278   3147  xc151355 		return (5000 + (chan * 5));	/* OFDM */
    279   3147  xc151355 	} else {				/* either, guess */
    280   3147  xc151355 		if (chan == 14)
    281   3147  xc151355 			return (2484);
    282   3147  xc151355 		if (chan < 14)			/* 0-13 */
    283   3147  xc151355 			return (2412 + (chan - 1) * 5);
    284   3147  xc151355 		if (chan < 27)			/* 15-26 */
    285   3147  xc151355 			return (2512 + ((chan - 15) * 20));
    286   3147  xc151355 		return (5000 + (chan * 5));
    287   3147  xc151355 	}
    288   3147  xc151355 }
    289   3147  xc151355 
    290   3147  xc151355 /*
    291   3147  xc151355  * Do late attach work. It must be called by the driver after
    292   3147  xc151355  * calling ieee80211_attach() and before calling most ieee80211
    293   3147  xc151355  * functions.
    294   3147  xc151355  */
    295   3147  xc151355 void
    296   3147  xc151355 ieee80211_media_init(ieee80211com_t *ic)
    297   3147  xc151355 {
    298   3147  xc151355 	/*
    299   3147  xc151355 	 * Do late attach work that must wait for any subclass
    300   3147  xc151355 	 * (i.e. driver) work such as overriding methods.
    301   3147  xc151355 	 */
    302   3147  xc151355 	ieee80211_node_lateattach(ic);
    303   3147  xc151355 }
    304   3147  xc151355 
    305   3147  xc151355 /*
    306   3147  xc151355  * Start Watchdog timer. After count down timer(s), ic_watchdog
    307   3147  xc151355  * will be called
    308   3147  xc151355  */
    309   3147  xc151355 void
    310   3147  xc151355 ieee80211_start_watchdog(ieee80211com_t *ic, uint32_t timer)
    311   3147  xc151355 {
    312   3147  xc151355 	if (ic->ic_watchdog_timer == 0 && ic->ic_watchdog != NULL) {
    313   3147  xc151355 		ic->ic_watchdog_timer = timeout(ic->ic_watchdog, ic,
    314   5296  zf162725 		    drv_usectohz(1000000 * timer));
    315   3147  xc151355 	}
    316   3147  xc151355 }
    317   3147  xc151355 
    318   3147  xc151355 /*
    319   3147  xc151355  * Stop watchdog timer.
    320   3147  xc151355  */
    321   3147  xc151355 void
    322   3147  xc151355 ieee80211_stop_watchdog(ieee80211com_t *ic)
    323   3147  xc151355 {
    324   3147  xc151355 	if (ic->ic_watchdog_timer != 0) {
    325   3147  xc151355 		if (ic->ic_watchdog != NULL)
    326   3147  xc151355 			(void) untimeout(ic->ic_watchdog_timer);
    327   3147  xc151355 		ic->ic_watchdog_timer = 0;
    328   3147  xc151355 	}
    329   3147  xc151355 }
    330   3147  xc151355 
    331   3147  xc151355 /*
    332   3147  xc151355  * Called from a driver's xxx_watchdog routine. It is used to
    333   3147  xc151355  * perform periodic cleanup of state for net80211, as well as
    334   3147  xc151355  * timeout scans.
    335   3147  xc151355  */
    336   3147  xc151355 void
    337   3147  xc151355 ieee80211_watchdog(void *arg)
    338   3147  xc151355 {
    339   3147  xc151355 	ieee80211com_t *ic = arg;
    340   3147  xc151355 	struct ieee80211_impl *im = ic->ic_private;
    341   3147  xc151355 	ieee80211_node_table_t *nt;
    342   3147  xc151355 	int inact_timer = 0;
    343   3147  xc151355 
    344   3147  xc151355 	if (ic->ic_state == IEEE80211_S_INIT)
    345   3147  xc151355 		return;
    346   3147  xc151355 
    347   3147  xc151355 	IEEE80211_LOCK(ic);
    348   3147  xc151355 	if ((im->im_mgt_timer != 0) && (--im->im_mgt_timer == 0)) {
    349   3147  xc151355 		IEEE80211_UNLOCK(ic);
    350   3147  xc151355 		ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
    351   3147  xc151355 		IEEE80211_LOCK(ic);
    352   3147  xc151355 	}
    353   3147  xc151355 
    354   3147  xc151355 	nt = &ic->ic_scan;
    355   3147  xc151355 	if (nt->nt_inact_timer != 0) {
    356   3147  xc151355 		if (--nt->nt_inact_timer == 0)
    357   3147  xc151355 			nt->nt_timeout(nt);
    358   3147  xc151355 		inact_timer += nt->nt_inact_timer;
    359   3147  xc151355 	}
    360   3147  xc151355 	nt = &ic->ic_sta;
    361   3147  xc151355 	if (nt->nt_inact_timer != 0) {
    362   3147  xc151355 		if (--nt->nt_inact_timer == 0)
    363   3147  xc151355 			nt->nt_timeout(nt);
    364   3147  xc151355 		inact_timer += nt->nt_inact_timer;
    365   3147  xc151355 	}
    366   3147  xc151355 
    367   3147  xc151355 	IEEE80211_UNLOCK(ic);
    368   3147  xc151355 
    369   3147  xc151355 	if (im->im_mgt_timer != 0 || inact_timer > 0)
    370   3147  xc151355 		ieee80211_start_watchdog(ic, 1);
    371   3147  xc151355 }
    372   3147  xc151355 
    373   3147  xc151355 /*
    374   3147  xc151355  * Set the current phy mode and recalculate the active channel
    375   3147  xc151355  * set and supported rates based on the available channels for
    376   3147  xc151355  * this mode. Also select a new BSS channel if the current one
    377   3147  xc151355  * is inappropriate for this mode.
    378   3147  xc151355  * This function is called by net80211, and not intended to be
    379   3147  xc151355  * called directly.
    380   3147  xc151355  */
    381   3147  xc151355 static int
    382   3147  xc151355 ieee80211_setmode(ieee80211com_t *ic, enum ieee80211_phymode mode)
    383   3147  xc151355 {
    384   3147  xc151355 	static const uint32_t chanflags[] = {
    385   3147  xc151355 		0,			/* IEEE80211_MODE_AUTO */
    386   3147  xc151355 		IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */
    387   3147  xc151355 		IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */
    388   3147  xc151355 		IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_11G */
    389   3147  xc151355 		IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */
    390   3147  xc151355 		IEEE80211_CHAN_T,	/* IEEE80211_MODE_TURBO_A */
    391   3147  xc151355 		IEEE80211_CHAN_108G,	/* IEEE80211_MODE_TURBO_G */
    392  10266    Quaker 		IEEE80211_CHAN_ST,	/* IEEE80211_MODE_STURBO_A */
    393  10266    Quaker 		IEEE80211_CHAN_A,	/* IEEE80211_MODE_11NA (check legacy) */
    394  10266    Quaker 		IEEE80211_CHAN_G,	/* IEEE80211_MODE_11NG (check legacy) */
    395   3147  xc151355 	};
    396   3147  xc151355 	struct ieee80211_channel *ch;
    397   3147  xc151355 	uint32_t modeflags;
    398   3147  xc151355 	int i;
    399   3147  xc151355 	int achannels = 0;
    400   3147  xc151355 
    401   3147  xc151355 	/* validate new mode */
    402   3147  xc151355 	if ((ic->ic_modecaps & (1 << mode)) == 0) {
    403   3147  xc151355 		ieee80211_err("ieee80211_setmode(): mode %u not supported"
    404   5296  zf162725 		    " (caps 0x%x)\n", mode, ic->ic_modecaps);
    405   3147  xc151355 		return (EINVAL);
    406   3147  xc151355 	}
    407   3147  xc151355 
    408   3147  xc151355 	/*
    409   3147  xc151355 	 * Verify at least one channel is present in the available
    410   3147  xc151355 	 * channel list before committing to the new mode.
    411   3147  xc151355 	 * Calculate the active channel set.
    412   3147  xc151355 	 */
    413   3147  xc151355 	ASSERT(mode < IEEE80211_N(chanflags));
    414   3147  xc151355 	modeflags = chanflags[mode];
    415   3147  xc151355 	bzero(ic->ic_chan_active, sizeof (ic->ic_chan_active));
    416   3147  xc151355 	for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
    417   3147  xc151355 		ch = &ic->ic_sup_channels[i];
    418   3147  xc151355 		if (ch->ich_flags == 0)
    419   3147  xc151355 			continue;
    420   3147  xc151355 		if (mode == IEEE80211_MODE_AUTO) {
    421   3147  xc151355 			/* take anything but pure turbo channels */
    422   3147  xc151355 			if ((ch->ich_flags & ~IEEE80211_CHAN_TURBO) != 0) {
    423   3147  xc151355 				ieee80211_setbit(ic->ic_chan_active, i);
    424   3147  xc151355 				achannels++;
    425   3147  xc151355 			}
    426   3147  xc151355 		} else {
    427   3147  xc151355 			if ((ch->ich_flags & modeflags) == modeflags) {
    428   3147  xc151355 				ieee80211_setbit(ic->ic_chan_active, i);
    429   3147  xc151355 				achannels++;
    430   3147  xc151355 			}
    431   3147  xc151355 		}
    432   3147  xc151355 	}
    433   3147  xc151355 	if (achannels == 0) {
    434   3147  xc151355 		ieee80211_err("ieee80211_setmode(): "
    435   5296  zf162725 		    "no channel found for mode %u\n", mode);
    436   3147  xc151355 		return (EINVAL);
    437   3147  xc151355 	}
    438   3147  xc151355 
    439   3147  xc151355 	/*
    440   3147  xc151355 	 * If no current/default channel is setup or the current
    441   3147  xc151355 	 * channel is wrong for the mode then pick the first
    442   3147  xc151355 	 * available channel from the active list.  This is likely
    443   3147  xc151355 	 * not the right one.
    444   3147  xc151355 	 */
    445   3147  xc151355 	if (ic->ic_ibss_chan == NULL ||
    446   3147  xc151355 	    ieee80211_isclr(ic->ic_chan_active,
    447   3147  xc151355 	    ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) {
    448   3147  xc151355 		for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
    449   3147  xc151355 			if (ieee80211_isset(ic->ic_chan_active, i)) {
    450   3147  xc151355 				ic->ic_ibss_chan = &ic->ic_sup_channels[i];
    451   3147  xc151355 				break;
    452   3147  xc151355 			}
    453   3147  xc151355 		}
    454   3147  xc151355 	}
    455   3147  xc151355 	/*
    456   3147  xc151355 	 * If the desired channel is set but no longer valid then reset it.
    457   3147  xc151355 	 */
    458   3147  xc151355 	if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
    459   3147  xc151355 	    ieee80211_isclr(ic->ic_chan_active,
    460   3147  xc151355 	    ieee80211_chan2ieee(ic, ic->ic_des_chan))) {
    461   3147  xc151355 		ic->ic_des_chan = IEEE80211_CHAN_ANYC;
    462   3147  xc151355 	}
    463   3147  xc151355 
    464   3147  xc151355 	/*
    465   3147  xc151355 	 * Do mode-specific rate setup.
    466   3147  xc151355 	 */
    467   3147  xc151355 	if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11B)
    468   3147  xc151355 		ieee80211_setbasicrates(&ic->ic_sup_rates[mode], mode);
    469   3147  xc151355 
    470   3147  xc151355 	/*
    471   3147  xc151355 	 * Setup an initial rate set according to the
    472   3147  xc151355 	 * current/default channel.  This will be changed
    473   3147  xc151355 	 * when scanning but must exist now so drivers have
    474   3147  xc151355 	 * consistent state of ic_bsschan.
    475   3147  xc151355 	 */
    476   3147  xc151355 	if (ic->ic_bss != NULL)
    477   3147  xc151355 		ic->ic_bss->in_rates = ic->ic_sup_rates[mode];
    478   3147  xc151355 	ic->ic_curmode = mode;
    479   3147  xc151355 	ieee80211_reset_erp(ic);	/* reset ERP state */
    480  10266    Quaker 	ieee80211_wme_initparams(ic);	/* reset WME stat */
    481   3147  xc151355 
    482   3147  xc151355 	return (0);
    483   3147  xc151355 }
    484   3147  xc151355 
    485   3147  xc151355 /*
    486   3147  xc151355  * Return the phy mode for with the specified channel so the
    487   3147  xc151355  * caller can select a rate set.  This is problematic for channels
    488   3147  xc151355  * where multiple operating modes are possible (e.g. 11g+11b).
    489   3147  xc151355  * In those cases we defer to the current operating mode when set.
    490   3147  xc151355  */
    491  10266    Quaker /* ARGSUSED */
    492   3147  xc151355 enum ieee80211_phymode
    493   3147  xc151355 ieee80211_chan2mode(ieee80211com_t *ic, struct ieee80211_channel *chan)
    494   3147  xc151355 {
    495  10266    Quaker 	if (IEEE80211_IS_CHAN_HTA(chan))
    496  10266    Quaker 		return (IEEE80211_MODE_11NA);
    497  10266    Quaker 	else if (IEEE80211_IS_CHAN_HTG(chan))
    498  10266    Quaker 		return (IEEE80211_MODE_11NG);
    499  10266    Quaker 	else if (IEEE80211_IS_CHAN_108G(chan))
    500  10266    Quaker 		return (IEEE80211_MODE_TURBO_G);
    501  10266    Quaker 	else if (IEEE80211_IS_CHAN_ST(chan))
    502  10266    Quaker 		return (IEEE80211_MODE_STURBO_A);
    503  10266    Quaker 	else if (IEEE80211_IS_CHAN_T(chan))
    504   3147  xc151355 		return (IEEE80211_MODE_TURBO_A);
    505  10266    Quaker 	else if (IEEE80211_IS_CHAN_A(chan))
    506   3147  xc151355 		return (IEEE80211_MODE_11A);
    507  10266    Quaker 	else if (IEEE80211_IS_CHAN_ANYG(chan))
    508  10266    Quaker 		return (IEEE80211_MODE_11G);
    509  10266    Quaker 	else if (IEEE80211_IS_CHAN_B(chan))
    510  10266    Quaker 		return (IEEE80211_MODE_11B);
    511  10266    Quaker 	else if (IEEE80211_IS_CHAN_FHSS(chan))
    512   3147  xc151355 		return (IEEE80211_MODE_FH);
    513  10266    Quaker 
    514  10266    Quaker 	/* NB: should not get here */
    515  10266    Quaker 	ieee80211_err("cannot map channel to mode; freq %u flags 0x%x\n",
    516  10266    Quaker 	    chan->ich_freq, chan->ich_flags);
    517  10266    Quaker 
    518  10266    Quaker 	return (IEEE80211_MODE_11B);
    519  10266    Quaker }
    520  10266    Quaker 
    521  10266    Quaker const struct ieee80211_rateset *
    522  10266    Quaker ieee80211_get_suprates(ieee80211com_t *ic, struct ieee80211_channel *c)
    523  10266    Quaker {
    524  10266    Quaker 	if (IEEE80211_IS_CHAN_HTA(c))
    525  10266    Quaker 		return (&ic->ic_sup_rates[IEEE80211_MODE_11A]);
    526  10266    Quaker 	if (IEEE80211_IS_CHAN_HTG(c)) {
    527  10266    Quaker 		return (&ic->ic_sup_rates[IEEE80211_MODE_11G]);
    528   3147  xc151355 	}
    529  10266    Quaker 	return (&ic->ic_sup_rates[ieee80211_chan2mode(ic, c)]);
    530  10266    Quaker }
    531  10266    Quaker 
    532  10266    Quaker /*
    533  10266    Quaker  * Locate a channel given a frequency+flags.  We cache
    534  10266    Quaker  * the previous lookup to optimize swithing between two
    535  10266    Quaker  * channels--as happens with dynamic turbo.
    536  10266    Quaker  */
    537  10266    Quaker struct ieee80211_channel *
    538  10266    Quaker ieee80211_find_channel(ieee80211com_t *ic, int freq, int flags)
    539  10266    Quaker {
    540  10266    Quaker 	struct ieee80211_channel *c;
    541  10266    Quaker 	int i;
    542  10266    Quaker 
    543  10266    Quaker 	flags &= IEEE80211_CHAN_ALLTURBO;
    544  10266    Quaker 	/* brute force search */
    545  10266    Quaker 	for (i = 0; i < IEEE80211_CHAN_MAX; i++) {
    546  10266    Quaker 		c = &ic->ic_sup_channels[i];
    547  10266    Quaker 		if (c->ich_freq == freq &&
    548  10266    Quaker 		    (c->ich_flags & IEEE80211_CHAN_ALLTURBO) == flags)
    549  10266    Quaker 			return (c);
    550  10266    Quaker 	}
    551  10266    Quaker 	return (NULL);
    552   3147  xc151355 }
    553   3147  xc151355 
    554   3147  xc151355 /*
    555   3147  xc151355  * Return the size of the 802.11 header for a management or data frame.
    556   3147  xc151355  */
    557   3147  xc151355 int
    558  10266    Quaker ieee80211_hdrsize(const void *data)
    559   3147  xc151355 {
    560   3147  xc151355 	const struct ieee80211_frame *wh = data;
    561   3147  xc151355 	int size = sizeof (struct ieee80211_frame);
    562   3147  xc151355 
    563   3147  xc151355 	/* NB: we don't handle control frames */
    564   3147  xc151355 	ASSERT((wh->i_fc[0]&IEEE80211_FC0_TYPE_MASK) !=
    565   5296  zf162725 	    IEEE80211_FC0_TYPE_CTL);
    566   3147  xc151355 	if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
    567   3147  xc151355 		size += IEEE80211_ADDR_LEN;
    568  10266    Quaker 	if (IEEE80211_QOS_HAS_SEQ(wh))
    569  10266    Quaker 		size += sizeof (uint16_t);
    570   3147  xc151355 
    571  10266    Quaker 	return (size);
    572  10266    Quaker }
    573  10266    Quaker 
    574  10266    Quaker /*
    575  10266    Quaker  * Return the space occupied by the 802.11 header and any
    576  10266    Quaker  * padding required by the driver.  This works for a
    577  10266    Quaker  * management or data frame.
    578  10266    Quaker  */
    579  10266    Quaker int
    580  10266    Quaker ieee80211_hdrspace(ieee80211com_t *ic, const void *data)
    581  10266    Quaker {
    582  10266    Quaker 	int size = ieee80211_hdrsize(data);
    583  10266    Quaker 	if (ic->ic_flags & IEEE80211_F_DATAPAD)
    584  10266    Quaker 		size = roundup(size, sizeof (uint32_t));
    585  10266    Quaker 	return (size);
    586  10266    Quaker }
    587  10266    Quaker 
    588  10266    Quaker /*
    589  10266    Quaker  * Like ieee80211_hdrsize, but handles any type of frame.
    590  10266    Quaker  */
    591  10266    Quaker int
    592  10266    Quaker ieee80211_anyhdrsize(const void *data)
    593  10266    Quaker {
    594  10266    Quaker 	const struct ieee80211_frame *wh = data;
    595  10266    Quaker 
    596  10266    Quaker 	if ((wh->i_fc[0]&IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) {
    597  10266    Quaker 		switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
    598  10266    Quaker 		case IEEE80211_FC0_SUBTYPE_CTS:
    599  10266    Quaker 		case IEEE80211_FC0_SUBTYPE_ACK:
    600  10266    Quaker 			return (sizeof (struct ieee80211_frame_ack));
    601  10266    Quaker 		case IEEE80211_FC0_SUBTYPE_BAR:
    602  10266    Quaker 			return (sizeof (struct ieee80211_frame_bar));
    603  10266    Quaker 		}
    604  10266    Quaker 		return (sizeof (struct ieee80211_frame_min));
    605  10266    Quaker 	} else
    606  10266    Quaker 		return (ieee80211_hdrsize(data));
    607  10266    Quaker }
    608  10266    Quaker 
    609  10266    Quaker /*
    610  10266    Quaker  * Like ieee80211_hdrspace, but handles any type of frame.
    611  10266    Quaker  */
    612  10266    Quaker int
    613  10266    Quaker ieee80211_anyhdrspace(ieee80211com_t *ic, const void *data)
    614  10266    Quaker {
    615  10266    Quaker 	int size = ieee80211_anyhdrsize(data);
    616  10266    Quaker 	if (ic->ic_flags & IEEE80211_F_DATAPAD)
    617  10266    Quaker 		size = roundup(size, sizeof (uint32_t));
    618   3147  xc151355 	return (size);
    619   3147  xc151355 }
    620   3147  xc151355 
    621   3147  xc151355 /*
    622   3147  xc151355  * Allocate and setup a management frame of the specified
    623   3147  xc151355  * size.  We return the mblk and a pointer to the start
    624   3147  xc151355  * of the contiguous data area that's been reserved based
    625   3147  xc151355  * on the packet length.
    626   3147  xc151355  */
    627   3147  xc151355 mblk_t *
    628   3147  xc151355 ieee80211_getmgtframe(uint8_t **frm, int pktlen)
    629   3147  xc151355 {
    630   3147  xc151355 	mblk_t *mp;
    631   3147  xc151355 	int len;
    632   3147  xc151355 
    633   3147  xc151355 	len = sizeof (struct ieee80211_frame) + pktlen;
    634   3147  xc151355 	mp = allocb(len, BPRI_MED);
    635   3147  xc151355 	if (mp != NULL) {
    636   3147  xc151355 		*frm = mp->b_rptr + sizeof (struct ieee80211_frame);
    637   3147  xc151355 		mp->b_wptr = mp->b_rptr + len;
    638   3147  xc151355 	} else {
    639   3147  xc151355 		ieee80211_err("ieee80211_getmgtframe: "
    640   5296  zf162725 		    "alloc frame failed, %d\n", len);
    641   3147  xc151355 	}
    642   3147  xc151355 	return (mp);
    643   3147  xc151355 }
    644   3147  xc151355 
    645   3147  xc151355 /*
    646   3147  xc151355  * Send system messages to notify the device has joined a WLAN.
    647   3147  xc151355  * This is an OS specific function. Solaris marks link status
    648   3147  xc151355  * as up.
    649   3147  xc151355  */
    650   3147  xc151355 void
    651   3147  xc151355 ieee80211_notify_node_join(ieee80211com_t *ic, ieee80211_node_t *in)
    652   3147  xc151355 {
    653   3147  xc151355 	if (in == ic->ic_bss)
    654   3147  xc151355 		mac_link_update(ic->ic_mach, LINK_STATE_UP);
    655   4126  zf162725 	ieee80211_notify(ic, EVENT_ASSOC);	/* notify WPA service */
    656   3147  xc151355 }
    657   3147  xc151355 
    658   3147  xc151355 /*
    659   3147  xc151355  * Send system messages to notify the device has left a WLAN.
    660   3147  xc151355  * This is an OS specific function. Solaris marks link status
    661   3147  xc151355  * as down.
    662   3147  xc151355  */
    663   3147  xc151355 void
    664   3147  xc151355 ieee80211_notify_node_leave(ieee80211com_t *ic, ieee80211_node_t *in)
    665   3147  xc151355 {
    666   3147  xc151355 	if (in == ic->ic_bss)
    667   3147  xc151355 		mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
    668   4126  zf162725 	ieee80211_notify(ic, EVENT_DISASSOC);	/* notify WPA service */
    669   3147  xc151355 }
    670  10266    Quaker 
    671   3147  xc151355 
    672   3147  xc151355 /*
    673   3147  xc151355  * Get 802.11 kstats defined in ieee802.11(5)
    674   3147  xc151355  *
    675   3147  xc151355  * Return 0 on success
    676   3147  xc151355  */
    677   3147  xc151355 int
    678   3147  xc151355 ieee80211_stat(ieee80211com_t *ic, uint_t stat, uint64_t *val)
    679   3147  xc151355 {
    680   3147  xc151355 	ASSERT(val != NULL);
    681   3147  xc151355 	IEEE80211_LOCK(ic);
    682   3147  xc151355 	switch (stat) {
    683   3147  xc151355 	case WIFI_STAT_TX_FRAGS:
    684   3147  xc151355 		*val = ic->ic_stats.is_tx_frags;
    685   3147  xc151355 		break;
    686   3147  xc151355 	case WIFI_STAT_MCAST_TX:
    687   3147  xc151355 		*val = ic->ic_stats.is_tx_mcast;
    688   3147  xc151355 		break;
    689   3147  xc151355 	case WIFI_STAT_TX_FAILED:
    690   3147  xc151355 		*val = ic->ic_stats.is_tx_failed;
    691   3147  xc151355 		break;
    692   3147  xc151355 	case WIFI_STAT_TX_RETRANS:
    693   3147  xc151355 		*val = ic->ic_stats.is_tx_retries;
    694   3147  xc151355 		break;
    695   3147  xc151355 	case WIFI_STAT_RTS_SUCCESS:
    696   3147  xc151355 		*val = ic->ic_stats.is_rts_success;
    697   3147  xc151355 		break;
    698   3147  xc151355 	case WIFI_STAT_RTS_FAILURE:
    699   3147  xc151355 		*val = ic->ic_stats.is_rts_failure;
    700   3147  xc151355 		break;
    701   3147  xc151355 	case WIFI_STAT_ACK_FAILURE:
    702   3147  xc151355 		*val = ic->ic_stats.is_ack_failure;
    703   3147  xc151355 		break;
    704   3147  xc151355 	case WIFI_STAT_RX_FRAGS:
    705   3147  xc151355 		*val = ic->ic_stats.is_rx_frags;
    706   3147  xc151355 		break;
    707   3147  xc151355 	case WIFI_STAT_MCAST_RX:
    708   3147  xc151355 		*val = ic->ic_stats.is_rx_mcast;
    709   3147  xc151355 		break;
    710   3147  xc151355 	case WIFI_STAT_RX_DUPS:
    711   3147  xc151355 		*val = ic->ic_stats.is_rx_dups;
    712   3147  xc151355 		break;
    713   3147  xc151355 	case WIFI_STAT_FCS_ERRORS:
    714   3147  xc151355 		*val = ic->ic_stats.is_fcs_errors;
    715   3147  xc151355 		break;
    716   3147  xc151355 	case WIFI_STAT_WEP_ERRORS:
    717   3147  xc151355 		*val = ic->ic_stats.is_wep_errors;
    718   3147  xc151355 		break;
    719   3147  xc151355 	}
    720   3147  xc151355 	IEEE80211_UNLOCK(ic);
    721   3147  xc151355 	return (0);
    722   3147  xc151355 }
    723   3147  xc151355 
    724   3147  xc151355 /*
    725   3147  xc151355  * Attach network interface to the 802.11 support module. This
    726   3147  xc151355  * function must be called before using any of the ieee80211
    727   3147  xc151355  * functionss. The parameter "ic" MUST be initialized to tell
    728   3147  xc151355  * net80211 about interface's capabilities.
    729   3147  xc151355  */
    730   3147  xc151355 void
    731   3147  xc151355 ieee80211_attach(ieee80211com_t *ic)
    732   3147  xc151355 {
    733   3147  xc151355 	struct ieee80211_impl		*im;
    734   3147  xc151355 	struct ieee80211_channel	*ch;
    735   3147  xc151355 	int				i;
    736   3147  xc151355 
    737   3147  xc151355 	/* Check mandatory callback functions not NULL */
    738   3147  xc151355 	ASSERT(ic->ic_xmit != NULL);
    739   3147  xc151355 
    740   3147  xc151355 	mutex_init(&ic->ic_genlock, NULL, MUTEX_DRIVER, NULL);
    741   4126  zf162725 	mutex_init(&ic->ic_doorlock, NULL, MUTEX_DRIVER, NULL);
    742   3147  xc151355 
    743   3147  xc151355 	im = kmem_alloc(sizeof (ieee80211_impl_t), KM_SLEEP);
    744   3147  xc151355 	ic->ic_private = im;
    745   3147  xc151355 	cv_init(&im->im_scan_cv, NULL, CV_DRIVER, NULL);
    746   3147  xc151355 
    747   3147  xc151355 	/*
    748   3147  xc151355 	 * Fill in 802.11 available channel set, mark
    749   3147  xc151355 	 * all available channels as active, and pick
    750   3147  xc151355 	 * a default channel if not already specified.
    751   3147  xc151355 	 */
    752   3147  xc151355 	bzero(im->im_chan_avail, sizeof (im->im_chan_avail));
    753   3147  xc151355 	ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO;
    754   3147  xc151355 	for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
    755   3147  xc151355 		ch = &ic->ic_sup_channels[i];
    756   3147  xc151355 		if (ch->ich_flags) {
    757   3147  xc151355 			/* Verify driver passed us valid data */
    758   3147  xc151355 			if (i != ieee80211_chan2ieee(ic, ch)) {
    759   3147  xc151355 				ieee80211_err("bad channel ignored: "
    760   5296  zf162725 				    "freq %u flags%x number %u\n",
    761   5296  zf162725 				    ch->ich_freq, ch->ich_flags, i);
    762   3147  xc151355 				ch->ich_flags = 0;
    763   3147  xc151355 				continue;
    764   3147  xc151355 			}
    765   3147  xc151355 			ieee80211_setbit(im->im_chan_avail, i);
    766   3147  xc151355 			/* Identify mode capabilities */
    767   3147  xc151355 			if (IEEE80211_IS_CHAN_A(ch))
    768   3147  xc151355 				ic->ic_modecaps |= 1 << IEEE80211_MODE_11A;
    769   3147  xc151355 			if (IEEE80211_IS_CHAN_B(ch))
    770   3147  xc151355 				ic->ic_modecaps |= 1 << IEEE80211_MODE_11B;
    771   3147  xc151355 			if (IEEE80211_IS_CHAN_PUREG(ch))
    772   3147  xc151355 				ic->ic_modecaps |= 1 << IEEE80211_MODE_11G;
    773   3147  xc151355 			if (IEEE80211_IS_CHAN_FHSS(ch))
    774   3147  xc151355 				ic->ic_modecaps |= 1 << IEEE80211_MODE_FH;
    775   3147  xc151355 			if (IEEE80211_IS_CHAN_T(ch))
    776   3147  xc151355 				ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_A;
    777   3147  xc151355 			if (IEEE80211_IS_CHAN_108G(ch))
    778   3147  xc151355 				ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_G;
    779  10266    Quaker 			if (IEEE80211_IS_CHAN_ST(ch))
    780  10266    Quaker 				ic->ic_modecaps |= 1 << IEEE80211_MODE_STURBO_A;
    781  10266    Quaker 			if (IEEE80211_IS_CHAN_HTA(ch))
    782  10266    Quaker 				ic->ic_modecaps |= 1 << IEEE80211_MODE_11NA;
    783  10266    Quaker 			if (IEEE80211_IS_CHAN_HTG(ch))
    784  10266    Quaker 				ic->ic_modecaps |= 1 << IEEE80211_MODE_11NG;
    785   3147  xc151355 			if (ic->ic_curchan == NULL) {
    786   3147  xc151355 				/* arbitrarily pick the first channel */
    787   3147  xc151355 				ic->ic_curchan = &ic->ic_sup_channels[i];
    788   3147  xc151355 			}
    789   3147  xc151355 		}
    790   3147  xc151355 	}
    791   3147  xc151355 	/* validate ic->ic_curmode */
    792   3147  xc151355 	if ((ic->ic_modecaps & (1 << ic->ic_curmode)) == 0)
    793   3147  xc151355 		ic->ic_curmode = IEEE80211_MODE_AUTO;
    794   3147  xc151355 	ic->ic_des_chan = IEEE80211_CHAN_ANYC;	/* any channel is ok */
    795   3147  xc151355 	(void) ieee80211_setmode(ic, ic->ic_curmode);
    796   3147  xc151355 
    797  10266    Quaker 	if (ic->ic_caps & IEEE80211_C_WME)	/* enable if capable */
    798  10266    Quaker 		ic->ic_flags |= IEEE80211_F_WME;
    799   3147  xc151355 	if (ic->ic_caps & IEEE80211_C_BURST)
    800   3147  xc151355 		ic->ic_flags |= IEEE80211_F_BURST;
    801   3147  xc151355 	ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT;
    802   3147  xc151355 	ic->ic_lintval = ic->ic_bintval;
    803   3147  xc151355 	ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX;
    804   3147  xc151355 	ic->ic_bmissthreshold = IEEE80211_HWBMISS_DEFAULT;
    805   3147  xc151355 
    806   3147  xc151355 	ic->ic_reset = ieee80211_default_reset;
    807   3147  xc151355 
    808   3147  xc151355 	ieee80211_node_attach(ic);
    809   3147  xc151355 	ieee80211_proto_attach(ic);
    810   3147  xc151355 	ieee80211_crypto_attach(ic);
    811  10266    Quaker 	ieee80211_ht_attach(ic);
    812   3147  xc151355 
    813   3147  xc151355 	ic->ic_watchdog_timer = 0;
    814   3147  xc151355 }
    815   3147  xc151355 
    816   3147  xc151355 /*
    817   3147  xc151355  * Free any ieee80211 structures associated with the driver.
    818   3147  xc151355  */
    819   3147  xc151355 void
    820   3147  xc151355 ieee80211_detach(ieee80211com_t *ic)
    821   3147  xc151355 {
    822   3147  xc151355 	struct ieee80211_impl *im = ic->ic_private;
    823   3147  xc151355 
    824   3147  xc151355 	ieee80211_stop_watchdog(ic);
    825   3147  xc151355 	cv_destroy(&im->im_scan_cv);
    826   3147  xc151355 	kmem_free(im, sizeof (ieee80211_impl_t));
    827   3147  xc151355 
    828   6629  zf162725 	if (ic->ic_opt_ie != NULL)
    829   6629  zf162725 		ieee80211_free(ic->ic_opt_ie);
    830   6629  zf162725 
    831  10266    Quaker 	ieee80211_ht_detach(ic);
    832   3147  xc151355 	ieee80211_node_detach(ic);
    833   3147  xc151355 	ieee80211_crypto_detach(ic);
    834   3147  xc151355 
    835   3147  xc151355 	mutex_destroy(&ic->ic_genlock);
    836   4126  zf162725 	mutex_destroy(&ic->ic_doorlock);
    837   3147  xc151355 }
    838   3147  xc151355 
    839   3147  xc151355 static struct modlmisc	i_wifi_modlmisc = {
    840   3147  xc151355 	&mod_miscops,
    841  10266    Quaker 	"IEEE80211 Kernel Module v2.0"
    842   3147  xc151355 };
    843   3147  xc151355 
    844   3147  xc151355 static struct modlinkage	i_wifi_modlinkage = {
    845   3147  xc151355 	MODREV_1,
    846   3147  xc151355 	&i_wifi_modlmisc,
    847   3147  xc151355 	NULL
    848   3147  xc151355 };
    849   3147  xc151355 
    850   3147  xc151355 /*
    851   3147  xc151355  * modlinkage functions
    852   3147  xc151355  */
    853   3147  xc151355 int
    854   3147  xc151355 _init(void)
    855   3147  xc151355 {
    856   3147  xc151355 	return (mod_install(&i_wifi_modlinkage));
    857   3147  xc151355 }
    858   3147  xc151355 
    859   3147  xc151355 int
    860   3147  xc151355 _fini(void)
    861   3147  xc151355 {
    862   3147  xc151355 	return (mod_remove(&i_wifi_modlinkage));
    863   3147  xc151355 }
    864   3147  xc151355 
    865   3147  xc151355 int
    866   3147  xc151355 _info(struct modinfo *modinfop)
    867   3147  xc151355 {
    868   3147  xc151355 	return (mod_info(&i_wifi_modlinkage, modinfop));
    869   3147  xc151355 }
    870