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