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