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] = 234 (uint8_t)i; 235 236 asc->asc_currates = rt; 237 asc->asc_curmode = mode; 238 } 239 240 /* Set correct parameters for a certain mode */ 241 void 242 ath_mode_init(ath_t *asc) 243 { 244 ieee80211com_t *ic = (ieee80211com_t *)asc; 245 struct ath_hal *ah = asc->asc_ah; 246 uint32_t rfilt; 247 248 /* configure rx filter */ 249 rfilt = ath_calcrxfilter(asc); 250 ATH_HAL_SETRXFILTER(ah, rfilt); 251 ATH_HAL_SETOPMODE(ah); 252 ATH_HAL_SETMCASTFILTER(ah, asc->asc_mcast_hash[0], 253 asc->asc_mcast_hash[1]); 254 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_mode_init(): " 255 "mode =%d RX filter 0x%x, MC filter %08x:%08x\n", 256 ic->ic_opmode, rfilt, 257 asc->asc_mcast_hash[0], asc->asc_mcast_hash[1])); 258 } 259 260 /* 261 * Disable the receive h/w in preparation for a reset. 262 */ 263 void 264 ath_stoprecv(ath_t *asc) 265 { 266 ATH_HAL_STOPPCURECV(asc->asc_ah); /* disable PCU */ 267 ATH_HAL_SETRXFILTER(asc->asc_ah, 0); /* clear recv filter */ 268 ATH_HAL_STOPDMARECV(asc->asc_ah); /* disable DMA engine */ 269 drv_usecwait(3000); 270 271 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_stoprecv(): rx queue %p, link %p\n", 272 ATH_HAL_GETRXBUF(asc->asc_ah), asc->asc_rxlink)); 273 asc->asc_rxlink = NULL; 274 } 275 276 uint32_t 277 ath_chan2flags(ieee80211com_t *isc, struct ieee80211_channel *chan) 278 { 279 static const uint32_t modeflags[] = { 280 0, /* IEEE80211_MODE_AUTO */ 281 CHANNEL_A, /* IEEE80211_MODE_11A */ 282 CHANNEL_B, /* IEEE80211_MODE_11B */ 283 CHANNEL_PUREG, /* IEEE80211_MODE_11G */ 284 0, /* IEEE80211_MODE_FH */ 285 CHANNEL_108A, /* IEEE80211_MODE_TURBO_A */ 286 CHANNEL_108G /* IEEE80211_MODE_TURBO_G */ 287 }; 288 return (modeflags[ieee80211_chan2mode(isc, chan)]); 289 } 290 291 292 int 293 ath_getchannels(ath_t *asc, uint32_t cc, HAL_BOOL outdoor, HAL_BOOL xchanmode) 294 { 295 ieee80211com_t *ic = (ieee80211com_t *)asc; 296 struct ath_hal *ah = asc->asc_ah; 297 HAL_CHANNEL *chans; 298 int i, ix; 299 uint32_t nchan; 300 301 chans = (HAL_CHANNEL *) 302 kmem_zalloc(IEEE80211_CHAN_MAX * sizeof (HAL_CHANNEL), KM_SLEEP); 303 304 if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan, 305 NULL, 0, NULL, cc, HAL_MODE_ALL, outdoor, xchanmode)) { 306 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_getchannels(): " 307 "unable to get channel list\n")); 308 kmem_free(chans, IEEE80211_CHAN_MAX * sizeof (HAL_CHANNEL)); 309 return (EINVAL); 310 } 311 312 /* 313 * Convert HAL channels to ieee80211 ones and insert 314 * them in the table according to their channel number. 315 */ 316 for (i = 0; i < nchan; i++) { 317 HAL_CHANNEL *c = &chans[i]; 318 uint16_t flags; 319 ix = ath_hal_mhz2ieee(ah, c->channel, c->channelFlags); 320 if (ix > IEEE80211_CHAN_MAX) { 321 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_getchannels(): " 322 "bad hal channel %d (%u/%x) ignored\n", 323 ix, c->channel, c->channelFlags)); 324 continue; 325 } 326 /* NB: flags are known to be compatible */ 327 if (ix < 0) { 328 /* 329 * can't handle frequency <2400MHz (negative 330 * channels) right now 331 */ 332 ATH_DEBUG((ATH_DBG_AUX, "ath:ath_getchannels(): " 333 "hal channel %d (%u/%x) " 334 "cannot be handled, ignored\n", 335 ix, c->channel, c->channelFlags)); 336 continue; 337 } 338 /* 339 * Calculate net80211 flags; most are compatible 340 * but some need massaging. Note the static turbo 341 * conversion can be removed once net80211 is updated 342 * to understand static vs. dynamic turbo. 343 */ 344 flags = c->channelFlags & CHANNEL_COMPAT; 345 if (c->channelFlags & CHANNEL_STURBO) 346 flags |= IEEE80211_CHAN_TURBO; 347 if (ic->ic_sup_channels[ix].ich_freq == 0) { 348 ic->ic_sup_channels[ix].ich_freq = c->channel; 349 ic->ic_sup_channels[ix].ich_flags = flags; 350 } else { 351 /* channels overlap; e.g. 11g and 11b */ 352 ic->ic_sup_channels[ix].ich_flags |= flags; 353 } 354 if ((c->channelFlags & CHANNEL_G) == CHANNEL_G) 355 asc->asc_have11g = 1; 356 } 357 kmem_free(chans, IEEE80211_CHAN_MAX * sizeof (HAL_CHANNEL)); 358 return (0); 359 } 360 361 static void 362 ath_drainq(ath_t *asc, struct ath_txq *txq) 363 { 364 struct ath_buf *bf; 365 366 /* 367 * This assumes output has been stopped. 368 */ 369 for (;;) { 370 mutex_enter(&txq->axq_lock); 371 bf = list_head(&txq->axq_list); 372 if (bf == NULL) { 373 txq->axq_link = NULL; 374 mutex_exit(&txq->axq_lock); 375 break; 376 } 377 list_remove(&txq->axq_list, bf); 378 mutex_exit(&txq->axq_lock); 379 bf->bf_in = NULL; 380 mutex_enter(&asc->asc_txbuflock); 381 list_insert_tail(&asc->asc_txbuf_list, bf); 382 mutex_exit(&asc->asc_txbuflock); 383 } 384 } 385 386 387 /* 388 * Drain the transmit queues and reclaim resources. 389 */ 390 void 391 ath_draintxq(ath_t *asc) 392 { 393 struct ath_hal *ah = asc->asc_ah; 394 struct ath_txq *txq; 395 int i; 396 397 if (!asc->asc_invalid) { 398 for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 399 if (ATH_TXQ_SETUP(asc, i)) { 400 txq = &asc->asc_txq[i]; 401 (void) ATH_HAL_STOPTXDMA(ah, txq->axq_qnum); 402 } 403 } 404 } 405 for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 406 if (ATH_TXQ_SETUP(asc, i)) { 407 ath_drainq(asc, &asc->asc_txq[i]); 408 } 409 } 410 } 411 412 413 /* Enable the receive h/w following a reset */ 414 int 415 ath_startrecv(ath_t *asc) 416 { 417 struct ath_buf *bf; 418 419 asc->asc_rxlink = NULL; 420 421 bf = list_head(&asc->asc_rxbuf_list); 422 while (bf != NULL) { 423 ath_setup_desc(asc, bf); 424 bf = list_next(&asc->asc_rxbuf_list, bf); 425 } 426 427 bf = list_head(&asc->asc_rxbuf_list); 428 ATH_HAL_PUTRXBUF(asc->asc_ah, bf->bf_daddr); 429 ATH_HAL_RXENA(asc->asc_ah); /* enable recv descriptors */ 430 ath_mode_init(asc); /* set filters, etc. */ 431 ATH_HAL_STARTPCURECV(asc->asc_ah); /* re-enable PCU/DMA engine */ 432 return (0); 433 } 434 435 /* 436 * Update internal state after a channel change. 437 */ 438 void 439 ath_chan_change(ath_t *asc, struct ieee80211_channel *chan) 440 { 441 struct ieee80211com *ic = &asc->asc_isc; 442 enum ieee80211_phymode mode; 443 444 /* 445 * Change channels and update the h/w rate map 446 * if we're switching; e.g. 11a to 11b/g. 447 */ 448 mode = ieee80211_chan2mode(ic, chan); 449 if (mode != asc->asc_curmode) 450 ath_setcurmode(asc, mode); 451 } 452 453 /* 454 * Set/change channels. If the channel is really being changed, 455 * it's done by resetting the chip. To accomplish this we must 456 * first cleanup any pending DMA. 457 */ 458 int 459 ath_chan_set(ath_t *asc, struct ieee80211_channel *chan) 460 { 461 struct ath_hal *ah = asc->asc_ah; 462 ieee80211com_t *ic = &asc->asc_isc; 463 464 if (chan != ic->ic_ibss_chan) { 465 HAL_STATUS status; 466 HAL_CHANNEL hchan; 467 468 /* 469 * To switch channels clear any pending DMA operations; 470 * wait long enough for the RX fifo to drain, reset the 471 * hardware at the new frequency, and then re-enable 472 * the relevant bits of the h/w. 473 */ 474 ATH_HAL_INTRSET(ah, 0); /* disable interrupts */ 475 ath_draintxq(asc); /* clear pending tx frames */ 476 ath_stoprecv(asc); /* turn off frame recv */ 477 /* 478 * Convert to a HAL channel description with 479 * the flags constrained to reflect the current 480 * operating mode. 481 */ 482 hchan.channel = chan->ich_freq; 483 hchan.channelFlags = ath_chan2flags(ic, chan); 484 if (!ATH_HAL_RESET(ah, (HAL_OPMODE)ic->ic_opmode, 485 &hchan, AH_TRUE, &status)) { 486 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_chan_set():" 487 "unable to reset channel %u (%uMhz)\n" 488 "flags 0x%x: '%s' (HAL status %u)\n", 489 ieee80211_chan2ieee(ic, chan), hchan.channel, 490 hchan.channelFlags, 491 ath_get_hal_status_desc(status), status)); 492 return (EIO); 493 } 494 asc->asc_curchan = hchan; 495 496 /* 497 * Re-enable rx framework. 498 */ 499 if (ath_startrecv(asc) != 0) { 500 ath_problem("ath: ath_chan_set(): " 501 "restarting receiving logic failed\n"); 502 return (EIO); 503 } 504 505 /* 506 * Change channels and update the h/w rate map 507 * if we're switching; e.g. 11a to 11b/g. 508 */ 509 ic->ic_ibss_chan = chan; 510 ath_chan_change(asc, chan); 511 /* 512 * Re-enable interrupts. 513 */ 514 ATH_HAL_INTRSET(ah, asc->asc_imask); 515 } 516 return (0); 517 } 518 519 520 /* 521 * Configure the beacon and sleep timers. 522 * 523 * When operating as an AP this resets the TSF and sets 524 * up the hardware to notify us when we need to issue beacons. 525 * 526 * When operating in station mode this sets up the beacon 527 * timers according to the timestamp of the last received 528 * beacon and the current TSF, configures PCF and DTIM 529 * handling, programs the sleep registers so the hardware 530 * will wakeup in time to receive beacons, and configures 531 * the beacon miss handling so we'll receive a BMISS 532 * interrupt when we stop seeing beacons from the AP 533 * we've associated with. 534 */ 535 void 536 ath_beacon_config(ath_t *asc) 537 { 538 struct ath_hal *ah = asc->asc_ah; 539 ieee80211com_t *ic = (ieee80211com_t *)asc; 540 struct ieee80211_node *in = ic->ic_bss; 541 uint32_t nexttbtt; 542 543 nexttbtt = (ATH_LE_READ_4(in->in_tstamp.data + 4) << 22) | 544 (ATH_LE_READ_4(in->in_tstamp.data) >> 10); 545 nexttbtt += in->in_intval; 546 if (ic->ic_opmode != IEEE80211_M_HOSTAP) { 547 HAL_BEACON_STATE bs; 548 549 /* NB: no PCF support right now */ 550 bzero(&bs, sizeof (bs)); 551 bs.bs_intval = in->in_intval; 552 bs.bs_nexttbtt = nexttbtt; 553 bs.bs_dtimperiod = bs.bs_intval; 554 bs.bs_nextdtim = nexttbtt; 555 556 /* 557 * Setup the number of consecutive beacons to miss 558 * before taking a BMISS interrupt. 559 * Note that we clamp the result to at most 10 beacons. 560 */ 561 bs.bs_bmissthreshold = ic->ic_bmissthreshold; 562 if (bs.bs_bmissthreshold > 10) 563 bs.bs_bmissthreshold = 10; 564 else if (bs.bs_bmissthreshold < 1) 565 bs.bs_bmissthreshold = 1; 566 /* 567 * Calculate sleep duration. The configuration is 568 * given in ms. We insure a multiple of the beacon 569 * period is used. Also, if the sleep duration is 570 * greater than the DTIM period then it makes senses 571 * to make it a multiple of that. 572 */ 573 bs.bs_sleepduration = 574 roundup((100 * 1000) / 1024, bs.bs_intval); 575 if (bs.bs_sleepduration > bs.bs_dtimperiod) 576 bs.bs_sleepduration = 577 roundup(bs.bs_sleepduration, bs.bs_dtimperiod); 578 579 580 ATH_DEBUG((ATH_DBG_AUX, "ath: ath_beacon_config(): " 581 "intval %u nexttbtt %u dtim %u" 582 " nextdtim %u bmiss %u sleep %u\n", 583 bs.bs_intval, 584 bs.bs_nexttbtt, 585 bs.bs_dtimperiod, 586 bs.bs_nextdtim, 587 bs.bs_bmissthreshold, 588 bs.bs_sleepduration)); 589 ATH_HAL_INTRSET(ah, 0); 590 /* 591 * Reset our tsf so the hardware will update the 592 * tsf register to reflect timestamps found in 593 * received beacons. 594 */ 595 ATH_HAL_RESETTSF(ah); 596 ATH_HAL_BEACONTIMERS(ah, &bs); 597 asc->asc_imask |= HAL_INT_BMISS; 598 ATH_HAL_INTRSET(ah, asc->asc_imask); 599 } else { 600 ATH_HAL_INTRSET(ah, 0); 601 ATH_HAL_BEACONINIT(ah, nexttbtt, in->in_intval); 602 asc->asc_imask |= HAL_INT_SWBA; /* beacon prepare */ 603 ATH_HAL_INTRSET(ah, asc->asc_imask); 604 } 605 } 606 607 /* 608 * Allocate tx/rx key slots for TKIP. We allocate two slots for 609 * each key, one for decrypt/encrypt and the other for the MIC. 610 */ 611 static int 612 key_alloc_2pair(ath_t *asc, ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) 613 { 614 uint16_t i, keyix; 615 616 ASSERT(asc->asc_splitmic); 617 for (i = 0; i < ATH_N(asc->asc_keymap)/4; i++) { 618 uint8_t b = asc->asc_keymap[i]; 619 if (b != 0xff) { 620 /* 621 * One or more slots in this byte are free. 622 */ 623 keyix = i*NBBY; 624 while (b & 1) { 625 again: 626 keyix++; 627 b >>= 1; 628 } 629 /* XXX IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV */ 630 if (isset(asc->asc_keymap, keyix+32) || 631 isset(asc->asc_keymap, keyix+64) || 632 isset(asc->asc_keymap, keyix+32+64)) { 633 /* full pair unavailable */ 634 if (keyix == (i+1)*NBBY) { 635 /* no slots were appropriate, advance */ 636 continue; 637 } 638 goto again; 639 } 640 setbit(asc->asc_keymap, keyix); 641 setbit(asc->asc_keymap, keyix+64); 642 setbit(asc->asc_keymap, keyix+32); 643 setbit(asc->asc_keymap, keyix+32+64); 644 ATH_DEBUG((ATH_DBG_AUX, 645 "key_alloc_2pair: key pair %u,%u %u,%u\n", 646 keyix, keyix+64, 647 keyix+32, keyix+32+64)); 648 *txkeyix = *rxkeyix = keyix; 649 return (1); 650 } 651 } 652 ATH_DEBUG((ATH_DBG_AUX, "key_alloc_2pair:" 653 " out of pair space\n")); 654 return (0); 655 } 656 /* 657 * Allocate a single key cache slot. 658 */ 659 static int 660 key_alloc_single(ath_t *asc, ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) 661 { 662 uint16_t i, keyix; 663 664 /* try i,i+32,i+64,i+32+64 to minimize key pair conflicts */ 665 for (i = 0; i < ATH_N(asc->asc_keymap); i++) { 666 uint8_t b = asc->asc_keymap[i]; 667 668 if (b != 0xff) { 669 /* 670 * One or more slots are free. 671 */ 672 keyix = i*NBBY; 673 while (b & 1) 674 keyix++, b >>= 1; 675 setbit(asc->asc_keymap, keyix); 676 ATH_DEBUG((ATH_DBG_AUX, "key_alloc_single:" 677 " key %u\n", keyix)); 678 *txkeyix = *rxkeyix = keyix; 679 return (1); 680 } 681 } 682 return (0); 683 } 684 685 /* 686 * Allocate one or more key cache slots for a unicast key. The 687 * key itself is needed only to identify the cipher. For hardware 688 * TKIP with split cipher+MIC keys we allocate two key cache slot 689 * pairs so that we can setup separate TX and RX MIC keys. Note 690 * that the MIC key for a TKIP key at slot i is assumed by the 691 * hardware to be at slot i+64. This limits TKIP keys to the first 692 * 64 entries. 693 */ 694 /* ARGSUSED */ 695 int 696 ath_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k, 697 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 698 { 699 ath_t *asc = (ath_t *)ic; 700 701 /* 702 * We allocate two pair for TKIP when using the h/w to do 703 * the MIC. For everything else, including software crypto, 704 * we allocate a single entry. Note that s/w crypto requires 705 * a pass-through slot on the 5211 and 5212. The 5210 does 706 * not support pass-through cache entries and we map all 707 * those requests to slot 0. 708 */ 709 if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { 710 return (key_alloc_single(asc, keyix, rxkeyix)); 711 } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP && 712 (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && asc->asc_splitmic) { 713 return (key_alloc_2pair(asc, keyix, rxkeyix)); 714 } else { 715 return (key_alloc_single(asc, keyix, rxkeyix)); 716 } 717 } 718 719 /* 720 * Delete an entry in the key cache allocated by ath_key_alloc. 721 */ 722 int 723 ath_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k) 724 { 725 ath_t *asc = (ath_t *)ic; 726 struct ath_hal *ah = asc->asc_ah; 727 const struct ieee80211_cipher *cip = k->wk_cipher; 728 ieee80211_keyix keyix = k->wk_keyix; 729 730 ATH_DEBUG((ATH_DBG_AUX, "ath_key_delete:" 731 " delete key %u ic_cipher=0x%x\n", keyix, cip->ic_cipher)); 732 733 ATH_HAL_KEYRESET(ah, keyix); 734 /* 735 * Handle split tx/rx keying required for TKIP with h/w MIC. 736 */ 737 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && 738 (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && asc->asc_splitmic) 739 ATH_HAL_KEYRESET(ah, keyix+32); /* RX key */ 740 741 if (keyix >= IEEE80211_WEP_NKID) { 742 /* 743 * Don't touch keymap entries for global keys so 744 * they are never considered for dynamic allocation. 745 */ 746 clrbit(asc->asc_keymap, keyix); 747 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && 748 (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && 749 asc->asc_splitmic) { 750 clrbit(asc->asc_keymap, keyix+64); /* TX key MIC */ 751 clrbit(asc->asc_keymap, keyix+32); /* RX key */ 752 clrbit(asc->asc_keymap, keyix+32+64); /* RX key MIC */ 753 } 754 } 755 return (1); 756 } 757 758 static void 759 ath_keyprint(const char *tag, uint_t ix, 760 const HAL_KEYVAL *hk, const uint8_t mac[IEEE80211_ADDR_LEN]) 761 { 762 static const char *ciphers[] = { 763 "WEP", 764 "AES-OCB", 765 "AES-CCM", 766 "CKIP", 767 "TKIP", 768 "CLR", 769 }; 770 int i, n; 771 char buf[MAX_IEEE80211STR], buft[32]; 772 773 (void) snprintf(buf, sizeof (buf), "%s: [%02u] %s ", 774 tag, ix, ciphers[hk->kv_type]); 775 for (i = 0, n = hk->kv_len; i < n; i++) { 776 (void) snprintf(buft, sizeof (buft), "%02x", hk->kv_val[i]); 777 (void) strlcat(buf, buft, sizeof (buf)); 778 } 779 (void) snprintf(buft, sizeof (buft), " mac %s", 780 ieee80211_macaddr_sprintf(mac)); 781 (void) strlcat(buf, buft, sizeof (buf)); 782 if (hk->kv_type == HAL_CIPHER_TKIP) { 783 (void) snprintf(buft, sizeof (buft), " mic "); 784 (void) strlcat(buf, buft, sizeof (buf)); 785 for (i = 0; i < sizeof (hk->kv_mic); i++) { 786 (void) snprintf(buft, sizeof (buft), "%02x", 787 hk->kv_mic[i]); 788 (void) strlcat(buf, buft, sizeof (buf)); 789 } 790 } 791 ATH_DEBUG((ATH_DBG_AUX, "%s", buf)); 792 } 793 794 /* 795 * Set a TKIP key into the hardware. This handles the 796 * potential distribution of key state to multiple key 797 * cache slots for TKIP. 798 */ 799 static int 800 ath_keyset_tkip(ath_t *asc, const struct ieee80211_key *k, 801 HAL_KEYVAL *hk, const uint8_t mac[IEEE80211_ADDR_LEN]) 802 { 803 #define IEEE80211_KEY_XR (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV) 804 static const uint8_t zerobssid[IEEE80211_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; 805 struct ath_hal *ah = asc->asc_ah; 806 807 ASSERT(k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP); 808 if ((k->wk_flags & IEEE80211_KEY_XR) == IEEE80211_KEY_XR) { 809 /* 810 * TX key goes at first index, RX key at +32. 811 * The hal handles the MIC keys at index+64. 812 */ 813 (void) memcpy(hk->kv_mic, k->wk_txmic, sizeof (hk->kv_mic)); 814 ath_keyprint("ath_keyset_tkip:", k->wk_keyix, hk, zerobssid); 815 if (!ATH_HAL_KEYSET(ah, k->wk_keyix, hk, zerobssid)) 816 return (0); 817 818 (void) memcpy(hk->kv_mic, k->wk_rxmic, sizeof (hk->kv_mic)); 819 ath_keyprint("ath_keyset_tkip:", k->wk_keyix+32, hk, mac); 820 return (ATH_HAL_KEYSET(ah, k->wk_keyix+32, hk, mac)); 821 } else if (k->wk_flags & IEEE80211_KEY_XR) { 822 /* 823 * TX/RX key goes at first index. 824 * The hal handles the MIC keys are index+64. 825 */ 826 (void) memcpy(hk->kv_mic, k->wk_flags & IEEE80211_KEY_XMIT ? 827 k->wk_txmic : k->wk_rxmic, sizeof (hk->kv_mic)); 828 ath_keyprint("ath_keyset_tkip:", k->wk_keyix, hk, zerobssid); 829 return (ATH_HAL_KEYSET(ah, k->wk_keyix, hk, zerobssid)); 830 } 831 return (0); 832 #undef IEEE80211_KEY_XR 833 } 834 835 /* 836 * Set the key cache contents for the specified key. Key cache 837 * slot(s) must already have been allocated by ath_key_alloc. 838 */ 839 int 840 ath_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 841 const uint8_t mac[IEEE80211_ADDR_LEN]) 842 { 843 static const uint8_t ciphermap[] = { 844 HAL_CIPHER_WEP, /* IEEE80211_CIPHER_WEP */ 845 HAL_CIPHER_TKIP, /* IEEE80211_CIPHER_TKIP */ 846 HAL_CIPHER_AES_OCB, /* IEEE80211_CIPHER_AES_OCB */ 847 HAL_CIPHER_AES_CCM, /* IEEE80211_CIPHER_AES_CCM */ 848 HAL_CIPHER_CKIP, /* IEEE80211_CIPHER_CKIP */ 849 HAL_CIPHER_CLR, /* IEEE80211_CIPHER_NONE */ 850 }; 851 ath_t *asc = (ath_t *)ic; 852 struct ath_hal *ah = asc->asc_ah; 853 const struct ieee80211_cipher *cip = k->wk_cipher; 854 HAL_KEYVAL hk; 855 856 bzero(&hk, sizeof (hk)); 857 /* 858 * Software crypto uses a "clear key" so non-crypto 859 * state kept in the key cache are maintainedd so that 860 * rx frames have an entry to match. 861 */ 862 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { 863 ASSERT(cip->ic_cipher < ATH_N(ciphermap)); 864 hk.kv_type = ciphermap[cip->ic_cipher]; 865 hk.kv_len = k->wk_keylen; 866 bcopy(k->wk_key, hk.kv_val, k->wk_keylen); 867 } else { 868 hk.kv_type = HAL_CIPHER_CLR; 869 } 870 871 if (hk.kv_type == HAL_CIPHER_TKIP && 872 (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && 873 asc->asc_splitmic) { 874 return (ath_keyset_tkip(asc, k, &hk, mac)); 875 } else { 876 ath_keyprint("ath_keyset:", k->wk_keyix, &hk, mac); 877 return (ATH_HAL_KEYSET(ah, k->wk_keyix, &hk, mac)); 878 } 879 } 880 881 /* 882 * Enable/Disable short slot timing 883 */ 884 void 885 ath_set_shortslot(ieee80211com_t *ic, int onoff) 886 { 887 struct ath_hal *ah = ((ath_t *)ic)->asc_ah; 888 889 if (onoff) 890 ATH_HAL_SETSLOTTIME(ah, HAL_SLOT_TIME_9); 891 else 892 ATH_HAL_SETSLOTTIME(ah, HAL_SLOT_TIME_20); 893 } 894 895 int 896 ath_reset(ieee80211com_t *ic) 897 { 898 ath_t *asc = (ath_t *)ic; 899 struct ath_hal *ah = asc->asc_ah; 900 struct ieee80211_channel *ch; 901 HAL_STATUS status; 902 903 /* 904 * Convert to a HAL channel description with the flags 905 * constrained to reflect the current operating mode. 906 */ 907 ch = ic->ic_curchan; 908 asc->asc_curchan.channel = ch->ich_freq; 909 asc->asc_curchan.channelFlags = ath_chan2flags(ic, ch); 910 911 ATH_HAL_INTRSET(ah, 0); /* disable interrupts */ 912 ath_draintxq(asc); /* stop xmit side */ 913 if (ATH_IS_RUNNING(asc)) { 914 ath_stoprecv(asc); /* stop recv side */ 915 /* indicate channel change so we do a full reset */ 916 if (!ATH_HAL_RESET(ah, (HAL_OPMODE)ic->ic_opmode, 917 &asc->asc_curchan, AH_TRUE, &status)) { 918 ath_problem("ath: ath_reset(): " 919 "resetting hardware failed, '%s' (HAL status %u)\n", 920 ath_get_hal_status_desc(status), status); 921 } 922 ath_chan_change(asc, ch); 923 } 924 if (ATH_IS_RUNNING(asc)) { 925 if (ath_startrecv(asc) != 0) /* restart recv */ 926 ath_problem("ath: ath_reset(): " 927 "starting receiving logic failed\n"); 928 if (ic->ic_state == IEEE80211_S_RUN) { 929 ath_beacon_config(asc); /* restart beacons */ 930 } 931 ATH_HAL_INTRSET(ah, asc->asc_imask); 932 } 933 return (0); 934 } 935