if_bwn.c revision 299891
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 299891 2016-05-16 04:03:43Z 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 = contigmalloc(
2679		    (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2680		    BWN_HDRSIZE(mac), M_DEVBUF, M_ZERO,
2681		    0, BUS_SPACE_MAXADDR, 8, 0);
2682		if (dr->dr_txhdr_cache == NULL) {
2683			device_printf(sc->sc_dev,
2684			    "can't allocate TX header DMA memory\n");
2685			goto fail1;
2686		}
2687
2688		/*
2689		 * Create TX ring DMA stuffs
2690		 */
2691		error = bus_dma_tag_create(dma->parent_dtag,
2692				    BWN_ALIGN, 0,
2693				    BUS_SPACE_MAXADDR,
2694				    BUS_SPACE_MAXADDR,
2695				    NULL, NULL,
2696				    BWN_HDRSIZE(mac),
2697				    1,
2698				    BUS_SPACE_MAXSIZE_32BIT,
2699				    0,
2700				    NULL, NULL,
2701				    &dr->dr_txring_dtag);
2702		if (error) {
2703			device_printf(sc->sc_dev,
2704			    "can't create TX ring DMA tag: TODO frees\n");
2705			goto fail2;
2706		}
2707
2708		for (i = 0; i < dr->dr_numslots; i += 2) {
2709			dr->getdesc(dr, i, &desc, &mt);
2710
2711			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
2712			mt->mt_m = NULL;
2713			mt->mt_ni = NULL;
2714			mt->mt_islast = 0;
2715			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
2716			    &mt->mt_dmap);
2717			if (error) {
2718				device_printf(sc->sc_dev,
2719				     "can't create RX buf DMA map\n");
2720				goto fail2;
2721			}
2722
2723			dr->getdesc(dr, i + 1, &desc, &mt);
2724
2725			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
2726			mt->mt_m = NULL;
2727			mt->mt_ni = NULL;
2728			mt->mt_islast = 1;
2729			error = bus_dmamap_create(dma->txbuf_dtag, 0,
2730			    &mt->mt_dmap);
2731			if (error) {
2732				device_printf(sc->sc_dev,
2733				     "can't create RX buf DMA map\n");
2734				goto fail2;
2735			}
2736		}
2737	} else {
2738		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2739		    &dr->dr_spare_dmap);
2740		if (error) {
2741			device_printf(sc->sc_dev,
2742			    "can't create RX buf DMA map\n");
2743			goto out;		/* XXX wrong! */
2744		}
2745
2746		for (i = 0; i < dr->dr_numslots; i++) {
2747			dr->getdesc(dr, i, &desc, &mt);
2748
2749			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2750			    &mt->mt_dmap);
2751			if (error) {
2752				device_printf(sc->sc_dev,
2753				    "can't create RX buf DMA map\n");
2754				goto out;	/* XXX wrong! */
2755			}
2756			error = bwn_dma_newbuf(dr, desc, mt, 1);
2757			if (error) {
2758				device_printf(sc->sc_dev,
2759				    "failed to allocate RX buf\n");
2760				goto out;	/* XXX wrong! */
2761			}
2762		}
2763
2764		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
2765		    BUS_DMASYNC_PREWRITE);
2766
2767		dr->dr_usedslot = dr->dr_numslots;
2768	}
2769
2770      out:
2771	return (dr);
2772
2773fail2:
2774	if (dr->dr_txhdr_cache != NULL) {
2775		contigfree(dr->dr_txhdr_cache,
2776		    (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2777		    BWN_HDRSIZE(mac), M_DEVBUF);
2778	}
2779fail1:
2780	free(dr->dr_meta, M_DEVBUF);
2781fail0:
2782	free(dr, M_DEVBUF);
2783	return (NULL);
2784}
2785
2786static void
2787bwn_dma_ringfree(struct bwn_dma_ring **dr)
2788{
2789
2790	if (dr == NULL)
2791		return;
2792
2793	bwn_dma_free_descbufs(*dr);
2794	bwn_dma_free_ringmemory(*dr);
2795
2796	if ((*dr)->dr_txhdr_cache != NULL) {
2797		contigfree((*dr)->dr_txhdr_cache,
2798		    ((*dr)->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2799		    BWN_HDRSIZE((*dr)->dr_mac), M_DEVBUF);
2800	}
2801	free((*dr)->dr_meta, M_DEVBUF);
2802	free(*dr, M_DEVBUF);
2803
2804	*dr = NULL;
2805}
2806
2807static void
2808bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
2809    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
2810{
2811	struct bwn_dmadesc32 *desc;
2812
2813	*meta = &(dr->dr_meta[slot]);
2814	desc = dr->dr_ring_descbase;
2815	desc = &(desc[slot]);
2816
2817	*gdesc = (struct bwn_dmadesc_generic *)desc;
2818}
2819
2820static void
2821bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
2822    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
2823    int start, int end, int irq)
2824{
2825	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
2826	struct bwn_softc *sc = dr->dr_mac->mac_sc;
2827	uint32_t addr, addrext, ctl;
2828	int slot;
2829
2830	slot = (int)(&(desc->dma.dma32) - descbase);
2831	KASSERT(slot >= 0 && slot < dr->dr_numslots,
2832	    ("%s:%d: fail", __func__, __LINE__));
2833
2834	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
2835	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
2836	addr |= siba_dma_translation(sc->sc_dev);
2837	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
2838	if (slot == dr->dr_numslots - 1)
2839		ctl |= BWN_DMA32_DCTL_DTABLEEND;
2840	if (start)
2841		ctl |= BWN_DMA32_DCTL_FRAMESTART;
2842	if (end)
2843		ctl |= BWN_DMA32_DCTL_FRAMEEND;
2844	if (irq)
2845		ctl |= BWN_DMA32_DCTL_IRQ;
2846	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
2847	    & BWN_DMA32_DCTL_ADDREXT_MASK;
2848
2849	desc->dma.dma32.control = htole32(ctl);
2850	desc->dma.dma32.address = htole32(addr);
2851}
2852
2853static void
2854bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
2855{
2856
2857	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
2858	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
2859}
2860
2861static void
2862bwn_dma_32_suspend(struct bwn_dma_ring *dr)
2863{
2864
2865	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2866	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
2867}
2868
2869static void
2870bwn_dma_32_resume(struct bwn_dma_ring *dr)
2871{
2872
2873	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2874	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
2875}
2876
2877static int
2878bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
2879{
2880	uint32_t val;
2881
2882	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
2883	val &= BWN_DMA32_RXDPTR;
2884
2885	return (val / sizeof(struct bwn_dmadesc32));
2886}
2887
2888static void
2889bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
2890{
2891
2892	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
2893	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
2894}
2895
2896static void
2897bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
2898    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
2899{
2900	struct bwn_dmadesc64 *desc;
2901
2902	*meta = &(dr->dr_meta[slot]);
2903	desc = dr->dr_ring_descbase;
2904	desc = &(desc[slot]);
2905
2906	*gdesc = (struct bwn_dmadesc_generic *)desc;
2907}
2908
2909static void
2910bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
2911    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
2912    int start, int end, int irq)
2913{
2914	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
2915	struct bwn_softc *sc = dr->dr_mac->mac_sc;
2916	int slot;
2917	uint32_t ctl0 = 0, ctl1 = 0;
2918	uint32_t addrlo, addrhi;
2919	uint32_t addrext;
2920
2921	slot = (int)(&(desc->dma.dma64) - descbase);
2922	KASSERT(slot >= 0 && slot < dr->dr_numslots,
2923	    ("%s:%d: fail", __func__, __LINE__));
2924
2925	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
2926	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
2927	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
2928	    30;
2929	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
2930	if (slot == dr->dr_numslots - 1)
2931		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
2932	if (start)
2933		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
2934	if (end)
2935		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
2936	if (irq)
2937		ctl0 |= BWN_DMA64_DCTL0_IRQ;
2938	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
2939	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
2940	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
2941
2942	desc->dma.dma64.control0 = htole32(ctl0);
2943	desc->dma.dma64.control1 = htole32(ctl1);
2944	desc->dma.dma64.address_low = htole32(addrlo);
2945	desc->dma.dma64.address_high = htole32(addrhi);
2946}
2947
2948static void
2949bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
2950{
2951
2952	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
2953	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
2954}
2955
2956static void
2957bwn_dma_64_suspend(struct bwn_dma_ring *dr)
2958{
2959
2960	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
2961	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
2962}
2963
2964static void
2965bwn_dma_64_resume(struct bwn_dma_ring *dr)
2966{
2967
2968	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
2969	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
2970}
2971
2972static int
2973bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
2974{
2975	uint32_t val;
2976
2977	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
2978	val &= BWN_DMA64_RXSTATDPTR;
2979
2980	return (val / sizeof(struct bwn_dmadesc64));
2981}
2982
2983static void
2984bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
2985{
2986
2987	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
2988	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
2989}
2990
2991static int
2992bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
2993{
2994	struct bwn_mac *mac = dr->dr_mac;
2995	struct bwn_dma *dma = &mac->mac_method.dma;
2996	struct bwn_softc *sc = mac->mac_sc;
2997	int error;
2998
2999	error = bus_dma_tag_create(dma->parent_dtag,
3000			    BWN_ALIGN, 0,
3001			    BUS_SPACE_MAXADDR,
3002			    BUS_SPACE_MAXADDR,
3003			    NULL, NULL,
3004			    BWN_DMA_RINGMEMSIZE,
3005			    1,
3006			    BUS_SPACE_MAXSIZE_32BIT,
3007			    0,
3008			    NULL, NULL,
3009			    &dr->dr_ring_dtag);
3010	if (error) {
3011		device_printf(sc->sc_dev,
3012		    "can't create TX ring DMA tag: TODO frees\n");
3013		return (-1);
3014	}
3015
3016	error = bus_dmamem_alloc(dr->dr_ring_dtag,
3017	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
3018	    &dr->dr_ring_dmap);
3019	if (error) {
3020		device_printf(sc->sc_dev,
3021		    "can't allocate DMA mem: TODO frees\n");
3022		return (-1);
3023	}
3024	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
3025	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
3026	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
3027	if (error) {
3028		device_printf(sc->sc_dev,
3029		    "can't load DMA mem: TODO free\n");
3030		return (-1);
3031	}
3032
3033	return (0);
3034}
3035
3036static void
3037bwn_dma_setup(struct bwn_dma_ring *dr)
3038{
3039	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3040	uint64_t ring64;
3041	uint32_t addrext, ring32, value;
3042	uint32_t trans = siba_dma_translation(sc->sc_dev);
3043
3044	if (dr->dr_tx) {
3045		dr->dr_curslot = -1;
3046
3047		if (dr->dr_type == BWN_DMA_64BIT) {
3048			ring64 = (uint64_t)(dr->dr_ring_dmabase);
3049			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
3050			    >> 30;
3051			value = BWN_DMA64_TXENABLE;
3052			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
3053			    & BWN_DMA64_TXADDREXT_MASK;
3054			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
3055			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
3056			    (ring64 & 0xffffffff));
3057			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
3058			    ((ring64 >> 32) &
3059			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
3060		} else {
3061			ring32 = (uint32_t)(dr->dr_ring_dmabase);
3062			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3063			value = BWN_DMA32_TXENABLE;
3064			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
3065			    & BWN_DMA32_TXADDREXT_MASK;
3066			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
3067			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
3068			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3069		}
3070		return;
3071	}
3072
3073	/*
3074	 * set for RX
3075	 */
3076	dr->dr_usedslot = dr->dr_numslots;
3077
3078	if (dr->dr_type == BWN_DMA_64BIT) {
3079		ring64 = (uint64_t)(dr->dr_ring_dmabase);
3080		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
3081		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
3082		value |= BWN_DMA64_RXENABLE;
3083		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
3084		    & BWN_DMA64_RXADDREXT_MASK;
3085		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
3086		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
3087		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
3088		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
3089		    | (trans << 1));
3090		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
3091		    sizeof(struct bwn_dmadesc64));
3092	} else {
3093		ring32 = (uint32_t)(dr->dr_ring_dmabase);
3094		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3095		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
3096		value |= BWN_DMA32_RXENABLE;
3097		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
3098		    & BWN_DMA32_RXADDREXT_MASK;
3099		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
3100		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
3101		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3102		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
3103		    sizeof(struct bwn_dmadesc32));
3104	}
3105}
3106
3107static void
3108bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
3109{
3110
3111	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
3112	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
3113	    dr->dr_ring_dmap);
3114}
3115
3116static void
3117bwn_dma_cleanup(struct bwn_dma_ring *dr)
3118{
3119
3120	if (dr->dr_tx) {
3121		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3122		if (dr->dr_type == BWN_DMA_64BIT) {
3123			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
3124			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
3125		} else
3126			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
3127	} else {
3128		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3129		if (dr->dr_type == BWN_DMA_64BIT) {
3130			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
3131			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
3132		} else
3133			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
3134	}
3135}
3136
3137static void
3138bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
3139{
3140	struct bwn_dmadesc_generic *desc;
3141	struct bwn_dmadesc_meta *meta;
3142	struct bwn_mac *mac = dr->dr_mac;
3143	struct bwn_dma *dma = &mac->mac_method.dma;
3144	struct bwn_softc *sc = mac->mac_sc;
3145	int i;
3146
3147	if (!dr->dr_usedslot)
3148		return;
3149	for (i = 0; i < dr->dr_numslots; i++) {
3150		dr->getdesc(dr, i, &desc, &meta);
3151
3152		if (meta->mt_m == NULL) {
3153			if (!dr->dr_tx)
3154				device_printf(sc->sc_dev, "%s: not TX?\n",
3155				    __func__);
3156			continue;
3157		}
3158		if (dr->dr_tx) {
3159			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
3160				bus_dmamap_unload(dr->dr_txring_dtag,
3161				    meta->mt_dmap);
3162			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
3163				bus_dmamap_unload(dma->txbuf_dtag,
3164				    meta->mt_dmap);
3165		} else
3166			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
3167		bwn_dma_free_descbuf(dr, meta);
3168	}
3169}
3170
3171static int
3172bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
3173    int type)
3174{
3175	struct bwn_softc *sc = mac->mac_sc;
3176	uint32_t value;
3177	int i;
3178	uint16_t offset;
3179
3180	for (i = 0; i < 10; i++) {
3181		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3182		    BWN_DMA32_TXSTATUS;
3183		value = BWN_READ_4(mac, base + offset);
3184		if (type == BWN_DMA_64BIT) {
3185			value &= BWN_DMA64_TXSTAT;
3186			if (value == BWN_DMA64_TXSTAT_DISABLED ||
3187			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
3188			    value == BWN_DMA64_TXSTAT_STOPPED)
3189				break;
3190		} else {
3191			value &= BWN_DMA32_TXSTATE;
3192			if (value == BWN_DMA32_TXSTAT_DISABLED ||
3193			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
3194			    value == BWN_DMA32_TXSTAT_STOPPED)
3195				break;
3196		}
3197		DELAY(1000);
3198	}
3199	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
3200	BWN_WRITE_4(mac, base + offset, 0);
3201	for (i = 0; i < 10; i++) {
3202		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3203						   BWN_DMA32_TXSTATUS;
3204		value = BWN_READ_4(mac, base + offset);
3205		if (type == BWN_DMA_64BIT) {
3206			value &= BWN_DMA64_TXSTAT;
3207			if (value == BWN_DMA64_TXSTAT_DISABLED) {
3208				i = -1;
3209				break;
3210			}
3211		} else {
3212			value &= BWN_DMA32_TXSTATE;
3213			if (value == BWN_DMA32_TXSTAT_DISABLED) {
3214				i = -1;
3215				break;
3216			}
3217		}
3218		DELAY(1000);
3219	}
3220	if (i != -1) {
3221		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3222		return (ENODEV);
3223	}
3224	DELAY(1000);
3225
3226	return (0);
3227}
3228
3229static int
3230bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
3231    int type)
3232{
3233	struct bwn_softc *sc = mac->mac_sc;
3234	uint32_t value;
3235	int i;
3236	uint16_t offset;
3237
3238	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
3239	BWN_WRITE_4(mac, base + offset, 0);
3240	for (i = 0; i < 10; i++) {
3241		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
3242		    BWN_DMA32_RXSTATUS;
3243		value = BWN_READ_4(mac, base + offset);
3244		if (type == BWN_DMA_64BIT) {
3245			value &= BWN_DMA64_RXSTAT;
3246			if (value == BWN_DMA64_RXSTAT_DISABLED) {
3247				i = -1;
3248				break;
3249			}
3250		} else {
3251			value &= BWN_DMA32_RXSTATE;
3252			if (value == BWN_DMA32_RXSTAT_DISABLED) {
3253				i = -1;
3254				break;
3255			}
3256		}
3257		DELAY(1000);
3258	}
3259	if (i != -1) {
3260		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3261		return (ENODEV);
3262	}
3263
3264	return (0);
3265}
3266
3267static void
3268bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
3269    struct bwn_dmadesc_meta *meta)
3270{
3271
3272	if (meta->mt_m != NULL) {
3273		m_freem(meta->mt_m);
3274		meta->mt_m = NULL;
3275	}
3276	if (meta->mt_ni != NULL) {
3277		ieee80211_free_node(meta->mt_ni);
3278		meta->mt_ni = NULL;
3279	}
3280}
3281
3282static void
3283bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3284{
3285	struct bwn_rxhdr4 *rxhdr;
3286	unsigned char *frame;
3287
3288	rxhdr = mtod(m, struct bwn_rxhdr4 *);
3289	rxhdr->frame_len = 0;
3290
3291	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
3292	    sizeof(struct bwn_plcp6) + 2,
3293	    ("%s:%d: fail", __func__, __LINE__));
3294	frame = mtod(m, char *) + dr->dr_frameoffset;
3295	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
3296}
3297
3298static uint8_t
3299bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3300{
3301	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
3302
3303	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
3304	    == 0xff);
3305}
3306
3307static void
3308bwn_wme_init(struct bwn_mac *mac)
3309{
3310
3311	bwn_wme_load(mac);
3312
3313	/* enable WME support. */
3314	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
3315	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
3316	    BWN_IFSCTL_USE_EDCF);
3317}
3318
3319static void
3320bwn_spu_setdelay(struct bwn_mac *mac, int idle)
3321{
3322	struct bwn_softc *sc = mac->mac_sc;
3323	struct ieee80211com *ic = &sc->sc_ic;
3324	uint16_t delay;	/* microsec */
3325
3326	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
3327	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
3328		delay = 500;
3329	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
3330		delay = max(delay, (uint16_t)2400);
3331
3332	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
3333}
3334
3335static void
3336bwn_bt_enable(struct bwn_mac *mac)
3337{
3338	struct bwn_softc *sc = mac->mac_sc;
3339	uint64_t hf;
3340
3341	if (bwn_bluetooth == 0)
3342		return;
3343	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
3344		return;
3345	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
3346		return;
3347
3348	hf = bwn_hf_read(mac);
3349	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
3350		hf |= BWN_HF_BT_COEXISTALT;
3351	else
3352		hf |= BWN_HF_BT_COEXIST;
3353	bwn_hf_write(mac, hf);
3354}
3355
3356static void
3357bwn_set_macaddr(struct bwn_mac *mac)
3358{
3359
3360	bwn_mac_write_bssid(mac);
3361	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
3362	    mac->mac_sc->sc_ic.ic_macaddr);
3363}
3364
3365static void
3366bwn_clear_keys(struct bwn_mac *mac)
3367{
3368	int i;
3369
3370	for (i = 0; i < mac->mac_max_nr_keys; i++) {
3371		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
3372		    ("%s:%d: fail", __func__, __LINE__));
3373
3374		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
3375		    NULL, BWN_SEC_KEYSIZE, NULL);
3376		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
3377			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
3378			    NULL, BWN_SEC_KEYSIZE, NULL);
3379		}
3380		mac->mac_key[i].keyconf = NULL;
3381	}
3382}
3383
3384static void
3385bwn_crypt_init(struct bwn_mac *mac)
3386{
3387	struct bwn_softc *sc = mac->mac_sc;
3388
3389	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
3390	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
3391	    ("%s:%d: fail", __func__, __LINE__));
3392	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
3393	mac->mac_ktp *= 2;
3394	if (siba_get_revid(sc->sc_dev) >= 5)
3395		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
3396	bwn_clear_keys(mac);
3397}
3398
3399static void
3400bwn_chip_exit(struct bwn_mac *mac)
3401{
3402	struct bwn_softc *sc = mac->mac_sc;
3403
3404	bwn_phy_exit(mac);
3405	siba_gpio_set(sc->sc_dev, 0);
3406}
3407
3408static int
3409bwn_fw_fillinfo(struct bwn_mac *mac)
3410{
3411	int error;
3412
3413	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
3414	if (error == 0)
3415		return (0);
3416	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
3417	if (error == 0)
3418		return (0);
3419	return (error);
3420}
3421
3422static int
3423bwn_gpio_init(struct bwn_mac *mac)
3424{
3425	struct bwn_softc *sc = mac->mac_sc;
3426	uint32_t mask = 0x1f, set = 0xf, value;
3427
3428	BWN_WRITE_4(mac, BWN_MACCTL,
3429	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
3430	BWN_WRITE_2(mac, BWN_GPIO_MASK,
3431	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
3432
3433	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
3434		mask |= 0x0060;
3435		set |= 0x0060;
3436	}
3437	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
3438		BWN_WRITE_2(mac, BWN_GPIO_MASK,
3439		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
3440		mask |= 0x0200;
3441		set |= 0x0200;
3442	}
3443	if (siba_get_revid(sc->sc_dev) >= 2)
3444		mask |= 0x0010;
3445
3446	value = siba_gpio_get(sc->sc_dev);
3447	if (value == -1)
3448		return (0);
3449	siba_gpio_set(sc->sc_dev, (value & mask) | set);
3450
3451	return (0);
3452}
3453
3454static int
3455bwn_fw_loadinitvals(struct bwn_mac *mac)
3456{
3457#define	GETFWOFFSET(fwp, offset)				\
3458	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
3459	const size_t hdr_len = sizeof(struct bwn_fwhdr);
3460	const struct bwn_fwhdr *hdr;
3461	struct bwn_fw *fw = &mac->mac_fw;
3462	int error;
3463
3464	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
3465	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
3466	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
3467	if (error)
3468		return (error);
3469	if (fw->initvals_band.fw) {
3470		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
3471		error = bwn_fwinitvals_write(mac,
3472		    GETFWOFFSET(fw->initvals_band, hdr_len),
3473		    be32toh(hdr->size),
3474		    fw->initvals_band.fw->datasize - hdr_len);
3475	}
3476	return (error);
3477#undef GETFWOFFSET
3478}
3479
3480static int
3481bwn_phy_init(struct bwn_mac *mac)
3482{
3483	struct bwn_softc *sc = mac->mac_sc;
3484	int error;
3485
3486	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
3487	mac->mac_phy.rf_onoff(mac, 1);
3488	error = mac->mac_phy.init(mac);
3489	if (error) {
3490		device_printf(sc->sc_dev, "PHY init failed\n");
3491		goto fail0;
3492	}
3493	error = bwn_switch_channel(mac,
3494	    mac->mac_phy.get_default_chan(mac));
3495	if (error) {
3496		device_printf(sc->sc_dev,
3497		    "failed to switch default channel\n");
3498		goto fail1;
3499	}
3500	return (0);
3501fail1:
3502	if (mac->mac_phy.exit)
3503		mac->mac_phy.exit(mac);
3504fail0:
3505	mac->mac_phy.rf_onoff(mac, 0);
3506
3507	return (error);
3508}
3509
3510static void
3511bwn_set_txantenna(struct bwn_mac *mac, int antenna)
3512{
3513	uint16_t ant;
3514	uint16_t tmp;
3515
3516	ant = bwn_ant2phy(antenna);
3517
3518	/* For ACK/CTS */
3519	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
3520	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3521	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
3522	/* For Probe Resposes */
3523	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
3524	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3525	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
3526}
3527
3528static void
3529bwn_set_opmode(struct bwn_mac *mac)
3530{
3531	struct bwn_softc *sc = mac->mac_sc;
3532	struct ieee80211com *ic = &sc->sc_ic;
3533	uint32_t ctl;
3534	uint16_t cfp_pretbtt;
3535
3536	ctl = BWN_READ_4(mac, BWN_MACCTL);
3537	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
3538	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
3539	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
3540	ctl |= BWN_MACCTL_STA;
3541
3542	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
3543	    ic->ic_opmode == IEEE80211_M_MBSS)
3544		ctl |= BWN_MACCTL_HOSTAP;
3545	else if (ic->ic_opmode == IEEE80211_M_IBSS)
3546		ctl &= ~BWN_MACCTL_STA;
3547	ctl |= sc->sc_filters;
3548
3549	if (siba_get_revid(sc->sc_dev) <= 4)
3550		ctl |= BWN_MACCTL_PROMISC;
3551
3552	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
3553
3554	cfp_pretbtt = 2;
3555	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
3556		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
3557		    siba_get_chiprev(sc->sc_dev) == 3)
3558			cfp_pretbtt = 100;
3559		else
3560			cfp_pretbtt = 50;
3561	}
3562	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
3563}
3564
3565static int
3566bwn_dma_gettype(struct bwn_mac *mac)
3567{
3568	uint32_t tmp;
3569	uint16_t base;
3570
3571	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3572	if (tmp & SIBA_TGSHIGH_DMA64)
3573		return (BWN_DMA_64BIT);
3574	base = bwn_dma_base(0, 0);
3575	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3576	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3577	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3578		return (BWN_DMA_32BIT);
3579
3580	return (BWN_DMA_30BIT);
3581}
3582
3583static void
3584bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
3585{
3586	if (!error) {
3587		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
3588		*((bus_addr_t *)arg) = seg->ds_addr;
3589	}
3590}
3591
3592void
3593bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
3594{
3595	struct bwn_phy *phy = &mac->mac_phy;
3596	struct bwn_softc *sc = mac->mac_sc;
3597	unsigned int i, max_loop;
3598	uint16_t value;
3599	uint32_t buffer[5] = {
3600		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
3601	};
3602
3603	if (ofdm) {
3604		max_loop = 0x1e;
3605		buffer[0] = 0x000201cc;
3606	} else {
3607		max_loop = 0xfa;
3608		buffer[0] = 0x000b846e;
3609	}
3610
3611	BWN_ASSERT_LOCKED(mac->mac_sc);
3612
3613	for (i = 0; i < 5; i++)
3614		bwn_ram_write(mac, i * 4, buffer[i]);
3615
3616	BWN_WRITE_2(mac, 0x0568, 0x0000);
3617	BWN_WRITE_2(mac, 0x07c0,
3618	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
3619
3620	value = (ofdm ? 0x41 : 0x40);
3621	BWN_WRITE_2(mac, 0x050c, value);
3622
3623	if (phy->type == BWN_PHYTYPE_N || phy->type == BWN_PHYTYPE_LP ||
3624	    phy->type == BWN_PHYTYPE_LCN)
3625		BWN_WRITE_2(mac, 0x0514, 0x1a02);
3626	BWN_WRITE_2(mac, 0x0508, 0x0000);
3627	BWN_WRITE_2(mac, 0x050a, 0x0000);
3628	BWN_WRITE_2(mac, 0x054c, 0x0000);
3629	BWN_WRITE_2(mac, 0x056a, 0x0014);
3630	BWN_WRITE_2(mac, 0x0568, 0x0826);
3631	BWN_WRITE_2(mac, 0x0500, 0x0000);
3632
3633	/* XXX TODO: n phy pa override? */
3634
3635	switch (phy->type) {
3636	case BWN_PHYTYPE_N:
3637	case BWN_PHYTYPE_LCN:
3638		BWN_WRITE_2(mac, 0x0502, 0x00d0);
3639		break;
3640	case BWN_PHYTYPE_LP:
3641		BWN_WRITE_2(mac, 0x0502, 0x0050);
3642		break;
3643	default:
3644		BWN_WRITE_2(mac, 0x0502, 0x0030);
3645		break;
3646	}
3647
3648	/* flush */
3649	BWN_READ_2(mac, 0x0502);
3650
3651	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3652		BWN_RF_WRITE(mac, 0x0051, 0x0017);
3653	for (i = 0x00; i < max_loop; i++) {
3654		value = BWN_READ_2(mac, 0x050e);
3655		if (value & 0x0080)
3656			break;
3657		DELAY(10);
3658	}
3659	for (i = 0x00; i < 0x0a; i++) {
3660		value = BWN_READ_2(mac, 0x050e);
3661		if (value & 0x0400)
3662			break;
3663		DELAY(10);
3664	}
3665	for (i = 0x00; i < 0x19; i++) {
3666		value = BWN_READ_2(mac, 0x0690);
3667		if (!(value & 0x0100))
3668			break;
3669		DELAY(10);
3670	}
3671	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3672		BWN_RF_WRITE(mac, 0x0051, 0x0037);
3673}
3674
3675void
3676bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
3677{
3678	uint32_t macctl;
3679
3680	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
3681
3682	macctl = BWN_READ_4(mac, BWN_MACCTL);
3683	if (macctl & BWN_MACCTL_BIGENDIAN)
3684		printf("TODO: need swap\n");
3685
3686	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
3687	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
3688	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
3689}
3690
3691void
3692bwn_mac_suspend(struct bwn_mac *mac)
3693{
3694	struct bwn_softc *sc = mac->mac_sc;
3695	int i;
3696	uint32_t tmp;
3697
3698	KASSERT(mac->mac_suspended >= 0,
3699	    ("%s:%d: fail", __func__, __LINE__));
3700
3701	if (mac->mac_suspended == 0) {
3702		bwn_psctl(mac, BWN_PS_AWAKE);
3703		BWN_WRITE_4(mac, BWN_MACCTL,
3704			    BWN_READ_4(mac, BWN_MACCTL)
3705			    & ~BWN_MACCTL_ON);
3706		BWN_READ_4(mac, BWN_MACCTL);
3707		for (i = 35; i; i--) {
3708			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3709			if (tmp & BWN_INTR_MAC_SUSPENDED)
3710				goto out;
3711			DELAY(10);
3712		}
3713		for (i = 40; i; i--) {
3714			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3715			if (tmp & BWN_INTR_MAC_SUSPENDED)
3716				goto out;
3717			DELAY(1000);
3718		}
3719		device_printf(sc->sc_dev, "MAC suspend failed\n");
3720	}
3721out:
3722	mac->mac_suspended++;
3723}
3724
3725void
3726bwn_mac_enable(struct bwn_mac *mac)
3727{
3728	struct bwn_softc *sc = mac->mac_sc;
3729	uint16_t state;
3730
3731	state = bwn_shm_read_2(mac, BWN_SHARED,
3732	    BWN_SHARED_UCODESTAT);
3733	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
3734	    state != BWN_SHARED_UCODESTAT_SLEEP)
3735		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
3736
3737	mac->mac_suspended--;
3738	KASSERT(mac->mac_suspended >= 0,
3739	    ("%s:%d: fail", __func__, __LINE__));
3740	if (mac->mac_suspended == 0) {
3741		BWN_WRITE_4(mac, BWN_MACCTL,
3742		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
3743		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
3744		BWN_READ_4(mac, BWN_MACCTL);
3745		BWN_READ_4(mac, BWN_INTR_REASON);
3746		bwn_psctl(mac, 0);
3747	}
3748}
3749
3750void
3751bwn_psctl(struct bwn_mac *mac, uint32_t flags)
3752{
3753	struct bwn_softc *sc = mac->mac_sc;
3754	int i;
3755	uint16_t ucstat;
3756
3757	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
3758	    ("%s:%d: fail", __func__, __LINE__));
3759	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
3760	    ("%s:%d: fail", __func__, __LINE__));
3761
3762	/* XXX forcibly awake and hwps-off */
3763
3764	BWN_WRITE_4(mac, BWN_MACCTL,
3765	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
3766	    ~BWN_MACCTL_HWPS);
3767	BWN_READ_4(mac, BWN_MACCTL);
3768	if (siba_get_revid(sc->sc_dev) >= 5) {
3769		for (i = 0; i < 100; i++) {
3770			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
3771			    BWN_SHARED_UCODESTAT);
3772			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
3773				break;
3774			DELAY(10);
3775		}
3776	}
3777}
3778
3779static int
3780bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
3781{
3782	struct bwn_softc *sc = mac->mac_sc;
3783	struct bwn_fw *fw = &mac->mac_fw;
3784	const uint8_t rev = siba_get_revid(sc->sc_dev);
3785	const char *filename;
3786	uint32_t high;
3787	int error;
3788
3789	/* microcode */
3790	filename = NULL;
3791	switch (rev) {
3792	case 42:
3793		if (mac->mac_phy.type == BWN_PHYTYPE_AC)
3794			filename = "ucode42";
3795		break;
3796	case 40:
3797		if (mac->mac_phy.type == BWN_PHYTYPE_AC)
3798			filename = "ucode40";
3799		break;
3800	case 33:
3801		if (mac->mac_phy.type == BWN_PHYTYPE_LCN40)
3802			filename = "ucode33_lcn40";
3803		break;
3804	case 30:
3805		if (mac->mac_phy.type == BWN_PHYTYPE_N)
3806			filename = "ucode30_mimo";
3807		break;
3808	case 29:
3809		if (mac->mac_phy.type == BWN_PHYTYPE_HT)
3810			filename = "ucode29_mimo";
3811		break;
3812	case 26:
3813		if (mac->mac_phy.type == BWN_PHYTYPE_HT)
3814			filename = "ucode26_mimo";
3815		break;
3816	case 28:
3817	case 25:
3818		if (mac->mac_phy.type == BWN_PHYTYPE_N)
3819			filename = "ucode25_mimo";
3820		else if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
3821			filename = "ucode25_lcn";
3822		break;
3823	case 24:
3824		if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
3825			filename = "ucode24_lcn";
3826		break;
3827	case 23:
3828		if (mac->mac_phy.type == BWN_PHYTYPE_N)
3829			filename = "ucode16_mimo";
3830		break;
3831	case 16:
3832	case 17:
3833	case 18:
3834	case 19:
3835		if (mac->mac_phy.type == BWN_PHYTYPE_N)
3836			filename = "ucode16_mimo";
3837		else if (mac->mac_phy.type == BWN_PHYTYPE_LP)
3838			filename = "ucode16_lp";
3839		break;
3840	case 15:
3841		filename = "ucode15";
3842		break;
3843	case 14:
3844		filename = "ucode14";
3845		break;
3846	case 13:
3847		filename = "ucode13";
3848		break;
3849	case 12:
3850	case 11:
3851		filename = "ucode11";
3852		break;
3853	case 10:
3854	case 9:
3855	case 8:
3856	case 7:
3857	case 6:
3858	case 5:
3859		filename = "ucode5";
3860		break;
3861	default:
3862		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
3863		bwn_release_firmware(mac);
3864		return (EOPNOTSUPP);
3865	}
3866
3867	device_printf(sc->sc_dev, "ucode fw: %s\n", filename);
3868	error = bwn_fw_get(mac, type, filename, &fw->ucode);
3869	if (error) {
3870		bwn_release_firmware(mac);
3871		return (error);
3872	}
3873
3874	/* PCM */
3875	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
3876	if (rev >= 5 && rev <= 10) {
3877		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
3878		if (error == ENOENT)
3879			fw->no_pcmfile = 1;
3880		else if (error) {
3881			bwn_release_firmware(mac);
3882			return (error);
3883		}
3884	} else if (rev < 11) {
3885		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
3886		return (EOPNOTSUPP);
3887	}
3888
3889	/* initvals */
3890	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
3891	switch (mac->mac_phy.type) {
3892	case BWN_PHYTYPE_A:
3893		if (rev < 5 || rev > 10)
3894			goto fail1;
3895		if (high & BWN_TGSHIGH_HAVE_2GHZ)
3896			filename = "a0g1initvals5";
3897		else
3898			filename = "a0g0initvals5";
3899		break;
3900	case BWN_PHYTYPE_G:
3901		if (rev >= 5 && rev <= 10)
3902			filename = "b0g0initvals5";
3903		else if (rev >= 13)
3904			filename = "b0g0initvals13";
3905		else
3906			goto fail1;
3907		break;
3908	case BWN_PHYTYPE_LP:
3909		if (rev == 13)
3910			filename = "lp0initvals13";
3911		else if (rev == 14)
3912			filename = "lp0initvals14";
3913		else if (rev >= 15)
3914			filename = "lp0initvals15";
3915		else
3916			goto fail1;
3917		break;
3918	case BWN_PHYTYPE_N:
3919		if (rev == 30)
3920			filename = "n16initvals30";
3921		else if (rev == 28 || rev == 25)
3922			filename = "n0initvals25";
3923		else if (rev == 24)
3924			filename = "n0initvals24";
3925		else if (rev == 23)
3926			filename = "n0initvals16";
3927		else if (rev >= 16 && rev <= 18)
3928			filename = "n0initvals16";
3929		else if (rev >= 11 && rev <= 12)
3930			filename = "n0initvals11";
3931		else
3932			goto fail1;
3933		break;
3934	default:
3935		goto fail1;
3936	}
3937	error = bwn_fw_get(mac, type, filename, &fw->initvals);
3938	if (error) {
3939		bwn_release_firmware(mac);
3940		return (error);
3941	}
3942
3943	/* bandswitch initvals */
3944	switch (mac->mac_phy.type) {
3945	case BWN_PHYTYPE_A:
3946		if (rev >= 5 && rev <= 10) {
3947			if (high & BWN_TGSHIGH_HAVE_2GHZ)
3948				filename = "a0g1bsinitvals5";
3949			else
3950				filename = "a0g0bsinitvals5";
3951		} else if (rev >= 11)
3952			filename = NULL;
3953		else
3954			goto fail1;
3955		break;
3956	case BWN_PHYTYPE_G:
3957		if (rev >= 5 && rev <= 10)
3958			filename = "b0g0bsinitvals5";
3959		else if (rev >= 11)
3960			filename = NULL;
3961		else
3962			goto fail1;
3963		break;
3964	case BWN_PHYTYPE_LP:
3965		if (rev == 13)
3966			filename = "lp0bsinitvals13";
3967		else if (rev == 14)
3968			filename = "lp0bsinitvals14";
3969		else if (rev >= 15)
3970			filename = "lp0bsinitvals15";
3971		else
3972			goto fail1;
3973		break;
3974	case BWN_PHYTYPE_N:
3975		if (rev == 30)
3976			filename = "n16bsinitvals30";
3977		else if (rev == 28 || rev == 25)
3978			filename = "n0bsinitvals25";
3979		else if (rev == 24)
3980			filename = "n0bsinitvals24";
3981		else if (rev == 23)
3982			filename = "n0bsinitvals16";
3983		else if (rev >= 16 && rev <= 18)
3984			filename = "n0bsinitvals16";
3985		else if (rev >= 11 && rev <= 12)
3986			filename = "n0bsinitvals11";
3987		else
3988			goto fail1;
3989		break;
3990	default:
3991		device_printf(sc->sc_dev, "unknown phy (%d)\n",
3992		    mac->mac_phy.type);
3993		goto fail1;
3994	}
3995	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
3996	if (error) {
3997		bwn_release_firmware(mac);
3998		return (error);
3999	}
4000	return (0);
4001fail1:
4002	device_printf(sc->sc_dev, "no INITVALS for rev %d, phy.type %d\n",
4003	    rev, mac->mac_phy.type);
4004	bwn_release_firmware(mac);
4005	return (EOPNOTSUPP);
4006}
4007
4008static int
4009bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
4010    const char *name, struct bwn_fwfile *bfw)
4011{
4012	const struct bwn_fwhdr *hdr;
4013	struct bwn_softc *sc = mac->mac_sc;
4014	const struct firmware *fw;
4015	char namebuf[64];
4016
4017	if (name == NULL) {
4018		bwn_do_release_fw(bfw);
4019		return (0);
4020	}
4021	if (bfw->filename != NULL) {
4022		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
4023			return (0);
4024		bwn_do_release_fw(bfw);
4025	}
4026
4027	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
4028	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
4029	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
4030	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
4031	fw = firmware_get(namebuf);
4032	if (fw == NULL) {
4033		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
4034		    namebuf);
4035		return (ENOENT);
4036	}
4037	if (fw->datasize < sizeof(struct bwn_fwhdr))
4038		goto fail;
4039	hdr = (const struct bwn_fwhdr *)(fw->data);
4040	switch (hdr->type) {
4041	case BWN_FWTYPE_UCODE:
4042	case BWN_FWTYPE_PCM:
4043		if (be32toh(hdr->size) !=
4044		    (fw->datasize - sizeof(struct bwn_fwhdr)))
4045			goto fail;
4046		/* FALLTHROUGH */
4047	case BWN_FWTYPE_IV:
4048		if (hdr->ver != 1)
4049			goto fail;
4050		break;
4051	default:
4052		goto fail;
4053	}
4054	bfw->filename = name;
4055	bfw->fw = fw;
4056	bfw->type = type;
4057	return (0);
4058fail:
4059	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
4060	if (fw != NULL)
4061		firmware_put(fw, FIRMWARE_UNLOAD);
4062	return (EPROTO);
4063}
4064
4065static void
4066bwn_release_firmware(struct bwn_mac *mac)
4067{
4068
4069	bwn_do_release_fw(&mac->mac_fw.ucode);
4070	bwn_do_release_fw(&mac->mac_fw.pcm);
4071	bwn_do_release_fw(&mac->mac_fw.initvals);
4072	bwn_do_release_fw(&mac->mac_fw.initvals_band);
4073}
4074
4075static void
4076bwn_do_release_fw(struct bwn_fwfile *bfw)
4077{
4078
4079	if (bfw->fw != NULL)
4080		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
4081	bfw->fw = NULL;
4082	bfw->filename = NULL;
4083}
4084
4085static int
4086bwn_fw_loaducode(struct bwn_mac *mac)
4087{
4088#define	GETFWOFFSET(fwp, offset)	\
4089	((const uint32_t *)((const char *)fwp.fw->data + offset))
4090#define	GETFWSIZE(fwp, offset)	\
4091	((fwp.fw->datasize - offset) / sizeof(uint32_t))
4092	struct bwn_softc *sc = mac->mac_sc;
4093	const uint32_t *data;
4094	unsigned int i;
4095	uint32_t ctl;
4096	uint16_t date, fwcaps, time;
4097	int error = 0;
4098
4099	ctl = BWN_READ_4(mac, BWN_MACCTL);
4100	ctl |= BWN_MACCTL_MCODE_JMP0;
4101	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
4102	    __LINE__));
4103	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4104	for (i = 0; i < 64; i++)
4105		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
4106	for (i = 0; i < 4096; i += 2)
4107		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
4108
4109	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4110	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
4111	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4112	     i++) {
4113		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4114		DELAY(10);
4115	}
4116
4117	if (mac->mac_fw.pcm.fw) {
4118		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
4119		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
4120		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
4121		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
4122		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
4123		    sizeof(struct bwn_fwhdr)); i++) {
4124			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4125			DELAY(10);
4126		}
4127	}
4128
4129	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
4130	BWN_WRITE_4(mac, BWN_MACCTL,
4131	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
4132	    BWN_MACCTL_MCODE_RUN);
4133
4134	for (i = 0; i < 21; i++) {
4135		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
4136			break;
4137		if (i >= 20) {
4138			device_printf(sc->sc_dev, "ucode timeout\n");
4139			error = ENXIO;
4140			goto error;
4141		}
4142		DELAY(50000);
4143	}
4144	BWN_READ_4(mac, BWN_INTR_REASON);
4145
4146	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
4147	if (mac->mac_fw.rev <= 0x128) {
4148		device_printf(sc->sc_dev, "the firmware is too old\n");
4149		error = EOPNOTSUPP;
4150		goto error;
4151	}
4152
4153	/*
4154	 * Determine firmware header version; needed for TX/RX packet
4155	 * handling.
4156	 */
4157	if (mac->mac_fw.rev >= 598)
4158		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_598;
4159	else if (mac->mac_fw.rev >= 410)
4160		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_410;
4161	else
4162		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_351;
4163
4164	/*
4165	 * We don't support rev 598 or later; that requires
4166	 * another round of changes to the TX/RX descriptor
4167	 * and status layout.
4168	 *
4169	 * So, complain this is the case and exit out, rather
4170	 * than attaching and then failing.
4171	 */
4172	if (mac->mac_fw.fw_hdr_format == BWN_FW_HDR_598) {
4173		device_printf(sc->sc_dev,
4174		    "firmware is too new (>=598); not supported\n");
4175		error = EOPNOTSUPP;
4176		goto error;
4177	}
4178
4179	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
4180	    BWN_SHARED_UCODE_PATCH);
4181	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
4182	mac->mac_fw.opensource = (date == 0xffff);
4183	if (bwn_wme != 0)
4184		mac->mac_flags |= BWN_MAC_FLAG_WME;
4185	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
4186
4187	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
4188	if (mac->mac_fw.opensource == 0) {
4189		device_printf(sc->sc_dev,
4190		    "firmware version (rev %u patch %u date %#x time %#x)\n",
4191		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
4192		if (mac->mac_fw.no_pcmfile)
4193			device_printf(sc->sc_dev,
4194			    "no HW crypto acceleration due to pcm5\n");
4195	} else {
4196		mac->mac_fw.patch = time;
4197		fwcaps = bwn_fwcaps_read(mac);
4198		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
4199			device_printf(sc->sc_dev,
4200			    "disabling HW crypto acceleration\n");
4201			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
4202		}
4203		if (!(fwcaps & BWN_FWCAPS_WME)) {
4204			device_printf(sc->sc_dev, "disabling WME support\n");
4205			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
4206		}
4207	}
4208
4209	if (BWN_ISOLDFMT(mac))
4210		device_printf(sc->sc_dev, "using old firmware image\n");
4211
4212	return (0);
4213
4214error:
4215	BWN_WRITE_4(mac, BWN_MACCTL,
4216	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
4217	    BWN_MACCTL_MCODE_JMP0);
4218
4219	return (error);
4220#undef GETFWSIZE
4221#undef GETFWOFFSET
4222}
4223
4224/* OpenFirmware only */
4225static uint16_t
4226bwn_fwcaps_read(struct bwn_mac *mac)
4227{
4228
4229	KASSERT(mac->mac_fw.opensource == 1,
4230	    ("%s:%d: fail", __func__, __LINE__));
4231	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
4232}
4233
4234static int
4235bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
4236    size_t count, size_t array_size)
4237{
4238#define	GET_NEXTIV16(iv)						\
4239	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
4240	    sizeof(uint16_t) + sizeof(uint16_t)))
4241#define	GET_NEXTIV32(iv)						\
4242	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
4243	    sizeof(uint16_t) + sizeof(uint32_t)))
4244	struct bwn_softc *sc = mac->mac_sc;
4245	const struct bwn_fwinitvals *iv;
4246	uint16_t offset;
4247	size_t i;
4248	uint8_t bit32;
4249
4250	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
4251	    ("%s:%d: fail", __func__, __LINE__));
4252	iv = ivals;
4253	for (i = 0; i < count; i++) {
4254		if (array_size < sizeof(iv->offset_size))
4255			goto fail;
4256		array_size -= sizeof(iv->offset_size);
4257		offset = be16toh(iv->offset_size);
4258		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
4259		offset &= BWN_FWINITVALS_OFFSET_MASK;
4260		if (offset >= 0x1000)
4261			goto fail;
4262		if (bit32) {
4263			if (array_size < sizeof(iv->data.d32))
4264				goto fail;
4265			array_size -= sizeof(iv->data.d32);
4266			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
4267			iv = GET_NEXTIV32(iv);
4268		} else {
4269
4270			if (array_size < sizeof(iv->data.d16))
4271				goto fail;
4272			array_size -= sizeof(iv->data.d16);
4273			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
4274
4275			iv = GET_NEXTIV16(iv);
4276		}
4277	}
4278	if (array_size != 0)
4279		goto fail;
4280	return (0);
4281fail:
4282	device_printf(sc->sc_dev, "initvals: invalid format\n");
4283	return (EPROTO);
4284#undef GET_NEXTIV16
4285#undef GET_NEXTIV32
4286}
4287
4288int
4289bwn_switch_channel(struct bwn_mac *mac, int chan)
4290{
4291	struct bwn_phy *phy = &(mac->mac_phy);
4292	struct bwn_softc *sc = mac->mac_sc;
4293	struct ieee80211com *ic = &sc->sc_ic;
4294	uint16_t channelcookie, savedcookie;
4295	int error;
4296
4297	if (chan == 0xffff)
4298		chan = phy->get_default_chan(mac);
4299
4300	channelcookie = chan;
4301	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
4302		channelcookie |= 0x100;
4303	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
4304	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
4305	error = phy->switch_channel(mac, chan);
4306	if (error)
4307		goto fail;
4308
4309	mac->mac_phy.chan = chan;
4310	DELAY(8000);
4311	return (0);
4312fail:
4313	device_printf(sc->sc_dev, "failed to switch channel\n");
4314	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
4315	return (error);
4316}
4317
4318static uint16_t
4319bwn_ant2phy(int antenna)
4320{
4321
4322	switch (antenna) {
4323	case BWN_ANT0:
4324		return (BWN_TX_PHY_ANT0);
4325	case BWN_ANT1:
4326		return (BWN_TX_PHY_ANT1);
4327	case BWN_ANT2:
4328		return (BWN_TX_PHY_ANT2);
4329	case BWN_ANT3:
4330		return (BWN_TX_PHY_ANT3);
4331	case BWN_ANTAUTO:
4332		return (BWN_TX_PHY_ANT01AUTO);
4333	}
4334	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4335	return (0);
4336}
4337
4338static void
4339bwn_wme_load(struct bwn_mac *mac)
4340{
4341	struct bwn_softc *sc = mac->mac_sc;
4342	int i;
4343
4344	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
4345	    ("%s:%d: fail", __func__, __LINE__));
4346
4347	bwn_mac_suspend(mac);
4348	for (i = 0; i < N(sc->sc_wmeParams); i++)
4349		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
4350		    bwn_wme_shm_offsets[i]);
4351	bwn_mac_enable(mac);
4352}
4353
4354static void
4355bwn_wme_loadparams(struct bwn_mac *mac,
4356    const struct wmeParams *p, uint16_t shm_offset)
4357{
4358#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
4359	struct bwn_softc *sc = mac->mac_sc;
4360	uint16_t params[BWN_NR_WMEPARAMS];
4361	int slot, tmp;
4362	unsigned int i;
4363
4364	slot = BWN_READ_2(mac, BWN_RNG) &
4365	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4366
4367	memset(&params, 0, sizeof(params));
4368
4369	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
4370	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
4371	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
4372
4373	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
4374	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4375	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
4376	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4377	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
4378	params[BWN_WMEPARAM_BSLOTS] = slot;
4379	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
4380
4381	for (i = 0; i < N(params); i++) {
4382		if (i == BWN_WMEPARAM_STATUS) {
4383			tmp = bwn_shm_read_2(mac, BWN_SHARED,
4384			    shm_offset + (i * 2));
4385			tmp |= 0x100;
4386			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4387			    tmp);
4388		} else {
4389			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4390			    params[i]);
4391		}
4392	}
4393}
4394
4395static void
4396bwn_mac_write_bssid(struct bwn_mac *mac)
4397{
4398	struct bwn_softc *sc = mac->mac_sc;
4399	uint32_t tmp;
4400	int i;
4401	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
4402
4403	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
4404	memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
4405	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
4406	    IEEE80211_ADDR_LEN);
4407
4408	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
4409		tmp = (uint32_t) (mac_bssid[i + 0]);
4410		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
4411		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
4412		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
4413		bwn_ram_write(mac, 0x20 + i, tmp);
4414	}
4415}
4416
4417static void
4418bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
4419    const uint8_t *macaddr)
4420{
4421	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
4422	uint16_t data;
4423
4424	if (!mac)
4425		macaddr = zero;
4426
4427	offset |= 0x0020;
4428	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
4429
4430	data = macaddr[0];
4431	data |= macaddr[1] << 8;
4432	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4433	data = macaddr[2];
4434	data |= macaddr[3] << 8;
4435	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4436	data = macaddr[4];
4437	data |= macaddr[5] << 8;
4438	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4439}
4440
4441static void
4442bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4443    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
4444{
4445	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
4446	uint8_t per_sta_keys_start = 8;
4447
4448	if (BWN_SEC_NEWAPI(mac))
4449		per_sta_keys_start = 4;
4450
4451	KASSERT(index < mac->mac_max_nr_keys,
4452	    ("%s:%d: fail", __func__, __LINE__));
4453	KASSERT(key_len <= BWN_SEC_KEYSIZE,
4454	    ("%s:%d: fail", __func__, __LINE__));
4455
4456	if (index >= per_sta_keys_start)
4457		bwn_key_macwrite(mac, index, NULL);
4458	if (key)
4459		memcpy(buf, key, key_len);
4460	bwn_key_write(mac, index, algorithm, buf);
4461	if (index >= per_sta_keys_start)
4462		bwn_key_macwrite(mac, index, mac_addr);
4463
4464	mac->mac_key[index].algorithm = algorithm;
4465}
4466
4467static void
4468bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
4469{
4470	struct bwn_softc *sc = mac->mac_sc;
4471	uint32_t addrtmp[2] = { 0, 0 };
4472	uint8_t start = 8;
4473
4474	if (BWN_SEC_NEWAPI(mac))
4475		start = 4;
4476
4477	KASSERT(index >= start,
4478	    ("%s:%d: fail", __func__, __LINE__));
4479	index -= start;
4480
4481	if (addr) {
4482		addrtmp[0] = addr[0];
4483		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
4484		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
4485		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
4486		addrtmp[1] = addr[4];
4487		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
4488	}
4489
4490	if (siba_get_revid(sc->sc_dev) >= 5) {
4491		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
4492		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
4493	} else {
4494		if (index >= 8) {
4495			bwn_shm_write_4(mac, BWN_SHARED,
4496			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
4497			bwn_shm_write_2(mac, BWN_SHARED,
4498			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
4499		}
4500	}
4501}
4502
4503static void
4504bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4505    const uint8_t *key)
4506{
4507	unsigned int i;
4508	uint32_t offset;
4509	uint16_t kidx, value;
4510
4511	kidx = BWN_SEC_KEY2FW(mac, index);
4512	bwn_shm_write_2(mac, BWN_SHARED,
4513	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
4514
4515	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
4516	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
4517		value = key[i];
4518		value |= (uint16_t)(key[i + 1]) << 8;
4519		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
4520	}
4521}
4522
4523static void
4524bwn_phy_exit(struct bwn_mac *mac)
4525{
4526
4527	mac->mac_phy.rf_onoff(mac, 0);
4528	if (mac->mac_phy.exit != NULL)
4529		mac->mac_phy.exit(mac);
4530}
4531
4532static void
4533bwn_dma_free(struct bwn_mac *mac)
4534{
4535	struct bwn_dma *dma;
4536
4537	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
4538		return;
4539	dma = &mac->mac_method.dma;
4540
4541	bwn_dma_ringfree(&dma->rx);
4542	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
4543	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
4544	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
4545	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
4546	bwn_dma_ringfree(&dma->mcast);
4547}
4548
4549static void
4550bwn_core_stop(struct bwn_mac *mac)
4551{
4552	struct bwn_softc *sc = mac->mac_sc;
4553
4554	BWN_ASSERT_LOCKED(sc);
4555
4556	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
4557		return;
4558
4559	callout_stop(&sc->sc_rfswitch_ch);
4560	callout_stop(&sc->sc_task_ch);
4561	callout_stop(&sc->sc_watchdog_ch);
4562	sc->sc_watchdog_timer = 0;
4563	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4564	BWN_READ_4(mac, BWN_INTR_MASK);
4565	bwn_mac_suspend(mac);
4566
4567	mac->mac_status = BWN_MAC_STATUS_INITED;
4568}
4569
4570static int
4571bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
4572{
4573	struct bwn_mac *up_dev = NULL;
4574	struct bwn_mac *down_dev;
4575	struct bwn_mac *mac;
4576	int err, status;
4577	uint8_t gmode;
4578
4579	BWN_ASSERT_LOCKED(sc);
4580
4581	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
4582		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
4583		    mac->mac_phy.supports_2ghz) {
4584			up_dev = mac;
4585			gmode = 1;
4586		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
4587		    mac->mac_phy.supports_5ghz) {
4588			up_dev = mac;
4589			gmode = 0;
4590		} else {
4591			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4592			return (EINVAL);
4593		}
4594		if (up_dev != NULL)
4595			break;
4596	}
4597	if (up_dev == NULL) {
4598		device_printf(sc->sc_dev, "Could not find a device\n");
4599		return (ENODEV);
4600	}
4601	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
4602		return (0);
4603
4604	DPRINTF(sc, BWN_DEBUG_RF | BWN_DEBUG_PHY | BWN_DEBUG_RESET,
4605	    "switching to %s-GHz band\n",
4606	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4607
4608	down_dev = sc->sc_curmac;
4609	status = down_dev->mac_status;
4610	if (status >= BWN_MAC_STATUS_STARTED)
4611		bwn_core_stop(down_dev);
4612	if (status >= BWN_MAC_STATUS_INITED)
4613		bwn_core_exit(down_dev);
4614
4615	if (down_dev != up_dev)
4616		bwn_phy_reset(down_dev);
4617
4618	up_dev->mac_phy.gmode = gmode;
4619	if (status >= BWN_MAC_STATUS_INITED) {
4620		err = bwn_core_init(up_dev);
4621		if (err) {
4622			device_printf(sc->sc_dev,
4623			    "fatal: failed to initialize for %s-GHz\n",
4624			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4625			goto fail;
4626		}
4627	}
4628	if (status >= BWN_MAC_STATUS_STARTED)
4629		bwn_core_start(up_dev);
4630	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
4631	sc->sc_curmac = up_dev;
4632
4633	return (0);
4634fail:
4635	sc->sc_curmac = NULL;
4636	return (err);
4637}
4638
4639static void
4640bwn_rf_turnon(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, 1);
4647	mac->mac_phy.rf_on = 1;
4648	bwn_mac_enable(mac);
4649}
4650
4651static void
4652bwn_rf_turnoff(struct bwn_mac *mac)
4653{
4654
4655	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4656
4657	bwn_mac_suspend(mac);
4658	mac->mac_phy.rf_onoff(mac, 0);
4659	mac->mac_phy.rf_on = 0;
4660	bwn_mac_enable(mac);
4661}
4662
4663/*
4664 * SSB PHY reset.
4665 *
4666 * XXX TODO: BCMA PHY reset.
4667 */
4668static void
4669bwn_phy_reset(struct bwn_mac *mac)
4670{
4671	struct bwn_softc *sc = mac->mac_sc;
4672
4673	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4674	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
4675	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
4676	DELAY(1000);
4677	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4678	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC));
4679	DELAY(1000);
4680}
4681
4682static int
4683bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
4684{
4685	struct bwn_vap *bvp = BWN_VAP(vap);
4686	struct ieee80211com *ic= vap->iv_ic;
4687	enum ieee80211_state ostate = vap->iv_state;
4688	struct bwn_softc *sc = ic->ic_softc;
4689	struct bwn_mac *mac = sc->sc_curmac;
4690	int error;
4691
4692	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
4693	    ieee80211_state_name[vap->iv_state],
4694	    ieee80211_state_name[nstate]);
4695
4696	error = bvp->bv_newstate(vap, nstate, arg);
4697	if (error != 0)
4698		return (error);
4699
4700	BWN_LOCK(sc);
4701
4702	bwn_led_newstate(mac, nstate);
4703
4704	/*
4705	 * Clear the BSSID when we stop a STA
4706	 */
4707	if (vap->iv_opmode == IEEE80211_M_STA) {
4708		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
4709			/*
4710			 * Clear out the BSSID.  If we reassociate to
4711			 * the same AP, this will reinialize things
4712			 * correctly...
4713			 */
4714			if (ic->ic_opmode == IEEE80211_M_STA &&
4715			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
4716				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
4717				bwn_set_macaddr(mac);
4718			}
4719		}
4720	}
4721
4722	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
4723	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
4724		/* XXX nothing to do? */
4725	} else if (nstate == IEEE80211_S_RUN) {
4726		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
4727		bwn_set_opmode(mac);
4728		bwn_set_pretbtt(mac);
4729		bwn_spu_setdelay(mac, 0);
4730		bwn_set_macaddr(mac);
4731	}
4732
4733	BWN_UNLOCK(sc);
4734
4735	return (error);
4736}
4737
4738static void
4739bwn_set_pretbtt(struct bwn_mac *mac)
4740{
4741	struct bwn_softc *sc = mac->mac_sc;
4742	struct ieee80211com *ic = &sc->sc_ic;
4743	uint16_t pretbtt;
4744
4745	if (ic->ic_opmode == IEEE80211_M_IBSS)
4746		pretbtt = 2;
4747	else
4748		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
4749	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
4750	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
4751}
4752
4753static int
4754bwn_intr(void *arg)
4755{
4756	struct bwn_mac *mac = arg;
4757	struct bwn_softc *sc = mac->mac_sc;
4758	uint32_t reason;
4759
4760	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4761	    (sc->sc_flags & BWN_FLAG_INVALID))
4762		return (FILTER_STRAY);
4763
4764	reason = BWN_READ_4(mac, BWN_INTR_REASON);
4765	if (reason == 0xffffffff)	/* shared IRQ */
4766		return (FILTER_STRAY);
4767	reason &= mac->mac_intr_mask;
4768	if (reason == 0)
4769		return (FILTER_HANDLED);
4770
4771	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
4772	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
4773	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
4774	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
4775	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
4776	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
4777	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
4778	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
4779	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
4780	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
4781	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
4782
4783	/* Disable interrupts. */
4784	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4785
4786	mac->mac_reason_intr = reason;
4787
4788	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4789	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4790
4791	taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask);
4792	return (FILTER_HANDLED);
4793}
4794
4795static void
4796bwn_intrtask(void *arg, int npending)
4797{
4798	struct bwn_mac *mac = arg;
4799	struct bwn_softc *sc = mac->mac_sc;
4800	uint32_t merged = 0;
4801	int i, tx = 0, rx = 0;
4802
4803	BWN_LOCK(sc);
4804	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4805	    (sc->sc_flags & BWN_FLAG_INVALID)) {
4806		BWN_UNLOCK(sc);
4807		return;
4808	}
4809
4810	for (i = 0; i < N(mac->mac_reason); i++)
4811		merged |= mac->mac_reason[i];
4812
4813	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
4814		device_printf(sc->sc_dev, "MAC trans error\n");
4815
4816	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
4817		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
4818		mac->mac_phy.txerrors--;
4819		if (mac->mac_phy.txerrors == 0) {
4820			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
4821			bwn_restart(mac, "PHY TX errors");
4822		}
4823	}
4824
4825	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
4826		if (merged & BWN_DMAINTR_FATALMASK) {
4827			device_printf(sc->sc_dev,
4828			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
4829			    mac->mac_reason[0], mac->mac_reason[1],
4830			    mac->mac_reason[2], mac->mac_reason[3],
4831			    mac->mac_reason[4], mac->mac_reason[5]);
4832			bwn_restart(mac, "DMA error");
4833			BWN_UNLOCK(sc);
4834			return;
4835		}
4836		if (merged & BWN_DMAINTR_NONFATALMASK) {
4837			device_printf(sc->sc_dev,
4838			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
4839			    mac->mac_reason[0], mac->mac_reason[1],
4840			    mac->mac_reason[2], mac->mac_reason[3],
4841			    mac->mac_reason[4], mac->mac_reason[5]);
4842		}
4843	}
4844
4845	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
4846		bwn_intr_ucode_debug(mac);
4847	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
4848		bwn_intr_tbtt_indication(mac);
4849	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
4850		bwn_intr_atim_end(mac);
4851	if (mac->mac_reason_intr & BWN_INTR_BEACON)
4852		bwn_intr_beacon(mac);
4853	if (mac->mac_reason_intr & BWN_INTR_PMQ)
4854		bwn_intr_pmq(mac);
4855	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
4856		bwn_intr_noise(mac);
4857
4858	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
4859		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
4860			bwn_dma_rx(mac->mac_method.dma.rx);
4861			rx = 1;
4862		}
4863	} else
4864		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
4865
4866	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4867	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4868	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4869	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4870	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4871
4872	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
4873		bwn_intr_txeof(mac);
4874		tx = 1;
4875	}
4876
4877	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
4878
4879	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
4880		int evt = BWN_LED_EVENT_NONE;
4881
4882		if (tx && rx) {
4883			if (sc->sc_rx_rate > sc->sc_tx_rate)
4884				evt = BWN_LED_EVENT_RX;
4885			else
4886				evt = BWN_LED_EVENT_TX;
4887		} else if (tx) {
4888			evt = BWN_LED_EVENT_TX;
4889		} else if (rx) {
4890			evt = BWN_LED_EVENT_RX;
4891		} else if (rx == 0) {
4892			evt = BWN_LED_EVENT_POLL;
4893		}
4894
4895		if (evt != BWN_LED_EVENT_NONE)
4896			bwn_led_event(mac, evt);
4897       }
4898
4899	if (mbufq_first(&sc->sc_snd) != NULL)
4900		bwn_start(sc);
4901
4902	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4903	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4904
4905	BWN_UNLOCK(sc);
4906}
4907
4908static void
4909bwn_restart(struct bwn_mac *mac, const char *msg)
4910{
4911	struct bwn_softc *sc = mac->mac_sc;
4912	struct ieee80211com *ic = &sc->sc_ic;
4913
4914	if (mac->mac_status < BWN_MAC_STATUS_INITED)
4915		return;
4916
4917	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
4918	ieee80211_runtask(ic, &mac->mac_hwreset);
4919}
4920
4921static void
4922bwn_intr_ucode_debug(struct bwn_mac *mac)
4923{
4924	struct bwn_softc *sc = mac->mac_sc;
4925	uint16_t reason;
4926
4927	if (mac->mac_fw.opensource == 0)
4928		return;
4929
4930	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
4931	switch (reason) {
4932	case BWN_DEBUGINTR_PANIC:
4933		bwn_handle_fwpanic(mac);
4934		break;
4935	case BWN_DEBUGINTR_DUMP_SHM:
4936		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
4937		break;
4938	case BWN_DEBUGINTR_DUMP_REGS:
4939		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
4940		break;
4941	case BWN_DEBUGINTR_MARKER:
4942		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
4943		break;
4944	default:
4945		device_printf(sc->sc_dev,
4946		    "ucode debug unknown reason: %#x\n", reason);
4947	}
4948
4949	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
4950	    BWN_DEBUGINTR_ACK);
4951}
4952
4953static void
4954bwn_intr_tbtt_indication(struct bwn_mac *mac)
4955{
4956	struct bwn_softc *sc = mac->mac_sc;
4957	struct ieee80211com *ic = &sc->sc_ic;
4958
4959	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
4960		bwn_psctl(mac, 0);
4961	if (ic->ic_opmode == IEEE80211_M_IBSS)
4962		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
4963}
4964
4965static void
4966bwn_intr_atim_end(struct bwn_mac *mac)
4967{
4968
4969	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
4970		BWN_WRITE_4(mac, BWN_MACCMD,
4971		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
4972		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
4973	}
4974}
4975
4976static void
4977bwn_intr_beacon(struct bwn_mac *mac)
4978{
4979	struct bwn_softc *sc = mac->mac_sc;
4980	struct ieee80211com *ic = &sc->sc_ic;
4981	uint32_t cmd, beacon0, beacon1;
4982
4983	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4984	    ic->ic_opmode == IEEE80211_M_MBSS)
4985		return;
4986
4987	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
4988
4989	cmd = BWN_READ_4(mac, BWN_MACCMD);
4990	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
4991	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
4992
4993	if (beacon0 && beacon1) {
4994		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
4995		mac->mac_intr_mask |= BWN_INTR_BEACON;
4996		return;
4997	}
4998
4999	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
5000		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
5001		bwn_load_beacon0(mac);
5002		bwn_load_beacon1(mac);
5003		cmd = BWN_READ_4(mac, BWN_MACCMD);
5004		cmd |= BWN_MACCMD_BEACON0_VALID;
5005		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5006	} else {
5007		if (!beacon0) {
5008			bwn_load_beacon0(mac);
5009			cmd = BWN_READ_4(mac, BWN_MACCMD);
5010			cmd |= BWN_MACCMD_BEACON0_VALID;
5011			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5012		} else if (!beacon1) {
5013			bwn_load_beacon1(mac);
5014			cmd = BWN_READ_4(mac, BWN_MACCMD);
5015			cmd |= BWN_MACCMD_BEACON1_VALID;
5016			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5017		}
5018	}
5019}
5020
5021static void
5022bwn_intr_pmq(struct bwn_mac *mac)
5023{
5024	uint32_t tmp;
5025
5026	while (1) {
5027		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
5028		if (!(tmp & 0x00000008))
5029			break;
5030	}
5031	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
5032}
5033
5034static void
5035bwn_intr_noise(struct bwn_mac *mac)
5036{
5037	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5038	uint16_t tmp;
5039	uint8_t noise[4];
5040	uint8_t i, j;
5041	int32_t average;
5042
5043	if (mac->mac_phy.type != BWN_PHYTYPE_G)
5044		return;
5045
5046	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
5047	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
5048	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
5049	    noise[3] == 0x7f)
5050		goto new;
5051
5052	KASSERT(mac->mac_noise.noi_nsamples < 8,
5053	    ("%s:%d: fail", __func__, __LINE__));
5054	i = mac->mac_noise.noi_nsamples;
5055	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
5056	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
5057	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
5058	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
5059	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
5060	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
5061	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
5062	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
5063	mac->mac_noise.noi_nsamples++;
5064	if (mac->mac_noise.noi_nsamples == 8) {
5065		average = 0;
5066		for (i = 0; i < 8; i++) {
5067			for (j = 0; j < 4; j++)
5068				average += mac->mac_noise.noi_samples[i][j];
5069		}
5070		average = (((average / 32) * 125) + 64) / 128;
5071		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
5072		if (tmp >= 8)
5073			average += 2;
5074		else
5075			average -= 25;
5076		average -= (tmp == 8) ? 72 : 48;
5077
5078		mac->mac_stats.link_noise = average;
5079		mac->mac_noise.noi_running = 0;
5080		return;
5081	}
5082new:
5083	bwn_noise_gensample(mac);
5084}
5085
5086static int
5087bwn_pio_rx(struct bwn_pio_rxqueue *prq)
5088{
5089	struct bwn_mac *mac = prq->prq_mac;
5090	struct bwn_softc *sc = mac->mac_sc;
5091	unsigned int i;
5092
5093	BWN_ASSERT_LOCKED(sc);
5094
5095	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
5096		return (0);
5097
5098	for (i = 0; i < 5000; i++) {
5099		if (bwn_pio_rxeof(prq) == 0)
5100			break;
5101	}
5102	if (i >= 5000)
5103		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
5104	return ((i > 0) ? 1 : 0);
5105}
5106
5107static void
5108bwn_dma_rx(struct bwn_dma_ring *dr)
5109{
5110	int slot, curslot;
5111
5112	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5113	curslot = dr->get_curslot(dr);
5114	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
5115	    ("%s:%d: fail", __func__, __LINE__));
5116
5117	slot = dr->dr_curslot;
5118	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
5119		bwn_dma_rxeof(dr, &slot);
5120
5121	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
5122	    BUS_DMASYNC_PREWRITE);
5123
5124	dr->set_curslot(dr, slot);
5125	dr->dr_curslot = slot;
5126}
5127
5128static void
5129bwn_intr_txeof(struct bwn_mac *mac)
5130{
5131	struct bwn_txstatus stat;
5132	uint32_t stat0, stat1;
5133	uint16_t tmp;
5134
5135	BWN_ASSERT_LOCKED(mac->mac_sc);
5136
5137	while (1) {
5138		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
5139		if (!(stat0 & 0x00000001))
5140			break;
5141		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
5142
5143		DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5144		    "%s: stat0=0x%08x, stat1=0x%08x\n",
5145		    __func__,
5146		    stat0,
5147		    stat1);
5148
5149		stat.cookie = (stat0 >> 16);
5150		stat.seq = (stat1 & 0x0000ffff);
5151		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
5152		tmp = (stat0 & 0x0000ffff);
5153		stat.framecnt = ((tmp & 0xf000) >> 12);
5154		stat.rtscnt = ((tmp & 0x0f00) >> 8);
5155		stat.sreason = ((tmp & 0x001c) >> 2);
5156		stat.pm = (tmp & 0x0080) ? 1 : 0;
5157		stat.im = (tmp & 0x0040) ? 1 : 0;
5158		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
5159		stat.ack = (tmp & 0x0002) ? 1 : 0;
5160
5161		DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5162		    "%s: cookie=%d, seq=%d, phystat=0x%02x, framecnt=%d, "
5163		    "rtscnt=%d, sreason=%d, pm=%d, im=%d, ampdu=%d, ack=%d\n",
5164		    __func__,
5165		    stat.cookie,
5166		    stat.seq,
5167		    stat.phy_stat,
5168		    stat.framecnt,
5169		    stat.rtscnt,
5170		    stat.sreason,
5171		    stat.pm,
5172		    stat.im,
5173		    stat.ampdu,
5174		    stat.ack);
5175
5176		bwn_handle_txeof(mac, &stat);
5177	}
5178}
5179
5180static void
5181bwn_hwreset(void *arg, int npending)
5182{
5183	struct bwn_mac *mac = arg;
5184	struct bwn_softc *sc = mac->mac_sc;
5185	int error = 0;
5186	int prev_status;
5187
5188	BWN_LOCK(sc);
5189
5190	prev_status = mac->mac_status;
5191	if (prev_status >= BWN_MAC_STATUS_STARTED)
5192		bwn_core_stop(mac);
5193	if (prev_status >= BWN_MAC_STATUS_INITED)
5194		bwn_core_exit(mac);
5195
5196	if (prev_status >= BWN_MAC_STATUS_INITED) {
5197		error = bwn_core_init(mac);
5198		if (error)
5199			goto out;
5200	}
5201	if (prev_status >= BWN_MAC_STATUS_STARTED)
5202		bwn_core_start(mac);
5203out:
5204	if (error) {
5205		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
5206		sc->sc_curmac = NULL;
5207	}
5208	BWN_UNLOCK(sc);
5209}
5210
5211static void
5212bwn_handle_fwpanic(struct bwn_mac *mac)
5213{
5214	struct bwn_softc *sc = mac->mac_sc;
5215	uint16_t reason;
5216
5217	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
5218	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
5219
5220	if (reason == BWN_FWPANIC_RESTART)
5221		bwn_restart(mac, "ucode panic");
5222}
5223
5224static void
5225bwn_load_beacon0(struct bwn_mac *mac)
5226{
5227
5228	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5229}
5230
5231static void
5232bwn_load_beacon1(struct bwn_mac *mac)
5233{
5234
5235	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5236}
5237
5238static uint32_t
5239bwn_jssi_read(struct bwn_mac *mac)
5240{
5241	uint32_t val = 0;
5242
5243	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
5244	val <<= 16;
5245	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
5246
5247	return (val);
5248}
5249
5250static void
5251bwn_noise_gensample(struct bwn_mac *mac)
5252{
5253	uint32_t jssi = 0x7f7f7f7f;
5254
5255	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
5256	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
5257	BWN_WRITE_4(mac, BWN_MACCMD,
5258	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
5259}
5260
5261static int
5262bwn_dma_freeslot(struct bwn_dma_ring *dr)
5263{
5264	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5265
5266	return (dr->dr_numslots - dr->dr_usedslot);
5267}
5268
5269static int
5270bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
5271{
5272	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5273
5274	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
5275	    ("%s:%d: fail", __func__, __LINE__));
5276	if (slot == dr->dr_numslots - 1)
5277		return (0);
5278	return (slot + 1);
5279}
5280
5281static void
5282bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
5283{
5284	struct bwn_mac *mac = dr->dr_mac;
5285	struct bwn_softc *sc = mac->mac_sc;
5286	struct bwn_dma *dma = &mac->mac_method.dma;
5287	struct bwn_dmadesc_generic *desc;
5288	struct bwn_dmadesc_meta *meta;
5289	struct bwn_rxhdr4 *rxhdr;
5290	struct mbuf *m;
5291	uint32_t macstat;
5292	int32_t tmp;
5293	int cnt = 0;
5294	uint16_t len;
5295
5296	dr->getdesc(dr, *slot, &desc, &meta);
5297
5298	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
5299	m = meta->mt_m;
5300
5301	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
5302		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5303		return;
5304	}
5305
5306	rxhdr = mtod(m, struct bwn_rxhdr4 *);
5307	len = le16toh(rxhdr->frame_len);
5308	if (len <= 0) {
5309		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5310		return;
5311	}
5312	if (bwn_dma_check_redzone(dr, m)) {
5313		device_printf(sc->sc_dev, "redzone error.\n");
5314		bwn_dma_set_redzone(dr, m);
5315		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5316		    BUS_DMASYNC_PREWRITE);
5317		return;
5318	}
5319	if (len > dr->dr_rx_bufsize) {
5320		tmp = len;
5321		while (1) {
5322			dr->getdesc(dr, *slot, &desc, &meta);
5323			bwn_dma_set_redzone(dr, meta->mt_m);
5324			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5325			    BUS_DMASYNC_PREWRITE);
5326			*slot = bwn_dma_nextslot(dr, *slot);
5327			cnt++;
5328			tmp -= dr->dr_rx_bufsize;
5329			if (tmp <= 0)
5330				break;
5331		}
5332		device_printf(sc->sc_dev, "too small buffer "
5333		       "(len %u buffer %u dropped %d)\n",
5334		       len, dr->dr_rx_bufsize, cnt);
5335		return;
5336	}
5337	macstat = le32toh(rxhdr->mac_status);
5338	if (macstat & BWN_RX_MAC_FCSERR) {
5339		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5340			device_printf(sc->sc_dev, "RX drop\n");
5341			return;
5342		}
5343	}
5344
5345	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
5346	m_adj(m, dr->dr_frameoffset);
5347
5348	bwn_rxeof(dr->dr_mac, m, rxhdr);
5349}
5350
5351static void
5352bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
5353{
5354	struct bwn_softc *sc = mac->mac_sc;
5355	struct bwn_stats *stats = &mac->mac_stats;
5356
5357	BWN_ASSERT_LOCKED(mac->mac_sc);
5358
5359	if (status->im)
5360		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
5361	if (status->ampdu)
5362		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
5363	if (status->rtscnt) {
5364		if (status->rtscnt == 0xf)
5365			stats->rtsfail++;
5366		else
5367			stats->rts++;
5368	}
5369
5370	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
5371		bwn_dma_handle_txeof(mac, status);
5372	} else {
5373		bwn_pio_handle_txeof(mac, status);
5374	}
5375
5376	bwn_phy_txpower_check(mac, 0);
5377}
5378
5379static uint8_t
5380bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
5381{
5382	struct bwn_mac *mac = prq->prq_mac;
5383	struct bwn_softc *sc = mac->mac_sc;
5384	struct bwn_rxhdr4 rxhdr;
5385	struct mbuf *m;
5386	uint32_t ctl32, macstat, v32;
5387	unsigned int i, padding;
5388	uint16_t ctl16, len, totlen, v16;
5389	unsigned char *mp;
5390	char *data;
5391
5392	memset(&rxhdr, 0, sizeof(rxhdr));
5393
5394	if (prq->prq_rev >= 8) {
5395		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5396		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
5397			return (0);
5398		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5399		    BWN_PIO8_RXCTL_FRAMEREADY);
5400		for (i = 0; i < 10; i++) {
5401			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5402			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
5403				goto ready;
5404			DELAY(10);
5405		}
5406	} else {
5407		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5408		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
5409			return (0);
5410		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
5411		    BWN_PIO_RXCTL_FRAMEREADY);
5412		for (i = 0; i < 10; i++) {
5413			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5414			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
5415				goto ready;
5416			DELAY(10);
5417		}
5418	}
5419	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
5420	return (1);
5421ready:
5422	if (prq->prq_rev >= 8)
5423		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5424		    prq->prq_base + BWN_PIO8_RXDATA);
5425	else
5426		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5427		    prq->prq_base + BWN_PIO_RXDATA);
5428	len = le16toh(rxhdr.frame_len);
5429	if (len > 0x700) {
5430		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
5431		goto error;
5432	}
5433	if (len == 0) {
5434		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
5435		goto error;
5436	}
5437
5438	macstat = le32toh(rxhdr.mac_status);
5439	if (macstat & BWN_RX_MAC_FCSERR) {
5440		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5441			device_printf(sc->sc_dev, "%s: FCS error", __func__);
5442			goto error;
5443		}
5444	}
5445
5446	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5447	totlen = len + padding;
5448	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
5449	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5450	if (m == NULL) {
5451		device_printf(sc->sc_dev, "%s: out of memory", __func__);
5452		goto error;
5453	}
5454	mp = mtod(m, unsigned char *);
5455	if (prq->prq_rev >= 8) {
5456		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
5457		    prq->prq_base + BWN_PIO8_RXDATA);
5458		if (totlen & 3) {
5459			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
5460			data = &(mp[totlen - 1]);
5461			switch (totlen & 3) {
5462			case 3:
5463				*data = (v32 >> 16);
5464				data--;
5465			case 2:
5466				*data = (v32 >> 8);
5467				data--;
5468			case 1:
5469				*data = v32;
5470			}
5471		}
5472	} else {
5473		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
5474		    prq->prq_base + BWN_PIO_RXDATA);
5475		if (totlen & 1) {
5476			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
5477			mp[totlen - 1] = v16;
5478		}
5479	}
5480
5481	m->m_len = m->m_pkthdr.len = totlen;
5482
5483	bwn_rxeof(prq->prq_mac, m, &rxhdr);
5484
5485	return (1);
5486error:
5487	if (prq->prq_rev >= 8)
5488		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5489		    BWN_PIO8_RXCTL_DATAREADY);
5490	else
5491		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
5492	return (1);
5493}
5494
5495static int
5496bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
5497    struct bwn_dmadesc_meta *meta, int init)
5498{
5499	struct bwn_mac *mac = dr->dr_mac;
5500	struct bwn_dma *dma = &mac->mac_method.dma;
5501	struct bwn_rxhdr4 *hdr;
5502	bus_dmamap_t map;
5503	bus_addr_t paddr;
5504	struct mbuf *m;
5505	int error;
5506
5507	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5508	if (m == NULL) {
5509		error = ENOBUFS;
5510
5511		/*
5512		 * If the NIC is up and running, we need to:
5513		 * - Clear RX buffer's header.
5514		 * - Restore RX descriptor settings.
5515		 */
5516		if (init)
5517			return (error);
5518		else
5519			goto back;
5520	}
5521	m->m_len = m->m_pkthdr.len = MCLBYTES;
5522
5523	bwn_dma_set_redzone(dr, m);
5524
5525	/*
5526	 * Try to load RX buf into temporary DMA map
5527	 */
5528	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
5529	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
5530	if (error) {
5531		m_freem(m);
5532
5533		/*
5534		 * See the comment above
5535		 */
5536		if (init)
5537			return (error);
5538		else
5539			goto back;
5540	}
5541
5542	if (!init)
5543		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
5544	meta->mt_m = m;
5545	meta->mt_paddr = paddr;
5546
5547	/*
5548	 * Swap RX buf's DMA map with the loaded temporary one
5549	 */
5550	map = meta->mt_dmap;
5551	meta->mt_dmap = dr->dr_spare_dmap;
5552	dr->dr_spare_dmap = map;
5553
5554back:
5555	/*
5556	 * Clear RX buf header
5557	 */
5558	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
5559	bzero(hdr, sizeof(*hdr));
5560	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5561	    BUS_DMASYNC_PREWRITE);
5562
5563	/*
5564	 * Setup RX buf descriptor
5565	 */
5566	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
5567	    sizeof(*hdr), 0, 0, 0);
5568	return (error);
5569}
5570
5571static void
5572bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
5573		 bus_size_t mapsz __unused, int error)
5574{
5575
5576	if (!error) {
5577		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
5578		*((bus_addr_t *)arg) = seg->ds_addr;
5579	}
5580}
5581
5582static int
5583bwn_hwrate2ieeerate(int rate)
5584{
5585
5586	switch (rate) {
5587	case BWN_CCK_RATE_1MB:
5588		return (2);
5589	case BWN_CCK_RATE_2MB:
5590		return (4);
5591	case BWN_CCK_RATE_5MB:
5592		return (11);
5593	case BWN_CCK_RATE_11MB:
5594		return (22);
5595	case BWN_OFDM_RATE_6MB:
5596		return (12);
5597	case BWN_OFDM_RATE_9MB:
5598		return (18);
5599	case BWN_OFDM_RATE_12MB:
5600		return (24);
5601	case BWN_OFDM_RATE_18MB:
5602		return (36);
5603	case BWN_OFDM_RATE_24MB:
5604		return (48);
5605	case BWN_OFDM_RATE_36MB:
5606		return (72);
5607	case BWN_OFDM_RATE_48MB:
5608		return (96);
5609	case BWN_OFDM_RATE_54MB:
5610		return (108);
5611	default:
5612		printf("Ooops\n");
5613		return (0);
5614	}
5615}
5616
5617/*
5618 * Post process the RX provided RSSI.
5619 *
5620 * Valid for A, B, G, LP PHYs.
5621 */
5622static int8_t
5623bwn_rx_rssi_calc(struct bwn_mac *mac, uint8_t in_rssi,
5624    int ofdm, int adjust_2053, int adjust_2050)
5625{
5626	struct bwn_phy *phy = &mac->mac_phy;
5627	struct bwn_phy_g *gphy = &phy->phy_g;
5628	int tmp;
5629
5630	switch (phy->rf_ver) {
5631	case 0x2050:
5632		if (ofdm) {
5633			tmp = in_rssi;
5634			if (tmp > 127)
5635				tmp -= 256;
5636			tmp = tmp * 73 / 64;
5637			if (adjust_2050)
5638				tmp += 25;
5639			else
5640				tmp -= 3;
5641		} else {
5642			if (siba_sprom_get_bf_lo(mac->mac_sc->sc_dev)
5643			    & BWN_BFL_RSSI) {
5644				if (in_rssi > 63)
5645					in_rssi = 63;
5646				tmp = gphy->pg_nrssi_lt[in_rssi];
5647				tmp = (31 - tmp) * -131 / 128 - 57;
5648			} else {
5649				tmp = in_rssi;
5650				tmp = (31 - tmp) * -149 / 128 - 68;
5651			}
5652			if (phy->type == BWN_PHYTYPE_G && adjust_2050)
5653				tmp += 25;
5654		}
5655		break;
5656	case 0x2060:
5657		if (in_rssi > 127)
5658			tmp = in_rssi - 256;
5659		else
5660			tmp = in_rssi;
5661		break;
5662	default:
5663		tmp = in_rssi;
5664		tmp = (tmp - 11) * 103 / 64;
5665		if (adjust_2053)
5666			tmp -= 109;
5667		else
5668			tmp -= 83;
5669	}
5670
5671	return (tmp);
5672}
5673
5674static void
5675bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
5676{
5677	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
5678	struct bwn_plcp6 *plcp;
5679	struct bwn_softc *sc = mac->mac_sc;
5680	struct ieee80211_frame_min *wh;
5681	struct ieee80211_node *ni;
5682	struct ieee80211com *ic = &sc->sc_ic;
5683	uint32_t macstat;
5684	int padding, rate, rssi = 0, noise = 0, type;
5685	uint16_t phytype, phystat0, phystat3, chanstat;
5686	unsigned char *mp = mtod(m, unsigned char *);
5687	static int rx_mac_dec_rpt = 0;
5688
5689	BWN_ASSERT_LOCKED(sc);
5690
5691	phystat0 = le16toh(rxhdr->phy_status0);
5692	phystat3 = le16toh(rxhdr->phy_status3);
5693
5694	/* XXX Note: mactime, macstat, chanstat need fixing for fw 598 */
5695	macstat = le32toh(rxhdr->mac_status);
5696	chanstat = le16toh(rxhdr->channel);
5697
5698	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
5699
5700	if (macstat & BWN_RX_MAC_FCSERR)
5701		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
5702	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
5703		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
5704	if (macstat & BWN_RX_MAC_DECERR)
5705		goto drop;
5706
5707	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5708	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
5709		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5710		    m->m_pkthdr.len);
5711		goto drop;
5712	}
5713	plcp = (struct bwn_plcp6 *)(mp + padding);
5714	m_adj(m, sizeof(struct bwn_plcp6) + padding);
5715	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
5716		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5717		    m->m_pkthdr.len);
5718		goto drop;
5719	}
5720	wh = mtod(m, struct ieee80211_frame_min *);
5721
5722	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
5723		device_printf(sc->sc_dev,
5724		    "RX decryption attempted (old %d keyidx %#x)\n",
5725		    BWN_ISOLDFMT(mac),
5726		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
5727
5728	if (phystat0 & BWN_RX_PHYST0_OFDM)
5729		rate = bwn_plcp_get_ofdmrate(mac, plcp,
5730		    phytype == BWN_PHYTYPE_A);
5731	else
5732		rate = bwn_plcp_get_cckrate(mac, plcp);
5733	if (rate == -1) {
5734		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
5735			goto drop;
5736	}
5737	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
5738
5739	/* rssi/noise */
5740	switch (phytype) {
5741	case BWN_PHYTYPE_A:
5742	case BWN_PHYTYPE_B:
5743	case BWN_PHYTYPE_G:
5744	case BWN_PHYTYPE_LP:
5745		rssi = bwn_rx_rssi_calc(mac, rxhdr->phy.abg.rssi,
5746		    !! (phystat0 & BWN_RX_PHYST0_OFDM),
5747		    !! (phystat0 & BWN_RX_PHYST0_GAINCTL),
5748		    !! (phystat3 & BWN_RX_PHYST3_TRSTATE));
5749		break;
5750	case BWN_PHYTYPE_N:
5751		/* Broadcom has code for min/avg, but always used max */
5752		if (rxhdr->phy.n.power0 == 16 || rxhdr->phy.n.power0 == 32)
5753			rssi = max(rxhdr->phy.n.power1, rxhdr->ps2.n.power2);
5754		else
5755			rssi = max(rxhdr->phy.n.power0, rxhdr->phy.n.power1);
5756		break;
5757	default:
5758		/* XXX TODO: implement rssi for other PHYs */
5759		break;
5760	}
5761
5762	noise = mac->mac_stats.link_noise;
5763
5764	/* RX radio tap */
5765	if (ieee80211_radiotap_active(ic))
5766		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
5767	m_adj(m, -IEEE80211_CRC_LEN);
5768
5769	BWN_UNLOCK(sc);
5770
5771	ni = ieee80211_find_rxnode(ic, wh);
5772	if (ni != NULL) {
5773		type = ieee80211_input(ni, m, rssi, noise);
5774		ieee80211_free_node(ni);
5775	} else
5776		type = ieee80211_input_all(ic, m, rssi, noise);
5777
5778	BWN_LOCK(sc);
5779	return;
5780drop:
5781	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
5782}
5783
5784static void
5785bwn_dma_handle_txeof(struct bwn_mac *mac,
5786    const struct bwn_txstatus *status)
5787{
5788	struct bwn_dma *dma = &mac->mac_method.dma;
5789	struct bwn_dma_ring *dr;
5790	struct bwn_dmadesc_generic *desc;
5791	struct bwn_dmadesc_meta *meta;
5792	struct bwn_softc *sc = mac->mac_sc;
5793	int slot;
5794	int retrycnt = 0;
5795
5796	BWN_ASSERT_LOCKED(sc);
5797
5798	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
5799	if (dr == NULL) {
5800		device_printf(sc->sc_dev, "failed to parse cookie\n");
5801		return;
5802	}
5803	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5804
5805	while (1) {
5806		KASSERT(slot >= 0 && slot < dr->dr_numslots,
5807		    ("%s:%d: fail", __func__, __LINE__));
5808		dr->getdesc(dr, slot, &desc, &meta);
5809
5810		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
5811			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
5812		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
5813			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
5814
5815		if (meta->mt_islast) {
5816			KASSERT(meta->mt_m != NULL,
5817			    ("%s:%d: fail", __func__, __LINE__));
5818
5819			/*
5820			 * If we don't get an ACK, then we should log the
5821			 * full framecnt.  That may be 0 if it's a PHY
5822			 * failure, so ensure that gets logged as some
5823			 * retry attempt.
5824			 */
5825			if (status->ack) {
5826				retrycnt = status->framecnt - 1;
5827			} else {
5828				retrycnt = status->framecnt;
5829				if (retrycnt == 0)
5830					retrycnt = 1;
5831			}
5832			ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni,
5833			    status->ack ?
5834			      IEEE80211_RATECTL_TX_SUCCESS :
5835			      IEEE80211_RATECTL_TX_FAILURE,
5836			    &retrycnt, 0);
5837			ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
5838			meta->mt_ni = NULL;
5839			meta->mt_m = NULL;
5840		} else
5841			KASSERT(meta->mt_m == NULL,
5842			    ("%s:%d: fail", __func__, __LINE__));
5843
5844		dr->dr_usedslot--;
5845		if (meta->mt_islast)
5846			break;
5847		slot = bwn_dma_nextslot(dr, slot);
5848	}
5849	sc->sc_watchdog_timer = 0;
5850	if (dr->dr_stop) {
5851		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
5852		    ("%s:%d: fail", __func__, __LINE__));
5853		dr->dr_stop = 0;
5854	}
5855}
5856
5857static void
5858bwn_pio_handle_txeof(struct bwn_mac *mac,
5859    const struct bwn_txstatus *status)
5860{
5861	struct bwn_pio_txqueue *tq;
5862	struct bwn_pio_txpkt *tp = NULL;
5863	struct bwn_softc *sc = mac->mac_sc;
5864	int retrycnt = 0;
5865
5866	BWN_ASSERT_LOCKED(sc);
5867
5868	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
5869	if (tq == NULL)
5870		return;
5871
5872	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
5873	tq->tq_free++;
5874
5875	if (tp->tp_ni != NULL) {
5876		/*
5877		 * Do any tx complete callback.  Note this must
5878		 * be done before releasing the node reference.
5879		 */
5880
5881		/*
5882		 * If we don't get an ACK, then we should log the
5883		 * full framecnt.  That may be 0 if it's a PHY
5884		 * failure, so ensure that gets logged as some
5885		 * retry attempt.
5886		 */
5887		if (status->ack) {
5888			retrycnt = status->framecnt - 1;
5889		} else {
5890			retrycnt = status->framecnt;
5891			if (retrycnt == 0)
5892				retrycnt = 1;
5893		}
5894		ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni,
5895		    status->ack ?
5896		      IEEE80211_RATECTL_TX_SUCCESS :
5897		      IEEE80211_RATECTL_TX_FAILURE,
5898		    &retrycnt, 0);
5899
5900		if (tp->tp_m->m_flags & M_TXCB)
5901			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
5902		ieee80211_free_node(tp->tp_ni);
5903		tp->tp_ni = NULL;
5904	}
5905	m_freem(tp->tp_m);
5906	tp->tp_m = NULL;
5907	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
5908
5909	sc->sc_watchdog_timer = 0;
5910}
5911
5912static void
5913bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
5914{
5915	struct bwn_softc *sc = mac->mac_sc;
5916	struct bwn_phy *phy = &mac->mac_phy;
5917	struct ieee80211com *ic = &sc->sc_ic;
5918	unsigned long now;
5919	bwn_txpwr_result_t result;
5920
5921	BWN_GETTIME(now);
5922
5923	if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime))
5924		return;
5925	phy->nexttime = now + 2 * 1000;
5926
5927	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
5928	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
5929		return;
5930
5931	if (phy->recalc_txpwr != NULL) {
5932		result = phy->recalc_txpwr(mac,
5933		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
5934		if (result == BWN_TXPWR_RES_DONE)
5935			return;
5936		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
5937		    ("%s: fail", __func__));
5938		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
5939
5940		ieee80211_runtask(ic, &mac->mac_txpower);
5941	}
5942}
5943
5944static uint16_t
5945bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
5946{
5947
5948	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
5949}
5950
5951static uint32_t
5952bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
5953{
5954
5955	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
5956}
5957
5958static void
5959bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
5960{
5961
5962	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
5963}
5964
5965static void
5966bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
5967{
5968
5969	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
5970}
5971
5972static int
5973bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
5974{
5975
5976	switch (rate) {
5977	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
5978	case 12:
5979		return (BWN_OFDM_RATE_6MB);
5980	case 18:
5981		return (BWN_OFDM_RATE_9MB);
5982	case 24:
5983		return (BWN_OFDM_RATE_12MB);
5984	case 36:
5985		return (BWN_OFDM_RATE_18MB);
5986	case 48:
5987		return (BWN_OFDM_RATE_24MB);
5988	case 72:
5989		return (BWN_OFDM_RATE_36MB);
5990	case 96:
5991		return (BWN_OFDM_RATE_48MB);
5992	case 108:
5993		return (BWN_OFDM_RATE_54MB);
5994	/* CCK rates (NB: not IEEE std, device-specific) */
5995	case 2:
5996		return (BWN_CCK_RATE_1MB);
5997	case 4:
5998		return (BWN_CCK_RATE_2MB);
5999	case 11:
6000		return (BWN_CCK_RATE_5MB);
6001	case 22:
6002		return (BWN_CCK_RATE_11MB);
6003	}
6004
6005	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
6006	return (BWN_CCK_RATE_1MB);
6007}
6008
6009static uint16_t
6010bwn_set_txhdr_phyctl1(struct bwn_mac *mac, uint8_t bitrate)
6011{
6012	struct bwn_phy *phy = &mac->mac_phy;
6013	uint16_t control = 0;
6014	uint16_t bw;
6015
6016	/* XXX TODO: this is for LP phy, what about N-PHY, etc? */
6017	bw = BWN_TXH_PHY1_BW_20;
6018
6019	if (BWN_ISCCKRATE(bitrate) && phy->type != BWN_PHYTYPE_LP) {
6020		control = bw;
6021	} else {
6022		control = bw;
6023		/* Figure out coding rate and modulation */
6024		/* XXX TODO: table-ize, for MCS transmit */
6025		/* Note: this is BWN_*_RATE values */
6026		switch (bitrate) {
6027		case BWN_CCK_RATE_1MB:
6028			control |= 0;
6029			break;
6030		case BWN_CCK_RATE_2MB:
6031			control |= 1;
6032			break;
6033		case BWN_CCK_RATE_5MB:
6034			control |= 2;
6035			break;
6036		case BWN_CCK_RATE_11MB:
6037			control |= 3;
6038			break;
6039		case BWN_OFDM_RATE_6MB:
6040			control |= BWN_TXH_PHY1_CRATE_1_2;
6041			control |= BWN_TXH_PHY1_MODUL_BPSK;
6042			break;
6043		case BWN_OFDM_RATE_9MB:
6044			control |= BWN_TXH_PHY1_CRATE_3_4;
6045			control |= BWN_TXH_PHY1_MODUL_BPSK;
6046			break;
6047		case BWN_OFDM_RATE_12MB:
6048			control |= BWN_TXH_PHY1_CRATE_1_2;
6049			control |= BWN_TXH_PHY1_MODUL_QPSK;
6050			break;
6051		case BWN_OFDM_RATE_18MB:
6052			control |= BWN_TXH_PHY1_CRATE_3_4;
6053			control |= BWN_TXH_PHY1_MODUL_QPSK;
6054			break;
6055		case BWN_OFDM_RATE_24MB:
6056			control |= BWN_TXH_PHY1_CRATE_1_2;
6057			control |= BWN_TXH_PHY1_MODUL_QAM16;
6058			break;
6059		case BWN_OFDM_RATE_36MB:
6060			control |= BWN_TXH_PHY1_CRATE_3_4;
6061			control |= BWN_TXH_PHY1_MODUL_QAM16;
6062			break;
6063		case BWN_OFDM_RATE_48MB:
6064			control |= BWN_TXH_PHY1_CRATE_1_2;
6065			control |= BWN_TXH_PHY1_MODUL_QAM64;
6066			break;
6067		case BWN_OFDM_RATE_54MB:
6068			control |= BWN_TXH_PHY1_CRATE_3_4;
6069			control |= BWN_TXH_PHY1_MODUL_QAM64;
6070			break;
6071		default:
6072			break;
6073		}
6074		control |= BWN_TXH_PHY1_MODE_SISO;
6075	}
6076
6077	return control;
6078}
6079
6080static int
6081bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
6082    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
6083{
6084	const struct bwn_phy *phy = &mac->mac_phy;
6085	struct bwn_softc *sc = mac->mac_sc;
6086	struct ieee80211_frame *wh;
6087	struct ieee80211_frame *protwh;
6088	struct ieee80211_frame_cts *cts;
6089	struct ieee80211_frame_rts *rts;
6090	const struct ieee80211_txparam *tp;
6091	struct ieee80211vap *vap = ni->ni_vap;
6092	struct ieee80211com *ic = &sc->sc_ic;
6093	struct mbuf *mprot;
6094	unsigned int len;
6095	uint32_t macctl = 0;
6096	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
6097	uint16_t phyctl = 0;
6098	uint8_t rate, rate_fb;
6099	int fill_phy_ctl1 = 0;
6100
6101	wh = mtod(m, struct ieee80211_frame *);
6102	memset(txhdr, 0, sizeof(*txhdr));
6103
6104	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
6105	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
6106	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
6107
6108	if ((phy->type == BWN_PHYTYPE_N) || (phy->type == BWN_PHYTYPE_LP)
6109	    || (phy->type == BWN_PHYTYPE_HT))
6110		fill_phy_ctl1 = 1;
6111
6112	/*
6113	 * Find TX rate
6114	 */
6115	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
6116	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
6117		rate = rate_fb = tp->mgmtrate;
6118	else if (ismcast)
6119		rate = rate_fb = tp->mcastrate;
6120	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
6121		rate = rate_fb = tp->ucastrate;
6122	else {
6123		/* XXX TODO: don't fall back to CCK rates for OFDM */
6124		rix = ieee80211_ratectl_rate(ni, NULL, 0);
6125		rate = ni->ni_txrate;
6126
6127		if (rix > 0)
6128			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
6129			    IEEE80211_RATE_VAL;
6130		else
6131			rate_fb = rate;
6132	}
6133
6134	sc->sc_tx_rate = rate;
6135
6136	/* Note: this maps the select ieee80211 rate to hardware rate */
6137	rate = bwn_ieeerate2hwrate(sc, rate);
6138	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
6139
6140	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
6141	    bwn_plcp_getcck(rate);
6142	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
6143	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
6144
6145	/* XXX rate/rate_fb is the hardware rate */
6146	if ((rate_fb == rate) ||
6147	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
6148	    (*(u_int16_t *)wh->i_dur == htole16(0)))
6149		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
6150	else
6151		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
6152		    m->m_pkthdr.len, rate, isshort);
6153
6154	/* XXX TX encryption */
6155	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
6156	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
6157	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
6158	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6159	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
6160	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
6161
6162	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
6163	    BWN_TX_EFT_FB_CCK;
6164	txhdr->chan = phy->chan;
6165	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
6166	    BWN_TX_PHY_ENC_CCK;
6167	/* XXX preamble? obey net80211 */
6168	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6169	     rate == BWN_CCK_RATE_11MB))
6170		phyctl |= BWN_TX_PHY_SHORTPRMBL;
6171
6172	if (! phy->gmode)
6173		macctl |= BWN_TX_MAC_5GHZ;
6174
6175	/* XXX TX antenna selection */
6176
6177	switch (bwn_antenna_sanitize(mac, 0)) {
6178	case 0:
6179		phyctl |= BWN_TX_PHY_ANT01AUTO;
6180		break;
6181	case 1:
6182		phyctl |= BWN_TX_PHY_ANT0;
6183		break;
6184	case 2:
6185		phyctl |= BWN_TX_PHY_ANT1;
6186		break;
6187	case 3:
6188		phyctl |= BWN_TX_PHY_ANT2;
6189		break;
6190	case 4:
6191		phyctl |= BWN_TX_PHY_ANT3;
6192		break;
6193	default:
6194		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6195	}
6196
6197	if (!ismcast)
6198		macctl |= BWN_TX_MAC_ACK;
6199
6200	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
6201	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
6202	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
6203		macctl |= BWN_TX_MAC_LONGFRAME;
6204
6205	if (ic->ic_flags & IEEE80211_F_USEPROT) {
6206		/* XXX RTS rate is always 1MB??? */
6207		/* XXX TODO: don't fall back to CCK rates for OFDM */
6208		rts_rate = BWN_CCK_RATE_1MB;
6209		rts_rate_fb = bwn_get_fbrate(rts_rate);
6210
6211		/* XXX 'rate' here is hardware rate now, not the net80211 rate */
6212		protdur = ieee80211_compute_duration(ic->ic_rt,
6213		    m->m_pkthdr.len, rate, isshort) +
6214		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
6215
6216		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
6217			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
6218			    (txhdr->body.old.rts_frame) :
6219			    (txhdr->body.new.rts_frame));
6220			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
6221			    protdur);
6222			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
6223			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
6224			    mprot->m_pkthdr.len);
6225			m_freem(mprot);
6226			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
6227			len = sizeof(struct ieee80211_frame_cts);
6228		} else {
6229			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
6230			    (txhdr->body.old.rts_frame) :
6231			    (txhdr->body.new.rts_frame));
6232			/* XXX rate/rate_fb is the hardware rate */
6233			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
6234			    isshort);
6235			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
6236			    wh->i_addr2, protdur);
6237			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
6238			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
6239			    mprot->m_pkthdr.len);
6240			m_freem(mprot);
6241			macctl |= BWN_TX_MAC_SEND_RTSCTS;
6242			len = sizeof(struct ieee80211_frame_rts);
6243		}
6244		len += IEEE80211_CRC_LEN;
6245		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
6246		    &txhdr->body.old.rts_plcp :
6247		    &txhdr->body.new.rts_plcp), len, rts_rate);
6248		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
6249		    rts_rate_fb);
6250
6251		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
6252		    (&txhdr->body.old.rts_frame) :
6253		    (&txhdr->body.new.rts_frame));
6254		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
6255
6256		if (BWN_ISOFDMRATE(rts_rate)) {
6257			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
6258			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
6259		} else {
6260			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
6261			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
6262		}
6263		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
6264		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
6265
6266		if (fill_phy_ctl1) {
6267			txhdr->phyctl_1rts = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate));
6268			txhdr->phyctl_1rtsfb = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate_fb));
6269		}
6270	}
6271
6272	if (fill_phy_ctl1) {
6273		txhdr->phyctl_1 = htole16(bwn_set_txhdr_phyctl1(mac, rate));
6274		txhdr->phyctl_1fb = htole16(bwn_set_txhdr_phyctl1(mac, rate_fb));
6275	}
6276
6277	if (BWN_ISOLDFMT(mac))
6278		txhdr->body.old.cookie = htole16(cookie);
6279	else
6280		txhdr->body.new.cookie = htole16(cookie);
6281
6282	txhdr->macctl = htole32(macctl);
6283	txhdr->phyctl = htole16(phyctl);
6284
6285	/*
6286	 * TX radio tap
6287	 */
6288	if (ieee80211_radiotap_active_vap(vap)) {
6289		sc->sc_tx_th.wt_flags = 0;
6290		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6291			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
6292		if (isshort &&
6293		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6294		     rate == BWN_CCK_RATE_11MB))
6295			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6296		sc->sc_tx_th.wt_rate = rate;
6297
6298		ieee80211_radiotap_tx(vap, m);
6299	}
6300
6301	return (0);
6302}
6303
6304static void
6305bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
6306    const uint8_t rate)
6307{
6308	uint32_t d, plen;
6309	uint8_t *raw = plcp->o.raw;
6310
6311	if (BWN_ISOFDMRATE(rate)) {
6312		d = bwn_plcp_getofdm(rate);
6313		KASSERT(!(octets & 0xf000),
6314		    ("%s:%d: fail", __func__, __LINE__));
6315		d |= (octets << 5);
6316		plcp->o.data = htole32(d);
6317	} else {
6318		plen = octets * 16 / rate;
6319		if ((octets * 16 % rate) > 0) {
6320			plen++;
6321			if ((rate == BWN_CCK_RATE_11MB)
6322			    && ((octets * 8 % 11) < 4)) {
6323				raw[1] = 0x84;
6324			} else
6325				raw[1] = 0x04;
6326		} else
6327			raw[1] = 0x04;
6328		plcp->o.data |= htole32(plen << 16);
6329		raw[0] = bwn_plcp_getcck(rate);
6330	}
6331}
6332
6333static uint8_t
6334bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
6335{
6336	struct bwn_softc *sc = mac->mac_sc;
6337	uint8_t mask;
6338
6339	if (n == 0)
6340		return (0);
6341	if (mac->mac_phy.gmode)
6342		mask = siba_sprom_get_ant_bg(sc->sc_dev);
6343	else
6344		mask = siba_sprom_get_ant_a(sc->sc_dev);
6345	if (!(mask & (1 << (n - 1))))
6346		return (0);
6347	return (n);
6348}
6349
6350/*
6351 * Return a fallback rate for the given rate.
6352 *
6353 * Note: Don't fall back from OFDM to CCK.
6354 */
6355static uint8_t
6356bwn_get_fbrate(uint8_t bitrate)
6357{
6358	switch (bitrate) {
6359	/* CCK */
6360	case BWN_CCK_RATE_1MB:
6361		return (BWN_CCK_RATE_1MB);
6362	case BWN_CCK_RATE_2MB:
6363		return (BWN_CCK_RATE_1MB);
6364	case BWN_CCK_RATE_5MB:
6365		return (BWN_CCK_RATE_2MB);
6366	case BWN_CCK_RATE_11MB:
6367		return (BWN_CCK_RATE_5MB);
6368
6369	/* OFDM */
6370	case BWN_OFDM_RATE_6MB:
6371		return (BWN_OFDM_RATE_6MB);
6372	case BWN_OFDM_RATE_9MB:
6373		return (BWN_OFDM_RATE_6MB);
6374	case BWN_OFDM_RATE_12MB:
6375		return (BWN_OFDM_RATE_9MB);
6376	case BWN_OFDM_RATE_18MB:
6377		return (BWN_OFDM_RATE_12MB);
6378	case BWN_OFDM_RATE_24MB:
6379		return (BWN_OFDM_RATE_18MB);
6380	case BWN_OFDM_RATE_36MB:
6381		return (BWN_OFDM_RATE_24MB);
6382	case BWN_OFDM_RATE_48MB:
6383		return (BWN_OFDM_RATE_36MB);
6384	case BWN_OFDM_RATE_54MB:
6385		return (BWN_OFDM_RATE_48MB);
6386	}
6387	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6388	return (0);
6389}
6390
6391static uint32_t
6392bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6393    uint32_t ctl, const void *_data, int len)
6394{
6395	struct bwn_softc *sc = mac->mac_sc;
6396	uint32_t value = 0;
6397	const uint8_t *data = _data;
6398
6399	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
6400	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
6401	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6402
6403	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
6404	    tq->tq_base + BWN_PIO8_TXDATA);
6405	if (len & 3) {
6406		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
6407		    BWN_PIO8_TXCTL_24_31);
6408		data = &(data[len - 1]);
6409		switch (len & 3) {
6410		case 3:
6411			ctl |= BWN_PIO8_TXCTL_16_23;
6412			value |= (uint32_t)(*data) << 16;
6413			data--;
6414		case 2:
6415			ctl |= BWN_PIO8_TXCTL_8_15;
6416			value |= (uint32_t)(*data) << 8;
6417			data--;
6418		case 1:
6419			value |= (uint32_t)(*data);
6420		}
6421		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6422		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
6423	}
6424
6425	return (ctl);
6426}
6427
6428static void
6429bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6430    uint16_t offset, uint32_t value)
6431{
6432
6433	BWN_WRITE_4(mac, tq->tq_base + offset, value);
6434}
6435
6436static uint16_t
6437bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6438    uint16_t ctl, const void *_data, int len)
6439{
6440	struct bwn_softc *sc = mac->mac_sc;
6441	const uint8_t *data = _data;
6442
6443	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6444	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6445
6446	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
6447	    tq->tq_base + BWN_PIO_TXDATA);
6448	if (len & 1) {
6449		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6450		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6451		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
6452	}
6453
6454	return (ctl);
6455}
6456
6457static uint16_t
6458bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6459    uint16_t ctl, struct mbuf *m0)
6460{
6461	int i, j = 0;
6462	uint16_t data = 0;
6463	const uint8_t *buf;
6464	struct mbuf *m = m0;
6465
6466	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6467	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6468
6469	for (; m != NULL; m = m->m_next) {
6470		buf = mtod(m, const uint8_t *);
6471		for (i = 0; i < m->m_len; i++) {
6472			if (!((j++) % 2))
6473				data |= buf[i];
6474			else {
6475				data |= (buf[i] << 8);
6476				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6477				data = 0;
6478			}
6479		}
6480	}
6481	if (m0->m_pkthdr.len % 2) {
6482		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6483		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6484		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6485	}
6486
6487	return (ctl);
6488}
6489
6490static void
6491bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
6492{
6493
6494	/* XXX should exit if 5GHz band .. */
6495	if (mac->mac_phy.type != BWN_PHYTYPE_G)
6496		return;
6497
6498	BWN_WRITE_2(mac, 0x684, 510 + time);
6499	/* Disabled in Linux b43, can adversely effect performance */
6500#if 0
6501	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
6502#endif
6503}
6504
6505static struct bwn_dma_ring *
6506bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
6507{
6508
6509	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
6510		return (mac->mac_method.dma.wme[WME_AC_BE]);
6511
6512	switch (prio) {
6513	case 3:
6514		return (mac->mac_method.dma.wme[WME_AC_VO]);
6515	case 2:
6516		return (mac->mac_method.dma.wme[WME_AC_VI]);
6517	case 0:
6518		return (mac->mac_method.dma.wme[WME_AC_BE]);
6519	case 1:
6520		return (mac->mac_method.dma.wme[WME_AC_BK]);
6521	}
6522	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6523	return (NULL);
6524}
6525
6526static int
6527bwn_dma_getslot(struct bwn_dma_ring *dr)
6528{
6529	int slot;
6530
6531	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
6532
6533	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
6534	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
6535	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
6536
6537	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
6538	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
6539	dr->dr_curslot = slot;
6540	dr->dr_usedslot++;
6541
6542	return (slot);
6543}
6544
6545static struct bwn_pio_txqueue *
6546bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
6547    struct bwn_pio_txpkt **pack)
6548{
6549	struct bwn_pio *pio = &mac->mac_method.pio;
6550	struct bwn_pio_txqueue *tq = NULL;
6551	unsigned int index;
6552
6553	switch (cookie & 0xf000) {
6554	case 0x1000:
6555		tq = &pio->wme[WME_AC_BK];
6556		break;
6557	case 0x2000:
6558		tq = &pio->wme[WME_AC_BE];
6559		break;
6560	case 0x3000:
6561		tq = &pio->wme[WME_AC_VI];
6562		break;
6563	case 0x4000:
6564		tq = &pio->wme[WME_AC_VO];
6565		break;
6566	case 0x5000:
6567		tq = &pio->mcast;
6568		break;
6569	}
6570	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
6571	if (tq == NULL)
6572		return (NULL);
6573	index = (cookie & 0x0fff);
6574	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
6575	if (index >= N(tq->tq_pkts))
6576		return (NULL);
6577	*pack = &tq->tq_pkts[index];
6578	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
6579	return (tq);
6580}
6581
6582static void
6583bwn_txpwr(void *arg, int npending)
6584{
6585	struct bwn_mac *mac = arg;
6586	struct bwn_softc *sc = mac->mac_sc;
6587
6588	BWN_LOCK(sc);
6589	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
6590	    mac->mac_phy.set_txpwr != NULL)
6591		mac->mac_phy.set_txpwr(mac);
6592	BWN_UNLOCK(sc);
6593}
6594
6595static void
6596bwn_task_15s(struct bwn_mac *mac)
6597{
6598	uint16_t reg;
6599
6600	if (mac->mac_fw.opensource) {
6601		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
6602		if (reg) {
6603			bwn_restart(mac, "fw watchdog");
6604			return;
6605		}
6606		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
6607	}
6608	if (mac->mac_phy.task_15s)
6609		mac->mac_phy.task_15s(mac);
6610
6611	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
6612}
6613
6614static void
6615bwn_task_30s(struct bwn_mac *mac)
6616{
6617
6618	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
6619		return;
6620	mac->mac_noise.noi_running = 1;
6621	mac->mac_noise.noi_nsamples = 0;
6622
6623	bwn_noise_gensample(mac);
6624}
6625
6626static void
6627bwn_task_60s(struct bwn_mac *mac)
6628{
6629
6630	if (mac->mac_phy.task_60s)
6631		mac->mac_phy.task_60s(mac);
6632	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
6633}
6634
6635static void
6636bwn_tasks(void *arg)
6637{
6638	struct bwn_mac *mac = arg;
6639	struct bwn_softc *sc = mac->mac_sc;
6640
6641	BWN_ASSERT_LOCKED(sc);
6642	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
6643		return;
6644
6645	if (mac->mac_task_state % 4 == 0)
6646		bwn_task_60s(mac);
6647	if (mac->mac_task_state % 2 == 0)
6648		bwn_task_30s(mac);
6649	bwn_task_15s(mac);
6650
6651	mac->mac_task_state++;
6652	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
6653}
6654
6655static int
6656bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
6657{
6658	struct bwn_softc *sc = mac->mac_sc;
6659
6660	KASSERT(a == 0, ("not support APHY\n"));
6661
6662	switch (plcp->o.raw[0] & 0xf) {
6663	case 0xb:
6664		return (BWN_OFDM_RATE_6MB);
6665	case 0xf:
6666		return (BWN_OFDM_RATE_9MB);
6667	case 0xa:
6668		return (BWN_OFDM_RATE_12MB);
6669	case 0xe:
6670		return (BWN_OFDM_RATE_18MB);
6671	case 0x9:
6672		return (BWN_OFDM_RATE_24MB);
6673	case 0xd:
6674		return (BWN_OFDM_RATE_36MB);
6675	case 0x8:
6676		return (BWN_OFDM_RATE_48MB);
6677	case 0xc:
6678		return (BWN_OFDM_RATE_54MB);
6679	}
6680	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
6681	    plcp->o.raw[0] & 0xf);
6682	return (-1);
6683}
6684
6685static int
6686bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
6687{
6688	struct bwn_softc *sc = mac->mac_sc;
6689
6690	switch (plcp->o.raw[0]) {
6691	case 0x0a:
6692		return (BWN_CCK_RATE_1MB);
6693	case 0x14:
6694		return (BWN_CCK_RATE_2MB);
6695	case 0x37:
6696		return (BWN_CCK_RATE_5MB);
6697	case 0x6e:
6698		return (BWN_CCK_RATE_11MB);
6699	}
6700	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
6701	return (-1);
6702}
6703
6704static void
6705bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
6706    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
6707    int rssi, int noise)
6708{
6709	struct bwn_softc *sc = mac->mac_sc;
6710	const struct ieee80211_frame_min *wh;
6711	uint64_t tsf;
6712	uint16_t low_mactime_now;
6713
6714	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
6715		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6716
6717	wh = mtod(m, const struct ieee80211_frame_min *);
6718	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6719		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
6720
6721	bwn_tsf_read(mac, &tsf);
6722	low_mactime_now = tsf;
6723	tsf = tsf & ~0xffffULL;
6724	tsf += le16toh(rxhdr->mac_time);
6725	if (low_mactime_now < le16toh(rxhdr->mac_time))
6726		tsf -= 0x10000;
6727
6728	sc->sc_rx_th.wr_tsf = tsf;
6729	sc->sc_rx_th.wr_rate = rate;
6730	sc->sc_rx_th.wr_antsignal = rssi;
6731	sc->sc_rx_th.wr_antnoise = noise;
6732}
6733
6734static void
6735bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
6736{
6737	uint32_t low, high;
6738
6739	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
6740	    ("%s:%d: fail", __func__, __LINE__));
6741
6742	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
6743	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
6744	*tsf = high;
6745	*tsf <<= 32;
6746	*tsf |= low;
6747}
6748
6749static int
6750bwn_dma_attach(struct bwn_mac *mac)
6751{
6752	struct bwn_dma *dma = &mac->mac_method.dma;
6753	struct bwn_softc *sc = mac->mac_sc;
6754	bus_addr_t lowaddr = 0;
6755	int error;
6756
6757	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
6758		return (0);
6759
6760	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
6761
6762	mac->mac_flags |= BWN_MAC_FLAG_DMA;
6763
6764	dma->dmatype = bwn_dma_gettype(mac);
6765	if (dma->dmatype == BWN_DMA_30BIT)
6766		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
6767	else if (dma->dmatype == BWN_DMA_32BIT)
6768		lowaddr = BUS_SPACE_MAXADDR_32BIT;
6769	else
6770		lowaddr = BUS_SPACE_MAXADDR;
6771
6772	/*
6773	 * Create top level DMA tag
6774	 */
6775	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
6776			       BWN_ALIGN, 0,		/* alignment, bounds */
6777			       lowaddr,			/* lowaddr */
6778			       BUS_SPACE_MAXADDR,	/* highaddr */
6779			       NULL, NULL,		/* filter, filterarg */
6780			       BUS_SPACE_MAXSIZE,	/* maxsize */
6781			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
6782			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
6783			       0,			/* flags */
6784			       NULL, NULL,		/* lockfunc, lockarg */
6785			       &dma->parent_dtag);
6786	if (error) {
6787		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
6788		return (error);
6789	}
6790
6791	/*
6792	 * Create TX/RX mbuf DMA tag
6793	 */
6794	error = bus_dma_tag_create(dma->parent_dtag,
6795				1,
6796				0,
6797				BUS_SPACE_MAXADDR,
6798				BUS_SPACE_MAXADDR,
6799				NULL, NULL,
6800				MCLBYTES,
6801				1,
6802				BUS_SPACE_MAXSIZE_32BIT,
6803				0,
6804				NULL, NULL,
6805				&dma->rxbuf_dtag);
6806	if (error) {
6807		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6808		goto fail0;
6809	}
6810	error = bus_dma_tag_create(dma->parent_dtag,
6811				1,
6812				0,
6813				BUS_SPACE_MAXADDR,
6814				BUS_SPACE_MAXADDR,
6815				NULL, NULL,
6816				MCLBYTES,
6817				1,
6818				BUS_SPACE_MAXSIZE_32BIT,
6819				0,
6820				NULL, NULL,
6821				&dma->txbuf_dtag);
6822	if (error) {
6823		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6824		goto fail1;
6825	}
6826
6827	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
6828	if (!dma->wme[WME_AC_BK])
6829		goto fail2;
6830
6831	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
6832	if (!dma->wme[WME_AC_BE])
6833		goto fail3;
6834
6835	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
6836	if (!dma->wme[WME_AC_VI])
6837		goto fail4;
6838
6839	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
6840	if (!dma->wme[WME_AC_VO])
6841		goto fail5;
6842
6843	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
6844	if (!dma->mcast)
6845		goto fail6;
6846	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
6847	if (!dma->rx)
6848		goto fail7;
6849
6850	return (error);
6851
6852fail7:	bwn_dma_ringfree(&dma->mcast);
6853fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
6854fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
6855fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
6856fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
6857fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
6858fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
6859fail0:	bus_dma_tag_destroy(dma->parent_dtag);
6860	return (error);
6861}
6862
6863static struct bwn_dma_ring *
6864bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
6865    uint16_t cookie, int *slot)
6866{
6867	struct bwn_dma *dma = &mac->mac_method.dma;
6868	struct bwn_dma_ring *dr;
6869	struct bwn_softc *sc = mac->mac_sc;
6870
6871	BWN_ASSERT_LOCKED(mac->mac_sc);
6872
6873	switch (cookie & 0xf000) {
6874	case 0x1000:
6875		dr = dma->wme[WME_AC_BK];
6876		break;
6877	case 0x2000:
6878		dr = dma->wme[WME_AC_BE];
6879		break;
6880	case 0x3000:
6881		dr = dma->wme[WME_AC_VI];
6882		break;
6883	case 0x4000:
6884		dr = dma->wme[WME_AC_VO];
6885		break;
6886	case 0x5000:
6887		dr = dma->mcast;
6888		break;
6889	default:
6890		dr = NULL;
6891		KASSERT(0 == 1,
6892		    ("invalid cookie value %d", cookie & 0xf000));
6893	}
6894	*slot = (cookie & 0x0fff);
6895	if (*slot < 0 || *slot >= dr->dr_numslots) {
6896		/*
6897		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
6898		 * that it occurs events which have same H/W sequence numbers.
6899		 * When it's occurred just prints a WARNING msgs and ignores.
6900		 */
6901		KASSERT(status->seq == dma->lastseq,
6902		    ("%s:%d: fail", __func__, __LINE__));
6903		device_printf(sc->sc_dev,
6904		    "out of slot ranges (0 < %d < %d)\n", *slot,
6905		    dr->dr_numslots);
6906		return (NULL);
6907	}
6908	dma->lastseq = status->seq;
6909	return (dr);
6910}
6911
6912static void
6913bwn_dma_stop(struct bwn_mac *mac)
6914{
6915	struct bwn_dma *dma;
6916
6917	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
6918		return;
6919	dma = &mac->mac_method.dma;
6920
6921	bwn_dma_ringstop(&dma->rx);
6922	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
6923	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
6924	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
6925	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
6926	bwn_dma_ringstop(&dma->mcast);
6927}
6928
6929static void
6930bwn_dma_ringstop(struct bwn_dma_ring **dr)
6931{
6932
6933	if (dr == NULL)
6934		return;
6935
6936	bwn_dma_cleanup(*dr);
6937}
6938
6939static void
6940bwn_pio_stop(struct bwn_mac *mac)
6941{
6942	struct bwn_pio *pio;
6943
6944	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
6945		return;
6946	pio = &mac->mac_method.pio;
6947
6948	bwn_destroy_queue_tx(&pio->mcast);
6949	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
6950	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
6951	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
6952	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
6953}
6954
6955static void
6956bwn_led_attach(struct bwn_mac *mac)
6957{
6958	struct bwn_softc *sc = mac->mac_sc;
6959	const uint8_t *led_act = NULL;
6960	uint16_t val[BWN_LED_MAX];
6961	int i;
6962
6963	sc->sc_led_idle = (2350 * hz) / 1000;
6964	sc->sc_led_blink = 1;
6965
6966	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
6967		if (siba_get_pci_subvendor(sc->sc_dev) ==
6968		    bwn_vendor_led_act[i].vid) {
6969			led_act = bwn_vendor_led_act[i].led_act;
6970			break;
6971		}
6972	}
6973	if (led_act == NULL)
6974		led_act = bwn_default_led_act;
6975
6976	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
6977	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
6978	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
6979	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
6980
6981	for (i = 0; i < BWN_LED_MAX; ++i) {
6982		struct bwn_led *led = &sc->sc_leds[i];
6983
6984		if (val[i] == 0xff) {
6985			led->led_act = led_act[i];
6986		} else {
6987			if (val[i] & BWN_LED_ACT_LOW)
6988				led->led_flags |= BWN_LED_F_ACTLOW;
6989			led->led_act = val[i] & BWN_LED_ACT_MASK;
6990		}
6991		led->led_mask = (1 << i);
6992
6993		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
6994		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
6995		    led->led_act == BWN_LED_ACT_BLINK) {
6996			led->led_flags |= BWN_LED_F_BLINK;
6997			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
6998				led->led_flags |= BWN_LED_F_POLLABLE;
6999			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
7000				led->led_flags |= BWN_LED_F_SLOW;
7001
7002			if (sc->sc_blink_led == NULL) {
7003				sc->sc_blink_led = led;
7004				if (led->led_flags & BWN_LED_F_SLOW)
7005					BWN_LED_SLOWDOWN(sc->sc_led_idle);
7006			}
7007		}
7008
7009		DPRINTF(sc, BWN_DEBUG_LED,
7010		    "%dth led, act %d, lowact %d\n", i,
7011		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
7012	}
7013	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
7014}
7015
7016static __inline uint16_t
7017bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
7018{
7019
7020	if (led->led_flags & BWN_LED_F_ACTLOW)
7021		on = !on;
7022	if (on)
7023		val |= led->led_mask;
7024	else
7025		val &= ~led->led_mask;
7026	return val;
7027}
7028
7029static void
7030bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
7031{
7032	struct bwn_softc *sc = mac->mac_sc;
7033	struct ieee80211com *ic = &sc->sc_ic;
7034	uint16_t val;
7035	int i;
7036
7037	if (nstate == IEEE80211_S_INIT) {
7038		callout_stop(&sc->sc_led_blink_ch);
7039		sc->sc_led_blinking = 0;
7040	}
7041
7042	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
7043		return;
7044
7045	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7046	for (i = 0; i < BWN_LED_MAX; ++i) {
7047		struct bwn_led *led = &sc->sc_leds[i];
7048		int on;
7049
7050		if (led->led_act == BWN_LED_ACT_UNKN ||
7051		    led->led_act == BWN_LED_ACT_NULL)
7052			continue;
7053
7054		if ((led->led_flags & BWN_LED_F_BLINK) &&
7055		    nstate != IEEE80211_S_INIT)
7056			continue;
7057
7058		switch (led->led_act) {
7059		case BWN_LED_ACT_ON:    /* Always on */
7060			on = 1;
7061			break;
7062		case BWN_LED_ACT_OFF:   /* Always off */
7063		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
7064			on = 0;
7065			break;
7066		default:
7067			on = 1;
7068			switch (nstate) {
7069			case IEEE80211_S_INIT:
7070				on = 0;
7071				break;
7072			case IEEE80211_S_RUN:
7073				if (led->led_act == BWN_LED_ACT_11G &&
7074				    ic->ic_curmode != IEEE80211_MODE_11G)
7075					on = 0;
7076				break;
7077			default:
7078				if (led->led_act == BWN_LED_ACT_ASSOC)
7079					on = 0;
7080				break;
7081			}
7082			break;
7083		}
7084
7085		val = bwn_led_onoff(led, val, on);
7086	}
7087	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7088}
7089
7090static void
7091bwn_led_event(struct bwn_mac *mac, int event)
7092{
7093	struct bwn_softc *sc = mac->mac_sc;
7094	struct bwn_led *led = sc->sc_blink_led;
7095	int rate;
7096
7097	if (event == BWN_LED_EVENT_POLL) {
7098		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
7099			return;
7100		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
7101			return;
7102	}
7103
7104	sc->sc_led_ticks = ticks;
7105	if (sc->sc_led_blinking)
7106		return;
7107
7108	switch (event) {
7109	case BWN_LED_EVENT_RX:
7110		rate = sc->sc_rx_rate;
7111		break;
7112	case BWN_LED_EVENT_TX:
7113		rate = sc->sc_tx_rate;
7114		break;
7115	case BWN_LED_EVENT_POLL:
7116		rate = 0;
7117		break;
7118	default:
7119		panic("unknown LED event %d\n", event);
7120		break;
7121	}
7122	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
7123	    bwn_led_duration[rate].off_dur);
7124}
7125
7126static void
7127bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
7128{
7129	struct bwn_softc *sc = mac->mac_sc;
7130	struct bwn_led *led = sc->sc_blink_led;
7131	uint16_t val;
7132
7133	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7134	val = bwn_led_onoff(led, val, 1);
7135	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7136
7137	if (led->led_flags & BWN_LED_F_SLOW) {
7138		BWN_LED_SLOWDOWN(on_dur);
7139		BWN_LED_SLOWDOWN(off_dur);
7140	}
7141
7142	sc->sc_led_blinking = 1;
7143	sc->sc_led_blink_offdur = off_dur;
7144
7145	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
7146}
7147
7148static void
7149bwn_led_blink_next(void *arg)
7150{
7151	struct bwn_mac *mac = arg;
7152	struct bwn_softc *sc = mac->mac_sc;
7153	uint16_t val;
7154
7155	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7156	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
7157	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7158
7159	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
7160	    bwn_led_blink_end, mac);
7161}
7162
7163static void
7164bwn_led_blink_end(void *arg)
7165{
7166	struct bwn_mac *mac = arg;
7167	struct bwn_softc *sc = mac->mac_sc;
7168
7169	sc->sc_led_blinking = 0;
7170}
7171
7172static int
7173bwn_suspend(device_t dev)
7174{
7175	struct bwn_softc *sc = device_get_softc(dev);
7176
7177	BWN_LOCK(sc);
7178	bwn_stop(sc);
7179	BWN_UNLOCK(sc);
7180	return (0);
7181}
7182
7183static int
7184bwn_resume(device_t dev)
7185{
7186	struct bwn_softc *sc = device_get_softc(dev);
7187	int error = EDOOFUS;
7188
7189	BWN_LOCK(sc);
7190	if (sc->sc_ic.ic_nrunning > 0)
7191		error = bwn_init(sc);
7192	BWN_UNLOCK(sc);
7193	if (error == 0)
7194		ieee80211_start_all(&sc->sc_ic);
7195	return (0);
7196}
7197
7198static void
7199bwn_rfswitch(void *arg)
7200{
7201	struct bwn_softc *sc = arg;
7202	struct bwn_mac *mac = sc->sc_curmac;
7203	int cur = 0, prev = 0;
7204
7205	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
7206	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
7207
7208	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP
7209	    || mac->mac_phy.type == BWN_PHYTYPE_N) {
7210		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
7211			& BWN_RF_HWENABLED_HI_MASK))
7212			cur = 1;
7213	} else {
7214		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
7215		    & BWN_RF_HWENABLED_LO_MASK)
7216			cur = 1;
7217	}
7218
7219	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
7220		prev = 1;
7221
7222	DPRINTF(sc, BWN_DEBUG_RESET, "%s: called; cur=%d, prev=%d\n",
7223	    __func__, cur, prev);
7224
7225	if (cur != prev) {
7226		if (cur)
7227			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
7228		else
7229			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
7230
7231		device_printf(sc->sc_dev,
7232		    "status of RF switch is changed to %s\n",
7233		    cur ? "ON" : "OFF");
7234		if (cur != mac->mac_phy.rf_on) {
7235			if (cur)
7236				bwn_rf_turnon(mac);
7237			else
7238				bwn_rf_turnoff(mac);
7239		}
7240	}
7241
7242	callout_schedule(&sc->sc_rfswitch_ch, hz);
7243}
7244
7245static void
7246bwn_sysctl_node(struct bwn_softc *sc)
7247{
7248	device_t dev = sc->sc_dev;
7249	struct bwn_mac *mac;
7250	struct bwn_stats *stats;
7251
7252	/* XXX assume that count of MAC is only 1. */
7253
7254	if ((mac = sc->sc_curmac) == NULL)
7255		return;
7256	stats = &mac->mac_stats;
7257
7258	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7259	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7260	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
7261	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7262	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7263	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
7264	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7265	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7266	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
7267
7268#ifdef BWN_DEBUG
7269	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
7270	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7271	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
7272#endif
7273}
7274
7275static device_method_t bwn_methods[] = {
7276	/* Device interface */
7277	DEVMETHOD(device_probe,		bwn_probe),
7278	DEVMETHOD(device_attach,	bwn_attach),
7279	DEVMETHOD(device_detach,	bwn_detach),
7280	DEVMETHOD(device_suspend,	bwn_suspend),
7281	DEVMETHOD(device_resume,	bwn_resume),
7282	DEVMETHOD_END
7283};
7284static driver_t bwn_driver = {
7285	"bwn",
7286	bwn_methods,
7287	sizeof(struct bwn_softc)
7288};
7289static devclass_t bwn_devclass;
7290DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
7291MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
7292MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
7293MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
7294MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
7295MODULE_VERSION(bwn, 1);
7296