xref: /freebsd/sys/dev/bwn/if_bwn.c (revision 52552d7572a6d3d7d3ce0d6862de9a9d203c5d01)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
5  * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
6  * Copyright (c) 2017 The FreeBSD Foundation
7  * All rights reserved.
8  *
9  * Portions of this software were developed by Landon Fuller
10  * under sponsorship from the FreeBSD Foundation.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
20  *    redistribution must be conditioned upon including a substantially
21  *    similar Disclaimer requirement for further binary redistribution.
22  *
23  * NO WARRANTY
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
27  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
29  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34  * THE POSSIBILITY OF SUCH DAMAGES.
35  */
36 
37 #include <sys/cdefs.h>
38 /*
39  * The Broadcom Wireless LAN controller driver.
40  */
41 
42 #include "opt_bwn.h"
43 #include "opt_wlan.h"
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/gpio.h>
49 #include <sys/malloc.h>
50 #include <sys/module.h>
51 #include <sys/endian.h>
52 #include <sys/errno.h>
53 #include <sys/firmware.h>
54 #include <sys/lock.h>
55 #include <sys/mutex.h>
56 #include <machine/bus.h>
57 #include <machine/resource.h>
58 #include <sys/bus.h>
59 #include <sys/rman.h>
60 #include <sys/socket.h>
61 #include <sys/sockio.h>
62 
63 #include <net/ethernet.h>
64 #include <net/if.h>
65 #include <net/if_var.h>
66 #include <net/if_arp.h>
67 #include <net/if_dl.h>
68 #include <net/if_llc.h>
69 #include <net/if_media.h>
70 #include <net/if_types.h>
71 
72 #include <net80211/ieee80211_var.h>
73 #include <net80211/ieee80211_radiotap.h>
74 #include <net80211/ieee80211_regdomain.h>
75 #include <net80211/ieee80211_phy.h>
76 #include <net80211/ieee80211_ratectl.h>
77 
78 #include <dev/bhnd/bhnd.h>
79 #include <dev/bhnd/bhnd_ids.h>
80 
81 #include <dev/bhnd/cores/chipc/chipc.h>
82 #include <dev/bhnd/cores/pmu/bhnd_pmu.h>
83 
84 #include <dev/bwn/if_bwnreg.h>
85 #include <dev/bwn/if_bwnvar.h>
86 
87 #include <dev/bwn/if_bwn_debug.h>
88 #include <dev/bwn/if_bwn_misc.h>
89 #include <dev/bwn/if_bwn_util.h>
90 #include <dev/bwn/if_bwn_phy_common.h>
91 #include <dev/bwn/if_bwn_phy_g.h>
92 #include <dev/bwn/if_bwn_phy_lp.h>
93 #include <dev/bwn/if_bwn_phy_n.h>
94 
95 #include "bhnd_nvram_map.h"
96 
97 #include "gpio_if.h"
98 
99 static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
100     "Broadcom driver parameters");
101 
102 /*
103  * Tunable & sysctl variables.
104  */
105 
106 #ifdef BWN_DEBUG
107 static	int bwn_debug = 0;
108 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
109     "Broadcom debugging printfs");
110 #endif
111 
112 static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
113 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
114     "uses Bad Frames Preemption");
115 static int	bwn_bluetooth = 1;
116 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
117     "turns on Bluetooth Coexistence");
118 static int	bwn_hwpctl = 0;
119 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
120     "uses H/W power control");
121 static int	bwn_usedma = 1;
122 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
123     "uses DMA");
124 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
125 static int	bwn_wme = 1;
126 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
127     "uses WME support");
128 
129 static void	bwn_attach_pre(struct bwn_softc *);
130 static int	bwn_attach_post(struct bwn_softc *);
131 static int	bwn_retain_bus_providers(struct bwn_softc *sc);
132 static void	bwn_release_bus_providers(struct bwn_softc *sc);
133 static void	bwn_sprom_bugfixes(device_t);
134 static int	bwn_init(struct bwn_softc *);
135 static void	bwn_parent(struct ieee80211com *);
136 static void	bwn_start(struct bwn_softc *);
137 static int	bwn_transmit(struct ieee80211com *, struct mbuf *);
138 static int	bwn_attach_core(struct bwn_mac *);
139 static int	bwn_phy_getinfo(struct bwn_mac *, int);
140 static int	bwn_chiptest(struct bwn_mac *);
141 static int	bwn_setup_channels(struct bwn_mac *, int, int);
142 static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
143 		    uint16_t);
144 static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
145 		    const struct bwn_channelinfo *, const uint8_t []);
146 static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
147 		    const struct ieee80211_bpf_params *);
148 static void	bwn_updateslot(struct ieee80211com *);
149 static void	bwn_update_promisc(struct ieee80211com *);
150 static void	bwn_wme_init(struct bwn_mac *);
151 static int	bwn_wme_update(struct ieee80211com *);
152 static void	bwn_wme_clear(struct bwn_softc *);
153 static void	bwn_wme_load(struct bwn_mac *);
154 static void	bwn_wme_loadparams(struct bwn_mac *,
155 		    const struct wmeParams *, uint16_t);
156 static void	bwn_scan_start(struct ieee80211com *);
157 static void	bwn_scan_end(struct ieee80211com *);
158 static void	bwn_set_channel(struct ieee80211com *);
159 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
160 		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
161 		    const uint8_t [IEEE80211_ADDR_LEN],
162 		    const uint8_t [IEEE80211_ADDR_LEN]);
163 static void	bwn_vap_delete(struct ieee80211vap *);
164 static void	bwn_stop(struct bwn_softc *);
165 static int	bwn_core_forceclk(struct bwn_mac *, bool);
166 static int	bwn_core_init(struct bwn_mac *);
167 static void	bwn_core_start(struct bwn_mac *);
168 static void	bwn_core_exit(struct bwn_mac *);
169 static void	bwn_bt_disable(struct bwn_mac *);
170 static int	bwn_chip_init(struct bwn_mac *);
171 static void	bwn_set_txretry(struct bwn_mac *, int, int);
172 static void	bwn_rate_init(struct bwn_mac *);
173 static void	bwn_set_phytxctl(struct bwn_mac *);
174 static void	bwn_spu_setdelay(struct bwn_mac *, int);
175 static void	bwn_bt_enable(struct bwn_mac *);
176 static void	bwn_set_macaddr(struct bwn_mac *);
177 static void	bwn_crypt_init(struct bwn_mac *);
178 static void	bwn_chip_exit(struct bwn_mac *);
179 static int	bwn_fw_fillinfo(struct bwn_mac *);
180 static int	bwn_fw_loaducode(struct bwn_mac *);
181 static int	bwn_gpio_init(struct bwn_mac *);
182 static int	bwn_fw_loadinitvals(struct bwn_mac *);
183 static int	bwn_phy_init(struct bwn_mac *);
184 static void	bwn_set_txantenna(struct bwn_mac *, int);
185 static void	bwn_set_opmode(struct bwn_mac *);
186 static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
187 static uint8_t	bwn_plcp_getcck(const uint8_t);
188 static uint8_t	bwn_plcp_getofdm(const uint8_t);
189 static void	bwn_pio_init(struct bwn_mac *);
190 static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
191 static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
192 		    int);
193 static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
194 		    struct bwn_pio_rxqueue *, int);
195 static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
196 static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
197 		    uint16_t);
198 static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
199 static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
200 static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
201 static void	bwn_pio_handle_txeof(struct bwn_mac *,
202 		    const struct bwn_txstatus *);
203 static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
204 static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
205 static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
206 		    uint16_t);
207 static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
208 		    uint32_t);
209 static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
210 		    struct mbuf **);
211 static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
212 static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
213 		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
214 static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
215 		    uint16_t, uint32_t);
216 static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
217 		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
218 static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
219 		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
220 static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
221 		    uint16_t, struct bwn_pio_txpkt **);
222 static void	bwn_dma_init(struct bwn_mac *);
223 static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
224 static uint16_t	bwn_dma_base(int, int);
225 static void	bwn_dma_ringfree(struct bwn_dma_ring **);
226 static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
227 		    int, struct bwn_dmadesc_generic **,
228 		    struct bwn_dmadesc_meta **);
229 static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
230 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
231 		    int, int);
232 static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
233 static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
234 static void	bwn_dma_32_resume(struct bwn_dma_ring *);
235 static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
236 static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
237 static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
238 		    int, struct bwn_dmadesc_generic **,
239 		    struct bwn_dmadesc_meta **);
240 static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
241 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
242 		    int, int);
243 static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
244 static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
245 static void	bwn_dma_64_resume(struct bwn_dma_ring *);
246 static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
247 static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
248 static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
249 static void	bwn_dma_setup(struct bwn_dma_ring *);
250 static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
251 static void	bwn_dma_cleanup(struct bwn_dma_ring *);
252 static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
253 static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
254 static void	bwn_dma_rx(struct bwn_dma_ring *);
255 static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
256 static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
257 		    struct bwn_dmadesc_meta *);
258 static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
259 static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
260 static int	bwn_dma_freeslot(struct bwn_dma_ring *);
261 static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
262 static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
263 static int	bwn_dma_newbuf(struct bwn_dma_ring *,
264 		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
265 		    int);
266 static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
267 		    bus_size_t, int);
268 static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
269 static void	bwn_ratectl_tx_complete(const struct ieee80211_node *,
270 		    const struct bwn_txstatus *);
271 static void	bwn_dma_handle_txeof(struct bwn_mac *,
272 		    const struct bwn_txstatus *);
273 static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
274 		    struct mbuf **);
275 static int	bwn_dma_getslot(struct bwn_dma_ring *);
276 static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
277 		    uint8_t);
278 static int	bwn_dma_attach(struct bwn_mac *);
279 static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
280 		    int, int);
281 static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
282 		    const struct bwn_txstatus *, uint16_t, int *);
283 static void	bwn_dma_free(struct bwn_mac *);
284 static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
285 static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
286 		    const char *, struct bwn_fwfile *);
287 static void	bwn_release_firmware(struct bwn_mac *);
288 static void	bwn_do_release_fw(struct bwn_fwfile *);
289 static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
290 static int	bwn_fwinitvals_write(struct bwn_mac *,
291 		    const struct bwn_fwinitvals *, size_t, size_t);
292 static uint16_t	bwn_ant2phy(int);
293 static void	bwn_mac_write_bssid(struct bwn_mac *);
294 static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
295 		    const uint8_t *);
296 static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
297 		    const uint8_t *, size_t, const uint8_t *);
298 static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
299 		    const uint8_t *);
300 static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
301 		    const uint8_t *);
302 static void	bwn_phy_exit(struct bwn_mac *);
303 static void	bwn_core_stop(struct bwn_mac *);
304 static int	bwn_switch_band(struct bwn_softc *,
305 		    struct ieee80211_channel *);
306 static int	bwn_phy_reset(struct bwn_mac *);
307 static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
308 static void	bwn_set_pretbtt(struct bwn_mac *);
309 static int	bwn_intr(void *);
310 static void	bwn_intrtask(void *, int);
311 static void	bwn_restart(struct bwn_mac *, const char *);
312 static void	bwn_intr_ucode_debug(struct bwn_mac *);
313 static void	bwn_intr_tbtt_indication(struct bwn_mac *);
314 static void	bwn_intr_atim_end(struct bwn_mac *);
315 static void	bwn_intr_beacon(struct bwn_mac *);
316 static void	bwn_intr_pmq(struct bwn_mac *);
317 static void	bwn_intr_noise(struct bwn_mac *);
318 static void	bwn_intr_txeof(struct bwn_mac *);
319 static void	bwn_hwreset(void *, int);
320 static void	bwn_handle_fwpanic(struct bwn_mac *);
321 static void	bwn_load_beacon0(struct bwn_mac *);
322 static void	bwn_load_beacon1(struct bwn_mac *);
323 static uint32_t	bwn_jssi_read(struct bwn_mac *);
324 static void	bwn_noise_gensample(struct bwn_mac *);
325 static void	bwn_handle_txeof(struct bwn_mac *,
326 		    const struct bwn_txstatus *);
327 static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
328 static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
329 static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
330 		    struct mbuf *);
331 static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
332 static int	bwn_set_txhdr(struct bwn_mac *,
333 		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
334 		    uint16_t);
335 static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
336 		    const uint8_t);
337 static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
338 static uint8_t	bwn_get_fbrate(uint8_t);
339 static void	bwn_txpwr(void *, int);
340 static void	bwn_tasks(void *);
341 static void	bwn_task_15s(struct bwn_mac *);
342 static void	bwn_task_30s(struct bwn_mac *);
343 static void	bwn_task_60s(struct bwn_mac *);
344 static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
345 		    uint8_t);
346 static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
347 static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
348 		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
349 		    int, int);
350 static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
351 static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
352 static void	bwn_watchdog(void *);
353 static void	bwn_dma_stop(struct bwn_mac *);
354 static void	bwn_pio_stop(struct bwn_mac *);
355 static void	bwn_dma_ringstop(struct bwn_dma_ring **);
356 static int	bwn_led_attach(struct bwn_mac *);
357 static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
358 static void	bwn_led_event(struct bwn_mac *, int);
359 static void	bwn_led_blink_start(struct bwn_mac *, int, int);
360 static void	bwn_led_blink_next(void *);
361 static void	bwn_led_blink_end(void *);
362 static void	bwn_rfswitch(void *);
363 static void	bwn_rf_turnon(struct bwn_mac *);
364 static void	bwn_rf_turnoff(struct bwn_mac *);
365 static void	bwn_sysctl_node(struct bwn_softc *);
366 
367 static const struct bwn_channelinfo bwn_chantable_bg = {
368 	.channels = {
369 		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
370 		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
371 		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
372 		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
373 		{ 2472, 13, 30 }, { 2484, 14, 30 } },
374 	.nchannels = 14
375 };
376 
377 static const struct bwn_channelinfo bwn_chantable_a = {
378 	.channels = {
379 		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
380 		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
381 		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
382 		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
383 		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
384 		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
385 		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
386 		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
387 		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
388 		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
389 		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
390 		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
391 		{ 6080, 216, 30 } },
392 	.nchannels = 37
393 };
394 
395 #if 0
396 static const struct bwn_channelinfo bwn_chantable_n = {
397 	.channels = {
398 		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
399 		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
400 		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
401 		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
402 		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
403 		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
404 		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
405 		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
406 		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
407 		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
408 		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
409 		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
410 		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
411 		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
412 		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
413 		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
414 		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
415 		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
416 		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
417 		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
418 		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
419 		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
420 		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
421 		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
422 		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
423 		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
424 		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
425 		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
426 		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
427 		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
428 		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
429 		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
430 		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
431 		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
432 		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
433 		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
434 		{ 6130, 226, 30 }, { 6140, 228, 30 } },
435 	.nchannels = 110
436 };
437 #endif
438 
439 #define	VENDOR_LED_ACT(vendor)				\
440 {							\
441 	.vid = PCI_VENDOR_##vendor,			\
442 	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
443 }
444 
445 static const struct {
446 	uint16_t	vid;
447 	uint8_t		led_act[BWN_LED_MAX];
448 } bwn_vendor_led_act[] = {
449 	VENDOR_LED_ACT(HP_COMPAQ),
450 	VENDOR_LED_ACT(ASUSTEK)
451 };
452 
453 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
454 	{ BWN_VENDOR_LED_ACT_DEFAULT };
455 
456 #undef VENDOR_LED_ACT
457 
458 static const char *bwn_led_vars[] = {
459 	BHND_NVAR_LEDBH0,
460 	BHND_NVAR_LEDBH1,
461 	BHND_NVAR_LEDBH2,
462 	BHND_NVAR_LEDBH3
463 };
464 
465 static const struct {
466 	int		on_dur;
467 	int		off_dur;
468 } bwn_led_duration[109] = {
469 	[0]	= { 400, 100 },
470 	[2]	= { 150, 75 },
471 	[4]	= { 90, 45 },
472 	[11]	= { 66, 34 },
473 	[12]	= { 53, 26 },
474 	[18]	= { 42, 21 },
475 	[22]	= { 35, 17 },
476 	[24]	= { 32, 16 },
477 	[36]	= { 21, 10 },
478 	[48]	= { 16, 8 },
479 	[72]	= { 11, 5 },
480 	[96]	= { 9, 4 },
481 	[108]	= { 7, 3 }
482 };
483 
484 static const uint16_t bwn_wme_shm_offsets[] = {
485 	[0] = BWN_WME_BESTEFFORT,
486 	[1] = BWN_WME_BACKGROUND,
487 	[2] = BWN_WME_VOICE,
488 	[3] = BWN_WME_VIDEO,
489 };
490 
491 /* Supported D11 core revisions */
492 #define	BWN_DEV(_hwrev)	{{					\
493 	BHND_MATCH_CORE(BHND_MFGID_BCM, BHND_COREID_D11),	\
494 	BHND_MATCH_CORE_REV(_hwrev),				\
495 }}
496 static const struct bhnd_device bwn_devices[] = {
497 	BWN_DEV(HWREV_RANGE(5, 16)),
498 	BWN_DEV(HWREV_EQ(23)),
499 	BHND_DEVICE_END
500 };
501 
502 /* D11 quirks when bridged via a PCI host bridge core */
503 static const struct bhnd_device_quirk pci_bridge_quirks[] = {
504 	BHND_CORE_QUIRK	(HWREV_LTE(10),	BWN_QUIRK_UCODE_SLOWCLOCK_WAR),
505 	BHND_DEVICE_QUIRK_END
506 };
507 
508 /* D11 quirks when bridged via a PCMCIA host bridge core */
509 static const struct bhnd_device_quirk pcmcia_bridge_quirks[] = {
510 	BHND_CORE_QUIRK	(HWREV_ANY,	BWN_QUIRK_NODMA),
511 	BHND_DEVICE_QUIRK_END
512 };
513 
514 /* Host bridge cores for which D11 quirk flags should be applied */
515 static const struct bhnd_device bridge_devices[] = {
516 	BHND_DEVICE(BCM, PCI,		NULL, pci_bridge_quirks),
517 	BHND_DEVICE(BCM, PCMCIA,	NULL, pcmcia_bridge_quirks),
518 	BHND_DEVICE_END
519 };
520 
521 static int
522 bwn_probe(device_t dev)
523 {
524 	const struct bhnd_device *id;
525 
526 	id = bhnd_device_lookup(dev, bwn_devices, sizeof(bwn_devices[0]));
527 	if (id == NULL)
528 		return (ENXIO);
529 
530 	bhnd_set_default_core_desc(dev);
531 	return (BUS_PROBE_DEFAULT);
532 }
533 
534 static int
535 bwn_attach(device_t dev)
536 {
537 	struct bwn_mac		*mac;
538 	struct bwn_softc	*sc;
539 	device_t		 parent, hostb;
540 	char			 chip_name[BHND_CHIPID_MAX_NAMELEN];
541 	int			 error;
542 
543 	sc = device_get_softc(dev);
544 	sc->sc_dev = dev;
545 #ifdef BWN_DEBUG
546 	sc->sc_debug = bwn_debug;
547 #endif
548 
549 	mac = NULL;
550 
551 	/* Determine the driver quirks applicable to this device, including any
552 	 * quirks specific to the bus host bridge core (if any) */
553 	sc->sc_quirks = bhnd_device_quirks(dev, bwn_devices,
554 	    sizeof(bwn_devices[0]));
555 
556 	parent = device_get_parent(dev);
557 	if ((hostb = bhnd_bus_find_hostb_device(parent)) != NULL) {
558 		sc->sc_quirks |= bhnd_device_quirks(hostb, bridge_devices,
559 		    sizeof(bridge_devices[0]));
560 	}
561 
562 	/* DMA explicitly disabled? */
563 	if (!bwn_usedma)
564 		sc->sc_quirks |= BWN_QUIRK_NODMA;
565 
566 	/* Fetch our chip identification and board info */
567 	sc->sc_cid = *bhnd_get_chipid(dev);
568 	if ((error = bhnd_read_board_info(dev, &sc->sc_board_info))) {
569 		device_printf(sc->sc_dev, "couldn't read board info\n");
570 		return (error);
571 	}
572 
573 	/* Allocate our D11 register block and PMU state */
574 	sc->sc_mem_rid = 0;
575 	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
576 	    &sc->sc_mem_rid, RF_ACTIVE);
577 	if (sc->sc_mem_res == NULL) {
578 		device_printf(sc->sc_dev, "couldn't allocate registers\n");
579 		return (error);
580 	}
581 
582 	if ((error = bhnd_alloc_pmu(sc->sc_dev))) {
583 		bus_release_resource(sc->sc_dev, SYS_RES_MEMORY,
584 		    sc->sc_mem_rid, sc->sc_mem_res);
585 		return (error);
586 	}
587 
588 	/* Retain references to all required bus service providers */
589 	if ((error = bwn_retain_bus_providers(sc)))
590 		goto fail;
591 
592 	/* Fetch mask of available antennas */
593 	error = bhnd_nvram_getvar_uint8(sc->sc_dev, BHND_NVAR_AA2G,
594 	    &sc->sc_ant2g);
595 	if (error) {
596 		device_printf(sc->sc_dev, "error determining 2GHz antenna "
597 		    "availability from NVRAM: %d\n", error);
598 		goto fail;
599 	}
600 
601 	error = bhnd_nvram_getvar_uint8(sc->sc_dev, BHND_NVAR_AA5G,
602 	    &sc->sc_ant5g);
603 	if (error) {
604 		device_printf(sc->sc_dev, "error determining 5GHz antenna "
605 		    "availability from NVRAM: %d\n", error);
606 		goto fail;
607 	}
608 
609 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
610 		bwn_attach_pre(sc);
611 		bwn_sprom_bugfixes(dev);
612 		sc->sc_flags |= BWN_FLAG_ATTACHED;
613 	}
614 
615 	mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO);
616 	mac->mac_sc = sc;
617 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
618 	if (bwn_bfp != 0)
619 		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
620 
621 	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
622 	NET_TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
623 	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
624 
625 	error = bwn_attach_core(mac);
626 	if (error)
627 		goto fail;
628 	error = bwn_led_attach(mac);
629 	if (error)
630 		goto fail;
631 
632 	bhnd_format_chip_id(chip_name, sizeof(chip_name), sc->sc_cid.chip_id);
633 	device_printf(sc->sc_dev, "WLAN (%s rev %u sromrev %u) "
634 	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
635 	    chip_name, bhnd_get_hwrev(sc->sc_dev),
636 	    sc->sc_board_info.board_srom_rev, mac->mac_phy.analog,
637 	    mac->mac_phy.type, mac->mac_phy.rev, mac->mac_phy.rf_manuf,
638 	    mac->mac_phy.rf_ver, mac->mac_phy.rf_rev);
639 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
640 		device_printf(sc->sc_dev, "DMA (%d bits)\n", mac->mac_dmatype);
641 	else
642 		device_printf(sc->sc_dev, "PIO\n");
643 
644 #ifdef	BWN_GPL_PHY
645 	device_printf(sc->sc_dev,
646 	    "Note: compiled with BWN_GPL_PHY; includes GPLv2 code\n");
647 #endif
648 
649 	mac->mac_rid_irq = 0;
650 	mac->mac_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
651 	    &mac->mac_rid_irq, RF_ACTIVE | RF_SHAREABLE);
652 
653 	if (mac->mac_res_irq == NULL) {
654 		device_printf(sc->sc_dev, "couldn't allocate IRQ resource\n");
655 		error = ENXIO;
656 		goto fail;
657 	}
658 
659 	error = bus_setup_intr(dev, mac->mac_res_irq,
660 	    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
661 	    &mac->mac_intrhand);
662 	if (error != 0) {
663 		device_printf(sc->sc_dev, "couldn't setup interrupt (%d)\n",
664 		    error);
665 		goto fail;
666 	}
667 
668 	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
669 
670 	/*
671 	 * calls attach-post routine
672 	 */
673 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
674 		bwn_attach_post(sc);
675 
676 	return (0);
677 fail:
678 	if (mac != NULL && mac->mac_res_irq != NULL) {
679 		bus_release_resource(dev, SYS_RES_IRQ, mac->mac_rid_irq,
680 		    mac->mac_res_irq);
681 	}
682 
683 	free(mac, M_DEVBUF);
684 	bhnd_release_pmu(dev);
685 	bwn_release_bus_providers(sc);
686 
687 	if (sc->sc_mem_res != NULL) {
688 		bus_release_resource(sc->sc_dev, SYS_RES_MEMORY,
689 		    sc->sc_mem_rid, sc->sc_mem_res);
690 	}
691 
692 	return (error);
693 }
694 
695 static int
696 bwn_retain_bus_providers(struct bwn_softc *sc)
697 {
698 	struct chipc_caps *ccaps;
699 
700 	sc->sc_chipc = bhnd_retain_provider(sc->sc_dev, BHND_SERVICE_CHIPC);
701 	if (sc->sc_chipc == NULL) {
702 		device_printf(sc->sc_dev, "ChipCommon device not found\n");
703 		goto failed;
704 	}
705 
706 	ccaps = BHND_CHIPC_GET_CAPS(sc->sc_chipc);
707 
708 	sc->sc_gpio = bhnd_retain_provider(sc->sc_dev, BHND_SERVICE_GPIO);
709 	if (sc->sc_gpio == NULL) {
710 		device_printf(sc->sc_dev, "GPIO device not found\n");
711 		goto failed;
712 	}
713 
714 	if (ccaps->pmu) {
715 		sc->sc_pmu = bhnd_retain_provider(sc->sc_dev, BHND_SERVICE_PMU);
716 		if (sc->sc_pmu == NULL) {
717 			device_printf(sc->sc_dev, "PMU device not found\n");
718 			goto failed;
719 		}
720 	}
721 
722 	return (0);
723 
724 failed:
725 	bwn_release_bus_providers(sc);
726 	return (ENXIO);
727 }
728 
729 static void
730 bwn_release_bus_providers(struct bwn_softc *sc)
731 {
732 #define	BWN_RELEASE_PROV(_sc, _prov, _service)	do {			\
733 	if ((_sc)-> _prov != NULL) {					\
734 		bhnd_release_provider((_sc)->sc_dev, (_sc)-> _prov,	\
735 		    (_service));					\
736 		(_sc)-> _prov = NULL;					\
737 	}								\
738 } while (0)
739 
740 	BWN_RELEASE_PROV(sc, sc_chipc, BHND_SERVICE_CHIPC);
741 	BWN_RELEASE_PROV(sc, sc_gpio, BHND_SERVICE_GPIO);
742 	BWN_RELEASE_PROV(sc, sc_pmu, BHND_SERVICE_PMU);
743 
744 #undef	BWN_RELEASE_PROV
745 }
746 
747 static int
748 bwn_attach_post(struct bwn_softc *sc)
749 {
750 	struct ieee80211com	*ic;
751 	const char		*mac_varname;
752 	u_int			 core_unit;
753 	int			 error;
754 
755 	ic = &sc->sc_ic;
756 
757 	ic->ic_softc = sc;
758 	ic->ic_name = device_get_nameunit(sc->sc_dev);
759 	/* XXX not right but it's not used anywhere important */
760 	ic->ic_phytype = IEEE80211_T_OFDM;
761 	ic->ic_opmode = IEEE80211_M_STA;
762 	ic->ic_caps =
763 		  IEEE80211_C_STA		/* station mode supported */
764 		| IEEE80211_C_MONITOR		/* monitor mode */
765 		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
766 		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
767 		| IEEE80211_C_SHSLOT		/* short slot time supported */
768 		| IEEE80211_C_WME		/* WME/WMM supported */
769 		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
770 #if 0
771 		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
772 #endif
773 		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
774 		;
775 
776 	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
777 
778 	/* Determine the NVRAM variable containing our MAC address */
779 	core_unit = bhnd_get_core_unit(sc->sc_dev);
780 	mac_varname = NULL;
781 	if (sc->sc_board_info.board_srom_rev <= 2) {
782 		if (core_unit == 0) {
783 			mac_varname = BHND_NVAR_IL0MACADDR;
784 		} else if (core_unit == 1) {
785 			mac_varname = BHND_NVAR_ET1MACADDR;
786 		}
787 	} else {
788 		if (core_unit == 0) {
789 			mac_varname = BHND_NVAR_MACADDR;
790 		}
791 	}
792 
793 	if (mac_varname == NULL) {
794 		device_printf(sc->sc_dev, "missing MAC address variable for "
795 		    "D11 core %u", core_unit);
796 		return (ENXIO);
797 	}
798 
799 	/* Read the MAC address from NVRAM */
800 	error = bhnd_nvram_getvar_array(sc->sc_dev, mac_varname, ic->ic_macaddr,
801 	    sizeof(ic->ic_macaddr), BHND_NVRAM_TYPE_UINT8_ARRAY);
802 	if (error) {
803 		device_printf(sc->sc_dev, "error reading %s: %d\n", mac_varname,
804 		    error);
805 		return (error);
806 	}
807 
808 	/* call MI attach routine. */
809 	ieee80211_ifattach(ic);
810 
811 	/* override default methods */
812 	ic->ic_raw_xmit = bwn_raw_xmit;
813 	ic->ic_updateslot = bwn_updateslot;
814 	ic->ic_update_promisc = bwn_update_promisc;
815 	ic->ic_wme.wme_update = bwn_wme_update;
816 	ic->ic_scan_start = bwn_scan_start;
817 	ic->ic_scan_end = bwn_scan_end;
818 	ic->ic_set_channel = bwn_set_channel;
819 	ic->ic_vap_create = bwn_vap_create;
820 	ic->ic_vap_delete = bwn_vap_delete;
821 	ic->ic_transmit = bwn_transmit;
822 	ic->ic_parent = bwn_parent;
823 
824 	ieee80211_radiotap_attach(ic,
825 	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
826 	    BWN_TX_RADIOTAP_PRESENT,
827 	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
828 	    BWN_RX_RADIOTAP_PRESENT);
829 
830 	bwn_sysctl_node(sc);
831 
832 	if (bootverbose)
833 		ieee80211_announce(ic);
834 	return (0);
835 }
836 
837 static void
838 bwn_phy_detach(struct bwn_mac *mac)
839 {
840 
841 	if (mac->mac_phy.detach != NULL)
842 		mac->mac_phy.detach(mac);
843 }
844 
845 static int
846 bwn_detach(device_t dev)
847 {
848 	struct bwn_softc *sc = device_get_softc(dev);
849 	struct bwn_mac *mac = sc->sc_curmac;
850 	struct ieee80211com *ic = &sc->sc_ic;
851 
852 	sc->sc_flags |= BWN_FLAG_INVALID;
853 
854 	if (device_is_attached(sc->sc_dev)) {
855 		BWN_LOCK(sc);
856 		bwn_stop(sc);
857 		BWN_UNLOCK(sc);
858 		bwn_dma_free(mac);
859 		callout_drain(&sc->sc_led_blink_ch);
860 		callout_drain(&sc->sc_rfswitch_ch);
861 		callout_drain(&sc->sc_task_ch);
862 		callout_drain(&sc->sc_watchdog_ch);
863 		bwn_phy_detach(mac);
864 		ieee80211_draintask(ic, &mac->mac_hwreset);
865 		ieee80211_draintask(ic, &mac->mac_txpower);
866 		ieee80211_ifdetach(ic);
867 	}
868 	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
869 	taskqueue_free(sc->sc_tq);
870 
871 	if (mac->mac_intrhand != NULL) {
872 		bus_teardown_intr(dev, mac->mac_res_irq, mac->mac_intrhand);
873 		mac->mac_intrhand = NULL;
874 	}
875 
876 	bhnd_release_pmu(dev);
877 	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid,
878 	    sc->sc_mem_res);
879 	bus_release_resource(dev, SYS_RES_IRQ, mac->mac_rid_irq,
880 	    mac->mac_res_irq);
881 	mbufq_drain(&sc->sc_snd);
882 	bwn_release_firmware(mac);
883 	BWN_LOCK_DESTROY(sc);
884 
885 	bwn_release_bus_providers(sc);
886 
887 	return (0);
888 }
889 
890 static void
891 bwn_attach_pre(struct bwn_softc *sc)
892 {
893 
894 	BWN_LOCK_INIT(sc);
895 	TAILQ_INIT(&sc->sc_maclist);
896 	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
897 	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
898 	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
899 	mbufq_init(&sc->sc_snd, ifqmaxlen);
900 	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
901 		taskqueue_thread_enqueue, &sc->sc_tq);
902 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
903 		"%s taskq", device_get_nameunit(sc->sc_dev));
904 }
905 
906 static void
907 bwn_sprom_bugfixes(device_t dev)
908 {
909 	struct bwn_softc *sc = device_get_softc(dev);
910 
911 #define	BWN_ISDEV(_device, _subvendor, _subdevice)		\
912 	((sc->sc_board_info.board_devid == PCI_DEVID_##_device) &&	\
913 	 (sc->sc_board_info.board_vendor == PCI_VENDOR_##_subvendor) &&	\
914 	 (sc->sc_board_info.board_type == _subdevice))
915 
916 	 /* A subset of Apple Airport Extreme (BCM4306 rev 2) devices
917 	  * were programmed with a missing PACTRL boardflag */
918 	 if (sc->sc_board_info.board_vendor == PCI_VENDOR_APPLE &&
919 	     sc->sc_board_info.board_type == 0x4e &&
920 	     sc->sc_board_info.board_rev > 0x40)
921 		 sc->sc_board_info.board_flags |= BHND_BFL_PACTRL;
922 
923 	if (BWN_ISDEV(BCM4318_D11G, ASUSTEK, 0x100f) ||
924 	    BWN_ISDEV(BCM4306_D11G, DELL, 0x0003) ||
925 	    BWN_ISDEV(BCM4306_D11G, HP, 0x12f8) ||
926 	    BWN_ISDEV(BCM4306_D11G, LINKSYS, 0x0013) ||
927 	    BWN_ISDEV(BCM4306_D11G, LINKSYS, 0x0014) ||
928 	    BWN_ISDEV(BCM4306_D11G, LINKSYS, 0x0015) ||
929 	    BWN_ISDEV(BCM4306_D11G, MOTOROLA, 0x7010))
930 		sc->sc_board_info.board_flags &= ~BHND_BFL_BTCOEX;
931 #undef	BWN_ISDEV
932 }
933 
934 static void
935 bwn_parent(struct ieee80211com *ic)
936 {
937 	struct bwn_softc *sc = ic->ic_softc;
938 	int startall = 0;
939 
940 	BWN_LOCK(sc);
941 	if (ic->ic_nrunning > 0) {
942 		if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
943 			bwn_init(sc);
944 			startall = 1;
945 		} else
946 			bwn_update_promisc(ic);
947 	} else if (sc->sc_flags & BWN_FLAG_RUNNING)
948 		bwn_stop(sc);
949 	BWN_UNLOCK(sc);
950 
951 	if (startall)
952 		ieee80211_start_all(ic);
953 }
954 
955 static int
956 bwn_transmit(struct ieee80211com *ic, struct mbuf *m)
957 {
958 	struct bwn_softc *sc = ic->ic_softc;
959 	int error;
960 
961 	BWN_LOCK(sc);
962 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
963 		BWN_UNLOCK(sc);
964 		return (ENXIO);
965 	}
966 	error = mbufq_enqueue(&sc->sc_snd, m);
967 	if (error) {
968 		BWN_UNLOCK(sc);
969 		return (error);
970 	}
971 	bwn_start(sc);
972 	BWN_UNLOCK(sc);
973 	return (0);
974 }
975 
976 static void
977 bwn_start(struct bwn_softc *sc)
978 {
979 	struct bwn_mac *mac = sc->sc_curmac;
980 	struct ieee80211_frame *wh;
981 	struct ieee80211_node *ni;
982 	struct ieee80211_key *k;
983 	struct mbuf *m;
984 
985 	BWN_ASSERT_LOCKED(sc);
986 
987 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL ||
988 	    mac->mac_status < BWN_MAC_STATUS_STARTED)
989 		return;
990 
991 	while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
992 		if (bwn_tx_isfull(sc, m))
993 			break;
994 		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
995 		if (ni == NULL) {
996 			device_printf(sc->sc_dev, "unexpected NULL ni\n");
997 			m_freem(m);
998 			counter_u64_add(sc->sc_ic.ic_oerrors, 1);
999 			continue;
1000 		}
1001 		wh = mtod(m, struct ieee80211_frame *);
1002 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1003 			k = ieee80211_crypto_encap(ni, m);
1004 			if (k == NULL) {
1005 				if_inc_counter(ni->ni_vap->iv_ifp,
1006 				    IFCOUNTER_OERRORS, 1);
1007 				ieee80211_free_node(ni);
1008 				m_freem(m);
1009 				continue;
1010 			}
1011 		}
1012 		wh = NULL;	/* Catch any invalid use */
1013 		if (bwn_tx_start(sc, ni, m) != 0) {
1014 			if (ni != NULL) {
1015 				if_inc_counter(ni->ni_vap->iv_ifp,
1016 				    IFCOUNTER_OERRORS, 1);
1017 				ieee80211_free_node(ni);
1018 			}
1019 			continue;
1020 		}
1021 		sc->sc_watchdog_timer = 5;
1022 	}
1023 }
1024 
1025 static int
1026 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1027 {
1028 	struct bwn_dma_ring *dr;
1029 	struct bwn_mac *mac = sc->sc_curmac;
1030 	struct bwn_pio_txqueue *tq;
1031 	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1032 
1033 	BWN_ASSERT_LOCKED(sc);
1034 
1035 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1036 		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1037 		if (dr->dr_stop == 1 ||
1038 		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1039 			dr->dr_stop = 1;
1040 			goto full;
1041 		}
1042 	} else {
1043 		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1044 		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1045 		    pktlen > (tq->tq_size - tq->tq_used))
1046 			goto full;
1047 	}
1048 	return (0);
1049 full:
1050 	mbufq_prepend(&sc->sc_snd, m);
1051 	return (1);
1052 }
1053 
1054 static int
1055 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1056 {
1057 	struct bwn_mac *mac = sc->sc_curmac;
1058 	int error;
1059 
1060 	BWN_ASSERT_LOCKED(sc);
1061 
1062 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1063 		m_freem(m);
1064 		return (ENXIO);
1065 	}
1066 
1067 	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1068 	    bwn_dma_tx_start(mac, ni, &m) : bwn_pio_tx_start(mac, ni, &m);
1069 	if (error) {
1070 		m_freem(m);
1071 		return (error);
1072 	}
1073 	return (0);
1074 }
1075 
1076 static int
1077 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni,
1078     struct mbuf **mp)
1079 {
1080 	struct bwn_pio_txpkt *tp;
1081 	struct bwn_pio_txqueue *tq;
1082 	struct bwn_softc *sc = mac->mac_sc;
1083 	struct bwn_txhdr txhdr;
1084 	struct mbuf *m, *m_new;
1085 	uint32_t ctl32;
1086 	int error;
1087 	uint16_t ctl16;
1088 
1089 	BWN_ASSERT_LOCKED(sc);
1090 
1091 	/* XXX TODO send packets after DTIM */
1092 
1093 	m = *mp;
1094 	tq = bwn_pio_select(mac, M_WME_GETAC(m));
1095 	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1096 	tp = TAILQ_FIRST(&tq->tq_pktlist);
1097 	tp->tp_ni = ni;
1098 	tp->tp_m = m;
1099 
1100 	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1101 	if (error) {
1102 		device_printf(sc->sc_dev, "tx fail\n");
1103 		return (error);
1104 	}
1105 
1106 	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1107 	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1108 	tq->tq_free--;
1109 
1110 	if (bhnd_get_hwrev(sc->sc_dev) >= 8) {
1111 		/*
1112 		 * XXX please removes m_defrag(9)
1113 		 */
1114 		m_new = m_defrag(*mp, M_NOWAIT);
1115 		if (m_new == NULL) {
1116 			device_printf(sc->sc_dev,
1117 			    "%s: can't defrag TX buffer\n",
1118 			    __func__);
1119 			return (ENOBUFS);
1120 		}
1121 		*mp = m_new;
1122 		if (m_new->m_next != NULL)
1123 			device_printf(sc->sc_dev,
1124 			    "TODO: fragmented packets for PIO\n");
1125 		tp->tp_m = m_new;
1126 
1127 		/* send HEADER */
1128 		ctl32 = bwn_pio_write_multi_4(mac, tq,
1129 		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1130 			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1131 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1132 		/* send BODY */
1133 		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1134 		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1135 		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1136 		    ctl32 | BWN_PIO8_TXCTL_EOF);
1137 	} else {
1138 		ctl16 = bwn_pio_write_multi_2(mac, tq,
1139 		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1140 			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1141 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1142 		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1143 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1144 		    ctl16 | BWN_PIO_TXCTL_EOF);
1145 	}
1146 
1147 	return (0);
1148 }
1149 
1150 static struct bwn_pio_txqueue *
1151 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1152 {
1153 
1154 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1155 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1156 
1157 	switch (prio) {
1158 	case 0:
1159 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1160 	case 1:
1161 		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1162 	case 2:
1163 		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1164 	case 3:
1165 		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1166 	}
1167 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1168 	return (NULL);
1169 }
1170 
1171 static int
1172 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni,
1173     struct mbuf **mp)
1174 {
1175 #define	BWN_GET_TXHDRCACHE(slot)					\
1176 	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1177 	struct bwn_dma *dma = &mac->mac_method.dma;
1178 	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(*mp));
1179 	struct bwn_dmadesc_generic *desc;
1180 	struct bwn_dmadesc_meta *mt;
1181 	struct bwn_softc *sc = mac->mac_sc;
1182 	struct mbuf *m;
1183 	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1184 	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1185 
1186 	BWN_ASSERT_LOCKED(sc);
1187 	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1188 
1189 	/* XXX send after DTIM */
1190 
1191 	m = *mp;
1192 	slot = bwn_dma_getslot(dr);
1193 	dr->getdesc(dr, slot, &desc, &mt);
1194 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1195 	    ("%s:%d: fail", __func__, __LINE__));
1196 
1197 	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1198 	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1199 	    BWN_DMA_COOKIE(dr, slot));
1200 	if (error)
1201 		goto fail;
1202 	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1203 	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1204 	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1205 	if (error) {
1206 		device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1207 		    __func__, error);
1208 		goto fail;
1209 	}
1210 	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1211 	    BUS_DMASYNC_PREWRITE);
1212 	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1213 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1214 	    BUS_DMASYNC_PREWRITE);
1215 
1216 	slot = bwn_dma_getslot(dr);
1217 	dr->getdesc(dr, slot, &desc, &mt);
1218 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1219 	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1220 	mt->mt_m = m;
1221 	mt->mt_ni = ni;
1222 
1223 	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1224 	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1225 	if (error && error != EFBIG) {
1226 		device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1227 		    __func__, error);
1228 		goto fail;
1229 	}
1230 	if (error) {    /* error == EFBIG */
1231 		struct mbuf *m_new;
1232 
1233 		m_new = m_defrag(m, M_NOWAIT);
1234 		if (m_new == NULL) {
1235 			device_printf(sc->sc_dev,
1236 			    "%s: can't defrag TX buffer\n",
1237 			    __func__);
1238 			error = ENOBUFS;
1239 			goto fail;
1240 		}
1241 		*mp = m = m_new;
1242 
1243 		mt->mt_m = m;
1244 		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1245 		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1246 		if (error) {
1247 			device_printf(sc->sc_dev,
1248 			    "%s: can't load TX buffer (2) %d\n",
1249 			    __func__, error);
1250 			goto fail;
1251 		}
1252 	}
1253 	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1254 	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1255 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1256 	    BUS_DMASYNC_PREWRITE);
1257 
1258 	/* XXX send after DTIM */
1259 
1260 	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1261 	return (0);
1262 fail:
1263 	dr->dr_curslot = backup[0];
1264 	dr->dr_usedslot = backup[1];
1265 	return (error);
1266 #undef BWN_GET_TXHDRCACHE
1267 }
1268 
1269 static void
1270 bwn_watchdog(void *arg)
1271 {
1272 	struct bwn_softc *sc = arg;
1273 
1274 	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1275 		device_printf(sc->sc_dev, "device timeout\n");
1276 		counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1277 	}
1278 	callout_schedule(&sc->sc_watchdog_ch, hz);
1279 }
1280 
1281 static int
1282 bwn_attach_core(struct bwn_mac *mac)
1283 {
1284 	struct bwn_softc *sc = mac->mac_sc;
1285 	int error, have_bg = 0, have_a = 0;
1286 	uint16_t iost;
1287 
1288 	KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 5,
1289 	    ("unsupported revision %d", bhnd_get_hwrev(sc->sc_dev)));
1290 
1291 	if ((error = bwn_core_forceclk(mac, true)))
1292 		return (error);
1293 
1294 	if ((error = bhnd_read_iost(sc->sc_dev, &iost))) {
1295 		device_printf(sc->sc_dev, "error reading I/O status flags: "
1296 		    "%d\n", error);
1297 		return (error);
1298 	}
1299 
1300 	have_a = (iost & BWN_IOST_HAVE_5GHZ) ? 1 : 0;
1301 	have_bg = (iost & BWN_IOST_HAVE_2GHZ) ? 1 : 0;
1302 	if (iost & BWN_IOST_DUALPHY) {
1303 		have_bg = 1;
1304 		have_a = 1;
1305 	}
1306 
1307 #if 0
1308 	device_printf(sc->sc_dev, "%s: iost=0x%04hx, have_a=%d, have_bg=%d,"
1309 	    " deviceid=0x%04x, siba_deviceid=0x%04x\n",
1310 	    __func__,
1311 	    iost,
1312 	    have_a,
1313 	    have_bg,
1314 	    sc->sc_board_info.board_devid,
1315 	    sc->sc_cid.chip_id);
1316 #endif
1317 
1318 	/*
1319 	 * Guess at whether it has A-PHY or G-PHY.
1320 	 * This is just used for resetting the core to probe things;
1321 	 * we will re-guess once it's all up and working.
1322 	 */
1323 	error = bwn_reset_core(mac, have_bg);
1324 	if (error)
1325 		goto fail;
1326 
1327 	/*
1328 	 * Determine the DMA engine type
1329 	 */
1330 	if (iost & BHND_IOST_DMA64) {
1331 		mac->mac_dmatype = BHND_DMA_ADDR_64BIT;
1332 	} else {
1333 		uint32_t tmp;
1334 		uint16_t base;
1335 
1336 		base = bwn_dma_base(0, 0);
1337 		BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL,
1338 		    BWN_DMA32_TXADDREXT_MASK);
1339 		tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
1340 		if (tmp & BWN_DMA32_TXADDREXT_MASK) {
1341 			mac->mac_dmatype = BHND_DMA_ADDR_32BIT;
1342 		} else {
1343 			mac->mac_dmatype = BHND_DMA_ADDR_30BIT;
1344 		}
1345 	}
1346 
1347 	/*
1348 	 * Get the PHY version.
1349 	 */
1350 	error = bwn_phy_getinfo(mac, have_bg);
1351 	if (error)
1352 		goto fail;
1353 
1354 	/*
1355 	 * This is the whitelist of devices which we "believe"
1356 	 * the SPROM PHY config from.  The rest are "guessed".
1357 	 */
1358 	if (sc->sc_board_info.board_devid != PCI_DEVID_BCM4311_D11DUAL &&
1359 	    sc->sc_board_info.board_devid != PCI_DEVID_BCM4328_D11G &&
1360 	    sc->sc_board_info.board_devid != PCI_DEVID_BCM4318_D11DUAL &&
1361 	    sc->sc_board_info.board_devid != PCI_DEVID_BCM4306_D11DUAL &&
1362 	    sc->sc_board_info.board_devid != PCI_DEVID_BCM4321_D11N &&
1363 	    sc->sc_board_info.board_devid != PCI_DEVID_BCM4322_D11N) {
1364 		have_a = have_bg = 0;
1365 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1366 			have_a = 1;
1367 		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1368 		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1369 		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1370 			have_bg = 1;
1371 		else
1372 			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1373 			    mac->mac_phy.type));
1374 	}
1375 
1376 	/*
1377 	 * XXX The PHY-G support doesn't do 5GHz operation.
1378 	 */
1379 	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1380 	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1381 		device_printf(sc->sc_dev,
1382 		    "%s: forcing 2GHz only; no dual-band support for PHY\n",
1383 		    __func__);
1384 		have_a = 0;
1385 		have_bg = 1;
1386 	}
1387 
1388 	mac->mac_phy.phy_n = NULL;
1389 
1390 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1391 		mac->mac_phy.attach = bwn_phy_g_attach;
1392 		mac->mac_phy.detach = bwn_phy_g_detach;
1393 		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1394 		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1395 		mac->mac_phy.init = bwn_phy_g_init;
1396 		mac->mac_phy.exit = bwn_phy_g_exit;
1397 		mac->mac_phy.phy_read = bwn_phy_g_read;
1398 		mac->mac_phy.phy_write = bwn_phy_g_write;
1399 		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1400 		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1401 		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1402 		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1403 		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1404 		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1405 		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1406 		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1407 		mac->mac_phy.set_im = bwn_phy_g_im;
1408 		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1409 		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1410 		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1411 		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1412 	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1413 		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1414 		mac->mac_phy.init = bwn_phy_lp_init;
1415 		mac->mac_phy.phy_read = bwn_phy_lp_read;
1416 		mac->mac_phy.phy_write = bwn_phy_lp_write;
1417 		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1418 		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1419 		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1420 		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1421 		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1422 		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1423 		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1424 		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1425 		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1426 	} else if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1427 		mac->mac_phy.attach = bwn_phy_n_attach;
1428 		mac->mac_phy.detach = bwn_phy_n_detach;
1429 		mac->mac_phy.prepare_hw = bwn_phy_n_prepare_hw;
1430 		mac->mac_phy.init_pre = bwn_phy_n_init_pre;
1431 		mac->mac_phy.init = bwn_phy_n_init;
1432 		mac->mac_phy.exit = bwn_phy_n_exit;
1433 		mac->mac_phy.phy_read = bwn_phy_n_read;
1434 		mac->mac_phy.phy_write = bwn_phy_n_write;
1435 		mac->mac_phy.rf_read = bwn_phy_n_rf_read;
1436 		mac->mac_phy.rf_write = bwn_phy_n_rf_write;
1437 		mac->mac_phy.use_hwpctl = bwn_phy_n_hwpctl;
1438 		mac->mac_phy.rf_onoff = bwn_phy_n_rf_onoff;
1439 		mac->mac_phy.switch_analog = bwn_phy_n_switch_analog;
1440 		mac->mac_phy.switch_channel = bwn_phy_n_switch_channel;
1441 		mac->mac_phy.get_default_chan = bwn_phy_n_get_default_chan;
1442 		mac->mac_phy.set_antenna = bwn_phy_n_set_antenna;
1443 		mac->mac_phy.set_im = bwn_phy_n_im;
1444 		mac->mac_phy.recalc_txpwr = bwn_phy_n_recalc_txpwr;
1445 		mac->mac_phy.set_txpwr = bwn_phy_n_set_txpwr;
1446 		mac->mac_phy.task_15s = bwn_phy_n_task_15s;
1447 		mac->mac_phy.task_60s = bwn_phy_n_task_60s;
1448 	} else {
1449 		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1450 		    mac->mac_phy.type);
1451 		error = ENXIO;
1452 		goto fail;
1453 	}
1454 
1455 	mac->mac_phy.gmode = have_bg;
1456 	if (mac->mac_phy.attach != NULL) {
1457 		error = mac->mac_phy.attach(mac);
1458 		if (error) {
1459 			device_printf(sc->sc_dev, "failed\n");
1460 			goto fail;
1461 		}
1462 	}
1463 
1464 	error = bwn_reset_core(mac, have_bg);
1465 	if (error)
1466 		goto fail;
1467 
1468 	error = bwn_chiptest(mac);
1469 	if (error)
1470 		goto fail;
1471 	error = bwn_setup_channels(mac, have_bg, have_a);
1472 	if (error) {
1473 		device_printf(sc->sc_dev, "failed to setup channels\n");
1474 		goto fail;
1475 	}
1476 
1477 	if (sc->sc_curmac == NULL)
1478 		sc->sc_curmac = mac;
1479 
1480 	error = bwn_dma_attach(mac);
1481 	if (error != 0) {
1482 		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1483 		goto fail;
1484 	}
1485 
1486 	mac->mac_phy.switch_analog(mac, 0);
1487 
1488 fail:
1489 	bhnd_suspend_hw(sc->sc_dev, 0);
1490 	bwn_release_firmware(mac);
1491 	return (error);
1492 }
1493 
1494 /*
1495  * Reset
1496  */
1497 int
1498 bwn_reset_core(struct bwn_mac *mac, int g_mode)
1499 {
1500 	struct bwn_softc	*sc;
1501 	uint32_t		 ctl;
1502 	uint16_t		 ioctl, ioctl_mask;
1503 	int			 error;
1504 
1505 	sc = mac->mac_sc;
1506 
1507 	DPRINTF(sc, BWN_DEBUG_RESET, "%s: g_mode=%d\n", __func__, g_mode);
1508 
1509 	/* Reset core */
1510 	ioctl = (BWN_IOCTL_PHYCLOCK_ENABLE | BWN_IOCTL_PHYRESET);
1511 	if (g_mode)
1512 		ioctl |= BWN_IOCTL_SUPPORT_G;
1513 
1514 	/* XXX N-PHY only; and hard-code to 20MHz for now */
1515 	if (mac->mac_phy.type == BWN_PHYTYPE_N)
1516 		ioctl |= BWN_IOCTL_PHY_BANDWIDTH_20MHZ;
1517 
1518 	if ((error = bhnd_reset_hw(sc->sc_dev, ioctl, ioctl))) {
1519 		device_printf(sc->sc_dev, "core reset failed: %d", error);
1520 		return (error);
1521 	}
1522 
1523 	DELAY(2000);
1524 
1525 	/* Take PHY out of reset */
1526 	ioctl = BHND_IOCTL_CLK_FORCE;
1527 	ioctl_mask = BHND_IOCTL_CLK_FORCE |
1528 		     BWN_IOCTL_PHYRESET |
1529 		     BWN_IOCTL_PHYCLOCK_ENABLE;
1530 
1531 	if ((error = bhnd_write_ioctl(sc->sc_dev, ioctl, ioctl_mask))) {
1532 		device_printf(sc->sc_dev, "failed to set core ioctl flags: "
1533 		    "%d\n", error);
1534 		return (error);
1535 	}
1536 
1537 	DELAY(2000);
1538 
1539 	ioctl = BWN_IOCTL_PHYCLOCK_ENABLE;
1540 	if ((error = bhnd_write_ioctl(sc->sc_dev, ioctl, ioctl_mask))) {
1541 		device_printf(sc->sc_dev, "failed to set core ioctl flags: "
1542 		    "%d\n", error);
1543 		return (error);
1544 	}
1545 
1546 	DELAY(2000);
1547 
1548 	if (mac->mac_phy.switch_analog != NULL)
1549 		mac->mac_phy.switch_analog(mac, 1);
1550 
1551 	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1552 	if (g_mode)
1553 		ctl |= BWN_MACCTL_GMODE;
1554 	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1555 
1556 	return (0);
1557 }
1558 
1559 static int
1560 bwn_phy_getinfo(struct bwn_mac *mac, int gmode)
1561 {
1562 	struct bwn_phy *phy = &mac->mac_phy;
1563 	struct bwn_softc *sc = mac->mac_sc;
1564 	uint32_t tmp;
1565 
1566 	/* PHY */
1567 	tmp = BWN_READ_2(mac, BWN_PHYVER);
1568 	phy->gmode = gmode;
1569 	phy->rf_on = 1;
1570 	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1571 	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1572 	phy->rev = (tmp & BWN_PHYVER_VERSION);
1573 	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1574 	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1575 		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1576 	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1577 	    (phy->type == BWN_PHYTYPE_N && phy->rev > 6) ||
1578 	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1579 		goto unsupphy;
1580 
1581 	/* RADIO */
1582 	BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1583 	tmp = BWN_READ_2(mac, BWN_RFDATALO);
1584 	BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1585 	tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1586 
1587 	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1588 	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1589 	phy->rf_manuf = (tmp & 0x00000fff);
1590 
1591 	/*
1592 	 * For now, just always do full init (ie, what bwn has traditionally
1593 	 * done)
1594 	 */
1595 	phy->phy_do_full_init = 1;
1596 
1597 	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1598 		goto unsupradio;
1599 	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1600 	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1601 	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1602 	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1603 	    (phy->type == BWN_PHYTYPE_N &&
1604 	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1605 	    (phy->type == BWN_PHYTYPE_LP &&
1606 	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1607 		goto unsupradio;
1608 
1609 	return (0);
1610 unsupphy:
1611 	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1612 	    "analog %#x)\n",
1613 	    phy->type, phy->rev, phy->analog);
1614 	return (ENXIO);
1615 unsupradio:
1616 	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1617 	    "rev %#x)\n",
1618 	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1619 	return (ENXIO);
1620 }
1621 
1622 static int
1623 bwn_chiptest(struct bwn_mac *mac)
1624 {
1625 #define	TESTVAL0	0x55aaaa55
1626 #define	TESTVAL1	0xaa5555aa
1627 	struct bwn_softc *sc = mac->mac_sc;
1628 	uint32_t v, backup;
1629 
1630 	BWN_LOCK(sc);
1631 
1632 	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1633 
1634 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1635 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1636 		goto error;
1637 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1638 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1639 		goto error;
1640 
1641 	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1642 
1643 	if ((bhnd_get_hwrev(sc->sc_dev) >= 3) &&
1644 	    (bhnd_get_hwrev(sc->sc_dev) <= 10)) {
1645 		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1646 		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1647 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1648 			goto error;
1649 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1650 			goto error;
1651 	}
1652 	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1653 
1654 	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1655 	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1656 		goto error;
1657 
1658 	BWN_UNLOCK(sc);
1659 	return (0);
1660 error:
1661 	BWN_UNLOCK(sc);
1662 	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1663 	return (ENODEV);
1664 }
1665 
1666 static int
1667 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1668 {
1669 	struct bwn_softc *sc = mac->mac_sc;
1670 	struct ieee80211com *ic = &sc->sc_ic;
1671 	uint8_t bands[IEEE80211_MODE_BYTES];
1672 
1673 	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1674 	ic->ic_nchans = 0;
1675 
1676 	DPRINTF(sc, BWN_DEBUG_EEPROM, "%s: called; bg=%d, a=%d\n",
1677 	    __func__,
1678 	    have_bg,
1679 	    have_a);
1680 
1681 	if (have_bg) {
1682 		memset(bands, 0, sizeof(bands));
1683 		setbit(bands, IEEE80211_MODE_11B);
1684 		setbit(bands, IEEE80211_MODE_11G);
1685 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1686 		    &ic->ic_nchans, &bwn_chantable_bg, bands);
1687 	}
1688 
1689 	if (have_a) {
1690 		memset(bands, 0, sizeof(bands));
1691 		setbit(bands, IEEE80211_MODE_11A);
1692 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1693 		    &ic->ic_nchans, &bwn_chantable_a, bands);
1694 	}
1695 
1696 	mac->mac_phy.supports_2ghz = have_bg;
1697 	mac->mac_phy.supports_5ghz = have_a;
1698 
1699 	return (ic->ic_nchans == 0 ? ENXIO : 0);
1700 }
1701 
1702 uint32_t
1703 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1704 {
1705 	uint32_t ret;
1706 
1707 	BWN_ASSERT_LOCKED(mac->mac_sc);
1708 
1709 	if (way == BWN_SHARED) {
1710 		KASSERT((offset & 0x0001) == 0,
1711 		    ("%s:%d warn", __func__, __LINE__));
1712 		if (offset & 0x0003) {
1713 			bwn_shm_ctlword(mac, way, offset >> 2);
1714 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1715 			ret <<= 16;
1716 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1717 			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1718 			goto out;
1719 		}
1720 		offset >>= 2;
1721 	}
1722 	bwn_shm_ctlword(mac, way, offset);
1723 	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1724 out:
1725 	return (ret);
1726 }
1727 
1728 uint16_t
1729 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1730 {
1731 	uint16_t ret;
1732 
1733 	BWN_ASSERT_LOCKED(mac->mac_sc);
1734 
1735 	if (way == BWN_SHARED) {
1736 		KASSERT((offset & 0x0001) == 0,
1737 		    ("%s:%d warn", __func__, __LINE__));
1738 		if (offset & 0x0003) {
1739 			bwn_shm_ctlword(mac, way, offset >> 2);
1740 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1741 			goto out;
1742 		}
1743 		offset >>= 2;
1744 	}
1745 	bwn_shm_ctlword(mac, way, offset);
1746 	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1747 out:
1748 
1749 	return (ret);
1750 }
1751 
1752 static void
1753 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1754     uint16_t offset)
1755 {
1756 	uint32_t control;
1757 
1758 	control = way;
1759 	control <<= 16;
1760 	control |= offset;
1761 	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1762 }
1763 
1764 void
1765 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1766     uint32_t value)
1767 {
1768 	BWN_ASSERT_LOCKED(mac->mac_sc);
1769 
1770 	if (way == BWN_SHARED) {
1771 		KASSERT((offset & 0x0001) == 0,
1772 		    ("%s:%d warn", __func__, __LINE__));
1773 		if (offset & 0x0003) {
1774 			bwn_shm_ctlword(mac, way, offset >> 2);
1775 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1776 				    (value >> 16) & 0xffff);
1777 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1778 			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1779 			return;
1780 		}
1781 		offset >>= 2;
1782 	}
1783 	bwn_shm_ctlword(mac, way, offset);
1784 	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1785 }
1786 
1787 void
1788 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1789     uint16_t value)
1790 {
1791 	BWN_ASSERT_LOCKED(mac->mac_sc);
1792 
1793 	if (way == BWN_SHARED) {
1794 		KASSERT((offset & 0x0001) == 0,
1795 		    ("%s:%d warn", __func__, __LINE__));
1796 		if (offset & 0x0003) {
1797 			bwn_shm_ctlword(mac, way, offset >> 2);
1798 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1799 			return;
1800 		}
1801 		offset >>= 2;
1802 	}
1803 	bwn_shm_ctlword(mac, way, offset);
1804 	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1805 }
1806 
1807 static void
1808 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1809     const struct bwn_channelinfo *ci, const uint8_t bands[])
1810 {
1811 	int i, error;
1812 
1813 	for (i = 0, error = 0; i < ci->nchannels && error == 0; i++) {
1814 		const struct bwn_channel *hc = &ci->channels[i];
1815 
1816 		error = ieee80211_add_channel(chans, maxchans, nchans,
1817 		    hc->ieee, hc->freq, hc->maxTxPow, 0, bands);
1818 	}
1819 }
1820 
1821 static int
1822 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1823 	const struct ieee80211_bpf_params *params)
1824 {
1825 	struct ieee80211com *ic = ni->ni_ic;
1826 	struct bwn_softc *sc = ic->ic_softc;
1827 	struct bwn_mac *mac = sc->sc_curmac;
1828 	int error;
1829 
1830 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
1831 	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
1832 		m_freem(m);
1833 		return (ENETDOWN);
1834 	}
1835 
1836 	BWN_LOCK(sc);
1837 	if (bwn_tx_isfull(sc, m)) {
1838 		m_freem(m);
1839 		BWN_UNLOCK(sc);
1840 		return (ENOBUFS);
1841 	}
1842 
1843 	error = bwn_tx_start(sc, ni, m);
1844 	if (error == 0)
1845 		sc->sc_watchdog_timer = 5;
1846 	BWN_UNLOCK(sc);
1847 	return (error);
1848 }
1849 
1850 /*
1851  * Callback from the 802.11 layer to update the slot time
1852  * based on the current setting.  We use it to notify the
1853  * firmware of ERP changes and the f/w takes care of things
1854  * like slot time and preamble.
1855  */
1856 static void
1857 bwn_updateslot(struct ieee80211com *ic)
1858 {
1859 	struct bwn_softc *sc = ic->ic_softc;
1860 	struct bwn_mac *mac;
1861 
1862 	BWN_LOCK(sc);
1863 	if (sc->sc_flags & BWN_FLAG_RUNNING) {
1864 		mac = (struct bwn_mac *)sc->sc_curmac;
1865 		bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic));
1866 	}
1867 	BWN_UNLOCK(sc);
1868 }
1869 
1870 /*
1871  * Callback from the 802.11 layer after a promiscuous mode change.
1872  * Note this interface does not check the operating mode as this
1873  * is an internal callback and we are expected to honor the current
1874  * state (e.g. this is used for setting the interface in promiscuous
1875  * mode when operating in hostap mode to do ACS).
1876  */
1877 static void
1878 bwn_update_promisc(struct ieee80211com *ic)
1879 {
1880 	struct bwn_softc *sc = ic->ic_softc;
1881 	struct bwn_mac *mac = sc->sc_curmac;
1882 
1883 	BWN_LOCK(sc);
1884 	mac = sc->sc_curmac;
1885 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1886 		if (ic->ic_promisc > 0)
1887 			sc->sc_filters |= BWN_MACCTL_PROMISC;
1888 		else
1889 			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
1890 		bwn_set_opmode(mac);
1891 	}
1892 	BWN_UNLOCK(sc);
1893 }
1894 
1895 /*
1896  * Callback from the 802.11 layer to update WME parameters.
1897  */
1898 static int
1899 bwn_wme_update(struct ieee80211com *ic)
1900 {
1901 	struct bwn_softc *sc = ic->ic_softc;
1902 	struct bwn_mac *mac = sc->sc_curmac;
1903 	struct chanAccParams chp;
1904 	struct wmeParams *wmep;
1905 	int i;
1906 
1907 	ieee80211_wme_ic_getparams(ic, &chp);
1908 
1909 	BWN_LOCK(sc);
1910 	mac = sc->sc_curmac;
1911 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1912 		bwn_mac_suspend(mac);
1913 		for (i = 0; i < N(sc->sc_wmeParams); i++) {
1914 			wmep = &chp.cap_wmeParams[i];
1915 			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
1916 		}
1917 		bwn_mac_enable(mac);
1918 	}
1919 	BWN_UNLOCK(sc);
1920 	return (0);
1921 }
1922 
1923 static void
1924 bwn_scan_start(struct ieee80211com *ic)
1925 {
1926 	struct bwn_softc *sc = ic->ic_softc;
1927 	struct bwn_mac *mac;
1928 
1929 	BWN_LOCK(sc);
1930 	mac = sc->sc_curmac;
1931 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1932 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
1933 		bwn_set_opmode(mac);
1934 		/* disable CFP update during scan */
1935 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
1936 	}
1937 	BWN_UNLOCK(sc);
1938 }
1939 
1940 static void
1941 bwn_scan_end(struct ieee80211com *ic)
1942 {
1943 	struct bwn_softc *sc = ic->ic_softc;
1944 	struct bwn_mac *mac;
1945 
1946 	BWN_LOCK(sc);
1947 	mac = sc->sc_curmac;
1948 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1949 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
1950 		bwn_set_opmode(mac);
1951 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
1952 	}
1953 	BWN_UNLOCK(sc);
1954 }
1955 
1956 static void
1957 bwn_set_channel(struct ieee80211com *ic)
1958 {
1959 	struct bwn_softc *sc = ic->ic_softc;
1960 	struct bwn_mac *mac = sc->sc_curmac;
1961 	struct bwn_phy *phy = &mac->mac_phy;
1962 	int chan, error;
1963 
1964 	BWN_LOCK(sc);
1965 
1966 	error = bwn_switch_band(sc, ic->ic_curchan);
1967 	if (error)
1968 		goto fail;
1969 	bwn_mac_suspend(mac);
1970 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
1971 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
1972 	if (chan != phy->chan)
1973 		bwn_switch_channel(mac, chan);
1974 
1975 	/* TX power level */
1976 	if (ic->ic_curchan->ic_maxpower != 0 &&
1977 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
1978 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
1979 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
1980 		    BWN_TXPWR_IGNORE_TSSI);
1981 	}
1982 
1983 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
1984 	if (phy->set_antenna)
1985 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
1986 
1987 	if (sc->sc_rf_enabled != phy->rf_on) {
1988 		if (sc->sc_rf_enabled) {
1989 			bwn_rf_turnon(mac);
1990 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
1991 				device_printf(sc->sc_dev,
1992 				    "please turn on the RF switch\n");
1993 		} else
1994 			bwn_rf_turnoff(mac);
1995 	}
1996 
1997 	bwn_mac_enable(mac);
1998 
1999 fail:
2000 	BWN_UNLOCK(sc);
2001 }
2002 
2003 static struct ieee80211vap *
2004 bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2005     enum ieee80211_opmode opmode, int flags,
2006     const uint8_t bssid[IEEE80211_ADDR_LEN],
2007     const uint8_t mac[IEEE80211_ADDR_LEN])
2008 {
2009 	struct ieee80211vap *vap;
2010 	struct bwn_vap *bvp;
2011 
2012 	switch (opmode) {
2013 	case IEEE80211_M_HOSTAP:
2014 	case IEEE80211_M_MBSS:
2015 	case IEEE80211_M_STA:
2016 	case IEEE80211_M_WDS:
2017 	case IEEE80211_M_MONITOR:
2018 	case IEEE80211_M_IBSS:
2019 	case IEEE80211_M_AHDEMO:
2020 		break;
2021 	default:
2022 		return (NULL);
2023 	}
2024 
2025 	bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
2026 	vap = &bvp->bv_vap;
2027 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
2028 	/* override with driver methods */
2029 	bvp->bv_newstate = vap->iv_newstate;
2030 	vap->iv_newstate = bwn_newstate;
2031 
2032 	/* override max aid so sta's cannot assoc when we're out of sta id's */
2033 	vap->iv_max_aid = BWN_STAID_MAX;
2034 
2035 	ieee80211_ratectl_init(vap);
2036 
2037 	/* complete setup */
2038 	ieee80211_vap_attach(vap, ieee80211_media_change,
2039 	    ieee80211_media_status, mac);
2040 	return (vap);
2041 }
2042 
2043 static void
2044 bwn_vap_delete(struct ieee80211vap *vap)
2045 {
2046 	struct bwn_vap *bvp = BWN_VAP(vap);
2047 
2048 	ieee80211_ratectl_deinit(vap);
2049 	ieee80211_vap_detach(vap);
2050 	free(bvp, M_80211_VAP);
2051 }
2052 
2053 static int
2054 bwn_init(struct bwn_softc *sc)
2055 {
2056 	struct bwn_mac *mac;
2057 	int error;
2058 
2059 	BWN_ASSERT_LOCKED(sc);
2060 
2061 	DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
2062 
2063 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
2064 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
2065 	sc->sc_filters = 0;
2066 	bwn_wme_clear(sc);
2067 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
2068 	sc->sc_rf_enabled = 1;
2069 
2070 	mac = sc->sc_curmac;
2071 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
2072 		error = bwn_core_init(mac);
2073 		if (error != 0)
2074 			return (error);
2075 	}
2076 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
2077 		bwn_core_start(mac);
2078 
2079 	bwn_set_opmode(mac);
2080 	bwn_set_pretbtt(mac);
2081 	bwn_spu_setdelay(mac, 0);
2082 	bwn_set_macaddr(mac);
2083 
2084 	sc->sc_flags |= BWN_FLAG_RUNNING;
2085 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
2086 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
2087 
2088 	return (0);
2089 }
2090 
2091 static void
2092 bwn_stop(struct bwn_softc *sc)
2093 {
2094 	struct bwn_mac *mac = sc->sc_curmac;
2095 
2096 	BWN_ASSERT_LOCKED(sc);
2097 
2098 	DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
2099 
2100 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
2101 		/* XXX FIXME opmode not based on VAP */
2102 		bwn_set_opmode(mac);
2103 		bwn_set_macaddr(mac);
2104 	}
2105 
2106 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
2107 		bwn_core_stop(mac);
2108 
2109 	callout_stop(&sc->sc_led_blink_ch);
2110 	sc->sc_led_blinking = 0;
2111 
2112 	bwn_core_exit(mac);
2113 	sc->sc_rf_enabled = 0;
2114 
2115 	sc->sc_flags &= ~BWN_FLAG_RUNNING;
2116 }
2117 
2118 static void
2119 bwn_wme_clear(struct bwn_softc *sc)
2120 {
2121 	struct wmeParams *p;
2122 	unsigned int i;
2123 
2124 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
2125 	    ("%s:%d: fail", __func__, __LINE__));
2126 
2127 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
2128 		p = &(sc->sc_wmeParams[i]);
2129 
2130 		switch (bwn_wme_shm_offsets[i]) {
2131 		case BWN_WME_VOICE:
2132 			p->wmep_txopLimit = 0;
2133 			p->wmep_aifsn = 2;
2134 			/* XXX FIXME: log2(cwmin) */
2135 			p->wmep_logcwmin =
2136 			    _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMIN);
2137 			p->wmep_logcwmax =
2138 			    _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMAX);
2139 			break;
2140 		case BWN_WME_VIDEO:
2141 			p->wmep_txopLimit = 0;
2142 			p->wmep_aifsn = 2;
2143 			/* XXX FIXME: log2(cwmin) */
2144 			p->wmep_logcwmin =
2145 			    _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMIN);
2146 			p->wmep_logcwmax =
2147 			    _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMAX);
2148 			break;
2149 		case BWN_WME_BESTEFFORT:
2150 			p->wmep_txopLimit = 0;
2151 			p->wmep_aifsn = 3;
2152 			/* XXX FIXME: log2(cwmin) */
2153 			p->wmep_logcwmin =
2154 			    _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMIN);
2155 			p->wmep_logcwmax =
2156 			    _IEEE80211_MASKSHIFT(0x03ff, WME_PARAM_LOGCWMAX);
2157 			break;
2158 		case BWN_WME_BACKGROUND:
2159 			p->wmep_txopLimit = 0;
2160 			p->wmep_aifsn = 7;
2161 			/* XXX FIXME: log2(cwmin) */
2162 			p->wmep_logcwmin =
2163 			    _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMIN);
2164 			p->wmep_logcwmax =
2165 			    _IEEE80211_MASKSHIFT(0x03ff, WME_PARAM_LOGCWMAX);
2166 			break;
2167 		default:
2168 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2169 		}
2170 	}
2171 }
2172 
2173 static int
2174 bwn_core_forceclk(struct bwn_mac *mac, bool force)
2175 {
2176 	struct bwn_softc	*sc;
2177 	bhnd_clock		 clock;
2178 	int			 error;
2179 
2180 	sc = mac->mac_sc;
2181 
2182 	/* On PMU equipped devices, we do not need to force the HT clock */
2183 	if (sc->sc_pmu != NULL)
2184 		return (0);
2185 
2186 	/* Issue a PMU clock request */
2187 	if (force)
2188 		clock = BHND_CLOCK_HT;
2189 	else
2190 		clock = BHND_CLOCK_DYN;
2191 
2192 	if ((error = bhnd_request_clock(sc->sc_dev, clock))) {
2193 		device_printf(sc->sc_dev, "%d clock request failed: %d\n",
2194 		    clock, error);
2195 		return (error);
2196 	}
2197 
2198 	return (0);
2199 }
2200 
2201 static int
2202 bwn_core_init(struct bwn_mac *mac)
2203 {
2204 	struct bwn_softc *sc = mac->mac_sc;
2205 	uint64_t hf;
2206 	int error;
2207 
2208 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2209 	    ("%s:%d: fail", __func__, __LINE__));
2210 
2211 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
2212 
2213 	if ((error = bwn_core_forceclk(mac, true)))
2214 		return (error);
2215 
2216 	if (bhnd_is_hw_suspended(sc->sc_dev)) {
2217 		if ((error = bwn_reset_core(mac, mac->mac_phy.gmode)))
2218 			goto fail0;
2219 	}
2220 
2221 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
2222 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
2223 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
2224 	BWN_GETTIME(mac->mac_phy.nexttime);
2225 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
2226 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
2227 	mac->mac_stats.link_noise = -95;
2228 	mac->mac_reason_intr = 0;
2229 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
2230 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
2231 #ifdef BWN_DEBUG
2232 	if (sc->sc_debug & BWN_DEBUG_XMIT)
2233 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
2234 #endif
2235 	mac->mac_suspended = 1;
2236 	mac->mac_task_state = 0;
2237 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
2238 
2239 	mac->mac_phy.init_pre(mac);
2240 
2241 	bwn_bt_disable(mac);
2242 	if (mac->mac_phy.prepare_hw) {
2243 		error = mac->mac_phy.prepare_hw(mac);
2244 		if (error)
2245 			goto fail0;
2246 	}
2247 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: chip_init\n", __func__);
2248 	error = bwn_chip_init(mac);
2249 	if (error)
2250 		goto fail0;
2251 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
2252 	    bhnd_get_hwrev(sc->sc_dev));
2253 	hf = bwn_hf_read(mac);
2254 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
2255 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
2256 		if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL)
2257 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
2258 		if (mac->mac_phy.rev == 1)
2259 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
2260 	}
2261 	if (mac->mac_phy.rf_ver == 0x2050) {
2262 		if (mac->mac_phy.rf_rev < 6)
2263 			hf |= BWN_HF_FORCE_VCO_RECALC;
2264 		if (mac->mac_phy.rf_rev == 6)
2265 			hf |= BWN_HF_4318_TSSI;
2266 	}
2267 	if (sc->sc_board_info.board_flags & BHND_BFL_NOPLLDOWN)
2268 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
2269 	if (sc->sc_quirks & BWN_QUIRK_UCODE_SLOWCLOCK_WAR)
2270 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
2271 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
2272 	bwn_hf_write(mac, hf);
2273 
2274 	/* Tell the firmware about the MAC capabilities */
2275 	if (bhnd_get_hwrev(sc->sc_dev) >= 13) {
2276 		uint32_t cap;
2277 		cap = BWN_READ_4(mac, BWN_MAC_HW_CAP);
2278 		DPRINTF(sc, BWN_DEBUG_RESET,
2279 		    "%s: hw capabilities: 0x%08x\n",
2280 		    __func__, cap);
2281 		bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_MACHW_L,
2282 		    cap & 0xffff);
2283 		bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_MACHW_H,
2284 		    (cap >> 16) & 0xffff);
2285 	}
2286 
2287 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2288 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
2289 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
2290 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
2291 
2292 	bwn_rate_init(mac);
2293 	bwn_set_phytxctl(mac);
2294 
2295 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
2296 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
2297 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
2298 
2299 	if (sc->sc_quirks & BWN_QUIRK_NODMA)
2300 		bwn_pio_init(mac);
2301 	else
2302 		bwn_dma_init(mac);
2303 	bwn_wme_init(mac);
2304 	bwn_spu_setdelay(mac, 1);
2305 	bwn_bt_enable(mac);
2306 
2307 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: powerup\n", __func__);
2308 	if (sc->sc_board_info.board_flags & BHND_BFL_NOPLLDOWN)
2309 		bwn_core_forceclk(mac, true);
2310 	else
2311 		bwn_core_forceclk(mac, false);
2312 
2313 	bwn_set_macaddr(mac);
2314 	bwn_crypt_init(mac);
2315 
2316 	/* XXX LED initializatin */
2317 
2318 	mac->mac_status = BWN_MAC_STATUS_INITED;
2319 
2320 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: done\n", __func__);
2321 	return (error);
2322 
2323 fail0:
2324 	bhnd_suspend_hw(sc->sc_dev, 0);
2325 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2326 	    ("%s:%d: fail", __func__, __LINE__));
2327 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: fail\n", __func__);
2328 	return (error);
2329 }
2330 
2331 static void
2332 bwn_core_start(struct bwn_mac *mac)
2333 {
2334 	struct bwn_softc *sc = mac->mac_sc;
2335 	uint32_t tmp;
2336 
2337 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
2338 	    ("%s:%d: fail", __func__, __LINE__));
2339 
2340 	if (bhnd_get_hwrev(sc->sc_dev) < 5)
2341 		return;
2342 
2343 	while (1) {
2344 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
2345 		if (!(tmp & 0x00000001))
2346 			break;
2347 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
2348 	}
2349 
2350 	bwn_mac_enable(mac);
2351 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
2352 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
2353 
2354 	mac->mac_status = BWN_MAC_STATUS_STARTED;
2355 }
2356 
2357 static void
2358 bwn_core_exit(struct bwn_mac *mac)
2359 {
2360 	struct bwn_softc *sc = mac->mac_sc;
2361 	uint32_t macctl;
2362 
2363 	BWN_ASSERT_LOCKED(mac->mac_sc);
2364 
2365 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
2366 	    ("%s:%d: fail", __func__, __LINE__));
2367 
2368 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
2369 		return;
2370 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
2371 
2372 	macctl = BWN_READ_4(mac, BWN_MACCTL);
2373 	macctl &= ~BWN_MACCTL_MCODE_RUN;
2374 	macctl |= BWN_MACCTL_MCODE_JMP0;
2375 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2376 
2377 	bwn_dma_stop(mac);
2378 	bwn_pio_stop(mac);
2379 	bwn_chip_exit(mac);
2380 	mac->mac_phy.switch_analog(mac, 0);
2381 	bhnd_suspend_hw(sc->sc_dev, 0);
2382 }
2383 
2384 static void
2385 bwn_bt_disable(struct bwn_mac *mac)
2386 {
2387 	struct bwn_softc *sc = mac->mac_sc;
2388 
2389 	(void)sc;
2390 	/* XXX do nothing yet */
2391 }
2392 
2393 static int
2394 bwn_chip_init(struct bwn_mac *mac)
2395 {
2396 	struct bwn_softc *sc = mac->mac_sc;
2397 	struct bwn_phy *phy = &mac->mac_phy;
2398 	uint32_t macctl;
2399 	u_int delay;
2400 	int error;
2401 
2402 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
2403 	if (phy->gmode)
2404 		macctl |= BWN_MACCTL_GMODE;
2405 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2406 
2407 	error = bwn_fw_fillinfo(mac);
2408 	if (error)
2409 		return (error);
2410 	error = bwn_fw_loaducode(mac);
2411 	if (error)
2412 		return (error);
2413 
2414 	error = bwn_gpio_init(mac);
2415 	if (error)
2416 		return (error);
2417 
2418 	error = bwn_fw_loadinitvals(mac);
2419 	if (error)
2420 		return (error);
2421 
2422 	phy->switch_analog(mac, 1);
2423 	error = bwn_phy_init(mac);
2424 	if (error)
2425 		return (error);
2426 
2427 	if (phy->set_im)
2428 		phy->set_im(mac, BWN_IMMODE_NONE);
2429 	if (phy->set_antenna)
2430 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2431 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2432 
2433 	if (phy->type == BWN_PHYTYPE_B)
2434 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
2435 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
2436 	if (bhnd_get_hwrev(sc->sc_dev) < 5)
2437 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
2438 
2439 	BWN_WRITE_4(mac, BWN_MACCTL,
2440 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
2441 	BWN_WRITE_4(mac, BWN_MACCTL,
2442 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
2443 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
2444 
2445 	bwn_set_opmode(mac);
2446 	if (bhnd_get_hwrev(sc->sc_dev) < 3) {
2447 		BWN_WRITE_2(mac, 0x060e, 0x0000);
2448 		BWN_WRITE_2(mac, 0x0610, 0x8000);
2449 		BWN_WRITE_2(mac, 0x0604, 0x0000);
2450 		BWN_WRITE_2(mac, 0x0606, 0x0200);
2451 	} else {
2452 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
2453 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
2454 	}
2455 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
2456 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
2457 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
2458 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
2459 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
2460 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
2461 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
2462 
2463 	bwn_mac_phy_clock_set(mac, true);
2464 
2465 	/* Provide the HT clock transition latency to the MAC core */
2466 	error = bhnd_get_clock_latency(sc->sc_dev, BHND_CLOCK_HT, &delay);
2467 	if (error) {
2468 		device_printf(sc->sc_dev, "failed to fetch HT clock latency: "
2469 		    "%d\n", error);
2470 		return (error);
2471 	}
2472 
2473 	if (delay > UINT16_MAX) {
2474 		device_printf(sc->sc_dev, "invalid HT clock latency: %u\n",
2475 		    delay);
2476 		return (ENXIO);
2477 	}
2478 
2479 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, delay);
2480 	return (0);
2481 }
2482 
2483 /* read hostflags */
2484 uint64_t
2485 bwn_hf_read(struct bwn_mac *mac)
2486 {
2487 	uint64_t ret;
2488 
2489 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
2490 	ret <<= 16;
2491 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
2492 	ret <<= 16;
2493 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
2494 	return (ret);
2495 }
2496 
2497 void
2498 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
2499 {
2500 
2501 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
2502 	    (value & 0x00000000ffffull));
2503 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
2504 	    (value & 0x0000ffff0000ull) >> 16);
2505 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
2506 	    (value & 0xffff00000000ULL) >> 32);
2507 }
2508 
2509 static void
2510 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
2511 {
2512 
2513 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
2514 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
2515 }
2516 
2517 static void
2518 bwn_rate_init(struct bwn_mac *mac)
2519 {
2520 
2521 	switch (mac->mac_phy.type) {
2522 	case BWN_PHYTYPE_A:
2523 	case BWN_PHYTYPE_G:
2524 	case BWN_PHYTYPE_LP:
2525 	case BWN_PHYTYPE_N:
2526 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
2527 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
2528 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
2529 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
2530 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
2531 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
2532 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
2533 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
2534 			break;
2535 		/* FALLTHROUGH */
2536 	case BWN_PHYTYPE_B:
2537 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
2538 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
2539 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
2540 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
2541 		break;
2542 	default:
2543 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2544 	}
2545 }
2546 
2547 static void
2548 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
2549 {
2550 	uint16_t offset;
2551 
2552 	if (ofdm) {
2553 		offset = 0x480;
2554 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
2555 	} else {
2556 		offset = 0x4c0;
2557 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
2558 	}
2559 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
2560 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
2561 }
2562 
2563 static uint8_t
2564 bwn_plcp_getcck(const uint8_t bitrate)
2565 {
2566 
2567 	switch (bitrate) {
2568 	case BWN_CCK_RATE_1MB:
2569 		return (0x0a);
2570 	case BWN_CCK_RATE_2MB:
2571 		return (0x14);
2572 	case BWN_CCK_RATE_5MB:
2573 		return (0x37);
2574 	case BWN_CCK_RATE_11MB:
2575 		return (0x6e);
2576 	}
2577 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2578 	return (0);
2579 }
2580 
2581 static uint8_t
2582 bwn_plcp_getofdm(const uint8_t bitrate)
2583 {
2584 
2585 	switch (bitrate) {
2586 	case BWN_OFDM_RATE_6MB:
2587 		return (0xb);
2588 	case BWN_OFDM_RATE_9MB:
2589 		return (0xf);
2590 	case BWN_OFDM_RATE_12MB:
2591 		return (0xa);
2592 	case BWN_OFDM_RATE_18MB:
2593 		return (0xe);
2594 	case BWN_OFDM_RATE_24MB:
2595 		return (0x9);
2596 	case BWN_OFDM_RATE_36MB:
2597 		return (0xd);
2598 	case BWN_OFDM_RATE_48MB:
2599 		return (0x8);
2600 	case BWN_OFDM_RATE_54MB:
2601 		return (0xc);
2602 	}
2603 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2604 	return (0);
2605 }
2606 
2607 static void
2608 bwn_set_phytxctl(struct bwn_mac *mac)
2609 {
2610 	uint16_t ctl;
2611 
2612 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
2613 	    BWN_TX_PHY_TXPWR);
2614 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
2615 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
2616 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
2617 }
2618 
2619 static void
2620 bwn_pio_init(struct bwn_mac *mac)
2621 {
2622 	struct bwn_pio *pio = &mac->mac_method.pio;
2623 
2624 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
2625 	    & ~BWN_MACCTL_BIGENDIAN);
2626 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
2627 
2628 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
2629 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
2630 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
2631 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
2632 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
2633 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
2634 }
2635 
2636 static void
2637 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2638     int index)
2639 {
2640 	struct bwn_pio_txpkt *tp;
2641 	struct bwn_softc *sc = mac->mac_sc;
2642 	unsigned int i;
2643 
2644 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
2645 	tq->tq_index = index;
2646 
2647 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
2648 	if (bhnd_get_hwrev(sc->sc_dev) >= 8)
2649 		tq->tq_size = 1920;
2650 	else {
2651 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
2652 		tq->tq_size -= 80;
2653 	}
2654 
2655 	TAILQ_INIT(&tq->tq_pktlist);
2656 	for (i = 0; i < N(tq->tq_pkts); i++) {
2657 		tp = &(tq->tq_pkts[i]);
2658 		tp->tp_index = i;
2659 		tp->tp_queue = tq;
2660 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
2661 	}
2662 }
2663 
2664 static uint16_t
2665 bwn_pio_idx2base(struct bwn_mac *mac, int index)
2666 {
2667 	struct bwn_softc *sc = mac->mac_sc;
2668 	static const uint16_t bases[] = {
2669 		BWN_PIO_BASE0,
2670 		BWN_PIO_BASE1,
2671 		BWN_PIO_BASE2,
2672 		BWN_PIO_BASE3,
2673 		BWN_PIO_BASE4,
2674 		BWN_PIO_BASE5,
2675 		BWN_PIO_BASE6,
2676 		BWN_PIO_BASE7,
2677 	};
2678 	static const uint16_t bases_rev11[] = {
2679 		BWN_PIO11_BASE0,
2680 		BWN_PIO11_BASE1,
2681 		BWN_PIO11_BASE2,
2682 		BWN_PIO11_BASE3,
2683 		BWN_PIO11_BASE4,
2684 		BWN_PIO11_BASE5,
2685 	};
2686 
2687 	if (bhnd_get_hwrev(sc->sc_dev) >= 11) {
2688 		if (index >= N(bases_rev11))
2689 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
2690 		return (bases_rev11[index]);
2691 	}
2692 	if (index >= N(bases))
2693 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
2694 	return (bases[index]);
2695 }
2696 
2697 static void
2698 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
2699     int index)
2700 {
2701 	struct bwn_softc *sc = mac->mac_sc;
2702 
2703 	prq->prq_mac = mac;
2704 	prq->prq_rev = bhnd_get_hwrev(sc->sc_dev);
2705 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
2706 	bwn_dma_rxdirectfifo(mac, index, 1);
2707 }
2708 
2709 static void
2710 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
2711 {
2712 	if (tq == NULL)
2713 		return;
2714 	bwn_pio_cancel_tx_packets(tq);
2715 }
2716 
2717 static void
2718 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
2719 {
2720 
2721 	bwn_destroy_pioqueue_tx(pio);
2722 }
2723 
2724 static uint16_t
2725 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2726     uint16_t offset)
2727 {
2728 
2729 	return (BWN_READ_2(mac, tq->tq_base + offset));
2730 }
2731 
2732 static void
2733 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
2734 {
2735 	uint32_t ctl;
2736 	uint16_t base;
2737 
2738 	base = bwn_dma_base(mac->mac_dmatype, idx);
2739 	if (mac->mac_dmatype == BHND_DMA_ADDR_64BIT) {
2740 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
2741 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
2742 		if (enable)
2743 			ctl |= BWN_DMA64_RXDIRECTFIFO;
2744 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
2745 	} else {
2746 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
2747 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
2748 		if (enable)
2749 			ctl |= BWN_DMA32_RXDIRECTFIFO;
2750 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
2751 	}
2752 }
2753 
2754 static void
2755 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
2756 {
2757 	struct bwn_pio_txpkt *tp;
2758 	unsigned int i;
2759 
2760 	for (i = 0; i < N(tq->tq_pkts); i++) {
2761 		tp = &(tq->tq_pkts[i]);
2762 		if (tp->tp_m) {
2763 			m_freem(tp->tp_m);
2764 			tp->tp_m = NULL;
2765 		}
2766 	}
2767 }
2768 
2769 static uint16_t
2770 bwn_dma_base(int type, int controller_idx)
2771 {
2772 	static const uint16_t map64[] = {
2773 		BWN_DMA64_BASE0,
2774 		BWN_DMA64_BASE1,
2775 		BWN_DMA64_BASE2,
2776 		BWN_DMA64_BASE3,
2777 		BWN_DMA64_BASE4,
2778 		BWN_DMA64_BASE5,
2779 	};
2780 	static const uint16_t map32[] = {
2781 		BWN_DMA32_BASE0,
2782 		BWN_DMA32_BASE1,
2783 		BWN_DMA32_BASE2,
2784 		BWN_DMA32_BASE3,
2785 		BWN_DMA32_BASE4,
2786 		BWN_DMA32_BASE5,
2787 	};
2788 
2789 	if (type == BHND_DMA_ADDR_64BIT) {
2790 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
2791 		    ("%s:%d: fail", __func__, __LINE__));
2792 		return (map64[controller_idx]);
2793 	}
2794 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
2795 	    ("%s:%d: fail", __func__, __LINE__));
2796 	return (map32[controller_idx]);
2797 }
2798 
2799 static void
2800 bwn_dma_init(struct bwn_mac *mac)
2801 {
2802 	struct bwn_dma *dma = &mac->mac_method.dma;
2803 
2804 	/* setup TX DMA channels. */
2805 	bwn_dma_setup(dma->wme[WME_AC_BK]);
2806 	bwn_dma_setup(dma->wme[WME_AC_BE]);
2807 	bwn_dma_setup(dma->wme[WME_AC_VI]);
2808 	bwn_dma_setup(dma->wme[WME_AC_VO]);
2809 	bwn_dma_setup(dma->mcast);
2810 	/* setup RX DMA channel. */
2811 	bwn_dma_setup(dma->rx);
2812 }
2813 
2814 static struct bwn_dma_ring *
2815 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
2816     int for_tx)
2817 {
2818 	struct bwn_dma *dma = &mac->mac_method.dma;
2819 	struct bwn_dma_ring *dr;
2820 	struct bwn_dmadesc_generic *desc;
2821 	struct bwn_dmadesc_meta *mt;
2822 	struct bwn_softc *sc = mac->mac_sc;
2823 	int error, i;
2824 
2825 	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
2826 	if (dr == NULL)
2827 		goto out;
2828 	dr->dr_numslots = BWN_RXRING_SLOTS;
2829 	if (for_tx)
2830 		dr->dr_numslots = BWN_TXRING_SLOTS;
2831 
2832 	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
2833 	    M_DEVBUF, M_NOWAIT | M_ZERO);
2834 	if (dr->dr_meta == NULL)
2835 		goto fail0;
2836 
2837 	dr->dr_type = mac->mac_dmatype;
2838 	dr->dr_mac = mac;
2839 	dr->dr_base = bwn_dma_base(dr->dr_type, controller_index);
2840 	dr->dr_index = controller_index;
2841 	if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
2842 		dr->getdesc = bwn_dma_64_getdesc;
2843 		dr->setdesc = bwn_dma_64_setdesc;
2844 		dr->start_transfer = bwn_dma_64_start_transfer;
2845 		dr->suspend = bwn_dma_64_suspend;
2846 		dr->resume = bwn_dma_64_resume;
2847 		dr->get_curslot = bwn_dma_64_get_curslot;
2848 		dr->set_curslot = bwn_dma_64_set_curslot;
2849 	} else {
2850 		dr->getdesc = bwn_dma_32_getdesc;
2851 		dr->setdesc = bwn_dma_32_setdesc;
2852 		dr->start_transfer = bwn_dma_32_start_transfer;
2853 		dr->suspend = bwn_dma_32_suspend;
2854 		dr->resume = bwn_dma_32_resume;
2855 		dr->get_curslot = bwn_dma_32_get_curslot;
2856 		dr->set_curslot = bwn_dma_32_set_curslot;
2857 	}
2858 	if (for_tx) {
2859 		dr->dr_tx = 1;
2860 		dr->dr_curslot = -1;
2861 	} else {
2862 		if (dr->dr_index == 0) {
2863 			switch (mac->mac_fw.fw_hdr_format) {
2864 			case BWN_FW_HDR_351:
2865 			case BWN_FW_HDR_410:
2866 				dr->dr_rx_bufsize =
2867 				    BWN_DMA0_RX_BUFFERSIZE_FW351;
2868 				dr->dr_frameoffset =
2869 				    BWN_DMA0_RX_FRAMEOFFSET_FW351;
2870 				break;
2871 			case BWN_FW_HDR_598:
2872 				dr->dr_rx_bufsize =
2873 				    BWN_DMA0_RX_BUFFERSIZE_FW598;
2874 				dr->dr_frameoffset =
2875 				    BWN_DMA0_RX_FRAMEOFFSET_FW598;
2876 				break;
2877 			}
2878 		} else
2879 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2880 	}
2881 
2882 	error = bwn_dma_allocringmemory(dr);
2883 	if (error)
2884 		goto fail2;
2885 
2886 	if (for_tx) {
2887 		/*
2888 		 * Assumption: BWN_TXRING_SLOTS can be divided by
2889 		 * BWN_TX_SLOTS_PER_FRAME
2890 		 */
2891 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
2892 		    ("%s:%d: fail", __func__, __LINE__));
2893 
2894 		dr->dr_txhdr_cache = contigmalloc(
2895 		    (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2896 		    BWN_MAXTXHDRSIZE, M_DEVBUF, M_ZERO,
2897 		    0, BUS_SPACE_MAXADDR, 8, 0);
2898 		if (dr->dr_txhdr_cache == NULL) {
2899 			device_printf(sc->sc_dev,
2900 			    "can't allocate TX header DMA memory\n");
2901 			goto fail1;
2902 		}
2903 
2904 		/*
2905 		 * Create TX ring DMA stuffs
2906 		 */
2907 		error = bus_dma_tag_create(dma->parent_dtag,
2908 				    BWN_ALIGN, 0,
2909 				    BUS_SPACE_MAXADDR,
2910 				    BUS_SPACE_MAXADDR,
2911 				    NULL, NULL,
2912 				    BWN_HDRSIZE(mac),
2913 				    1,
2914 				    BUS_SPACE_MAXSIZE_32BIT,
2915 				    0,
2916 				    NULL, NULL,
2917 				    &dr->dr_txring_dtag);
2918 		if (error) {
2919 			device_printf(sc->sc_dev,
2920 			    "can't create TX ring DMA tag: TODO frees\n");
2921 			goto fail2;
2922 		}
2923 
2924 		for (i = 0; i < dr->dr_numslots; i += 2) {
2925 			dr->getdesc(dr, i, &desc, &mt);
2926 
2927 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
2928 			mt->mt_m = NULL;
2929 			mt->mt_ni = NULL;
2930 			mt->mt_islast = 0;
2931 			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
2932 			    &mt->mt_dmap);
2933 			if (error) {
2934 				device_printf(sc->sc_dev,
2935 				     "can't create RX buf DMA map\n");
2936 				goto fail2;
2937 			}
2938 
2939 			dr->getdesc(dr, i + 1, &desc, &mt);
2940 
2941 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
2942 			mt->mt_m = NULL;
2943 			mt->mt_ni = NULL;
2944 			mt->mt_islast = 1;
2945 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
2946 			    &mt->mt_dmap);
2947 			if (error) {
2948 				device_printf(sc->sc_dev,
2949 				     "can't create RX buf DMA map\n");
2950 				goto fail2;
2951 			}
2952 		}
2953 	} else {
2954 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2955 		    &dr->dr_spare_dmap);
2956 		if (error) {
2957 			device_printf(sc->sc_dev,
2958 			    "can't create RX buf DMA map\n");
2959 			goto out;		/* XXX wrong! */
2960 		}
2961 
2962 		for (i = 0; i < dr->dr_numslots; i++) {
2963 			dr->getdesc(dr, i, &desc, &mt);
2964 
2965 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2966 			    &mt->mt_dmap);
2967 			if (error) {
2968 				device_printf(sc->sc_dev,
2969 				    "can't create RX buf DMA map\n");
2970 				goto out;	/* XXX wrong! */
2971 			}
2972 			error = bwn_dma_newbuf(dr, desc, mt, 1);
2973 			if (error) {
2974 				device_printf(sc->sc_dev,
2975 				    "failed to allocate RX buf\n");
2976 				goto out;	/* XXX wrong! */
2977 			}
2978 		}
2979 
2980 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
2981 		    BUS_DMASYNC_PREWRITE);
2982 
2983 		dr->dr_usedslot = dr->dr_numslots;
2984 	}
2985 
2986       out:
2987 	return (dr);
2988 
2989 fail2:
2990 	free(dr->dr_txhdr_cache, M_DEVBUF);
2991 fail1:
2992 	free(dr->dr_meta, M_DEVBUF);
2993 fail0:
2994 	free(dr, M_DEVBUF);
2995 	return (NULL);
2996 }
2997 
2998 static void
2999 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3000 {
3001 
3002 	if (dr == NULL)
3003 		return;
3004 
3005 	bwn_dma_free_descbufs(*dr);
3006 	bwn_dma_free_ringmemory(*dr);
3007 
3008 	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3009 	free((*dr)->dr_meta, M_DEVBUF);
3010 	free(*dr, M_DEVBUF);
3011 
3012 	*dr = NULL;
3013 }
3014 
3015 static void
3016 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3017     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3018 {
3019 	struct bwn_dmadesc32 *desc;
3020 
3021 	*meta = &(dr->dr_meta[slot]);
3022 	desc = dr->dr_ring_descbase;
3023 	desc = &(desc[slot]);
3024 
3025 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3026 }
3027 
3028 static void
3029 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3030     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3031     int start, int end, int irq)
3032 {
3033 	struct bwn_dmadesc32		*descbase;
3034 	struct bwn_dma			*dma;
3035 	struct bhnd_dma_translation	*dt;
3036 	uint32_t			 addr, addrext, ctl;
3037 	int				 slot;
3038 
3039 	descbase = dr->dr_ring_descbase;
3040 	dma = &dr->dr_mac->mac_method.dma;
3041 	dt = &dma->translation;
3042 
3043 	slot = (int)(&(desc->dma.dma32) - descbase);
3044 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3045 	    ("%s:%d: fail", __func__, __LINE__));
3046 
3047 	addr = (dmaaddr & dt->addr_mask) | dt->base_addr;
3048 	addrext = ((dmaaddr & dt->addrext_mask) >> dma->addrext_shift);
3049 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3050 	if (slot == dr->dr_numslots - 1)
3051 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3052 	if (start)
3053 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3054 	if (end)
3055 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3056 	if (irq)
3057 		ctl |= BWN_DMA32_DCTL_IRQ;
3058 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3059 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3060 
3061 	desc->dma.dma32.control = htole32(ctl);
3062 	desc->dma.dma32.address = htole32(addr);
3063 }
3064 
3065 static void
3066 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3067 {
3068 
3069 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3070 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3071 }
3072 
3073 static void
3074 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3075 {
3076 
3077 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3078 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3079 }
3080 
3081 static void
3082 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3083 {
3084 
3085 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3086 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3087 }
3088 
3089 static int
3090 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3091 {
3092 	uint32_t val;
3093 
3094 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
3095 	val &= BWN_DMA32_RXDPTR;
3096 
3097 	return (val / sizeof(struct bwn_dmadesc32));
3098 }
3099 
3100 static void
3101 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
3102 {
3103 
3104 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
3105 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
3106 }
3107 
3108 static void
3109 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
3110     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3111 {
3112 	struct bwn_dmadesc64 *desc;
3113 
3114 	*meta = &(dr->dr_meta[slot]);
3115 	desc = dr->dr_ring_descbase;
3116 	desc = &(desc[slot]);
3117 
3118 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3119 }
3120 
3121 static void
3122 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
3123     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3124     int start, int end, int irq)
3125 {
3126 	struct bwn_dmadesc64		*descbase;
3127 	struct bwn_dma			*dma;
3128 	struct bhnd_dma_translation	*dt;
3129 	bhnd_addr_t			 addr;
3130 	uint32_t			 addrhi, addrlo;
3131 	uint32_t			 addrext;
3132 	uint32_t			 ctl0, ctl1;
3133 	int				 slot;
3134 
3135 	descbase = dr->dr_ring_descbase;
3136 	dma = &dr->dr_mac->mac_method.dma;
3137 	dt = &dma->translation;
3138 
3139 	slot = (int)(&(desc->dma.dma64) - descbase);
3140 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3141 	    ("%s:%d: fail", __func__, __LINE__));
3142 
3143 	addr = (dmaaddr & dt->addr_mask) | dt->base_addr;
3144 	addrhi = (addr >> 32);
3145 	addrlo = (addr & UINT32_MAX);
3146 	addrext = ((dmaaddr & dt->addrext_mask) >> dma->addrext_shift);
3147 
3148 	ctl0 = 0;
3149 	if (slot == dr->dr_numslots - 1)
3150 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
3151 	if (start)
3152 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
3153 	if (end)
3154 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
3155 	if (irq)
3156 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
3157 
3158 	ctl1 = 0;
3159 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
3160 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
3161 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
3162 
3163 	desc->dma.dma64.control0 = htole32(ctl0);
3164 	desc->dma.dma64.control1 = htole32(ctl1);
3165 	desc->dma.dma64.address_low = htole32(addrlo);
3166 	desc->dma.dma64.address_high = htole32(addrhi);
3167 }
3168 
3169 static void
3170 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
3171 {
3172 
3173 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
3174 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3175 }
3176 
3177 static void
3178 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
3179 {
3180 
3181 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3182 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
3183 }
3184 
3185 static void
3186 bwn_dma_64_resume(struct bwn_dma_ring *dr)
3187 {
3188 
3189 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3190 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
3191 }
3192 
3193 static int
3194 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
3195 {
3196 	uint32_t val;
3197 
3198 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
3199 	val &= BWN_DMA64_RXSTATDPTR;
3200 
3201 	return (val / sizeof(struct bwn_dmadesc64));
3202 }
3203 
3204 static void
3205 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
3206 {
3207 
3208 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
3209 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3210 }
3211 
3212 static int
3213 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
3214 {
3215 	struct bwn_mac *mac = dr->dr_mac;
3216 	struct bwn_dma *dma = &mac->mac_method.dma;
3217 	struct bwn_softc *sc = mac->mac_sc;
3218 	int error;
3219 
3220 	error = bus_dma_tag_create(dma->parent_dtag,
3221 			    BWN_ALIGN, 0,
3222 			    BUS_SPACE_MAXADDR,
3223 			    BUS_SPACE_MAXADDR,
3224 			    NULL, NULL,
3225 			    BWN_DMA_RINGMEMSIZE,
3226 			    1,
3227 			    BUS_SPACE_MAXSIZE_32BIT,
3228 			    0,
3229 			    NULL, NULL,
3230 			    &dr->dr_ring_dtag);
3231 	if (error) {
3232 		device_printf(sc->sc_dev,
3233 		    "can't create TX ring DMA tag: TODO frees\n");
3234 		return (-1);
3235 	}
3236 
3237 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
3238 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
3239 	    &dr->dr_ring_dmap);
3240 	if (error) {
3241 		device_printf(sc->sc_dev,
3242 		    "can't allocate DMA mem: TODO frees\n");
3243 		return (-1);
3244 	}
3245 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
3246 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
3247 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
3248 	if (error) {
3249 		device_printf(sc->sc_dev,
3250 		    "can't load DMA mem: TODO free\n");
3251 		return (-1);
3252 	}
3253 
3254 	return (0);
3255 }
3256 
3257 static void
3258 bwn_dma_setup(struct bwn_dma_ring *dr)
3259 {
3260 	struct bwn_mac			*mac;
3261 	struct bwn_dma			*dma;
3262 	struct bhnd_dma_translation	*dt;
3263 	bhnd_addr_t			 addr, paddr;
3264 	uint32_t			 addrhi, addrlo, addrext, value;
3265 
3266 	mac = dr->dr_mac;
3267 	dma = &mac->mac_method.dma;
3268 	dt = &dma->translation;
3269 
3270 	paddr = dr->dr_ring_dmabase;
3271 	addr = (paddr & dt->addr_mask) | dt->base_addr;
3272 	addrhi = (addr >> 32);
3273 	addrlo = (addr & UINT32_MAX);
3274 	addrext = ((paddr & dt->addrext_mask) >> dma->addrext_shift);
3275 
3276 	if (dr->dr_tx) {
3277 		dr->dr_curslot = -1;
3278 
3279 		if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
3280 			value = BWN_DMA64_TXENABLE;
3281 			value |= BWN_DMA64_TXPARITY_DISABLE;
3282 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
3283 			    & BWN_DMA64_TXADDREXT_MASK;
3284 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
3285 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, addrlo);
3286 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, addrhi);
3287 		} else {
3288 			value = BWN_DMA32_TXENABLE;
3289 			value |= BWN_DMA32_TXPARITY_DISABLE;
3290 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
3291 			    & BWN_DMA32_TXADDREXT_MASK;
3292 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
3293 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, addrlo);
3294 		}
3295 		return;
3296 	}
3297 
3298 	/*
3299 	 * set for RX
3300 	 */
3301 	dr->dr_usedslot = dr->dr_numslots;
3302 
3303 	if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
3304 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
3305 		value |= BWN_DMA64_RXENABLE;
3306 		value |= BWN_DMA64_RXPARITY_DISABLE;
3307 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
3308 		    & BWN_DMA64_RXADDREXT_MASK;
3309 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
3310 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, addrlo);
3311 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, addrhi);
3312 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
3313 		    sizeof(struct bwn_dmadesc64));
3314 	} else {
3315 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
3316 		value |= BWN_DMA32_RXENABLE;
3317 		value |= BWN_DMA32_RXPARITY_DISABLE;
3318 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
3319 		    & BWN_DMA32_RXADDREXT_MASK;
3320 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
3321 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, addrlo);
3322 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
3323 		    sizeof(struct bwn_dmadesc32));
3324 	}
3325 }
3326 
3327 static void
3328 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
3329 {
3330 
3331 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
3332 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
3333 	    dr->dr_ring_dmap);
3334 }
3335 
3336 static void
3337 bwn_dma_cleanup(struct bwn_dma_ring *dr)
3338 {
3339 
3340 	if (dr->dr_tx) {
3341 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3342 		if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
3343 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
3344 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
3345 		} else
3346 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
3347 	} else {
3348 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3349 		if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
3350 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
3351 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
3352 		} else
3353 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
3354 	}
3355 }
3356 
3357 static void
3358 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
3359 {
3360 	struct bwn_dmadesc_generic *desc;
3361 	struct bwn_dmadesc_meta *meta;
3362 	struct bwn_mac *mac = dr->dr_mac;
3363 	struct bwn_dma *dma = &mac->mac_method.dma;
3364 	struct bwn_softc *sc = mac->mac_sc;
3365 	int i;
3366 
3367 	if (!dr->dr_usedslot)
3368 		return;
3369 	for (i = 0; i < dr->dr_numslots; i++) {
3370 		dr->getdesc(dr, i, &desc, &meta);
3371 
3372 		if (meta->mt_m == NULL) {
3373 			if (!dr->dr_tx)
3374 				device_printf(sc->sc_dev, "%s: not TX?\n",
3375 				    __func__);
3376 			continue;
3377 		}
3378 		if (dr->dr_tx) {
3379 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
3380 				bus_dmamap_unload(dr->dr_txring_dtag,
3381 				    meta->mt_dmap);
3382 			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
3383 				bus_dmamap_unload(dma->txbuf_dtag,
3384 				    meta->mt_dmap);
3385 		} else
3386 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
3387 		bwn_dma_free_descbuf(dr, meta);
3388 	}
3389 }
3390 
3391 static int
3392 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
3393     int type)
3394 {
3395 	struct bwn_softc *sc = mac->mac_sc;
3396 	uint32_t value;
3397 	int i;
3398 	uint16_t offset;
3399 
3400 	for (i = 0; i < 10; i++) {
3401 		offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_TXSTATUS :
3402 		    BWN_DMA32_TXSTATUS;
3403 		value = BWN_READ_4(mac, base + offset);
3404 		if (type == BHND_DMA_ADDR_64BIT) {
3405 			value &= BWN_DMA64_TXSTAT;
3406 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
3407 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
3408 			    value == BWN_DMA64_TXSTAT_STOPPED)
3409 				break;
3410 		} else {
3411 			value &= BWN_DMA32_TXSTATE;
3412 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
3413 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
3414 			    value == BWN_DMA32_TXSTAT_STOPPED)
3415 				break;
3416 		}
3417 		DELAY(1000);
3418 	}
3419 	offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_TXCTL :
3420 	    BWN_DMA32_TXCTL;
3421 	BWN_WRITE_4(mac, base + offset, 0);
3422 	for (i = 0; i < 10; i++) {
3423 		offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_TXSTATUS :
3424 		    BWN_DMA32_TXSTATUS;
3425 		value = BWN_READ_4(mac, base + offset);
3426 		if (type == BHND_DMA_ADDR_64BIT) {
3427 			value &= BWN_DMA64_TXSTAT;
3428 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
3429 				i = -1;
3430 				break;
3431 			}
3432 		} else {
3433 			value &= BWN_DMA32_TXSTATE;
3434 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
3435 				i = -1;
3436 				break;
3437 			}
3438 		}
3439 		DELAY(1000);
3440 	}
3441 	if (i != -1) {
3442 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3443 		return (ENODEV);
3444 	}
3445 	DELAY(1000);
3446 
3447 	return (0);
3448 }
3449 
3450 static int
3451 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
3452     int type)
3453 {
3454 	struct bwn_softc *sc = mac->mac_sc;
3455 	uint32_t value;
3456 	int i;
3457 	uint16_t offset;
3458 
3459 	offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_RXCTL :
3460 	    BWN_DMA32_RXCTL;
3461 	BWN_WRITE_4(mac, base + offset, 0);
3462 	for (i = 0; i < 10; i++) {
3463 		offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_RXSTATUS :
3464 		    BWN_DMA32_RXSTATUS;
3465 		value = BWN_READ_4(mac, base + offset);
3466 		if (type == BHND_DMA_ADDR_64BIT) {
3467 			value &= BWN_DMA64_RXSTAT;
3468 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
3469 				i = -1;
3470 				break;
3471 			}
3472 		} else {
3473 			value &= BWN_DMA32_RXSTATE;
3474 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
3475 				i = -1;
3476 				break;
3477 			}
3478 		}
3479 		DELAY(1000);
3480 	}
3481 	if (i != -1) {
3482 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3483 		return (ENODEV);
3484 	}
3485 
3486 	return (0);
3487 }
3488 
3489 static void
3490 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
3491     struct bwn_dmadesc_meta *meta)
3492 {
3493 
3494 	if (meta->mt_m != NULL) {
3495 		m_freem(meta->mt_m);
3496 		meta->mt_m = NULL;
3497 	}
3498 	if (meta->mt_ni != NULL) {
3499 		ieee80211_free_node(meta->mt_ni);
3500 		meta->mt_ni = NULL;
3501 	}
3502 }
3503 
3504 static void
3505 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3506 {
3507 	struct bwn_rxhdr4 *rxhdr;
3508 	unsigned char *frame;
3509 
3510 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
3511 	rxhdr->frame_len = 0;
3512 
3513 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
3514 	    sizeof(struct bwn_plcp6) + 2,
3515 	    ("%s:%d: fail", __func__, __LINE__));
3516 	frame = mtod(m, char *) + dr->dr_frameoffset;
3517 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
3518 }
3519 
3520 static uint8_t
3521 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3522 {
3523 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
3524 
3525 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
3526 	    == 0xff);
3527 }
3528 
3529 static void
3530 bwn_wme_init(struct bwn_mac *mac)
3531 {
3532 
3533 	bwn_wme_load(mac);
3534 
3535 	/* enable WME support. */
3536 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
3537 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
3538 	    BWN_IFSCTL_USE_EDCF);
3539 }
3540 
3541 static void
3542 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
3543 {
3544 	struct bwn_softc *sc = mac->mac_sc;
3545 	struct ieee80211com *ic = &sc->sc_ic;
3546 	uint16_t delay;	/* microsec */
3547 
3548 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
3549 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
3550 		delay = 500;
3551 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
3552 		delay = max(delay, (uint16_t)2400);
3553 
3554 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
3555 }
3556 
3557 static void
3558 bwn_bt_enable(struct bwn_mac *mac)
3559 {
3560 	struct bwn_softc *sc = mac->mac_sc;
3561 	uint64_t hf;
3562 
3563 	if (bwn_bluetooth == 0)
3564 		return;
3565 	if ((sc->sc_board_info.board_flags & BHND_BFL_BTCOEX) == 0)
3566 		return;
3567 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
3568 		return;
3569 
3570 	hf = bwn_hf_read(mac);
3571 	if (sc->sc_board_info.board_flags & BHND_BFL_BTC2WIRE_ALTGPIO)
3572 		hf |= BWN_HF_BT_COEXISTALT;
3573 	else
3574 		hf |= BWN_HF_BT_COEXIST;
3575 	bwn_hf_write(mac, hf);
3576 }
3577 
3578 static void
3579 bwn_set_macaddr(struct bwn_mac *mac)
3580 {
3581 
3582 	bwn_mac_write_bssid(mac);
3583 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
3584 	    mac->mac_sc->sc_ic.ic_macaddr);
3585 }
3586 
3587 static void
3588 bwn_clear_keys(struct bwn_mac *mac)
3589 {
3590 	int i;
3591 
3592 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
3593 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
3594 		    ("%s:%d: fail", __func__, __LINE__));
3595 
3596 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
3597 		    NULL, BWN_SEC_KEYSIZE, NULL);
3598 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
3599 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
3600 			    NULL, BWN_SEC_KEYSIZE, NULL);
3601 		}
3602 		mac->mac_key[i].keyconf = NULL;
3603 	}
3604 }
3605 
3606 static void
3607 bwn_crypt_init(struct bwn_mac *mac)
3608 {
3609 	struct bwn_softc *sc = mac->mac_sc;
3610 
3611 	mac->mac_max_nr_keys = (bhnd_get_hwrev(sc->sc_dev) >= 5) ? 58 : 20;
3612 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
3613 	    ("%s:%d: fail", __func__, __LINE__));
3614 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
3615 	mac->mac_ktp *= 2;
3616 	if (bhnd_get_hwrev(sc->sc_dev) >= 5)
3617 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
3618 	bwn_clear_keys(mac);
3619 }
3620 
3621 static void
3622 bwn_chip_exit(struct bwn_mac *mac)
3623 {
3624 	bwn_phy_exit(mac);
3625 }
3626 
3627 static int
3628 bwn_fw_fillinfo(struct bwn_mac *mac)
3629 {
3630 	int error;
3631 
3632 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
3633 	if (error == 0)
3634 		return (0);
3635 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
3636 	if (error == 0)
3637 		return (0);
3638 	return (error);
3639 }
3640 
3641 /**
3642  * Request that the GPIO controller tristate all pins set in @p mask, granting
3643  * the MAC core control over the pins.
3644  *
3645  * @param mac	bwn MAC state.
3646  * @param pins	If the bit position for a pin number is set to one, tristate the
3647  *		pin.
3648  */
3649 int
3650 bwn_gpio_control(struct bwn_mac *mac, uint32_t pins)
3651 {
3652 	struct bwn_softc	*sc;
3653 	uint32_t		 flags[32];
3654 	int			 error;
3655 
3656 	sc = mac->mac_sc;
3657 
3658 	/* Determine desired pin flags */
3659 	for (size_t pin = 0; pin < nitems(flags); pin++) {
3660 		uint32_t pinbit = (1 << pin);
3661 
3662 		if (pins & pinbit) {
3663 			/* Tristate output */
3664 			flags[pin] = GPIO_PIN_OUTPUT|GPIO_PIN_TRISTATE;
3665 		} else {
3666 			/* Leave unmodified */
3667 			flags[pin] = 0;
3668 		}
3669 	}
3670 
3671 	/* Configure all pins */
3672 	error = GPIO_PIN_CONFIG_32(sc->sc_gpio, 0, nitems(flags), flags);
3673 	if (error) {
3674 		device_printf(sc->sc_dev, "error configuring %s pin flags: "
3675 		    "%d\n", device_get_nameunit(sc->sc_gpio), error);
3676 		return (error);
3677 	}
3678 
3679 	return (0);
3680 }
3681 
3682 static int
3683 bwn_gpio_init(struct bwn_mac *mac)
3684 {
3685 	struct bwn_softc	*sc;
3686 	uint32_t		 pins;
3687 
3688 	sc = mac->mac_sc;
3689 
3690 	pins = 0xF;
3691 
3692 	BWN_WRITE_4(mac, BWN_MACCTL,
3693 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
3694 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
3695 	    BWN_READ_2(mac, BWN_GPIO_MASK) | pins);
3696 
3697 	if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL) {
3698 		/* MAC core is responsible for toggling PAREF via gpio9 */
3699 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
3700 		    BWN_READ_2(mac, BWN_GPIO_MASK) | BHND_GPIO_BOARD_PACTRL);
3701 
3702 		pins |= BHND_GPIO_BOARD_PACTRL;
3703 	}
3704 
3705 	return (bwn_gpio_control(mac, pins));
3706 }
3707 
3708 static int
3709 bwn_fw_loadinitvals(struct bwn_mac *mac)
3710 {
3711 #define	GETFWOFFSET(fwp, offset)				\
3712 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
3713 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
3714 	const struct bwn_fwhdr *hdr;
3715 	struct bwn_fw *fw = &mac->mac_fw;
3716 	int error;
3717 
3718 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
3719 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
3720 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
3721 	if (error)
3722 		return (error);
3723 	if (fw->initvals_band.fw) {
3724 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
3725 		error = bwn_fwinitvals_write(mac,
3726 		    GETFWOFFSET(fw->initvals_band, hdr_len),
3727 		    be32toh(hdr->size),
3728 		    fw->initvals_band.fw->datasize - hdr_len);
3729 	}
3730 	return (error);
3731 #undef GETFWOFFSET
3732 }
3733 
3734 static int
3735 bwn_phy_init(struct bwn_mac *mac)
3736 {
3737 	struct bwn_softc *sc = mac->mac_sc;
3738 	int error;
3739 
3740 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
3741 	mac->mac_phy.rf_onoff(mac, 1);
3742 	error = mac->mac_phy.init(mac);
3743 	if (error) {
3744 		device_printf(sc->sc_dev, "PHY init failed\n");
3745 		goto fail0;
3746 	}
3747 	error = bwn_switch_channel(mac,
3748 	    mac->mac_phy.get_default_chan(mac));
3749 	if (error) {
3750 		device_printf(sc->sc_dev,
3751 		    "failed to switch default channel\n");
3752 		goto fail1;
3753 	}
3754 	return (0);
3755 fail1:
3756 	if (mac->mac_phy.exit)
3757 		mac->mac_phy.exit(mac);
3758 fail0:
3759 	mac->mac_phy.rf_onoff(mac, 0);
3760 
3761 	return (error);
3762 }
3763 
3764 static void
3765 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
3766 {
3767 	uint16_t ant;
3768 	uint16_t tmp;
3769 
3770 	ant = bwn_ant2phy(antenna);
3771 
3772 	/* For ACK/CTS */
3773 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
3774 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3775 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
3776 	/* For Probe Resposes */
3777 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
3778 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3779 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
3780 }
3781 
3782 static void
3783 bwn_set_opmode(struct bwn_mac *mac)
3784 {
3785 	struct bwn_softc *sc = mac->mac_sc;
3786 	struct ieee80211com *ic = &sc->sc_ic;
3787 	uint32_t ctl;
3788 	uint16_t cfp_pretbtt;
3789 
3790 	ctl = BWN_READ_4(mac, BWN_MACCTL);
3791 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
3792 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
3793 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
3794 	ctl |= BWN_MACCTL_STA;
3795 
3796 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
3797 	    ic->ic_opmode == IEEE80211_M_MBSS)
3798 		ctl |= BWN_MACCTL_HOSTAP;
3799 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
3800 		ctl &= ~BWN_MACCTL_STA;
3801 	ctl |= sc->sc_filters;
3802 
3803 	if (bhnd_get_hwrev(sc->sc_dev) <= 4)
3804 		ctl |= BWN_MACCTL_PROMISC;
3805 
3806 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
3807 
3808 	cfp_pretbtt = 2;
3809 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
3810 		if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4306 &&
3811 		    sc->sc_cid.chip_rev == 3)
3812 			cfp_pretbtt = 100;
3813 		else
3814 			cfp_pretbtt = 50;
3815 	}
3816 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
3817 }
3818 
3819 static void
3820 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
3821 {
3822 	if (!error) {
3823 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
3824 		*((bus_addr_t *)arg) = seg->ds_addr;
3825 	}
3826 }
3827 
3828 void
3829 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
3830 {
3831 	struct bwn_phy *phy = &mac->mac_phy;
3832 	struct bwn_softc *sc = mac->mac_sc;
3833 	unsigned int i, max_loop;
3834 	uint16_t value;
3835 	uint32_t buffer[5] = {
3836 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
3837 	};
3838 
3839 	if (ofdm) {
3840 		max_loop = 0x1e;
3841 		buffer[0] = 0x000201cc;
3842 	} else {
3843 		max_loop = 0xfa;
3844 		buffer[0] = 0x000b846e;
3845 	}
3846 
3847 	BWN_ASSERT_LOCKED(mac->mac_sc);
3848 
3849 	for (i = 0; i < 5; i++)
3850 		bwn_ram_write(mac, i * 4, buffer[i]);
3851 
3852 	BWN_WRITE_2(mac, 0x0568, 0x0000);
3853 	BWN_WRITE_2(mac, 0x07c0,
3854 	    (bhnd_get_hwrev(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
3855 
3856 	value = (ofdm ? 0x41 : 0x40);
3857 	BWN_WRITE_2(mac, 0x050c, value);
3858 
3859 	if (phy->type == BWN_PHYTYPE_N || phy->type == BWN_PHYTYPE_LP ||
3860 	    phy->type == BWN_PHYTYPE_LCN)
3861 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
3862 	BWN_WRITE_2(mac, 0x0508, 0x0000);
3863 	BWN_WRITE_2(mac, 0x050a, 0x0000);
3864 	BWN_WRITE_2(mac, 0x054c, 0x0000);
3865 	BWN_WRITE_2(mac, 0x056a, 0x0014);
3866 	BWN_WRITE_2(mac, 0x0568, 0x0826);
3867 	BWN_WRITE_2(mac, 0x0500, 0x0000);
3868 
3869 	/* XXX TODO: n phy pa override? */
3870 
3871 	switch (phy->type) {
3872 	case BWN_PHYTYPE_N:
3873 	case BWN_PHYTYPE_LCN:
3874 		BWN_WRITE_2(mac, 0x0502, 0x00d0);
3875 		break;
3876 	case BWN_PHYTYPE_LP:
3877 		BWN_WRITE_2(mac, 0x0502, 0x0050);
3878 		break;
3879 	default:
3880 		BWN_WRITE_2(mac, 0x0502, 0x0030);
3881 		break;
3882 	}
3883 
3884 	/* flush */
3885 	BWN_READ_2(mac, 0x0502);
3886 
3887 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3888 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
3889 	for (i = 0x00; i < max_loop; i++) {
3890 		value = BWN_READ_2(mac, 0x050e);
3891 		if (value & 0x0080)
3892 			break;
3893 		DELAY(10);
3894 	}
3895 	for (i = 0x00; i < 0x0a; i++) {
3896 		value = BWN_READ_2(mac, 0x050e);
3897 		if (value & 0x0400)
3898 			break;
3899 		DELAY(10);
3900 	}
3901 	for (i = 0x00; i < 0x19; i++) {
3902 		value = BWN_READ_2(mac, 0x0690);
3903 		if (!(value & 0x0100))
3904 			break;
3905 		DELAY(10);
3906 	}
3907 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3908 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
3909 }
3910 
3911 void
3912 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
3913 {
3914 	uint32_t macctl;
3915 
3916 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
3917 
3918 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3919 	if (macctl & BWN_MACCTL_BIGENDIAN)
3920 		printf("TODO: need swap\n");
3921 
3922 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
3923 	BWN_BARRIER(mac, BWN_RAM_CONTROL, 4, BUS_SPACE_BARRIER_WRITE);
3924 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
3925 }
3926 
3927 void
3928 bwn_mac_suspend(struct bwn_mac *mac)
3929 {
3930 	struct bwn_softc *sc = mac->mac_sc;
3931 	int i;
3932 	uint32_t tmp;
3933 
3934 	KASSERT(mac->mac_suspended >= 0,
3935 	    ("%s:%d: fail", __func__, __LINE__));
3936 
3937 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: suspended=%d\n",
3938 	    __func__, mac->mac_suspended);
3939 
3940 	if (mac->mac_suspended == 0) {
3941 		bwn_psctl(mac, BWN_PS_AWAKE);
3942 		BWN_WRITE_4(mac, BWN_MACCTL,
3943 			    BWN_READ_4(mac, BWN_MACCTL)
3944 			    & ~BWN_MACCTL_ON);
3945 		BWN_READ_4(mac, BWN_MACCTL);
3946 		for (i = 35; i; i--) {
3947 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3948 			if (tmp & BWN_INTR_MAC_SUSPENDED)
3949 				goto out;
3950 			DELAY(10);
3951 		}
3952 		for (i = 40; i; i--) {
3953 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3954 			if (tmp & BWN_INTR_MAC_SUSPENDED)
3955 				goto out;
3956 			DELAY(1000);
3957 		}
3958 		device_printf(sc->sc_dev, "MAC suspend failed\n");
3959 	}
3960 out:
3961 	mac->mac_suspended++;
3962 }
3963 
3964 void
3965 bwn_mac_enable(struct bwn_mac *mac)
3966 {
3967 	struct bwn_softc *sc = mac->mac_sc;
3968 	uint16_t state;
3969 
3970 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: suspended=%d\n",
3971 	    __func__, mac->mac_suspended);
3972 
3973 	state = bwn_shm_read_2(mac, BWN_SHARED,
3974 	    BWN_SHARED_UCODESTAT);
3975 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
3976 	    state != BWN_SHARED_UCODESTAT_SLEEP) {
3977 		DPRINTF(sc, BWN_DEBUG_FW,
3978 		    "%s: warn: firmware state (%d)\n",
3979 		    __func__, state);
3980 	}
3981 
3982 	mac->mac_suspended--;
3983 	KASSERT(mac->mac_suspended >= 0,
3984 	    ("%s:%d: fail", __func__, __LINE__));
3985 	if (mac->mac_suspended == 0) {
3986 		BWN_WRITE_4(mac, BWN_MACCTL,
3987 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
3988 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
3989 		BWN_READ_4(mac, BWN_MACCTL);
3990 		BWN_READ_4(mac, BWN_INTR_REASON);
3991 		bwn_psctl(mac, 0);
3992 	}
3993 }
3994 
3995 void
3996 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
3997 {
3998 	struct bwn_softc *sc = mac->mac_sc;
3999 	int i;
4000 	uint16_t ucstat;
4001 
4002 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
4003 	    ("%s:%d: fail", __func__, __LINE__));
4004 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
4005 	    ("%s:%d: fail", __func__, __LINE__));
4006 
4007 	/* XXX forcibly awake and hwps-off */
4008 
4009 	BWN_WRITE_4(mac, BWN_MACCTL,
4010 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
4011 	    ~BWN_MACCTL_HWPS);
4012 	BWN_READ_4(mac, BWN_MACCTL);
4013 	if (bhnd_get_hwrev(sc->sc_dev) >= 5) {
4014 		for (i = 0; i < 100; i++) {
4015 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
4016 			    BWN_SHARED_UCODESTAT);
4017 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
4018 				break;
4019 			DELAY(10);
4020 		}
4021 	}
4022 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: ucstat=%d\n", __func__,
4023 	    ucstat);
4024 }
4025 
4026 static int
4027 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
4028 {
4029 	struct bwn_softc *sc = mac->mac_sc;
4030 	struct bwn_fw *fw = &mac->mac_fw;
4031 	const uint8_t rev = bhnd_get_hwrev(sc->sc_dev);
4032 	const char *filename;
4033 	uint16_t iost;
4034 	int error;
4035 
4036 	/* microcode */
4037 	filename = NULL;
4038 	switch (rev) {
4039 	case 42:
4040 		if (mac->mac_phy.type == BWN_PHYTYPE_AC)
4041 			filename = "ucode42";
4042 		break;
4043 	case 40:
4044 		if (mac->mac_phy.type == BWN_PHYTYPE_AC)
4045 			filename = "ucode40";
4046 		break;
4047 	case 33:
4048 		if (mac->mac_phy.type == BWN_PHYTYPE_LCN40)
4049 			filename = "ucode33_lcn40";
4050 		break;
4051 	case 30:
4052 		if (mac->mac_phy.type == BWN_PHYTYPE_N)
4053 			filename = "ucode30_mimo";
4054 		break;
4055 	case 29:
4056 		if (mac->mac_phy.type == BWN_PHYTYPE_HT)
4057 			filename = "ucode29_mimo";
4058 		break;
4059 	case 26:
4060 		if (mac->mac_phy.type == BWN_PHYTYPE_HT)
4061 			filename = "ucode26_mimo";
4062 		break;
4063 	case 28:
4064 	case 25:
4065 		if (mac->mac_phy.type == BWN_PHYTYPE_N)
4066 			filename = "ucode25_mimo";
4067 		else if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
4068 			filename = "ucode25_lcn";
4069 		break;
4070 	case 24:
4071 		if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
4072 			filename = "ucode24_lcn";
4073 		break;
4074 	case 23:
4075 		if (mac->mac_phy.type == BWN_PHYTYPE_N)
4076 			filename = "ucode16_mimo";
4077 		break;
4078 	case 16:
4079 	case 17:
4080 	case 18:
4081 	case 19:
4082 		if (mac->mac_phy.type == BWN_PHYTYPE_N)
4083 			filename = "ucode16_mimo";
4084 		else if (mac->mac_phy.type == BWN_PHYTYPE_LP)
4085 			filename = "ucode16_lp";
4086 		break;
4087 	case 15:
4088 		filename = "ucode15";
4089 		break;
4090 	case 14:
4091 		filename = "ucode14";
4092 		break;
4093 	case 13:
4094 		filename = "ucode13";
4095 		break;
4096 	case 12:
4097 	case 11:
4098 		filename = "ucode11";
4099 		break;
4100 	case 10:
4101 	case 9:
4102 	case 8:
4103 	case 7:
4104 	case 6:
4105 	case 5:
4106 		filename = "ucode5";
4107 		break;
4108 	default:
4109 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
4110 		bwn_release_firmware(mac);
4111 		return (EOPNOTSUPP);
4112 	}
4113 
4114 	device_printf(sc->sc_dev, "ucode fw: %s\n", filename);
4115 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
4116 	if (error) {
4117 		bwn_release_firmware(mac);
4118 		return (error);
4119 	}
4120 
4121 	/* PCM */
4122 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
4123 	if (rev >= 5 && rev <= 10) {
4124 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
4125 		if (error == ENOENT)
4126 			fw->no_pcmfile = 1;
4127 		else if (error) {
4128 			bwn_release_firmware(mac);
4129 			return (error);
4130 		}
4131 	} else if (rev < 11) {
4132 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
4133 		bwn_release_firmware(mac);
4134 		return (EOPNOTSUPP);
4135 	}
4136 
4137 	/* initvals */
4138 	error = bhnd_read_iost(sc->sc_dev, &iost);
4139 	if (error)
4140 		goto fail1;
4141 
4142 	switch (mac->mac_phy.type) {
4143 	case BWN_PHYTYPE_A:
4144 		if (rev < 5 || rev > 10)
4145 			goto fail1;
4146 		if (iost & BWN_IOST_HAVE_2GHZ)
4147 			filename = "a0g1initvals5";
4148 		else
4149 			filename = "a0g0initvals5";
4150 		break;
4151 	case BWN_PHYTYPE_G:
4152 		if (rev >= 5 && rev <= 10)
4153 			filename = "b0g0initvals5";
4154 		else if (rev >= 13)
4155 			filename = "b0g0initvals13";
4156 		else
4157 			goto fail1;
4158 		break;
4159 	case BWN_PHYTYPE_LP:
4160 		if (rev == 13)
4161 			filename = "lp0initvals13";
4162 		else if (rev == 14)
4163 			filename = "lp0initvals14";
4164 		else if (rev >= 15)
4165 			filename = "lp0initvals15";
4166 		else
4167 			goto fail1;
4168 		break;
4169 	case BWN_PHYTYPE_N:
4170 		if (rev == 30)
4171 			filename = "n16initvals30";
4172 		else if (rev == 28 || rev == 25)
4173 			filename = "n0initvals25";
4174 		else if (rev == 24)
4175 			filename = "n0initvals24";
4176 		else if (rev == 23)
4177 			filename = "n0initvals16";
4178 		else if (rev >= 16 && rev <= 18)
4179 			filename = "n0initvals16";
4180 		else if (rev >= 11 && rev <= 12)
4181 			filename = "n0initvals11";
4182 		else
4183 			goto fail1;
4184 		break;
4185 	default:
4186 		goto fail1;
4187 	}
4188 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
4189 	if (error) {
4190 		bwn_release_firmware(mac);
4191 		return (error);
4192 	}
4193 
4194 	/* bandswitch initvals */
4195 	switch (mac->mac_phy.type) {
4196 	case BWN_PHYTYPE_A:
4197 		if (rev >= 5 && rev <= 10) {
4198 			if (iost & BWN_IOST_HAVE_2GHZ)
4199 				filename = "a0g1bsinitvals5";
4200 			else
4201 				filename = "a0g0bsinitvals5";
4202 		} else if (rev >= 11)
4203 			filename = NULL;
4204 		else
4205 			goto fail1;
4206 		break;
4207 	case BWN_PHYTYPE_G:
4208 		if (rev >= 5 && rev <= 10)
4209 			filename = "b0g0bsinitvals5";
4210 		else if (rev >= 11)
4211 			filename = NULL;
4212 		else
4213 			goto fail1;
4214 		break;
4215 	case BWN_PHYTYPE_LP:
4216 		if (rev == 13)
4217 			filename = "lp0bsinitvals13";
4218 		else if (rev == 14)
4219 			filename = "lp0bsinitvals14";
4220 		else if (rev >= 15)
4221 			filename = "lp0bsinitvals15";
4222 		else
4223 			goto fail1;
4224 		break;
4225 	case BWN_PHYTYPE_N:
4226 		if (rev == 30)
4227 			filename = "n16bsinitvals30";
4228 		else if (rev == 28 || rev == 25)
4229 			filename = "n0bsinitvals25";
4230 		else if (rev == 24)
4231 			filename = "n0bsinitvals24";
4232 		else if (rev == 23)
4233 			filename = "n0bsinitvals16";
4234 		else if (rev >= 16 && rev <= 18)
4235 			filename = "n0bsinitvals16";
4236 		else if (rev >= 11 && rev <= 12)
4237 			filename = "n0bsinitvals11";
4238 		else
4239 			goto fail1;
4240 		break;
4241 	default:
4242 		device_printf(sc->sc_dev, "unknown phy (%d)\n",
4243 		    mac->mac_phy.type);
4244 		goto fail1;
4245 	}
4246 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
4247 	if (error) {
4248 		bwn_release_firmware(mac);
4249 		return (error);
4250 	}
4251 	return (0);
4252 fail1:
4253 	device_printf(sc->sc_dev, "no INITVALS for rev %d, phy.type %d\n",
4254 	    rev, mac->mac_phy.type);
4255 	bwn_release_firmware(mac);
4256 	return (EOPNOTSUPP);
4257 }
4258 
4259 static int
4260 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
4261     const char *name, struct bwn_fwfile *bfw)
4262 {
4263 	const struct bwn_fwhdr *hdr;
4264 	struct bwn_softc *sc = mac->mac_sc;
4265 	const struct firmware *fw;
4266 	char namebuf[64];
4267 
4268 	if (name == NULL) {
4269 		bwn_do_release_fw(bfw);
4270 		return (0);
4271 	}
4272 	if (bfw->filename != NULL) {
4273 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
4274 			return (0);
4275 		bwn_do_release_fw(bfw);
4276 	}
4277 
4278 	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
4279 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
4280 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
4281 	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
4282 	fw = firmware_get(namebuf);
4283 	if (fw == NULL) {
4284 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
4285 		    namebuf);
4286 		return (ENOENT);
4287 	}
4288 	if (fw->datasize < sizeof(struct bwn_fwhdr))
4289 		goto fail;
4290 	hdr = (const struct bwn_fwhdr *)(fw->data);
4291 	switch (hdr->type) {
4292 	case BWN_FWTYPE_UCODE:
4293 	case BWN_FWTYPE_PCM:
4294 		if (be32toh(hdr->size) !=
4295 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
4296 			goto fail;
4297 		/* FALLTHROUGH */
4298 	case BWN_FWTYPE_IV:
4299 		if (hdr->ver != 1)
4300 			goto fail;
4301 		break;
4302 	default:
4303 		goto fail;
4304 	}
4305 	bfw->filename = name;
4306 	bfw->fw = fw;
4307 	bfw->type = type;
4308 	return (0);
4309 fail:
4310 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
4311 	if (fw != NULL)
4312 		firmware_put(fw, FIRMWARE_UNLOAD);
4313 	return (EPROTO);
4314 }
4315 
4316 static void
4317 bwn_release_firmware(struct bwn_mac *mac)
4318 {
4319 
4320 	bwn_do_release_fw(&mac->mac_fw.ucode);
4321 	bwn_do_release_fw(&mac->mac_fw.pcm);
4322 	bwn_do_release_fw(&mac->mac_fw.initvals);
4323 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
4324 }
4325 
4326 static void
4327 bwn_do_release_fw(struct bwn_fwfile *bfw)
4328 {
4329 
4330 	if (bfw->fw != NULL)
4331 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
4332 	bfw->fw = NULL;
4333 	bfw->filename = NULL;
4334 }
4335 
4336 static int
4337 bwn_fw_loaducode(struct bwn_mac *mac)
4338 {
4339 #define	GETFWOFFSET(fwp, offset)	\
4340 	((const uint32_t *)((const char *)fwp.fw->data + offset))
4341 #define	GETFWSIZE(fwp, offset)	\
4342 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
4343 	struct bwn_softc *sc = mac->mac_sc;
4344 	const uint32_t *data;
4345 	unsigned int i;
4346 	uint32_t ctl;
4347 	uint16_t date, fwcaps, time;
4348 	int error = 0;
4349 
4350 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4351 	ctl |= BWN_MACCTL_MCODE_JMP0;
4352 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
4353 	    __LINE__));
4354 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4355 	for (i = 0; i < 64; i++)
4356 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
4357 	for (i = 0; i < 4096; i += 2)
4358 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
4359 
4360 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4361 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
4362 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4363 	     i++) {
4364 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4365 		DELAY(10);
4366 	}
4367 
4368 	if (mac->mac_fw.pcm.fw) {
4369 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
4370 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
4371 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
4372 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
4373 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
4374 		    sizeof(struct bwn_fwhdr)); i++) {
4375 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4376 			DELAY(10);
4377 		}
4378 	}
4379 
4380 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
4381 	BWN_WRITE_4(mac, BWN_MACCTL,
4382 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
4383 	    BWN_MACCTL_MCODE_RUN);
4384 
4385 	for (i = 0; i < 21; i++) {
4386 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
4387 			break;
4388 		if (i >= 20) {
4389 			device_printf(sc->sc_dev, "ucode timeout\n");
4390 			error = ENXIO;
4391 			goto error;
4392 		}
4393 		DELAY(50000);
4394 	}
4395 	BWN_READ_4(mac, BWN_INTR_REASON);
4396 
4397 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
4398 	if (mac->mac_fw.rev <= 0x128) {
4399 		device_printf(sc->sc_dev, "the firmware is too old\n");
4400 		error = EOPNOTSUPP;
4401 		goto error;
4402 	}
4403 
4404 	/*
4405 	 * Determine firmware header version; needed for TX/RX packet
4406 	 * handling.
4407 	 */
4408 	if (mac->mac_fw.rev >= 598)
4409 		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_598;
4410 	else if (mac->mac_fw.rev >= 410)
4411 		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_410;
4412 	else
4413 		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_351;
4414 
4415 	/*
4416 	 * We don't support rev 598 or later; that requires
4417 	 * another round of changes to the TX/RX descriptor
4418 	 * and status layout.
4419 	 *
4420 	 * So, complain this is the case and exit out, rather
4421 	 * than attaching and then failing.
4422 	 */
4423 #if 0
4424 	if (mac->mac_fw.fw_hdr_format == BWN_FW_HDR_598) {
4425 		device_printf(sc->sc_dev,
4426 		    "firmware is too new (>=598); not supported\n");
4427 		error = EOPNOTSUPP;
4428 		goto error;
4429 	}
4430 #endif
4431 
4432 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
4433 	    BWN_SHARED_UCODE_PATCH);
4434 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
4435 	mac->mac_fw.opensource = (date == 0xffff);
4436 	if (bwn_wme != 0)
4437 		mac->mac_flags |= BWN_MAC_FLAG_WME;
4438 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
4439 
4440 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
4441 	if (mac->mac_fw.opensource == 0) {
4442 		device_printf(sc->sc_dev,
4443 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
4444 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
4445 		if (mac->mac_fw.no_pcmfile)
4446 			device_printf(sc->sc_dev,
4447 			    "no HW crypto acceleration due to pcm5\n");
4448 	} else {
4449 		mac->mac_fw.patch = time;
4450 		fwcaps = bwn_fwcaps_read(mac);
4451 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
4452 			device_printf(sc->sc_dev,
4453 			    "disabling HW crypto acceleration\n");
4454 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
4455 		}
4456 		if (!(fwcaps & BWN_FWCAPS_WME)) {
4457 			device_printf(sc->sc_dev, "disabling WME support\n");
4458 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
4459 		}
4460 	}
4461 
4462 	if (BWN_ISOLDFMT(mac))
4463 		device_printf(sc->sc_dev, "using old firmware image\n");
4464 
4465 	return (0);
4466 
4467 error:
4468 	BWN_WRITE_4(mac, BWN_MACCTL,
4469 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
4470 	    BWN_MACCTL_MCODE_JMP0);
4471 
4472 	return (error);
4473 #undef GETFWSIZE
4474 #undef GETFWOFFSET
4475 }
4476 
4477 /* OpenFirmware only */
4478 static uint16_t
4479 bwn_fwcaps_read(struct bwn_mac *mac)
4480 {
4481 
4482 	KASSERT(mac->mac_fw.opensource == 1,
4483 	    ("%s:%d: fail", __func__, __LINE__));
4484 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
4485 }
4486 
4487 static int
4488 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
4489     size_t count, size_t array_size)
4490 {
4491 #define	GET_NEXTIV16(iv)						\
4492 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
4493 	    sizeof(uint16_t) + sizeof(uint16_t)))
4494 #define	GET_NEXTIV32(iv)						\
4495 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
4496 	    sizeof(uint16_t) + sizeof(uint32_t)))
4497 	struct bwn_softc *sc = mac->mac_sc;
4498 	const struct bwn_fwinitvals *iv;
4499 	uint16_t offset;
4500 	size_t i;
4501 	uint8_t bit32;
4502 
4503 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
4504 	    ("%s:%d: fail", __func__, __LINE__));
4505 	iv = ivals;
4506 	for (i = 0; i < count; i++) {
4507 		if (array_size < sizeof(iv->offset_size))
4508 			goto fail;
4509 		array_size -= sizeof(iv->offset_size);
4510 		offset = be16toh(iv->offset_size);
4511 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
4512 		offset &= BWN_FWINITVALS_OFFSET_MASK;
4513 		if (offset >= 0x1000)
4514 			goto fail;
4515 		if (bit32) {
4516 			if (array_size < sizeof(iv->data.d32))
4517 				goto fail;
4518 			array_size -= sizeof(iv->data.d32);
4519 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
4520 			iv = GET_NEXTIV32(iv);
4521 		} else {
4522 			if (array_size < sizeof(iv->data.d16))
4523 				goto fail;
4524 			array_size -= sizeof(iv->data.d16);
4525 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
4526 
4527 			iv = GET_NEXTIV16(iv);
4528 		}
4529 	}
4530 	if (array_size != 0)
4531 		goto fail;
4532 	return (0);
4533 fail:
4534 	device_printf(sc->sc_dev, "initvals: invalid format\n");
4535 	return (EPROTO);
4536 #undef GET_NEXTIV16
4537 #undef GET_NEXTIV32
4538 }
4539 
4540 int
4541 bwn_switch_channel(struct bwn_mac *mac, int chan)
4542 {
4543 	struct bwn_phy *phy = &(mac->mac_phy);
4544 	struct bwn_softc *sc = mac->mac_sc;
4545 	struct ieee80211com *ic = &sc->sc_ic;
4546 	uint16_t channelcookie, savedcookie;
4547 	int error;
4548 
4549 	if (chan == 0xffff)
4550 		chan = phy->get_default_chan(mac);
4551 
4552 	channelcookie = chan;
4553 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
4554 		channelcookie |= 0x100;
4555 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
4556 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
4557 	error = phy->switch_channel(mac, chan);
4558 	if (error)
4559 		goto fail;
4560 
4561 	mac->mac_phy.chan = chan;
4562 	DELAY(8000);
4563 	return (0);
4564 fail:
4565 	device_printf(sc->sc_dev, "failed to switch channel\n");
4566 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
4567 	return (error);
4568 }
4569 
4570 static uint16_t
4571 bwn_ant2phy(int antenna)
4572 {
4573 
4574 	switch (antenna) {
4575 	case BWN_ANT0:
4576 		return (BWN_TX_PHY_ANT0);
4577 	case BWN_ANT1:
4578 		return (BWN_TX_PHY_ANT1);
4579 	case BWN_ANT2:
4580 		return (BWN_TX_PHY_ANT2);
4581 	case BWN_ANT3:
4582 		return (BWN_TX_PHY_ANT3);
4583 	case BWN_ANTAUTO:
4584 		return (BWN_TX_PHY_ANT01AUTO);
4585 	}
4586 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4587 	return (0);
4588 }
4589 
4590 static void
4591 bwn_wme_load(struct bwn_mac *mac)
4592 {
4593 	struct bwn_softc *sc = mac->mac_sc;
4594 	int i;
4595 
4596 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
4597 	    ("%s:%d: fail", __func__, __LINE__));
4598 
4599 	bwn_mac_suspend(mac);
4600 	for (i = 0; i < N(sc->sc_wmeParams); i++)
4601 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
4602 		    bwn_wme_shm_offsets[i]);
4603 	bwn_mac_enable(mac);
4604 }
4605 
4606 static void
4607 bwn_wme_loadparams(struct bwn_mac *mac,
4608     const struct wmeParams *p, uint16_t shm_offset)
4609 {
4610 	struct bwn_softc *sc = mac->mac_sc;
4611 	uint16_t params[BWN_NR_WMEPARAMS];
4612 	int slot, tmp;
4613 	unsigned int i;
4614 
4615 	slot = BWN_READ_2(mac, BWN_RNG) &
4616 	    _IEEE80211_SHIFTMASK(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4617 
4618 	memset(&params, 0, sizeof(params));
4619 
4620 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
4621 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
4622 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
4623 
4624 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
4625 	params[BWN_WMEPARAM_CWMIN] =
4626 	    _IEEE80211_SHIFTMASK(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4627 	params[BWN_WMEPARAM_CWMAX] =
4628 	     _IEEE80211_SHIFTMASK(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
4629 	params[BWN_WMEPARAM_CWCUR] =
4630 	     _IEEE80211_SHIFTMASK(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4631 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
4632 	params[BWN_WMEPARAM_BSLOTS] = slot;
4633 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
4634 
4635 	for (i = 0; i < N(params); i++) {
4636 		if (i == BWN_WMEPARAM_STATUS) {
4637 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
4638 			    shm_offset + (i * 2));
4639 			tmp |= 0x100;
4640 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4641 			    tmp);
4642 		} else {
4643 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4644 			    params[i]);
4645 		}
4646 	}
4647 }
4648 
4649 static void
4650 bwn_mac_write_bssid(struct bwn_mac *mac)
4651 {
4652 	struct bwn_softc *sc = mac->mac_sc;
4653 	uint32_t tmp;
4654 	int i;
4655 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
4656 
4657 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
4658 	memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
4659 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
4660 	    IEEE80211_ADDR_LEN);
4661 
4662 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
4663 		tmp = (uint32_t) (mac_bssid[i + 0]);
4664 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
4665 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
4666 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
4667 		bwn_ram_write(mac, 0x20 + i, tmp);
4668 	}
4669 }
4670 
4671 static void
4672 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
4673     const uint8_t *macaddr)
4674 {
4675 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
4676 	uint16_t data;
4677 
4678 	if (!mac)
4679 		macaddr = zero;
4680 
4681 	offset |= 0x0020;
4682 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
4683 
4684 	data = macaddr[0];
4685 	data |= macaddr[1] << 8;
4686 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4687 	data = macaddr[2];
4688 	data |= macaddr[3] << 8;
4689 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4690 	data = macaddr[4];
4691 	data |= macaddr[5] << 8;
4692 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4693 }
4694 
4695 static void
4696 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4697     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
4698 {
4699 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
4700 	uint8_t per_sta_keys_start = 8;
4701 
4702 	if (BWN_SEC_NEWAPI(mac))
4703 		per_sta_keys_start = 4;
4704 
4705 	KASSERT(index < mac->mac_max_nr_keys,
4706 	    ("%s:%d: fail", __func__, __LINE__));
4707 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
4708 	    ("%s:%d: fail", __func__, __LINE__));
4709 
4710 	if (index >= per_sta_keys_start)
4711 		bwn_key_macwrite(mac, index, NULL);
4712 	if (key)
4713 		memcpy(buf, key, key_len);
4714 	bwn_key_write(mac, index, algorithm, buf);
4715 	if (index >= per_sta_keys_start)
4716 		bwn_key_macwrite(mac, index, mac_addr);
4717 
4718 	mac->mac_key[index].algorithm = algorithm;
4719 }
4720 
4721 static void
4722 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
4723 {
4724 	struct bwn_softc *sc = mac->mac_sc;
4725 	uint32_t addrtmp[2] = { 0, 0 };
4726 	uint8_t start = 8;
4727 
4728 	if (BWN_SEC_NEWAPI(mac))
4729 		start = 4;
4730 
4731 	KASSERT(index >= start,
4732 	    ("%s:%d: fail", __func__, __LINE__));
4733 	index -= start;
4734 
4735 	if (addr) {
4736 		addrtmp[0] = addr[0];
4737 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
4738 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
4739 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
4740 		addrtmp[1] = addr[4];
4741 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
4742 	}
4743 
4744 	if (bhnd_get_hwrev(sc->sc_dev) >= 5) {
4745 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
4746 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
4747 	} else {
4748 		if (index >= 8) {
4749 			bwn_shm_write_4(mac, BWN_SHARED,
4750 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
4751 			bwn_shm_write_2(mac, BWN_SHARED,
4752 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
4753 		}
4754 	}
4755 }
4756 
4757 static void
4758 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4759     const uint8_t *key)
4760 {
4761 	unsigned int i;
4762 	uint32_t offset;
4763 	uint16_t kidx, value;
4764 
4765 	kidx = BWN_SEC_KEY2FW(mac, index);
4766 	bwn_shm_write_2(mac, BWN_SHARED,
4767 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
4768 
4769 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
4770 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
4771 		value = key[i];
4772 		value |= (uint16_t)(key[i + 1]) << 8;
4773 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
4774 	}
4775 }
4776 
4777 static void
4778 bwn_phy_exit(struct bwn_mac *mac)
4779 {
4780 
4781 	mac->mac_phy.rf_onoff(mac, 0);
4782 	if (mac->mac_phy.exit != NULL)
4783 		mac->mac_phy.exit(mac);
4784 }
4785 
4786 static void
4787 bwn_dma_free(struct bwn_mac *mac)
4788 {
4789 	struct bwn_dma *dma;
4790 
4791 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
4792 		return;
4793 	dma = &mac->mac_method.dma;
4794 
4795 	bwn_dma_ringfree(&dma->rx);
4796 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
4797 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
4798 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
4799 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
4800 	bwn_dma_ringfree(&dma->mcast);
4801 }
4802 
4803 static void
4804 bwn_core_stop(struct bwn_mac *mac)
4805 {
4806 	struct bwn_softc *sc = mac->mac_sc;
4807 
4808 	BWN_ASSERT_LOCKED(sc);
4809 
4810 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
4811 		return;
4812 
4813 	callout_stop(&sc->sc_rfswitch_ch);
4814 	callout_stop(&sc->sc_task_ch);
4815 	callout_stop(&sc->sc_watchdog_ch);
4816 	sc->sc_watchdog_timer = 0;
4817 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4818 	BWN_READ_4(mac, BWN_INTR_MASK);
4819 	bwn_mac_suspend(mac);
4820 
4821 	mac->mac_status = BWN_MAC_STATUS_INITED;
4822 }
4823 
4824 static int
4825 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
4826 {
4827 	struct bwn_mac *up_dev = NULL;
4828 	struct bwn_mac *down_dev;
4829 	struct bwn_mac *mac;
4830 	int err, status;
4831 	uint8_t gmode;
4832 
4833 	BWN_ASSERT_LOCKED(sc);
4834 
4835 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
4836 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
4837 		    mac->mac_phy.supports_2ghz) {
4838 			up_dev = mac;
4839 			gmode = 1;
4840 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
4841 		    mac->mac_phy.supports_5ghz) {
4842 			up_dev = mac;
4843 			gmode = 0;
4844 		} else {
4845 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4846 			return (EINVAL);
4847 		}
4848 		if (up_dev != NULL)
4849 			break;
4850 	}
4851 	if (up_dev == NULL) {
4852 		device_printf(sc->sc_dev, "Could not find a device\n");
4853 		return (ENODEV);
4854 	}
4855 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
4856 		return (0);
4857 
4858 	DPRINTF(sc, BWN_DEBUG_RF | BWN_DEBUG_PHY | BWN_DEBUG_RESET,
4859 	    "switching to %s-GHz band\n",
4860 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4861 
4862 	down_dev = sc->sc_curmac;
4863 	status = down_dev->mac_status;
4864 	if (status >= BWN_MAC_STATUS_STARTED)
4865 		bwn_core_stop(down_dev);
4866 	if (status >= BWN_MAC_STATUS_INITED)
4867 		bwn_core_exit(down_dev);
4868 
4869 	if (down_dev != up_dev) {
4870 		err = bwn_phy_reset(down_dev);
4871 		if (err)
4872 			goto fail;
4873 	}
4874 
4875 	up_dev->mac_phy.gmode = gmode;
4876 	if (status >= BWN_MAC_STATUS_INITED) {
4877 		err = bwn_core_init(up_dev);
4878 		if (err) {
4879 			device_printf(sc->sc_dev,
4880 			    "fatal: failed to initialize for %s-GHz\n",
4881 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4882 			goto fail;
4883 		}
4884 	}
4885 	if (status >= BWN_MAC_STATUS_STARTED)
4886 		bwn_core_start(up_dev);
4887 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
4888 	sc->sc_curmac = up_dev;
4889 
4890 	return (0);
4891 fail:
4892 	sc->sc_curmac = NULL;
4893 	return (err);
4894 }
4895 
4896 static void
4897 bwn_rf_turnon(struct bwn_mac *mac)
4898 {
4899 
4900 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4901 
4902 	bwn_mac_suspend(mac);
4903 	mac->mac_phy.rf_onoff(mac, 1);
4904 	mac->mac_phy.rf_on = 1;
4905 	bwn_mac_enable(mac);
4906 }
4907 
4908 static void
4909 bwn_rf_turnoff(struct bwn_mac *mac)
4910 {
4911 
4912 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4913 
4914 	bwn_mac_suspend(mac);
4915 	mac->mac_phy.rf_onoff(mac, 0);
4916 	mac->mac_phy.rf_on = 0;
4917 	bwn_mac_enable(mac);
4918 }
4919 
4920 /*
4921  * PHY reset.
4922  */
4923 static int
4924 bwn_phy_reset(struct bwn_mac *mac)
4925 {
4926 	struct bwn_softc	*sc;
4927 	uint16_t		 iost, mask;
4928 	int			 error;
4929 
4930 	sc = mac->mac_sc;
4931 
4932 	iost = BWN_IOCTL_PHYRESET | BHND_IOCTL_CLK_FORCE;
4933 	mask = iost | BWN_IOCTL_SUPPORT_G;
4934 
4935 	if ((error = bhnd_write_ioctl(sc->sc_dev, iost, mask)))
4936 		return (error);
4937 
4938 	DELAY(1000);
4939 
4940 	iost &= ~BHND_IOCTL_CLK_FORCE;
4941 
4942 	if ((error = bhnd_write_ioctl(sc->sc_dev, iost, mask)))
4943 		return (error);
4944 
4945 	DELAY(1000);
4946 
4947 	return (0);
4948 }
4949 
4950 static int
4951 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
4952 {
4953 	struct bwn_vap *bvp = BWN_VAP(vap);
4954 	struct ieee80211com *ic= vap->iv_ic;
4955 	enum ieee80211_state ostate = vap->iv_state;
4956 	struct bwn_softc *sc = ic->ic_softc;
4957 	struct bwn_mac *mac = sc->sc_curmac;
4958 	int error;
4959 
4960 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
4961 	    ieee80211_state_name[vap->iv_state],
4962 	    ieee80211_state_name[nstate]);
4963 
4964 	error = bvp->bv_newstate(vap, nstate, arg);
4965 	if (error != 0)
4966 		return (error);
4967 
4968 	BWN_LOCK(sc);
4969 
4970 	bwn_led_newstate(mac, nstate);
4971 
4972 	/*
4973 	 * Clear the BSSID when we stop a STA
4974 	 */
4975 	if (vap->iv_opmode == IEEE80211_M_STA) {
4976 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
4977 			/*
4978 			 * Clear out the BSSID.  If we reassociate to
4979 			 * the same AP, this will reinialize things
4980 			 * correctly...
4981 			 */
4982 			if (ic->ic_opmode == IEEE80211_M_STA &&
4983 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
4984 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
4985 				bwn_set_macaddr(mac);
4986 			}
4987 		}
4988 	}
4989 
4990 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
4991 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
4992 		/* XXX nothing to do? */
4993 	} else if (nstate == IEEE80211_S_RUN) {
4994 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
4995 		bwn_set_opmode(mac);
4996 		bwn_set_pretbtt(mac);
4997 		bwn_spu_setdelay(mac, 0);
4998 		bwn_set_macaddr(mac);
4999 	}
5000 
5001 	BWN_UNLOCK(sc);
5002 
5003 	return (error);
5004 }
5005 
5006 static void
5007 bwn_set_pretbtt(struct bwn_mac *mac)
5008 {
5009 	struct bwn_softc *sc = mac->mac_sc;
5010 	struct ieee80211com *ic = &sc->sc_ic;
5011 	uint16_t pretbtt;
5012 
5013 	if (ic->ic_opmode == IEEE80211_M_IBSS)
5014 		pretbtt = 2;
5015 	else
5016 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
5017 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
5018 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
5019 }
5020 
5021 static int
5022 bwn_intr(void *arg)
5023 {
5024 	struct bwn_mac *mac = arg;
5025 	struct bwn_softc *sc = mac->mac_sc;
5026 	uint32_t reason;
5027 
5028 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
5029 	    (sc->sc_flags & BWN_FLAG_INVALID))
5030 		return (FILTER_STRAY);
5031 
5032 	DPRINTF(sc, BWN_DEBUG_INTR, "%s: called\n", __func__);
5033 
5034 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
5035 	if (reason == 0xffffffff)	/* shared IRQ */
5036 		return (FILTER_STRAY);
5037 	reason &= mac->mac_intr_mask;
5038 	if (reason == 0)
5039 		return (FILTER_HANDLED);
5040 	DPRINTF(sc, BWN_DEBUG_INTR, "%s: reason=0x%08x\n", __func__, reason);
5041 
5042 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
5043 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
5044 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
5045 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
5046 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
5047 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
5048 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
5049 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
5050 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
5051 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
5052 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
5053 
5054 	/* Disable interrupts. */
5055 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
5056 
5057 	mac->mac_reason_intr = reason;
5058 
5059 	BWN_BARRIER(mac, 0, 0, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
5060 
5061 	taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask);
5062 	return (FILTER_HANDLED);
5063 }
5064 
5065 static void
5066 bwn_intrtask(void *arg, int npending)
5067 {
5068 	struct bwn_mac *mac = arg;
5069 	struct bwn_softc *sc = mac->mac_sc;
5070 	uint32_t merged = 0;
5071 	int i, tx = 0, rx = 0;
5072 
5073 	BWN_LOCK(sc);
5074 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
5075 	    (sc->sc_flags & BWN_FLAG_INVALID)) {
5076 		BWN_UNLOCK(sc);
5077 		return;
5078 	}
5079 
5080 	for (i = 0; i < N(mac->mac_reason); i++)
5081 		merged |= mac->mac_reason[i];
5082 
5083 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
5084 		device_printf(sc->sc_dev, "MAC trans error\n");
5085 
5086 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
5087 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
5088 		mac->mac_phy.txerrors--;
5089 		if (mac->mac_phy.txerrors == 0) {
5090 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
5091 			bwn_restart(mac, "PHY TX errors");
5092 		}
5093 	}
5094 
5095 	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
5096 		if (merged & BWN_DMAINTR_FATALMASK) {
5097 			device_printf(sc->sc_dev,
5098 			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
5099 			    mac->mac_reason[0], mac->mac_reason[1],
5100 			    mac->mac_reason[2], mac->mac_reason[3],
5101 			    mac->mac_reason[4], mac->mac_reason[5]);
5102 			bwn_restart(mac, "DMA error");
5103 			BWN_UNLOCK(sc);
5104 			return;
5105 		}
5106 		if (merged & BWN_DMAINTR_NONFATALMASK) {
5107 			device_printf(sc->sc_dev,
5108 			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
5109 			    mac->mac_reason[0], mac->mac_reason[1],
5110 			    mac->mac_reason[2], mac->mac_reason[3],
5111 			    mac->mac_reason[4], mac->mac_reason[5]);
5112 		}
5113 	}
5114 
5115 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
5116 		bwn_intr_ucode_debug(mac);
5117 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
5118 		bwn_intr_tbtt_indication(mac);
5119 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
5120 		bwn_intr_atim_end(mac);
5121 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
5122 		bwn_intr_beacon(mac);
5123 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
5124 		bwn_intr_pmq(mac);
5125 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
5126 		bwn_intr_noise(mac);
5127 
5128 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
5129 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
5130 			bwn_dma_rx(mac->mac_method.dma.rx);
5131 			rx = 1;
5132 		}
5133 	} else
5134 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
5135 
5136 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5137 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5138 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5139 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5140 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5141 
5142 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
5143 		bwn_intr_txeof(mac);
5144 		tx = 1;
5145 	}
5146 
5147 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
5148 
5149 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
5150 		int evt = BWN_LED_EVENT_NONE;
5151 
5152 		if (tx && rx) {
5153 			if (sc->sc_rx_rate > sc->sc_tx_rate)
5154 				evt = BWN_LED_EVENT_RX;
5155 			else
5156 				evt = BWN_LED_EVENT_TX;
5157 		} else if (tx) {
5158 			evt = BWN_LED_EVENT_TX;
5159 		} else if (rx) {
5160 			evt = BWN_LED_EVENT_RX;
5161 		} else if (rx == 0) {
5162 			evt = BWN_LED_EVENT_POLL;
5163 		}
5164 
5165 		if (evt != BWN_LED_EVENT_NONE)
5166 			bwn_led_event(mac, evt);
5167        }
5168 
5169 	if (mbufq_first(&sc->sc_snd) != NULL)
5170 		bwn_start(sc);
5171 
5172 	BWN_BARRIER(mac, 0, 0, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
5173 
5174 	BWN_UNLOCK(sc);
5175 }
5176 
5177 static void
5178 bwn_restart(struct bwn_mac *mac, const char *msg)
5179 {
5180 	struct bwn_softc *sc = mac->mac_sc;
5181 	struct ieee80211com *ic = &sc->sc_ic;
5182 
5183 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
5184 		return;
5185 
5186 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
5187 	ieee80211_runtask(ic, &mac->mac_hwreset);
5188 }
5189 
5190 static void
5191 bwn_intr_ucode_debug(struct bwn_mac *mac)
5192 {
5193 	struct bwn_softc *sc = mac->mac_sc;
5194 	uint16_t reason;
5195 
5196 	if (mac->mac_fw.opensource == 0)
5197 		return;
5198 
5199 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
5200 	switch (reason) {
5201 	case BWN_DEBUGINTR_PANIC:
5202 		bwn_handle_fwpanic(mac);
5203 		break;
5204 	case BWN_DEBUGINTR_DUMP_SHM:
5205 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
5206 		break;
5207 	case BWN_DEBUGINTR_DUMP_REGS:
5208 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
5209 		break;
5210 	case BWN_DEBUGINTR_MARKER:
5211 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
5212 		break;
5213 	default:
5214 		device_printf(sc->sc_dev,
5215 		    "ucode debug unknown reason: %#x\n", reason);
5216 	}
5217 
5218 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
5219 	    BWN_DEBUGINTR_ACK);
5220 }
5221 
5222 static void
5223 bwn_intr_tbtt_indication(struct bwn_mac *mac)
5224 {
5225 	struct bwn_softc *sc = mac->mac_sc;
5226 	struct ieee80211com *ic = &sc->sc_ic;
5227 
5228 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
5229 		bwn_psctl(mac, 0);
5230 	if (ic->ic_opmode == IEEE80211_M_IBSS)
5231 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
5232 }
5233 
5234 static void
5235 bwn_intr_atim_end(struct bwn_mac *mac)
5236 {
5237 
5238 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
5239 		BWN_WRITE_4(mac, BWN_MACCMD,
5240 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
5241 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
5242 	}
5243 }
5244 
5245 static void
5246 bwn_intr_beacon(struct bwn_mac *mac)
5247 {
5248 	struct bwn_softc *sc = mac->mac_sc;
5249 	struct ieee80211com *ic = &sc->sc_ic;
5250 	uint32_t cmd, beacon0, beacon1;
5251 
5252 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
5253 	    ic->ic_opmode == IEEE80211_M_MBSS)
5254 		return;
5255 
5256 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
5257 
5258 	cmd = BWN_READ_4(mac, BWN_MACCMD);
5259 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
5260 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
5261 
5262 	if (beacon0 && beacon1) {
5263 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
5264 		mac->mac_intr_mask |= BWN_INTR_BEACON;
5265 		return;
5266 	}
5267 
5268 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
5269 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
5270 		bwn_load_beacon0(mac);
5271 		bwn_load_beacon1(mac);
5272 		cmd = BWN_READ_4(mac, BWN_MACCMD);
5273 		cmd |= BWN_MACCMD_BEACON0_VALID;
5274 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5275 	} else {
5276 		if (!beacon0) {
5277 			bwn_load_beacon0(mac);
5278 			cmd = BWN_READ_4(mac, BWN_MACCMD);
5279 			cmd |= BWN_MACCMD_BEACON0_VALID;
5280 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5281 		} else if (!beacon1) {
5282 			bwn_load_beacon1(mac);
5283 			cmd = BWN_READ_4(mac, BWN_MACCMD);
5284 			cmd |= BWN_MACCMD_BEACON1_VALID;
5285 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5286 		}
5287 	}
5288 }
5289 
5290 static void
5291 bwn_intr_pmq(struct bwn_mac *mac)
5292 {
5293 	uint32_t tmp;
5294 
5295 	while (1) {
5296 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
5297 		if (!(tmp & 0x00000008))
5298 			break;
5299 	}
5300 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
5301 }
5302 
5303 static void
5304 bwn_intr_noise(struct bwn_mac *mac)
5305 {
5306 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5307 	uint16_t tmp;
5308 	uint8_t noise[4];
5309 	uint8_t i, j;
5310 	int32_t average;
5311 
5312 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
5313 		return;
5314 
5315 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
5316 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
5317 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
5318 	    noise[3] == 0x7f)
5319 		goto new;
5320 
5321 	KASSERT(mac->mac_noise.noi_nsamples < 8,
5322 	    ("%s:%d: fail", __func__, __LINE__));
5323 	i = mac->mac_noise.noi_nsamples;
5324 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
5325 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
5326 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
5327 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
5328 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
5329 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
5330 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
5331 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
5332 	mac->mac_noise.noi_nsamples++;
5333 	if (mac->mac_noise.noi_nsamples == 8) {
5334 		average = 0;
5335 		for (i = 0; i < 8; i++) {
5336 			for (j = 0; j < 4; j++)
5337 				average += mac->mac_noise.noi_samples[i][j];
5338 		}
5339 		average = (((average / 32) * 125) + 64) / 128;
5340 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
5341 		if (tmp >= 8)
5342 			average += 2;
5343 		else
5344 			average -= 25;
5345 		average -= (tmp == 8) ? 72 : 48;
5346 
5347 		mac->mac_stats.link_noise = average;
5348 		mac->mac_noise.noi_running = 0;
5349 		return;
5350 	}
5351 new:
5352 	bwn_noise_gensample(mac);
5353 }
5354 
5355 static int
5356 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
5357 {
5358 	struct bwn_mac *mac = prq->prq_mac;
5359 	struct bwn_softc *sc = mac->mac_sc;
5360 	unsigned int i;
5361 
5362 	BWN_ASSERT_LOCKED(sc);
5363 
5364 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
5365 		return (0);
5366 
5367 	for (i = 0; i < 5000; i++) {
5368 		if (bwn_pio_rxeof(prq) == 0)
5369 			break;
5370 	}
5371 	if (i >= 5000)
5372 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
5373 	return ((i > 0) ? 1 : 0);
5374 }
5375 
5376 static void
5377 bwn_dma_rx(struct bwn_dma_ring *dr)
5378 {
5379 	int slot, curslot;
5380 
5381 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5382 	curslot = dr->get_curslot(dr);
5383 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
5384 	    ("%s:%d: fail", __func__, __LINE__));
5385 
5386 	slot = dr->dr_curslot;
5387 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
5388 		bwn_dma_rxeof(dr, &slot);
5389 
5390 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
5391 	    BUS_DMASYNC_PREWRITE);
5392 
5393 	dr->set_curslot(dr, slot);
5394 	dr->dr_curslot = slot;
5395 }
5396 
5397 static void
5398 bwn_intr_txeof(struct bwn_mac *mac)
5399 {
5400 	struct bwn_txstatus stat;
5401 	uint32_t stat0, stat1;
5402 	uint16_t tmp;
5403 
5404 	BWN_ASSERT_LOCKED(mac->mac_sc);
5405 
5406 	while (1) {
5407 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
5408 		if (!(stat0 & 0x00000001))
5409 			break;
5410 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
5411 
5412 		DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5413 		    "%s: stat0=0x%08x, stat1=0x%08x\n",
5414 		    __func__,
5415 		    stat0,
5416 		    stat1);
5417 
5418 		stat.cookie = (stat0 >> 16);
5419 		stat.seq = (stat1 & 0x0000ffff);
5420 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
5421 		tmp = (stat0 & 0x0000ffff);
5422 		stat.framecnt = ((tmp & 0xf000) >> 12);
5423 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
5424 		stat.sreason = ((tmp & 0x001c) >> 2);
5425 		stat.pm = (tmp & 0x0080) ? 1 : 0;
5426 		stat.im = (tmp & 0x0040) ? 1 : 0;
5427 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
5428 		stat.ack = (tmp & 0x0002) ? 1 : 0;
5429 
5430 		DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5431 		    "%s: cookie=%d, seq=%d, phystat=0x%02x, framecnt=%d, "
5432 		    "rtscnt=%d, sreason=%d, pm=%d, im=%d, ampdu=%d, ack=%d\n",
5433 		    __func__,
5434 		    stat.cookie,
5435 		    stat.seq,
5436 		    stat.phy_stat,
5437 		    stat.framecnt,
5438 		    stat.rtscnt,
5439 		    stat.sreason,
5440 		    stat.pm,
5441 		    stat.im,
5442 		    stat.ampdu,
5443 		    stat.ack);
5444 
5445 		bwn_handle_txeof(mac, &stat);
5446 	}
5447 }
5448 
5449 static void
5450 bwn_hwreset(void *arg, int npending)
5451 {
5452 	struct bwn_mac *mac = arg;
5453 	struct bwn_softc *sc = mac->mac_sc;
5454 	int error = 0;
5455 	int prev_status;
5456 
5457 	BWN_LOCK(sc);
5458 
5459 	prev_status = mac->mac_status;
5460 	if (prev_status >= BWN_MAC_STATUS_STARTED)
5461 		bwn_core_stop(mac);
5462 	if (prev_status >= BWN_MAC_STATUS_INITED)
5463 		bwn_core_exit(mac);
5464 
5465 	if (prev_status >= BWN_MAC_STATUS_INITED) {
5466 		error = bwn_core_init(mac);
5467 		if (error)
5468 			goto out;
5469 	}
5470 	if (prev_status >= BWN_MAC_STATUS_STARTED)
5471 		bwn_core_start(mac);
5472 out:
5473 	if (error) {
5474 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
5475 		sc->sc_curmac = NULL;
5476 	}
5477 	BWN_UNLOCK(sc);
5478 }
5479 
5480 static void
5481 bwn_handle_fwpanic(struct bwn_mac *mac)
5482 {
5483 	struct bwn_softc *sc = mac->mac_sc;
5484 	uint16_t reason;
5485 
5486 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
5487 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
5488 
5489 	if (reason == BWN_FWPANIC_RESTART)
5490 		bwn_restart(mac, "ucode panic");
5491 }
5492 
5493 static void
5494 bwn_load_beacon0(struct bwn_mac *mac)
5495 {
5496 
5497 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5498 }
5499 
5500 static void
5501 bwn_load_beacon1(struct bwn_mac *mac)
5502 {
5503 
5504 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5505 }
5506 
5507 static uint32_t
5508 bwn_jssi_read(struct bwn_mac *mac)
5509 {
5510 	uint32_t val = 0;
5511 
5512 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
5513 	val <<= 16;
5514 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
5515 
5516 	return (val);
5517 }
5518 
5519 static void
5520 bwn_noise_gensample(struct bwn_mac *mac)
5521 {
5522 	uint32_t jssi = 0x7f7f7f7f;
5523 
5524 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
5525 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
5526 	BWN_WRITE_4(mac, BWN_MACCMD,
5527 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
5528 }
5529 
5530 static int
5531 bwn_dma_freeslot(struct bwn_dma_ring *dr)
5532 {
5533 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5534 
5535 	return (dr->dr_numslots - dr->dr_usedslot);
5536 }
5537 
5538 static int
5539 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
5540 {
5541 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5542 
5543 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
5544 	    ("%s:%d: fail", __func__, __LINE__));
5545 	if (slot == dr->dr_numslots - 1)
5546 		return (0);
5547 	return (slot + 1);
5548 }
5549 
5550 static void
5551 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
5552 {
5553 	struct bwn_mac *mac = dr->dr_mac;
5554 	struct bwn_softc *sc = mac->mac_sc;
5555 	struct bwn_dma *dma = &mac->mac_method.dma;
5556 	struct bwn_dmadesc_generic *desc;
5557 	struct bwn_dmadesc_meta *meta;
5558 	struct bwn_rxhdr4 *rxhdr;
5559 	struct mbuf *m;
5560 	uint32_t macstat;
5561 	int32_t tmp;
5562 	int cnt = 0;
5563 	uint16_t len;
5564 
5565 	dr->getdesc(dr, *slot, &desc, &meta);
5566 
5567 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
5568 	m = meta->mt_m;
5569 
5570 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
5571 		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5572 		return;
5573 	}
5574 
5575 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
5576 	len = le16toh(rxhdr->frame_len);
5577 	if (len <= 0) {
5578 		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5579 		return;
5580 	}
5581 	if (bwn_dma_check_redzone(dr, m)) {
5582 		device_printf(sc->sc_dev, "redzone error.\n");
5583 		bwn_dma_set_redzone(dr, m);
5584 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5585 		    BUS_DMASYNC_PREWRITE);
5586 		return;
5587 	}
5588 	if (len > dr->dr_rx_bufsize) {
5589 		tmp = len;
5590 		while (1) {
5591 			dr->getdesc(dr, *slot, &desc, &meta);
5592 			bwn_dma_set_redzone(dr, meta->mt_m);
5593 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5594 			    BUS_DMASYNC_PREWRITE);
5595 			*slot = bwn_dma_nextslot(dr, *slot);
5596 			cnt++;
5597 			tmp -= dr->dr_rx_bufsize;
5598 			if (tmp <= 0)
5599 				break;
5600 		}
5601 		device_printf(sc->sc_dev, "too small buffer "
5602 		       "(len %u buffer %u dropped %d)\n",
5603 		       len, dr->dr_rx_bufsize, cnt);
5604 		return;
5605 	}
5606 
5607 	switch (mac->mac_fw.fw_hdr_format) {
5608 	case BWN_FW_HDR_351:
5609 	case BWN_FW_HDR_410:
5610 		macstat = le32toh(rxhdr->ps4.r351.mac_status);
5611 		break;
5612 	case BWN_FW_HDR_598:
5613 		macstat = le32toh(rxhdr->ps4.r598.mac_status);
5614 		break;
5615 	}
5616 
5617 	if (macstat & BWN_RX_MAC_FCSERR) {
5618 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5619 			device_printf(sc->sc_dev, "RX drop\n");
5620 			return;
5621 		}
5622 	}
5623 
5624 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
5625 	m_adj(m, dr->dr_frameoffset);
5626 
5627 	bwn_rxeof(dr->dr_mac, m, rxhdr);
5628 }
5629 
5630 static void
5631 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
5632 {
5633 	struct bwn_softc *sc = mac->mac_sc;
5634 	struct bwn_stats *stats = &mac->mac_stats;
5635 
5636 	BWN_ASSERT_LOCKED(mac->mac_sc);
5637 
5638 	if (status->im)
5639 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
5640 	if (status->ampdu)
5641 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
5642 	if (status->rtscnt) {
5643 		if (status->rtscnt == 0xf)
5644 			stats->rtsfail++;
5645 		else
5646 			stats->rts++;
5647 	}
5648 
5649 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
5650 		bwn_dma_handle_txeof(mac, status);
5651 	} else {
5652 		bwn_pio_handle_txeof(mac, status);
5653 	}
5654 
5655 	bwn_phy_txpower_check(mac, 0);
5656 }
5657 
5658 static uint8_t
5659 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
5660 {
5661 	struct bwn_mac *mac = prq->prq_mac;
5662 	struct bwn_softc *sc = mac->mac_sc;
5663 	struct bwn_rxhdr4 rxhdr;
5664 	struct mbuf *m;
5665 	uint32_t ctl32, macstat, v32;
5666 	unsigned int i, padding;
5667 	uint16_t ctl16, len, totlen, v16;
5668 	unsigned char *mp;
5669 	char *data;
5670 
5671 	memset(&rxhdr, 0, sizeof(rxhdr));
5672 
5673 	if (prq->prq_rev >= 8) {
5674 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5675 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
5676 			return (0);
5677 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5678 		    BWN_PIO8_RXCTL_FRAMEREADY);
5679 		for (i = 0; i < 10; i++) {
5680 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5681 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
5682 				goto ready;
5683 			DELAY(10);
5684 		}
5685 	} else {
5686 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5687 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
5688 			return (0);
5689 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
5690 		    BWN_PIO_RXCTL_FRAMEREADY);
5691 		for (i = 0; i < 10; i++) {
5692 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5693 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
5694 				goto ready;
5695 			DELAY(10);
5696 		}
5697 	}
5698 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
5699 	return (1);
5700 ready:
5701 	if (prq->prq_rev >= 8) {
5702 		bus_read_multi_4(sc->sc_mem_res,
5703 		    prq->prq_base + BWN_PIO8_RXDATA, (void *)&rxhdr,
5704 		    sizeof(rxhdr));
5705 	} else {
5706 		bus_read_multi_2(sc->sc_mem_res,
5707 		    prq->prq_base + BWN_PIO_RXDATA, (void *)&rxhdr,
5708 		    sizeof(rxhdr));
5709 	}
5710 	len = le16toh(rxhdr.frame_len);
5711 	if (len > 0x700) {
5712 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
5713 		goto error;
5714 	}
5715 	if (len == 0) {
5716 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
5717 		goto error;
5718 	}
5719 
5720 	switch (mac->mac_fw.fw_hdr_format) {
5721 	case BWN_FW_HDR_351:
5722 	case BWN_FW_HDR_410:
5723 		macstat = le32toh(rxhdr.ps4.r351.mac_status);
5724 		break;
5725 	case BWN_FW_HDR_598:
5726 		macstat = le32toh(rxhdr.ps4.r598.mac_status);
5727 		break;
5728 	}
5729 
5730 	if (macstat & BWN_RX_MAC_FCSERR) {
5731 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5732 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
5733 			goto error;
5734 		}
5735 	}
5736 
5737 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5738 	totlen = len + padding;
5739 	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
5740 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5741 	if (m == NULL) {
5742 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
5743 		goto error;
5744 	}
5745 	mp = mtod(m, unsigned char *);
5746 	if (prq->prq_rev >= 8) {
5747 		bus_read_multi_4(sc->sc_mem_res,
5748 		    prq->prq_base + BWN_PIO8_RXDATA, (void *)mp, (totlen & ~3));
5749 		if (totlen & 3) {
5750 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
5751 			data = &(mp[totlen - 1]);
5752 			switch (totlen & 3) {
5753 			case 3:
5754 				*data = (v32 >> 16);
5755 				data--;
5756 			case 2:
5757 				*data = (v32 >> 8);
5758 				data--;
5759 			case 1:
5760 				*data = v32;
5761 			}
5762 		}
5763 	} else {
5764 		bus_read_multi_2(sc->sc_mem_res,
5765 		    prq->prq_base + BWN_PIO_RXDATA, (void *)mp, (totlen & ~1));
5766 		if (totlen & 1) {
5767 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
5768 			mp[totlen - 1] = v16;
5769 		}
5770 	}
5771 
5772 	m->m_len = m->m_pkthdr.len = totlen;
5773 
5774 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
5775 
5776 	return (1);
5777 error:
5778 	if (prq->prq_rev >= 8)
5779 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5780 		    BWN_PIO8_RXCTL_DATAREADY);
5781 	else
5782 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
5783 	return (1);
5784 }
5785 
5786 static int
5787 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
5788     struct bwn_dmadesc_meta *meta, int init)
5789 {
5790 	struct bwn_mac *mac = dr->dr_mac;
5791 	struct bwn_dma *dma = &mac->mac_method.dma;
5792 	struct bwn_rxhdr4 *hdr;
5793 	bus_dmamap_t map;
5794 	bus_addr_t paddr;
5795 	struct mbuf *m;
5796 	int error;
5797 
5798 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5799 	if (m == NULL) {
5800 		error = ENOBUFS;
5801 
5802 		/*
5803 		 * If the NIC is up and running, we need to:
5804 		 * - Clear RX buffer's header.
5805 		 * - Restore RX descriptor settings.
5806 		 */
5807 		if (init)
5808 			return (error);
5809 		else
5810 			goto back;
5811 	}
5812 	m->m_len = m->m_pkthdr.len = MCLBYTES;
5813 
5814 	bwn_dma_set_redzone(dr, m);
5815 
5816 	/*
5817 	 * Try to load RX buf into temporary DMA map
5818 	 */
5819 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
5820 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
5821 	if (error) {
5822 		m_freem(m);
5823 
5824 		/*
5825 		 * See the comment above
5826 		 */
5827 		if (init)
5828 			return (error);
5829 		else
5830 			goto back;
5831 	}
5832 
5833 	if (!init)
5834 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
5835 	meta->mt_m = m;
5836 	meta->mt_paddr = paddr;
5837 
5838 	/*
5839 	 * Swap RX buf's DMA map with the loaded temporary one
5840 	 */
5841 	map = meta->mt_dmap;
5842 	meta->mt_dmap = dr->dr_spare_dmap;
5843 	dr->dr_spare_dmap = map;
5844 
5845 back:
5846 	/*
5847 	 * Clear RX buf header
5848 	 */
5849 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
5850 	bzero(hdr, sizeof(*hdr));
5851 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5852 	    BUS_DMASYNC_PREWRITE);
5853 
5854 	/*
5855 	 * Setup RX buf descriptor
5856 	 */
5857 	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
5858 	    sizeof(*hdr), 0, 0, 0);
5859 	return (error);
5860 }
5861 
5862 static void
5863 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
5864 		 bus_size_t mapsz __unused, int error)
5865 {
5866 
5867 	if (!error) {
5868 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
5869 		*((bus_addr_t *)arg) = seg->ds_addr;
5870 	}
5871 }
5872 
5873 static int
5874 bwn_hwrate2ieeerate(int rate)
5875 {
5876 
5877 	switch (rate) {
5878 	case BWN_CCK_RATE_1MB:
5879 		return (2);
5880 	case BWN_CCK_RATE_2MB:
5881 		return (4);
5882 	case BWN_CCK_RATE_5MB:
5883 		return (11);
5884 	case BWN_CCK_RATE_11MB:
5885 		return (22);
5886 	case BWN_OFDM_RATE_6MB:
5887 		return (12);
5888 	case BWN_OFDM_RATE_9MB:
5889 		return (18);
5890 	case BWN_OFDM_RATE_12MB:
5891 		return (24);
5892 	case BWN_OFDM_RATE_18MB:
5893 		return (36);
5894 	case BWN_OFDM_RATE_24MB:
5895 		return (48);
5896 	case BWN_OFDM_RATE_36MB:
5897 		return (72);
5898 	case BWN_OFDM_RATE_48MB:
5899 		return (96);
5900 	case BWN_OFDM_RATE_54MB:
5901 		return (108);
5902 	default:
5903 		printf("Ooops\n");
5904 		return (0);
5905 	}
5906 }
5907 
5908 /*
5909  * Post process the RX provided RSSI.
5910  *
5911  * Valid for A, B, G, LP PHYs.
5912  */
5913 static int8_t
5914 bwn_rx_rssi_calc(struct bwn_mac *mac, uint8_t in_rssi,
5915     int ofdm, int adjust_2053, int adjust_2050)
5916 {
5917 	struct bwn_phy *phy = &mac->mac_phy;
5918 	struct bwn_phy_g *gphy = &phy->phy_g;
5919 	int tmp;
5920 
5921 	switch (phy->rf_ver) {
5922 	case 0x2050:
5923 		if (ofdm) {
5924 			tmp = in_rssi;
5925 			if (tmp > 127)
5926 				tmp -= 256;
5927 			tmp = tmp * 73 / 64;
5928 			if (adjust_2050)
5929 				tmp += 25;
5930 			else
5931 				tmp -= 3;
5932 		} else {
5933 			if (mac->mac_sc->sc_board_info.board_flags
5934 			    & BHND_BFL_ADCDIV) {
5935 				if (in_rssi > 63)
5936 					in_rssi = 63;
5937 				tmp = gphy->pg_nrssi_lt[in_rssi];
5938 				tmp = (31 - tmp) * -131 / 128 - 57;
5939 			} else {
5940 				tmp = in_rssi;
5941 				tmp = (31 - tmp) * -149 / 128 - 68;
5942 			}
5943 			if (phy->type == BWN_PHYTYPE_G && adjust_2050)
5944 				tmp += 25;
5945 		}
5946 		break;
5947 	case 0x2060:
5948 		if (in_rssi > 127)
5949 			tmp = in_rssi - 256;
5950 		else
5951 			tmp = in_rssi;
5952 		break;
5953 	default:
5954 		tmp = in_rssi;
5955 		tmp = (tmp - 11) * 103 / 64;
5956 		if (adjust_2053)
5957 			tmp -= 109;
5958 		else
5959 			tmp -= 83;
5960 	}
5961 
5962 	return (tmp);
5963 }
5964 
5965 static void
5966 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
5967 {
5968 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
5969 	struct bwn_plcp6 *plcp;
5970 	struct bwn_softc *sc = mac->mac_sc;
5971 	struct ieee80211_frame_min *wh;
5972 	struct ieee80211_node *ni;
5973 	struct ieee80211com *ic = &sc->sc_ic;
5974 	uint32_t macstat;
5975 	int padding, rate, rssi = 0, noise = 0;
5976 	uint16_t phytype, phystat0, phystat3, chanstat;
5977 	unsigned char *mp = mtod(m, unsigned char *);
5978 
5979 	BWN_ASSERT_LOCKED(sc);
5980 
5981 	phystat0 = le16toh(rxhdr->phy_status0);
5982 
5983 	/*
5984 	 * XXX Note: phy_status3 doesn't exist for HT-PHY; it's only
5985 	 * used for LP-PHY.
5986 	 */
5987 	phystat3 = le16toh(rxhdr->ps3.lp.phy_status3);
5988 
5989 	switch (mac->mac_fw.fw_hdr_format) {
5990 	case BWN_FW_HDR_351:
5991 	case BWN_FW_HDR_410:
5992 		macstat = le32toh(rxhdr->ps4.r351.mac_status);
5993 		chanstat = le16toh(rxhdr->ps4.r351.channel);
5994 		break;
5995 	case BWN_FW_HDR_598:
5996 		macstat = le32toh(rxhdr->ps4.r598.mac_status);
5997 		chanstat = le16toh(rxhdr->ps4.r598.channel);
5998 		break;
5999 	}
6000 
6001 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
6002 
6003 	if (macstat & BWN_RX_MAC_FCSERR)
6004 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
6005 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
6006 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
6007 	if (macstat & BWN_RX_MAC_DECERR)
6008 		goto drop;
6009 
6010 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
6011 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
6012 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
6013 		    m->m_pkthdr.len);
6014 		goto drop;
6015 	}
6016 	plcp = (struct bwn_plcp6 *)(mp + padding);
6017 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
6018 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
6019 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
6020 		    m->m_pkthdr.len);
6021 		goto drop;
6022 	}
6023 	wh = mtod(m, struct ieee80211_frame_min *);
6024 
6025 	if (macstat & BWN_RX_MAC_DEC) {
6026 		DPRINTF(sc, BWN_DEBUG_HWCRYPTO,
6027 		    "RX decryption attempted (old %d keyidx %#x)\n",
6028 		    BWN_ISOLDFMT(mac),
6029 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
6030 	}
6031 
6032 	if (phystat0 & BWN_RX_PHYST0_OFDM)
6033 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
6034 		    phytype == BWN_PHYTYPE_A);
6035 	else
6036 		rate = bwn_plcp_get_cckrate(mac, plcp);
6037 	if (rate == -1) {
6038 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
6039 			goto drop;
6040 	}
6041 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
6042 
6043 	/* rssi/noise */
6044 	switch (phytype) {
6045 	case BWN_PHYTYPE_A:
6046 	case BWN_PHYTYPE_B:
6047 	case BWN_PHYTYPE_G:
6048 	case BWN_PHYTYPE_LP:
6049 		rssi = bwn_rx_rssi_calc(mac, rxhdr->phy.abg.rssi,
6050 		    !! (phystat0 & BWN_RX_PHYST0_OFDM),
6051 		    !! (phystat0 & BWN_RX_PHYST0_GAINCTL),
6052 		    !! (phystat3 & BWN_RX_PHYST3_TRSTATE));
6053 		break;
6054 	case BWN_PHYTYPE_N:
6055 		/* Broadcom has code for min/avg, but always used max */
6056 		if (rxhdr->phy.n.power0 == 16 || rxhdr->phy.n.power0 == 32)
6057 			rssi = max(rxhdr->phy.n.power1, rxhdr->ps2.n.power2);
6058 		else
6059 			rssi = max(rxhdr->phy.n.power0, rxhdr->phy.n.power1);
6060 #if 0
6061 		DPRINTF(mac->mac_sc, BWN_DEBUG_RECV,
6062 		    "%s: power0=%d, power1=%d, power2=%d\n",
6063 		    __func__,
6064 		    rxhdr->phy.n.power0,
6065 		    rxhdr->phy.n.power1,
6066 		    rxhdr->ps2.n.power2);
6067 #endif
6068 		break;
6069 	default:
6070 		/* XXX TODO: implement rssi for other PHYs */
6071 		break;
6072 	}
6073 
6074 	/*
6075 	 * RSSI here is absolute, not relative to the noise floor.
6076 	 */
6077 	noise = mac->mac_stats.link_noise;
6078 	rssi = rssi - noise;
6079 
6080 	/* RX radio tap */
6081 	if (ieee80211_radiotap_active(ic))
6082 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
6083 	m_adj(m, -IEEE80211_CRC_LEN);
6084 
6085 	BWN_UNLOCK(sc);
6086 
6087 	ni = ieee80211_find_rxnode(ic, wh);
6088 	if (ni != NULL) {
6089 		ieee80211_input(ni, m, rssi, noise);
6090 		ieee80211_free_node(ni);
6091 	} else
6092 		ieee80211_input_all(ic, m, rssi, noise);
6093 
6094 	BWN_LOCK(sc);
6095 	return;
6096 drop:
6097 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
6098 }
6099 
6100 static void
6101 bwn_ratectl_tx_complete(const struct ieee80211_node *ni,
6102     const struct bwn_txstatus *status)
6103 {
6104 	struct ieee80211_ratectl_tx_status txs;
6105 	int retrycnt = 0;
6106 
6107 	/*
6108 	 * If we don't get an ACK, then we should log the
6109 	 * full framecnt.  That may be 0 if it's a PHY
6110 	 * failure, so ensure that gets logged as some
6111 	 * retry attempt.
6112 	 */
6113 	txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY;
6114 	if (status->ack) {
6115 		txs.status = IEEE80211_RATECTL_TX_SUCCESS;
6116 		retrycnt = status->framecnt - 1;
6117 	} else {
6118 		txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED;
6119 		retrycnt = status->framecnt;
6120 		if (retrycnt == 0)
6121 			retrycnt = 1;
6122 	}
6123 	txs.long_retries = retrycnt;
6124 	ieee80211_ratectl_tx_complete(ni, &txs);
6125 }
6126 
6127 static void
6128 bwn_dma_handle_txeof(struct bwn_mac *mac,
6129     const struct bwn_txstatus *status)
6130 {
6131 	struct bwn_dma *dma = &mac->mac_method.dma;
6132 	struct bwn_dma_ring *dr;
6133 	struct bwn_dmadesc_generic *desc;
6134 	struct bwn_dmadesc_meta *meta;
6135 	struct bwn_softc *sc = mac->mac_sc;
6136 	int slot;
6137 
6138 	BWN_ASSERT_LOCKED(sc);
6139 
6140 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
6141 	if (dr == NULL) {
6142 		device_printf(sc->sc_dev, "failed to parse cookie\n");
6143 		return;
6144 	}
6145 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
6146 
6147 	while (1) {
6148 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
6149 		    ("%s:%d: fail", __func__, __LINE__));
6150 		dr->getdesc(dr, slot, &desc, &meta);
6151 
6152 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
6153 			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
6154 		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
6155 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
6156 
6157 		if (meta->mt_islast) {
6158 			KASSERT(meta->mt_m != NULL,
6159 			    ("%s:%d: fail", __func__, __LINE__));
6160 
6161 			bwn_ratectl_tx_complete(meta->mt_ni, status);
6162 			ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
6163 			meta->mt_ni = NULL;
6164 			meta->mt_m = NULL;
6165 		} else
6166 			KASSERT(meta->mt_m == NULL,
6167 			    ("%s:%d: fail", __func__, __LINE__));
6168 
6169 		dr->dr_usedslot--;
6170 		if (meta->mt_islast)
6171 			break;
6172 		slot = bwn_dma_nextslot(dr, slot);
6173 	}
6174 	sc->sc_watchdog_timer = 0;
6175 	if (dr->dr_stop) {
6176 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
6177 		    ("%s:%d: fail", __func__, __LINE__));
6178 		dr->dr_stop = 0;
6179 	}
6180 }
6181 
6182 static void
6183 bwn_pio_handle_txeof(struct bwn_mac *mac,
6184     const struct bwn_txstatus *status)
6185 {
6186 	struct bwn_pio_txqueue *tq;
6187 	struct bwn_pio_txpkt *tp = NULL;
6188 	struct bwn_softc *sc = mac->mac_sc;
6189 
6190 	BWN_ASSERT_LOCKED(sc);
6191 
6192 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
6193 	if (tq == NULL)
6194 		return;
6195 
6196 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
6197 	tq->tq_free++;
6198 
6199 	if (tp->tp_ni != NULL) {
6200 		/*
6201 		 * Do any tx complete callback.  Note this must
6202 		 * be done before releasing the node reference.
6203 		 */
6204 		bwn_ratectl_tx_complete(tp->tp_ni, status);
6205 	}
6206 	ieee80211_tx_complete(tp->tp_ni, tp->tp_m, 0);
6207 	tp->tp_ni = NULL;
6208 	tp->tp_m = NULL;
6209 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
6210 
6211 	sc->sc_watchdog_timer = 0;
6212 }
6213 
6214 static void
6215 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
6216 {
6217 	struct bwn_softc *sc = mac->mac_sc;
6218 	struct bwn_phy *phy = &mac->mac_phy;
6219 	struct ieee80211com *ic = &sc->sc_ic;
6220 	unsigned long now;
6221 	bwn_txpwr_result_t result;
6222 
6223 	BWN_GETTIME(now);
6224 
6225 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime))
6226 		return;
6227 	phy->nexttime = now + 2 * 1000;
6228 
6229 	if (sc->sc_board_info.board_vendor == PCI_VENDOR_BROADCOM &&
6230 	    sc->sc_board_info.board_type == BHND_BOARD_BU4306)
6231 		return;
6232 
6233 	if (phy->recalc_txpwr != NULL) {
6234 		result = phy->recalc_txpwr(mac,
6235 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
6236 		if (result == BWN_TXPWR_RES_DONE)
6237 			return;
6238 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
6239 		    ("%s: fail", __func__));
6240 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
6241 
6242 		ieee80211_runtask(ic, &mac->mac_txpower);
6243 	}
6244 }
6245 
6246 static uint16_t
6247 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
6248 {
6249 
6250 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
6251 }
6252 
6253 static uint32_t
6254 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
6255 {
6256 
6257 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
6258 }
6259 
6260 static void
6261 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
6262 {
6263 
6264 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
6265 }
6266 
6267 static void
6268 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
6269 {
6270 
6271 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
6272 }
6273 
6274 static int
6275 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
6276 {
6277 
6278 	switch (rate) {
6279 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
6280 	case 12:
6281 		return (BWN_OFDM_RATE_6MB);
6282 	case 18:
6283 		return (BWN_OFDM_RATE_9MB);
6284 	case 24:
6285 		return (BWN_OFDM_RATE_12MB);
6286 	case 36:
6287 		return (BWN_OFDM_RATE_18MB);
6288 	case 48:
6289 		return (BWN_OFDM_RATE_24MB);
6290 	case 72:
6291 		return (BWN_OFDM_RATE_36MB);
6292 	case 96:
6293 		return (BWN_OFDM_RATE_48MB);
6294 	case 108:
6295 		return (BWN_OFDM_RATE_54MB);
6296 	/* CCK rates (NB: not IEEE std, device-specific) */
6297 	case 2:
6298 		return (BWN_CCK_RATE_1MB);
6299 	case 4:
6300 		return (BWN_CCK_RATE_2MB);
6301 	case 11:
6302 		return (BWN_CCK_RATE_5MB);
6303 	case 22:
6304 		return (BWN_CCK_RATE_11MB);
6305 	}
6306 
6307 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
6308 	return (BWN_CCK_RATE_1MB);
6309 }
6310 
6311 static uint16_t
6312 bwn_set_txhdr_phyctl1(struct bwn_mac *mac, uint8_t bitrate)
6313 {
6314 	struct bwn_phy *phy = &mac->mac_phy;
6315 	uint16_t control = 0;
6316 	uint16_t bw;
6317 
6318 	/* XXX TODO: this is for LP phy, what about N-PHY, etc? */
6319 	bw = BWN_TXH_PHY1_BW_20;
6320 
6321 	if (BWN_ISCCKRATE(bitrate) && phy->type != BWN_PHYTYPE_LP) {
6322 		control = bw;
6323 	} else {
6324 		control = bw;
6325 		/* Figure out coding rate and modulation */
6326 		/* XXX TODO: table-ize, for MCS transmit */
6327 		/* Note: this is BWN_*_RATE values */
6328 		switch (bitrate) {
6329 		case BWN_CCK_RATE_1MB:
6330 			control |= 0;
6331 			break;
6332 		case BWN_CCK_RATE_2MB:
6333 			control |= 1;
6334 			break;
6335 		case BWN_CCK_RATE_5MB:
6336 			control |= 2;
6337 			break;
6338 		case BWN_CCK_RATE_11MB:
6339 			control |= 3;
6340 			break;
6341 		case BWN_OFDM_RATE_6MB:
6342 			control |= BWN_TXH_PHY1_CRATE_1_2;
6343 			control |= BWN_TXH_PHY1_MODUL_BPSK;
6344 			break;
6345 		case BWN_OFDM_RATE_9MB:
6346 			control |= BWN_TXH_PHY1_CRATE_3_4;
6347 			control |= BWN_TXH_PHY1_MODUL_BPSK;
6348 			break;
6349 		case BWN_OFDM_RATE_12MB:
6350 			control |= BWN_TXH_PHY1_CRATE_1_2;
6351 			control |= BWN_TXH_PHY1_MODUL_QPSK;
6352 			break;
6353 		case BWN_OFDM_RATE_18MB:
6354 			control |= BWN_TXH_PHY1_CRATE_3_4;
6355 			control |= BWN_TXH_PHY1_MODUL_QPSK;
6356 			break;
6357 		case BWN_OFDM_RATE_24MB:
6358 			control |= BWN_TXH_PHY1_CRATE_1_2;
6359 			control |= BWN_TXH_PHY1_MODUL_QAM16;
6360 			break;
6361 		case BWN_OFDM_RATE_36MB:
6362 			control |= BWN_TXH_PHY1_CRATE_3_4;
6363 			control |= BWN_TXH_PHY1_MODUL_QAM16;
6364 			break;
6365 		case BWN_OFDM_RATE_48MB:
6366 			control |= BWN_TXH_PHY1_CRATE_1_2;
6367 			control |= BWN_TXH_PHY1_MODUL_QAM64;
6368 			break;
6369 		case BWN_OFDM_RATE_54MB:
6370 			control |= BWN_TXH_PHY1_CRATE_3_4;
6371 			control |= BWN_TXH_PHY1_MODUL_QAM64;
6372 			break;
6373 		default:
6374 			break;
6375 		}
6376 		control |= BWN_TXH_PHY1_MODE_SISO;
6377 	}
6378 
6379 	return control;
6380 }
6381 
6382 static int
6383 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
6384     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
6385 {
6386 	const struct bwn_phy *phy = &mac->mac_phy;
6387 	struct bwn_softc *sc = mac->mac_sc;
6388 	struct ieee80211_frame *wh;
6389 	struct ieee80211_frame *protwh;
6390 	const struct ieee80211_txparam *tp = ni->ni_txparms;
6391 	struct ieee80211vap *vap = ni->ni_vap;
6392 	struct ieee80211com *ic = &sc->sc_ic;
6393 	struct mbuf *mprot;
6394 	uint8_t *prot_ptr;
6395 	unsigned int len;
6396 	uint32_t macctl = 0;
6397 	int rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
6398 	uint16_t phyctl = 0;
6399 	uint8_t rate, rate_fb;
6400 	int fill_phy_ctl1 = 0;
6401 
6402 	wh = mtod(m, struct ieee80211_frame *);
6403 	memset(txhdr, 0, sizeof(*txhdr));
6404 
6405 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
6406 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
6407 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
6408 
6409 	if ((phy->type == BWN_PHYTYPE_N) || (phy->type == BWN_PHYTYPE_LP)
6410 	    || (phy->type == BWN_PHYTYPE_HT))
6411 		fill_phy_ctl1 = 1;
6412 
6413 	/*
6414 	 * Find TX rate
6415 	 */
6416 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
6417 		rate = rate_fb = tp->mgmtrate;
6418 	else if (ismcast)
6419 		rate = rate_fb = tp->mcastrate;
6420 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
6421 		rate = rate_fb = tp->ucastrate;
6422 	else {
6423 		rix = ieee80211_ratectl_rate(ni, NULL, 0);
6424 		rate = ni->ni_txrate;
6425 
6426 		if (rix > 0)
6427 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
6428 			    IEEE80211_RATE_VAL;
6429 		else
6430 			rate_fb = rate;
6431 	}
6432 
6433 	sc->sc_tx_rate = rate;
6434 
6435 	/* Note: this maps the select ieee80211 rate to hardware rate */
6436 	rate = bwn_ieeerate2hwrate(sc, rate);
6437 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
6438 
6439 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
6440 	    bwn_plcp_getcck(rate);
6441 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
6442 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
6443 
6444 	/* XXX rate/rate_fb is the hardware rate */
6445 	if ((rate_fb == rate) ||
6446 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
6447 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
6448 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
6449 	else
6450 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
6451 		    m->m_pkthdr.len, rate, isshort);
6452 
6453 	/* XXX TX encryption */
6454 
6455 	switch (mac->mac_fw.fw_hdr_format) {
6456 	case BWN_FW_HDR_351:
6457 		bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->body.r351.plcp),
6458 		    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6459 		break;
6460 	case BWN_FW_HDR_410:
6461 		bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->body.r410.plcp),
6462 		    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6463 		break;
6464 	case BWN_FW_HDR_598:
6465 		bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->body.r598.plcp),
6466 		    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6467 		break;
6468 	}
6469 
6470 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
6471 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
6472 
6473 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
6474 	    BWN_TX_EFT_FB_CCK;
6475 	txhdr->chan = phy->chan;
6476 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
6477 	    BWN_TX_PHY_ENC_CCK;
6478 	/* XXX preamble? obey net80211 */
6479 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6480 	     rate == BWN_CCK_RATE_11MB))
6481 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
6482 
6483 	if (! phy->gmode)
6484 		macctl |= BWN_TX_MAC_5GHZ;
6485 
6486 	/* XXX TX antenna selection */
6487 
6488 	switch (bwn_antenna_sanitize(mac, 0)) {
6489 	case 0:
6490 		phyctl |= BWN_TX_PHY_ANT01AUTO;
6491 		break;
6492 	case 1:
6493 		phyctl |= BWN_TX_PHY_ANT0;
6494 		break;
6495 	case 2:
6496 		phyctl |= BWN_TX_PHY_ANT1;
6497 		break;
6498 	case 3:
6499 		phyctl |= BWN_TX_PHY_ANT2;
6500 		break;
6501 	case 4:
6502 		phyctl |= BWN_TX_PHY_ANT3;
6503 		break;
6504 	default:
6505 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6506 	}
6507 
6508 	if (!ismcast)
6509 		macctl |= BWN_TX_MAC_ACK;
6510 
6511 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
6512 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
6513 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
6514 		macctl |= BWN_TX_MAC_LONGFRAME;
6515 
6516 	if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
6517 	    ic->ic_protmode != IEEE80211_PROT_NONE) {
6518 		/* Note: don't fall back to CCK rates for 5G */
6519 		if (phy->gmode)
6520 			rts_rate = BWN_CCK_RATE_1MB;
6521 		else
6522 			rts_rate = BWN_OFDM_RATE_6MB;
6523 		rts_rate_fb = bwn_get_fbrate(rts_rate);
6524 
6525 		/* XXX 'rate' here is hardware rate now, not the net80211 rate */
6526 		mprot = ieee80211_alloc_prot(ni, m, rate, ic->ic_protmode);
6527 		if (mprot == NULL) {
6528 			if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1);
6529 			device_printf(sc->sc_dev,
6530 			    "could not allocate mbuf for protection mode %d\n",
6531 			    ic->ic_protmode);
6532 			return (ENOBUFS);
6533 		}
6534 
6535 		switch (mac->mac_fw.fw_hdr_format) {
6536 		case BWN_FW_HDR_351:
6537 			prot_ptr = txhdr->body.r351.rts_frame;
6538 			break;
6539 		case BWN_FW_HDR_410:
6540 			prot_ptr = txhdr->body.r410.rts_frame;
6541 			break;
6542 		case BWN_FW_HDR_598:
6543 			prot_ptr = txhdr->body.r598.rts_frame;
6544 			break;
6545 		}
6546 
6547 		bcopy(mtod(mprot, uint8_t *), prot_ptr, mprot->m_pkthdr.len);
6548 		m_freem(mprot);
6549 
6550 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
6551 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
6552 			len = sizeof(struct ieee80211_frame_cts);
6553 		} else {
6554 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
6555 			len = sizeof(struct ieee80211_frame_rts);
6556 		}
6557 		len += IEEE80211_CRC_LEN;
6558 
6559 		switch (mac->mac_fw.fw_hdr_format) {
6560 		case BWN_FW_HDR_351:
6561 			bwn_plcp_genhdr((struct bwn_plcp4 *)
6562 			    &txhdr->body.r351.rts_plcp, len, rts_rate);
6563 			break;
6564 		case BWN_FW_HDR_410:
6565 			bwn_plcp_genhdr((struct bwn_plcp4 *)
6566 			    &txhdr->body.r410.rts_plcp, len, rts_rate);
6567 			break;
6568 		case BWN_FW_HDR_598:
6569 			bwn_plcp_genhdr((struct bwn_plcp4 *)
6570 			    &txhdr->body.r598.rts_plcp, len, rts_rate);
6571 			break;
6572 		}
6573 
6574 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
6575 		    rts_rate_fb);
6576 
6577 		switch (mac->mac_fw.fw_hdr_format) {
6578 		case BWN_FW_HDR_351:
6579 			protwh = (struct ieee80211_frame *)
6580 			    &txhdr->body.r351.rts_frame;
6581 			break;
6582 		case BWN_FW_HDR_410:
6583 			protwh = (struct ieee80211_frame *)
6584 			    &txhdr->body.r410.rts_frame;
6585 			break;
6586 		case BWN_FW_HDR_598:
6587 			protwh = (struct ieee80211_frame *)
6588 			    &txhdr->body.r598.rts_frame;
6589 			break;
6590 		}
6591 
6592 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
6593 
6594 		if (BWN_ISOFDMRATE(rts_rate)) {
6595 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
6596 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
6597 		} else {
6598 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
6599 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
6600 		}
6601 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
6602 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
6603 
6604 		if (fill_phy_ctl1) {
6605 			txhdr->phyctl_1rts = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate));
6606 			txhdr->phyctl_1rtsfb = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate_fb));
6607 		}
6608 	}
6609 
6610 	if (fill_phy_ctl1) {
6611 		txhdr->phyctl_1 = htole16(bwn_set_txhdr_phyctl1(mac, rate));
6612 		txhdr->phyctl_1fb = htole16(bwn_set_txhdr_phyctl1(mac, rate_fb));
6613 	}
6614 
6615 	switch (mac->mac_fw.fw_hdr_format) {
6616 	case BWN_FW_HDR_351:
6617 		txhdr->body.r351.cookie = htole16(cookie);
6618 		break;
6619 	case BWN_FW_HDR_410:
6620 		txhdr->body.r410.cookie = htole16(cookie);
6621 		break;
6622 	case BWN_FW_HDR_598:
6623 		txhdr->body.r598.cookie = htole16(cookie);
6624 		break;
6625 	}
6626 
6627 	txhdr->macctl = htole32(macctl);
6628 	txhdr->phyctl = htole16(phyctl);
6629 
6630 	/*
6631 	 * TX radio tap
6632 	 */
6633 	if (ieee80211_radiotap_active_vap(vap)) {
6634 		sc->sc_tx_th.wt_flags = 0;
6635 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6636 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
6637 		if (isshort &&
6638 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6639 		     rate == BWN_CCK_RATE_11MB))
6640 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6641 		sc->sc_tx_th.wt_rate = rate;
6642 
6643 		ieee80211_radiotap_tx(vap, m);
6644 	}
6645 
6646 	return (0);
6647 }
6648 
6649 static void
6650 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
6651     const uint8_t rate)
6652 {
6653 	uint32_t d, plen;
6654 	uint8_t *raw = plcp->o.raw;
6655 
6656 	if (BWN_ISOFDMRATE(rate)) {
6657 		d = bwn_plcp_getofdm(rate);
6658 		KASSERT(!(octets & 0xf000),
6659 		    ("%s:%d: fail", __func__, __LINE__));
6660 		d |= (octets << 5);
6661 		plcp->o.data = htole32(d);
6662 	} else {
6663 		plen = octets * 16 / rate;
6664 		if ((octets * 16 % rate) > 0) {
6665 			plen++;
6666 			if ((rate == BWN_CCK_RATE_11MB)
6667 			    && ((octets * 8 % 11) < 4)) {
6668 				raw[1] = 0x84;
6669 			} else
6670 				raw[1] = 0x04;
6671 		} else
6672 			raw[1] = 0x04;
6673 		plcp->o.data |= htole32(plen << 16);
6674 		raw[0] = bwn_plcp_getcck(rate);
6675 	}
6676 }
6677 
6678 static uint8_t
6679 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
6680 {
6681 	struct bwn_softc *sc = mac->mac_sc;
6682 	uint8_t mask;
6683 
6684 	if (n == 0)
6685 		return (0);
6686 	if (mac->mac_phy.gmode)
6687 		mask = sc->sc_ant2g;
6688 	else
6689 		mask = sc->sc_ant5g;
6690 	if (!(mask & (1 << (n - 1))))
6691 		return (0);
6692 	return (n);
6693 }
6694 
6695 /*
6696  * Return a fallback rate for the given rate.
6697  *
6698  * Note: Don't fall back from OFDM to CCK.
6699  */
6700 static uint8_t
6701 bwn_get_fbrate(uint8_t bitrate)
6702 {
6703 	switch (bitrate) {
6704 	/* CCK */
6705 	case BWN_CCK_RATE_1MB:
6706 		return (BWN_CCK_RATE_1MB);
6707 	case BWN_CCK_RATE_2MB:
6708 		return (BWN_CCK_RATE_1MB);
6709 	case BWN_CCK_RATE_5MB:
6710 		return (BWN_CCK_RATE_2MB);
6711 	case BWN_CCK_RATE_11MB:
6712 		return (BWN_CCK_RATE_5MB);
6713 
6714 	/* OFDM */
6715 	case BWN_OFDM_RATE_6MB:
6716 		return (BWN_OFDM_RATE_6MB);
6717 	case BWN_OFDM_RATE_9MB:
6718 		return (BWN_OFDM_RATE_6MB);
6719 	case BWN_OFDM_RATE_12MB:
6720 		return (BWN_OFDM_RATE_9MB);
6721 	case BWN_OFDM_RATE_18MB:
6722 		return (BWN_OFDM_RATE_12MB);
6723 	case BWN_OFDM_RATE_24MB:
6724 		return (BWN_OFDM_RATE_18MB);
6725 	case BWN_OFDM_RATE_36MB:
6726 		return (BWN_OFDM_RATE_24MB);
6727 	case BWN_OFDM_RATE_48MB:
6728 		return (BWN_OFDM_RATE_36MB);
6729 	case BWN_OFDM_RATE_54MB:
6730 		return (BWN_OFDM_RATE_48MB);
6731 	}
6732 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6733 	return (0);
6734 }
6735 
6736 static uint32_t
6737 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6738     uint32_t ctl, const void *_data, int len)
6739 {
6740 	struct bwn_softc *sc = mac->mac_sc;
6741 	uint32_t value = 0;
6742 	const uint8_t *data = _data;
6743 
6744 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
6745 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
6746 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6747 
6748 	bus_write_multi_4(sc->sc_mem_res, tq->tq_base + BWN_PIO8_TXDATA,
6749 	    __DECONST(void *, data), (len & ~3));
6750 	if (len & 3) {
6751 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
6752 		    BWN_PIO8_TXCTL_24_31);
6753 		data = &(data[len - 1]);
6754 		switch (len & 3) {
6755 		case 3:
6756 			ctl |= BWN_PIO8_TXCTL_16_23;
6757 			value |= (uint32_t)(*data) << 16;
6758 			data--;
6759 		case 2:
6760 			ctl |= BWN_PIO8_TXCTL_8_15;
6761 			value |= (uint32_t)(*data) << 8;
6762 			data--;
6763 		case 1:
6764 			value |= (uint32_t)(*data);
6765 		}
6766 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6767 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
6768 	}
6769 
6770 	return (ctl);
6771 }
6772 
6773 static void
6774 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6775     uint16_t offset, uint32_t value)
6776 {
6777 
6778 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
6779 }
6780 
6781 static uint16_t
6782 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6783     uint16_t ctl, const void *_data, int len)
6784 {
6785 	struct bwn_softc *sc = mac->mac_sc;
6786 	const uint8_t *data = _data;
6787 
6788 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6789 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6790 
6791 	bus_write_multi_2(sc->sc_mem_res, tq->tq_base + BWN_PIO_TXDATA,
6792 	    __DECONST(void *, data), (len & ~1));
6793 	if (len & 1) {
6794 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6795 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6796 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
6797 	}
6798 
6799 	return (ctl);
6800 }
6801 
6802 static uint16_t
6803 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6804     uint16_t ctl, struct mbuf *m0)
6805 {
6806 	int i, j = 0;
6807 	uint16_t data = 0;
6808 	const uint8_t *buf;
6809 	struct mbuf *m = m0;
6810 
6811 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6812 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6813 
6814 	for (; m != NULL; m = m->m_next) {
6815 		buf = mtod(m, const uint8_t *);
6816 		for (i = 0; i < m->m_len; i++) {
6817 			if (!((j++) % 2))
6818 				data |= buf[i];
6819 			else {
6820 				data |= (buf[i] << 8);
6821 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6822 				data = 0;
6823 			}
6824 		}
6825 	}
6826 	if (m0->m_pkthdr.len % 2) {
6827 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6828 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6829 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6830 	}
6831 
6832 	return (ctl);
6833 }
6834 
6835 static void
6836 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
6837 {
6838 
6839 	/* XXX should exit if 5GHz band .. */
6840 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
6841 		return;
6842 
6843 	BWN_WRITE_2(mac, 0x684, 510 + time);
6844 	/* Disabled in Linux b43, can adversely effect performance */
6845 #if 0
6846 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
6847 #endif
6848 }
6849 
6850 static struct bwn_dma_ring *
6851 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
6852 {
6853 
6854 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
6855 		return (mac->mac_method.dma.wme[WME_AC_BE]);
6856 
6857 	switch (prio) {
6858 	case 3:
6859 		return (mac->mac_method.dma.wme[WME_AC_VO]);
6860 	case 2:
6861 		return (mac->mac_method.dma.wme[WME_AC_VI]);
6862 	case 0:
6863 		return (mac->mac_method.dma.wme[WME_AC_BE]);
6864 	case 1:
6865 		return (mac->mac_method.dma.wme[WME_AC_BK]);
6866 	}
6867 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6868 	return (NULL);
6869 }
6870 
6871 static int
6872 bwn_dma_getslot(struct bwn_dma_ring *dr)
6873 {
6874 	int slot;
6875 
6876 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
6877 
6878 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
6879 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
6880 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
6881 
6882 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
6883 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
6884 	dr->dr_curslot = slot;
6885 	dr->dr_usedslot++;
6886 
6887 	return (slot);
6888 }
6889 
6890 static struct bwn_pio_txqueue *
6891 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
6892     struct bwn_pio_txpkt **pack)
6893 {
6894 	struct bwn_pio *pio = &mac->mac_method.pio;
6895 	struct bwn_pio_txqueue *tq = NULL;
6896 	unsigned int index;
6897 
6898 	switch (cookie & 0xf000) {
6899 	case 0x1000:
6900 		tq = &pio->wme[WME_AC_BK];
6901 		break;
6902 	case 0x2000:
6903 		tq = &pio->wme[WME_AC_BE];
6904 		break;
6905 	case 0x3000:
6906 		tq = &pio->wme[WME_AC_VI];
6907 		break;
6908 	case 0x4000:
6909 		tq = &pio->wme[WME_AC_VO];
6910 		break;
6911 	case 0x5000:
6912 		tq = &pio->mcast;
6913 		break;
6914 	}
6915 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
6916 	if (tq == NULL)
6917 		return (NULL);
6918 	index = (cookie & 0x0fff);
6919 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
6920 	if (index >= N(tq->tq_pkts))
6921 		return (NULL);
6922 	*pack = &tq->tq_pkts[index];
6923 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
6924 	return (tq);
6925 }
6926 
6927 static void
6928 bwn_txpwr(void *arg, int npending)
6929 {
6930 	struct bwn_mac *mac = arg;
6931 	struct bwn_softc *sc;
6932 
6933 	if (mac == NULL)
6934 		return;
6935 
6936 	sc = mac->mac_sc;
6937 
6938 	BWN_LOCK(sc);
6939 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED &&
6940 	    mac->mac_phy.set_txpwr != NULL)
6941 		mac->mac_phy.set_txpwr(mac);
6942 	BWN_UNLOCK(sc);
6943 }
6944 
6945 static void
6946 bwn_task_15s(struct bwn_mac *mac)
6947 {
6948 	uint16_t reg;
6949 
6950 	if (mac->mac_fw.opensource) {
6951 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
6952 		if (reg) {
6953 			bwn_restart(mac, "fw watchdog");
6954 			return;
6955 		}
6956 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
6957 	}
6958 	if (mac->mac_phy.task_15s)
6959 		mac->mac_phy.task_15s(mac);
6960 
6961 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
6962 }
6963 
6964 static void
6965 bwn_task_30s(struct bwn_mac *mac)
6966 {
6967 
6968 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
6969 		return;
6970 	mac->mac_noise.noi_running = 1;
6971 	mac->mac_noise.noi_nsamples = 0;
6972 
6973 	bwn_noise_gensample(mac);
6974 }
6975 
6976 static void
6977 bwn_task_60s(struct bwn_mac *mac)
6978 {
6979 
6980 	if (mac->mac_phy.task_60s)
6981 		mac->mac_phy.task_60s(mac);
6982 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
6983 }
6984 
6985 static void
6986 bwn_tasks(void *arg)
6987 {
6988 	struct bwn_mac *mac = arg;
6989 	struct bwn_softc *sc = mac->mac_sc;
6990 
6991 	BWN_ASSERT_LOCKED(sc);
6992 	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
6993 		return;
6994 
6995 	if (mac->mac_task_state % 4 == 0)
6996 		bwn_task_60s(mac);
6997 	if (mac->mac_task_state % 2 == 0)
6998 		bwn_task_30s(mac);
6999 	bwn_task_15s(mac);
7000 
7001 	mac->mac_task_state++;
7002 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
7003 }
7004 
7005 static int
7006 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
7007 {
7008 	struct bwn_softc *sc = mac->mac_sc;
7009 
7010 	KASSERT(a == 0, ("not support APHY\n"));
7011 
7012 	switch (plcp->o.raw[0] & 0xf) {
7013 	case 0xb:
7014 		return (BWN_OFDM_RATE_6MB);
7015 	case 0xf:
7016 		return (BWN_OFDM_RATE_9MB);
7017 	case 0xa:
7018 		return (BWN_OFDM_RATE_12MB);
7019 	case 0xe:
7020 		return (BWN_OFDM_RATE_18MB);
7021 	case 0x9:
7022 		return (BWN_OFDM_RATE_24MB);
7023 	case 0xd:
7024 		return (BWN_OFDM_RATE_36MB);
7025 	case 0x8:
7026 		return (BWN_OFDM_RATE_48MB);
7027 	case 0xc:
7028 		return (BWN_OFDM_RATE_54MB);
7029 	}
7030 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
7031 	    plcp->o.raw[0] & 0xf);
7032 	return (-1);
7033 }
7034 
7035 static int
7036 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
7037 {
7038 	struct bwn_softc *sc = mac->mac_sc;
7039 
7040 	switch (plcp->o.raw[0]) {
7041 	case 0x0a:
7042 		return (BWN_CCK_RATE_1MB);
7043 	case 0x14:
7044 		return (BWN_CCK_RATE_2MB);
7045 	case 0x37:
7046 		return (BWN_CCK_RATE_5MB);
7047 	case 0x6e:
7048 		return (BWN_CCK_RATE_11MB);
7049 	}
7050 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
7051 	return (-1);
7052 }
7053 
7054 static void
7055 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
7056     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
7057     int rssi, int noise)
7058 {
7059 	struct bwn_softc *sc = mac->mac_sc;
7060 	const struct ieee80211_frame_min *wh;
7061 	uint64_t tsf;
7062 	uint16_t low_mactime_now;
7063 	uint16_t mt;
7064 
7065 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
7066 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
7067 
7068 	wh = mtod(m, const struct ieee80211_frame_min *);
7069 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
7070 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
7071 
7072 	bwn_tsf_read(mac, &tsf);
7073 	low_mactime_now = tsf;
7074 	tsf = tsf & ~0xffffULL;
7075 
7076 	switch (mac->mac_fw.fw_hdr_format) {
7077 	case BWN_FW_HDR_351:
7078 	case BWN_FW_HDR_410:
7079 		mt = le16toh(rxhdr->ps4.r351.mac_time);
7080 		break;
7081 	case BWN_FW_HDR_598:
7082 		mt = le16toh(rxhdr->ps4.r598.mac_time);
7083 		break;
7084 	}
7085 
7086 	tsf += mt;
7087 	if (low_mactime_now < mt)
7088 		tsf -= 0x10000;
7089 
7090 	sc->sc_rx_th.wr_tsf = tsf;
7091 	sc->sc_rx_th.wr_rate = rate;
7092 	sc->sc_rx_th.wr_antsignal = rssi;
7093 	sc->sc_rx_th.wr_antnoise = noise;
7094 }
7095 
7096 static void
7097 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
7098 {
7099 	uint32_t low, high;
7100 
7101 	KASSERT(bhnd_get_hwrev(mac->mac_sc->sc_dev) >= 3,
7102 	    ("%s:%d: fail", __func__, __LINE__));
7103 
7104 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
7105 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
7106 	*tsf = high;
7107 	*tsf <<= 32;
7108 	*tsf |= low;
7109 }
7110 
7111 static int
7112 bwn_dma_attach(struct bwn_mac *mac)
7113 {
7114 	struct bwn_dma			*dma;
7115 	struct bwn_softc		*sc;
7116 	struct bhnd_dma_translation	*dt, dma_translation;
7117 	bhnd_addr_t			 addrext_req;
7118 	bus_dma_tag_t			 dmat;
7119 	bus_addr_t			 lowaddr;
7120 	u_int				 addrext_shift, addr_width;
7121 	int				 error;
7122 
7123 	dma = &mac->mac_method.dma;
7124 	sc = mac->mac_sc;
7125 	dt = NULL;
7126 
7127 	if (sc->sc_quirks & BWN_QUIRK_NODMA)
7128 		return (0);
7129 
7130 	KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 5, ("%s: fail", __func__));
7131 
7132 	/* Use the DMA engine's maximum host address width to determine the
7133 	 * addrext constraints, and supported device address width. */
7134 	switch (mac->mac_dmatype) {
7135 	case BHND_DMA_ADDR_30BIT:
7136 		/* 32-bit engine without addrext support */
7137 		addrext_req = 0x0;
7138 		addrext_shift = 0;
7139 
7140 		/* We can address the full 32-bit device address space */
7141 		addr_width = BHND_DMA_ADDR_32BIT;
7142 		break;
7143 
7144 	case BHND_DMA_ADDR_32BIT:
7145 		/* 32-bit engine with addrext support */
7146 		addrext_req = BWN_DMA32_ADDREXT_MASK;
7147 		addrext_shift = BWN_DMA32_ADDREXT_SHIFT;
7148 		addr_width = BHND_DMA_ADDR_32BIT;
7149 		break;
7150 
7151 	case BHND_DMA_ADDR_64BIT:
7152 		/* 64-bit engine with addrext support */
7153 		addrext_req = BWN_DMA64_ADDREXT_MASK;
7154 		addrext_shift = BWN_DMA64_ADDREXT_SHIFT;
7155 		addr_width = BHND_DMA_ADDR_64BIT;
7156 		break;
7157 
7158 	default:
7159 		device_printf(sc->sc_dev, "unsupported DMA address width: %d\n",
7160 		    mac->mac_dmatype);
7161 		return (ENXIO);
7162 	}
7163 
7164 	/* Fetch our device->host DMA translation and tag */
7165 	error = bhnd_get_dma_translation(sc->sc_dev, addr_width, 0, &dmat,
7166 	    &dma_translation);
7167 	if (error) {
7168 		device_printf(sc->sc_dev, "error fetching DMA translation: "
7169 		    "%d\n", error);
7170 		return (error);
7171 	}
7172 
7173 	/* Verify that our DMA engine's addrext constraints are compatible with
7174 	 * our DMA translation */
7175 	if (addrext_req != 0x0 &&
7176 	    (dma_translation.addrext_mask & addrext_req) != addrext_req)
7177 	{
7178 		device_printf(sc->sc_dev, "bus addrext mask %#jx incompatible "
7179 		    "with device addrext mask %#jx, disabling extended address "
7180 		    "support\n", (uintmax_t)dma_translation.addrext_mask,
7181 		    (uintmax_t)addrext_req);
7182 
7183 		addrext_req = 0x0;
7184 		addrext_shift = 0;
7185 	}
7186 
7187 	/* Apply our addrext translation constraint */
7188 	dma_translation.addrext_mask = addrext_req;
7189 
7190 	/* Initialize our DMA engine configuration */
7191 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
7192 
7193 	dma->addrext_shift = addrext_shift;
7194 	dma->translation = dma_translation;
7195 
7196 	dt = &dma->translation;
7197 
7198 	/* Dermine our translation's maximum supported address */
7199 	lowaddr = MIN((dt->addr_mask | dt->addrext_mask), BUS_SPACE_MAXADDR);
7200 
7201 	/*
7202 	 * Create top level DMA tag
7203 	 */
7204 	error = bus_dma_tag_create(dmat,		/* parent */
7205 			       BWN_ALIGN, 0,		/* alignment, bounds */
7206 			       lowaddr,			/* lowaddr */
7207 			       BUS_SPACE_MAXADDR,	/* highaddr */
7208 			       NULL, NULL,		/* filter, filterarg */
7209 			       BUS_SPACE_MAXSIZE,	/* maxsize */
7210 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
7211 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
7212 			       0,			/* flags */
7213 			       NULL, NULL,		/* lockfunc, lockarg */
7214 			       &dma->parent_dtag);
7215 	if (error) {
7216 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
7217 		return (error);
7218 	}
7219 
7220 	/*
7221 	 * Create TX/RX mbuf DMA tag
7222 	 */
7223 	error = bus_dma_tag_create(dma->parent_dtag,
7224 				1,
7225 				0,
7226 				BUS_SPACE_MAXADDR,
7227 				BUS_SPACE_MAXADDR,
7228 				NULL, NULL,
7229 				MCLBYTES,
7230 				1,
7231 				BUS_SPACE_MAXSIZE_32BIT,
7232 				0,
7233 				NULL, NULL,
7234 				&dma->rxbuf_dtag);
7235 	if (error) {
7236 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
7237 		goto fail0;
7238 	}
7239 	error = bus_dma_tag_create(dma->parent_dtag,
7240 				1,
7241 				0,
7242 				BUS_SPACE_MAXADDR,
7243 				BUS_SPACE_MAXADDR,
7244 				NULL, NULL,
7245 				MCLBYTES,
7246 				1,
7247 				BUS_SPACE_MAXSIZE_32BIT,
7248 				0,
7249 				NULL, NULL,
7250 				&dma->txbuf_dtag);
7251 	if (error) {
7252 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
7253 		goto fail1;
7254 	}
7255 
7256 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1);
7257 	if (!dma->wme[WME_AC_BK])
7258 		goto fail2;
7259 
7260 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1);
7261 	if (!dma->wme[WME_AC_BE])
7262 		goto fail3;
7263 
7264 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1);
7265 	if (!dma->wme[WME_AC_VI])
7266 		goto fail4;
7267 
7268 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1);
7269 	if (!dma->wme[WME_AC_VO])
7270 		goto fail5;
7271 
7272 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1);
7273 	if (!dma->mcast)
7274 		goto fail6;
7275 	dma->rx = bwn_dma_ringsetup(mac, 0, 0);
7276 	if (!dma->rx)
7277 		goto fail7;
7278 
7279 	return (error);
7280 
7281 fail7:	bwn_dma_ringfree(&dma->mcast);
7282 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
7283 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
7284 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
7285 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
7286 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
7287 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
7288 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
7289 	return (error);
7290 }
7291 
7292 static struct bwn_dma_ring *
7293 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
7294     uint16_t cookie, int *slot)
7295 {
7296 	struct bwn_dma *dma = &mac->mac_method.dma;
7297 	struct bwn_dma_ring *dr;
7298 	struct bwn_softc *sc = mac->mac_sc;
7299 
7300 	BWN_ASSERT_LOCKED(mac->mac_sc);
7301 
7302 	switch (cookie & 0xf000) {
7303 	case 0x1000:
7304 		dr = dma->wme[WME_AC_BK];
7305 		break;
7306 	case 0x2000:
7307 		dr = dma->wme[WME_AC_BE];
7308 		break;
7309 	case 0x3000:
7310 		dr = dma->wme[WME_AC_VI];
7311 		break;
7312 	case 0x4000:
7313 		dr = dma->wme[WME_AC_VO];
7314 		break;
7315 	case 0x5000:
7316 		dr = dma->mcast;
7317 		break;
7318 	default:
7319 		dr = NULL;
7320 		KASSERT(0 == 1,
7321 		    ("invalid cookie value %d", cookie & 0xf000));
7322 	}
7323 	*slot = (cookie & 0x0fff);
7324 	if (*slot < 0 || *slot >= dr->dr_numslots) {
7325 		/*
7326 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
7327 		 * that it occurs events which have same H/W sequence numbers.
7328 		 * When it's occurred just prints a WARNING msgs and ignores.
7329 		 */
7330 		KASSERT(status->seq == dma->lastseq,
7331 		    ("%s:%d: fail", __func__, __LINE__));
7332 		device_printf(sc->sc_dev,
7333 		    "out of slot ranges (0 < %d < %d)\n", *slot,
7334 		    dr->dr_numslots);
7335 		return (NULL);
7336 	}
7337 	dma->lastseq = status->seq;
7338 	return (dr);
7339 }
7340 
7341 static void
7342 bwn_dma_stop(struct bwn_mac *mac)
7343 {
7344 	struct bwn_dma *dma;
7345 
7346 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
7347 		return;
7348 	dma = &mac->mac_method.dma;
7349 
7350 	bwn_dma_ringstop(&dma->rx);
7351 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
7352 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
7353 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
7354 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
7355 	bwn_dma_ringstop(&dma->mcast);
7356 }
7357 
7358 static void
7359 bwn_dma_ringstop(struct bwn_dma_ring **dr)
7360 {
7361 
7362 	if (dr == NULL)
7363 		return;
7364 
7365 	bwn_dma_cleanup(*dr);
7366 }
7367 
7368 static void
7369 bwn_pio_stop(struct bwn_mac *mac)
7370 {
7371 	struct bwn_pio *pio;
7372 
7373 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
7374 		return;
7375 	pio = &mac->mac_method.pio;
7376 
7377 	bwn_destroy_queue_tx(&pio->mcast);
7378 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
7379 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
7380 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
7381 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
7382 }
7383 
7384 static int
7385 bwn_led_attach(struct bwn_mac *mac)
7386 {
7387 	struct bwn_softc *sc = mac->mac_sc;
7388 	const uint8_t *led_act = NULL;
7389 	int error;
7390 	int i;
7391 
7392 	sc->sc_led_idle = (2350 * hz) / 1000;
7393 	sc->sc_led_blink = 1;
7394 
7395 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
7396 		if (sc->sc_board_info.board_vendor ==
7397 		    bwn_vendor_led_act[i].vid) {
7398 			led_act = bwn_vendor_led_act[i].led_act;
7399 			break;
7400 		}
7401 	}
7402 	if (led_act == NULL)
7403 		led_act = bwn_default_led_act;
7404 
7405 	_Static_assert(nitems(bwn_led_vars) == BWN_LED_MAX,
7406 	    "invalid NVRAM variable name array");
7407 
7408 	for (i = 0; i < BWN_LED_MAX; ++i) {
7409 		struct bwn_led	*led;
7410 		uint8_t		 val;
7411 
7412 		led = &sc->sc_leds[i];
7413 
7414 		KASSERT(i < nitems(bwn_led_vars), ("unknown LED index"));
7415 		error = bhnd_nvram_getvar_uint8(sc->sc_dev, bwn_led_vars[i],
7416 		    &val);
7417 		if (error) {
7418 			if (error != ENOENT) {
7419 				device_printf(sc->sc_dev, "NVRAM variable %s "
7420 				    "unreadable: %d", bwn_led_vars[i], error);
7421 				return (error);
7422 			}
7423 
7424 			/* Not found; use default */
7425 			led->led_act = led_act[i];
7426 		} else {
7427 			if (val & BWN_LED_ACT_LOW)
7428 				led->led_flags |= BWN_LED_F_ACTLOW;
7429 			led->led_act = val & BWN_LED_ACT_MASK;
7430 		}
7431 		led->led_mask = (1 << i);
7432 
7433 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
7434 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
7435 		    led->led_act == BWN_LED_ACT_BLINK) {
7436 			led->led_flags |= BWN_LED_F_BLINK;
7437 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
7438 				led->led_flags |= BWN_LED_F_POLLABLE;
7439 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
7440 				led->led_flags |= BWN_LED_F_SLOW;
7441 
7442 			if (sc->sc_blink_led == NULL) {
7443 				sc->sc_blink_led = led;
7444 				if (led->led_flags & BWN_LED_F_SLOW)
7445 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
7446 			}
7447 		}
7448 
7449 		DPRINTF(sc, BWN_DEBUG_LED,
7450 		    "%dth led, act %d, lowact %d\n", i,
7451 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
7452 	}
7453 	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
7454 
7455 	return (0);
7456 }
7457 
7458 static __inline uint16_t
7459 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
7460 {
7461 
7462 	if (led->led_flags & BWN_LED_F_ACTLOW)
7463 		on = !on;
7464 	if (on)
7465 		val |= led->led_mask;
7466 	else
7467 		val &= ~led->led_mask;
7468 	return val;
7469 }
7470 
7471 static void
7472 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
7473 {
7474 	struct bwn_softc *sc = mac->mac_sc;
7475 	struct ieee80211com *ic = &sc->sc_ic;
7476 	uint16_t val;
7477 	int i;
7478 
7479 	if (nstate == IEEE80211_S_INIT) {
7480 		callout_stop(&sc->sc_led_blink_ch);
7481 		sc->sc_led_blinking = 0;
7482 	}
7483 
7484 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
7485 		return;
7486 
7487 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7488 	for (i = 0; i < BWN_LED_MAX; ++i) {
7489 		struct bwn_led *led = &sc->sc_leds[i];
7490 		int on;
7491 
7492 		if (led->led_act == BWN_LED_ACT_UNKN ||
7493 		    led->led_act == BWN_LED_ACT_NULL)
7494 			continue;
7495 
7496 		if ((led->led_flags & BWN_LED_F_BLINK) &&
7497 		    nstate != IEEE80211_S_INIT)
7498 			continue;
7499 
7500 		switch (led->led_act) {
7501 		case BWN_LED_ACT_ON:    /* Always on */
7502 			on = 1;
7503 			break;
7504 		case BWN_LED_ACT_OFF:   /* Always off */
7505 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
7506 			on = 0;
7507 			break;
7508 		default:
7509 			on = 1;
7510 			switch (nstate) {
7511 			case IEEE80211_S_INIT:
7512 				on = 0;
7513 				break;
7514 			case IEEE80211_S_RUN:
7515 				if (led->led_act == BWN_LED_ACT_11G &&
7516 				    ic->ic_curmode != IEEE80211_MODE_11G)
7517 					on = 0;
7518 				break;
7519 			default:
7520 				if (led->led_act == BWN_LED_ACT_ASSOC)
7521 					on = 0;
7522 				break;
7523 			}
7524 			break;
7525 		}
7526 
7527 		val = bwn_led_onoff(led, val, on);
7528 	}
7529 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7530 }
7531 
7532 static void
7533 bwn_led_event(struct bwn_mac *mac, int event)
7534 {
7535 	struct bwn_softc *sc = mac->mac_sc;
7536 	struct bwn_led *led = sc->sc_blink_led;
7537 	int rate;
7538 
7539 	if (event == BWN_LED_EVENT_POLL) {
7540 		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
7541 			return;
7542 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
7543 			return;
7544 	}
7545 
7546 	sc->sc_led_ticks = ticks;
7547 	if (sc->sc_led_blinking)
7548 		return;
7549 
7550 	switch (event) {
7551 	case BWN_LED_EVENT_RX:
7552 		rate = sc->sc_rx_rate;
7553 		break;
7554 	case BWN_LED_EVENT_TX:
7555 		rate = sc->sc_tx_rate;
7556 		break;
7557 	case BWN_LED_EVENT_POLL:
7558 		rate = 0;
7559 		break;
7560 	default:
7561 		panic("unknown LED event %d\n", event);
7562 		break;
7563 	}
7564 	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
7565 	    bwn_led_duration[rate].off_dur);
7566 }
7567 
7568 static void
7569 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
7570 {
7571 	struct bwn_softc *sc = mac->mac_sc;
7572 	struct bwn_led *led = sc->sc_blink_led;
7573 	uint16_t val;
7574 
7575 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7576 	val = bwn_led_onoff(led, val, 1);
7577 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7578 
7579 	if (led->led_flags & BWN_LED_F_SLOW) {
7580 		BWN_LED_SLOWDOWN(on_dur);
7581 		BWN_LED_SLOWDOWN(off_dur);
7582 	}
7583 
7584 	sc->sc_led_blinking = 1;
7585 	sc->sc_led_blink_offdur = off_dur;
7586 
7587 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
7588 }
7589 
7590 static void
7591 bwn_led_blink_next(void *arg)
7592 {
7593 	struct bwn_mac *mac = arg;
7594 	struct bwn_softc *sc = mac->mac_sc;
7595 	uint16_t val;
7596 
7597 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7598 	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
7599 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7600 
7601 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
7602 	    bwn_led_blink_end, mac);
7603 }
7604 
7605 static void
7606 bwn_led_blink_end(void *arg)
7607 {
7608 	struct bwn_mac *mac = arg;
7609 	struct bwn_softc *sc = mac->mac_sc;
7610 
7611 	sc->sc_led_blinking = 0;
7612 }
7613 
7614 static int
7615 bwn_suspend(device_t dev)
7616 {
7617 	struct bwn_softc *sc = device_get_softc(dev);
7618 
7619 	BWN_LOCK(sc);
7620 	bwn_stop(sc);
7621 	BWN_UNLOCK(sc);
7622 	return (0);
7623 }
7624 
7625 static int
7626 bwn_resume(device_t dev)
7627 {
7628 	struct bwn_softc *sc = device_get_softc(dev);
7629 	int error = EDOOFUS;
7630 
7631 	BWN_LOCK(sc);
7632 	if (sc->sc_ic.ic_nrunning > 0)
7633 		error = bwn_init(sc);
7634 	BWN_UNLOCK(sc);
7635 	if (error == 0)
7636 		ieee80211_start_all(&sc->sc_ic);
7637 	return (0);
7638 }
7639 
7640 static void
7641 bwn_rfswitch(void *arg)
7642 {
7643 	struct bwn_softc *sc = arg;
7644 	struct bwn_mac *mac = sc->sc_curmac;
7645 	int cur = 0, prev = 0;
7646 
7647 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
7648 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
7649 
7650 	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP
7651 	    || mac->mac_phy.type == BWN_PHYTYPE_N) {
7652 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
7653 			& BWN_RF_HWENABLED_HI_MASK))
7654 			cur = 1;
7655 	} else {
7656 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
7657 		    & BWN_RF_HWENABLED_LO_MASK)
7658 			cur = 1;
7659 	}
7660 
7661 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
7662 		prev = 1;
7663 
7664 	DPRINTF(sc, BWN_DEBUG_RESET, "%s: called; cur=%d, prev=%d\n",
7665 	    __func__, cur, prev);
7666 
7667 	if (cur != prev) {
7668 		if (cur)
7669 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
7670 		else
7671 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
7672 
7673 		device_printf(sc->sc_dev,
7674 		    "status of RF switch is changed to %s\n",
7675 		    cur ? "ON" : "OFF");
7676 		if (cur != mac->mac_phy.rf_on) {
7677 			if (cur)
7678 				bwn_rf_turnon(mac);
7679 			else
7680 				bwn_rf_turnoff(mac);
7681 		}
7682 	}
7683 
7684 	callout_schedule(&sc->sc_rfswitch_ch, hz);
7685 }
7686 
7687 static void
7688 bwn_sysctl_node(struct bwn_softc *sc)
7689 {
7690 	device_t dev = sc->sc_dev;
7691 	struct bwn_mac *mac;
7692 	struct bwn_stats *stats;
7693 
7694 	/* XXX assume that count of MAC is only 1. */
7695 
7696 	if ((mac = sc->sc_curmac) == NULL)
7697 		return;
7698 	stats = &mac->mac_stats;
7699 
7700 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7701 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7702 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
7703 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7704 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7705 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
7706 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7707 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7708 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
7709 
7710 #ifdef BWN_DEBUG
7711 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
7712 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7713 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
7714 #endif
7715 }
7716 
7717 static device_method_t bwn_methods[] = {
7718 	/* Device interface */
7719 	DEVMETHOD(device_probe,		bwn_probe),
7720 	DEVMETHOD(device_attach,	bwn_attach),
7721 	DEVMETHOD(device_detach,	bwn_detach),
7722 	DEVMETHOD(device_suspend,	bwn_suspend),
7723 	DEVMETHOD(device_resume,	bwn_resume),
7724 	DEVMETHOD_END
7725 };
7726 
7727 static driver_t bwn_driver = {
7728 	"bwn",
7729 	bwn_methods,
7730 	sizeof(struct bwn_softc)
7731 };
7732 
7733 DRIVER_MODULE(bwn, bhnd, bwn_driver, 0, 0);
7734 MODULE_DEPEND(bwn, bhnd, 1, 1, 1);
7735 MODULE_DEPEND(bwn, gpiobus, 1, 1, 1);
7736 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
7737 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
7738 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
7739 MODULE_VERSION(bwn, 1);
7740