1/*-
2 * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting
3 * Copyright (c) 2007-2008 Marvell Semiconductor, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer,
11 *    without modification.
12 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
13 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
14 *    redistribution must be conditioned upon including a substantially
15 *    similar Disclaimer requirement for further binary redistribution.
16 *
17 * NO WARRANTY
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
23 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGES.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD$");
33
34/*
35 * Driver for the Marvell 88W8363 Wireless LAN controller.
36 */
37
38#include "opt_inet.h"
39#include "opt_mwl.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/sysctl.h>
44#include <sys/mbuf.h>
45#include <sys/malloc.h>
46#include <sys/lock.h>
47#include <sys/mutex.h>
48#include <sys/kernel.h>
49#include <sys/socket.h>
50#include <sys/sockio.h>
51#include <sys/errno.h>
52#include <sys/callout.h>
53#include <sys/bus.h>
54#include <sys/endian.h>
55#include <sys/kthread.h>
56#include <sys/taskqueue.h>
57
58#include <machine/bus.h>
59
60#include <net/if.h>
61#include <net/if_dl.h>
62#include <net/if_media.h>
63#include <net/if_types.h>
64#include <net/if_arp.h>
65#include <net/ethernet.h>
66#include <net/if_llc.h>
67
68#include <net/bpf.h>
69
70#include <net80211/ieee80211_var.h>
71#include <net80211/ieee80211_regdomain.h>
72
73#ifdef INET
74#include <netinet/in.h>
75#include <netinet/if_ether.h>
76#endif /* INET */
77
78#include <dev/mwl/if_mwlvar.h>
79#include <dev/mwl/mwldiag.h>
80
81/* idiomatic shorthands: MS = mask+shift, SM = shift+mask */
82#define	MS(v,x)	(((v) & x) >> x##_S)
83#define	SM(v,x)	(((v) << x##_S) & x)
84
85static struct ieee80211vap *mwl_vap_create(struct ieee80211com *,
86		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
87		    const uint8_t [IEEE80211_ADDR_LEN],
88		    const uint8_t [IEEE80211_ADDR_LEN]);
89static void	mwl_vap_delete(struct ieee80211vap *);
90static int	mwl_setupdma(struct mwl_softc *);
91static int	mwl_hal_reset(struct mwl_softc *sc);
92static int	mwl_init_locked(struct mwl_softc *);
93static void	mwl_init(void *);
94static void	mwl_stop_locked(struct ifnet *, int);
95static int	mwl_reset(struct ieee80211vap *, u_long);
96static void	mwl_stop(struct ifnet *, int);
97static void	mwl_start(struct ifnet *);
98static int	mwl_raw_xmit(struct ieee80211_node *, struct mbuf *,
99			const struct ieee80211_bpf_params *);
100static int	mwl_media_change(struct ifnet *);
101static void	mwl_watchdog(void *);
102static int	mwl_ioctl(struct ifnet *, u_long, caddr_t);
103static void	mwl_radar_proc(void *, int);
104static void	mwl_chanswitch_proc(void *, int);
105static void	mwl_bawatchdog_proc(void *, int);
106static int	mwl_key_alloc(struct ieee80211vap *,
107			struct ieee80211_key *,
108			ieee80211_keyix *, ieee80211_keyix *);
109static int	mwl_key_delete(struct ieee80211vap *,
110			const struct ieee80211_key *);
111static int	mwl_key_set(struct ieee80211vap *, const struct ieee80211_key *,
112			const uint8_t mac[IEEE80211_ADDR_LEN]);
113static int	mwl_mode_init(struct mwl_softc *);
114static void	mwl_update_mcast(struct ifnet *);
115static void	mwl_update_promisc(struct ifnet *);
116static void	mwl_updateslot(struct ifnet *);
117static int	mwl_beacon_setup(struct ieee80211vap *);
118static void	mwl_beacon_update(struct ieee80211vap *, int);
119#ifdef MWL_HOST_PS_SUPPORT
120static void	mwl_update_ps(struct ieee80211vap *, int);
121static int	mwl_set_tim(struct ieee80211_node *, int);
122#endif
123static int	mwl_dma_setup(struct mwl_softc *);
124static void	mwl_dma_cleanup(struct mwl_softc *);
125static struct ieee80211_node *mwl_node_alloc(struct ieee80211vap *,
126		    const uint8_t [IEEE80211_ADDR_LEN]);
127static void	mwl_node_cleanup(struct ieee80211_node *);
128static void	mwl_node_drain(struct ieee80211_node *);
129static void	mwl_node_getsignal(const struct ieee80211_node *,
130			int8_t *, int8_t *);
131static void	mwl_node_getmimoinfo(const struct ieee80211_node *,
132			struct ieee80211_mimo_info *);
133static int	mwl_rxbuf_init(struct mwl_softc *, struct mwl_rxbuf *);
134static void	mwl_rx_proc(void *, int);
135static void	mwl_txq_init(struct mwl_softc *sc, struct mwl_txq *, int);
136static int	mwl_tx_setup(struct mwl_softc *, int, int);
137static int	mwl_wme_update(struct ieee80211com *);
138static void	mwl_tx_cleanupq(struct mwl_softc *, struct mwl_txq *);
139static void	mwl_tx_cleanup(struct mwl_softc *);
140static uint16_t	mwl_calcformat(uint8_t rate, const struct ieee80211_node *);
141static int	mwl_tx_start(struct mwl_softc *, struct ieee80211_node *,
142			     struct mwl_txbuf *, struct mbuf *);
143static void	mwl_tx_proc(void *, int);
144static int	mwl_chan_set(struct mwl_softc *, struct ieee80211_channel *);
145static void	mwl_draintxq(struct mwl_softc *);
146static void	mwl_cleartxq(struct mwl_softc *, struct ieee80211vap *);
147static int	mwl_recv_action(struct ieee80211_node *,
148			const struct ieee80211_frame *,
149			const uint8_t *, const uint8_t *);
150static int	mwl_addba_request(struct ieee80211_node *,
151			struct ieee80211_tx_ampdu *, int dialogtoken,
152			int baparamset, int batimeout);
153static int	mwl_addba_response(struct ieee80211_node *,
154			struct ieee80211_tx_ampdu *, int status,
155			int baparamset, int batimeout);
156static void	mwl_addba_stop(struct ieee80211_node *,
157			struct ieee80211_tx_ampdu *);
158static int	mwl_startrecv(struct mwl_softc *);
159static MWL_HAL_APMODE mwl_getapmode(const struct ieee80211vap *,
160			struct ieee80211_channel *);
161static int	mwl_setapmode(struct ieee80211vap *, struct ieee80211_channel*);
162static void	mwl_scan_start(struct ieee80211com *);
163static void	mwl_scan_end(struct ieee80211com *);
164static void	mwl_set_channel(struct ieee80211com *);
165static int	mwl_peerstadb(struct ieee80211_node *,
166			int aid, int staid, MWL_HAL_PEERINFO *pi);
167static int	mwl_localstadb(struct ieee80211vap *);
168static int	mwl_newstate(struct ieee80211vap *, enum ieee80211_state, int);
169static int	allocstaid(struct mwl_softc *sc, int aid);
170static void	delstaid(struct mwl_softc *sc, int staid);
171static void	mwl_newassoc(struct ieee80211_node *, int);
172static void	mwl_agestations(void *);
173static int	mwl_setregdomain(struct ieee80211com *,
174			struct ieee80211_regdomain *, int,
175			struct ieee80211_channel []);
176static void	mwl_getradiocaps(struct ieee80211com *, int, int *,
177			struct ieee80211_channel []);
178static int	mwl_getchannels(struct mwl_softc *);
179
180static void	mwl_sysctlattach(struct mwl_softc *);
181static void	mwl_announce(struct mwl_softc *);
182
183SYSCTL_NODE(_hw, OID_AUTO, mwl, CTLFLAG_RD, 0, "Marvell driver parameters");
184
185static	int mwl_rxdesc = MWL_RXDESC;		/* # rx desc's to allocate */
186SYSCTL_INT(_hw_mwl, OID_AUTO, rxdesc, CTLFLAG_RW, &mwl_rxdesc,
187	    0, "rx descriptors allocated");
188static	int mwl_rxbuf = MWL_RXBUF;		/* # rx buffers to allocate */
189SYSCTL_INT(_hw_mwl, OID_AUTO, rxbuf, CTLFLAG_RW, &mwl_rxbuf,
190	    0, "rx buffers allocated");
191TUNABLE_INT("hw.mwl.rxbuf", &mwl_rxbuf);
192static	int mwl_txbuf = MWL_TXBUF;		/* # tx buffers to allocate */
193SYSCTL_INT(_hw_mwl, OID_AUTO, txbuf, CTLFLAG_RW, &mwl_txbuf,
194	    0, "tx buffers allocated");
195TUNABLE_INT("hw.mwl.txbuf", &mwl_txbuf);
196static	int mwl_txcoalesce = 8;		/* # tx packets to q before poking f/w*/
197SYSCTL_INT(_hw_mwl, OID_AUTO, txcoalesce, CTLFLAG_RW, &mwl_txcoalesce,
198	    0, "tx buffers to send at once");
199TUNABLE_INT("hw.mwl.txcoalesce", &mwl_txcoalesce);
200static	int mwl_rxquota = MWL_RXBUF;		/* # max buffers to process */
201SYSCTL_INT(_hw_mwl, OID_AUTO, rxquota, CTLFLAG_RW, &mwl_rxquota,
202	    0, "max rx buffers to process per interrupt");
203TUNABLE_INT("hw.mwl.rxquota", &mwl_rxquota);
204static	int mwl_rxdmalow = 3;			/* # min buffers for wakeup */
205SYSCTL_INT(_hw_mwl, OID_AUTO, rxdmalow, CTLFLAG_RW, &mwl_rxdmalow,
206	    0, "min free rx buffers before restarting traffic");
207TUNABLE_INT("hw.mwl.rxdmalow", &mwl_rxdmalow);
208
209#ifdef MWL_DEBUG
210static	int mwl_debug = 0;
211SYSCTL_INT(_hw_mwl, OID_AUTO, debug, CTLFLAG_RW, &mwl_debug,
212	    0, "control debugging printfs");
213TUNABLE_INT("hw.mwl.debug", &mwl_debug);
214enum {
215	MWL_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
216	MWL_DEBUG_XMIT_DESC	= 0x00000002,	/* xmit descriptors */
217	MWL_DEBUG_RECV		= 0x00000004,	/* basic recv operation */
218	MWL_DEBUG_RECV_DESC	= 0x00000008,	/* recv descriptors */
219	MWL_DEBUG_RESET		= 0x00000010,	/* reset processing */
220	MWL_DEBUG_BEACON 	= 0x00000020,	/* beacon handling */
221	MWL_DEBUG_INTR		= 0x00000040,	/* ISR */
222	MWL_DEBUG_TX_PROC	= 0x00000080,	/* tx ISR proc */
223	MWL_DEBUG_RX_PROC	= 0x00000100,	/* rx ISR proc */
224	MWL_DEBUG_KEYCACHE	= 0x00000200,	/* key cache management */
225	MWL_DEBUG_STATE		= 0x00000400,	/* 802.11 state transitions */
226	MWL_DEBUG_NODE		= 0x00000800,	/* node management */
227	MWL_DEBUG_RECV_ALL	= 0x00001000,	/* trace all frames (beacons) */
228	MWL_DEBUG_TSO		= 0x00002000,	/* TSO processing */
229	MWL_DEBUG_AMPDU		= 0x00004000,	/* BA stream handling */
230	MWL_DEBUG_ANY		= 0xffffffff
231};
232#define	IS_BEACON(wh) \
233    ((wh->i_fc[0] & (IEEE80211_FC0_TYPE_MASK|IEEE80211_FC0_SUBTYPE_MASK)) == \
234	 (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON))
235#define	IFF_DUMPPKTS_RECV(sc, wh) \
236    (((sc->sc_debug & MWL_DEBUG_RECV) && \
237      ((sc->sc_debug & MWL_DEBUG_RECV_ALL) || !IS_BEACON(wh))) || \
238     (sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
239#define	IFF_DUMPPKTS_XMIT(sc) \
240	((sc->sc_debug & MWL_DEBUG_XMIT) || \
241	 (sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
242#define	DPRINTF(sc, m, fmt, ...) do {				\
243	if (sc->sc_debug & (m))					\
244		printf(fmt, __VA_ARGS__);			\
245} while (0)
246#define	KEYPRINTF(sc, hk, mac) do {				\
247	if (sc->sc_debug & MWL_DEBUG_KEYCACHE)			\
248		mwl_keyprint(sc, __func__, hk, mac);		\
249} while (0)
250static	void mwl_printrxbuf(const struct mwl_rxbuf *bf, u_int ix);
251static	void mwl_printtxbuf(const struct mwl_txbuf *bf, u_int qnum, u_int ix);
252#else
253#define	IFF_DUMPPKTS_RECV(sc, wh) \
254	((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
255#define	IFF_DUMPPKTS_XMIT(sc) \
256	((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
257#define	DPRINTF(sc, m, fmt, ...) do {				\
258	(void) sc;						\
259} while (0)
260#define	KEYPRINTF(sc, k, mac) do {				\
261	(void) sc;						\
262} while (0)
263#endif
264
265static MALLOC_DEFINE(M_MWLDEV, "mwldev", "mwl driver dma buffers");
266
267/*
268 * Each packet has fixed front matter: a 2-byte length
269 * of the payload, followed by a 4-address 802.11 header
270 * (regardless of the actual header and always w/o any
271 * QoS header).  The payload then follows.
272 */
273struct mwltxrec {
274	uint16_t fwlen;
275	struct ieee80211_frame_addr4 wh;
276} __packed;
277
278/*
279 * Read/Write shorthands for accesses to BAR 0.  Note
280 * that all BAR 1 operations are done in the "hal" and
281 * there should be no reference to them here.
282 */
283#ifdef MWL_DEBUG
284static __inline uint32_t
285RD4(struct mwl_softc *sc, bus_size_t off)
286{
287	return bus_space_read_4(sc->sc_io0t, sc->sc_io0h, off);
288}
289#endif
290
291static __inline void
292WR4(struct mwl_softc *sc, bus_size_t off, uint32_t val)
293{
294	bus_space_write_4(sc->sc_io0t, sc->sc_io0h, off, val);
295}
296
297int
298mwl_attach(uint16_t devid, struct mwl_softc *sc)
299{
300	struct ifnet *ifp;
301	struct ieee80211com *ic;
302	struct mwl_hal *mh;
303	int error = 0;
304
305	DPRINTF(sc, MWL_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
306
307	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
308	if (ifp == NULL) {
309		device_printf(sc->sc_dev, "cannot if_alloc()\n");
310		return ENOSPC;
311	}
312	ic = ifp->if_l2com;
313
314	/* set these up early for if_printf use */
315	if_initname(ifp, device_get_name(sc->sc_dev),
316		device_get_unit(sc->sc_dev));
317
318	mh = mwl_hal_attach(sc->sc_dev, devid,
319	    sc->sc_io1h, sc->sc_io1t, sc->sc_dmat);
320	if (mh == NULL) {
321		if_printf(ifp, "unable to attach HAL\n");
322		error = EIO;
323		goto bad;
324	}
325	sc->sc_mh = mh;
326	/*
327	 * Load firmware so we can get setup.  We arbitrarily
328	 * pick station firmware; we'll re-load firmware as
329	 * needed so setting up the wrong mode isn't a big deal.
330	 */
331	if (mwl_hal_fwload(mh, NULL) != 0) {
332		if_printf(ifp, "unable to setup builtin firmware\n");
333		error = EIO;
334		goto bad1;
335	}
336	if (mwl_hal_gethwspecs(mh, &sc->sc_hwspecs) != 0) {
337		if_printf(ifp, "unable to fetch h/w specs\n");
338		error = EIO;
339		goto bad1;
340	}
341	error = mwl_getchannels(sc);
342	if (error != 0)
343		goto bad1;
344
345	sc->sc_txantenna = 0;		/* h/w default */
346	sc->sc_rxantenna = 0;		/* h/w default */
347	sc->sc_invalid = 0;		/* ready to go, enable int handling */
348	sc->sc_ageinterval = MWL_AGEINTERVAL;
349
350	/*
351	 * Allocate tx+rx descriptors and populate the lists.
352	 * We immediately push the information to the firmware
353	 * as otherwise it gets upset.
354	 */
355	error = mwl_dma_setup(sc);
356	if (error != 0) {
357		if_printf(ifp, "failed to setup descriptors: %d\n", error);
358		goto bad1;
359	}
360	error = mwl_setupdma(sc);	/* push to firmware */
361	if (error != 0)			/* NB: mwl_setupdma prints msg */
362		goto bad1;
363
364	callout_init(&sc->sc_timer, CALLOUT_MPSAFE);
365	callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
366
367	sc->sc_tq = taskqueue_create("mwl_taskq", M_NOWAIT,
368		taskqueue_thread_enqueue, &sc->sc_tq);
369	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
370		"%s taskq", ifp->if_xname);
371
372	TASK_INIT(&sc->sc_rxtask, 0, mwl_rx_proc, sc);
373	TASK_INIT(&sc->sc_radartask, 0, mwl_radar_proc, sc);
374	TASK_INIT(&sc->sc_chanswitchtask, 0, mwl_chanswitch_proc, sc);
375	TASK_INIT(&sc->sc_bawatchdogtask, 0, mwl_bawatchdog_proc, sc);
376
377	/* NB: insure BK queue is the lowest priority h/w queue */
378	if (!mwl_tx_setup(sc, WME_AC_BK, MWL_WME_AC_BK)) {
379		if_printf(ifp, "unable to setup xmit queue for %s traffic!\n",
380			ieee80211_wme_acnames[WME_AC_BK]);
381		error = EIO;
382		goto bad2;
383	}
384	if (!mwl_tx_setup(sc, WME_AC_BE, MWL_WME_AC_BE) ||
385	    !mwl_tx_setup(sc, WME_AC_VI, MWL_WME_AC_VI) ||
386	    !mwl_tx_setup(sc, WME_AC_VO, MWL_WME_AC_VO)) {
387		/*
388		 * Not enough hardware tx queues to properly do WME;
389		 * just punt and assign them all to the same h/w queue.
390		 * We could do a better job of this if, for example,
391		 * we allocate queues when we switch from station to
392		 * AP mode.
393		 */
394		if (sc->sc_ac2q[WME_AC_VI] != NULL)
395			mwl_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_VI]);
396		if (sc->sc_ac2q[WME_AC_BE] != NULL)
397			mwl_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_BE]);
398		sc->sc_ac2q[WME_AC_BE] = sc->sc_ac2q[WME_AC_BK];
399		sc->sc_ac2q[WME_AC_VI] = sc->sc_ac2q[WME_AC_BK];
400		sc->sc_ac2q[WME_AC_VO] = sc->sc_ac2q[WME_AC_BK];
401	}
402	TASK_INIT(&sc->sc_txtask, 0, mwl_tx_proc, sc);
403
404	ifp->if_softc = sc;
405	ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
406	ifp->if_start = mwl_start;
407	ifp->if_ioctl = mwl_ioctl;
408	ifp->if_init = mwl_init;
409	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
410	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
411	IFQ_SET_READY(&ifp->if_snd);
412
413	ic->ic_ifp = ifp;
414	/* XXX not right but it's not used anywhere important */
415	ic->ic_phytype = IEEE80211_T_OFDM;
416	ic->ic_opmode = IEEE80211_M_STA;
417	ic->ic_caps =
418		  IEEE80211_C_STA		/* station mode supported */
419		| IEEE80211_C_HOSTAP		/* hostap mode */
420		| IEEE80211_C_MONITOR		/* monitor mode */
421#if 0
422		| IEEE80211_C_IBSS		/* ibss, nee adhoc, mode */
423		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
424#endif
425		| IEEE80211_C_MBSS		/* mesh point link mode */
426		| IEEE80211_C_WDS		/* WDS supported */
427		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
428		| IEEE80211_C_SHSLOT		/* short slot time supported */
429		| IEEE80211_C_WME		/* WME/WMM supported */
430		| IEEE80211_C_BURST		/* xmit bursting supported */
431		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
432		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
433		| IEEE80211_C_TXFRAG		/* handle tx frags */
434		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
435		| IEEE80211_C_DFS		/* DFS supported */
436		;
437
438	ic->ic_htcaps =
439		  IEEE80211_HTCAP_SMPS_ENA	/* SM PS mode enabled */
440		| IEEE80211_HTCAP_CHWIDTH40	/* 40MHz channel width */
441		| IEEE80211_HTCAP_SHORTGI20	/* short GI in 20MHz */
442		| IEEE80211_HTCAP_SHORTGI40	/* short GI in 40MHz */
443		| IEEE80211_HTCAP_RXSTBC_2STREAM/* 1-2 spatial streams */
444#if MWL_AGGR_SIZE == 7935
445		| IEEE80211_HTCAP_MAXAMSDU_7935	/* max A-MSDU length */
446#else
447		| IEEE80211_HTCAP_MAXAMSDU_3839	/* max A-MSDU length */
448#endif
449#if 0
450		| IEEE80211_HTCAP_PSMP		/* PSMP supported */
451		| IEEE80211_HTCAP_40INTOLERANT	/* 40MHz intolerant */
452#endif
453		/* s/w capabilities */
454		| IEEE80211_HTC_HT		/* HT operation */
455		| IEEE80211_HTC_AMPDU		/* tx A-MPDU */
456		| IEEE80211_HTC_AMSDU		/* tx A-MSDU */
457		| IEEE80211_HTC_SMPS		/* SMPS available */
458		;
459
460	/*
461	 * Mark h/w crypto support.
462	 * XXX no way to query h/w support.
463	 */
464	ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
465			  |  IEEE80211_CRYPTO_AES_CCM
466			  |  IEEE80211_CRYPTO_TKIP
467			  |  IEEE80211_CRYPTO_TKIPMIC
468			  ;
469	/*
470	 * Transmit requires space in the packet for a special
471	 * format transmit record and optional padding between
472	 * this record and the payload.  Ask the net80211 layer
473	 * to arrange this when encapsulating packets so we can
474	 * add it efficiently.
475	 */
476	ic->ic_headroom = sizeof(struct mwltxrec) -
477		sizeof(struct ieee80211_frame);
478
479	/* call MI attach routine. */
480	ieee80211_ifattach(ic, sc->sc_hwspecs.macAddr);
481	ic->ic_setregdomain = mwl_setregdomain;
482	ic->ic_getradiocaps = mwl_getradiocaps;
483	/* override default methods */
484	ic->ic_raw_xmit = mwl_raw_xmit;
485	ic->ic_newassoc = mwl_newassoc;
486	ic->ic_updateslot = mwl_updateslot;
487	ic->ic_update_mcast = mwl_update_mcast;
488	ic->ic_update_promisc = mwl_update_promisc;
489	ic->ic_wme.wme_update = mwl_wme_update;
490
491	ic->ic_node_alloc = mwl_node_alloc;
492	sc->sc_node_cleanup = ic->ic_node_cleanup;
493	ic->ic_node_cleanup = mwl_node_cleanup;
494	sc->sc_node_drain = ic->ic_node_drain;
495	ic->ic_node_drain = mwl_node_drain;
496	ic->ic_node_getsignal = mwl_node_getsignal;
497	ic->ic_node_getmimoinfo = mwl_node_getmimoinfo;
498
499	ic->ic_scan_start = mwl_scan_start;
500	ic->ic_scan_end = mwl_scan_end;
501	ic->ic_set_channel = mwl_set_channel;
502
503	sc->sc_recv_action = ic->ic_recv_action;
504	ic->ic_recv_action = mwl_recv_action;
505	sc->sc_addba_request = ic->ic_addba_request;
506	ic->ic_addba_request = mwl_addba_request;
507	sc->sc_addba_response = ic->ic_addba_response;
508	ic->ic_addba_response = mwl_addba_response;
509	sc->sc_addba_stop = ic->ic_addba_stop;
510	ic->ic_addba_stop = mwl_addba_stop;
511
512	ic->ic_vap_create = mwl_vap_create;
513	ic->ic_vap_delete = mwl_vap_delete;
514
515	ieee80211_radiotap_attach(ic,
516	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
517		MWL_TX_RADIOTAP_PRESENT,
518	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
519		MWL_RX_RADIOTAP_PRESENT);
520	/*
521	 * Setup dynamic sysctl's now that country code and
522	 * regdomain are available from the hal.
523	 */
524	mwl_sysctlattach(sc);
525
526	if (bootverbose)
527		ieee80211_announce(ic);
528	mwl_announce(sc);
529	return 0;
530bad2:
531	mwl_dma_cleanup(sc);
532bad1:
533	mwl_hal_detach(mh);
534bad:
535	if_free(ifp);
536	sc->sc_invalid = 1;
537	return error;
538}
539
540int
541mwl_detach(struct mwl_softc *sc)
542{
543	struct ifnet *ifp = sc->sc_ifp;
544	struct ieee80211com *ic = ifp->if_l2com;
545
546	DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags %x\n",
547		__func__, ifp->if_flags);
548
549	mwl_stop(ifp, 1);
550	/*
551	 * NB: the order of these is important:
552	 * o call the 802.11 layer before detaching the hal to
553	 *   insure callbacks into the driver to delete global
554	 *   key cache entries can be handled
555	 * o reclaim the tx queue data structures after calling
556	 *   the 802.11 layer as we'll get called back to reclaim
557	 *   node state and potentially want to use them
558	 * o to cleanup the tx queues the hal is called, so detach
559	 *   it last
560	 * Other than that, it's straightforward...
561	 */
562	ieee80211_ifdetach(ic);
563	callout_drain(&sc->sc_watchdog);
564	mwl_dma_cleanup(sc);
565	mwl_tx_cleanup(sc);
566	mwl_hal_detach(sc->sc_mh);
567	if_free(ifp);
568
569	return 0;
570}
571
572/*
573 * MAC address handling for multiple BSS on the same radio.
574 * The first vap uses the MAC address from the EEPROM.  For
575 * subsequent vap's we set the U/L bit (bit 1) in the MAC
576 * address and use the next six bits as an index.
577 */
578static void
579assign_address(struct mwl_softc *sc, uint8_t mac[IEEE80211_ADDR_LEN], int clone)
580{
581	int i;
582
583	if (clone && mwl_hal_ismbsscapable(sc->sc_mh)) {
584		/* NB: we only do this if h/w supports multiple bssid */
585		for (i = 0; i < 32; i++)
586			if ((sc->sc_bssidmask & (1<<i)) == 0)
587				break;
588		if (i != 0)
589			mac[0] |= (i << 2)|0x2;
590	} else
591		i = 0;
592	sc->sc_bssidmask |= 1<<i;
593	if (i == 0)
594		sc->sc_nbssid0++;
595}
596
597static void
598reclaim_address(struct mwl_softc *sc, uint8_t mac[IEEE80211_ADDR_LEN])
599{
600	int i = mac[0] >> 2;
601	if (i != 0 || --sc->sc_nbssid0 == 0)
602		sc->sc_bssidmask &= ~(1<<i);
603}
604
605static struct ieee80211vap *
606mwl_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
607    enum ieee80211_opmode opmode, int flags,
608    const uint8_t bssid[IEEE80211_ADDR_LEN],
609    const uint8_t mac0[IEEE80211_ADDR_LEN])
610{
611	struct ifnet *ifp = ic->ic_ifp;
612	struct mwl_softc *sc = ifp->if_softc;
613	struct mwl_hal *mh = sc->sc_mh;
614	struct ieee80211vap *vap, *apvap;
615	struct mwl_hal_vap *hvap;
616	struct mwl_vap *mvp;
617	uint8_t mac[IEEE80211_ADDR_LEN];
618
619	IEEE80211_ADDR_COPY(mac, mac0);
620	switch (opmode) {
621	case IEEE80211_M_HOSTAP:
622	case IEEE80211_M_MBSS:
623		if ((flags & IEEE80211_CLONE_MACADDR) == 0)
624			assign_address(sc, mac, flags & IEEE80211_CLONE_BSSID);
625		hvap = mwl_hal_newvap(mh, MWL_HAL_AP, mac);
626		if (hvap == NULL) {
627			if ((flags & IEEE80211_CLONE_MACADDR) == 0)
628				reclaim_address(sc, mac);
629			return NULL;
630		}
631		break;
632	case IEEE80211_M_STA:
633		if ((flags & IEEE80211_CLONE_MACADDR) == 0)
634			assign_address(sc, mac, flags & IEEE80211_CLONE_BSSID);
635		hvap = mwl_hal_newvap(mh, MWL_HAL_STA, mac);
636		if (hvap == NULL) {
637			if ((flags & IEEE80211_CLONE_MACADDR) == 0)
638				reclaim_address(sc, mac);
639			return NULL;
640		}
641		/* no h/w beacon miss support; always use s/w */
642		flags |= IEEE80211_CLONE_NOBEACONS;
643		break;
644	case IEEE80211_M_WDS:
645		hvap = NULL;		/* NB: we use associated AP vap */
646		if (sc->sc_napvaps == 0)
647			return NULL;	/* no existing AP vap */
648		break;
649	case IEEE80211_M_MONITOR:
650		hvap = NULL;
651		break;
652	case IEEE80211_M_IBSS:
653	case IEEE80211_M_AHDEMO:
654	default:
655		return NULL;
656	}
657
658	mvp = (struct mwl_vap *) malloc(sizeof(struct mwl_vap),
659	    M_80211_VAP, M_NOWAIT | M_ZERO);
660	if (mvp == NULL) {
661		if (hvap != NULL) {
662			mwl_hal_delvap(hvap);
663			if ((flags & IEEE80211_CLONE_MACADDR) == 0)
664				reclaim_address(sc, mac);
665		}
666		/* XXX msg */
667		return NULL;
668	}
669	mvp->mv_hvap = hvap;
670	if (opmode == IEEE80211_M_WDS) {
671		/*
672		 * WDS vaps must have an associated AP vap; find one.
673		 * XXX not right.
674		 */
675		TAILQ_FOREACH(apvap, &ic->ic_vaps, iv_next)
676			if (apvap->iv_opmode == IEEE80211_M_HOSTAP) {
677				mvp->mv_ap_hvap = MWL_VAP(apvap)->mv_hvap;
678				break;
679			}
680		KASSERT(mvp->mv_ap_hvap != NULL, ("no ap vap"));
681	}
682	vap = &mvp->mv_vap;
683	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
684	if (hvap != NULL)
685		IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
686	/* override with driver methods */
687	mvp->mv_newstate = vap->iv_newstate;
688	vap->iv_newstate = mwl_newstate;
689	vap->iv_max_keyix = 0;	/* XXX */
690	vap->iv_key_alloc = mwl_key_alloc;
691	vap->iv_key_delete = mwl_key_delete;
692	vap->iv_key_set = mwl_key_set;
693#ifdef MWL_HOST_PS_SUPPORT
694	if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_MBSS) {
695		vap->iv_update_ps = mwl_update_ps;
696		mvp->mv_set_tim = vap->iv_set_tim;
697		vap->iv_set_tim = mwl_set_tim;
698	}
699#endif
700	vap->iv_reset = mwl_reset;
701	vap->iv_update_beacon = mwl_beacon_update;
702
703	/* override max aid so sta's cannot assoc when we're out of sta id's */
704	vap->iv_max_aid = MWL_MAXSTAID;
705	/* override default A-MPDU rx parameters */
706	vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K;
707	vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_4;
708
709	/* complete setup */
710	ieee80211_vap_attach(vap, mwl_media_change, ieee80211_media_status);
711
712	switch (vap->iv_opmode) {
713	case IEEE80211_M_HOSTAP:
714	case IEEE80211_M_MBSS:
715	case IEEE80211_M_STA:
716		/*
717		 * Setup sta db entry for local address.
718		 */
719		mwl_localstadb(vap);
720		if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
721		    vap->iv_opmode == IEEE80211_M_MBSS)
722			sc->sc_napvaps++;
723		else
724			sc->sc_nstavaps++;
725		break;
726	case IEEE80211_M_WDS:
727		sc->sc_nwdsvaps++;
728		break;
729	default:
730		break;
731	}
732	/*
733	 * Setup overall operating mode.
734	 */
735	if (sc->sc_napvaps)
736		ic->ic_opmode = IEEE80211_M_HOSTAP;
737	else if (sc->sc_nstavaps)
738		ic->ic_opmode = IEEE80211_M_STA;
739	else
740		ic->ic_opmode = opmode;
741
742	return vap;
743}
744
745static void
746mwl_vap_delete(struct ieee80211vap *vap)
747{
748	struct mwl_vap *mvp = MWL_VAP(vap);
749	struct ifnet *parent = vap->iv_ic->ic_ifp;
750	struct mwl_softc *sc = parent->if_softc;
751	struct mwl_hal *mh = sc->sc_mh;
752	struct mwl_hal_vap *hvap = mvp->mv_hvap;
753	enum ieee80211_opmode opmode = vap->iv_opmode;
754
755	/* XXX disallow ap vap delete if WDS still present */
756	if (parent->if_drv_flags & IFF_DRV_RUNNING) {
757		/* quiesce h/w while we remove the vap */
758		mwl_hal_intrset(mh, 0);		/* disable interrupts */
759	}
760	ieee80211_vap_detach(vap);
761	switch (opmode) {
762	case IEEE80211_M_HOSTAP:
763	case IEEE80211_M_MBSS:
764	case IEEE80211_M_STA:
765		KASSERT(hvap != NULL, ("no hal vap handle"));
766		(void) mwl_hal_delstation(hvap, vap->iv_myaddr);
767		mwl_hal_delvap(hvap);
768		if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_MBSS)
769			sc->sc_napvaps--;
770		else
771			sc->sc_nstavaps--;
772		/* XXX don't do it for IEEE80211_CLONE_MACADDR */
773		reclaim_address(sc, vap->iv_myaddr);
774		break;
775	case IEEE80211_M_WDS:
776		sc->sc_nwdsvaps--;
777		break;
778	default:
779		break;
780	}
781	mwl_cleartxq(sc, vap);
782	free(mvp, M_80211_VAP);
783	if (parent->if_drv_flags & IFF_DRV_RUNNING)
784		mwl_hal_intrset(mh, sc->sc_imask);
785}
786
787void
788mwl_suspend(struct mwl_softc *sc)
789{
790	struct ifnet *ifp = sc->sc_ifp;
791
792	DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags %x\n",
793		__func__, ifp->if_flags);
794
795	mwl_stop(ifp, 1);
796}
797
798void
799mwl_resume(struct mwl_softc *sc)
800{
801	struct ifnet *ifp = sc->sc_ifp;
802
803	DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags %x\n",
804		__func__, ifp->if_flags);
805
806	if (ifp->if_flags & IFF_UP)
807		mwl_init(sc);
808}
809
810void
811mwl_shutdown(void *arg)
812{
813	struct mwl_softc *sc = arg;
814
815	mwl_stop(sc->sc_ifp, 1);
816}
817
818/*
819 * Interrupt handler.  Most of the actual processing is deferred.
820 */
821void
822mwl_intr(void *arg)
823{
824	struct mwl_softc *sc = arg;
825	struct mwl_hal *mh = sc->sc_mh;
826	uint32_t status;
827
828	if (sc->sc_invalid) {
829		/*
830		 * The hardware is not ready/present, don't touch anything.
831		 * Note this can happen early on if the IRQ is shared.
832		 */
833		DPRINTF(sc, MWL_DEBUG_ANY, "%s: invalid; ignored\n", __func__);
834		return;
835	}
836	/*
837	 * Figure out the reason(s) for the interrupt.
838	 */
839	mwl_hal_getisr(mh, &status);		/* NB: clears ISR too */
840	if (status == 0)			/* must be a shared irq */
841		return;
842
843	DPRINTF(sc, MWL_DEBUG_INTR, "%s: status 0x%x imask 0x%x\n",
844	    __func__, status, sc->sc_imask);
845	if (status & MACREG_A2HRIC_BIT_RX_RDY)
846		taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
847	if (status & MACREG_A2HRIC_BIT_TX_DONE)
848		taskqueue_enqueue(sc->sc_tq, &sc->sc_txtask);
849	if (status & MACREG_A2HRIC_BIT_BA_WATCHDOG)
850		taskqueue_enqueue(sc->sc_tq, &sc->sc_bawatchdogtask);
851	if (status & MACREG_A2HRIC_BIT_OPC_DONE)
852		mwl_hal_cmddone(mh);
853	if (status & MACREG_A2HRIC_BIT_MAC_EVENT) {
854		;
855	}
856	if (status & MACREG_A2HRIC_BIT_ICV_ERROR) {
857		/* TKIP ICV error */
858		sc->sc_stats.mst_rx_badtkipicv++;
859	}
860	if (status & MACREG_A2HRIC_BIT_QUEUE_EMPTY) {
861		/* 11n aggregation queue is empty, re-fill */
862		;
863	}
864	if (status & MACREG_A2HRIC_BIT_QUEUE_FULL) {
865		;
866	}
867	if (status & MACREG_A2HRIC_BIT_RADAR_DETECT) {
868		/* radar detected, process event */
869		taskqueue_enqueue(sc->sc_tq, &sc->sc_radartask);
870	}
871	if (status & MACREG_A2HRIC_BIT_CHAN_SWITCH) {
872		/* DFS channel switch */
873		taskqueue_enqueue(sc->sc_tq, &sc->sc_chanswitchtask);
874	}
875}
876
877static void
878mwl_radar_proc(void *arg, int pending)
879{
880	struct mwl_softc *sc = arg;
881	struct ifnet *ifp = sc->sc_ifp;
882	struct ieee80211com *ic = ifp->if_l2com;
883
884	DPRINTF(sc, MWL_DEBUG_ANY, "%s: radar detected, pending %u\n",
885	    __func__, pending);
886
887	sc->sc_stats.mst_radardetect++;
888	/* XXX stop h/w BA streams? */
889
890	IEEE80211_LOCK(ic);
891	ieee80211_dfs_notify_radar(ic, ic->ic_curchan);
892	IEEE80211_UNLOCK(ic);
893}
894
895static void
896mwl_chanswitch_proc(void *arg, int pending)
897{
898	struct mwl_softc *sc = arg;
899	struct ifnet *ifp = sc->sc_ifp;
900	struct ieee80211com *ic = ifp->if_l2com;
901
902	DPRINTF(sc, MWL_DEBUG_ANY, "%s: channel switch notice, pending %u\n",
903	    __func__, pending);
904
905	IEEE80211_LOCK(ic);
906	sc->sc_csapending = 0;
907	ieee80211_csa_completeswitch(ic);
908	IEEE80211_UNLOCK(ic);
909}
910
911static void
912mwl_bawatchdog(const MWL_HAL_BASTREAM *sp)
913{
914	struct ieee80211_node *ni = sp->data[0];
915
916	/* send DELBA and drop the stream */
917	ieee80211_ampdu_stop(ni, sp->data[1], IEEE80211_REASON_UNSPECIFIED);
918}
919
920static void
921mwl_bawatchdog_proc(void *arg, int pending)
922{
923	struct mwl_softc *sc = arg;
924	struct mwl_hal *mh = sc->sc_mh;
925	const MWL_HAL_BASTREAM *sp;
926	uint8_t bitmap, n;
927
928	sc->sc_stats.mst_bawatchdog++;
929
930	if (mwl_hal_getwatchdogbitmap(mh, &bitmap) != 0) {
931		DPRINTF(sc, MWL_DEBUG_AMPDU,
932		    "%s: could not get bitmap\n", __func__);
933		sc->sc_stats.mst_bawatchdog_failed++;
934		return;
935	}
936	DPRINTF(sc, MWL_DEBUG_AMPDU, "%s: bitmap 0x%x\n", __func__, bitmap);
937	if (bitmap == 0xff) {
938		n = 0;
939		/* disable all ba streams */
940		for (bitmap = 0; bitmap < 8; bitmap++) {
941			sp = mwl_hal_bastream_lookup(mh, bitmap);
942			if (sp != NULL) {
943				mwl_bawatchdog(sp);
944				n++;
945			}
946		}
947		if (n == 0) {
948			DPRINTF(sc, MWL_DEBUG_AMPDU,
949			    "%s: no BA streams found\n", __func__);
950			sc->sc_stats.mst_bawatchdog_empty++;
951		}
952	} else if (bitmap != 0xaa) {
953		/* disable a single ba stream */
954		sp = mwl_hal_bastream_lookup(mh, bitmap);
955		if (sp != NULL) {
956			mwl_bawatchdog(sp);
957		} else {
958			DPRINTF(sc, MWL_DEBUG_AMPDU,
959			    "%s: no BA stream %d\n", __func__, bitmap);
960			sc->sc_stats.mst_bawatchdog_notfound++;
961		}
962	}
963}
964
965/*
966 * Convert net80211 channel to a HAL channel.
967 */
968static void
969mwl_mapchan(MWL_HAL_CHANNEL *hc, const struct ieee80211_channel *chan)
970{
971	hc->channel = chan->ic_ieee;
972
973	*(uint32_t *)&hc->channelFlags = 0;
974	if (IEEE80211_IS_CHAN_2GHZ(chan))
975		hc->channelFlags.FreqBand = MWL_FREQ_BAND_2DOT4GHZ;
976	else if (IEEE80211_IS_CHAN_5GHZ(chan))
977		hc->channelFlags.FreqBand = MWL_FREQ_BAND_5GHZ;
978	if (IEEE80211_IS_CHAN_HT40(chan)) {
979		hc->channelFlags.ChnlWidth = MWL_CH_40_MHz_WIDTH;
980		if (IEEE80211_IS_CHAN_HT40U(chan))
981			hc->channelFlags.ExtChnlOffset = MWL_EXT_CH_ABOVE_CTRL_CH;
982		else
983			hc->channelFlags.ExtChnlOffset = MWL_EXT_CH_BELOW_CTRL_CH;
984	} else
985		hc->channelFlags.ChnlWidth = MWL_CH_20_MHz_WIDTH;
986	/* XXX 10MHz channels */
987}
988
989/*
990 * Inform firmware of our tx/rx dma setup.  The BAR 0
991 * writes below are for compatibility with older firmware.
992 * For current firmware we send this information with a
993 * cmd block via mwl_hal_sethwdma.
994 */
995static int
996mwl_setupdma(struct mwl_softc *sc)
997{
998	int error, i;
999
1000	sc->sc_hwdma.rxDescRead = sc->sc_rxdma.dd_desc_paddr;
1001	WR4(sc, sc->sc_hwspecs.rxDescRead, sc->sc_hwdma.rxDescRead);
1002	WR4(sc, sc->sc_hwspecs.rxDescWrite, sc->sc_hwdma.rxDescRead);
1003
1004	for (i = 0; i < MWL_NUM_TX_QUEUES-MWL_NUM_ACK_QUEUES; i++) {
1005		struct mwl_txq *txq = &sc->sc_txq[i];
1006		sc->sc_hwdma.wcbBase[i] = txq->dma.dd_desc_paddr;
1007		WR4(sc, sc->sc_hwspecs.wcbBase[i], sc->sc_hwdma.wcbBase[i]);
1008	}
1009	sc->sc_hwdma.maxNumTxWcb = mwl_txbuf;
1010	sc->sc_hwdma.maxNumWCB = MWL_NUM_TX_QUEUES-MWL_NUM_ACK_QUEUES;
1011
1012	error = mwl_hal_sethwdma(sc->sc_mh, &sc->sc_hwdma);
1013	if (error != 0) {
1014		device_printf(sc->sc_dev,
1015		    "unable to setup tx/rx dma; hal status %u\n", error);
1016		/* XXX */
1017	}
1018	return error;
1019}
1020
1021/*
1022 * Inform firmware of tx rate parameters.
1023 * Called after a channel change.
1024 */
1025static int
1026mwl_setcurchanrates(struct mwl_softc *sc)
1027{
1028	struct ifnet *ifp = sc->sc_ifp;
1029	struct ieee80211com *ic = ifp->if_l2com;
1030	const struct ieee80211_rateset *rs;
1031	MWL_HAL_TXRATE rates;
1032
1033	memset(&rates, 0, sizeof(rates));
1034	rs = ieee80211_get_suprates(ic, ic->ic_curchan);
1035	/* rate used to send management frames */
1036	rates.MgtRate = rs->rs_rates[0] & IEEE80211_RATE_VAL;
1037	/* rate used to send multicast frames */
1038	rates.McastRate = rates.MgtRate;
1039
1040	return mwl_hal_settxrate_auto(sc->sc_mh, &rates);
1041}
1042
1043/*
1044 * Inform firmware of tx rate parameters.  Called whenever
1045 * user-settable params change and after a channel change.
1046 */
1047static int
1048mwl_setrates(struct ieee80211vap *vap)
1049{
1050	struct mwl_vap *mvp = MWL_VAP(vap);
1051	struct ieee80211_node *ni = vap->iv_bss;
1052	const struct ieee80211_txparam *tp = ni->ni_txparms;
1053	MWL_HAL_TXRATE rates;
1054
1055	KASSERT(vap->iv_state == IEEE80211_S_RUN, ("state %d", vap->iv_state));
1056
1057	/*
1058	 * Update the h/w rate map.
1059	 * NB: 0x80 for MCS is passed through unchanged
1060	 */
1061	memset(&rates, 0, sizeof(rates));
1062	/* rate used to send management frames */
1063	rates.MgtRate = tp->mgmtrate;
1064	/* rate used to send multicast frames */
1065	rates.McastRate = tp->mcastrate;
1066
1067	/* while here calculate EAPOL fixed rate cookie */
1068	mvp->mv_eapolformat = htole16(mwl_calcformat(rates.MgtRate, ni));
1069
1070	return mwl_hal_settxrate(mvp->mv_hvap,
1071	    tp->ucastrate != IEEE80211_FIXED_RATE_NONE ?
1072		RATE_FIXED : RATE_AUTO, &rates);
1073}
1074
1075/*
1076 * Setup a fixed xmit rate cookie for EAPOL frames.
1077 */
1078static void
1079mwl_seteapolformat(struct ieee80211vap *vap)
1080{
1081	struct mwl_vap *mvp = MWL_VAP(vap);
1082	struct ieee80211_node *ni = vap->iv_bss;
1083	enum ieee80211_phymode mode;
1084	uint8_t rate;
1085
1086	KASSERT(vap->iv_state == IEEE80211_S_RUN, ("state %d", vap->iv_state));
1087
1088	mode = ieee80211_chan2mode(ni->ni_chan);
1089	/*
1090	 * Use legacy rates when operating a mixed HT+non-HT bss.
1091	 * NB: this may violate POLA for sta and wds vap's.
1092	 */
1093	if (mode == IEEE80211_MODE_11NA &&
1094	    (vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0)
1095		rate = vap->iv_txparms[IEEE80211_MODE_11A].mgmtrate;
1096	else if (mode == IEEE80211_MODE_11NG &&
1097	    (vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0)
1098		rate = vap->iv_txparms[IEEE80211_MODE_11G].mgmtrate;
1099	else
1100		rate = vap->iv_txparms[mode].mgmtrate;
1101
1102	mvp->mv_eapolformat = htole16(mwl_calcformat(rate, ni));
1103}
1104
1105/*
1106 * Map SKU+country code to region code for radar bin'ing.
1107 */
1108static int
1109mwl_map2regioncode(const struct ieee80211_regdomain *rd)
1110{
1111	switch (rd->regdomain) {
1112	case SKU_FCC:
1113	case SKU_FCC3:
1114		return DOMAIN_CODE_FCC;
1115	case SKU_CA:
1116		return DOMAIN_CODE_IC;
1117	case SKU_ETSI:
1118	case SKU_ETSI2:
1119	case SKU_ETSI3:
1120		if (rd->country == CTRY_SPAIN)
1121			return DOMAIN_CODE_SPAIN;
1122		if (rd->country == CTRY_FRANCE || rd->country == CTRY_FRANCE2)
1123			return DOMAIN_CODE_FRANCE;
1124		/* XXX force 1.3.1 radar type */
1125		return DOMAIN_CODE_ETSI_131;
1126	case SKU_JAPAN:
1127		return DOMAIN_CODE_MKK;
1128	case SKU_ROW:
1129		return DOMAIN_CODE_DGT;	/* Taiwan */
1130	case SKU_APAC:
1131	case SKU_APAC2:
1132	case SKU_APAC3:
1133		return DOMAIN_CODE_AUS;	/* Australia */
1134	}
1135	/* XXX KOREA? */
1136	return DOMAIN_CODE_FCC;			/* XXX? */
1137}
1138
1139static int
1140mwl_hal_reset(struct mwl_softc *sc)
1141{
1142	struct ifnet *ifp = sc->sc_ifp;
1143	struct ieee80211com *ic = ifp->if_l2com;
1144	struct mwl_hal *mh = sc->sc_mh;
1145
1146	mwl_hal_setantenna(mh, WL_ANTENNATYPE_RX, sc->sc_rxantenna);
1147	mwl_hal_setantenna(mh, WL_ANTENNATYPE_TX, sc->sc_txantenna);
1148	mwl_hal_setradio(mh, 1, WL_AUTO_PREAMBLE);
1149	mwl_hal_setwmm(sc->sc_mh, (ic->ic_flags & IEEE80211_F_WME) != 0);
1150	mwl_chan_set(sc, ic->ic_curchan);
1151	/* NB: RF/RA performance tuned for indoor mode */
1152	mwl_hal_setrateadaptmode(mh, 0);
1153	mwl_hal_setoptimizationlevel(mh,
1154	    (ic->ic_flags & IEEE80211_F_BURST) != 0);
1155
1156	mwl_hal_setregioncode(mh, mwl_map2regioncode(&ic->ic_regdomain));
1157
1158	mwl_hal_setaggampduratemode(mh, 1, 80);		/* XXX */
1159	mwl_hal_setcfend(mh, 0);			/* XXX */
1160
1161	return 1;
1162}
1163
1164static int
1165mwl_init_locked(struct mwl_softc *sc)
1166{
1167	struct ifnet *ifp = sc->sc_ifp;
1168	struct mwl_hal *mh = sc->sc_mh;
1169	int error = 0;
1170
1171	DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags 0x%x\n",
1172		__func__, ifp->if_flags);
1173
1174	MWL_LOCK_ASSERT(sc);
1175
1176	/*
1177	 * Stop anything previously setup.  This is safe
1178	 * whether this is the first time through or not.
1179	 */
1180	mwl_stop_locked(ifp, 0);
1181
1182	/*
1183	 * Push vap-independent state to the firmware.
1184	 */
1185	if (!mwl_hal_reset(sc)) {
1186		if_printf(ifp, "unable to reset hardware\n");
1187		return EIO;
1188	}
1189
1190	/*
1191	 * Setup recv (once); transmit is already good to go.
1192	 */
1193	error = mwl_startrecv(sc);
1194	if (error != 0) {
1195		if_printf(ifp, "unable to start recv logic\n");
1196		return error;
1197	}
1198
1199	/*
1200	 * Enable interrupts.
1201	 */
1202	sc->sc_imask = MACREG_A2HRIC_BIT_RX_RDY
1203		     | MACREG_A2HRIC_BIT_TX_DONE
1204		     | MACREG_A2HRIC_BIT_OPC_DONE
1205#if 0
1206		     | MACREG_A2HRIC_BIT_MAC_EVENT
1207#endif
1208		     | MACREG_A2HRIC_BIT_ICV_ERROR
1209		     | MACREG_A2HRIC_BIT_RADAR_DETECT
1210		     | MACREG_A2HRIC_BIT_CHAN_SWITCH
1211#if 0
1212		     | MACREG_A2HRIC_BIT_QUEUE_EMPTY
1213#endif
1214		     | MACREG_A2HRIC_BIT_BA_WATCHDOG
1215		     | MACREQ_A2HRIC_BIT_TX_ACK
1216		     ;
1217
1218	ifp->if_drv_flags |= IFF_DRV_RUNNING;
1219	mwl_hal_intrset(mh, sc->sc_imask);
1220	callout_reset(&sc->sc_watchdog, hz, mwl_watchdog, sc);
1221
1222	return 0;
1223}
1224
1225static void
1226mwl_init(void *arg)
1227{
1228	struct mwl_softc *sc = arg;
1229	struct ifnet *ifp = sc->sc_ifp;
1230	struct ieee80211com *ic = ifp->if_l2com;
1231	int error = 0;
1232
1233	DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags 0x%x\n",
1234		__func__, ifp->if_flags);
1235
1236	MWL_LOCK(sc);
1237	error = mwl_init_locked(sc);
1238	MWL_UNLOCK(sc);
1239
1240	if (error == 0)
1241		ieee80211_start_all(ic);	/* start all vap's */
1242}
1243
1244static void
1245mwl_stop_locked(struct ifnet *ifp, int disable)
1246{
1247	struct mwl_softc *sc = ifp->if_softc;
1248
1249	DPRINTF(sc, MWL_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
1250		__func__, sc->sc_invalid, ifp->if_flags);
1251
1252	MWL_LOCK_ASSERT(sc);
1253	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1254		/*
1255		 * Shutdown the hardware and driver.
1256		 */
1257		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1258		callout_stop(&sc->sc_watchdog);
1259		sc->sc_tx_timer = 0;
1260		mwl_draintxq(sc);
1261	}
1262}
1263
1264static void
1265mwl_stop(struct ifnet *ifp, int disable)
1266{
1267	struct mwl_softc *sc = ifp->if_softc;
1268
1269	MWL_LOCK(sc);
1270	mwl_stop_locked(ifp, disable);
1271	MWL_UNLOCK(sc);
1272}
1273
1274static int
1275mwl_reset_vap(struct ieee80211vap *vap, int state)
1276{
1277	struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
1278	struct ieee80211com *ic = vap->iv_ic;
1279
1280	if (state == IEEE80211_S_RUN)
1281		mwl_setrates(vap);
1282	/* XXX off by 1? */
1283	mwl_hal_setrtsthreshold(hvap, vap->iv_rtsthreshold);
1284	/* XXX auto? 20/40 split? */
1285	mwl_hal_sethtgi(hvap, (vap->iv_flags_ht &
1286	    (IEEE80211_FHT_SHORTGI20|IEEE80211_FHT_SHORTGI40)) ? 1 : 0);
1287	mwl_hal_setnprot(hvap, ic->ic_htprotmode == IEEE80211_PROT_NONE ?
1288	    HTPROTECT_NONE : HTPROTECT_AUTO);
1289	/* XXX txpower cap */
1290
1291	/* re-setup beacons */
1292	if (state == IEEE80211_S_RUN &&
1293	    (vap->iv_opmode == IEEE80211_M_HOSTAP ||
1294	     vap->iv_opmode == IEEE80211_M_MBSS ||
1295	     vap->iv_opmode == IEEE80211_M_IBSS)) {
1296		mwl_setapmode(vap, vap->iv_bss->ni_chan);
1297		mwl_hal_setnprotmode(hvap,
1298		    MS(ic->ic_curhtprotmode, IEEE80211_HTINFO_OPMODE));
1299		return mwl_beacon_setup(vap);
1300	}
1301	return 0;
1302}
1303
1304/*
1305 * Reset the hardware w/o losing operational state.
1306 * Used to to reset or reload hardware state for a vap.
1307 */
1308static int
1309mwl_reset(struct ieee80211vap *vap, u_long cmd)
1310{
1311	struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
1312	int error = 0;
1313
1314	if (hvap != NULL) {			/* WDS, MONITOR, etc. */
1315		struct ieee80211com *ic = vap->iv_ic;
1316		struct ifnet *ifp = ic->ic_ifp;
1317		struct mwl_softc *sc = ifp->if_softc;
1318		struct mwl_hal *mh = sc->sc_mh;
1319
1320		/* XXX handle DWDS sta vap change */
1321		/* XXX do we need to disable interrupts? */
1322		mwl_hal_intrset(mh, 0);		/* disable interrupts */
1323		error = mwl_reset_vap(vap, vap->iv_state);
1324		mwl_hal_intrset(mh, sc->sc_imask);
1325	}
1326	return error;
1327}
1328
1329/*
1330 * Allocate a tx buffer for sending a frame.  The
1331 * packet is assumed to have the WME AC stored so
1332 * we can use it to select the appropriate h/w queue.
1333 */
1334static struct mwl_txbuf *
1335mwl_gettxbuf(struct mwl_softc *sc, struct mwl_txq *txq)
1336{
1337	struct mwl_txbuf *bf;
1338
1339	/*
1340	 * Grab a TX buffer and associated resources.
1341	 */
1342	MWL_TXQ_LOCK(txq);
1343	bf = STAILQ_FIRST(&txq->free);
1344	if (bf != NULL) {
1345		STAILQ_REMOVE_HEAD(&txq->free, bf_list);
1346		txq->nfree--;
1347	}
1348	MWL_TXQ_UNLOCK(txq);
1349	if (bf == NULL)
1350		DPRINTF(sc, MWL_DEBUG_XMIT,
1351		    "%s: out of xmit buffers on q %d\n", __func__, txq->qnum);
1352	return bf;
1353}
1354
1355/*
1356 * Return a tx buffer to the queue it came from.  Note there
1357 * are two cases because we must preserve the order of buffers
1358 * as it reflects the fixed order of descriptors in memory
1359 * (the firmware pre-fetches descriptors so we cannot reorder).
1360 */
1361static void
1362mwl_puttxbuf_head(struct mwl_txq *txq, struct mwl_txbuf *bf)
1363{
1364	bf->bf_m = NULL;
1365	bf->bf_node = NULL;
1366	MWL_TXQ_LOCK(txq);
1367	STAILQ_INSERT_HEAD(&txq->free, bf, bf_list);
1368	txq->nfree++;
1369	MWL_TXQ_UNLOCK(txq);
1370}
1371
1372static void
1373mwl_puttxbuf_tail(struct mwl_txq *txq, struct mwl_txbuf *bf)
1374{
1375	bf->bf_m = NULL;
1376	bf->bf_node = NULL;
1377	MWL_TXQ_LOCK(txq);
1378	STAILQ_INSERT_TAIL(&txq->free, bf, bf_list);
1379	txq->nfree++;
1380	MWL_TXQ_UNLOCK(txq);
1381}
1382
1383static void
1384mwl_start(struct ifnet *ifp)
1385{
1386	struct mwl_softc *sc = ifp->if_softc;
1387	struct ieee80211_node *ni;
1388	struct mwl_txbuf *bf;
1389	struct mbuf *m;
1390	struct mwl_txq *txq = NULL;	/* XXX silence gcc */
1391	int nqueued;
1392
1393	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
1394		return;
1395	nqueued = 0;
1396	for (;;) {
1397		bf = NULL;
1398		IFQ_DEQUEUE(&ifp->if_snd, m);
1399		if (m == NULL)
1400			break;
1401		/*
1402		 * Grab the node for the destination.
1403		 */
1404		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1405		KASSERT(ni != NULL, ("no node"));
1406		m->m_pkthdr.rcvif = NULL;	/* committed, clear ref */
1407		/*
1408		 * Grab a TX buffer and associated resources.
1409		 * We honor the classification by the 802.11 layer.
1410		 */
1411		txq = sc->sc_ac2q[M_WME_GETAC(m)];
1412		bf = mwl_gettxbuf(sc, txq);
1413		if (bf == NULL) {
1414			m_freem(m);
1415			ieee80211_free_node(ni);
1416#ifdef MWL_TX_NODROP
1417			sc->sc_stats.mst_tx_qstop++;
1418			/* XXX blocks other traffic */
1419			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1420			break;
1421#else
1422			DPRINTF(sc, MWL_DEBUG_XMIT,
1423			    "%s: tail drop on q %d\n", __func__, txq->qnum);
1424			sc->sc_stats.mst_tx_qdrop++;
1425			continue;
1426#endif /* MWL_TX_NODROP */
1427		}
1428
1429		/*
1430		 * Pass the frame to the h/w for transmission.
1431		 */
1432		if (mwl_tx_start(sc, ni, bf, m)) {
1433			ifp->if_oerrors++;
1434			mwl_puttxbuf_head(txq, bf);
1435			ieee80211_free_node(ni);
1436			continue;
1437		}
1438		nqueued++;
1439		if (nqueued >= mwl_txcoalesce) {
1440			/*
1441			 * Poke the firmware to process queued frames;
1442			 * see below about (lack of) locking.
1443			 */
1444			nqueued = 0;
1445			mwl_hal_txstart(sc->sc_mh, 0/*XXX*/);
1446		}
1447	}
1448	if (nqueued) {
1449		/*
1450		 * NB: We don't need to lock against tx done because
1451		 * this just prods the firmware to check the transmit
1452		 * descriptors.  The firmware will also start fetching
1453		 * descriptors by itself if it notices new ones are
1454		 * present when it goes to deliver a tx done interrupt
1455		 * to the host. So if we race with tx done processing
1456		 * it's ok.  Delivering the kick here rather than in
1457		 * mwl_tx_start is an optimization to avoid poking the
1458		 * firmware for each packet.
1459		 *
1460		 * NB: the queue id isn't used so 0 is ok.
1461		 */
1462		mwl_hal_txstart(sc->sc_mh, 0/*XXX*/);
1463	}
1464}
1465
1466static int
1467mwl_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1468	const struct ieee80211_bpf_params *params)
1469{
1470	struct ieee80211com *ic = ni->ni_ic;
1471	struct ifnet *ifp = ic->ic_ifp;
1472	struct mwl_softc *sc = ifp->if_softc;
1473	struct mwl_txbuf *bf;
1474	struct mwl_txq *txq;
1475
1476	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) {
1477		ieee80211_free_node(ni);
1478		m_freem(m);
1479		return ENETDOWN;
1480	}
1481	/*
1482	 * Grab a TX buffer and associated resources.
1483	 * Note that we depend on the classification
1484	 * by the 802.11 layer to get to the right h/w
1485	 * queue.  Management frames must ALWAYS go on
1486	 * queue 1 but we cannot just force that here
1487	 * because we may receive non-mgt frames.
1488	 */
1489	txq = sc->sc_ac2q[M_WME_GETAC(m)];
1490	bf = mwl_gettxbuf(sc, txq);
1491	if (bf == NULL) {
1492		sc->sc_stats.mst_tx_qstop++;
1493		/* XXX blocks other traffic */
1494		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1495		ieee80211_free_node(ni);
1496		m_freem(m);
1497		return ENOBUFS;
1498	}
1499	/*
1500	 * Pass the frame to the h/w for transmission.
1501	 */
1502	if (mwl_tx_start(sc, ni, bf, m)) {
1503		ifp->if_oerrors++;
1504		mwl_puttxbuf_head(txq, bf);
1505
1506		ieee80211_free_node(ni);
1507		return EIO;		/* XXX */
1508	}
1509	/*
1510	 * NB: We don't need to lock against tx done because
1511	 * this just prods the firmware to check the transmit
1512	 * descriptors.  The firmware will also start fetching
1513	 * descriptors by itself if it notices new ones are
1514	 * present when it goes to deliver a tx done interrupt
1515	 * to the host. So if we race with tx done processing
1516	 * it's ok.  Delivering the kick here rather than in
1517	 * mwl_tx_start is an optimization to avoid poking the
1518	 * firmware for each packet.
1519	 *
1520	 * NB: the queue id isn't used so 0 is ok.
1521	 */
1522	mwl_hal_txstart(sc->sc_mh, 0/*XXX*/);
1523	return 0;
1524}
1525
1526static int
1527mwl_media_change(struct ifnet *ifp)
1528{
1529	struct ieee80211vap *vap = ifp->if_softc;
1530	int error;
1531
1532	error = ieee80211_media_change(ifp);
1533	/* NB: only the fixed rate can change and that doesn't need a reset */
1534	if (error == ENETRESET) {
1535		mwl_setrates(vap);
1536		error = 0;
1537	}
1538	return error;
1539}
1540
1541#ifdef MWL_DEBUG
1542static void
1543mwl_keyprint(struct mwl_softc *sc, const char *tag,
1544	const MWL_HAL_KEYVAL *hk, const uint8_t mac[IEEE80211_ADDR_LEN])
1545{
1546	static const char *ciphers[] = {
1547		"WEP",
1548		"TKIP",
1549		"AES-CCM",
1550	};
1551	int i, n;
1552
1553	printf("%s: [%u] %-7s", tag, hk->keyIndex, ciphers[hk->keyTypeId]);
1554	for (i = 0, n = hk->keyLen; i < n; i++)
1555		printf(" %02x", hk->key.aes[i]);
1556	printf(" mac %s", ether_sprintf(mac));
1557	if (hk->keyTypeId == KEY_TYPE_ID_TKIP) {
1558		printf(" %s", "rxmic");
1559		for (i = 0; i < sizeof(hk->key.tkip.rxMic); i++)
1560			printf(" %02x", hk->key.tkip.rxMic[i]);
1561		printf(" txmic");
1562		for (i = 0; i < sizeof(hk->key.tkip.txMic); i++)
1563			printf(" %02x", hk->key.tkip.txMic[i]);
1564	}
1565	printf(" flags 0x%x\n", hk->keyFlags);
1566}
1567#endif
1568
1569/*
1570 * Allocate a key cache slot for a unicast key.  The
1571 * firmware handles key allocation and every station is
1572 * guaranteed key space so we are always successful.
1573 */
1574static int
1575mwl_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
1576	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
1577{
1578	struct mwl_softc *sc = vap->iv_ic->ic_ifp->if_softc;
1579
1580	if (k->wk_keyix != IEEE80211_KEYIX_NONE ||
1581	    (k->wk_flags & IEEE80211_KEY_GROUP)) {
1582		if (!(&vap->iv_nw_keys[0] <= k &&
1583		      k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) {
1584			/* should not happen */
1585			DPRINTF(sc, MWL_DEBUG_KEYCACHE,
1586				"%s: bogus group key\n", __func__);
1587			return 0;
1588		}
1589		/* give the caller what they requested */
1590		*keyix = *rxkeyix = k - vap->iv_nw_keys;
1591	} else {
1592		/*
1593		 * Firmware handles key allocation.
1594		 */
1595		*keyix = *rxkeyix = 0;
1596	}
1597	return 1;
1598}
1599
1600/*
1601 * Delete a key entry allocated by mwl_key_alloc.
1602 */
1603static int
1604mwl_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
1605{
1606	struct mwl_softc *sc = vap->iv_ic->ic_ifp->if_softc;
1607	struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
1608	MWL_HAL_KEYVAL hk;
1609	const uint8_t bcastaddr[IEEE80211_ADDR_LEN] =
1610	    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1611
1612	if (hvap == NULL) {
1613		if (vap->iv_opmode != IEEE80211_M_WDS) {
1614			/* XXX monitor mode? */
1615			DPRINTF(sc, MWL_DEBUG_KEYCACHE,
1616			    "%s: no hvap for opmode %d\n", __func__,
1617			    vap->iv_opmode);
1618			return 0;
1619		}
1620		hvap = MWL_VAP(vap)->mv_ap_hvap;
1621	}
1622
1623	DPRINTF(sc, MWL_DEBUG_KEYCACHE, "%s: delete key %u\n",
1624	    __func__, k->wk_keyix);
1625
1626	memset(&hk, 0, sizeof(hk));
1627	hk.keyIndex = k->wk_keyix;
1628	switch (k->wk_cipher->ic_cipher) {
1629	case IEEE80211_CIPHER_WEP:
1630		hk.keyTypeId = KEY_TYPE_ID_WEP;
1631		break;
1632	case IEEE80211_CIPHER_TKIP:
1633		hk.keyTypeId = KEY_TYPE_ID_TKIP;
1634		break;
1635	case IEEE80211_CIPHER_AES_CCM:
1636		hk.keyTypeId = KEY_TYPE_ID_AES;
1637		break;
1638	default:
1639		/* XXX should not happen */
1640		DPRINTF(sc, MWL_DEBUG_KEYCACHE, "%s: unknown cipher %d\n",
1641		    __func__, k->wk_cipher->ic_cipher);
1642		return 0;
1643	}
1644	return (mwl_hal_keyreset(hvap, &hk, bcastaddr) == 0);	/*XXX*/
1645}
1646
1647static __inline int
1648addgroupflags(MWL_HAL_KEYVAL *hk, const struct ieee80211_key *k)
1649{
1650	if (k->wk_flags & IEEE80211_KEY_GROUP) {
1651		if (k->wk_flags & IEEE80211_KEY_XMIT)
1652			hk->keyFlags |= KEY_FLAG_TXGROUPKEY;
1653		if (k->wk_flags & IEEE80211_KEY_RECV)
1654			hk->keyFlags |= KEY_FLAG_RXGROUPKEY;
1655		return 1;
1656	} else
1657		return 0;
1658}
1659
1660/*
1661 * Set the key cache contents for the specified key.  Key cache
1662 * slot(s) must already have been allocated by mwl_key_alloc.
1663 */
1664static int
1665mwl_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
1666	const uint8_t mac[IEEE80211_ADDR_LEN])
1667{
1668#define	GRPXMIT	(IEEE80211_KEY_XMIT | IEEE80211_KEY_GROUP)
1669/* NB: static wep keys are marked GROUP+tx/rx; GTK will be tx or rx */
1670#define	IEEE80211_IS_STATICKEY(k) \
1671	(((k)->wk_flags & (GRPXMIT|IEEE80211_KEY_RECV)) == \
1672	 (GRPXMIT|IEEE80211_KEY_RECV))
1673	struct mwl_softc *sc = vap->iv_ic->ic_ifp->if_softc;
1674	struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
1675	const struct ieee80211_cipher *cip = k->wk_cipher;
1676	const uint8_t *macaddr;
1677	MWL_HAL_KEYVAL hk;
1678
1679	KASSERT((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0,
1680		("s/w crypto set?"));
1681
1682	if (hvap == NULL) {
1683		if (vap->iv_opmode != IEEE80211_M_WDS) {
1684			/* XXX monitor mode? */
1685			DPRINTF(sc, MWL_DEBUG_KEYCACHE,
1686			    "%s: no hvap for opmode %d\n", __func__,
1687			    vap->iv_opmode);
1688			return 0;
1689		}
1690		hvap = MWL_VAP(vap)->mv_ap_hvap;
1691	}
1692	memset(&hk, 0, sizeof(hk));
1693	hk.keyIndex = k->wk_keyix;
1694	switch (cip->ic_cipher) {
1695	case IEEE80211_CIPHER_WEP:
1696		hk.keyTypeId = KEY_TYPE_ID_WEP;
1697		hk.keyLen = k->wk_keylen;
1698		if (k->wk_keyix == vap->iv_def_txkey)
1699			hk.keyFlags = KEY_FLAG_WEP_TXKEY;
1700		if (!IEEE80211_IS_STATICKEY(k)) {
1701			/* NB: WEP is never used for the PTK */
1702			(void) addgroupflags(&hk, k);
1703		}
1704		break;
1705	case IEEE80211_CIPHER_TKIP:
1706		hk.keyTypeId = KEY_TYPE_ID_TKIP;
1707		hk.key.tkip.tsc.high = (uint32_t)(k->wk_keytsc >> 16);
1708		hk.key.tkip.tsc.low = (uint16_t)k->wk_keytsc;
1709		hk.keyFlags = KEY_FLAG_TSC_VALID | KEY_FLAG_MICKEY_VALID;
1710		hk.keyLen = k->wk_keylen + IEEE80211_MICBUF_SIZE;
1711		if (!addgroupflags(&hk, k))
1712			hk.keyFlags |= KEY_FLAG_PAIRWISE;
1713		break;
1714	case IEEE80211_CIPHER_AES_CCM:
1715		hk.keyTypeId = KEY_TYPE_ID_AES;
1716		hk.keyLen = k->wk_keylen;
1717		if (!addgroupflags(&hk, k))
1718			hk.keyFlags |= KEY_FLAG_PAIRWISE;
1719		break;
1720	default:
1721		/* XXX should not happen */
1722		DPRINTF(sc, MWL_DEBUG_KEYCACHE, "%s: unknown cipher %d\n",
1723		    __func__, k->wk_cipher->ic_cipher);
1724		return 0;
1725	}
1726	/*
1727	 * NB: tkip mic keys get copied here too; the layout
1728	 *     just happens to match that in ieee80211_key.
1729	 */
1730	memcpy(hk.key.aes, k->wk_key, hk.keyLen);
1731
1732	/*
1733	 * Locate address of sta db entry for writing key;
1734	 * the convention unfortunately is somewhat different
1735	 * than how net80211, hostapd, and wpa_supplicant think.
1736	 */
1737	if (vap->iv_opmode == IEEE80211_M_STA) {
1738		/*
1739		 * NB: keys plumbed before the sta reaches AUTH state
1740		 * will be discarded or written to the wrong sta db
1741		 * entry because iv_bss is meaningless.  This is ok
1742		 * (right now) because we handle deferred plumbing of
1743		 * WEP keys when the sta reaches AUTH state.
1744		 */
1745		macaddr = vap->iv_bss->ni_bssid;
1746		if ((k->wk_flags & IEEE80211_KEY_GROUP) == 0) {
1747			/* XXX plumb to local sta db too for static key wep */
1748			mwl_hal_keyset(hvap, &hk, vap->iv_myaddr);
1749		}
1750	} else if (vap->iv_opmode == IEEE80211_M_WDS &&
1751	    vap->iv_state != IEEE80211_S_RUN) {
1752		/*
1753		 * Prior to RUN state a WDS vap will not it's BSS node
1754		 * setup so we will plumb the key to the wrong mac
1755		 * address (it'll be our local address).  Workaround
1756		 * this for the moment by grabbing the correct address.
1757		 */
1758		macaddr = vap->iv_des_bssid;
1759	} else if ((k->wk_flags & GRPXMIT) == GRPXMIT)
1760		macaddr = vap->iv_myaddr;
1761	else
1762		macaddr = mac;
1763	KEYPRINTF(sc, &hk, macaddr);
1764	return (mwl_hal_keyset(hvap, &hk, macaddr) == 0);
1765#undef IEEE80211_IS_STATICKEY
1766#undef GRPXMIT
1767}
1768
1769/* unaligned little endian access */
1770#define LE_READ_2(p)				\
1771	((uint16_t)				\
1772	 ((((const uint8_t *)(p))[0]      ) |	\
1773	  (((const uint8_t *)(p))[1] <<  8)))
1774#define LE_READ_4(p)				\
1775	((uint32_t)				\
1776	 ((((const uint8_t *)(p))[0]      ) |	\
1777	  (((const uint8_t *)(p))[1] <<  8) |	\
1778	  (((const uint8_t *)(p))[2] << 16) |	\
1779	  (((const uint8_t *)(p))[3] << 24)))
1780
1781/*
1782 * Set the multicast filter contents into the hardware.
1783 * XXX f/w has no support; just defer to the os.
1784 */
1785static void
1786mwl_setmcastfilter(struct mwl_softc *sc)
1787{
1788	struct ifnet *ifp = sc->sc_ifp;
1789#if 0
1790	struct ether_multi *enm;
1791	struct ether_multistep estep;
1792	uint8_t macs[IEEE80211_ADDR_LEN*MWL_HAL_MCAST_MAX];/* XXX stack use */
1793	uint8_t *mp;
1794	int nmc;
1795
1796	mp = macs;
1797	nmc = 0;
1798	ETHER_FIRST_MULTI(estep, &sc->sc_ec, enm);
1799	while (enm != NULL) {
1800		/* XXX Punt on ranges. */
1801		if (nmc == MWL_HAL_MCAST_MAX ||
1802		    !IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi)) {
1803			ifp->if_flags |= IFF_ALLMULTI;
1804			return;
1805		}
1806		IEEE80211_ADDR_COPY(mp, enm->enm_addrlo);
1807		mp += IEEE80211_ADDR_LEN, nmc++;
1808		ETHER_NEXT_MULTI(estep, enm);
1809	}
1810	ifp->if_flags &= ~IFF_ALLMULTI;
1811	mwl_hal_setmcast(sc->sc_mh, nmc, macs);
1812#else
1813	/* XXX no mcast filter support; we get everything */
1814	ifp->if_flags |= IFF_ALLMULTI;
1815#endif
1816}
1817
1818static int
1819mwl_mode_init(struct mwl_softc *sc)
1820{
1821	struct ifnet *ifp = sc->sc_ifp;
1822	struct ieee80211com *ic = ifp->if_l2com;
1823	struct mwl_hal *mh = sc->sc_mh;
1824
1825	/*
1826	 * NB: Ignore promisc in hostap mode; it's set by the
1827	 * bridge.  This is wrong but we have no way to
1828	 * identify internal requests (from the bridge)
1829	 * versus external requests such as for tcpdump.
1830	 */
1831	mwl_hal_setpromisc(mh, (ifp->if_flags & IFF_PROMISC) &&
1832	    ic->ic_opmode != IEEE80211_M_HOSTAP);
1833	mwl_setmcastfilter(sc);
1834
1835	return 0;
1836}
1837
1838/*
1839 * Callback from the 802.11 layer after a multicast state change.
1840 */
1841static void
1842mwl_update_mcast(struct ifnet *ifp)
1843{
1844	struct mwl_softc *sc = ifp->if_softc;
1845
1846	mwl_setmcastfilter(sc);
1847}
1848
1849/*
1850 * Callback from the 802.11 layer after a promiscuous mode change.
1851 * Note this interface does not check the operating mode as this
1852 * is an internal callback and we are expected to honor the current
1853 * state (e.g. this is used for setting the interface in promiscuous
1854 * mode when operating in hostap mode to do ACS).
1855 */
1856static void
1857mwl_update_promisc(struct ifnet *ifp)
1858{
1859	struct mwl_softc *sc = ifp->if_softc;
1860
1861	mwl_hal_setpromisc(sc->sc_mh, (ifp->if_flags & IFF_PROMISC) != 0);
1862}
1863
1864/*
1865 * Callback from the 802.11 layer to update the slot time
1866 * based on the current setting.  We use it to notify the
1867 * firmware of ERP changes and the f/w takes care of things
1868 * like slot time and preamble.
1869 */
1870static void
1871mwl_updateslot(struct ifnet *ifp)
1872{
1873	struct mwl_softc *sc = ifp->if_softc;
1874	struct ieee80211com *ic = ifp->if_l2com;
1875	struct mwl_hal *mh = sc->sc_mh;
1876	int prot;
1877
1878	/* NB: can be called early; suppress needless cmds */
1879	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1880		return;
1881
1882	/*
1883	 * Calculate the ERP flags.  The firwmare will use
1884	 * this to carry out the appropriate measures.
1885	 */
1886	prot = 0;
1887	if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
1888		if ((ic->ic_flags & IEEE80211_F_SHSLOT) == 0)
1889			prot |= IEEE80211_ERP_NON_ERP_PRESENT;
1890		if (ic->ic_flags & IEEE80211_F_USEPROT)
1891			prot |= IEEE80211_ERP_USE_PROTECTION;
1892		if (ic->ic_flags & IEEE80211_F_USEBARKER)
1893			prot |= IEEE80211_ERP_LONG_PREAMBLE;
1894	}
1895
1896	DPRINTF(sc, MWL_DEBUG_RESET,
1897	    "%s: chan %u MHz/flags 0x%x %s slot, (prot 0x%x ic_flags 0x%x)\n",
1898	    __func__, ic->ic_curchan->ic_freq, ic->ic_curchan->ic_flags,
1899	    ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long", prot,
1900	    ic->ic_flags);
1901
1902	mwl_hal_setgprot(mh, prot);
1903}
1904
1905/*
1906 * Setup the beacon frame.
1907 */
1908static int
1909mwl_beacon_setup(struct ieee80211vap *vap)
1910{
1911	struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
1912	struct ieee80211_node *ni = vap->iv_bss;
1913	struct ieee80211_beacon_offsets bo;
1914	struct mbuf *m;
1915
1916	m = ieee80211_beacon_alloc(ni, &bo);
1917	if (m == NULL)
1918		return ENOBUFS;
1919	mwl_hal_setbeacon(hvap, mtod(m, const void *), m->m_len);
1920	m_free(m);
1921
1922	return 0;
1923}
1924
1925/*
1926 * Update the beacon frame in response to a change.
1927 */
1928static void
1929mwl_beacon_update(struct ieee80211vap *vap, int item)
1930{
1931	struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
1932	struct ieee80211com *ic = vap->iv_ic;
1933
1934	KASSERT(hvap != NULL, ("no beacon"));
1935	switch (item) {
1936	case IEEE80211_BEACON_ERP:
1937		mwl_updateslot(ic->ic_ifp);
1938		break;
1939	case IEEE80211_BEACON_HTINFO:
1940		mwl_hal_setnprotmode(hvap,
1941		    MS(ic->ic_curhtprotmode, IEEE80211_HTINFO_OPMODE));
1942		break;
1943	case IEEE80211_BEACON_CAPS:
1944	case IEEE80211_BEACON_WME:
1945	case IEEE80211_BEACON_APPIE:
1946	case IEEE80211_BEACON_CSA:
1947		break;
1948	case IEEE80211_BEACON_TIM:
1949		/* NB: firmware always forms TIM */
1950		return;
1951	}
1952	/* XXX retain beacon frame and update */
1953	mwl_beacon_setup(vap);
1954}
1955
1956static void
1957mwl_load_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
1958{
1959	bus_addr_t *paddr = (bus_addr_t*) arg;
1960	KASSERT(error == 0, ("error %u on bus_dma callback", error));
1961	*paddr = segs->ds_addr;
1962}
1963
1964#ifdef MWL_HOST_PS_SUPPORT
1965/*
1966 * Handle power save station occupancy changes.
1967 */
1968static void
1969mwl_update_ps(struct ieee80211vap *vap, int nsta)
1970{
1971	struct mwl_vap *mvp = MWL_VAP(vap);
1972
1973	if (nsta == 0 || mvp->mv_last_ps_sta == 0)
1974		mwl_hal_setpowersave_bss(mvp->mv_hvap, nsta);
1975	mvp->mv_last_ps_sta = nsta;
1976}
1977
1978/*
1979 * Handle associated station power save state changes.
1980 */
1981static int
1982mwl_set_tim(struct ieee80211_node *ni, int set)
1983{
1984	struct ieee80211vap *vap = ni->ni_vap;
1985	struct mwl_vap *mvp = MWL_VAP(vap);
1986
1987	if (mvp->mv_set_tim(ni, set)) {		/* NB: state change */
1988		mwl_hal_setpowersave_sta(mvp->mv_hvap,
1989		    IEEE80211_AID(ni->ni_associd), set);
1990		return 1;
1991	} else
1992		return 0;
1993}
1994#endif /* MWL_HOST_PS_SUPPORT */
1995
1996static int
1997mwl_desc_setup(struct mwl_softc *sc, const char *name,
1998	struct mwl_descdma *dd,
1999	int nbuf, size_t bufsize, int ndesc, size_t descsize)
2000{
2001	struct ifnet *ifp = sc->sc_ifp;
2002	uint8_t *ds;
2003	int error;
2004
2005	DPRINTF(sc, MWL_DEBUG_RESET,
2006	    "%s: %s DMA: %u bufs (%ju) %u desc/buf (%ju)\n",
2007	    __func__, name, nbuf, (uintmax_t) bufsize,
2008	    ndesc, (uintmax_t) descsize);
2009
2010	dd->dd_name = name;
2011	dd->dd_desc_len = nbuf * ndesc * descsize;
2012
2013	/*
2014	 * Setup DMA descriptor area.
2015	 */
2016	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
2017		       PAGE_SIZE, 0,		/* alignment, bounds */
2018		       BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
2019		       BUS_SPACE_MAXADDR,	/* highaddr */
2020		       NULL, NULL,		/* filter, filterarg */
2021		       dd->dd_desc_len,		/* maxsize */
2022		       1,			/* nsegments */
2023		       dd->dd_desc_len,		/* maxsegsize */
2024		       BUS_DMA_ALLOCNOW,	/* flags */
2025		       NULL,			/* lockfunc */
2026		       NULL,			/* lockarg */
2027		       &dd->dd_dmat);
2028	if (error != 0) {
2029		if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
2030		return error;
2031	}
2032
2033	/* allocate descriptors */
2034	error = bus_dmamap_create(dd->dd_dmat, BUS_DMA_NOWAIT, &dd->dd_dmamap);
2035	if (error != 0) {
2036		if_printf(ifp, "unable to create dmamap for %s descriptors, "
2037			"error %u\n", dd->dd_name, error);
2038		goto fail0;
2039	}
2040
2041	error = bus_dmamem_alloc(dd->dd_dmat, (void**) &dd->dd_desc,
2042				 BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
2043				 &dd->dd_dmamap);
2044	if (error != 0) {
2045		if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
2046			"error %u\n", nbuf * ndesc, dd->dd_name, error);
2047		goto fail1;
2048	}
2049
2050	error = bus_dmamap_load(dd->dd_dmat, dd->dd_dmamap,
2051				dd->dd_desc, dd->dd_desc_len,
2052				mwl_load_cb, &dd->dd_desc_paddr,
2053				BUS_DMA_NOWAIT);
2054	if (error != 0) {
2055		if_printf(ifp, "unable to map %s descriptors, error %u\n",
2056			dd->dd_name, error);
2057		goto fail2;
2058	}
2059
2060	ds = dd->dd_desc;
2061	memset(ds, 0, dd->dd_desc_len);
2062	DPRINTF(sc, MWL_DEBUG_RESET, "%s: %s DMA map: %p (%lu) -> %p (%lu)\n",
2063	    __func__, dd->dd_name, ds, (u_long) dd->dd_desc_len,
2064	    (caddr_t) dd->dd_desc_paddr, /*XXX*/ (u_long) dd->dd_desc_len);
2065
2066	return 0;
2067fail2:
2068	bus_dmamem_free(dd->dd_dmat, dd->dd_desc, dd->dd_dmamap);
2069fail1:
2070	bus_dmamap_destroy(dd->dd_dmat, dd->dd_dmamap);
2071fail0:
2072	bus_dma_tag_destroy(dd->dd_dmat);
2073	memset(dd, 0, sizeof(*dd));
2074	return error;
2075#undef DS2PHYS
2076}
2077
2078static void
2079mwl_desc_cleanup(struct mwl_softc *sc, struct mwl_descdma *dd)
2080{
2081	bus_dmamap_unload(dd->dd_dmat, dd->dd_dmamap);
2082	bus_dmamem_free(dd->dd_dmat, dd->dd_desc, dd->dd_dmamap);
2083	bus_dmamap_destroy(dd->dd_dmat, dd->dd_dmamap);
2084	bus_dma_tag_destroy(dd->dd_dmat);
2085
2086	memset(dd, 0, sizeof(*dd));
2087}
2088
2089/*
2090 * Construct a tx q's free list.  The order of entries on
2091 * the list must reflect the physical layout of tx descriptors
2092 * because the firmware pre-fetches descriptors.
2093 *
2094 * XXX might be better to use indices into the buffer array.
2095 */
2096static void
2097mwl_txq_reset(struct mwl_softc *sc, struct mwl_txq *txq)
2098{
2099	struct mwl_txbuf *bf;
2100	int i;
2101
2102	bf = txq->dma.dd_bufptr;
2103	STAILQ_INIT(&txq->free);
2104	for (i = 0; i < mwl_txbuf; i++, bf++)
2105		STAILQ_INSERT_TAIL(&txq->free, bf, bf_list);
2106	txq->nfree = i;
2107}
2108
2109#define	DS2PHYS(_dd, _ds) \
2110	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
2111
2112static int
2113mwl_txdma_setup(struct mwl_softc *sc, struct mwl_txq *txq)
2114{
2115	struct ifnet *ifp = sc->sc_ifp;
2116	int error, bsize, i;
2117	struct mwl_txbuf *bf;
2118	struct mwl_txdesc *ds;
2119
2120	error = mwl_desc_setup(sc, "tx", &txq->dma,
2121			mwl_txbuf, sizeof(struct mwl_txbuf),
2122			MWL_TXDESC, sizeof(struct mwl_txdesc));
2123	if (error != 0)
2124		return error;
2125
2126	/* allocate and setup tx buffers */
2127	bsize = mwl_txbuf * sizeof(struct mwl_txbuf);
2128	bf = malloc(bsize, M_MWLDEV, M_NOWAIT | M_ZERO);
2129	if (bf == NULL) {
2130		if_printf(ifp, "malloc of %u tx buffers failed\n",
2131			mwl_txbuf);
2132		return ENOMEM;
2133	}
2134	txq->dma.dd_bufptr = bf;
2135
2136	ds = txq->dma.dd_desc;
2137	for (i = 0; i < mwl_txbuf; i++, bf++, ds += MWL_TXDESC) {
2138		bf->bf_desc = ds;
2139		bf->bf_daddr = DS2PHYS(&txq->dma, ds);
2140		error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
2141				&bf->bf_dmamap);
2142		if (error != 0) {
2143			if_printf(ifp, "unable to create dmamap for tx "
2144				"buffer %u, error %u\n", i, error);
2145			return error;
2146		}
2147	}
2148	mwl_txq_reset(sc, txq);
2149	return 0;
2150}
2151
2152static void
2153mwl_txdma_cleanup(struct mwl_softc *sc, struct mwl_txq *txq)
2154{
2155	struct mwl_txbuf *bf;
2156	int i;
2157
2158	bf = txq->dma.dd_bufptr;
2159	for (i = 0; i < mwl_txbuf; i++, bf++) {
2160		KASSERT(bf->bf_m == NULL, ("mbuf on free list"));
2161		KASSERT(bf->bf_node == NULL, ("node on free list"));
2162		if (bf->bf_dmamap != NULL)
2163			bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap);
2164	}
2165	STAILQ_INIT(&txq->free);
2166	txq->nfree = 0;
2167	if (txq->dma.dd_bufptr != NULL) {
2168		free(txq->dma.dd_bufptr, M_MWLDEV);
2169		txq->dma.dd_bufptr = NULL;
2170	}
2171	if (txq->dma.dd_desc_len != 0)
2172		mwl_desc_cleanup(sc, &txq->dma);
2173}
2174
2175static int
2176mwl_rxdma_setup(struct mwl_softc *sc)
2177{
2178	struct ifnet *ifp = sc->sc_ifp;
2179	int error, jumbosize, bsize, i;
2180	struct mwl_rxbuf *bf;
2181	struct mwl_jumbo *rbuf;
2182	struct mwl_rxdesc *ds;
2183	caddr_t data;
2184
2185	error = mwl_desc_setup(sc, "rx", &sc->sc_rxdma,
2186			mwl_rxdesc, sizeof(struct mwl_rxbuf),
2187			1, sizeof(struct mwl_rxdesc));
2188	if (error != 0)
2189		return error;
2190
2191	/*
2192	 * Receive is done to a private pool of jumbo buffers.
2193	 * This allows us to attach to mbuf's and avoid re-mapping
2194	 * memory on each rx we post.  We allocate a large chunk
2195	 * of memory and manage it in the driver.  The mbuf free
2196	 * callback method is used to reclaim frames after sending
2197	 * them up the stack.  By default we allocate 2x the number of
2198	 * rx descriptors configured so we have some slop to hold
2199	 * us while frames are processed.
2200	 */
2201	if (mwl_rxbuf < 2*mwl_rxdesc) {
2202		if_printf(ifp,
2203		    "too few rx dma buffers (%d); increasing to %d\n",
2204		    mwl_rxbuf, 2*mwl_rxdesc);
2205		mwl_rxbuf = 2*mwl_rxdesc;
2206	}
2207	jumbosize = roundup(MWL_AGGR_SIZE, PAGE_SIZE);
2208	sc->sc_rxmemsize = mwl_rxbuf*jumbosize;
2209
2210	error = bus_dma_tag_create(sc->sc_dmat,	/* parent */
2211		       PAGE_SIZE, 0,		/* alignment, bounds */
2212		       BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
2213		       BUS_SPACE_MAXADDR,	/* highaddr */
2214		       NULL, NULL,		/* filter, filterarg */
2215		       sc->sc_rxmemsize,	/* maxsize */
2216		       1,			/* nsegments */
2217		       sc->sc_rxmemsize,	/* maxsegsize */
2218		       BUS_DMA_ALLOCNOW,	/* flags */
2219		       NULL,			/* lockfunc */
2220		       NULL,			/* lockarg */
2221		       &sc->sc_rxdmat);
2222	error = bus_dmamap_create(sc->sc_rxdmat, BUS_DMA_NOWAIT, &sc->sc_rxmap);
2223	if (error != 0) {
2224		if_printf(ifp, "could not create rx DMA map\n");
2225		return error;
2226	}
2227
2228	error = bus_dmamem_alloc(sc->sc_rxdmat, (void**) &sc->sc_rxmem,
2229				 BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
2230				 &sc->sc_rxmap);
2231	if (error != 0) {
2232		if_printf(ifp, "could not alloc %ju bytes of rx DMA memory\n",
2233		    (uintmax_t) sc->sc_rxmemsize);
2234		return error;
2235	}
2236
2237	error = bus_dmamap_load(sc->sc_rxdmat, sc->sc_rxmap,
2238				sc->sc_rxmem, sc->sc_rxmemsize,
2239				mwl_load_cb, &sc->sc_rxmem_paddr,
2240				BUS_DMA_NOWAIT);
2241	if (error != 0) {
2242		if_printf(ifp, "could not load rx DMA map\n");
2243		return error;
2244	}
2245
2246	/*
2247	 * Allocate rx buffers and set them up.
2248	 */
2249	bsize = mwl_rxdesc * sizeof(struct mwl_rxbuf);
2250	bf = malloc(bsize, M_MWLDEV, M_NOWAIT | M_ZERO);
2251	if (bf == NULL) {
2252		if_printf(ifp, "malloc of %u rx buffers failed\n", bsize);
2253		return error;
2254	}
2255	sc->sc_rxdma.dd_bufptr = bf;
2256
2257	STAILQ_INIT(&sc->sc_rxbuf);
2258	ds = sc->sc_rxdma.dd_desc;
2259	for (i = 0; i < mwl_rxdesc; i++, bf++, ds++) {
2260		bf->bf_desc = ds;
2261		bf->bf_daddr = DS2PHYS(&sc->sc_rxdma, ds);
2262		/* pre-assign dma buffer */
2263		bf->bf_data = ((uint8_t *)sc->sc_rxmem) + (i*jumbosize);
2264		/* NB: tail is intentional to preserve descriptor order */
2265		STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
2266	}
2267
2268	/*
2269	 * Place remainder of dma memory buffers on the free list.
2270	 */
2271	SLIST_INIT(&sc->sc_rxfree);
2272	for (; i < mwl_rxbuf; i++) {
2273		data = ((uint8_t *)sc->sc_rxmem) + (i*jumbosize);
2274		rbuf = MWL_JUMBO_DATA2BUF(data);
2275		SLIST_INSERT_HEAD(&sc->sc_rxfree, rbuf, next);
2276		sc->sc_nrxfree++;
2277	}
2278	MWL_RXFREE_INIT(sc);
2279	return 0;
2280}
2281#undef DS2PHYS
2282
2283static void
2284mwl_rxdma_cleanup(struct mwl_softc *sc)
2285{
2286	if (sc->sc_rxmap != NULL)
2287		bus_dmamap_unload(sc->sc_rxdmat, sc->sc_rxmap);
2288	if (sc->sc_rxmem != NULL) {
2289		bus_dmamem_free(sc->sc_rxdmat, sc->sc_rxmem, sc->sc_rxmap);
2290		sc->sc_rxmem = NULL;
2291	}
2292	if (sc->sc_rxmap != NULL) {
2293		bus_dmamap_destroy(sc->sc_rxdmat, sc->sc_rxmap);
2294		sc->sc_rxmap = NULL;
2295	}
2296	if (sc->sc_rxdma.dd_bufptr != NULL) {
2297		free(sc->sc_rxdma.dd_bufptr, M_MWLDEV);
2298		sc->sc_rxdma.dd_bufptr = NULL;
2299	}
2300	if (sc->sc_rxdma.dd_desc_len != 0)
2301		mwl_desc_cleanup(sc, &sc->sc_rxdma);
2302	MWL_RXFREE_DESTROY(sc);
2303}
2304
2305static int
2306mwl_dma_setup(struct mwl_softc *sc)
2307{
2308	int error, i;
2309
2310	error = mwl_rxdma_setup(sc);
2311	if (error != 0) {
2312		mwl_rxdma_cleanup(sc);
2313		return error;
2314	}
2315
2316	for (i = 0; i < MWL_NUM_TX_QUEUES; i++) {
2317		error = mwl_txdma_setup(sc, &sc->sc_txq[i]);
2318		if (error != 0) {
2319			mwl_dma_cleanup(sc);
2320			return error;
2321		}
2322	}
2323	return 0;
2324}
2325
2326static void
2327mwl_dma_cleanup(struct mwl_softc *sc)
2328{
2329	int i;
2330
2331	for (i = 0; i < MWL_NUM_TX_QUEUES; i++)
2332		mwl_txdma_cleanup(sc, &sc->sc_txq[i]);
2333	mwl_rxdma_cleanup(sc);
2334}
2335
2336static struct ieee80211_node *
2337mwl_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2338{
2339	struct ieee80211com *ic = vap->iv_ic;
2340	struct mwl_softc *sc = ic->ic_ifp->if_softc;
2341	const size_t space = sizeof(struct mwl_node);
2342	struct mwl_node *mn;
2343
2344	mn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2345	if (mn == NULL) {
2346		/* XXX stat+msg */
2347		return NULL;
2348	}
2349	DPRINTF(sc, MWL_DEBUG_NODE, "%s: mn %p\n", __func__, mn);
2350	return &mn->mn_node;
2351}
2352
2353static void
2354mwl_node_cleanup(struct ieee80211_node *ni)
2355{
2356	struct ieee80211com *ic = ni->ni_ic;
2357        struct mwl_softc *sc = ic->ic_ifp->if_softc;
2358	struct mwl_node *mn = MWL_NODE(ni);
2359
2360	DPRINTF(sc, MWL_DEBUG_NODE, "%s: ni %p ic %p staid %d\n",
2361	    __func__, ni, ni->ni_ic, mn->mn_staid);
2362
2363	if (mn->mn_staid != 0) {
2364		struct ieee80211vap *vap = ni->ni_vap;
2365
2366		if (mn->mn_hvap != NULL) {
2367			if (vap->iv_opmode == IEEE80211_M_STA)
2368				mwl_hal_delstation(mn->mn_hvap, vap->iv_myaddr);
2369			else
2370				mwl_hal_delstation(mn->mn_hvap, ni->ni_macaddr);
2371		}
2372		/*
2373		 * NB: legacy WDS peer sta db entry is installed using
2374		 * the associate ap's hvap; use it again to delete it.
2375		 * XXX can vap be NULL?
2376		 */
2377		else if (vap->iv_opmode == IEEE80211_M_WDS &&
2378		    MWL_VAP(vap)->mv_ap_hvap != NULL)
2379			mwl_hal_delstation(MWL_VAP(vap)->mv_ap_hvap,
2380			    ni->ni_macaddr);
2381		delstaid(sc, mn->mn_staid);
2382		mn->mn_staid = 0;
2383	}
2384	sc->sc_node_cleanup(ni);
2385}
2386
2387/*
2388 * Reclaim rx dma buffers from packets sitting on the ampdu
2389 * reorder queue for a station.  We replace buffers with a
2390 * system cluster (if available).
2391 */
2392static void
2393mwl_ampdu_rxdma_reclaim(struct ieee80211_rx_ampdu *rap)
2394{
2395#if 0
2396	int i, n, off;
2397	struct mbuf *m;
2398	void *cl;
2399
2400	n = rap->rxa_qframes;
2401	for (i = 0; i < rap->rxa_wnd && n > 0; i++) {
2402		m = rap->rxa_m[i];
2403		if (m == NULL)
2404			continue;
2405		n--;
2406		/* our dma buffers have a well-known free routine */
2407		if ((m->m_flags & M_EXT) == 0 ||
2408		    m->m_ext.ext_free != mwl_ext_free)
2409			continue;
2410		/*
2411		 * Try to allocate a cluster and move the data.
2412		 */
2413		off = m->m_data - m->m_ext.ext_buf;
2414		if (off + m->m_pkthdr.len > MCLBYTES) {
2415			/* XXX no AMSDU for now */
2416			continue;
2417		}
2418		cl = pool_cache_get_paddr(&mclpool_cache, 0,
2419		    &m->m_ext.ext_paddr);
2420		if (cl != NULL) {
2421			/*
2422			 * Copy the existing data to the cluster, remove
2423			 * the rx dma buffer, and attach the cluster in
2424			 * its place.  Note we preserve the offset to the
2425			 * data so frames being bridged can still prepend
2426			 * their headers without adding another mbuf.
2427			 */
2428			memcpy((caddr_t) cl + off, m->m_data, m->m_pkthdr.len);
2429			MEXTREMOVE(m);
2430			MEXTADD(m, cl, MCLBYTES, 0, NULL, &mclpool_cache);
2431			/* setup mbuf like _MCLGET does */
2432			m->m_flags |= M_CLUSTER | M_EXT_RW;
2433			_MOWNERREF(m, M_EXT | M_CLUSTER);
2434			/* NB: m_data is clobbered by MEXTADDR, adjust */
2435			m->m_data += off;
2436		}
2437	}
2438#endif
2439}
2440
2441/*
2442 * Callback to reclaim resources.  We first let the
2443 * net80211 layer do it's thing, then if we are still
2444 * blocked by a lack of rx dma buffers we walk the ampdu
2445 * reorder q's to reclaim buffers by copying to a system
2446 * cluster.
2447 */
2448static void
2449mwl_node_drain(struct ieee80211_node *ni)
2450{
2451	struct ieee80211com *ic = ni->ni_ic;
2452        struct mwl_softc *sc = ic->ic_ifp->if_softc;
2453	struct mwl_node *mn = MWL_NODE(ni);
2454
2455	DPRINTF(sc, MWL_DEBUG_NODE, "%s: ni %p vap %p staid %d\n",
2456	    __func__, ni, ni->ni_vap, mn->mn_staid);
2457
2458	/* NB: call up first to age out ampdu q's */
2459	sc->sc_node_drain(ni);
2460
2461	/* XXX better to not check low water mark? */
2462	if (sc->sc_rxblocked && mn->mn_staid != 0 &&
2463	    (ni->ni_flags & IEEE80211_NODE_HT)) {
2464		uint8_t tid;
2465		/*
2466		 * Walk the reorder q and reclaim rx dma buffers by copying
2467		 * the packet contents into clusters.
2468		 */
2469		for (tid = 0; tid < WME_NUM_TID; tid++) {
2470			struct ieee80211_rx_ampdu *rap;
2471
2472			rap = &ni->ni_rx_ampdu[tid];
2473			if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0)
2474				continue;
2475			if (rap->rxa_qframes)
2476				mwl_ampdu_rxdma_reclaim(rap);
2477		}
2478	}
2479}
2480
2481static void
2482mwl_node_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise)
2483{
2484	*rssi = ni->ni_ic->ic_node_getrssi(ni);
2485#ifdef MWL_ANT_INFO_SUPPORT
2486#if 0
2487	/* XXX need to smooth data */
2488	*noise = -MWL_NODE_CONST(ni)->mn_ai.nf;
2489#else
2490	*noise = -95;		/* XXX */
2491#endif
2492#else
2493	*noise = -95;		/* XXX */
2494#endif
2495}
2496
2497/*
2498 * Convert Hardware per-antenna rssi info to common format:
2499 * Let a1, a2, a3 represent the amplitudes per chain
2500 * Let amax represent max[a1, a2, a3]
2501 * Rssi1_dBm = RSSI_dBm + 20*log10(a1/amax)
2502 * Rssi1_dBm = RSSI_dBm + 20*log10(a1) - 20*log10(amax)
2503 * We store a table that is 4*20*log10(idx) - the extra 4 is to store or
2504 * maintain some extra precision.
2505 *
2506 * Values are stored in .5 db format capped at 127.
2507 */
2508static void
2509mwl_node_getmimoinfo(const struct ieee80211_node *ni,
2510	struct ieee80211_mimo_info *mi)
2511{
2512#define	CVT(_dst, _src) do {						\
2513	(_dst) = rssi + ((logdbtbl[_src] - logdbtbl[rssi_max]) >> 2);	\
2514	(_dst) = (_dst) > 64 ? 127 : ((_dst) << 1);			\
2515} while (0)
2516	static const int8_t logdbtbl[32] = {
2517	       0,   0,  24,  38,  48,  56,  62,  68,
2518	      72,  76,  80,  83,  86,  89,  92,  94,
2519	      96,  98, 100, 102, 104, 106, 107, 109,
2520	     110, 112, 113, 115, 116, 117, 118, 119
2521	};
2522	const struct mwl_node *mn = MWL_NODE_CONST(ni);
2523	uint8_t rssi = mn->mn_ai.rsvd1/2;		/* XXX */
2524	uint32_t rssi_max;
2525
2526	rssi_max = mn->mn_ai.rssi_a;
2527	if (mn->mn_ai.rssi_b > rssi_max)
2528		rssi_max = mn->mn_ai.rssi_b;
2529	if (mn->mn_ai.rssi_c > rssi_max)
2530		rssi_max = mn->mn_ai.rssi_c;
2531
2532	CVT(mi->rssi[0], mn->mn_ai.rssi_a);
2533	CVT(mi->rssi[1], mn->mn_ai.rssi_b);
2534	CVT(mi->rssi[2], mn->mn_ai.rssi_c);
2535
2536	mi->noise[0] = mn->mn_ai.nf_a;
2537	mi->noise[1] = mn->mn_ai.nf_b;
2538	mi->noise[2] = mn->mn_ai.nf_c;
2539#undef CVT
2540}
2541
2542static __inline void *
2543mwl_getrxdma(struct mwl_softc *sc)
2544{
2545	struct mwl_jumbo *buf;
2546	void *data;
2547
2548	/*
2549	 * Allocate from jumbo pool.
2550	 */
2551	MWL_RXFREE_LOCK(sc);
2552	buf = SLIST_FIRST(&sc->sc_rxfree);
2553	if (buf == NULL) {
2554		DPRINTF(sc, MWL_DEBUG_ANY,
2555		    "%s: out of rx dma buffers\n", __func__);
2556		sc->sc_stats.mst_rx_nodmabuf++;
2557		data = NULL;
2558	} else {
2559		SLIST_REMOVE_HEAD(&sc->sc_rxfree, next);
2560		sc->sc_nrxfree--;
2561		data = MWL_JUMBO_BUF2DATA(buf);
2562	}
2563	MWL_RXFREE_UNLOCK(sc);
2564	return data;
2565}
2566
2567static __inline void
2568mwl_putrxdma(struct mwl_softc *sc, void *data)
2569{
2570	struct mwl_jumbo *buf;
2571
2572	/* XXX bounds check data */
2573	MWL_RXFREE_LOCK(sc);
2574	buf = MWL_JUMBO_DATA2BUF(data);
2575	SLIST_INSERT_HEAD(&sc->sc_rxfree, buf, next);
2576	sc->sc_nrxfree++;
2577	MWL_RXFREE_UNLOCK(sc);
2578}
2579
2580static int
2581mwl_rxbuf_init(struct mwl_softc *sc, struct mwl_rxbuf *bf)
2582{
2583	struct mwl_rxdesc *ds;
2584
2585	ds = bf->bf_desc;
2586	if (bf->bf_data == NULL) {
2587		bf->bf_data = mwl_getrxdma(sc);
2588		if (bf->bf_data == NULL) {
2589			/* mark descriptor to be skipped */
2590			ds->RxControl = EAGLE_RXD_CTRL_OS_OWN;
2591			/* NB: don't need PREREAD */
2592			MWL_RXDESC_SYNC(sc, ds, BUS_DMASYNC_PREWRITE);
2593			sc->sc_stats.mst_rxbuf_failed++;
2594			return ENOMEM;
2595		}
2596	}
2597	/*
2598	 * NB: DMA buffer contents is known to be unmodified
2599	 *     so there's no need to flush the data cache.
2600	 */
2601
2602	/*
2603	 * Setup descriptor.
2604	 */
2605	ds->QosCtrl = 0;
2606	ds->RSSI = 0;
2607	ds->Status = EAGLE_RXD_STATUS_IDLE;
2608	ds->Channel = 0;
2609	ds->PktLen = htole16(MWL_AGGR_SIZE);
2610	ds->SQ2 = 0;
2611	ds->pPhysBuffData = htole32(MWL_JUMBO_DMA_ADDR(sc, bf->bf_data));
2612	/* NB: don't touch pPhysNext, set once */
2613	ds->RxControl = EAGLE_RXD_CTRL_DRIVER_OWN;
2614	MWL_RXDESC_SYNC(sc, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2615
2616	return 0;
2617}
2618
2619static void
2620mwl_ext_free(void *data, void *arg)
2621{
2622	struct mwl_softc *sc = arg;
2623
2624	/* XXX bounds check data */
2625	mwl_putrxdma(sc, data);
2626	/*
2627	 * If we were previously blocked by a lack of rx dma buffers
2628	 * check if we now have enough to restart rx interrupt handling.
2629	 * NB: we know we are called at splvm which is above splnet.
2630	 */
2631	if (sc->sc_rxblocked && sc->sc_nrxfree > mwl_rxdmalow) {
2632		sc->sc_rxblocked = 0;
2633		mwl_hal_intrset(sc->sc_mh, sc->sc_imask);
2634	}
2635}
2636
2637struct mwl_frame_bar {
2638	u_int8_t	i_fc[2];
2639	u_int8_t	i_dur[2];
2640	u_int8_t	i_ra[IEEE80211_ADDR_LEN];
2641	u_int8_t	i_ta[IEEE80211_ADDR_LEN];
2642	/* ctl, seq, FCS */
2643} __packed;
2644
2645/*
2646 * Like ieee80211_anyhdrsize, but handles BAR frames
2647 * specially so the logic below to piece the 802.11
2648 * header together works.
2649 */
2650static __inline int
2651mwl_anyhdrsize(const void *data)
2652{
2653	const struct ieee80211_frame *wh = data;
2654
2655	if ((wh->i_fc[0]&IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) {
2656		switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
2657		case IEEE80211_FC0_SUBTYPE_CTS:
2658		case IEEE80211_FC0_SUBTYPE_ACK:
2659			return sizeof(struct ieee80211_frame_ack);
2660		case IEEE80211_FC0_SUBTYPE_BAR:
2661			return sizeof(struct mwl_frame_bar);
2662		}
2663		return sizeof(struct ieee80211_frame_min);
2664	} else
2665		return ieee80211_hdrsize(data);
2666}
2667
2668static void
2669mwl_handlemicerror(struct ieee80211com *ic, const uint8_t *data)
2670{
2671	const struct ieee80211_frame *wh;
2672	struct ieee80211_node *ni;
2673
2674	wh = (const struct ieee80211_frame *)(data + sizeof(uint16_t));
2675	ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) wh);
2676	if (ni != NULL) {
2677		ieee80211_notify_michael_failure(ni->ni_vap, wh, 0);
2678		ieee80211_free_node(ni);
2679	}
2680}
2681
2682/*
2683 * Convert hardware signal strength to rssi.  The value
2684 * provided by the device has the noise floor added in;
2685 * we need to compensate for this but we don't have that
2686 * so we use a fixed value.
2687 *
2688 * The offset of 8 is good for both 2.4 and 5GHz.  The LNA
2689 * offset is already set as part of the initial gain.  This
2690 * will give at least +/- 3dB for 2.4GHz and +/- 5dB for 5GHz.
2691 */
2692static __inline int
2693cvtrssi(uint8_t ssi)
2694{
2695	int rssi = (int) ssi + 8;
2696	/* XXX hack guess until we have a real noise floor */
2697	rssi = 2*(87 - rssi);	/* NB: .5 dBm units */
2698	return (rssi < 0 ? 0 : rssi > 127 ? 127 : rssi);
2699}
2700
2701static void
2702mwl_rx_proc(void *arg, int npending)
2703{
2704#define	IEEE80211_DIR_DSTODS(wh) \
2705	((((const struct ieee80211_frame *)wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
2706	struct mwl_softc *sc = arg;
2707	struct ifnet *ifp = sc->sc_ifp;
2708	struct ieee80211com *ic = ifp->if_l2com;
2709	struct mwl_rxbuf *bf;
2710	struct mwl_rxdesc *ds;
2711	struct mbuf *m;
2712	struct ieee80211_qosframe *wh;
2713	struct ieee80211_qosframe_addr4 *wh4;
2714	struct ieee80211_node *ni;
2715	struct mwl_node *mn;
2716	int off, len, hdrlen, pktlen, rssi, ntodo;
2717	uint8_t *data, status;
2718	void *newdata;
2719	int16_t nf;
2720
2721	DPRINTF(sc, MWL_DEBUG_RX_PROC, "%s: pending %u rdptr 0x%x wrptr 0x%x\n",
2722	    __func__, npending, RD4(sc, sc->sc_hwspecs.rxDescRead),
2723	    RD4(sc, sc->sc_hwspecs.rxDescWrite));
2724	nf = -96;			/* XXX */
2725	bf = sc->sc_rxnext;
2726	for (ntodo = mwl_rxquota; ntodo > 0; ntodo--) {
2727		if (bf == NULL)
2728			bf = STAILQ_FIRST(&sc->sc_rxbuf);
2729		ds = bf->bf_desc;
2730		data = bf->bf_data;
2731		if (data == NULL) {
2732			/*
2733			 * If data allocation failed previously there
2734			 * will be no buffer; try again to re-populate it.
2735			 * Note the firmware will not advance to the next
2736			 * descriptor with a dma buffer so we must mimic
2737			 * this or we'll get out of sync.
2738			 */
2739			DPRINTF(sc, MWL_DEBUG_ANY,
2740			    "%s: rx buf w/o dma memory\n", __func__);
2741			(void) mwl_rxbuf_init(sc, bf);
2742			sc->sc_stats.mst_rx_dmabufmissing++;
2743			break;
2744		}
2745		MWL_RXDESC_SYNC(sc, ds,
2746		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2747		if (ds->RxControl != EAGLE_RXD_CTRL_DMA_OWN)
2748			break;
2749#ifdef MWL_DEBUG
2750		if (sc->sc_debug & MWL_DEBUG_RECV_DESC)
2751			mwl_printrxbuf(bf, 0);
2752#endif
2753		status = ds->Status;
2754		if (status & EAGLE_RXD_STATUS_DECRYPT_ERR_MASK) {
2755			ifp->if_ierrors++;
2756			sc->sc_stats.mst_rx_crypto++;
2757			/*
2758			 * NB: Check EAGLE_RXD_STATUS_GENERAL_DECRYPT_ERR
2759			 *     for backwards compatibility.
2760			 */
2761			if (status != EAGLE_RXD_STATUS_GENERAL_DECRYPT_ERR &&
2762			    (status & EAGLE_RXD_STATUS_TKIP_MIC_DECRYPT_ERR)) {
2763				/*
2764				 * MIC error, notify upper layers.
2765				 */
2766				bus_dmamap_sync(sc->sc_rxdmat, sc->sc_rxmap,
2767				    BUS_DMASYNC_POSTREAD);
2768				mwl_handlemicerror(ic, data);
2769				sc->sc_stats.mst_rx_tkipmic++;
2770			}
2771			/* XXX too painful to tap packets */
2772			goto rx_next;
2773		}
2774		/*
2775		 * Sync the data buffer.
2776		 */
2777		len = le16toh(ds->PktLen);
2778		bus_dmamap_sync(sc->sc_rxdmat, sc->sc_rxmap, BUS_DMASYNC_POSTREAD);
2779		/*
2780		 * The 802.11 header is provided all or in part at the front;
2781		 * use it to calculate the true size of the header that we'll
2782		 * construct below.  We use this to figure out where to copy
2783		 * payload prior to constructing the header.
2784		 */
2785		hdrlen = mwl_anyhdrsize(data + sizeof(uint16_t));
2786		off = sizeof(uint16_t) + sizeof(struct ieee80211_frame_addr4);
2787
2788		/* calculate rssi early so we can re-use for each aggregate */
2789		rssi = cvtrssi(ds->RSSI);
2790
2791		pktlen = hdrlen + (len - off);
2792		/*
2793		 * NB: we know our frame is at least as large as
2794		 * IEEE80211_MIN_LEN because there is a 4-address
2795		 * frame at the front.  Hence there's no need to
2796		 * vet the packet length.  If the frame in fact
2797		 * is too small it should be discarded at the
2798		 * net80211 layer.
2799		 */
2800
2801		/*
2802		 * Attach dma buffer to an mbuf.  We tried
2803		 * doing this based on the packet size (i.e.
2804		 * copying small packets) but it turns out to
2805		 * be a net loss.  The tradeoff might be system
2806		 * dependent (cache architecture is important).
2807		 */
2808		MGETHDR(m, M_NOWAIT, MT_DATA);
2809		if (m == NULL) {
2810			DPRINTF(sc, MWL_DEBUG_ANY,
2811			    "%s: no rx mbuf\n", __func__);
2812			sc->sc_stats.mst_rx_nombuf++;
2813			goto rx_next;
2814		}
2815		/*
2816		 * Acquire the replacement dma buffer before
2817		 * processing the frame.  If we're out of dma
2818		 * buffers we disable rx interrupts and wait
2819		 * for the free pool to reach mlw_rxdmalow buffers
2820		 * before starting to do work again.  If the firmware
2821		 * runs out of descriptors then it will toss frames
2822		 * which is better than our doing it as that can
2823		 * starve our processing.  It is also important that
2824		 * we always process rx'd frames in case they are
2825		 * A-MPDU as otherwise the host's view of the BA
2826		 * window may get out of sync with the firmware.
2827		 */
2828		newdata = mwl_getrxdma(sc);
2829		if (newdata == NULL) {
2830			/* NB: stat+msg in mwl_getrxdma */
2831			m_free(m);
2832			/* disable RX interrupt and mark state */
2833			mwl_hal_intrset(sc->sc_mh,
2834			    sc->sc_imask &~ MACREG_A2HRIC_BIT_RX_RDY);
2835			sc->sc_rxblocked = 1;
2836			ieee80211_drain(ic);
2837			/* XXX check rxblocked and immediately start again? */
2838			goto rx_stop;
2839		}
2840		bf->bf_data = newdata;
2841		/*
2842		 * Attach the dma buffer to the mbuf;
2843		 * mwl_rxbuf_init will re-setup the rx
2844		 * descriptor using the replacement dma
2845		 * buffer we just installed above.
2846		 */
2847		MEXTADD(m, data, MWL_AGGR_SIZE, mwl_ext_free,
2848		    data, sc, 0, EXT_NET_DRV);
2849		m->m_data += off - hdrlen;
2850		m->m_pkthdr.len = m->m_len = pktlen;
2851		m->m_pkthdr.rcvif = ifp;
2852		/* NB: dma buffer assumed read-only */
2853
2854		/*
2855		 * Piece 802.11 header together.
2856		 */
2857		wh = mtod(m, struct ieee80211_qosframe *);
2858		/* NB: don't need to do this sometimes but ... */
2859		/* XXX special case so we can memcpy after m_devget? */
2860		ovbcopy(data + sizeof(uint16_t), wh, hdrlen);
2861		if (IEEE80211_QOS_HAS_SEQ(wh)) {
2862			if (IEEE80211_DIR_DSTODS(wh)) {
2863				wh4 = mtod(m,
2864				    struct ieee80211_qosframe_addr4*);
2865				*(uint16_t *)wh4->i_qos = ds->QosCtrl;
2866			} else {
2867				*(uint16_t *)wh->i_qos = ds->QosCtrl;
2868			}
2869		}
2870		/*
2871		 * The f/w strips WEP header but doesn't clear
2872		 * the WEP bit; mark the packet with M_WEP so
2873		 * net80211 will treat the data as decrypted.
2874		 * While here also clear the PWR_MGT bit since
2875		 * power save is handled by the firmware and
2876		 * passing this up will potentially cause the
2877		 * upper layer to put a station in power save
2878		 * (except when configured with MWL_HOST_PS_SUPPORT).
2879		 */
2880		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
2881			m->m_flags |= M_WEP;
2882#ifdef MWL_HOST_PS_SUPPORT
2883		wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
2884#else
2885		wh->i_fc[1] &= ~(IEEE80211_FC1_WEP | IEEE80211_FC1_PWR_MGT);
2886#endif
2887
2888		if (ieee80211_radiotap_active(ic)) {
2889			struct mwl_rx_radiotap_header *tap = &sc->sc_rx_th;
2890
2891			tap->wr_flags = 0;
2892			tap->wr_rate = ds->Rate;
2893			tap->wr_antsignal = rssi + nf;
2894			tap->wr_antnoise = nf;
2895		}
2896		if (IFF_DUMPPKTS_RECV(sc, wh)) {
2897			ieee80211_dump_pkt(ic, mtod(m, caddr_t),
2898			    len, ds->Rate, rssi);
2899		}
2900		ifp->if_ipackets++;
2901
2902		/* dispatch */
2903		ni = ieee80211_find_rxnode(ic,
2904		    (const struct ieee80211_frame_min *) wh);
2905		if (ni != NULL) {
2906			mn = MWL_NODE(ni);
2907#ifdef MWL_ANT_INFO_SUPPORT
2908			mn->mn_ai.rssi_a = ds->ai.rssi_a;
2909			mn->mn_ai.rssi_b = ds->ai.rssi_b;
2910			mn->mn_ai.rssi_c = ds->ai.rssi_c;
2911			mn->mn_ai.rsvd1 = rssi;
2912#endif
2913			/* tag AMPDU aggregates for reorder processing */
2914			if (ni->ni_flags & IEEE80211_NODE_HT)
2915				m->m_flags |= M_AMPDU;
2916			(void) ieee80211_input(ni, m, rssi, nf);
2917			ieee80211_free_node(ni);
2918		} else
2919			(void) ieee80211_input_all(ic, m, rssi, nf);
2920rx_next:
2921		/* NB: ignore ENOMEM so we process more descriptors */
2922		(void) mwl_rxbuf_init(sc, bf);
2923		bf = STAILQ_NEXT(bf, bf_list);
2924	}
2925rx_stop:
2926	sc->sc_rxnext = bf;
2927
2928	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
2929	    !IFQ_IS_EMPTY(&ifp->if_snd)) {
2930		/* NB: kick fw; the tx thread may have been preempted */
2931		mwl_hal_txstart(sc->sc_mh, 0);
2932		mwl_start(ifp);
2933	}
2934#undef IEEE80211_DIR_DSTODS
2935}
2936
2937static void
2938mwl_txq_init(struct mwl_softc *sc, struct mwl_txq *txq, int qnum)
2939{
2940	struct mwl_txbuf *bf, *bn;
2941	struct mwl_txdesc *ds;
2942
2943	MWL_TXQ_LOCK_INIT(sc, txq);
2944	txq->qnum = qnum;
2945	txq->txpri = 0;	/* XXX */
2946#if 0
2947	/* NB: q setup by mwl_txdma_setup XXX */
2948	STAILQ_INIT(&txq->free);
2949#endif
2950	STAILQ_FOREACH(bf, &txq->free, bf_list) {
2951		bf->bf_txq = txq;
2952
2953		ds = bf->bf_desc;
2954		bn = STAILQ_NEXT(bf, bf_list);
2955		if (bn == NULL)
2956			bn = STAILQ_FIRST(&txq->free);
2957		ds->pPhysNext = htole32(bn->bf_daddr);
2958	}
2959	STAILQ_INIT(&txq->active);
2960}
2961
2962/*
2963 * Setup a hardware data transmit queue for the specified
2964 * access control.  We record the mapping from ac's
2965 * to h/w queues for use by mwl_tx_start.
2966 */
2967static int
2968mwl_tx_setup(struct mwl_softc *sc, int ac, int mvtype)
2969{
2970#define	N(a)	(sizeof(a)/sizeof(a[0]))
2971	struct mwl_txq *txq;
2972
2973	if (ac >= N(sc->sc_ac2q)) {
2974		device_printf(sc->sc_dev, "AC %u out of range, max %zu!\n",
2975			ac, N(sc->sc_ac2q));
2976		return 0;
2977	}
2978	if (mvtype >= MWL_NUM_TX_QUEUES) {
2979		device_printf(sc->sc_dev, "mvtype %u out of range, max %u!\n",
2980			mvtype, MWL_NUM_TX_QUEUES);
2981		return 0;
2982	}
2983	txq = &sc->sc_txq[mvtype];
2984	mwl_txq_init(sc, txq, mvtype);
2985	sc->sc_ac2q[ac] = txq;
2986	return 1;
2987#undef N
2988}
2989
2990/*
2991 * Update WME parameters for a transmit queue.
2992 */
2993static int
2994mwl_txq_update(struct mwl_softc *sc, int ac)
2995{
2996#define	MWL_EXPONENT_TO_VALUE(v)	((1<<v)-1)
2997	struct ifnet *ifp = sc->sc_ifp;
2998	struct ieee80211com *ic = ifp->if_l2com;
2999	struct mwl_txq *txq = sc->sc_ac2q[ac];
3000	struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
3001	struct mwl_hal *mh = sc->sc_mh;
3002	int aifs, cwmin, cwmax, txoplim;
3003
3004	aifs = wmep->wmep_aifsn;
3005	/* XXX in sta mode need to pass log values for cwmin/max */
3006	cwmin = MWL_EXPONENT_TO_VALUE(wmep->wmep_logcwmin);
3007	cwmax = MWL_EXPONENT_TO_VALUE(wmep->wmep_logcwmax);
3008	txoplim = wmep->wmep_txopLimit;		/* NB: units of 32us */
3009
3010	if (mwl_hal_setedcaparams(mh, txq->qnum, cwmin, cwmax, aifs, txoplim)) {
3011		device_printf(sc->sc_dev, "unable to update hardware queue "
3012			"parameters for %s traffic!\n",
3013			ieee80211_wme_acnames[ac]);
3014		return 0;
3015	}
3016	return 1;
3017#undef MWL_EXPONENT_TO_VALUE
3018}
3019
3020/*
3021 * Callback from the 802.11 layer to update WME parameters.
3022 */
3023static int
3024mwl_wme_update(struct ieee80211com *ic)
3025{
3026	struct mwl_softc *sc = ic->ic_ifp->if_softc;
3027
3028	return !mwl_txq_update(sc, WME_AC_BE) ||
3029	    !mwl_txq_update(sc, WME_AC_BK) ||
3030	    !mwl_txq_update(sc, WME_AC_VI) ||
3031	    !mwl_txq_update(sc, WME_AC_VO) ? EIO : 0;
3032}
3033
3034/*
3035 * Reclaim resources for a setup queue.
3036 */
3037static void
3038mwl_tx_cleanupq(struct mwl_softc *sc, struct mwl_txq *txq)
3039{
3040	/* XXX hal work? */
3041	MWL_TXQ_LOCK_DESTROY(txq);
3042}
3043
3044/*
3045 * Reclaim all tx queue resources.
3046 */
3047static void
3048mwl_tx_cleanup(struct mwl_softc *sc)
3049{
3050	int i;
3051
3052	for (i = 0; i < MWL_NUM_TX_QUEUES; i++)
3053		mwl_tx_cleanupq(sc, &sc->sc_txq[i]);
3054}
3055
3056static int
3057mwl_tx_dmasetup(struct mwl_softc *sc, struct mwl_txbuf *bf, struct mbuf *m0)
3058{
3059	struct mbuf *m;
3060	int error;
3061
3062	/*
3063	 * Load the DMA map so any coalescing is done.  This
3064	 * also calculates the number of descriptors we need.
3065	 */
3066	error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
3067				     bf->bf_segs, &bf->bf_nseg,
3068				     BUS_DMA_NOWAIT);
3069	if (error == EFBIG) {
3070		/* XXX packet requires too many descriptors */
3071		bf->bf_nseg = MWL_TXDESC+1;
3072	} else if (error != 0) {
3073		sc->sc_stats.mst_tx_busdma++;
3074		m_freem(m0);
3075		return error;
3076	}
3077	/*
3078	 * Discard null packets and check for packets that
3079	 * require too many TX descriptors.  We try to convert
3080	 * the latter to a cluster.
3081	 */
3082	if (error == EFBIG) {		/* too many desc's, linearize */
3083		sc->sc_stats.mst_tx_linear++;
3084#if MWL_TXDESC > 1
3085		m = m_collapse(m0, M_NOWAIT, MWL_TXDESC);
3086#else
3087		m = m_defrag(m0, M_NOWAIT);
3088#endif
3089		if (m == NULL) {
3090			m_freem(m0);
3091			sc->sc_stats.mst_tx_nombuf++;
3092			return ENOMEM;
3093		}
3094		m0 = m;
3095		error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
3096					     bf->bf_segs, &bf->bf_nseg,
3097					     BUS_DMA_NOWAIT);
3098		if (error != 0) {
3099			sc->sc_stats.mst_tx_busdma++;
3100			m_freem(m0);
3101			return error;
3102		}
3103		KASSERT(bf->bf_nseg <= MWL_TXDESC,
3104		    ("too many segments after defrag; nseg %u", bf->bf_nseg));
3105	} else if (bf->bf_nseg == 0) {		/* null packet, discard */
3106		sc->sc_stats.mst_tx_nodata++;
3107		m_freem(m0);
3108		return EIO;
3109	}
3110	DPRINTF(sc, MWL_DEBUG_XMIT, "%s: m %p len %u\n",
3111		__func__, m0, m0->m_pkthdr.len);
3112	bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
3113	bf->bf_m = m0;
3114
3115	return 0;
3116}
3117
3118static __inline int
3119mwl_cvtlegacyrate(int rate)
3120{
3121	switch (rate) {
3122	case 2:	 return 0;
3123	case 4:	 return 1;
3124	case 11: return 2;
3125	case 22: return 3;
3126	case 44: return 4;
3127	case 12: return 5;
3128	case 18: return 6;
3129	case 24: return 7;
3130	case 36: return 8;
3131	case 48: return 9;
3132	case 72: return 10;
3133	case 96: return 11;
3134	case 108:return 12;
3135	}
3136	return 0;
3137}
3138
3139/*
3140 * Calculate fixed tx rate information per client state;
3141 * this value is suitable for writing to the Format field
3142 * of a tx descriptor.
3143 */
3144static uint16_t
3145mwl_calcformat(uint8_t rate, const struct ieee80211_node *ni)
3146{
3147	uint16_t fmt;
3148
3149	fmt = SM(3, EAGLE_TXD_ANTENNA)
3150	    | (IEEE80211_IS_CHAN_HT40D(ni->ni_chan) ?
3151		EAGLE_TXD_EXTCHAN_LO : EAGLE_TXD_EXTCHAN_HI);
3152	if (rate & IEEE80211_RATE_MCS) {	/* HT MCS */
3153		fmt |= EAGLE_TXD_FORMAT_HT
3154		    /* NB: 0x80 implicitly stripped from ucastrate */
3155		    | SM(rate, EAGLE_TXD_RATE);
3156		/* XXX short/long GI may be wrong; re-check */
3157		if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
3158			fmt |= EAGLE_TXD_CHW_40
3159			    | (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40 ?
3160			        EAGLE_TXD_GI_SHORT : EAGLE_TXD_GI_LONG);
3161		} else {
3162			fmt |= EAGLE_TXD_CHW_20
3163			    | (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20 ?
3164			        EAGLE_TXD_GI_SHORT : EAGLE_TXD_GI_LONG);
3165		}
3166	} else {			/* legacy rate */
3167		fmt |= EAGLE_TXD_FORMAT_LEGACY
3168		    | SM(mwl_cvtlegacyrate(rate), EAGLE_TXD_RATE)
3169		    | EAGLE_TXD_CHW_20
3170		    /* XXX iv_flags & IEEE80211_F_SHPREAMBLE? */
3171		    | (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE ?
3172			EAGLE_TXD_PREAMBLE_SHORT : EAGLE_TXD_PREAMBLE_LONG);
3173	}
3174	return fmt;
3175}
3176
3177static int
3178mwl_tx_start(struct mwl_softc *sc, struct ieee80211_node *ni, struct mwl_txbuf *bf,
3179    struct mbuf *m0)
3180{
3181#define	IEEE80211_DIR_DSTODS(wh) \
3182	((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
3183	struct ifnet *ifp = sc->sc_ifp;
3184	struct ieee80211com *ic = ifp->if_l2com;
3185	struct ieee80211vap *vap = ni->ni_vap;
3186	int error, iswep, ismcast;
3187	int hdrlen, copyhdrlen, pktlen;
3188	struct mwl_txdesc *ds;
3189	struct mwl_txq *txq;
3190	struct ieee80211_frame *wh;
3191	struct mwltxrec *tr;
3192	struct mwl_node *mn;
3193	uint16_t qos;
3194#if MWL_TXDESC > 1
3195	int i;
3196#endif
3197
3198	wh = mtod(m0, struct ieee80211_frame *);
3199	iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
3200	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
3201	hdrlen = ieee80211_anyhdrsize(wh);
3202	copyhdrlen = hdrlen;
3203	pktlen = m0->m_pkthdr.len;
3204	if (IEEE80211_QOS_HAS_SEQ(wh)) {
3205		if (IEEE80211_DIR_DSTODS(wh)) {
3206			qos = *(uint16_t *)
3207			    (((struct ieee80211_qosframe_addr4 *) wh)->i_qos);
3208			copyhdrlen -= sizeof(qos);
3209		} else
3210			qos = *(uint16_t *)
3211			    (((struct ieee80211_qosframe *) wh)->i_qos);
3212	} else
3213		qos = 0;
3214
3215	if (iswep) {
3216		const struct ieee80211_cipher *cip;
3217		struct ieee80211_key *k;
3218
3219		/*
3220		 * Construct the 802.11 header+trailer for an encrypted
3221		 * frame. The only reason this can fail is because of an
3222		 * unknown or unsupported cipher/key type.
3223		 *
3224		 * NB: we do this even though the firmware will ignore
3225		 *     what we've done for WEP and TKIP as we need the
3226		 *     ExtIV filled in for CCMP and this also adjusts
3227		 *     the headers which simplifies our work below.
3228		 */
3229		k = ieee80211_crypto_encap(ni, m0);
3230		if (k == NULL) {
3231			/*
3232			 * This can happen when the key is yanked after the
3233			 * frame was queued.  Just discard the frame; the
3234			 * 802.11 layer counts failures and provides
3235			 * debugging/diagnostics.
3236			 */
3237			m_freem(m0);
3238			return EIO;
3239		}
3240		/*
3241		 * Adjust the packet length for the crypto additions
3242		 * done during encap and any other bits that the f/w
3243		 * will add later on.
3244		 */
3245		cip = k->wk_cipher;
3246		pktlen += cip->ic_header + cip->ic_miclen + cip->ic_trailer;
3247
3248		/* packet header may have moved, reset our local pointer */
3249		wh = mtod(m0, struct ieee80211_frame *);
3250	}
3251
3252	if (ieee80211_radiotap_active_vap(vap)) {
3253		sc->sc_tx_th.wt_flags = 0;	/* XXX */
3254		if (iswep)
3255			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
3256#if 0
3257		sc->sc_tx_th.wt_rate = ds->DataRate;
3258#endif
3259		sc->sc_tx_th.wt_txpower = ni->ni_txpower;
3260		sc->sc_tx_th.wt_antenna = sc->sc_txantenna;
3261
3262		ieee80211_radiotap_tx(vap, m0);
3263	}
3264	/*
3265	 * Copy up/down the 802.11 header; the firmware requires
3266	 * we present a 2-byte payload length followed by a
3267	 * 4-address header (w/o QoS), followed (optionally) by
3268	 * any WEP/ExtIV header (but only filled in for CCMP).
3269	 * We are assured the mbuf has sufficient headroom to
3270	 * prepend in-place by the setup of ic_headroom in
3271	 * mwl_attach.
3272	 */
3273	if (hdrlen < sizeof(struct mwltxrec)) {
3274		const int space = sizeof(struct mwltxrec) - hdrlen;
3275		if (M_LEADINGSPACE(m0) < space) {
3276			/* NB: should never happen */
3277			device_printf(sc->sc_dev,
3278			    "not enough headroom, need %d found %zd, "
3279			    "m_flags 0x%x m_len %d\n",
3280			    space, M_LEADINGSPACE(m0), m0->m_flags, m0->m_len);
3281			ieee80211_dump_pkt(ic,
3282			    mtod(m0, const uint8_t *), m0->m_len, 0, -1);
3283			m_freem(m0);
3284			sc->sc_stats.mst_tx_noheadroom++;
3285			return EIO;
3286		}
3287		M_PREPEND(m0, space, M_NOWAIT);
3288	}
3289	tr = mtod(m0, struct mwltxrec *);
3290	if (wh != (struct ieee80211_frame *) &tr->wh)
3291		ovbcopy(wh, &tr->wh, hdrlen);
3292	/*
3293	 * Note: the "firmware length" is actually the length
3294	 * of the fully formed "802.11 payload".  That is, it's
3295	 * everything except for the 802.11 header.  In particular
3296	 * this includes all crypto material including the MIC!
3297	 */
3298	tr->fwlen = htole16(pktlen - hdrlen);
3299
3300	/*
3301	 * Load the DMA map so any coalescing is done.  This
3302	 * also calculates the number of descriptors we need.
3303	 */
3304	error = mwl_tx_dmasetup(sc, bf, m0);
3305	if (error != 0) {
3306		/* NB: stat collected in mwl_tx_dmasetup */
3307		DPRINTF(sc, MWL_DEBUG_XMIT,
3308		    "%s: unable to setup dma\n", __func__);
3309		return error;
3310	}
3311	bf->bf_node = ni;			/* NB: held reference */
3312	m0 = bf->bf_m;				/* NB: may have changed */
3313	tr = mtod(m0, struct mwltxrec *);
3314	wh = (struct ieee80211_frame *)&tr->wh;
3315
3316	/*
3317	 * Formulate tx descriptor.
3318	 */
3319	ds = bf->bf_desc;
3320	txq = bf->bf_txq;
3321
3322	ds->QosCtrl = qos;			/* NB: already little-endian */
3323#if MWL_TXDESC == 1
3324	/*
3325	 * NB: multiframes should be zero because the descriptors
3326	 *     are initialized to zero.  This should handle the case
3327	 *     where the driver is built with MWL_TXDESC=1 but we are
3328	 *     using firmware with multi-segment support.
3329	 */
3330	ds->PktPtr = htole32(bf->bf_segs[0].ds_addr);
3331	ds->PktLen = htole16(bf->bf_segs[0].ds_len);
3332#else
3333	ds->multiframes = htole32(bf->bf_nseg);
3334	ds->PktLen = htole16(m0->m_pkthdr.len);
3335	for (i = 0; i < bf->bf_nseg; i++) {
3336		ds->PktPtrArray[i] = htole32(bf->bf_segs[i].ds_addr);
3337		ds->PktLenArray[i] = htole16(bf->bf_segs[i].ds_len);
3338	}
3339#endif
3340	/* NB: pPhysNext, DataRate, and SapPktInfo setup once, don't touch */
3341	ds->Format = 0;
3342	ds->pad = 0;
3343	ds->ack_wcb_addr = 0;
3344
3345	mn = MWL_NODE(ni);
3346	/*
3347	 * Select transmit rate.
3348	 */
3349	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
3350	case IEEE80211_FC0_TYPE_MGT:
3351		sc->sc_stats.mst_tx_mgmt++;
3352		/* fall thru... */
3353	case IEEE80211_FC0_TYPE_CTL:
3354		/* NB: assign to BE q to avoid bursting */
3355		ds->TxPriority = MWL_WME_AC_BE;
3356		break;
3357	case IEEE80211_FC0_TYPE_DATA:
3358		if (!ismcast) {
3359			const struct ieee80211_txparam *tp = ni->ni_txparms;
3360			/*
3361			 * EAPOL frames get forced to a fixed rate and w/o
3362			 * aggregation; otherwise check for any fixed rate
3363			 * for the client (may depend on association state).
3364			 */
3365			if (m0->m_flags & M_EAPOL) {
3366				const struct mwl_vap *mvp = MWL_VAP_CONST(vap);
3367				ds->Format = mvp->mv_eapolformat;
3368				ds->pad = htole16(
3369				    EAGLE_TXD_FIXED_RATE | EAGLE_TXD_DONT_AGGR);
3370			} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
3371				/* XXX pre-calculate per node */
3372				ds->Format = htole16(
3373				    mwl_calcformat(tp->ucastrate, ni));
3374				ds->pad = htole16(EAGLE_TXD_FIXED_RATE);
3375			}
3376			/* NB: EAPOL frames will never have qos set */
3377			if (qos == 0)
3378				ds->TxPriority = txq->qnum;
3379#if MWL_MAXBA > 3
3380			else if (mwl_bastream_match(&mn->mn_ba[3], qos))
3381				ds->TxPriority = mn->mn_ba[3].txq;
3382#endif
3383#if MWL_MAXBA > 2
3384			else if (mwl_bastream_match(&mn->mn_ba[2], qos))
3385				ds->TxPriority = mn->mn_ba[2].txq;
3386#endif
3387#if MWL_MAXBA > 1
3388			else if (mwl_bastream_match(&mn->mn_ba[1], qos))
3389				ds->TxPriority = mn->mn_ba[1].txq;
3390#endif
3391#if MWL_MAXBA > 0
3392			else if (mwl_bastream_match(&mn->mn_ba[0], qos))
3393				ds->TxPriority = mn->mn_ba[0].txq;
3394#endif
3395			else
3396				ds->TxPriority = txq->qnum;
3397		} else
3398			ds->TxPriority = txq->qnum;
3399		break;
3400	default:
3401		if_printf(ifp, "bogus frame type 0x%x (%s)\n",
3402			wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
3403		sc->sc_stats.mst_tx_badframetype++;
3404		m_freem(m0);
3405		return EIO;
3406	}
3407
3408	if (IFF_DUMPPKTS_XMIT(sc))
3409		ieee80211_dump_pkt(ic,
3410		    mtod(m0, const uint8_t *)+sizeof(uint16_t),
3411		    m0->m_len - sizeof(uint16_t), ds->DataRate, -1);
3412
3413	MWL_TXQ_LOCK(txq);
3414	ds->Status = htole32(EAGLE_TXD_STATUS_FW_OWNED);
3415	STAILQ_INSERT_TAIL(&txq->active, bf, bf_list);
3416	MWL_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3417
3418	ifp->if_opackets++;
3419	sc->sc_tx_timer = 5;
3420	MWL_TXQ_UNLOCK(txq);
3421
3422	return 0;
3423#undef	IEEE80211_DIR_DSTODS
3424}
3425
3426static __inline int
3427mwl_cvtlegacyrix(int rix)
3428{
3429#define	N(x)	(sizeof(x)/sizeof(x[0]))
3430	static const int ieeerates[] =
3431	    { 2, 4, 11, 22, 44, 12, 18, 24, 36, 48, 72, 96, 108 };
3432	return (rix < N(ieeerates) ? ieeerates[rix] : 0);
3433#undef N
3434}
3435
3436/*
3437 * Process completed xmit descriptors from the specified queue.
3438 */
3439static int
3440mwl_tx_processq(struct mwl_softc *sc, struct mwl_txq *txq)
3441{
3442#define	EAGLE_TXD_STATUS_MCAST \
3443	(EAGLE_TXD_STATUS_MULTICAST_TX | EAGLE_TXD_STATUS_BROADCAST_TX)
3444	struct ifnet *ifp = sc->sc_ifp;
3445	struct ieee80211com *ic = ifp->if_l2com;
3446	struct mwl_txbuf *bf;
3447	struct mwl_txdesc *ds;
3448	struct ieee80211_node *ni;
3449	struct mwl_node *an;
3450	int nreaped;
3451	uint32_t status;
3452
3453	DPRINTF(sc, MWL_DEBUG_TX_PROC, "%s: tx queue %u\n", __func__, txq->qnum);
3454	for (nreaped = 0;; nreaped++) {
3455		MWL_TXQ_LOCK(txq);
3456		bf = STAILQ_FIRST(&txq->active);
3457		if (bf == NULL) {
3458			MWL_TXQ_UNLOCK(txq);
3459			break;
3460		}
3461		ds = bf->bf_desc;
3462		MWL_TXDESC_SYNC(txq, ds,
3463		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
3464		if (ds->Status & htole32(EAGLE_TXD_STATUS_FW_OWNED)) {
3465			MWL_TXQ_UNLOCK(txq);
3466			break;
3467		}
3468		STAILQ_REMOVE_HEAD(&txq->active, bf_list);
3469		MWL_TXQ_UNLOCK(txq);
3470
3471#ifdef MWL_DEBUG
3472		if (sc->sc_debug & MWL_DEBUG_XMIT_DESC)
3473			mwl_printtxbuf(bf, txq->qnum, nreaped);
3474#endif
3475		ni = bf->bf_node;
3476		if (ni != NULL) {
3477			an = MWL_NODE(ni);
3478			status = le32toh(ds->Status);
3479			if (status & EAGLE_TXD_STATUS_OK) {
3480				uint16_t Format = le16toh(ds->Format);
3481				uint8_t txant = MS(Format, EAGLE_TXD_ANTENNA);
3482
3483				sc->sc_stats.mst_ant_tx[txant]++;
3484				if (status & EAGLE_TXD_STATUS_OK_RETRY)
3485					sc->sc_stats.mst_tx_retries++;
3486				if (status & EAGLE_TXD_STATUS_OK_MORE_RETRY)
3487					sc->sc_stats.mst_tx_mretries++;
3488				if (txq->qnum >= MWL_WME_AC_VO)
3489					ic->ic_wme.wme_hipri_traffic++;
3490				ni->ni_txrate = MS(Format, EAGLE_TXD_RATE);
3491				if ((Format & EAGLE_TXD_FORMAT_HT) == 0) {
3492					ni->ni_txrate = mwl_cvtlegacyrix(
3493					    ni->ni_txrate);
3494				} else
3495					ni->ni_txrate |= IEEE80211_RATE_MCS;
3496				sc->sc_stats.mst_tx_rate = ni->ni_txrate;
3497			} else {
3498				if (status & EAGLE_TXD_STATUS_FAILED_LINK_ERROR)
3499					sc->sc_stats.mst_tx_linkerror++;
3500				if (status & EAGLE_TXD_STATUS_FAILED_XRETRY)
3501					sc->sc_stats.mst_tx_xretries++;
3502				if (status & EAGLE_TXD_STATUS_FAILED_AGING)
3503					sc->sc_stats.mst_tx_aging++;
3504				if (bf->bf_m->m_flags & M_FF)
3505					sc->sc_stats.mst_ff_txerr++;
3506			}
3507			/*
3508			 * Do any tx complete callback.  Note this must
3509			 * be done before releasing the node reference.
3510			 * XXX no way to figure out if frame was ACK'd
3511			 */
3512			if (bf->bf_m->m_flags & M_TXCB) {
3513				/* XXX strip fw len in case header inspected */
3514				m_adj(bf->bf_m, sizeof(uint16_t));
3515				ieee80211_process_callback(ni, bf->bf_m,
3516					(status & EAGLE_TXD_STATUS_OK) == 0);
3517			}
3518			/*
3519			 * Reclaim reference to node.
3520			 *
3521			 * NB: the node may be reclaimed here if, for example
3522			 *     this is a DEAUTH message that was sent and the
3523			 *     node was timed out due to inactivity.
3524			 */
3525			ieee80211_free_node(ni);
3526		}
3527		ds->Status = htole32(EAGLE_TXD_STATUS_IDLE);
3528
3529		bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
3530		    BUS_DMASYNC_POSTWRITE);
3531		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
3532		m_freem(bf->bf_m);
3533
3534		mwl_puttxbuf_tail(txq, bf);
3535	}
3536	return nreaped;
3537#undef EAGLE_TXD_STATUS_MCAST
3538}
3539
3540/*
3541 * Deferred processing of transmit interrupt; special-cased
3542 * for four hardware queues, 0-3.
3543 */
3544static void
3545mwl_tx_proc(void *arg, int npending)
3546{
3547	struct mwl_softc *sc = arg;
3548	struct ifnet *ifp = sc->sc_ifp;
3549	int nreaped;
3550
3551	/*
3552	 * Process each active queue.
3553	 */
3554	nreaped = 0;
3555	if (!STAILQ_EMPTY(&sc->sc_txq[0].active))
3556		nreaped += mwl_tx_processq(sc, &sc->sc_txq[0]);
3557	if (!STAILQ_EMPTY(&sc->sc_txq[1].active))
3558		nreaped += mwl_tx_processq(sc, &sc->sc_txq[1]);
3559	if (!STAILQ_EMPTY(&sc->sc_txq[2].active))
3560		nreaped += mwl_tx_processq(sc, &sc->sc_txq[2]);
3561	if (!STAILQ_EMPTY(&sc->sc_txq[3].active))
3562		nreaped += mwl_tx_processq(sc, &sc->sc_txq[3]);
3563
3564	if (nreaped != 0) {
3565		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
3566		sc->sc_tx_timer = 0;
3567		if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
3568			/* NB: kick fw; the tx thread may have been preempted */
3569			mwl_hal_txstart(sc->sc_mh, 0);
3570			mwl_start(ifp);
3571		}
3572	}
3573}
3574
3575static void
3576mwl_tx_draintxq(struct mwl_softc *sc, struct mwl_txq *txq)
3577{
3578	struct ieee80211_node *ni;
3579	struct mwl_txbuf *bf;
3580	u_int ix;
3581
3582	/*
3583	 * NB: this assumes output has been stopped and
3584	 *     we do not need to block mwl_tx_tasklet
3585	 */
3586	for (ix = 0;; ix++) {
3587		MWL_TXQ_LOCK(txq);
3588		bf = STAILQ_FIRST(&txq->active);
3589		if (bf == NULL) {
3590			MWL_TXQ_UNLOCK(txq);
3591			break;
3592		}
3593		STAILQ_REMOVE_HEAD(&txq->active, bf_list);
3594		MWL_TXQ_UNLOCK(txq);
3595#ifdef MWL_DEBUG
3596		if (sc->sc_debug & MWL_DEBUG_RESET) {
3597			struct ifnet *ifp = sc->sc_ifp;
3598			struct ieee80211com *ic = ifp->if_l2com;
3599			const struct mwltxrec *tr =
3600			    mtod(bf->bf_m, const struct mwltxrec *);
3601			mwl_printtxbuf(bf, txq->qnum, ix);
3602			ieee80211_dump_pkt(ic, (const uint8_t *)&tr->wh,
3603				bf->bf_m->m_len - sizeof(tr->fwlen), 0, -1);
3604		}
3605#endif /* MWL_DEBUG */
3606		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
3607		ni = bf->bf_node;
3608		if (ni != NULL) {
3609			/*
3610			 * Reclaim node reference.
3611			 */
3612			ieee80211_free_node(ni);
3613		}
3614		m_freem(bf->bf_m);
3615
3616		mwl_puttxbuf_tail(txq, bf);
3617	}
3618}
3619
3620/*
3621 * Drain the transmit queues and reclaim resources.
3622 */
3623static void
3624mwl_draintxq(struct mwl_softc *sc)
3625{
3626	struct ifnet *ifp = sc->sc_ifp;
3627	int i;
3628
3629	for (i = 0; i < MWL_NUM_TX_QUEUES; i++)
3630		mwl_tx_draintxq(sc, &sc->sc_txq[i]);
3631	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
3632	sc->sc_tx_timer = 0;
3633}
3634
3635#ifdef MWL_DIAGAPI
3636/*
3637 * Reset the transmit queues to a pristine state after a fw download.
3638 */
3639static void
3640mwl_resettxq(struct mwl_softc *sc)
3641{
3642	int i;
3643
3644	for (i = 0; i < MWL_NUM_TX_QUEUES; i++)
3645		mwl_txq_reset(sc, &sc->sc_txq[i]);
3646}
3647#endif /* MWL_DIAGAPI */
3648
3649/*
3650 * Clear the transmit queues of any frames submitted for the
3651 * specified vap.  This is done when the vap is deleted so we
3652 * don't potentially reference the vap after it is gone.
3653 * Note we cannot remove the frames; we only reclaim the node
3654 * reference.
3655 */
3656static void
3657mwl_cleartxq(struct mwl_softc *sc, struct ieee80211vap *vap)
3658{
3659	struct mwl_txq *txq;
3660	struct mwl_txbuf *bf;
3661	int i;
3662
3663	for (i = 0; i < MWL_NUM_TX_QUEUES; i++) {
3664		txq = &sc->sc_txq[i];
3665		MWL_TXQ_LOCK(txq);
3666		STAILQ_FOREACH(bf, &txq->active, bf_list) {
3667			struct ieee80211_node *ni = bf->bf_node;
3668			if (ni != NULL && ni->ni_vap == vap) {
3669				bf->bf_node = NULL;
3670				ieee80211_free_node(ni);
3671			}
3672		}
3673		MWL_TXQ_UNLOCK(txq);
3674	}
3675}
3676
3677static int
3678mwl_recv_action(struct ieee80211_node *ni, const struct ieee80211_frame *wh,
3679	const uint8_t *frm, const uint8_t *efrm)
3680{
3681	struct mwl_softc *sc = ni->ni_ic->ic_ifp->if_softc;
3682	const struct ieee80211_action *ia;
3683
3684	ia = (const struct ieee80211_action *) frm;
3685	if (ia->ia_category == IEEE80211_ACTION_CAT_HT &&
3686	    ia->ia_action == IEEE80211_ACTION_HT_MIMOPWRSAVE) {
3687		const struct ieee80211_action_ht_mimopowersave *mps =
3688		    (const struct ieee80211_action_ht_mimopowersave *) ia;
3689
3690		mwl_hal_setmimops(sc->sc_mh, ni->ni_macaddr,
3691		    mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_ENA,
3692		    MS(mps->am_control, IEEE80211_A_HT_MIMOPWRSAVE_MODE));
3693		return 0;
3694	} else
3695		return sc->sc_recv_action(ni, wh, frm, efrm);
3696}
3697
3698static int
3699mwl_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
3700	int dialogtoken, int baparamset, int batimeout)
3701{
3702	struct mwl_softc *sc = ni->ni_ic->ic_ifp->if_softc;
3703	struct ieee80211vap *vap = ni->ni_vap;
3704	struct mwl_node *mn = MWL_NODE(ni);
3705	struct mwl_bastate *bas;
3706
3707	bas = tap->txa_private;
3708	if (bas == NULL) {
3709		const MWL_HAL_BASTREAM *sp;
3710		/*
3711		 * Check for a free BA stream slot.
3712		 */
3713#if MWL_MAXBA > 3
3714		if (mn->mn_ba[3].bastream == NULL)
3715			bas = &mn->mn_ba[3];
3716		else
3717#endif
3718#if MWL_MAXBA > 2
3719		if (mn->mn_ba[2].bastream == NULL)
3720			bas = &mn->mn_ba[2];
3721		else
3722#endif
3723#if MWL_MAXBA > 1
3724		if (mn->mn_ba[1].bastream == NULL)
3725			bas = &mn->mn_ba[1];
3726		else
3727#endif
3728#if MWL_MAXBA > 0
3729		if (mn->mn_ba[0].bastream == NULL)
3730			bas = &mn->mn_ba[0];
3731		else
3732#endif
3733		{
3734			/* sta already has max BA streams */
3735			/* XXX assign BA stream to highest priority tid */
3736			DPRINTF(sc, MWL_DEBUG_AMPDU,
3737			    "%s: already has max bastreams\n", __func__);
3738			sc->sc_stats.mst_ampdu_reject++;
3739			return 0;
3740		}
3741		/* NB: no held reference to ni */
3742		sp = mwl_hal_bastream_alloc(MWL_VAP(vap)->mv_hvap,
3743		    (baparamset & IEEE80211_BAPS_POLICY_IMMEDIATE) != 0,
3744		    ni->ni_macaddr, WME_AC_TO_TID(tap->txa_ac), ni->ni_htparam,
3745		    ni, tap);
3746		if (sp == NULL) {
3747			/*
3748			 * No available stream, return 0 so no
3749			 * a-mpdu aggregation will be done.
3750			 */
3751			DPRINTF(sc, MWL_DEBUG_AMPDU,
3752			    "%s: no bastream available\n", __func__);
3753			sc->sc_stats.mst_ampdu_nostream++;
3754			return 0;
3755		}
3756		DPRINTF(sc, MWL_DEBUG_AMPDU, "%s: alloc bastream %p\n",
3757		    __func__, sp);
3758		/* NB: qos is left zero so we won't match in mwl_tx_start */
3759		bas->bastream = sp;
3760		tap->txa_private = bas;
3761	}
3762	/* fetch current seq# from the firmware; if available */
3763	if (mwl_hal_bastream_get_seqno(sc->sc_mh, bas->bastream,
3764	    vap->iv_opmode == IEEE80211_M_STA ? vap->iv_myaddr : ni->ni_macaddr,
3765	    &tap->txa_start) != 0)
3766		tap->txa_start = 0;
3767	return sc->sc_addba_request(ni, tap, dialogtoken, baparamset, batimeout);
3768}
3769
3770static int
3771mwl_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
3772	int code, int baparamset, int batimeout)
3773{
3774	struct mwl_softc *sc = ni->ni_ic->ic_ifp->if_softc;
3775	struct mwl_bastate *bas;
3776
3777	bas = tap->txa_private;
3778	if (bas == NULL) {
3779		/* XXX should not happen */
3780		DPRINTF(sc, MWL_DEBUG_AMPDU,
3781		    "%s: no BA stream allocated, AC %d\n",
3782		    __func__, tap->txa_ac);
3783		sc->sc_stats.mst_addba_nostream++;
3784		return 0;
3785	}
3786	if (code == IEEE80211_STATUS_SUCCESS) {
3787		struct ieee80211vap *vap = ni->ni_vap;
3788		int bufsiz, error;
3789
3790		/*
3791		 * Tell the firmware to setup the BA stream;
3792		 * we know resources are available because we
3793		 * pre-allocated one before forming the request.
3794		 */
3795		bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ);
3796		if (bufsiz == 0)
3797			bufsiz = IEEE80211_AGGR_BAWMAX;
3798		error = mwl_hal_bastream_create(MWL_VAP(vap)->mv_hvap,
3799		    bas->bastream, bufsiz, bufsiz, tap->txa_start);
3800		if (error != 0) {
3801			/*
3802			 * Setup failed, return immediately so no a-mpdu
3803			 * aggregation will be done.
3804			 */
3805			mwl_hal_bastream_destroy(sc->sc_mh, bas->bastream);
3806			mwl_bastream_free(bas);
3807			tap->txa_private = NULL;
3808
3809			DPRINTF(sc, MWL_DEBUG_AMPDU,
3810			    "%s: create failed, error %d, bufsiz %d AC %d "
3811			    "htparam 0x%x\n", __func__, error, bufsiz,
3812			    tap->txa_ac, ni->ni_htparam);
3813			sc->sc_stats.mst_bacreate_failed++;
3814			return 0;
3815		}
3816		/* NB: cache txq to avoid ptr indirect */
3817		mwl_bastream_setup(bas, tap->txa_ac, bas->bastream->txq);
3818		DPRINTF(sc, MWL_DEBUG_AMPDU,
3819		    "%s: bastream %p assigned to txq %d AC %d bufsiz %d "
3820		    "htparam 0x%x\n", __func__, bas->bastream,
3821		    bas->txq, tap->txa_ac, bufsiz, ni->ni_htparam);
3822	} else {
3823		/*
3824		 * Other side NAK'd us; return the resources.
3825		 */
3826		DPRINTF(sc, MWL_DEBUG_AMPDU,
3827		    "%s: request failed with code %d, destroy bastream %p\n",
3828		    __func__, code, bas->bastream);
3829		mwl_hal_bastream_destroy(sc->sc_mh, bas->bastream);
3830		mwl_bastream_free(bas);
3831		tap->txa_private = NULL;
3832	}
3833	/* NB: firmware sends BAR so we don't need to */
3834	return sc->sc_addba_response(ni, tap, code, baparamset, batimeout);
3835}
3836
3837static void
3838mwl_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
3839{
3840	struct mwl_softc *sc = ni->ni_ic->ic_ifp->if_softc;
3841	struct mwl_bastate *bas;
3842
3843	bas = tap->txa_private;
3844	if (bas != NULL) {
3845		DPRINTF(sc, MWL_DEBUG_AMPDU, "%s: destroy bastream %p\n",
3846		    __func__, bas->bastream);
3847		mwl_hal_bastream_destroy(sc->sc_mh, bas->bastream);
3848		mwl_bastream_free(bas);
3849		tap->txa_private = NULL;
3850	}
3851	sc->sc_addba_stop(ni, tap);
3852}
3853
3854/*
3855 * Setup the rx data structures.  This should only be
3856 * done once or we may get out of sync with the firmware.
3857 */
3858static int
3859mwl_startrecv(struct mwl_softc *sc)
3860{
3861	if (!sc->sc_recvsetup) {
3862		struct mwl_rxbuf *bf, *prev;
3863		struct mwl_rxdesc *ds;
3864
3865		prev = NULL;
3866		STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
3867			int error = mwl_rxbuf_init(sc, bf);
3868			if (error != 0) {
3869				DPRINTF(sc, MWL_DEBUG_RECV,
3870					"%s: mwl_rxbuf_init failed %d\n",
3871					__func__, error);
3872				return error;
3873			}
3874			if (prev != NULL) {
3875				ds = prev->bf_desc;
3876				ds->pPhysNext = htole32(bf->bf_daddr);
3877			}
3878			prev = bf;
3879		}
3880		if (prev != NULL) {
3881			ds = prev->bf_desc;
3882			ds->pPhysNext =
3883			    htole32(STAILQ_FIRST(&sc->sc_rxbuf)->bf_daddr);
3884		}
3885		sc->sc_recvsetup = 1;
3886	}
3887	mwl_mode_init(sc);		/* set filters, etc. */
3888	return 0;
3889}
3890
3891static MWL_HAL_APMODE
3892mwl_getapmode(const struct ieee80211vap *vap, struct ieee80211_channel *chan)
3893{
3894	MWL_HAL_APMODE mode;
3895
3896	if (IEEE80211_IS_CHAN_HT(chan)) {
3897		if (vap->iv_flags_ht & IEEE80211_FHT_PUREN)
3898			mode = AP_MODE_N_ONLY;
3899		else if (IEEE80211_IS_CHAN_5GHZ(chan))
3900			mode = AP_MODE_AandN;
3901		else if (vap->iv_flags & IEEE80211_F_PUREG)
3902			mode = AP_MODE_GandN;
3903		else
3904			mode = AP_MODE_BandGandN;
3905	} else if (IEEE80211_IS_CHAN_ANYG(chan)) {
3906		if (vap->iv_flags & IEEE80211_F_PUREG)
3907			mode = AP_MODE_G_ONLY;
3908		else
3909			mode = AP_MODE_MIXED;
3910	} else if (IEEE80211_IS_CHAN_B(chan))
3911		mode = AP_MODE_B_ONLY;
3912	else if (IEEE80211_IS_CHAN_A(chan))
3913		mode = AP_MODE_A_ONLY;
3914	else
3915		mode = AP_MODE_MIXED;		/* XXX should not happen? */
3916	return mode;
3917}
3918
3919static int
3920mwl_setapmode(struct ieee80211vap *vap, struct ieee80211_channel *chan)
3921{
3922	struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
3923	return mwl_hal_setapmode(hvap, mwl_getapmode(vap, chan));
3924}
3925
3926/*
3927 * Set/change channels.
3928 */
3929static int
3930mwl_chan_set(struct mwl_softc *sc, struct ieee80211_channel *chan)
3931{
3932	struct mwl_hal *mh = sc->sc_mh;
3933	struct ifnet *ifp = sc->sc_ifp;
3934	struct ieee80211com *ic = ifp->if_l2com;
3935	MWL_HAL_CHANNEL hchan;
3936	int maxtxpow;
3937
3938	DPRINTF(sc, MWL_DEBUG_RESET, "%s: chan %u MHz/flags 0x%x\n",
3939	    __func__, chan->ic_freq, chan->ic_flags);
3940
3941	/*
3942	 * Convert to a HAL channel description with
3943	 * the flags constrained to reflect the current
3944	 * operating mode.
3945	 */
3946	mwl_mapchan(&hchan, chan);
3947	mwl_hal_intrset(mh, 0);		/* disable interrupts */
3948#if 0
3949	mwl_draintxq(sc);		/* clear pending tx frames */
3950#endif
3951	mwl_hal_setchannel(mh, &hchan);
3952	/*
3953	 * Tx power is cap'd by the regulatory setting and
3954	 * possibly a user-set limit.  We pass the min of
3955	 * these to the hal to apply them to the cal data
3956	 * for this channel.
3957	 * XXX min bound?
3958	 */
3959	maxtxpow = 2*chan->ic_maxregpower;
3960	if (maxtxpow > ic->ic_txpowlimit)
3961		maxtxpow = ic->ic_txpowlimit;
3962	mwl_hal_settxpower(mh, &hchan, maxtxpow / 2);
3963	/* NB: potentially change mcast/mgt rates */
3964	mwl_setcurchanrates(sc);
3965
3966	/*
3967	 * Update internal state.
3968	 */
3969	sc->sc_tx_th.wt_chan_freq = htole16(chan->ic_freq);
3970	sc->sc_rx_th.wr_chan_freq = htole16(chan->ic_freq);
3971	if (IEEE80211_IS_CHAN_A(chan)) {
3972		sc->sc_tx_th.wt_chan_flags = htole16(IEEE80211_CHAN_A);
3973		sc->sc_rx_th.wr_chan_flags = htole16(IEEE80211_CHAN_A);
3974	} else if (IEEE80211_IS_CHAN_ANYG(chan)) {
3975		sc->sc_tx_th.wt_chan_flags = htole16(IEEE80211_CHAN_G);
3976		sc->sc_rx_th.wr_chan_flags = htole16(IEEE80211_CHAN_G);
3977	} else {
3978		sc->sc_tx_th.wt_chan_flags = htole16(IEEE80211_CHAN_B);
3979		sc->sc_rx_th.wr_chan_flags = htole16(IEEE80211_CHAN_B);
3980	}
3981	sc->sc_curchan = hchan;
3982	mwl_hal_intrset(mh, sc->sc_imask);
3983
3984	return 0;
3985}
3986
3987static void
3988mwl_scan_start(struct ieee80211com *ic)
3989{
3990	struct ifnet *ifp = ic->ic_ifp;
3991	struct mwl_softc *sc = ifp->if_softc;
3992
3993	DPRINTF(sc, MWL_DEBUG_STATE, "%s\n", __func__);
3994}
3995
3996static void
3997mwl_scan_end(struct ieee80211com *ic)
3998{
3999	struct ifnet *ifp = ic->ic_ifp;
4000	struct mwl_softc *sc = ifp->if_softc;
4001
4002	DPRINTF(sc, MWL_DEBUG_STATE, "%s\n", __func__);
4003}
4004
4005static void
4006mwl_set_channel(struct ieee80211com *ic)
4007{
4008	struct ifnet *ifp = ic->ic_ifp;
4009	struct mwl_softc *sc = ifp->if_softc;
4010
4011	(void) mwl_chan_set(sc, ic->ic_curchan);
4012}
4013
4014/*
4015 * Handle a channel switch request.  We inform the firmware
4016 * and mark the global state to suppress various actions.
4017 * NB: we issue only one request to the fw; we may be called
4018 * multiple times if there are multiple vap's.
4019 */
4020static void
4021mwl_startcsa(struct ieee80211vap *vap)
4022{
4023	struct ieee80211com *ic = vap->iv_ic;
4024	struct mwl_softc *sc = ic->ic_ifp->if_softc;
4025	MWL_HAL_CHANNEL hchan;
4026
4027	if (sc->sc_csapending)
4028		return;
4029
4030	mwl_mapchan(&hchan, ic->ic_csa_newchan);
4031	/* 1 =>'s quiet channel */
4032	mwl_hal_setchannelswitchie(sc->sc_mh, &hchan, 1, ic->ic_csa_count);
4033	sc->sc_csapending = 1;
4034}
4035
4036/*
4037 * Plumb any static WEP key for the station.  This is
4038 * necessary as we must propagate the key from the
4039 * global key table of the vap to each sta db entry.
4040 */
4041static void
4042mwl_setanywepkey(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
4043{
4044	if ((vap->iv_flags & (IEEE80211_F_PRIVACY|IEEE80211_F_WPA)) ==
4045		IEEE80211_F_PRIVACY &&
4046	    vap->iv_def_txkey != IEEE80211_KEYIX_NONE &&
4047	    vap->iv_nw_keys[vap->iv_def_txkey].wk_keyix != IEEE80211_KEYIX_NONE)
4048		(void) mwl_key_set(vap, &vap->iv_nw_keys[vap->iv_def_txkey], mac);
4049}
4050
4051static int
4052mwl_peerstadb(struct ieee80211_node *ni, int aid, int staid, MWL_HAL_PEERINFO *pi)
4053{
4054#define	WME(ie) ((const struct ieee80211_wme_info *) ie)
4055	struct ieee80211vap *vap = ni->ni_vap;
4056	struct mwl_hal_vap *hvap;
4057	int error;
4058
4059	if (vap->iv_opmode == IEEE80211_M_WDS) {
4060		/*
4061		 * WDS vap's do not have a f/w vap; instead they piggyback
4062		 * on an AP vap and we must install the sta db entry and
4063		 * crypto state using that AP's handle (the WDS vap has none).
4064		 */
4065		hvap = MWL_VAP(vap)->mv_ap_hvap;
4066	} else
4067		hvap = MWL_VAP(vap)->mv_hvap;
4068	error = mwl_hal_newstation(hvap, ni->ni_macaddr,
4069	    aid, staid, pi,
4070	    ni->ni_flags & (IEEE80211_NODE_QOS | IEEE80211_NODE_HT),
4071	    ni->ni_ies.wme_ie != NULL ? WME(ni->ni_ies.wme_ie)->wme_info : 0);
4072	if (error == 0) {
4073		/*
4074		 * Setup security for this station.  For sta mode this is
4075		 * needed even though do the same thing on transition to
4076		 * AUTH state because the call to mwl_hal_newstation
4077		 * clobbers the crypto state we setup.
4078		 */
4079		mwl_setanywepkey(vap, ni->ni_macaddr);
4080	}
4081	return error;
4082#undef WME
4083}
4084
4085static void
4086mwl_setglobalkeys(struct ieee80211vap *vap)
4087{
4088	struct ieee80211_key *wk;
4089
4090	wk = &vap->iv_nw_keys[0];
4091	for (; wk < &vap->iv_nw_keys[IEEE80211_WEP_NKID]; wk++)
4092		if (wk->wk_keyix != IEEE80211_KEYIX_NONE)
4093			(void) mwl_key_set(vap, wk, vap->iv_myaddr);
4094}
4095
4096/*
4097 * Convert a legacy rate set to a firmware bitmask.
4098 */
4099static uint32_t
4100get_rate_bitmap(const struct ieee80211_rateset *rs)
4101{
4102	uint32_t rates;
4103	int i;
4104
4105	rates = 0;
4106	for (i = 0; i < rs->rs_nrates; i++)
4107		switch (rs->rs_rates[i] & IEEE80211_RATE_VAL) {
4108		case 2:	  rates |= 0x001; break;
4109		case 4:	  rates |= 0x002; break;
4110		case 11:  rates |= 0x004; break;
4111		case 22:  rates |= 0x008; break;
4112		case 44:  rates |= 0x010; break;
4113		case 12:  rates |= 0x020; break;
4114		case 18:  rates |= 0x040; break;
4115		case 24:  rates |= 0x080; break;
4116		case 36:  rates |= 0x100; break;
4117		case 48:  rates |= 0x200; break;
4118		case 72:  rates |= 0x400; break;
4119		case 96:  rates |= 0x800; break;
4120		case 108: rates |= 0x1000; break;
4121		}
4122	return rates;
4123}
4124
4125/*
4126 * Construct an HT firmware bitmask from an HT rate set.
4127 */
4128static uint32_t
4129get_htrate_bitmap(const struct ieee80211_htrateset *rs)
4130{
4131	uint32_t rates;
4132	int i;
4133
4134	rates = 0;
4135	for (i = 0; i < rs->rs_nrates; i++) {
4136		if (rs->rs_rates[i] < 16)
4137			rates |= 1<<rs->rs_rates[i];
4138	}
4139	return rates;
4140}
4141
4142/*
4143 * Craft station database entry for station.
4144 * NB: use host byte order here, the hal handles byte swapping.
4145 */
4146static MWL_HAL_PEERINFO *
4147mkpeerinfo(MWL_HAL_PEERINFO *pi, const struct ieee80211_node *ni)
4148{
4149	const struct ieee80211vap *vap = ni->ni_vap;
4150
4151	memset(pi, 0, sizeof(*pi));
4152	pi->LegacyRateBitMap = get_rate_bitmap(&ni->ni_rates);
4153	pi->CapInfo = ni->ni_capinfo;
4154	if (ni->ni_flags & IEEE80211_NODE_HT) {
4155		/* HT capabilities, etc */
4156		pi->HTCapabilitiesInfo = ni->ni_htcap;
4157		/* XXX pi.HTCapabilitiesInfo */
4158	        pi->MacHTParamInfo = ni->ni_htparam;
4159		pi->HTRateBitMap = get_htrate_bitmap(&ni->ni_htrates);
4160		pi->AddHtInfo.ControlChan = ni->ni_htctlchan;
4161		pi->AddHtInfo.AddChan = ni->ni_ht2ndchan;
4162		pi->AddHtInfo.OpMode = ni->ni_htopmode;
4163		pi->AddHtInfo.stbc = ni->ni_htstbc;
4164
4165		/* constrain according to local configuration */
4166		if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) == 0)
4167			pi->HTCapabilitiesInfo &= ~IEEE80211_HTCAP_SHORTGI40;
4168		if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) == 0)
4169			pi->HTCapabilitiesInfo &= ~IEEE80211_HTCAP_SHORTGI20;
4170		if (ni->ni_chw != 40)
4171			pi->HTCapabilitiesInfo &= ~IEEE80211_HTCAP_CHWIDTH40;
4172	}
4173	return pi;
4174}
4175
4176/*
4177 * Re-create the local sta db entry for a vap to ensure
4178 * up to date WME state is pushed to the firmware.  Because
4179 * this resets crypto state this must be followed by a
4180 * reload of any keys in the global key table.
4181 */
4182static int
4183mwl_localstadb(struct ieee80211vap *vap)
4184{
4185#define	WME(ie) ((const struct ieee80211_wme_info *) ie)
4186	struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
4187	struct ieee80211_node *bss;
4188	MWL_HAL_PEERINFO pi;
4189	int error;
4190
4191	switch (vap->iv_opmode) {
4192	case IEEE80211_M_STA:
4193		bss = vap->iv_bss;
4194		error = mwl_hal_newstation(hvap, vap->iv_myaddr, 0, 0,
4195		    vap->iv_state == IEEE80211_S_RUN ?
4196			mkpeerinfo(&pi, bss) : NULL,
4197		    (bss->ni_flags & (IEEE80211_NODE_QOS | IEEE80211_NODE_HT)),
4198		    bss->ni_ies.wme_ie != NULL ?
4199			WME(bss->ni_ies.wme_ie)->wme_info : 0);
4200		if (error == 0)
4201			mwl_setglobalkeys(vap);
4202		break;
4203	case IEEE80211_M_HOSTAP:
4204	case IEEE80211_M_MBSS:
4205		error = mwl_hal_newstation(hvap, vap->iv_myaddr,
4206		    0, 0, NULL, vap->iv_flags & IEEE80211_F_WME, 0);
4207		if (error == 0)
4208			mwl_setglobalkeys(vap);
4209		break;
4210	default:
4211		error = 0;
4212		break;
4213	}
4214	return error;
4215#undef WME
4216}
4217
4218static int
4219mwl_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
4220{
4221	struct mwl_vap *mvp = MWL_VAP(vap);
4222	struct mwl_hal_vap *hvap = mvp->mv_hvap;
4223	struct ieee80211com *ic = vap->iv_ic;
4224	struct ieee80211_node *ni = NULL;
4225	struct ifnet *ifp = ic->ic_ifp;
4226	struct mwl_softc *sc = ifp->if_softc;
4227	struct mwl_hal *mh = sc->sc_mh;
4228	enum ieee80211_state ostate = vap->iv_state;
4229	int error;
4230
4231	DPRINTF(sc, MWL_DEBUG_STATE, "%s: %s: %s -> %s\n",
4232	    vap->iv_ifp->if_xname, __func__,
4233	    ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
4234
4235	callout_stop(&sc->sc_timer);
4236	/*
4237	 * Clear current radar detection state.
4238	 */
4239	if (ostate == IEEE80211_S_CAC) {
4240		/* stop quiet mode radar detection */
4241		mwl_hal_setradardetection(mh, DR_CHK_CHANNEL_AVAILABLE_STOP);
4242	} else if (sc->sc_radarena) {
4243		/* stop in-service radar detection */
4244		mwl_hal_setradardetection(mh, DR_DFS_DISABLE);
4245		sc->sc_radarena = 0;
4246	}
4247	/*
4248	 * Carry out per-state actions before doing net80211 work.
4249	 */
4250	if (nstate == IEEE80211_S_INIT) {
4251		/* NB: only ap+sta vap's have a fw entity */
4252		if (hvap != NULL)
4253			mwl_hal_stop(hvap);
4254	} else if (nstate == IEEE80211_S_SCAN) {
4255		mwl_hal_start(hvap);
4256		/* NB: this disables beacon frames */
4257		mwl_hal_setinframode(hvap);
4258	} else if (nstate == IEEE80211_S_AUTH) {
4259		/*
4260		 * Must create a sta db entry in case a WEP key needs to
4261		 * be plumbed.  This entry will be overwritten if we
4262		 * associate; otherwise it will be reclaimed on node free.
4263		 */
4264		ni = vap->iv_bss;
4265		MWL_NODE(ni)->mn_hvap = hvap;
4266		(void) mwl_peerstadb(ni, 0, 0, NULL);
4267	} else if (nstate == IEEE80211_S_CSA) {
4268		/* XXX move to below? */
4269		if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
4270		    vap->iv_opmode == IEEE80211_M_MBSS)
4271			mwl_startcsa(vap);
4272	} else if (nstate == IEEE80211_S_CAC) {
4273		/* XXX move to below? */
4274		/* stop ap xmit and enable quiet mode radar detection */
4275		mwl_hal_setradardetection(mh, DR_CHK_CHANNEL_AVAILABLE_START);
4276	}
4277
4278	/*
4279	 * Invoke the parent method to do net80211 work.
4280	 */
4281	error = mvp->mv_newstate(vap, nstate, arg);
4282
4283	/*
4284	 * Carry out work that must be done after net80211 runs;
4285	 * this work requires up to date state (e.g. iv_bss).
4286	 */
4287	if (error == 0 && nstate == IEEE80211_S_RUN) {
4288		/* NB: collect bss node again, it may have changed */
4289		ni = vap->iv_bss;
4290
4291		DPRINTF(sc, MWL_DEBUG_STATE,
4292		    "%s: %s(RUN): iv_flags 0x%08x bintvl %d bssid %s "
4293		    "capinfo 0x%04x chan %d\n",
4294		    vap->iv_ifp->if_xname, __func__, vap->iv_flags,
4295		    ni->ni_intval, ether_sprintf(ni->ni_bssid), ni->ni_capinfo,
4296		    ieee80211_chan2ieee(ic, ic->ic_curchan));
4297
4298		/*
4299		 * Recreate local sta db entry to update WME/HT state.
4300		 */
4301		mwl_localstadb(vap);
4302		switch (vap->iv_opmode) {
4303		case IEEE80211_M_HOSTAP:
4304		case IEEE80211_M_MBSS:
4305			if (ostate == IEEE80211_S_CAC) {
4306				/* enable in-service radar detection */
4307				mwl_hal_setradardetection(mh,
4308				    DR_IN_SERVICE_MONITOR_START);
4309				sc->sc_radarena = 1;
4310			}
4311			/*
4312			 * Allocate and setup the beacon frame
4313			 * (and related state).
4314			 */
4315			error = mwl_reset_vap(vap, IEEE80211_S_RUN);
4316			if (error != 0) {
4317				DPRINTF(sc, MWL_DEBUG_STATE,
4318				    "%s: beacon setup failed, error %d\n",
4319				    __func__, error);
4320				goto bad;
4321			}
4322			/* NB: must be after setting up beacon */
4323			mwl_hal_start(hvap);
4324			break;
4325		case IEEE80211_M_STA:
4326			DPRINTF(sc, MWL_DEBUG_STATE, "%s: %s: aid 0x%x\n",
4327			    vap->iv_ifp->if_xname, __func__, ni->ni_associd);
4328			/*
4329			 * Set state now that we're associated.
4330			 */
4331			mwl_hal_setassocid(hvap, ni->ni_bssid, ni->ni_associd);
4332			mwl_setrates(vap);
4333			mwl_hal_setrtsthreshold(hvap, vap->iv_rtsthreshold);
4334			if ((vap->iv_flags & IEEE80211_F_DWDS) &&
4335			    sc->sc_ndwdsvaps++ == 0)
4336				mwl_hal_setdwds(mh, 1);
4337			break;
4338		case IEEE80211_M_WDS:
4339			DPRINTF(sc, MWL_DEBUG_STATE, "%s: %s: bssid %s\n",
4340			    vap->iv_ifp->if_xname, __func__,
4341			    ether_sprintf(ni->ni_bssid));
4342			mwl_seteapolformat(vap);
4343			break;
4344		default:
4345			break;
4346		}
4347		/*
4348		 * Set CS mode according to operating channel;
4349		 * this mostly an optimization for 5GHz.
4350		 *
4351		 * NB: must follow mwl_hal_start which resets csmode
4352		 */
4353		if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan))
4354			mwl_hal_setcsmode(mh, CSMODE_AGGRESSIVE);
4355		else
4356			mwl_hal_setcsmode(mh, CSMODE_AUTO_ENA);
4357		/*
4358		 * Start timer to prod firmware.
4359		 */
4360		if (sc->sc_ageinterval != 0)
4361			callout_reset(&sc->sc_timer, sc->sc_ageinterval*hz,
4362			    mwl_agestations, sc);
4363	} else if (nstate == IEEE80211_S_SLEEP) {
4364		/* XXX set chip in power save */
4365	} else if ((vap->iv_flags & IEEE80211_F_DWDS) &&
4366	    --sc->sc_ndwdsvaps == 0)
4367		mwl_hal_setdwds(mh, 0);
4368bad:
4369	return error;
4370}
4371
4372/*
4373 * Manage station id's; these are separate from AID's
4374 * as AID's may have values out of the range of possible
4375 * station id's acceptable to the firmware.
4376 */
4377static int
4378allocstaid(struct mwl_softc *sc, int aid)
4379{
4380	int staid;
4381
4382	if (!(0 < aid && aid < MWL_MAXSTAID) || isset(sc->sc_staid, aid)) {
4383		/* NB: don't use 0 */
4384		for (staid = 1; staid < MWL_MAXSTAID; staid++)
4385			if (isclr(sc->sc_staid, staid))
4386				break;
4387	} else
4388		staid = aid;
4389	setbit(sc->sc_staid, staid);
4390	return staid;
4391}
4392
4393static void
4394delstaid(struct mwl_softc *sc, int staid)
4395{
4396	clrbit(sc->sc_staid, staid);
4397}
4398
4399/*
4400 * Setup driver-specific state for a newly associated node.
4401 * Note that we're called also on a re-associate, the isnew
4402 * param tells us if this is the first time or not.
4403 */
4404static void
4405mwl_newassoc(struct ieee80211_node *ni, int isnew)
4406{
4407	struct ieee80211vap *vap = ni->ni_vap;
4408        struct mwl_softc *sc = vap->iv_ic->ic_ifp->if_softc;
4409	struct mwl_node *mn = MWL_NODE(ni);
4410	MWL_HAL_PEERINFO pi;
4411	uint16_t aid;
4412	int error;
4413
4414	aid = IEEE80211_AID(ni->ni_associd);
4415	if (isnew) {
4416		mn->mn_staid = allocstaid(sc, aid);
4417		mn->mn_hvap = MWL_VAP(vap)->mv_hvap;
4418	} else {
4419		mn = MWL_NODE(ni);
4420		/* XXX reset BA stream? */
4421	}
4422	DPRINTF(sc, MWL_DEBUG_NODE, "%s: mac %s isnew %d aid %d staid %d\n",
4423	    __func__, ether_sprintf(ni->ni_macaddr), isnew, aid, mn->mn_staid);
4424	error = mwl_peerstadb(ni, aid, mn->mn_staid, mkpeerinfo(&pi, ni));
4425	if (error != 0) {
4426		DPRINTF(sc, MWL_DEBUG_NODE,
4427		    "%s: error %d creating sta db entry\n",
4428		    __func__, error);
4429		/* XXX how to deal with error? */
4430	}
4431}
4432
4433/*
4434 * Periodically poke the firmware to age out station state
4435 * (power save queues, pending tx aggregates).
4436 */
4437static void
4438mwl_agestations(void *arg)
4439{
4440	struct mwl_softc *sc = arg;
4441
4442	mwl_hal_setkeepalive(sc->sc_mh);
4443	if (sc->sc_ageinterval != 0)		/* NB: catch dynamic changes */
4444		callout_schedule(&sc->sc_timer, sc->sc_ageinterval*hz);
4445}
4446
4447static const struct mwl_hal_channel *
4448findhalchannel(const MWL_HAL_CHANNELINFO *ci, int ieee)
4449{
4450	int i;
4451
4452	for (i = 0; i < ci->nchannels; i++) {
4453		const struct mwl_hal_channel *hc = &ci->channels[i];
4454		if (hc->ieee == ieee)
4455			return hc;
4456	}
4457	return NULL;
4458}
4459
4460static int
4461mwl_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd,
4462	int nchan, struct ieee80211_channel chans[])
4463{
4464	struct mwl_softc *sc = ic->ic_ifp->if_softc;
4465	struct mwl_hal *mh = sc->sc_mh;
4466	const MWL_HAL_CHANNELINFO *ci;
4467	int i;
4468
4469	for (i = 0; i < nchan; i++) {
4470		struct ieee80211_channel *c = &chans[i];
4471		const struct mwl_hal_channel *hc;
4472
4473		if (IEEE80211_IS_CHAN_2GHZ(c)) {
4474			mwl_hal_getchannelinfo(mh, MWL_FREQ_BAND_2DOT4GHZ,
4475			    IEEE80211_IS_CHAN_HT40(c) ?
4476				MWL_CH_40_MHz_WIDTH : MWL_CH_20_MHz_WIDTH, &ci);
4477		} else if (IEEE80211_IS_CHAN_5GHZ(c)) {
4478			mwl_hal_getchannelinfo(mh, MWL_FREQ_BAND_5GHZ,
4479			    IEEE80211_IS_CHAN_HT40(c) ?
4480				MWL_CH_40_MHz_WIDTH : MWL_CH_20_MHz_WIDTH, &ci);
4481		} else {
4482			if_printf(ic->ic_ifp,
4483			    "%s: channel %u freq %u/0x%x not 2.4/5GHz\n",
4484			    __func__, c->ic_ieee, c->ic_freq, c->ic_flags);
4485			return EINVAL;
4486		}
4487		/*
4488		 * Verify channel has cal data and cap tx power.
4489		 */
4490		hc = findhalchannel(ci, c->ic_ieee);
4491		if (hc != NULL) {
4492			if (c->ic_maxpower > 2*hc->maxTxPow)
4493				c->ic_maxpower = 2*hc->maxTxPow;
4494			goto next;
4495		}
4496		if (IEEE80211_IS_CHAN_HT40(c)) {
4497			/*
4498			 * Look for the extension channel since the
4499			 * hal table only has the primary channel.
4500			 */
4501			hc = findhalchannel(ci, c->ic_extieee);
4502			if (hc != NULL) {
4503				if (c->ic_maxpower > 2*hc->maxTxPow)
4504					c->ic_maxpower = 2*hc->maxTxPow;
4505				goto next;
4506			}
4507		}
4508		if_printf(ic->ic_ifp,
4509		    "%s: no cal data for channel %u ext %u freq %u/0x%x\n",
4510		    __func__, c->ic_ieee, c->ic_extieee,
4511		    c->ic_freq, c->ic_flags);
4512		return EINVAL;
4513	next:
4514		;
4515	}
4516	return 0;
4517}
4518
4519#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT|IEEE80211_CHAN_G)
4520#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT|IEEE80211_CHAN_A)
4521
4522static void
4523addchan(struct ieee80211_channel *c, int freq, int flags, int ieee, int txpow)
4524{
4525	c->ic_freq = freq;
4526	c->ic_flags = flags;
4527	c->ic_ieee = ieee;
4528	c->ic_minpower = 0;
4529	c->ic_maxpower = 2*txpow;
4530	c->ic_maxregpower = txpow;
4531}
4532
4533static const struct ieee80211_channel *
4534findchannel(const struct ieee80211_channel chans[], int nchans,
4535	int freq, int flags)
4536{
4537	const struct ieee80211_channel *c;
4538	int i;
4539
4540	for (i = 0; i < nchans; i++) {
4541		c = &chans[i];
4542		if (c->ic_freq == freq && c->ic_flags == flags)
4543			return c;
4544	}
4545	return NULL;
4546}
4547
4548static void
4549addht40channels(struct ieee80211_channel chans[], int maxchans, int *nchans,
4550	const MWL_HAL_CHANNELINFO *ci, int flags)
4551{
4552	struct ieee80211_channel *c;
4553	const struct ieee80211_channel *extc;
4554	const struct mwl_hal_channel *hc;
4555	int i;
4556
4557	c = &chans[*nchans];
4558
4559	flags &= ~IEEE80211_CHAN_HT;
4560	for (i = 0; i < ci->nchannels; i++) {
4561		/*
4562		 * Each entry defines an HT40 channel pair; find the
4563		 * extension channel above and the insert the pair.
4564		 */
4565		hc = &ci->channels[i];
4566		extc = findchannel(chans, *nchans, hc->freq+20,
4567		    flags | IEEE80211_CHAN_HT20);
4568		if (extc != NULL) {
4569			if (*nchans >= maxchans)
4570				break;
4571			addchan(c, hc->freq, flags | IEEE80211_CHAN_HT40U,
4572			    hc->ieee, hc->maxTxPow);
4573			c->ic_extieee = extc->ic_ieee;
4574			c++, (*nchans)++;
4575			if (*nchans >= maxchans)
4576				break;
4577			addchan(c, extc->ic_freq, flags | IEEE80211_CHAN_HT40D,
4578			    extc->ic_ieee, hc->maxTxPow);
4579			c->ic_extieee = hc->ieee;
4580			c++, (*nchans)++;
4581		}
4582	}
4583}
4584
4585static void
4586addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
4587	const MWL_HAL_CHANNELINFO *ci, int flags)
4588{
4589	struct ieee80211_channel *c;
4590	int i;
4591
4592	c = &chans[*nchans];
4593
4594	for (i = 0; i < ci->nchannels; i++) {
4595		const struct mwl_hal_channel *hc;
4596
4597		hc = &ci->channels[i];
4598		if (*nchans >= maxchans)
4599			break;
4600		addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
4601		c++, (*nchans)++;
4602		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
4603			/* g channel have a separate b-only entry */
4604			if (*nchans >= maxchans)
4605				break;
4606			c[0] = c[-1];
4607			c[-1].ic_flags = IEEE80211_CHAN_B;
4608			c++, (*nchans)++;
4609		}
4610		if (flags == IEEE80211_CHAN_HTG) {
4611			/* HT g channel have a separate g-only entry */
4612			if (*nchans >= maxchans)
4613				break;
4614			c[-1].ic_flags = IEEE80211_CHAN_G;
4615			c[0] = c[-1];
4616			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
4617			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
4618			c++, (*nchans)++;
4619		}
4620		if (flags == IEEE80211_CHAN_HTA) {
4621			/* HT a channel have a separate a-only entry */
4622			if (*nchans >= maxchans)
4623				break;
4624			c[-1].ic_flags = IEEE80211_CHAN_A;
4625			c[0] = c[-1];
4626			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
4627			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
4628			c++, (*nchans)++;
4629		}
4630	}
4631}
4632
4633static void
4634getchannels(struct mwl_softc *sc, int maxchans, int *nchans,
4635	struct ieee80211_channel chans[])
4636{
4637	const MWL_HAL_CHANNELINFO *ci;
4638
4639	/*
4640	 * Use the channel info from the hal to craft the
4641	 * channel list.  Note that we pass back an unsorted
4642	 * list; the caller is required to sort it for us
4643	 * (if desired).
4644	 */
4645	*nchans = 0;
4646	if (mwl_hal_getchannelinfo(sc->sc_mh,
4647	    MWL_FREQ_BAND_2DOT4GHZ, MWL_CH_20_MHz_WIDTH, &ci) == 0)
4648		addchannels(chans, maxchans, nchans, ci, IEEE80211_CHAN_HTG);
4649	if (mwl_hal_getchannelinfo(sc->sc_mh,
4650	    MWL_FREQ_BAND_5GHZ, MWL_CH_20_MHz_WIDTH, &ci) == 0)
4651		addchannels(chans, maxchans, nchans, ci, IEEE80211_CHAN_HTA);
4652	if (mwl_hal_getchannelinfo(sc->sc_mh,
4653	    MWL_FREQ_BAND_2DOT4GHZ, MWL_CH_40_MHz_WIDTH, &ci) == 0)
4654		addht40channels(chans, maxchans, nchans, ci, IEEE80211_CHAN_HTG);
4655	if (mwl_hal_getchannelinfo(sc->sc_mh,
4656	    MWL_FREQ_BAND_5GHZ, MWL_CH_40_MHz_WIDTH, &ci) == 0)
4657		addht40channels(chans, maxchans, nchans, ci, IEEE80211_CHAN_HTA);
4658}
4659
4660static void
4661mwl_getradiocaps(struct ieee80211com *ic,
4662	int maxchans, int *nchans, struct ieee80211_channel chans[])
4663{
4664	struct mwl_softc *sc = ic->ic_ifp->if_softc;
4665
4666	getchannels(sc, maxchans, nchans, chans);
4667}
4668
4669static int
4670mwl_getchannels(struct mwl_softc *sc)
4671{
4672	struct ifnet *ifp = sc->sc_ifp;
4673	struct ieee80211com *ic = ifp->if_l2com;
4674
4675	/*
4676	 * Use the channel info from the hal to craft the
4677	 * channel list for net80211.  Note that we pass up
4678	 * an unsorted list; net80211 will sort it for us.
4679	 */
4680	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
4681	ic->ic_nchans = 0;
4682	getchannels(sc, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels);
4683
4684	ic->ic_regdomain.regdomain = SKU_DEBUG;
4685	ic->ic_regdomain.country = CTRY_DEFAULT;
4686	ic->ic_regdomain.location = 'I';
4687	ic->ic_regdomain.isocc[0] = ' ';	/* XXX? */
4688	ic->ic_regdomain.isocc[1] = ' ';
4689	return (ic->ic_nchans == 0 ? EIO : 0);
4690}
4691#undef IEEE80211_CHAN_HTA
4692#undef IEEE80211_CHAN_HTG
4693
4694#ifdef MWL_DEBUG
4695static void
4696mwl_printrxbuf(const struct mwl_rxbuf *bf, u_int ix)
4697{
4698	const struct mwl_rxdesc *ds = bf->bf_desc;
4699	uint32_t status = le32toh(ds->Status);
4700
4701	printf("R[%2u] (DS.V:%p DS.P:%p) NEXT:%08x DATA:%08x RC:%02x%s\n"
4702	       "      STAT:%02x LEN:%04x RSSI:%02x CHAN:%02x RATE:%02x QOS:%04x HT:%04x\n",
4703	    ix, ds, (const struct mwl_desc *)bf->bf_daddr,
4704	    le32toh(ds->pPhysNext), le32toh(ds->pPhysBuffData),
4705	    ds->RxControl,
4706	    ds->RxControl != EAGLE_RXD_CTRL_DRIVER_OWN ?
4707	        "" : (status & EAGLE_RXD_STATUS_OK) ? " *" : " !",
4708	    ds->Status, le16toh(ds->PktLen), ds->RSSI, ds->Channel,
4709	    ds->Rate, le16toh(ds->QosCtrl), le16toh(ds->HtSig2));
4710}
4711
4712static void
4713mwl_printtxbuf(const struct mwl_txbuf *bf, u_int qnum, u_int ix)
4714{
4715	const struct mwl_txdesc *ds = bf->bf_desc;
4716	uint32_t status = le32toh(ds->Status);
4717
4718	printf("Q%u[%3u]", qnum, ix);
4719	printf(" (DS.V:%p DS.P:%p)\n",
4720	    ds, (const struct mwl_txdesc *)bf->bf_daddr);
4721	printf("    NEXT:%08x DATA:%08x LEN:%04x STAT:%08x%s\n",
4722	    le32toh(ds->pPhysNext),
4723	    le32toh(ds->PktPtr), le16toh(ds->PktLen), status,
4724	    status & EAGLE_TXD_STATUS_USED ?
4725		"" : (status & 3) != 0 ? " *" : " !");
4726	printf("    RATE:%02x PRI:%x QOS:%04x SAP:%08x FORMAT:%04x\n",
4727	    ds->DataRate, ds->TxPriority, le16toh(ds->QosCtrl),
4728	    le32toh(ds->SapPktInfo), le16toh(ds->Format));
4729#if MWL_TXDESC > 1
4730	printf("    MULTIFRAMES:%u LEN:%04x %04x %04x %04x %04x %04x\n"
4731	    , le32toh(ds->multiframes)
4732	    , le16toh(ds->PktLenArray[0]), le16toh(ds->PktLenArray[1])
4733	    , le16toh(ds->PktLenArray[2]), le16toh(ds->PktLenArray[3])
4734	    , le16toh(ds->PktLenArray[4]), le16toh(ds->PktLenArray[5])
4735	);
4736	printf("    DATA:%08x %08x %08x %08x %08x %08x\n"
4737	    , le32toh(ds->PktPtrArray[0]), le32toh(ds->PktPtrArray[1])
4738	    , le32toh(ds->PktPtrArray[2]), le32toh(ds->PktPtrArray[3])
4739	    , le32toh(ds->PktPtrArray[4]), le32toh(ds->PktPtrArray[5])
4740	);
4741#endif
4742#if 0
4743{ const uint8_t *cp = (const uint8_t *) ds;
4744  int i;
4745  for (i = 0; i < sizeof(struct mwl_txdesc); i++) {
4746	printf("%02x ", cp[i]);
4747	if (((i+1) % 16) == 0)
4748		printf("\n");
4749  }
4750  printf("\n");
4751}
4752#endif
4753}
4754#endif /* MWL_DEBUG */
4755
4756#if 0
4757static void
4758mwl_txq_dump(struct mwl_txq *txq)
4759{
4760	struct mwl_txbuf *bf;
4761	int i = 0;
4762
4763	MWL_TXQ_LOCK(txq);
4764	STAILQ_FOREACH(bf, &txq->active, bf_list) {
4765		struct mwl_txdesc *ds = bf->bf_desc;
4766		MWL_TXDESC_SYNC(txq, ds,
4767		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
4768#ifdef MWL_DEBUG
4769		mwl_printtxbuf(bf, txq->qnum, i);
4770#endif
4771		i++;
4772	}
4773	MWL_TXQ_UNLOCK(txq);
4774}
4775#endif
4776
4777static void
4778mwl_watchdog(void *arg)
4779{
4780	struct mwl_softc *sc;
4781	struct ifnet *ifp;
4782
4783	sc = arg;
4784	callout_reset(&sc->sc_watchdog, hz, mwl_watchdog, sc);
4785	if (sc->sc_tx_timer == 0 || --sc->sc_tx_timer > 0)
4786		return;
4787
4788	ifp = sc->sc_ifp;
4789	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && !sc->sc_invalid) {
4790		if (mwl_hal_setkeepalive(sc->sc_mh))
4791			if_printf(ifp, "transmit timeout (firmware hung?)\n");
4792		else
4793			if_printf(ifp, "transmit timeout\n");
4794#if 0
4795		mwl_reset(ifp);
4796mwl_txq_dump(&sc->sc_txq[0]);/*XXX*/
4797#endif
4798		ifp->if_oerrors++;
4799		sc->sc_stats.mst_watchdog++;
4800	}
4801}
4802
4803#ifdef MWL_DIAGAPI
4804/*
4805 * Diagnostic interface to the HAL.  This is used by various
4806 * tools to do things like retrieve register contents for
4807 * debugging.  The mechanism is intentionally opaque so that
4808 * it can change frequently w/o concern for compatiblity.
4809 */
4810static int
4811mwl_ioctl_diag(struct mwl_softc *sc, struct mwl_diag *md)
4812{
4813	struct mwl_hal *mh = sc->sc_mh;
4814	u_int id = md->md_id & MWL_DIAG_ID;
4815	void *indata = NULL;
4816	void *outdata = NULL;
4817	u_int32_t insize = md->md_in_size;
4818	u_int32_t outsize = md->md_out_size;
4819	int error = 0;
4820
4821	if (md->md_id & MWL_DIAG_IN) {
4822		/*
4823		 * Copy in data.
4824		 */
4825		indata = malloc(insize, M_TEMP, M_NOWAIT);
4826		if (indata == NULL) {
4827			error = ENOMEM;
4828			goto bad;
4829		}
4830		error = copyin(md->md_in_data, indata, insize);
4831		if (error)
4832			goto bad;
4833	}
4834	if (md->md_id & MWL_DIAG_DYN) {
4835		/*
4836		 * Allocate a buffer for the results (otherwise the HAL
4837		 * returns a pointer to a buffer where we can read the
4838		 * results).  Note that we depend on the HAL leaving this
4839		 * pointer for us to use below in reclaiming the buffer;
4840		 * may want to be more defensive.
4841		 */
4842		outdata = malloc(outsize, M_TEMP, M_NOWAIT);
4843		if (outdata == NULL) {
4844			error = ENOMEM;
4845			goto bad;
4846		}
4847	}
4848	if (mwl_hal_getdiagstate(mh, id, indata, insize, &outdata, &outsize)) {
4849		if (outsize < md->md_out_size)
4850			md->md_out_size = outsize;
4851		if (outdata != NULL)
4852			error = copyout(outdata, md->md_out_data,
4853					md->md_out_size);
4854	} else {
4855		error = EINVAL;
4856	}
4857bad:
4858	if ((md->md_id & MWL_DIAG_IN) && indata != NULL)
4859		free(indata, M_TEMP);
4860	if ((md->md_id & MWL_DIAG_DYN) && outdata != NULL)
4861		free(outdata, M_TEMP);
4862	return error;
4863}
4864
4865static int
4866mwl_ioctl_reset(struct mwl_softc *sc, struct mwl_diag *md)
4867{
4868	struct mwl_hal *mh = sc->sc_mh;
4869	int error;
4870
4871	MWL_LOCK_ASSERT(sc);
4872
4873	if (md->md_id == 0 && mwl_hal_fwload(mh, NULL) != 0) {
4874		device_printf(sc->sc_dev, "unable to load firmware\n");
4875		return EIO;
4876	}
4877	if (mwl_hal_gethwspecs(mh, &sc->sc_hwspecs) != 0) {
4878		device_printf(sc->sc_dev, "unable to fetch h/w specs\n");
4879		return EIO;
4880	}
4881	error = mwl_setupdma(sc);
4882	if (error != 0) {
4883		/* NB: mwl_setupdma prints a msg */
4884		return error;
4885	}
4886	/*
4887	 * Reset tx/rx data structures; after reload we must
4888	 * re-start the driver's notion of the next xmit/recv.
4889	 */
4890	mwl_draintxq(sc);		/* clear pending frames */
4891	mwl_resettxq(sc);		/* rebuild tx q lists */
4892	sc->sc_rxnext = NULL;		/* force rx to start at the list head */
4893	return 0;
4894}
4895#endif /* MWL_DIAGAPI */
4896
4897static int
4898mwl_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
4899{
4900#define	IS_RUNNING(ifp) \
4901	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
4902	struct mwl_softc *sc = ifp->if_softc;
4903	struct ieee80211com *ic = ifp->if_l2com;
4904	struct ifreq *ifr = (struct ifreq *)data;
4905	int error = 0, startall;
4906
4907	switch (cmd) {
4908	case SIOCSIFFLAGS:
4909		MWL_LOCK(sc);
4910		startall = 0;
4911		if (IS_RUNNING(ifp)) {
4912			/*
4913			 * To avoid rescanning another access point,
4914			 * do not call mwl_init() here.  Instead,
4915			 * only reflect promisc mode settings.
4916			 */
4917			mwl_mode_init(sc);
4918		} else if (ifp->if_flags & IFF_UP) {
4919			/*
4920			 * Beware of being called during attach/detach
4921			 * to reset promiscuous mode.  In that case we
4922			 * will still be marked UP but not RUNNING.
4923			 * However trying to re-init the interface
4924			 * is the wrong thing to do as we've already
4925			 * torn down much of our state.  There's
4926			 * probably a better way to deal with this.
4927			 */
4928			if (!sc->sc_invalid) {
4929				mwl_init_locked(sc);	/* XXX lose error */
4930				startall = 1;
4931			}
4932		} else
4933			mwl_stop_locked(ifp, 1);
4934		MWL_UNLOCK(sc);
4935		if (startall)
4936			ieee80211_start_all(ic);
4937		break;
4938	case SIOCGMVSTATS:
4939		mwl_hal_gethwstats(sc->sc_mh, &sc->sc_stats.hw_stats);
4940		/* NB: embed these numbers to get a consistent view */
4941		sc->sc_stats.mst_tx_packets = ifp->if_opackets;
4942		sc->sc_stats.mst_rx_packets = ifp->if_ipackets;
4943		/*
4944		 * NB: Drop the softc lock in case of a page fault;
4945		 * we'll accept any potential inconsisentcy in the
4946		 * statistics.  The alternative is to copy the data
4947		 * to a local structure.
4948		 */
4949		return copyout(&sc->sc_stats,
4950				ifr->ifr_data, sizeof (sc->sc_stats));
4951#ifdef MWL_DIAGAPI
4952	case SIOCGMVDIAG:
4953		/* XXX check privs */
4954		return mwl_ioctl_diag(sc, (struct mwl_diag *) ifr);
4955	case SIOCGMVRESET:
4956		/* XXX check privs */
4957		MWL_LOCK(sc);
4958		error = mwl_ioctl_reset(sc,(struct mwl_diag *) ifr);
4959		MWL_UNLOCK(sc);
4960		break;
4961#endif /* MWL_DIAGAPI */
4962	case SIOCGIFMEDIA:
4963		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
4964		break;
4965	case SIOCGIFADDR:
4966		error = ether_ioctl(ifp, cmd, data);
4967		break;
4968	default:
4969		error = EINVAL;
4970		break;
4971	}
4972	return error;
4973#undef IS_RUNNING
4974}
4975
4976#ifdef	MWL_DEBUG
4977static int
4978mwl_sysctl_debug(SYSCTL_HANDLER_ARGS)
4979{
4980	struct mwl_softc *sc = arg1;
4981	int debug, error;
4982
4983	debug = sc->sc_debug | (mwl_hal_getdebug(sc->sc_mh) << 24);
4984	error = sysctl_handle_int(oidp, &debug, 0, req);
4985	if (error || !req->newptr)
4986		return error;
4987	mwl_hal_setdebug(sc->sc_mh, debug >> 24);
4988	sc->sc_debug = debug & 0x00ffffff;
4989	return 0;
4990}
4991#endif /* MWL_DEBUG */
4992
4993static void
4994mwl_sysctlattach(struct mwl_softc *sc)
4995{
4996#ifdef	MWL_DEBUG
4997	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
4998	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
4999
5000	sc->sc_debug = mwl_debug;
5001	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
5002		"debug", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
5003		mwl_sysctl_debug, "I", "control debugging printfs");
5004#endif
5005}
5006
5007/*
5008 * Announce various information on device/driver attach.
5009 */
5010static void
5011mwl_announce(struct mwl_softc *sc)
5012{
5013	struct ifnet *ifp = sc->sc_ifp;
5014
5015	if_printf(ifp, "Rev A%d hardware, v%d.%d.%d.%d firmware (regioncode %d)\n",
5016		sc->sc_hwspecs.hwVersion,
5017		(sc->sc_hwspecs.fwReleaseNumber>>24) & 0xff,
5018		(sc->sc_hwspecs.fwReleaseNumber>>16) & 0xff,
5019		(sc->sc_hwspecs.fwReleaseNumber>>8) & 0xff,
5020		(sc->sc_hwspecs.fwReleaseNumber>>0) & 0xff,
5021		sc->sc_hwspecs.regionCode);
5022	sc->sc_fwrelease = sc->sc_hwspecs.fwReleaseNumber;
5023
5024	if (bootverbose) {
5025		int i;
5026		for (i = 0; i <= WME_AC_VO; i++) {
5027			struct mwl_txq *txq = sc->sc_ac2q[i];
5028			if_printf(ifp, "Use hw queue %u for %s traffic\n",
5029				txq->qnum, ieee80211_wme_acnames[i]);
5030		}
5031	}
5032	if (bootverbose || mwl_rxdesc != MWL_RXDESC)
5033		if_printf(ifp, "using %u rx descriptors\n", mwl_rxdesc);
5034	if (bootverbose || mwl_rxbuf != MWL_RXBUF)
5035		if_printf(ifp, "using %u rx buffers\n", mwl_rxbuf);
5036	if (bootverbose || mwl_txbuf != MWL_TXBUF)
5037		if_printf(ifp, "using %u tx buffers\n", mwl_txbuf);
5038	if (bootverbose && mwl_hal_ismbsscapable(sc->sc_mh))
5039		if_printf(ifp, "multi-bss support\n");
5040#ifdef MWL_TX_NODROP
5041	if (bootverbose)
5042		if_printf(ifp, "no tx drop\n");
5043#endif
5044}
5045