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