1 /* 2 * Copyright 2008 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 }; 62 63 #define IEEE80211_DPRINT(_level, _fmt) do { \ 64 _NOTE(CONSTCOND) \ 65 va_list ap; \ 66 va_start(ap, (_fmt)); \ 67 vcmn_err((_level), (_fmt), ap); \ 68 va_end(ap); \ 69 _NOTE(CONSTCOND) \ 70 } while (0) 71 72 /* 73 * Print error messages 74 */ 75 void 76 ieee80211_err(const int8_t *fmt, ...) 77 { 78 IEEE80211_DPRINT(CE_WARN, fmt); 79 } 80 81 /* 82 * Print debug messages 83 */ 84 void 85 ieee80211_dbg(uint32_t flag, const int8_t *fmt, ...) 86 { 87 if (flag & ieee80211_debug) 88 IEEE80211_DPRINT(CE_CONT, fmt); 89 } 90 91 /* 92 * Alloc memory, and save the size 93 */ 94 void * 95 ieee80211_malloc(size_t size) 96 { 97 void *p = kmem_zalloc((size + 4), KM_SLEEP); 98 *(int *)p = size; 99 p = (char *)p + 4; 100 101 return (p); 102 } 103 104 void 105 ieee80211_free(void *p) 106 { 107 void *tp = (char *)p - 4; 108 kmem_free((char *)p - 4, *(int *)tp + 4); 109 } 110 111 void 112 ieee80211_mac_update(ieee80211com_t *ic) 113 { 114 wifi_data_t wd = { 0 }; 115 ieee80211_node_t *in; 116 117 /* 118 * We can send data now; update the fastpath with our 119 * current associated BSSID and other relevant settings. 120 */ 121 in = ic->ic_bss; 122 wd.wd_secalloc = ieee80211_crypto_getciphertype(ic); 123 wd.wd_opmode = ic->ic_opmode; 124 IEEE80211_ADDR_COPY(wd.wd_bssid, in->in_bssid); 125 (void) mac_pdata_update(ic->ic_mach, &wd, sizeof (wd)); 126 mac_tx_update(ic->ic_mach); 127 ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_mac_update" 128 "(cipher = %d)\n", wd.wd_secalloc); 129 } 130 131 /* 132 * ieee80211_event_thread 133 * open door of wpa, send event to wpad service 134 */ 135 static void 136 ieee80211_event_thread(void *arg) 137 { 138 ieee80211com_t *ic = arg; 139 door_handle_t event_door = NULL; /* Door for upcalls */ 140 wl_events_t ev; 141 door_arg_t darg; 142 143 mutex_enter(&ic->ic_doorlock); 144 145 ev.event = ic->ic_eventq[ic->ic_evq_head]; 146 ic->ic_evq_head ++; 147 if (ic->ic_evq_head >= MAX_EVENT) 148 ic->ic_evq_head = 0; 149 150 ieee80211_dbg(IEEE80211_MSG_DEBUG, "ieee80211_event(%d)\n", ev.event); 151 /* 152 * Locate the door used for upcalls 153 */ 154 if (door_ki_open(ic->ic_wpadoor, &event_door) != 0) { 155 ieee80211_err("ieee80211_event: door_ki_open(%s) failed\n", 156 ic->ic_wpadoor); 157 goto out; 158 } 159 160 darg.data_ptr = (char *)&ev; 161 darg.data_size = sizeof (wl_events_t); 162 darg.desc_ptr = NULL; 163 darg.desc_num = 0; 164 darg.rbuf = NULL; 165 darg.rsize = 0; 166 167 if (door_ki_upcall_limited(event_door, &darg, NULL, SIZE_MAX, 0) != 0) { 168 ieee80211_err("ieee80211_event: door_ki_upcall() failed\n"); 169 } 170 171 if (event_door) { /* release our hold (if any) */ 172 door_ki_rele(event_door); 173 } 174 175 out: 176 mutex_exit(&ic->ic_doorlock); 177 } 178 179 /* 180 * Notify state transition event message to WPA daemon 181 */ 182 void 183 ieee80211_notify(ieee80211com_t *ic, wpa_event_type event) 184 { 185 if ((ic->ic_flags & IEEE80211_F_WPA) == 0) 186 return; /* Not running on WPA mode */ 187 188 ic->ic_eventq[ic->ic_evq_tail] = event; 189 ic->ic_evq_tail ++; 190 if (ic->ic_evq_tail >= MAX_EVENT) ic->ic_evq_tail = 0; 191 192 /* async */ 193 (void) timeout(ieee80211_event_thread, (void *)ic, 0); 194 } 195 196 /* 197 * Register WPA door 198 */ 199 void 200 ieee80211_register_door(ieee80211com_t *ic, const char *drvname, int inst) 201 { 202 (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", 203 WPA_DOOR, drvname, inst); 204 } 205 206 /* 207 * Default reset method for use with the ioctl support. This 208 * method is invoked after any state change in the 802.11 209 * layer that should be propagated to the hardware but not 210 * require re-initialization of the 802.11 state machine (e.g 211 * rescanning for an ap). We always return ENETRESET which 212 * should cause the driver to re-initialize the device. Drivers 213 * can override this method to implement more optimized support. 214 */ 215 /* ARGSUSED */ 216 static int 217 ieee80211_default_reset(ieee80211com_t *ic) 218 { 219 return (ENETRESET); 220 } 221 222 /* 223 * Convert channel to IEEE channel number. 224 */ 225 uint32_t 226 ieee80211_chan2ieee(ieee80211com_t *ic, struct ieee80211_channel *ch) 227 { 228 if ((ic->ic_sup_channels <= ch) && 229 (ch <= &ic->ic_sup_channels[IEEE80211_CHAN_MAX])) { 230 return (ch - ic->ic_sup_channels); 231 } else if (ch == IEEE80211_CHAN_ANYC) { 232 return (IEEE80211_CHAN_ANY); 233 } else if (ch != NULL) { 234 ieee80211_err("invalid channel freq %u flags %x\n", 235 ch->ich_freq, ch->ich_flags); 236 return (0); 237 } 238 ieee80211_err("invalid channel (NULL)\n"); /* ch == NULL */ 239 return (0); 240 } 241 242 /* 243 * Convert IEEE channel number to MHz frequency. 244 * chan IEEE channel number 245 * flags specify whether the frequency is in the 2GHz ISM 246 * band or the 5GHz band 247 * 248 * 802.11b 2GHz: 14 channels, each 5 MHz wide. Channel 1 is placed 249 * at 2.412 GHz, channel 2 at 2.417 GHz, and so on up to channel 13 250 * at 2.472 GHz. Channel 14 was defined especially for operation in 251 * Japan, and has a center frequency 2.484 GHz. 252 * 802.11g 2GHz: adopts the frequency plan of 802.11b. Japan only 253 * allows 802.11g operation in channels 1-13 254 * 802.11a 5GHz: starting every 5 MHz 255 * 802.11b/g channels 15-24 (2512-2692) are used by some implementation 256 * (Atheros etc.) 257 */ 258 uint32_t 259 ieee80211_ieee2mhz(uint32_t chan, uint32_t flags) 260 { 261 if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ 262 if (chan == 14) 263 return (2484); 264 if (chan < 14) 265 return (2412 + (chan - 1) * 5); 266 else 267 return (2512 + ((chan - 15) * 20)); 268 } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */ 269 return (5000 + (chan * 5)); /* OFDM */ 270 } else { /* either, guess */ 271 if (chan == 14) 272 return (2484); 273 if (chan < 14) /* 0-13 */ 274 return (2412 + (chan - 1) * 5); 275 if (chan < 27) /* 15-26 */ 276 return (2512 + ((chan - 15) * 20)); 277 return (5000 + (chan * 5)); 278 } 279 } 280 281 /* 282 * Do late attach work. It must be called by the driver after 283 * calling ieee80211_attach() and before calling most ieee80211 284 * functions. 285 */ 286 void 287 ieee80211_media_init(ieee80211com_t *ic) 288 { 289 /* 290 * Do late attach work that must wait for any subclass 291 * (i.e. driver) work such as overriding methods. 292 */ 293 ieee80211_node_lateattach(ic); 294 } 295 296 /* 297 * Start Watchdog timer. After count down timer(s), ic_watchdog 298 * will be called 299 */ 300 void 301 ieee80211_start_watchdog(ieee80211com_t *ic, uint32_t timer) 302 { 303 if (ic->ic_watchdog_timer == 0 && ic->ic_watchdog != NULL) { 304 ic->ic_watchdog_timer = timeout(ic->ic_watchdog, ic, 305 drv_usectohz(1000000 * timer)); 306 } 307 } 308 309 /* 310 * Stop watchdog timer. 311 */ 312 void 313 ieee80211_stop_watchdog(ieee80211com_t *ic) 314 { 315 if (ic->ic_watchdog_timer != 0) { 316 if (ic->ic_watchdog != NULL) 317 (void) untimeout(ic->ic_watchdog_timer); 318 ic->ic_watchdog_timer = 0; 319 } 320 } 321 322 /* 323 * Called from a driver's xxx_watchdog routine. It is used to 324 * perform periodic cleanup of state for net80211, as well as 325 * timeout scans. 326 */ 327 void 328 ieee80211_watchdog(void *arg) 329 { 330 ieee80211com_t *ic = arg; 331 struct ieee80211_impl *im = ic->ic_private; 332 ieee80211_node_table_t *nt; 333 int inact_timer = 0; 334 335 if (ic->ic_state == IEEE80211_S_INIT) 336 return; 337 338 IEEE80211_LOCK(ic); 339 if ((im->im_mgt_timer != 0) && (--im->im_mgt_timer == 0)) { 340 IEEE80211_UNLOCK(ic); 341 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 342 IEEE80211_LOCK(ic); 343 } 344 345 nt = &ic->ic_scan; 346 if (nt->nt_inact_timer != 0) { 347 if (--nt->nt_inact_timer == 0) 348 nt->nt_timeout(nt); 349 inact_timer += nt->nt_inact_timer; 350 } 351 nt = &ic->ic_sta; 352 if (nt->nt_inact_timer != 0) { 353 if (--nt->nt_inact_timer == 0) 354 nt->nt_timeout(nt); 355 inact_timer += nt->nt_inact_timer; 356 } 357 358 IEEE80211_UNLOCK(ic); 359 360 if (im->im_mgt_timer != 0 || inact_timer > 0) 361 ieee80211_start_watchdog(ic, 1); 362 } 363 364 /* 365 * Set the current phy mode and recalculate the active channel 366 * set and supported rates based on the available channels for 367 * this mode. Also select a new BSS channel if the current one 368 * is inappropriate for this mode. 369 * This function is called by net80211, and not intended to be 370 * called directly. 371 */ 372 static int 373 ieee80211_setmode(ieee80211com_t *ic, enum ieee80211_phymode mode) 374 { 375 static const uint32_t chanflags[] = { 376 0, /* IEEE80211_MODE_AUTO */ 377 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ 378 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ 379 IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ 380 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ 381 IEEE80211_CHAN_T, /* IEEE80211_MODE_TURBO_A */ 382 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */ 383 }; 384 struct ieee80211_channel *ch; 385 uint32_t modeflags; 386 int i; 387 int achannels = 0; 388 389 /* validate new mode */ 390 if ((ic->ic_modecaps & (1 << mode)) == 0) { 391 ieee80211_err("ieee80211_setmode(): mode %u not supported" 392 " (caps 0x%x)\n", mode, ic->ic_modecaps); 393 return (EINVAL); 394 } 395 396 /* 397 * Verify at least one channel is present in the available 398 * channel list before committing to the new mode. 399 * Calculate the active channel set. 400 */ 401 ASSERT(mode < IEEE80211_N(chanflags)); 402 modeflags = chanflags[mode]; 403 bzero(ic->ic_chan_active, sizeof (ic->ic_chan_active)); 404 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 405 ch = &ic->ic_sup_channels[i]; 406 if (ch->ich_flags == 0) 407 continue; 408 if (mode == IEEE80211_MODE_AUTO) { 409 /* take anything but pure turbo channels */ 410 if ((ch->ich_flags & ~IEEE80211_CHAN_TURBO) != 0) { 411 ieee80211_setbit(ic->ic_chan_active, i); 412 achannels++; 413 } 414 } else { 415 if ((ch->ich_flags & modeflags) == modeflags) { 416 ieee80211_setbit(ic->ic_chan_active, i); 417 achannels++; 418 } 419 } 420 } 421 if (achannels == 0) { 422 ieee80211_err("ieee80211_setmode(): " 423 "no channel found for mode %u\n", mode); 424 return (EINVAL); 425 } 426 427 /* 428 * If no current/default channel is setup or the current 429 * channel is wrong for the mode then pick the first 430 * available channel from the active list. This is likely 431 * not the right one. 432 */ 433 if (ic->ic_ibss_chan == NULL || 434 ieee80211_isclr(ic->ic_chan_active, 435 ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { 436 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 437 if (ieee80211_isset(ic->ic_chan_active, i)) { 438 ic->ic_ibss_chan = &ic->ic_sup_channels[i]; 439 break; 440 } 441 } 442 } 443 /* 444 * If the desired channel is set but no longer valid then reset it. 445 */ 446 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 447 ieee80211_isclr(ic->ic_chan_active, 448 ieee80211_chan2ieee(ic, ic->ic_des_chan))) { 449 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 450 } 451 452 /* 453 * Do mode-specific rate setup. 454 */ 455 if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11B) 456 ieee80211_setbasicrates(&ic->ic_sup_rates[mode], mode); 457 458 /* 459 * Setup an initial rate set according to the 460 * current/default channel. This will be changed 461 * when scanning but must exist now so drivers have 462 * consistent state of ic_bsschan. 463 */ 464 if (ic->ic_bss != NULL) 465 ic->ic_bss->in_rates = ic->ic_sup_rates[mode]; 466 ic->ic_curmode = mode; 467 ieee80211_reset_erp(ic); /* reset ERP state */ 468 469 return (0); 470 } 471 472 /* 473 * Return the phy mode for with the specified channel so the 474 * caller can select a rate set. This is problematic for channels 475 * where multiple operating modes are possible (e.g. 11g+11b). 476 * In those cases we defer to the current operating mode when set. 477 */ 478 enum ieee80211_phymode 479 ieee80211_chan2mode(ieee80211com_t *ic, struct ieee80211_channel *chan) 480 { 481 if (IEEE80211_IS_CHAN_T(chan)) { 482 return (IEEE80211_MODE_TURBO_A); 483 } else if (IEEE80211_IS_CHAN_5GHZ(chan)) { 484 return (IEEE80211_MODE_11A); 485 } else if (IEEE80211_IS_CHAN_FHSS(chan)) { 486 return (IEEE80211_MODE_FH); 487 } else if (chan->ich_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN)) { 488 /* 489 * This assumes all 11g channels are also usable 490 * for 11b, which is currently true. 491 */ 492 if (ic->ic_curmode == IEEE80211_MODE_TURBO_G) 493 return (IEEE80211_MODE_TURBO_G); 494 if (ic->ic_curmode == IEEE80211_MODE_11B) 495 return (IEEE80211_MODE_11B); 496 return (IEEE80211_MODE_11G); 497 } else { 498 return (IEEE80211_MODE_11B); 499 } 500 } 501 502 /* 503 * Return the size of the 802.11 header for a management or data frame. 504 */ 505 int 506 ieee80211_hdrspace(const void *data) 507 { 508 const struct ieee80211_frame *wh = data; 509 int size = sizeof (struct ieee80211_frame); 510 511 /* NB: we don't handle control frames */ 512 ASSERT((wh->i_fc[0]&IEEE80211_FC0_TYPE_MASK) != 513 IEEE80211_FC0_TYPE_CTL); 514 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) 515 size += IEEE80211_ADDR_LEN; 516 517 return (size); 518 } 519 520 /* 521 * Allocate and setup a management frame of the specified 522 * size. We return the mblk and a pointer to the start 523 * of the contiguous data area that's been reserved based 524 * on the packet length. 525 */ 526 mblk_t * 527 ieee80211_getmgtframe(uint8_t **frm, int pktlen) 528 { 529 mblk_t *mp; 530 int len; 531 532 len = sizeof (struct ieee80211_frame) + pktlen; 533 mp = allocb(len, BPRI_MED); 534 if (mp != NULL) { 535 *frm = mp->b_rptr + sizeof (struct ieee80211_frame); 536 mp->b_wptr = mp->b_rptr + len; 537 } else { 538 ieee80211_err("ieee80211_getmgtframe: " 539 "alloc frame failed, %d\n", len); 540 } 541 return (mp); 542 } 543 544 /* 545 * Send system messages to notify the device has joined a WLAN. 546 * This is an OS specific function. Solaris marks link status 547 * as up. 548 */ 549 void 550 ieee80211_notify_node_join(ieee80211com_t *ic, ieee80211_node_t *in) 551 { 552 if (in == ic->ic_bss) 553 mac_link_update(ic->ic_mach, LINK_STATE_UP); 554 ieee80211_notify(ic, EVENT_ASSOC); /* notify WPA service */ 555 } 556 557 /* 558 * Send system messages to notify the device has left a WLAN. 559 * This is an OS specific function. Solaris marks link status 560 * as down. 561 */ 562 void 563 ieee80211_notify_node_leave(ieee80211com_t *ic, ieee80211_node_t *in) 564 { 565 if (in == ic->ic_bss) 566 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 567 ieee80211_notify(ic, EVENT_DISASSOC); /* notify WPA service */ 568 } 569 570 /* 571 * Get 802.11 kstats defined in ieee802.11(5) 572 * 573 * Return 0 on success 574 */ 575 int 576 ieee80211_stat(ieee80211com_t *ic, uint_t stat, uint64_t *val) 577 { 578 ASSERT(val != NULL); 579 IEEE80211_LOCK(ic); 580 switch (stat) { 581 case WIFI_STAT_TX_FRAGS: 582 *val = ic->ic_stats.is_tx_frags; 583 break; 584 case WIFI_STAT_MCAST_TX: 585 *val = ic->ic_stats.is_tx_mcast; 586 break; 587 case WIFI_STAT_TX_FAILED: 588 *val = ic->ic_stats.is_tx_failed; 589 break; 590 case WIFI_STAT_TX_RETRANS: 591 *val = ic->ic_stats.is_tx_retries; 592 break; 593 case WIFI_STAT_RTS_SUCCESS: 594 *val = ic->ic_stats.is_rts_success; 595 break; 596 case WIFI_STAT_RTS_FAILURE: 597 *val = ic->ic_stats.is_rts_failure; 598 break; 599 case WIFI_STAT_ACK_FAILURE: 600 *val = ic->ic_stats.is_ack_failure; 601 break; 602 case WIFI_STAT_RX_FRAGS: 603 *val = ic->ic_stats.is_rx_frags; 604 break; 605 case WIFI_STAT_MCAST_RX: 606 *val = ic->ic_stats.is_rx_mcast; 607 break; 608 case WIFI_STAT_RX_DUPS: 609 *val = ic->ic_stats.is_rx_dups; 610 break; 611 case WIFI_STAT_FCS_ERRORS: 612 *val = ic->ic_stats.is_fcs_errors; 613 break; 614 case WIFI_STAT_WEP_ERRORS: 615 *val = ic->ic_stats.is_wep_errors; 616 break; 617 } 618 IEEE80211_UNLOCK(ic); 619 return (0); 620 } 621 622 /* 623 * Attach network interface to the 802.11 support module. This 624 * function must be called before using any of the ieee80211 625 * functionss. The parameter "ic" MUST be initialized to tell 626 * net80211 about interface's capabilities. 627 */ 628 void 629 ieee80211_attach(ieee80211com_t *ic) 630 { 631 struct ieee80211_impl *im; 632 struct ieee80211_channel *ch; 633 int i; 634 635 /* Check mandatory callback functions not NULL */ 636 ASSERT(ic->ic_xmit != NULL); 637 638 mutex_init(&ic->ic_genlock, NULL, MUTEX_DRIVER, NULL); 639 mutex_init(&ic->ic_doorlock, NULL, MUTEX_DRIVER, NULL); 640 641 im = kmem_alloc(sizeof (ieee80211_impl_t), KM_SLEEP); 642 ic->ic_private = im; 643 cv_init(&im->im_scan_cv, NULL, CV_DRIVER, NULL); 644 645 /* 646 * Fill in 802.11 available channel set, mark 647 * all available channels as active, and pick 648 * a default channel if not already specified. 649 */ 650 bzero(im->im_chan_avail, sizeof (im->im_chan_avail)); 651 ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO; 652 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 653 ch = &ic->ic_sup_channels[i]; 654 if (ch->ich_flags) { 655 /* Verify driver passed us valid data */ 656 if (i != ieee80211_chan2ieee(ic, ch)) { 657 ieee80211_err("bad channel ignored: " 658 "freq %u flags%x number %u\n", 659 ch->ich_freq, ch->ich_flags, i); 660 ch->ich_flags = 0; 661 continue; 662 } 663 ieee80211_setbit(im->im_chan_avail, i); 664 /* Identify mode capabilities */ 665 if (IEEE80211_IS_CHAN_A(ch)) 666 ic->ic_modecaps |= 1 << IEEE80211_MODE_11A; 667 if (IEEE80211_IS_CHAN_B(ch)) 668 ic->ic_modecaps |= 1 << IEEE80211_MODE_11B; 669 if (IEEE80211_IS_CHAN_PUREG(ch)) 670 ic->ic_modecaps |= 1 << IEEE80211_MODE_11G; 671 if (IEEE80211_IS_CHAN_FHSS(ch)) 672 ic->ic_modecaps |= 1 << IEEE80211_MODE_FH; 673 if (IEEE80211_IS_CHAN_T(ch)) 674 ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_A; 675 if (IEEE80211_IS_CHAN_108G(ch)) 676 ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_G; 677 if (ic->ic_curchan == NULL) { 678 /* arbitrarily pick the first channel */ 679 ic->ic_curchan = &ic->ic_sup_channels[i]; 680 } 681 } 682 } 683 /* validate ic->ic_curmode */ 684 if ((ic->ic_modecaps & (1 << ic->ic_curmode)) == 0) 685 ic->ic_curmode = IEEE80211_MODE_AUTO; 686 ic->ic_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */ 687 (void) ieee80211_setmode(ic, ic->ic_curmode); 688 689 if (ic->ic_caps & IEEE80211_C_BURST) 690 ic->ic_flags |= IEEE80211_F_BURST; 691 ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT; 692 ic->ic_lintval = ic->ic_bintval; 693 ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; 694 ic->ic_bmissthreshold = IEEE80211_HWBMISS_DEFAULT; 695 696 ic->ic_reset = ieee80211_default_reset; 697 698 ieee80211_node_attach(ic); 699 ieee80211_proto_attach(ic); 700 ieee80211_crypto_attach(ic); 701 702 ic->ic_watchdog_timer = 0; 703 } 704 705 /* 706 * Free any ieee80211 structures associated with the driver. 707 */ 708 void 709 ieee80211_detach(ieee80211com_t *ic) 710 { 711 struct ieee80211_impl *im = ic->ic_private; 712 713 ieee80211_stop_watchdog(ic); 714 cv_destroy(&im->im_scan_cv); 715 kmem_free(im, sizeof (ieee80211_impl_t)); 716 717 if (ic->ic_opt_ie != NULL) 718 ieee80211_free(ic->ic_opt_ie); 719 720 ieee80211_node_detach(ic); 721 ieee80211_crypto_detach(ic); 722 723 mutex_destroy(&ic->ic_genlock); 724 mutex_destroy(&ic->ic_doorlock); 725 } 726 727 static struct modlmisc i_wifi_modlmisc = { 728 &mod_miscops, 729 "IEEE80211 Kernel Module v1.3" 730 }; 731 732 static struct modlinkage i_wifi_modlinkage = { 733 MODREV_1, 734 &i_wifi_modlmisc, 735 NULL 736 }; 737 738 /* 739 * modlinkage functions 740 */ 741 int 742 _init(void) 743 { 744 return (mod_install(&i_wifi_modlinkage)); 745 } 746 747 int 748 _fini(void) 749 { 750 return (mod_remove(&i_wifi_modlinkage)); 751 } 752 753 int 754 _info(struct modinfo *modinfop) 755 { 756 return (mod_info(&i_wifi_modlinkage, modinfop)); 757 } 758