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