if_bwn.c revision 300076
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 300076 2016-05-17 20:21:39Z 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 turns off PHY A because it's not supported.
1220	 * Implement PHY-A support so we can use it for PHY-G
1221	 * dual-band support.
1222	 */
1223	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1224	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1225		device_printf(sc->sc_dev,
1226		    "%s: forcing 2GHz only; missing PHY-A support\n",
1227		    __func__);
1228		have_a = 0;
1229		have_bg = 1;
1230	}
1231
1232	mac->mac_phy.phy_n = NULL;
1233
1234	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1235		mac->mac_phy.attach = bwn_phy_g_attach;
1236		mac->mac_phy.detach = bwn_phy_g_detach;
1237		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1238		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1239		mac->mac_phy.init = bwn_phy_g_init;
1240		mac->mac_phy.exit = bwn_phy_g_exit;
1241		mac->mac_phy.phy_read = bwn_phy_g_read;
1242		mac->mac_phy.phy_write = bwn_phy_g_write;
1243		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1244		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1245		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1246		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1247		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1248		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1249		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1250		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1251		mac->mac_phy.set_im = bwn_phy_g_im;
1252		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1253		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1254		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1255		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1256	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1257		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1258		mac->mac_phy.init = bwn_phy_lp_init;
1259		mac->mac_phy.phy_read = bwn_phy_lp_read;
1260		mac->mac_phy.phy_write = bwn_phy_lp_write;
1261		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1262		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1263		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1264		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1265		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1266		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1267		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1268		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1269		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1270	} else if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1271		mac->mac_phy.attach = bwn_phy_n_attach;
1272		mac->mac_phy.detach = bwn_phy_n_detach;
1273		mac->mac_phy.prepare_hw = bwn_phy_n_prepare_hw;
1274		mac->mac_phy.init_pre = bwn_phy_n_init_pre;
1275		mac->mac_phy.init = bwn_phy_n_init;
1276		mac->mac_phy.exit = bwn_phy_n_exit;
1277		mac->mac_phy.phy_read = bwn_phy_n_read;
1278		mac->mac_phy.phy_write = bwn_phy_n_write;
1279		mac->mac_phy.rf_read = bwn_phy_n_rf_read;
1280		mac->mac_phy.rf_write = bwn_phy_n_rf_write;
1281		mac->mac_phy.use_hwpctl = bwn_phy_n_hwpctl;
1282		mac->mac_phy.rf_onoff = bwn_phy_n_rf_onoff;
1283		mac->mac_phy.switch_analog = bwn_phy_n_switch_analog;
1284		mac->mac_phy.switch_channel = bwn_phy_n_switch_channel;
1285		mac->mac_phy.get_default_chan = bwn_phy_n_get_default_chan;
1286		mac->mac_phy.set_antenna = bwn_phy_n_set_antenna;
1287		mac->mac_phy.set_im = bwn_phy_n_im;
1288		mac->mac_phy.recalc_txpwr = bwn_phy_n_recalc_txpwr;
1289		mac->mac_phy.set_txpwr = bwn_phy_n_set_txpwr;
1290		mac->mac_phy.task_15s = bwn_phy_n_task_15s;
1291		mac->mac_phy.task_60s = bwn_phy_n_task_60s;
1292	} else {
1293		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1294		    mac->mac_phy.type);
1295		error = ENXIO;
1296		goto fail;
1297	}
1298
1299	mac->mac_phy.gmode = have_bg;
1300	if (mac->mac_phy.attach != NULL) {
1301		error = mac->mac_phy.attach(mac);
1302		if (error) {
1303			device_printf(sc->sc_dev, "failed\n");
1304			goto fail;
1305		}
1306	}
1307
1308	bwn_reset_core(mac, have_bg);
1309
1310	error = bwn_chiptest(mac);
1311	if (error)
1312		goto fail;
1313	error = bwn_setup_channels(mac, have_bg, have_a);
1314	if (error) {
1315		device_printf(sc->sc_dev, "failed to setup channels\n");
1316		goto fail;
1317	}
1318
1319	if (sc->sc_curmac == NULL)
1320		sc->sc_curmac = mac;
1321
1322	error = bwn_dma_attach(mac);
1323	if (error != 0) {
1324		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1325		goto fail;
1326	}
1327
1328	mac->mac_phy.switch_analog(mac, 0);
1329
1330	siba_dev_down(sc->sc_dev, 0);
1331fail:
1332	siba_powerdown(sc->sc_dev);
1333	return (error);
1334}
1335
1336/*
1337 * Reset - SIBA.
1338 *
1339 * XXX TODO: implement BCMA version!
1340 */
1341void
1342bwn_reset_core(struct bwn_mac *mac, int g_mode)
1343{
1344	struct bwn_softc *sc = mac->mac_sc;
1345	uint32_t low, ctl;
1346	uint32_t flags = 0;
1347
1348	DPRINTF(sc, BWN_DEBUG_RESET, "%s: g_mode=%d\n", __func__, g_mode);
1349
1350	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1351	if (g_mode)
1352		flags |= BWN_TGSLOW_SUPPORT_G;
1353
1354	/* XXX N-PHY only; and hard-code to 20MHz for now */
1355	if (mac->mac_phy.type == BWN_PHYTYPE_N)
1356		flags |= BWN_TGSLOW_PHY_BANDWIDTH_20MHZ;
1357
1358	siba_dev_up(sc->sc_dev, flags);
1359	DELAY(2000);
1360
1361	/* Take PHY out of reset */
1362	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1363	    ~BWN_TGSLOW_PHYRESET;
1364	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1365	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1366	DELAY(1000);
1367	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1368	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1369	DELAY(1000);
1370
1371	if (mac->mac_phy.switch_analog != NULL)
1372		mac->mac_phy.switch_analog(mac, 1);
1373
1374	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1375	if (g_mode)
1376		ctl |= BWN_MACCTL_GMODE;
1377	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1378}
1379
1380static int
1381bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1382{
1383	struct bwn_phy *phy = &mac->mac_phy;
1384	struct bwn_softc *sc = mac->mac_sc;
1385	uint32_t tmp;
1386
1387	/* PHY */
1388	tmp = BWN_READ_2(mac, BWN_PHYVER);
1389	phy->gmode = !! (tgshigh & BWN_TGSHIGH_HAVE_2GHZ);
1390	phy->rf_on = 1;
1391	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1392	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1393	phy->rev = (tmp & BWN_PHYVER_VERSION);
1394	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1395	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1396		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1397	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1398	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1399	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1400		goto unsupphy;
1401
1402	/* RADIO */
1403	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1404		if (siba_get_chiprev(sc->sc_dev) == 0)
1405			tmp = 0x3205017f;
1406		else if (siba_get_chiprev(sc->sc_dev) == 1)
1407			tmp = 0x4205017f;
1408		else
1409			tmp = 0x5205017f;
1410	} else {
1411		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1412		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1413		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1414		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1415	}
1416	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1417	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1418	phy->rf_manuf = (tmp & 0x00000fff);
1419
1420	/*
1421	 * For now, just always do full init (ie, what bwn has traditionally
1422	 * done)
1423	 */
1424	phy->phy_do_full_init = 1;
1425
1426	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1427		goto unsupradio;
1428	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1429	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1430	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1431	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1432	    (phy->type == BWN_PHYTYPE_N &&
1433	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1434	    (phy->type == BWN_PHYTYPE_LP &&
1435	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1436		goto unsupradio;
1437
1438	return (0);
1439unsupphy:
1440	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1441	    "analog %#x)\n",
1442	    phy->type, phy->rev, phy->analog);
1443	return (ENXIO);
1444unsupradio:
1445	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1446	    "rev %#x)\n",
1447	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1448	return (ENXIO);
1449}
1450
1451static int
1452bwn_chiptest(struct bwn_mac *mac)
1453{
1454#define	TESTVAL0	0x55aaaa55
1455#define	TESTVAL1	0xaa5555aa
1456	struct bwn_softc *sc = mac->mac_sc;
1457	uint32_t v, backup;
1458
1459	BWN_LOCK(sc);
1460
1461	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1462
1463	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1464	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1465		goto error;
1466	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1467	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1468		goto error;
1469
1470	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1471
1472	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1473	    (siba_get_revid(sc->sc_dev) <= 10)) {
1474		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1475		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1476		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1477			goto error;
1478		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1479			goto error;
1480	}
1481	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1482
1483	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1484	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1485		goto error;
1486
1487	BWN_UNLOCK(sc);
1488	return (0);
1489error:
1490	BWN_UNLOCK(sc);
1491	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1492	return (ENODEV);
1493}
1494
1495static int
1496bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1497{
1498	struct bwn_softc *sc = mac->mac_sc;
1499	struct ieee80211com *ic = &sc->sc_ic;
1500	uint8_t bands[howmany(IEEE80211_MODE_MAX, 8)];
1501
1502	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1503	ic->ic_nchans = 0;
1504
1505	DPRINTF(sc, BWN_DEBUG_EEPROM, "%s: called; bg=%d, a=%d\n",
1506	    __func__,
1507	    have_bg,
1508	    have_a);
1509
1510	if (have_bg) {
1511		memset(bands, 0, sizeof(bands));
1512		setbit(bands, IEEE80211_MODE_11B);
1513		setbit(bands, IEEE80211_MODE_11G);
1514		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1515		    &ic->ic_nchans, &bwn_chantable_bg, bands);
1516	}
1517
1518	if (have_a) {
1519		memset(bands, 0, sizeof(bands));
1520		setbit(bands, IEEE80211_MODE_11A);
1521		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1522		    &ic->ic_nchans, &bwn_chantable_a, bands);
1523	}
1524
1525	mac->mac_phy.supports_2ghz = have_bg;
1526	mac->mac_phy.supports_5ghz = have_a;
1527
1528	return (ic->ic_nchans == 0 ? ENXIO : 0);
1529}
1530
1531uint32_t
1532bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1533{
1534	uint32_t ret;
1535
1536	BWN_ASSERT_LOCKED(mac->mac_sc);
1537
1538	if (way == BWN_SHARED) {
1539		KASSERT((offset & 0x0001) == 0,
1540		    ("%s:%d warn", __func__, __LINE__));
1541		if (offset & 0x0003) {
1542			bwn_shm_ctlword(mac, way, offset >> 2);
1543			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1544			ret <<= 16;
1545			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1546			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1547			goto out;
1548		}
1549		offset >>= 2;
1550	}
1551	bwn_shm_ctlword(mac, way, offset);
1552	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1553out:
1554	return (ret);
1555}
1556
1557uint16_t
1558bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1559{
1560	uint16_t ret;
1561
1562	BWN_ASSERT_LOCKED(mac->mac_sc);
1563
1564	if (way == BWN_SHARED) {
1565		KASSERT((offset & 0x0001) == 0,
1566		    ("%s:%d warn", __func__, __LINE__));
1567		if (offset & 0x0003) {
1568			bwn_shm_ctlword(mac, way, offset >> 2);
1569			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1570			goto out;
1571		}
1572		offset >>= 2;
1573	}
1574	bwn_shm_ctlword(mac, way, offset);
1575	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1576out:
1577
1578	return (ret);
1579}
1580
1581static void
1582bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1583    uint16_t offset)
1584{
1585	uint32_t control;
1586
1587	control = way;
1588	control <<= 16;
1589	control |= offset;
1590	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1591}
1592
1593void
1594bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1595    uint32_t value)
1596{
1597	BWN_ASSERT_LOCKED(mac->mac_sc);
1598
1599	if (way == BWN_SHARED) {
1600		KASSERT((offset & 0x0001) == 0,
1601		    ("%s:%d warn", __func__, __LINE__));
1602		if (offset & 0x0003) {
1603			bwn_shm_ctlword(mac, way, offset >> 2);
1604			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1605				    (value >> 16) & 0xffff);
1606			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1607			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1608			return;
1609		}
1610		offset >>= 2;
1611	}
1612	bwn_shm_ctlword(mac, way, offset);
1613	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1614}
1615
1616void
1617bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1618    uint16_t value)
1619{
1620	BWN_ASSERT_LOCKED(mac->mac_sc);
1621
1622	if (way == BWN_SHARED) {
1623		KASSERT((offset & 0x0001) == 0,
1624		    ("%s:%d warn", __func__, __LINE__));
1625		if (offset & 0x0003) {
1626			bwn_shm_ctlword(mac, way, offset >> 2);
1627			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1628			return;
1629		}
1630		offset >>= 2;
1631	}
1632	bwn_shm_ctlword(mac, way, offset);
1633	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1634}
1635
1636static void
1637bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1638    const struct bwn_channelinfo *ci, const uint8_t bands[])
1639{
1640	int i, error;
1641
1642	for (i = 0, error = 0; i < ci->nchannels && error == 0; i++) {
1643		const struct bwn_channel *hc = &ci->channels[i];
1644
1645		error = ieee80211_add_channel(chans, maxchans, nchans,
1646		    hc->ieee, hc->freq, hc->maxTxPow, 0, bands);
1647	}
1648}
1649
1650static int
1651bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1652	const struct ieee80211_bpf_params *params)
1653{
1654	struct ieee80211com *ic = ni->ni_ic;
1655	struct bwn_softc *sc = ic->ic_softc;
1656	struct bwn_mac *mac = sc->sc_curmac;
1657	int error;
1658
1659	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
1660	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
1661		m_freem(m);
1662		return (ENETDOWN);
1663	}
1664
1665	BWN_LOCK(sc);
1666	if (bwn_tx_isfull(sc, m)) {
1667		m_freem(m);
1668		BWN_UNLOCK(sc);
1669		return (ENOBUFS);
1670	}
1671
1672	error = bwn_tx_start(sc, ni, m);
1673	if (error == 0)
1674		sc->sc_watchdog_timer = 5;
1675	BWN_UNLOCK(sc);
1676	return (error);
1677}
1678
1679/*
1680 * Callback from the 802.11 layer to update the slot time
1681 * based on the current setting.  We use it to notify the
1682 * firmware of ERP changes and the f/w takes care of things
1683 * like slot time and preamble.
1684 */
1685static void
1686bwn_updateslot(struct ieee80211com *ic)
1687{
1688	struct bwn_softc *sc = ic->ic_softc;
1689	struct bwn_mac *mac;
1690
1691	BWN_LOCK(sc);
1692	if (sc->sc_flags & BWN_FLAG_RUNNING) {
1693		mac = (struct bwn_mac *)sc->sc_curmac;
1694		bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic));
1695	}
1696	BWN_UNLOCK(sc);
1697}
1698
1699/*
1700 * Callback from the 802.11 layer after a promiscuous mode change.
1701 * Note this interface does not check the operating mode as this
1702 * is an internal callback and we are expected to honor the current
1703 * state (e.g. this is used for setting the interface in promiscuous
1704 * mode when operating in hostap mode to do ACS).
1705 */
1706static void
1707bwn_update_promisc(struct ieee80211com *ic)
1708{
1709	struct bwn_softc *sc = ic->ic_softc;
1710	struct bwn_mac *mac = sc->sc_curmac;
1711
1712	BWN_LOCK(sc);
1713	mac = sc->sc_curmac;
1714	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1715		if (ic->ic_promisc > 0)
1716			sc->sc_filters |= BWN_MACCTL_PROMISC;
1717		else
1718			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
1719		bwn_set_opmode(mac);
1720	}
1721	BWN_UNLOCK(sc);
1722}
1723
1724/*
1725 * Callback from the 802.11 layer to update WME parameters.
1726 */
1727static int
1728bwn_wme_update(struct ieee80211com *ic)
1729{
1730	struct bwn_softc *sc = ic->ic_softc;
1731	struct bwn_mac *mac = sc->sc_curmac;
1732	struct wmeParams *wmep;
1733	int i;
1734
1735	BWN_LOCK(sc);
1736	mac = sc->sc_curmac;
1737	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1738		bwn_mac_suspend(mac);
1739		for (i = 0; i < N(sc->sc_wmeParams); i++) {
1740			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
1741			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
1742		}
1743		bwn_mac_enable(mac);
1744	}
1745	BWN_UNLOCK(sc);
1746	return (0);
1747}
1748
1749static void
1750bwn_scan_start(struct ieee80211com *ic)
1751{
1752	struct bwn_softc *sc = ic->ic_softc;
1753	struct bwn_mac *mac;
1754
1755	BWN_LOCK(sc);
1756	mac = sc->sc_curmac;
1757	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1758		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
1759		bwn_set_opmode(mac);
1760		/* disable CFP update during scan */
1761		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
1762	}
1763	BWN_UNLOCK(sc);
1764}
1765
1766static void
1767bwn_scan_end(struct ieee80211com *ic)
1768{
1769	struct bwn_softc *sc = ic->ic_softc;
1770	struct bwn_mac *mac;
1771
1772	BWN_LOCK(sc);
1773	mac = sc->sc_curmac;
1774	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1775		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
1776		bwn_set_opmode(mac);
1777		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
1778	}
1779	BWN_UNLOCK(sc);
1780}
1781
1782static void
1783bwn_set_channel(struct ieee80211com *ic)
1784{
1785	struct bwn_softc *sc = ic->ic_softc;
1786	struct bwn_mac *mac = sc->sc_curmac;
1787	struct bwn_phy *phy = &mac->mac_phy;
1788	int chan, error;
1789
1790	BWN_LOCK(sc);
1791
1792	error = bwn_switch_band(sc, ic->ic_curchan);
1793	if (error)
1794		goto fail;
1795	bwn_mac_suspend(mac);
1796	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
1797	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
1798	if (chan != phy->chan)
1799		bwn_switch_channel(mac, chan);
1800
1801	/* TX power level */
1802	if (ic->ic_curchan->ic_maxpower != 0 &&
1803	    ic->ic_curchan->ic_maxpower != phy->txpower) {
1804		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
1805		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
1806		    BWN_TXPWR_IGNORE_TSSI);
1807	}
1808
1809	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
1810	if (phy->set_antenna)
1811		phy->set_antenna(mac, BWN_ANT_DEFAULT);
1812
1813	if (sc->sc_rf_enabled != phy->rf_on) {
1814		if (sc->sc_rf_enabled) {
1815			bwn_rf_turnon(mac);
1816			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
1817				device_printf(sc->sc_dev,
1818				    "please turn on the RF switch\n");
1819		} else
1820			bwn_rf_turnoff(mac);
1821	}
1822
1823	bwn_mac_enable(mac);
1824
1825fail:
1826	/*
1827	 * Setup radio tap channel freq and flags
1828	 */
1829	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
1830		htole16(ic->ic_curchan->ic_freq);
1831	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
1832		htole16(ic->ic_curchan->ic_flags & 0xffff);
1833
1834	BWN_UNLOCK(sc);
1835}
1836
1837static struct ieee80211vap *
1838bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
1839    enum ieee80211_opmode opmode, int flags,
1840    const uint8_t bssid[IEEE80211_ADDR_LEN],
1841    const uint8_t mac[IEEE80211_ADDR_LEN])
1842{
1843	struct ieee80211vap *vap;
1844	struct bwn_vap *bvp;
1845
1846	switch (opmode) {
1847	case IEEE80211_M_HOSTAP:
1848	case IEEE80211_M_MBSS:
1849	case IEEE80211_M_STA:
1850	case IEEE80211_M_WDS:
1851	case IEEE80211_M_MONITOR:
1852	case IEEE80211_M_IBSS:
1853	case IEEE80211_M_AHDEMO:
1854		break;
1855	default:
1856		return (NULL);
1857	}
1858
1859	bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1860	vap = &bvp->bv_vap;
1861	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1862	/* override with driver methods */
1863	bvp->bv_newstate = vap->iv_newstate;
1864	vap->iv_newstate = bwn_newstate;
1865
1866	/* override max aid so sta's cannot assoc when we're out of sta id's */
1867	vap->iv_max_aid = BWN_STAID_MAX;
1868
1869	ieee80211_ratectl_init(vap);
1870
1871	/* complete setup */
1872	ieee80211_vap_attach(vap, ieee80211_media_change,
1873	    ieee80211_media_status, mac);
1874	return (vap);
1875}
1876
1877static void
1878bwn_vap_delete(struct ieee80211vap *vap)
1879{
1880	struct bwn_vap *bvp = BWN_VAP(vap);
1881
1882	ieee80211_ratectl_deinit(vap);
1883	ieee80211_vap_detach(vap);
1884	free(bvp, M_80211_VAP);
1885}
1886
1887static int
1888bwn_init(struct bwn_softc *sc)
1889{
1890	struct bwn_mac *mac;
1891	int error;
1892
1893	BWN_ASSERT_LOCKED(sc);
1894
1895	DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
1896
1897	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
1898	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
1899	sc->sc_filters = 0;
1900	bwn_wme_clear(sc);
1901	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
1902	sc->sc_rf_enabled = 1;
1903
1904	mac = sc->sc_curmac;
1905	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
1906		error = bwn_core_init(mac);
1907		if (error != 0)
1908			return (error);
1909	}
1910	if (mac->mac_status == BWN_MAC_STATUS_INITED)
1911		bwn_core_start(mac);
1912
1913	bwn_set_opmode(mac);
1914	bwn_set_pretbtt(mac);
1915	bwn_spu_setdelay(mac, 0);
1916	bwn_set_macaddr(mac);
1917
1918	sc->sc_flags |= BWN_FLAG_RUNNING;
1919	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
1920	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
1921
1922	return (0);
1923}
1924
1925static void
1926bwn_stop(struct bwn_softc *sc)
1927{
1928	struct bwn_mac *mac = sc->sc_curmac;
1929
1930	BWN_ASSERT_LOCKED(sc);
1931
1932	DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
1933
1934	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
1935		/* XXX FIXME opmode not based on VAP */
1936		bwn_set_opmode(mac);
1937		bwn_set_macaddr(mac);
1938	}
1939
1940	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
1941		bwn_core_stop(mac);
1942
1943	callout_stop(&sc->sc_led_blink_ch);
1944	sc->sc_led_blinking = 0;
1945
1946	bwn_core_exit(mac);
1947	sc->sc_rf_enabled = 0;
1948
1949	sc->sc_flags &= ~BWN_FLAG_RUNNING;
1950}
1951
1952static void
1953bwn_wme_clear(struct bwn_softc *sc)
1954{
1955#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
1956	struct wmeParams *p;
1957	unsigned int i;
1958
1959	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
1960	    ("%s:%d: fail", __func__, __LINE__));
1961
1962	for (i = 0; i < N(sc->sc_wmeParams); i++) {
1963		p = &(sc->sc_wmeParams[i]);
1964
1965		switch (bwn_wme_shm_offsets[i]) {
1966		case BWN_WME_VOICE:
1967			p->wmep_txopLimit = 0;
1968			p->wmep_aifsn = 2;
1969			/* XXX FIXME: log2(cwmin) */
1970			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1971			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
1972			break;
1973		case BWN_WME_VIDEO:
1974			p->wmep_txopLimit = 0;
1975			p->wmep_aifsn = 2;
1976			/* XXX FIXME: log2(cwmin) */
1977			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1978			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
1979			break;
1980		case BWN_WME_BESTEFFORT:
1981			p->wmep_txopLimit = 0;
1982			p->wmep_aifsn = 3;
1983			/* XXX FIXME: log2(cwmin) */
1984			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1985			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
1986			break;
1987		case BWN_WME_BACKGROUND:
1988			p->wmep_txopLimit = 0;
1989			p->wmep_aifsn = 7;
1990			/* XXX FIXME: log2(cwmin) */
1991			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1992			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
1993			break;
1994		default:
1995			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1996		}
1997	}
1998}
1999
2000static int
2001bwn_core_init(struct bwn_mac *mac)
2002{
2003	struct bwn_softc *sc = mac->mac_sc;
2004	uint64_t hf;
2005	int error;
2006
2007	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2008	    ("%s:%d: fail", __func__, __LINE__));
2009
2010	siba_powerup(sc->sc_dev, 0);
2011	if (!siba_dev_isup(sc->sc_dev))
2012		bwn_reset_core(mac, mac->mac_phy.gmode);
2013
2014	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
2015	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
2016	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
2017	BWN_GETTIME(mac->mac_phy.nexttime);
2018	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
2019	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
2020	mac->mac_stats.link_noise = -95;
2021	mac->mac_reason_intr = 0;
2022	bzero(mac->mac_reason, sizeof(mac->mac_reason));
2023	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
2024#ifdef BWN_DEBUG
2025	if (sc->sc_debug & BWN_DEBUG_XMIT)
2026		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
2027#endif
2028	mac->mac_suspended = 1;
2029	mac->mac_task_state = 0;
2030	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
2031
2032	mac->mac_phy.init_pre(mac);
2033
2034	siba_pcicore_intr(sc->sc_dev);
2035
2036	siba_fix_imcfglobug(sc->sc_dev);
2037	bwn_bt_disable(mac);
2038	if (mac->mac_phy.prepare_hw) {
2039		error = mac->mac_phy.prepare_hw(mac);
2040		if (error)
2041			goto fail0;
2042	}
2043	error = bwn_chip_init(mac);
2044	if (error)
2045		goto fail0;
2046	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
2047	    siba_get_revid(sc->sc_dev));
2048	hf = bwn_hf_read(mac);
2049	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
2050		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
2051		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2052			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
2053		if (mac->mac_phy.rev == 1)
2054			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
2055	}
2056	if (mac->mac_phy.rf_ver == 0x2050) {
2057		if (mac->mac_phy.rf_rev < 6)
2058			hf |= BWN_HF_FORCE_VCO_RECALC;
2059		if (mac->mac_phy.rf_rev == 6)
2060			hf |= BWN_HF_4318_TSSI;
2061	}
2062	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
2063		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
2064	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
2065	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
2066		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
2067	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
2068	bwn_hf_write(mac, hf);
2069
2070	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2071	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
2072	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
2073	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
2074
2075	bwn_rate_init(mac);
2076	bwn_set_phytxctl(mac);
2077
2078	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
2079	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
2080	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
2081
2082	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
2083		bwn_pio_init(mac);
2084	else
2085		bwn_dma_init(mac);
2086	bwn_wme_init(mac);
2087	bwn_spu_setdelay(mac, 1);
2088	bwn_bt_enable(mac);
2089
2090	siba_powerup(sc->sc_dev,
2091	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
2092	bwn_set_macaddr(mac);
2093	bwn_crypt_init(mac);
2094
2095	/* XXX LED initializatin */
2096
2097	mac->mac_status = BWN_MAC_STATUS_INITED;
2098
2099	return (error);
2100
2101fail0:
2102	siba_powerdown(sc->sc_dev);
2103	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2104	    ("%s:%d: fail", __func__, __LINE__));
2105	return (error);
2106}
2107
2108static void
2109bwn_core_start(struct bwn_mac *mac)
2110{
2111	struct bwn_softc *sc = mac->mac_sc;
2112	uint32_t tmp;
2113
2114	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
2115	    ("%s:%d: fail", __func__, __LINE__));
2116
2117	if (siba_get_revid(sc->sc_dev) < 5)
2118		return;
2119
2120	while (1) {
2121		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
2122		if (!(tmp & 0x00000001))
2123			break;
2124		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
2125	}
2126
2127	bwn_mac_enable(mac);
2128	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
2129	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
2130
2131	mac->mac_status = BWN_MAC_STATUS_STARTED;
2132}
2133
2134static void
2135bwn_core_exit(struct bwn_mac *mac)
2136{
2137	struct bwn_softc *sc = mac->mac_sc;
2138	uint32_t macctl;
2139
2140	BWN_ASSERT_LOCKED(mac->mac_sc);
2141
2142	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
2143	    ("%s:%d: fail", __func__, __LINE__));
2144
2145	if (mac->mac_status != BWN_MAC_STATUS_INITED)
2146		return;
2147	mac->mac_status = BWN_MAC_STATUS_UNINIT;
2148
2149	macctl = BWN_READ_4(mac, BWN_MACCTL);
2150	macctl &= ~BWN_MACCTL_MCODE_RUN;
2151	macctl |= BWN_MACCTL_MCODE_JMP0;
2152	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2153
2154	bwn_dma_stop(mac);
2155	bwn_pio_stop(mac);
2156	bwn_chip_exit(mac);
2157	mac->mac_phy.switch_analog(mac, 0);
2158	siba_dev_down(sc->sc_dev, 0);
2159	siba_powerdown(sc->sc_dev);
2160}
2161
2162static void
2163bwn_bt_disable(struct bwn_mac *mac)
2164{
2165	struct bwn_softc *sc = mac->mac_sc;
2166
2167	(void)sc;
2168	/* XXX do nothing yet */
2169}
2170
2171static int
2172bwn_chip_init(struct bwn_mac *mac)
2173{
2174	struct bwn_softc *sc = mac->mac_sc;
2175	struct bwn_phy *phy = &mac->mac_phy;
2176	uint32_t macctl;
2177	int error;
2178
2179	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
2180	if (phy->gmode)
2181		macctl |= BWN_MACCTL_GMODE;
2182	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2183
2184	error = bwn_fw_fillinfo(mac);
2185	if (error)
2186		return (error);
2187	error = bwn_fw_loaducode(mac);
2188	if (error)
2189		return (error);
2190
2191	error = bwn_gpio_init(mac);
2192	if (error)
2193		return (error);
2194
2195	error = bwn_fw_loadinitvals(mac);
2196	if (error) {
2197		siba_gpio_set(sc->sc_dev, 0);
2198		return (error);
2199	}
2200	phy->switch_analog(mac, 1);
2201	error = bwn_phy_init(mac);
2202	if (error) {
2203		siba_gpio_set(sc->sc_dev, 0);
2204		return (error);
2205	}
2206	if (phy->set_im)
2207		phy->set_im(mac, BWN_IMMODE_NONE);
2208	if (phy->set_antenna)
2209		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2210	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2211
2212	if (phy->type == BWN_PHYTYPE_B)
2213		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
2214	BWN_WRITE_4(mac, 0x0100, 0x01000000);
2215	if (siba_get_revid(sc->sc_dev) < 5)
2216		BWN_WRITE_4(mac, 0x010c, 0x01000000);
2217
2218	BWN_WRITE_4(mac, BWN_MACCTL,
2219	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
2220	BWN_WRITE_4(mac, BWN_MACCTL,
2221	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
2222	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
2223
2224	bwn_set_opmode(mac);
2225	if (siba_get_revid(sc->sc_dev) < 3) {
2226		BWN_WRITE_2(mac, 0x060e, 0x0000);
2227		BWN_WRITE_2(mac, 0x0610, 0x8000);
2228		BWN_WRITE_2(mac, 0x0604, 0x0000);
2229		BWN_WRITE_2(mac, 0x0606, 0x0200);
2230	} else {
2231		BWN_WRITE_4(mac, 0x0188, 0x80000000);
2232		BWN_WRITE_4(mac, 0x018c, 0x02000000);
2233	}
2234	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
2235	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
2236	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
2237	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
2238	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
2239	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
2240	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
2241
2242	bwn_mac_phy_clock_set(mac, true);
2243
2244	/* SIBA powerup */
2245	/* XXX TODO: BCMA powerup */
2246	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
2247	return (error);
2248}
2249
2250/* read hostflags */
2251uint64_t
2252bwn_hf_read(struct bwn_mac *mac)
2253{
2254	uint64_t ret;
2255
2256	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
2257	ret <<= 16;
2258	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
2259	ret <<= 16;
2260	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
2261	return (ret);
2262}
2263
2264void
2265bwn_hf_write(struct bwn_mac *mac, uint64_t value)
2266{
2267
2268	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
2269	    (value & 0x00000000ffffull));
2270	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
2271	    (value & 0x0000ffff0000ull) >> 16);
2272	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
2273	    (value & 0xffff00000000ULL) >> 32);
2274}
2275
2276static void
2277bwn_set_txretry(struct bwn_mac *mac, int s, int l)
2278{
2279
2280	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
2281	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
2282}
2283
2284static void
2285bwn_rate_init(struct bwn_mac *mac)
2286{
2287
2288	switch (mac->mac_phy.type) {
2289	case BWN_PHYTYPE_A:
2290	case BWN_PHYTYPE_G:
2291	case BWN_PHYTYPE_LP:
2292	case BWN_PHYTYPE_N:
2293		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
2294		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
2295		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
2296		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
2297		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
2298		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
2299		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
2300		if (mac->mac_phy.type == BWN_PHYTYPE_A)
2301			break;
2302		/* FALLTHROUGH */
2303	case BWN_PHYTYPE_B:
2304		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
2305		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
2306		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
2307		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
2308		break;
2309	default:
2310		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2311	}
2312}
2313
2314static void
2315bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
2316{
2317	uint16_t offset;
2318
2319	if (ofdm) {
2320		offset = 0x480;
2321		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
2322	} else {
2323		offset = 0x4c0;
2324		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
2325	}
2326	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
2327	    bwn_shm_read_2(mac, BWN_SHARED, offset));
2328}
2329
2330static uint8_t
2331bwn_plcp_getcck(const uint8_t bitrate)
2332{
2333
2334	switch (bitrate) {
2335	case BWN_CCK_RATE_1MB:
2336		return (0x0a);
2337	case BWN_CCK_RATE_2MB:
2338		return (0x14);
2339	case BWN_CCK_RATE_5MB:
2340		return (0x37);
2341	case BWN_CCK_RATE_11MB:
2342		return (0x6e);
2343	}
2344	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2345	return (0);
2346}
2347
2348static uint8_t
2349bwn_plcp_getofdm(const uint8_t bitrate)
2350{
2351
2352	switch (bitrate) {
2353	case BWN_OFDM_RATE_6MB:
2354		return (0xb);
2355	case BWN_OFDM_RATE_9MB:
2356		return (0xf);
2357	case BWN_OFDM_RATE_12MB:
2358		return (0xa);
2359	case BWN_OFDM_RATE_18MB:
2360		return (0xe);
2361	case BWN_OFDM_RATE_24MB:
2362		return (0x9);
2363	case BWN_OFDM_RATE_36MB:
2364		return (0xd);
2365	case BWN_OFDM_RATE_48MB:
2366		return (0x8);
2367	case BWN_OFDM_RATE_54MB:
2368		return (0xc);
2369	}
2370	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2371	return (0);
2372}
2373
2374static void
2375bwn_set_phytxctl(struct bwn_mac *mac)
2376{
2377	uint16_t ctl;
2378
2379	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
2380	    BWN_TX_PHY_TXPWR);
2381	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
2382	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
2383	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
2384}
2385
2386static void
2387bwn_pio_init(struct bwn_mac *mac)
2388{
2389	struct bwn_pio *pio = &mac->mac_method.pio;
2390
2391	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
2392	    & ~BWN_MACCTL_BIGENDIAN);
2393	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
2394
2395	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
2396	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
2397	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
2398	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
2399	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
2400	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
2401}
2402
2403static void
2404bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2405    int index)
2406{
2407	struct bwn_pio_txpkt *tp;
2408	struct bwn_softc *sc = mac->mac_sc;
2409	unsigned int i;
2410
2411	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
2412	tq->tq_index = index;
2413
2414	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
2415	if (siba_get_revid(sc->sc_dev) >= 8)
2416		tq->tq_size = 1920;
2417	else {
2418		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
2419		tq->tq_size -= 80;
2420	}
2421
2422	TAILQ_INIT(&tq->tq_pktlist);
2423	for (i = 0; i < N(tq->tq_pkts); i++) {
2424		tp = &(tq->tq_pkts[i]);
2425		tp->tp_index = i;
2426		tp->tp_queue = tq;
2427		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
2428	}
2429}
2430
2431static uint16_t
2432bwn_pio_idx2base(struct bwn_mac *mac, int index)
2433{
2434	struct bwn_softc *sc = mac->mac_sc;
2435	static const uint16_t bases[] = {
2436		BWN_PIO_BASE0,
2437		BWN_PIO_BASE1,
2438		BWN_PIO_BASE2,
2439		BWN_PIO_BASE3,
2440		BWN_PIO_BASE4,
2441		BWN_PIO_BASE5,
2442		BWN_PIO_BASE6,
2443		BWN_PIO_BASE7,
2444	};
2445	static const uint16_t bases_rev11[] = {
2446		BWN_PIO11_BASE0,
2447		BWN_PIO11_BASE1,
2448		BWN_PIO11_BASE2,
2449		BWN_PIO11_BASE3,
2450		BWN_PIO11_BASE4,
2451		BWN_PIO11_BASE5,
2452	};
2453
2454	if (siba_get_revid(sc->sc_dev) >= 11) {
2455		if (index >= N(bases_rev11))
2456			device_printf(sc->sc_dev, "%s: warning\n", __func__);
2457		return (bases_rev11[index]);
2458	}
2459	if (index >= N(bases))
2460		device_printf(sc->sc_dev, "%s: warning\n", __func__);
2461	return (bases[index]);
2462}
2463
2464static void
2465bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
2466    int index)
2467{
2468	struct bwn_softc *sc = mac->mac_sc;
2469
2470	prq->prq_mac = mac;
2471	prq->prq_rev = siba_get_revid(sc->sc_dev);
2472	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
2473	bwn_dma_rxdirectfifo(mac, index, 1);
2474}
2475
2476static void
2477bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
2478{
2479	if (tq == NULL)
2480		return;
2481	bwn_pio_cancel_tx_packets(tq);
2482}
2483
2484static void
2485bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
2486{
2487
2488	bwn_destroy_pioqueue_tx(pio);
2489}
2490
2491static uint16_t
2492bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2493    uint16_t offset)
2494{
2495
2496	return (BWN_READ_2(mac, tq->tq_base + offset));
2497}
2498
2499static void
2500bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
2501{
2502	uint32_t ctl;
2503	int type;
2504	uint16_t base;
2505
2506	type = bwn_dma_mask2type(bwn_dma_mask(mac));
2507	base = bwn_dma_base(type, idx);
2508	if (type == BWN_DMA_64BIT) {
2509		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
2510		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
2511		if (enable)
2512			ctl |= BWN_DMA64_RXDIRECTFIFO;
2513		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
2514	} else {
2515		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
2516		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
2517		if (enable)
2518			ctl |= BWN_DMA32_RXDIRECTFIFO;
2519		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
2520	}
2521}
2522
2523static uint64_t
2524bwn_dma_mask(struct bwn_mac *mac)
2525{
2526	uint32_t tmp;
2527	uint16_t base;
2528
2529	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
2530	if (tmp & SIBA_TGSHIGH_DMA64)
2531		return (BWN_DMA_BIT_MASK(64));
2532	base = bwn_dma_base(0, 0);
2533	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
2534	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
2535	if (tmp & BWN_DMA32_TXADDREXT_MASK)
2536		return (BWN_DMA_BIT_MASK(32));
2537
2538	return (BWN_DMA_BIT_MASK(30));
2539}
2540
2541static int
2542bwn_dma_mask2type(uint64_t dmamask)
2543{
2544
2545	if (dmamask == BWN_DMA_BIT_MASK(30))
2546		return (BWN_DMA_30BIT);
2547	if (dmamask == BWN_DMA_BIT_MASK(32))
2548		return (BWN_DMA_32BIT);
2549	if (dmamask == BWN_DMA_BIT_MASK(64))
2550		return (BWN_DMA_64BIT);
2551	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2552	return (BWN_DMA_30BIT);
2553}
2554
2555static void
2556bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
2557{
2558	struct bwn_pio_txpkt *tp;
2559	unsigned int i;
2560
2561	for (i = 0; i < N(tq->tq_pkts); i++) {
2562		tp = &(tq->tq_pkts[i]);
2563		if (tp->tp_m) {
2564			m_freem(tp->tp_m);
2565			tp->tp_m = NULL;
2566		}
2567	}
2568}
2569
2570static uint16_t
2571bwn_dma_base(int type, int controller_idx)
2572{
2573	static const uint16_t map64[] = {
2574		BWN_DMA64_BASE0,
2575		BWN_DMA64_BASE1,
2576		BWN_DMA64_BASE2,
2577		BWN_DMA64_BASE3,
2578		BWN_DMA64_BASE4,
2579		BWN_DMA64_BASE5,
2580	};
2581	static const uint16_t map32[] = {
2582		BWN_DMA32_BASE0,
2583		BWN_DMA32_BASE1,
2584		BWN_DMA32_BASE2,
2585		BWN_DMA32_BASE3,
2586		BWN_DMA32_BASE4,
2587		BWN_DMA32_BASE5,
2588	};
2589
2590	if (type == BWN_DMA_64BIT) {
2591		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
2592		    ("%s:%d: fail", __func__, __LINE__));
2593		return (map64[controller_idx]);
2594	}
2595	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
2596	    ("%s:%d: fail", __func__, __LINE__));
2597	return (map32[controller_idx]);
2598}
2599
2600static void
2601bwn_dma_init(struct bwn_mac *mac)
2602{
2603	struct bwn_dma *dma = &mac->mac_method.dma;
2604
2605	/* setup TX DMA channels. */
2606	bwn_dma_setup(dma->wme[WME_AC_BK]);
2607	bwn_dma_setup(dma->wme[WME_AC_BE]);
2608	bwn_dma_setup(dma->wme[WME_AC_VI]);
2609	bwn_dma_setup(dma->wme[WME_AC_VO]);
2610	bwn_dma_setup(dma->mcast);
2611	/* setup RX DMA channel. */
2612	bwn_dma_setup(dma->rx);
2613}
2614
2615static struct bwn_dma_ring *
2616bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
2617    int for_tx, int type)
2618{
2619	struct bwn_dma *dma = &mac->mac_method.dma;
2620	struct bwn_dma_ring *dr;
2621	struct bwn_dmadesc_generic *desc;
2622	struct bwn_dmadesc_meta *mt;
2623	struct bwn_softc *sc = mac->mac_sc;
2624	int error, i;
2625
2626	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
2627	if (dr == NULL)
2628		goto out;
2629	dr->dr_numslots = BWN_RXRING_SLOTS;
2630	if (for_tx)
2631		dr->dr_numslots = BWN_TXRING_SLOTS;
2632
2633	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
2634	    M_DEVBUF, M_NOWAIT | M_ZERO);
2635	if (dr->dr_meta == NULL)
2636		goto fail0;
2637
2638	dr->dr_type = type;
2639	dr->dr_mac = mac;
2640	dr->dr_base = bwn_dma_base(type, controller_index);
2641	dr->dr_index = controller_index;
2642	if (type == BWN_DMA_64BIT) {
2643		dr->getdesc = bwn_dma_64_getdesc;
2644		dr->setdesc = bwn_dma_64_setdesc;
2645		dr->start_transfer = bwn_dma_64_start_transfer;
2646		dr->suspend = bwn_dma_64_suspend;
2647		dr->resume = bwn_dma_64_resume;
2648		dr->get_curslot = bwn_dma_64_get_curslot;
2649		dr->set_curslot = bwn_dma_64_set_curslot;
2650	} else {
2651		dr->getdesc = bwn_dma_32_getdesc;
2652		dr->setdesc = bwn_dma_32_setdesc;
2653		dr->start_transfer = bwn_dma_32_start_transfer;
2654		dr->suspend = bwn_dma_32_suspend;
2655		dr->resume = bwn_dma_32_resume;
2656		dr->get_curslot = bwn_dma_32_get_curslot;
2657		dr->set_curslot = bwn_dma_32_set_curslot;
2658	}
2659	if (for_tx) {
2660		dr->dr_tx = 1;
2661		dr->dr_curslot = -1;
2662	} else {
2663		if (dr->dr_index == 0) {
2664			switch (mac->mac_fw.fw_hdr_format) {
2665			case BWN_FW_HDR_351:
2666			case BWN_FW_HDR_410:
2667				dr->dr_rx_bufsize =
2668				    BWN_DMA0_RX_BUFFERSIZE_FW351;
2669				dr->dr_frameoffset =
2670				    BWN_DMA0_RX_FRAMEOFFSET_FW351;
2671				break;
2672			case BWN_FW_HDR_598:
2673				dr->dr_rx_bufsize =
2674				    BWN_DMA0_RX_BUFFERSIZE_FW598;
2675				dr->dr_frameoffset =
2676				    BWN_DMA0_RX_FRAMEOFFSET_FW598;
2677				break;
2678			}
2679		} else
2680			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2681	}
2682
2683	error = bwn_dma_allocringmemory(dr);
2684	if (error)
2685		goto fail2;
2686
2687	if (for_tx) {
2688		/*
2689		 * Assumption: BWN_TXRING_SLOTS can be divided by
2690		 * BWN_TX_SLOTS_PER_FRAME
2691		 */
2692		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
2693		    ("%s:%d: fail", __func__, __LINE__));
2694
2695		dr->dr_txhdr_cache = contigmalloc(
2696		    (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2697		    BWN_MAXTXHDRSIZE, M_DEVBUF, M_ZERO,
2698		    0, BUS_SPACE_MAXADDR, 8, 0);
2699		if (dr->dr_txhdr_cache == NULL) {
2700			device_printf(sc->sc_dev,
2701			    "can't allocate TX header DMA memory\n");
2702			goto fail1;
2703		}
2704
2705		/*
2706		 * Create TX ring DMA stuffs
2707		 */
2708		error = bus_dma_tag_create(dma->parent_dtag,
2709				    BWN_ALIGN, 0,
2710				    BUS_SPACE_MAXADDR,
2711				    BUS_SPACE_MAXADDR,
2712				    NULL, NULL,
2713				    BWN_HDRSIZE(mac),
2714				    1,
2715				    BUS_SPACE_MAXSIZE_32BIT,
2716				    0,
2717				    NULL, NULL,
2718				    &dr->dr_txring_dtag);
2719		if (error) {
2720			device_printf(sc->sc_dev,
2721			    "can't create TX ring DMA tag: TODO frees\n");
2722			goto fail2;
2723		}
2724
2725		for (i = 0; i < dr->dr_numslots; i += 2) {
2726			dr->getdesc(dr, i, &desc, &mt);
2727
2728			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
2729			mt->mt_m = NULL;
2730			mt->mt_ni = NULL;
2731			mt->mt_islast = 0;
2732			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
2733			    &mt->mt_dmap);
2734			if (error) {
2735				device_printf(sc->sc_dev,
2736				     "can't create RX buf DMA map\n");
2737				goto fail2;
2738			}
2739
2740			dr->getdesc(dr, i + 1, &desc, &mt);
2741
2742			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
2743			mt->mt_m = NULL;
2744			mt->mt_ni = NULL;
2745			mt->mt_islast = 1;
2746			error = bus_dmamap_create(dma->txbuf_dtag, 0,
2747			    &mt->mt_dmap);
2748			if (error) {
2749				device_printf(sc->sc_dev,
2750				     "can't create RX buf DMA map\n");
2751				goto fail2;
2752			}
2753		}
2754	} else {
2755		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2756		    &dr->dr_spare_dmap);
2757		if (error) {
2758			device_printf(sc->sc_dev,
2759			    "can't create RX buf DMA map\n");
2760			goto out;		/* XXX wrong! */
2761		}
2762
2763		for (i = 0; i < dr->dr_numslots; i++) {
2764			dr->getdesc(dr, i, &desc, &mt);
2765
2766			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2767			    &mt->mt_dmap);
2768			if (error) {
2769				device_printf(sc->sc_dev,
2770				    "can't create RX buf DMA map\n");
2771				goto out;	/* XXX wrong! */
2772			}
2773			error = bwn_dma_newbuf(dr, desc, mt, 1);
2774			if (error) {
2775				device_printf(sc->sc_dev,
2776				    "failed to allocate RX buf\n");
2777				goto out;	/* XXX wrong! */
2778			}
2779		}
2780
2781		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
2782		    BUS_DMASYNC_PREWRITE);
2783
2784		dr->dr_usedslot = dr->dr_numslots;
2785	}
2786
2787      out:
2788	return (dr);
2789
2790fail2:
2791	if (dr->dr_txhdr_cache != NULL) {
2792		contigfree(dr->dr_txhdr_cache,
2793		    (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2794		    BWN_MAXTXHDRSIZE, M_DEVBUF);
2795	}
2796fail1:
2797	free(dr->dr_meta, M_DEVBUF);
2798fail0:
2799	free(dr, M_DEVBUF);
2800	return (NULL);
2801}
2802
2803static void
2804bwn_dma_ringfree(struct bwn_dma_ring **dr)
2805{
2806
2807	if (dr == NULL)
2808		return;
2809
2810	bwn_dma_free_descbufs(*dr);
2811	bwn_dma_free_ringmemory(*dr);
2812
2813	if ((*dr)->dr_txhdr_cache != NULL) {
2814		contigfree((*dr)->dr_txhdr_cache,
2815		    ((*dr)->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2816		    BWN_MAXTXHDRSIZE, M_DEVBUF);
2817	}
2818	free((*dr)->dr_meta, M_DEVBUF);
2819	free(*dr, M_DEVBUF);
2820
2821	*dr = NULL;
2822}
2823
2824static void
2825bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
2826    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
2827{
2828	struct bwn_dmadesc32 *desc;
2829
2830	*meta = &(dr->dr_meta[slot]);
2831	desc = dr->dr_ring_descbase;
2832	desc = &(desc[slot]);
2833
2834	*gdesc = (struct bwn_dmadesc_generic *)desc;
2835}
2836
2837static void
2838bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
2839    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
2840    int start, int end, int irq)
2841{
2842	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
2843	struct bwn_softc *sc = dr->dr_mac->mac_sc;
2844	uint32_t addr, addrext, ctl;
2845	int slot;
2846
2847	slot = (int)(&(desc->dma.dma32) - descbase);
2848	KASSERT(slot >= 0 && slot < dr->dr_numslots,
2849	    ("%s:%d: fail", __func__, __LINE__));
2850
2851	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
2852	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
2853	addr |= siba_dma_translation(sc->sc_dev);
2854	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
2855	if (slot == dr->dr_numslots - 1)
2856		ctl |= BWN_DMA32_DCTL_DTABLEEND;
2857	if (start)
2858		ctl |= BWN_DMA32_DCTL_FRAMESTART;
2859	if (end)
2860		ctl |= BWN_DMA32_DCTL_FRAMEEND;
2861	if (irq)
2862		ctl |= BWN_DMA32_DCTL_IRQ;
2863	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
2864	    & BWN_DMA32_DCTL_ADDREXT_MASK;
2865
2866	desc->dma.dma32.control = htole32(ctl);
2867	desc->dma.dma32.address = htole32(addr);
2868}
2869
2870static void
2871bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
2872{
2873
2874	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
2875	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
2876}
2877
2878static void
2879bwn_dma_32_suspend(struct bwn_dma_ring *dr)
2880{
2881
2882	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2883	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
2884}
2885
2886static void
2887bwn_dma_32_resume(struct bwn_dma_ring *dr)
2888{
2889
2890	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2891	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
2892}
2893
2894static int
2895bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
2896{
2897	uint32_t val;
2898
2899	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
2900	val &= BWN_DMA32_RXDPTR;
2901
2902	return (val / sizeof(struct bwn_dmadesc32));
2903}
2904
2905static void
2906bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
2907{
2908
2909	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
2910	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
2911}
2912
2913static void
2914bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
2915    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
2916{
2917	struct bwn_dmadesc64 *desc;
2918
2919	*meta = &(dr->dr_meta[slot]);
2920	desc = dr->dr_ring_descbase;
2921	desc = &(desc[slot]);
2922
2923	*gdesc = (struct bwn_dmadesc_generic *)desc;
2924}
2925
2926static void
2927bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
2928    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
2929    int start, int end, int irq)
2930{
2931	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
2932	struct bwn_softc *sc = dr->dr_mac->mac_sc;
2933	int slot;
2934	uint32_t ctl0 = 0, ctl1 = 0;
2935	uint32_t addrlo, addrhi;
2936	uint32_t addrext;
2937
2938	slot = (int)(&(desc->dma.dma64) - descbase);
2939	KASSERT(slot >= 0 && slot < dr->dr_numslots,
2940	    ("%s:%d: fail", __func__, __LINE__));
2941
2942	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
2943	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
2944	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
2945	    30;
2946	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
2947	if (slot == dr->dr_numslots - 1)
2948		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
2949	if (start)
2950		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
2951	if (end)
2952		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
2953	if (irq)
2954		ctl0 |= BWN_DMA64_DCTL0_IRQ;
2955	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
2956	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
2957	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
2958
2959	desc->dma.dma64.control0 = htole32(ctl0);
2960	desc->dma.dma64.control1 = htole32(ctl1);
2961	desc->dma.dma64.address_low = htole32(addrlo);
2962	desc->dma.dma64.address_high = htole32(addrhi);
2963}
2964
2965static void
2966bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
2967{
2968
2969	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
2970	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
2971}
2972
2973static void
2974bwn_dma_64_suspend(struct bwn_dma_ring *dr)
2975{
2976
2977	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
2978	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
2979}
2980
2981static void
2982bwn_dma_64_resume(struct bwn_dma_ring *dr)
2983{
2984
2985	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
2986	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
2987}
2988
2989static int
2990bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
2991{
2992	uint32_t val;
2993
2994	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
2995	val &= BWN_DMA64_RXSTATDPTR;
2996
2997	return (val / sizeof(struct bwn_dmadesc64));
2998}
2999
3000static void
3001bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
3002{
3003
3004	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
3005	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3006}
3007
3008static int
3009bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
3010{
3011	struct bwn_mac *mac = dr->dr_mac;
3012	struct bwn_dma *dma = &mac->mac_method.dma;
3013	struct bwn_softc *sc = mac->mac_sc;
3014	int error;
3015
3016	error = bus_dma_tag_create(dma->parent_dtag,
3017			    BWN_ALIGN, 0,
3018			    BUS_SPACE_MAXADDR,
3019			    BUS_SPACE_MAXADDR,
3020			    NULL, NULL,
3021			    BWN_DMA_RINGMEMSIZE,
3022			    1,
3023			    BUS_SPACE_MAXSIZE_32BIT,
3024			    0,
3025			    NULL, NULL,
3026			    &dr->dr_ring_dtag);
3027	if (error) {
3028		device_printf(sc->sc_dev,
3029		    "can't create TX ring DMA tag: TODO frees\n");
3030		return (-1);
3031	}
3032
3033	error = bus_dmamem_alloc(dr->dr_ring_dtag,
3034	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
3035	    &dr->dr_ring_dmap);
3036	if (error) {
3037		device_printf(sc->sc_dev,
3038		    "can't allocate DMA mem: TODO frees\n");
3039		return (-1);
3040	}
3041	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
3042	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
3043	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
3044	if (error) {
3045		device_printf(sc->sc_dev,
3046		    "can't load DMA mem: TODO free\n");
3047		return (-1);
3048	}
3049
3050	return (0);
3051}
3052
3053static void
3054bwn_dma_setup(struct bwn_dma_ring *dr)
3055{
3056	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3057	uint64_t ring64;
3058	uint32_t addrext, ring32, value;
3059	uint32_t trans = siba_dma_translation(sc->sc_dev);
3060
3061	if (dr->dr_tx) {
3062		dr->dr_curslot = -1;
3063
3064		if (dr->dr_type == BWN_DMA_64BIT) {
3065			ring64 = (uint64_t)(dr->dr_ring_dmabase);
3066			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
3067			    >> 30;
3068			value = BWN_DMA64_TXENABLE;
3069			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
3070			    & BWN_DMA64_TXADDREXT_MASK;
3071			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
3072			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
3073			    (ring64 & 0xffffffff));
3074			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
3075			    ((ring64 >> 32) &
3076			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
3077		} else {
3078			ring32 = (uint32_t)(dr->dr_ring_dmabase);
3079			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3080			value = BWN_DMA32_TXENABLE;
3081			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
3082			    & BWN_DMA32_TXADDREXT_MASK;
3083			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
3084			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
3085			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3086		}
3087		return;
3088	}
3089
3090	/*
3091	 * set for RX
3092	 */
3093	dr->dr_usedslot = dr->dr_numslots;
3094
3095	if (dr->dr_type == BWN_DMA_64BIT) {
3096		ring64 = (uint64_t)(dr->dr_ring_dmabase);
3097		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
3098		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
3099		value |= BWN_DMA64_RXENABLE;
3100		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
3101		    & BWN_DMA64_RXADDREXT_MASK;
3102		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
3103		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
3104		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
3105		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
3106		    | (trans << 1));
3107		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
3108		    sizeof(struct bwn_dmadesc64));
3109	} else {
3110		ring32 = (uint32_t)(dr->dr_ring_dmabase);
3111		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3112		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
3113		value |= BWN_DMA32_RXENABLE;
3114		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
3115		    & BWN_DMA32_RXADDREXT_MASK;
3116		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
3117		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
3118		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3119		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
3120		    sizeof(struct bwn_dmadesc32));
3121	}
3122}
3123
3124static void
3125bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
3126{
3127
3128	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
3129	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
3130	    dr->dr_ring_dmap);
3131}
3132
3133static void
3134bwn_dma_cleanup(struct bwn_dma_ring *dr)
3135{
3136
3137	if (dr->dr_tx) {
3138		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3139		if (dr->dr_type == BWN_DMA_64BIT) {
3140			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
3141			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
3142		} else
3143			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
3144	} else {
3145		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3146		if (dr->dr_type == BWN_DMA_64BIT) {
3147			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
3148			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
3149		} else
3150			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
3151	}
3152}
3153
3154static void
3155bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
3156{
3157	struct bwn_dmadesc_generic *desc;
3158	struct bwn_dmadesc_meta *meta;
3159	struct bwn_mac *mac = dr->dr_mac;
3160	struct bwn_dma *dma = &mac->mac_method.dma;
3161	struct bwn_softc *sc = mac->mac_sc;
3162	int i;
3163
3164	if (!dr->dr_usedslot)
3165		return;
3166	for (i = 0; i < dr->dr_numslots; i++) {
3167		dr->getdesc(dr, i, &desc, &meta);
3168
3169		if (meta->mt_m == NULL) {
3170			if (!dr->dr_tx)
3171				device_printf(sc->sc_dev, "%s: not TX?\n",
3172				    __func__);
3173			continue;
3174		}
3175		if (dr->dr_tx) {
3176			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
3177				bus_dmamap_unload(dr->dr_txring_dtag,
3178				    meta->mt_dmap);
3179			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
3180				bus_dmamap_unload(dma->txbuf_dtag,
3181				    meta->mt_dmap);
3182		} else
3183			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
3184		bwn_dma_free_descbuf(dr, meta);
3185	}
3186}
3187
3188static int
3189bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
3190    int type)
3191{
3192	struct bwn_softc *sc = mac->mac_sc;
3193	uint32_t value;
3194	int i;
3195	uint16_t offset;
3196
3197	for (i = 0; i < 10; i++) {
3198		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3199		    BWN_DMA32_TXSTATUS;
3200		value = BWN_READ_4(mac, base + offset);
3201		if (type == BWN_DMA_64BIT) {
3202			value &= BWN_DMA64_TXSTAT;
3203			if (value == BWN_DMA64_TXSTAT_DISABLED ||
3204			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
3205			    value == BWN_DMA64_TXSTAT_STOPPED)
3206				break;
3207		} else {
3208			value &= BWN_DMA32_TXSTATE;
3209			if (value == BWN_DMA32_TXSTAT_DISABLED ||
3210			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
3211			    value == BWN_DMA32_TXSTAT_STOPPED)
3212				break;
3213		}
3214		DELAY(1000);
3215	}
3216	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
3217	BWN_WRITE_4(mac, base + offset, 0);
3218	for (i = 0; i < 10; i++) {
3219		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3220						   BWN_DMA32_TXSTATUS;
3221		value = BWN_READ_4(mac, base + offset);
3222		if (type == BWN_DMA_64BIT) {
3223			value &= BWN_DMA64_TXSTAT;
3224			if (value == BWN_DMA64_TXSTAT_DISABLED) {
3225				i = -1;
3226				break;
3227			}
3228		} else {
3229			value &= BWN_DMA32_TXSTATE;
3230			if (value == BWN_DMA32_TXSTAT_DISABLED) {
3231				i = -1;
3232				break;
3233			}
3234		}
3235		DELAY(1000);
3236	}
3237	if (i != -1) {
3238		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3239		return (ENODEV);
3240	}
3241	DELAY(1000);
3242
3243	return (0);
3244}
3245
3246static int
3247bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
3248    int type)
3249{
3250	struct bwn_softc *sc = mac->mac_sc;
3251	uint32_t value;
3252	int i;
3253	uint16_t offset;
3254
3255	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
3256	BWN_WRITE_4(mac, base + offset, 0);
3257	for (i = 0; i < 10; i++) {
3258		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
3259		    BWN_DMA32_RXSTATUS;
3260		value = BWN_READ_4(mac, base + offset);
3261		if (type == BWN_DMA_64BIT) {
3262			value &= BWN_DMA64_RXSTAT;
3263			if (value == BWN_DMA64_RXSTAT_DISABLED) {
3264				i = -1;
3265				break;
3266			}
3267		} else {
3268			value &= BWN_DMA32_RXSTATE;
3269			if (value == BWN_DMA32_RXSTAT_DISABLED) {
3270				i = -1;
3271				break;
3272			}
3273		}
3274		DELAY(1000);
3275	}
3276	if (i != -1) {
3277		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3278		return (ENODEV);
3279	}
3280
3281	return (0);
3282}
3283
3284static void
3285bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
3286    struct bwn_dmadesc_meta *meta)
3287{
3288
3289	if (meta->mt_m != NULL) {
3290		m_freem(meta->mt_m);
3291		meta->mt_m = NULL;
3292	}
3293	if (meta->mt_ni != NULL) {
3294		ieee80211_free_node(meta->mt_ni);
3295		meta->mt_ni = NULL;
3296	}
3297}
3298
3299static void
3300bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3301{
3302	struct bwn_rxhdr4 *rxhdr;
3303	unsigned char *frame;
3304
3305	rxhdr = mtod(m, struct bwn_rxhdr4 *);
3306	rxhdr->frame_len = 0;
3307
3308	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
3309	    sizeof(struct bwn_plcp6) + 2,
3310	    ("%s:%d: fail", __func__, __LINE__));
3311	frame = mtod(m, char *) + dr->dr_frameoffset;
3312	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
3313}
3314
3315static uint8_t
3316bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3317{
3318	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
3319
3320	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
3321	    == 0xff);
3322}
3323
3324static void
3325bwn_wme_init(struct bwn_mac *mac)
3326{
3327
3328	bwn_wme_load(mac);
3329
3330	/* enable WME support. */
3331	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
3332	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
3333	    BWN_IFSCTL_USE_EDCF);
3334}
3335
3336static void
3337bwn_spu_setdelay(struct bwn_mac *mac, int idle)
3338{
3339	struct bwn_softc *sc = mac->mac_sc;
3340	struct ieee80211com *ic = &sc->sc_ic;
3341	uint16_t delay;	/* microsec */
3342
3343	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
3344	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
3345		delay = 500;
3346	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
3347		delay = max(delay, (uint16_t)2400);
3348
3349	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
3350}
3351
3352static void
3353bwn_bt_enable(struct bwn_mac *mac)
3354{
3355	struct bwn_softc *sc = mac->mac_sc;
3356	uint64_t hf;
3357
3358	if (bwn_bluetooth == 0)
3359		return;
3360	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
3361		return;
3362	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
3363		return;
3364
3365	hf = bwn_hf_read(mac);
3366	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
3367		hf |= BWN_HF_BT_COEXISTALT;
3368	else
3369		hf |= BWN_HF_BT_COEXIST;
3370	bwn_hf_write(mac, hf);
3371}
3372
3373static void
3374bwn_set_macaddr(struct bwn_mac *mac)
3375{
3376
3377	bwn_mac_write_bssid(mac);
3378	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
3379	    mac->mac_sc->sc_ic.ic_macaddr);
3380}
3381
3382static void
3383bwn_clear_keys(struct bwn_mac *mac)
3384{
3385	int i;
3386
3387	for (i = 0; i < mac->mac_max_nr_keys; i++) {
3388		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
3389		    ("%s:%d: fail", __func__, __LINE__));
3390
3391		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
3392		    NULL, BWN_SEC_KEYSIZE, NULL);
3393		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
3394			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
3395			    NULL, BWN_SEC_KEYSIZE, NULL);
3396		}
3397		mac->mac_key[i].keyconf = NULL;
3398	}
3399}
3400
3401static void
3402bwn_crypt_init(struct bwn_mac *mac)
3403{
3404	struct bwn_softc *sc = mac->mac_sc;
3405
3406	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
3407	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
3408	    ("%s:%d: fail", __func__, __LINE__));
3409	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
3410	mac->mac_ktp *= 2;
3411	if (siba_get_revid(sc->sc_dev) >= 5)
3412		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
3413	bwn_clear_keys(mac);
3414}
3415
3416static void
3417bwn_chip_exit(struct bwn_mac *mac)
3418{
3419	struct bwn_softc *sc = mac->mac_sc;
3420
3421	bwn_phy_exit(mac);
3422	siba_gpio_set(sc->sc_dev, 0);
3423}
3424
3425static int
3426bwn_fw_fillinfo(struct bwn_mac *mac)
3427{
3428	int error;
3429
3430	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
3431	if (error == 0)
3432		return (0);
3433	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
3434	if (error == 0)
3435		return (0);
3436	return (error);
3437}
3438
3439static int
3440bwn_gpio_init(struct bwn_mac *mac)
3441{
3442	struct bwn_softc *sc = mac->mac_sc;
3443	uint32_t mask = 0x1f, set = 0xf, value;
3444
3445	BWN_WRITE_4(mac, BWN_MACCTL,
3446	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
3447	BWN_WRITE_2(mac, BWN_GPIO_MASK,
3448	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
3449
3450	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
3451		mask |= 0x0060;
3452		set |= 0x0060;
3453	}
3454	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
3455		BWN_WRITE_2(mac, BWN_GPIO_MASK,
3456		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
3457		mask |= 0x0200;
3458		set |= 0x0200;
3459	}
3460	if (siba_get_revid(sc->sc_dev) >= 2)
3461		mask |= 0x0010;
3462
3463	value = siba_gpio_get(sc->sc_dev);
3464	if (value == -1)
3465		return (0);
3466	siba_gpio_set(sc->sc_dev, (value & mask) | set);
3467
3468	return (0);
3469}
3470
3471static int
3472bwn_fw_loadinitvals(struct bwn_mac *mac)
3473{
3474#define	GETFWOFFSET(fwp, offset)				\
3475	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
3476	const size_t hdr_len = sizeof(struct bwn_fwhdr);
3477	const struct bwn_fwhdr *hdr;
3478	struct bwn_fw *fw = &mac->mac_fw;
3479	int error;
3480
3481	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
3482	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
3483	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
3484	if (error)
3485		return (error);
3486	if (fw->initvals_band.fw) {
3487		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
3488		error = bwn_fwinitvals_write(mac,
3489		    GETFWOFFSET(fw->initvals_band, hdr_len),
3490		    be32toh(hdr->size),
3491		    fw->initvals_band.fw->datasize - hdr_len);
3492	}
3493	return (error);
3494#undef GETFWOFFSET
3495}
3496
3497static int
3498bwn_phy_init(struct bwn_mac *mac)
3499{
3500	struct bwn_softc *sc = mac->mac_sc;
3501	int error;
3502
3503	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
3504	mac->mac_phy.rf_onoff(mac, 1);
3505	error = mac->mac_phy.init(mac);
3506	if (error) {
3507		device_printf(sc->sc_dev, "PHY init failed\n");
3508		goto fail0;
3509	}
3510	error = bwn_switch_channel(mac,
3511	    mac->mac_phy.get_default_chan(mac));
3512	if (error) {
3513		device_printf(sc->sc_dev,
3514		    "failed to switch default channel\n");
3515		goto fail1;
3516	}
3517	return (0);
3518fail1:
3519	if (mac->mac_phy.exit)
3520		mac->mac_phy.exit(mac);
3521fail0:
3522	mac->mac_phy.rf_onoff(mac, 0);
3523
3524	return (error);
3525}
3526
3527static void
3528bwn_set_txantenna(struct bwn_mac *mac, int antenna)
3529{
3530	uint16_t ant;
3531	uint16_t tmp;
3532
3533	ant = bwn_ant2phy(antenna);
3534
3535	/* For ACK/CTS */
3536	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
3537	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3538	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
3539	/* For Probe Resposes */
3540	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
3541	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3542	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
3543}
3544
3545static void
3546bwn_set_opmode(struct bwn_mac *mac)
3547{
3548	struct bwn_softc *sc = mac->mac_sc;
3549	struct ieee80211com *ic = &sc->sc_ic;
3550	uint32_t ctl;
3551	uint16_t cfp_pretbtt;
3552
3553	ctl = BWN_READ_4(mac, BWN_MACCTL);
3554	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
3555	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
3556	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
3557	ctl |= BWN_MACCTL_STA;
3558
3559	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
3560	    ic->ic_opmode == IEEE80211_M_MBSS)
3561		ctl |= BWN_MACCTL_HOSTAP;
3562	else if (ic->ic_opmode == IEEE80211_M_IBSS)
3563		ctl &= ~BWN_MACCTL_STA;
3564	ctl |= sc->sc_filters;
3565
3566	if (siba_get_revid(sc->sc_dev) <= 4)
3567		ctl |= BWN_MACCTL_PROMISC;
3568
3569	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
3570
3571	cfp_pretbtt = 2;
3572	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
3573		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
3574		    siba_get_chiprev(sc->sc_dev) == 3)
3575			cfp_pretbtt = 100;
3576		else
3577			cfp_pretbtt = 50;
3578	}
3579	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
3580}
3581
3582static int
3583bwn_dma_gettype(struct bwn_mac *mac)
3584{
3585	uint32_t tmp;
3586	uint16_t base;
3587
3588	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3589	if (tmp & SIBA_TGSHIGH_DMA64)
3590		return (BWN_DMA_64BIT);
3591	base = bwn_dma_base(0, 0);
3592	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3593	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3594	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3595		return (BWN_DMA_32BIT);
3596
3597	return (BWN_DMA_30BIT);
3598}
3599
3600static void
3601bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
3602{
3603	if (!error) {
3604		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
3605		*((bus_addr_t *)arg) = seg->ds_addr;
3606	}
3607}
3608
3609void
3610bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
3611{
3612	struct bwn_phy *phy = &mac->mac_phy;
3613	struct bwn_softc *sc = mac->mac_sc;
3614	unsigned int i, max_loop;
3615	uint16_t value;
3616	uint32_t buffer[5] = {
3617		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
3618	};
3619
3620	if (ofdm) {
3621		max_loop = 0x1e;
3622		buffer[0] = 0x000201cc;
3623	} else {
3624		max_loop = 0xfa;
3625		buffer[0] = 0x000b846e;
3626	}
3627
3628	BWN_ASSERT_LOCKED(mac->mac_sc);
3629
3630	for (i = 0; i < 5; i++)
3631		bwn_ram_write(mac, i * 4, buffer[i]);
3632
3633	BWN_WRITE_2(mac, 0x0568, 0x0000);
3634	BWN_WRITE_2(mac, 0x07c0,
3635	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
3636
3637	value = (ofdm ? 0x41 : 0x40);
3638	BWN_WRITE_2(mac, 0x050c, value);
3639
3640	if (phy->type == BWN_PHYTYPE_N || phy->type == BWN_PHYTYPE_LP ||
3641	    phy->type == BWN_PHYTYPE_LCN)
3642		BWN_WRITE_2(mac, 0x0514, 0x1a02);
3643	BWN_WRITE_2(mac, 0x0508, 0x0000);
3644	BWN_WRITE_2(mac, 0x050a, 0x0000);
3645	BWN_WRITE_2(mac, 0x054c, 0x0000);
3646	BWN_WRITE_2(mac, 0x056a, 0x0014);
3647	BWN_WRITE_2(mac, 0x0568, 0x0826);
3648	BWN_WRITE_2(mac, 0x0500, 0x0000);
3649
3650	/* XXX TODO: n phy pa override? */
3651
3652	switch (phy->type) {
3653	case BWN_PHYTYPE_N:
3654	case BWN_PHYTYPE_LCN:
3655		BWN_WRITE_2(mac, 0x0502, 0x00d0);
3656		break;
3657	case BWN_PHYTYPE_LP:
3658		BWN_WRITE_2(mac, 0x0502, 0x0050);
3659		break;
3660	default:
3661		BWN_WRITE_2(mac, 0x0502, 0x0030);
3662		break;
3663	}
3664
3665	/* flush */
3666	BWN_READ_2(mac, 0x0502);
3667
3668	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3669		BWN_RF_WRITE(mac, 0x0051, 0x0017);
3670	for (i = 0x00; i < max_loop; i++) {
3671		value = BWN_READ_2(mac, 0x050e);
3672		if (value & 0x0080)
3673			break;
3674		DELAY(10);
3675	}
3676	for (i = 0x00; i < 0x0a; i++) {
3677		value = BWN_READ_2(mac, 0x050e);
3678		if (value & 0x0400)
3679			break;
3680		DELAY(10);
3681	}
3682	for (i = 0x00; i < 0x19; i++) {
3683		value = BWN_READ_2(mac, 0x0690);
3684		if (!(value & 0x0100))
3685			break;
3686		DELAY(10);
3687	}
3688	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3689		BWN_RF_WRITE(mac, 0x0051, 0x0037);
3690}
3691
3692void
3693bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
3694{
3695	uint32_t macctl;
3696
3697	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
3698
3699	macctl = BWN_READ_4(mac, BWN_MACCTL);
3700	if (macctl & BWN_MACCTL_BIGENDIAN)
3701		printf("TODO: need swap\n");
3702
3703	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
3704	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
3705	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
3706}
3707
3708void
3709bwn_mac_suspend(struct bwn_mac *mac)
3710{
3711	struct bwn_softc *sc = mac->mac_sc;
3712	int i;
3713	uint32_t tmp;
3714
3715	KASSERT(mac->mac_suspended >= 0,
3716	    ("%s:%d: fail", __func__, __LINE__));
3717
3718	if (mac->mac_suspended == 0) {
3719		bwn_psctl(mac, BWN_PS_AWAKE);
3720		BWN_WRITE_4(mac, BWN_MACCTL,
3721			    BWN_READ_4(mac, BWN_MACCTL)
3722			    & ~BWN_MACCTL_ON);
3723		BWN_READ_4(mac, BWN_MACCTL);
3724		for (i = 35; i; i--) {
3725			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3726			if (tmp & BWN_INTR_MAC_SUSPENDED)
3727				goto out;
3728			DELAY(10);
3729		}
3730		for (i = 40; i; i--) {
3731			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3732			if (tmp & BWN_INTR_MAC_SUSPENDED)
3733				goto out;
3734			DELAY(1000);
3735		}
3736		device_printf(sc->sc_dev, "MAC suspend failed\n");
3737	}
3738out:
3739	mac->mac_suspended++;
3740}
3741
3742void
3743bwn_mac_enable(struct bwn_mac *mac)
3744{
3745	struct bwn_softc *sc = mac->mac_sc;
3746	uint16_t state;
3747
3748	state = bwn_shm_read_2(mac, BWN_SHARED,
3749	    BWN_SHARED_UCODESTAT);
3750	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
3751	    state != BWN_SHARED_UCODESTAT_SLEEP)
3752		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
3753
3754	mac->mac_suspended--;
3755	KASSERT(mac->mac_suspended >= 0,
3756	    ("%s:%d: fail", __func__, __LINE__));
3757	if (mac->mac_suspended == 0) {
3758		BWN_WRITE_4(mac, BWN_MACCTL,
3759		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
3760		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
3761		BWN_READ_4(mac, BWN_MACCTL);
3762		BWN_READ_4(mac, BWN_INTR_REASON);
3763		bwn_psctl(mac, 0);
3764	}
3765}
3766
3767void
3768bwn_psctl(struct bwn_mac *mac, uint32_t flags)
3769{
3770	struct bwn_softc *sc = mac->mac_sc;
3771	int i;
3772	uint16_t ucstat;
3773
3774	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
3775	    ("%s:%d: fail", __func__, __LINE__));
3776	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
3777	    ("%s:%d: fail", __func__, __LINE__));
3778
3779	/* XXX forcibly awake and hwps-off */
3780
3781	BWN_WRITE_4(mac, BWN_MACCTL,
3782	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
3783	    ~BWN_MACCTL_HWPS);
3784	BWN_READ_4(mac, BWN_MACCTL);
3785	if (siba_get_revid(sc->sc_dev) >= 5) {
3786		for (i = 0; i < 100; i++) {
3787			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
3788			    BWN_SHARED_UCODESTAT);
3789			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
3790				break;
3791			DELAY(10);
3792		}
3793	}
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 (mac->mac_fw.fw_hdr_format == BWN_FW_HDR_598) {
4190		device_printf(sc->sc_dev,
4191		    "firmware is too new (>=598); not supported\n");
4192		error = EOPNOTSUPP;
4193		goto error;
4194	}
4195
4196	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
4197	    BWN_SHARED_UCODE_PATCH);
4198	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
4199	mac->mac_fw.opensource = (date == 0xffff);
4200	if (bwn_wme != 0)
4201		mac->mac_flags |= BWN_MAC_FLAG_WME;
4202	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
4203
4204	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
4205	if (mac->mac_fw.opensource == 0) {
4206		device_printf(sc->sc_dev,
4207		    "firmware version (rev %u patch %u date %#x time %#x)\n",
4208		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
4209		if (mac->mac_fw.no_pcmfile)
4210			device_printf(sc->sc_dev,
4211			    "no HW crypto acceleration due to pcm5\n");
4212	} else {
4213		mac->mac_fw.patch = time;
4214		fwcaps = bwn_fwcaps_read(mac);
4215		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
4216			device_printf(sc->sc_dev,
4217			    "disabling HW crypto acceleration\n");
4218			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
4219		}
4220		if (!(fwcaps & BWN_FWCAPS_WME)) {
4221			device_printf(sc->sc_dev, "disabling WME support\n");
4222			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
4223		}
4224	}
4225
4226	if (BWN_ISOLDFMT(mac))
4227		device_printf(sc->sc_dev, "using old firmware image\n");
4228
4229	return (0);
4230
4231error:
4232	BWN_WRITE_4(mac, BWN_MACCTL,
4233	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
4234	    BWN_MACCTL_MCODE_JMP0);
4235
4236	return (error);
4237#undef GETFWSIZE
4238#undef GETFWOFFSET
4239}
4240
4241/* OpenFirmware only */
4242static uint16_t
4243bwn_fwcaps_read(struct bwn_mac *mac)
4244{
4245
4246	KASSERT(mac->mac_fw.opensource == 1,
4247	    ("%s:%d: fail", __func__, __LINE__));
4248	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
4249}
4250
4251static int
4252bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
4253    size_t count, size_t array_size)
4254{
4255#define	GET_NEXTIV16(iv)						\
4256	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
4257	    sizeof(uint16_t) + sizeof(uint16_t)))
4258#define	GET_NEXTIV32(iv)						\
4259	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
4260	    sizeof(uint16_t) + sizeof(uint32_t)))
4261	struct bwn_softc *sc = mac->mac_sc;
4262	const struct bwn_fwinitvals *iv;
4263	uint16_t offset;
4264	size_t i;
4265	uint8_t bit32;
4266
4267	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
4268	    ("%s:%d: fail", __func__, __LINE__));
4269	iv = ivals;
4270	for (i = 0; i < count; i++) {
4271		if (array_size < sizeof(iv->offset_size))
4272			goto fail;
4273		array_size -= sizeof(iv->offset_size);
4274		offset = be16toh(iv->offset_size);
4275		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
4276		offset &= BWN_FWINITVALS_OFFSET_MASK;
4277		if (offset >= 0x1000)
4278			goto fail;
4279		if (bit32) {
4280			if (array_size < sizeof(iv->data.d32))
4281				goto fail;
4282			array_size -= sizeof(iv->data.d32);
4283			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
4284			iv = GET_NEXTIV32(iv);
4285		} else {
4286
4287			if (array_size < sizeof(iv->data.d16))
4288				goto fail;
4289			array_size -= sizeof(iv->data.d16);
4290			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
4291
4292			iv = GET_NEXTIV16(iv);
4293		}
4294	}
4295	if (array_size != 0)
4296		goto fail;
4297	return (0);
4298fail:
4299	device_printf(sc->sc_dev, "initvals: invalid format\n");
4300	return (EPROTO);
4301#undef GET_NEXTIV16
4302#undef GET_NEXTIV32
4303}
4304
4305int
4306bwn_switch_channel(struct bwn_mac *mac, int chan)
4307{
4308	struct bwn_phy *phy = &(mac->mac_phy);
4309	struct bwn_softc *sc = mac->mac_sc;
4310	struct ieee80211com *ic = &sc->sc_ic;
4311	uint16_t channelcookie, savedcookie;
4312	int error;
4313
4314	if (chan == 0xffff)
4315		chan = phy->get_default_chan(mac);
4316
4317	channelcookie = chan;
4318	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
4319		channelcookie |= 0x100;
4320	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
4321	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
4322	error = phy->switch_channel(mac, chan);
4323	if (error)
4324		goto fail;
4325
4326	mac->mac_phy.chan = chan;
4327	DELAY(8000);
4328	return (0);
4329fail:
4330	device_printf(sc->sc_dev, "failed to switch channel\n");
4331	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
4332	return (error);
4333}
4334
4335static uint16_t
4336bwn_ant2phy(int antenna)
4337{
4338
4339	switch (antenna) {
4340	case BWN_ANT0:
4341		return (BWN_TX_PHY_ANT0);
4342	case BWN_ANT1:
4343		return (BWN_TX_PHY_ANT1);
4344	case BWN_ANT2:
4345		return (BWN_TX_PHY_ANT2);
4346	case BWN_ANT3:
4347		return (BWN_TX_PHY_ANT3);
4348	case BWN_ANTAUTO:
4349		return (BWN_TX_PHY_ANT01AUTO);
4350	}
4351	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4352	return (0);
4353}
4354
4355static void
4356bwn_wme_load(struct bwn_mac *mac)
4357{
4358	struct bwn_softc *sc = mac->mac_sc;
4359	int i;
4360
4361	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
4362	    ("%s:%d: fail", __func__, __LINE__));
4363
4364	bwn_mac_suspend(mac);
4365	for (i = 0; i < N(sc->sc_wmeParams); i++)
4366		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
4367		    bwn_wme_shm_offsets[i]);
4368	bwn_mac_enable(mac);
4369}
4370
4371static void
4372bwn_wme_loadparams(struct bwn_mac *mac,
4373    const struct wmeParams *p, uint16_t shm_offset)
4374{
4375#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
4376	struct bwn_softc *sc = mac->mac_sc;
4377	uint16_t params[BWN_NR_WMEPARAMS];
4378	int slot, tmp;
4379	unsigned int i;
4380
4381	slot = BWN_READ_2(mac, BWN_RNG) &
4382	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4383
4384	memset(&params, 0, sizeof(params));
4385
4386	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
4387	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
4388	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
4389
4390	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
4391	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4392	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
4393	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4394	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
4395	params[BWN_WMEPARAM_BSLOTS] = slot;
4396	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
4397
4398	for (i = 0; i < N(params); i++) {
4399		if (i == BWN_WMEPARAM_STATUS) {
4400			tmp = bwn_shm_read_2(mac, BWN_SHARED,
4401			    shm_offset + (i * 2));
4402			tmp |= 0x100;
4403			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4404			    tmp);
4405		} else {
4406			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4407			    params[i]);
4408		}
4409	}
4410}
4411
4412static void
4413bwn_mac_write_bssid(struct bwn_mac *mac)
4414{
4415	struct bwn_softc *sc = mac->mac_sc;
4416	uint32_t tmp;
4417	int i;
4418	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
4419
4420	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
4421	memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
4422	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
4423	    IEEE80211_ADDR_LEN);
4424
4425	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
4426		tmp = (uint32_t) (mac_bssid[i + 0]);
4427		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
4428		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
4429		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
4430		bwn_ram_write(mac, 0x20 + i, tmp);
4431	}
4432}
4433
4434static void
4435bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
4436    const uint8_t *macaddr)
4437{
4438	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
4439	uint16_t data;
4440
4441	if (!mac)
4442		macaddr = zero;
4443
4444	offset |= 0x0020;
4445	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
4446
4447	data = macaddr[0];
4448	data |= macaddr[1] << 8;
4449	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4450	data = macaddr[2];
4451	data |= macaddr[3] << 8;
4452	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4453	data = macaddr[4];
4454	data |= macaddr[5] << 8;
4455	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4456}
4457
4458static void
4459bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4460    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
4461{
4462	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
4463	uint8_t per_sta_keys_start = 8;
4464
4465	if (BWN_SEC_NEWAPI(mac))
4466		per_sta_keys_start = 4;
4467
4468	KASSERT(index < mac->mac_max_nr_keys,
4469	    ("%s:%d: fail", __func__, __LINE__));
4470	KASSERT(key_len <= BWN_SEC_KEYSIZE,
4471	    ("%s:%d: fail", __func__, __LINE__));
4472
4473	if (index >= per_sta_keys_start)
4474		bwn_key_macwrite(mac, index, NULL);
4475	if (key)
4476		memcpy(buf, key, key_len);
4477	bwn_key_write(mac, index, algorithm, buf);
4478	if (index >= per_sta_keys_start)
4479		bwn_key_macwrite(mac, index, mac_addr);
4480
4481	mac->mac_key[index].algorithm = algorithm;
4482}
4483
4484static void
4485bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
4486{
4487	struct bwn_softc *sc = mac->mac_sc;
4488	uint32_t addrtmp[2] = { 0, 0 };
4489	uint8_t start = 8;
4490
4491	if (BWN_SEC_NEWAPI(mac))
4492		start = 4;
4493
4494	KASSERT(index >= start,
4495	    ("%s:%d: fail", __func__, __LINE__));
4496	index -= start;
4497
4498	if (addr) {
4499		addrtmp[0] = addr[0];
4500		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
4501		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
4502		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
4503		addrtmp[1] = addr[4];
4504		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
4505	}
4506
4507	if (siba_get_revid(sc->sc_dev) >= 5) {
4508		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
4509		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
4510	} else {
4511		if (index >= 8) {
4512			bwn_shm_write_4(mac, BWN_SHARED,
4513			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
4514			bwn_shm_write_2(mac, BWN_SHARED,
4515			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
4516		}
4517	}
4518}
4519
4520static void
4521bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4522    const uint8_t *key)
4523{
4524	unsigned int i;
4525	uint32_t offset;
4526	uint16_t kidx, value;
4527
4528	kidx = BWN_SEC_KEY2FW(mac, index);
4529	bwn_shm_write_2(mac, BWN_SHARED,
4530	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
4531
4532	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
4533	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
4534		value = key[i];
4535		value |= (uint16_t)(key[i + 1]) << 8;
4536		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
4537	}
4538}
4539
4540static void
4541bwn_phy_exit(struct bwn_mac *mac)
4542{
4543
4544	mac->mac_phy.rf_onoff(mac, 0);
4545	if (mac->mac_phy.exit != NULL)
4546		mac->mac_phy.exit(mac);
4547}
4548
4549static void
4550bwn_dma_free(struct bwn_mac *mac)
4551{
4552	struct bwn_dma *dma;
4553
4554	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
4555		return;
4556	dma = &mac->mac_method.dma;
4557
4558	bwn_dma_ringfree(&dma->rx);
4559	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
4560	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
4561	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
4562	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
4563	bwn_dma_ringfree(&dma->mcast);
4564}
4565
4566static void
4567bwn_core_stop(struct bwn_mac *mac)
4568{
4569	struct bwn_softc *sc = mac->mac_sc;
4570
4571	BWN_ASSERT_LOCKED(sc);
4572
4573	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
4574		return;
4575
4576	callout_stop(&sc->sc_rfswitch_ch);
4577	callout_stop(&sc->sc_task_ch);
4578	callout_stop(&sc->sc_watchdog_ch);
4579	sc->sc_watchdog_timer = 0;
4580	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4581	BWN_READ_4(mac, BWN_INTR_MASK);
4582	bwn_mac_suspend(mac);
4583
4584	mac->mac_status = BWN_MAC_STATUS_INITED;
4585}
4586
4587static int
4588bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
4589{
4590	struct bwn_mac *up_dev = NULL;
4591	struct bwn_mac *down_dev;
4592	struct bwn_mac *mac;
4593	int err, status;
4594	uint8_t gmode;
4595
4596	BWN_ASSERT_LOCKED(sc);
4597
4598	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
4599		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
4600		    mac->mac_phy.supports_2ghz) {
4601			up_dev = mac;
4602			gmode = 1;
4603		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
4604		    mac->mac_phy.supports_5ghz) {
4605			up_dev = mac;
4606			gmode = 0;
4607		} else {
4608			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4609			return (EINVAL);
4610		}
4611		if (up_dev != NULL)
4612			break;
4613	}
4614	if (up_dev == NULL) {
4615		device_printf(sc->sc_dev, "Could not find a device\n");
4616		return (ENODEV);
4617	}
4618	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
4619		return (0);
4620
4621	DPRINTF(sc, BWN_DEBUG_RF | BWN_DEBUG_PHY | BWN_DEBUG_RESET,
4622	    "switching to %s-GHz band\n",
4623	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4624
4625	down_dev = sc->sc_curmac;
4626	status = down_dev->mac_status;
4627	if (status >= BWN_MAC_STATUS_STARTED)
4628		bwn_core_stop(down_dev);
4629	if (status >= BWN_MAC_STATUS_INITED)
4630		bwn_core_exit(down_dev);
4631
4632	if (down_dev != up_dev)
4633		bwn_phy_reset(down_dev);
4634
4635	up_dev->mac_phy.gmode = gmode;
4636	if (status >= BWN_MAC_STATUS_INITED) {
4637		err = bwn_core_init(up_dev);
4638		if (err) {
4639			device_printf(sc->sc_dev,
4640			    "fatal: failed to initialize for %s-GHz\n",
4641			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4642			goto fail;
4643		}
4644	}
4645	if (status >= BWN_MAC_STATUS_STARTED)
4646		bwn_core_start(up_dev);
4647	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
4648	sc->sc_curmac = up_dev;
4649
4650	return (0);
4651fail:
4652	sc->sc_curmac = NULL;
4653	return (err);
4654}
4655
4656static void
4657bwn_rf_turnon(struct bwn_mac *mac)
4658{
4659
4660	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4661
4662	bwn_mac_suspend(mac);
4663	mac->mac_phy.rf_onoff(mac, 1);
4664	mac->mac_phy.rf_on = 1;
4665	bwn_mac_enable(mac);
4666}
4667
4668static void
4669bwn_rf_turnoff(struct bwn_mac *mac)
4670{
4671
4672	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4673
4674	bwn_mac_suspend(mac);
4675	mac->mac_phy.rf_onoff(mac, 0);
4676	mac->mac_phy.rf_on = 0;
4677	bwn_mac_enable(mac);
4678}
4679
4680/*
4681 * SSB PHY reset.
4682 *
4683 * XXX TODO: BCMA PHY reset.
4684 */
4685static void
4686bwn_phy_reset(struct bwn_mac *mac)
4687{
4688	struct bwn_softc *sc = mac->mac_sc;
4689
4690	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4691	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
4692	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
4693	DELAY(1000);
4694	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4695	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC));
4696	DELAY(1000);
4697}
4698
4699static int
4700bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
4701{
4702	struct bwn_vap *bvp = BWN_VAP(vap);
4703	struct ieee80211com *ic= vap->iv_ic;
4704	enum ieee80211_state ostate = vap->iv_state;
4705	struct bwn_softc *sc = ic->ic_softc;
4706	struct bwn_mac *mac = sc->sc_curmac;
4707	int error;
4708
4709	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
4710	    ieee80211_state_name[vap->iv_state],
4711	    ieee80211_state_name[nstate]);
4712
4713	error = bvp->bv_newstate(vap, nstate, arg);
4714	if (error != 0)
4715		return (error);
4716
4717	BWN_LOCK(sc);
4718
4719	bwn_led_newstate(mac, nstate);
4720
4721	/*
4722	 * Clear the BSSID when we stop a STA
4723	 */
4724	if (vap->iv_opmode == IEEE80211_M_STA) {
4725		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
4726			/*
4727			 * Clear out the BSSID.  If we reassociate to
4728			 * the same AP, this will reinialize things
4729			 * correctly...
4730			 */
4731			if (ic->ic_opmode == IEEE80211_M_STA &&
4732			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
4733				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
4734				bwn_set_macaddr(mac);
4735			}
4736		}
4737	}
4738
4739	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
4740	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
4741		/* XXX nothing to do? */
4742	} else if (nstate == IEEE80211_S_RUN) {
4743		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
4744		bwn_set_opmode(mac);
4745		bwn_set_pretbtt(mac);
4746		bwn_spu_setdelay(mac, 0);
4747		bwn_set_macaddr(mac);
4748	}
4749
4750	BWN_UNLOCK(sc);
4751
4752	return (error);
4753}
4754
4755static void
4756bwn_set_pretbtt(struct bwn_mac *mac)
4757{
4758	struct bwn_softc *sc = mac->mac_sc;
4759	struct ieee80211com *ic = &sc->sc_ic;
4760	uint16_t pretbtt;
4761
4762	if (ic->ic_opmode == IEEE80211_M_IBSS)
4763		pretbtt = 2;
4764	else
4765		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
4766	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
4767	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
4768}
4769
4770static int
4771bwn_intr(void *arg)
4772{
4773	struct bwn_mac *mac = arg;
4774	struct bwn_softc *sc = mac->mac_sc;
4775	uint32_t reason;
4776
4777	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4778	    (sc->sc_flags & BWN_FLAG_INVALID))
4779		return (FILTER_STRAY);
4780
4781	reason = BWN_READ_4(mac, BWN_INTR_REASON);
4782	if (reason == 0xffffffff)	/* shared IRQ */
4783		return (FILTER_STRAY);
4784	reason &= mac->mac_intr_mask;
4785	if (reason == 0)
4786		return (FILTER_HANDLED);
4787
4788	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
4789	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
4790	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
4791	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
4792	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
4793	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
4794	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
4795	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
4796	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
4797	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
4798	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
4799
4800	/* Disable interrupts. */
4801	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4802
4803	mac->mac_reason_intr = reason;
4804
4805	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4806	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4807
4808	taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask);
4809	return (FILTER_HANDLED);
4810}
4811
4812static void
4813bwn_intrtask(void *arg, int npending)
4814{
4815	struct bwn_mac *mac = arg;
4816	struct bwn_softc *sc = mac->mac_sc;
4817	uint32_t merged = 0;
4818	int i, tx = 0, rx = 0;
4819
4820	BWN_LOCK(sc);
4821	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4822	    (sc->sc_flags & BWN_FLAG_INVALID)) {
4823		BWN_UNLOCK(sc);
4824		return;
4825	}
4826
4827	for (i = 0; i < N(mac->mac_reason); i++)
4828		merged |= mac->mac_reason[i];
4829
4830	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
4831		device_printf(sc->sc_dev, "MAC trans error\n");
4832
4833	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
4834		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
4835		mac->mac_phy.txerrors--;
4836		if (mac->mac_phy.txerrors == 0) {
4837			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
4838			bwn_restart(mac, "PHY TX errors");
4839		}
4840	}
4841
4842	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
4843		if (merged & BWN_DMAINTR_FATALMASK) {
4844			device_printf(sc->sc_dev,
4845			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
4846			    mac->mac_reason[0], mac->mac_reason[1],
4847			    mac->mac_reason[2], mac->mac_reason[3],
4848			    mac->mac_reason[4], mac->mac_reason[5]);
4849			bwn_restart(mac, "DMA error");
4850			BWN_UNLOCK(sc);
4851			return;
4852		}
4853		if (merged & BWN_DMAINTR_NONFATALMASK) {
4854			device_printf(sc->sc_dev,
4855			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
4856			    mac->mac_reason[0], mac->mac_reason[1],
4857			    mac->mac_reason[2], mac->mac_reason[3],
4858			    mac->mac_reason[4], mac->mac_reason[5]);
4859		}
4860	}
4861
4862	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
4863		bwn_intr_ucode_debug(mac);
4864	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
4865		bwn_intr_tbtt_indication(mac);
4866	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
4867		bwn_intr_atim_end(mac);
4868	if (mac->mac_reason_intr & BWN_INTR_BEACON)
4869		bwn_intr_beacon(mac);
4870	if (mac->mac_reason_intr & BWN_INTR_PMQ)
4871		bwn_intr_pmq(mac);
4872	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
4873		bwn_intr_noise(mac);
4874
4875	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
4876		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
4877			bwn_dma_rx(mac->mac_method.dma.rx);
4878			rx = 1;
4879		}
4880	} else
4881		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
4882
4883	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4884	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4885	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4886	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4887	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4888
4889	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
4890		bwn_intr_txeof(mac);
4891		tx = 1;
4892	}
4893
4894	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
4895
4896	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
4897		int evt = BWN_LED_EVENT_NONE;
4898
4899		if (tx && rx) {
4900			if (sc->sc_rx_rate > sc->sc_tx_rate)
4901				evt = BWN_LED_EVENT_RX;
4902			else
4903				evt = BWN_LED_EVENT_TX;
4904		} else if (tx) {
4905			evt = BWN_LED_EVENT_TX;
4906		} else if (rx) {
4907			evt = BWN_LED_EVENT_RX;
4908		} else if (rx == 0) {
4909			evt = BWN_LED_EVENT_POLL;
4910		}
4911
4912		if (evt != BWN_LED_EVENT_NONE)
4913			bwn_led_event(mac, evt);
4914       }
4915
4916	if (mbufq_first(&sc->sc_snd) != NULL)
4917		bwn_start(sc);
4918
4919	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4920	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4921
4922	BWN_UNLOCK(sc);
4923}
4924
4925static void
4926bwn_restart(struct bwn_mac *mac, const char *msg)
4927{
4928	struct bwn_softc *sc = mac->mac_sc;
4929	struct ieee80211com *ic = &sc->sc_ic;
4930
4931	if (mac->mac_status < BWN_MAC_STATUS_INITED)
4932		return;
4933
4934	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
4935	ieee80211_runtask(ic, &mac->mac_hwreset);
4936}
4937
4938static void
4939bwn_intr_ucode_debug(struct bwn_mac *mac)
4940{
4941	struct bwn_softc *sc = mac->mac_sc;
4942	uint16_t reason;
4943
4944	if (mac->mac_fw.opensource == 0)
4945		return;
4946
4947	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
4948	switch (reason) {
4949	case BWN_DEBUGINTR_PANIC:
4950		bwn_handle_fwpanic(mac);
4951		break;
4952	case BWN_DEBUGINTR_DUMP_SHM:
4953		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
4954		break;
4955	case BWN_DEBUGINTR_DUMP_REGS:
4956		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
4957		break;
4958	case BWN_DEBUGINTR_MARKER:
4959		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
4960		break;
4961	default:
4962		device_printf(sc->sc_dev,
4963		    "ucode debug unknown reason: %#x\n", reason);
4964	}
4965
4966	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
4967	    BWN_DEBUGINTR_ACK);
4968}
4969
4970static void
4971bwn_intr_tbtt_indication(struct bwn_mac *mac)
4972{
4973	struct bwn_softc *sc = mac->mac_sc;
4974	struct ieee80211com *ic = &sc->sc_ic;
4975
4976	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
4977		bwn_psctl(mac, 0);
4978	if (ic->ic_opmode == IEEE80211_M_IBSS)
4979		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
4980}
4981
4982static void
4983bwn_intr_atim_end(struct bwn_mac *mac)
4984{
4985
4986	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
4987		BWN_WRITE_4(mac, BWN_MACCMD,
4988		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
4989		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
4990	}
4991}
4992
4993static void
4994bwn_intr_beacon(struct bwn_mac *mac)
4995{
4996	struct bwn_softc *sc = mac->mac_sc;
4997	struct ieee80211com *ic = &sc->sc_ic;
4998	uint32_t cmd, beacon0, beacon1;
4999
5000	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
5001	    ic->ic_opmode == IEEE80211_M_MBSS)
5002		return;
5003
5004	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
5005
5006	cmd = BWN_READ_4(mac, BWN_MACCMD);
5007	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
5008	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
5009
5010	if (beacon0 && beacon1) {
5011		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
5012		mac->mac_intr_mask |= BWN_INTR_BEACON;
5013		return;
5014	}
5015
5016	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
5017		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
5018		bwn_load_beacon0(mac);
5019		bwn_load_beacon1(mac);
5020		cmd = BWN_READ_4(mac, BWN_MACCMD);
5021		cmd |= BWN_MACCMD_BEACON0_VALID;
5022		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5023	} else {
5024		if (!beacon0) {
5025			bwn_load_beacon0(mac);
5026			cmd = BWN_READ_4(mac, BWN_MACCMD);
5027			cmd |= BWN_MACCMD_BEACON0_VALID;
5028			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5029		} else if (!beacon1) {
5030			bwn_load_beacon1(mac);
5031			cmd = BWN_READ_4(mac, BWN_MACCMD);
5032			cmd |= BWN_MACCMD_BEACON1_VALID;
5033			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5034		}
5035	}
5036}
5037
5038static void
5039bwn_intr_pmq(struct bwn_mac *mac)
5040{
5041	uint32_t tmp;
5042
5043	while (1) {
5044		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
5045		if (!(tmp & 0x00000008))
5046			break;
5047	}
5048	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
5049}
5050
5051static void
5052bwn_intr_noise(struct bwn_mac *mac)
5053{
5054	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5055	uint16_t tmp;
5056	uint8_t noise[4];
5057	uint8_t i, j;
5058	int32_t average;
5059
5060	if (mac->mac_phy.type != BWN_PHYTYPE_G)
5061		return;
5062
5063	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
5064	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
5065	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
5066	    noise[3] == 0x7f)
5067		goto new;
5068
5069	KASSERT(mac->mac_noise.noi_nsamples < 8,
5070	    ("%s:%d: fail", __func__, __LINE__));
5071	i = mac->mac_noise.noi_nsamples;
5072	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
5073	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
5074	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
5075	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
5076	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
5077	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
5078	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
5079	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
5080	mac->mac_noise.noi_nsamples++;
5081	if (mac->mac_noise.noi_nsamples == 8) {
5082		average = 0;
5083		for (i = 0; i < 8; i++) {
5084			for (j = 0; j < 4; j++)
5085				average += mac->mac_noise.noi_samples[i][j];
5086		}
5087		average = (((average / 32) * 125) + 64) / 128;
5088		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
5089		if (tmp >= 8)
5090			average += 2;
5091		else
5092			average -= 25;
5093		average -= (tmp == 8) ? 72 : 48;
5094
5095		mac->mac_stats.link_noise = average;
5096		mac->mac_noise.noi_running = 0;
5097		return;
5098	}
5099new:
5100	bwn_noise_gensample(mac);
5101}
5102
5103static int
5104bwn_pio_rx(struct bwn_pio_rxqueue *prq)
5105{
5106	struct bwn_mac *mac = prq->prq_mac;
5107	struct bwn_softc *sc = mac->mac_sc;
5108	unsigned int i;
5109
5110	BWN_ASSERT_LOCKED(sc);
5111
5112	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
5113		return (0);
5114
5115	for (i = 0; i < 5000; i++) {
5116		if (bwn_pio_rxeof(prq) == 0)
5117			break;
5118	}
5119	if (i >= 5000)
5120		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
5121	return ((i > 0) ? 1 : 0);
5122}
5123
5124static void
5125bwn_dma_rx(struct bwn_dma_ring *dr)
5126{
5127	int slot, curslot;
5128
5129	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5130	curslot = dr->get_curslot(dr);
5131	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
5132	    ("%s:%d: fail", __func__, __LINE__));
5133
5134	slot = dr->dr_curslot;
5135	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
5136		bwn_dma_rxeof(dr, &slot);
5137
5138	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
5139	    BUS_DMASYNC_PREWRITE);
5140
5141	dr->set_curslot(dr, slot);
5142	dr->dr_curslot = slot;
5143}
5144
5145static void
5146bwn_intr_txeof(struct bwn_mac *mac)
5147{
5148	struct bwn_txstatus stat;
5149	uint32_t stat0, stat1;
5150	uint16_t tmp;
5151
5152	BWN_ASSERT_LOCKED(mac->mac_sc);
5153
5154	while (1) {
5155		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
5156		if (!(stat0 & 0x00000001))
5157			break;
5158		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
5159
5160		DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5161		    "%s: stat0=0x%08x, stat1=0x%08x\n",
5162		    __func__,
5163		    stat0,
5164		    stat1);
5165
5166		stat.cookie = (stat0 >> 16);
5167		stat.seq = (stat1 & 0x0000ffff);
5168		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
5169		tmp = (stat0 & 0x0000ffff);
5170		stat.framecnt = ((tmp & 0xf000) >> 12);
5171		stat.rtscnt = ((tmp & 0x0f00) >> 8);
5172		stat.sreason = ((tmp & 0x001c) >> 2);
5173		stat.pm = (tmp & 0x0080) ? 1 : 0;
5174		stat.im = (tmp & 0x0040) ? 1 : 0;
5175		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
5176		stat.ack = (tmp & 0x0002) ? 1 : 0;
5177
5178		DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5179		    "%s: cookie=%d, seq=%d, phystat=0x%02x, framecnt=%d, "
5180		    "rtscnt=%d, sreason=%d, pm=%d, im=%d, ampdu=%d, ack=%d\n",
5181		    __func__,
5182		    stat.cookie,
5183		    stat.seq,
5184		    stat.phy_stat,
5185		    stat.framecnt,
5186		    stat.rtscnt,
5187		    stat.sreason,
5188		    stat.pm,
5189		    stat.im,
5190		    stat.ampdu,
5191		    stat.ack);
5192
5193		bwn_handle_txeof(mac, &stat);
5194	}
5195}
5196
5197static void
5198bwn_hwreset(void *arg, int npending)
5199{
5200	struct bwn_mac *mac = arg;
5201	struct bwn_softc *sc = mac->mac_sc;
5202	int error = 0;
5203	int prev_status;
5204
5205	BWN_LOCK(sc);
5206
5207	prev_status = mac->mac_status;
5208	if (prev_status >= BWN_MAC_STATUS_STARTED)
5209		bwn_core_stop(mac);
5210	if (prev_status >= BWN_MAC_STATUS_INITED)
5211		bwn_core_exit(mac);
5212
5213	if (prev_status >= BWN_MAC_STATUS_INITED) {
5214		error = bwn_core_init(mac);
5215		if (error)
5216			goto out;
5217	}
5218	if (prev_status >= BWN_MAC_STATUS_STARTED)
5219		bwn_core_start(mac);
5220out:
5221	if (error) {
5222		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
5223		sc->sc_curmac = NULL;
5224	}
5225	BWN_UNLOCK(sc);
5226}
5227
5228static void
5229bwn_handle_fwpanic(struct bwn_mac *mac)
5230{
5231	struct bwn_softc *sc = mac->mac_sc;
5232	uint16_t reason;
5233
5234	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
5235	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
5236
5237	if (reason == BWN_FWPANIC_RESTART)
5238		bwn_restart(mac, "ucode panic");
5239}
5240
5241static void
5242bwn_load_beacon0(struct bwn_mac *mac)
5243{
5244
5245	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5246}
5247
5248static void
5249bwn_load_beacon1(struct bwn_mac *mac)
5250{
5251
5252	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5253}
5254
5255static uint32_t
5256bwn_jssi_read(struct bwn_mac *mac)
5257{
5258	uint32_t val = 0;
5259
5260	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
5261	val <<= 16;
5262	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
5263
5264	return (val);
5265}
5266
5267static void
5268bwn_noise_gensample(struct bwn_mac *mac)
5269{
5270	uint32_t jssi = 0x7f7f7f7f;
5271
5272	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
5273	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
5274	BWN_WRITE_4(mac, BWN_MACCMD,
5275	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
5276}
5277
5278static int
5279bwn_dma_freeslot(struct bwn_dma_ring *dr)
5280{
5281	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5282
5283	return (dr->dr_numslots - dr->dr_usedslot);
5284}
5285
5286static int
5287bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
5288{
5289	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5290
5291	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
5292	    ("%s:%d: fail", __func__, __LINE__));
5293	if (slot == dr->dr_numslots - 1)
5294		return (0);
5295	return (slot + 1);
5296}
5297
5298static void
5299bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
5300{
5301	struct bwn_mac *mac = dr->dr_mac;
5302	struct bwn_softc *sc = mac->mac_sc;
5303	struct bwn_dma *dma = &mac->mac_method.dma;
5304	struct bwn_dmadesc_generic *desc;
5305	struct bwn_dmadesc_meta *meta;
5306	struct bwn_rxhdr4 *rxhdr;
5307	struct mbuf *m;
5308	uint32_t macstat;
5309	int32_t tmp;
5310	int cnt = 0;
5311	uint16_t len;
5312
5313	dr->getdesc(dr, *slot, &desc, &meta);
5314
5315	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
5316	m = meta->mt_m;
5317
5318	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
5319		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5320		return;
5321	}
5322
5323	rxhdr = mtod(m, struct bwn_rxhdr4 *);
5324	len = le16toh(rxhdr->frame_len);
5325	if (len <= 0) {
5326		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5327		return;
5328	}
5329	if (bwn_dma_check_redzone(dr, m)) {
5330		device_printf(sc->sc_dev, "redzone error.\n");
5331		bwn_dma_set_redzone(dr, m);
5332		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5333		    BUS_DMASYNC_PREWRITE);
5334		return;
5335	}
5336	if (len > dr->dr_rx_bufsize) {
5337		tmp = len;
5338		while (1) {
5339			dr->getdesc(dr, *slot, &desc, &meta);
5340			bwn_dma_set_redzone(dr, meta->mt_m);
5341			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5342			    BUS_DMASYNC_PREWRITE);
5343			*slot = bwn_dma_nextslot(dr, *slot);
5344			cnt++;
5345			tmp -= dr->dr_rx_bufsize;
5346			if (tmp <= 0)
5347				break;
5348		}
5349		device_printf(sc->sc_dev, "too small buffer "
5350		       "(len %u buffer %u dropped %d)\n",
5351		       len, dr->dr_rx_bufsize, cnt);
5352		return;
5353	}
5354	macstat = le32toh(rxhdr->mac_status);
5355	if (macstat & BWN_RX_MAC_FCSERR) {
5356		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5357			device_printf(sc->sc_dev, "RX drop\n");
5358			return;
5359		}
5360	}
5361
5362	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
5363	m_adj(m, dr->dr_frameoffset);
5364
5365	bwn_rxeof(dr->dr_mac, m, rxhdr);
5366}
5367
5368static void
5369bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
5370{
5371	struct bwn_softc *sc = mac->mac_sc;
5372	struct bwn_stats *stats = &mac->mac_stats;
5373
5374	BWN_ASSERT_LOCKED(mac->mac_sc);
5375
5376	if (status->im)
5377		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
5378	if (status->ampdu)
5379		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
5380	if (status->rtscnt) {
5381		if (status->rtscnt == 0xf)
5382			stats->rtsfail++;
5383		else
5384			stats->rts++;
5385	}
5386
5387	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
5388		bwn_dma_handle_txeof(mac, status);
5389	} else {
5390		bwn_pio_handle_txeof(mac, status);
5391	}
5392
5393	bwn_phy_txpower_check(mac, 0);
5394}
5395
5396static uint8_t
5397bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
5398{
5399	struct bwn_mac *mac = prq->prq_mac;
5400	struct bwn_softc *sc = mac->mac_sc;
5401	struct bwn_rxhdr4 rxhdr;
5402	struct mbuf *m;
5403	uint32_t ctl32, macstat, v32;
5404	unsigned int i, padding;
5405	uint16_t ctl16, len, totlen, v16;
5406	unsigned char *mp;
5407	char *data;
5408
5409	memset(&rxhdr, 0, sizeof(rxhdr));
5410
5411	if (prq->prq_rev >= 8) {
5412		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5413		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
5414			return (0);
5415		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5416		    BWN_PIO8_RXCTL_FRAMEREADY);
5417		for (i = 0; i < 10; i++) {
5418			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5419			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
5420				goto ready;
5421			DELAY(10);
5422		}
5423	} else {
5424		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5425		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
5426			return (0);
5427		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
5428		    BWN_PIO_RXCTL_FRAMEREADY);
5429		for (i = 0; i < 10; i++) {
5430			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5431			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
5432				goto ready;
5433			DELAY(10);
5434		}
5435	}
5436	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
5437	return (1);
5438ready:
5439	if (prq->prq_rev >= 8)
5440		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5441		    prq->prq_base + BWN_PIO8_RXDATA);
5442	else
5443		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5444		    prq->prq_base + BWN_PIO_RXDATA);
5445	len = le16toh(rxhdr.frame_len);
5446	if (len > 0x700) {
5447		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
5448		goto error;
5449	}
5450	if (len == 0) {
5451		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
5452		goto error;
5453	}
5454
5455	macstat = le32toh(rxhdr.mac_status);
5456	if (macstat & BWN_RX_MAC_FCSERR) {
5457		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5458			device_printf(sc->sc_dev, "%s: FCS error", __func__);
5459			goto error;
5460		}
5461	}
5462
5463	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5464	totlen = len + padding;
5465	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
5466	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5467	if (m == NULL) {
5468		device_printf(sc->sc_dev, "%s: out of memory", __func__);
5469		goto error;
5470	}
5471	mp = mtod(m, unsigned char *);
5472	if (prq->prq_rev >= 8) {
5473		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
5474		    prq->prq_base + BWN_PIO8_RXDATA);
5475		if (totlen & 3) {
5476			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
5477			data = &(mp[totlen - 1]);
5478			switch (totlen & 3) {
5479			case 3:
5480				*data = (v32 >> 16);
5481				data--;
5482			case 2:
5483				*data = (v32 >> 8);
5484				data--;
5485			case 1:
5486				*data = v32;
5487			}
5488		}
5489	} else {
5490		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
5491		    prq->prq_base + BWN_PIO_RXDATA);
5492		if (totlen & 1) {
5493			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
5494			mp[totlen - 1] = v16;
5495		}
5496	}
5497
5498	m->m_len = m->m_pkthdr.len = totlen;
5499
5500	bwn_rxeof(prq->prq_mac, m, &rxhdr);
5501
5502	return (1);
5503error:
5504	if (prq->prq_rev >= 8)
5505		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5506		    BWN_PIO8_RXCTL_DATAREADY);
5507	else
5508		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
5509	return (1);
5510}
5511
5512static int
5513bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
5514    struct bwn_dmadesc_meta *meta, int init)
5515{
5516	struct bwn_mac *mac = dr->dr_mac;
5517	struct bwn_dma *dma = &mac->mac_method.dma;
5518	struct bwn_rxhdr4 *hdr;
5519	bus_dmamap_t map;
5520	bus_addr_t paddr;
5521	struct mbuf *m;
5522	int error;
5523
5524	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5525	if (m == NULL) {
5526		error = ENOBUFS;
5527
5528		/*
5529		 * If the NIC is up and running, we need to:
5530		 * - Clear RX buffer's header.
5531		 * - Restore RX descriptor settings.
5532		 */
5533		if (init)
5534			return (error);
5535		else
5536			goto back;
5537	}
5538	m->m_len = m->m_pkthdr.len = MCLBYTES;
5539
5540	bwn_dma_set_redzone(dr, m);
5541
5542	/*
5543	 * Try to load RX buf into temporary DMA map
5544	 */
5545	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
5546	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
5547	if (error) {
5548		m_freem(m);
5549
5550		/*
5551		 * See the comment above
5552		 */
5553		if (init)
5554			return (error);
5555		else
5556			goto back;
5557	}
5558
5559	if (!init)
5560		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
5561	meta->mt_m = m;
5562	meta->mt_paddr = paddr;
5563
5564	/*
5565	 * Swap RX buf's DMA map with the loaded temporary one
5566	 */
5567	map = meta->mt_dmap;
5568	meta->mt_dmap = dr->dr_spare_dmap;
5569	dr->dr_spare_dmap = map;
5570
5571back:
5572	/*
5573	 * Clear RX buf header
5574	 */
5575	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
5576	bzero(hdr, sizeof(*hdr));
5577	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5578	    BUS_DMASYNC_PREWRITE);
5579
5580	/*
5581	 * Setup RX buf descriptor
5582	 */
5583	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
5584	    sizeof(*hdr), 0, 0, 0);
5585	return (error);
5586}
5587
5588static void
5589bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
5590		 bus_size_t mapsz __unused, int error)
5591{
5592
5593	if (!error) {
5594		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
5595		*((bus_addr_t *)arg) = seg->ds_addr;
5596	}
5597}
5598
5599static int
5600bwn_hwrate2ieeerate(int rate)
5601{
5602
5603	switch (rate) {
5604	case BWN_CCK_RATE_1MB:
5605		return (2);
5606	case BWN_CCK_RATE_2MB:
5607		return (4);
5608	case BWN_CCK_RATE_5MB:
5609		return (11);
5610	case BWN_CCK_RATE_11MB:
5611		return (22);
5612	case BWN_OFDM_RATE_6MB:
5613		return (12);
5614	case BWN_OFDM_RATE_9MB:
5615		return (18);
5616	case BWN_OFDM_RATE_12MB:
5617		return (24);
5618	case BWN_OFDM_RATE_18MB:
5619		return (36);
5620	case BWN_OFDM_RATE_24MB:
5621		return (48);
5622	case BWN_OFDM_RATE_36MB:
5623		return (72);
5624	case BWN_OFDM_RATE_48MB:
5625		return (96);
5626	case BWN_OFDM_RATE_54MB:
5627		return (108);
5628	default:
5629		printf("Ooops\n");
5630		return (0);
5631	}
5632}
5633
5634/*
5635 * Post process the RX provided RSSI.
5636 *
5637 * Valid for A, B, G, LP PHYs.
5638 */
5639static int8_t
5640bwn_rx_rssi_calc(struct bwn_mac *mac, uint8_t in_rssi,
5641    int ofdm, int adjust_2053, int adjust_2050)
5642{
5643	struct bwn_phy *phy = &mac->mac_phy;
5644	struct bwn_phy_g *gphy = &phy->phy_g;
5645	int tmp;
5646
5647	switch (phy->rf_ver) {
5648	case 0x2050:
5649		if (ofdm) {
5650			tmp = in_rssi;
5651			if (tmp > 127)
5652				tmp -= 256;
5653			tmp = tmp * 73 / 64;
5654			if (adjust_2050)
5655				tmp += 25;
5656			else
5657				tmp -= 3;
5658		} else {
5659			if (siba_sprom_get_bf_lo(mac->mac_sc->sc_dev)
5660			    & BWN_BFL_RSSI) {
5661				if (in_rssi > 63)
5662					in_rssi = 63;
5663				tmp = gphy->pg_nrssi_lt[in_rssi];
5664				tmp = (31 - tmp) * -131 / 128 - 57;
5665			} else {
5666				tmp = in_rssi;
5667				tmp = (31 - tmp) * -149 / 128 - 68;
5668			}
5669			if (phy->type == BWN_PHYTYPE_G && adjust_2050)
5670				tmp += 25;
5671		}
5672		break;
5673	case 0x2060:
5674		if (in_rssi > 127)
5675			tmp = in_rssi - 256;
5676		else
5677			tmp = in_rssi;
5678		break;
5679	default:
5680		tmp = in_rssi;
5681		tmp = (tmp - 11) * 103 / 64;
5682		if (adjust_2053)
5683			tmp -= 109;
5684		else
5685			tmp -= 83;
5686	}
5687
5688	return (tmp);
5689}
5690
5691static void
5692bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
5693{
5694	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
5695	struct bwn_plcp6 *plcp;
5696	struct bwn_softc *sc = mac->mac_sc;
5697	struct ieee80211_frame_min *wh;
5698	struct ieee80211_node *ni;
5699	struct ieee80211com *ic = &sc->sc_ic;
5700	uint32_t macstat;
5701	int padding, rate, rssi = 0, noise = 0, type;
5702	uint16_t phytype, phystat0, phystat3, chanstat;
5703	unsigned char *mp = mtod(m, unsigned char *);
5704	static int rx_mac_dec_rpt = 0;
5705
5706	BWN_ASSERT_LOCKED(sc);
5707
5708	phystat0 = le16toh(rxhdr->phy_status0);
5709	phystat3 = le16toh(rxhdr->phy_status3);
5710
5711	/* XXX Note: mactime, macstat, chanstat need fixing for fw 598 */
5712	macstat = le32toh(rxhdr->mac_status);
5713	chanstat = le16toh(rxhdr->channel);
5714
5715	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
5716
5717	if (macstat & BWN_RX_MAC_FCSERR)
5718		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
5719	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
5720		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
5721	if (macstat & BWN_RX_MAC_DECERR)
5722		goto drop;
5723
5724	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5725	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
5726		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5727		    m->m_pkthdr.len);
5728		goto drop;
5729	}
5730	plcp = (struct bwn_plcp6 *)(mp + padding);
5731	m_adj(m, sizeof(struct bwn_plcp6) + padding);
5732	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
5733		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5734		    m->m_pkthdr.len);
5735		goto drop;
5736	}
5737	wh = mtod(m, struct ieee80211_frame_min *);
5738
5739	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
5740		device_printf(sc->sc_dev,
5741		    "RX decryption attempted (old %d keyidx %#x)\n",
5742		    BWN_ISOLDFMT(mac),
5743		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
5744
5745	if (phystat0 & BWN_RX_PHYST0_OFDM)
5746		rate = bwn_plcp_get_ofdmrate(mac, plcp,
5747		    phytype == BWN_PHYTYPE_A);
5748	else
5749		rate = bwn_plcp_get_cckrate(mac, plcp);
5750	if (rate == -1) {
5751		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
5752			goto drop;
5753	}
5754	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
5755
5756	/* rssi/noise */
5757	switch (phytype) {
5758	case BWN_PHYTYPE_A:
5759	case BWN_PHYTYPE_B:
5760	case BWN_PHYTYPE_G:
5761	case BWN_PHYTYPE_LP:
5762		rssi = bwn_rx_rssi_calc(mac, rxhdr->phy.abg.rssi,
5763		    !! (phystat0 & BWN_RX_PHYST0_OFDM),
5764		    !! (phystat0 & BWN_RX_PHYST0_GAINCTL),
5765		    !! (phystat3 & BWN_RX_PHYST3_TRSTATE));
5766		break;
5767	case BWN_PHYTYPE_N:
5768		/* Broadcom has code for min/avg, but always used max */
5769		if (rxhdr->phy.n.power0 == 16 || rxhdr->phy.n.power0 == 32)
5770			rssi = max(rxhdr->phy.n.power1, rxhdr->ps2.n.power2);
5771		else
5772			rssi = max(rxhdr->phy.n.power0, rxhdr->phy.n.power1);
5773		break;
5774	default:
5775		/* XXX TODO: implement rssi for other PHYs */
5776		break;
5777	}
5778
5779	noise = mac->mac_stats.link_noise;
5780
5781	/* RX radio tap */
5782	if (ieee80211_radiotap_active(ic))
5783		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
5784	m_adj(m, -IEEE80211_CRC_LEN);
5785
5786	BWN_UNLOCK(sc);
5787
5788	ni = ieee80211_find_rxnode(ic, wh);
5789	if (ni != NULL) {
5790		type = ieee80211_input(ni, m, rssi, noise);
5791		ieee80211_free_node(ni);
5792	} else
5793		type = ieee80211_input_all(ic, m, rssi, noise);
5794
5795	BWN_LOCK(sc);
5796	return;
5797drop:
5798	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
5799}
5800
5801static void
5802bwn_dma_handle_txeof(struct bwn_mac *mac,
5803    const struct bwn_txstatus *status)
5804{
5805	struct bwn_dma *dma = &mac->mac_method.dma;
5806	struct bwn_dma_ring *dr;
5807	struct bwn_dmadesc_generic *desc;
5808	struct bwn_dmadesc_meta *meta;
5809	struct bwn_softc *sc = mac->mac_sc;
5810	int slot;
5811	int retrycnt = 0;
5812
5813	BWN_ASSERT_LOCKED(sc);
5814
5815	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
5816	if (dr == NULL) {
5817		device_printf(sc->sc_dev, "failed to parse cookie\n");
5818		return;
5819	}
5820	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5821
5822	while (1) {
5823		KASSERT(slot >= 0 && slot < dr->dr_numslots,
5824		    ("%s:%d: fail", __func__, __LINE__));
5825		dr->getdesc(dr, slot, &desc, &meta);
5826
5827		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
5828			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
5829		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
5830			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
5831
5832		if (meta->mt_islast) {
5833			KASSERT(meta->mt_m != NULL,
5834			    ("%s:%d: fail", __func__, __LINE__));
5835
5836			/*
5837			 * If we don't get an ACK, then we should log the
5838			 * full framecnt.  That may be 0 if it's a PHY
5839			 * failure, so ensure that gets logged as some
5840			 * retry attempt.
5841			 */
5842			if (status->ack) {
5843				retrycnt = status->framecnt - 1;
5844			} else {
5845				retrycnt = status->framecnt;
5846				if (retrycnt == 0)
5847					retrycnt = 1;
5848			}
5849			ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni,
5850			    status->ack ?
5851			      IEEE80211_RATECTL_TX_SUCCESS :
5852			      IEEE80211_RATECTL_TX_FAILURE,
5853			    &retrycnt, 0);
5854			ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
5855			meta->mt_ni = NULL;
5856			meta->mt_m = NULL;
5857		} else
5858			KASSERT(meta->mt_m == NULL,
5859			    ("%s:%d: fail", __func__, __LINE__));
5860
5861		dr->dr_usedslot--;
5862		if (meta->mt_islast)
5863			break;
5864		slot = bwn_dma_nextslot(dr, slot);
5865	}
5866	sc->sc_watchdog_timer = 0;
5867	if (dr->dr_stop) {
5868		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
5869		    ("%s:%d: fail", __func__, __LINE__));
5870		dr->dr_stop = 0;
5871	}
5872}
5873
5874static void
5875bwn_pio_handle_txeof(struct bwn_mac *mac,
5876    const struct bwn_txstatus *status)
5877{
5878	struct bwn_pio_txqueue *tq;
5879	struct bwn_pio_txpkt *tp = NULL;
5880	struct bwn_softc *sc = mac->mac_sc;
5881	int retrycnt = 0;
5882
5883	BWN_ASSERT_LOCKED(sc);
5884
5885	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
5886	if (tq == NULL)
5887		return;
5888
5889	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
5890	tq->tq_free++;
5891
5892	if (tp->tp_ni != NULL) {
5893		/*
5894		 * Do any tx complete callback.  Note this must
5895		 * be done before releasing the node reference.
5896		 */
5897
5898		/*
5899		 * If we don't get an ACK, then we should log the
5900		 * full framecnt.  That may be 0 if it's a PHY
5901		 * failure, so ensure that gets logged as some
5902		 * retry attempt.
5903		 */
5904		if (status->ack) {
5905			retrycnt = status->framecnt - 1;
5906		} else {
5907			retrycnt = status->framecnt;
5908			if (retrycnt == 0)
5909				retrycnt = 1;
5910		}
5911		ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni,
5912		    status->ack ?
5913		      IEEE80211_RATECTL_TX_SUCCESS :
5914		      IEEE80211_RATECTL_TX_FAILURE,
5915		    &retrycnt, 0);
5916
5917		if (tp->tp_m->m_flags & M_TXCB)
5918			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
5919		ieee80211_free_node(tp->tp_ni);
5920		tp->tp_ni = NULL;
5921	}
5922	m_freem(tp->tp_m);
5923	tp->tp_m = NULL;
5924	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
5925
5926	sc->sc_watchdog_timer = 0;
5927}
5928
5929static void
5930bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
5931{
5932	struct bwn_softc *sc = mac->mac_sc;
5933	struct bwn_phy *phy = &mac->mac_phy;
5934	struct ieee80211com *ic = &sc->sc_ic;
5935	unsigned long now;
5936	bwn_txpwr_result_t result;
5937
5938	BWN_GETTIME(now);
5939
5940	if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime))
5941		return;
5942	phy->nexttime = now + 2 * 1000;
5943
5944	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
5945	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
5946		return;
5947
5948	if (phy->recalc_txpwr != NULL) {
5949		result = phy->recalc_txpwr(mac,
5950		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
5951		if (result == BWN_TXPWR_RES_DONE)
5952			return;
5953		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
5954		    ("%s: fail", __func__));
5955		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
5956
5957		ieee80211_runtask(ic, &mac->mac_txpower);
5958	}
5959}
5960
5961static uint16_t
5962bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
5963{
5964
5965	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
5966}
5967
5968static uint32_t
5969bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
5970{
5971
5972	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
5973}
5974
5975static void
5976bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
5977{
5978
5979	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
5980}
5981
5982static void
5983bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
5984{
5985
5986	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
5987}
5988
5989static int
5990bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
5991{
5992
5993	switch (rate) {
5994	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
5995	case 12:
5996		return (BWN_OFDM_RATE_6MB);
5997	case 18:
5998		return (BWN_OFDM_RATE_9MB);
5999	case 24:
6000		return (BWN_OFDM_RATE_12MB);
6001	case 36:
6002		return (BWN_OFDM_RATE_18MB);
6003	case 48:
6004		return (BWN_OFDM_RATE_24MB);
6005	case 72:
6006		return (BWN_OFDM_RATE_36MB);
6007	case 96:
6008		return (BWN_OFDM_RATE_48MB);
6009	case 108:
6010		return (BWN_OFDM_RATE_54MB);
6011	/* CCK rates (NB: not IEEE std, device-specific) */
6012	case 2:
6013		return (BWN_CCK_RATE_1MB);
6014	case 4:
6015		return (BWN_CCK_RATE_2MB);
6016	case 11:
6017		return (BWN_CCK_RATE_5MB);
6018	case 22:
6019		return (BWN_CCK_RATE_11MB);
6020	}
6021
6022	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
6023	return (BWN_CCK_RATE_1MB);
6024}
6025
6026static uint16_t
6027bwn_set_txhdr_phyctl1(struct bwn_mac *mac, uint8_t bitrate)
6028{
6029	struct bwn_phy *phy = &mac->mac_phy;
6030	uint16_t control = 0;
6031	uint16_t bw;
6032
6033	/* XXX TODO: this is for LP phy, what about N-PHY, etc? */
6034	bw = BWN_TXH_PHY1_BW_20;
6035
6036	if (BWN_ISCCKRATE(bitrate) && phy->type != BWN_PHYTYPE_LP) {
6037		control = bw;
6038	} else {
6039		control = bw;
6040		/* Figure out coding rate and modulation */
6041		/* XXX TODO: table-ize, for MCS transmit */
6042		/* Note: this is BWN_*_RATE values */
6043		switch (bitrate) {
6044		case BWN_CCK_RATE_1MB:
6045			control |= 0;
6046			break;
6047		case BWN_CCK_RATE_2MB:
6048			control |= 1;
6049			break;
6050		case BWN_CCK_RATE_5MB:
6051			control |= 2;
6052			break;
6053		case BWN_CCK_RATE_11MB:
6054			control |= 3;
6055			break;
6056		case BWN_OFDM_RATE_6MB:
6057			control |= BWN_TXH_PHY1_CRATE_1_2;
6058			control |= BWN_TXH_PHY1_MODUL_BPSK;
6059			break;
6060		case BWN_OFDM_RATE_9MB:
6061			control |= BWN_TXH_PHY1_CRATE_3_4;
6062			control |= BWN_TXH_PHY1_MODUL_BPSK;
6063			break;
6064		case BWN_OFDM_RATE_12MB:
6065			control |= BWN_TXH_PHY1_CRATE_1_2;
6066			control |= BWN_TXH_PHY1_MODUL_QPSK;
6067			break;
6068		case BWN_OFDM_RATE_18MB:
6069			control |= BWN_TXH_PHY1_CRATE_3_4;
6070			control |= BWN_TXH_PHY1_MODUL_QPSK;
6071			break;
6072		case BWN_OFDM_RATE_24MB:
6073			control |= BWN_TXH_PHY1_CRATE_1_2;
6074			control |= BWN_TXH_PHY1_MODUL_QAM16;
6075			break;
6076		case BWN_OFDM_RATE_36MB:
6077			control |= BWN_TXH_PHY1_CRATE_3_4;
6078			control |= BWN_TXH_PHY1_MODUL_QAM16;
6079			break;
6080		case BWN_OFDM_RATE_48MB:
6081			control |= BWN_TXH_PHY1_CRATE_1_2;
6082			control |= BWN_TXH_PHY1_MODUL_QAM64;
6083			break;
6084		case BWN_OFDM_RATE_54MB:
6085			control |= BWN_TXH_PHY1_CRATE_3_4;
6086			control |= BWN_TXH_PHY1_MODUL_QAM64;
6087			break;
6088		default:
6089			break;
6090		}
6091		control |= BWN_TXH_PHY1_MODE_SISO;
6092	}
6093
6094	return control;
6095}
6096
6097static int
6098bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
6099    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
6100{
6101	const struct bwn_phy *phy = &mac->mac_phy;
6102	struct bwn_softc *sc = mac->mac_sc;
6103	struct ieee80211_frame *wh;
6104	struct ieee80211_frame *protwh;
6105	struct ieee80211_frame_cts *cts;
6106	struct ieee80211_frame_rts *rts;
6107	const struct ieee80211_txparam *tp;
6108	struct ieee80211vap *vap = ni->ni_vap;
6109	struct ieee80211com *ic = &sc->sc_ic;
6110	struct mbuf *mprot;
6111	unsigned int len;
6112	uint32_t macctl = 0;
6113	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
6114	uint16_t phyctl = 0;
6115	uint8_t rate, rate_fb;
6116	int fill_phy_ctl1 = 0;
6117
6118	wh = mtod(m, struct ieee80211_frame *);
6119	memset(txhdr, 0, sizeof(*txhdr));
6120
6121	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
6122	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
6123	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
6124
6125	if ((phy->type == BWN_PHYTYPE_N) || (phy->type == BWN_PHYTYPE_LP)
6126	    || (phy->type == BWN_PHYTYPE_HT))
6127		fill_phy_ctl1 = 1;
6128
6129	/*
6130	 * Find TX rate
6131	 */
6132	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
6133	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
6134		rate = rate_fb = tp->mgmtrate;
6135	else if (ismcast)
6136		rate = rate_fb = tp->mcastrate;
6137	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
6138		rate = rate_fb = tp->ucastrate;
6139	else {
6140		/* XXX TODO: don't fall back to CCK rates for OFDM */
6141		rix = ieee80211_ratectl_rate(ni, NULL, 0);
6142		rate = ni->ni_txrate;
6143
6144		if (rix > 0)
6145			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
6146			    IEEE80211_RATE_VAL;
6147		else
6148			rate_fb = rate;
6149	}
6150
6151	sc->sc_tx_rate = rate;
6152
6153	/* Note: this maps the select ieee80211 rate to hardware rate */
6154	rate = bwn_ieeerate2hwrate(sc, rate);
6155	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
6156
6157	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
6158	    bwn_plcp_getcck(rate);
6159	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
6160	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
6161
6162	/* XXX rate/rate_fb is the hardware rate */
6163	if ((rate_fb == rate) ||
6164	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
6165	    (*(u_int16_t *)wh->i_dur == htole16(0)))
6166		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
6167	else
6168		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
6169		    m->m_pkthdr.len, rate, isshort);
6170
6171	/* XXX TX encryption */
6172	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
6173	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
6174	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
6175	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6176	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
6177	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
6178
6179	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
6180	    BWN_TX_EFT_FB_CCK;
6181	txhdr->chan = phy->chan;
6182	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
6183	    BWN_TX_PHY_ENC_CCK;
6184	/* XXX preamble? obey net80211 */
6185	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6186	     rate == BWN_CCK_RATE_11MB))
6187		phyctl |= BWN_TX_PHY_SHORTPRMBL;
6188
6189	if (! phy->gmode)
6190		macctl |= BWN_TX_MAC_5GHZ;
6191
6192	/* XXX TX antenna selection */
6193
6194	switch (bwn_antenna_sanitize(mac, 0)) {
6195	case 0:
6196		phyctl |= BWN_TX_PHY_ANT01AUTO;
6197		break;
6198	case 1:
6199		phyctl |= BWN_TX_PHY_ANT0;
6200		break;
6201	case 2:
6202		phyctl |= BWN_TX_PHY_ANT1;
6203		break;
6204	case 3:
6205		phyctl |= BWN_TX_PHY_ANT2;
6206		break;
6207	case 4:
6208		phyctl |= BWN_TX_PHY_ANT3;
6209		break;
6210	default:
6211		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6212	}
6213
6214	if (!ismcast)
6215		macctl |= BWN_TX_MAC_ACK;
6216
6217	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
6218	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
6219	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
6220		macctl |= BWN_TX_MAC_LONGFRAME;
6221
6222	if (ic->ic_flags & IEEE80211_F_USEPROT) {
6223		/* XXX RTS rate is always 1MB??? */
6224		/* XXX TODO: don't fall back to CCK rates for OFDM */
6225		rts_rate = BWN_CCK_RATE_1MB;
6226		rts_rate_fb = bwn_get_fbrate(rts_rate);
6227
6228		/* XXX 'rate' here is hardware rate now, not the net80211 rate */
6229		protdur = ieee80211_compute_duration(ic->ic_rt,
6230		    m->m_pkthdr.len, rate, isshort) +
6231		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
6232
6233		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
6234			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
6235			    (txhdr->body.old.rts_frame) :
6236			    (txhdr->body.new.rts_frame));
6237			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
6238			    protdur);
6239			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
6240			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
6241			    mprot->m_pkthdr.len);
6242			m_freem(mprot);
6243			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
6244			len = sizeof(struct ieee80211_frame_cts);
6245		} else {
6246			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
6247			    (txhdr->body.old.rts_frame) :
6248			    (txhdr->body.new.rts_frame));
6249			/* XXX rate/rate_fb is the hardware rate */
6250			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
6251			    isshort);
6252			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
6253			    wh->i_addr2, protdur);
6254			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
6255			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
6256			    mprot->m_pkthdr.len);
6257			m_freem(mprot);
6258			macctl |= BWN_TX_MAC_SEND_RTSCTS;
6259			len = sizeof(struct ieee80211_frame_rts);
6260		}
6261		len += IEEE80211_CRC_LEN;
6262		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
6263		    &txhdr->body.old.rts_plcp :
6264		    &txhdr->body.new.rts_plcp), len, rts_rate);
6265		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
6266		    rts_rate_fb);
6267
6268		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
6269		    (&txhdr->body.old.rts_frame) :
6270		    (&txhdr->body.new.rts_frame));
6271		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
6272
6273		if (BWN_ISOFDMRATE(rts_rate)) {
6274			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
6275			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
6276		} else {
6277			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
6278			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
6279		}
6280		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
6281		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
6282
6283		if (fill_phy_ctl1) {
6284			txhdr->phyctl_1rts = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate));
6285			txhdr->phyctl_1rtsfb = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate_fb));
6286		}
6287	}
6288
6289	if (fill_phy_ctl1) {
6290		txhdr->phyctl_1 = htole16(bwn_set_txhdr_phyctl1(mac, rate));
6291		txhdr->phyctl_1fb = htole16(bwn_set_txhdr_phyctl1(mac, rate_fb));
6292	}
6293
6294	if (BWN_ISOLDFMT(mac))
6295		txhdr->body.old.cookie = htole16(cookie);
6296	else
6297		txhdr->body.new.cookie = htole16(cookie);
6298
6299	txhdr->macctl = htole32(macctl);
6300	txhdr->phyctl = htole16(phyctl);
6301
6302	/*
6303	 * TX radio tap
6304	 */
6305	if (ieee80211_radiotap_active_vap(vap)) {
6306		sc->sc_tx_th.wt_flags = 0;
6307		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6308			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
6309		if (isshort &&
6310		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6311		     rate == BWN_CCK_RATE_11MB))
6312			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6313		sc->sc_tx_th.wt_rate = rate;
6314
6315		ieee80211_radiotap_tx(vap, m);
6316	}
6317
6318	return (0);
6319}
6320
6321static void
6322bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
6323    const uint8_t rate)
6324{
6325	uint32_t d, plen;
6326	uint8_t *raw = plcp->o.raw;
6327
6328	if (BWN_ISOFDMRATE(rate)) {
6329		d = bwn_plcp_getofdm(rate);
6330		KASSERT(!(octets & 0xf000),
6331		    ("%s:%d: fail", __func__, __LINE__));
6332		d |= (octets << 5);
6333		plcp->o.data = htole32(d);
6334	} else {
6335		plen = octets * 16 / rate;
6336		if ((octets * 16 % rate) > 0) {
6337			plen++;
6338			if ((rate == BWN_CCK_RATE_11MB)
6339			    && ((octets * 8 % 11) < 4)) {
6340				raw[1] = 0x84;
6341			} else
6342				raw[1] = 0x04;
6343		} else
6344			raw[1] = 0x04;
6345		plcp->o.data |= htole32(plen << 16);
6346		raw[0] = bwn_plcp_getcck(rate);
6347	}
6348}
6349
6350static uint8_t
6351bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
6352{
6353	struct bwn_softc *sc = mac->mac_sc;
6354	uint8_t mask;
6355
6356	if (n == 0)
6357		return (0);
6358	if (mac->mac_phy.gmode)
6359		mask = siba_sprom_get_ant_bg(sc->sc_dev);
6360	else
6361		mask = siba_sprom_get_ant_a(sc->sc_dev);
6362	if (!(mask & (1 << (n - 1))))
6363		return (0);
6364	return (n);
6365}
6366
6367/*
6368 * Return a fallback rate for the given rate.
6369 *
6370 * Note: Don't fall back from OFDM to CCK.
6371 */
6372static uint8_t
6373bwn_get_fbrate(uint8_t bitrate)
6374{
6375	switch (bitrate) {
6376	/* CCK */
6377	case BWN_CCK_RATE_1MB:
6378		return (BWN_CCK_RATE_1MB);
6379	case BWN_CCK_RATE_2MB:
6380		return (BWN_CCK_RATE_1MB);
6381	case BWN_CCK_RATE_5MB:
6382		return (BWN_CCK_RATE_2MB);
6383	case BWN_CCK_RATE_11MB:
6384		return (BWN_CCK_RATE_5MB);
6385
6386	/* OFDM */
6387	case BWN_OFDM_RATE_6MB:
6388		return (BWN_OFDM_RATE_6MB);
6389	case BWN_OFDM_RATE_9MB:
6390		return (BWN_OFDM_RATE_6MB);
6391	case BWN_OFDM_RATE_12MB:
6392		return (BWN_OFDM_RATE_9MB);
6393	case BWN_OFDM_RATE_18MB:
6394		return (BWN_OFDM_RATE_12MB);
6395	case BWN_OFDM_RATE_24MB:
6396		return (BWN_OFDM_RATE_18MB);
6397	case BWN_OFDM_RATE_36MB:
6398		return (BWN_OFDM_RATE_24MB);
6399	case BWN_OFDM_RATE_48MB:
6400		return (BWN_OFDM_RATE_36MB);
6401	case BWN_OFDM_RATE_54MB:
6402		return (BWN_OFDM_RATE_48MB);
6403	}
6404	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6405	return (0);
6406}
6407
6408static uint32_t
6409bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6410    uint32_t ctl, const void *_data, int len)
6411{
6412	struct bwn_softc *sc = mac->mac_sc;
6413	uint32_t value = 0;
6414	const uint8_t *data = _data;
6415
6416	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
6417	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
6418	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6419
6420	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
6421	    tq->tq_base + BWN_PIO8_TXDATA);
6422	if (len & 3) {
6423		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
6424		    BWN_PIO8_TXCTL_24_31);
6425		data = &(data[len - 1]);
6426		switch (len & 3) {
6427		case 3:
6428			ctl |= BWN_PIO8_TXCTL_16_23;
6429			value |= (uint32_t)(*data) << 16;
6430			data--;
6431		case 2:
6432			ctl |= BWN_PIO8_TXCTL_8_15;
6433			value |= (uint32_t)(*data) << 8;
6434			data--;
6435		case 1:
6436			value |= (uint32_t)(*data);
6437		}
6438		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6439		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
6440	}
6441
6442	return (ctl);
6443}
6444
6445static void
6446bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6447    uint16_t offset, uint32_t value)
6448{
6449
6450	BWN_WRITE_4(mac, tq->tq_base + offset, value);
6451}
6452
6453static uint16_t
6454bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6455    uint16_t ctl, const void *_data, int len)
6456{
6457	struct bwn_softc *sc = mac->mac_sc;
6458	const uint8_t *data = _data;
6459
6460	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6461	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6462
6463	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
6464	    tq->tq_base + BWN_PIO_TXDATA);
6465	if (len & 1) {
6466		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6467		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6468		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
6469	}
6470
6471	return (ctl);
6472}
6473
6474static uint16_t
6475bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6476    uint16_t ctl, struct mbuf *m0)
6477{
6478	int i, j = 0;
6479	uint16_t data = 0;
6480	const uint8_t *buf;
6481	struct mbuf *m = m0;
6482
6483	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6484	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6485
6486	for (; m != NULL; m = m->m_next) {
6487		buf = mtod(m, const uint8_t *);
6488		for (i = 0; i < m->m_len; i++) {
6489			if (!((j++) % 2))
6490				data |= buf[i];
6491			else {
6492				data |= (buf[i] << 8);
6493				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6494				data = 0;
6495			}
6496		}
6497	}
6498	if (m0->m_pkthdr.len % 2) {
6499		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6500		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6501		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6502	}
6503
6504	return (ctl);
6505}
6506
6507static void
6508bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
6509{
6510
6511	/* XXX should exit if 5GHz band .. */
6512	if (mac->mac_phy.type != BWN_PHYTYPE_G)
6513		return;
6514
6515	BWN_WRITE_2(mac, 0x684, 510 + time);
6516	/* Disabled in Linux b43, can adversely effect performance */
6517#if 0
6518	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
6519#endif
6520}
6521
6522static struct bwn_dma_ring *
6523bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
6524{
6525
6526	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
6527		return (mac->mac_method.dma.wme[WME_AC_BE]);
6528
6529	switch (prio) {
6530	case 3:
6531		return (mac->mac_method.dma.wme[WME_AC_VO]);
6532	case 2:
6533		return (mac->mac_method.dma.wme[WME_AC_VI]);
6534	case 0:
6535		return (mac->mac_method.dma.wme[WME_AC_BE]);
6536	case 1:
6537		return (mac->mac_method.dma.wme[WME_AC_BK]);
6538	}
6539	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6540	return (NULL);
6541}
6542
6543static int
6544bwn_dma_getslot(struct bwn_dma_ring *dr)
6545{
6546	int slot;
6547
6548	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
6549
6550	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
6551	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
6552	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
6553
6554	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
6555	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
6556	dr->dr_curslot = slot;
6557	dr->dr_usedslot++;
6558
6559	return (slot);
6560}
6561
6562static struct bwn_pio_txqueue *
6563bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
6564    struct bwn_pio_txpkt **pack)
6565{
6566	struct bwn_pio *pio = &mac->mac_method.pio;
6567	struct bwn_pio_txqueue *tq = NULL;
6568	unsigned int index;
6569
6570	switch (cookie & 0xf000) {
6571	case 0x1000:
6572		tq = &pio->wme[WME_AC_BK];
6573		break;
6574	case 0x2000:
6575		tq = &pio->wme[WME_AC_BE];
6576		break;
6577	case 0x3000:
6578		tq = &pio->wme[WME_AC_VI];
6579		break;
6580	case 0x4000:
6581		tq = &pio->wme[WME_AC_VO];
6582		break;
6583	case 0x5000:
6584		tq = &pio->mcast;
6585		break;
6586	}
6587	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
6588	if (tq == NULL)
6589		return (NULL);
6590	index = (cookie & 0x0fff);
6591	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
6592	if (index >= N(tq->tq_pkts))
6593		return (NULL);
6594	*pack = &tq->tq_pkts[index];
6595	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
6596	return (tq);
6597}
6598
6599static void
6600bwn_txpwr(void *arg, int npending)
6601{
6602	struct bwn_mac *mac = arg;
6603	struct bwn_softc *sc = mac->mac_sc;
6604
6605	BWN_LOCK(sc);
6606	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
6607	    mac->mac_phy.set_txpwr != NULL)
6608		mac->mac_phy.set_txpwr(mac);
6609	BWN_UNLOCK(sc);
6610}
6611
6612static void
6613bwn_task_15s(struct bwn_mac *mac)
6614{
6615	uint16_t reg;
6616
6617	if (mac->mac_fw.opensource) {
6618		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
6619		if (reg) {
6620			bwn_restart(mac, "fw watchdog");
6621			return;
6622		}
6623		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
6624	}
6625	if (mac->mac_phy.task_15s)
6626		mac->mac_phy.task_15s(mac);
6627
6628	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
6629}
6630
6631static void
6632bwn_task_30s(struct bwn_mac *mac)
6633{
6634
6635	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
6636		return;
6637	mac->mac_noise.noi_running = 1;
6638	mac->mac_noise.noi_nsamples = 0;
6639
6640	bwn_noise_gensample(mac);
6641}
6642
6643static void
6644bwn_task_60s(struct bwn_mac *mac)
6645{
6646
6647	if (mac->mac_phy.task_60s)
6648		mac->mac_phy.task_60s(mac);
6649	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
6650}
6651
6652static void
6653bwn_tasks(void *arg)
6654{
6655	struct bwn_mac *mac = arg;
6656	struct bwn_softc *sc = mac->mac_sc;
6657
6658	BWN_ASSERT_LOCKED(sc);
6659	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
6660		return;
6661
6662	if (mac->mac_task_state % 4 == 0)
6663		bwn_task_60s(mac);
6664	if (mac->mac_task_state % 2 == 0)
6665		bwn_task_30s(mac);
6666	bwn_task_15s(mac);
6667
6668	mac->mac_task_state++;
6669	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
6670}
6671
6672static int
6673bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
6674{
6675	struct bwn_softc *sc = mac->mac_sc;
6676
6677	KASSERT(a == 0, ("not support APHY\n"));
6678
6679	switch (plcp->o.raw[0] & 0xf) {
6680	case 0xb:
6681		return (BWN_OFDM_RATE_6MB);
6682	case 0xf:
6683		return (BWN_OFDM_RATE_9MB);
6684	case 0xa:
6685		return (BWN_OFDM_RATE_12MB);
6686	case 0xe:
6687		return (BWN_OFDM_RATE_18MB);
6688	case 0x9:
6689		return (BWN_OFDM_RATE_24MB);
6690	case 0xd:
6691		return (BWN_OFDM_RATE_36MB);
6692	case 0x8:
6693		return (BWN_OFDM_RATE_48MB);
6694	case 0xc:
6695		return (BWN_OFDM_RATE_54MB);
6696	}
6697	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
6698	    plcp->o.raw[0] & 0xf);
6699	return (-1);
6700}
6701
6702static int
6703bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
6704{
6705	struct bwn_softc *sc = mac->mac_sc;
6706
6707	switch (plcp->o.raw[0]) {
6708	case 0x0a:
6709		return (BWN_CCK_RATE_1MB);
6710	case 0x14:
6711		return (BWN_CCK_RATE_2MB);
6712	case 0x37:
6713		return (BWN_CCK_RATE_5MB);
6714	case 0x6e:
6715		return (BWN_CCK_RATE_11MB);
6716	}
6717	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
6718	return (-1);
6719}
6720
6721static void
6722bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
6723    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
6724    int rssi, int noise)
6725{
6726	struct bwn_softc *sc = mac->mac_sc;
6727	const struct ieee80211_frame_min *wh;
6728	uint64_t tsf;
6729	uint16_t low_mactime_now;
6730
6731	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
6732		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6733
6734	wh = mtod(m, const struct ieee80211_frame_min *);
6735	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6736		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
6737
6738	bwn_tsf_read(mac, &tsf);
6739	low_mactime_now = tsf;
6740	tsf = tsf & ~0xffffULL;
6741	tsf += le16toh(rxhdr->mac_time);
6742	if (low_mactime_now < le16toh(rxhdr->mac_time))
6743		tsf -= 0x10000;
6744
6745	sc->sc_rx_th.wr_tsf = tsf;
6746	sc->sc_rx_th.wr_rate = rate;
6747	sc->sc_rx_th.wr_antsignal = rssi;
6748	sc->sc_rx_th.wr_antnoise = noise;
6749}
6750
6751static void
6752bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
6753{
6754	uint32_t low, high;
6755
6756	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
6757	    ("%s:%d: fail", __func__, __LINE__));
6758
6759	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
6760	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
6761	*tsf = high;
6762	*tsf <<= 32;
6763	*tsf |= low;
6764}
6765
6766static int
6767bwn_dma_attach(struct bwn_mac *mac)
6768{
6769	struct bwn_dma *dma = &mac->mac_method.dma;
6770	struct bwn_softc *sc = mac->mac_sc;
6771	bus_addr_t lowaddr = 0;
6772	int error;
6773
6774	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
6775		return (0);
6776
6777	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
6778
6779	mac->mac_flags |= BWN_MAC_FLAG_DMA;
6780
6781	dma->dmatype = bwn_dma_gettype(mac);
6782	if (dma->dmatype == BWN_DMA_30BIT)
6783		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
6784	else if (dma->dmatype == BWN_DMA_32BIT)
6785		lowaddr = BUS_SPACE_MAXADDR_32BIT;
6786	else
6787		lowaddr = BUS_SPACE_MAXADDR;
6788
6789	/*
6790	 * Create top level DMA tag
6791	 */
6792	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
6793			       BWN_ALIGN, 0,		/* alignment, bounds */
6794			       lowaddr,			/* lowaddr */
6795			       BUS_SPACE_MAXADDR,	/* highaddr */
6796			       NULL, NULL,		/* filter, filterarg */
6797			       BUS_SPACE_MAXSIZE,	/* maxsize */
6798			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
6799			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
6800			       0,			/* flags */
6801			       NULL, NULL,		/* lockfunc, lockarg */
6802			       &dma->parent_dtag);
6803	if (error) {
6804		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
6805		return (error);
6806	}
6807
6808	/*
6809	 * Create TX/RX mbuf DMA tag
6810	 */
6811	error = bus_dma_tag_create(dma->parent_dtag,
6812				1,
6813				0,
6814				BUS_SPACE_MAXADDR,
6815				BUS_SPACE_MAXADDR,
6816				NULL, NULL,
6817				MCLBYTES,
6818				1,
6819				BUS_SPACE_MAXSIZE_32BIT,
6820				0,
6821				NULL, NULL,
6822				&dma->rxbuf_dtag);
6823	if (error) {
6824		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6825		goto fail0;
6826	}
6827	error = bus_dma_tag_create(dma->parent_dtag,
6828				1,
6829				0,
6830				BUS_SPACE_MAXADDR,
6831				BUS_SPACE_MAXADDR,
6832				NULL, NULL,
6833				MCLBYTES,
6834				1,
6835				BUS_SPACE_MAXSIZE_32BIT,
6836				0,
6837				NULL, NULL,
6838				&dma->txbuf_dtag);
6839	if (error) {
6840		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6841		goto fail1;
6842	}
6843
6844	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
6845	if (!dma->wme[WME_AC_BK])
6846		goto fail2;
6847
6848	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
6849	if (!dma->wme[WME_AC_BE])
6850		goto fail3;
6851
6852	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
6853	if (!dma->wme[WME_AC_VI])
6854		goto fail4;
6855
6856	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
6857	if (!dma->wme[WME_AC_VO])
6858		goto fail5;
6859
6860	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
6861	if (!dma->mcast)
6862		goto fail6;
6863	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
6864	if (!dma->rx)
6865		goto fail7;
6866
6867	return (error);
6868
6869fail7:	bwn_dma_ringfree(&dma->mcast);
6870fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
6871fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
6872fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
6873fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
6874fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
6875fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
6876fail0:	bus_dma_tag_destroy(dma->parent_dtag);
6877	return (error);
6878}
6879
6880static struct bwn_dma_ring *
6881bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
6882    uint16_t cookie, int *slot)
6883{
6884	struct bwn_dma *dma = &mac->mac_method.dma;
6885	struct bwn_dma_ring *dr;
6886	struct bwn_softc *sc = mac->mac_sc;
6887
6888	BWN_ASSERT_LOCKED(mac->mac_sc);
6889
6890	switch (cookie & 0xf000) {
6891	case 0x1000:
6892		dr = dma->wme[WME_AC_BK];
6893		break;
6894	case 0x2000:
6895		dr = dma->wme[WME_AC_BE];
6896		break;
6897	case 0x3000:
6898		dr = dma->wme[WME_AC_VI];
6899		break;
6900	case 0x4000:
6901		dr = dma->wme[WME_AC_VO];
6902		break;
6903	case 0x5000:
6904		dr = dma->mcast;
6905		break;
6906	default:
6907		dr = NULL;
6908		KASSERT(0 == 1,
6909		    ("invalid cookie value %d", cookie & 0xf000));
6910	}
6911	*slot = (cookie & 0x0fff);
6912	if (*slot < 0 || *slot >= dr->dr_numslots) {
6913		/*
6914		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
6915		 * that it occurs events which have same H/W sequence numbers.
6916		 * When it's occurred just prints a WARNING msgs and ignores.
6917		 */
6918		KASSERT(status->seq == dma->lastseq,
6919		    ("%s:%d: fail", __func__, __LINE__));
6920		device_printf(sc->sc_dev,
6921		    "out of slot ranges (0 < %d < %d)\n", *slot,
6922		    dr->dr_numslots);
6923		return (NULL);
6924	}
6925	dma->lastseq = status->seq;
6926	return (dr);
6927}
6928
6929static void
6930bwn_dma_stop(struct bwn_mac *mac)
6931{
6932	struct bwn_dma *dma;
6933
6934	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
6935		return;
6936	dma = &mac->mac_method.dma;
6937
6938	bwn_dma_ringstop(&dma->rx);
6939	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
6940	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
6941	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
6942	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
6943	bwn_dma_ringstop(&dma->mcast);
6944}
6945
6946static void
6947bwn_dma_ringstop(struct bwn_dma_ring **dr)
6948{
6949
6950	if (dr == NULL)
6951		return;
6952
6953	bwn_dma_cleanup(*dr);
6954}
6955
6956static void
6957bwn_pio_stop(struct bwn_mac *mac)
6958{
6959	struct bwn_pio *pio;
6960
6961	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
6962		return;
6963	pio = &mac->mac_method.pio;
6964
6965	bwn_destroy_queue_tx(&pio->mcast);
6966	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
6967	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
6968	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
6969	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
6970}
6971
6972static void
6973bwn_led_attach(struct bwn_mac *mac)
6974{
6975	struct bwn_softc *sc = mac->mac_sc;
6976	const uint8_t *led_act = NULL;
6977	uint16_t val[BWN_LED_MAX];
6978	int i;
6979
6980	sc->sc_led_idle = (2350 * hz) / 1000;
6981	sc->sc_led_blink = 1;
6982
6983	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
6984		if (siba_get_pci_subvendor(sc->sc_dev) ==
6985		    bwn_vendor_led_act[i].vid) {
6986			led_act = bwn_vendor_led_act[i].led_act;
6987			break;
6988		}
6989	}
6990	if (led_act == NULL)
6991		led_act = bwn_default_led_act;
6992
6993	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
6994	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
6995	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
6996	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
6997
6998	for (i = 0; i < BWN_LED_MAX; ++i) {
6999		struct bwn_led *led = &sc->sc_leds[i];
7000
7001		if (val[i] == 0xff) {
7002			led->led_act = led_act[i];
7003		} else {
7004			if (val[i] & BWN_LED_ACT_LOW)
7005				led->led_flags |= BWN_LED_F_ACTLOW;
7006			led->led_act = val[i] & BWN_LED_ACT_MASK;
7007		}
7008		led->led_mask = (1 << i);
7009
7010		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
7011		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
7012		    led->led_act == BWN_LED_ACT_BLINK) {
7013			led->led_flags |= BWN_LED_F_BLINK;
7014			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
7015				led->led_flags |= BWN_LED_F_POLLABLE;
7016			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
7017				led->led_flags |= BWN_LED_F_SLOW;
7018
7019			if (sc->sc_blink_led == NULL) {
7020				sc->sc_blink_led = led;
7021				if (led->led_flags & BWN_LED_F_SLOW)
7022					BWN_LED_SLOWDOWN(sc->sc_led_idle);
7023			}
7024		}
7025
7026		DPRINTF(sc, BWN_DEBUG_LED,
7027		    "%dth led, act %d, lowact %d\n", i,
7028		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
7029	}
7030	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
7031}
7032
7033static __inline uint16_t
7034bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
7035{
7036
7037	if (led->led_flags & BWN_LED_F_ACTLOW)
7038		on = !on;
7039	if (on)
7040		val |= led->led_mask;
7041	else
7042		val &= ~led->led_mask;
7043	return val;
7044}
7045
7046static void
7047bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
7048{
7049	struct bwn_softc *sc = mac->mac_sc;
7050	struct ieee80211com *ic = &sc->sc_ic;
7051	uint16_t val;
7052	int i;
7053
7054	if (nstate == IEEE80211_S_INIT) {
7055		callout_stop(&sc->sc_led_blink_ch);
7056		sc->sc_led_blinking = 0;
7057	}
7058
7059	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
7060		return;
7061
7062	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7063	for (i = 0; i < BWN_LED_MAX; ++i) {
7064		struct bwn_led *led = &sc->sc_leds[i];
7065		int on;
7066
7067		if (led->led_act == BWN_LED_ACT_UNKN ||
7068		    led->led_act == BWN_LED_ACT_NULL)
7069			continue;
7070
7071		if ((led->led_flags & BWN_LED_F_BLINK) &&
7072		    nstate != IEEE80211_S_INIT)
7073			continue;
7074
7075		switch (led->led_act) {
7076		case BWN_LED_ACT_ON:    /* Always on */
7077			on = 1;
7078			break;
7079		case BWN_LED_ACT_OFF:   /* Always off */
7080		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
7081			on = 0;
7082			break;
7083		default:
7084			on = 1;
7085			switch (nstate) {
7086			case IEEE80211_S_INIT:
7087				on = 0;
7088				break;
7089			case IEEE80211_S_RUN:
7090				if (led->led_act == BWN_LED_ACT_11G &&
7091				    ic->ic_curmode != IEEE80211_MODE_11G)
7092					on = 0;
7093				break;
7094			default:
7095				if (led->led_act == BWN_LED_ACT_ASSOC)
7096					on = 0;
7097				break;
7098			}
7099			break;
7100		}
7101
7102		val = bwn_led_onoff(led, val, on);
7103	}
7104	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7105}
7106
7107static void
7108bwn_led_event(struct bwn_mac *mac, int event)
7109{
7110	struct bwn_softc *sc = mac->mac_sc;
7111	struct bwn_led *led = sc->sc_blink_led;
7112	int rate;
7113
7114	if (event == BWN_LED_EVENT_POLL) {
7115		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
7116			return;
7117		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
7118			return;
7119	}
7120
7121	sc->sc_led_ticks = ticks;
7122	if (sc->sc_led_blinking)
7123		return;
7124
7125	switch (event) {
7126	case BWN_LED_EVENT_RX:
7127		rate = sc->sc_rx_rate;
7128		break;
7129	case BWN_LED_EVENT_TX:
7130		rate = sc->sc_tx_rate;
7131		break;
7132	case BWN_LED_EVENT_POLL:
7133		rate = 0;
7134		break;
7135	default:
7136		panic("unknown LED event %d\n", event);
7137		break;
7138	}
7139	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
7140	    bwn_led_duration[rate].off_dur);
7141}
7142
7143static void
7144bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
7145{
7146	struct bwn_softc *sc = mac->mac_sc;
7147	struct bwn_led *led = sc->sc_blink_led;
7148	uint16_t val;
7149
7150	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7151	val = bwn_led_onoff(led, val, 1);
7152	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7153
7154	if (led->led_flags & BWN_LED_F_SLOW) {
7155		BWN_LED_SLOWDOWN(on_dur);
7156		BWN_LED_SLOWDOWN(off_dur);
7157	}
7158
7159	sc->sc_led_blinking = 1;
7160	sc->sc_led_blink_offdur = off_dur;
7161
7162	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
7163}
7164
7165static void
7166bwn_led_blink_next(void *arg)
7167{
7168	struct bwn_mac *mac = arg;
7169	struct bwn_softc *sc = mac->mac_sc;
7170	uint16_t val;
7171
7172	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7173	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
7174	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7175
7176	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
7177	    bwn_led_blink_end, mac);
7178}
7179
7180static void
7181bwn_led_blink_end(void *arg)
7182{
7183	struct bwn_mac *mac = arg;
7184	struct bwn_softc *sc = mac->mac_sc;
7185
7186	sc->sc_led_blinking = 0;
7187}
7188
7189static int
7190bwn_suspend(device_t dev)
7191{
7192	struct bwn_softc *sc = device_get_softc(dev);
7193
7194	BWN_LOCK(sc);
7195	bwn_stop(sc);
7196	BWN_UNLOCK(sc);
7197	return (0);
7198}
7199
7200static int
7201bwn_resume(device_t dev)
7202{
7203	struct bwn_softc *sc = device_get_softc(dev);
7204	int error = EDOOFUS;
7205
7206	BWN_LOCK(sc);
7207	if (sc->sc_ic.ic_nrunning > 0)
7208		error = bwn_init(sc);
7209	BWN_UNLOCK(sc);
7210	if (error == 0)
7211		ieee80211_start_all(&sc->sc_ic);
7212	return (0);
7213}
7214
7215static void
7216bwn_rfswitch(void *arg)
7217{
7218	struct bwn_softc *sc = arg;
7219	struct bwn_mac *mac = sc->sc_curmac;
7220	int cur = 0, prev = 0;
7221
7222	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
7223	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
7224
7225	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP
7226	    || mac->mac_phy.type == BWN_PHYTYPE_N) {
7227		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
7228			& BWN_RF_HWENABLED_HI_MASK))
7229			cur = 1;
7230	} else {
7231		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
7232		    & BWN_RF_HWENABLED_LO_MASK)
7233			cur = 1;
7234	}
7235
7236	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
7237		prev = 1;
7238
7239	DPRINTF(sc, BWN_DEBUG_RESET, "%s: called; cur=%d, prev=%d\n",
7240	    __func__, cur, prev);
7241
7242	if (cur != prev) {
7243		if (cur)
7244			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
7245		else
7246			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
7247
7248		device_printf(sc->sc_dev,
7249		    "status of RF switch is changed to %s\n",
7250		    cur ? "ON" : "OFF");
7251		if (cur != mac->mac_phy.rf_on) {
7252			if (cur)
7253				bwn_rf_turnon(mac);
7254			else
7255				bwn_rf_turnoff(mac);
7256		}
7257	}
7258
7259	callout_schedule(&sc->sc_rfswitch_ch, hz);
7260}
7261
7262static void
7263bwn_sysctl_node(struct bwn_softc *sc)
7264{
7265	device_t dev = sc->sc_dev;
7266	struct bwn_mac *mac;
7267	struct bwn_stats *stats;
7268
7269	/* XXX assume that count of MAC is only 1. */
7270
7271	if ((mac = sc->sc_curmac) == NULL)
7272		return;
7273	stats = &mac->mac_stats;
7274
7275	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7276	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7277	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
7278	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7279	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7280	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
7281	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7282	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7283	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
7284
7285#ifdef BWN_DEBUG
7286	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
7287	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7288	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
7289#endif
7290}
7291
7292static device_method_t bwn_methods[] = {
7293	/* Device interface */
7294	DEVMETHOD(device_probe,		bwn_probe),
7295	DEVMETHOD(device_attach,	bwn_attach),
7296	DEVMETHOD(device_detach,	bwn_detach),
7297	DEVMETHOD(device_suspend,	bwn_suspend),
7298	DEVMETHOD(device_resume,	bwn_resume),
7299	DEVMETHOD_END
7300};
7301static driver_t bwn_driver = {
7302	"bwn",
7303	bwn_methods,
7304	sizeof(struct bwn_softc)
7305};
7306static devclass_t bwn_devclass;
7307DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
7308MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
7309MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
7310MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
7311MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
7312MODULE_VERSION(bwn, 1);
7313