1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer, 15 * without modification. 16 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 17 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 18 * redistribution must be conditioned upon including a substantially 19 * similar Disclaimer requirement for further binary redistribution. 20 * 3. Neither the names of the above-listed copyright holders nor the names 21 * of any contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * NO WARRANTY 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 28 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 29 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 30 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 33 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 35 * THE POSSIBILITY OF SUCH DAMAGES. 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 #include <sys/param.h> 41 #include <sys/types.h> 42 #include <sys/signal.h> 43 #include <sys/stream.h> 44 #include <sys/termio.h> 45 #include <sys/errno.h> 46 #include <sys/file.h> 47 #include <sys/cmn_err.h> 48 #include <sys/stropts.h> 49 #include <sys/strsubr.h> 50 #include <sys/strtty.h> 51 #include <sys/kbio.h> 52 #include <sys/cred.h> 53 #include <sys/stat.h> 54 #include <sys/consdev.h> 55 #include <sys/kmem.h> 56 #include <sys/modctl.h> 57 #include <sys/ddi.h> 58 #include <sys/sunddi.h> 59 #include <sys/pci.h> 60 #include <sys/errno.h> 61 #include <sys/gld.h> 62 #include <sys/dlpi.h> 63 #include <sys/ethernet.h> 64 #include <sys/list.h> 65 #include <sys/byteorder.h> 66 #include <sys/strsun.h> 67 #include <inet/common.h> 68 #include <inet/nd.h> 69 #include <inet/mi.h> 70 #include <inet/wifi_ioctl.h> 71 #include "ath_hal.h" 72 #include "ath_impl.h" 73 74 static const char *acnames[] = { 75 "WME_AC_BE", 76 "WME_AC_BK", 77 "WME_AC_VI", 78 "WME_AC_VO", 79 "WME_UPSD" 80 }; 81 82 extern void ath_setup_desc(ath_t *asc, struct ath_buf *bf); 83 84 85 const char * 86 ath_get_hal_status_desc(HAL_STATUS status) 87 { 88 static const char *hal_status_desc[] = { 89 "No error", 90 "No hardware present or device not yet supported", 91 "Memory allocation failed", 92 "Hardware didn't respond as expected", 93 "EEPROM magic number invalid", 94 "EEPROM version invalid", 95 "EEPROM unreadable", 96 "EEPROM checksum invalid", 97 "EEPROM read problem", 98 "EEPROM mac address invalid", 99 "EEPROM size not supported", 100 "Attempt to change write-locked EEPROM", 101 "Invalid parameter to function", 102 "Hardware revision not supported", 103 "Hardware self-test failed", 104 "Operation incomplete" 105 }; 106 107 if (status >= 0 && status < sizeof (hal_status_desc)/sizeof (char *)) 108 return (hal_status_desc[status]); 109 else 110 return (""); 111 } 112 113 uint32_t 114 ath_calcrxfilter(ath_t *asc) 115 { 116 ieee80211com_t *ic = (ieee80211com_t *)asc; 117 struct ath_hal *ah = asc->asc_ah; 118 uint32_t rfilt; 119 120 rfilt = (ATH_HAL_GETRXFILTER(ah) & HAL_RX_FILTER_PHYERR) 121 | HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST; 122 if (ic->ic_opmode != IEEE80211_M_STA) 123 rfilt |= HAL_RX_FILTER_PROBEREQ; 124 if (ic->ic_opmode != IEEE80211_M_HOSTAP && asc->asc_promisc) 125 rfilt |= HAL_RX_FILTER_PROM; /* promiscuous */ 126 if (ic->ic_opmode == IEEE80211_M_STA || 127 ic->ic_opmode == IEEE80211_M_IBSS || 128 ic->ic_state == IEEE80211_S_SCAN) 129 rfilt |= HAL_RX_FILTER_BEACON; 130 return (rfilt); 131 } 132 133 static int 134 ath_set_data_queue(ath_t *asc, int ac, int haltype) 135 { 136 HAL_TXQ_INFO qi; 137 int qnum; 138 struct ath_hal *ah = asc->asc_ah; 139 struct ath_txq *txq; 140 141 if (ac >= ATH_N(asc->asc_ac2q)) { 142 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_set_data_queue(): " 143 "ac %u out of range, max %u!\n", 144 ac, ATH_N(asc->asc_ac2q))); 145 return (1); 146 } 147 (void) memset(&qi, 0, sizeof (qi)); 148 qi.tqi_subtype = haltype; 149 /* 150 * Enable interrupts only for EOL and DESC conditions. 151 * We mark tx descriptors to receive a DESC interrupt 152 * when a tx queue gets deep; otherwise waiting for the 153 * EOL to reap descriptors. Note that this is done to 154 * reduce interrupt load and this only defers reaping 155 * descriptors, never transmitting frames. Aside from 156 * reducing interrupts this also permits more concurrency. 157 * The only potential downside is if the tx queue backs 158 * up in which case the top half of the kernel may backup 159 * due to a lack of tx descriptors. 160 */ 161 qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | HAL_TXQ_TXDESCINT_ENABLE; 162 qnum = ATH_HAL_SETUPTXQUEUE(ah, HAL_TX_QUEUE_DATA, &qi); 163 if (qnum == -1) { 164 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_set_data_queue(): " 165 "Unable to setup hardware queue for %s traffic!\n", 166 acnames[ac])); 167 return (1); 168 } 169 if (qnum >= ATH_N(asc->asc_txq)) { 170 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_set_data_queue(): " 171 "hal qnum %u out of range, max %u!\n", 172 qnum, ATH_N(asc->asc_txq))); 173 return (1); 174 } 175 if (!ATH_TXQ_SETUP(asc, qnum)) { 176 txq = &asc->asc_txq[qnum]; 177 txq->axq_qnum = qnum; 178 txq->axq_depth = 0; 179 txq->axq_intrcnt = 0; 180 txq->axq_link = NULL; 181 list_create(&txq->axq_list, sizeof (struct ath_buf), 182 offsetof(struct ath_buf, bf_node)); 183 mutex_init(&txq->axq_lock, NULL, MUTEX_DRIVER, NULL); 184 asc->asc_txqsetup |= 1<<qnum; 185 } 186 asc->asc_ac2q[ac] = &asc->asc_txq[qnum]; 187 return (0); 188 } 189 190 int 191 ath_txq_setup(ath_t *asc) 192 { 193 if (ath_set_data_queue(asc, WME_AC_BE, HAL_WME_AC_BK) || 194 ath_set_data_queue(asc, WME_AC_BK, HAL_WME_AC_BE) || 195 ath_set_data_queue(asc, WME_AC_VI, HAL_WME_AC_VI) || 196 ath_set_data_queue(asc, WME_AC_VO, HAL_WME_AC_VO)) { 197 return (1); 198 } 199 200 return (0); 201 } 202 203 void 204 ath_txq_cleanup(ath_t *asc) 205 { 206 int i; 207 208 mutex_destroy(&asc->asc_txbuflock); 209 for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 210 if (ATH_TXQ_SETUP(asc, i)) { 211 struct ath_txq *txq = &asc->asc_txq[i]; 212 213 ATH_HAL_RELEASETXQUEUE(asc->asc_ah, txq->axq_qnum); 214 mutex_destroy(&txq->axq_lock); 215 asc->asc_txqsetup &= ~(1 << txq->axq_qnum); 216 } 217 } 218 } 219 220 void 221 ath_setcurmode(ath_t *asc, enum ieee80211_phymode mode) 222 { 223 const HAL_RATE_TABLE *rt; 224 int i; 225 226 for (i = 0; i < sizeof (asc->asc_rixmap); i++) 227 asc->asc_rixmap[i] = 0xff; 228 229 rt = asc->asc_rates[mode]; 230 ASSERT(rt != NULL); 231 232 for (i = 0; i < rt->rateCount; i++) 233 asc->asc_rixmap[rt->info[i].dot11Rate & IEEE80211_RATE_VAL] = (uint8_t)i; 234 235 asc->asc_currates = rt; 236 asc->asc_curmode = mode; 237 } 238 239 /* Set correct parameters for a certain mode */ 240 void 241 ath_mode_init(ath_t *asc) 242 { 243 ieee80211com_t *ic = (ieee80211com_t *)asc; 244 struct ath_hal *ah = asc->asc_ah; 245 uint32_t rfilt; 246 247 /* configure rx filter */ 248 rfilt = ath_calcrxfilter(asc); 249 ATH_HAL_SETRXFILTER(ah, rfilt); 250 ATH_HAL_SETOPMODE(ah); 251 ATH_HAL_SETMCASTFILTER(ah, asc->asc_mcast_hash[0], 252 asc->asc_mcast_hash[1]); 253 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_mode_init(): " 254 "mode =%d RX filter 0x%x, MC filter %08x:%08x\n", 255 ic->ic_opmode, rfilt, 256 asc->asc_mcast_hash[0], asc->asc_mcast_hash[1])); 257 } 258 259 /* 260 * Disable the receive h/w in preparation for a reset. 261 */ 262 void 263 ath_stoprecv(ath_t *asc) 264 { 265 ATH_HAL_STOPPCURECV(asc->asc_ah); /* disable PCU */ 266 ATH_HAL_SETRXFILTER(asc->asc_ah, 0); /* clear recv filter */ 267 ATH_HAL_STOPDMARECV(asc->asc_ah); /* disable DMA engine */ 268 drv_usecwait(3000); 269 270 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_stoprecv(): rx queue %p, link %p\n", 271 ATH_HAL_GETRXBUF(asc->asc_ah), asc->asc_rxlink)); 272 asc->asc_rxlink = NULL; 273 } 274 275 uint32_t 276 ath_chan2flags(ieee80211com_t *isc, struct ieee80211_channel *chan) 277 { 278 static const uint32_t modeflags[] = { 279 0, /* IEEE80211_MODE_AUTO */ 280 CHANNEL_A, /* IEEE80211_MODE_11A */ 281 CHANNEL_B, /* IEEE80211_MODE_11B */ 282 CHANNEL_PUREG, /* IEEE80211_MODE_11G */ 283 0, /* IEEE80211_MODE_FH */ 284 CHANNEL_108A, /* IEEE80211_MODE_TURBO_A */ 285 CHANNEL_108G /* IEEE80211_MODE_TURBO_G */ 286 }; 287 return (modeflags[ieee80211_chan2mode(isc, chan)]); 288 } 289 290 291 int 292 ath_getchannels(ath_t *asc, uint32_t cc, HAL_BOOL outdoor, HAL_BOOL xchanmode) 293 { 294 ieee80211com_t *ic = (ieee80211com_t *)asc; 295 struct ath_hal *ah = asc->asc_ah; 296 HAL_CHANNEL *chans; 297 int i, ix; 298 uint32_t nchan; 299 300 chans = (HAL_CHANNEL *) 301 kmem_zalloc(IEEE80211_CHAN_MAX * sizeof (HAL_CHANNEL), KM_SLEEP); 302 303 if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan, 304 NULL, 0, NULL, cc, HAL_MODE_ALL, outdoor, xchanmode)) { 305 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_getchannels(): " 306 "unable to get channel list\n")); 307 kmem_free(chans, IEEE80211_CHAN_MAX * sizeof (HAL_CHANNEL)); 308 return (EINVAL); 309 } 310 311 /* 312 * Convert HAL channels to ieee80211 ones and insert 313 * them in the table according to their channel number. 314 */ 315 for (i = 0; i < nchan; i++) { 316 HAL_CHANNEL *c = &chans[i]; 317 uint16_t flags; 318 ix = ath_hal_mhz2ieee(ah, c->channel, c->channelFlags); 319 if (ix > IEEE80211_CHAN_MAX) { 320 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_getchannels(): " 321 "bad hal channel %d (%u/%x) ignored\n", 322 ix, c->channel, c->channelFlags)); 323 continue; 324 } 325 /* NB: flags are known to be compatible */ 326 if (ix < 0) { 327 /* 328 * can't handle frequency <2400MHz (negative 329 * channels) right now 330 */ 331 ATH_DEBUG((ATH_DBG_AUX, "ath:ath_getchannels(): " 332 "hal channel %d (%u/%x) " 333 "cannot be handled, ignored\n", 334 ix, c->channel, c->channelFlags)); 335 continue; 336 } 337 /* 338 * Calculate net80211 flags; most are compatible 339 * but some need massaging. Note the static turbo 340 * conversion can be removed once net80211 is updated 341 * to understand static vs. dynamic turbo. 342 */ 343 flags = c->channelFlags & CHANNEL_COMPAT; 344 if (c->channelFlags & CHANNEL_STURBO) 345 flags |= IEEE80211_CHAN_TURBO; 346 if (ic->ic_sup_channels[ix].ich_freq == 0) { 347 ic->ic_sup_channels[ix].ich_freq = c->channel; 348 ic->ic_sup_channels[ix].ich_flags = flags; 349 } else { 350 /* channels overlap; e.g. 11g and 11b */ 351 ic->ic_sup_channels[ix].ich_flags |= flags; 352 } 353 if ((c->channelFlags & CHANNEL_G) == CHANNEL_G) 354 asc->asc_have11g = 1; 355 } 356 kmem_free(chans, IEEE80211_CHAN_MAX * sizeof (HAL_CHANNEL)); 357 return (0); 358 } 359 360 static void 361 ath_drainq(ath_t *asc, struct ath_txq *txq) 362 { 363 struct ath_buf *bf; 364 365 /* 366 * This assumes output has been stopped. 367 */ 368 for (;;) { 369 mutex_enter(&txq->axq_lock); 370 bf = list_head(&txq->axq_list); 371 if (bf == NULL) { 372 txq->axq_link = NULL; 373 mutex_exit(&txq->axq_lock); 374 break; 375 } 376 list_remove(&txq->axq_list, bf); 377 mutex_exit(&txq->axq_lock); 378 bf->bf_in = NULL; 379 mutex_enter(&asc->asc_txbuflock); 380 list_insert_tail(&asc->asc_txbuf_list, bf); 381 mutex_exit(&asc->asc_txbuflock); 382 } 383 } 384 385 386 /* 387 * Drain the transmit queues and reclaim resources. 388 */ 389 void 390 ath_draintxq(ath_t *asc) 391 { 392 struct ath_hal *ah = asc->asc_ah; 393 struct ath_txq *txq; 394 int i; 395 396 if (!asc->asc_invalid) { 397 for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 398 if (ATH_TXQ_SETUP(asc, i)) { 399 txq = &asc->asc_txq[i]; 400 (void) ATH_HAL_STOPTXDMA(ah, txq->axq_qnum); 401 } 402 } 403 } 404 for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 405 if (ATH_TXQ_SETUP(asc, i)) { 406 ath_drainq(asc, &asc->asc_txq[i]); 407 } 408 } 409 } 410 411 412 /* Enable the receive h/w following a reset */ 413 int 414 ath_startrecv(ath_t *asc) 415 { 416 struct ath_buf *bf; 417 418 asc->asc_rxlink = NULL; 419 420 bf = list_head(&asc->asc_rxbuf_list); 421 while (bf != NULL) { 422 ath_setup_desc(asc, bf); 423 bf = list_next(&asc->asc_rxbuf_list, bf); 424 } 425 426 bf = list_head(&asc->asc_rxbuf_list); 427 ATH_HAL_PUTRXBUF(asc->asc_ah, bf->bf_daddr); 428 ATH_HAL_RXENA(asc->asc_ah); /* enable recv descriptors */ 429 ath_mode_init(asc); /* set filters, etc. */ 430 ATH_HAL_STARTPCURECV(asc->asc_ah); /* re-enable PCU/DMA engine */ 431 return (0); 432 } 433 434 /* 435 * Update internal state after a channel change. 436 */ 437 void 438 ath_chan_change(ath_t *asc, struct ieee80211_channel *chan) 439 { 440 struct ieee80211com *ic = &asc->asc_isc; 441 enum ieee80211_phymode mode; 442 443 /* 444 * Change channels and update the h/w rate map 445 * if we're switching; e.g. 11a to 11b/g. 446 */ 447 mode = ieee80211_chan2mode(ic, chan); 448 if (mode != asc->asc_curmode) 449 ath_setcurmode(asc, mode); 450 } 451 452 /* 453 * Set/change channels. If the channel is really being changed, 454 * it's done by resetting the chip. To accomplish this we must 455 * first cleanup any pending DMA. 456 */ 457 int 458 ath_chan_set(ath_t *asc, struct ieee80211_channel *chan) 459 { 460 struct ath_hal *ah = asc->asc_ah; 461 ieee80211com_t *ic = &asc->asc_isc; 462 463 if (chan != ic->ic_ibss_chan) { 464 HAL_STATUS status; 465 HAL_CHANNEL hchan; 466 467 /* 468 * To switch channels clear any pending DMA operations; 469 * wait long enough for the RX fifo to drain, reset the 470 * hardware at the new frequency, and then re-enable 471 * the relevant bits of the h/w. 472 */ 473 ATH_HAL_INTRSET(ah, 0); /* disable interrupts */ 474 ath_draintxq(asc); /* clear pending tx frames */ 475 ath_stoprecv(asc); /* turn off frame recv */ 476 /* 477 * Convert to a HAL channel description with 478 * the flags constrained to reflect the current 479 * operating mode. 480 */ 481 hchan.channel = chan->ich_freq; 482 hchan.channelFlags = ath_chan2flags(ic, chan); 483 if (!ATH_HAL_RESET(ah, (HAL_OPMODE)ic->ic_opmode, 484 &hchan, AH_TRUE, &status)) { 485 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_chan_set():" 486 "unable to reset channel %u (%uMhz)\n" 487 "flags 0x%x: '%s' (HAL status %u)\n", 488 ieee80211_chan2ieee(ic, chan), hchan.channel, 489 hchan.channelFlags, 490 ath_get_hal_status_desc(status), status)); 491 return (EIO); 492 } 493 asc->asc_curchan = hchan; 494 495 /* 496 * Re-enable rx framework. 497 */ 498 if (ath_startrecv(asc) != 0) { 499 ath_problem("ath: ath_chan_set(): " 500 "restarting receiving logic failed\n"); 501 return (EIO); 502 } 503 504 /* 505 * Change channels and update the h/w rate map 506 * if we're switching; e.g. 11a to 11b/g. 507 */ 508 ic->ic_ibss_chan = chan; 509 ath_chan_change(asc, chan); 510 /* 511 * Re-enable interrupts. 512 */ 513 ATH_HAL_INTRSET(ah, asc->asc_imask); 514 } 515 return (0); 516 } 517 518 519 /* 520 * Configure the beacon and sleep timers. 521 * 522 * When operating as an AP this resets the TSF and sets 523 * up the hardware to notify us when we need to issue beacons. 524 * 525 * When operating in station mode this sets up the beacon 526 * timers according to the timestamp of the last received 527 * beacon and the current TSF, configures PCF and DTIM 528 * handling, programs the sleep registers so the hardware 529 * will wakeup in time to receive beacons, and configures 530 * the beacon miss handling so we'll receive a BMISS 531 * interrupt when we stop seeing beacons from the AP 532 * we've associated with. 533 */ 534 void 535 ath_beacon_config(ath_t *asc) 536 { 537 struct ath_hal *ah = asc->asc_ah; 538 ieee80211com_t *ic = (ieee80211com_t *)asc; 539 struct ieee80211_node *in = ic->ic_bss; 540 uint32_t nexttbtt; 541 542 nexttbtt = (ATH_LE_READ_4(in->in_tstamp.data + 4) << 22) | 543 (ATH_LE_READ_4(in->in_tstamp.data) >> 10); 544 nexttbtt += in->in_intval; 545 if (ic->ic_opmode != IEEE80211_M_HOSTAP) { 546 HAL_BEACON_STATE bs; 547 548 /* NB: no PCF support right now */ 549 bzero(&bs, sizeof (bs)); 550 bs.bs_intval = in->in_intval; 551 bs.bs_nexttbtt = nexttbtt; 552 bs.bs_dtimperiod = bs.bs_intval; 553 bs.bs_nextdtim = nexttbtt; 554 555 /* 556 * Setup the number of consecutive beacons to miss 557 * before taking a BMISS interrupt. 558 * Note that we clamp the result to at most 10 beacons. 559 */ 560 bs.bs_bmissthreshold = ic->ic_bmissthreshold; 561 if (bs.bs_bmissthreshold > 10) 562 bs.bs_bmissthreshold = 10; 563 else if (bs.bs_bmissthreshold < 1) 564 bs.bs_bmissthreshold = 1; 565 /* 566 * Calculate sleep duration. The configuration is 567 * given in ms. We insure a multiple of the beacon 568 * period is used. Also, if the sleep duration is 569 * greater than the DTIM period then it makes senses 570 * to make it a multiple of that. 571 */ 572 bs.bs_sleepduration = 573 roundup((100 * 1000) / 1024, bs.bs_intval); 574 if (bs.bs_sleepduration > bs.bs_dtimperiod) 575 bs.bs_sleepduration = 576 roundup(bs.bs_sleepduration, bs.bs_dtimperiod); 577 578 579 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_beacon_config(): " 580 "intval %u nexttbtt %u dtim %u" 581 " nextdtim %u bmiss %u sleep %u\n", 582 bs.bs_intval, 583 bs.bs_nexttbtt, 584 bs.bs_dtimperiod, 585 bs.bs_nextdtim, 586 bs.bs_bmissthreshold, 587 bs.bs_sleepduration)); 588 ATH_HAL_INTRSET(ah, 0); 589 /* 590 * Reset our tsf so the hardware will update the 591 * tsf register to reflect timestamps found in 592 * received beacons. 593 */ 594 ATH_HAL_RESETTSF(ah); 595 ATH_HAL_BEACONTIMERS(ah, &bs); 596 asc->asc_imask |= HAL_INT_BMISS; 597 ATH_HAL_INTRSET(ah, asc->asc_imask); 598 } else { 599 ATH_HAL_INTRSET(ah, 0); 600 ATH_HAL_BEACONINIT(ah, nexttbtt, in->in_intval); 601 asc->asc_imask |= HAL_INT_SWBA; /* beacon prepare */ 602 ATH_HAL_INTRSET(ah, asc->asc_imask); 603 } 604 } 605 606 /* 607 * Allocate tx/rx key slots for TKIP. We allocate two slots for 608 * each key, one for decrypt/encrypt and the other for the MIC. 609 */ 610 static int 611 key_alloc_2pair(ath_t *asc, ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) 612 { 613 uint16_t i, keyix; 614 615 ASSERT(asc->asc_splitmic); 616 for (i = 0; i < ATH_N(asc->asc_keymap)/4; i++) { 617 uint8_t b = asc->asc_keymap[i]; 618 if (b != 0xff) { 619 /* 620 * One or more slots in this byte are free. 621 */ 622 keyix = i*NBBY; 623 while (b & 1) { 624 again: 625 keyix++; 626 b >>= 1; 627 } 628 /* XXX IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV */ 629 if (isset(asc->asc_keymap, keyix+32) || 630 isset(asc->asc_keymap, keyix+64) || 631 isset(asc->asc_keymap, keyix+32+64)) { 632 /* full pair unavailable */ 633 if (keyix == (i+1)*NBBY) { 634 /* no slots were appropriate, advance */ 635 continue; 636 } 637 goto again; 638 } 639 setbit(asc->asc_keymap, keyix); 640 setbit(asc->asc_keymap, keyix+64); 641 setbit(asc->asc_keymap, keyix+32); 642 setbit(asc->asc_keymap, keyix+32+64); 643 ATH_DEBUG((ATH_DBG_AUX, 644 "key_alloc_2pair: key pair %u,%u %u,%u\n", 645 keyix, keyix+64, 646 keyix+32, keyix+32+64)); 647 *txkeyix = *rxkeyix = keyix; 648 return (1); 649 } 650 } 651 ATH_DEBUG((ATH_DBG_AUX, "key_alloc_2pair:" 652 " out of pair space\n")); 653 return (0); 654 } 655 /* 656 * Allocate a single key cache slot. 657 */ 658 static int 659 key_alloc_single(ath_t *asc, ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) 660 { 661 uint16_t i, keyix; 662 663 /* try i,i+32,i+64,i+32+64 to minimize key pair conflicts */ 664 for (i = 0; i < ATH_N(asc->asc_keymap); i++) { 665 uint8_t b = asc->asc_keymap[i]; 666 667 if (b != 0xff) { 668 /* 669 * One or more slots are free. 670 */ 671 keyix = i*NBBY; 672 while (b & 1) 673 keyix++, b >>= 1; 674 setbit(asc->asc_keymap, keyix); 675 ATH_DEBUG((ATH_DBG_AUX, "key_alloc_single:" 676 " key %u\n", keyix)); 677 *txkeyix = *rxkeyix = keyix; 678 return (1); 679 } 680 } 681 return (0); 682 } 683 684 /* 685 * Allocate one or more key cache slots for a unicast key. The 686 * key itself is needed only to identify the cipher. For hardware 687 * TKIP with split cipher+MIC keys we allocate two key cache slot 688 * pairs so that we can setup separate TX and RX MIC keys. Note 689 * that the MIC key for a TKIP key at slot i is assumed by the 690 * hardware to be at slot i+64. This limits TKIP keys to the first 691 * 64 entries. 692 */ 693 /* ARGSUSED */ 694 int 695 ath_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k, 696 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 697 { 698 ath_t *asc = (ath_t *)ic; 699 700 /* 701 * We allocate two pair for TKIP when using the h/w to do 702 * the MIC. For everything else, including software crypto, 703 * we allocate a single entry. Note that s/w crypto requires 704 * a pass-through slot on the 5211 and 5212. The 5210 does 705 * not support pass-through cache entries and we map all 706 * those requests to slot 0. 707 */ 708 if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { 709 return (key_alloc_single(asc, keyix, rxkeyix)); 710 } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP && 711 (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && asc->asc_splitmic) { 712 return (key_alloc_2pair(asc, keyix, rxkeyix)); 713 } else { 714 return (key_alloc_single(asc, keyix, rxkeyix)); 715 } 716 } 717 718 /* 719 * Delete an entry in the key cache allocated by ath_key_alloc. 720 */ 721 int 722 ath_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k) 723 { 724 ath_t *asc = (ath_t *)ic; 725 struct ath_hal *ah = asc->asc_ah; 726 const struct ieee80211_cipher *cip = k->wk_cipher; 727 ieee80211_keyix keyix = k->wk_keyix; 728 729 ATH_DEBUG((ATH_DBG_AUX, "ath_key_delete:" 730 " delete key %u ic_cipher=0x%x\n", keyix, cip->ic_cipher)); 731 732 ATH_HAL_KEYRESET(ah, keyix); 733 /* 734 * Handle split tx/rx keying required for TKIP with h/w MIC. 735 */ 736 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && 737 (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && asc->asc_splitmic) 738 ATH_HAL_KEYRESET(ah, keyix+32); /* RX key */ 739 740 if (keyix >= IEEE80211_WEP_NKID) { 741 /* 742 * Don't touch keymap entries for global keys so 743 * they are never considered for dynamic allocation. 744 */ 745 clrbit(asc->asc_keymap, keyix); 746 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && 747 (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && 748 asc->asc_splitmic) { 749 clrbit(asc->asc_keymap, keyix+64); /* TX key MIC */ 750 clrbit(asc->asc_keymap, keyix+32); /* RX key */ 751 clrbit(asc->asc_keymap, keyix+32+64); /* RX key MIC */ 752 } 753 } 754 return (1); 755 } 756 757 static void 758 ath_keyprint(const char *tag, uint_t ix, 759 const HAL_KEYVAL *hk, const uint8_t mac[IEEE80211_ADDR_LEN]) 760 { 761 static const char *ciphers[] = { 762 "WEP", 763 "AES-OCB", 764 "AES-CCM", 765 "CKIP", 766 "TKIP", 767 "CLR", 768 }; 769 int i, n; 770 char buf[MAX_IEEE80211STR], buft[32]; 771 772 (void) snprintf(buf, sizeof (buf), "%s: [%02u] %s ", 773 tag, ix, ciphers[hk->kv_type]); 774 for (i = 0, n = hk->kv_len; i < n; i++) { 775 (void) snprintf(buft, sizeof (buft), "%02x", hk->kv_val[i]); 776 (void) strlcat(buf, buft, sizeof (buf)); 777 } 778 (void) snprintf(buft, sizeof (buft), " mac %s", 779 ieee80211_macaddr_sprintf(mac)); 780 (void) strlcat(buf, buft, sizeof (buf)); 781 if (hk->kv_type == HAL_CIPHER_TKIP) { 782 (void) snprintf(buft, sizeof (buft), " mic "); 783 (void) strlcat(buf, buft, sizeof (buf)); 784 for (i = 0; i < sizeof (hk->kv_mic); i++) { 785 (void) snprintf(buft, sizeof (buft), "%02x", 786 hk->kv_mic[i]); 787 (void) strlcat(buf, buft, sizeof (buf)); 788 } 789 } 790 ATH_DEBUG((ATH_DBG_AUX, "%s", buf)); 791 } 792 793 /* 794 * Set a TKIP key into the hardware. This handles the 795 * potential distribution of key state to multiple key 796 * cache slots for TKIP. 797 */ 798 static int 799 ath_keyset_tkip(ath_t *asc, const struct ieee80211_key *k, 800 HAL_KEYVAL *hk, const uint8_t mac[IEEE80211_ADDR_LEN]) 801 { 802 #define IEEE80211_KEY_XR (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV) 803 static const uint8_t zerobssid[IEEE80211_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; 804 struct ath_hal *ah = asc->asc_ah; 805 806 ASSERT(k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP); 807 if ((k->wk_flags & IEEE80211_KEY_XR) == IEEE80211_KEY_XR) { 808 /* 809 * TX key goes at first index, RX key at +32. 810 * The hal handles the MIC keys at index+64. 811 */ 812 (void) memcpy(hk->kv_mic, k->wk_txmic, sizeof (hk->kv_mic)); 813 ath_keyprint("ath_keyset_tkip:", k->wk_keyix, hk, zerobssid); 814 if (!ATH_HAL_KEYSET(ah, k->wk_keyix, hk, zerobssid)) 815 return (0); 816 817 (void) memcpy(hk->kv_mic, k->wk_rxmic, sizeof (hk->kv_mic)); 818 ath_keyprint("ath_keyset_tkip:", k->wk_keyix+32, hk, mac); 819 return (ATH_HAL_KEYSET(ah, k->wk_keyix+32, hk, mac)); 820 } else if (k->wk_flags & IEEE80211_KEY_XR) { 821 /* 822 * TX/RX key goes at first index. 823 * The hal handles the MIC keys are index+64. 824 */ 825 (void) memcpy(hk->kv_mic, k->wk_flags & IEEE80211_KEY_XMIT ? 826 k->wk_txmic : k->wk_rxmic, sizeof (hk->kv_mic)); 827 ath_keyprint("ath_keyset_tkip:", k->wk_keyix, hk, zerobssid); 828 return (ATH_HAL_KEYSET(ah, k->wk_keyix, hk, zerobssid)); 829 } 830 return (0); 831 #undef IEEE80211_KEY_XR 832 } 833 834 /* 835 * Set the key cache contents for the specified key. Key cache 836 * slot(s) must already have been allocated by ath_key_alloc. 837 */ 838 int 839 ath_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 840 const uint8_t mac[IEEE80211_ADDR_LEN]) 841 { 842 static const uint8_t ciphermap[] = { 843 HAL_CIPHER_WEP, /* IEEE80211_CIPHER_WEP */ 844 HAL_CIPHER_TKIP, /* IEEE80211_CIPHER_TKIP */ 845 HAL_CIPHER_AES_OCB, /* IEEE80211_CIPHER_AES_OCB */ 846 HAL_CIPHER_AES_CCM, /* IEEE80211_CIPHER_AES_CCM */ 847 HAL_CIPHER_CKIP, /* IEEE80211_CIPHER_CKIP */ 848 HAL_CIPHER_CLR, /* IEEE80211_CIPHER_NONE */ 849 }; 850 ath_t *asc = (ath_t *)ic; 851 struct ath_hal *ah = asc->asc_ah; 852 const struct ieee80211_cipher *cip = k->wk_cipher; 853 HAL_KEYVAL hk; 854 855 bzero(&hk, sizeof (hk)); 856 /* 857 * Software crypto uses a "clear key" so non-crypto 858 * state kept in the key cache are maintainedd so that 859 * rx frames have an entry to match. 860 */ 861 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { 862 ASSERT(cip->ic_cipher < ATH_N(ciphermap)); 863 hk.kv_type = ciphermap[cip->ic_cipher]; 864 hk.kv_len = k->wk_keylen; 865 bcopy(k->wk_key, hk.kv_val, k->wk_keylen); 866 } else { 867 hk.kv_type = HAL_CIPHER_CLR; 868 } 869 870 if (hk.kv_type == HAL_CIPHER_TKIP && 871 (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && 872 asc->asc_splitmic) { 873 return (ath_keyset_tkip(asc, k, &hk, mac)); 874 } else { 875 ath_keyprint("ath_keyset:", k->wk_keyix, &hk, mac); 876 return (ATH_HAL_KEYSET(ah, k->wk_keyix, &hk, mac)); 877 } 878 } 879 880 /* 881 * Enable/Disable short slot timing 882 */ 883 void 884 ath_set_shortslot(ieee80211com_t *ic, int onoff) 885 { 886 struct ath_hal *ah = ((ath_t *)ic)->asc_ah; 887 888 if (onoff) 889 ATH_HAL_SETSLOTTIME(ah, HAL_SLOT_TIME_9); 890 else 891 ATH_HAL_SETSLOTTIME(ah, HAL_SLOT_TIME_20); 892 } 893 894 int 895 ath_reset(ieee80211com_t *ic) 896 { 897 ath_t *asc = (ath_t *)ic; 898 struct ath_hal *ah = asc->asc_ah; 899 struct ieee80211_channel *ch; 900 HAL_STATUS status; 901 902 /* 903 * Convert to a HAL channel description with the flags 904 * constrained to reflect the current operating mode. 905 */ 906 ch = ic->ic_curchan; 907 asc->asc_curchan.channel = ch->ich_freq; 908 asc->asc_curchan.channelFlags = ath_chan2flags(ic, ch); 909 910 ATH_HAL_INTRSET(ah, 0); /* disable interrupts */ 911 ath_draintxq(asc); /* stop xmit side */ 912 if (ATH_IS_RUNNING(asc)) { 913 ath_stoprecv(asc); /* stop recv side */ 914 /* indicate channel change so we do a full reset */ 915 if (!ATH_HAL_RESET(ah, (HAL_OPMODE)ic->ic_opmode, 916 &asc->asc_curchan, AH_TRUE, &status)) { 917 ath_problem("ath: ath_reset(): " 918 "resetting hardware failed, '%s' (HAL status %u)\n", 919 ath_get_hal_status_desc(status), status); 920 } 921 ath_chan_change(asc, ch); 922 } 923 if (ATH_IS_RUNNING(asc)) { 924 if (ath_startrecv(asc) != 0) /* restart recv */ 925 ath_problem("ath: ath_reset(): " 926 "starting receiving logic failed\n"); 927 if (ic->ic_state == IEEE80211_S_RUN) { 928 ath_beacon_config(asc); /* restart beacons */ 929 } 930 ATH_HAL_INTRSET(ah, asc->asc_imask); 931 } 932 return (0); 933 } 934