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