if_bwn.c revision 299776
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 299776 2016-05-14 23:20:46Z 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	if (rev >= 5 && rev <= 10)
3735		filename = "ucode5";
3736	else if (rev >= 11 && rev <= 12)
3737		filename = "ucode11";
3738	else if (rev == 13)
3739		filename = "ucode13";
3740	else if (rev == 14)
3741		filename = "ucode14";
3742	else if (rev >= 15)
3743		filename = "ucode15";
3744	else {
3745		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
3746		bwn_release_firmware(mac);
3747		return (EOPNOTSUPP);
3748	}
3749	error = bwn_fw_get(mac, type, filename, &fw->ucode);
3750	if (error) {
3751		bwn_release_firmware(mac);
3752		return (error);
3753	}
3754
3755	/* PCM */
3756	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
3757	if (rev >= 5 && rev <= 10) {
3758		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
3759		if (error == ENOENT)
3760			fw->no_pcmfile = 1;
3761		else if (error) {
3762			bwn_release_firmware(mac);
3763			return (error);
3764		}
3765	} else if (rev < 11) {
3766		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
3767		return (EOPNOTSUPP);
3768	}
3769
3770	/* initvals */
3771	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
3772	switch (mac->mac_phy.type) {
3773	case BWN_PHYTYPE_A:
3774		if (rev < 5 || rev > 10)
3775			goto fail1;
3776		if (high & BWN_TGSHIGH_HAVE_2GHZ)
3777			filename = "a0g1initvals5";
3778		else
3779			filename = "a0g0initvals5";
3780		break;
3781	case BWN_PHYTYPE_G:
3782		if (rev >= 5 && rev <= 10)
3783			filename = "b0g0initvals5";
3784		else if (rev >= 13)
3785			filename = "b0g0initvals13";
3786		else
3787			goto fail1;
3788		break;
3789	case BWN_PHYTYPE_LP:
3790		if (rev == 13)
3791			filename = "lp0initvals13";
3792		else if (rev == 14)
3793			filename = "lp0initvals14";
3794		else if (rev >= 15)
3795			filename = "lp0initvals15";
3796		else
3797			goto fail1;
3798		break;
3799	case BWN_PHYTYPE_N:
3800		if (rev >= 11 && rev <= 12)
3801			filename = "n0initvals11";
3802		else
3803			goto fail1;
3804		break;
3805	default:
3806		goto fail1;
3807	}
3808	error = bwn_fw_get(mac, type, filename, &fw->initvals);
3809	if (error) {
3810		bwn_release_firmware(mac);
3811		return (error);
3812	}
3813
3814	/* bandswitch initvals */
3815	switch (mac->mac_phy.type) {
3816	case BWN_PHYTYPE_A:
3817		if (rev >= 5 && rev <= 10) {
3818			if (high & BWN_TGSHIGH_HAVE_2GHZ)
3819				filename = "a0g1bsinitvals5";
3820			else
3821				filename = "a0g0bsinitvals5";
3822		} else if (rev >= 11)
3823			filename = NULL;
3824		else
3825			goto fail1;
3826		break;
3827	case BWN_PHYTYPE_G:
3828		if (rev >= 5 && rev <= 10)
3829			filename = "b0g0bsinitvals5";
3830		else if (rev >= 11)
3831			filename = NULL;
3832		else
3833			goto fail1;
3834		break;
3835	case BWN_PHYTYPE_LP:
3836		if (rev == 13)
3837			filename = "lp0bsinitvals13";
3838		else if (rev == 14)
3839			filename = "lp0bsinitvals14";
3840		else if (rev >= 15)
3841			filename = "lp0bsinitvals15";
3842		else
3843			goto fail1;
3844		break;
3845	case BWN_PHYTYPE_N:
3846		if (rev >= 11 && rev <= 12)
3847			filename = "n0bsinitvals11";
3848		else
3849			goto fail1;
3850		break;
3851	default:
3852		goto fail1;
3853	}
3854	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
3855	if (error) {
3856		bwn_release_firmware(mac);
3857		return (error);
3858	}
3859	return (0);
3860fail1:
3861	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
3862	bwn_release_firmware(mac);
3863	return (EOPNOTSUPP);
3864}
3865
3866static int
3867bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
3868    const char *name, struct bwn_fwfile *bfw)
3869{
3870	const struct bwn_fwhdr *hdr;
3871	struct bwn_softc *sc = mac->mac_sc;
3872	const struct firmware *fw;
3873	char namebuf[64];
3874
3875	if (name == NULL) {
3876		bwn_do_release_fw(bfw);
3877		return (0);
3878	}
3879	if (bfw->filename != NULL) {
3880		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
3881			return (0);
3882		bwn_do_release_fw(bfw);
3883	}
3884
3885	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
3886	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
3887	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
3888	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
3889	fw = firmware_get(namebuf);
3890	if (fw == NULL) {
3891		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
3892		    namebuf);
3893		return (ENOENT);
3894	}
3895	if (fw->datasize < sizeof(struct bwn_fwhdr))
3896		goto fail;
3897	hdr = (const struct bwn_fwhdr *)(fw->data);
3898	switch (hdr->type) {
3899	case BWN_FWTYPE_UCODE:
3900	case BWN_FWTYPE_PCM:
3901		if (be32toh(hdr->size) !=
3902		    (fw->datasize - sizeof(struct bwn_fwhdr)))
3903			goto fail;
3904		/* FALLTHROUGH */
3905	case BWN_FWTYPE_IV:
3906		if (hdr->ver != 1)
3907			goto fail;
3908		break;
3909	default:
3910		goto fail;
3911	}
3912	bfw->filename = name;
3913	bfw->fw = fw;
3914	bfw->type = type;
3915	return (0);
3916fail:
3917	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
3918	if (fw != NULL)
3919		firmware_put(fw, FIRMWARE_UNLOAD);
3920	return (EPROTO);
3921}
3922
3923static void
3924bwn_release_firmware(struct bwn_mac *mac)
3925{
3926
3927	bwn_do_release_fw(&mac->mac_fw.ucode);
3928	bwn_do_release_fw(&mac->mac_fw.pcm);
3929	bwn_do_release_fw(&mac->mac_fw.initvals);
3930	bwn_do_release_fw(&mac->mac_fw.initvals_band);
3931}
3932
3933static void
3934bwn_do_release_fw(struct bwn_fwfile *bfw)
3935{
3936
3937	if (bfw->fw != NULL)
3938		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
3939	bfw->fw = NULL;
3940	bfw->filename = NULL;
3941}
3942
3943static int
3944bwn_fw_loaducode(struct bwn_mac *mac)
3945{
3946#define	GETFWOFFSET(fwp, offset)	\
3947	((const uint32_t *)((const char *)fwp.fw->data + offset))
3948#define	GETFWSIZE(fwp, offset)	\
3949	((fwp.fw->datasize - offset) / sizeof(uint32_t))
3950	struct bwn_softc *sc = mac->mac_sc;
3951	const uint32_t *data;
3952	unsigned int i;
3953	uint32_t ctl;
3954	uint16_t date, fwcaps, time;
3955	int error = 0;
3956
3957	ctl = BWN_READ_4(mac, BWN_MACCTL);
3958	ctl |= BWN_MACCTL_MCODE_JMP0;
3959	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
3960	    __LINE__));
3961	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
3962	for (i = 0; i < 64; i++)
3963		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
3964	for (i = 0; i < 4096; i += 2)
3965		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
3966
3967	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
3968	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
3969	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
3970	     i++) {
3971		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
3972		DELAY(10);
3973	}
3974
3975	if (mac->mac_fw.pcm.fw) {
3976		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
3977		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
3978		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
3979		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
3980		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
3981		    sizeof(struct bwn_fwhdr)); i++) {
3982			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
3983			DELAY(10);
3984		}
3985	}
3986
3987	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
3988	BWN_WRITE_4(mac, BWN_MACCTL,
3989	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
3990	    BWN_MACCTL_MCODE_RUN);
3991
3992	for (i = 0; i < 21; i++) {
3993		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
3994			break;
3995		if (i >= 20) {
3996			device_printf(sc->sc_dev, "ucode timeout\n");
3997			error = ENXIO;
3998			goto error;
3999		}
4000		DELAY(50000);
4001	}
4002	BWN_READ_4(mac, BWN_INTR_REASON);
4003
4004	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
4005	if (mac->mac_fw.rev <= 0x128) {
4006		device_printf(sc->sc_dev, "the firmware is too old\n");
4007		error = EOPNOTSUPP;
4008		goto error;
4009	}
4010
4011	/*
4012	 * Determine firmware header version; needed for TX/RX packet
4013	 * handling.
4014	 */
4015	if (mac->mac_fw.rev >= 598)
4016		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_598;
4017	else if (mac->mac_fw.rev >= 410)
4018		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_410;
4019	else
4020		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_351;
4021
4022	/*
4023	 * We don't support rev 598 or later; that requires
4024	 * another round of changes to the TX/RX descriptor
4025	 * and status layout.
4026	 *
4027	 * So, complain this is the case and exit out, rather
4028	 * than attaching and then failing.
4029	 */
4030	if (mac->mac_fw.fw_hdr_format == BWN_FW_HDR_598) {
4031		device_printf(sc->sc_dev,
4032		    "firmware is too new (>=598); not supported\n");
4033		error = EOPNOTSUPP;
4034		goto error;
4035	}
4036
4037	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
4038	    BWN_SHARED_UCODE_PATCH);
4039	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
4040	mac->mac_fw.opensource = (date == 0xffff);
4041	if (bwn_wme != 0)
4042		mac->mac_flags |= BWN_MAC_FLAG_WME;
4043	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
4044
4045	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
4046	if (mac->mac_fw.opensource == 0) {
4047		device_printf(sc->sc_dev,
4048		    "firmware version (rev %u patch %u date %#x time %#x)\n",
4049		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
4050		if (mac->mac_fw.no_pcmfile)
4051			device_printf(sc->sc_dev,
4052			    "no HW crypto acceleration due to pcm5\n");
4053	} else {
4054		mac->mac_fw.patch = time;
4055		fwcaps = bwn_fwcaps_read(mac);
4056		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
4057			device_printf(sc->sc_dev,
4058			    "disabling HW crypto acceleration\n");
4059			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
4060		}
4061		if (!(fwcaps & BWN_FWCAPS_WME)) {
4062			device_printf(sc->sc_dev, "disabling WME support\n");
4063			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
4064		}
4065	}
4066
4067	if (BWN_ISOLDFMT(mac))
4068		device_printf(sc->sc_dev, "using old firmware image\n");
4069
4070	return (0);
4071
4072error:
4073	BWN_WRITE_4(mac, BWN_MACCTL,
4074	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
4075	    BWN_MACCTL_MCODE_JMP0);
4076
4077	return (error);
4078#undef GETFWSIZE
4079#undef GETFWOFFSET
4080}
4081
4082/* OpenFirmware only */
4083static uint16_t
4084bwn_fwcaps_read(struct bwn_mac *mac)
4085{
4086
4087	KASSERT(mac->mac_fw.opensource == 1,
4088	    ("%s:%d: fail", __func__, __LINE__));
4089	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
4090}
4091
4092static int
4093bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
4094    size_t count, size_t array_size)
4095{
4096#define	GET_NEXTIV16(iv)						\
4097	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
4098	    sizeof(uint16_t) + sizeof(uint16_t)))
4099#define	GET_NEXTIV32(iv)						\
4100	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
4101	    sizeof(uint16_t) + sizeof(uint32_t)))
4102	struct bwn_softc *sc = mac->mac_sc;
4103	const struct bwn_fwinitvals *iv;
4104	uint16_t offset;
4105	size_t i;
4106	uint8_t bit32;
4107
4108	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
4109	    ("%s:%d: fail", __func__, __LINE__));
4110	iv = ivals;
4111	for (i = 0; i < count; i++) {
4112		if (array_size < sizeof(iv->offset_size))
4113			goto fail;
4114		array_size -= sizeof(iv->offset_size);
4115		offset = be16toh(iv->offset_size);
4116		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
4117		offset &= BWN_FWINITVALS_OFFSET_MASK;
4118		if (offset >= 0x1000)
4119			goto fail;
4120		if (bit32) {
4121			if (array_size < sizeof(iv->data.d32))
4122				goto fail;
4123			array_size -= sizeof(iv->data.d32);
4124			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
4125			iv = GET_NEXTIV32(iv);
4126		} else {
4127
4128			if (array_size < sizeof(iv->data.d16))
4129				goto fail;
4130			array_size -= sizeof(iv->data.d16);
4131			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
4132
4133			iv = GET_NEXTIV16(iv);
4134		}
4135	}
4136	if (array_size != 0)
4137		goto fail;
4138	return (0);
4139fail:
4140	device_printf(sc->sc_dev, "initvals: invalid format\n");
4141	return (EPROTO);
4142#undef GET_NEXTIV16
4143#undef GET_NEXTIV32
4144}
4145
4146int
4147bwn_switch_channel(struct bwn_mac *mac, int chan)
4148{
4149	struct bwn_phy *phy = &(mac->mac_phy);
4150	struct bwn_softc *sc = mac->mac_sc;
4151	struct ieee80211com *ic = &sc->sc_ic;
4152	uint16_t channelcookie, savedcookie;
4153	int error;
4154
4155	if (chan == 0xffff)
4156		chan = phy->get_default_chan(mac);
4157
4158	channelcookie = chan;
4159	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
4160		channelcookie |= 0x100;
4161	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
4162	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
4163	error = phy->switch_channel(mac, chan);
4164	if (error)
4165		goto fail;
4166
4167	mac->mac_phy.chan = chan;
4168	DELAY(8000);
4169	return (0);
4170fail:
4171	device_printf(sc->sc_dev, "failed to switch channel\n");
4172	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
4173	return (error);
4174}
4175
4176static uint16_t
4177bwn_ant2phy(int antenna)
4178{
4179
4180	switch (antenna) {
4181	case BWN_ANT0:
4182		return (BWN_TX_PHY_ANT0);
4183	case BWN_ANT1:
4184		return (BWN_TX_PHY_ANT1);
4185	case BWN_ANT2:
4186		return (BWN_TX_PHY_ANT2);
4187	case BWN_ANT3:
4188		return (BWN_TX_PHY_ANT3);
4189	case BWN_ANTAUTO:
4190		return (BWN_TX_PHY_ANT01AUTO);
4191	}
4192	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4193	return (0);
4194}
4195
4196static void
4197bwn_wme_load(struct bwn_mac *mac)
4198{
4199	struct bwn_softc *sc = mac->mac_sc;
4200	int i;
4201
4202	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
4203	    ("%s:%d: fail", __func__, __LINE__));
4204
4205	bwn_mac_suspend(mac);
4206	for (i = 0; i < N(sc->sc_wmeParams); i++)
4207		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
4208		    bwn_wme_shm_offsets[i]);
4209	bwn_mac_enable(mac);
4210}
4211
4212static void
4213bwn_wme_loadparams(struct bwn_mac *mac,
4214    const struct wmeParams *p, uint16_t shm_offset)
4215{
4216#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
4217	struct bwn_softc *sc = mac->mac_sc;
4218	uint16_t params[BWN_NR_WMEPARAMS];
4219	int slot, tmp;
4220	unsigned int i;
4221
4222	slot = BWN_READ_2(mac, BWN_RNG) &
4223	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4224
4225	memset(&params, 0, sizeof(params));
4226
4227	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
4228	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
4229	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
4230
4231	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
4232	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4233	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
4234	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4235	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
4236	params[BWN_WMEPARAM_BSLOTS] = slot;
4237	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
4238
4239	for (i = 0; i < N(params); i++) {
4240		if (i == BWN_WMEPARAM_STATUS) {
4241			tmp = bwn_shm_read_2(mac, BWN_SHARED,
4242			    shm_offset + (i * 2));
4243			tmp |= 0x100;
4244			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4245			    tmp);
4246		} else {
4247			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4248			    params[i]);
4249		}
4250	}
4251}
4252
4253static void
4254bwn_mac_write_bssid(struct bwn_mac *mac)
4255{
4256	struct bwn_softc *sc = mac->mac_sc;
4257	uint32_t tmp;
4258	int i;
4259	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
4260
4261	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
4262	memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
4263	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
4264	    IEEE80211_ADDR_LEN);
4265
4266	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
4267		tmp = (uint32_t) (mac_bssid[i + 0]);
4268		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
4269		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
4270		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
4271		bwn_ram_write(mac, 0x20 + i, tmp);
4272	}
4273}
4274
4275static void
4276bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
4277    const uint8_t *macaddr)
4278{
4279	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
4280	uint16_t data;
4281
4282	if (!mac)
4283		macaddr = zero;
4284
4285	offset |= 0x0020;
4286	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
4287
4288	data = macaddr[0];
4289	data |= macaddr[1] << 8;
4290	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4291	data = macaddr[2];
4292	data |= macaddr[3] << 8;
4293	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4294	data = macaddr[4];
4295	data |= macaddr[5] << 8;
4296	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4297}
4298
4299static void
4300bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4301    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
4302{
4303	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
4304	uint8_t per_sta_keys_start = 8;
4305
4306	if (BWN_SEC_NEWAPI(mac))
4307		per_sta_keys_start = 4;
4308
4309	KASSERT(index < mac->mac_max_nr_keys,
4310	    ("%s:%d: fail", __func__, __LINE__));
4311	KASSERT(key_len <= BWN_SEC_KEYSIZE,
4312	    ("%s:%d: fail", __func__, __LINE__));
4313
4314	if (index >= per_sta_keys_start)
4315		bwn_key_macwrite(mac, index, NULL);
4316	if (key)
4317		memcpy(buf, key, key_len);
4318	bwn_key_write(mac, index, algorithm, buf);
4319	if (index >= per_sta_keys_start)
4320		bwn_key_macwrite(mac, index, mac_addr);
4321
4322	mac->mac_key[index].algorithm = algorithm;
4323}
4324
4325static void
4326bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
4327{
4328	struct bwn_softc *sc = mac->mac_sc;
4329	uint32_t addrtmp[2] = { 0, 0 };
4330	uint8_t start = 8;
4331
4332	if (BWN_SEC_NEWAPI(mac))
4333		start = 4;
4334
4335	KASSERT(index >= start,
4336	    ("%s:%d: fail", __func__, __LINE__));
4337	index -= start;
4338
4339	if (addr) {
4340		addrtmp[0] = addr[0];
4341		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
4342		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
4343		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
4344		addrtmp[1] = addr[4];
4345		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
4346	}
4347
4348	if (siba_get_revid(sc->sc_dev) >= 5) {
4349		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
4350		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
4351	} else {
4352		if (index >= 8) {
4353			bwn_shm_write_4(mac, BWN_SHARED,
4354			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
4355			bwn_shm_write_2(mac, BWN_SHARED,
4356			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
4357		}
4358	}
4359}
4360
4361static void
4362bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4363    const uint8_t *key)
4364{
4365	unsigned int i;
4366	uint32_t offset;
4367	uint16_t kidx, value;
4368
4369	kidx = BWN_SEC_KEY2FW(mac, index);
4370	bwn_shm_write_2(mac, BWN_SHARED,
4371	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
4372
4373	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
4374	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
4375		value = key[i];
4376		value |= (uint16_t)(key[i + 1]) << 8;
4377		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
4378	}
4379}
4380
4381static void
4382bwn_phy_exit(struct bwn_mac *mac)
4383{
4384
4385	mac->mac_phy.rf_onoff(mac, 0);
4386	if (mac->mac_phy.exit != NULL)
4387		mac->mac_phy.exit(mac);
4388}
4389
4390static void
4391bwn_dma_free(struct bwn_mac *mac)
4392{
4393	struct bwn_dma *dma;
4394
4395	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
4396		return;
4397	dma = &mac->mac_method.dma;
4398
4399	bwn_dma_ringfree(&dma->rx);
4400	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
4401	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
4402	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
4403	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
4404	bwn_dma_ringfree(&dma->mcast);
4405}
4406
4407static void
4408bwn_core_stop(struct bwn_mac *mac)
4409{
4410	struct bwn_softc *sc = mac->mac_sc;
4411
4412	BWN_ASSERT_LOCKED(sc);
4413
4414	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
4415		return;
4416
4417	callout_stop(&sc->sc_rfswitch_ch);
4418	callout_stop(&sc->sc_task_ch);
4419	callout_stop(&sc->sc_watchdog_ch);
4420	sc->sc_watchdog_timer = 0;
4421	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4422	BWN_READ_4(mac, BWN_INTR_MASK);
4423	bwn_mac_suspend(mac);
4424
4425	mac->mac_status = BWN_MAC_STATUS_INITED;
4426}
4427
4428static int
4429bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
4430{
4431	struct bwn_mac *up_dev = NULL;
4432	struct bwn_mac *down_dev;
4433	struct bwn_mac *mac;
4434	int err, status;
4435	uint8_t gmode;
4436
4437	BWN_ASSERT_LOCKED(sc);
4438
4439	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
4440		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
4441		    mac->mac_phy.supports_2ghz) {
4442			up_dev = mac;
4443			gmode = 1;
4444		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
4445		    mac->mac_phy.supports_5ghz) {
4446			up_dev = mac;
4447			gmode = 0;
4448		} else {
4449			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4450			return (EINVAL);
4451		}
4452		if (up_dev != NULL)
4453			break;
4454	}
4455	if (up_dev == NULL) {
4456		device_printf(sc->sc_dev, "Could not find a device\n");
4457		return (ENODEV);
4458	}
4459	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
4460		return (0);
4461
4462	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
4463	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4464
4465	down_dev = sc->sc_curmac;
4466	status = down_dev->mac_status;
4467	if (status >= BWN_MAC_STATUS_STARTED)
4468		bwn_core_stop(down_dev);
4469	if (status >= BWN_MAC_STATUS_INITED)
4470		bwn_core_exit(down_dev);
4471
4472	if (down_dev != up_dev)
4473		bwn_phy_reset(down_dev);
4474
4475	up_dev->mac_phy.gmode = gmode;
4476	if (status >= BWN_MAC_STATUS_INITED) {
4477		err = bwn_core_init(up_dev);
4478		if (err) {
4479			device_printf(sc->sc_dev,
4480			    "fatal: failed to initialize for %s-GHz\n",
4481			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4482			goto fail;
4483		}
4484	}
4485	if (status >= BWN_MAC_STATUS_STARTED)
4486		bwn_core_start(up_dev);
4487	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
4488	sc->sc_curmac = up_dev;
4489
4490	return (0);
4491fail:
4492	sc->sc_curmac = NULL;
4493	return (err);
4494}
4495
4496static void
4497bwn_rf_turnon(struct bwn_mac *mac)
4498{
4499
4500	bwn_mac_suspend(mac);
4501	mac->mac_phy.rf_onoff(mac, 1);
4502	mac->mac_phy.rf_on = 1;
4503	bwn_mac_enable(mac);
4504}
4505
4506static void
4507bwn_rf_turnoff(struct bwn_mac *mac)
4508{
4509
4510	bwn_mac_suspend(mac);
4511	mac->mac_phy.rf_onoff(mac, 0);
4512	mac->mac_phy.rf_on = 0;
4513	bwn_mac_enable(mac);
4514}
4515
4516/*
4517 * SSB PHY reset.
4518 *
4519 * XXX TODO: BCMA PHY reset.
4520 */
4521static void
4522bwn_phy_reset(struct bwn_mac *mac)
4523{
4524	struct bwn_softc *sc = mac->mac_sc;
4525
4526	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4527	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
4528	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
4529	DELAY(1000);
4530	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4531	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC));
4532	DELAY(1000);
4533}
4534
4535static int
4536bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
4537{
4538	struct bwn_vap *bvp = BWN_VAP(vap);
4539	struct ieee80211com *ic= vap->iv_ic;
4540	enum ieee80211_state ostate = vap->iv_state;
4541	struct bwn_softc *sc = ic->ic_softc;
4542	struct bwn_mac *mac = sc->sc_curmac;
4543	int error;
4544
4545	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
4546	    ieee80211_state_name[vap->iv_state],
4547	    ieee80211_state_name[nstate]);
4548
4549	error = bvp->bv_newstate(vap, nstate, arg);
4550	if (error != 0)
4551		return (error);
4552
4553	BWN_LOCK(sc);
4554
4555	bwn_led_newstate(mac, nstate);
4556
4557	/*
4558	 * Clear the BSSID when we stop a STA
4559	 */
4560	if (vap->iv_opmode == IEEE80211_M_STA) {
4561		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
4562			/*
4563			 * Clear out the BSSID.  If we reassociate to
4564			 * the same AP, this will reinialize things
4565			 * correctly...
4566			 */
4567			if (ic->ic_opmode == IEEE80211_M_STA &&
4568			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
4569				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
4570				bwn_set_macaddr(mac);
4571			}
4572		}
4573	}
4574
4575	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
4576	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
4577		/* XXX nothing to do? */
4578	} else if (nstate == IEEE80211_S_RUN) {
4579		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
4580		bwn_set_opmode(mac);
4581		bwn_set_pretbtt(mac);
4582		bwn_spu_setdelay(mac, 0);
4583		bwn_set_macaddr(mac);
4584	}
4585
4586	BWN_UNLOCK(sc);
4587
4588	return (error);
4589}
4590
4591static void
4592bwn_set_pretbtt(struct bwn_mac *mac)
4593{
4594	struct bwn_softc *sc = mac->mac_sc;
4595	struct ieee80211com *ic = &sc->sc_ic;
4596	uint16_t pretbtt;
4597
4598	if (ic->ic_opmode == IEEE80211_M_IBSS)
4599		pretbtt = 2;
4600	else
4601		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
4602	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
4603	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
4604}
4605
4606static int
4607bwn_intr(void *arg)
4608{
4609	struct bwn_mac *mac = arg;
4610	struct bwn_softc *sc = mac->mac_sc;
4611	uint32_t reason;
4612
4613	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4614	    (sc->sc_flags & BWN_FLAG_INVALID))
4615		return (FILTER_STRAY);
4616
4617	reason = BWN_READ_4(mac, BWN_INTR_REASON);
4618	if (reason == 0xffffffff)	/* shared IRQ */
4619		return (FILTER_STRAY);
4620	reason &= mac->mac_intr_mask;
4621	if (reason == 0)
4622		return (FILTER_HANDLED);
4623
4624	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
4625	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
4626	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
4627	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
4628	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
4629	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
4630	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
4631	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
4632	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
4633	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
4634	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
4635
4636	/* Disable interrupts. */
4637	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4638
4639	mac->mac_reason_intr = reason;
4640
4641	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4642	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4643
4644	taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask);
4645	return (FILTER_HANDLED);
4646}
4647
4648static void
4649bwn_intrtask(void *arg, int npending)
4650{
4651	struct bwn_mac *mac = arg;
4652	struct bwn_softc *sc = mac->mac_sc;
4653	uint32_t merged = 0;
4654	int i, tx = 0, rx = 0;
4655
4656	BWN_LOCK(sc);
4657	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4658	    (sc->sc_flags & BWN_FLAG_INVALID)) {
4659		BWN_UNLOCK(sc);
4660		return;
4661	}
4662
4663	for (i = 0; i < N(mac->mac_reason); i++)
4664		merged |= mac->mac_reason[i];
4665
4666	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
4667		device_printf(sc->sc_dev, "MAC trans error\n");
4668
4669	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
4670		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
4671		mac->mac_phy.txerrors--;
4672		if (mac->mac_phy.txerrors == 0) {
4673			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
4674			bwn_restart(mac, "PHY TX errors");
4675		}
4676	}
4677
4678	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
4679		if (merged & BWN_DMAINTR_FATALMASK) {
4680			device_printf(sc->sc_dev,
4681			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
4682			    mac->mac_reason[0], mac->mac_reason[1],
4683			    mac->mac_reason[2], mac->mac_reason[3],
4684			    mac->mac_reason[4], mac->mac_reason[5]);
4685			bwn_restart(mac, "DMA error");
4686			BWN_UNLOCK(sc);
4687			return;
4688		}
4689		if (merged & BWN_DMAINTR_NONFATALMASK) {
4690			device_printf(sc->sc_dev,
4691			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
4692			    mac->mac_reason[0], mac->mac_reason[1],
4693			    mac->mac_reason[2], mac->mac_reason[3],
4694			    mac->mac_reason[4], mac->mac_reason[5]);
4695		}
4696	}
4697
4698	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
4699		bwn_intr_ucode_debug(mac);
4700	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
4701		bwn_intr_tbtt_indication(mac);
4702	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
4703		bwn_intr_atim_end(mac);
4704	if (mac->mac_reason_intr & BWN_INTR_BEACON)
4705		bwn_intr_beacon(mac);
4706	if (mac->mac_reason_intr & BWN_INTR_PMQ)
4707		bwn_intr_pmq(mac);
4708	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
4709		bwn_intr_noise(mac);
4710
4711	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
4712		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
4713			bwn_dma_rx(mac->mac_method.dma.rx);
4714			rx = 1;
4715		}
4716	} else
4717		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
4718
4719	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4720	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4721	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4722	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4723	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4724
4725	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
4726		bwn_intr_txeof(mac);
4727		tx = 1;
4728	}
4729
4730	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
4731
4732	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
4733		int evt = BWN_LED_EVENT_NONE;
4734
4735		if (tx && rx) {
4736			if (sc->sc_rx_rate > sc->sc_tx_rate)
4737				evt = BWN_LED_EVENT_RX;
4738			else
4739				evt = BWN_LED_EVENT_TX;
4740		} else if (tx) {
4741			evt = BWN_LED_EVENT_TX;
4742		} else if (rx) {
4743			evt = BWN_LED_EVENT_RX;
4744		} else if (rx == 0) {
4745			evt = BWN_LED_EVENT_POLL;
4746		}
4747
4748		if (evt != BWN_LED_EVENT_NONE)
4749			bwn_led_event(mac, evt);
4750       }
4751
4752	if (mbufq_first(&sc->sc_snd) != NULL)
4753		bwn_start(sc);
4754
4755	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4756	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4757
4758	BWN_UNLOCK(sc);
4759}
4760
4761static void
4762bwn_restart(struct bwn_mac *mac, const char *msg)
4763{
4764	struct bwn_softc *sc = mac->mac_sc;
4765	struct ieee80211com *ic = &sc->sc_ic;
4766
4767	if (mac->mac_status < BWN_MAC_STATUS_INITED)
4768		return;
4769
4770	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
4771	ieee80211_runtask(ic, &mac->mac_hwreset);
4772}
4773
4774static void
4775bwn_intr_ucode_debug(struct bwn_mac *mac)
4776{
4777	struct bwn_softc *sc = mac->mac_sc;
4778	uint16_t reason;
4779
4780	if (mac->mac_fw.opensource == 0)
4781		return;
4782
4783	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
4784	switch (reason) {
4785	case BWN_DEBUGINTR_PANIC:
4786		bwn_handle_fwpanic(mac);
4787		break;
4788	case BWN_DEBUGINTR_DUMP_SHM:
4789		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
4790		break;
4791	case BWN_DEBUGINTR_DUMP_REGS:
4792		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
4793		break;
4794	case BWN_DEBUGINTR_MARKER:
4795		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
4796		break;
4797	default:
4798		device_printf(sc->sc_dev,
4799		    "ucode debug unknown reason: %#x\n", reason);
4800	}
4801
4802	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
4803	    BWN_DEBUGINTR_ACK);
4804}
4805
4806static void
4807bwn_intr_tbtt_indication(struct bwn_mac *mac)
4808{
4809	struct bwn_softc *sc = mac->mac_sc;
4810	struct ieee80211com *ic = &sc->sc_ic;
4811
4812	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
4813		bwn_psctl(mac, 0);
4814	if (ic->ic_opmode == IEEE80211_M_IBSS)
4815		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
4816}
4817
4818static void
4819bwn_intr_atim_end(struct bwn_mac *mac)
4820{
4821
4822	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
4823		BWN_WRITE_4(mac, BWN_MACCMD,
4824		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
4825		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
4826	}
4827}
4828
4829static void
4830bwn_intr_beacon(struct bwn_mac *mac)
4831{
4832	struct bwn_softc *sc = mac->mac_sc;
4833	struct ieee80211com *ic = &sc->sc_ic;
4834	uint32_t cmd, beacon0, beacon1;
4835
4836	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4837	    ic->ic_opmode == IEEE80211_M_MBSS)
4838		return;
4839
4840	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
4841
4842	cmd = BWN_READ_4(mac, BWN_MACCMD);
4843	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
4844	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
4845
4846	if (beacon0 && beacon1) {
4847		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
4848		mac->mac_intr_mask |= BWN_INTR_BEACON;
4849		return;
4850	}
4851
4852	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
4853		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
4854		bwn_load_beacon0(mac);
4855		bwn_load_beacon1(mac);
4856		cmd = BWN_READ_4(mac, BWN_MACCMD);
4857		cmd |= BWN_MACCMD_BEACON0_VALID;
4858		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
4859	} else {
4860		if (!beacon0) {
4861			bwn_load_beacon0(mac);
4862			cmd = BWN_READ_4(mac, BWN_MACCMD);
4863			cmd |= BWN_MACCMD_BEACON0_VALID;
4864			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
4865		} else if (!beacon1) {
4866			bwn_load_beacon1(mac);
4867			cmd = BWN_READ_4(mac, BWN_MACCMD);
4868			cmd |= BWN_MACCMD_BEACON1_VALID;
4869			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
4870		}
4871	}
4872}
4873
4874static void
4875bwn_intr_pmq(struct bwn_mac *mac)
4876{
4877	uint32_t tmp;
4878
4879	while (1) {
4880		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
4881		if (!(tmp & 0x00000008))
4882			break;
4883	}
4884	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
4885}
4886
4887static void
4888bwn_intr_noise(struct bwn_mac *mac)
4889{
4890	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
4891	uint16_t tmp;
4892	uint8_t noise[4];
4893	uint8_t i, j;
4894	int32_t average;
4895
4896	if (mac->mac_phy.type != BWN_PHYTYPE_G)
4897		return;
4898
4899	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
4900	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
4901	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
4902	    noise[3] == 0x7f)
4903		goto new;
4904
4905	KASSERT(mac->mac_noise.noi_nsamples < 8,
4906	    ("%s:%d: fail", __func__, __LINE__));
4907	i = mac->mac_noise.noi_nsamples;
4908	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
4909	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
4910	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
4911	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
4912	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
4913	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
4914	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
4915	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
4916	mac->mac_noise.noi_nsamples++;
4917	if (mac->mac_noise.noi_nsamples == 8) {
4918		average = 0;
4919		for (i = 0; i < 8; i++) {
4920			for (j = 0; j < 4; j++)
4921				average += mac->mac_noise.noi_samples[i][j];
4922		}
4923		average = (((average / 32) * 125) + 64) / 128;
4924		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
4925		if (tmp >= 8)
4926			average += 2;
4927		else
4928			average -= 25;
4929		average -= (tmp == 8) ? 72 : 48;
4930
4931		mac->mac_stats.link_noise = average;
4932		mac->mac_noise.noi_running = 0;
4933		return;
4934	}
4935new:
4936	bwn_noise_gensample(mac);
4937}
4938
4939static int
4940bwn_pio_rx(struct bwn_pio_rxqueue *prq)
4941{
4942	struct bwn_mac *mac = prq->prq_mac;
4943	struct bwn_softc *sc = mac->mac_sc;
4944	unsigned int i;
4945
4946	BWN_ASSERT_LOCKED(sc);
4947
4948	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
4949		return (0);
4950
4951	for (i = 0; i < 5000; i++) {
4952		if (bwn_pio_rxeof(prq) == 0)
4953			break;
4954	}
4955	if (i >= 5000)
4956		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
4957	return ((i > 0) ? 1 : 0);
4958}
4959
4960static void
4961bwn_dma_rx(struct bwn_dma_ring *dr)
4962{
4963	int slot, curslot;
4964
4965	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
4966	curslot = dr->get_curslot(dr);
4967	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
4968	    ("%s:%d: fail", __func__, __LINE__));
4969
4970	slot = dr->dr_curslot;
4971	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
4972		bwn_dma_rxeof(dr, &slot);
4973
4974	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
4975	    BUS_DMASYNC_PREWRITE);
4976
4977	dr->set_curslot(dr, slot);
4978	dr->dr_curslot = slot;
4979}
4980
4981static void
4982bwn_intr_txeof(struct bwn_mac *mac)
4983{
4984	struct bwn_txstatus stat;
4985	uint32_t stat0, stat1;
4986	uint16_t tmp;
4987
4988	BWN_ASSERT_LOCKED(mac->mac_sc);
4989
4990	while (1) {
4991		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
4992		if (!(stat0 & 0x00000001))
4993			break;
4994		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
4995
4996		DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
4997		    "%s: stat0=0x%08x, stat1=0x%08x\n",
4998		    __func__,
4999		    stat0,
5000		    stat1);
5001
5002		stat.cookie = (stat0 >> 16);
5003		stat.seq = (stat1 & 0x0000ffff);
5004		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
5005		tmp = (stat0 & 0x0000ffff);
5006		stat.framecnt = ((tmp & 0xf000) >> 12);
5007		stat.rtscnt = ((tmp & 0x0f00) >> 8);
5008		stat.sreason = ((tmp & 0x001c) >> 2);
5009		stat.pm = (tmp & 0x0080) ? 1 : 0;
5010		stat.im = (tmp & 0x0040) ? 1 : 0;
5011		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
5012		stat.ack = (tmp & 0x0002) ? 1 : 0;
5013
5014		bwn_handle_txeof(mac, &stat);
5015	}
5016}
5017
5018static void
5019bwn_hwreset(void *arg, int npending)
5020{
5021	struct bwn_mac *mac = arg;
5022	struct bwn_softc *sc = mac->mac_sc;
5023	int error = 0;
5024	int prev_status;
5025
5026	BWN_LOCK(sc);
5027
5028	prev_status = mac->mac_status;
5029	if (prev_status >= BWN_MAC_STATUS_STARTED)
5030		bwn_core_stop(mac);
5031	if (prev_status >= BWN_MAC_STATUS_INITED)
5032		bwn_core_exit(mac);
5033
5034	if (prev_status >= BWN_MAC_STATUS_INITED) {
5035		error = bwn_core_init(mac);
5036		if (error)
5037			goto out;
5038	}
5039	if (prev_status >= BWN_MAC_STATUS_STARTED)
5040		bwn_core_start(mac);
5041out:
5042	if (error) {
5043		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
5044		sc->sc_curmac = NULL;
5045	}
5046	BWN_UNLOCK(sc);
5047}
5048
5049static void
5050bwn_handle_fwpanic(struct bwn_mac *mac)
5051{
5052	struct bwn_softc *sc = mac->mac_sc;
5053	uint16_t reason;
5054
5055	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
5056	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
5057
5058	if (reason == BWN_FWPANIC_RESTART)
5059		bwn_restart(mac, "ucode panic");
5060}
5061
5062static void
5063bwn_load_beacon0(struct bwn_mac *mac)
5064{
5065
5066	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5067}
5068
5069static void
5070bwn_load_beacon1(struct bwn_mac *mac)
5071{
5072
5073	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5074}
5075
5076static uint32_t
5077bwn_jssi_read(struct bwn_mac *mac)
5078{
5079	uint32_t val = 0;
5080
5081	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
5082	val <<= 16;
5083	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
5084
5085	return (val);
5086}
5087
5088static void
5089bwn_noise_gensample(struct bwn_mac *mac)
5090{
5091	uint32_t jssi = 0x7f7f7f7f;
5092
5093	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
5094	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
5095	BWN_WRITE_4(mac, BWN_MACCMD,
5096	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
5097}
5098
5099static int
5100bwn_dma_freeslot(struct bwn_dma_ring *dr)
5101{
5102	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5103
5104	return (dr->dr_numslots - dr->dr_usedslot);
5105}
5106
5107static int
5108bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
5109{
5110	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5111
5112	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
5113	    ("%s:%d: fail", __func__, __LINE__));
5114	if (slot == dr->dr_numslots - 1)
5115		return (0);
5116	return (slot + 1);
5117}
5118
5119static void
5120bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
5121{
5122	struct bwn_mac *mac = dr->dr_mac;
5123	struct bwn_softc *sc = mac->mac_sc;
5124	struct bwn_dma *dma = &mac->mac_method.dma;
5125	struct bwn_dmadesc_generic *desc;
5126	struct bwn_dmadesc_meta *meta;
5127	struct bwn_rxhdr4 *rxhdr;
5128	struct mbuf *m;
5129	uint32_t macstat;
5130	int32_t tmp;
5131	int cnt = 0;
5132	uint16_t len;
5133
5134	dr->getdesc(dr, *slot, &desc, &meta);
5135
5136	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
5137	m = meta->mt_m;
5138
5139	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
5140		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5141		return;
5142	}
5143
5144	rxhdr = mtod(m, struct bwn_rxhdr4 *);
5145	len = le16toh(rxhdr->frame_len);
5146	if (len <= 0) {
5147		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5148		return;
5149	}
5150	if (bwn_dma_check_redzone(dr, m)) {
5151		device_printf(sc->sc_dev, "redzone error.\n");
5152		bwn_dma_set_redzone(dr, m);
5153		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5154		    BUS_DMASYNC_PREWRITE);
5155		return;
5156	}
5157	if (len > dr->dr_rx_bufsize) {
5158		tmp = len;
5159		while (1) {
5160			dr->getdesc(dr, *slot, &desc, &meta);
5161			bwn_dma_set_redzone(dr, meta->mt_m);
5162			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5163			    BUS_DMASYNC_PREWRITE);
5164			*slot = bwn_dma_nextslot(dr, *slot);
5165			cnt++;
5166			tmp -= dr->dr_rx_bufsize;
5167			if (tmp <= 0)
5168				break;
5169		}
5170		device_printf(sc->sc_dev, "too small buffer "
5171		       "(len %u buffer %u dropped %d)\n",
5172		       len, dr->dr_rx_bufsize, cnt);
5173		return;
5174	}
5175	macstat = le32toh(rxhdr->mac_status);
5176	if (macstat & BWN_RX_MAC_FCSERR) {
5177		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5178			device_printf(sc->sc_dev, "RX drop\n");
5179			return;
5180		}
5181	}
5182
5183	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
5184	m_adj(m, dr->dr_frameoffset);
5185
5186	bwn_rxeof(dr->dr_mac, m, rxhdr);
5187}
5188
5189static void
5190bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
5191{
5192	struct bwn_softc *sc = mac->mac_sc;
5193	struct bwn_stats *stats = &mac->mac_stats;
5194
5195	BWN_ASSERT_LOCKED(mac->mac_sc);
5196
5197	if (status->im)
5198		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
5199	if (status->ampdu)
5200		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
5201	if (status->rtscnt) {
5202		if (status->rtscnt == 0xf)
5203			stats->rtsfail++;
5204		else
5205			stats->rts++;
5206	}
5207
5208	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
5209		bwn_dma_handle_txeof(mac, status);
5210	} else {
5211		bwn_pio_handle_txeof(mac, status);
5212	}
5213
5214	bwn_phy_txpower_check(mac, 0);
5215}
5216
5217static uint8_t
5218bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
5219{
5220	struct bwn_mac *mac = prq->prq_mac;
5221	struct bwn_softc *sc = mac->mac_sc;
5222	struct bwn_rxhdr4 rxhdr;
5223	struct mbuf *m;
5224	uint32_t ctl32, macstat, v32;
5225	unsigned int i, padding;
5226	uint16_t ctl16, len, totlen, v16;
5227	unsigned char *mp;
5228	char *data;
5229
5230	memset(&rxhdr, 0, sizeof(rxhdr));
5231
5232	if (prq->prq_rev >= 8) {
5233		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5234		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
5235			return (0);
5236		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5237		    BWN_PIO8_RXCTL_FRAMEREADY);
5238		for (i = 0; i < 10; i++) {
5239			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5240			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
5241				goto ready;
5242			DELAY(10);
5243		}
5244	} else {
5245		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5246		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
5247			return (0);
5248		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
5249		    BWN_PIO_RXCTL_FRAMEREADY);
5250		for (i = 0; i < 10; i++) {
5251			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5252			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
5253				goto ready;
5254			DELAY(10);
5255		}
5256	}
5257	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
5258	return (1);
5259ready:
5260	if (prq->prq_rev >= 8)
5261		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5262		    prq->prq_base + BWN_PIO8_RXDATA);
5263	else
5264		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5265		    prq->prq_base + BWN_PIO_RXDATA);
5266	len = le16toh(rxhdr.frame_len);
5267	if (len > 0x700) {
5268		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
5269		goto error;
5270	}
5271	if (len == 0) {
5272		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
5273		goto error;
5274	}
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, "%s: FCS error", __func__);
5280			goto error;
5281		}
5282	}
5283
5284	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5285	totlen = len + padding;
5286	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
5287	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5288	if (m == NULL) {
5289		device_printf(sc->sc_dev, "%s: out of memory", __func__);
5290		goto error;
5291	}
5292	mp = mtod(m, unsigned char *);
5293	if (prq->prq_rev >= 8) {
5294		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
5295		    prq->prq_base + BWN_PIO8_RXDATA);
5296		if (totlen & 3) {
5297			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
5298			data = &(mp[totlen - 1]);
5299			switch (totlen & 3) {
5300			case 3:
5301				*data = (v32 >> 16);
5302				data--;
5303			case 2:
5304				*data = (v32 >> 8);
5305				data--;
5306			case 1:
5307				*data = v32;
5308			}
5309		}
5310	} else {
5311		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
5312		    prq->prq_base + BWN_PIO_RXDATA);
5313		if (totlen & 1) {
5314			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
5315			mp[totlen - 1] = v16;
5316		}
5317	}
5318
5319	m->m_len = m->m_pkthdr.len = totlen;
5320
5321	bwn_rxeof(prq->prq_mac, m, &rxhdr);
5322
5323	return (1);
5324error:
5325	if (prq->prq_rev >= 8)
5326		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5327		    BWN_PIO8_RXCTL_DATAREADY);
5328	else
5329		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
5330	return (1);
5331}
5332
5333static int
5334bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
5335    struct bwn_dmadesc_meta *meta, int init)
5336{
5337	struct bwn_mac *mac = dr->dr_mac;
5338	struct bwn_dma *dma = &mac->mac_method.dma;
5339	struct bwn_rxhdr4 *hdr;
5340	bus_dmamap_t map;
5341	bus_addr_t paddr;
5342	struct mbuf *m;
5343	int error;
5344
5345	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5346	if (m == NULL) {
5347		error = ENOBUFS;
5348
5349		/*
5350		 * If the NIC is up and running, we need to:
5351		 * - Clear RX buffer's header.
5352		 * - Restore RX descriptor settings.
5353		 */
5354		if (init)
5355			return (error);
5356		else
5357			goto back;
5358	}
5359	m->m_len = m->m_pkthdr.len = MCLBYTES;
5360
5361	bwn_dma_set_redzone(dr, m);
5362
5363	/*
5364	 * Try to load RX buf into temporary DMA map
5365	 */
5366	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
5367	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
5368	if (error) {
5369		m_freem(m);
5370
5371		/*
5372		 * See the comment above
5373		 */
5374		if (init)
5375			return (error);
5376		else
5377			goto back;
5378	}
5379
5380	if (!init)
5381		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
5382	meta->mt_m = m;
5383	meta->mt_paddr = paddr;
5384
5385	/*
5386	 * Swap RX buf's DMA map with the loaded temporary one
5387	 */
5388	map = meta->mt_dmap;
5389	meta->mt_dmap = dr->dr_spare_dmap;
5390	dr->dr_spare_dmap = map;
5391
5392back:
5393	/*
5394	 * Clear RX buf header
5395	 */
5396	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
5397	bzero(hdr, sizeof(*hdr));
5398	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5399	    BUS_DMASYNC_PREWRITE);
5400
5401	/*
5402	 * Setup RX buf descriptor
5403	 */
5404	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
5405	    sizeof(*hdr), 0, 0, 0);
5406	return (error);
5407}
5408
5409static void
5410bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
5411		 bus_size_t mapsz __unused, int error)
5412{
5413
5414	if (!error) {
5415		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
5416		*((bus_addr_t *)arg) = seg->ds_addr;
5417	}
5418}
5419
5420static int
5421bwn_hwrate2ieeerate(int rate)
5422{
5423
5424	switch (rate) {
5425	case BWN_CCK_RATE_1MB:
5426		return (2);
5427	case BWN_CCK_RATE_2MB:
5428		return (4);
5429	case BWN_CCK_RATE_5MB:
5430		return (11);
5431	case BWN_CCK_RATE_11MB:
5432		return (22);
5433	case BWN_OFDM_RATE_6MB:
5434		return (12);
5435	case BWN_OFDM_RATE_9MB:
5436		return (18);
5437	case BWN_OFDM_RATE_12MB:
5438		return (24);
5439	case BWN_OFDM_RATE_18MB:
5440		return (36);
5441	case BWN_OFDM_RATE_24MB:
5442		return (48);
5443	case BWN_OFDM_RATE_36MB:
5444		return (72);
5445	case BWN_OFDM_RATE_48MB:
5446		return (96);
5447	case BWN_OFDM_RATE_54MB:
5448		return (108);
5449	default:
5450		printf("Ooops\n");
5451		return (0);
5452	}
5453}
5454
5455/*
5456 * Post process the RX provided RSSI.
5457 *
5458 * Valid for A, B, G, LP PHYs.
5459 */
5460static int8_t
5461bwn_rx_rssi_calc(struct bwn_mac *mac, uint8_t in_rssi,
5462    int ofdm, int adjust_2053, int adjust_2050)
5463{
5464	struct bwn_phy *phy = &mac->mac_phy;
5465	struct bwn_phy_g *gphy = &phy->phy_g;
5466	int tmp;
5467
5468	switch (phy->rf_ver) {
5469	case 0x2050:
5470		if (ofdm) {
5471			tmp = in_rssi;
5472			if (tmp > 127)
5473				tmp -= 256;
5474			tmp = tmp * 73 / 64;
5475			if (adjust_2050)
5476				tmp += 25;
5477			else
5478				tmp -= 3;
5479		} else {
5480			if (siba_sprom_get_bf_lo(mac->mac_sc->sc_dev)
5481			    & BWN_BFL_RSSI) {
5482				if (in_rssi > 63)
5483					in_rssi = 63;
5484				tmp = gphy->pg_nrssi_lt[in_rssi];
5485				tmp = (31 - tmp) * -131 / 128 - 57;
5486			} else {
5487				tmp = in_rssi;
5488				tmp = (31 - tmp) * -149 / 128 - 68;
5489			}
5490			if (phy->type == BWN_PHYTYPE_G && adjust_2050)
5491				tmp += 25;
5492		}
5493		break;
5494	case 0x2060:
5495		if (in_rssi > 127)
5496			tmp = in_rssi - 256;
5497		else
5498			tmp = in_rssi;
5499		break;
5500	default:
5501		tmp = in_rssi;
5502		tmp = (tmp - 11) * 103 / 64;
5503		if (adjust_2053)
5504			tmp -= 109;
5505		else
5506			tmp -= 83;
5507	}
5508
5509	return (tmp);
5510}
5511
5512static void
5513bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
5514{
5515	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
5516	struct bwn_plcp6 *plcp;
5517	struct bwn_softc *sc = mac->mac_sc;
5518	struct ieee80211_frame_min *wh;
5519	struct ieee80211_node *ni;
5520	struct ieee80211com *ic = &sc->sc_ic;
5521	uint32_t macstat;
5522	int padding, rate, rssi = 0, noise = 0, type;
5523	uint16_t phytype, phystat0, phystat3, chanstat;
5524	unsigned char *mp = mtod(m, unsigned char *);
5525	static int rx_mac_dec_rpt = 0;
5526
5527	BWN_ASSERT_LOCKED(sc);
5528
5529	phystat0 = le16toh(rxhdr->phy_status0);
5530	phystat3 = le16toh(rxhdr->phy_status3);
5531
5532	/* XXX Note: mactime, macstat, chanstat need fixing for fw 598 */
5533	macstat = le32toh(rxhdr->mac_status);
5534	chanstat = le16toh(rxhdr->channel);
5535
5536	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
5537
5538	if (macstat & BWN_RX_MAC_FCSERR)
5539		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
5540	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
5541		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
5542	if (macstat & BWN_RX_MAC_DECERR)
5543		goto drop;
5544
5545	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5546	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
5547		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5548		    m->m_pkthdr.len);
5549		goto drop;
5550	}
5551	plcp = (struct bwn_plcp6 *)(mp + padding);
5552	m_adj(m, sizeof(struct bwn_plcp6) + padding);
5553	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
5554		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5555		    m->m_pkthdr.len);
5556		goto drop;
5557	}
5558	wh = mtod(m, struct ieee80211_frame_min *);
5559
5560	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
5561		device_printf(sc->sc_dev,
5562		    "RX decryption attempted (old %d keyidx %#x)\n",
5563		    BWN_ISOLDFMT(mac),
5564		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
5565
5566	if (phystat0 & BWN_RX_PHYST0_OFDM)
5567		rate = bwn_plcp_get_ofdmrate(mac, plcp,
5568		    phytype == BWN_PHYTYPE_A);
5569	else
5570		rate = bwn_plcp_get_cckrate(mac, plcp);
5571	if (rate == -1) {
5572		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
5573			goto drop;
5574	}
5575	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
5576
5577	/* rssi/noise */
5578	switch (phytype) {
5579	case BWN_PHYTYPE_A:
5580	case BWN_PHYTYPE_B:
5581	case BWN_PHYTYPE_G:
5582	case BWN_PHYTYPE_LP:
5583		rssi = bwn_rx_rssi_calc(mac, rxhdr->phy.abg.rssi,
5584		    !! (phystat0 & BWN_RX_PHYST0_OFDM),
5585		    !! (phystat0 & BWN_RX_PHYST0_GAINCTL),
5586		    !! (phystat3 & BWN_RX_PHYST3_TRSTATE));
5587		break;
5588	default:
5589		/* XXX TODO: implement rssi for other PHYs */
5590		break;
5591	}
5592
5593	noise = mac->mac_stats.link_noise;
5594
5595	/* RX radio tap */
5596	if (ieee80211_radiotap_active(ic))
5597		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
5598	m_adj(m, -IEEE80211_CRC_LEN);
5599
5600	BWN_UNLOCK(sc);
5601
5602	ni = ieee80211_find_rxnode(ic, wh);
5603	if (ni != NULL) {
5604		type = ieee80211_input(ni, m, rssi, noise);
5605		ieee80211_free_node(ni);
5606	} else
5607		type = ieee80211_input_all(ic, m, rssi, noise);
5608
5609	BWN_LOCK(sc);
5610	return;
5611drop:
5612	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
5613}
5614
5615static void
5616bwn_dma_handle_txeof(struct bwn_mac *mac,
5617    const struct bwn_txstatus *status)
5618{
5619	struct bwn_dma *dma = &mac->mac_method.dma;
5620	struct bwn_dma_ring *dr;
5621	struct bwn_dmadesc_generic *desc;
5622	struct bwn_dmadesc_meta *meta;
5623	struct bwn_softc *sc = mac->mac_sc;
5624	int slot;
5625	int retrycnt = 0;
5626
5627	BWN_ASSERT_LOCKED(sc);
5628
5629	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
5630	if (dr == NULL) {
5631		device_printf(sc->sc_dev, "failed to parse cookie\n");
5632		return;
5633	}
5634	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5635
5636	while (1) {
5637		KASSERT(slot >= 0 && slot < dr->dr_numslots,
5638		    ("%s:%d: fail", __func__, __LINE__));
5639		dr->getdesc(dr, slot, &desc, &meta);
5640
5641		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
5642			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
5643		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
5644			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
5645
5646		if (meta->mt_islast) {
5647			KASSERT(meta->mt_m != NULL,
5648			    ("%s:%d: fail", __func__, __LINE__));
5649
5650			/* Just count full frame retries for now */
5651			retrycnt = status->framecnt - 1;
5652			ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni,
5653			    status->ack ?
5654			      IEEE80211_RATECTL_TX_SUCCESS :
5655			      IEEE80211_RATECTL_TX_FAILURE,
5656			    &retrycnt, 0);
5657			ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
5658			meta->mt_ni = NULL;
5659			meta->mt_m = NULL;
5660		} else
5661			KASSERT(meta->mt_m == NULL,
5662			    ("%s:%d: fail", __func__, __LINE__));
5663
5664		dr->dr_usedslot--;
5665		if (meta->mt_islast)
5666			break;
5667		slot = bwn_dma_nextslot(dr, slot);
5668	}
5669	sc->sc_watchdog_timer = 0;
5670	if (dr->dr_stop) {
5671		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
5672		    ("%s:%d: fail", __func__, __LINE__));
5673		dr->dr_stop = 0;
5674	}
5675}
5676
5677static void
5678bwn_pio_handle_txeof(struct bwn_mac *mac,
5679    const struct bwn_txstatus *status)
5680{
5681	struct bwn_pio_txqueue *tq;
5682	struct bwn_pio_txpkt *tp = NULL;
5683	struct bwn_softc *sc = mac->mac_sc;
5684	int retrycnt = 0;
5685
5686	BWN_ASSERT_LOCKED(sc);
5687
5688	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
5689	if (tq == NULL)
5690		return;
5691
5692	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
5693	tq->tq_free++;
5694
5695	if (tp->tp_ni != NULL) {
5696		/*
5697		 * Do any tx complete callback.  Note this must
5698		 * be done before releasing the node reference.
5699		 */
5700
5701		/* Just count full frame retries for now */
5702		retrycnt = status->framecnt - 1;
5703		ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni,
5704		    status->ack ?
5705		      IEEE80211_RATECTL_TX_SUCCESS :
5706		      IEEE80211_RATECTL_TX_FAILURE,
5707		    &retrycnt, 0);
5708
5709		if (tp->tp_m->m_flags & M_TXCB)
5710			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
5711		ieee80211_free_node(tp->tp_ni);
5712		tp->tp_ni = NULL;
5713	}
5714	m_freem(tp->tp_m);
5715	tp->tp_m = NULL;
5716	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
5717
5718	sc->sc_watchdog_timer = 0;
5719}
5720
5721static void
5722bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
5723{
5724	struct bwn_softc *sc = mac->mac_sc;
5725	struct bwn_phy *phy = &mac->mac_phy;
5726	struct ieee80211com *ic = &sc->sc_ic;
5727	unsigned long now;
5728	int result;
5729
5730	BWN_GETTIME(now);
5731
5732	if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime))
5733		return;
5734	phy->nexttime = now + 2 * 1000;
5735
5736	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
5737	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
5738		return;
5739
5740	if (phy->recalc_txpwr != NULL) {
5741		result = phy->recalc_txpwr(mac,
5742		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
5743		if (result == BWN_TXPWR_RES_DONE)
5744			return;
5745		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
5746		    ("%s: fail", __func__));
5747		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
5748
5749		ieee80211_runtask(ic, &mac->mac_txpower);
5750	}
5751}
5752
5753static uint16_t
5754bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
5755{
5756
5757	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
5758}
5759
5760static uint32_t
5761bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
5762{
5763
5764	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
5765}
5766
5767static void
5768bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
5769{
5770
5771	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
5772}
5773
5774static void
5775bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
5776{
5777
5778	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
5779}
5780
5781static int
5782bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
5783{
5784
5785	switch (rate) {
5786	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
5787	case 12:
5788		return (BWN_OFDM_RATE_6MB);
5789	case 18:
5790		return (BWN_OFDM_RATE_9MB);
5791	case 24:
5792		return (BWN_OFDM_RATE_12MB);
5793	case 36:
5794		return (BWN_OFDM_RATE_18MB);
5795	case 48:
5796		return (BWN_OFDM_RATE_24MB);
5797	case 72:
5798		return (BWN_OFDM_RATE_36MB);
5799	case 96:
5800		return (BWN_OFDM_RATE_48MB);
5801	case 108:
5802		return (BWN_OFDM_RATE_54MB);
5803	/* CCK rates (NB: not IEEE std, device-specific) */
5804	case 2:
5805		return (BWN_CCK_RATE_1MB);
5806	case 4:
5807		return (BWN_CCK_RATE_2MB);
5808	case 11:
5809		return (BWN_CCK_RATE_5MB);
5810	case 22:
5811		return (BWN_CCK_RATE_11MB);
5812	}
5813
5814	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
5815	return (BWN_CCK_RATE_1MB);
5816}
5817
5818static int
5819bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
5820    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
5821{
5822	const struct bwn_phy *phy = &mac->mac_phy;
5823	struct bwn_softc *sc = mac->mac_sc;
5824	struct ieee80211_frame *wh;
5825	struct ieee80211_frame *protwh;
5826	struct ieee80211_frame_cts *cts;
5827	struct ieee80211_frame_rts *rts;
5828	const struct ieee80211_txparam *tp;
5829	struct ieee80211vap *vap = ni->ni_vap;
5830	struct ieee80211com *ic = &sc->sc_ic;
5831	struct mbuf *mprot;
5832	unsigned int len;
5833	uint32_t macctl = 0;
5834	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
5835	uint16_t phyctl = 0;
5836	uint8_t rate, rate_fb;
5837
5838	wh = mtod(m, struct ieee80211_frame *);
5839	memset(txhdr, 0, sizeof(*txhdr));
5840
5841	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
5842	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
5843	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
5844
5845	/*
5846	 * Find TX rate
5847	 */
5848	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
5849	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
5850		rate = rate_fb = tp->mgmtrate;
5851	else if (ismcast)
5852		rate = rate_fb = tp->mcastrate;
5853	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
5854		rate = rate_fb = tp->ucastrate;
5855	else {
5856		/* XXX TODO: don't fall back to CCK rates for OFDM */
5857		rix = ieee80211_ratectl_rate(ni, NULL, 0);
5858		rate = ni->ni_txrate;
5859
5860		if (rix > 0)
5861			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
5862			    IEEE80211_RATE_VAL;
5863		else
5864			rate_fb = rate;
5865	}
5866
5867	sc->sc_tx_rate = rate;
5868
5869	/* Note: this maps the select ieee80211 rate to hardware rate */
5870	rate = bwn_ieeerate2hwrate(sc, rate);
5871	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
5872
5873	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
5874	    bwn_plcp_getcck(rate);
5875	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
5876	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
5877
5878	/* XXX rate/rate_fb is the hardware rate */
5879	if ((rate_fb == rate) ||
5880	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
5881	    (*(u_int16_t *)wh->i_dur == htole16(0)))
5882		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
5883	else
5884		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
5885		    m->m_pkthdr.len, rate, isshort);
5886
5887	/* XXX TX encryption */
5888	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
5889	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
5890	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
5891	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
5892	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
5893	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
5894
5895	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
5896	    BWN_TX_EFT_FB_CCK;
5897	txhdr->chan = phy->chan;
5898	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
5899	    BWN_TX_PHY_ENC_CCK;
5900	/* XXX preamble? obey net80211 */
5901	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
5902	     rate == BWN_CCK_RATE_11MB))
5903		phyctl |= BWN_TX_PHY_SHORTPRMBL;
5904
5905	/* XXX TX antenna selection */
5906
5907	switch (bwn_antenna_sanitize(mac, 0)) {
5908	case 0:
5909		phyctl |= BWN_TX_PHY_ANT01AUTO;
5910		break;
5911	case 1:
5912		phyctl |= BWN_TX_PHY_ANT0;
5913		break;
5914	case 2:
5915		phyctl |= BWN_TX_PHY_ANT1;
5916		break;
5917	case 3:
5918		phyctl |= BWN_TX_PHY_ANT2;
5919		break;
5920	case 4:
5921		phyctl |= BWN_TX_PHY_ANT3;
5922		break;
5923	default:
5924		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5925	}
5926
5927	if (!ismcast)
5928		macctl |= BWN_TX_MAC_ACK;
5929
5930	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
5931	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
5932	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
5933		macctl |= BWN_TX_MAC_LONGFRAME;
5934
5935	if (ic->ic_flags & IEEE80211_F_USEPROT) {
5936		/* XXX RTS rate is always 1MB??? */
5937		/* XXX TODO: don't fall back to CCK rates for OFDM */
5938		rts_rate = BWN_CCK_RATE_1MB;
5939		rts_rate_fb = bwn_get_fbrate(rts_rate);
5940
5941		/* XXX 'rate' here is hardware rate now, not the net80211 rate */
5942		protdur = ieee80211_compute_duration(ic->ic_rt,
5943		    m->m_pkthdr.len, rate, isshort) +
5944		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
5945
5946		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
5947			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
5948			    (txhdr->body.old.rts_frame) :
5949			    (txhdr->body.new.rts_frame));
5950			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
5951			    protdur);
5952			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
5953			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
5954			    mprot->m_pkthdr.len);
5955			m_freem(mprot);
5956			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
5957			len = sizeof(struct ieee80211_frame_cts);
5958		} else {
5959			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
5960			    (txhdr->body.old.rts_frame) :
5961			    (txhdr->body.new.rts_frame));
5962			/* XXX rate/rate_fb is the hardware rate */
5963			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
5964			    isshort);
5965			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
5966			    wh->i_addr2, protdur);
5967			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
5968			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
5969			    mprot->m_pkthdr.len);
5970			m_freem(mprot);
5971			macctl |= BWN_TX_MAC_SEND_RTSCTS;
5972			len = sizeof(struct ieee80211_frame_rts);
5973		}
5974		len += IEEE80211_CRC_LEN;
5975		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
5976		    &txhdr->body.old.rts_plcp :
5977		    &txhdr->body.new.rts_plcp), len, rts_rate);
5978		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
5979		    rts_rate_fb);
5980
5981		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
5982		    (&txhdr->body.old.rts_frame) :
5983		    (&txhdr->body.new.rts_frame));
5984		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
5985
5986		if (BWN_ISOFDMRATE(rts_rate)) {
5987			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
5988			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
5989		} else {
5990			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
5991			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
5992		}
5993		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
5994		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
5995	}
5996
5997	if (BWN_ISOLDFMT(mac))
5998		txhdr->body.old.cookie = htole16(cookie);
5999	else
6000		txhdr->body.new.cookie = htole16(cookie);
6001
6002	txhdr->macctl = htole32(macctl);
6003	txhdr->phyctl = htole16(phyctl);
6004
6005	/*
6006	 * TX radio tap
6007	 */
6008	if (ieee80211_radiotap_active_vap(vap)) {
6009		sc->sc_tx_th.wt_flags = 0;
6010		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6011			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
6012		if (isshort &&
6013		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6014		     rate == BWN_CCK_RATE_11MB))
6015			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6016		sc->sc_tx_th.wt_rate = rate;
6017
6018		ieee80211_radiotap_tx(vap, m);
6019	}
6020
6021	return (0);
6022}
6023
6024static void
6025bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
6026    const uint8_t rate)
6027{
6028	uint32_t d, plen;
6029	uint8_t *raw = plcp->o.raw;
6030
6031	if (BWN_ISOFDMRATE(rate)) {
6032		d = bwn_plcp_getofdm(rate);
6033		KASSERT(!(octets & 0xf000),
6034		    ("%s:%d: fail", __func__, __LINE__));
6035		d |= (octets << 5);
6036		plcp->o.data = htole32(d);
6037	} else {
6038		plen = octets * 16 / rate;
6039		if ((octets * 16 % rate) > 0) {
6040			plen++;
6041			if ((rate == BWN_CCK_RATE_11MB)
6042			    && ((octets * 8 % 11) < 4)) {
6043				raw[1] = 0x84;
6044			} else
6045				raw[1] = 0x04;
6046		} else
6047			raw[1] = 0x04;
6048		plcp->o.data |= htole32(plen << 16);
6049		raw[0] = bwn_plcp_getcck(rate);
6050	}
6051}
6052
6053static uint8_t
6054bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
6055{
6056	struct bwn_softc *sc = mac->mac_sc;
6057	uint8_t mask;
6058
6059	if (n == 0)
6060		return (0);
6061	if (mac->mac_phy.gmode)
6062		mask = siba_sprom_get_ant_bg(sc->sc_dev);
6063	else
6064		mask = siba_sprom_get_ant_a(sc->sc_dev);
6065	if (!(mask & (1 << (n - 1))))
6066		return (0);
6067	return (n);
6068}
6069
6070/*
6071 * Return a fallback rate for the given rate.
6072 *
6073 * Note: Don't fall back from OFDM to CCK.
6074 */
6075static uint8_t
6076bwn_get_fbrate(uint8_t bitrate)
6077{
6078	switch (bitrate) {
6079	/* CCK */
6080	case BWN_CCK_RATE_1MB:
6081		return (BWN_CCK_RATE_1MB);
6082	case BWN_CCK_RATE_2MB:
6083		return (BWN_CCK_RATE_1MB);
6084	case BWN_CCK_RATE_5MB:
6085		return (BWN_CCK_RATE_2MB);
6086	case BWN_CCK_RATE_11MB:
6087		return (BWN_CCK_RATE_5MB);
6088
6089	/* OFDM */
6090	case BWN_OFDM_RATE_6MB:
6091		return (BWN_OFDM_RATE_6MB);
6092	case BWN_OFDM_RATE_9MB:
6093		return (BWN_OFDM_RATE_6MB);
6094	case BWN_OFDM_RATE_12MB:
6095		return (BWN_OFDM_RATE_9MB);
6096	case BWN_OFDM_RATE_18MB:
6097		return (BWN_OFDM_RATE_12MB);
6098	case BWN_OFDM_RATE_24MB:
6099		return (BWN_OFDM_RATE_18MB);
6100	case BWN_OFDM_RATE_36MB:
6101		return (BWN_OFDM_RATE_24MB);
6102	case BWN_OFDM_RATE_48MB:
6103		return (BWN_OFDM_RATE_36MB);
6104	case BWN_OFDM_RATE_54MB:
6105		return (BWN_OFDM_RATE_48MB);
6106	}
6107	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6108	return (0);
6109}
6110
6111static uint32_t
6112bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6113    uint32_t ctl, const void *_data, int len)
6114{
6115	struct bwn_softc *sc = mac->mac_sc;
6116	uint32_t value = 0;
6117	const uint8_t *data = _data;
6118
6119	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
6120	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
6121	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6122
6123	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
6124	    tq->tq_base + BWN_PIO8_TXDATA);
6125	if (len & 3) {
6126		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
6127		    BWN_PIO8_TXCTL_24_31);
6128		data = &(data[len - 1]);
6129		switch (len & 3) {
6130		case 3:
6131			ctl |= BWN_PIO8_TXCTL_16_23;
6132			value |= (uint32_t)(*data) << 16;
6133			data--;
6134		case 2:
6135			ctl |= BWN_PIO8_TXCTL_8_15;
6136			value |= (uint32_t)(*data) << 8;
6137			data--;
6138		case 1:
6139			value |= (uint32_t)(*data);
6140		}
6141		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6142		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
6143	}
6144
6145	return (ctl);
6146}
6147
6148static void
6149bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6150    uint16_t offset, uint32_t value)
6151{
6152
6153	BWN_WRITE_4(mac, tq->tq_base + offset, value);
6154}
6155
6156static uint16_t
6157bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6158    uint16_t ctl, const void *_data, int len)
6159{
6160	struct bwn_softc *sc = mac->mac_sc;
6161	const uint8_t *data = _data;
6162
6163	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6164	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6165
6166	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
6167	    tq->tq_base + BWN_PIO_TXDATA);
6168	if (len & 1) {
6169		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6170		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6171		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
6172	}
6173
6174	return (ctl);
6175}
6176
6177static uint16_t
6178bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6179    uint16_t ctl, struct mbuf *m0)
6180{
6181	int i, j = 0;
6182	uint16_t data = 0;
6183	const uint8_t *buf;
6184	struct mbuf *m = m0;
6185
6186	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6187	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6188
6189	for (; m != NULL; m = m->m_next) {
6190		buf = mtod(m, const uint8_t *);
6191		for (i = 0; i < m->m_len; i++) {
6192			if (!((j++) % 2))
6193				data |= buf[i];
6194			else {
6195				data |= (buf[i] << 8);
6196				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6197				data = 0;
6198			}
6199		}
6200	}
6201	if (m0->m_pkthdr.len % 2) {
6202		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6203		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6204		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6205	}
6206
6207	return (ctl);
6208}
6209
6210static void
6211bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
6212{
6213
6214	if (mac->mac_phy.type != BWN_PHYTYPE_G)
6215		return;
6216	BWN_WRITE_2(mac, 0x684, 510 + time);
6217	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
6218}
6219
6220static struct bwn_dma_ring *
6221bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
6222{
6223
6224	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
6225		return (mac->mac_method.dma.wme[WME_AC_BE]);
6226
6227	switch (prio) {
6228	case 3:
6229		return (mac->mac_method.dma.wme[WME_AC_VO]);
6230	case 2:
6231		return (mac->mac_method.dma.wme[WME_AC_VI]);
6232	case 0:
6233		return (mac->mac_method.dma.wme[WME_AC_BE]);
6234	case 1:
6235		return (mac->mac_method.dma.wme[WME_AC_BK]);
6236	}
6237	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6238	return (NULL);
6239}
6240
6241static int
6242bwn_dma_getslot(struct bwn_dma_ring *dr)
6243{
6244	int slot;
6245
6246	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
6247
6248	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
6249	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
6250	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
6251
6252	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
6253	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
6254	dr->dr_curslot = slot;
6255	dr->dr_usedslot++;
6256
6257	return (slot);
6258}
6259
6260static struct bwn_pio_txqueue *
6261bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
6262    struct bwn_pio_txpkt **pack)
6263{
6264	struct bwn_pio *pio = &mac->mac_method.pio;
6265	struct bwn_pio_txqueue *tq = NULL;
6266	unsigned int index;
6267
6268	switch (cookie & 0xf000) {
6269	case 0x1000:
6270		tq = &pio->wme[WME_AC_BK];
6271		break;
6272	case 0x2000:
6273		tq = &pio->wme[WME_AC_BE];
6274		break;
6275	case 0x3000:
6276		tq = &pio->wme[WME_AC_VI];
6277		break;
6278	case 0x4000:
6279		tq = &pio->wme[WME_AC_VO];
6280		break;
6281	case 0x5000:
6282		tq = &pio->mcast;
6283		break;
6284	}
6285	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
6286	if (tq == NULL)
6287		return (NULL);
6288	index = (cookie & 0x0fff);
6289	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
6290	if (index >= N(tq->tq_pkts))
6291		return (NULL);
6292	*pack = &tq->tq_pkts[index];
6293	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
6294	return (tq);
6295}
6296
6297static void
6298bwn_txpwr(void *arg, int npending)
6299{
6300	struct bwn_mac *mac = arg;
6301	struct bwn_softc *sc = mac->mac_sc;
6302
6303	BWN_LOCK(sc);
6304	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
6305	    mac->mac_phy.set_txpwr != NULL)
6306		mac->mac_phy.set_txpwr(mac);
6307	BWN_UNLOCK(sc);
6308}
6309
6310static void
6311bwn_task_15s(struct bwn_mac *mac)
6312{
6313	uint16_t reg;
6314
6315	if (mac->mac_fw.opensource) {
6316		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
6317		if (reg) {
6318			bwn_restart(mac, "fw watchdog");
6319			return;
6320		}
6321		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
6322	}
6323	if (mac->mac_phy.task_15s)
6324		mac->mac_phy.task_15s(mac);
6325
6326	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
6327}
6328
6329static void
6330bwn_task_30s(struct bwn_mac *mac)
6331{
6332
6333	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
6334		return;
6335	mac->mac_noise.noi_running = 1;
6336	mac->mac_noise.noi_nsamples = 0;
6337
6338	bwn_noise_gensample(mac);
6339}
6340
6341static void
6342bwn_task_60s(struct bwn_mac *mac)
6343{
6344
6345	if (mac->mac_phy.task_60s)
6346		mac->mac_phy.task_60s(mac);
6347	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
6348}
6349
6350static void
6351bwn_tasks(void *arg)
6352{
6353	struct bwn_mac *mac = arg;
6354	struct bwn_softc *sc = mac->mac_sc;
6355
6356	BWN_ASSERT_LOCKED(sc);
6357	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
6358		return;
6359
6360	if (mac->mac_task_state % 4 == 0)
6361		bwn_task_60s(mac);
6362	if (mac->mac_task_state % 2 == 0)
6363		bwn_task_30s(mac);
6364	bwn_task_15s(mac);
6365
6366	mac->mac_task_state++;
6367	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
6368}
6369
6370static int
6371bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
6372{
6373	struct bwn_softc *sc = mac->mac_sc;
6374
6375	KASSERT(a == 0, ("not support APHY\n"));
6376
6377	switch (plcp->o.raw[0] & 0xf) {
6378	case 0xb:
6379		return (BWN_OFDM_RATE_6MB);
6380	case 0xf:
6381		return (BWN_OFDM_RATE_9MB);
6382	case 0xa:
6383		return (BWN_OFDM_RATE_12MB);
6384	case 0xe:
6385		return (BWN_OFDM_RATE_18MB);
6386	case 0x9:
6387		return (BWN_OFDM_RATE_24MB);
6388	case 0xd:
6389		return (BWN_OFDM_RATE_36MB);
6390	case 0x8:
6391		return (BWN_OFDM_RATE_48MB);
6392	case 0xc:
6393		return (BWN_OFDM_RATE_54MB);
6394	}
6395	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
6396	    plcp->o.raw[0] & 0xf);
6397	return (-1);
6398}
6399
6400static int
6401bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
6402{
6403	struct bwn_softc *sc = mac->mac_sc;
6404
6405	switch (plcp->o.raw[0]) {
6406	case 0x0a:
6407		return (BWN_CCK_RATE_1MB);
6408	case 0x14:
6409		return (BWN_CCK_RATE_2MB);
6410	case 0x37:
6411		return (BWN_CCK_RATE_5MB);
6412	case 0x6e:
6413		return (BWN_CCK_RATE_11MB);
6414	}
6415	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
6416	return (-1);
6417}
6418
6419static void
6420bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
6421    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
6422    int rssi, int noise)
6423{
6424	struct bwn_softc *sc = mac->mac_sc;
6425	const struct ieee80211_frame_min *wh;
6426	uint64_t tsf;
6427	uint16_t low_mactime_now;
6428
6429	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
6430		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6431
6432	wh = mtod(m, const struct ieee80211_frame_min *);
6433	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6434		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
6435
6436	bwn_tsf_read(mac, &tsf);
6437	low_mactime_now = tsf;
6438	tsf = tsf & ~0xffffULL;
6439	tsf += le16toh(rxhdr->mac_time);
6440	if (low_mactime_now < le16toh(rxhdr->mac_time))
6441		tsf -= 0x10000;
6442
6443	sc->sc_rx_th.wr_tsf = tsf;
6444	sc->sc_rx_th.wr_rate = rate;
6445	sc->sc_rx_th.wr_antsignal = rssi;
6446	sc->sc_rx_th.wr_antnoise = noise;
6447}
6448
6449static void
6450bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
6451{
6452	uint32_t low, high;
6453
6454	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
6455	    ("%s:%d: fail", __func__, __LINE__));
6456
6457	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
6458	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
6459	*tsf = high;
6460	*tsf <<= 32;
6461	*tsf |= low;
6462}
6463
6464static int
6465bwn_dma_attach(struct bwn_mac *mac)
6466{
6467	struct bwn_dma *dma = &mac->mac_method.dma;
6468	struct bwn_softc *sc = mac->mac_sc;
6469	bus_addr_t lowaddr = 0;
6470	int error;
6471
6472	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
6473		return (0);
6474
6475	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
6476
6477	mac->mac_flags |= BWN_MAC_FLAG_DMA;
6478
6479	dma->dmatype = bwn_dma_gettype(mac);
6480	if (dma->dmatype == BWN_DMA_30BIT)
6481		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
6482	else if (dma->dmatype == BWN_DMA_32BIT)
6483		lowaddr = BUS_SPACE_MAXADDR_32BIT;
6484	else
6485		lowaddr = BUS_SPACE_MAXADDR;
6486
6487	/*
6488	 * Create top level DMA tag
6489	 */
6490	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
6491			       BWN_ALIGN, 0,		/* alignment, bounds */
6492			       lowaddr,			/* lowaddr */
6493			       BUS_SPACE_MAXADDR,	/* highaddr */
6494			       NULL, NULL,		/* filter, filterarg */
6495			       BUS_SPACE_MAXSIZE,	/* maxsize */
6496			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
6497			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
6498			       0,			/* flags */
6499			       NULL, NULL,		/* lockfunc, lockarg */
6500			       &dma->parent_dtag);
6501	if (error) {
6502		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
6503		return (error);
6504	}
6505
6506	/*
6507	 * Create TX/RX mbuf DMA tag
6508	 */
6509	error = bus_dma_tag_create(dma->parent_dtag,
6510				1,
6511				0,
6512				BUS_SPACE_MAXADDR,
6513				BUS_SPACE_MAXADDR,
6514				NULL, NULL,
6515				MCLBYTES,
6516				1,
6517				BUS_SPACE_MAXSIZE_32BIT,
6518				0,
6519				NULL, NULL,
6520				&dma->rxbuf_dtag);
6521	if (error) {
6522		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6523		goto fail0;
6524	}
6525	error = bus_dma_tag_create(dma->parent_dtag,
6526				1,
6527				0,
6528				BUS_SPACE_MAXADDR,
6529				BUS_SPACE_MAXADDR,
6530				NULL, NULL,
6531				MCLBYTES,
6532				1,
6533				BUS_SPACE_MAXSIZE_32BIT,
6534				0,
6535				NULL, NULL,
6536				&dma->txbuf_dtag);
6537	if (error) {
6538		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6539		goto fail1;
6540	}
6541
6542	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
6543	if (!dma->wme[WME_AC_BK])
6544		goto fail2;
6545
6546	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
6547	if (!dma->wme[WME_AC_BE])
6548		goto fail3;
6549
6550	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
6551	if (!dma->wme[WME_AC_VI])
6552		goto fail4;
6553
6554	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
6555	if (!dma->wme[WME_AC_VO])
6556		goto fail5;
6557
6558	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
6559	if (!dma->mcast)
6560		goto fail6;
6561	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
6562	if (!dma->rx)
6563		goto fail7;
6564
6565	return (error);
6566
6567fail7:	bwn_dma_ringfree(&dma->mcast);
6568fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
6569fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
6570fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
6571fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
6572fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
6573fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
6574fail0:	bus_dma_tag_destroy(dma->parent_dtag);
6575	return (error);
6576}
6577
6578static struct bwn_dma_ring *
6579bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
6580    uint16_t cookie, int *slot)
6581{
6582	struct bwn_dma *dma = &mac->mac_method.dma;
6583	struct bwn_dma_ring *dr;
6584	struct bwn_softc *sc = mac->mac_sc;
6585
6586	BWN_ASSERT_LOCKED(mac->mac_sc);
6587
6588	switch (cookie & 0xf000) {
6589	case 0x1000:
6590		dr = dma->wme[WME_AC_BK];
6591		break;
6592	case 0x2000:
6593		dr = dma->wme[WME_AC_BE];
6594		break;
6595	case 0x3000:
6596		dr = dma->wme[WME_AC_VI];
6597		break;
6598	case 0x4000:
6599		dr = dma->wme[WME_AC_VO];
6600		break;
6601	case 0x5000:
6602		dr = dma->mcast;
6603		break;
6604	default:
6605		dr = NULL;
6606		KASSERT(0 == 1,
6607		    ("invalid cookie value %d", cookie & 0xf000));
6608	}
6609	*slot = (cookie & 0x0fff);
6610	if (*slot < 0 || *slot >= dr->dr_numslots) {
6611		/*
6612		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
6613		 * that it occurs events which have same H/W sequence numbers.
6614		 * When it's occurred just prints a WARNING msgs and ignores.
6615		 */
6616		KASSERT(status->seq == dma->lastseq,
6617		    ("%s:%d: fail", __func__, __LINE__));
6618		device_printf(sc->sc_dev,
6619		    "out of slot ranges (0 < %d < %d)\n", *slot,
6620		    dr->dr_numslots);
6621		return (NULL);
6622	}
6623	dma->lastseq = status->seq;
6624	return (dr);
6625}
6626
6627static void
6628bwn_dma_stop(struct bwn_mac *mac)
6629{
6630	struct bwn_dma *dma;
6631
6632	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
6633		return;
6634	dma = &mac->mac_method.dma;
6635
6636	bwn_dma_ringstop(&dma->rx);
6637	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
6638	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
6639	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
6640	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
6641	bwn_dma_ringstop(&dma->mcast);
6642}
6643
6644static void
6645bwn_dma_ringstop(struct bwn_dma_ring **dr)
6646{
6647
6648	if (dr == NULL)
6649		return;
6650
6651	bwn_dma_cleanup(*dr);
6652}
6653
6654static void
6655bwn_pio_stop(struct bwn_mac *mac)
6656{
6657	struct bwn_pio *pio;
6658
6659	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
6660		return;
6661	pio = &mac->mac_method.pio;
6662
6663	bwn_destroy_queue_tx(&pio->mcast);
6664	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
6665	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
6666	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
6667	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
6668}
6669
6670static void
6671bwn_led_attach(struct bwn_mac *mac)
6672{
6673	struct bwn_softc *sc = mac->mac_sc;
6674	const uint8_t *led_act = NULL;
6675	uint16_t val[BWN_LED_MAX];
6676	int i;
6677
6678	sc->sc_led_idle = (2350 * hz) / 1000;
6679	sc->sc_led_blink = 1;
6680
6681	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
6682		if (siba_get_pci_subvendor(sc->sc_dev) ==
6683		    bwn_vendor_led_act[i].vid) {
6684			led_act = bwn_vendor_led_act[i].led_act;
6685			break;
6686		}
6687	}
6688	if (led_act == NULL)
6689		led_act = bwn_default_led_act;
6690
6691	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
6692	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
6693	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
6694	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
6695
6696	for (i = 0; i < BWN_LED_MAX; ++i) {
6697		struct bwn_led *led = &sc->sc_leds[i];
6698
6699		if (val[i] == 0xff) {
6700			led->led_act = led_act[i];
6701		} else {
6702			if (val[i] & BWN_LED_ACT_LOW)
6703				led->led_flags |= BWN_LED_F_ACTLOW;
6704			led->led_act = val[i] & BWN_LED_ACT_MASK;
6705		}
6706		led->led_mask = (1 << i);
6707
6708		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
6709		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
6710		    led->led_act == BWN_LED_ACT_BLINK) {
6711			led->led_flags |= BWN_LED_F_BLINK;
6712			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
6713				led->led_flags |= BWN_LED_F_POLLABLE;
6714			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
6715				led->led_flags |= BWN_LED_F_SLOW;
6716
6717			if (sc->sc_blink_led == NULL) {
6718				sc->sc_blink_led = led;
6719				if (led->led_flags & BWN_LED_F_SLOW)
6720					BWN_LED_SLOWDOWN(sc->sc_led_idle);
6721			}
6722		}
6723
6724		DPRINTF(sc, BWN_DEBUG_LED,
6725		    "%dth led, act %d, lowact %d\n", i,
6726		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
6727	}
6728	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
6729}
6730
6731static __inline uint16_t
6732bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
6733{
6734
6735	if (led->led_flags & BWN_LED_F_ACTLOW)
6736		on = !on;
6737	if (on)
6738		val |= led->led_mask;
6739	else
6740		val &= ~led->led_mask;
6741	return val;
6742}
6743
6744static void
6745bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
6746{
6747	struct bwn_softc *sc = mac->mac_sc;
6748	struct ieee80211com *ic = &sc->sc_ic;
6749	uint16_t val;
6750	int i;
6751
6752	if (nstate == IEEE80211_S_INIT) {
6753		callout_stop(&sc->sc_led_blink_ch);
6754		sc->sc_led_blinking = 0;
6755	}
6756
6757	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
6758		return;
6759
6760	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
6761	for (i = 0; i < BWN_LED_MAX; ++i) {
6762		struct bwn_led *led = &sc->sc_leds[i];
6763		int on;
6764
6765		if (led->led_act == BWN_LED_ACT_UNKN ||
6766		    led->led_act == BWN_LED_ACT_NULL)
6767			continue;
6768
6769		if ((led->led_flags & BWN_LED_F_BLINK) &&
6770		    nstate != IEEE80211_S_INIT)
6771			continue;
6772
6773		switch (led->led_act) {
6774		case BWN_LED_ACT_ON:    /* Always on */
6775			on = 1;
6776			break;
6777		case BWN_LED_ACT_OFF:   /* Always off */
6778		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
6779			on = 0;
6780			break;
6781		default:
6782			on = 1;
6783			switch (nstate) {
6784			case IEEE80211_S_INIT:
6785				on = 0;
6786				break;
6787			case IEEE80211_S_RUN:
6788				if (led->led_act == BWN_LED_ACT_11G &&
6789				    ic->ic_curmode != IEEE80211_MODE_11G)
6790					on = 0;
6791				break;
6792			default:
6793				if (led->led_act == BWN_LED_ACT_ASSOC)
6794					on = 0;
6795				break;
6796			}
6797			break;
6798		}
6799
6800		val = bwn_led_onoff(led, val, on);
6801	}
6802	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
6803}
6804
6805static void
6806bwn_led_event(struct bwn_mac *mac, int event)
6807{
6808	struct bwn_softc *sc = mac->mac_sc;
6809	struct bwn_led *led = sc->sc_blink_led;
6810	int rate;
6811
6812	if (event == BWN_LED_EVENT_POLL) {
6813		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
6814			return;
6815		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
6816			return;
6817	}
6818
6819	sc->sc_led_ticks = ticks;
6820	if (sc->sc_led_blinking)
6821		return;
6822
6823	switch (event) {
6824	case BWN_LED_EVENT_RX:
6825		rate = sc->sc_rx_rate;
6826		break;
6827	case BWN_LED_EVENT_TX:
6828		rate = sc->sc_tx_rate;
6829		break;
6830	case BWN_LED_EVENT_POLL:
6831		rate = 0;
6832		break;
6833	default:
6834		panic("unknown LED event %d\n", event);
6835		break;
6836	}
6837	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
6838	    bwn_led_duration[rate].off_dur);
6839}
6840
6841static void
6842bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
6843{
6844	struct bwn_softc *sc = mac->mac_sc;
6845	struct bwn_led *led = sc->sc_blink_led;
6846	uint16_t val;
6847
6848	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
6849	val = bwn_led_onoff(led, val, 1);
6850	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
6851
6852	if (led->led_flags & BWN_LED_F_SLOW) {
6853		BWN_LED_SLOWDOWN(on_dur);
6854		BWN_LED_SLOWDOWN(off_dur);
6855	}
6856
6857	sc->sc_led_blinking = 1;
6858	sc->sc_led_blink_offdur = off_dur;
6859
6860	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
6861}
6862
6863static void
6864bwn_led_blink_next(void *arg)
6865{
6866	struct bwn_mac *mac = arg;
6867	struct bwn_softc *sc = mac->mac_sc;
6868	uint16_t val;
6869
6870	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
6871	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
6872	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
6873
6874	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
6875	    bwn_led_blink_end, mac);
6876}
6877
6878static void
6879bwn_led_blink_end(void *arg)
6880{
6881	struct bwn_mac *mac = arg;
6882	struct bwn_softc *sc = mac->mac_sc;
6883
6884	sc->sc_led_blinking = 0;
6885}
6886
6887static int
6888bwn_suspend(device_t dev)
6889{
6890	struct bwn_softc *sc = device_get_softc(dev);
6891
6892	BWN_LOCK(sc);
6893	bwn_stop(sc);
6894	BWN_UNLOCK(sc);
6895	return (0);
6896}
6897
6898static int
6899bwn_resume(device_t dev)
6900{
6901	struct bwn_softc *sc = device_get_softc(dev);
6902	int error = EDOOFUS;
6903
6904	BWN_LOCK(sc);
6905	if (sc->sc_ic.ic_nrunning > 0)
6906		error = bwn_init(sc);
6907	BWN_UNLOCK(sc);
6908	if (error == 0)
6909		ieee80211_start_all(&sc->sc_ic);
6910	return (0);
6911}
6912
6913static void
6914bwn_rfswitch(void *arg)
6915{
6916	struct bwn_softc *sc = arg;
6917	struct bwn_mac *mac = sc->sc_curmac;
6918	int cur = 0, prev = 0;
6919
6920	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
6921	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
6922
6923	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
6924		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
6925			& BWN_RF_HWENABLED_HI_MASK))
6926			cur = 1;
6927	} else {
6928		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
6929		    & BWN_RF_HWENABLED_LO_MASK)
6930			cur = 1;
6931	}
6932
6933	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
6934		prev = 1;
6935
6936	if (cur != prev) {
6937		if (cur)
6938			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
6939		else
6940			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
6941
6942		device_printf(sc->sc_dev,
6943		    "status of RF switch is changed to %s\n",
6944		    cur ? "ON" : "OFF");
6945		if (cur != mac->mac_phy.rf_on) {
6946			if (cur)
6947				bwn_rf_turnon(mac);
6948			else
6949				bwn_rf_turnoff(mac);
6950		}
6951	}
6952
6953	callout_schedule(&sc->sc_rfswitch_ch, hz);
6954}
6955
6956static void
6957bwn_sysctl_node(struct bwn_softc *sc)
6958{
6959	device_t dev = sc->sc_dev;
6960	struct bwn_mac *mac;
6961	struct bwn_stats *stats;
6962
6963	/* XXX assume that count of MAC is only 1. */
6964
6965	if ((mac = sc->sc_curmac) == NULL)
6966		return;
6967	stats = &mac->mac_stats;
6968
6969	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
6970	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
6971	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
6972	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
6973	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
6974	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
6975	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
6976	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
6977	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
6978
6979#ifdef BWN_DEBUG
6980	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
6981	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
6982	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
6983#endif
6984}
6985
6986static device_method_t bwn_methods[] = {
6987	/* Device interface */
6988	DEVMETHOD(device_probe,		bwn_probe),
6989	DEVMETHOD(device_attach,	bwn_attach),
6990	DEVMETHOD(device_detach,	bwn_detach),
6991	DEVMETHOD(device_suspend,	bwn_suspend),
6992	DEVMETHOD(device_resume,	bwn_resume),
6993	DEVMETHOD_END
6994};
6995static driver_t bwn_driver = {
6996	"bwn",
6997	bwn_methods,
6998	sizeof(struct bwn_softc)
6999};
7000static devclass_t bwn_devclass;
7001DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
7002MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
7003MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
7004MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
7005MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
7006MODULE_VERSION(bwn, 1);
7007