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