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