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