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
72static const char *acnames[] = {
73	"WME_AC_BE",
74	"WME_AC_BK",
75	"WME_AC_VI",
76	"WME_AC_VO",
77	"WME_UPSD"
78};
79
80extern void ath_setup_desc(ath_t *asc, struct ath_buf *bf);
81
82
83const char *
84ath_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
111uint32_t
112ath_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
131static int
132ath_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
188int
189ath_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
201void
202ath_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
218void
219ath_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 */
246void
247ath_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 */
268void
269ath_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
281uint32_t
282ath_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
297int
298ath_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
366static void
367ath_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 */
395void
396ath_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 */
419int
420ath_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 */
443void
444ath_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 */
463int
464ath_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 */
540void
541ath_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 */
616static uint16_t
617key_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 */
651static int
652key_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 */
699static int
700key_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 */
735int
736ath_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 */
765int
766ath_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
808static void
809ath_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 */
859static int
860ath_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 */
919int
920ath_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 */
963void
964ath_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
974int
975ath_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