if_bwn.c revision 204256
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 204256 2010-02-23 19:44:51Z weongyo $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_amrr.h>
71#include <net80211/ieee80211_phy.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77
78/*
79 * Tunable & sysctl variables.
80 */
81
82#ifdef BWN_DEBUG
83static	int bwn_debug = 0;
84SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85    "Broadcom debugging printfs");
86TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87enum {
88	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106	BWN_DEBUG_ANY		= 0xffffffff
107};
108#define	DPRINTF(sc, m, fmt, ...) do {			\
109	if (sc->sc_debug & (m))				\
110		printf(fmt, __VA_ARGS__);		\
111} while (0)
112#else
113#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114#endif
115
116static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118    "uses Bad Frames Preemption");
119static int	bwn_bluetooth = 1;
120SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121    "turns on Bluetooth Coexistence");
122static int	bwn_hwpctl = 0;
123SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124    "uses H/W power control");
125static int	bwn_msi_disable = 0;		/* MSI disabled  */
126TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127static int	bwn_usedma = 1;
128SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129    "uses DMA");
130TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131static int	bwn_wme = 1;
132SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133    "uses WME support");
134
135static int	bwn_attach_pre(struct bwn_softc *);
136static int	bwn_attach_post(struct bwn_softc *);
137static void	bwn_sprom_bugfixes(struct siba_softc *);
138static void	bwn_init(void *);
139static int	bwn_init_locked(struct bwn_softc *);
140static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141static void	bwn_start(struct ifnet *);
142static int	bwn_attach_core(struct bwn_mac *);
143static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144static int	bwn_phy_getinfo(struct bwn_mac *, int);
145static int	bwn_chiptest(struct bwn_mac *);
146static int	bwn_setup_channels(struct bwn_mac *, int, int);
147static int	bwn_phy_g_attach(struct bwn_mac *);
148static void	bwn_phy_g_detach(struct bwn_mac *);
149static void	bwn_phy_g_init_pre(struct bwn_mac *);
150static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151static int	bwn_phy_g_init(struct bwn_mac *);
152static void	bwn_phy_g_exit(struct bwn_mac *);
153static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155		    uint16_t);
156static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158		    uint16_t);
159static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164static int	bwn_phy_g_im(struct bwn_mac *, int);
165static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167static void	bwn_phy_g_task_15s(struct bwn_mac *);
168static void	bwn_phy_g_task_60s(struct bwn_mac *);
169static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173		    uint16_t);
174static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176		    uint32_t);
177static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178		    uint16_t);
179static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180		    const struct bwn_channelinfo *, int);
181static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182		    const struct ieee80211_bpf_params *);
183static void	bwn_newassoc(struct ieee80211_node *, int);
184static void	bwn_updateslot(struct ifnet *);
185static void	bwn_update_promisc(struct ifnet *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189		    const uint8_t [IEEE80211_ADDR_LEN]);
190static void	bwn_wme_clear(struct bwn_softc *);
191static void	bwn_wme_load(struct bwn_mac *);
192static void	bwn_wme_loadparams(struct bwn_mac *,
193		    const struct wmeParams *, uint16_t);
194static void	bwn_node_cleanup(struct ieee80211_node *);
195static void	bwn_scan_start(struct ieee80211com *);
196static void	bwn_scan_end(struct ieee80211com *);
197static void	bwn_set_channel(struct ieee80211com *);
198static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199		    const char [IFNAMSIZ], int, int,
200		    int, const uint8_t [IEEE80211_ADDR_LEN],
201		    const uint8_t [IEEE80211_ADDR_LEN]);
202static void	bwn_vap_delete(struct ieee80211vap *);
203static void	bwn_stop(struct bwn_softc *, int);
204static void	bwn_stop_locked(struct bwn_softc *, int);
205static int	bwn_core_init(struct bwn_mac *);
206static void	bwn_core_start(struct bwn_mac *);
207static void	bwn_core_exit(struct bwn_mac *);
208static void	bwn_fix_imcfglobug(struct bwn_mac *);
209static void	bwn_bt_disable(struct bwn_mac *);
210static int	bwn_chip_init(struct bwn_mac *);
211static uint64_t	bwn_hf_read(struct bwn_mac *);
212static void	bwn_hf_write(struct bwn_mac *, uint64_t);
213static void	bwn_set_txretry(struct bwn_mac *, int, int);
214static void	bwn_rate_init(struct bwn_mac *);
215static void	bwn_set_phytxctl(struct bwn_mac *);
216static void	bwn_spu_setdelay(struct bwn_mac *, int);
217static void	bwn_bt_enable(struct bwn_mac *);
218static void	bwn_set_macaddr(struct bwn_mac *);
219static void	bwn_crypt_init(struct bwn_mac *);
220static void	bwn_chip_exit(struct bwn_mac *);
221static int	bwn_fw_fillinfo(struct bwn_mac *);
222static int	bwn_fw_loaducode(struct bwn_mac *);
223static int	bwn_gpio_init(struct bwn_mac *);
224static int	bwn_fw_loadinitvals(struct bwn_mac *);
225static int	bwn_phy_init(struct bwn_mac *);
226static void	bwn_set_txantenna(struct bwn_mac *, int);
227static void	bwn_set_opmode(struct bwn_mac *);
228static void	bwn_gpio_cleanup(struct bwn_mac *);
229static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
230static uint8_t	bwn_plcp_getcck(const uint8_t);
231static uint8_t	bwn_plcp_getofdm(const uint8_t);
232static void	bwn_pio_init(struct bwn_mac *);
233static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
234static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
235		    int);
236static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
237		    struct bwn_pio_rxqueue *, int);
238static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
239static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
240		    uint16_t);
241static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
242static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
243static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
244static void	bwn_pio_handle_txeof(struct bwn_mac *,
245		    const struct bwn_txstatus *);
246static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
247static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
248static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
249		    uint16_t);
250static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
251		    uint32_t);
252static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
253		    struct mbuf *);
254static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
255static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
256		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
257static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
258		    uint16_t, uint32_t);
259static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
260		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
261static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
262		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
263static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
264		    uint16_t, struct bwn_pio_txpkt **);
265static void	bwn_dma_init(struct bwn_mac *);
266static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
267static int	bwn_dma_mask2type(uint64_t);
268static uint64_t	bwn_dma_mask(struct bwn_mac *);
269static uint16_t	bwn_dma_base(int, int);
270static void	bwn_dma_ringfree(struct bwn_dma_ring **);
271static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
272		    int, struct bwn_dmadesc_generic **,
273		    struct bwn_dmadesc_meta **);
274static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
275		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
276		    int, int);
277static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
278static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
279static void	bwn_dma_32_resume(struct bwn_dma_ring *);
280static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
281static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
282static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
283		    int, struct bwn_dmadesc_generic **,
284		    struct bwn_dmadesc_meta **);
285static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
286		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
287		    int, int);
288static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
289static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
290static void	bwn_dma_64_resume(struct bwn_dma_ring *);
291static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
292static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
293static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
294static void	bwn_dma_setup(struct bwn_dma_ring *);
295static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
296static void	bwn_dma_cleanup(struct bwn_dma_ring *);
297static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
298static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
299static void	bwn_dma_rx(struct bwn_dma_ring *);
300static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
301static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
302		    struct bwn_dmadesc_meta *);
303static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
304static int	bwn_dma_gettype(struct bwn_mac *);
305static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
306static int	bwn_dma_freeslot(struct bwn_dma_ring *);
307static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
308static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
309static int	bwn_dma_newbuf(struct bwn_dma_ring *,
310		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
311		    int);
312static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
313		    bus_size_t, int);
314static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
315static void	bwn_dma_handle_txeof(struct bwn_mac *,
316		    const struct bwn_txstatus *);
317static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
318		    struct mbuf *);
319static int	bwn_dma_getslot(struct bwn_dma_ring *);
320static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
321		    uint8_t);
322static int	bwn_dma_attach(struct bwn_mac *);
323static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
324		    int, int, int);
325static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
326		    const struct bwn_txstatus *, uint16_t, int *);
327static void	bwn_dma_free(struct bwn_mac *);
328static void	bwn_phy_g_init_sub(struct bwn_mac *);
329static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
330static void	bwn_phy_init_b5(struct bwn_mac *);
331static void	bwn_phy_init_b6(struct bwn_mac *);
332static void	bwn_phy_init_a(struct bwn_mac *);
333static void	bwn_loopback_calcgain(struct bwn_mac *);
334static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
335static void	bwn_lo_g_init(struct bwn_mac *);
336static void	bwn_lo_g_adjust(struct bwn_mac *);
337static void	bwn_lo_get_powervector(struct bwn_mac *);
338static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
339		    const struct bwn_bbatt *, const struct bwn_rfatt *);
340static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
341static void	bwn_phy_hwpctl_init(struct bwn_mac *);
342static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
343static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
344		    const struct bwn_bbatt *, const struct bwn_rfatt *,
345		    uint8_t);
346static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
347static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
348static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
349static void	bwn_wa_init(struct bwn_mac *);
350static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
351		    uint16_t);
352static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
353static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
354		    uint32_t);
355static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
356		    uint16_t);
357static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
358static void	bwn_mac_suspend(struct bwn_mac *);
359static void	bwn_mac_enable(struct bwn_mac *);
360static void	bwn_psctl(struct bwn_mac *, uint32_t);
361static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
362static void	bwn_nrssi_offset(struct bwn_mac *);
363static void	bwn_nrssi_threshold(struct bwn_mac *);
364static void	bwn_nrssi_slope_11g(struct bwn_mac *);
365static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
366		    int16_t);
367static void	bwn_set_original_gains(struct bwn_mac *);
368static void	bwn_hwpctl_early_init(struct bwn_mac *);
369static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
370static uint16_t	bwn_phy_g_chan2freq(uint8_t);
371static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
372static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
373		    const char *, struct bwn_fwfile *);
374static void	bwn_release_firmware(struct bwn_mac *);
375static void	bwn_do_release_fw(struct bwn_fwfile *);
376static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
377static int	bwn_fwinitvals_write(struct bwn_mac *,
378		    const struct bwn_fwinitvals *, size_t, size_t);
379static int	bwn_switch_channel(struct bwn_mac *, int);
380static uint16_t	bwn_ant2phy(int);
381static void	bwn_mac_write_bssid(struct bwn_mac *);
382static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
383		    const uint8_t *);
384static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
385		    const uint8_t *, size_t, const uint8_t *);
386static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
387		    const uint8_t *);
388static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
389		    const uint8_t *);
390static void	bwn_phy_exit(struct bwn_mac *);
391static void	bwn_core_stop(struct bwn_mac *);
392static int	bwn_switch_band(struct bwn_softc *,
393		    struct ieee80211_channel *);
394static void	bwn_phy_reset(struct bwn_mac *);
395static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
396static void	bwn_set_pretbtt(struct bwn_mac *);
397static int	bwn_intr(void *);
398static void	bwn_intrtask(void *, int);
399static void	bwn_restart(struct bwn_mac *, const char *);
400static void	bwn_intr_ucode_debug(struct bwn_mac *);
401static void	bwn_intr_tbtt_indication(struct bwn_mac *);
402static void	bwn_intr_atim_end(struct bwn_mac *);
403static void	bwn_intr_beacon(struct bwn_mac *);
404static void	bwn_intr_pmq(struct bwn_mac *);
405static void	bwn_intr_noise(struct bwn_mac *);
406static void	bwn_intr_txeof(struct bwn_mac *);
407static void	bwn_hwreset(void *, int);
408static void	bwn_handle_fwpanic(struct bwn_mac *);
409static void	bwn_load_beacon0(struct bwn_mac *);
410static void	bwn_load_beacon1(struct bwn_mac *);
411static uint32_t	bwn_jssi_read(struct bwn_mac *);
412static void	bwn_noise_gensample(struct bwn_mac *);
413static void	bwn_handle_txeof(struct bwn_mac *,
414		    const struct bwn_txstatus *);
415static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
416static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
417static void	bwn_start_locked(struct ifnet *);
418static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
419		    struct mbuf *);
420static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
421static int	bwn_set_txhdr(struct bwn_mac *,
422		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
423		    uint16_t);
424static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
425		    const uint8_t);
426static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
427static uint8_t	bwn_get_fbrate(uint8_t);
428static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
429static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
430static void	bwn_phy_lock(struct bwn_mac *);
431static void	bwn_phy_unlock(struct bwn_mac *);
432static void	bwn_rf_lock(struct bwn_mac *);
433static void	bwn_rf_unlock(struct bwn_mac *);
434static void	bwn_txpwr(void *, int);
435static void	bwn_tasks(void *);
436static void	bwn_task_15s(struct bwn_mac *);
437static void	bwn_task_30s(struct bwn_mac *);
438static void	bwn_task_60s(struct bwn_mac *);
439static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
440		    uint8_t);
441static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
442static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
443		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
444		    int, int);
445static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
446static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
447static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
448static void	bwn_watchdog(void *);
449static void	bwn_dma_stop(struct bwn_mac *);
450static void	bwn_pio_stop(struct bwn_mac *);
451static void	bwn_dma_ringstop(struct bwn_dma_ring **);
452static void	bwn_led_attach(struct bwn_mac *);
453static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
454static void	bwn_led_event(struct bwn_mac *, int);
455static void	bwn_led_blink_start(struct bwn_mac *, int, int);
456static void	bwn_led_blink_next(void *);
457static void	bwn_led_blink_end(void *);
458static void	bwn_rfswitch(void *);
459static void	bwn_rf_turnon(struct bwn_mac *);
460static void	bwn_rf_turnoff(struct bwn_mac *);
461static void	bwn_phy_lp_init_pre(struct bwn_mac *);
462static int	bwn_phy_lp_init(struct bwn_mac *);
463static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
464static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
465static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
466		    uint16_t);
467static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
468static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
469static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
470static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
471static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
472static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
473static void	bwn_phy_lp_task_60s(struct bwn_mac *);
474static void	bwn_phy_lp_readsprom(struct bwn_mac *);
475static void	bwn_phy_lp_bbinit(struct bwn_mac *);
476static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
477static void	bwn_phy_lp_calib(struct bwn_mac *);
478static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
479static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
480static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
481static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
482static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
483static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
484static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
485static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
486static void	bwn_phy_lp_bugfix(struct bwn_mac *);
487static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
488static void	bwn_phy_lp_tblinit(struct bwn_mac *);
489static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
490static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
491static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
492static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
493static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
494static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
495static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
496static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
497static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
498static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
499static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
500		    const void *);
501static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
502static struct bwn_txgain
503		bwn_phy_lp_get_txgain(struct bwn_mac *);
504static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
505static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
506static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
507static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
508static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
509static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
510static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
511static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
512static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
513static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
514static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
515static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
516static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
517static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
518static int	bwn_phy_lp_loopback(struct bwn_mac *);
519static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
520static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
521		    int);
522static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
523		    struct bwn_phy_lp_iq_est *);
524static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
525static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
526static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
527static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
528static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
529static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
530static uint8_t	bwn_nbits(int32_t);
531static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
532		    struct bwn_txgain_entry *);
533static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
534		    struct bwn_txgain_entry);
535static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
536		    struct bwn_txgain_entry);
537static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
538		    struct bwn_txgain_entry);
539
540static struct resource_spec bwn_res_spec_legacy[] = {
541	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
542	{ -1,			0,		0 }
543};
544
545static struct resource_spec bwn_res_spec_msi[] = {
546	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
547	{ -1,			0,		0 }
548};
549
550static const struct bwn_channelinfo bwn_chantable_bg = {
551	.channels = {
552		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
553		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
554		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
555		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
556		{ 2472, 13, 30 }, { 2484, 14, 30 } },
557	.nchannels = 14
558};
559
560static const struct bwn_channelinfo bwn_chantable_a = {
561	.channels = {
562		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
563		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
564		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
565		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
566		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
567		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
568		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
569		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
570		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
571		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
572		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
573		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
574		{ 6080, 216, 30 } },
575	.nchannels = 37
576};
577
578static const struct bwn_channelinfo bwn_chantable_n = {
579	.channels = {
580		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
581		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
582		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
583		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
584		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
585		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
586		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
587		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
588		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
589		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
590		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
591		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
592		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
593		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
594		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
595		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
596		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
597		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
598		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
599		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
600		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
601		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
602		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
603		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
604		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
605		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
606		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
607		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
608		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
609		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
610		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
611		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
612		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
613		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
614		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
615		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
616		{ 6130, 226, 30 }, { 6140, 228, 30 } },
617	.nchannels = 110
618};
619
620static const uint8_t bwn_b2063_chantable_data[33][12] = {
621	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
626	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
627	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
628	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
629	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
630	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
631	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
632	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
633	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
634	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
635	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
636	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
637	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
638	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
639	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
640	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
641	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
642	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
643	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
645	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
646	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
647	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
648	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
649	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
651	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
652	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
653	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
654};
655
656static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
657	{ 1, 2412, bwn_b2063_chantable_data[0] },
658	{ 2, 2417, bwn_b2063_chantable_data[0] },
659	{ 3, 2422, bwn_b2063_chantable_data[0] },
660	{ 4, 2427, bwn_b2063_chantable_data[1] },
661	{ 5, 2432, bwn_b2063_chantable_data[1] },
662	{ 6, 2437, bwn_b2063_chantable_data[1] },
663	{ 7, 2442, bwn_b2063_chantable_data[1] },
664	{ 8, 2447, bwn_b2063_chantable_data[1] },
665	{ 9, 2452, bwn_b2063_chantable_data[2] },
666	{ 10, 2457, bwn_b2063_chantable_data[2] },
667	{ 11, 2462, bwn_b2063_chantable_data[3] },
668	{ 12, 2467, bwn_b2063_chantable_data[3] },
669	{ 13, 2472, bwn_b2063_chantable_data[3] },
670	{ 14, 2484, bwn_b2063_chantable_data[4] },
671	{ 34, 5170, bwn_b2063_chantable_data[5] },
672	{ 36, 5180, bwn_b2063_chantable_data[6] },
673	{ 38, 5190, bwn_b2063_chantable_data[7] },
674	{ 40, 5200, bwn_b2063_chantable_data[8] },
675	{ 42, 5210, bwn_b2063_chantable_data[9] },
676	{ 44, 5220, bwn_b2063_chantable_data[10] },
677	{ 46, 5230, bwn_b2063_chantable_data[11] },
678	{ 48, 5240, bwn_b2063_chantable_data[12] },
679	{ 52, 5260, bwn_b2063_chantable_data[13] },
680	{ 56, 5280, bwn_b2063_chantable_data[14] },
681	{ 60, 5300, bwn_b2063_chantable_data[14] },
682	{ 64, 5320, bwn_b2063_chantable_data[15] },
683	{ 100, 5500, bwn_b2063_chantable_data[16] },
684	{ 104, 5520, bwn_b2063_chantable_data[17] },
685	{ 108, 5540, bwn_b2063_chantable_data[18] },
686	{ 112, 5560, bwn_b2063_chantable_data[19] },
687	{ 116, 5580, bwn_b2063_chantable_data[20] },
688	{ 120, 5600, bwn_b2063_chantable_data[21] },
689	{ 124, 5620, bwn_b2063_chantable_data[21] },
690	{ 128, 5640, bwn_b2063_chantable_data[22] },
691	{ 132, 5660, bwn_b2063_chantable_data[22] },
692	{ 136, 5680, bwn_b2063_chantable_data[22] },
693	{ 140, 5700, bwn_b2063_chantable_data[23] },
694	{ 149, 5745, bwn_b2063_chantable_data[23] },
695	{ 153, 5765, bwn_b2063_chantable_data[23] },
696	{ 157, 5785, bwn_b2063_chantable_data[23] },
697	{ 161, 5805, bwn_b2063_chantable_data[23] },
698	{ 165, 5825, bwn_b2063_chantable_data[23] },
699	{ 184, 4920, bwn_b2063_chantable_data[24] },
700	{ 188, 4940, bwn_b2063_chantable_data[25] },
701	{ 192, 4960, bwn_b2063_chantable_data[26] },
702	{ 196, 4980, bwn_b2063_chantable_data[27] },
703	{ 200, 5000, bwn_b2063_chantable_data[28] },
704	{ 204, 5020, bwn_b2063_chantable_data[29] },
705	{ 208, 5040, bwn_b2063_chantable_data[30] },
706	{ 212, 5060, bwn_b2063_chantable_data[31] },
707	{ 216, 5080, bwn_b2063_chantable_data[32] }
708};
709
710static const uint8_t bwn_b2062_chantable_data[22][12] = {
711	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
712	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
720	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
721	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
724	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
731	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
732	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
733};
734
735static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
736	{ 1, 2412, bwn_b2062_chantable_data[0] },
737	{ 2, 2417, bwn_b2062_chantable_data[0] },
738	{ 3, 2422, bwn_b2062_chantable_data[0] },
739	{ 4, 2427, bwn_b2062_chantable_data[0] },
740	{ 5, 2432, bwn_b2062_chantable_data[0] },
741	{ 6, 2437, bwn_b2062_chantable_data[0] },
742	{ 7, 2442, bwn_b2062_chantable_data[0] },
743	{ 8, 2447, bwn_b2062_chantable_data[0] },
744	{ 9, 2452, bwn_b2062_chantable_data[0] },
745	{ 10, 2457, bwn_b2062_chantable_data[0] },
746	{ 11, 2462, bwn_b2062_chantable_data[0] },
747	{ 12, 2467, bwn_b2062_chantable_data[0] },
748	{ 13, 2472, bwn_b2062_chantable_data[0] },
749	{ 14, 2484, bwn_b2062_chantable_data[0] },
750	{ 34, 5170, bwn_b2062_chantable_data[1] },
751	{ 38, 5190, bwn_b2062_chantable_data[2] },
752	{ 42, 5210, bwn_b2062_chantable_data[2] },
753	{ 46, 5230, bwn_b2062_chantable_data[3] },
754	{ 36, 5180, bwn_b2062_chantable_data[4] },
755	{ 40, 5200, bwn_b2062_chantable_data[5] },
756	{ 44, 5220, bwn_b2062_chantable_data[6] },
757	{ 48, 5240, bwn_b2062_chantable_data[3] },
758	{ 52, 5260, bwn_b2062_chantable_data[3] },
759	{ 56, 5280, bwn_b2062_chantable_data[3] },
760	{ 60, 5300, bwn_b2062_chantable_data[7] },
761	{ 64, 5320, bwn_b2062_chantable_data[8] },
762	{ 100, 5500, bwn_b2062_chantable_data[9] },
763	{ 104, 5520, bwn_b2062_chantable_data[10] },
764	{ 108, 5540, bwn_b2062_chantable_data[10] },
765	{ 112, 5560, bwn_b2062_chantable_data[10] },
766	{ 116, 5580, bwn_b2062_chantable_data[11] },
767	{ 120, 5600, bwn_b2062_chantable_data[12] },
768	{ 124, 5620, bwn_b2062_chantable_data[12] },
769	{ 128, 5640, bwn_b2062_chantable_data[12] },
770	{ 132, 5660, bwn_b2062_chantable_data[12] },
771	{ 136, 5680, bwn_b2062_chantable_data[12] },
772	{ 140, 5700, bwn_b2062_chantable_data[12] },
773	{ 149, 5745, bwn_b2062_chantable_data[12] },
774	{ 153, 5765, bwn_b2062_chantable_data[12] },
775	{ 157, 5785, bwn_b2062_chantable_data[12] },
776	{ 161, 5805, bwn_b2062_chantable_data[12] },
777	{ 165, 5825, bwn_b2062_chantable_data[12] },
778	{ 184, 4920, bwn_b2062_chantable_data[13] },
779	{ 188, 4940, bwn_b2062_chantable_data[14] },
780	{ 192, 4960, bwn_b2062_chantable_data[15] },
781	{ 196, 4980, bwn_b2062_chantable_data[16] },
782	{ 200, 5000, bwn_b2062_chantable_data[17] },
783	{ 204, 5020, bwn_b2062_chantable_data[18] },
784	{ 208, 5040, bwn_b2062_chantable_data[19] },
785	{ 212, 5060, bwn_b2062_chantable_data[20] },
786	{ 216, 5080, bwn_b2062_chantable_data[21] }
787};
788
789/* for LP PHY */
790static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
791	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
792	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
793	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
794	{ 13, -66, 13 }, { 14, -66, 13 },
795};
796
797/* for LP PHY */
798static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
799	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
800	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
801	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
802	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
803	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
804	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
805	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
806	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
807	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
808	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
809	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
810	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
811	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
812};
813
814static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
815
816static const uint8_t bwn_tab_sigsq_tbl[] = {
817	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
818	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
819	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
820	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
821	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
822	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
823};
824
825static const uint8_t bwn_tab_pllfrac_tbl[] = {
826	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
827	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
828};
829
830static const uint16_t bwn_tabl_iqlocal_tbl[] = {
831	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
832	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
833	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
835	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
836	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
837	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
840	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
841	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
842	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
843};
844
845static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
846static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
847static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
848static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
849static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
850const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
851
852#define	VENDOR_LED_ACT(vendor)				\
853{							\
854	.vid = PCI_VENDOR_##vendor,			\
855	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
856}
857
858static const struct {
859	uint16_t	vid;
860	uint8_t		led_act[BWN_LED_MAX];
861} bwn_vendor_led_act[] = {
862	VENDOR_LED_ACT(COMPAQ),
863	VENDOR_LED_ACT(ASUSTEK)
864};
865
866static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
867	{ BWN_VENDOR_LED_ACT_DEFAULT };
868
869#undef VENDOR_LED_ACT
870
871static const struct {
872	int		on_dur;
873	int		off_dur;
874} bwn_led_duration[109] = {
875	[0]	= { 400, 100 },
876	[2]	= { 150, 75 },
877	[4]	= { 90, 45 },
878	[11]	= { 66, 34 },
879	[12]	= { 53, 26 },
880	[18]	= { 42, 21 },
881	[22]	= { 35, 17 },
882	[24]	= { 32, 16 },
883	[36]	= { 21, 10 },
884	[48]	= { 16, 8 },
885	[72]	= { 11, 5 },
886	[96]	= { 9, 4 },
887	[108]	= { 7, 3 }
888};
889
890static const uint16_t bwn_wme_shm_offsets[] = {
891	[0] = BWN_WME_BESTEFFORT,
892	[1] = BWN_WME_BACKGROUND,
893	[2] = BWN_WME_VOICE,
894	[3] = BWN_WME_VIDEO,
895};
896
897static const struct siba_devid bwn_devs[] = {
898	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
899	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
900	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
901	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
902	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
903	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
904	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
905	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
906	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
907};
908
909static int
910bwn_probe(device_t dev)
911{
912	struct siba_dev_softc *sd = device_get_ivars(dev);
913	int i;
914
915	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
916		if (sd->sd_id.sd_vendor == bwn_devs[i].sd_vendor &&
917		    sd->sd_id.sd_device == bwn_devs[i].sd_device &&
918		    sd->sd_id.sd_rev == bwn_devs[i].sd_rev)
919			return (BUS_PROBE_DEFAULT);
920	}
921
922	return (ENXIO);
923}
924
925static int
926bwn_attach(device_t dev)
927{
928	struct bwn_mac *mac;
929	struct bwn_softc *sc = device_get_softc(dev);
930	struct siba_dev_softc *sd = device_get_ivars(dev);
931	struct siba_softc *siba = sd->sd_bus;
932	int error, i, msic, reg;
933
934	sc->sc_dev = dev;
935	sc->sc_sd = sd;
936#ifdef BWN_DEBUG
937	sc->sc_debug = bwn_debug;
938#endif
939
940	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
941		error = bwn_attach_pre(sc);
942		if (error != 0)
943			return (error);
944		bwn_sprom_bugfixes(sd->sd_bus);
945		sc->sc_flags |= BWN_FLAG_ATTACHED;
946	}
947
948	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
949		if (siba->siba_pci_did != 0x4313 &&
950		    siba->siba_pci_did != 0x431a &&
951		    siba->siba_pci_did != 0x4321) {
952			device_printf(sc->sc_dev,
953			    "skip 802.11 cores\n");
954			return (ENODEV);
955		}
956	}
957
958	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
959	    M_NOWAIT | M_ZERO);
960	if (mac == NULL)
961		return (ENOMEM);
962	mac->mac_sc = sc;
963	mac->mac_sd = sd;
964	mac->mac_status = BWN_MAC_STATUS_UNINIT;
965	if (bwn_bfp != 0)
966		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
967
968	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
969	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
970	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
971
972	error = bwn_attach_core(mac);
973	if (error)
974		goto fail0;
975	bwn_led_attach(mac);
976
977	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
978	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
979	    sd->sd_bus->siba_chipid, sd->sd_id.sd_rev,
980	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
981	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
982	    mac->mac_phy.rf_rev);
983	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
984		device_printf(sc->sc_dev, "DMA (%d bits)\n",
985		    mac->mac_method.dma.dmatype);
986	else
987		device_printf(sc->sc_dev, "PIO\n");
988
989	/*
990	 * setup PCI resources and interrupt.
991	 */
992	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
993		msic = pci_msi_count(dev);
994		if (bootverbose)
995			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
996	} else
997		msic = 0;
998
999	mac->mac_intr_spec = bwn_res_spec_legacy;
1000	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
1001		if (pci_alloc_msi(dev, &msic) == 0) {
1002			device_printf(sc->sc_dev,
1003			    "Using %d MSI messages\n", msic);
1004			mac->mac_intr_spec = bwn_res_spec_msi;
1005			mac->mac_msi = 1;
1006		}
1007	}
1008
1009	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1010	    mac->mac_res_irq);
1011	if (error) {
1012		device_printf(sc->sc_dev,
1013		    "couldn't allocate IRQ resources (%d)\n", error);
1014		goto fail1;
1015	}
1016
1017	if (mac->mac_msi == 0)
1018		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1019		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1020		    &mac->mac_intrhand[0]);
1021	else {
1022		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1023			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1024			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1025			    &mac->mac_intrhand[i]);
1026			if (error != 0) {
1027				device_printf(sc->sc_dev,
1028				    "couldn't setup interrupt (%d)\n", error);
1029				break;
1030			}
1031		}
1032	}
1033
1034	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1035
1036	/*
1037	 * calls attach-post routine
1038	 */
1039	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1040		bwn_attach_post(sc);
1041
1042	return (0);
1043fail1:
1044	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1045		pci_release_msi(dev);
1046fail0:
1047	free(mac, M_DEVBUF);
1048	return (error);
1049}
1050
1051static int
1052bwn_is_valid_ether_addr(uint8_t *addr)
1053{
1054	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1055
1056	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1057		return (FALSE);
1058
1059	return (TRUE);
1060}
1061
1062static int
1063bwn_attach_post(struct bwn_softc *sc)
1064{
1065	struct ieee80211com *ic;
1066	struct ifnet *ifp = sc->sc_ifp;
1067	struct siba_dev_softc *sd = sc->sc_sd;
1068	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
1069#ifdef BWN_DEBUG
1070	device_t dev = sc->sc_dev;
1071#endif
1072
1073	ic = ifp->if_l2com;
1074	ic->ic_ifp = ifp;
1075	/* XXX not right but it's not used anywhere important */
1076	ic->ic_phytype = IEEE80211_T_OFDM;
1077	ic->ic_opmode = IEEE80211_M_STA;
1078	ic->ic_caps =
1079		  IEEE80211_C_STA		/* station mode supported */
1080		| IEEE80211_C_MONITOR		/* monitor mode */
1081		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1082		| IEEE80211_C_SHSLOT		/* short slot time supported */
1083		| IEEE80211_C_WME		/* WME/WMM supported */
1084		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1085		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1086		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1087		;
1088
1089	/* call MI attach routine. */
1090	ieee80211_ifattach(ic,
1091	    bwn_is_valid_ether_addr(sprom->mac_80211a) ? sprom->mac_80211a :
1092	    sprom->mac_80211bg);
1093
1094	ic->ic_headroom = sizeof(struct bwn_txhdr);
1095
1096	/* override default methods */
1097	ic->ic_raw_xmit = bwn_raw_xmit;
1098	ic->ic_newassoc = bwn_newassoc;
1099	ic->ic_updateslot = bwn_updateslot;
1100	ic->ic_update_promisc = bwn_update_promisc;
1101	ic->ic_wme.wme_update = bwn_wme_update;
1102
1103	ic->ic_node_alloc = bwn_node_alloc;
1104	sc->sc_node_cleanup = ic->ic_node_cleanup;
1105	ic->ic_node_cleanup = bwn_node_cleanup;
1106
1107	ic->ic_scan_start = bwn_scan_start;
1108	ic->ic_scan_end = bwn_scan_end;
1109	ic->ic_set_channel = bwn_set_channel;
1110
1111	ic->ic_vap_create = bwn_vap_create;
1112	ic->ic_vap_delete = bwn_vap_delete;
1113
1114	ieee80211_radiotap_attach(ic,
1115	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1116	    BWN_TX_RADIOTAP_PRESENT,
1117	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1118	    BWN_RX_RADIOTAP_PRESENT);
1119
1120#ifdef BWN_DEBUG
1121	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1122	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1123	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
1124#endif
1125
1126	if (bootverbose)
1127		ieee80211_announce(ic);
1128	return (0);
1129}
1130
1131static void
1132bwn_phy_detach(struct bwn_mac *mac)
1133{
1134
1135	if (mac->mac_phy.detach != NULL)
1136		mac->mac_phy.detach(mac);
1137}
1138
1139static int
1140bwn_detach(device_t dev)
1141{
1142	struct bwn_softc *sc = device_get_softc(dev);
1143	struct bwn_mac *mac = sc->sc_curmac;
1144	struct ifnet *ifp = sc->sc_ifp;
1145	struct ieee80211com *ic = ifp->if_l2com;
1146	int i;
1147
1148	sc->sc_flags |= BWN_FLAG_INVALID;
1149
1150	if (device_is_attached(sc->sc_dev)) {
1151		bwn_stop(sc, 1);
1152		bwn_dma_free(mac);
1153		callout_drain(&sc->sc_led_blink_ch);
1154		callout_drain(&sc->sc_rfswitch_ch);
1155		callout_drain(&sc->sc_task_ch);
1156		callout_drain(&sc->sc_watchdog_ch);
1157		bwn_phy_detach(mac);
1158		if (ifp != NULL) {
1159			ieee80211_draintask(ic, &mac->mac_hwreset);
1160			ieee80211_draintask(ic, &mac->mac_txpower);
1161			ieee80211_ifdetach(ic);
1162			if_free(ifp);
1163		}
1164	}
1165	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1166	taskqueue_free(sc->sc_tq);
1167
1168	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1169		if (mac->mac_intrhand[i] != NULL) {
1170			bus_teardown_intr(dev, mac->mac_res_irq[i],
1171			    mac->mac_intrhand[i]);
1172			mac->mac_intrhand[i] = NULL;
1173		}
1174	}
1175	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1176	if (mac->mac_msi != 0)
1177		pci_release_msi(dev);
1178
1179	BWN_LOCK_DESTROY(sc);
1180	return (0);
1181}
1182
1183static int
1184bwn_attach_pre(struct bwn_softc *sc)
1185{
1186	struct ifnet *ifp;
1187	int error = 0;
1188
1189	BWN_LOCK_INIT(sc);
1190	TAILQ_INIT(&sc->sc_maclist);
1191	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1192	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1193	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1194
1195	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1196		taskqueue_thread_enqueue, &sc->sc_tq);
1197	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1198		"%s taskq", device_get_nameunit(sc->sc_dev));
1199
1200	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1201	if (ifp == NULL) {
1202		device_printf(sc->sc_dev, "can not if_alloc()\n");
1203		error = ENOSPC;
1204		goto fail;
1205	}
1206
1207	/* set these up early for if_printf use */
1208	if_initname(ifp, device_get_name(sc->sc_dev),
1209	    device_get_unit(sc->sc_dev));
1210
1211	ifp->if_softc = sc;
1212	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1213	ifp->if_init = bwn_init;
1214	ifp->if_ioctl = bwn_ioctl;
1215	ifp->if_start = bwn_start;
1216	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1217	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1218	IFQ_SET_READY(&ifp->if_snd);
1219
1220	return (0);
1221
1222fail:	BWN_LOCK_DESTROY(sc);
1223	return (error);
1224}
1225
1226static void
1227bwn_sprom_bugfixes(struct siba_softc *siba)
1228{
1229#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1230	((siba->siba_pci_vid == PCI_VENDOR_##_vendor) &&		\
1231	 (siba->siba_pci_did == _device) &&				\
1232	 (siba->siba_pci_subvid == PCI_VENDOR_##_subvendor) &&		\
1233	 (siba->siba_pci_subdid == _subdevice))
1234
1235	if (siba->siba_board_vendor == PCI_VENDOR_APPLE &&
1236	    siba->siba_board_type == 0x4e && siba->siba_board_rev > 0x40)
1237		siba->siba_sprom.bf_lo |= BWN_BFL_PACTRL;
1238	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_DELL &&
1239	    siba->siba_chipid == 0x4301 && siba->siba_board_rev == 0x74)
1240		siba->siba_sprom.bf_lo |= BWN_BFL_BTCOEXIST;
1241	if (siba->siba_type == SIBA_TYPE_PCI) {
1242		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1243		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1244		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1245		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1246		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1247		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1248		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1249			siba->siba_sprom.bf_lo &= ~BWN_BFL_BTCOEXIST;
1250	}
1251#undef	BWN_ISDEV
1252}
1253
1254static int
1255bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1256{
1257#define	IS_RUNNING(ifp) \
1258	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1259	struct bwn_softc *sc = ifp->if_softc;
1260	struct ieee80211com *ic = ifp->if_l2com;
1261	struct ifreq *ifr = (struct ifreq *)data;
1262	int error = 0, startall;
1263
1264	switch (cmd) {
1265	case SIOCSIFFLAGS:
1266		startall = 0;
1267		if (IS_RUNNING(ifp)) {
1268			bwn_update_promisc(ifp);
1269		} else if (ifp->if_flags & IFF_UP) {
1270			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1271				bwn_init(sc);
1272				startall = 1;
1273			}
1274		} else
1275			bwn_stop(sc, 1);
1276		if (startall)
1277			ieee80211_start_all(ic);
1278		break;
1279	case SIOCGIFMEDIA:
1280		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1281		break;
1282	case SIOCGIFADDR:
1283		error = ether_ioctl(ifp, cmd, data);
1284		break;
1285	default:
1286		error = EINVAL;
1287		break;
1288	}
1289	return (error);
1290}
1291
1292static void
1293bwn_start(struct ifnet *ifp)
1294{
1295	struct bwn_softc *sc = ifp->if_softc;
1296
1297	BWN_LOCK(sc);
1298	bwn_start_locked(ifp);
1299	BWN_UNLOCK(sc);
1300}
1301
1302static void
1303bwn_start_locked(struct ifnet *ifp)
1304{
1305	struct bwn_softc *sc = ifp->if_softc;
1306	struct bwn_mac *mac = sc->sc_curmac;
1307	struct ieee80211_frame *wh;
1308	struct ieee80211_node *ni;
1309	struct ieee80211_key *k;
1310	struct mbuf *m;
1311
1312	BWN_ASSERT_LOCKED(sc);
1313
1314	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1315	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1316		return;
1317
1318	for (;;) {
1319		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1320		if (m == NULL)
1321			break;
1322
1323		if (bwn_tx_isfull(sc, m))
1324			break;
1325		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1326		if (ni == NULL) {
1327			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1328			m_freem(m);
1329			ifp->if_oerrors++;
1330			continue;
1331		}
1332		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1333		wh = mtod(m, struct ieee80211_frame *);
1334		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1335			k = ieee80211_crypto_encap(ni, m);
1336			if (k == NULL) {
1337				ieee80211_free_node(ni);
1338				m_freem(m);
1339				ifp->if_oerrors++;
1340				continue;
1341			}
1342		}
1343		wh = NULL;	/* Catch any invalid use */
1344
1345		if (bwn_tx_start(sc, ni, m) != 0) {
1346			if (ni != NULL)
1347				ieee80211_free_node(ni);
1348			ifp->if_oerrors++;
1349			continue;
1350		}
1351
1352		sc->sc_watchdog_timer = 5;
1353	}
1354}
1355
1356static int
1357bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1358{
1359	struct bwn_dma_ring *dr;
1360	struct bwn_mac *mac = sc->sc_curmac;
1361	struct bwn_pio_txqueue *tq;
1362	struct ifnet *ifp = sc->sc_ifp;
1363	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1364
1365	BWN_ASSERT_LOCKED(sc);
1366
1367	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1368		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1369		if (dr->dr_stop == 1 ||
1370		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1371			dr->dr_stop = 1;
1372			goto full;
1373		}
1374	} else {
1375		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1376		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1377		    pktlen > (tq->tq_size - tq->tq_used)) {
1378			tq->tq_stop = 1;
1379			goto full;
1380		}
1381	}
1382	return (0);
1383full:
1384	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1385	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1386	return (1);
1387}
1388
1389static int
1390bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1391{
1392	struct bwn_mac *mac = sc->sc_curmac;
1393	int error;
1394
1395	BWN_ASSERT_LOCKED(sc);
1396
1397	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1398		m_freem(m);
1399		return (ENXIO);
1400	}
1401
1402	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1403	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1404	if (error) {
1405		m_freem(m);
1406		return (error);
1407	}
1408	return (0);
1409}
1410
1411static int
1412bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1413{
1414	struct bwn_pio_txpkt *tp;
1415	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1416	struct bwn_softc *sc = mac->mac_sc;
1417	struct bwn_txhdr txhdr;
1418	struct mbuf *m_new;
1419	uint32_t ctl32;
1420	int error;
1421	uint16_t ctl16;
1422
1423	BWN_ASSERT_LOCKED(sc);
1424
1425	/* XXX TODO send packets after DTIM */
1426
1427	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1428	tp = TAILQ_FIRST(&tq->tq_pktlist);
1429	tp->tp_ni = ni;
1430	tp->tp_m = m;
1431
1432	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1433	if (error) {
1434		device_printf(sc->sc_dev, "tx fail\n");
1435		return (error);
1436	}
1437
1438	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1439	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1440	tq->tq_free--;
1441
1442	if (mac->mac_sd->sd_id.sd_rev >= 8) {
1443		/*
1444		 * XXX please removes m_defrag(9)
1445		 */
1446		m_new = m_defrag(m, M_DONTWAIT);
1447		if (m_new == NULL) {
1448			device_printf(sc->sc_dev,
1449			    "%s: can't defrag TX buffer\n",
1450			    __func__);
1451			return (ENOBUFS);
1452		}
1453		if (m_new->m_next != NULL)
1454			device_printf(sc->sc_dev,
1455			    "TODO: fragmented packets for PIO\n");
1456		tp->tp_m = m_new;
1457
1458		/* send HEADER */
1459		ctl32 = bwn_pio_write_multi_4(mac, tq,
1460		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1461			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1462		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1463		/* send BODY */
1464		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1465		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1466		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1467		    ctl32 | BWN_PIO8_TXCTL_EOF);
1468	} else {
1469		ctl16 = bwn_pio_write_multi_2(mac, tq,
1470		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1471			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1472		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1473		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1474		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1475		    ctl16 | BWN_PIO_TXCTL_EOF);
1476	}
1477
1478	return (0);
1479}
1480
1481static struct bwn_pio_txqueue *
1482bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1483{
1484
1485	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1486		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1487
1488	switch (prio) {
1489	case 0:
1490		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1491	case 1:
1492		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1493	case 2:
1494		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1495	case 3:
1496		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1497	}
1498	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1499	return (NULL);
1500}
1501
1502static int
1503bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1504{
1505#define	BWN_GET_TXHDRCACHE(slot)					\
1506	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1507	struct bwn_dma *dma = &mac->mac_method.dma;
1508	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1509	struct bwn_dmadesc_generic *desc;
1510	struct bwn_dmadesc_meta *mt;
1511	struct bwn_softc *sc = mac->mac_sc;
1512	struct ifnet *ifp = sc->sc_ifp;
1513	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1514	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1515
1516	BWN_ASSERT_LOCKED(sc);
1517	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1518
1519	/* XXX send after DTIM */
1520
1521	slot = bwn_dma_getslot(dr);
1522	dr->getdesc(dr, slot, &desc, &mt);
1523	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1524	    ("%s:%d: fail", __func__, __LINE__));
1525
1526	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1527	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1528	    BWN_DMA_COOKIE(dr, slot));
1529	if (error)
1530		goto fail;
1531	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1532	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1533	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1534	if (error) {
1535		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1536		    __func__, error);
1537		goto fail;
1538	}
1539	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1540	    BUS_DMASYNC_PREWRITE);
1541	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1542	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1543	    BUS_DMASYNC_PREWRITE);
1544
1545	slot = bwn_dma_getslot(dr);
1546	dr->getdesc(dr, slot, &desc, &mt);
1547	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1548	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1549	mt->mt_m = m;
1550	mt->mt_ni = ni;
1551
1552	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1553	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1554	if (error && error != EFBIG) {
1555		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1556		    __func__, error);
1557		goto fail;
1558	}
1559	if (error) {    /* error == EFBIG */
1560		struct mbuf *m_new;
1561
1562		m_new = m_defrag(m, M_DONTWAIT);
1563		if (m_new == NULL) {
1564			if_printf(ifp, "%s: can't defrag TX buffer\n",
1565			    __func__);
1566			error = ENOBUFS;
1567			goto fail;
1568		} else {
1569			m = m_new;
1570		}
1571
1572		mt->mt_m = m;
1573		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1574		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1575		if (error) {
1576			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1577			    __func__, error);
1578			goto fail;
1579		}
1580	}
1581	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1582	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1583	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1584	    BUS_DMASYNC_PREWRITE);
1585
1586	/* XXX send after DTIM */
1587
1588	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1589	return (0);
1590fail:
1591	dr->dr_curslot = backup[0];
1592	dr->dr_usedslot = backup[1];
1593	return (error);
1594#undef BWN_GET_TXHDRCACHE
1595}
1596
1597static void
1598bwn_watchdog(void *arg)
1599{
1600	struct bwn_softc *sc = arg;
1601	struct ifnet *ifp = sc->sc_ifp;
1602
1603	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1604		if_printf(ifp, "device timeout\n");
1605		ifp->if_oerrors++;
1606	}
1607	callout_schedule(&sc->sc_watchdog_ch, hz);
1608}
1609
1610static int
1611bwn_attach_core(struct bwn_mac *mac)
1612{
1613	struct bwn_softc *sc = mac->mac_sc;
1614	struct siba_dev_softc *sd = mac->mac_sd;
1615	struct siba_softc *siba = sd->sd_bus;
1616	int error, have_bg = 0, have_a = 0;
1617	uint32_t high;
1618
1619	KASSERT(sd->sd_id.sd_rev >= 5,
1620	    ("unsupported revision %d", sd->sd_id.sd_rev));
1621
1622	siba_powerup(siba, 0);
1623
1624	high = siba_read_4(sd, SIBA_TGSHIGH);
1625	bwn_reset_core(mac,
1626	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1627	error = bwn_phy_getinfo(mac, high);
1628	if (error)
1629		goto fail;
1630
1631	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1632	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1633	if (siba->siba_pci_did != 0x4312 && siba->siba_pci_did != 0x4319 &&
1634	    siba->siba_pci_did != 0x4324) {
1635		have_a = have_bg = 0;
1636		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1637			have_a = 1;
1638		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1639		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1640		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1641			have_bg = 1;
1642		else
1643			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1644			    mac->mac_phy.type));
1645	}
1646	/* XXX turns off PHY A because it's not supported */
1647	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1648	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1649		have_a = 0;
1650		have_bg = 1;
1651	}
1652
1653	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1654		mac->mac_phy.attach = bwn_phy_g_attach;
1655		mac->mac_phy.detach = bwn_phy_g_detach;
1656		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1657		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1658		mac->mac_phy.init = bwn_phy_g_init;
1659		mac->mac_phy.exit = bwn_phy_g_exit;
1660		mac->mac_phy.phy_read = bwn_phy_g_read;
1661		mac->mac_phy.phy_write = bwn_phy_g_write;
1662		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1663		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1664		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1665		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1666		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1667		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1668		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1669		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1670		mac->mac_phy.set_im = bwn_phy_g_im;
1671		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1672		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1673		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1674		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1675	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1676		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1677		mac->mac_phy.init = bwn_phy_lp_init;
1678		mac->mac_phy.phy_read = bwn_phy_lp_read;
1679		mac->mac_phy.phy_write = bwn_phy_lp_write;
1680		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1681		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1682		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1683		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1684		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1685		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1686		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1687		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1688		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1689	} else {
1690		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1691		    mac->mac_phy.type);
1692		error = ENXIO;
1693		goto fail;
1694	}
1695
1696	mac->mac_phy.gmode = have_bg;
1697	if (mac->mac_phy.attach != NULL) {
1698		error = mac->mac_phy.attach(mac);
1699		if (error) {
1700			device_printf(sc->sc_dev, "failed\n");
1701			goto fail;
1702		}
1703	}
1704
1705	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1706
1707	error = bwn_chiptest(mac);
1708	if (error)
1709		goto fail;
1710	error = bwn_setup_channels(mac, have_bg, have_a);
1711	if (error) {
1712		device_printf(sc->sc_dev, "failed to setup channels\n");
1713		goto fail;
1714	}
1715
1716	if (sc->sc_curmac == NULL)
1717		sc->sc_curmac = mac;
1718
1719	error = bwn_dma_attach(mac);
1720	if (error != 0) {
1721		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1722		goto fail;
1723	}
1724
1725	mac->mac_phy.switch_analog(mac, 0);
1726
1727	siba_dev_down(sd, 0);
1728fail:
1729	siba_powerdown(siba);
1730	return (error);
1731}
1732
1733static void
1734bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1735{
1736	struct siba_dev_softc *sd = mac->mac_sd;
1737	uint32_t low, ctl;
1738
1739	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1740
1741	siba_dev_up(sd, flags);
1742	DELAY(2000);
1743
1744	low = (siba_read_4(sd, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1745	    ~BWN_TGSLOW_PHYRESET;
1746	siba_write_4(sd, SIBA_TGSLOW, low);
1747	siba_read_4(sd, SIBA_TGSLOW);
1748	DELAY(1000);
1749	siba_write_4(sd, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1750	siba_read_4(sd, SIBA_TGSLOW);
1751	DELAY(1000);
1752
1753	if (mac->mac_phy.switch_analog != NULL)
1754		mac->mac_phy.switch_analog(mac, 1);
1755
1756	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1757	if (flags & BWN_TGSLOW_SUPPORT_G)
1758		ctl |= BWN_MACCTL_GMODE;
1759	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1760}
1761
1762static int
1763bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1764{
1765	struct bwn_phy *phy = &mac->mac_phy;
1766	struct bwn_softc *sc = mac->mac_sc;
1767	struct siba_dev_softc *sd = mac->mac_sd;
1768	struct siba_softc *siba = sd->sd_bus;
1769	uint32_t tmp;
1770
1771	/* PHY */
1772	tmp = BWN_READ_2(mac, BWN_PHYVER);
1773	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1774	phy->rf_on = 1;
1775	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1776	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1777	phy->rev = (tmp & BWN_PHYVER_VERSION);
1778	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1779	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1780		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1781	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1782	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1783	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1784		goto unsupphy;
1785
1786	/* RADIO */
1787	if (siba->siba_chipid == 0x4317) {
1788		if (siba->siba_chiprev == 0)
1789			tmp = 0x3205017f;
1790		else if (siba->siba_chiprev == 1)
1791			tmp = 0x4205017f;
1792		else
1793			tmp = 0x5205017f;
1794	} else {
1795		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1796		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1797		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1798		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1799	}
1800	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1801	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1802	phy->rf_manuf = (tmp & 0x00000fff);
1803	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1804		goto unsupradio;
1805	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1806	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1807	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1808	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1809	    (phy->type == BWN_PHYTYPE_N &&
1810	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1811	    (phy->type == BWN_PHYTYPE_LP &&
1812	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1813		goto unsupradio;
1814
1815	return (0);
1816unsupphy:
1817	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1818	    "analog %#x)\n",
1819	    phy->type, phy->rev, phy->analog);
1820	return (ENXIO);
1821unsupradio:
1822	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1823	    "rev %#x)\n",
1824	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1825	return (ENXIO);
1826}
1827
1828static int
1829bwn_chiptest(struct bwn_mac *mac)
1830{
1831#define	TESTVAL0	0x55aaaa55
1832#define	TESTVAL1	0xaa5555aa
1833	struct bwn_softc *sc = mac->mac_sc;
1834	struct siba_dev_softc *sd = mac->mac_sd;
1835	uint32_t v, backup;
1836
1837	BWN_LOCK(sc);
1838
1839	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1840
1841	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1842	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1843		goto error;
1844	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1845	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1846		goto error;
1847
1848	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1849
1850	if ((sd->sd_id.sd_rev >= 3) && (sd->sd_id.sd_rev <= 10)) {
1851		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1852		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1853		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1854			goto error;
1855		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1856			goto error;
1857	}
1858	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1859
1860	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1861	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1862		goto error;
1863
1864	BWN_UNLOCK(sc);
1865	return (0);
1866error:
1867	BWN_UNLOCK(sc);
1868	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1869	return (ENODEV);
1870}
1871
1872#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1873#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1874
1875static int
1876bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1877{
1878	struct bwn_softc *sc = mac->mac_sc;
1879	struct ifnet *ifp = sc->sc_ifp;
1880	struct ieee80211com *ic = ifp->if_l2com;
1881
1882	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1883	ic->ic_nchans = 0;
1884
1885	if (have_bg)
1886		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1887		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1888	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1889		if (have_a)
1890			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1891			    &ic->ic_nchans, &bwn_chantable_n,
1892			    IEEE80211_CHAN_HTA);
1893	} else {
1894		if (have_a)
1895			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1896			    &ic->ic_nchans, &bwn_chantable_a,
1897			    IEEE80211_CHAN_A);
1898	}
1899
1900	mac->mac_phy.supports_2ghz = have_bg;
1901	mac->mac_phy.supports_5ghz = have_a;
1902
1903	return (ic->ic_nchans == 0 ? ENXIO : 0);
1904}
1905
1906static uint32_t
1907bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1908{
1909	uint32_t ret;
1910
1911	BWN_ASSERT_LOCKED(mac->mac_sc);
1912
1913	if (way == BWN_SHARED) {
1914		KASSERT((offset & 0x0001) == 0,
1915		    ("%s:%d warn", __func__, __LINE__));
1916		if (offset & 0x0003) {
1917			bwn_shm_ctlword(mac, way, offset >> 2);
1918			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1919			ret <<= 16;
1920			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1921			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1922			goto out;
1923		}
1924		offset >>= 2;
1925	}
1926	bwn_shm_ctlword(mac, way, offset);
1927	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1928out:
1929	return (ret);
1930}
1931
1932static uint16_t
1933bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1934{
1935	uint16_t ret;
1936
1937	BWN_ASSERT_LOCKED(mac->mac_sc);
1938
1939	if (way == BWN_SHARED) {
1940		KASSERT((offset & 0x0001) == 0,
1941		    ("%s:%d warn", __func__, __LINE__));
1942		if (offset & 0x0003) {
1943			bwn_shm_ctlword(mac, way, offset >> 2);
1944			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1945			goto out;
1946		}
1947		offset >>= 2;
1948	}
1949	bwn_shm_ctlword(mac, way, offset);
1950	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1951out:
1952
1953	return (ret);
1954}
1955
1956static void
1957bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1958    uint16_t offset)
1959{
1960	uint32_t control;
1961
1962	control = way;
1963	control <<= 16;
1964	control |= offset;
1965	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1966}
1967
1968static void
1969bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1970    uint32_t value)
1971{
1972	BWN_ASSERT_LOCKED(mac->mac_sc);
1973
1974	if (way == BWN_SHARED) {
1975		KASSERT((offset & 0x0001) == 0,
1976		    ("%s:%d warn", __func__, __LINE__));
1977		if (offset & 0x0003) {
1978			bwn_shm_ctlword(mac, way, offset >> 2);
1979			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1980				    (value >> 16) & 0xffff);
1981			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1982			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1983			return;
1984		}
1985		offset >>= 2;
1986	}
1987	bwn_shm_ctlword(mac, way, offset);
1988	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1989}
1990
1991static void
1992bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1993    uint16_t value)
1994{
1995	BWN_ASSERT_LOCKED(mac->mac_sc);
1996
1997	if (way == BWN_SHARED) {
1998		KASSERT((offset & 0x0001) == 0,
1999		    ("%s:%d warn", __func__, __LINE__));
2000		if (offset & 0x0003) {
2001			bwn_shm_ctlword(mac, way, offset >> 2);
2002			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
2003			return;
2004		}
2005		offset >>= 2;
2006	}
2007	bwn_shm_ctlword(mac, way, offset);
2008	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
2009}
2010
2011static void
2012bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2013    int txpow)
2014{
2015
2016	c->ic_freq = freq;
2017	c->ic_flags = flags;
2018	c->ic_ieee = ieee;
2019	c->ic_minpower = 0;
2020	c->ic_maxpower = 2 * txpow;
2021	c->ic_maxregpower = txpow;
2022}
2023
2024static void
2025bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2026    const struct bwn_channelinfo *ci, int flags)
2027{
2028	struct ieee80211_channel *c;
2029	int i;
2030
2031	c = &chans[*nchans];
2032
2033	for (i = 0; i < ci->nchannels; i++) {
2034		const struct bwn_channel *hc;
2035
2036		hc = &ci->channels[i];
2037		if (*nchans >= maxchans)
2038			break;
2039		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2040		c++, (*nchans)++;
2041		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2042			/* g channel have a separate b-only entry */
2043			if (*nchans >= maxchans)
2044				break;
2045			c[0] = c[-1];
2046			c[-1].ic_flags = IEEE80211_CHAN_B;
2047			c++, (*nchans)++;
2048		}
2049		if (flags == IEEE80211_CHAN_HTG) {
2050			/* HT g channel have a separate g-only entry */
2051			if (*nchans >= maxchans)
2052				break;
2053			c[-1].ic_flags = IEEE80211_CHAN_G;
2054			c[0] = c[-1];
2055			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2056			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2057			c++, (*nchans)++;
2058		}
2059		if (flags == IEEE80211_CHAN_HTA) {
2060			/* HT a channel have a separate a-only entry */
2061			if (*nchans >= maxchans)
2062				break;
2063			c[-1].ic_flags = IEEE80211_CHAN_A;
2064			c[0] = c[-1];
2065			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2066			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2067			c++, (*nchans)++;
2068		}
2069	}
2070}
2071
2072static int
2073bwn_phy_g_attach(struct bwn_mac *mac)
2074{
2075	struct bwn_softc *sc = mac->mac_sc;
2076	struct bwn_phy *phy = &mac->mac_phy;
2077	struct bwn_phy_g *pg = &phy->phy_g;
2078	struct siba_dev_softc *sd = mac->mac_sd;
2079	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
2080	unsigned int i;
2081	int16_t pab0 = (int16_t)(sprom->pa0b0), pab1 = (int16_t)(sprom->pa0b1),
2082	    pab2 = (int16_t)(sprom->pa0b2);
2083	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2084	int8_t bg = (int8_t)sprom->tssi_bg;
2085
2086	if ((sd->sd_bus->siba_chipid == 0x4301) && (phy->rf_ver != 0x2050))
2087		device_printf(sc->sc_dev, "not supported anymore\n");
2088
2089	pg->pg_flags = 0;
2090	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2091	    pab2 == -1) {
2092		pg->pg_idletssi = 52;
2093		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2094		return (0);
2095	}
2096
2097	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2098	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2099	if (pg->pg_tssi2dbm == NULL) {
2100		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2101		return (ENOMEM);
2102	}
2103	for (i = 0; i < 64; i++) {
2104		int32_t m1, m2, f, q, delta;
2105		int8_t j = 0;
2106
2107		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2108		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2109		f = 256;
2110
2111		do {
2112			if (j > 15) {
2113				device_printf(sc->sc_dev,
2114				    "failed to generate tssi2dBm\n");
2115				free(pg->pg_tssi2dbm, M_DEVBUF);
2116				return (ENOMEM);
2117			}
2118			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2119			    f, 2048);
2120			delta = abs(q - f);
2121			f = q;
2122			j++;
2123		} while (delta >= 2);
2124
2125		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2126		    128);
2127	}
2128
2129	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2130	return (0);
2131}
2132
2133static void
2134bwn_phy_g_detach(struct bwn_mac *mac)
2135{
2136	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2137
2138	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2139		free(pg->pg_tssi2dbm, M_DEVBUF);
2140		pg->pg_tssi2dbm = NULL;
2141	}
2142	pg->pg_flags = 0;
2143}
2144
2145static void
2146bwn_phy_g_init_pre(struct bwn_mac *mac)
2147{
2148	struct bwn_phy *phy = &mac->mac_phy;
2149	struct bwn_phy_g *pg = &phy->phy_g;
2150	void *tssi2dbm;
2151	int idletssi;
2152	unsigned int i;
2153
2154	tssi2dbm = pg->pg_tssi2dbm;
2155	idletssi = pg->pg_idletssi;
2156
2157	memset(pg, 0, sizeof(*pg));
2158
2159	pg->pg_tssi2dbm = tssi2dbm;
2160	pg->pg_idletssi = idletssi;
2161
2162	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2163
2164	for (i = 0; i < N(pg->pg_nrssi); i++)
2165		pg->pg_nrssi[i] = -1000;
2166	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2167		pg->pg_nrssi_lt[i] = i;
2168	pg->pg_lofcal = 0xffff;
2169	pg->pg_initval = 0xffff;
2170	pg->pg_immode = BWN_IMMODE_NONE;
2171	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2172	pg->pg_avgtssi = 0xff;
2173
2174	pg->pg_loctl.tx_bias = 0xff;
2175	TAILQ_INIT(&pg->pg_loctl.calib_list);
2176}
2177
2178static int
2179bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2180{
2181	struct bwn_phy *phy = &mac->mac_phy;
2182	struct bwn_phy_g *pg = &phy->phy_g;
2183	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2184	struct siba_softc *bus = mac->mac_sd->sd_bus;
2185	static const struct bwn_rfatt rfatt0[] = {
2186		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2187		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2188		{ 3, 1 }, { 4, 1 }
2189	};
2190	static const struct bwn_rfatt rfatt1[] = {
2191		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2192		{ 14, 1 }
2193	};
2194	static const struct bwn_rfatt rfatt2[] = {
2195		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2196		{ 9, 1 }
2197	};
2198	static const struct bwn_bbatt bbatt_0[] = {
2199		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2200	};
2201
2202	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2203
2204	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2205		pg->pg_bbatt.att = 0;
2206	else
2207		pg->pg_bbatt.att = 2;
2208
2209	/* prepare Radio Attenuation */
2210	pg->pg_rfatt.padmix = 0;
2211
2212	if (bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
2213	    bus->siba_board_type == SIBA_BOARD_BCM4309G) {
2214		if (bus->siba_board_rev < 0x43) {
2215			pg->pg_rfatt.att = 2;
2216			goto done;
2217		} else if (bus->siba_board_rev < 0x51) {
2218			pg->pg_rfatt.att = 3;
2219			goto done;
2220		}
2221	}
2222
2223	if (phy->type == BWN_PHYTYPE_A) {
2224		pg->pg_rfatt.att = 0x60;
2225		goto done;
2226	}
2227
2228	switch (phy->rf_ver) {
2229	case 0x2050:
2230		switch (phy->rf_rev) {
2231		case 0:
2232			pg->pg_rfatt.att = 5;
2233			goto done;
2234		case 1:
2235			if (phy->type == BWN_PHYTYPE_G) {
2236				if (bus->siba_board_vendor ==
2237				    SIBA_BOARDVENDOR_BCM &&
2238				    bus->siba_board_type ==
2239				    SIBA_BOARD_BCM4309G &&
2240				    bus->siba_board_rev >= 30)
2241					pg->pg_rfatt.att = 3;
2242				else if (bus->siba_board_vendor ==
2243				    SIBA_BOARDVENDOR_BCM &&
2244				    bus->siba_board_type == SIBA_BOARD_BU4306)
2245					pg->pg_rfatt.att = 3;
2246				else
2247					pg->pg_rfatt.att = 1;
2248			} else {
2249				if (bus->siba_board_vendor ==
2250				    SIBA_BOARDVENDOR_BCM &&
2251				    bus->siba_board_type ==
2252				    SIBA_BOARD_BCM4309G &&
2253				    bus->siba_board_rev >= 30)
2254					pg->pg_rfatt.att = 7;
2255				else
2256					pg->pg_rfatt.att = 6;
2257			}
2258			goto done;
2259		case 2:
2260			if (phy->type == BWN_PHYTYPE_G) {
2261				if (bus->siba_board_vendor ==
2262				    SIBA_BOARDVENDOR_BCM &&
2263				    bus->siba_board_type ==
2264				    SIBA_BOARD_BCM4309G &&
2265				    bus->siba_board_rev >= 30)
2266					pg->pg_rfatt.att = 3;
2267				else if (bus->siba_board_vendor ==
2268				    SIBA_BOARDVENDOR_BCM &&
2269				    bus->siba_board_type == SIBA_BOARD_BU4306)
2270					pg->pg_rfatt.att = 5;
2271				else if (bus->siba_chipid == 0x4320)
2272					pg->pg_rfatt.att = 4;
2273				else
2274					pg->pg_rfatt.att = 3;
2275			} else
2276				pg->pg_rfatt.att = 6;
2277			goto done;
2278		case 3:
2279			pg->pg_rfatt.att = 5;
2280			goto done;
2281		case 4:
2282		case 5:
2283			pg->pg_rfatt.att = 1;
2284			goto done;
2285		case 6:
2286		case 7:
2287			pg->pg_rfatt.att = 5;
2288			goto done;
2289		case 8:
2290			pg->pg_rfatt.att = 0xa;
2291			pg->pg_rfatt.padmix = 1;
2292			goto done;
2293		case 9:
2294		default:
2295			pg->pg_rfatt.att = 5;
2296			goto done;
2297		}
2298		break;
2299	case 0x2053:
2300		switch (phy->rf_rev) {
2301		case 1:
2302			pg->pg_rfatt.att = 6;
2303			goto done;
2304		}
2305		break;
2306	}
2307	pg->pg_rfatt.att = 5;
2308done:
2309	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2310
2311	if (!bwn_has_hwpctl(mac)) {
2312		lo->rfatt.array = rfatt0;
2313		lo->rfatt.len = N(rfatt0);
2314		lo->rfatt.min = 0;
2315		lo->rfatt.max = 9;
2316		goto genbbatt;
2317	}
2318	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2319		lo->rfatt.array = rfatt1;
2320		lo->rfatt.len = N(rfatt1);
2321		lo->rfatt.min = 0;
2322		lo->rfatt.max = 14;
2323		goto genbbatt;
2324	}
2325	lo->rfatt.array = rfatt2;
2326	lo->rfatt.len = N(rfatt2);
2327	lo->rfatt.min = 0;
2328	lo->rfatt.max = 9;
2329genbbatt:
2330	lo->bbatt.array = bbatt_0;
2331	lo->bbatt.len = N(bbatt_0);
2332	lo->bbatt.min = 0;
2333	lo->bbatt.max = 8;
2334
2335	BWN_READ_4(mac, BWN_MACCTL);
2336	if (phy->rev == 1) {
2337		phy->gmode = 0;
2338		bwn_reset_core(mac, 0);
2339		bwn_phy_g_init_sub(mac);
2340		phy->gmode = 1;
2341		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2342	}
2343	return (0);
2344}
2345
2346static uint16_t
2347bwn_phy_g_txctl(struct bwn_mac *mac)
2348{
2349	struct bwn_phy *phy = &mac->mac_phy;
2350
2351	if (phy->rf_ver != 0x2050)
2352		return (0);
2353	if (phy->rf_rev == 1)
2354		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2355	if (phy->rf_rev < 6)
2356		return (BWN_TXCTL_PA2DB);
2357	if (phy->rf_rev == 8)
2358		return (BWN_TXCTL_TXMIX);
2359	return (0);
2360}
2361
2362static int
2363bwn_phy_g_init(struct bwn_mac *mac)
2364{
2365
2366	bwn_phy_g_init_sub(mac);
2367	return (0);
2368}
2369
2370static void
2371bwn_phy_g_exit(struct bwn_mac *mac)
2372{
2373	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2374	struct bwn_lo_calib *cal, *tmp;
2375
2376	if (lo == NULL)
2377		return;
2378	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2379		TAILQ_REMOVE(&lo->calib_list, cal, list);
2380		free(cal, M_DEVBUF);
2381	}
2382}
2383
2384static uint16_t
2385bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2386{
2387
2388	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2389	return (BWN_READ_2(mac, BWN_PHYDATA));
2390}
2391
2392static void
2393bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2394{
2395
2396	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2397	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2398}
2399
2400static uint16_t
2401bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2402{
2403
2404	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2405	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2406	return (BWN_READ_2(mac, BWN_RFDATALO));
2407}
2408
2409static void
2410bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2411{
2412
2413	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2414	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2415	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2416}
2417
2418static int
2419bwn_phy_g_hwpctl(struct bwn_mac *mac)
2420{
2421
2422	return (mac->mac_phy.rev >= 6);
2423}
2424
2425static void
2426bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2427{
2428	struct bwn_phy *phy = &mac->mac_phy;
2429	struct bwn_phy_g *pg = &phy->phy_g;
2430	unsigned int channel;
2431	uint16_t rfover, rfoverval;
2432
2433	if (on) {
2434		if (phy->rf_on)
2435			return;
2436
2437		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2438		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2439		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2440		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2441			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2442			    pg->pg_radioctx_over);
2443			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2444			    pg->pg_radioctx_overval);
2445			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2446		}
2447		channel = phy->chan;
2448		bwn_phy_g_switch_chan(mac, 6, 1);
2449		bwn_phy_g_switch_chan(mac, channel, 0);
2450		return;
2451	}
2452
2453	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2454	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2455	pg->pg_radioctx_over = rfover;
2456	pg->pg_radioctx_overval = rfoverval;
2457	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2458	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2459	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2460}
2461
2462static int
2463bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2464{
2465
2466	if ((newchan < 1) || (newchan > 14))
2467		return (EINVAL);
2468	bwn_phy_g_switch_chan(mac, newchan, 0);
2469
2470	return (0);
2471}
2472
2473static uint32_t
2474bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2475{
2476
2477	return (1);
2478}
2479
2480static void
2481bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2482{
2483	struct bwn_phy *phy = &mac->mac_phy;
2484	uint64_t hf;
2485	int autodiv = 0;
2486	uint16_t tmp;
2487
2488	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2489		autodiv = 1;
2490
2491	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2492	bwn_hf_write(mac, hf);
2493
2494	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2495	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2496	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2497		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2498
2499	if (autodiv) {
2500		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2501		if (antenna == BWN_ANTAUTO1)
2502			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2503		else
2504			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2505		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2506	}
2507	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2508	if (autodiv)
2509		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2510	else
2511		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2512	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2513	if (phy->rev >= 2) {
2514		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2515		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2516		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2517		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2518		    0x15);
2519		if (phy->rev == 2)
2520			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2521		else
2522			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2523			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2524			    8);
2525	}
2526	if (phy->rev >= 6)
2527		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2528
2529	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2530	bwn_hf_write(mac, hf);
2531}
2532
2533static int
2534bwn_phy_g_im(struct bwn_mac *mac, int mode)
2535{
2536	struct bwn_phy *phy = &mac->mac_phy;
2537	struct bwn_phy_g *pg = &phy->phy_g;
2538
2539	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2540	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2541
2542	if (phy->rev == 0 || !phy->gmode)
2543		return (ENODEV);
2544
2545	pg->pg_aci_wlan_automatic = 0;
2546	return (0);
2547}
2548
2549static int
2550bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2551{
2552	struct bwn_phy *phy = &mac->mac_phy;
2553	struct bwn_phy_g *pg = &phy->phy_g;
2554	struct bwn_softc *sc = mac->mac_sc;
2555	struct siba_softc *siba = mac->mac_sd->sd_bus;
2556	unsigned int tssi;
2557	int cck, ofdm;
2558	int power;
2559	int rfatt, bbatt;
2560	unsigned int max;
2561
2562	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2563
2564	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2565	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2566	if (cck < 0 && ofdm < 0) {
2567		if (ignore_tssi == 0)
2568			return (BWN_TXPWR_RES_DONE);
2569		cck = 0;
2570		ofdm = 0;
2571	}
2572	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2573	if (pg->pg_avgtssi != 0xff)
2574		tssi = (tssi + pg->pg_avgtssi) / 2;
2575	pg->pg_avgtssi = tssi;
2576	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2577
2578	max = siba->siba_sprom.maxpwr_bg;
2579	if (siba->siba_sprom.bf_lo & BWN_BFL_PACTRL)
2580		max -= 3;
2581	if (max >= 120) {
2582		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2583		siba->siba_sprom.maxpwr_bg = max = 80;
2584	}
2585
2586	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2587	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2588	     tssi, 0x00), 0x3f)]);
2589	if (power == 0)
2590		return (BWN_TXPWR_RES_DONE);
2591
2592	rfatt = -((power + 7) / 8);
2593	bbatt = (-(power / 2)) - (4 * rfatt);
2594	if ((rfatt == 0) && (bbatt == 0))
2595		return (BWN_TXPWR_RES_DONE);
2596	pg->pg_bbatt_delta = bbatt;
2597	pg->pg_rfatt_delta = rfatt;
2598	return (BWN_TXPWR_RES_NEED_ADJUST);
2599}
2600
2601static void
2602bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2603{
2604	struct bwn_phy *phy = &mac->mac_phy;
2605	struct bwn_phy_g *pg = &phy->phy_g;
2606	struct bwn_softc *sc = mac->mac_sc;
2607	int rfatt, bbatt;
2608	uint8_t txctl;
2609
2610	bwn_mac_suspend(mac);
2611
2612	BWN_ASSERT_LOCKED(sc);
2613
2614	bbatt = pg->pg_bbatt.att;
2615	bbatt += pg->pg_bbatt_delta;
2616	rfatt = pg->pg_rfatt.att;
2617	rfatt += pg->pg_rfatt_delta;
2618
2619	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2620	txctl = pg->pg_txctl;
2621	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2622		if (rfatt <= 1) {
2623			if (txctl == 0) {
2624				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2625				rfatt += 2;
2626				bbatt += 2;
2627			} else if (mac->mac_sd->sd_bus->siba_sprom.
2628				   bf_lo &
2629				   BWN_BFL_PACTRL) {
2630				bbatt += 4 * (rfatt - 2);
2631				rfatt = 2;
2632			}
2633		} else if (rfatt > 4 && txctl) {
2634			txctl = 0;
2635			if (bbatt < 3) {
2636				rfatt -= 3;
2637				bbatt += 2;
2638			} else {
2639				rfatt -= 2;
2640				bbatt -= 2;
2641			}
2642		}
2643	}
2644	pg->pg_txctl = txctl;
2645	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2646	pg->pg_rfatt.att = rfatt;
2647	pg->pg_bbatt.att = bbatt;
2648
2649	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2650
2651	bwn_phy_lock(mac);
2652	bwn_rf_lock(mac);
2653	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2654	    pg->pg_txctl);
2655	bwn_rf_unlock(mac);
2656	bwn_phy_unlock(mac);
2657
2658	bwn_mac_enable(mac);
2659}
2660
2661static void
2662bwn_phy_g_task_15s(struct bwn_mac *mac)
2663{
2664	struct bwn_phy *phy = &mac->mac_phy;
2665	struct bwn_phy_g *pg = &phy->phy_g;
2666	struct bwn_softc *sc = mac->mac_sc;
2667	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2668	unsigned long expire, now;
2669	struct bwn_lo_calib *cal, *tmp;
2670	uint8_t expired = 0;
2671
2672	bwn_mac_suspend(mac);
2673
2674	if (lo == NULL)
2675		goto fail;
2676
2677	BWN_GETTIME(now);
2678	if (bwn_has_hwpctl(mac)) {
2679		expire = now - BWN_LO_PWRVEC_EXPIRE;
2680		if (time_before(lo->pwr_vec_read_time, expire)) {
2681			bwn_lo_get_powervector(mac);
2682			bwn_phy_g_dc_lookup_init(mac, 0);
2683		}
2684		goto fail;
2685	}
2686
2687	expire = now - BWN_LO_CALIB_EXPIRE;
2688	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2689		if (!time_before(cal->calib_time, expire))
2690			continue;
2691		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2692		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2693			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2694			expired = 1;
2695		}
2696
2697		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2698		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2699		    cal->ctl.i, cal->ctl.q);
2700
2701		TAILQ_REMOVE(&lo->calib_list, cal, list);
2702		free(cal, M_DEVBUF);
2703	}
2704	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2705		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2706		    &pg->pg_rfatt);
2707		if (cal == NULL) {
2708			device_printf(sc->sc_dev,
2709			    "failed to recalibrate LO\n");
2710			goto fail;
2711		}
2712		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2713		bwn_lo_write(mac, &cal->ctl);
2714	}
2715
2716fail:
2717	bwn_mac_enable(mac);
2718}
2719
2720static void
2721bwn_phy_g_task_60s(struct bwn_mac *mac)
2722{
2723	struct bwn_phy *phy = &mac->mac_phy;
2724	uint8_t old = phy->chan;
2725
2726	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI))
2727		return;
2728
2729	bwn_mac_suspend(mac);
2730	bwn_nrssi_slope_11g(mac);
2731	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2732		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2733		bwn_switch_channel(mac, old);
2734	}
2735	bwn_mac_enable(mac);
2736}
2737
2738static void
2739bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2740{
2741
2742	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2743}
2744
2745static int
2746bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2747	const struct ieee80211_bpf_params *params)
2748{
2749	struct ieee80211com *ic = ni->ni_ic;
2750	struct ifnet *ifp = ic->ic_ifp;
2751	struct bwn_softc *sc = ifp->if_softc;
2752	struct bwn_mac *mac = sc->sc_curmac;
2753
2754	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2755	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2756		ieee80211_free_node(ni);
2757		m_freem(m);
2758		return (ENETDOWN);
2759	}
2760
2761	BWN_LOCK(sc);
2762	if (bwn_tx_isfull(sc, m)) {
2763		ieee80211_free_node(ni);
2764		m_freem(m);
2765		ifp->if_oerrors++;
2766		BWN_UNLOCK(sc);
2767		return (ENOBUFS);
2768	}
2769
2770	if (bwn_tx_start(sc, ni, m) != 0) {
2771		if (ni != NULL)
2772			ieee80211_free_node(ni);
2773		ifp->if_oerrors++;
2774	}
2775	sc->sc_watchdog_timer = 5;
2776	BWN_UNLOCK(sc);
2777	return (0);
2778}
2779
2780/*
2781 * Setup driver-specific state for a newly associated node.
2782 * Note that we're called also on a re-associate, the isnew
2783 * param tells us if this is the first time or not.
2784 */
2785static void
2786bwn_newassoc(struct ieee80211_node *ni, int isnew)
2787{
2788	struct ieee80211vap *vap = ni->ni_vap;
2789
2790	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2791	    &BWN_NODE(ni)->bn_amn, ni);
2792}
2793
2794/*
2795 * Callback from the 802.11 layer to update the slot time
2796 * based on the current setting.  We use it to notify the
2797 * firmware of ERP changes and the f/w takes care of things
2798 * like slot time and preamble.
2799 */
2800static void
2801bwn_updateslot(struct ifnet *ifp)
2802{
2803	struct bwn_softc *sc = ifp->if_softc;
2804	struct ieee80211com *ic = ifp->if_l2com;
2805	struct bwn_mac *mac;
2806
2807	BWN_LOCK(sc);
2808	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2809		mac = (struct bwn_mac *)sc->sc_curmac;
2810		bwn_set_slot_time(mac,
2811		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2812	}
2813	BWN_UNLOCK(sc);
2814}
2815
2816/*
2817 * Callback from the 802.11 layer after a promiscuous mode change.
2818 * Note this interface does not check the operating mode as this
2819 * is an internal callback and we are expected to honor the current
2820 * state (e.g. this is used for setting the interface in promiscuous
2821 * mode when operating in hostap mode to do ACS).
2822 */
2823static void
2824bwn_update_promisc(struct ifnet *ifp)
2825{
2826	struct bwn_softc *sc = ifp->if_softc;
2827	struct bwn_mac *mac = sc->sc_curmac;
2828
2829	BWN_LOCK(sc);
2830	mac = sc->sc_curmac;
2831	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2832		if (ifp->if_flags & IFF_PROMISC)
2833			sc->sc_filters |= BWN_MACCTL_PROMISC;
2834		else
2835			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2836		bwn_set_opmode(mac);
2837	}
2838	BWN_UNLOCK(sc);
2839}
2840
2841/*
2842 * Callback from the 802.11 layer to update WME parameters.
2843 */
2844static int
2845bwn_wme_update(struct ieee80211com *ic)
2846{
2847	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2848	struct bwn_mac *mac = sc->sc_curmac;
2849	struct wmeParams *wmep;
2850	int i;
2851
2852	BWN_LOCK(sc);
2853	mac = sc->sc_curmac;
2854	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2855		bwn_mac_suspend(mac);
2856		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2857			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2858			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2859		}
2860		bwn_mac_enable(mac);
2861	}
2862	BWN_UNLOCK(sc);
2863	return (0);
2864}
2865
2866static struct ieee80211_node *
2867bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2868{
2869	struct ieee80211com *ic = vap->iv_ic;
2870	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2871	const size_t space = sizeof(struct bwn_node);
2872	struct bwn_node *bn;
2873
2874	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2875	if (bn == NULL) {
2876		/* XXX stat+msg */
2877		return (NULL);
2878	}
2879	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2880	return (&bn->bn_node);
2881}
2882
2883static void
2884bwn_node_cleanup(struct ieee80211_node *ni)
2885{
2886	struct ieee80211com *ic = ni->ni_ic;
2887	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2888
2889	sc->sc_node_cleanup(ni);
2890}
2891
2892static void
2893bwn_scan_start(struct ieee80211com *ic)
2894{
2895	struct ifnet *ifp = ic->ic_ifp;
2896	struct bwn_softc *sc = ifp->if_softc;
2897	struct bwn_mac *mac;
2898
2899	BWN_LOCK(sc);
2900	mac = sc->sc_curmac;
2901	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2902		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2903		bwn_set_opmode(mac);
2904		/* disable CFP update during scan */
2905		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2906	}
2907	BWN_UNLOCK(sc);
2908}
2909
2910static void
2911bwn_scan_end(struct ieee80211com *ic)
2912{
2913	struct ifnet *ifp = ic->ic_ifp;
2914	struct bwn_softc *sc = ifp->if_softc;
2915	struct bwn_mac *mac;
2916
2917	BWN_LOCK(sc);
2918	mac = sc->sc_curmac;
2919	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2920		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2921		bwn_set_opmode(mac);
2922		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2923	}
2924	BWN_UNLOCK(sc);
2925}
2926
2927static void
2928bwn_set_channel(struct ieee80211com *ic)
2929{
2930	struct ifnet *ifp = ic->ic_ifp;
2931	struct bwn_softc *sc = ifp->if_softc;
2932	struct bwn_mac *mac = sc->sc_curmac;
2933	struct bwn_phy *phy = &mac->mac_phy;
2934	int chan, error;
2935
2936	BWN_LOCK(sc);
2937
2938	error = bwn_switch_band(sc, ic->ic_curchan);
2939	if (error)
2940		goto fail;;
2941	bwn_mac_suspend(mac);
2942	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2943	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2944	if (chan != phy->chan)
2945		bwn_switch_channel(mac, chan);
2946
2947	/* TX power level */
2948	if (ic->ic_curchan->ic_maxpower != 0 &&
2949	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2950		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2951		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2952		    BWN_TXPWR_IGNORE_TSSI);
2953	}
2954
2955	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2956	if (phy->set_antenna)
2957		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2958
2959	if (sc->sc_rf_enabled != phy->rf_on) {
2960		if (sc->sc_rf_enabled) {
2961			bwn_rf_turnon(mac);
2962			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2963				device_printf(sc->sc_dev,
2964				    "please turns on the RF switch\n");
2965		} else
2966			bwn_rf_turnoff(mac);
2967	}
2968
2969	bwn_mac_enable(mac);
2970
2971fail:
2972	/*
2973	 * Setup radio tap channel freq and flags
2974	 */
2975	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2976		htole16(ic->ic_curchan->ic_freq);
2977	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2978		htole16(ic->ic_curchan->ic_flags & 0xffff);
2979
2980	BWN_UNLOCK(sc);
2981}
2982
2983static struct ieee80211vap *
2984bwn_vap_create(struct ieee80211com *ic,
2985	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2986	const uint8_t bssid[IEEE80211_ADDR_LEN],
2987	const uint8_t mac0[IEEE80211_ADDR_LEN])
2988{
2989	struct ifnet *ifp = ic->ic_ifp;
2990	struct bwn_softc *sc = ifp->if_softc;
2991	struct ieee80211vap *vap;
2992	struct bwn_vap *bvp;
2993	uint8_t mac[IEEE80211_ADDR_LEN];
2994
2995	IEEE80211_ADDR_COPY(mac, mac0);
2996	switch (opmode) {
2997	case IEEE80211_M_HOSTAP:
2998	case IEEE80211_M_MBSS:
2999	case IEEE80211_M_STA:
3000	case IEEE80211_M_WDS:
3001	case IEEE80211_M_MONITOR:
3002	case IEEE80211_M_IBSS:
3003	case IEEE80211_M_AHDEMO:
3004		break;
3005	default:
3006		return (NULL);
3007	}
3008
3009	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3010
3011	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3012	    M_80211_VAP, M_NOWAIT | M_ZERO);
3013	if (bvp == NULL) {
3014		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3015		return (NULL);
3016	}
3017	vap = &bvp->bv_vap;
3018	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3019	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3020	/* override with driver methods */
3021	bvp->bv_newstate = vap->iv_newstate;
3022	vap->iv_newstate = bwn_newstate;
3023
3024	/* override max aid so sta's cannot assoc when we're out of sta id's */
3025	vap->iv_max_aid = BWN_STAID_MAX;
3026
3027	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3028	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3029	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3030	    500 /*ms*/);
3031
3032	/* complete setup */
3033	ieee80211_vap_attach(vap, ieee80211_media_change,
3034	    ieee80211_media_status);
3035	return (vap);
3036}
3037
3038static void
3039bwn_vap_delete(struct ieee80211vap *vap)
3040{
3041	struct bwn_vap *bvp = BWN_VAP(vap);
3042
3043	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3044	ieee80211_vap_detach(vap);
3045	free(bvp, M_80211_VAP);
3046}
3047
3048static void
3049bwn_init(void *arg)
3050{
3051	struct bwn_softc *sc = arg;
3052	struct ifnet *ifp = sc->sc_ifp;
3053	struct ieee80211com *ic = ifp->if_l2com;
3054	int error = 0;
3055
3056	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3057		__func__, ifp->if_flags);
3058
3059	BWN_LOCK(sc);
3060	error = bwn_init_locked(sc);
3061	BWN_UNLOCK(sc);
3062
3063	if (error == 0)
3064		ieee80211_start_all(ic);	/* start all vap's */
3065}
3066
3067static int
3068bwn_init_locked(struct bwn_softc *sc)
3069{
3070	struct bwn_mac *mac;
3071	struct ifnet *ifp = sc->sc_ifp;
3072	int error;
3073
3074	BWN_ASSERT_LOCKED(sc);
3075
3076	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3077	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3078	sc->sc_filters = 0;
3079	bwn_wme_clear(sc);
3080	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3081	sc->sc_rf_enabled = 1;
3082
3083	mac = sc->sc_curmac;
3084	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3085		error = bwn_core_init(mac);
3086		if (error != 0)
3087			return (error);
3088	}
3089	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3090		bwn_core_start(mac);
3091
3092	bwn_set_opmode(mac);
3093	bwn_set_pretbtt(mac);
3094	bwn_spu_setdelay(mac, 0);
3095	bwn_set_macaddr(mac);
3096
3097	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3098	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3099	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3100
3101	return (0);
3102}
3103
3104static void
3105bwn_stop(struct bwn_softc *sc, int statechg)
3106{
3107
3108	BWN_LOCK(sc);
3109	bwn_stop_locked(sc, statechg);
3110	BWN_UNLOCK(sc);
3111}
3112
3113static void
3114bwn_stop_locked(struct bwn_softc *sc, int statechg)
3115{
3116	struct bwn_mac *mac = sc->sc_curmac;
3117	struct ifnet *ifp = sc->sc_ifp;
3118
3119	BWN_ASSERT_LOCKED(sc);
3120
3121	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3122		/* XXX FIXME opmode not based on VAP */
3123		bwn_set_opmode(mac);
3124		bwn_set_macaddr(mac);
3125	}
3126
3127	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3128		bwn_core_stop(mac);
3129
3130	callout_stop(&sc->sc_led_blink_ch);
3131	sc->sc_led_blinking = 0;
3132
3133	bwn_core_exit(mac);
3134	sc->sc_rf_enabled = 0;
3135
3136	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3137}
3138
3139static void
3140bwn_wme_clear(struct bwn_softc *sc)
3141{
3142#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3143	struct wmeParams *p;
3144	unsigned int i;
3145
3146	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3147	    ("%s:%d: fail", __func__, __LINE__));
3148
3149	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3150		p = &(sc->sc_wmeParams[i]);
3151
3152		switch (bwn_wme_shm_offsets[i]) {
3153		case BWN_WME_VOICE:
3154			p->wmep_txopLimit = 0;
3155			p->wmep_aifsn = 2;
3156			/* XXX FIXME: log2(cwmin) */
3157			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3158			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3159			break;
3160		case BWN_WME_VIDEO:
3161			p->wmep_txopLimit = 0;
3162			p->wmep_aifsn = 2;
3163			/* XXX FIXME: log2(cwmin) */
3164			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3165			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3166			break;
3167		case BWN_WME_BESTEFFORT:
3168			p->wmep_txopLimit = 0;
3169			p->wmep_aifsn = 3;
3170			/* XXX FIXME: log2(cwmin) */
3171			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3172			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3173			break;
3174		case BWN_WME_BACKGROUND:
3175			p->wmep_txopLimit = 0;
3176			p->wmep_aifsn = 7;
3177			/* XXX FIXME: log2(cwmin) */
3178			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3179			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3180			break;
3181		default:
3182			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3183		}
3184	}
3185}
3186
3187static int
3188bwn_core_init(struct bwn_mac *mac)
3189{
3190#ifdef BWN_DEBUG
3191	struct bwn_softc *sc = mac->mac_sc;
3192#endif
3193	struct siba_dev_softc *sd = mac->mac_sd;
3194	struct siba_softc *siba = sd->sd_bus;
3195	struct siba_sprom *sprom = &siba->siba_sprom;
3196	uint64_t hf;
3197	int error;
3198
3199	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3200	    ("%s:%d: fail", __func__, __LINE__));
3201
3202	siba_powerup(siba, 0);
3203	if (!siba_dev_isup(sd))
3204		bwn_reset_core(mac,
3205		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3206
3207	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3208	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3209	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3210	BWN_GETTIME(mac->mac_phy.nexttime);
3211	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3212	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3213	mac->mac_stats.link_noise = -95;
3214	mac->mac_reason_intr = 0;
3215	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3216	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3217#ifdef BWN_DEBUG
3218	if (sc->sc_debug & BWN_DEBUG_XMIT)
3219		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3220#endif
3221	mac->mac_suspended = 1;
3222	mac->mac_task_state = 0;
3223	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3224
3225	mac->mac_phy.init_pre(mac);
3226
3227	siba_pcicore_intr(&siba->siba_pci, sd);
3228
3229	bwn_fix_imcfglobug(mac);
3230	bwn_bt_disable(mac);
3231	if (mac->mac_phy.prepare_hw) {
3232		error = mac->mac_phy.prepare_hw(mac);
3233		if (error)
3234			goto fail0;
3235	}
3236	error = bwn_chip_init(mac);
3237	if (error)
3238		goto fail0;
3239	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3240	    mac->mac_sd->sd_id.sd_rev);
3241	hf = bwn_hf_read(mac);
3242	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3243		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3244		if (sprom->bf_lo & BWN_BFL_PACTRL)
3245			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3246		if (mac->mac_phy.rev == 1)
3247			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3248	}
3249	if (mac->mac_phy.rf_ver == 0x2050) {
3250		if (mac->mac_phy.rf_rev < 6)
3251			hf |= BWN_HF_FORCE_VCO_RECALC;
3252		if (mac->mac_phy.rf_rev == 6)
3253			hf |= BWN_HF_4318_TSSI;
3254	}
3255	if (sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW)
3256		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3257	if ((siba->siba_type == SIBA_TYPE_PCI) &&
3258	    (siba->siba_pci.spc_dev->sd_id.sd_rev <= 10))
3259		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3260	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3261	bwn_hf_write(mac, hf);
3262
3263	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3264	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3265	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3266	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3267
3268	bwn_rate_init(mac);
3269	bwn_set_phytxctl(mac);
3270
3271	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3272	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3273	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3274
3275	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3276		bwn_pio_init(mac);
3277	else
3278		bwn_dma_init(mac);
3279	if (error)
3280		goto fail1;
3281	bwn_wme_init(mac);
3282	bwn_spu_setdelay(mac, 1);
3283	bwn_bt_enable(mac);
3284
3285	siba_powerup(siba, !(sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW));
3286	bwn_set_macaddr(mac);
3287	bwn_crypt_init(mac);
3288
3289	/* XXX LED initializatin */
3290
3291	mac->mac_status = BWN_MAC_STATUS_INITED;
3292
3293	return (error);
3294
3295fail1:
3296	bwn_chip_exit(mac);
3297fail0:
3298	siba_powerdown(siba);
3299	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3300	    ("%s:%d: fail", __func__, __LINE__));
3301	return (error);
3302}
3303
3304static void
3305bwn_core_start(struct bwn_mac *mac)
3306{
3307	struct bwn_softc *sc = mac->mac_sc;
3308	uint32_t tmp;
3309
3310	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3311	    ("%s:%d: fail", __func__, __LINE__));
3312
3313	if (mac->mac_sd->sd_id.sd_rev < 5)
3314		return;
3315
3316	while (1) {
3317		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3318		if (!(tmp & 0x00000001))
3319			break;
3320		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3321	}
3322
3323	bwn_mac_enable(mac);
3324	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3325	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3326
3327	mac->mac_status = BWN_MAC_STATUS_STARTED;
3328}
3329
3330static void
3331bwn_core_exit(struct bwn_mac *mac)
3332{
3333	uint32_t macctl;
3334
3335	BWN_ASSERT_LOCKED(mac->mac_sc);
3336
3337	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3338	    ("%s:%d: fail", __func__, __LINE__));
3339
3340	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3341		return;
3342	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3343
3344	macctl = BWN_READ_4(mac, BWN_MACCTL);
3345	macctl &= ~BWN_MACCTL_MCODE_RUN;
3346	macctl |= BWN_MACCTL_MCODE_JMP0;
3347	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3348
3349	bwn_dma_stop(mac);
3350	bwn_pio_stop(mac);
3351	bwn_chip_exit(mac);
3352	mac->mac_phy.switch_analog(mac, 0);
3353	siba_dev_down(mac->mac_sd, 0);
3354	siba_powerdown(mac->mac_sd->sd_bus);
3355}
3356
3357static void
3358bwn_fix_imcfglobug(struct bwn_mac *mac)
3359{
3360	struct siba_dev_softc *sd = mac->mac_sd;
3361	struct siba_softc *siba = sd->sd_bus;
3362	uint32_t tmp;
3363
3364	if (siba->siba_pci.spc_dev == NULL)
3365		return;
3366	if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI ||
3367	    siba->siba_pci.spc_dev->sd_id.sd_rev > 5)
3368		return;
3369
3370	tmp = siba_read_4(sd, SIBA_IMCFGLO) &
3371	    ~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO);
3372	switch (siba->siba_type) {
3373	case SIBA_TYPE_PCI:
3374	case SIBA_TYPE_PCMCIA:
3375		tmp |= 0x32;
3376		break;
3377	case SIBA_TYPE_SSB:
3378		tmp |= 0x53;
3379		break;
3380	}
3381	siba_write_4(sd, SIBA_IMCFGLO, tmp);
3382}
3383
3384static void
3385bwn_bt_disable(struct bwn_mac *mac)
3386{
3387	struct bwn_softc *sc = mac->mac_sc;
3388
3389	(void)sc;
3390	/* XXX do nothing yet */
3391}
3392
3393static int
3394bwn_chip_init(struct bwn_mac *mac)
3395{
3396	struct bwn_phy *phy = &mac->mac_phy;
3397	uint32_t macctl;
3398	int error;
3399
3400	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3401	if (phy->gmode)
3402		macctl |= BWN_MACCTL_GMODE;
3403	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3404
3405	error = bwn_fw_fillinfo(mac);
3406	if (error)
3407		return (error);
3408	error = bwn_fw_loaducode(mac);
3409	if (error)
3410		return (error);
3411
3412	error = bwn_gpio_init(mac);
3413	if (error)
3414		return (error);
3415
3416	error = bwn_fw_loadinitvals(mac);
3417	if (error) {
3418		bwn_gpio_cleanup(mac);
3419		return (error);
3420	}
3421	phy->switch_analog(mac, 1);
3422	error = bwn_phy_init(mac);
3423	if (error) {
3424		bwn_gpio_cleanup(mac);
3425		return (error);
3426	}
3427	if (phy->set_im)
3428		phy->set_im(mac, BWN_IMMODE_NONE);
3429	if (phy->set_antenna)
3430		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3431	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3432
3433	if (phy->type == BWN_PHYTYPE_B)
3434		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3435	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3436	if (mac->mac_sd->sd_id.sd_rev < 5)
3437		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3438
3439	BWN_WRITE_4(mac, BWN_MACCTL,
3440	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3441	BWN_WRITE_4(mac, BWN_MACCTL,
3442	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3443	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3444
3445	bwn_set_opmode(mac);
3446	if (mac->mac_sd->sd_id.sd_rev < 3) {
3447		BWN_WRITE_2(mac, 0x060e, 0x0000);
3448		BWN_WRITE_2(mac, 0x0610, 0x8000);
3449		BWN_WRITE_2(mac, 0x0604, 0x0000);
3450		BWN_WRITE_2(mac, 0x0606, 0x0200);
3451	} else {
3452		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3453		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3454	}
3455	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3456	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3457	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3458	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3459	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3460	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3461	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3462	siba_write_4(mac->mac_sd, SIBA_TGSLOW,
3463	    siba_read_4(mac->mac_sd, SIBA_TGSLOW) | 0x00100000);
3464	BWN_WRITE_2(mac, BWN_POWERUP_DELAY,
3465	    mac->mac_sd->sd_bus->siba_cc.scc_powerup_delay);
3466	return (error);
3467}
3468
3469/* read hostflags */
3470static uint64_t
3471bwn_hf_read(struct bwn_mac *mac)
3472{
3473	uint64_t ret;
3474
3475	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3476	ret <<= 16;
3477	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3478	ret <<= 16;
3479	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3480	return (ret);
3481}
3482
3483static void
3484bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3485{
3486
3487	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3488	    (value & 0x00000000ffffull));
3489	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3490	    (value & 0x0000ffff0000ull) >> 16);
3491	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3492	    (value & 0xffff00000000ULL) >> 32);
3493}
3494
3495static void
3496bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3497{
3498
3499	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3500	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3501}
3502
3503static void
3504bwn_rate_init(struct bwn_mac *mac)
3505{
3506
3507	switch (mac->mac_phy.type) {
3508	case BWN_PHYTYPE_A:
3509	case BWN_PHYTYPE_G:
3510	case BWN_PHYTYPE_LP:
3511	case BWN_PHYTYPE_N:
3512		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3513		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3514		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3515		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3516		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3517		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3518		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3519		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3520			break;
3521		/* FALLTHROUGH */
3522	case BWN_PHYTYPE_B:
3523		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3524		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3525		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3526		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3527		break;
3528	default:
3529		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3530	}
3531}
3532
3533static void
3534bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3535{
3536	uint16_t offset;
3537
3538	if (ofdm) {
3539		offset = 0x480;
3540		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3541	} else {
3542		offset = 0x4c0;
3543		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3544	}
3545	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3546	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3547}
3548
3549static uint8_t
3550bwn_plcp_getcck(const uint8_t bitrate)
3551{
3552
3553	switch (bitrate) {
3554	case BWN_CCK_RATE_1MB:
3555		return (0x0a);
3556	case BWN_CCK_RATE_2MB:
3557		return (0x14);
3558	case BWN_CCK_RATE_5MB:
3559		return (0x37);
3560	case BWN_CCK_RATE_11MB:
3561		return (0x6e);
3562	}
3563	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3564	return (0);
3565}
3566
3567static uint8_t
3568bwn_plcp_getofdm(const uint8_t bitrate)
3569{
3570
3571	switch (bitrate) {
3572	case BWN_OFDM_RATE_6MB:
3573		return (0xb);
3574	case BWN_OFDM_RATE_9MB:
3575		return (0xf);
3576	case BWN_OFDM_RATE_12MB:
3577		return (0xa);
3578	case BWN_OFDM_RATE_18MB:
3579		return (0xe);
3580	case BWN_OFDM_RATE_24MB:
3581		return (0x9);
3582	case BWN_OFDM_RATE_36MB:
3583		return (0xd);
3584	case BWN_OFDM_RATE_48MB:
3585		return (0x8);
3586	case BWN_OFDM_RATE_54MB:
3587		return (0xc);
3588	}
3589	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3590	return (0);
3591}
3592
3593static void
3594bwn_set_phytxctl(struct bwn_mac *mac)
3595{
3596	uint16_t ctl;
3597
3598	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3599	    BWN_TX_PHY_TXPWR);
3600	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3601	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3602	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3603}
3604
3605static void
3606bwn_pio_init(struct bwn_mac *mac)
3607{
3608	struct bwn_pio *pio = &mac->mac_method.pio;
3609
3610	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3611	    & ~BWN_MACCTL_BIGENDIAN);
3612	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3613
3614	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3615	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3616	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3617	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3618	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3619	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3620}
3621
3622static void
3623bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3624    int index)
3625{
3626	struct bwn_pio_txpkt *tp;
3627	unsigned int i;
3628
3629	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3630	tq->tq_index = index;
3631
3632	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3633	if (mac->mac_sd->sd_id.sd_rev >= 8)
3634		tq->tq_size = 1920;
3635	else {
3636		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3637		tq->tq_size -= 80;
3638	}
3639
3640	TAILQ_INIT(&tq->tq_pktlist);
3641	for (i = 0; i < N(tq->tq_pkts); i++) {
3642		tp = &(tq->tq_pkts[i]);
3643		tp->tp_index = i;
3644		tp->tp_queue = tq;
3645		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3646	}
3647}
3648
3649static uint16_t
3650bwn_pio_idx2base(struct bwn_mac *mac, int index)
3651{
3652	struct bwn_softc *sc = mac->mac_sc;
3653	static const uint16_t bases[] = {
3654		BWN_PIO_BASE0,
3655		BWN_PIO_BASE1,
3656		BWN_PIO_BASE2,
3657		BWN_PIO_BASE3,
3658		BWN_PIO_BASE4,
3659		BWN_PIO_BASE5,
3660		BWN_PIO_BASE6,
3661		BWN_PIO_BASE7,
3662	};
3663	static const uint16_t bases_rev11[] = {
3664		BWN_PIO11_BASE0,
3665		BWN_PIO11_BASE1,
3666		BWN_PIO11_BASE2,
3667		BWN_PIO11_BASE3,
3668		BWN_PIO11_BASE4,
3669		BWN_PIO11_BASE5,
3670	};
3671
3672	if (mac->mac_sd->sd_id.sd_rev >= 11) {
3673		if (index >= N(bases_rev11))
3674			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3675		return (bases_rev11[index]);
3676	}
3677	if (index >= N(bases))
3678		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3679	return (bases[index]);
3680}
3681
3682static void
3683bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3684    int index)
3685{
3686
3687	prq->prq_mac = mac;
3688	prq->prq_rev = mac->mac_sd->sd_id.sd_rev;
3689	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3690	bwn_dma_rxdirectfifo(mac, index, 1);
3691}
3692
3693static void
3694bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3695{
3696	if (tq == NULL)
3697		return;
3698	bwn_pio_cancel_tx_packets(tq);
3699}
3700
3701static void
3702bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3703{
3704
3705	bwn_destroy_pioqueue_tx(pio);
3706}
3707
3708static uint16_t
3709bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3710    uint16_t offset)
3711{
3712
3713	return (BWN_READ_2(mac, tq->tq_base + offset));
3714}
3715
3716static void
3717bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3718{
3719	uint32_t ctl;
3720	int type;
3721	uint16_t base;
3722
3723	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3724	base = bwn_dma_base(type, idx);
3725	if (type == BWN_DMA_64BIT) {
3726		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3727		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3728		if (enable)
3729			ctl |= BWN_DMA64_RXDIRECTFIFO;
3730		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3731	} else {
3732		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3733		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3734		if (enable)
3735			ctl |= BWN_DMA32_RXDIRECTFIFO;
3736		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3737	}
3738}
3739
3740static uint64_t
3741bwn_dma_mask(struct bwn_mac *mac)
3742{
3743	uint32_t tmp;
3744	uint16_t base;
3745
3746	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3747	if (tmp & SIBA_TGSHIGH_DMA64)
3748		return (BWN_DMA_BIT_MASK(64));
3749	base = bwn_dma_base(0, 0);
3750	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3751	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3752	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3753		return (BWN_DMA_BIT_MASK(32));
3754
3755	return (BWN_DMA_BIT_MASK(30));
3756}
3757
3758static int
3759bwn_dma_mask2type(uint64_t dmamask)
3760{
3761
3762	if (dmamask == BWN_DMA_BIT_MASK(30))
3763		return (BWN_DMA_30BIT);
3764	if (dmamask == BWN_DMA_BIT_MASK(32))
3765		return (BWN_DMA_32BIT);
3766	if (dmamask == BWN_DMA_BIT_MASK(64))
3767		return (BWN_DMA_64BIT);
3768	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3769	return (BWN_DMA_30BIT);
3770}
3771
3772static void
3773bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3774{
3775	struct bwn_pio_txpkt *tp;
3776	unsigned int i;
3777
3778	for (i = 0; i < N(tq->tq_pkts); i++) {
3779		tp = &(tq->tq_pkts[i]);
3780		if (tp->tp_m) {
3781			m_freem(tp->tp_m);
3782			tp->tp_m = NULL;
3783		}
3784	}
3785}
3786
3787static uint16_t
3788bwn_dma_base(int type, int controller_idx)
3789{
3790	static const uint16_t map64[] = {
3791		BWN_DMA64_BASE0,
3792		BWN_DMA64_BASE1,
3793		BWN_DMA64_BASE2,
3794		BWN_DMA64_BASE3,
3795		BWN_DMA64_BASE4,
3796		BWN_DMA64_BASE5,
3797	};
3798	static const uint16_t map32[] = {
3799		BWN_DMA32_BASE0,
3800		BWN_DMA32_BASE1,
3801		BWN_DMA32_BASE2,
3802		BWN_DMA32_BASE3,
3803		BWN_DMA32_BASE4,
3804		BWN_DMA32_BASE5,
3805	};
3806
3807	if (type == BWN_DMA_64BIT) {
3808		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3809		    ("%s:%d: fail", __func__, __LINE__));
3810		return (map64[controller_idx]);
3811	}
3812	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3813	    ("%s:%d: fail", __func__, __LINE__));
3814	return (map32[controller_idx]);
3815}
3816
3817static void
3818bwn_dma_init(struct bwn_mac *mac)
3819{
3820	struct bwn_dma *dma = &mac->mac_method.dma;
3821
3822	/* setup TX DMA channels. */
3823	bwn_dma_setup(dma->wme[WME_AC_BK]);
3824	bwn_dma_setup(dma->wme[WME_AC_BE]);
3825	bwn_dma_setup(dma->wme[WME_AC_VI]);
3826	bwn_dma_setup(dma->wme[WME_AC_VO]);
3827	bwn_dma_setup(dma->mcast);
3828	/* setup RX DMA channel. */
3829	bwn_dma_setup(dma->rx);
3830}
3831
3832static struct bwn_dma_ring *
3833bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3834    int for_tx, int type)
3835{
3836	struct bwn_dma *dma = &mac->mac_method.dma;
3837	struct bwn_dma_ring *dr;
3838	struct bwn_dmadesc_generic *desc;
3839	struct bwn_dmadesc_meta *mt;
3840	struct bwn_softc *sc = mac->mac_sc;
3841	int error, i;
3842
3843	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3844	if (dr == NULL)
3845		goto out;
3846	dr->dr_numslots = BWN_RXRING_SLOTS;
3847	if (for_tx)
3848		dr->dr_numslots = BWN_TXRING_SLOTS;
3849
3850	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3851	    M_DEVBUF, M_NOWAIT | M_ZERO);
3852	if (dr->dr_meta == NULL)
3853		goto fail0;
3854
3855	dr->dr_type = type;
3856	dr->dr_mac = mac;
3857	dr->dr_base = bwn_dma_base(type, controller_index);
3858	dr->dr_index = controller_index;
3859	if (type == BWN_DMA_64BIT) {
3860		dr->getdesc = bwn_dma_64_getdesc;
3861		dr->setdesc = bwn_dma_64_setdesc;
3862		dr->start_transfer = bwn_dma_64_start_transfer;
3863		dr->suspend = bwn_dma_64_suspend;
3864		dr->resume = bwn_dma_64_resume;
3865		dr->get_curslot = bwn_dma_64_get_curslot;
3866		dr->set_curslot = bwn_dma_64_set_curslot;
3867	} else {
3868		dr->getdesc = bwn_dma_32_getdesc;
3869		dr->setdesc = bwn_dma_32_setdesc;
3870		dr->start_transfer = bwn_dma_32_start_transfer;
3871		dr->suspend = bwn_dma_32_suspend;
3872		dr->resume = bwn_dma_32_resume;
3873		dr->get_curslot = bwn_dma_32_get_curslot;
3874		dr->set_curslot = bwn_dma_32_set_curslot;
3875	}
3876	if (for_tx) {
3877		dr->dr_tx = 1;
3878		dr->dr_curslot = -1;
3879	} else {
3880		if (dr->dr_index == 0) {
3881			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3882			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3883		} else
3884			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3885	}
3886
3887	error = bwn_dma_allocringmemory(dr);
3888	if (error)
3889		goto fail2;
3890
3891	if (for_tx) {
3892		/*
3893		 * Assumption: BWN_TXRING_SLOTS can be divided by
3894		 * BWN_TX_SLOTS_PER_FRAME
3895		 */
3896		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3897		    ("%s:%d: fail", __func__, __LINE__));
3898
3899		dr->dr_txhdr_cache =
3900		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3901			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3902		KASSERT(dr->dr_txhdr_cache != NULL,
3903		    ("%s:%d: fail", __func__, __LINE__));
3904
3905		/*
3906		 * Create TX ring DMA stuffs
3907		 */
3908		error = bus_dma_tag_create(dma->parent_dtag,
3909				    BWN_ALIGN, 0,
3910				    BUS_SPACE_MAXADDR,
3911				    BUS_SPACE_MAXADDR,
3912				    NULL, NULL,
3913				    BWN_HDRSIZE(mac),
3914				    1,
3915				    BUS_SPACE_MAXSIZE_32BIT,
3916				    0,
3917				    NULL, NULL,
3918				    &dr->dr_txring_dtag);
3919		if (error) {
3920			device_printf(sc->sc_dev,
3921			    "can't create TX ring DMA tag: TODO frees\n");
3922			goto fail1;
3923		}
3924
3925		for (i = 0; i < dr->dr_numslots; i += 2) {
3926			dr->getdesc(dr, i, &desc, &mt);
3927
3928			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3929			mt->mt_m = NULL;
3930			mt->mt_ni = NULL;
3931			mt->mt_islast = 0;
3932			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3933			    &mt->mt_dmap);
3934			if (error) {
3935				device_printf(sc->sc_dev,
3936				     "can't create RX buf DMA map\n");
3937				goto fail1;
3938			}
3939
3940			dr->getdesc(dr, i + 1, &desc, &mt);
3941
3942			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3943			mt->mt_m = NULL;
3944			mt->mt_ni = NULL;
3945			mt->mt_islast = 1;
3946			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3947			    &mt->mt_dmap);
3948			if (error) {
3949				device_printf(sc->sc_dev,
3950				     "can't create RX buf DMA map\n");
3951				goto fail1;
3952			}
3953		}
3954	} else {
3955		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3956		    &dr->dr_spare_dmap);
3957		if (error) {
3958			device_printf(sc->sc_dev,
3959			    "can't create RX buf DMA map\n");
3960			goto out;		/* XXX wrong! */
3961		}
3962
3963		for (i = 0; i < dr->dr_numslots; i++) {
3964			dr->getdesc(dr, i, &desc, &mt);
3965
3966			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3967			    &mt->mt_dmap);
3968			if (error) {
3969				device_printf(sc->sc_dev,
3970				    "can't create RX buf DMA map\n");
3971				goto out;	/* XXX wrong! */
3972			}
3973			error = bwn_dma_newbuf(dr, desc, mt, 1);
3974			if (error) {
3975				device_printf(sc->sc_dev,
3976				    "failed to allocate RX buf\n");
3977				goto out;	/* XXX wrong! */
3978			}
3979		}
3980
3981		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3982		    BUS_DMASYNC_PREWRITE);
3983
3984		dr->dr_usedslot = dr->dr_numslots;
3985	}
3986
3987      out:
3988	return (dr);
3989
3990fail2:
3991	free(dr->dr_txhdr_cache, M_DEVBUF);
3992fail1:
3993	free(dr->dr_meta, M_DEVBUF);
3994fail0:
3995	free(dr, M_DEVBUF);
3996	return (NULL);
3997}
3998
3999static void
4000bwn_dma_ringfree(struct bwn_dma_ring **dr)
4001{
4002
4003	if (dr == NULL)
4004		return;
4005
4006	bwn_dma_free_descbufs(*dr);
4007	bwn_dma_free_ringmemory(*dr);
4008
4009	free((*dr)->dr_txhdr_cache, M_DEVBUF);
4010	free((*dr)->dr_meta, M_DEVBUF);
4011	free(*dr, M_DEVBUF);
4012
4013	*dr = NULL;
4014}
4015
4016static void
4017bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
4018    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4019{
4020	struct bwn_dmadesc32 *desc;
4021
4022	*meta = &(dr->dr_meta[slot]);
4023	desc = dr->dr_ring_descbase;
4024	desc = &(desc[slot]);
4025
4026	*gdesc = (struct bwn_dmadesc_generic *)desc;
4027}
4028
4029static void
4030bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
4031    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4032    int start, int end, int irq)
4033{
4034	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
4035	uint32_t addr, addrext, ctl;
4036	int slot;
4037
4038	slot = (int)(&(desc->dma.dma32) - descbase);
4039	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4040	    ("%s:%d: fail", __func__, __LINE__));
4041
4042	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4043	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4044	addr |= siba_dma_translation(dr->dr_mac->mac_sd);
4045	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4046	if (slot == dr->dr_numslots - 1)
4047		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4048	if (start)
4049		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4050	if (end)
4051		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4052	if (irq)
4053		ctl |= BWN_DMA32_DCTL_IRQ;
4054	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4055	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4056
4057	desc->dma.dma32.control = htole32(ctl);
4058	desc->dma.dma32.address = htole32(addr);
4059}
4060
4061static void
4062bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4063{
4064
4065	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4066	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4067}
4068
4069static void
4070bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4071{
4072
4073	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4074	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4075}
4076
4077static void
4078bwn_dma_32_resume(struct bwn_dma_ring *dr)
4079{
4080
4081	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4082	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4083}
4084
4085static int
4086bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4087{
4088	uint32_t val;
4089
4090	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4091	val &= BWN_DMA32_RXDPTR;
4092
4093	return (val / sizeof(struct bwn_dmadesc32));
4094}
4095
4096static void
4097bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4098{
4099
4100	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4101	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4102}
4103
4104static void
4105bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4106    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4107{
4108	struct bwn_dmadesc64 *desc;
4109
4110	*meta = &(dr->dr_meta[slot]);
4111	desc = dr->dr_ring_descbase;
4112	desc = &(desc[slot]);
4113
4114	*gdesc = (struct bwn_dmadesc_generic *)desc;
4115}
4116
4117static void
4118bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4119    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4120    int start, int end, int irq)
4121{
4122	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4123	int slot;
4124	uint32_t ctl0 = 0, ctl1 = 0;
4125	uint32_t addrlo, addrhi;
4126	uint32_t addrext;
4127
4128	slot = (int)(&(desc->dma.dma64) - descbase);
4129	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4130	    ("%s:%d: fail", __func__, __LINE__));
4131
4132	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4133	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4134	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4135	    30;
4136	addrhi |= (siba_dma_translation(dr->dr_mac->mac_sd) << 1);
4137	if (slot == dr->dr_numslots - 1)
4138		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4139	if (start)
4140		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4141	if (end)
4142		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4143	if (irq)
4144		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4145	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4146	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4147	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4148
4149	desc->dma.dma64.control0 = htole32(ctl0);
4150	desc->dma.dma64.control1 = htole32(ctl1);
4151	desc->dma.dma64.address_low = htole32(addrlo);
4152	desc->dma.dma64.address_high = htole32(addrhi);
4153}
4154
4155static void
4156bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4157{
4158
4159	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4160	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4161}
4162
4163static void
4164bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4165{
4166
4167	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4168	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4169}
4170
4171static void
4172bwn_dma_64_resume(struct bwn_dma_ring *dr)
4173{
4174
4175	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4176	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4177}
4178
4179static int
4180bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4181{
4182	uint32_t val;
4183
4184	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4185	val &= BWN_DMA64_RXSTATDPTR;
4186
4187	return (val / sizeof(struct bwn_dmadesc64));
4188}
4189
4190static void
4191bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4192{
4193
4194	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4195	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4196}
4197
4198static int
4199bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4200{
4201	struct bwn_mac *mac = dr->dr_mac;
4202	struct bwn_dma *dma = &mac->mac_method.dma;
4203	struct bwn_softc *sc = mac->mac_sc;
4204	int error;
4205
4206	error = bus_dma_tag_create(dma->parent_dtag,
4207			    BWN_ALIGN, 0,
4208			    BUS_SPACE_MAXADDR,
4209			    BUS_SPACE_MAXADDR,
4210			    NULL, NULL,
4211			    BWN_DMA_RINGMEMSIZE,
4212			    1,
4213			    BUS_SPACE_MAXSIZE_32BIT,
4214			    0,
4215			    NULL, NULL,
4216			    &dr->dr_ring_dtag);
4217	if (error) {
4218		device_printf(sc->sc_dev,
4219		    "can't create TX ring DMA tag: TODO frees\n");
4220		return (-1);
4221	}
4222
4223	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4224	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4225	    &dr->dr_ring_dmap);
4226	if (error) {
4227		device_printf(sc->sc_dev,
4228		    "can't allocate DMA mem: TODO frees\n");
4229		return (-1);
4230	}
4231	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4232	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4233	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4234	if (error) {
4235		device_printf(sc->sc_dev,
4236		    "can't load DMA mem: TODO free\n");
4237		return (-1);
4238	}
4239
4240	return (0);
4241}
4242
4243static void
4244bwn_dma_setup(struct bwn_dma_ring *dr)
4245{
4246	uint64_t ring64;
4247	uint32_t addrext, ring32, value;
4248	uint32_t trans = siba_dma_translation(dr->dr_mac->mac_sd);
4249
4250	if (dr->dr_tx) {
4251		dr->dr_curslot = -1;
4252
4253		if (dr->dr_type == BWN_DMA_64BIT) {
4254			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4255			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4256			    >> 30;
4257			value = BWN_DMA64_TXENABLE;
4258			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4259			    & BWN_DMA64_TXADDREXT_MASK;
4260			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4261			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4262			    (ring64 & 0xffffffff));
4263			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4264			    ((ring64 >> 32) &
4265			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4266		} else {
4267			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4268			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4269			value = BWN_DMA32_TXENABLE;
4270			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4271			    & BWN_DMA32_TXADDREXT_MASK;
4272			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4273			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4274			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4275		}
4276		return;
4277	}
4278
4279	/*
4280	 * set for RX
4281	 */
4282	dr->dr_usedslot = dr->dr_numslots;
4283
4284	if (dr->dr_type == BWN_DMA_64BIT) {
4285		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4286		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4287		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4288		value |= BWN_DMA64_RXENABLE;
4289		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4290		    & BWN_DMA64_RXADDREXT_MASK;
4291		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4292		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4293		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4294		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4295		    | (trans << 1));
4296		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4297		    sizeof(struct bwn_dmadesc64));
4298	} else {
4299		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4300		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4301		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4302		value |= BWN_DMA32_RXENABLE;
4303		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4304		    & BWN_DMA32_RXADDREXT_MASK;
4305		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4306		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4307		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4308		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4309		    sizeof(struct bwn_dmadesc32));
4310	}
4311}
4312
4313static void
4314bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4315{
4316
4317	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4318	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4319	    dr->dr_ring_dmap);
4320}
4321
4322static void
4323bwn_dma_cleanup(struct bwn_dma_ring *dr)
4324{
4325
4326	if (dr->dr_tx) {
4327		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4328		if (dr->dr_type == BWN_DMA_64BIT) {
4329			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4330			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4331		} else
4332			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4333	} else {
4334		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4335		if (dr->dr_type == BWN_DMA_64BIT) {
4336			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4337			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4338		} else
4339			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4340	}
4341}
4342
4343static void
4344bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4345{
4346	struct bwn_dmadesc_generic *desc;
4347	struct bwn_dmadesc_meta *meta;
4348	struct bwn_mac *mac = dr->dr_mac;
4349	struct bwn_dma *dma = &mac->mac_method.dma;
4350	struct bwn_softc *sc = mac->mac_sc;
4351	int i;
4352
4353	if (!dr->dr_usedslot)
4354		return;
4355	for (i = 0; i < dr->dr_numslots; i++) {
4356		dr->getdesc(dr, i, &desc, &meta);
4357
4358		if (meta->mt_m == NULL) {
4359			if (!dr->dr_tx)
4360				device_printf(sc->sc_dev, "%s: not TX?\n",
4361				    __func__);
4362			continue;
4363		}
4364		if (dr->dr_tx) {
4365			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4366				bus_dmamap_unload(dr->dr_txring_dtag,
4367				    meta->mt_dmap);
4368			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4369				bus_dmamap_unload(dma->txbuf_dtag,
4370				    meta->mt_dmap);
4371		} else
4372			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4373		bwn_dma_free_descbuf(dr, meta);
4374	}
4375}
4376
4377static int
4378bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4379    int type)
4380{
4381	struct bwn_softc *sc = mac->mac_sc;
4382	uint32_t value;
4383	int i;
4384	uint16_t offset;
4385
4386	for (i = 0; i < 10; i++) {
4387		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4388		    BWN_DMA32_TXSTATUS;
4389		value = BWN_READ_4(mac, base + offset);
4390		if (type == BWN_DMA_64BIT) {
4391			value &= BWN_DMA64_TXSTAT;
4392			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4393			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4394			    value == BWN_DMA64_TXSTAT_STOPPED)
4395				break;
4396		} else {
4397			value &= BWN_DMA32_TXSTATE;
4398			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4399			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4400			    value == BWN_DMA32_TXSTAT_STOPPED)
4401				break;
4402		}
4403		DELAY(1000);
4404	}
4405	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4406	BWN_WRITE_4(mac, base + offset, 0);
4407	for (i = 0; i < 10; i++) {
4408		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4409						   BWN_DMA32_TXSTATUS;
4410		value = BWN_READ_4(mac, base + offset);
4411		if (type == BWN_DMA_64BIT) {
4412			value &= BWN_DMA64_TXSTAT;
4413			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4414				i = -1;
4415				break;
4416			}
4417		} else {
4418			value &= BWN_DMA32_TXSTATE;
4419			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4420				i = -1;
4421				break;
4422			}
4423		}
4424		DELAY(1000);
4425	}
4426	if (i != -1) {
4427		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4428		return (ENODEV);
4429	}
4430	DELAY(1000);
4431
4432	return (0);
4433}
4434
4435static int
4436bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4437    int type)
4438{
4439	struct bwn_softc *sc = mac->mac_sc;
4440	uint32_t value;
4441	int i;
4442	uint16_t offset;
4443
4444	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4445	BWN_WRITE_4(mac, base + offset, 0);
4446	for (i = 0; i < 10; i++) {
4447		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4448		    BWN_DMA32_RXSTATUS;
4449		value = BWN_READ_4(mac, base + offset);
4450		if (type == BWN_DMA_64BIT) {
4451			value &= BWN_DMA64_RXSTAT;
4452			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4453				i = -1;
4454				break;
4455			}
4456		} else {
4457			value &= BWN_DMA32_RXSTATE;
4458			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4459				i = -1;
4460				break;
4461			}
4462		}
4463		DELAY(1000);
4464	}
4465	if (i != -1) {
4466		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4467		return (ENODEV);
4468	}
4469
4470	return (0);
4471}
4472
4473static void
4474bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4475    struct bwn_dmadesc_meta *meta)
4476{
4477
4478	if (meta->mt_m != NULL) {
4479		m_freem(meta->mt_m);
4480		meta->mt_m = NULL;
4481	}
4482	if (meta->mt_ni != NULL) {
4483		ieee80211_free_node(meta->mt_ni);
4484		meta->mt_ni = NULL;
4485	}
4486}
4487
4488static void
4489bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4490{
4491	struct bwn_rxhdr4 *rxhdr;
4492	unsigned char *frame;
4493
4494	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4495	rxhdr->frame_len = 0;
4496
4497	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4498	    sizeof(struct bwn_plcp6) + 2,
4499	    ("%s:%d: fail", __func__, __LINE__));
4500	frame = mtod(m, char *) + dr->dr_frameoffset;
4501	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4502}
4503
4504static uint8_t
4505bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4506{
4507	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4508
4509	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4510	    == 0xff);
4511}
4512
4513static void
4514bwn_wme_init(struct bwn_mac *mac)
4515{
4516
4517	bwn_wme_load(mac);
4518
4519	/* enable WME support. */
4520	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4521	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4522	    BWN_IFSCTL_USE_EDCF);
4523}
4524
4525static void
4526bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4527{
4528	struct bwn_softc *sc = mac->mac_sc;
4529	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4530	uint16_t delay;	/* microsec */
4531
4532	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4533	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4534		delay = 500;
4535	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4536		delay = max(delay, (uint16_t)2400);
4537
4538	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4539}
4540
4541static void
4542bwn_bt_enable(struct bwn_mac *mac)
4543{
4544	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
4545	uint64_t hf;
4546
4547	if (bwn_bluetooth == 0)
4548		return;
4549	if ((sprom->bf_lo & BWN_BFL_BTCOEXIST) == 0)
4550		return;
4551	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4552		return;
4553
4554	hf = bwn_hf_read(mac);
4555	if (sprom->bf_lo & BWN_BFL_BTCMOD)
4556		hf |= BWN_HF_BT_COEXISTALT;
4557	else
4558		hf |= BWN_HF_BT_COEXIST;
4559	bwn_hf_write(mac, hf);
4560}
4561
4562static void
4563bwn_set_macaddr(struct bwn_mac *mac)
4564{
4565
4566	bwn_mac_write_bssid(mac);
4567	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4568}
4569
4570static void
4571bwn_clear_keys(struct bwn_mac *mac)
4572{
4573	int i;
4574
4575	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4576		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4577		    ("%s:%d: fail", __func__, __LINE__));
4578
4579		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4580		    NULL, BWN_SEC_KEYSIZE, NULL);
4581		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4582			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4583			    NULL, BWN_SEC_KEYSIZE, NULL);
4584		}
4585		mac->mac_key[i].keyconf = NULL;
4586	}
4587}
4588
4589static void
4590bwn_crypt_init(struct bwn_mac *mac)
4591{
4592
4593	mac->mac_max_nr_keys = (mac->mac_sd->sd_id.sd_rev >= 5) ? 58 : 20;
4594	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4595	    ("%s:%d: fail", __func__, __LINE__));
4596	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4597	mac->mac_ktp *= 2;
4598	if (mac->mac_sd->sd_id.sd_rev >= 5) {
4599		BWN_WRITE_2(mac, BWN_RCMTA_COUNT,
4600		    mac->mac_max_nr_keys - 8);
4601	}
4602	bwn_clear_keys(mac);
4603}
4604
4605static void
4606bwn_chip_exit(struct bwn_mac *mac)
4607{
4608
4609	bwn_phy_exit(mac);
4610	bwn_gpio_cleanup(mac);
4611}
4612
4613static int
4614bwn_fw_fillinfo(struct bwn_mac *mac)
4615{
4616	int error;
4617
4618	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4619	if (error == 0)
4620		return (0);
4621	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4622	if (error == 0)
4623		return (0);
4624	return (error);
4625}
4626
4627static int
4628bwn_gpio_init(struct bwn_mac *mac)
4629{
4630	struct siba_softc *bus = mac->mac_sd->sd_bus;
4631	struct siba_dev_softc *sd;
4632	uint32_t mask = 0x0000001f, set = 0x0000000f;
4633
4634	BWN_WRITE_4(mac, BWN_MACCTL,
4635	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4636	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4637	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4638
4639	if (bus->siba_chipid == 0x4301) {
4640		mask |= 0x0060;
4641		set |= 0x0060;
4642	}
4643	if (bus->siba_sprom.bf_lo & BWN_BFL_PACTRL) {
4644		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4645		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4646		mask |= 0x0200;
4647		set |= 0x0200;
4648	}
4649	if (mac->mac_sd->sd_id.sd_rev >= 2)
4650		mask |= 0x0010;
4651	sd = (bus->siba_cc.scc_dev != NULL) ? bus->siba_cc.scc_dev :
4652	    bus->siba_pci.spc_dev;
4653	if (sd == NULL)
4654		return (0);
4655	siba_write_4(sd, BWN_GPIOCTL,
4656	    (siba_read_4(sd, BWN_GPIOCTL) & mask) | set);
4657
4658	return (0);
4659}
4660
4661static int
4662bwn_fw_loadinitvals(struct bwn_mac *mac)
4663{
4664#define	GETFWOFFSET(fwp, offset)				\
4665	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4666	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4667	const struct bwn_fwhdr *hdr;
4668	struct bwn_fw *fw = &mac->mac_fw;
4669	int error;
4670
4671	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4672	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4673	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4674	if (error)
4675		return (error);
4676	if (fw->initvals_band.fw) {
4677		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4678		error = bwn_fwinitvals_write(mac,
4679		    GETFWOFFSET(fw->initvals_band, hdr_len),
4680		    be32toh(hdr->size),
4681		    fw->initvals_band.fw->datasize - hdr_len);
4682	}
4683	return (error);
4684#undef GETFWOFFSET
4685}
4686
4687static int
4688bwn_phy_init(struct bwn_mac *mac)
4689{
4690	struct bwn_softc *sc = mac->mac_sc;
4691	int error;
4692
4693	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4694	mac->mac_phy.rf_onoff(mac, 1);
4695	error = mac->mac_phy.init(mac);
4696	if (error) {
4697		device_printf(sc->sc_dev, "PHY init failed\n");
4698		goto fail0;
4699	}
4700	error = bwn_switch_channel(mac,
4701	    mac->mac_phy.get_default_chan(mac));
4702	if (error) {
4703		device_printf(sc->sc_dev,
4704		    "failed to switch default channel\n");
4705		goto fail1;
4706	}
4707	return (0);
4708fail1:
4709	if (mac->mac_phy.exit)
4710		mac->mac_phy.exit(mac);
4711fail0:
4712	mac->mac_phy.rf_onoff(mac, 0);
4713
4714	return (error);
4715}
4716
4717static void
4718bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4719{
4720	uint16_t ant;
4721	uint16_t tmp;
4722
4723	ant = bwn_ant2phy(antenna);
4724
4725	/* For ACK/CTS */
4726	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4727	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4728	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4729	/* For Probe Resposes */
4730	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4731	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4732	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4733}
4734
4735static void
4736bwn_set_opmode(struct bwn_mac *mac)
4737{
4738	struct bwn_softc *sc = mac->mac_sc;
4739	struct ifnet *ifp = sc->sc_ifp;
4740	struct ieee80211com *ic = ifp->if_l2com;
4741	uint32_t ctl;
4742	uint16_t cfp_pretbtt;
4743
4744	ctl = BWN_READ_4(mac, BWN_MACCTL);
4745	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4746	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4747	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4748	ctl |= BWN_MACCTL_STA;
4749
4750	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4751	    ic->ic_opmode == IEEE80211_M_MBSS)
4752		ctl |= BWN_MACCTL_HOSTAP;
4753	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4754		ctl &= ~BWN_MACCTL_STA;
4755	ctl |= sc->sc_filters;
4756
4757	if (mac->mac_sd->sd_id.sd_rev <= 4)
4758		ctl |= BWN_MACCTL_PROMISC;
4759
4760	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4761
4762	cfp_pretbtt = 2;
4763	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4764		if (mac->mac_sd->sd_bus->siba_chipid == 0x4306 &&
4765		    mac->mac_sd->sd_bus->siba_chiprev == 3)
4766			cfp_pretbtt = 100;
4767		else
4768			cfp_pretbtt = 50;
4769	}
4770	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4771}
4772
4773static void
4774bwn_gpio_cleanup(struct bwn_mac *mac)
4775{
4776	struct siba_softc *bus = mac->mac_sd->sd_bus;
4777	struct siba_dev_softc *gpiodev, *pcidev = NULL;
4778
4779	pcidev = bus->siba_pci.spc_dev;
4780	gpiodev = bus->siba_cc.scc_dev ? bus->siba_cc.scc_dev : pcidev;
4781	if (!gpiodev)
4782		return;
4783	siba_write_4(gpiodev, BWN_GPIOCTL, 0);
4784}
4785
4786static int
4787bwn_dma_gettype(struct bwn_mac *mac)
4788{
4789	uint32_t tmp;
4790	uint16_t base;
4791
4792	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4793	if (tmp & SIBA_TGSHIGH_DMA64)
4794		return (BWN_DMA_64BIT);
4795	base = bwn_dma_base(0, 0);
4796	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4797	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4798	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4799		return (BWN_DMA_32BIT);
4800
4801	return (BWN_DMA_30BIT);
4802}
4803
4804static void
4805bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4806{
4807	if (!error) {
4808		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4809		*((bus_addr_t *)arg) = seg->ds_addr;
4810	}
4811}
4812
4813static void
4814bwn_phy_g_init_sub(struct bwn_mac *mac)
4815{
4816	struct bwn_phy *phy = &mac->mac_phy;
4817	struct bwn_phy_g *pg = &phy->phy_g;
4818	uint16_t i, tmp;
4819
4820	if (phy->rev == 1)
4821		bwn_phy_init_b5(mac);
4822	else
4823		bwn_phy_init_b6(mac);
4824
4825	if (phy->rev >= 2 || phy->gmode)
4826		bwn_phy_init_a(mac);
4827
4828	if (phy->rev >= 2) {
4829		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4830		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4831	}
4832	if (phy->rev == 2) {
4833		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4834		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4835	}
4836	if (phy->rev > 5) {
4837		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4838		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4839	}
4840	if (phy->gmode || phy->rev >= 2) {
4841		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4842		tmp &= BWN_PHYVER_VERSION;
4843		if (tmp == 3 || tmp == 5) {
4844			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4845			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4846		}
4847		if (tmp == 5) {
4848			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4849			    0x1f00);
4850		}
4851	}
4852	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4853		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4854	if (phy->rf_rev == 8) {
4855		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4856		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4857	}
4858	if (BWN_HAS_LOOPBACK(phy))
4859		bwn_loopback_calcgain(mac);
4860
4861	if (phy->rf_rev != 8) {
4862		if (pg->pg_initval == 0xffff)
4863			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4864		else
4865			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4866	}
4867	bwn_lo_g_init(mac);
4868	if (BWN_HAS_TXMAG(phy)) {
4869		BWN_RF_WRITE(mac, 0x52,
4870		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4871		    | pg->pg_loctl.tx_bias |
4872		    pg->pg_loctl.tx_magn);
4873	} else {
4874		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4875	}
4876	if (phy->rev >= 6) {
4877		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4878		    (pg->pg_loctl.tx_bias << 12));
4879	}
4880	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL)
4881		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4882	else
4883		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4884	if (phy->rev < 2)
4885		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4886	else
4887		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4888	if (phy->gmode || phy->rev >= 2) {
4889		bwn_lo_g_adjust(mac);
4890		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4891	}
4892
4893	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
4894		for (i = 0; i < 64; i++) {
4895			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4896			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4897			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4898			    -32), 31));
4899		}
4900		bwn_nrssi_threshold(mac);
4901	} else if (phy->gmode || phy->rev >= 2) {
4902		if (pg->pg_nrssi[0] == -1000) {
4903			KASSERT(pg->pg_nrssi[1] == -1000,
4904			    ("%s:%d: fail", __func__, __LINE__));
4905			bwn_nrssi_slope_11g(mac);
4906		} else
4907			bwn_nrssi_threshold(mac);
4908	}
4909	if (phy->rf_rev == 8)
4910		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4911	bwn_phy_hwpctl_init(mac);
4912	if ((mac->mac_sd->sd_bus->siba_chipid == 0x4306
4913	     && mac->mac_sd->sd_bus->siba_chippkg == 2) || 0) {
4914		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4915		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4916	}
4917}
4918
4919static uint8_t
4920bwn_has_hwpctl(struct bwn_mac *mac)
4921{
4922
4923	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4924		return (0);
4925	return (mac->mac_phy.use_hwpctl(mac));
4926}
4927
4928static void
4929bwn_phy_init_b5(struct bwn_mac *mac)
4930{
4931	struct siba_softc *bus = mac->mac_sd->sd_bus;
4932	struct bwn_phy *phy = &mac->mac_phy;
4933	struct bwn_phy_g *pg = &phy->phy_g;
4934	uint16_t offset, value;
4935	uint8_t old_channel;
4936
4937	if (phy->analog == 1)
4938		BWN_RF_SET(mac, 0x007a, 0x0050);
4939	if ((bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM) &&
4940	    (bus->siba_board_type != SIBA_BOARD_BU4306)) {
4941		value = 0x2120;
4942		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4943			BWN_PHY_WRITE(mac, offset, value);
4944			value += 0x202;
4945		}
4946	}
4947	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4948	if (phy->rf_ver == 0x2050)
4949		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4950
4951	if (phy->gmode || phy->rev >= 2) {
4952		if (phy->rf_ver == 0x2050) {
4953			BWN_RF_SET(mac, 0x007a, 0x0020);
4954			BWN_RF_SET(mac, 0x0051, 0x0004);
4955		}
4956		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4957
4958		BWN_PHY_SET(mac, 0x0802, 0x0100);
4959		BWN_PHY_SET(mac, 0x042b, 0x2000);
4960
4961		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4962
4963		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4964		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4965		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4966	}
4967
4968	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4969		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4970
4971	if (phy->analog == 1) {
4972		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4973		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4974		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4975		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4976		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4977	} else
4978		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4979	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4980	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4981
4982	if (phy->analog == 1)
4983		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4984	else
4985		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4986
4987	if (phy->analog == 0)
4988		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4989
4990	old_channel = phy->chan;
4991	bwn_phy_g_switch_chan(mac, 7, 0);
4992
4993	if (phy->rf_ver != 0x2050) {
4994		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4995		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4996	}
4997
4998	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4999	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5000
5001	if (phy->rf_ver == 0x2050) {
5002		BWN_RF_WRITE(mac, 0x0050, 0x0020);
5003		BWN_RF_WRITE(mac, 0x005a, 0x0070);
5004	}
5005
5006	BWN_RF_WRITE(mac, 0x005b, 0x007b);
5007	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
5008	BWN_RF_SET(mac, 0x007a, 0x0007);
5009
5010	bwn_phy_g_switch_chan(mac, old_channel, 0);
5011	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
5012	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
5013	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
5014
5015	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5016	    pg->pg_txctl);
5017
5018	if (phy->rf_ver == 0x2050)
5019		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5020
5021	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
5022}
5023
5024static void
5025bwn_loopback_calcgain(struct bwn_mac *mac)
5026{
5027	struct bwn_phy *phy = &mac->mac_phy;
5028	struct bwn_phy_g *pg = &phy->phy_g;
5029	uint16_t backup_phy[16] = { 0 };
5030	uint16_t backup_radio[3];
5031	uint16_t backup_bband;
5032	uint16_t i, j, loop_i_max;
5033	uint16_t trsw_rx;
5034	uint16_t loop1_outer_done, loop1_inner_done;
5035
5036	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5037	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
5038	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5039	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5040	if (phy->rev != 1) {
5041		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5042		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5043	}
5044	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5045	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5046	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5047	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5048	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5049	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5050	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5051	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5052	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5053	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5054	backup_bband = pg->pg_bbatt.att;
5055	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5056	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5057	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5058
5059	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5060	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5061	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5062	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5063	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5064	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5065	if (phy->rev != 1) {
5066		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5067		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5068		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5069		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5070	}
5071	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5072	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5073	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5074	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5075
5076	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5077	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5078	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5079
5080	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5081	if (phy->rev != 1) {
5082		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5083		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5084	}
5085	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5086
5087	if (phy->rf_rev == 8)
5088		BWN_RF_WRITE(mac, 0x43, 0x000f);
5089	else {
5090		BWN_RF_WRITE(mac, 0x52, 0);
5091		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5092	}
5093	bwn_phy_g_set_bbatt(mac, 11);
5094
5095	if (phy->rev >= 3)
5096		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5097	else
5098		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5099	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5100
5101	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5102	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5103
5104	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5105	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5106
5107	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) {
5108		if (phy->rev >= 7) {
5109			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5110			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5111		}
5112	}
5113	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5114
5115	j = 0;
5116	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5117	for (i = 0; i < loop_i_max; i++) {
5118		for (j = 0; j < 16; j++) {
5119			BWN_RF_WRITE(mac, 0x43, i);
5120			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5121			    (j << 8));
5122			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5123			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5124			DELAY(20);
5125			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5126				goto done0;
5127		}
5128	}
5129done0:
5130	loop1_outer_done = i;
5131	loop1_inner_done = j;
5132	if (j >= 8) {
5133		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5134		trsw_rx = 0x1b;
5135		for (j = j - 8; j < 16; j++) {
5136			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5137			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5138			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5139			DELAY(20);
5140			trsw_rx -= 3;
5141			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5142				goto done1;
5143		}
5144	} else
5145		trsw_rx = 0x18;
5146done1:
5147
5148	if (phy->rev != 1) {
5149		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5150		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5151	}
5152	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5153	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5154	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5155	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5156	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5157	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5158	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5159	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5160	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5161
5162	bwn_phy_g_set_bbatt(mac, backup_bband);
5163
5164	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5165	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5166	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5167
5168	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5169	DELAY(10);
5170	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5171	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5172	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5173	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5174
5175	pg->pg_max_lb_gain =
5176	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5177	pg->pg_trsw_rx_gain = trsw_rx * 2;
5178}
5179
5180static uint16_t
5181bwn_rf_init_bcm2050(struct bwn_mac *mac)
5182{
5183	struct bwn_phy *phy = &mac->mac_phy;
5184	uint32_t tmp1 = 0, tmp2 = 0;
5185	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5186	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5187	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5188	static const uint8_t rcc_table[] = {
5189		0x02, 0x03, 0x01, 0x0f,
5190		0x06, 0x07, 0x05, 0x0f,
5191		0x0a, 0x0b, 0x09, 0x0f,
5192		0x0e, 0x0f, 0x0d, 0x0f,
5193	};
5194
5195	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5196	    rfoverval = rfover = cck3 = 0;
5197	radio0 = BWN_RF_READ(mac, 0x43);
5198	radio1 = BWN_RF_READ(mac, 0x51);
5199	radio2 = BWN_RF_READ(mac, 0x52);
5200	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5201	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5202	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5203	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5204
5205	if (phy->type == BWN_PHYTYPE_B) {
5206		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5207		reg0 = BWN_READ_2(mac, 0x3ec);
5208
5209		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5210		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5211	} else if (phy->gmode || phy->rev >= 2) {
5212		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5213		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5214		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5215		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5216		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5217		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5218
5219		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5220		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5221		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5222		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5223		if (BWN_HAS_LOOPBACK(phy)) {
5224			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5225			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5226			if (phy->rev >= 3)
5227				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5228			else
5229				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5230			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5231		}
5232
5233		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5234		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5235			BWN_LPD(0, 1, 1)));
5236		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5237		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5238	}
5239	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5240
5241	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5242	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5243	reg1 = BWN_READ_2(mac, 0x3e6);
5244	reg2 = BWN_READ_2(mac, 0x3f4);
5245
5246	if (phy->analog == 0)
5247		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5248	else {
5249		if (phy->analog >= 2)
5250			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5251		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5252		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5253	}
5254
5255	reg = BWN_RF_READ(mac, 0x60);
5256	index = (reg & 0x001e) >> 1;
5257	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5258
5259	if (phy->type == BWN_PHYTYPE_B)
5260		BWN_RF_WRITE(mac, 0x78, 0x26);
5261	if (phy->gmode || phy->rev >= 2) {
5262		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5263		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5264			BWN_LPD(0, 1, 1)));
5265	}
5266	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5267	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5268	if (phy->gmode || phy->rev >= 2) {
5269		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5270		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5271			BWN_LPD(0, 0, 1)));
5272	}
5273	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5274	BWN_RF_SET(mac, 0x51, 0x0004);
5275	if (phy->rf_rev == 8)
5276		BWN_RF_WRITE(mac, 0x43, 0x1f);
5277	else {
5278		BWN_RF_WRITE(mac, 0x52, 0);
5279		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5280	}
5281	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5282
5283	for (i = 0; i < 16; i++) {
5284		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5285		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5286		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5287		if (phy->gmode || phy->rev >= 2) {
5288			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5289			    bwn_rf_2050_rfoverval(mac,
5290				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5291		}
5292		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5293		DELAY(10);
5294		if (phy->gmode || phy->rev >= 2) {
5295			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5296			    bwn_rf_2050_rfoverval(mac,
5297				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5298		}
5299		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5300		DELAY(10);
5301		if (phy->gmode || phy->rev >= 2) {
5302			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5303			    bwn_rf_2050_rfoverval(mac,
5304				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5305		}
5306		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5307		DELAY(20);
5308		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5309		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5310		if (phy->gmode || phy->rev >= 2) {
5311			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5312			    bwn_rf_2050_rfoverval(mac,
5313				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5314		}
5315		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5316	}
5317	DELAY(10);
5318
5319	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5320	tmp1++;
5321	tmp1 >>= 9;
5322
5323	for (i = 0; i < 16; i++) {
5324		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5325		BWN_RF_WRITE(mac, 0x78, radio78);
5326		DELAY(10);
5327		for (j = 0; j < 16; j++) {
5328			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5329			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5330			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5331			if (phy->gmode || phy->rev >= 2) {
5332				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5333				    bwn_rf_2050_rfoverval(mac,
5334					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5335			}
5336			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5337			DELAY(10);
5338			if (phy->gmode || phy->rev >= 2) {
5339				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5340				    bwn_rf_2050_rfoverval(mac,
5341					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5342			}
5343			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5344			DELAY(10);
5345			if (phy->gmode || phy->rev >= 2) {
5346				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5347				    bwn_rf_2050_rfoverval(mac,
5348					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5349			}
5350			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5351			DELAY(10);
5352			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5353			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5354			if (phy->gmode || phy->rev >= 2) {
5355				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5356				    bwn_rf_2050_rfoverval(mac,
5357					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5358			}
5359			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5360		}
5361		tmp2++;
5362		tmp2 >>= 8;
5363		if (tmp1 < tmp2)
5364			break;
5365	}
5366
5367	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5368	BWN_RF_WRITE(mac, 0x51, radio1);
5369	BWN_RF_WRITE(mac, 0x52, radio2);
5370	BWN_RF_WRITE(mac, 0x43, radio0);
5371	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5372	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5373	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5374	BWN_WRITE_2(mac, 0x3e6, reg1);
5375	if (phy->analog != 0)
5376		BWN_WRITE_2(mac, 0x3f4, reg2);
5377	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5378	bwn_spu_workaround(mac, phy->chan);
5379	if (phy->type == BWN_PHYTYPE_B) {
5380		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5381		BWN_WRITE_2(mac, 0x3ec, reg0);
5382	} else if (phy->gmode) {
5383		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5384			    BWN_READ_2(mac, BWN_PHY_RADIO)
5385			    & 0x7fff);
5386		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5387		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5388		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5389		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5390			      analogoverval);
5391		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5392		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5393		if (BWN_HAS_LOOPBACK(phy)) {
5394			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5395			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5396		}
5397	}
5398
5399	return ((i > 15) ? radio78 : rcc);
5400}
5401
5402static void
5403bwn_phy_init_b6(struct bwn_mac *mac)
5404{
5405	struct bwn_phy *phy = &mac->mac_phy;
5406	struct bwn_phy_g *pg = &phy->phy_g;
5407	uint16_t offset, val;
5408	uint8_t old_channel;
5409
5410	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5411	    ("%s:%d: fail", __func__, __LINE__));
5412
5413	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5414	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5415	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5416		BWN_RF_WRITE(mac, 0x51, 0x37);
5417		BWN_RF_WRITE(mac, 0x52, 0x70);
5418		BWN_RF_WRITE(mac, 0x53, 0xb3);
5419		BWN_RF_WRITE(mac, 0x54, 0x9b);
5420		BWN_RF_WRITE(mac, 0x5a, 0x88);
5421		BWN_RF_WRITE(mac, 0x5b, 0x88);
5422		BWN_RF_WRITE(mac, 0x5d, 0x88);
5423		BWN_RF_WRITE(mac, 0x5e, 0x88);
5424		BWN_RF_WRITE(mac, 0x7d, 0x88);
5425		bwn_hf_write(mac,
5426		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5427	}
5428	if (phy->rf_rev == 8) {
5429		BWN_RF_WRITE(mac, 0x51, 0);
5430		BWN_RF_WRITE(mac, 0x52, 0x40);
5431		BWN_RF_WRITE(mac, 0x53, 0xb7);
5432		BWN_RF_WRITE(mac, 0x54, 0x98);
5433		BWN_RF_WRITE(mac, 0x5a, 0x88);
5434		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5435		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5436		if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_ALTIQ) {
5437			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5438			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5439		} else {
5440			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5441			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5442		}
5443		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5444		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5445		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5446		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5447	}
5448	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5449		BWN_PHY_WRITE(mac, offset, val);
5450		val -= 0x0202;
5451	}
5452	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5453		BWN_PHY_WRITE(mac, offset, val);
5454		val -= 0x0202;
5455	}
5456	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5457		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5458		val += 0x0202;
5459	}
5460	if (phy->type == BWN_PHYTYPE_G) {
5461		BWN_RF_SET(mac, 0x007a, 0x0020);
5462		BWN_RF_SET(mac, 0x0051, 0x0004);
5463		BWN_PHY_SET(mac, 0x0802, 0x0100);
5464		BWN_PHY_SET(mac, 0x042b, 0x2000);
5465		BWN_PHY_WRITE(mac, 0x5b, 0);
5466		BWN_PHY_WRITE(mac, 0x5c, 0);
5467	}
5468
5469	old_channel = phy->chan;
5470	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5471
5472	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5473	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5474	DELAY(40);
5475	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5476		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5477		BWN_RF_WRITE(mac, 0x50, 0x20);
5478	}
5479	if (phy->rf_rev <= 2) {
5480		BWN_RF_WRITE(mac, 0x7c, 0x20);
5481		BWN_RF_WRITE(mac, 0x5a, 0x70);
5482		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5483		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5484	}
5485	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5486
5487	bwn_phy_g_switch_chan(mac, old_channel, 0);
5488
5489	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5490	if (phy->rf_rev >= 6)
5491		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5492	else
5493		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5494	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5495	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5496	    pg->pg_txctl);
5497	if (phy->rf_rev <= 5)
5498		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5499	if (phy->rf_rev <= 2)
5500		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5501
5502	if (phy->analog == 4) {
5503		BWN_WRITE_2(mac, 0x3e4, 9);
5504		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5505	} else
5506		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5507	if (phy->type == BWN_PHYTYPE_B)
5508		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5509	else if (phy->type == BWN_PHYTYPE_G)
5510		BWN_WRITE_2(mac, 0x03e6, 0x0);
5511}
5512
5513static void
5514bwn_phy_init_a(struct bwn_mac *mac)
5515{
5516	struct bwn_phy *phy = &mac->mac_phy;
5517
5518	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5519	    ("%s:%d: fail", __func__, __LINE__));
5520
5521	if (phy->rev >= 6) {
5522		if (phy->type == BWN_PHYTYPE_A)
5523			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5524		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5525			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5526		else
5527			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5528	}
5529
5530	bwn_wa_init(mac);
5531
5532	if (phy->type == BWN_PHYTYPE_G &&
5533	    (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL))
5534		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5535}
5536
5537static void
5538bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5539{
5540	int i;
5541
5542	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5543		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5544}
5545
5546static void
5547bwn_wa_agc(struct bwn_mac *mac)
5548{
5549	struct bwn_phy *phy = &mac->mac_phy;
5550
5551	if (phy->rev == 1) {
5552		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5553		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5554		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5555		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5556		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5557		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5558		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5559		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5560		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5561	} else {
5562		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5563		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5564		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5565		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5566	}
5567
5568	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5569	    0x5700);
5570	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5571	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5572	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5573	BWN_RF_SET(mac, 0x7a, 0x0008);
5574	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5575	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5576	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5577	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5578	if (phy->rev == 1)
5579		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5580	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5581	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5582	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5583	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5584	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5585	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5586	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5587	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5588	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5589	if (phy->rev == 1) {
5590		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5591		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5592	} else {
5593		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5594		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5595		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5596		if (phy->rev >= 6) {
5597			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5598			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5599			    (uint16_t)~0xf000, 0x3000);
5600		}
5601	}
5602	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5603	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5604	if (phy->rev == 1) {
5605		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5606		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5607		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5608		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5609		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5610		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5611		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5612		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5613	} else {
5614		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5615		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5616		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5617		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5618	}
5619	if (phy->rev >= 6) {
5620		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5621		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5622	}
5623	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5624}
5625
5626static void
5627bwn_wa_grev1(struct bwn_mac *mac)
5628{
5629	struct bwn_phy *phy = &mac->mac_phy;
5630	int i;
5631	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5632	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5633	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5634
5635	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5636
5637	/* init CRSTHRES and ANTDWELL */
5638	if (phy->rev == 1) {
5639		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5640	} else if (phy->rev == 2) {
5641		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5642		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5643		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5644	} else {
5645		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5646		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5647		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5648		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5649	}
5650	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5651	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5652	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5653
5654	/* XXX support PHY-A??? */
5655	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5656		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5657		    bwn_tab_finefreqg[i]);
5658
5659	/* XXX support PHY-A??? */
5660	if (phy->rev == 1)
5661		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5662			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5663			    bwn_tab_noise_g1[i]);
5664	else
5665		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5666			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5667			    bwn_tab_noise_g2[i]);
5668
5669
5670	for (i = 0; i < N(bwn_tab_rotor); i++)
5671		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5672		    bwn_tab_rotor[i]);
5673
5674	/* XXX support PHY-A??? */
5675	if (phy->rev >= 6) {
5676		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5677		    BWN_PHY_ENCORE_EN)
5678			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5679		else
5680			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5681	} else
5682		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5683
5684	for (i = 0; i < N(bwn_tab_retard); i++)
5685		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5686		    bwn_tab_retard[i]);
5687
5688	if (phy->rev == 1) {
5689		for (i = 0; i < 16; i++)
5690			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5691			    i, 0x0020);
5692	} else {
5693		for (i = 0; i < 32; i++)
5694			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5695	}
5696
5697	bwn_wa_agc(mac);
5698}
5699
5700static void
5701bwn_wa_grev26789(struct bwn_mac *mac)
5702{
5703	struct bwn_phy *phy = &mac->mac_phy;
5704	int i;
5705	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5706	uint16_t ofdmrev;
5707
5708	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5709
5710	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5711
5712	/* init CRSTHRES and ANTDWELL */
5713	if (phy->rev == 1)
5714		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5715	else if (phy->rev == 2) {
5716		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5717		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5718		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5719	} else {
5720		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5721		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5722		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5723		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5724	}
5725
5726	for (i = 0; i < 64; i++)
5727		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5728
5729	/* XXX support PHY-A??? */
5730	if (phy->rev == 1)
5731		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5732			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5733			    bwn_tab_noise_g1[i]);
5734	else
5735		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5736			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5737			    bwn_tab_noise_g2[i]);
5738
5739	/* XXX support PHY-A??? */
5740	if (phy->rev >= 6) {
5741		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5742		    BWN_PHY_ENCORE_EN)
5743			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5744		else
5745			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5746	} else
5747		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5748
5749	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5750		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5751		    bwn_tab_sigmasqr2[i]);
5752
5753	if (phy->rev == 1) {
5754		for (i = 0; i < 16; i++)
5755			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5756			    0x0020);
5757	} else {
5758		for (i = 0; i < 32; i++)
5759			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5760	}
5761
5762	bwn_wa_agc(mac);
5763
5764	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5765	if (ofdmrev > 2) {
5766		if (phy->type == BWN_PHYTYPE_A)
5767			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5768		else
5769			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5770	} else {
5771		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5772		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5773		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5774	}
5775
5776	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5777	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5778}
5779
5780static void
5781bwn_wa_init(struct bwn_mac *mac)
5782{
5783	struct bwn_phy *phy = &mac->mac_phy;
5784	struct siba_softc *bus = mac->mac_sd->sd_bus;
5785
5786	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5787
5788	switch (phy->rev) {
5789	case 1:
5790		bwn_wa_grev1(mac);
5791		break;
5792	case 2:
5793	case 6:
5794	case 7:
5795	case 8:
5796	case 9:
5797		bwn_wa_grev26789(mac);
5798		break;
5799	default:
5800		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5801	}
5802
5803	if (bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM ||
5804	    bus->siba_board_type != SIBA_BOARD_BU4306 ||
5805	    bus->siba_board_rev != 0x17) {
5806		if (phy->rev < 2) {
5807			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5808			    0x0002);
5809			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5810			    0x0001);
5811		} else {
5812			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5813			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5814			if ((bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) &&
5815			    (phy->rev >= 7)) {
5816				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5817				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5818				    0x0020, 0x0001);
5819				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5820				    0x0021, 0x0001);
5821				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5822				    0x0022, 0x0001);
5823				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5824				    0x0023, 0x0000);
5825				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5826				    0x0000, 0x0000);
5827				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5828				    0x0003, 0x0002);
5829			}
5830		}
5831	}
5832	if (bus->siba_sprom.bf_lo & BWN_BFL_FEM) {
5833		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5834		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5835	}
5836
5837	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5838	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5839}
5840
5841static void
5842bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5843    uint16_t value)
5844{
5845	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5846	uint16_t addr;
5847
5848	addr = table + offset;
5849	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5850	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5851		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5852		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5853	}
5854	pg->pg_ofdmtab_addr = addr;
5855	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5856}
5857
5858static void
5859bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5860    uint32_t value)
5861{
5862	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5863	uint16_t addr;
5864
5865	addr = table + offset;
5866	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5867	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5868		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5869		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5870	}
5871	pg->pg_ofdmtab_addr = addr;
5872
5873	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5874	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5875}
5876
5877static void
5878bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5879    uint16_t value)
5880{
5881
5882	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5883	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5884}
5885
5886static void
5887bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5888{
5889	struct bwn_phy *phy = &mac->mac_phy;
5890	unsigned int i, max_loop;
5891	uint16_t value;
5892	uint32_t buffer[5] = {
5893		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5894	};
5895
5896	if (ofdm) {
5897		max_loop = 0x1e;
5898		buffer[0] = 0x000201cc;
5899	} else {
5900		max_loop = 0xfa;
5901		buffer[0] = 0x000b846e;
5902	}
5903
5904	BWN_ASSERT_LOCKED(mac->mac_sc);
5905
5906	for (i = 0; i < 5; i++)
5907		bwn_ram_write(mac, i * 4, buffer[i]);
5908
5909	BWN_WRITE_2(mac, 0x0568, 0x0000);
5910	BWN_WRITE_2(mac, 0x07c0,
5911	    (mac->mac_sd->sd_id.sd_rev < 11) ? 0x0000 : 0x0100);
5912	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5913	BWN_WRITE_2(mac, 0x050c, value);
5914	if (phy->type == BWN_PHYTYPE_LP)
5915		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5916	BWN_WRITE_2(mac, 0x0508, 0x0000);
5917	BWN_WRITE_2(mac, 0x050a, 0x0000);
5918	BWN_WRITE_2(mac, 0x054c, 0x0000);
5919	BWN_WRITE_2(mac, 0x056a, 0x0014);
5920	BWN_WRITE_2(mac, 0x0568, 0x0826);
5921	BWN_WRITE_2(mac, 0x0500, 0x0000);
5922	if (phy->type == BWN_PHYTYPE_LP)
5923		BWN_WRITE_2(mac, 0x0502, 0x0050);
5924	else
5925		BWN_WRITE_2(mac, 0x0502, 0x0030);
5926
5927	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5928		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5929	for (i = 0x00; i < max_loop; i++) {
5930		value = BWN_READ_2(mac, 0x050e);
5931		if (value & 0x0080)
5932			break;
5933		DELAY(10);
5934	}
5935	for (i = 0x00; i < 0x0a; i++) {
5936		value = BWN_READ_2(mac, 0x050e);
5937		if (value & 0x0400)
5938			break;
5939		DELAY(10);
5940	}
5941	for (i = 0x00; i < 0x19; i++) {
5942		value = BWN_READ_2(mac, 0x0690);
5943		if (!(value & 0x0100))
5944			break;
5945		DELAY(10);
5946	}
5947	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5948		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5949}
5950
5951static void
5952bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5953{
5954	uint32_t macctl;
5955
5956	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5957
5958	macctl = BWN_READ_4(mac, BWN_MACCTL);
5959	if (macctl & BWN_MACCTL_BIGENDIAN)
5960		printf("TODO: need swap\n");
5961
5962	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5963	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5964	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5965}
5966
5967static void
5968bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5969{
5970	uint16_t value;
5971
5972	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5973	    ("%s:%d: fail", __func__, __LINE__));
5974
5975	value = (uint8_t) (ctl->q);
5976	value |= ((uint8_t) (ctl->i)) << 8;
5977	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5978}
5979
5980static uint16_t
5981bwn_lo_calcfeed(struct bwn_mac *mac,
5982    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5983{
5984	struct bwn_phy *phy = &mac->mac_phy;
5985	uint16_t rfover;
5986	uint16_t feedthrough;
5987
5988	if (phy->gmode) {
5989		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5990		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5991
5992		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5993		    ("%s:%d: fail", __func__, __LINE__));
5994		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5995		    ("%s:%d: fail", __func__, __LINE__));
5996
5997		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5998
5999		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
6000		if ((mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA)
6001		    && phy->rev > 6)
6002			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
6003
6004		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6005		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6006		DELAY(10);
6007		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
6008		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6009		DELAY(10);
6010		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
6011		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6012		DELAY(10);
6013		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
6014	} else {
6015		pga |= BWN_PHY_PGACTL_UNKNOWN;
6016		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6017		DELAY(10);
6018		pga |= BWN_PHY_PGACTL_LOWBANDW;
6019		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6020		DELAY(10);
6021		pga |= BWN_PHY_PGACTL_LPF;
6022		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6023	}
6024	DELAY(21);
6025	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
6026
6027	return (feedthrough);
6028}
6029
6030static uint16_t
6031bwn_lo_txctl_regtable(struct bwn_mac *mac,
6032    uint16_t *value, uint16_t *pad_mix_gain)
6033{
6034	struct bwn_phy *phy = &mac->mac_phy;
6035	uint16_t reg, v, padmix;
6036
6037	if (phy->type == BWN_PHYTYPE_B) {
6038		v = 0x30;
6039		if (phy->rf_rev <= 5) {
6040			reg = 0x43;
6041			padmix = 0;
6042		} else {
6043			reg = 0x52;
6044			padmix = 5;
6045		}
6046	} else {
6047		if (phy->rev >= 2 && phy->rf_rev == 8) {
6048			reg = 0x43;
6049			v = 0x10;
6050			padmix = 2;
6051		} else {
6052			reg = 0x52;
6053			v = 0x30;
6054			padmix = 5;
6055		}
6056	}
6057	if (value)
6058		*value = v;
6059	if (pad_mix_gain)
6060		*pad_mix_gain = padmix;
6061
6062	return (reg);
6063}
6064
6065static void
6066bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6067{
6068	struct bwn_phy *phy = &mac->mac_phy;
6069	struct bwn_phy_g *pg = &phy->phy_g;
6070	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6071	uint16_t reg, mask;
6072	uint16_t trsw_rx, pga;
6073	uint16_t rf_pctl_reg;
6074
6075	static const uint8_t tx_bias_values[] = {
6076		0x09, 0x08, 0x0a, 0x01, 0x00,
6077		0x02, 0x05, 0x04, 0x06,
6078	};
6079	static const uint8_t tx_magn_values[] = {
6080		0x70, 0x40,
6081	};
6082
6083	if (!BWN_HAS_LOOPBACK(phy)) {
6084		rf_pctl_reg = 6;
6085		trsw_rx = 2;
6086		pga = 0;
6087	} else {
6088		int lb_gain;
6089
6090		trsw_rx = 0;
6091		lb_gain = pg->pg_max_lb_gain / 2;
6092		if (lb_gain > 10) {
6093			rf_pctl_reg = 0;
6094			pga = abs(10 - lb_gain) / 6;
6095			pga = MIN(MAX(pga, 0), 15);
6096		} else {
6097			int cmp_val;
6098			int tmp;
6099
6100			pga = 0;
6101			cmp_val = 0x24;
6102			if ((phy->rev >= 2) &&
6103			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6104				cmp_val = 0x3c;
6105			tmp = lb_gain;
6106			if ((10 - lb_gain) < cmp_val)
6107				tmp = (10 - lb_gain);
6108			if (tmp < 0)
6109				tmp += 6;
6110			else
6111				tmp += 3;
6112			cmp_val /= 4;
6113			tmp /= 4;
6114			if (tmp >= cmp_val)
6115				rf_pctl_reg = cmp_val;
6116			else
6117				rf_pctl_reg = tmp;
6118		}
6119	}
6120	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6121	bwn_phy_g_set_bbatt(mac, 2);
6122
6123	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6124	mask = ~mask;
6125	BWN_RF_MASK(mac, reg, mask);
6126
6127	if (BWN_HAS_TXMAG(phy)) {
6128		int i, j;
6129		int feedthrough;
6130		int min_feedth = 0xffff;
6131		uint8_t tx_magn, tx_bias;
6132
6133		for (i = 0; i < N(tx_magn_values); i++) {
6134			tx_magn = tx_magn_values[i];
6135			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6136			for (j = 0; j < N(tx_bias_values); j++) {
6137				tx_bias = tx_bias_values[j];
6138				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6139				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6140				    trsw_rx);
6141				if (feedthrough < min_feedth) {
6142					lo->tx_bias = tx_bias;
6143					lo->tx_magn = tx_magn;
6144					min_feedth = feedthrough;
6145				}
6146				if (lo->tx_bias == 0)
6147					break;
6148			}
6149			BWN_RF_WRITE(mac, 0x52,
6150					  (BWN_RF_READ(mac, 0x52)
6151					   & 0xff00) | lo->tx_bias | lo->
6152					  tx_magn);
6153		}
6154	} else {
6155		lo->tx_magn = 0;
6156		lo->tx_bias = 0;
6157		BWN_RF_MASK(mac, 0x52, 0xfff0);
6158	}
6159
6160	BWN_GETTIME(lo->txctl_measured_time);
6161}
6162
6163static void
6164bwn_lo_get_powervector(struct bwn_mac *mac)
6165{
6166	struct bwn_phy *phy = &mac->mac_phy;
6167	struct bwn_phy_g *pg = &phy->phy_g;
6168	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6169	int i;
6170	uint64_t tmp;
6171	uint64_t power_vector = 0;
6172
6173	for (i = 0; i < 8; i += 2) {
6174		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6175		power_vector |= (tmp << (i * 8));
6176		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6177	}
6178	if (power_vector)
6179		lo->power_vector = power_vector;
6180
6181	BWN_GETTIME(lo->pwr_vec_read_time);
6182}
6183
6184static void
6185bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6186    int use_trsw_rx)
6187{
6188	struct bwn_phy *phy = &mac->mac_phy;
6189	struct bwn_phy_g *pg = &phy->phy_g;
6190	uint16_t tmp;
6191
6192	if (max_rx_gain < 0)
6193		max_rx_gain = 0;
6194
6195	if (BWN_HAS_LOOPBACK(phy)) {
6196		int trsw_rx = 0;
6197		int trsw_rx_gain;
6198
6199		if (use_trsw_rx) {
6200			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6201			if (max_rx_gain >= trsw_rx_gain) {
6202				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6203				trsw_rx = 0x20;
6204			}
6205		} else
6206			trsw_rx_gain = max_rx_gain;
6207		if (trsw_rx_gain < 9) {
6208			pg->pg_lna_lod_gain = 0;
6209		} else {
6210			pg->pg_lna_lod_gain = 1;
6211			trsw_rx_gain -= 8;
6212		}
6213		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6214		pg->pg_pga_gain = trsw_rx_gain / 3;
6215		if (pg->pg_pga_gain >= 5) {
6216			pg->pg_pga_gain -= 5;
6217			pg->pg_lna_gain = 2;
6218		} else
6219			pg->pg_lna_gain = 0;
6220	} else {
6221		pg->pg_lna_gain = 0;
6222		pg->pg_trsw_rx_gain = 0x20;
6223		if (max_rx_gain >= 0x14) {
6224			pg->pg_lna_lod_gain = 1;
6225			pg->pg_pga_gain = 2;
6226		} else if (max_rx_gain >= 0x12) {
6227			pg->pg_lna_lod_gain = 1;
6228			pg->pg_pga_gain = 1;
6229		} else if (max_rx_gain >= 0xf) {
6230			pg->pg_lna_lod_gain = 1;
6231			pg->pg_pga_gain = 0;
6232		} else {
6233			pg->pg_lna_lod_gain = 0;
6234			pg->pg_pga_gain = 0;
6235		}
6236	}
6237
6238	tmp = BWN_RF_READ(mac, 0x7a);
6239	if (pg->pg_lna_lod_gain == 0)
6240		tmp &= ~0x0008;
6241	else
6242		tmp |= 0x0008;
6243	BWN_RF_WRITE(mac, 0x7a, tmp);
6244}
6245
6246static void
6247bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6248{
6249	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
6250	struct bwn_phy *phy = &mac->mac_phy;
6251	struct bwn_phy_g *pg = &phy->phy_g;
6252	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6253	struct timespec ts;
6254	uint16_t tmp;
6255
6256	if (bwn_has_hwpctl(mac)) {
6257		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6258		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6259		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6260		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6261		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6262
6263		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6264		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6265		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6266		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6267	}
6268	if (phy->type == BWN_PHYTYPE_B &&
6269	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6270		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6271		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6272	}
6273	if (phy->rev >= 2) {
6274		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6275		sav->phy_analogoverval =
6276		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6277		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6278		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6279		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6280		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6281		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6282
6283		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6284		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6285		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6286		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6287		if (phy->type == BWN_PHYTYPE_G) {
6288			if ((phy->rev >= 7) &&
6289			    (sprom->bf_lo & BWN_BFL_EXTLNA)) {
6290				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6291			} else {
6292				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6293			}
6294		} else {
6295			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6296		}
6297		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6298	}
6299	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6300	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6301	sav->rf0 = BWN_RF_READ(mac, 0x43);
6302	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6303	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6304	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6305	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6306	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6307
6308	if (!BWN_HAS_TXMAG(phy)) {
6309		sav->rf2 = BWN_RF_READ(mac, 0x52);
6310		sav->rf2 &= 0x00f0;
6311	}
6312	if (phy->type == BWN_PHYTYPE_B) {
6313		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6314		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6315		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6316		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6317	} else {
6318		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6319			    | 0x8000);
6320	}
6321	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6322		    & 0xf000);
6323
6324	tmp =
6325	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6326	BWN_PHY_WRITE(mac, tmp, 0x007f);
6327
6328	tmp = sav->phy_syncctl;
6329	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6330	tmp = sav->rf1;
6331	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6332
6333	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6334	if (phy->type == BWN_PHYTYPE_G ||
6335	    (phy->type == BWN_PHYTYPE_B &&
6336	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6337		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6338	} else
6339		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6340	if (phy->rev >= 2)
6341		bwn_dummy_transmission(mac, 0, 1);
6342	bwn_phy_g_switch_chan(mac, 6, 0);
6343	BWN_RF_READ(mac, 0x51);
6344	if (phy->type == BWN_PHYTYPE_G)
6345		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6346
6347	nanouptime(&ts);
6348	if (time_before(lo->txctl_measured_time,
6349	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6350		bwn_lo_measure_txctl_values(mac);
6351
6352	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6353		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6354	else {
6355		if (phy->type == BWN_PHYTYPE_B)
6356			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6357		else
6358			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6359	}
6360}
6361
6362static void
6363bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6364{
6365	struct bwn_phy *phy = &mac->mac_phy;
6366	struct bwn_phy_g *pg = &phy->phy_g;
6367	uint16_t tmp;
6368
6369	if (phy->rev >= 2) {
6370		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6371		tmp = (pg->pg_pga_gain << 8);
6372		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6373		DELAY(5);
6374		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6375		DELAY(2);
6376		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6377	} else {
6378		tmp = (pg->pg_pga_gain | 0xefa0);
6379		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6380	}
6381	if (phy->type == BWN_PHYTYPE_G) {
6382		if (phy->rev >= 3)
6383			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6384		else
6385			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6386		if (phy->rev >= 2)
6387			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6388		else
6389			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6390	}
6391	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6392	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6393	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6394	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6395	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6396	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6397	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6398	if (!BWN_HAS_TXMAG(phy)) {
6399		tmp = sav->rf2;
6400		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6401	}
6402	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6403	if (phy->type == BWN_PHYTYPE_B &&
6404	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6405		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6406		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6407	}
6408	if (phy->rev >= 2) {
6409		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6410		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6411			      sav->phy_analogoverval);
6412		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6413		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6414		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6415		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6416		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6417	}
6418	if (bwn_has_hwpctl(mac)) {
6419		tmp = (sav->phy_lomask & 0xbfff);
6420		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6421		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6422		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6423		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6424		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6425	}
6426	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6427}
6428
6429static int
6430bwn_lo_probe_loctl(struct bwn_mac *mac,
6431    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6432{
6433	struct bwn_phy *phy = &mac->mac_phy;
6434	struct bwn_phy_g *pg = &phy->phy_g;
6435	struct bwn_loctl orig, test;
6436	struct bwn_loctl prev = { -100, -100 };
6437	static const struct bwn_loctl modifiers[] = {
6438		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6439		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6440	};
6441	int begin, end, lower = 0, i;
6442	uint16_t feedth;
6443
6444	if (d->curstate == 0) {
6445		begin = 1;
6446		end = 8;
6447	} else if (d->curstate % 2 == 0) {
6448		begin = d->curstate - 1;
6449		end = d->curstate + 1;
6450	} else {
6451		begin = d->curstate - 2;
6452		end = d->curstate + 2;
6453	}
6454	if (begin < 1)
6455		begin += 8;
6456	if (end > 8)
6457		end -= 8;
6458
6459	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6460	i = begin;
6461	d->curstate = i;
6462	while (1) {
6463		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6464		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6465		test.i += modifiers[i - 1].i * d->multipler;
6466		test.q += modifiers[i - 1].q * d->multipler;
6467		if ((test.i != prev.i || test.q != prev.q) &&
6468		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6469			bwn_lo_write(mac, &test);
6470			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6471			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6472			if (feedth < d->feedth) {
6473				memcpy(probe, &test,
6474				    sizeof(struct bwn_loctl));
6475				lower = 1;
6476				d->feedth = feedth;
6477				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6478					break;
6479			}
6480		}
6481		memcpy(&prev, &test, sizeof(prev));
6482		if (i == end)
6483			break;
6484		if (i == 8)
6485			i = 1;
6486		else
6487			i++;
6488		d->curstate = i;
6489	}
6490
6491	return (lower);
6492}
6493
6494static void
6495bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6496{
6497	struct bwn_phy *phy = &mac->mac_phy;
6498	struct bwn_phy_g *pg = &phy->phy_g;
6499	struct bwn_lo_g_sm d;
6500	struct bwn_loctl probe;
6501	int lower, repeat, cnt = 0;
6502	uint16_t feedth;
6503
6504	d.nmeasure = 0;
6505	d.multipler = 1;
6506	if (BWN_HAS_LOOPBACK(phy))
6507		d.multipler = 3;
6508
6509	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6510	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6511
6512	do {
6513		bwn_lo_write(mac, &d.loctl);
6514		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6515		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6516		if (feedth < 0x258) {
6517			if (feedth >= 0x12c)
6518				*rxgain += 6;
6519			else
6520				*rxgain += 3;
6521			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6522			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6523		}
6524		d.feedth = feedth;
6525		d.curstate = 0;
6526		do {
6527			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6528			    ("%s:%d: fail", __func__, __LINE__));
6529			memcpy(&probe, &d.loctl,
6530			       sizeof(struct bwn_loctl));
6531			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6532			if (!lower)
6533				break;
6534			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6535				break;
6536			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6537			d.nmeasure++;
6538		} while (d.nmeasure < 24);
6539		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6540
6541		if (BWN_HAS_LOOPBACK(phy)) {
6542			if (d.feedth > 0x1194)
6543				*rxgain -= 6;
6544			else if (d.feedth < 0x5dc)
6545				*rxgain += 3;
6546			if (cnt == 0) {
6547				if (d.feedth <= 0x5dc) {
6548					d.multipler = 1;
6549					cnt++;
6550				} else
6551					d.multipler = 2;
6552			} else if (cnt == 2)
6553				d.multipler = 1;
6554		}
6555		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6556	} while (++cnt < repeat);
6557}
6558
6559static struct bwn_lo_calib *
6560bwn_lo_calibset(struct bwn_mac *mac,
6561    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6562{
6563	struct bwn_phy *phy = &mac->mac_phy;
6564	struct bwn_phy_g *pg = &phy->phy_g;
6565	struct bwn_loctl loctl = { 0, 0 };
6566	struct bwn_lo_calib *cal;
6567	struct bwn_lo_g_value sval = { 0 };
6568	int rxgain;
6569	uint16_t pad, reg, value;
6570
6571	sval.old_channel = phy->chan;
6572	bwn_mac_suspend(mac);
6573	bwn_lo_save(mac, &sval);
6574
6575	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6576	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6577	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6578
6579	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6580	if (rfatt->padmix)
6581		rxgain -= pad;
6582	if (BWN_HAS_LOOPBACK(phy))
6583		rxgain += pg->pg_max_lb_gain;
6584	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6585	bwn_phy_g_set_bbatt(mac, bbatt->att);
6586	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6587
6588	bwn_lo_restore(mac, &sval);
6589	bwn_mac_enable(mac);
6590
6591	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6592	if (!cal) {
6593		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6594		return (NULL);
6595	}
6596	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6597	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6598	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6599
6600	BWN_GETTIME(cal->calib_time);
6601
6602	return (cal);
6603}
6604
6605static struct bwn_lo_calib *
6606bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6607    const struct bwn_rfatt *rfatt)
6608{
6609	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6610	struct bwn_lo_calib *c;
6611
6612	TAILQ_FOREACH(c, &lo->calib_list, list) {
6613		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6614			continue;
6615		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6616			continue;
6617		return (c);
6618	}
6619
6620	c = bwn_lo_calibset(mac, bbatt, rfatt);
6621	if (!c)
6622		return (NULL);
6623	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6624
6625	return (c);
6626}
6627
6628static void
6629bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6630{
6631	struct bwn_phy *phy = &mac->mac_phy;
6632	struct bwn_phy_g *pg = &phy->phy_g;
6633	struct bwn_softc *sc = mac->mac_sc;
6634	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6635	const struct bwn_rfatt *rfatt;
6636	const struct bwn_bbatt *bbatt;
6637	uint64_t pvector;
6638	int i;
6639	int rf_offset, bb_offset;
6640	uint8_t changed = 0;
6641
6642	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6643	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6644	    ("%s:%d: fail", __func__, __LINE__));
6645
6646	pvector = lo->power_vector;
6647	if (!update && !pvector)
6648		return;
6649
6650	bwn_mac_suspend(mac);
6651
6652	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6653		struct bwn_lo_calib *cal;
6654		int idx;
6655		uint16_t val;
6656
6657		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6658			continue;
6659		bb_offset = i / lo->rfatt.len;
6660		rf_offset = i % lo->rfatt.len;
6661		bbatt = &(lo->bbatt.array[bb_offset]);
6662		rfatt = &(lo->rfatt.array[rf_offset]);
6663
6664		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6665		if (!cal) {
6666			device_printf(sc->sc_dev, "LO: Could not "
6667			    "calibrate DC table entry\n");
6668			continue;
6669		}
6670		val = (uint8_t)(cal->ctl.q);
6671		val |= ((uint8_t)(cal->ctl.i)) << 4;
6672		free(cal, M_DEVBUF);
6673
6674		idx = i / 2;
6675		if (i % 2)
6676			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6677			    | ((val & 0x00ff) << 8);
6678		else
6679			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6680			    | (val & 0x00ff);
6681		changed = 1;
6682	}
6683	if (changed) {
6684		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6685			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6686	}
6687	bwn_mac_enable(mac);
6688}
6689
6690static void
6691bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6692{
6693
6694	if (!rf->padmix)
6695		return;
6696	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6697		rf->att = 4;
6698}
6699
6700static void
6701bwn_lo_g_adjust(struct bwn_mac *mac)
6702{
6703	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6704	struct bwn_lo_calib *cal;
6705	struct bwn_rfatt rf;
6706
6707	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6708	bwn_lo_fixup_rfatt(&rf);
6709
6710	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6711	if (!cal)
6712		return;
6713	bwn_lo_write(mac, &cal->ctl);
6714}
6715
6716static void
6717bwn_lo_g_init(struct bwn_mac *mac)
6718{
6719
6720	if (!bwn_has_hwpctl(mac))
6721		return;
6722
6723	bwn_lo_get_powervector(mac);
6724	bwn_phy_g_dc_lookup_init(mac, 1);
6725}
6726
6727static void
6728bwn_mac_suspend(struct bwn_mac *mac)
6729{
6730	struct bwn_softc *sc = mac->mac_sc;
6731	int i;
6732	uint32_t tmp;
6733
6734	KASSERT(mac->mac_suspended >= 0,
6735	    ("%s:%d: fail", __func__, __LINE__));
6736
6737	if (mac->mac_suspended == 0) {
6738		bwn_psctl(mac, BWN_PS_AWAKE);
6739		BWN_WRITE_4(mac, BWN_MACCTL,
6740			    BWN_READ_4(mac, BWN_MACCTL)
6741			    & ~BWN_MACCTL_ON);
6742		BWN_READ_4(mac, BWN_MACCTL);
6743		for (i = 35; i; i--) {
6744			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6745			if (tmp & BWN_INTR_MAC_SUSPENDED)
6746				goto out;
6747			DELAY(10);
6748		}
6749		for (i = 40; i; i--) {
6750			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6751			if (tmp & BWN_INTR_MAC_SUSPENDED)
6752				goto out;
6753			DELAY(1000);
6754		}
6755		device_printf(sc->sc_dev, "MAC suspend failed\n");
6756	}
6757out:
6758	mac->mac_suspended++;
6759}
6760
6761static void
6762bwn_mac_enable(struct bwn_mac *mac)
6763{
6764	struct bwn_softc *sc = mac->mac_sc;
6765	uint16_t state;
6766
6767	state = bwn_shm_read_2(mac, BWN_SHARED,
6768	    BWN_SHARED_UCODESTAT);
6769	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6770	    state != BWN_SHARED_UCODESTAT_SLEEP)
6771		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6772
6773	mac->mac_suspended--;
6774	KASSERT(mac->mac_suspended >= 0,
6775	    ("%s:%d: fail", __func__, __LINE__));
6776	if (mac->mac_suspended == 0) {
6777		BWN_WRITE_4(mac, BWN_MACCTL,
6778		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6779		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6780		BWN_READ_4(mac, BWN_MACCTL);
6781		BWN_READ_4(mac, BWN_INTR_REASON);
6782		bwn_psctl(mac, 0);
6783	}
6784}
6785
6786static void
6787bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6788{
6789	int i;
6790	uint16_t ucstat;
6791
6792	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6793	    ("%s:%d: fail", __func__, __LINE__));
6794	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6795	    ("%s:%d: fail", __func__, __LINE__));
6796
6797	/* XXX forcibly awake and hwps-off */
6798
6799	BWN_WRITE_4(mac, BWN_MACCTL,
6800	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6801	    ~BWN_MACCTL_HWPS);
6802	BWN_READ_4(mac, BWN_MACCTL);
6803	if (mac->mac_sd->sd_id.sd_rev >= 5) {
6804		for (i = 0; i < 100; i++) {
6805			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6806			    BWN_SHARED_UCODESTAT);
6807			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6808				break;
6809			DELAY(10);
6810		}
6811	}
6812}
6813
6814static int16_t
6815bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6816{
6817
6818	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6819	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6820}
6821
6822static void
6823bwn_nrssi_threshold(struct bwn_mac *mac)
6824{
6825	struct bwn_phy *phy = &mac->mac_phy;
6826	struct bwn_phy_g *pg = &phy->phy_g;
6827	struct siba_softc *siba = mac->mac_sd->sd_bus;
6828	int32_t a, b;
6829	int16_t tmp16;
6830	uint16_t tmpu16;
6831
6832	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6833
6834	if (phy->gmode && (siba->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
6835		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6836			a = 0x13;
6837			b = 0x12;
6838		} else {
6839			a = 0xe;
6840			b = 0x11;
6841		}
6842
6843		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6844		a += (pg->pg_nrssi[0] << 6);
6845		a += (a < 32) ? 31 : 32;
6846		a = a >> 6;
6847		a = MIN(MAX(a, -31), 31);
6848
6849		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6850		b += (pg->pg_nrssi[0] << 6);
6851		if (b < 32)
6852			b += 31;
6853		else
6854			b += 32;
6855		b = b >> 6;
6856		b = MIN(MAX(b, -31), 31);
6857
6858		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6859		tmpu16 |= ((uint32_t)b & 0x0000003f);
6860		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6861		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6862		return;
6863	}
6864
6865	tmp16 = bwn_nrssi_read(mac, 0x20);
6866	if (tmp16 >= 0x20)
6867		tmp16 -= 0x40;
6868	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6869}
6870
6871static void
6872bwn_nrssi_slope_11g(struct bwn_mac *mac)
6873{
6874#define	SAVE_RF_MAX		3
6875#define	SAVE_PHY_COMM_MAX	4
6876#define	SAVE_PHY3_MAX		8
6877	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6878		{ 0x7a, 0x52, 0x43 };
6879	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6880		{ 0x15, 0x5a, 0x59, 0x58 };
6881	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6882		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6883		0x0801, 0x0060, 0x0014, 0x0478
6884	};
6885	struct bwn_phy *phy = &mac->mac_phy;
6886	struct bwn_phy_g *pg = &phy->phy_g;
6887	int32_t i, tmp32, phy3_idx = 0;
6888	uint16_t delta, tmp;
6889	uint16_t save_rf[SAVE_RF_MAX];
6890	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6891	uint16_t save_phy3[SAVE_PHY3_MAX];
6892	uint16_t ant_div, phy0, chan_ex;
6893	int16_t nrssi0, nrssi1;
6894
6895	KASSERT(phy->type == BWN_PHYTYPE_G,
6896	    ("%s:%d: fail", __func__, __LINE__));
6897
6898	if (phy->rf_rev >= 9)
6899		return;
6900	if (phy->rf_rev == 8)
6901		bwn_nrssi_offset(mac);
6902
6903	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6904	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6905
6906	/*
6907	 * Save RF/PHY registers for later restoration
6908	 */
6909	ant_div = BWN_READ_2(mac, 0x03e2);
6910	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6911	for (i = 0; i < SAVE_RF_MAX; ++i)
6912		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6913	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6914		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6915
6916	phy0 = BWN_READ_2(mac, BWN_PHY0);
6917	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6918	if (phy->rev >= 3) {
6919		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6920			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6921		BWN_PHY_WRITE(mac, 0x002e, 0);
6922		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6923		switch (phy->rev) {
6924		case 4:
6925		case 6:
6926		case 7:
6927			BWN_PHY_SET(mac, 0x0478, 0x0100);
6928			BWN_PHY_SET(mac, 0x0801, 0x0040);
6929			break;
6930		case 3:
6931		case 5:
6932			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6933			break;
6934		}
6935		BWN_PHY_SET(mac, 0x0060, 0x0040);
6936		BWN_PHY_SET(mac, 0x0014, 0x0200);
6937	}
6938	/*
6939	 * Calculate nrssi0
6940	 */
6941	BWN_RF_SET(mac, 0x007a, 0x0070);
6942	bwn_set_all_gains(mac, 0, 8, 0);
6943	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6944	if (phy->rev >= 2) {
6945		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6946		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6947	}
6948	BWN_RF_SET(mac, 0x007a, 0x0080);
6949	DELAY(20);
6950
6951	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6952	if (nrssi0 >= 0x0020)
6953		nrssi0 -= 0x0040;
6954
6955	/*
6956	 * Calculate nrssi1
6957	 */
6958	BWN_RF_MASK(mac, 0x007a, 0x007f);
6959	if (phy->rev >= 2)
6960		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6961
6962	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6963	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6964	BWN_RF_SET(mac, 0x007a, 0x000f);
6965	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6966	if (phy->rev >= 2) {
6967		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6968		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6969	}
6970
6971	bwn_set_all_gains(mac, 3, 0, 1);
6972	if (phy->rf_rev == 8) {
6973		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6974	} else {
6975		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6976		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6977		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6978		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6979	}
6980	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6981	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6982	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6983	DELAY(20);
6984	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6985
6986	/*
6987	 * Install calculated narrow RSSI values
6988	 */
6989	if (nrssi1 >= 0x0020)
6990		nrssi1 -= 0x0040;
6991	if (nrssi0 == nrssi1)
6992		pg->pg_nrssi_slope = 0x00010000;
6993	else
6994		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6995	if (nrssi0 >= -4) {
6996		pg->pg_nrssi[0] = nrssi1;
6997		pg->pg_nrssi[1] = nrssi0;
6998	}
6999
7000	/*
7001	 * Restore saved RF/PHY registers
7002	 */
7003	if (phy->rev >= 3) {
7004		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
7005			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7006			    save_phy3[phy3_idx]);
7007		}
7008	}
7009	if (phy->rev >= 2) {
7010		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
7011		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
7012	}
7013
7014	for (i = 0; i < SAVE_RF_MAX; ++i)
7015		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7016
7017	BWN_WRITE_2(mac, 0x03e2, ant_div);
7018	BWN_WRITE_2(mac, 0x03e6, phy0);
7019	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
7020
7021	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7022		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7023
7024	bwn_spu_workaround(mac, phy->chan);
7025	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
7026	bwn_set_original_gains(mac);
7027	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
7028	if (phy->rev >= 3) {
7029		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
7030			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7031			    save_phy3[phy3_idx]);
7032		}
7033	}
7034
7035	delta = 0x1f - pg->pg_nrssi[0];
7036	for (i = 0; i < 64; i++) {
7037		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
7038		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7039		pg->pg_nrssi_lt[i] = tmp32;
7040	}
7041
7042	bwn_nrssi_threshold(mac);
7043#undef SAVE_RF_MAX
7044#undef SAVE_PHY_COMM_MAX
7045#undef SAVE_PHY3_MAX
7046}
7047
7048static void
7049bwn_nrssi_offset(struct bwn_mac *mac)
7050{
7051#define	SAVE_RF_MAX		2
7052#define	SAVE_PHY_COMM_MAX	10
7053#define	SAVE_PHY6_MAX		8
7054	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7055		{ 0x7a, 0x43 };
7056	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7057		0x0001, 0x0811, 0x0812, 0x0814,
7058		0x0815, 0x005a, 0x0059, 0x0058,
7059		0x000a, 0x0003
7060	};
7061	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7062		0x002e, 0x002f, 0x080f, 0x0810,
7063		0x0801, 0x0060, 0x0014, 0x0478
7064	};
7065	struct bwn_phy *phy = &mac->mac_phy;
7066	int i, phy6_idx = 0;
7067	uint16_t save_rf[SAVE_RF_MAX];
7068	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7069	uint16_t save_phy6[SAVE_PHY6_MAX];
7070	int16_t nrssi;
7071	uint16_t saved = 0xffff;
7072
7073	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7074		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7075	for (i = 0; i < SAVE_RF_MAX; ++i)
7076		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7077
7078	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7079	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7080	BWN_PHY_SET(mac, 0x0811, 0x000c);
7081	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7082	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7083	if (phy->rev >= 6) {
7084		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7085			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7086
7087		BWN_PHY_WRITE(mac, 0x002e, 0);
7088		BWN_PHY_WRITE(mac, 0x002f, 0);
7089		BWN_PHY_WRITE(mac, 0x080f, 0);
7090		BWN_PHY_WRITE(mac, 0x0810, 0);
7091		BWN_PHY_SET(mac, 0x0478, 0x0100);
7092		BWN_PHY_SET(mac, 0x0801, 0x0040);
7093		BWN_PHY_SET(mac, 0x0060, 0x0040);
7094		BWN_PHY_SET(mac, 0x0014, 0x0200);
7095	}
7096	BWN_RF_SET(mac, 0x007a, 0x0070);
7097	BWN_RF_SET(mac, 0x007a, 0x0080);
7098	DELAY(30);
7099
7100	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7101	if (nrssi >= 0x20)
7102		nrssi -= 0x40;
7103	if (nrssi == 31) {
7104		for (i = 7; i >= 4; i--) {
7105			BWN_RF_WRITE(mac, 0x007b, i);
7106			DELAY(20);
7107			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7108			    0x003f);
7109			if (nrssi >= 0x20)
7110				nrssi -= 0x40;
7111			if (nrssi < 31 && saved == 0xffff)
7112				saved = i;
7113		}
7114		if (saved == 0xffff)
7115			saved = 4;
7116	} else {
7117		BWN_RF_MASK(mac, 0x007a, 0x007f);
7118		if (phy->rev != 1) {
7119			BWN_PHY_SET(mac, 0x0814, 0x0001);
7120			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7121		}
7122		BWN_PHY_SET(mac, 0x0811, 0x000c);
7123		BWN_PHY_SET(mac, 0x0812, 0x000c);
7124		BWN_PHY_SET(mac, 0x0811, 0x0030);
7125		BWN_PHY_SET(mac, 0x0812, 0x0030);
7126		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7127		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7128		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7129		if (phy->rev == 0)
7130			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7131		else
7132			BWN_PHY_SET(mac, 0x000a, 0x2000);
7133		if (phy->rev != 1) {
7134			BWN_PHY_SET(mac, 0x0814, 0x0004);
7135			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7136		}
7137		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7138		BWN_RF_SET(mac, 0x007a, 0x000f);
7139		bwn_set_all_gains(mac, 3, 0, 1);
7140		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7141		DELAY(30);
7142		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7143		if (nrssi >= 0x20)
7144			nrssi -= 0x40;
7145		if (nrssi == -32) {
7146			for (i = 0; i < 4; i++) {
7147				BWN_RF_WRITE(mac, 0x007b, i);
7148				DELAY(20);
7149				nrssi = (int16_t)((BWN_PHY_READ(mac,
7150				    0x047f) >> 8) & 0x003f);
7151				if (nrssi >= 0x20)
7152					nrssi -= 0x40;
7153				if (nrssi > -31 && saved == 0xffff)
7154					saved = i;
7155			}
7156			if (saved == 0xffff)
7157				saved = 3;
7158		} else
7159			saved = 0;
7160	}
7161	BWN_RF_WRITE(mac, 0x007b, saved);
7162
7163	/*
7164	 * Restore saved RF/PHY registers
7165	 */
7166	if (phy->rev >= 6) {
7167		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7168			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7169			    save_phy6[phy6_idx]);
7170		}
7171	}
7172	if (phy->rev != 1) {
7173		for (i = 3; i < 5; i++)
7174			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7175			    save_phy_comm[i]);
7176	}
7177	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7178		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7179
7180	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7181		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7182
7183	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7184	BWN_PHY_SET(mac, 0x0429, 0x8000);
7185	bwn_set_original_gains(mac);
7186	if (phy->rev >= 6) {
7187		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7188			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7189			    save_phy6[phy6_idx]);
7190		}
7191	}
7192
7193	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7194	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7195	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7196}
7197
7198static void
7199bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7200    int16_t third)
7201{
7202	struct bwn_phy *phy = &mac->mac_phy;
7203	uint16_t i;
7204	uint16_t start = 0x08, end = 0x18;
7205	uint16_t tmp;
7206	uint16_t table;
7207
7208	if (phy->rev <= 1) {
7209		start = 0x10;
7210		end = 0x20;
7211	}
7212
7213	table = BWN_OFDMTAB_GAINX;
7214	if (phy->rev <= 1)
7215		table = BWN_OFDMTAB_GAINX_R1;
7216	for (i = 0; i < 4; i++)
7217		bwn_ofdmtab_write_2(mac, table, i, first);
7218
7219	for (i = start; i < end; i++)
7220		bwn_ofdmtab_write_2(mac, table, i, second);
7221
7222	if (third != -1) {
7223		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7224		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7225		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7226		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7227	}
7228	bwn_dummy_transmission(mac, 0, 1);
7229}
7230
7231static void
7232bwn_set_original_gains(struct bwn_mac *mac)
7233{
7234	struct bwn_phy *phy = &mac->mac_phy;
7235	uint16_t i, tmp;
7236	uint16_t table;
7237	uint16_t start = 0x0008, end = 0x0018;
7238
7239	if (phy->rev <= 1) {
7240		start = 0x0010;
7241		end = 0x0020;
7242	}
7243
7244	table = BWN_OFDMTAB_GAINX;
7245	if (phy->rev <= 1)
7246		table = BWN_OFDMTAB_GAINX_R1;
7247	for (i = 0; i < 4; i++) {
7248		tmp = (i & 0xfffc);
7249		tmp |= (i & 0x0001) << 1;
7250		tmp |= (i & 0x0002) >> 1;
7251
7252		bwn_ofdmtab_write_2(mac, table, i, tmp);
7253	}
7254
7255	for (i = start; i < end; i++)
7256		bwn_ofdmtab_write_2(mac, table, i, i - start);
7257
7258	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7259	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7260	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7261	bwn_dummy_transmission(mac, 0, 1);
7262}
7263
7264static void
7265bwn_phy_hwpctl_init(struct bwn_mac *mac)
7266{
7267	struct siba_softc *bus = mac->mac_sd->sd_bus;
7268	struct bwn_phy *phy = &mac->mac_phy;
7269	struct bwn_phy_g *pg = &phy->phy_g;
7270	struct bwn_rfatt old_rfatt, rfatt;
7271	struct bwn_bbatt old_bbatt, bbatt;
7272	uint8_t old_txctl = 0;
7273
7274	KASSERT(phy->type == BWN_PHYTYPE_G,
7275	    ("%s:%d: fail", __func__, __LINE__));
7276
7277	if ((bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM) &&
7278	    (bus->siba_board_type == SIBA_BOARD_BU4306))
7279		return;
7280
7281	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7282
7283	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7284
7285	if (!phy->gmode)
7286		return;
7287	bwn_hwpctl_early_init(mac);
7288	if (pg->pg_curtssi == 0) {
7289		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7290			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7291		} else {
7292			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7293			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7294			old_txctl = pg->pg_txctl;
7295
7296			bbatt.att = 11;
7297			if (phy->rf_rev == 8) {
7298				rfatt.att = 15;
7299				rfatt.padmix = 1;
7300			} else {
7301				rfatt.att = 9;
7302				rfatt.padmix = 0;
7303			}
7304			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7305		}
7306		bwn_dummy_transmission(mac, 0, 1);
7307		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7308		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7309			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7310		else
7311			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7312			    &old_rfatt, old_txctl);
7313	}
7314	bwn_hwpctl_init_gphy(mac);
7315
7316	/* clear TSSI */
7317	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7318	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7319	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7320	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7321}
7322
7323static void
7324bwn_hwpctl_early_init(struct bwn_mac *mac)
7325{
7326	struct bwn_phy *phy = &mac->mac_phy;
7327
7328	if (!bwn_has_hwpctl(mac)) {
7329		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7330		return;
7331	}
7332
7333	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7334	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7335	BWN_PHY_SET(mac, 0x047c, 0x0002);
7336	BWN_PHY_SET(mac, 0x047a, 0xf000);
7337	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7338		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7339		BWN_PHY_SET(mac, 0x005d, 0x8000);
7340		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7341		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7342		BWN_PHY_SET(mac, 0x0036, 0x0400);
7343	} else {
7344		BWN_PHY_SET(mac, 0x0036, 0x0200);
7345		BWN_PHY_SET(mac, 0x0036, 0x0400);
7346		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7347		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7348		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7349		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7350		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7351	}
7352}
7353
7354static void
7355bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7356{
7357	struct bwn_phy *phy = &mac->mac_phy;
7358	struct bwn_phy_g *pg = &phy->phy_g;
7359	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7360	int i;
7361	uint16_t nr_written = 0, tmp, value;
7362	uint8_t rf, bb;
7363
7364	if (!bwn_has_hwpctl(mac)) {
7365		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7366		return;
7367	}
7368
7369	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7370	    (pg->pg_idletssi - pg->pg_curtssi));
7371	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7372	    (pg->pg_idletssi - pg->pg_curtssi));
7373
7374	for (i = 0; i < 32; i++)
7375		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7376	for (i = 32; i < 64; i++)
7377		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7378	for (i = 0; i < 64; i += 2) {
7379		value = (uint16_t) pg->pg_tssi2dbm[i];
7380		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7381		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7382	}
7383
7384	for (rf = 0; rf < lo->rfatt.len; rf++) {
7385		for (bb = 0; bb < lo->bbatt.len; bb++) {
7386			if (nr_written >= 0x40)
7387				return;
7388			tmp = lo->bbatt.array[bb].att;
7389			tmp <<= 8;
7390			if (phy->rf_rev == 8)
7391				tmp |= 0x50;
7392			else
7393				tmp |= 0x40;
7394			tmp |= lo->rfatt.array[rf].att;
7395			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7396			nr_written++;
7397		}
7398	}
7399
7400	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7401	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7402
7403	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7404	BWN_PHY_SET(mac, 0x0478, 0x0800);
7405	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7406	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7407
7408	bwn_phy_g_dc_lookup_init(mac, 1);
7409	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7410}
7411
7412static void
7413bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7414{
7415	struct siba_softc *siba = mac->mac_sd->sd_bus;
7416
7417	if (spu != 0)
7418		bwn_spu_workaround(mac, channel);
7419
7420	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7421
7422	if (channel == 14) {
7423		if (siba->siba_sprom.ccode == SIBA_CCODE_JAPAN)
7424			bwn_hf_write(mac,
7425			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7426		else
7427			bwn_hf_write(mac,
7428			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7429		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7430		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7431		return;
7432	}
7433
7434	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7435	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7436}
7437
7438static uint16_t
7439bwn_phy_g_chan2freq(uint8_t channel)
7440{
7441	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7442
7443	KASSERT(channel >= 1 && channel <= 14,
7444	    ("%s:%d: fail", __func__, __LINE__));
7445
7446	return (bwn_phy_g_rf_channels[channel - 1]);
7447}
7448
7449static void
7450bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7451    const struct bwn_rfatt *rfatt, uint8_t txctl)
7452{
7453	struct bwn_phy *phy = &mac->mac_phy;
7454	struct bwn_phy_g *pg = &phy->phy_g;
7455	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7456	uint16_t bb, rf;
7457	uint16_t tx_bias, tx_magn;
7458
7459	bb = bbatt->att;
7460	rf = rfatt->att;
7461	tx_bias = lo->tx_bias;
7462	tx_magn = lo->tx_magn;
7463	if (tx_bias == 0xff)
7464		tx_bias = 0;
7465
7466	pg->pg_txctl = txctl;
7467	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7468	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7469	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7470	bwn_phy_g_set_bbatt(mac, bb);
7471	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7472	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7473		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7474	else {
7475		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7476		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7477	}
7478	if (BWN_HAS_TXMAG(phy))
7479		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7480	else
7481		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7482	bwn_lo_g_adjust(mac);
7483}
7484
7485static void
7486bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7487    uint16_t bbatt)
7488{
7489	struct bwn_phy *phy = &mac->mac_phy;
7490
7491	if (phy->analog == 0) {
7492		BWN_WRITE_2(mac, BWN_PHY0,
7493		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7494		return;
7495	}
7496	if (phy->analog > 1) {
7497		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7498		return;
7499	}
7500	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7501}
7502
7503static uint16_t
7504bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7505{
7506	struct bwn_phy *phy = &mac->mac_phy;
7507	struct bwn_phy_g *pg = &phy->phy_g;
7508	struct siba_sprom *sprom = &(mac->mac_sd->sd_bus->siba_sprom);
7509	int max_lb_gain;
7510	uint16_t extlna;
7511	uint16_t i;
7512
7513	if (phy->gmode == 0)
7514		return (0);
7515
7516	if (BWN_HAS_LOOPBACK(phy)) {
7517		max_lb_gain = pg->pg_max_lb_gain;
7518		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7519		if (max_lb_gain >= 0x46) {
7520			extlna = 0x3000;
7521			max_lb_gain -= 0x46;
7522		} else if (max_lb_gain >= 0x3a) {
7523			extlna = 0x1000;
7524			max_lb_gain -= 0x3a;
7525		} else if (max_lb_gain >= 0x2e) {
7526			extlna = 0x2000;
7527			max_lb_gain -= 0x2e;
7528		} else {
7529			extlna = 0;
7530			max_lb_gain -= 0x10;
7531		}
7532
7533		for (i = 0; i < 16; i++) {
7534			max_lb_gain -= (i * 6);
7535			if (max_lb_gain < 6)
7536				break;
7537		}
7538
7539		if ((phy->rev < 7) || !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7540			if (reg == BWN_PHY_RFOVER) {
7541				return (0x1b3);
7542			} else if (reg == BWN_PHY_RFOVERVAL) {
7543				extlna |= (i << 8);
7544				switch (lpd) {
7545				case BWN_LPD(0, 1, 1):
7546					return (0x0f92);
7547				case BWN_LPD(0, 0, 1):
7548				case BWN_LPD(1, 0, 1):
7549					return (0x0092 | extlna);
7550				case BWN_LPD(1, 0, 0):
7551					return (0x0093 | extlna);
7552				}
7553				KASSERT(0 == 1,
7554				    ("%s:%d: fail", __func__, __LINE__));
7555			}
7556			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7557		} else {
7558			if (reg == BWN_PHY_RFOVER)
7559				return (0x9b3);
7560			if (reg == BWN_PHY_RFOVERVAL) {
7561				if (extlna)
7562					extlna |= 0x8000;
7563				extlna |= (i << 8);
7564				switch (lpd) {
7565				case BWN_LPD(0, 1, 1):
7566					return (0x8f92);
7567				case BWN_LPD(0, 0, 1):
7568					return (0x8092 | extlna);
7569				case BWN_LPD(1, 0, 1):
7570					return (0x2092 | extlna);
7571				case BWN_LPD(1, 0, 0):
7572					return (0x2093 | extlna);
7573				}
7574				KASSERT(0 == 1,
7575				    ("%s:%d: fail", __func__, __LINE__));
7576			}
7577			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7578		}
7579		return (0);
7580	}
7581
7582	if ((phy->rev < 7) ||
7583	    !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7584		if (reg == BWN_PHY_RFOVER) {
7585			return (0x1b3);
7586		} else if (reg == BWN_PHY_RFOVERVAL) {
7587			switch (lpd) {
7588			case BWN_LPD(0, 1, 1):
7589				return (0x0fb2);
7590			case BWN_LPD(0, 0, 1):
7591				return (0x00b2);
7592			case BWN_LPD(1, 0, 1):
7593				return (0x30b2);
7594			case BWN_LPD(1, 0, 0):
7595				return (0x30b3);
7596			}
7597			KASSERT(0 == 1,
7598			    ("%s:%d: fail", __func__, __LINE__));
7599		}
7600		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7601	} else {
7602		if (reg == BWN_PHY_RFOVER) {
7603			return (0x9b3);
7604		} else if (reg == BWN_PHY_RFOVERVAL) {
7605			switch (lpd) {
7606			case BWN_LPD(0, 1, 1):
7607				return (0x8fb2);
7608			case BWN_LPD(0, 0, 1):
7609				return (0x80b2);
7610			case BWN_LPD(1, 0, 1):
7611				return (0x20b2);
7612			case BWN_LPD(1, 0, 0):
7613				return (0x20b3);
7614			}
7615			KASSERT(0 == 1,
7616			    ("%s:%d: fail", __func__, __LINE__));
7617		}
7618		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7619	}
7620	return (0);
7621}
7622
7623static void
7624bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7625{
7626
7627	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7628		return;
7629	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7630	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7631	DELAY(1000);
7632	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7633}
7634
7635static int
7636bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7637{
7638	struct bwn_softc *sc = mac->mac_sc;
7639	struct bwn_fw *fw = &mac->mac_fw;
7640	const uint8_t rev = mac->mac_sd->sd_id.sd_rev;
7641	const char *filename;
7642	uint32_t high;
7643	int error;
7644
7645	/* microcode */
7646	if (rev >= 5 && rev <= 10)
7647		filename = "ucode5";
7648	else if (rev >= 11 && rev <= 12)
7649		filename = "ucode11";
7650	else if (rev == 13)
7651		filename = "ucode13";
7652	else if (rev == 14)
7653		filename = "ucode14";
7654	else if (rev >= 15)
7655		filename = "ucode15";
7656	else {
7657		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7658		bwn_release_firmware(mac);
7659		return (EOPNOTSUPP);
7660	}
7661	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7662	if (error) {
7663		bwn_release_firmware(mac);
7664		return (error);
7665	}
7666
7667	/* PCM */
7668	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7669	if (rev >= 5 && rev <= 10) {
7670		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7671		if (error == ENOENT)
7672			fw->no_pcmfile = 1;
7673		else if (error) {
7674			bwn_release_firmware(mac);
7675			return (error);
7676		}
7677	} else if (rev < 11) {
7678		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7679		return (EOPNOTSUPP);
7680	}
7681
7682	/* initvals */
7683	high = siba_read_4(mac->mac_sd, SIBA_TGSHIGH);
7684	switch (mac->mac_phy.type) {
7685	case BWN_PHYTYPE_A:
7686		if (rev < 5 || rev > 10)
7687			goto fail1;
7688		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7689			filename = "a0g1initvals5";
7690		else
7691			filename = "a0g0initvals5";
7692		break;
7693	case BWN_PHYTYPE_G:
7694		if (rev >= 5 && rev <= 10)
7695			filename = "b0g0initvals5";
7696		else if (rev >= 13)
7697			filename = "b0g0initvals13";
7698		else
7699			goto fail1;
7700		break;
7701	case BWN_PHYTYPE_LP:
7702		if (rev == 13)
7703			filename = "lp0initvals13";
7704		else if (rev == 14)
7705			filename = "lp0initvals14";
7706		else if (rev >= 15)
7707			filename = "lp0initvals15";
7708		else
7709			goto fail1;
7710		break;
7711	case BWN_PHYTYPE_N:
7712		if (rev >= 11 && rev <= 12)
7713			filename = "n0initvals11";
7714		else
7715			goto fail1;
7716		break;
7717	default:
7718		goto fail1;
7719	}
7720	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7721	if (error) {
7722		bwn_release_firmware(mac);
7723		return (error);
7724	}
7725
7726	/* bandswitch initvals */
7727	switch (mac->mac_phy.type) {
7728	case BWN_PHYTYPE_A:
7729		if (rev >= 5 && rev <= 10) {
7730			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7731				filename = "a0g1bsinitvals5";
7732			else
7733				filename = "a0g0bsinitvals5";
7734		} else if (rev >= 11)
7735			filename = NULL;
7736		else
7737			goto fail1;
7738		break;
7739	case BWN_PHYTYPE_G:
7740		if (rev >= 5 && rev <= 10)
7741			filename = "b0g0bsinitvals5";
7742		else if (rev >= 11)
7743			filename = NULL;
7744		else
7745			goto fail1;
7746		break;
7747	case BWN_PHYTYPE_LP:
7748		if (rev == 13)
7749			filename = "lp0bsinitvals13";
7750		else if (rev == 14)
7751			filename = "lp0bsinitvals14";
7752		else if (rev >= 15)
7753			filename = "lp0bsinitvals15";
7754		else
7755			goto fail1;
7756		break;
7757	case BWN_PHYTYPE_N:
7758		if (rev >= 11 && rev <= 12)
7759			filename = "n0bsinitvals11";
7760		else
7761			goto fail1;
7762		break;
7763	default:
7764		goto fail1;
7765	}
7766	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7767	if (error) {
7768		bwn_release_firmware(mac);
7769		return (error);
7770	}
7771	return (0);
7772fail1:
7773	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7774	bwn_release_firmware(mac);
7775	return (EOPNOTSUPP);
7776}
7777
7778static int
7779bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7780    const char *name, struct bwn_fwfile *bfw)
7781{
7782	const struct bwn_fwhdr *hdr;
7783	struct bwn_softc *sc = mac->mac_sc;
7784	const struct firmware *fw;
7785	char namebuf[64];
7786
7787	if (name == NULL) {
7788		bwn_do_release_fw(bfw);
7789		return (0);
7790	}
7791	if (bfw->filename != NULL) {
7792		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7793			return (0);
7794		bwn_do_release_fw(bfw);
7795	}
7796
7797	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s",
7798	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "", name);
7799	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7800	fw = firmware_get(namebuf);
7801	if (fw == NULL) {
7802		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7803		    namebuf);
7804		return (ENOENT);
7805	}
7806	if (fw->datasize < sizeof(struct bwn_fwhdr))
7807		goto fail;
7808	hdr = (const struct bwn_fwhdr *)(fw->data);
7809	switch (hdr->type) {
7810	case BWN_FWTYPE_UCODE:
7811	case BWN_FWTYPE_PCM:
7812		if (be32toh(hdr->size) !=
7813		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7814			goto fail;
7815		/* FALLTHROUGH */
7816	case BWN_FWTYPE_IV:
7817		if (hdr->ver != 1)
7818			goto fail;
7819		break;
7820	default:
7821		goto fail;
7822	}
7823	bfw->filename = name;
7824	bfw->fw = fw;
7825	bfw->type = type;
7826	return (0);
7827fail:
7828	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7829	if (fw != NULL)
7830		firmware_put(fw, FIRMWARE_UNLOAD);
7831	return (EPROTO);
7832}
7833
7834static void
7835bwn_release_firmware(struct bwn_mac *mac)
7836{
7837
7838	bwn_do_release_fw(&mac->mac_fw.ucode);
7839	bwn_do_release_fw(&mac->mac_fw.pcm);
7840	bwn_do_release_fw(&mac->mac_fw.initvals);
7841	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7842}
7843
7844static void
7845bwn_do_release_fw(struct bwn_fwfile *bfw)
7846{
7847
7848	if (bfw->fw != NULL)
7849		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7850	bfw->fw = NULL;
7851	bfw->filename = NULL;
7852}
7853
7854static int
7855bwn_fw_loaducode(struct bwn_mac *mac)
7856{
7857#define	GETFWOFFSET(fwp, offset)	\
7858	((const uint32_t *)((const char *)fwp.fw->data + offset))
7859#define	GETFWSIZE(fwp, offset)	\
7860	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7861	struct bwn_softc *sc = mac->mac_sc;
7862	const uint32_t *data;
7863	unsigned int i;
7864	uint32_t ctl;
7865	uint16_t date, fwcaps, time;
7866	int error = 0;
7867
7868	ctl = BWN_READ_4(mac, BWN_MACCTL);
7869	ctl |= BWN_MACCTL_MCODE_JMP0;
7870	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7871	    __LINE__));
7872	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7873	for (i = 0; i < 64; i++)
7874		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7875	for (i = 0; i < 4096; i += 2)
7876		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7877
7878	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7879	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7880	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7881	     i++) {
7882		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7883		DELAY(10);
7884	}
7885
7886	if (mac->mac_fw.pcm.fw) {
7887		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7888		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7889		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7890		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7891		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7892		    sizeof(struct bwn_fwhdr)); i++) {
7893			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7894			DELAY(10);
7895		}
7896	}
7897
7898	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7899	BWN_WRITE_4(mac, BWN_MACCTL,
7900	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7901	    BWN_MACCTL_MCODE_RUN);
7902
7903	for (i = 0; i < 21; i++) {
7904		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7905			break;
7906		if (i >= 20) {
7907			device_printf(sc->sc_dev, "ucode timeout\n");
7908			error = ENXIO;
7909			goto error;
7910		}
7911		DELAY(50000);
7912	}
7913	BWN_READ_4(mac, BWN_INTR_REASON);
7914
7915	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7916	if (mac->mac_fw.rev <= 0x128) {
7917		device_printf(sc->sc_dev, "the firmware is too old\n");
7918		error = EOPNOTSUPP;
7919		goto error;
7920	}
7921	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7922	    BWN_SHARED_UCODE_PATCH);
7923	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7924	mac->mac_fw.opensource = (date == 0xffff);
7925	if (bwn_wme != 0)
7926		mac->mac_flags |= BWN_MAC_FLAG_WME;
7927	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7928
7929	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7930	if (mac->mac_fw.opensource == 0) {
7931		device_printf(sc->sc_dev,
7932		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7933		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7934		if (mac->mac_fw.no_pcmfile)
7935			device_printf(sc->sc_dev,
7936			    "no HW crypto acceleration due to pcm5\n");
7937	} else {
7938		mac->mac_fw.patch = time;
7939		fwcaps = bwn_fwcaps_read(mac);
7940		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7941			device_printf(sc->sc_dev,
7942			    "disabling HW crypto acceleration\n");
7943			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7944		}
7945		if (!(fwcaps & BWN_FWCAPS_WME)) {
7946			device_printf(sc->sc_dev, "disabling WME support\n");
7947			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7948		}
7949	}
7950
7951	if (BWN_ISOLDFMT(mac))
7952		device_printf(sc->sc_dev, "using old firmware image\n");
7953
7954	return (0);
7955
7956error:
7957	BWN_WRITE_4(mac, BWN_MACCTL,
7958	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7959	    BWN_MACCTL_MCODE_JMP0);
7960
7961	return (error);
7962#undef GETFWSIZE
7963#undef GETFWOFFSET
7964}
7965
7966/* OpenFirmware only */
7967static uint16_t
7968bwn_fwcaps_read(struct bwn_mac *mac)
7969{
7970
7971	KASSERT(mac->mac_fw.opensource == 1,
7972	    ("%s:%d: fail", __func__, __LINE__));
7973	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7974}
7975
7976static int
7977bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7978    size_t count, size_t array_size)
7979{
7980#define	GET_NEXTIV16(iv)						\
7981	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7982	    sizeof(uint16_t) + sizeof(uint16_t)))
7983#define	GET_NEXTIV32(iv)						\
7984	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7985	    sizeof(uint16_t) + sizeof(uint32_t)))
7986	struct bwn_softc *sc = mac->mac_sc;
7987	const struct bwn_fwinitvals *iv;
7988	uint16_t offset;
7989	size_t i;
7990	uint8_t bit32;
7991
7992	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7993	    ("%s:%d: fail", __func__, __LINE__));
7994	iv = ivals;
7995	for (i = 0; i < count; i++) {
7996		if (array_size < sizeof(iv->offset_size))
7997			goto fail;
7998		array_size -= sizeof(iv->offset_size);
7999		offset = be16toh(iv->offset_size);
8000		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
8001		offset &= BWN_FWINITVALS_OFFSET_MASK;
8002		if (offset >= 0x1000)
8003			goto fail;
8004		if (bit32) {
8005			if (array_size < sizeof(iv->data.d32))
8006				goto fail;
8007			array_size -= sizeof(iv->data.d32);
8008			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
8009			iv = GET_NEXTIV32(iv);
8010		} else {
8011
8012			if (array_size < sizeof(iv->data.d16))
8013				goto fail;
8014			array_size -= sizeof(iv->data.d16);
8015			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
8016
8017			iv = GET_NEXTIV16(iv);
8018		}
8019	}
8020	if (array_size != 0)
8021		goto fail;
8022	return (0);
8023fail:
8024	device_printf(sc->sc_dev, "initvals: invalid format\n");
8025	return (EPROTO);
8026#undef GET_NEXTIV16
8027#undef GET_NEXTIV32
8028}
8029
8030static int
8031bwn_switch_channel(struct bwn_mac *mac, int chan)
8032{
8033	struct bwn_phy *phy = &(mac->mac_phy);
8034	struct bwn_softc *sc = mac->mac_sc;
8035	struct ifnet *ifp = sc->sc_ifp;
8036	struct ieee80211com *ic = ifp->if_l2com;
8037	uint16_t channelcookie, savedcookie;
8038	int error;
8039
8040	if (chan == 0xffff)
8041		chan = phy->get_default_chan(mac);
8042
8043	channelcookie = chan;
8044	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8045		channelcookie |= 0x100;
8046	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8047	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8048	error = phy->switch_channel(mac, chan);
8049	if (error)
8050		goto fail;
8051
8052	mac->mac_phy.chan = chan;
8053	DELAY(8000);
8054	return (0);
8055fail:
8056	device_printf(sc->sc_dev, "failed to switch channel\n");
8057	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8058	return (error);
8059}
8060
8061static uint16_t
8062bwn_ant2phy(int antenna)
8063{
8064
8065	switch (antenna) {
8066	case BWN_ANT0:
8067		return (BWN_TX_PHY_ANT0);
8068	case BWN_ANT1:
8069		return (BWN_TX_PHY_ANT1);
8070	case BWN_ANT2:
8071		return (BWN_TX_PHY_ANT2);
8072	case BWN_ANT3:
8073		return (BWN_TX_PHY_ANT3);
8074	case BWN_ANTAUTO:
8075		return (BWN_TX_PHY_ANT01AUTO);
8076	}
8077	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8078	return (0);
8079}
8080
8081static void
8082bwn_wme_load(struct bwn_mac *mac)
8083{
8084	struct bwn_softc *sc = mac->mac_sc;
8085	int i;
8086
8087	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8088	    ("%s:%d: fail", __func__, __LINE__));
8089
8090	bwn_mac_suspend(mac);
8091	for (i = 0; i < N(sc->sc_wmeParams); i++)
8092		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8093		    bwn_wme_shm_offsets[i]);
8094	bwn_mac_enable(mac);
8095}
8096
8097static void
8098bwn_wme_loadparams(struct bwn_mac *mac,
8099    const struct wmeParams *p, uint16_t shm_offset)
8100{
8101#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8102	struct bwn_softc *sc = mac->mac_sc;
8103	uint16_t params[BWN_NR_WMEPARAMS];
8104	int slot, tmp;
8105	unsigned int i;
8106
8107	slot = BWN_READ_2(mac, BWN_RNG) &
8108	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8109
8110	memset(&params, 0, sizeof(params));
8111
8112	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8113	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8114	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8115
8116	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8117	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8118	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8119	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8120	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8121	params[BWN_WMEPARAM_BSLOTS] = slot;
8122	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8123
8124	for (i = 0; i < N(params); i++) {
8125		if (i == BWN_WMEPARAM_STATUS) {
8126			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8127			    shm_offset + (i * 2));
8128			tmp |= 0x100;
8129			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8130			    tmp);
8131		} else {
8132			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8133			    params[i]);
8134		}
8135	}
8136}
8137
8138static void
8139bwn_mac_write_bssid(struct bwn_mac *mac)
8140{
8141	struct bwn_softc *sc = mac->mac_sc;
8142	uint32_t tmp;
8143	int i;
8144	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8145
8146	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8147	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8148	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8149	    IEEE80211_ADDR_LEN);
8150
8151	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8152		tmp = (uint32_t) (mac_bssid[i + 0]);
8153		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8154		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8155		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8156		bwn_ram_write(mac, 0x20 + i, tmp);
8157	}
8158}
8159
8160static void
8161bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8162    const uint8_t *macaddr)
8163{
8164	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8165	uint16_t data;
8166
8167	if (!mac)
8168		macaddr = zero;
8169
8170	offset |= 0x0020;
8171	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8172
8173	data = macaddr[0];
8174	data |= macaddr[1] << 8;
8175	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8176	data = macaddr[2];
8177	data |= macaddr[3] << 8;
8178	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8179	data = macaddr[4];
8180	data |= macaddr[5] << 8;
8181	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8182}
8183
8184static void
8185bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8186    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8187{
8188	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8189	uint8_t per_sta_keys_start = 8;
8190
8191	if (BWN_SEC_NEWAPI(mac))
8192		per_sta_keys_start = 4;
8193
8194	KASSERT(index < mac->mac_max_nr_keys,
8195	    ("%s:%d: fail", __func__, __LINE__));
8196	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8197	    ("%s:%d: fail", __func__, __LINE__));
8198
8199	if (index >= per_sta_keys_start)
8200		bwn_key_macwrite(mac, index, NULL);
8201	if (key)
8202		memcpy(buf, key, key_len);
8203	bwn_key_write(mac, index, algorithm, buf);
8204	if (index >= per_sta_keys_start)
8205		bwn_key_macwrite(mac, index, mac_addr);
8206
8207	mac->mac_key[index].algorithm = algorithm;
8208}
8209
8210static void
8211bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8212{
8213	uint32_t addrtmp[2] = { 0, 0 };
8214	uint8_t start = 8;
8215
8216	if (BWN_SEC_NEWAPI(mac))
8217		start = 4;
8218
8219	KASSERT(index >= start,
8220	    ("%s:%d: fail", __func__, __LINE__));
8221	index -= start;
8222
8223	if (addr) {
8224		addrtmp[0] = addr[0];
8225		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8226		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8227		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8228		addrtmp[1] = addr[4];
8229		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8230	}
8231
8232	if (mac->mac_sd->sd_id.sd_rev >= 5) {
8233		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8234		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8235	} else {
8236		if (index >= 8) {
8237			bwn_shm_write_4(mac, BWN_SHARED,
8238			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8239			bwn_shm_write_2(mac, BWN_SHARED,
8240			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8241		}
8242	}
8243}
8244
8245static void
8246bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8247    const uint8_t *key)
8248{
8249	unsigned int i;
8250	uint32_t offset;
8251	uint16_t kidx, value;
8252
8253	kidx = BWN_SEC_KEY2FW(mac, index);
8254	bwn_shm_write_2(mac, BWN_SHARED,
8255	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8256
8257	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8258	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8259		value = key[i];
8260		value |= (uint16_t)(key[i + 1]) << 8;
8261		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8262	}
8263}
8264
8265static void
8266bwn_phy_exit(struct bwn_mac *mac)
8267{
8268
8269	mac->mac_phy.rf_onoff(mac, 0);
8270	if (mac->mac_phy.exit != NULL)
8271		mac->mac_phy.exit(mac);
8272}
8273
8274static void
8275bwn_dma_free(struct bwn_mac *mac)
8276{
8277	struct bwn_dma *dma;
8278
8279	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8280		return;
8281	dma = &mac->mac_method.dma;
8282
8283	bwn_dma_ringfree(&dma->rx);
8284	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8285	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8286	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8287	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8288	bwn_dma_ringfree(&dma->mcast);
8289}
8290
8291static void
8292bwn_core_stop(struct bwn_mac *mac)
8293{
8294	struct bwn_softc *sc = mac->mac_sc;
8295
8296	BWN_ASSERT_LOCKED(sc);
8297
8298	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8299		return;
8300
8301	callout_stop(&sc->sc_rfswitch_ch);
8302	callout_stop(&sc->sc_task_ch);
8303	callout_stop(&sc->sc_watchdog_ch);
8304	sc->sc_watchdog_timer = 0;
8305	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8306	BWN_READ_4(mac, BWN_INTR_MASK);
8307	bwn_mac_suspend(mac);
8308
8309	mac->mac_status = BWN_MAC_STATUS_INITED;
8310}
8311
8312static int
8313bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8314{
8315	struct bwn_mac *up_dev = NULL;
8316	struct bwn_mac *down_dev;
8317	struct bwn_mac *mac;
8318	int err, status;
8319	uint8_t gmode;
8320
8321	BWN_ASSERT_LOCKED(sc);
8322
8323	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8324		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8325		    mac->mac_phy.supports_2ghz) {
8326			up_dev = mac;
8327			gmode = 1;
8328		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8329		    mac->mac_phy.supports_5ghz) {
8330			up_dev = mac;
8331			gmode = 0;
8332		} else {
8333			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8334			return (EINVAL);
8335		}
8336		if (up_dev != NULL)
8337			break;
8338	}
8339	if (up_dev == NULL) {
8340		device_printf(sc->sc_dev, "Could not find a device\n");
8341		return (ENODEV);
8342	}
8343	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8344		return (0);
8345
8346	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8347	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8348
8349	down_dev = sc->sc_curmac;;
8350	status = down_dev->mac_status;
8351	if (status >= BWN_MAC_STATUS_STARTED)
8352		bwn_core_stop(down_dev);
8353	if (status >= BWN_MAC_STATUS_INITED)
8354		bwn_core_exit(down_dev);
8355
8356	if (down_dev != up_dev)
8357		bwn_phy_reset(down_dev);
8358
8359	up_dev->mac_phy.gmode = gmode;
8360	if (status >= BWN_MAC_STATUS_INITED) {
8361		err = bwn_core_init(up_dev);
8362		if (err) {
8363			device_printf(sc->sc_dev,
8364			    "fatal: failed to initialize for %s-GHz\n",
8365			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8366			goto fail;
8367		}
8368	}
8369	if (status >= BWN_MAC_STATUS_STARTED)
8370		bwn_core_start(up_dev);
8371	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8372	sc->sc_curmac = up_dev;
8373
8374	return (0);
8375fail:
8376	sc->sc_curmac = NULL;
8377	return (err);
8378}
8379
8380static void
8381bwn_rf_turnon(struct bwn_mac *mac)
8382{
8383
8384	bwn_mac_suspend(mac);
8385	mac->mac_phy.rf_onoff(mac, 1);
8386	mac->mac_phy.rf_on = 1;
8387	bwn_mac_enable(mac);
8388}
8389
8390static void
8391bwn_rf_turnoff(struct bwn_mac *mac)
8392{
8393
8394	bwn_mac_suspend(mac);
8395	mac->mac_phy.rf_onoff(mac, 0);
8396	mac->mac_phy.rf_on = 0;
8397	bwn_mac_enable(mac);
8398}
8399
8400static void
8401bwn_phy_reset(struct bwn_mac *mac)
8402{
8403	struct siba_dev_softc *sd = mac->mac_sd;
8404
8405	siba_write_4(sd, SIBA_TGSLOW,
8406	    ((siba_read_4(sd, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8407	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8408	DELAY(1000);
8409	siba_write_4(sd, SIBA_TGSLOW,
8410	    (siba_read_4(sd, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8411	    BWN_TGSLOW_PHYRESET);
8412	DELAY(1000);
8413}
8414
8415static int
8416bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8417{
8418	struct bwn_vap *bvp = BWN_VAP(vap);
8419	struct ieee80211com *ic= vap->iv_ic;
8420	struct ifnet *ifp = ic->ic_ifp;
8421	enum ieee80211_state ostate = vap->iv_state;
8422	struct bwn_softc *sc = ifp->if_softc;
8423	struct bwn_mac *mac = sc->sc_curmac;
8424	int error;
8425
8426	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8427	    ieee80211_state_name[vap->iv_state],
8428	    ieee80211_state_name[nstate]);
8429
8430	error = bvp->bv_newstate(vap, nstate, arg);
8431	if (error != 0)
8432		return (error);
8433
8434	BWN_LOCK(sc);
8435
8436	bwn_led_newstate(mac, nstate);
8437
8438	/*
8439	 * Clear the BSSID when we stop a STA
8440	 */
8441	if (vap->iv_opmode == IEEE80211_M_STA) {
8442		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8443			/*
8444			 * Clear out the BSSID.  If we reassociate to
8445			 * the same AP, this will reinialize things
8446			 * correctly...
8447			 */
8448			if (ic->ic_opmode == IEEE80211_M_STA &&
8449			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8450				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8451				bwn_set_macaddr(mac);
8452			}
8453		}
8454	}
8455
8456	if (vap->iv_opmode == IEEE80211_M_MONITOR) {
8457		/* XXX nothing to do? */
8458	} else if (nstate == IEEE80211_S_RUN) {
8459		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8460		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8461		bwn_set_opmode(mac);
8462		bwn_set_pretbtt(mac);
8463		bwn_spu_setdelay(mac, 0);
8464		bwn_set_macaddr(mac);
8465	}
8466
8467	BWN_UNLOCK(sc);
8468
8469	return (error);
8470}
8471
8472static void
8473bwn_set_pretbtt(struct bwn_mac *mac)
8474{
8475	struct bwn_softc *sc = mac->mac_sc;
8476	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8477	uint16_t pretbtt;
8478
8479	if (ic->ic_opmode == IEEE80211_M_IBSS)
8480		pretbtt = 2;
8481	else
8482		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8483	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8484	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8485}
8486
8487static int
8488bwn_intr(void *arg)
8489{
8490	struct bwn_mac *mac = arg;
8491	struct bwn_softc *sc = mac->mac_sc;
8492	struct siba_softc *siba = mac->mac_sd->sd_bus;
8493	uint32_t reason;
8494
8495	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid)
8496		return (FILTER_STRAY);
8497
8498	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8499	if (reason == 0xffffffff)	/* shared IRQ */
8500		return (FILTER_STRAY);
8501	reason &= mac->mac_intr_mask;
8502	if (reason == 0)
8503		return (FILTER_HANDLED);
8504
8505	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8506	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8507	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8508	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8509	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8510	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8511	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8512	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8513	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8514	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8515	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8516
8517	/* Disable interrupts. */
8518	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8519
8520	mac->mac_reason_intr = reason;
8521
8522	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8523	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8524
8525	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8526	return (FILTER_HANDLED);
8527}
8528
8529static void
8530bwn_intrtask(void *arg, int npending)
8531{
8532	struct bwn_mac *mac = arg;
8533	struct bwn_softc *sc = mac->mac_sc;
8534	struct ifnet *ifp = sc->sc_ifp;
8535	struct siba_softc *siba = mac->mac_sd->sd_bus;
8536	uint32_t merged = 0;
8537	int i, tx = 0, rx = 0;
8538
8539	BWN_LOCK(sc);
8540	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid) {
8541		BWN_UNLOCK(sc);
8542		return;
8543	}
8544
8545	for (i = 0; i < N(mac->mac_reason); i++)
8546		merged |= mac->mac_reason[i];
8547
8548	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8549		device_printf(sc->sc_dev, "MAC trans error\n");
8550
8551	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8552		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8553		mac->mac_phy.txerrors--;
8554		if (mac->mac_phy.txerrors == 0) {
8555			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8556			bwn_restart(mac, "PHY TX errors");
8557		}
8558	}
8559
8560	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8561		if (merged & BWN_DMAINTR_FATALMASK) {
8562			device_printf(sc->sc_dev,
8563			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8564			    mac->mac_reason[0], mac->mac_reason[1],
8565			    mac->mac_reason[2], mac->mac_reason[3],
8566			    mac->mac_reason[4], mac->mac_reason[5]);
8567			bwn_restart(mac, "DMA error");
8568			BWN_UNLOCK(sc);
8569			return;
8570		}
8571		if (merged & BWN_DMAINTR_NONFATALMASK) {
8572			device_printf(sc->sc_dev,
8573			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8574			    mac->mac_reason[0], mac->mac_reason[1],
8575			    mac->mac_reason[2], mac->mac_reason[3],
8576			    mac->mac_reason[4], mac->mac_reason[5]);
8577		}
8578	}
8579
8580	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8581		bwn_intr_ucode_debug(mac);
8582	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8583		bwn_intr_tbtt_indication(mac);
8584	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8585		bwn_intr_atim_end(mac);
8586	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8587		bwn_intr_beacon(mac);
8588	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8589		bwn_intr_pmq(mac);
8590	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8591		bwn_intr_noise(mac);
8592
8593	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8594		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8595			bwn_dma_rx(mac->mac_method.dma.rx);
8596			rx = 1;
8597		}
8598	} else
8599		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8600
8601	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8602	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8603	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8604	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8605	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8606
8607	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8608		bwn_intr_txeof(mac);
8609		tx = 1;
8610	}
8611
8612	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8613
8614	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8615		int evt = BWN_LED_EVENT_NONE;
8616
8617		if (tx && rx) {
8618			if (sc->sc_rx_rate > sc->sc_tx_rate)
8619				evt = BWN_LED_EVENT_RX;
8620			else
8621				evt = BWN_LED_EVENT_TX;
8622		} else if (tx) {
8623			evt = BWN_LED_EVENT_TX;
8624		} else if (rx) {
8625			evt = BWN_LED_EVENT_RX;
8626		} else if (rx == 0) {
8627			evt = BWN_LED_EVENT_POLL;
8628		}
8629
8630		if (evt != BWN_LED_EVENT_NONE)
8631			bwn_led_event(mac, evt);
8632       }
8633
8634	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8635		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8636			bwn_start_locked(ifp);
8637	}
8638
8639	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8640	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8641
8642	BWN_UNLOCK(sc);
8643}
8644
8645static void
8646bwn_restart(struct bwn_mac *mac, const char *msg)
8647{
8648	struct bwn_softc *sc = mac->mac_sc;
8649	struct ifnet *ifp = sc->sc_ifp;
8650	struct ieee80211com *ic = ifp->if_l2com;
8651
8652	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8653		return;
8654
8655	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8656	ieee80211_runtask(ic, &mac->mac_hwreset);
8657}
8658
8659static void
8660bwn_intr_ucode_debug(struct bwn_mac *mac)
8661{
8662	struct bwn_softc *sc = mac->mac_sc;
8663	uint16_t reason;
8664
8665	if (mac->mac_fw.opensource == 0)
8666		return;
8667
8668	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8669	switch (reason) {
8670	case BWN_DEBUGINTR_PANIC:
8671		bwn_handle_fwpanic(mac);
8672		break;
8673	case BWN_DEBUGINTR_DUMP_SHM:
8674		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8675		break;
8676	case BWN_DEBUGINTR_DUMP_REGS:
8677		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8678		break;
8679	case BWN_DEBUGINTR_MARKER:
8680		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8681		break;
8682	default:
8683		device_printf(sc->sc_dev,
8684		    "ucode debug unknown reason: %#x\n", reason);
8685	}
8686
8687	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8688	    BWN_DEBUGINTR_ACK);
8689}
8690
8691static void
8692bwn_intr_tbtt_indication(struct bwn_mac *mac)
8693{
8694	struct bwn_softc *sc = mac->mac_sc;
8695	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8696
8697	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8698		bwn_psctl(mac, 0);
8699	if (ic->ic_opmode == IEEE80211_M_IBSS)
8700		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8701}
8702
8703static void
8704bwn_intr_atim_end(struct bwn_mac *mac)
8705{
8706
8707	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8708		BWN_WRITE_4(mac, BWN_MACCMD,
8709		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8710		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8711	}
8712}
8713
8714static void
8715bwn_intr_beacon(struct bwn_mac *mac)
8716{
8717	struct bwn_softc *sc = mac->mac_sc;
8718	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8719	uint32_t cmd, beacon0, beacon1;
8720
8721	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8722	    ic->ic_opmode == IEEE80211_M_MBSS)
8723		return;
8724
8725	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8726
8727	cmd = BWN_READ_4(mac, BWN_MACCMD);
8728	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8729	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8730
8731	if (beacon0 && beacon1) {
8732		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8733		mac->mac_intr_mask |= BWN_INTR_BEACON;
8734		return;
8735	}
8736
8737	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8738		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8739		bwn_load_beacon0(mac);
8740		bwn_load_beacon1(mac);
8741		cmd = BWN_READ_4(mac, BWN_MACCMD);
8742		cmd |= BWN_MACCMD_BEACON0_VALID;
8743		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8744	} else {
8745		if (!beacon0) {
8746			bwn_load_beacon0(mac);
8747			cmd = BWN_READ_4(mac, BWN_MACCMD);
8748			cmd |= BWN_MACCMD_BEACON0_VALID;
8749			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8750		} else if (!beacon1) {
8751			bwn_load_beacon1(mac);
8752			cmd = BWN_READ_4(mac, BWN_MACCMD);
8753			cmd |= BWN_MACCMD_BEACON1_VALID;
8754			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8755		}
8756	}
8757}
8758
8759static void
8760bwn_intr_pmq(struct bwn_mac *mac)
8761{
8762	uint32_t tmp;
8763
8764	while (1) {
8765		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8766		if (!(tmp & 0x00000008))
8767			break;
8768	}
8769	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8770}
8771
8772static void
8773bwn_intr_noise(struct bwn_mac *mac)
8774{
8775	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8776	uint16_t tmp;
8777	uint8_t noise[4];
8778	uint8_t i, j;
8779	int32_t average;
8780
8781	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8782		return;
8783
8784	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8785	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8786	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8787	    noise[3] == 0x7f)
8788		goto new;
8789
8790	KASSERT(mac->mac_noise.noi_nsamples < 8,
8791	    ("%s:%d: fail", __func__, __LINE__));
8792	i = mac->mac_noise.noi_nsamples;
8793	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8794	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8795	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8796	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8797	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8798	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8799	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8800	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8801	mac->mac_noise.noi_nsamples++;
8802	if (mac->mac_noise.noi_nsamples == 8) {
8803		average = 0;
8804		for (i = 0; i < 8; i++) {
8805			for (j = 0; j < 4; j++)
8806				average += mac->mac_noise.noi_samples[i][j];
8807		}
8808		average = (((average / 32) * 125) + 64) / 128;
8809		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8810		if (tmp >= 8)
8811			average += 2;
8812		else
8813			average -= 25;
8814		average -= (tmp == 8) ? 72 : 48;
8815
8816		mac->mac_stats.link_noise = average;
8817		mac->mac_noise.noi_running = 0;
8818		return;
8819	}
8820new:
8821	bwn_noise_gensample(mac);
8822}
8823
8824static int
8825bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8826{
8827	struct bwn_mac *mac = prq->prq_mac;
8828	struct bwn_softc *sc = mac->mac_sc;
8829	unsigned int i;
8830
8831	BWN_ASSERT_LOCKED(sc);
8832
8833	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8834		return (0);
8835
8836	for (i = 0; i < 5000; i++) {
8837		if (bwn_pio_rxeof(prq) == 0)
8838			break;
8839	}
8840	if (i >= 5000)
8841		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8842	return ((i > 0) ? 1 : 0);
8843}
8844
8845static void
8846bwn_dma_rx(struct bwn_dma_ring *dr)
8847{
8848	int slot, curslot;
8849
8850	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8851	curslot = dr->get_curslot(dr);
8852	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8853	    ("%s:%d: fail", __func__, __LINE__));
8854
8855	slot = dr->dr_curslot;
8856	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8857		bwn_dma_rxeof(dr, &slot);
8858
8859	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8860	    BUS_DMASYNC_PREWRITE);
8861
8862	dr->set_curslot(dr, slot);
8863	dr->dr_curslot = slot;
8864}
8865
8866static void
8867bwn_intr_txeof(struct bwn_mac *mac)
8868{
8869	struct bwn_txstatus stat;
8870	uint32_t stat0, stat1;
8871	uint16_t tmp;
8872
8873	BWN_ASSERT_LOCKED(mac->mac_sc);
8874
8875	while (1) {
8876		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8877		if (!(stat0 & 0x00000001))
8878			break;
8879		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8880
8881		stat.cookie = (stat0 >> 16);
8882		stat.seq = (stat1 & 0x0000ffff);
8883		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8884		tmp = (stat0 & 0x0000ffff);
8885		stat.framecnt = ((tmp & 0xf000) >> 12);
8886		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8887		stat.sreason = ((tmp & 0x001c) >> 2);
8888		stat.pm = (tmp & 0x0080) ? 1 : 0;
8889		stat.im = (tmp & 0x0040) ? 1 : 0;
8890		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8891		stat.ack = (tmp & 0x0002) ? 1 : 0;
8892
8893		bwn_handle_txeof(mac, &stat);
8894	}
8895}
8896
8897static void
8898bwn_hwreset(void *arg, int npending)
8899{
8900	struct bwn_mac *mac = arg;
8901	struct bwn_softc *sc = mac->mac_sc;
8902	int error = 0;
8903	int prev_status;
8904
8905	BWN_LOCK(sc);
8906
8907	prev_status = mac->mac_status;
8908	if (prev_status >= BWN_MAC_STATUS_STARTED)
8909		bwn_core_stop(mac);
8910	if (prev_status >= BWN_MAC_STATUS_INITED)
8911		bwn_core_exit(mac);
8912
8913	if (prev_status >= BWN_MAC_STATUS_INITED) {
8914		error = bwn_core_init(mac);
8915		if (error)
8916			goto out;
8917	}
8918	if (prev_status >= BWN_MAC_STATUS_STARTED)
8919		bwn_core_start(mac);
8920out:
8921	if (error) {
8922		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8923		sc->sc_curmac = NULL;
8924	}
8925	BWN_UNLOCK(sc);
8926}
8927
8928static void
8929bwn_handle_fwpanic(struct bwn_mac *mac)
8930{
8931	struct bwn_softc *sc = mac->mac_sc;
8932	uint16_t reason;
8933
8934	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8935	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8936
8937	if (reason == BWN_FWPANIC_RESTART)
8938		bwn_restart(mac, "ucode panic");
8939}
8940
8941static void
8942bwn_load_beacon0(struct bwn_mac *mac)
8943{
8944
8945	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8946}
8947
8948static void
8949bwn_load_beacon1(struct bwn_mac *mac)
8950{
8951
8952	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8953}
8954
8955static uint32_t
8956bwn_jssi_read(struct bwn_mac *mac)
8957{
8958	uint32_t val = 0;
8959
8960	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8961	val <<= 16;
8962	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8963
8964	return (val);
8965}
8966
8967static void
8968bwn_noise_gensample(struct bwn_mac *mac)
8969{
8970	uint32_t jssi = 0x7f7f7f7f;
8971
8972	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8973	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8974	BWN_WRITE_4(mac, BWN_MACCMD,
8975	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8976}
8977
8978static int
8979bwn_dma_freeslot(struct bwn_dma_ring *dr)
8980{
8981	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8982
8983	return (dr->dr_numslots - dr->dr_usedslot);
8984}
8985
8986static int
8987bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8988{
8989	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8990
8991	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8992	    ("%s:%d: fail", __func__, __LINE__));
8993	if (slot == dr->dr_numslots - 1)
8994		return (0);
8995	return (slot + 1);
8996}
8997
8998static void
8999bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
9000{
9001	struct bwn_mac *mac = dr->dr_mac;
9002	struct bwn_softc *sc = mac->mac_sc;
9003	struct bwn_dma *dma = &mac->mac_method.dma;
9004	struct bwn_dmadesc_generic *desc;
9005	struct bwn_dmadesc_meta *meta;
9006	struct bwn_rxhdr4 *rxhdr;
9007	struct ifnet *ifp = sc->sc_ifp;
9008	struct mbuf *m;
9009	uint32_t macstat;
9010	int32_t tmp;
9011	int cnt = 0;
9012	uint16_t len;
9013
9014	dr->getdesc(dr, *slot, &desc, &meta);
9015
9016	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
9017	m = meta->mt_m;
9018
9019	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
9020		ifp->if_ierrors++;
9021		return;
9022	}
9023
9024	rxhdr = mtod(m, struct bwn_rxhdr4 *);
9025	len = le16toh(rxhdr->frame_len);
9026	if (len <= 0) {
9027		ifp->if_ierrors++;
9028		return;
9029	}
9030	if (bwn_dma_check_redzone(dr, m)) {
9031		device_printf(sc->sc_dev, "redzone error.\n");
9032		bwn_dma_set_redzone(dr, m);
9033		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9034		    BUS_DMASYNC_PREWRITE);
9035		return;
9036	}
9037	if (len > dr->dr_rx_bufsize) {
9038		tmp = len;
9039		while (1) {
9040			dr->getdesc(dr, *slot, &desc, &meta);
9041			bwn_dma_set_redzone(dr, meta->mt_m);
9042			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9043			    BUS_DMASYNC_PREWRITE);
9044			*slot = bwn_dma_nextslot(dr, *slot);
9045			cnt++;
9046			tmp -= dr->dr_rx_bufsize;
9047			if (tmp <= 0)
9048				break;
9049		}
9050		device_printf(sc->sc_dev, "too small buffer "
9051		       "(len %u buffer %u dropped %d)\n",
9052		       len, dr->dr_rx_bufsize, cnt);
9053		return;
9054	}
9055	macstat = le32toh(rxhdr->mac_status);
9056	if (macstat & BWN_RX_MAC_FCSERR) {
9057		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9058			device_printf(sc->sc_dev, "RX drop\n");
9059			return;
9060		}
9061	}
9062
9063	m->m_pkthdr.rcvif = ifp;
9064	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9065	m_adj(m, dr->dr_frameoffset);
9066
9067	bwn_rxeof(dr->dr_mac, m, rxhdr);
9068}
9069
9070static void
9071bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9072{
9073	struct bwn_dma_ring *dr;
9074	struct bwn_dmadesc_generic *desc;
9075	struct bwn_dmadesc_meta *meta;
9076	struct bwn_node *bn;
9077	struct bwn_pio_txqueue *tq;
9078	struct bwn_pio_txpkt *tp = NULL;
9079	struct bwn_softc *sc = mac->mac_sc;
9080	struct ieee80211_node *ni;
9081	int slot;
9082
9083	BWN_ASSERT_LOCKED(mac->mac_sc);
9084
9085	if (status->im)
9086		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9087	if (status->ampdu)
9088		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9089	if (status->rtscnt) {
9090		if (status->rtscnt == 0xf)
9091			device_printf(sc->sc_dev, "TODO: RTS fail\n");
9092		else
9093			device_printf(sc->sc_dev, "TODO: RTS ok\n");
9094	}
9095
9096	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9097		if (status->ack) {
9098			dr = bwn_dma_parse_cookie(mac, status,
9099			    status->cookie, &slot);
9100			if (dr == NULL) {
9101				device_printf(sc->sc_dev,
9102				    "failed to parse cookie\n");
9103				return;
9104			}
9105			while (1) {
9106				dr->getdesc(dr, slot, &desc, &meta);
9107				if (meta->mt_islast) {
9108					ni = meta->mt_ni;
9109					bn = (struct bwn_node *)ni;
9110					ieee80211_amrr_tx_complete(&bn->bn_amn,
9111					    status->ack, 0);
9112					break;
9113				}
9114				slot = bwn_dma_nextslot(dr, slot);
9115			}
9116		}
9117		bwn_dma_handle_txeof(mac, status);
9118	} else {
9119		if (status->ack) {
9120			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9121			if (tq == NULL) {
9122				device_printf(sc->sc_dev,
9123				    "failed to parse cookie\n");
9124				return;
9125			}
9126			ni = tp->tp_ni;
9127			bn = (struct bwn_node *)ni;
9128			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9129		}
9130		bwn_pio_handle_txeof(mac, status);
9131	}
9132
9133	bwn_phy_txpower_check(mac, 0);
9134}
9135
9136static uint8_t
9137bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9138{
9139	struct bwn_mac *mac = prq->prq_mac;
9140	struct bwn_softc *sc = mac->mac_sc;
9141	struct bwn_rxhdr4 rxhdr;
9142	struct ifnet *ifp = sc->sc_ifp;
9143	struct mbuf *m;
9144	uint32_t ctl32, macstat, v32;
9145	unsigned int i, padding;
9146	uint16_t ctl16, len, v16;
9147	unsigned char *mp;
9148	char *data;
9149
9150	memset(&rxhdr, 0, sizeof(rxhdr));
9151
9152	if (prq->prq_rev >= 8) {
9153		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9154		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9155			return (0);
9156		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9157		    BWN_PIO8_RXCTL_FRAMEREADY);
9158		for (i = 0; i < 10; i++) {
9159			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9160			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9161				goto ready;
9162			DELAY(10);
9163		}
9164	} else {
9165		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9166		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9167			return (0);
9168		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9169		    BWN_PIO_RXCTL_FRAMEREADY);
9170		for (i = 0; i < 10; i++) {
9171			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9172			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9173				goto ready;
9174			DELAY(10);
9175		}
9176	}
9177	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9178	return (1);
9179ready:
9180	if (prq->prq_rev >= 8)
9181		siba_read_multi_4(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9182		    prq->prq_base + BWN_PIO8_RXDATA);
9183	else
9184		siba_read_multi_2(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9185		    prq->prq_base + BWN_PIO_RXDATA);
9186	len = le16toh(rxhdr.frame_len);
9187	if (len > 0x700) {
9188		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9189		goto error;
9190	}
9191	if (len == 0) {
9192		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9193		goto error;
9194	}
9195
9196	macstat = le32toh(rxhdr.mac_status);
9197	if (macstat & BWN_RX_MAC_FCSERR) {
9198		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9199			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9200			goto error;
9201		}
9202	}
9203
9204	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9205	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9206	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9207	if (m == NULL) {
9208		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9209		goto error;
9210	}
9211	mp = mtod(m, unsigned char *);
9212	if (prq->prq_rev >= 8) {
9213		siba_read_multi_4(mac->mac_sd, mp + padding, (len & ~3),
9214		    prq->prq_base + BWN_PIO8_RXDATA);
9215		if (len & 3) {
9216			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9217			data = &(mp[len + padding - 1]);
9218			switch (len & 3) {
9219			case 3:
9220				*data = (v32 >> 16);
9221				data--;
9222			case 2:
9223				*data = (v32 >> 8);
9224				data--;
9225			case 1:
9226				*data = v32;
9227			}
9228		}
9229	} else {
9230		siba_read_multi_2(mac->mac_sd, mp + padding, (len & ~1),
9231		    prq->prq_base + BWN_PIO_RXDATA);
9232		if (len & 1) {
9233			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9234			mp[len + padding - 1] = v16;
9235		}
9236	}
9237
9238	m->m_pkthdr.rcvif = ifp;
9239	m->m_len = m->m_pkthdr.len = len + padding;
9240
9241	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9242
9243	return (1);
9244error:
9245	if (prq->prq_rev >= 8)
9246		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9247		    BWN_PIO8_RXCTL_DATAREADY);
9248	else
9249		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9250	return (1);
9251}
9252
9253static int
9254bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9255    struct bwn_dmadesc_meta *meta, int init)
9256{
9257	struct bwn_mac *mac = dr->dr_mac;
9258	struct bwn_dma *dma = &mac->mac_method.dma;
9259	struct bwn_rxhdr4 *hdr;
9260	bus_dmamap_t map;
9261	bus_addr_t paddr;
9262	struct mbuf *m;
9263	int error;
9264
9265	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9266	if (m == NULL) {
9267		error = ENOBUFS;
9268
9269		/*
9270		 * If the NIC is up and running, we need to:
9271		 * - Clear RX buffer's header.
9272		 * - Restore RX descriptor settings.
9273		 */
9274		if (init)
9275			return (error);
9276		else
9277			goto back;
9278	}
9279	m->m_len = m->m_pkthdr.len = MCLBYTES;
9280
9281	bwn_dma_set_redzone(dr, m);
9282
9283	/*
9284	 * Try to load RX buf into temporary DMA map
9285	 */
9286	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9287	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9288	if (error) {
9289		m_freem(m);
9290
9291		/*
9292		 * See the comment above
9293		 */
9294		if (init)
9295			return (error);
9296		else
9297			goto back;
9298	}
9299
9300	if (!init)
9301		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9302	meta->mt_m = m;
9303	meta->mt_paddr = paddr;
9304
9305	/*
9306	 * Swap RX buf's DMA map with the loaded temporary one
9307	 */
9308	map = meta->mt_dmap;
9309	meta->mt_dmap = dr->dr_spare_dmap;
9310	dr->dr_spare_dmap = map;
9311
9312back:
9313	/*
9314	 * Clear RX buf header
9315	 */
9316	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9317	bzero(hdr, sizeof(*hdr));
9318	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9319	    BUS_DMASYNC_PREWRITE);
9320
9321	/*
9322	 * Setup RX buf descriptor
9323	 */
9324	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9325	    sizeof(*hdr), 0, 0, 0);
9326	return (error);
9327}
9328
9329static void
9330bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9331		 bus_size_t mapsz __unused, int error)
9332{
9333
9334	if (!error) {
9335		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9336		*((bus_addr_t *)arg) = seg->ds_addr;
9337	}
9338}
9339
9340static int
9341bwn_hwrate2ieeerate(int rate)
9342{
9343
9344	switch (rate) {
9345	case BWN_CCK_RATE_1MB:
9346		return (2);
9347	case BWN_CCK_RATE_2MB:
9348		return (4);
9349	case BWN_CCK_RATE_5MB:
9350		return (11);
9351	case BWN_CCK_RATE_11MB:
9352		return (22);
9353	case BWN_OFDM_RATE_6MB:
9354		return (12);
9355	case BWN_OFDM_RATE_9MB:
9356		return (18);
9357	case BWN_OFDM_RATE_12MB:
9358		return (24);
9359	case BWN_OFDM_RATE_18MB:
9360		return (36);
9361	case BWN_OFDM_RATE_24MB:
9362		return (48);
9363	case BWN_OFDM_RATE_36MB:
9364		return (72);
9365	case BWN_OFDM_RATE_48MB:
9366		return (96);
9367	case BWN_OFDM_RATE_54MB:
9368		return (108);
9369	default:
9370		printf("Ooops\n");
9371		return (0);
9372	}
9373}
9374
9375static void
9376bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9377{
9378	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9379	struct bwn_plcp6 *plcp;
9380	struct bwn_softc *sc = mac->mac_sc;
9381	struct ieee80211_frame_min *wh;
9382	struct ieee80211_node *ni;
9383	struct ifnet *ifp = sc->sc_ifp;
9384	struct ieee80211com *ic = ifp->if_l2com;
9385	uint32_t macstat;
9386	int padding, rate, rssi = 0, noise = 0, type;
9387	uint16_t phytype, phystat0, phystat3, chanstat;
9388	unsigned char *mp = mtod(m, unsigned char *);
9389	static int rx_mac_dec_rpt = 0;
9390
9391	BWN_ASSERT_LOCKED(sc);
9392
9393	phystat0 = le16toh(rxhdr->phy_status0);
9394	phystat3 = le16toh(rxhdr->phy_status3);
9395	macstat = le32toh(rxhdr->mac_status);
9396	chanstat = le16toh(rxhdr->channel);
9397	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9398
9399	if (macstat & BWN_RX_MAC_FCSERR)
9400		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9401	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9402		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9403	if (phystat0 & BWN_RX_PHYST0_SHORTPRMBL)
9404		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_SHORTPRE\n");
9405	if (macstat & BWN_RX_MAC_DECERR)
9406		goto drop;
9407
9408	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9409	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9410		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9411		    m->m_pkthdr.len);
9412		goto drop;
9413	}
9414	plcp = (struct bwn_plcp6 *)(mp + padding);
9415	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9416	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9417		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9418		    m->m_pkthdr.len);
9419		goto drop;
9420	}
9421	wh = mtod(m, struct ieee80211_frame_min *);
9422
9423	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9424		device_printf(sc->sc_dev,
9425		    "RX decryption attempted (old %d keyidx %#x)\n",
9426		    BWN_ISOLDFMT(mac),
9427		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9428
9429	/* XXX calculating RSSI & noise & antenna */
9430
9431	if (phystat0 & BWN_RX_PHYST0_OFDM)
9432		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9433		    phytype == BWN_PHYTYPE_A);
9434	else
9435		rate = bwn_plcp_get_cckrate(mac, plcp);
9436	if (rate == -1) {
9437		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9438			goto drop;
9439	}
9440	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9441
9442	/* RX radio tap */
9443	if (ieee80211_radiotap_active(ic))
9444		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9445	m_adj(m, -IEEE80211_CRC_LEN);
9446
9447	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9448	noise = mac->mac_stats.link_noise;
9449
9450	BWN_UNLOCK(sc);
9451
9452	ni = ieee80211_find_rxnode(ic, wh);
9453	if (ni != NULL) {
9454		type = ieee80211_input(ni, m, rssi, noise);
9455		ieee80211_free_node(ni);
9456	} else
9457		type = ieee80211_input_all(ic, m, rssi, noise);
9458
9459	BWN_LOCK(sc);
9460	return;
9461drop:
9462	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9463}
9464
9465static void
9466bwn_dma_handle_txeof(struct bwn_mac *mac,
9467    const struct bwn_txstatus *status)
9468{
9469	struct bwn_dma *dma = &mac->mac_method.dma;
9470	struct bwn_dma_ring *dr;
9471	struct bwn_dmadesc_generic *desc;
9472	struct bwn_dmadesc_meta *meta;
9473	struct bwn_softc *sc = mac->mac_sc;
9474	struct ieee80211_node *ni;
9475	struct ifnet *ifp = sc->sc_ifp;
9476	struct mbuf *m;
9477	int slot;
9478
9479	BWN_ASSERT_LOCKED(sc);
9480
9481	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9482	if (dr == NULL) {
9483		device_printf(sc->sc_dev, "failed to parse cookie\n");
9484		return;
9485	}
9486	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9487
9488	while (1) {
9489		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9490		    ("%s:%d: fail", __func__, __LINE__));
9491		dr->getdesc(dr, slot, &desc, &meta);
9492
9493		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9494			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9495		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9496			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9497
9498		if (meta->mt_islast) {
9499			KASSERT(meta->mt_m != NULL,
9500			    ("%s:%d: fail", __func__, __LINE__));
9501
9502			ni = meta->mt_ni;
9503			m = meta->mt_m;
9504			if (ni != NULL) {
9505				/*
9506				 * Do any tx complete callback. Note this must
9507				 * be done before releasing the node reference.
9508				 */
9509				if (m->m_flags & M_TXCB)
9510					ieee80211_process_callback(ni, m, 0);
9511				ieee80211_free_node(ni);
9512				meta->mt_ni = NULL;
9513			}
9514			m_freem(m);
9515			meta->mt_m = NULL;
9516		} else {
9517			KASSERT(meta->mt_m == NULL,
9518			    ("%s:%d: fail", __func__, __LINE__));
9519		}
9520
9521		dr->dr_usedslot--;
9522		if (meta->mt_islast) {
9523			ifp->if_opackets++;
9524			break;
9525		}
9526		slot = bwn_dma_nextslot(dr, slot);
9527	}
9528	sc->sc_watchdog_timer = 0;
9529	if (dr->dr_stop) {
9530		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9531		    ("%s:%d: fail", __func__, __LINE__));
9532		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9533		dr->dr_stop = 0;
9534	}
9535}
9536
9537static void
9538bwn_pio_handle_txeof(struct bwn_mac *mac,
9539    const struct bwn_txstatus *status)
9540{
9541	struct bwn_pio_txqueue *tq;
9542	struct bwn_pio_txpkt *tp = NULL;
9543	struct bwn_softc *sc = mac->mac_sc;
9544	struct ifnet *ifp = sc->sc_ifp;
9545
9546	BWN_ASSERT_LOCKED(sc);
9547
9548	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9549	if (tq == NULL)
9550		return;
9551
9552	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9553	tq->tq_free++;
9554
9555	if (tp->tp_ni != NULL) {
9556		/*
9557		 * Do any tx complete callback.  Note this must
9558		 * be done before releasing the node reference.
9559		 */
9560		if (tp->tp_m->m_flags & M_TXCB)
9561			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9562		ieee80211_free_node(tp->tp_ni);
9563		tp->tp_ni = NULL;
9564	}
9565	m_freem(tp->tp_m);
9566	tp->tp_m = NULL;
9567	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9568
9569	ifp->if_opackets++;
9570
9571	sc->sc_watchdog_timer = 0;
9572	if (tq->tq_stop) {
9573		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9574		tq->tq_stop = 0;
9575	}
9576}
9577
9578static void
9579bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9580{
9581	struct bwn_softc *sc = mac->mac_sc;
9582	struct bwn_phy *phy = &mac->mac_phy;
9583	struct ifnet *ifp = sc->sc_ifp;
9584	struct ieee80211com *ic = ifp->if_l2com;
9585	struct siba_softc *siba = mac->mac_sd->sd_bus;
9586	unsigned long now;
9587	int result;
9588
9589	BWN_GETTIME(now);
9590
9591	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9592		return;
9593	phy->nexttime = now + 2 * 1000;
9594
9595	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
9596	    siba->siba_board_type == SIBA_BOARD_BU4306)
9597		return;
9598
9599	if (phy->recalc_txpwr != NULL) {
9600		result = phy->recalc_txpwr(mac,
9601		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9602		if (result == BWN_TXPWR_RES_DONE)
9603			return;
9604		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9605		    ("%s: fail", __func__));
9606		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9607
9608		ieee80211_runtask(ic, &mac->mac_txpower);
9609	}
9610}
9611
9612static uint16_t
9613bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9614{
9615
9616	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9617}
9618
9619static uint32_t
9620bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9621{
9622
9623	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9624}
9625
9626static void
9627bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9628{
9629
9630	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9631}
9632
9633static void
9634bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9635{
9636
9637	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9638}
9639
9640static int
9641bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9642{
9643
9644	switch (rate) {
9645	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9646	case 12:
9647		return (BWN_OFDM_RATE_6MB);
9648	case 18:
9649		return (BWN_OFDM_RATE_9MB);
9650	case 24:
9651		return (BWN_OFDM_RATE_12MB);
9652	case 36:
9653		return (BWN_OFDM_RATE_18MB);
9654	case 48:
9655		return (BWN_OFDM_RATE_24MB);
9656	case 72:
9657		return (BWN_OFDM_RATE_36MB);
9658	case 96:
9659		return (BWN_OFDM_RATE_48MB);
9660	case 108:
9661		return (BWN_OFDM_RATE_54MB);
9662	/* CCK rates (NB: not IEEE std, device-specific) */
9663	case 2:
9664		return (BWN_CCK_RATE_1MB);
9665	case 4:
9666		return (BWN_CCK_RATE_2MB);
9667	case 11:
9668		return (BWN_CCK_RATE_5MB);
9669	case 22:
9670		return (BWN_CCK_RATE_11MB);
9671	}
9672
9673	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9674	return (BWN_CCK_RATE_1MB);
9675}
9676
9677static int
9678bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9679    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9680{
9681	const struct bwn_phy *phy = &mac->mac_phy;
9682	struct bwn_softc *sc = mac->mac_sc;
9683	struct ieee80211_frame *wh;
9684	struct ieee80211_frame *protwh;
9685	struct ieee80211_frame_cts *cts;
9686	struct ieee80211_frame_rts *rts;
9687	const struct ieee80211_txparam *tp;
9688	struct ieee80211vap *vap = ni->ni_vap;
9689	struct ifnet *ifp = sc->sc_ifp;
9690	struct ieee80211com *ic = ifp->if_l2com;
9691	struct mbuf *mprot;
9692	unsigned int len;
9693	uint32_t macctl = 0;
9694	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9695	uint16_t phyctl = 0;
9696	uint8_t rate, rate_fb;
9697
9698	wh = mtod(m, struct ieee80211_frame *);
9699	memset(txhdr, 0, sizeof(*txhdr));
9700
9701	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9702	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9703	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9704
9705	/*
9706	 * Find TX rate
9707	 */
9708	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9709	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9710		rate = rate_fb = tp->mgmtrate;
9711	else if (ismcast)
9712		rate = rate_fb = tp->mcastrate;
9713	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9714		rate = rate_fb = tp->ucastrate;
9715	else {
9716		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9717		rate = ni->ni_txrate;
9718
9719		if (rix > 0)
9720			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9721			    IEEE80211_RATE_VAL;
9722		else
9723			rate_fb = rate;
9724	}
9725
9726	sc->sc_tx_rate = rate;
9727
9728	rate = bwn_ieeerate2hwrate(sc, rate);
9729	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9730
9731	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9732	    bwn_plcp_getcck(rate);
9733	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9734	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9735
9736	if ((rate_fb == rate) ||
9737	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9738	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9739		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9740	else
9741		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9742		    m->m_pkthdr.len, rate, isshort);
9743
9744	/* XXX TX encryption */
9745	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9746	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9747	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9748	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9749	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9750	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9751
9752	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9753	    BWN_TX_EFT_FB_CCK;
9754	txhdr->chan = phy->chan;
9755	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9756	    BWN_TX_PHY_ENC_CCK;
9757	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9758	     rate == BWN_CCK_RATE_11MB))
9759		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9760
9761	/* XXX TX antenna selection */
9762
9763	switch (bwn_antenna_sanitize(mac, 0)) {
9764	case 0:
9765		phyctl |= BWN_TX_PHY_ANT01AUTO;
9766		break;
9767	case 1:
9768		phyctl |= BWN_TX_PHY_ANT0;
9769		break;
9770	case 2:
9771		phyctl |= BWN_TX_PHY_ANT1;
9772		break;
9773	case 3:
9774		phyctl |= BWN_TX_PHY_ANT2;
9775		break;
9776	case 4:
9777		phyctl |= BWN_TX_PHY_ANT3;
9778		break;
9779	default:
9780		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9781	}
9782
9783	if (!ismcast)
9784		macctl |= BWN_TX_MAC_ACK;
9785
9786	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9787	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9788	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9789		macctl |= BWN_TX_MAC_LONGFRAME;
9790
9791	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9792		/* XXX RTS rate is always 1MB??? */
9793		rts_rate = BWN_CCK_RATE_1MB;
9794		rts_rate_fb = bwn_get_fbrate(rts_rate);
9795
9796		protdur = ieee80211_compute_duration(ic->ic_rt,
9797		    m->m_pkthdr.len, rate, isshort) +
9798		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9799
9800		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9801			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9802			    (txhdr->body.old.rts_frame) :
9803			    (txhdr->body.new.rts_frame));
9804			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9805			    protdur);
9806			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9807			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9808			    mprot->m_pkthdr.len);
9809			m_freem(mprot);
9810			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9811			len = sizeof(struct ieee80211_frame_cts);
9812		} else {
9813			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9814			    (txhdr->body.old.rts_frame) :
9815			    (txhdr->body.new.rts_frame));
9816			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9817			    isshort);
9818			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9819			    wh->i_addr2, protdur);
9820			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9821			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9822			    mprot->m_pkthdr.len);
9823			m_freem(mprot);
9824			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9825			len = sizeof(struct ieee80211_frame_rts);
9826		}
9827		len += IEEE80211_CRC_LEN;
9828		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9829		    &txhdr->body.old.rts_plcp :
9830		    &txhdr->body.new.rts_plcp), len, rts_rate);
9831		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9832		    rts_rate_fb);
9833
9834		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9835		    (&txhdr->body.old.rts_frame) :
9836		    (&txhdr->body.new.rts_frame));
9837		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9838
9839		if (BWN_ISOFDMRATE(rts_rate)) {
9840			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9841			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9842		} else {
9843			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9844			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9845		}
9846		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9847		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9848	}
9849
9850	if (BWN_ISOLDFMT(mac))
9851		txhdr->body.old.cookie = htole16(cookie);
9852	else
9853		txhdr->body.new.cookie = htole16(cookie);
9854
9855	txhdr->macctl = htole32(macctl);
9856	txhdr->phyctl = htole16(phyctl);
9857
9858	/*
9859	 * TX radio tap
9860	 */
9861	if (ieee80211_radiotap_active_vap(vap)) {
9862		sc->sc_tx_th.wt_flags = 0;
9863		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9864			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9865		if (isshort &&
9866		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9867		     rate == BWN_CCK_RATE_11MB))
9868			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9869		sc->sc_tx_th.wt_rate = rate;
9870
9871		ieee80211_radiotap_tx(vap, m);
9872	}
9873
9874	return (0);
9875}
9876
9877static void
9878bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9879    const uint8_t rate)
9880{
9881	uint32_t d, plen;
9882	uint8_t *raw = plcp->o.raw;
9883
9884	if (BWN_ISOFDMRATE(rate)) {
9885		d = bwn_plcp_getofdm(rate);
9886		KASSERT(!(octets & 0xf000),
9887		    ("%s:%d: fail", __func__, __LINE__));
9888		d |= (octets << 5);
9889		plcp->o.data = htole32(d);
9890	} else {
9891		plen = octets * 16 / rate;
9892		if ((octets * 16 % rate) > 0) {
9893			plen++;
9894			if ((rate == BWN_CCK_RATE_11MB)
9895			    && ((octets * 8 % 11) < 4)) {
9896				raw[1] = 0x84;
9897			} else
9898				raw[1] = 0x04;
9899		} else
9900			raw[1] = 0x04;
9901		plcp->o.data |= htole32(plen << 16);
9902		raw[0] = bwn_plcp_getcck(rate);
9903	}
9904}
9905
9906static uint8_t
9907bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9908{
9909	uint8_t mask;
9910
9911	if (n == 0)
9912		return (0);
9913	if (mac->mac_phy.gmode)
9914		mask = mac->mac_sd->sd_bus->siba_sprom.ant_bg;
9915	else
9916		mask = mac->mac_sd->sd_bus->siba_sprom.ant_a;
9917	if (!(mask & (1 << (n - 1))))
9918		return (0);
9919	return (n);
9920}
9921
9922static uint8_t
9923bwn_get_fbrate(uint8_t bitrate)
9924{
9925	switch (bitrate) {
9926	case BWN_CCK_RATE_1MB:
9927		return (BWN_CCK_RATE_1MB);
9928	case BWN_CCK_RATE_2MB:
9929		return (BWN_CCK_RATE_1MB);
9930	case BWN_CCK_RATE_5MB:
9931		return (BWN_CCK_RATE_2MB);
9932	case BWN_CCK_RATE_11MB:
9933		return (BWN_CCK_RATE_5MB);
9934	case BWN_OFDM_RATE_6MB:
9935		return (BWN_CCK_RATE_5MB);
9936	case BWN_OFDM_RATE_9MB:
9937		return (BWN_OFDM_RATE_6MB);
9938	case BWN_OFDM_RATE_12MB:
9939		return (BWN_OFDM_RATE_9MB);
9940	case BWN_OFDM_RATE_18MB:
9941		return (BWN_OFDM_RATE_12MB);
9942	case BWN_OFDM_RATE_24MB:
9943		return (BWN_OFDM_RATE_18MB);
9944	case BWN_OFDM_RATE_36MB:
9945		return (BWN_OFDM_RATE_24MB);
9946	case BWN_OFDM_RATE_48MB:
9947		return (BWN_OFDM_RATE_36MB);
9948	case BWN_OFDM_RATE_54MB:
9949		return (BWN_OFDM_RATE_48MB);
9950	}
9951	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9952	return (0);
9953}
9954
9955static uint32_t
9956bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9957    uint32_t ctl, const void *_data, int len)
9958{
9959	uint32_t value = 0;
9960	const uint8_t *data = _data;
9961
9962	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9963	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9964	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9965
9966	siba_write_multi_4(mac->mac_sd, data, (len & ~3),
9967	    tq->tq_base + BWN_PIO8_TXDATA);
9968	if (len & 3) {
9969		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9970		    BWN_PIO8_TXCTL_24_31);
9971		data = &(data[len - 1]);
9972		switch (len & 3) {
9973		case 3:
9974			ctl |= BWN_PIO8_TXCTL_16_23;
9975			value |= (uint32_t)(*data) << 16;
9976			data--;
9977		case 2:
9978			ctl |= BWN_PIO8_TXCTL_8_15;
9979			value |= (uint32_t)(*data) << 8;
9980			data--;
9981		case 1:
9982			value |= (uint32_t)(*data);
9983		}
9984		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9985		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9986	}
9987
9988	return (ctl);
9989}
9990
9991static void
9992bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9993    uint16_t offset, uint32_t value)
9994{
9995
9996	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9997}
9998
9999static uint16_t
10000bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10001    uint16_t ctl, const void *_data, int len)
10002{
10003	const uint8_t *data = _data;
10004
10005	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10006	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10007
10008	siba_write_multi_2(mac->mac_sd, data, (len & ~1),
10009	    tq->tq_base + BWN_PIO_TXDATA);
10010	if (len & 1) {
10011		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10012		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10013		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
10014	}
10015
10016	return (ctl);
10017}
10018
10019static uint16_t
10020bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10021    uint16_t ctl, struct mbuf *m0)
10022{
10023	int i, j = 0;
10024	uint16_t data = 0;
10025	const uint8_t *buf;
10026	struct mbuf *m = m0;
10027
10028	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10029	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10030
10031	for (; m != NULL; m = m->m_next) {
10032		buf = mtod(m, const uint8_t *);
10033		for (i = 0; i < m->m_len; i++) {
10034			if (!((j++) % 2))
10035				data |= buf[i];
10036			else {
10037				data |= (buf[i] << 8);
10038				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10039				data = 0;
10040			}
10041		}
10042	}
10043	if (m0->m_pkthdr.len % 2) {
10044		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10045		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10046		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10047	}
10048
10049	return (ctl);
10050}
10051
10052static void
10053bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10054{
10055
10056	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10057		return;
10058	BWN_WRITE_2(mac, 0x684, 510 + time);
10059	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10060}
10061
10062static struct bwn_dma_ring *
10063bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10064{
10065
10066	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10067		return (mac->mac_method.dma.wme[WME_AC_BE]);
10068
10069	switch (prio) {
10070	case 3:
10071		return (mac->mac_method.dma.wme[WME_AC_VO]);
10072	case 2:
10073		return (mac->mac_method.dma.wme[WME_AC_VI]);
10074	case 0:
10075		return (mac->mac_method.dma.wme[WME_AC_BE]);
10076	case 1:
10077		return (mac->mac_method.dma.wme[WME_AC_BK]);
10078	}
10079	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10080	return (NULL);
10081}
10082
10083static int
10084bwn_dma_getslot(struct bwn_dma_ring *dr)
10085{
10086	int slot;
10087
10088	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10089
10090	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10091	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10092	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10093
10094	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10095	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10096	dr->dr_curslot = slot;
10097	dr->dr_usedslot++;
10098
10099	return (slot);
10100}
10101
10102static int
10103bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10104{
10105	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10106	unsigned int a, b, c, d;
10107	unsigned int avg;
10108	uint32_t tmp;
10109
10110	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10111	a = tmp & 0xff;
10112	b = (tmp >> 8) & 0xff;
10113	c = (tmp >> 16) & 0xff;
10114	d = (tmp >> 24) & 0xff;
10115	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10116	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10117		return (ENOENT);
10118	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10119	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10120	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10121
10122	if (ofdm) {
10123		a = (a + 32) & 0x3f;
10124		b = (b + 32) & 0x3f;
10125		c = (c + 32) & 0x3f;
10126		d = (d + 32) & 0x3f;
10127	}
10128
10129	avg = (a + b + c + d + 2) / 4;
10130	if (ofdm) {
10131		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10132		    & BWN_HF_4DB_CCK_POWERBOOST)
10133			avg = (avg >= 13) ? (avg - 13) : 0;
10134	}
10135	return (avg);
10136}
10137
10138static void
10139bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10140{
10141	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10142	int rfatt = *rfattp;
10143	int bbatt = *bbattp;
10144
10145	while (1) {
10146		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10147			break;
10148		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10149			break;
10150		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10151			break;
10152		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10153			break;
10154		if (bbatt > lo->bbatt.max) {
10155			bbatt -= 4;
10156			rfatt += 1;
10157			continue;
10158		}
10159		if (bbatt < lo->bbatt.min) {
10160			bbatt += 4;
10161			rfatt -= 1;
10162			continue;
10163		}
10164		if (rfatt > lo->rfatt.max) {
10165			rfatt -= 1;
10166			bbatt += 4;
10167			continue;
10168		}
10169		if (rfatt < lo->rfatt.min) {
10170			rfatt += 1;
10171			bbatt -= 4;
10172			continue;
10173		}
10174		break;
10175	}
10176
10177	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10178	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10179}
10180
10181static void
10182bwn_phy_lock(struct bwn_mac *mac)
10183{
10184	struct bwn_softc *sc = mac->mac_sc;
10185	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10186
10187	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10188	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10189
10190	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10191		bwn_psctl(mac, BWN_PS_AWAKE);
10192}
10193
10194static void
10195bwn_phy_unlock(struct bwn_mac *mac)
10196{
10197	struct bwn_softc *sc = mac->mac_sc;
10198	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10199
10200	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10201	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10202
10203	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10204		bwn_psctl(mac, 0);
10205}
10206
10207static void
10208bwn_rf_lock(struct bwn_mac *mac)
10209{
10210
10211	BWN_WRITE_4(mac, BWN_MACCTL,
10212	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10213	BWN_READ_4(mac, BWN_MACCTL);
10214	DELAY(10);
10215}
10216
10217static void
10218bwn_rf_unlock(struct bwn_mac *mac)
10219{
10220
10221	BWN_READ_2(mac, BWN_PHYVER);
10222	BWN_WRITE_4(mac, BWN_MACCTL,
10223	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10224}
10225
10226static struct bwn_pio_txqueue *
10227bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10228    struct bwn_pio_txpkt **pack)
10229{
10230	struct bwn_pio *pio = &mac->mac_method.pio;
10231	struct bwn_pio_txqueue *tq = NULL;
10232	unsigned int index;
10233
10234	switch (cookie & 0xf000) {
10235	case 0x1000:
10236		tq = &pio->wme[WME_AC_BK];
10237		break;
10238	case 0x2000:
10239		tq = &pio->wme[WME_AC_BE];
10240		break;
10241	case 0x3000:
10242		tq = &pio->wme[WME_AC_VI];
10243		break;
10244	case 0x4000:
10245		tq = &pio->wme[WME_AC_VO];
10246		break;
10247	case 0x5000:
10248		tq = &pio->mcast;
10249		break;
10250	}
10251	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10252	if (tq == NULL)
10253		return (NULL);
10254	index = (cookie & 0x0fff);
10255	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10256	if (index >= N(tq->tq_pkts))
10257		return (NULL);
10258	*pack = &tq->tq_pkts[index];
10259	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10260	return (tq);
10261}
10262
10263static void
10264bwn_txpwr(void *arg, int npending)
10265{
10266	struct bwn_mac *mac = arg;
10267	struct bwn_softc *sc = mac->mac_sc;
10268
10269	BWN_LOCK(sc);
10270	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10271	    mac->mac_phy.set_txpwr != NULL)
10272		mac->mac_phy.set_txpwr(mac);
10273	BWN_UNLOCK(sc);
10274}
10275
10276static void
10277bwn_task_15s(struct bwn_mac *mac)
10278{
10279	uint16_t reg;
10280
10281	if (mac->mac_fw.opensource) {
10282		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10283		if (reg) {
10284			bwn_restart(mac, "fw watchdog");
10285			return;
10286		}
10287		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10288	}
10289	if (mac->mac_phy.task_15s)
10290		mac->mac_phy.task_15s(mac);
10291
10292	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10293}
10294
10295static void
10296bwn_task_30s(struct bwn_mac *mac)
10297{
10298
10299	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10300		return;
10301	mac->mac_noise.noi_running = 1;
10302	mac->mac_noise.noi_nsamples = 0;
10303
10304	bwn_noise_gensample(mac);
10305}
10306
10307static void
10308bwn_task_60s(struct bwn_mac *mac)
10309{
10310
10311	if (mac->mac_phy.task_60s)
10312		mac->mac_phy.task_60s(mac);
10313	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10314}
10315
10316static void
10317bwn_tasks(void *arg)
10318{
10319	struct bwn_mac *mac = arg;
10320	struct bwn_softc *sc = mac->mac_sc;
10321
10322	BWN_ASSERT_LOCKED(sc);
10323	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10324		return;
10325
10326	if (mac->mac_task_state % 4 == 0)
10327		bwn_task_60s(mac);
10328	if (mac->mac_task_state % 2 == 0)
10329		bwn_task_30s(mac);
10330	bwn_task_15s(mac);
10331
10332	mac->mac_task_state++;
10333	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10334}
10335
10336static int
10337bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10338{
10339	struct bwn_softc *sc = mac->mac_sc;
10340
10341	KASSERT(a == 0, ("not support APHY\n"));
10342
10343	switch (plcp->o.raw[0] & 0xf) {
10344	case 0xb:
10345		return (BWN_OFDM_RATE_6MB);
10346	case 0xf:
10347		return (BWN_OFDM_RATE_9MB);
10348	case 0xa:
10349		return (BWN_OFDM_RATE_12MB);
10350	case 0xe:
10351		return (BWN_OFDM_RATE_18MB);
10352	case 0x9:
10353		return (BWN_OFDM_RATE_24MB);
10354	case 0xd:
10355		return (BWN_OFDM_RATE_36MB);
10356	case 0x8:
10357		return (BWN_OFDM_RATE_48MB);
10358	case 0xc:
10359		return (BWN_OFDM_RATE_54MB);
10360	}
10361	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10362	    plcp->o.raw[0] & 0xf);
10363	return (-1);
10364}
10365
10366static int
10367bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10368{
10369	struct bwn_softc *sc = mac->mac_sc;
10370
10371	switch (plcp->o.raw[0]) {
10372	case 0x0a:
10373		return (BWN_CCK_RATE_1MB);
10374	case 0x14:
10375		return (BWN_CCK_RATE_2MB);
10376	case 0x37:
10377		return (BWN_CCK_RATE_5MB);
10378	case 0x6e:
10379		return (BWN_CCK_RATE_11MB);
10380	}
10381	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10382	return (-1);
10383}
10384
10385static void
10386bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10387    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10388    int rssi, int noise)
10389{
10390	struct bwn_softc *sc = mac->mac_sc;
10391	const struct ieee80211_frame_min *wh;
10392	uint64_t tsf;
10393	uint16_t low_mactime_now;
10394
10395	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10396		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10397
10398	wh = mtod(m, const struct ieee80211_frame_min *);
10399	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10400		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10401
10402	bwn_tsf_read(mac, &tsf);
10403	low_mactime_now = tsf;
10404	tsf = tsf & ~0xffffULL;
10405	tsf += le16toh(rxhdr->mac_time);
10406	if (low_mactime_now < le16toh(rxhdr->mac_time))
10407		tsf -= 0x10000;
10408
10409	sc->sc_rx_th.wr_tsf = tsf;
10410	sc->sc_rx_th.wr_rate = rate;
10411	sc->sc_rx_th.wr_antsignal = rssi;
10412	sc->sc_rx_th.wr_antnoise = noise;
10413}
10414
10415static void
10416bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10417{
10418	uint32_t low, high;
10419
10420	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10421	    ("%s:%d: fail", __func__, __LINE__));
10422
10423	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10424	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10425	*tsf = high;
10426	*tsf <<= 32;
10427	*tsf |= low;
10428}
10429
10430static int
10431bwn_dma_attach(struct bwn_mac *mac)
10432{
10433	struct bwn_dma *dma = &mac->mac_method.dma;
10434	struct bwn_softc *sc = mac->mac_sc;
10435	struct siba_dev_softc *sd = mac->mac_sd;
10436	struct siba_softc *siba = sd->sd_bus;
10437	bus_addr_t lowaddr = 0;
10438	int error;
10439
10440	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10441		return (0);
10442
10443	KASSERT(mac->mac_sd->sd_id.sd_rev >= 5, ("%s: fail", __func__));
10444
10445	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10446
10447	dma->dmatype = bwn_dma_gettype(mac);
10448	if (dma->dmatype == BWN_DMA_30BIT)
10449		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10450	else if (dma->dmatype == BWN_DMA_32BIT)
10451		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10452	else
10453		lowaddr = BUS_SPACE_MAXADDR;
10454
10455	/*
10456	 * Create top level DMA tag
10457	 */
10458	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10459			       BWN_ALIGN, 0,		/* alignment, bounds */
10460			       lowaddr,			/* lowaddr */
10461			       BUS_SPACE_MAXADDR,	/* highaddr */
10462			       NULL, NULL,		/* filter, filterarg */
10463			       MAXBSIZE,		/* maxsize */
10464			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10465			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10466			       0,			/* flags */
10467			       NULL, NULL,		/* lockfunc, lockarg */
10468			       &dma->parent_dtag);
10469	if (error) {
10470		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10471		return (error);
10472	}
10473
10474	/*
10475	 * Create TX/RX mbuf DMA tag
10476	 */
10477	error = bus_dma_tag_create(dma->parent_dtag,
10478				1,
10479				0,
10480				BUS_SPACE_MAXADDR,
10481				BUS_SPACE_MAXADDR,
10482				NULL, NULL,
10483				MCLBYTES,
10484				1,
10485				BUS_SPACE_MAXSIZE_32BIT,
10486				0,
10487				NULL, NULL,
10488				&dma->rxbuf_dtag);
10489	if (error) {
10490		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10491		goto fail0;
10492	}
10493	error = bus_dma_tag_create(dma->parent_dtag,
10494				1,
10495				0,
10496				BUS_SPACE_MAXADDR,
10497				BUS_SPACE_MAXADDR,
10498				NULL, NULL,
10499				MCLBYTES,
10500				1,
10501				BUS_SPACE_MAXSIZE_32BIT,
10502				0,
10503				NULL, NULL,
10504				&dma->txbuf_dtag);
10505	if (error) {
10506		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10507		goto fail1;
10508	}
10509
10510	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10511	if (!dma->wme[WME_AC_BK])
10512		goto fail2;
10513
10514	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10515	if (!dma->wme[WME_AC_BE])
10516		goto fail3;
10517
10518	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10519	if (!dma->wme[WME_AC_VI])
10520		goto fail4;
10521
10522	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10523	if (!dma->wme[WME_AC_VO])
10524		goto fail5;
10525
10526	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10527	if (!dma->mcast)
10528		goto fail6;
10529	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10530	if (!dma->rx)
10531		goto fail7;
10532
10533	return (error);
10534
10535fail7:	bwn_dma_ringfree(&dma->mcast);
10536fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10537fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10538fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10539fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10540fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10541fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10542fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10543	return (error);
10544}
10545
10546static struct bwn_dma_ring *
10547bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10548    uint16_t cookie, int *slot)
10549{
10550	struct bwn_dma *dma = &mac->mac_method.dma;
10551	struct bwn_dma_ring *dr;
10552	struct bwn_softc *sc = mac->mac_sc;
10553
10554	BWN_ASSERT_LOCKED(mac->mac_sc);
10555
10556	switch (cookie & 0xf000) {
10557	case 0x1000:
10558		dr = dma->wme[WME_AC_BK];
10559		break;
10560	case 0x2000:
10561		dr = dma->wme[WME_AC_BE];
10562		break;
10563	case 0x3000:
10564		dr = dma->wme[WME_AC_VI];
10565		break;
10566	case 0x4000:
10567		dr = dma->wme[WME_AC_VO];
10568		break;
10569	case 0x5000:
10570		dr = dma->mcast;
10571		break;
10572	default:
10573		dr = NULL;
10574		KASSERT(0 == 1,
10575		    ("invalid cookie value %d", cookie & 0xf000));
10576	}
10577	*slot = (cookie & 0x0fff);
10578	if (*slot < 0 || *slot >= dr->dr_numslots) {
10579		/*
10580		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10581		 * that it occurs events which have same H/W sequence numbers.
10582		 * When it's occurred just prints a WARNING msgs and ignores.
10583		 */
10584		KASSERT(status->seq == dma->lastseq,
10585		    ("%s:%d: fail", __func__, __LINE__));
10586		device_printf(sc->sc_dev,
10587		    "out of slot ranges (0 < %d < %d)\n", *slot,
10588		    dr->dr_numslots);
10589		return (NULL);
10590	}
10591	dma->lastseq = status->seq;
10592	return (dr);
10593}
10594
10595static void
10596bwn_dma_stop(struct bwn_mac *mac)
10597{
10598	struct bwn_dma *dma;
10599
10600	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10601		return;
10602	dma = &mac->mac_method.dma;
10603
10604	bwn_dma_ringstop(&dma->rx);
10605	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10606	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10607	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10608	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10609	bwn_dma_ringstop(&dma->mcast);
10610}
10611
10612static void
10613bwn_dma_ringstop(struct bwn_dma_ring **dr)
10614{
10615
10616	if (dr == NULL)
10617		return;
10618
10619	bwn_dma_cleanup(*dr);
10620}
10621
10622static void
10623bwn_pio_stop(struct bwn_mac *mac)
10624{
10625	struct bwn_pio *pio;
10626
10627	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10628		return;
10629	pio = &mac->mac_method.pio;
10630
10631	bwn_destroy_queue_tx(&pio->mcast);
10632	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10633	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10634	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10635	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10636}
10637
10638static void
10639bwn_led_attach(struct bwn_mac *mac)
10640{
10641	struct bwn_softc *sc = mac->mac_sc;
10642	struct siba_softc *siba = mac->mac_sd->sd_bus;
10643	const uint8_t *led_act = NULL;
10644	uint16_t val[BWN_LED_MAX];
10645	int i;
10646
10647	sc->sc_led_idle = (2350 * hz) / 1000;
10648	sc->sc_led_blink = 1;
10649
10650	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10651		if (siba->siba_pci_subvid == bwn_vendor_led_act[i].vid) {
10652			led_act = bwn_vendor_led_act[i].led_act;
10653			break;
10654		}
10655	}
10656	if (led_act == NULL)
10657		led_act = bwn_default_led_act;
10658
10659	val[0] = siba->siba_sprom.gpio0;
10660	val[1] = siba->siba_sprom.gpio1;
10661	val[2] = siba->siba_sprom.gpio2;
10662	val[3] = siba->siba_sprom.gpio3;
10663
10664	for (i = 0; i < BWN_LED_MAX; ++i) {
10665		struct bwn_led *led = &sc->sc_leds[i];
10666
10667		if (val[i] == 0xff) {
10668			led->led_act = led_act[i];
10669		} else {
10670			if (val[i] & BWN_LED_ACT_LOW)
10671				led->led_flags |= BWN_LED_F_ACTLOW;
10672			led->led_act = val[i] & BWN_LED_ACT_MASK;
10673		}
10674		led->led_mask = (1 << i);
10675
10676		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10677		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10678		    led->led_act == BWN_LED_ACT_BLINK) {
10679			led->led_flags |= BWN_LED_F_BLINK;
10680			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10681				led->led_flags |= BWN_LED_F_POLLABLE;
10682			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10683				led->led_flags |= BWN_LED_F_SLOW;
10684
10685			if (sc->sc_blink_led == NULL) {
10686				sc->sc_blink_led = led;
10687				if (led->led_flags & BWN_LED_F_SLOW)
10688					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10689			}
10690		}
10691
10692		DPRINTF(sc, BWN_DEBUG_LED,
10693		    "%dth led, act %d, lowact %d\n", i,
10694		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10695	}
10696	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10697}
10698
10699static __inline uint16_t
10700bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10701{
10702
10703	if (led->led_flags & BWN_LED_F_ACTLOW)
10704		on = !on;
10705	if (on)
10706		val |= led->led_mask;
10707	else
10708		val &= ~led->led_mask;
10709	return val;
10710}
10711
10712static void
10713bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10714{
10715	struct bwn_softc *sc = mac->mac_sc;
10716	struct ifnet *ifp = sc->sc_ifp;
10717	struct ieee80211com *ic = ifp->if_l2com;
10718	uint16_t val;
10719	int i;
10720
10721	if (nstate == IEEE80211_S_INIT) {
10722		callout_stop(&sc->sc_led_blink_ch);
10723		sc->sc_led_blinking = 0;
10724	}
10725
10726	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10727		return;
10728
10729	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10730	for (i = 0; i < BWN_LED_MAX; ++i) {
10731		struct bwn_led *led = &sc->sc_leds[i];
10732		int on;
10733
10734		if (led->led_act == BWN_LED_ACT_UNKN ||
10735		    led->led_act == BWN_LED_ACT_NULL)
10736			continue;
10737
10738		if ((led->led_flags & BWN_LED_F_BLINK) &&
10739		    nstate != IEEE80211_S_INIT)
10740			continue;
10741
10742		switch (led->led_act) {
10743		case BWN_LED_ACT_ON:    /* Always on */
10744			on = 1;
10745			break;
10746		case BWN_LED_ACT_OFF:   /* Always off */
10747		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10748			on = 0;
10749			break;
10750		default:
10751			on = 1;
10752			switch (nstate) {
10753			case IEEE80211_S_INIT:
10754				on = 0;
10755				break;
10756			case IEEE80211_S_RUN:
10757				if (led->led_act == BWN_LED_ACT_11G &&
10758				    ic->ic_curmode != IEEE80211_MODE_11G)
10759					on = 0;
10760				break;
10761			default:
10762				if (led->led_act == BWN_LED_ACT_ASSOC)
10763					on = 0;
10764				break;
10765			}
10766			break;
10767		}
10768
10769		val = bwn_led_onoff(led, val, on);
10770	}
10771	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10772}
10773
10774static void
10775bwn_led_event(struct bwn_mac *mac, int event)
10776{
10777	struct bwn_softc *sc = mac->mac_sc;
10778        struct bwn_led *led = sc->sc_blink_led;
10779        int rate;
10780
10781        if (event == BWN_LED_EVENT_POLL) {
10782                if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10783                        return;
10784                if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10785                        return;
10786        }
10787
10788        sc->sc_led_ticks = ticks;
10789        if (sc->sc_led_blinking)
10790                return;
10791
10792        switch (event) {
10793        case BWN_LED_EVENT_RX:
10794                rate = sc->sc_rx_rate;
10795                break;
10796        case BWN_LED_EVENT_TX:
10797                rate = sc->sc_tx_rate;
10798                break;
10799        case BWN_LED_EVENT_POLL:
10800                rate = 0;
10801                break;
10802        default:
10803                panic("unknown LED event %d\n", event);
10804                break;
10805        }
10806        bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10807            bwn_led_duration[rate].off_dur);
10808}
10809
10810static void
10811bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10812{
10813	struct bwn_softc *sc = mac->mac_sc;
10814        struct bwn_led *led = sc->sc_blink_led;
10815        uint16_t val;
10816
10817        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10818        val = bwn_led_onoff(led, val, 1);
10819        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10820
10821        if (led->led_flags & BWN_LED_F_SLOW) {
10822                BWN_LED_SLOWDOWN(on_dur);
10823                BWN_LED_SLOWDOWN(off_dur);
10824        }
10825
10826        sc->sc_led_blinking = 1;
10827        sc->sc_led_blink_offdur = off_dur;
10828
10829        callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10830}
10831
10832static void
10833bwn_led_blink_next(void *arg)
10834{
10835	struct bwn_mac *mac = arg;
10836        struct bwn_softc *sc = mac->mac_sc;
10837        uint16_t val;
10838
10839        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10840        val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10841        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10842
10843        callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10844            bwn_led_blink_end, mac);
10845}
10846
10847static void
10848bwn_led_blink_end(void *arg)
10849{
10850	struct bwn_mac *mac = arg;
10851        struct bwn_softc *sc = mac->mac_sc;
10852
10853        sc->sc_led_blinking = 0;
10854}
10855
10856static int
10857bwn_suspend(device_t dev)
10858{
10859	struct bwn_softc *sc = device_get_softc(dev);
10860
10861	bwn_stop(sc, 1);
10862	return (0);
10863}
10864
10865static int
10866bwn_resume(device_t dev)
10867{
10868	struct bwn_softc *sc = device_get_softc(dev);
10869	struct ifnet *ifp = sc->sc_ifp;
10870
10871	if (ifp->if_flags & IFF_UP)
10872		bwn_init(sc);
10873	return (0);
10874}
10875
10876static void
10877bwn_rfswitch(void *arg)
10878{
10879	struct bwn_softc *sc = arg;
10880	struct bwn_mac *mac = sc->sc_curmac;
10881	int cur = 0, prev = 0;
10882
10883	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10884	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10885
10886	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10887		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10888			& BWN_RF_HWENABLED_HI_MASK))
10889			cur = 1;
10890	} else {
10891		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10892		    & BWN_RF_HWENABLED_LO_MASK)
10893			cur = 1;
10894	}
10895
10896	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10897		prev = 1;
10898
10899	if (cur != prev) {
10900		if (cur)
10901			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10902		else
10903			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10904
10905		device_printf(sc->sc_dev,
10906		    "status of RF switch is changed to %s\n",
10907		    cur ? "ON" : "OFF");
10908		if (cur != mac->mac_phy.rf_on) {
10909			if (cur)
10910				bwn_rf_turnon(mac);
10911			else
10912				bwn_rf_turnoff(mac);
10913		}
10914	}
10915
10916	callout_schedule(&sc->sc_rfswitch_ch, hz);
10917}
10918
10919static void
10920bwn_phy_lp_init_pre(struct bwn_mac *mac)
10921{
10922	struct bwn_phy *phy = &mac->mac_phy;
10923	struct bwn_phy_lp *plp = &phy->phy_lp;
10924
10925	plp->plp_antenna = BWN_ANT_DEFAULT;
10926}
10927
10928static int
10929bwn_phy_lp_init(struct bwn_mac *mac)
10930{
10931	static const struct bwn_stxtable tables[] = {
10932		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10933		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10934		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10935		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10936		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10937		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10938		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10939		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10940		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10941		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10942		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10943		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10944		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10945		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10946		{ 2, 11, 0x40, 0, 0x0f }
10947	};
10948	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10949	struct bwn_softc *sc = mac->mac_sc;
10950	const struct bwn_stxtable *st;
10951	struct ifnet *ifp = sc->sc_ifp;
10952	struct ieee80211com *ic = ifp->if_l2com;
10953	int i, error;
10954	uint16_t tmp;
10955
10956	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10957	bwn_phy_lp_bbinit(mac);
10958
10959	/* initialize RF */
10960	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10961	DELAY(1);
10962	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10963	DELAY(1);
10964
10965	if (mac->mac_phy.rf_ver == 0x2062)
10966		bwn_phy_lp_b2062_init(mac);
10967	else {
10968		bwn_phy_lp_b2063_init(mac);
10969
10970		/* synchronize stx table. */
10971		for (i = 0; i < N(tables); i++) {
10972			st = &tables[i];
10973			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10974			tmp >>= st->st_rfshift;
10975			tmp <<= st->st_physhift;
10976			BWN_PHY_SETMASK(mac,
10977			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10978			    ~(st->st_mask << st->st_physhift), tmp);
10979		}
10980
10981		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10982		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10983	}
10984
10985	/* calibrate RC */
10986	if (mac->mac_phy.rev >= 2)
10987		bwn_phy_lp_rxcal_r2(mac);
10988	else if (!plp->plp_rccap) {
10989		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10990			bwn_phy_lp_rccal_r12(mac);
10991	} else
10992		bwn_phy_lp_set_rccap(mac);
10993
10994	error = bwn_phy_lp_switch_channel(mac, 7);
10995	if (error)
10996		device_printf(sc->sc_dev,
10997		    "failed to change channel 7 (%d)\n", error);
10998	bwn_phy_lp_txpctl_init(mac);
10999	bwn_phy_lp_calib(mac);
11000	return (0);
11001}
11002
11003static uint16_t
11004bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
11005{
11006
11007	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11008	return (BWN_READ_2(mac, BWN_PHYDATA));
11009}
11010
11011static void
11012bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11013{
11014
11015	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11016	BWN_WRITE_2(mac, BWN_PHYDATA, value);
11017}
11018
11019static void
11020bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
11021    uint16_t set)
11022{
11023
11024	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11025	BWN_WRITE_2(mac, BWN_PHYDATA,
11026	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
11027}
11028
11029static uint16_t
11030bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
11031{
11032
11033	KASSERT(reg != 1, ("unaccessible register %d", reg));
11034	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11035		reg |= 0x100;
11036	if (mac->mac_phy.rev >= 2)
11037		reg |= 0x200;
11038	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11039	return BWN_READ_2(mac, BWN_RFDATALO);
11040}
11041
11042static void
11043bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11044{
11045
11046	KASSERT(reg != 1, ("unaccessible register %d", reg));
11047	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11048	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11049}
11050
11051static void
11052bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11053{
11054
11055	if (on) {
11056		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11057		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11058		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11059		return;
11060	}
11061
11062	if (mac->mac_phy.rev >= 2) {
11063		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11064		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11065		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11066		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11067		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11068		return;
11069	}
11070
11071	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11072	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11073	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11074	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11075}
11076
11077static int
11078bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11079{
11080	struct bwn_phy *phy = &mac->mac_phy;
11081	struct bwn_phy_lp *plp = &phy->phy_lp;
11082	int error;
11083
11084	if (phy->rf_ver == 0x2063) {
11085		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11086		if (error)
11087			return (error);
11088	} else {
11089		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11090		if (error)
11091			return (error);
11092		bwn_phy_lp_set_anafilter(mac, chan);
11093		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11094	}
11095
11096	plp->plp_chan = chan;
11097	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11098	return (0);
11099}
11100
11101static uint32_t
11102bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11103{
11104	struct bwn_softc *sc = mac->mac_sc;
11105	struct ifnet *ifp = sc->sc_ifp;
11106	struct ieee80211com *ic = ifp->if_l2com;
11107
11108	device_printf(sc->sc_dev, "correct?\n");
11109
11110	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11111}
11112
11113static void
11114bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11115{
11116	struct bwn_phy *phy = &mac->mac_phy;
11117	struct bwn_phy_lp *plp = &phy->phy_lp;
11118
11119	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11120		return;
11121
11122	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11123	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11124	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11125	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11126	plp->plp_antenna = antenna;
11127}
11128
11129static void
11130bwn_phy_lp_task_60s(struct bwn_mac *mac)
11131{
11132
11133	bwn_phy_lp_calib(mac);
11134}
11135
11136static void
11137bwn_phy_lp_readsprom(struct bwn_mac *mac)
11138{
11139	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11140	struct bwn_softc *sc = mac->mac_sc;
11141	struct ifnet *ifp = sc->sc_ifp;
11142	struct ieee80211com *ic = ifp->if_l2com;
11143	struct siba_dev_softc *sd = mac->mac_sd;
11144	struct siba_softc *siba = sd->sd_bus;
11145	struct siba_sprom *sprom = &siba->siba_sprom;
11146
11147	device_printf(sc->sc_dev, "XXX using %dghz\n",
11148	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 2 : 5);
11149
11150	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11151		plp->plp_txisoband_m = sprom->tri2g;
11152		plp->plp_bxarch = sprom->bxa2g;
11153		plp->plp_rxpwroffset = sprom->rxpo2g;
11154		plp->plp_rssivf = sprom->rssismf2g;
11155		plp->plp_rssivc = sprom->rssismc2g;
11156		plp->plp_rssigs = sprom->rssisav2g;
11157		return;
11158	}
11159
11160	plp->plp_txisoband_l = sprom->tri5gl;
11161	plp->plp_txisoband_m = sprom->tri5g;
11162	plp->plp_txisoband_h = sprom->tri5gh;
11163	plp->plp_bxarch = sprom->bxa5g;
11164	plp->plp_rxpwroffset = sprom->rxpo5g;
11165	plp->plp_rssivf = sprom->rssismf5g;
11166	plp->plp_rssivc = sprom->rssismc5g;
11167	plp->plp_rssigs = sprom->rssisav5g;
11168}
11169
11170static void
11171bwn_phy_lp_bbinit(struct bwn_mac *mac)
11172{
11173
11174	bwn_phy_lp_tblinit(mac);
11175	if (mac->mac_phy.rev >= 2)
11176		bwn_phy_lp_bbinit_r2(mac);
11177	else
11178		bwn_phy_lp_bbinit_r01(mac);
11179}
11180
11181static void
11182bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11183{
11184	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11185	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11186	struct bwn_softc *sc = mac->mac_sc;
11187	struct ifnet *ifp = sc->sc_ifp;
11188	struct ieee80211com *ic = ifp->if_l2com;
11189
11190	bwn_phy_lp_set_txgain(mac,
11191	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11192	bwn_phy_lp_set_bbmult(mac, 150);
11193}
11194
11195static void
11196bwn_phy_lp_calib(struct bwn_mac *mac)
11197{
11198	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11199	struct siba_dev_softc *sd = mac->mac_sd;
11200	struct siba_softc *siba = sd->sd_bus;
11201	struct bwn_softc *sc = mac->mac_sc;
11202	struct ifnet *ifp = sc->sc_ifp;
11203	struct ieee80211com *ic = ifp->if_l2com;
11204	const struct bwn_rxcompco *rc = NULL;
11205	struct bwn_txgain ogain;
11206	int i, omode, oafeovr, orf, obbmult;
11207	uint8_t mode, fc = 0;
11208
11209	if (plp->plp_chanfullcal != plp->plp_chan) {
11210		plp->plp_chanfullcal = plp->plp_chan;
11211		fc = 1;
11212	}
11213
11214	bwn_mac_suspend(mac);
11215
11216	/* BlueTooth Coexistance Override */
11217	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11218	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11219
11220	if (mac->mac_phy.rev >= 2)
11221		bwn_phy_lp_digflt_save(mac);
11222	bwn_phy_lp_get_txpctlmode(mac);
11223	mode = plp->plp_txpctlmode;
11224	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11225	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11226		bwn_phy_lp_bugfix(mac);
11227	if (mac->mac_phy.rev >= 2 && fc == 1) {
11228		bwn_phy_lp_get_txpctlmode(mac);
11229		omode = plp->plp_txpctlmode;
11230		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11231		if (oafeovr)
11232			ogain = bwn_phy_lp_get_txgain(mac);
11233		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11234		obbmult = bwn_phy_lp_get_bbmult(mac);
11235		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11236		if (oafeovr)
11237			bwn_phy_lp_set_txgain(mac, &ogain);
11238		bwn_phy_lp_set_bbmult(mac, obbmult);
11239		bwn_phy_lp_set_txpctlmode(mac, omode);
11240		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11241	}
11242	bwn_phy_lp_set_txpctlmode(mac, mode);
11243	if (mac->mac_phy.rev >= 2)
11244		bwn_phy_lp_digflt_restore(mac);
11245
11246	/* do RX IQ Calculation; assumes that noise is true. */
11247	if (siba->siba_chipid == 0x5354) {
11248		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11249			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11250				rc = &bwn_rxcompco_5354[i];
11251		}
11252	} else if (mac->mac_phy.rev >= 2)
11253		rc = &bwn_rxcompco_r2;
11254	else {
11255		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11256			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11257				rc = &bwn_rxcompco_r12[i];
11258		}
11259	}
11260	if (rc == NULL)
11261		goto fail;
11262
11263	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11264	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11265
11266	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11267
11268	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11269		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11270		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11271	} else {
11272		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11273		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11274	}
11275
11276	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11277	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11278	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11279	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11280	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11281	bwn_phy_lp_set_deaf(mac, 0);
11282	/* XXX no checking return value? */
11283	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11284	bwn_phy_lp_clear_deaf(mac, 0);
11285	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11286	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11287	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11288
11289	/* disable RX GAIN override. */
11290	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11291	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11292	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11293	if (mac->mac_phy.rev >= 2) {
11294		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11295		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11296			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11297			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11298		}
11299	} else {
11300		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11301	}
11302
11303	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11304	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11305fail:
11306	bwn_mac_enable(mac);
11307}
11308
11309static void
11310bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11311{
11312
11313       if (on) {
11314               BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11315	       return;
11316       }
11317
11318       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11319       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11320}
11321
11322static int
11323bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11324{
11325	struct siba_dev_softc *sd = mac->mac_sd;
11326	struct siba_softc *siba = sd->sd_bus;
11327	static const struct bwn_b206x_chan *bc = NULL;
11328	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11329	    tmp[6];
11330	uint16_t old, scale, tmp16;
11331	int i, div;
11332
11333	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11334		if (bwn_b2063_chantable[i].bc_chan == chan) {
11335			bc = &bwn_b2063_chantable[i];
11336			break;
11337		}
11338	}
11339	if (bc == NULL)
11340		return (EINVAL);
11341
11342	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11343	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11344	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11345	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11346	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11347	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11348	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11349	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11350	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11351	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11352	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11353	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11354
11355	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11356	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11357
11358	freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11359	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11360	freqref = freqxtal * 3;
11361	div = (freqxtal <= 26000000 ? 1 : 2);
11362	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11363	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11364		999999) / 1000000) + 1;
11365
11366	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11367	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11368	    0xfff8, timeout >> 2);
11369	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11370	    0xff9f,timeout << 5);
11371	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11372
11373	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11374	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11375	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11376
11377	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11378	    (timeoutref + 1)) - 1;
11379	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11380	    0xf0, count >> 8);
11381	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11382
11383	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11384	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11385	while (tmp[1] >= freqref) {
11386		tmp[0]++;
11387		tmp[1] -= freqref;
11388	}
11389	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11390	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11391	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11392	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11393	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11394
11395	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11396	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11397	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11398	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11399
11400	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11401	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11402
11403	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11404		scale = 1;
11405		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11406	} else {
11407		scale = 0;
11408		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11409	}
11410	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11411	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11412
11413	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11414	    (scale + 1);
11415	if (tmp[5] > 150)
11416		tmp[5] = 0;
11417
11418	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11419	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11420
11421	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11422	if (freqxtal > 26000000)
11423		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11424	else
11425		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11426
11427	if (val[0] == 45)
11428		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11429	else
11430		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11431
11432	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11433	DELAY(1);
11434	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11435
11436	/* VCO Calibration */
11437	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11438	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11439	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11440	DELAY(1);
11441	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11442	DELAY(1);
11443	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11444	DELAY(1);
11445	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11446	DELAY(300);
11447	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11448
11449	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11450	return (0);
11451}
11452
11453static int
11454bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11455{
11456	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11457	struct siba_dev_softc *sd = mac->mac_sd;
11458	struct siba_softc *siba = sd->sd_bus;
11459	const struct bwn_b206x_chan *bc = NULL;
11460	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11461	uint32_t tmp[9];
11462	int i;
11463
11464	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11465		if (bwn_b2062_chantable[i].bc_chan == chan) {
11466			bc = &bwn_b2062_chantable[i];
11467			break;
11468		}
11469	}
11470
11471	if (bc == NULL)
11472		return (EINVAL);
11473
11474	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11475	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11476	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11477	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11478	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11479	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11480	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11481	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11482	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11483	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11484
11485	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11486	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11487	bwn_phy_lp_b2062_reset_pllbias(mac);
11488	tmp[0] = freqxtal / 1000;
11489	tmp[1] = plp->plp_div * 1000;
11490	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11491	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11492		tmp[2] *= 2;
11493	tmp[3] = 48 * tmp[0];
11494	tmp[5] = tmp[2] / tmp[3];
11495	tmp[6] = tmp[2] % tmp[3];
11496	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11497	tmp[4] = tmp[6] * 0x100;
11498	tmp[5] = tmp[4] / tmp[3];
11499	tmp[6] = tmp[4] % tmp[3];
11500	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11501	tmp[4] = tmp[6] * 0x100;
11502	tmp[5] = tmp[4] / tmp[3];
11503	tmp[6] = tmp[4] % tmp[3];
11504	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11505	tmp[4] = tmp[6] * 0x100;
11506	tmp[5] = tmp[4] / tmp[3];
11507	tmp[6] = tmp[4] % tmp[3];
11508	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11509	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11510	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11511	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11512	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11513	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11514
11515	bwn_phy_lp_b2062_vco_calib(mac);
11516	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11517		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11518		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11519		bwn_phy_lp_b2062_reset_pllbias(mac);
11520		bwn_phy_lp_b2062_vco_calib(mac);
11521		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11522			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11523			return (EIO);
11524		}
11525	}
11526	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11527	return (0);
11528}
11529
11530static void
11531bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11532{
11533	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11534	uint16_t tmp = (channel == 14);
11535
11536	if (mac->mac_phy.rev < 2) {
11537		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11538		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11539			bwn_phy_lp_set_rccap(mac);
11540		return;
11541	}
11542
11543	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11544}
11545
11546static void
11547bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11548{
11549	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11550	struct bwn_softc *sc = mac->mac_sc;
11551	struct ifnet *ifp = sc->sc_ifp;
11552	struct ieee80211com *ic = ifp->if_l2com;
11553	uint16_t iso, tmp[3];
11554
11555	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11556
11557	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11558		iso = plp->plp_txisoband_m;
11559	else if (freq <= 5320)
11560		iso = plp->plp_txisoband_l;
11561	else if (freq <= 5700)
11562		iso = plp->plp_txisoband_m;
11563	else
11564		iso = plp->plp_txisoband_h;
11565
11566	tmp[0] = ((iso - 26) / 12) << 12;
11567	tmp[1] = tmp[0] + 0x1000;
11568	tmp[2] = tmp[0] + 0x2000;
11569
11570	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11571	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11572}
11573
11574static void
11575bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11576{
11577	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11578	int i;
11579	static const uint16_t addr[] = {
11580		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11581		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11582		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11583		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11584		BWN_PHY_OFDM(0xcf),
11585	};
11586	static const uint16_t val[] = {
11587		0xde5e, 0xe832, 0xe331, 0x4d26,
11588		0x0026, 0x1420, 0x0020, 0xfe08,
11589		0x0008,
11590	};
11591
11592	for (i = 0; i < N(addr); i++) {
11593		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11594		BWN_PHY_WRITE(mac, addr[i], val[i]);
11595	}
11596}
11597
11598static void
11599bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11600{
11601	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11602	struct bwn_softc *sc = mac->mac_sc;
11603	uint16_t ctl;
11604
11605	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11606	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11607	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11608		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11609		break;
11610	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11611		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11612		break;
11613	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11614		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11615		break;
11616	default:
11617		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11618		device_printf(sc->sc_dev, "unknown command mode\n");
11619		break;
11620	}
11621}
11622
11623static void
11624bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11625{
11626	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11627	uint16_t ctl;
11628	uint8_t old;
11629
11630	bwn_phy_lp_get_txpctlmode(mac);
11631	old = plp->plp_txpctlmode;
11632	if (old == mode)
11633		return;
11634	plp->plp_txpctlmode = mode;
11635
11636	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11637		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11638		    plp->plp_tssiidx);
11639		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11640		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11641
11642		/* disable TX GAIN override */
11643		if (mac->mac_phy.rev < 2)
11644			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11645		else {
11646			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11647			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11648		}
11649		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11650
11651		plp->plp_txpwridx = -1;
11652	}
11653	if (mac->mac_phy.rev >= 2) {
11654		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11655			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11656		else
11657			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11658	}
11659
11660	/* writes TX Power Control mode */
11661	switch (plp->plp_txpctlmode) {
11662	case BWN_PHYLP_TXPCTL_OFF:
11663		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11664		break;
11665	case BWN_PHYLP_TXPCTL_ON_HW:
11666		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11667		break;
11668	case BWN_PHYLP_TXPCTL_ON_SW:
11669		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11670		break;
11671	default:
11672		ctl = 0;
11673		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11674	}
11675	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11676	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11677}
11678
11679static void
11680bwn_phy_lp_bugfix(struct bwn_mac *mac)
11681{
11682	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11683	struct bwn_softc *sc = mac->mac_sc;
11684	const unsigned int size = 256;
11685	struct bwn_txgain tg;
11686	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11687	uint16_t tssinpt, tssiidx, value[2];
11688	uint8_t mode;
11689	int8_t txpwridx;
11690
11691	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11692	    M_NOWAIT | M_ZERO);
11693	if (tabs == NULL) {
11694		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11695		return;
11696	}
11697
11698	bwn_phy_lp_get_txpctlmode(mac);
11699	mode = plp->plp_txpctlmode;
11700	txpwridx = plp->plp_txpwridx;
11701	tssinpt = plp->plp_tssinpt;
11702	tssiidx = plp->plp_tssiidx;
11703
11704	bwn_tab_read_multi(mac,
11705	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11706	    BWN_TAB_4(7, 0x140), size, tabs);
11707
11708	bwn_phy_lp_tblinit(mac);
11709	bwn_phy_lp_bbinit(mac);
11710	bwn_phy_lp_txpctl_init(mac);
11711	bwn_phy_lp_rf_onoff(mac, 1);
11712	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11713
11714	bwn_tab_write_multi(mac,
11715	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11716	    BWN_TAB_4(7, 0x140), size, tabs);
11717
11718	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11719	plp->plp_tssinpt = tssinpt;
11720	plp->plp_tssiidx = tssiidx;
11721	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11722	if (txpwridx != -1) {
11723		/* set TX power by index */
11724		plp->plp_txpwridx = txpwridx;
11725		bwn_phy_lp_get_txpctlmode(mac);
11726		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11727			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11728		if (mac->mac_phy.rev >= 2) {
11729			rxcomp = bwn_tab_read(mac,
11730			    BWN_TAB_4(7, txpwridx + 320));
11731			txgain = bwn_tab_read(mac,
11732			    BWN_TAB_4(7, txpwridx + 192));
11733			tg.tg_pad = (txgain >> 16) & 0xff;
11734			tg.tg_gm = txgain & 0xff;
11735			tg.tg_pga = (txgain >> 8) & 0xff;
11736			tg.tg_dac = (rxcomp >> 28) & 0xff;
11737			bwn_phy_lp_set_txgain(mac, &tg);
11738		} else {
11739			rxcomp = bwn_tab_read(mac,
11740			    BWN_TAB_4(10, txpwridx + 320));
11741			txgain = bwn_tab_read(mac,
11742			    BWN_TAB_4(10, txpwridx + 192));
11743			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11744			    0xf800, (txgain >> 4) & 0x7fff);
11745			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11746			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11747		}
11748		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11749
11750		/* set TX IQCC */
11751		value[0] = (rxcomp >> 10) & 0x3ff;
11752		value[1] = rxcomp & 0x3ff;
11753		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11754
11755		coeff = bwn_tab_read(mac,
11756		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11757		    BWN_TAB_4(10, txpwridx + 448));
11758		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11759		if (mac->mac_phy.rev >= 2) {
11760			rfpwr = bwn_tab_read(mac,
11761			    BWN_TAB_4(7, txpwridx + 576));
11762			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11763			    rfpwr & 0xffff);
11764		}
11765		bwn_phy_lp_set_txgain_override(mac);
11766	}
11767	if (plp->plp_rccap)
11768		bwn_phy_lp_set_rccap(mac);
11769	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11770	bwn_phy_lp_set_txpctlmode(mac, mode);
11771	free(tabs, M_DEVBUF);
11772}
11773
11774static void
11775bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11776{
11777	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11778	int i;
11779	static const uint16_t addr[] = {
11780		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11781		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11782		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11783		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11784		BWN_PHY_OFDM(0xcf),
11785	};
11786
11787	for (i = 0; i < N(addr); i++)
11788		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11789}
11790
11791static void
11792bwn_phy_lp_tblinit(struct bwn_mac *mac)
11793{
11794	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11795
11796	if (mac->mac_phy.rev < 2) {
11797		bwn_phy_lp_tblinit_r01(mac);
11798		bwn_phy_lp_tblinit_txgain(mac);
11799		bwn_phy_lp_set_gaintbl(mac, freq);
11800		return;
11801	}
11802
11803	bwn_phy_lp_tblinit_r2(mac);
11804	bwn_phy_lp_tblinit_txgain(mac);
11805}
11806
11807struct bwn_wpair {
11808	uint16_t		reg;
11809	uint16_t		value;
11810};
11811
11812struct bwn_smpair {
11813	uint16_t		offset;
11814	uint16_t		mask;
11815	uint16_t		set;
11816};
11817
11818static void
11819bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11820{
11821	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11822	struct siba_dev_softc *sd = mac->mac_sd;
11823	struct siba_softc *siba = sd->sd_bus;
11824	struct bwn_softc *sc = mac->mac_sc;
11825	struct ifnet *ifp = sc->sc_ifp;
11826	struct ieee80211com *ic = ifp->if_l2com;
11827	static const struct bwn_wpair v1[] = {
11828		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11829		{ BWN_PHY_AFE_CTL, 0x8800 },
11830		{ BWN_PHY_AFE_CTL_OVR, 0 },
11831		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11832		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11833		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11834		{ BWN_PHY_OFDM(0xf9), 0 },
11835		{ BWN_PHY_TR_LOOKUP_1, 0 }
11836	};
11837	static const struct bwn_smpair v2[] = {
11838		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11839		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11840		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11841		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11842		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11843	};
11844	static const struct bwn_smpair v3[] = {
11845		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11846		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11847		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11848		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11849		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11850		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11851		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11852		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11853		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11854		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11855
11856	};
11857	int i;
11858
11859	for (i = 0; i < N(v1); i++)
11860		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11861	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11862	for (i = 0; i < N(v2); i++)
11863		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11864
11865	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11866	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11867	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11868	if (siba->siba_board_rev >= 0x18) {
11869		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11870		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11871	} else {
11872		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11873	}
11874	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11875	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11876	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11877	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11878	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11879	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11880	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11881	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11882	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11883	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11884	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11885	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11886		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11887		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11888	} else {
11889		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11890		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11891	}
11892	for (i = 0; i < N(v3); i++)
11893		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11894	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11895		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11896		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11897	}
11898
11899	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11900		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11901		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11902		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11903		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11904		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11905		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11906	} else
11907		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11908
11909	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11910	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11911	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11912	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11913	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11914	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11915	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11916	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11917	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11918
11919	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11920		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11921		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11922		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11923	}
11924
11925	bwn_phy_lp_digflt_save(mac);
11926}
11927
11928static void
11929bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11930{
11931	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11932	struct siba_dev_softc *sd = mac->mac_sd;
11933	struct siba_softc *siba = sd->sd_bus;
11934	struct bwn_softc *sc = mac->mac_sc;
11935	struct ifnet *ifp = sc->sc_ifp;
11936	struct ieee80211com *ic = ifp->if_l2com;
11937	static const struct bwn_smpair v1[] = {
11938		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11939		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11940		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11941		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11942		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11943		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11944		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11945	};
11946	static const struct bwn_smpair v2[] = {
11947		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11948		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11949		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11950		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11951		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11952		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11953		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11954		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11955		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11956		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11957		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11958		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11959		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11960		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11961		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11962		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11963	};
11964	static const struct bwn_smpair v3[] = {
11965		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11966		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11967		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11968		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11969		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11970		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11971		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11972		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11973	};
11974	static const struct bwn_smpair v4[] = {
11975		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11976		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11977		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11978		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11979		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11980		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11981		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11982		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11983	};
11984	static const struct bwn_smpair v5[] = {
11985		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11986		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11987		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11988		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11989		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11990		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11991		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11992		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11993	};
11994	int i;
11995	uint16_t tmp, tmp2;
11996
11997	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11998	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11999	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
12000	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
12001	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
12002	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
12003	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
12004	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
12005	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
12006	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
12007	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
12008	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
12009	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
12010	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
12011	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
12012	for (i = 0; i < N(v1); i++)
12013		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
12014	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
12015	    0xff00, plp->plp_rxpwroffset);
12016	if ((siba->siba_sprom.bf_lo & BWN_BFL_FEM) &&
12017	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
12018	   (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF))) {
12019		siba_cc_pmu_set_ldovolt(&siba->siba_cc, SIBA_LDO_PAREF, 0x28);
12020		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 1);
12021		if (mac->mac_phy.rev == 0)
12022			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
12023			    0xffcf, 0x0010);
12024		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
12025	} else {
12026		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 0);
12027		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
12028		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
12029	}
12030	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
12031	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
12032	if (siba->siba_sprom.bf_hi & BWN_BFH_RSSIINV)
12033		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
12034	else
12035		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
12036	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
12037	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
12038	    0xfff9, (plp->plp_bxarch << 1));
12039	if (mac->mac_phy.rev == 1 &&
12040	    (siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT)) {
12041		for (i = 0; i < N(v2); i++)
12042			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
12043			    v2[i].set);
12044	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
12045	    (siba->siba_board_type == 0x048a) || ((mac->mac_phy.rev == 0) &&
12046	    (siba->siba_sprom.bf_lo & BWN_BFL_FEM))) {
12047		for (i = 0; i < N(v3); i++)
12048			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12049			    v3[i].set);
12050	} else if (mac->mac_phy.rev == 1 ||
12051		  (siba->siba_sprom.bf_lo & BWN_BFL_FEM)) {
12052		for (i = 0; i < N(v4); i++)
12053			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12054			    v4[i].set);
12055	} else {
12056		for (i = 0; i < N(v5); i++)
12057			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12058			    v5[i].set);
12059	}
12060	if (mac->mac_phy.rev == 1 &&
12061	    (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF)) {
12062		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12063		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12064		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12065		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12066	}
12067	if ((siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT) &&
12068	    (siba->siba_chipid == 0x5354) &&
12069	    (siba->siba_chippkg == SIBA_CHIPPACK_BCM4712S)) {
12070		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12071		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12072		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12073		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12074	}
12075	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12076		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12077		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12078		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12079		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12080		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12081		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12082		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12083		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12084	} else {
12085		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12086		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12087	}
12088	if (mac->mac_phy.rev == 1) {
12089		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12090		tmp2 = (tmp & 0x03e0) >> 5;
12091		tmp2 |= tmp2 << 5;
12092		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12093		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12094		tmp2 = (tmp & 0x1f00) >> 8;
12095		tmp2 |= tmp2 << 5;
12096		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12097		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12098		tmp2 = tmp & 0x00ff;
12099		tmp2 |= tmp << 8;
12100		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12101	}
12102}
12103
12104struct bwn_b2062_freq {
12105	uint16_t		freq;
12106	uint8_t			value[6];
12107};
12108
12109static void
12110bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12111{
12112#define	CALC_CTL7(freq, div)						\
12113	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12114#define	CALC_CTL18(freq, div)						\
12115	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12116#define	CALC_CTL19(freq, div)						\
12117	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12118	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12119	struct siba_dev_softc *sd = mac->mac_sd;
12120	struct siba_softc *siba = sd->sd_bus;
12121	struct bwn_softc *sc = mac->mac_sc;
12122	struct ifnet *ifp = sc->sc_ifp;
12123	struct ieee80211com *ic = ifp->if_l2com;
12124	static const struct bwn_b2062_freq freqdata_tab[] = {
12125		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12126		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12127		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12128		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12129		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12130		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12131	};
12132	static const struct bwn_wpair v1[] = {
12133		{ BWN_B2062_N_TXCTL3, 0 },
12134		{ BWN_B2062_N_TXCTL4, 0 },
12135		{ BWN_B2062_N_TXCTL5, 0 },
12136		{ BWN_B2062_N_TXCTL6, 0 },
12137		{ BWN_B2062_N_PDNCTL0, 0x40 },
12138		{ BWN_B2062_N_PDNCTL0, 0 },
12139		{ BWN_B2062_N_CALIB_TS, 0x10 },
12140		{ BWN_B2062_N_CALIB_TS, 0 }
12141	};
12142	const struct bwn_b2062_freq *f = NULL;
12143	uint32_t xtalfreq, ref;
12144	unsigned int i;
12145
12146	bwn_phy_lp_b2062_tblinit(mac);
12147
12148	for (i = 0; i < N(v1); i++)
12149		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12150	if (mac->mac_phy.rev > 0)
12151		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12152		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12153	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12154		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12155	else
12156		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12157
12158	KASSERT(siba->siba_cc.scc_caps & SIBA_CC_CAPS_PMU,
12159	    ("%s:%d: fail", __func__, __LINE__));
12160	xtalfreq = siba->siba_cc.scc_pmu.freq * 1000;
12161	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12162
12163	if (xtalfreq <= 30000000) {
12164		plp->plp_div = 1;
12165		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12166	} else {
12167		plp->plp_div = 2;
12168		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12169	}
12170
12171	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12172	    CALC_CTL7(xtalfreq, plp->plp_div));
12173	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12174	    CALC_CTL18(xtalfreq, plp->plp_div));
12175	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12176	    CALC_CTL19(xtalfreq, plp->plp_div));
12177
12178	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12179	ref &= 0xffff;
12180	for (i = 0; i < N(freqdata_tab); i++) {
12181		if (ref < freqdata_tab[i].freq) {
12182			f = &freqdata_tab[i];
12183			break;
12184		}
12185	}
12186	if (f == NULL)
12187		f = &freqdata_tab[N(freqdata_tab) - 1];
12188	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12189	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12190	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12191	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12192	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12193	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12194#undef CALC_CTL7
12195#undef CALC_CTL18
12196#undef CALC_CTL19
12197}
12198
12199static void
12200bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12201{
12202
12203	bwn_phy_lp_b2063_tblinit(mac);
12204	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12205	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12206	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12207	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12208	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12209	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12210	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12211	if (mac->mac_phy.rev == 2) {
12212		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12213		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12214		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12215	} else {
12216		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12217		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12218	}
12219}
12220
12221static void
12222bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12223{
12224	struct siba_dev_softc *sd = mac->mac_sd;
12225	struct siba_softc *siba = sd->sd_bus;
12226	static const struct bwn_wpair v1[] = {
12227		{ BWN_B2063_RX_BB_SP8, 0x0 },
12228		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12229		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12230		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12231		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12232		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12233		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12234		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12235	};
12236	static const struct bwn_wpair v2[] = {
12237		{ BWN_B2063_TX_BB_SP3, 0x0 },
12238		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12239		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12240		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12241		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12242	};
12243	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
12244	int i;
12245	uint8_t tmp;
12246
12247	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12248
12249	for (i = 0; i < 2; i++)
12250		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12251	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12252	for (i = 2; i < N(v1); i++)
12253		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12254	for (i = 0; i < 10000; i++) {
12255		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12256			break;
12257		DELAY(1000);
12258	}
12259
12260	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12261		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12262
12263	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12264
12265	for (i = 0; i < N(v2); i++)
12266		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12267	if (freqxtal == 24000000) {
12268		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12269		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12270	} else {
12271		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12272		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12273	}
12274	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12275	for (i = 0; i < 10000; i++) {
12276		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12277			break;
12278		DELAY(1000);
12279	}
12280	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12281		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12282	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12283}
12284
12285static void
12286bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12287{
12288	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12289	struct bwn_softc *sc = mac->mac_sc;
12290	struct bwn_phy_lp_iq_est ie;
12291	struct bwn_txgain tx_gains;
12292	static const uint32_t pwrtbl[21] = {
12293		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12294		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12295		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12296		0x0004c, 0x0002c, 0x0001a,
12297	};
12298	uint32_t npwr, ipwr, sqpwr, tmp;
12299	int loopback, i, j, sum, error;
12300	uint16_t save[7];
12301	uint8_t txo, bbmult, txpctlmode;
12302
12303	error = bwn_phy_lp_switch_channel(mac, 7);
12304	if (error)
12305		device_printf(sc->sc_dev,
12306		    "failed to change channel to 7 (%d)\n", error);
12307	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12308	bbmult = bwn_phy_lp_get_bbmult(mac);
12309	if (txo)
12310		tx_gains = bwn_phy_lp_get_txgain(mac);
12311
12312	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12313	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12314	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12315	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12316	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12317	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12318	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12319
12320	bwn_phy_lp_get_txpctlmode(mac);
12321	txpctlmode = plp->plp_txpctlmode;
12322	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12323
12324	/* disable CRS */
12325	bwn_phy_lp_set_deaf(mac, 1);
12326	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12327	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12328	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12329	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12330	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12331	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12332	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12333	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12334	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12335	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12336	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12337	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12338	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12339	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12340	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12341	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12342	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12343	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12344	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12345	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12346	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12347	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12348	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12349	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12350
12351	loopback = bwn_phy_lp_loopback(mac);
12352	if (loopback == -1)
12353		goto done;
12354	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12355	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12356	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12357	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12358	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12359
12360	tmp = 0;
12361	memset(&ie, 0, sizeof(ie));
12362	for (i = 128; i <= 159; i++) {
12363		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12364		sum = 0;
12365		for (j = 5; j <= 25; j++) {
12366			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12367			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12368				goto done;
12369			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12370			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12371			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12372			    12);
12373			sum += ((ipwr - npwr) * (ipwr - npwr));
12374			if ((i == 128) || (sum < tmp)) {
12375				plp->plp_rccap = i;
12376				tmp = sum;
12377			}
12378		}
12379	}
12380	bwn_phy_lp_ddfs_turnoff(mac);
12381done:
12382	/* restore CRS */
12383	bwn_phy_lp_clear_deaf(mac, 1);
12384	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12385	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12386
12387	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12388	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12389	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12390	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12391	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12392	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12393	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12394
12395	bwn_phy_lp_set_bbmult(mac, bbmult);
12396	if (txo)
12397		bwn_phy_lp_set_txgain(mac, &tx_gains);
12398	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12399	if (plp->plp_rccap)
12400		bwn_phy_lp_set_rccap(mac);
12401}
12402
12403static void
12404bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12405{
12406	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12407	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12408
12409	if (mac->mac_phy.rev == 1)
12410		rc_cap = MIN(rc_cap + 5, 15);
12411
12412	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12413	    MAX(plp->plp_rccap - 4, 0x80));
12414	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12415	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12416	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12417}
12418
12419static uint32_t
12420bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12421{
12422	uint32_t i, q, r;
12423
12424	if (div == 0)
12425		return (0);
12426
12427	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12428		q <<= 1;
12429		if (r << 1 >= div) {
12430			q++;
12431			r = (r << 1) - div;
12432		}
12433	}
12434	if (r << 1 >= div)
12435		q++;
12436	return (q);
12437}
12438
12439static void
12440bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12441{
12442	struct siba_dev_softc *sd = mac->mac_sd;
12443	struct siba_softc *siba = sd->sd_bus;
12444
12445	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12446	DELAY(20);
12447	if (siba->siba_chipid == 0x5354) {
12448		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12449		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12450	} else {
12451		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12452	}
12453	DELAY(5);
12454}
12455
12456static void
12457bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12458{
12459
12460	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12461	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12462	DELAY(200);
12463}
12464
12465static void
12466bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12467{
12468#define	FLAG_A	0x01
12469#define	FLAG_G	0x02
12470	struct bwn_softc *sc = mac->mac_sc;
12471	struct ifnet *ifp = sc->sc_ifp;
12472	struct ieee80211com *ic = ifp->if_l2com;
12473	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12474		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12475		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12476		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12477		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12478		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12479		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12480		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12481		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12482		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12483		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12484		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12485		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12486		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12487		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12488		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12489		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12490		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12491		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12492		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12493		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12494		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12495		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12496		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12497		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12498		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12499		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12500		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12501		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12502		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12503		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12504		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12505		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12506		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12507		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12508		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12509		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12510		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12511		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12512		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12513		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12514		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12515		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12516		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12517		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12518		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12519		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12520		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12521	};
12522	const struct bwn_b206x_rfinit_entry *br;
12523	unsigned int i;
12524
12525	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12526		br = &bwn_b2062_init_tab[i];
12527		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12528			if (br->br_flags & FLAG_G)
12529				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12530		} else {
12531			if (br->br_flags & FLAG_A)
12532				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12533		}
12534	}
12535#undef FLAG_A
12536#undef FLAG_B
12537}
12538
12539static void
12540bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12541{
12542#define	FLAG_A	0x01
12543#define	FLAG_G	0x02
12544	struct bwn_softc *sc = mac->mac_sc;
12545	struct ifnet *ifp = sc->sc_ifp;
12546	struct ieee80211com *ic = ifp->if_l2com;
12547	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12548		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12549		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12550		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12551		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12552		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12553		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12554		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12555		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12556		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12557		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12558		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12559		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12560		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12561		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12562		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12563		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12564		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12565		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12566		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12567		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12568		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12569		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12570		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12571		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12572		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12573		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12574		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12575		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12576		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12577		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12578		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12579		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12580		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12581		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12582		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12583		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12584		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12585		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12586		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12587		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12588		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12589		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12590	};
12591	const struct bwn_b206x_rfinit_entry *br;
12592	unsigned int i;
12593
12594	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12595		br = &bwn_b2063_init_tab[i];
12596		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12597			if (br->br_flags & FLAG_G)
12598				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12599		} else {
12600			if (br->br_flags & FLAG_A)
12601				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12602		}
12603	}
12604#undef FLAG_A
12605#undef FLAG_B
12606}
12607
12608static void
12609bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12610    int count, void *_data)
12611{
12612	unsigned int i;
12613	uint32_t offset, type;
12614	uint8_t *data = _data;
12615
12616	type = BWN_TAB_GETTYPE(typenoffset);
12617	offset = BWN_TAB_GETOFFSET(typenoffset);
12618	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12619
12620	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12621
12622	for (i = 0; i < count; i++) {
12623		switch (type) {
12624		case BWN_TAB_8BIT:
12625			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12626			data++;
12627			break;
12628		case BWN_TAB_16BIT:
12629			*((uint16_t *)data) = BWN_PHY_READ(mac,
12630			    BWN_PHY_TABLEDATALO);
12631			data += 2;
12632			break;
12633		case BWN_TAB_32BIT:
12634			*((uint32_t *)data) = BWN_PHY_READ(mac,
12635			    BWN_PHY_TABLEDATAHI);
12636			*((uint32_t *)data) <<= 16;
12637			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12638			    BWN_PHY_TABLEDATALO);
12639			data += 4;
12640			break;
12641		default:
12642			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12643		}
12644	}
12645}
12646
12647static void
12648bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12649    int count, const void *_data)
12650{
12651	uint32_t offset, type, value;
12652	const uint8_t *data = _data;
12653	unsigned int i;
12654
12655	type = BWN_TAB_GETTYPE(typenoffset);
12656	offset = BWN_TAB_GETOFFSET(typenoffset);
12657	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12658
12659	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12660
12661	for (i = 0; i < count; i++) {
12662		switch (type) {
12663		case BWN_TAB_8BIT:
12664			value = *data;
12665			data++;
12666			KASSERT(!(value & ~0xff),
12667			    ("%s:%d: fail", __func__, __LINE__));
12668			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12669			break;
12670		case BWN_TAB_16BIT:
12671			value = *((const uint16_t *)data);
12672			data += 2;
12673			KASSERT(!(value & ~0xffff),
12674			    ("%s:%d: fail", __func__, __LINE__));
12675			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12676			break;
12677		case BWN_TAB_32BIT:
12678			value = *((const uint32_t *)data);
12679			data += 4;
12680			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12681			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12682			break;
12683		default:
12684			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12685		}
12686	}
12687}
12688
12689static struct bwn_txgain
12690bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12691{
12692	struct bwn_txgain tg;
12693	uint16_t tmp;
12694
12695	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12696	if (mac->mac_phy.rev < 2) {
12697		tmp = BWN_PHY_READ(mac,
12698		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12699		tg.tg_gm = tmp & 0x0007;
12700		tg.tg_pga = (tmp & 0x0078) >> 3;
12701		tg.tg_pad = (tmp & 0x780) >> 7;
12702		return (tg);
12703	}
12704
12705	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12706	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12707	tg.tg_gm = tmp & 0xff;
12708	tg.tg_pga = (tmp >> 8) & 0xff;
12709	return (tg);
12710}
12711
12712static uint8_t
12713bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12714{
12715
12716	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12717}
12718
12719static void
12720bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12721{
12722	uint16_t pa;
12723
12724	if (mac->mac_phy.rev < 2) {
12725		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12726		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12727		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12728		bwn_phy_lp_set_txgain_override(mac);
12729		return;
12730	}
12731
12732	pa = bwn_phy_lp_get_pa_gain(mac);
12733	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12734	    (tg->tg_pga << 8) | tg->tg_gm);
12735	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12736	    tg->tg_pad | (pa << 6));
12737	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12738	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12739	    tg->tg_pad | (pa << 8));
12740	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12741	bwn_phy_lp_set_txgain_override(mac);
12742}
12743
12744static void
12745bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12746{
12747
12748	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12749}
12750
12751static void
12752bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12753{
12754	uint16_t trsw = (tx << 1) | rx;
12755
12756	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12757	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12758}
12759
12760static void
12761bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12762{
12763	struct bwn_softc *sc = mac->mac_sc;
12764	struct ifnet *ifp = sc->sc_ifp;
12765	struct ieee80211com *ic = ifp->if_l2com;
12766	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12767
12768	if (mac->mac_phy.rev < 2) {
12769		trsw = gain & 0x1;
12770		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12771		ext_lna = (gain & 2) >> 1;
12772
12773		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12774		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12775		    0xfbff, ext_lna << 10);
12776		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12777		    0xf7ff, ext_lna << 11);
12778		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12779	} else {
12780		low_gain = gain & 0xffff;
12781		high_gain = (gain >> 16) & 0xf;
12782		ext_lna = (gain >> 21) & 0x1;
12783		trsw = ~(gain >> 20) & 0x1;
12784
12785		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12786		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12787		    0xfdff, ext_lna << 9);
12788		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12789		    0xfbff, ext_lna << 10);
12790		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12791		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12792		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12793			tmp = (gain >> 2) & 0x3;
12794			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12795			    0xe7ff, tmp<<11);
12796			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12797			    tmp << 3);
12798		}
12799	}
12800
12801	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12802	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12803	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12804	if (mac->mac_phy.rev >= 2) {
12805		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12806		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12807			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12808			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12809		}
12810		return;
12811	}
12812	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12813}
12814
12815static void
12816bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12817{
12818	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12819
12820	if (user)
12821		plp->plp_crsusr_off = 1;
12822	else
12823		plp->plp_crssys_off = 1;
12824
12825	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12826}
12827
12828static void
12829bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12830{
12831	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12832	struct bwn_softc *sc = mac->mac_sc;
12833	struct ifnet *ifp = sc->sc_ifp;
12834	struct ieee80211com *ic = ifp->if_l2com;
12835
12836	if (user)
12837		plp->plp_crsusr_off = 0;
12838	else
12839		plp->plp_crssys_off = 0;
12840
12841	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12842		return;
12843
12844	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12845		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12846	else
12847		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12848}
12849
12850static unsigned int
12851bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12852{
12853	struct bwn_softc *sc = mac->mac_sc;
12854	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12855	static uint8_t sqrt_table[256] = {
12856		10, 14, 17, 20, 22, 24, 26, 28,
12857		30, 31, 33, 34, 36, 37, 38, 40,
12858		41, 42, 43, 44, 45, 46, 47, 48,
12859		50, 50, 51, 52, 53, 54, 55, 56,
12860		57, 58, 59, 60, 60, 61, 62, 63,
12861		64, 64, 65, 66, 67, 67, 68, 69,
12862		70, 70, 71, 72, 72, 73, 74, 74,
12863		75, 76, 76, 77, 78, 78, 79, 80,
12864		80, 81, 81, 82, 83, 83, 84, 84,
12865		85, 86, 86, 87, 87, 88, 88, 89,
12866		90, 90, 91, 91, 92, 92, 93, 93,
12867		94, 94, 95, 95, 96, 96, 97, 97,
12868		98, 98, 99, 100, 100, 100, 101, 101,
12869		102, 102, 103, 103, 104, 104, 105, 105,
12870		106, 106, 107, 107, 108, 108, 109, 109,
12871		110, 110, 110, 111, 111, 112, 112, 113,
12872		113, 114, 114, 114, 115, 115, 116, 116,
12873		117, 117, 117, 118, 118, 119, 119, 120,
12874		120, 120, 121, 121, 122, 122, 122, 123,
12875		123, 124, 124, 124, 125, 125, 126, 126,
12876		126, 127, 127, 128, 128, 128, 129, 129,
12877		130, 130, 130, 131, 131, 131, 132, 132,
12878		133, 133, 133, 134, 134, 134, 135, 135,
12879		136, 136, 136, 137, 137, 137, 138, 138,
12880		138, 139, 139, 140, 140, 140, 141, 141,
12881		141, 142, 142, 142, 143, 143, 143, 144,
12882		144, 144, 145, 145, 145, 146, 146, 146,
12883		147, 147, 147, 148, 148, 148, 149, 149,
12884		150, 150, 150, 150, 151, 151, 151, 152,
12885		152, 152, 153, 153, 153, 154, 154, 154,
12886		155, 155, 155, 156, 156, 156, 157, 157,
12887		157, 158, 158, 158, 159, 159, 159, 160
12888	};
12889
12890	if (x == 0)
12891		return (0);
12892	if (x >= 256) {
12893		device_printf(sc->sc_dev,
12894		    "out of bounds of the square-root table (%d)\n", x);
12895		return (16);
12896	}
12897	return (sqrt_table[x - 1] / 10);
12898}
12899
12900static int
12901bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12902{
12903#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12904	int _t;								\
12905	_t = _x - 20;							\
12906	if (_t >= 0) {							\
12907		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12908	} else {							\
12909		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12910	}								\
12911} while (0)
12912#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12913	int _t;								\
12914	_t = _x - 11;							\
12915	if (_t >= 0)							\
12916		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12917	else								\
12918		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12919} while (0)
12920	struct bwn_phy_lp_iq_est ie;
12921	uint16_t v0, v1;
12922	int tmp[2], ret;
12923
12924	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12925	v0 = v1 >> 8;
12926	v1 |= 0xff;
12927
12928	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12929	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12930
12931	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12932	if (ret == 0)
12933		goto done;
12934
12935	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12936		ret = 0;
12937		goto done;
12938	}
12939
12940	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12941	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12942
12943	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12944	v0 = tmp[0] >> 3;
12945	v1 = tmp[1] >> 4;
12946done:
12947	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12948	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12949	return ret;
12950#undef CALC_COEFF
12951#undef CALC_COEFF2
12952}
12953
12954static void
12955bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12956{
12957	static const uint16_t noisescale[] = {
12958		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12959		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12960		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12961		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12962		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12963	};
12964	static const uint16_t crsgainnft[] = {
12965		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12966		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12967		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12968		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12969		0x013d,
12970	};
12971	static const uint16_t filterctl[] = {
12972		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12973		0xff53, 0x0127,
12974	};
12975	static const uint32_t psctl[] = {
12976		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12977		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12978		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12979		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12980		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12981		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12982		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12983		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12984	};
12985	static const uint16_t ofdmcckgain_r0[] = {
12986		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12987		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12988		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12989		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12990		0x755d,
12991	};
12992	static const uint16_t ofdmcckgain_r1[] = {
12993		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12994		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12995		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12996		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12997		0x755d,
12998	};
12999	static const uint16_t gaindelta[] = {
13000		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13001		0x0000,
13002	};
13003	static const uint32_t txpwrctl[] = {
13004		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
13005		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
13006		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
13007		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
13008		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
13009		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
13010		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
13011		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
13012		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
13013		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
13014		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
13015		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
13016		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
13017		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13018		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13019		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13020		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13021		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13022		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13023		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13024		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13025		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13026		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13027		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13028		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13029		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13030		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13031		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13032		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13033		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13034		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13035		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13036		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13037		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13038		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13039		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13040		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13041		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13042		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
13043		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
13044		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
13045		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
13046		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
13047		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
13048		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13049		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13050		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13051		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13052		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13053		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13054		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13055		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13056		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13057		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13058		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13059		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13060		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13061		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13062		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13063		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13064		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13065		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13066		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13067		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13068		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13069		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13070		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13071		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13072		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13073		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13074		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13075		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13076		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13077		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13078		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13079		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13080		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13081		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13082		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13083		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13084		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13085		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13086		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13087		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13088		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13089		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13090		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13091		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13092		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13093		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13094		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13095		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13096		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13097		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13098		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13099		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13100		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13101		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13102		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13103		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13104		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13105		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13106		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13107		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13108		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13109		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13110		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13111		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13112		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13113		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13114		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13115		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13116		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13117		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13118		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13119		0x00000702,
13120	};
13121
13122	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13123
13124	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13125	    bwn_tab_sigsq_tbl);
13126	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13127	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13128	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13129	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13130	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13131	    bwn_tab_pllfrac_tbl);
13132	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13133	    bwn_tabl_iqlocal_tbl);
13134	if (mac->mac_phy.rev == 0) {
13135		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13136		    ofdmcckgain_r0);
13137		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13138		    ofdmcckgain_r0);
13139	} else {
13140		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13141		    ofdmcckgain_r1);
13142		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13143		    ofdmcckgain_r1);
13144	}
13145	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13146	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13147}
13148
13149static void
13150bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13151{
13152	struct siba_dev_softc *sd = mac->mac_sd;
13153	struct siba_softc *siba = sd->sd_bus;
13154	int i;
13155	static const uint16_t noisescale[] = {
13156		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13157		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13158		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13159		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13160		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13161		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13162		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13163	};
13164	static const uint32_t filterctl[] = {
13165		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13166		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13167	};
13168	static const uint32_t psctl[] = {
13169		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13170		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13171		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13172		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13173	};
13174	static const uint32_t gainidx[] = {
13175		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13176		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13177		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13178		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13179		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13180		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13181		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13182		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13183		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13184		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13185		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13186		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13187		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13188		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13189		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13190		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13191		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13192		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13193		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13194		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13195		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13196		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13197		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13198		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13199		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13200		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13201		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13202		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13203		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13204		0x0000001a, 0x64ca55ad, 0x0000001a
13205	};
13206	static const uint16_t auxgainidx[] = {
13207		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13208		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13209		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13210		0x0004, 0x0016
13211	};
13212	static const uint16_t swctl[] = {
13213		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13214		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13215		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13216		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13217		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13218		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13219		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13220		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13221	};
13222	static const uint8_t hf[] = {
13223		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13224		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13225	};
13226	static const uint32_t gainval[] = {
13227		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13228		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13229		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13230		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13231		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13232		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13233		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13234		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13235		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13236		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13237		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13238		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13239		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13240		0x000000f1, 0x00000000, 0x00000000
13241	};
13242	static const uint16_t gain[] = {
13243		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13244		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13245		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13246		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13247		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13248		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13249		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13250		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13251		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13252		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13253		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13254		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13255	};
13256	static const uint32_t papdeps[] = {
13257		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13258		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13259		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13260		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13261		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13262		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13263		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13264		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13265		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13266		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13267		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13268		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13269		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13270	};
13271	static const uint32_t papdmult[] = {
13272		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13273		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13274		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13275		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13276		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13277		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13278		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13279		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13280		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13281		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13282		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13283		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13284		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13285	};
13286	static const uint32_t gainidx_a0[] = {
13287		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13288		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13289		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13290		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13291		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13292		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13293		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13294		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13295		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13296		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13297		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13298		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13299		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13300	};
13301	static const uint16_t auxgainidx_a0[] = {
13302		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13303		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13304		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13305		0x0002, 0x0014
13306	};
13307	static const uint32_t gainval_a0[] = {
13308		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13309		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13310		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13311		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13312		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13313		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13314		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13315		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13316		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13317		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13318		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13319		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13320		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13321		0x000000f7, 0x00000000, 0x00000000
13322	};
13323	static const uint16_t gain_a0[] = {
13324		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13325		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13326		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13327		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13328		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13329		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13330		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13331		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13332		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13333		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13334		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13335		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13336	};
13337
13338	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13339
13340	for (i = 0; i < 704; i++)
13341		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13342
13343	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13344	    bwn_tab_sigsq_tbl);
13345	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13346	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13347	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13348	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13349	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13350	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13351	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13352	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13353	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13354	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13355	    bwn_tab_pllfrac_tbl);
13356	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13357	    bwn_tabl_iqlocal_tbl);
13358	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13359	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13360
13361	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
13362		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13363		    gainidx_a0);
13364		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13365		    auxgainidx_a0);
13366		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13367		    gainval_a0);
13368		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13369	}
13370}
13371
13372static void
13373bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13374{
13375	struct siba_dev_softc *sd = mac->mac_sd;
13376	struct siba_softc *siba = sd->sd_bus;
13377	struct bwn_softc *sc = mac->mac_sc;
13378	struct ifnet *ifp = sc->sc_ifp;
13379	struct ieee80211com *ic = ifp->if_l2com;
13380	static struct bwn_txgain_entry txgain_r2[] = {
13381		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13382		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13383		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13384		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13385		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13386		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13387		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13388		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13389		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13390		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13391		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13392		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13393		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13394		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13395		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13396		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13397		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13398		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13399		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13400		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13401		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13402		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13403		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13404		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13405		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13406		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13407		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13408		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13409		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13410		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13411		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13412		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13413		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13414		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13415		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13416		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13417		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13418		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13419		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13420		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13421		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13422		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13423		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13424		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13425		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13426		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13427		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13428		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13429		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13430		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13431		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13432		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13433		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13434		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13435		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13436		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13437		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13438		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13439		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13440		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13441		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13442		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13443		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13444		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13445	};
13446	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13447		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13448		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13449		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13450		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13451		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13452		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13453		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13454		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13455		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13456		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13457		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13458		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13459		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13460		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13461		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13462		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13463		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13464		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13465		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13466		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13467		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13468		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13469		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13470		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13471		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13472		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13473		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13474		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13475		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13476		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13477		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13478		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13479		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13480		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13481		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13482		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13483		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13484		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13485		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13486		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13487		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13488		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13489		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13490		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13491		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13492		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13493		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13494		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13495		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13496		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13497		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13498		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13499		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13500		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13501		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13502		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13503		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13504		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13505		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13506		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13507		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13508		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13509		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13510		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13511	};
13512	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13513		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13514		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13515		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13516		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13517		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13518		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13519		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13520		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13521		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13522		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13523		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13524		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13525		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13526		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13527		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13528		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13529		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13530		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13531		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13532		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13533		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13534		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13535		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13536		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13537		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13538		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13539		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13540		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13541		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13542		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13543		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13544		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13545		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13546		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13547		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13548		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13549		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13550		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13551		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13552		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13553		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13554		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13555		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13556		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13557		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13558		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13559		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13560		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13561		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13562		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13563		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13564		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13565		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13566		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13567		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13568		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13569		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13570		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13571		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13572		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13573		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13574		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13575		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13576		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13577	};
13578	static struct bwn_txgain_entry txgain_r0[] = {
13579		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13580		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13581		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13582		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13583		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13584		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13585		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13586		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13587		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13588		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13589		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13590		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13591		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13592		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13593		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13594		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13595		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13596		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13597		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13598		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13599		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13600		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13601		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13602		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13603		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13604		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13605		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13606		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13607		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13608		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13609		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13610		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13611		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13612		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13613		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13614		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13615		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13616		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13617		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13618		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13619		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13620		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13621		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13622		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13623		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13624		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13625		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13626		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13627		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13628		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13629		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13630		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13631		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13632		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13633		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13634		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13635		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13636		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13637		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13638		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13639		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13640		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13641		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13642		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13643	};
13644	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13645		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13646		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13647		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13648		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13649		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13650		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13651		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13652		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13653		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13654		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13655		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13656		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13657		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13658		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13659		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13660		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13661		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13662		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13663		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13664		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13665		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13666		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13667		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13668		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13669		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13670		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13671		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13672		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13673		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13674		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13675		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13676		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13677		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13678		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13679		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13680		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13681		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13682		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13683		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13684		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13685		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13686		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13687		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13688		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13689		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13690		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13691		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13692		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13693		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13694		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13695		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13696		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13697		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13698		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13699		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13700		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13701		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13702		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13703		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13704		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13705		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13706		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13707		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13708		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13709	};
13710	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13711		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13712		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13713		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13714		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13715		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13716		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13717		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13718		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13719		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13720		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13721		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13722		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13723		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13724		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13725		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13726		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13727		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13728		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13729		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13730		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13731		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13732		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13733		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13734		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13735		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13736		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13737		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13738		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13739		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13740		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13741		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13742		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13743		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13744		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13745		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13746		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13747		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13748		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13749		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13750		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13751		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13752		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13753		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13754		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13755		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13756		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13757		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13758		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13759		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13760		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13761		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13762		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13763		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13764		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13765		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13766		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13767		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13768		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13769		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13770		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13771		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13772		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13773		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13774		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13775	};
13776	static struct bwn_txgain_entry txgain_r1[] = {
13777		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13778		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13779		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13780		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13781		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13782		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13783		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13784		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13785		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13786		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13787		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13788		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13789		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13790		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13791		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13792		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13793		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13794		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13795		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13796		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13797		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13798		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13799		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13800		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13801		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13802		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13803		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13804		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13805		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13806		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13807		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13808		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13809		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13810		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13811		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13812		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13813		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13814		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13815		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13816		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13817		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13818		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13819		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13820		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13821		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13822		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13823		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13824		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13825		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13826		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13827		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13828		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13829		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13830		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13831		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13832		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13833		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13834		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13835		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13836		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13837		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13838		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13839		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13840		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13841		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13842		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13843		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13844		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13845		{ 7, 11, 6, 0, 71 }
13846	};
13847	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13848		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13849		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13850		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13851		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13852		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13853		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13854		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13855		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13856		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13857		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13858		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13859		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13860		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13861		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13862		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13863		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13864		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13865		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13866		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13867		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13868		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13869		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13870		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13871		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13872		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13873		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13874		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13875		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13876		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13877		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13878		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13879		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13880		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13881		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13882		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13883		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13884		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13885		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13886		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13887		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13888		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13889		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13890		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13891		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13892		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13893		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13894		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13895		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13896		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13897		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13898		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13899		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13900		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13901		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13902		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13903		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13904		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13905		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13906		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13907		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13908		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13909		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13910		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13911		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13912	};
13913	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13914		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13915		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13916		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13917		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13918		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13919		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13920		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13921		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13922		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13923		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13924		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13925		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13926		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13927		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13928		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13929		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13930		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13931		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13932		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13933		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13934		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13935		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13936		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13937		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13938		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13939		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13940		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13941		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13942		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13943		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13944		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13945		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13946		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13947		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13948		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13949		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13950		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13951		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13952		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13953		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13954		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13955		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13956		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13957		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13958		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13959		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13960		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13961		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13962		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13963		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13964		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13965		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13966		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13967		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13968		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13969		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13970		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13971		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13972		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13973		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13974		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13975		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13976		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13977		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13978	};
13979
13980	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13981		if (siba->siba_sprom.bf_hi & BWN_BFH_NOPA)
13982			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13983		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13984			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13985			    txgain_2ghz_r2);
13986		else
13987			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13988			    txgain_5ghz_r2);
13989		return;
13990	}
13991
13992	if (mac->mac_phy.rev == 0) {
13993		if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
13994		    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
13995			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13996		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13997			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13998			    txgain_2ghz_r0);
13999		else
14000			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
14001			    txgain_5ghz_r0);
14002		return;
14003	}
14004
14005	if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
14006	    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
14007		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
14008	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
14009		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
14010	else
14011		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
14012}
14013
14014static void
14015bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
14016{
14017	uint32_t offset, type;
14018
14019	type = BWN_TAB_GETTYPE(typeoffset);
14020	offset = BWN_TAB_GETOFFSET(typeoffset);
14021	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14022
14023	switch (type) {
14024	case BWN_TAB_8BIT:
14025		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
14026		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14027		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14028		break;
14029	case BWN_TAB_16BIT:
14030		KASSERT(!(value & ~0xffff),
14031		    ("%s:%d: fail", __func__, __LINE__));
14032		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14033		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14034		break;
14035	case BWN_TAB_32BIT:
14036		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14037		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
14038		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14039		break;
14040	default:
14041		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14042	}
14043}
14044
14045static int
14046bwn_phy_lp_loopback(struct bwn_mac *mac)
14047{
14048	struct bwn_phy_lp_iq_est ie;
14049	int i, index = -1;
14050	uint32_t tmp;
14051
14052	memset(&ie, 0, sizeof(ie));
14053
14054	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14055	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14056	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14057	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14058	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14059	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14060	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14061	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14062	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14063	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14064	for (i = 0; i < 32; i++) {
14065		bwn_phy_lp_set_rxgain_idx(mac, i);
14066		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14067		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14068			continue;
14069		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14070		if ((tmp > 4000) && (tmp < 10000)) {
14071			index = i;
14072			break;
14073		}
14074	}
14075	bwn_phy_lp_ddfs_turnoff(mac);
14076	return (index);
14077}
14078
14079static void
14080bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14081{
14082
14083	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14084}
14085
14086static void
14087bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14088    int incr1, int incr2, int scale_idx)
14089{
14090
14091	bwn_phy_lp_ddfs_turnoff(mac);
14092	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14093	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14094	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14095	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14096	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14097	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14098	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14099	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14100	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14101	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14102}
14103
14104static uint8_t
14105bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14106    struct bwn_phy_lp_iq_est *ie)
14107{
14108	int i;
14109
14110	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14111	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14112	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14113	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14114	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14115
14116	for (i = 0; i < 500; i++) {
14117		if (!(BWN_PHY_READ(mac,
14118		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14119			break;
14120		DELAY(1000);
14121	}
14122	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14123		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14124		return 0;
14125	}
14126
14127	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14128	ie->ie_iqprod <<= 16;
14129	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14130	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14131	ie->ie_ipwr <<= 16;
14132	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14133	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14134	ie->ie_qpwr <<= 16;
14135	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14136
14137	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14138	return 1;
14139}
14140
14141static uint32_t
14142bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14143{
14144	uint32_t offset, type, value;
14145
14146	type = BWN_TAB_GETTYPE(typeoffset);
14147	offset = BWN_TAB_GETOFFSET(typeoffset);
14148	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14149
14150	switch (type) {
14151	case BWN_TAB_8BIT:
14152		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14153		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14154		break;
14155	case BWN_TAB_16BIT:
14156		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14157		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14158		break;
14159	case BWN_TAB_32BIT:
14160		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14161		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14162		value <<= 16;
14163		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14164		break;
14165	default:
14166		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14167		value = 0;
14168	}
14169
14170	return (value);
14171}
14172
14173static void
14174bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14175{
14176
14177	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14178	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14179}
14180
14181static void
14182bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14183{
14184	uint16_t ctl;
14185
14186	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14187	ctl |= dac << 7;
14188	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14189}
14190
14191static void
14192bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14193{
14194
14195	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14196	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14197}
14198
14199static void
14200bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14201{
14202
14203	if (mac->mac_phy.rev < 2)
14204		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14205	else {
14206		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14207		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14208	}
14209	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14210}
14211
14212static uint16_t
14213bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14214{
14215
14216	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14217}
14218
14219static uint8_t
14220bwn_nbits(int32_t val)
14221{
14222	uint32_t tmp;
14223	uint8_t nbits = 0;
14224
14225	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14226		nbits++;
14227	return (nbits);
14228}
14229
14230static void
14231bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14232    struct bwn_txgain_entry *table)
14233{
14234	int i;
14235
14236	for (i = offset; i < count; i++)
14237		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14238}
14239
14240static void
14241bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14242    struct bwn_txgain_entry data)
14243{
14244
14245	if (mac->mac_phy.rev >= 2)
14246		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14247	else
14248		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14249}
14250
14251static void
14252bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14253    struct bwn_txgain_entry te)
14254{
14255	struct bwn_softc *sc = mac->mac_sc;
14256	struct ifnet *ifp = sc->sc_ifp;
14257	struct ieee80211com *ic = ifp->if_l2com;
14258	uint32_t tmp;
14259
14260	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14261
14262	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14263	if (mac->mac_phy.rev >= 3) {
14264		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14265		    (0x10 << 24) : (0x70 << 24));
14266	} else {
14267		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14268		    (0x14 << 24) : (0x7f << 24));
14269	}
14270	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14271	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14272	    te.te_bbmult << 20 | te.te_dac << 28);
14273}
14274
14275static void
14276bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14277    struct bwn_txgain_entry te)
14278{
14279
14280	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14281
14282	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14283	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14284	    te.te_dac);
14285	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14286}
14287
14288static void
14289bwn_identify(driver_t *driver, device_t parent)
14290{
14291
14292	BUS_ADD_CHILD(parent, 0, "bwn", -1);
14293}
14294
14295static device_method_t bwn_methods[] = {
14296	/* Device interface */
14297	DEVMETHOD(device_identify,	bwn_identify),
14298	DEVMETHOD(device_probe,		bwn_probe),
14299	DEVMETHOD(device_attach,	bwn_attach),
14300	DEVMETHOD(device_detach,	bwn_detach),
14301	DEVMETHOD(device_suspend,	bwn_suspend),
14302	DEVMETHOD(device_resume,	bwn_resume),
14303	{ 0,0 }
14304};
14305static driver_t bwn_driver = {
14306	"bwn",
14307	bwn_methods,
14308	sizeof(struct bwn_softc)
14309};
14310static devclass_t bwn_devclass;
14311DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14312MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14313MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14314MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14315MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14316