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