xref: /illumos-gate/usr/src/uts/common/io/ath/ath_aux.c (revision e688a0bc223983e7c7fedad44c92b8d0292a10f7)
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] = 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 <= 0)
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