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