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