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