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