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