if_bwn.c revision 286410
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 286410 2015-08-07 11:43:14Z glebius $");
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_var.h>
56#include <net/if_arp.h>
57#include <net/if_dl.h>
58#include <net/if_llc.h>
59#include <net/if_media.h>
60#include <net/if_types.h>
61
62#include <dev/pci/pcivar.h>
63#include <dev/pci/pcireg.h>
64#include <dev/siba/siba_ids.h>
65#include <dev/siba/sibareg.h>
66#include <dev/siba/sibavar.h>
67
68#include <net80211/ieee80211_var.h>
69#include <net80211/ieee80211_radiotap.h>
70#include <net80211/ieee80211_regdomain.h>
71#include <net80211/ieee80211_phy.h>
72#include <net80211/ieee80211_ratectl.h>
73
74#include <dev/bwn/if_bwnreg.h>
75#include <dev/bwn/if_bwnvar.h>
76
77static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
78    "Broadcom driver parameters");
79
80/*
81 * Tunable & sysctl variables.
82 */
83
84#ifdef BWN_DEBUG
85static	int bwn_debug = 0;
86SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
87    "Broadcom debugging printfs");
88enum {
89	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
90	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
91	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
92	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
93	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
94	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
95	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
96	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
97	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
98	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
99	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
100	BWN_DEBUG_LED		= 0x00000800,	/* led management */
101	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
102	BWN_DEBUG_LO		= 0x00002000,	/* LO */
103	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
104	BWN_DEBUG_WME		= 0x00008000,	/* WME */
105	BWN_DEBUG_RF		= 0x00010000,	/* RF */
106	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
107	BWN_DEBUG_ANY		= 0xffffffff
108};
109#define	DPRINTF(sc, m, fmt, ...) do {			\
110	if (sc->sc_debug & (m))				\
111		printf(fmt, __VA_ARGS__);		\
112} while (0)
113#else
114#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
115#endif
116
117static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
118SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
119    "uses Bad Frames Preemption");
120static int	bwn_bluetooth = 1;
121SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
122    "turns on Bluetooth Coexistence");
123static int	bwn_hwpctl = 0;
124SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
125    "uses H/W power control");
126static int	bwn_msi_disable = 0;		/* MSI disabled  */
127TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
128static int	bwn_usedma = 1;
129SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
130    "uses DMA");
131TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
132static int	bwn_wme = 1;
133SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
134    "uses WME support");
135
136static void	bwn_attach_pre(struct bwn_softc *);
137static int	bwn_attach_post(struct bwn_softc *);
138static void	bwn_sprom_bugfixes(device_t);
139static int	bwn_init(struct bwn_softc *);
140static void	bwn_parent(struct ieee80211com *);
141static void	bwn_start(struct bwn_softc *);
142static int	bwn_transmit(struct ieee80211com *, struct mbuf *);
143static int	bwn_attach_core(struct bwn_mac *);
144static void	bwn_reset_core(struct bwn_mac *, uint32_t);
145static int	bwn_phy_getinfo(struct bwn_mac *, int);
146static int	bwn_chiptest(struct bwn_mac *);
147static int	bwn_setup_channels(struct bwn_mac *, int, int);
148static int	bwn_phy_g_attach(struct bwn_mac *);
149static void	bwn_phy_g_detach(struct bwn_mac *);
150static void	bwn_phy_g_init_pre(struct bwn_mac *);
151static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
152static int	bwn_phy_g_init(struct bwn_mac *);
153static void	bwn_phy_g_exit(struct bwn_mac *);
154static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
155static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
156		    uint16_t);
157static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
158static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
159		    uint16_t);
160static int	bwn_phy_g_hwpctl(struct bwn_mac *);
161static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
162static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
163static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
164static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
165static int	bwn_phy_g_im(struct bwn_mac *, int);
166static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
167static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
168static void	bwn_phy_g_task_15s(struct bwn_mac *);
169static void	bwn_phy_g_task_60s(struct bwn_mac *);
170static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
171static void	bwn_phy_switch_analog(struct bwn_mac *, int);
172static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
173static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
174		    uint16_t);
175static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
176static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
177		    uint32_t);
178static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
179		    uint16_t);
180static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
181		    const struct bwn_channelinfo *, int);
182static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
183		    const struct ieee80211_bpf_params *);
184static void	bwn_updateslot(struct ieee80211com *);
185static void	bwn_update_promisc(struct ieee80211com *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static void	bwn_wme_clear(struct bwn_softc *);
189static void	bwn_wme_load(struct bwn_mac *);
190static void	bwn_wme_loadparams(struct bwn_mac *,
191		    const struct wmeParams *, uint16_t);
192static void	bwn_scan_start(struct ieee80211com *);
193static void	bwn_scan_end(struct ieee80211com *);
194static void	bwn_set_channel(struct ieee80211com *);
195static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
196		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
197		    const uint8_t [IEEE80211_ADDR_LEN],
198		    const uint8_t [IEEE80211_ADDR_LEN]);
199static void	bwn_vap_delete(struct ieee80211vap *);
200static void	bwn_stop(struct bwn_softc *);
201static int	bwn_core_init(struct bwn_mac *);
202static void	bwn_core_start(struct bwn_mac *);
203static void	bwn_core_exit(struct bwn_mac *);
204static void	bwn_bt_disable(struct bwn_mac *);
205static int	bwn_chip_init(struct bwn_mac *);
206static uint64_t	bwn_hf_read(struct bwn_mac *);
207static void	bwn_hf_write(struct bwn_mac *, uint64_t);
208static void	bwn_set_txretry(struct bwn_mac *, int, int);
209static void	bwn_rate_init(struct bwn_mac *);
210static void	bwn_set_phytxctl(struct bwn_mac *);
211static void	bwn_spu_setdelay(struct bwn_mac *, int);
212static void	bwn_bt_enable(struct bwn_mac *);
213static void	bwn_set_macaddr(struct bwn_mac *);
214static void	bwn_crypt_init(struct bwn_mac *);
215static void	bwn_chip_exit(struct bwn_mac *);
216static int	bwn_fw_fillinfo(struct bwn_mac *);
217static int	bwn_fw_loaducode(struct bwn_mac *);
218static int	bwn_gpio_init(struct bwn_mac *);
219static int	bwn_fw_loadinitvals(struct bwn_mac *);
220static int	bwn_phy_init(struct bwn_mac *);
221static void	bwn_set_txantenna(struct bwn_mac *, int);
222static void	bwn_set_opmode(struct bwn_mac *);
223static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
224static uint8_t	bwn_plcp_getcck(const uint8_t);
225static uint8_t	bwn_plcp_getofdm(const uint8_t);
226static void	bwn_pio_init(struct bwn_mac *);
227static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
228static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
229		    int);
230static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
231		    struct bwn_pio_rxqueue *, int);
232static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
233static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
234		    uint16_t);
235static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
236static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
237static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
238static void	bwn_pio_handle_txeof(struct bwn_mac *,
239		    const struct bwn_txstatus *);
240static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
241static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
242static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
243		    uint16_t);
244static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
245		    uint32_t);
246static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
247		    struct mbuf *);
248static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
249static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
250		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
251static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
252		    uint16_t, uint32_t);
253static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
254		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
255static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
256		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
257static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
258		    uint16_t, struct bwn_pio_txpkt **);
259static void	bwn_dma_init(struct bwn_mac *);
260static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
261static int	bwn_dma_mask2type(uint64_t);
262static uint64_t	bwn_dma_mask(struct bwn_mac *);
263static uint16_t	bwn_dma_base(int, int);
264static void	bwn_dma_ringfree(struct bwn_dma_ring **);
265static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
266		    int, struct bwn_dmadesc_generic **,
267		    struct bwn_dmadesc_meta **);
268static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
269		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
270		    int, int);
271static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
272static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
273static void	bwn_dma_32_resume(struct bwn_dma_ring *);
274static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
275static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
276static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
277		    int, struct bwn_dmadesc_generic **,
278		    struct bwn_dmadesc_meta **);
279static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
280		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
281		    int, int);
282static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
283static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
284static void	bwn_dma_64_resume(struct bwn_dma_ring *);
285static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
286static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
287static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
288static void	bwn_dma_setup(struct bwn_dma_ring *);
289static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
290static void	bwn_dma_cleanup(struct bwn_dma_ring *);
291static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
292static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
293static void	bwn_dma_rx(struct bwn_dma_ring *);
294static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
295static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
296		    struct bwn_dmadesc_meta *);
297static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
298static int	bwn_dma_gettype(struct bwn_mac *);
299static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
300static int	bwn_dma_freeslot(struct bwn_dma_ring *);
301static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
302static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
303static int	bwn_dma_newbuf(struct bwn_dma_ring *,
304		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
305		    int);
306static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
307		    bus_size_t, int);
308static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
309static void	bwn_dma_handle_txeof(struct bwn_mac *,
310		    const struct bwn_txstatus *);
311static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
312		    struct mbuf *);
313static int	bwn_dma_getslot(struct bwn_dma_ring *);
314static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
315		    uint8_t);
316static int	bwn_dma_attach(struct bwn_mac *);
317static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
318		    int, int, int);
319static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
320		    const struct bwn_txstatus *, uint16_t, int *);
321static void	bwn_dma_free(struct bwn_mac *);
322static void	bwn_phy_g_init_sub(struct bwn_mac *);
323static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
324static void	bwn_phy_init_b5(struct bwn_mac *);
325static void	bwn_phy_init_b6(struct bwn_mac *);
326static void	bwn_phy_init_a(struct bwn_mac *);
327static void	bwn_loopback_calcgain(struct bwn_mac *);
328static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
329static void	bwn_lo_g_init(struct bwn_mac *);
330static void	bwn_lo_g_adjust(struct bwn_mac *);
331static void	bwn_lo_get_powervector(struct bwn_mac *);
332static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
333		    const struct bwn_bbatt *, const struct bwn_rfatt *);
334static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
335static void	bwn_phy_hwpctl_init(struct bwn_mac *);
336static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
337static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
338		    const struct bwn_bbatt *, const struct bwn_rfatt *,
339		    uint8_t);
340static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
341static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
342static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
343static void	bwn_wa_init(struct bwn_mac *);
344static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
345		    uint16_t);
346static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
347static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
348		    uint32_t);
349static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
350		    uint16_t);
351static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
352static void	bwn_mac_suspend(struct bwn_mac *);
353static void	bwn_mac_enable(struct bwn_mac *);
354static void	bwn_psctl(struct bwn_mac *, uint32_t);
355static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
356static void	bwn_nrssi_offset(struct bwn_mac *);
357static void	bwn_nrssi_threshold(struct bwn_mac *);
358static void	bwn_nrssi_slope_11g(struct bwn_mac *);
359static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
360		    int16_t);
361static void	bwn_set_original_gains(struct bwn_mac *);
362static void	bwn_hwpctl_early_init(struct bwn_mac *);
363static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
364static uint16_t	bwn_phy_g_chan2freq(uint8_t);
365static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
366static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
367		    const char *, struct bwn_fwfile *);
368static void	bwn_release_firmware(struct bwn_mac *);
369static void	bwn_do_release_fw(struct bwn_fwfile *);
370static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
371static int	bwn_fwinitvals_write(struct bwn_mac *,
372		    const struct bwn_fwinitvals *, size_t, size_t);
373static int	bwn_switch_channel(struct bwn_mac *, int);
374static uint16_t	bwn_ant2phy(int);
375static void	bwn_mac_write_bssid(struct bwn_mac *);
376static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
377		    const uint8_t *);
378static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
379		    const uint8_t *, size_t, const uint8_t *);
380static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
381		    const uint8_t *);
382static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
383		    const uint8_t *);
384static void	bwn_phy_exit(struct bwn_mac *);
385static void	bwn_core_stop(struct bwn_mac *);
386static int	bwn_switch_band(struct bwn_softc *,
387		    struct ieee80211_channel *);
388static void	bwn_phy_reset(struct bwn_mac *);
389static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
390static void	bwn_set_pretbtt(struct bwn_mac *);
391static int	bwn_intr(void *);
392static void	bwn_intrtask(void *, int);
393static void	bwn_restart(struct bwn_mac *, const char *);
394static void	bwn_intr_ucode_debug(struct bwn_mac *);
395static void	bwn_intr_tbtt_indication(struct bwn_mac *);
396static void	bwn_intr_atim_end(struct bwn_mac *);
397static void	bwn_intr_beacon(struct bwn_mac *);
398static void	bwn_intr_pmq(struct bwn_mac *);
399static void	bwn_intr_noise(struct bwn_mac *);
400static void	bwn_intr_txeof(struct bwn_mac *);
401static void	bwn_hwreset(void *, int);
402static void	bwn_handle_fwpanic(struct bwn_mac *);
403static void	bwn_load_beacon0(struct bwn_mac *);
404static void	bwn_load_beacon1(struct bwn_mac *);
405static uint32_t	bwn_jssi_read(struct bwn_mac *);
406static void	bwn_noise_gensample(struct bwn_mac *);
407static void	bwn_handle_txeof(struct bwn_mac *,
408		    const struct bwn_txstatus *);
409static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
410static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
411static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
412		    struct mbuf *);
413static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
414static int	bwn_set_txhdr(struct bwn_mac *,
415		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
416		    uint16_t);
417static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
418		    const uint8_t);
419static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
420static uint8_t	bwn_get_fbrate(uint8_t);
421static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
422static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
423static void	bwn_phy_lock(struct bwn_mac *);
424static void	bwn_phy_unlock(struct bwn_mac *);
425static void	bwn_rf_lock(struct bwn_mac *);
426static void	bwn_rf_unlock(struct bwn_mac *);
427static void	bwn_txpwr(void *, int);
428static void	bwn_tasks(void *);
429static void	bwn_task_15s(struct bwn_mac *);
430static void	bwn_task_30s(struct bwn_mac *);
431static void	bwn_task_60s(struct bwn_mac *);
432static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
433		    uint8_t);
434static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
435static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
436		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
437		    int, int);
438static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
439static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
440static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
441static void	bwn_watchdog(void *);
442static void	bwn_dma_stop(struct bwn_mac *);
443static void	bwn_pio_stop(struct bwn_mac *);
444static void	bwn_dma_ringstop(struct bwn_dma_ring **);
445static void	bwn_led_attach(struct bwn_mac *);
446static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
447static void	bwn_led_event(struct bwn_mac *, int);
448static void	bwn_led_blink_start(struct bwn_mac *, int, int);
449static void	bwn_led_blink_next(void *);
450static void	bwn_led_blink_end(void *);
451static void	bwn_rfswitch(void *);
452static void	bwn_rf_turnon(struct bwn_mac *);
453static void	bwn_rf_turnoff(struct bwn_mac *);
454static void	bwn_phy_lp_init_pre(struct bwn_mac *);
455static int	bwn_phy_lp_init(struct bwn_mac *);
456static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
457static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
458static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
459		    uint16_t);
460static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
461static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
462static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
463static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
464static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
465static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
466static void	bwn_phy_lp_task_60s(struct bwn_mac *);
467static void	bwn_phy_lp_readsprom(struct bwn_mac *);
468static void	bwn_phy_lp_bbinit(struct bwn_mac *);
469static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
470static void	bwn_phy_lp_calib(struct bwn_mac *);
471static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
472static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
473static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
474static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
475static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
476static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
477static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
478static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
479static void	bwn_phy_lp_bugfix(struct bwn_mac *);
480static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
481static void	bwn_phy_lp_tblinit(struct bwn_mac *);
482static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
483static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
484static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
485static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
486static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
487static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
488static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
489static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
490static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
491static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
492static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
493		    const void *);
494static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
495static struct bwn_txgain
496		bwn_phy_lp_get_txgain(struct bwn_mac *);
497static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
498static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
499static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
500static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
501static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
502static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
503static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
504static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
505static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
506static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
507static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
508static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
509static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
510static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
511static int	bwn_phy_lp_loopback(struct bwn_mac *);
512static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
513static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
514		    int);
515static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
516		    struct bwn_phy_lp_iq_est *);
517static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
518static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
519static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
520static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
521static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
522static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
523static uint8_t	bwn_nbits(int32_t);
524static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
525		    struct bwn_txgain_entry *);
526static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
527		    struct bwn_txgain_entry);
528static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
529		    struct bwn_txgain_entry);
530static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
531		    struct bwn_txgain_entry);
532static void	bwn_sysctl_node(struct bwn_softc *);
533
534static struct resource_spec bwn_res_spec_legacy[] = {
535	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
536	{ -1,			0,		0 }
537};
538
539static struct resource_spec bwn_res_spec_msi[] = {
540	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
541	{ -1,			0,		0 }
542};
543
544static const struct bwn_channelinfo bwn_chantable_bg = {
545	.channels = {
546		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
547		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
548		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
549		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
550		{ 2472, 13, 30 }, { 2484, 14, 30 } },
551	.nchannels = 14
552};
553
554static const struct bwn_channelinfo bwn_chantable_a = {
555	.channels = {
556		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
557		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
558		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
559		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
560		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
561		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
562		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
563		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
564		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
565		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
566		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
567		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
568		{ 6080, 216, 30 } },
569	.nchannels = 37
570};
571
572static const struct bwn_channelinfo bwn_chantable_n = {
573	.channels = {
574		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
575		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
576		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
577		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
578		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
579		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
580		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
581		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
582		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
583		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
584		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
585		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
586		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
587		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
588		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
589		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
590		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
591		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
592		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
593		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
594		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
595		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
596		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
597		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
598		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
599		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
600		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
601		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
602		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
603		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
604		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
605		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
606		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
607		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
608		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
609		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
610		{ 6130, 226, 30 }, { 6140, 228, 30 } },
611	.nchannels = 110
612};
613
614static const uint8_t bwn_b2063_chantable_data[33][12] = {
615	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
616	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
617	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
621	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
622	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
623	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
624	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
625	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
626	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
627	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
628	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
629	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
630	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
631	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
632	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
633	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
634	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
635	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
636	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
637	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
638	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
640	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
641	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
642	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
643	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
644	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
646	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
647	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
648};
649
650static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
651	{ 1, 2412, bwn_b2063_chantable_data[0] },
652	{ 2, 2417, bwn_b2063_chantable_data[0] },
653	{ 3, 2422, bwn_b2063_chantable_data[0] },
654	{ 4, 2427, bwn_b2063_chantable_data[1] },
655	{ 5, 2432, bwn_b2063_chantable_data[1] },
656	{ 6, 2437, bwn_b2063_chantable_data[1] },
657	{ 7, 2442, bwn_b2063_chantable_data[1] },
658	{ 8, 2447, bwn_b2063_chantable_data[1] },
659	{ 9, 2452, bwn_b2063_chantable_data[2] },
660	{ 10, 2457, bwn_b2063_chantable_data[2] },
661	{ 11, 2462, bwn_b2063_chantable_data[3] },
662	{ 12, 2467, bwn_b2063_chantable_data[3] },
663	{ 13, 2472, bwn_b2063_chantable_data[3] },
664	{ 14, 2484, bwn_b2063_chantable_data[4] },
665	{ 34, 5170, bwn_b2063_chantable_data[5] },
666	{ 36, 5180, bwn_b2063_chantable_data[6] },
667	{ 38, 5190, bwn_b2063_chantable_data[7] },
668	{ 40, 5200, bwn_b2063_chantable_data[8] },
669	{ 42, 5210, bwn_b2063_chantable_data[9] },
670	{ 44, 5220, bwn_b2063_chantable_data[10] },
671	{ 46, 5230, bwn_b2063_chantable_data[11] },
672	{ 48, 5240, bwn_b2063_chantable_data[12] },
673	{ 52, 5260, bwn_b2063_chantable_data[13] },
674	{ 56, 5280, bwn_b2063_chantable_data[14] },
675	{ 60, 5300, bwn_b2063_chantable_data[14] },
676	{ 64, 5320, bwn_b2063_chantable_data[15] },
677	{ 100, 5500, bwn_b2063_chantable_data[16] },
678	{ 104, 5520, bwn_b2063_chantable_data[17] },
679	{ 108, 5540, bwn_b2063_chantable_data[18] },
680	{ 112, 5560, bwn_b2063_chantable_data[19] },
681	{ 116, 5580, bwn_b2063_chantable_data[20] },
682	{ 120, 5600, bwn_b2063_chantable_data[21] },
683	{ 124, 5620, bwn_b2063_chantable_data[21] },
684	{ 128, 5640, bwn_b2063_chantable_data[22] },
685	{ 132, 5660, bwn_b2063_chantable_data[22] },
686	{ 136, 5680, bwn_b2063_chantable_data[22] },
687	{ 140, 5700, bwn_b2063_chantable_data[23] },
688	{ 149, 5745, bwn_b2063_chantable_data[23] },
689	{ 153, 5765, bwn_b2063_chantable_data[23] },
690	{ 157, 5785, bwn_b2063_chantable_data[23] },
691	{ 161, 5805, bwn_b2063_chantable_data[23] },
692	{ 165, 5825, bwn_b2063_chantable_data[23] },
693	{ 184, 4920, bwn_b2063_chantable_data[24] },
694	{ 188, 4940, bwn_b2063_chantable_data[25] },
695	{ 192, 4960, bwn_b2063_chantable_data[26] },
696	{ 196, 4980, bwn_b2063_chantable_data[27] },
697	{ 200, 5000, bwn_b2063_chantable_data[28] },
698	{ 204, 5020, bwn_b2063_chantable_data[29] },
699	{ 208, 5040, bwn_b2063_chantable_data[30] },
700	{ 212, 5060, bwn_b2063_chantable_data[31] },
701	{ 216, 5080, bwn_b2063_chantable_data[32] }
702};
703
704static const uint8_t bwn_b2062_chantable_data[22][12] = {
705	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
706	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
707	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
708	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
719	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
720	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
726	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
727};
728
729static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
730	{ 1, 2412, bwn_b2062_chantable_data[0] },
731	{ 2, 2417, bwn_b2062_chantable_data[0] },
732	{ 3, 2422, bwn_b2062_chantable_data[0] },
733	{ 4, 2427, bwn_b2062_chantable_data[0] },
734	{ 5, 2432, bwn_b2062_chantable_data[0] },
735	{ 6, 2437, bwn_b2062_chantable_data[0] },
736	{ 7, 2442, bwn_b2062_chantable_data[0] },
737	{ 8, 2447, bwn_b2062_chantable_data[0] },
738	{ 9, 2452, bwn_b2062_chantable_data[0] },
739	{ 10, 2457, bwn_b2062_chantable_data[0] },
740	{ 11, 2462, bwn_b2062_chantable_data[0] },
741	{ 12, 2467, bwn_b2062_chantable_data[0] },
742	{ 13, 2472, bwn_b2062_chantable_data[0] },
743	{ 14, 2484, bwn_b2062_chantable_data[0] },
744	{ 34, 5170, bwn_b2062_chantable_data[1] },
745	{ 38, 5190, bwn_b2062_chantable_data[2] },
746	{ 42, 5210, bwn_b2062_chantable_data[2] },
747	{ 46, 5230, bwn_b2062_chantable_data[3] },
748	{ 36, 5180, bwn_b2062_chantable_data[4] },
749	{ 40, 5200, bwn_b2062_chantable_data[5] },
750	{ 44, 5220, bwn_b2062_chantable_data[6] },
751	{ 48, 5240, bwn_b2062_chantable_data[3] },
752	{ 52, 5260, bwn_b2062_chantable_data[3] },
753	{ 56, 5280, bwn_b2062_chantable_data[3] },
754	{ 60, 5300, bwn_b2062_chantable_data[7] },
755	{ 64, 5320, bwn_b2062_chantable_data[8] },
756	{ 100, 5500, bwn_b2062_chantable_data[9] },
757	{ 104, 5520, bwn_b2062_chantable_data[10] },
758	{ 108, 5540, bwn_b2062_chantable_data[10] },
759	{ 112, 5560, bwn_b2062_chantable_data[10] },
760	{ 116, 5580, bwn_b2062_chantable_data[11] },
761	{ 120, 5600, bwn_b2062_chantable_data[12] },
762	{ 124, 5620, bwn_b2062_chantable_data[12] },
763	{ 128, 5640, bwn_b2062_chantable_data[12] },
764	{ 132, 5660, bwn_b2062_chantable_data[12] },
765	{ 136, 5680, bwn_b2062_chantable_data[12] },
766	{ 140, 5700, bwn_b2062_chantable_data[12] },
767	{ 149, 5745, bwn_b2062_chantable_data[12] },
768	{ 153, 5765, bwn_b2062_chantable_data[12] },
769	{ 157, 5785, bwn_b2062_chantable_data[12] },
770	{ 161, 5805, bwn_b2062_chantable_data[12] },
771	{ 165, 5825, bwn_b2062_chantable_data[12] },
772	{ 184, 4920, bwn_b2062_chantable_data[13] },
773	{ 188, 4940, bwn_b2062_chantable_data[14] },
774	{ 192, 4960, bwn_b2062_chantable_data[15] },
775	{ 196, 4980, bwn_b2062_chantable_data[16] },
776	{ 200, 5000, bwn_b2062_chantable_data[17] },
777	{ 204, 5020, bwn_b2062_chantable_data[18] },
778	{ 208, 5040, bwn_b2062_chantable_data[19] },
779	{ 212, 5060, bwn_b2062_chantable_data[20] },
780	{ 216, 5080, bwn_b2062_chantable_data[21] }
781};
782
783/* for LP PHY */
784static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
785	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
786	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
787	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
788	{ 13, -66, 13 }, { 14, -66, 13 },
789};
790
791/* for LP PHY */
792static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
793	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
794	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
795	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
796	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
797	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
798	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
799	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
800	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
801	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
802	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
803	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
804	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
805	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
806};
807
808static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
809
810static const uint8_t bwn_tab_sigsq_tbl[] = {
811	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
812	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
813	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
814	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
815	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
816	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
817};
818
819static const uint8_t bwn_tab_pllfrac_tbl[] = {
820	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
821	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
822};
823
824static const uint16_t bwn_tabl_iqlocal_tbl[] = {
825	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
826	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
827	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
828	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
829	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
830	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
831	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
832	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
833	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
835	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
836	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837};
838
839static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
840static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
841static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
842static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
843static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
844const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
845
846#define	VENDOR_LED_ACT(vendor)				\
847{							\
848	.vid = PCI_VENDOR_##vendor,			\
849	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
850}
851
852static const struct {
853	uint16_t	vid;
854	uint8_t		led_act[BWN_LED_MAX];
855} bwn_vendor_led_act[] = {
856	VENDOR_LED_ACT(COMPAQ),
857	VENDOR_LED_ACT(ASUSTEK)
858};
859
860static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
861	{ BWN_VENDOR_LED_ACT_DEFAULT };
862
863#undef VENDOR_LED_ACT
864
865static const struct {
866	int		on_dur;
867	int		off_dur;
868} bwn_led_duration[109] = {
869	[0]	= { 400, 100 },
870	[2]	= { 150, 75 },
871	[4]	= { 90, 45 },
872	[11]	= { 66, 34 },
873	[12]	= { 53, 26 },
874	[18]	= { 42, 21 },
875	[22]	= { 35, 17 },
876	[24]	= { 32, 16 },
877	[36]	= { 21, 10 },
878	[48]	= { 16, 8 },
879	[72]	= { 11, 5 },
880	[96]	= { 9, 4 },
881	[108]	= { 7, 3 }
882};
883
884static const uint16_t bwn_wme_shm_offsets[] = {
885	[0] = BWN_WME_BESTEFFORT,
886	[1] = BWN_WME_BACKGROUND,
887	[2] = BWN_WME_VOICE,
888	[3] = BWN_WME_VIDEO,
889};
890
891static const struct siba_devid bwn_devs[] = {
892	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
893	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
894	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
895	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
896	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
897	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
898	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
899	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
900	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
901};
902
903static int
904bwn_probe(device_t dev)
905{
906	int i;
907
908	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
909		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
910		    siba_get_device(dev) == bwn_devs[i].sd_device &&
911		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
912			return (BUS_PROBE_DEFAULT);
913	}
914
915	return (ENXIO);
916}
917
918static int
919bwn_attach(device_t dev)
920{
921	struct bwn_mac *mac;
922	struct bwn_softc *sc = device_get_softc(dev);
923	int error, i, msic, reg;
924
925	sc->sc_dev = dev;
926#ifdef BWN_DEBUG
927	sc->sc_debug = bwn_debug;
928#endif
929
930	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
931		bwn_attach_pre(sc);
932		bwn_sprom_bugfixes(dev);
933		sc->sc_flags |= BWN_FLAG_ATTACHED;
934	}
935
936	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
937		if (siba_get_pci_device(dev) != 0x4313 &&
938		    siba_get_pci_device(dev) != 0x431a &&
939		    siba_get_pci_device(dev) != 0x4321) {
940			device_printf(sc->sc_dev,
941			    "skip 802.11 cores\n");
942			return (ENODEV);
943		}
944	}
945
946	mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO);
947	mac->mac_sc = sc;
948	mac->mac_status = BWN_MAC_STATUS_UNINIT;
949	if (bwn_bfp != 0)
950		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
951
952	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
953	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
954	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
955
956	error = bwn_attach_core(mac);
957	if (error)
958		goto fail0;
959	bwn_led_attach(mac);
960
961	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
962	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
963	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
964	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
965	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
966	    mac->mac_phy.rf_rev);
967	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
968		device_printf(sc->sc_dev, "DMA (%d bits)\n",
969		    mac->mac_method.dma.dmatype);
970	else
971		device_printf(sc->sc_dev, "PIO\n");
972
973	/*
974	 * setup PCI resources and interrupt.
975	 */
976	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
977		msic = pci_msi_count(dev);
978		if (bootverbose)
979			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
980	} else
981		msic = 0;
982
983	mac->mac_intr_spec = bwn_res_spec_legacy;
984	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
985		if (pci_alloc_msi(dev, &msic) == 0) {
986			device_printf(sc->sc_dev,
987			    "Using %d MSI messages\n", msic);
988			mac->mac_intr_spec = bwn_res_spec_msi;
989			mac->mac_msi = 1;
990		}
991	}
992
993	error = bus_alloc_resources(dev, mac->mac_intr_spec,
994	    mac->mac_res_irq);
995	if (error) {
996		device_printf(sc->sc_dev,
997		    "couldn't allocate IRQ resources (%d)\n", error);
998		goto fail1;
999	}
1000
1001	if (mac->mac_msi == 0)
1002		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1003		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1004		    &mac->mac_intrhand[0]);
1005	else {
1006		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1007			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1008			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1009			    &mac->mac_intrhand[i]);
1010			if (error != 0) {
1011				device_printf(sc->sc_dev,
1012				    "couldn't setup interrupt (%d)\n", error);
1013				break;
1014			}
1015		}
1016	}
1017
1018	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1019
1020	/*
1021	 * calls attach-post routine
1022	 */
1023	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1024		bwn_attach_post(sc);
1025
1026	return (0);
1027fail1:
1028	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1029		pci_release_msi(dev);
1030fail0:
1031	free(mac, M_DEVBUF);
1032	return (error);
1033}
1034
1035static int
1036bwn_is_valid_ether_addr(uint8_t *addr)
1037{
1038	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1039
1040	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1041		return (FALSE);
1042
1043	return (TRUE);
1044}
1045
1046static int
1047bwn_attach_post(struct bwn_softc *sc)
1048{
1049	struct ieee80211com *ic = &sc->sc_ic;
1050
1051	ic->ic_softc = sc;
1052	ic->ic_name = device_get_nameunit(sc->sc_dev);
1053	/* XXX not right but it's not used anywhere important */
1054	ic->ic_phytype = IEEE80211_T_OFDM;
1055	ic->ic_opmode = IEEE80211_M_STA;
1056	ic->ic_caps =
1057		  IEEE80211_C_STA		/* station mode supported */
1058		| IEEE80211_C_MONITOR		/* monitor mode */
1059		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1060		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1061		| IEEE80211_C_SHSLOT		/* short slot time supported */
1062		| IEEE80211_C_WME		/* WME/WMM supported */
1063		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1064		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1065		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1066		;
1067
1068	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1069
1070	IEEE80211_ADDR_COPY(ic->ic_macaddr,
1071	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1072	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1073	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1074
1075	/* call MI attach routine. */
1076	ieee80211_ifattach(ic);
1077
1078	ic->ic_headroom = sizeof(struct bwn_txhdr);
1079
1080	/* override default methods */
1081	ic->ic_raw_xmit = bwn_raw_xmit;
1082	ic->ic_updateslot = bwn_updateslot;
1083	ic->ic_update_promisc = bwn_update_promisc;
1084	ic->ic_wme.wme_update = bwn_wme_update;
1085	ic->ic_scan_start = bwn_scan_start;
1086	ic->ic_scan_end = bwn_scan_end;
1087	ic->ic_set_channel = bwn_set_channel;
1088	ic->ic_vap_create = bwn_vap_create;
1089	ic->ic_vap_delete = bwn_vap_delete;
1090	ic->ic_transmit = bwn_transmit;
1091	ic->ic_parent = bwn_parent;
1092
1093	ieee80211_radiotap_attach(ic,
1094	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1095	    BWN_TX_RADIOTAP_PRESENT,
1096	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1097	    BWN_RX_RADIOTAP_PRESENT);
1098
1099	bwn_sysctl_node(sc);
1100
1101	if (bootverbose)
1102		ieee80211_announce(ic);
1103	return (0);
1104}
1105
1106static void
1107bwn_phy_detach(struct bwn_mac *mac)
1108{
1109
1110	if (mac->mac_phy.detach != NULL)
1111		mac->mac_phy.detach(mac);
1112}
1113
1114static int
1115bwn_detach(device_t dev)
1116{
1117	struct bwn_softc *sc = device_get_softc(dev);
1118	struct bwn_mac *mac = sc->sc_curmac;
1119	struct ieee80211com *ic = &sc->sc_ic;
1120	int i;
1121
1122	sc->sc_flags |= BWN_FLAG_INVALID;
1123
1124	if (device_is_attached(sc->sc_dev)) {
1125		BWN_LOCK(sc);
1126		bwn_stop(sc);
1127		BWN_UNLOCK(sc);
1128		bwn_dma_free(mac);
1129		callout_drain(&sc->sc_led_blink_ch);
1130		callout_drain(&sc->sc_rfswitch_ch);
1131		callout_drain(&sc->sc_task_ch);
1132		callout_drain(&sc->sc_watchdog_ch);
1133		bwn_phy_detach(mac);
1134		ieee80211_draintask(ic, &mac->mac_hwreset);
1135		ieee80211_draintask(ic, &mac->mac_txpower);
1136		ieee80211_ifdetach(ic);
1137	}
1138	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1139	taskqueue_free(sc->sc_tq);
1140
1141	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1142		if (mac->mac_intrhand[i] != NULL) {
1143			bus_teardown_intr(dev, mac->mac_res_irq[i],
1144			    mac->mac_intrhand[i]);
1145			mac->mac_intrhand[i] = NULL;
1146		}
1147	}
1148	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1149	if (mac->mac_msi != 0)
1150		pci_release_msi(dev);
1151	mbufq_drain(&sc->sc_snd);
1152	BWN_LOCK_DESTROY(sc);
1153	return (0);
1154}
1155
1156static void
1157bwn_attach_pre(struct bwn_softc *sc)
1158{
1159
1160	BWN_LOCK_INIT(sc);
1161	TAILQ_INIT(&sc->sc_maclist);
1162	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1163	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1164	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1165	mbufq_init(&sc->sc_snd, ifqmaxlen);
1166	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1167		taskqueue_thread_enqueue, &sc->sc_tq);
1168	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1169		"%s taskq", device_get_nameunit(sc->sc_dev));
1170}
1171
1172static void
1173bwn_sprom_bugfixes(device_t dev)
1174{
1175#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1176	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1177	 (siba_get_pci_device(dev) == _device) &&			\
1178	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1179	 (siba_get_pci_subdevice(dev) == _subdevice))
1180
1181	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1182	    siba_get_pci_subdevice(dev) == 0x4e &&
1183	    siba_get_pci_revid(dev) > 0x40)
1184		siba_sprom_set_bf_lo(dev,
1185		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1186	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1187	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1188		siba_sprom_set_bf_lo(dev,
1189		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1190	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1191		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1192		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1193		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1194		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1195		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1196		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1197		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1198			siba_sprom_set_bf_lo(dev,
1199			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1200	}
1201#undef	BWN_ISDEV
1202}
1203
1204static void
1205bwn_parent(struct ieee80211com *ic)
1206{
1207	struct bwn_softc *sc = ic->ic_softc;
1208	int startall = 0;
1209
1210	BWN_LOCK(sc);
1211	if (ic->ic_nrunning > 0) {
1212		if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
1213			bwn_init(sc);
1214			startall = 1;
1215		} else
1216			bwn_update_promisc(ic);
1217	} else if (sc->sc_flags & BWN_FLAG_RUNNING)
1218		bwn_stop(sc);
1219	BWN_UNLOCK(sc);
1220
1221	if (startall)
1222		ieee80211_start_all(ic);
1223}
1224
1225static int
1226bwn_transmit(struct ieee80211com *ic, struct mbuf *m)
1227{
1228	struct bwn_softc *sc = ic->ic_softc;
1229	int error;
1230
1231	BWN_LOCK(sc);
1232	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
1233		BWN_UNLOCK(sc);
1234		return (ENXIO);
1235	}
1236	error = mbufq_enqueue(&sc->sc_snd, m);
1237	if (error) {
1238		BWN_UNLOCK(sc);
1239		return (error);
1240	}
1241	bwn_start(sc);
1242	BWN_UNLOCK(sc);
1243	return (0);
1244}
1245
1246static void
1247bwn_start(struct bwn_softc *sc)
1248{
1249	struct bwn_mac *mac = sc->sc_curmac;
1250	struct ieee80211_frame *wh;
1251	struct ieee80211_node *ni;
1252	struct ieee80211_key *k;
1253	struct mbuf *m;
1254
1255	BWN_ASSERT_LOCKED(sc);
1256
1257	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL ||
1258	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1259		return;
1260
1261	while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
1262		if (bwn_tx_isfull(sc, m))
1263			break;
1264		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1265		if (ni == NULL) {
1266			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1267			m_freem(m);
1268			counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1269			continue;
1270		}
1271		wh = mtod(m, struct ieee80211_frame *);
1272		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1273			k = ieee80211_crypto_encap(ni, m);
1274			if (k == NULL) {
1275				if_inc_counter(ni->ni_vap->iv_ifp,
1276				    IFCOUNTER_OERRORS, 1);
1277				ieee80211_free_node(ni);
1278				m_freem(m);
1279				continue;
1280			}
1281		}
1282		wh = NULL;	/* Catch any invalid use */
1283		if (bwn_tx_start(sc, ni, m) != 0) {
1284			if (ni != NULL) {
1285				if_inc_counter(ni->ni_vap->iv_ifp,
1286				    IFCOUNTER_OERRORS, 1);
1287				ieee80211_free_node(ni);
1288			}
1289			continue;
1290		}
1291		sc->sc_watchdog_timer = 5;
1292	}
1293}
1294
1295static int
1296bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1297{
1298	struct bwn_dma_ring *dr;
1299	struct bwn_mac *mac = sc->sc_curmac;
1300	struct bwn_pio_txqueue *tq;
1301	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1302
1303	BWN_ASSERT_LOCKED(sc);
1304
1305	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1306		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1307		if (dr->dr_stop == 1 ||
1308		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1309			dr->dr_stop = 1;
1310			goto full;
1311		}
1312	} else {
1313		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1314		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1315		    pktlen > (tq->tq_size - tq->tq_used))
1316			goto full;
1317	}
1318	return (0);
1319full:
1320	mbufq_prepend(&sc->sc_snd, m);
1321	return (1);
1322}
1323
1324static int
1325bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1326{
1327	struct bwn_mac *mac = sc->sc_curmac;
1328	int error;
1329
1330	BWN_ASSERT_LOCKED(sc);
1331
1332	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1333		m_freem(m);
1334		return (ENXIO);
1335	}
1336
1337	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1338	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1339	if (error) {
1340		m_freem(m);
1341		return (error);
1342	}
1343	return (0);
1344}
1345
1346static int
1347bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1348{
1349	struct bwn_pio_txpkt *tp;
1350	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1351	struct bwn_softc *sc = mac->mac_sc;
1352	struct bwn_txhdr txhdr;
1353	struct mbuf *m_new;
1354	uint32_t ctl32;
1355	int error;
1356	uint16_t ctl16;
1357
1358	BWN_ASSERT_LOCKED(sc);
1359
1360	/* XXX TODO send packets after DTIM */
1361
1362	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1363	tp = TAILQ_FIRST(&tq->tq_pktlist);
1364	tp->tp_ni = ni;
1365	tp->tp_m = m;
1366
1367	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1368	if (error) {
1369		device_printf(sc->sc_dev, "tx fail\n");
1370		return (error);
1371	}
1372
1373	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1374	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1375	tq->tq_free--;
1376
1377	if (siba_get_revid(sc->sc_dev) >= 8) {
1378		/*
1379		 * XXX please removes m_defrag(9)
1380		 */
1381		m_new = m_defrag(m, M_NOWAIT);
1382		if (m_new == NULL) {
1383			device_printf(sc->sc_dev,
1384			    "%s: can't defrag TX buffer\n",
1385			    __func__);
1386			return (ENOBUFS);
1387		}
1388		if (m_new->m_next != NULL)
1389			device_printf(sc->sc_dev,
1390			    "TODO: fragmented packets for PIO\n");
1391		tp->tp_m = m_new;
1392
1393		/* send HEADER */
1394		ctl32 = bwn_pio_write_multi_4(mac, tq,
1395		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1396			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1397		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1398		/* send BODY */
1399		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1400		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1401		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1402		    ctl32 | BWN_PIO8_TXCTL_EOF);
1403	} else {
1404		ctl16 = bwn_pio_write_multi_2(mac, tq,
1405		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1406			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1407		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1408		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1409		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1410		    ctl16 | BWN_PIO_TXCTL_EOF);
1411	}
1412
1413	return (0);
1414}
1415
1416static struct bwn_pio_txqueue *
1417bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1418{
1419
1420	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1421		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1422
1423	switch (prio) {
1424	case 0:
1425		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1426	case 1:
1427		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1428	case 2:
1429		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1430	case 3:
1431		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1432	}
1433	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1434	return (NULL);
1435}
1436
1437static int
1438bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1439{
1440#define	BWN_GET_TXHDRCACHE(slot)					\
1441	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1442	struct bwn_dma *dma = &mac->mac_method.dma;
1443	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1444	struct bwn_dmadesc_generic *desc;
1445	struct bwn_dmadesc_meta *mt;
1446	struct bwn_softc *sc = mac->mac_sc;
1447	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1448	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1449
1450	BWN_ASSERT_LOCKED(sc);
1451	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1452
1453	/* XXX send after DTIM */
1454
1455	slot = bwn_dma_getslot(dr);
1456	dr->getdesc(dr, slot, &desc, &mt);
1457	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1458	    ("%s:%d: fail", __func__, __LINE__));
1459
1460	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1461	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1462	    BWN_DMA_COOKIE(dr, slot));
1463	if (error)
1464		goto fail;
1465	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1466	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1467	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1468	if (error) {
1469		device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1470		    __func__, error);
1471		goto fail;
1472	}
1473	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1474	    BUS_DMASYNC_PREWRITE);
1475	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1476	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1477	    BUS_DMASYNC_PREWRITE);
1478
1479	slot = bwn_dma_getslot(dr);
1480	dr->getdesc(dr, slot, &desc, &mt);
1481	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1482	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1483	mt->mt_m = m;
1484	mt->mt_ni = ni;
1485
1486	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1487	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1488	if (error && error != EFBIG) {
1489		device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1490		    __func__, error);
1491		goto fail;
1492	}
1493	if (error) {    /* error == EFBIG */
1494		struct mbuf *m_new;
1495
1496		m_new = m_defrag(m, M_NOWAIT);
1497		if (m_new == NULL) {
1498			device_printf(sc->sc_dev,
1499			    "%s: can't defrag TX buffer\n",
1500			    __func__);
1501			error = ENOBUFS;
1502			goto fail;
1503		} else {
1504			m = m_new;
1505		}
1506
1507		mt->mt_m = m;
1508		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1509		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1510		if (error) {
1511			device_printf(sc->sc_dev,
1512			    "%s: can't load TX buffer (2) %d\n",
1513			    __func__, error);
1514			goto fail;
1515		}
1516	}
1517	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1518	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1519	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1520	    BUS_DMASYNC_PREWRITE);
1521
1522	/* XXX send after DTIM */
1523
1524	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1525	return (0);
1526fail:
1527	dr->dr_curslot = backup[0];
1528	dr->dr_usedslot = backup[1];
1529	return (error);
1530#undef BWN_GET_TXHDRCACHE
1531}
1532
1533static void
1534bwn_watchdog(void *arg)
1535{
1536	struct bwn_softc *sc = arg;
1537
1538	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1539		device_printf(sc->sc_dev, "device timeout\n");
1540		counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1541	}
1542	callout_schedule(&sc->sc_watchdog_ch, hz);
1543}
1544
1545static int
1546bwn_attach_core(struct bwn_mac *mac)
1547{
1548	struct bwn_softc *sc = mac->mac_sc;
1549	int error, have_bg = 0, have_a = 0;
1550	uint32_t high;
1551
1552	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1553	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1554
1555	siba_powerup(sc->sc_dev, 0);
1556
1557	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1558	bwn_reset_core(mac,
1559	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1560	error = bwn_phy_getinfo(mac, high);
1561	if (error)
1562		goto fail;
1563
1564	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1565	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1566	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1567	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1568	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1569		have_a = have_bg = 0;
1570		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1571			have_a = 1;
1572		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1573		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1574		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1575			have_bg = 1;
1576		else
1577			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1578			    mac->mac_phy.type));
1579	}
1580	/* XXX turns off PHY A because it's not supported */
1581	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1582	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1583		have_a = 0;
1584		have_bg = 1;
1585	}
1586
1587	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1588		mac->mac_phy.attach = bwn_phy_g_attach;
1589		mac->mac_phy.detach = bwn_phy_g_detach;
1590		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1591		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1592		mac->mac_phy.init = bwn_phy_g_init;
1593		mac->mac_phy.exit = bwn_phy_g_exit;
1594		mac->mac_phy.phy_read = bwn_phy_g_read;
1595		mac->mac_phy.phy_write = bwn_phy_g_write;
1596		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1597		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1598		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1599		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1600		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1601		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1602		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1603		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1604		mac->mac_phy.set_im = bwn_phy_g_im;
1605		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1606		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1607		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1608		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1609	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1610		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1611		mac->mac_phy.init = bwn_phy_lp_init;
1612		mac->mac_phy.phy_read = bwn_phy_lp_read;
1613		mac->mac_phy.phy_write = bwn_phy_lp_write;
1614		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1615		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1616		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1617		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1618		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1619		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1620		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1621		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1622		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1623	} else {
1624		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1625		    mac->mac_phy.type);
1626		error = ENXIO;
1627		goto fail;
1628	}
1629
1630	mac->mac_phy.gmode = have_bg;
1631	if (mac->mac_phy.attach != NULL) {
1632		error = mac->mac_phy.attach(mac);
1633		if (error) {
1634			device_printf(sc->sc_dev, "failed\n");
1635			goto fail;
1636		}
1637	}
1638
1639	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1640
1641	error = bwn_chiptest(mac);
1642	if (error)
1643		goto fail;
1644	error = bwn_setup_channels(mac, have_bg, have_a);
1645	if (error) {
1646		device_printf(sc->sc_dev, "failed to setup channels\n");
1647		goto fail;
1648	}
1649
1650	if (sc->sc_curmac == NULL)
1651		sc->sc_curmac = mac;
1652
1653	error = bwn_dma_attach(mac);
1654	if (error != 0) {
1655		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1656		goto fail;
1657	}
1658
1659	mac->mac_phy.switch_analog(mac, 0);
1660
1661	siba_dev_down(sc->sc_dev, 0);
1662fail:
1663	siba_powerdown(sc->sc_dev);
1664	return (error);
1665}
1666
1667static void
1668bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1669{
1670	struct bwn_softc *sc = mac->mac_sc;
1671	uint32_t low, ctl;
1672
1673	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1674
1675	siba_dev_up(sc->sc_dev, flags);
1676	DELAY(2000);
1677
1678	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1679	    ~BWN_TGSLOW_PHYRESET;
1680	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1681	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1682	DELAY(1000);
1683	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1684	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1685	DELAY(1000);
1686
1687	if (mac->mac_phy.switch_analog != NULL)
1688		mac->mac_phy.switch_analog(mac, 1);
1689
1690	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1691	if (flags & BWN_TGSLOW_SUPPORT_G)
1692		ctl |= BWN_MACCTL_GMODE;
1693	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1694}
1695
1696static int
1697bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1698{
1699	struct bwn_phy *phy = &mac->mac_phy;
1700	struct bwn_softc *sc = mac->mac_sc;
1701	uint32_t tmp;
1702
1703	/* PHY */
1704	tmp = BWN_READ_2(mac, BWN_PHYVER);
1705	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1706	phy->rf_on = 1;
1707	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1708	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1709	phy->rev = (tmp & BWN_PHYVER_VERSION);
1710	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1711	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1712		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1713	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1714	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1715	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1716		goto unsupphy;
1717
1718	/* RADIO */
1719	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1720		if (siba_get_chiprev(sc->sc_dev) == 0)
1721			tmp = 0x3205017f;
1722		else if (siba_get_chiprev(sc->sc_dev) == 1)
1723			tmp = 0x4205017f;
1724		else
1725			tmp = 0x5205017f;
1726	} else {
1727		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1728		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1729		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1730		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1731	}
1732	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1733	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1734	phy->rf_manuf = (tmp & 0x00000fff);
1735	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1736		goto unsupradio;
1737	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1738	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1739	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1740	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1741	    (phy->type == BWN_PHYTYPE_N &&
1742	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1743	    (phy->type == BWN_PHYTYPE_LP &&
1744	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1745		goto unsupradio;
1746
1747	return (0);
1748unsupphy:
1749	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1750	    "analog %#x)\n",
1751	    phy->type, phy->rev, phy->analog);
1752	return (ENXIO);
1753unsupradio:
1754	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1755	    "rev %#x)\n",
1756	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1757	return (ENXIO);
1758}
1759
1760static int
1761bwn_chiptest(struct bwn_mac *mac)
1762{
1763#define	TESTVAL0	0x55aaaa55
1764#define	TESTVAL1	0xaa5555aa
1765	struct bwn_softc *sc = mac->mac_sc;
1766	uint32_t v, backup;
1767
1768	BWN_LOCK(sc);
1769
1770	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1771
1772	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1773	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1774		goto error;
1775	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1776	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1777		goto error;
1778
1779	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1780
1781	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1782	    (siba_get_revid(sc->sc_dev) <= 10)) {
1783		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1784		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1785		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1786			goto error;
1787		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1788			goto error;
1789	}
1790	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1791
1792	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1793	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1794		goto error;
1795
1796	BWN_UNLOCK(sc);
1797	return (0);
1798error:
1799	BWN_UNLOCK(sc);
1800	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1801	return (ENODEV);
1802}
1803
1804#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1805#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1806
1807static int
1808bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1809{
1810	struct bwn_softc *sc = mac->mac_sc;
1811	struct ieee80211com *ic = &sc->sc_ic;
1812
1813	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1814	ic->ic_nchans = 0;
1815
1816	if (have_bg)
1817		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1818		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1819	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1820		if (have_a)
1821			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1822			    &ic->ic_nchans, &bwn_chantable_n,
1823			    IEEE80211_CHAN_HTA);
1824	} else {
1825		if (have_a)
1826			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1827			    &ic->ic_nchans, &bwn_chantable_a,
1828			    IEEE80211_CHAN_A);
1829	}
1830
1831	mac->mac_phy.supports_2ghz = have_bg;
1832	mac->mac_phy.supports_5ghz = have_a;
1833
1834	return (ic->ic_nchans == 0 ? ENXIO : 0);
1835}
1836
1837static uint32_t
1838bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1839{
1840	uint32_t ret;
1841
1842	BWN_ASSERT_LOCKED(mac->mac_sc);
1843
1844	if (way == BWN_SHARED) {
1845		KASSERT((offset & 0x0001) == 0,
1846		    ("%s:%d warn", __func__, __LINE__));
1847		if (offset & 0x0003) {
1848			bwn_shm_ctlword(mac, way, offset >> 2);
1849			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1850			ret <<= 16;
1851			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1852			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1853			goto out;
1854		}
1855		offset >>= 2;
1856	}
1857	bwn_shm_ctlword(mac, way, offset);
1858	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1859out:
1860	return (ret);
1861}
1862
1863static uint16_t
1864bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1865{
1866	uint16_t ret;
1867
1868	BWN_ASSERT_LOCKED(mac->mac_sc);
1869
1870	if (way == BWN_SHARED) {
1871		KASSERT((offset & 0x0001) == 0,
1872		    ("%s:%d warn", __func__, __LINE__));
1873		if (offset & 0x0003) {
1874			bwn_shm_ctlword(mac, way, offset >> 2);
1875			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1876			goto out;
1877		}
1878		offset >>= 2;
1879	}
1880	bwn_shm_ctlword(mac, way, offset);
1881	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1882out:
1883
1884	return (ret);
1885}
1886
1887static void
1888bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1889    uint16_t offset)
1890{
1891	uint32_t control;
1892
1893	control = way;
1894	control <<= 16;
1895	control |= offset;
1896	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1897}
1898
1899static void
1900bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1901    uint32_t value)
1902{
1903	BWN_ASSERT_LOCKED(mac->mac_sc);
1904
1905	if (way == BWN_SHARED) {
1906		KASSERT((offset & 0x0001) == 0,
1907		    ("%s:%d warn", __func__, __LINE__));
1908		if (offset & 0x0003) {
1909			bwn_shm_ctlword(mac, way, offset >> 2);
1910			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1911				    (value >> 16) & 0xffff);
1912			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1913			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1914			return;
1915		}
1916		offset >>= 2;
1917	}
1918	bwn_shm_ctlword(mac, way, offset);
1919	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1920}
1921
1922static void
1923bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1924    uint16_t value)
1925{
1926	BWN_ASSERT_LOCKED(mac->mac_sc);
1927
1928	if (way == BWN_SHARED) {
1929		KASSERT((offset & 0x0001) == 0,
1930		    ("%s:%d warn", __func__, __LINE__));
1931		if (offset & 0x0003) {
1932			bwn_shm_ctlword(mac, way, offset >> 2);
1933			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1934			return;
1935		}
1936		offset >>= 2;
1937	}
1938	bwn_shm_ctlword(mac, way, offset);
1939	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1940}
1941
1942static void
1943bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1944    int txpow)
1945{
1946
1947	c->ic_freq = freq;
1948	c->ic_flags = flags;
1949	c->ic_ieee = ieee;
1950	c->ic_minpower = 0;
1951	c->ic_maxpower = 2 * txpow;
1952	c->ic_maxregpower = txpow;
1953}
1954
1955static void
1956bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1957    const struct bwn_channelinfo *ci, int flags)
1958{
1959	struct ieee80211_channel *c;
1960	int i;
1961
1962	c = &chans[*nchans];
1963
1964	for (i = 0; i < ci->nchannels; i++) {
1965		const struct bwn_channel *hc;
1966
1967		hc = &ci->channels[i];
1968		if (*nchans >= maxchans)
1969			break;
1970		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
1971		c++, (*nchans)++;
1972		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
1973			/* g channel have a separate b-only entry */
1974			if (*nchans >= maxchans)
1975				break;
1976			c[0] = c[-1];
1977			c[-1].ic_flags = IEEE80211_CHAN_B;
1978			c++, (*nchans)++;
1979		}
1980		if (flags == IEEE80211_CHAN_HTG) {
1981			/* HT g channel have a separate g-only entry */
1982			if (*nchans >= maxchans)
1983				break;
1984			c[-1].ic_flags = IEEE80211_CHAN_G;
1985			c[0] = c[-1];
1986			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
1987			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
1988			c++, (*nchans)++;
1989		}
1990		if (flags == IEEE80211_CHAN_HTA) {
1991			/* HT a channel have a separate a-only entry */
1992			if (*nchans >= maxchans)
1993				break;
1994			c[-1].ic_flags = IEEE80211_CHAN_A;
1995			c[0] = c[-1];
1996			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
1997			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
1998			c++, (*nchans)++;
1999		}
2000	}
2001}
2002
2003static int
2004bwn_phy_g_attach(struct bwn_mac *mac)
2005{
2006	struct bwn_softc *sc = mac->mac_sc;
2007	struct bwn_phy *phy = &mac->mac_phy;
2008	struct bwn_phy_g *pg = &phy->phy_g;
2009	unsigned int i;
2010	int16_t pab0, pab1, pab2;
2011	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2012	int8_t bg;
2013
2014	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2015	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2016	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2017	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2018
2019	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2020		device_printf(sc->sc_dev, "not supported anymore\n");
2021
2022	pg->pg_flags = 0;
2023	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2024	    pab2 == -1) {
2025		pg->pg_idletssi = 52;
2026		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2027		return (0);
2028	}
2029
2030	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2031	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2032	if (pg->pg_tssi2dbm == NULL) {
2033		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2034		return (ENOMEM);
2035	}
2036	for (i = 0; i < 64; i++) {
2037		int32_t m1, m2, f, q, delta;
2038		int8_t j = 0;
2039
2040		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2041		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2042		f = 256;
2043
2044		do {
2045			if (j > 15) {
2046				device_printf(sc->sc_dev,
2047				    "failed to generate tssi2dBm\n");
2048				free(pg->pg_tssi2dbm, M_DEVBUF);
2049				return (ENOMEM);
2050			}
2051			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2052			    f, 2048);
2053			delta = abs(q - f);
2054			f = q;
2055			j++;
2056		} while (delta >= 2);
2057
2058		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2059		    128);
2060	}
2061
2062	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2063	return (0);
2064}
2065
2066static void
2067bwn_phy_g_detach(struct bwn_mac *mac)
2068{
2069	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2070
2071	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2072		free(pg->pg_tssi2dbm, M_DEVBUF);
2073		pg->pg_tssi2dbm = NULL;
2074	}
2075	pg->pg_flags = 0;
2076}
2077
2078static void
2079bwn_phy_g_init_pre(struct bwn_mac *mac)
2080{
2081	struct bwn_phy *phy = &mac->mac_phy;
2082	struct bwn_phy_g *pg = &phy->phy_g;
2083	void *tssi2dbm;
2084	int idletssi;
2085	unsigned int i;
2086
2087	tssi2dbm = pg->pg_tssi2dbm;
2088	idletssi = pg->pg_idletssi;
2089
2090	memset(pg, 0, sizeof(*pg));
2091
2092	pg->pg_tssi2dbm = tssi2dbm;
2093	pg->pg_idletssi = idletssi;
2094
2095	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2096
2097	for (i = 0; i < N(pg->pg_nrssi); i++)
2098		pg->pg_nrssi[i] = -1000;
2099	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2100		pg->pg_nrssi_lt[i] = i;
2101	pg->pg_lofcal = 0xffff;
2102	pg->pg_initval = 0xffff;
2103	pg->pg_immode = BWN_IMMODE_NONE;
2104	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2105	pg->pg_avgtssi = 0xff;
2106
2107	pg->pg_loctl.tx_bias = 0xff;
2108	TAILQ_INIT(&pg->pg_loctl.calib_list);
2109}
2110
2111static int
2112bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2113{
2114	struct bwn_phy *phy = &mac->mac_phy;
2115	struct bwn_phy_g *pg = &phy->phy_g;
2116	struct bwn_softc *sc = mac->mac_sc;
2117	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2118	static const struct bwn_rfatt rfatt0[] = {
2119		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2120		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2121		{ 3, 1 }, { 4, 1 }
2122	};
2123	static const struct bwn_rfatt rfatt1[] = {
2124		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2125		{ 14, 1 }
2126	};
2127	static const struct bwn_rfatt rfatt2[] = {
2128		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2129		{ 9, 1 }
2130	};
2131	static const struct bwn_bbatt bbatt_0[] = {
2132		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2133	};
2134
2135	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2136
2137	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2138		pg->pg_bbatt.att = 0;
2139	else
2140		pg->pg_bbatt.att = 2;
2141
2142	/* prepare Radio Attenuation */
2143	pg->pg_rfatt.padmix = 0;
2144
2145	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2146	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2147		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2148			pg->pg_rfatt.att = 2;
2149			goto done;
2150		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2151			pg->pg_rfatt.att = 3;
2152			goto done;
2153		}
2154	}
2155
2156	if (phy->type == BWN_PHYTYPE_A) {
2157		pg->pg_rfatt.att = 0x60;
2158		goto done;
2159	}
2160
2161	switch (phy->rf_ver) {
2162	case 0x2050:
2163		switch (phy->rf_rev) {
2164		case 0:
2165			pg->pg_rfatt.att = 5;
2166			goto done;
2167		case 1:
2168			if (phy->type == BWN_PHYTYPE_G) {
2169				if (siba_get_pci_subvendor(sc->sc_dev) ==
2170				    SIBA_BOARDVENDOR_BCM &&
2171				    siba_get_pci_subdevice(sc->sc_dev) ==
2172				    SIBA_BOARD_BCM4309G &&
2173				    siba_get_pci_revid(sc->sc_dev) >= 30)
2174					pg->pg_rfatt.att = 3;
2175				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2176				    SIBA_BOARDVENDOR_BCM &&
2177				    siba_get_pci_subdevice(sc->sc_dev) ==
2178				    SIBA_BOARD_BU4306)
2179					pg->pg_rfatt.att = 3;
2180				else
2181					pg->pg_rfatt.att = 1;
2182			} else {
2183				if (siba_get_pci_subvendor(sc->sc_dev) ==
2184				    SIBA_BOARDVENDOR_BCM &&
2185				    siba_get_pci_subdevice(sc->sc_dev) ==
2186				    SIBA_BOARD_BCM4309G &&
2187				    siba_get_pci_revid(sc->sc_dev) >= 30)
2188					pg->pg_rfatt.att = 7;
2189				else
2190					pg->pg_rfatt.att = 6;
2191			}
2192			goto done;
2193		case 2:
2194			if (phy->type == BWN_PHYTYPE_G) {
2195				if (siba_get_pci_subvendor(sc->sc_dev) ==
2196				    SIBA_BOARDVENDOR_BCM &&
2197				    siba_get_pci_subdevice(sc->sc_dev) ==
2198				    SIBA_BOARD_BCM4309G &&
2199				    siba_get_pci_revid(sc->sc_dev) >= 30)
2200					pg->pg_rfatt.att = 3;
2201				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2202				    SIBA_BOARDVENDOR_BCM &&
2203				    siba_get_pci_subdevice(sc->sc_dev) ==
2204				    SIBA_BOARD_BU4306)
2205					pg->pg_rfatt.att = 5;
2206				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2207					pg->pg_rfatt.att = 4;
2208				else
2209					pg->pg_rfatt.att = 3;
2210			} else
2211				pg->pg_rfatt.att = 6;
2212			goto done;
2213		case 3:
2214			pg->pg_rfatt.att = 5;
2215			goto done;
2216		case 4:
2217		case 5:
2218			pg->pg_rfatt.att = 1;
2219			goto done;
2220		case 6:
2221		case 7:
2222			pg->pg_rfatt.att = 5;
2223			goto done;
2224		case 8:
2225			pg->pg_rfatt.att = 0xa;
2226			pg->pg_rfatt.padmix = 1;
2227			goto done;
2228		case 9:
2229		default:
2230			pg->pg_rfatt.att = 5;
2231			goto done;
2232		}
2233		break;
2234	case 0x2053:
2235		switch (phy->rf_rev) {
2236		case 1:
2237			pg->pg_rfatt.att = 6;
2238			goto done;
2239		}
2240		break;
2241	}
2242	pg->pg_rfatt.att = 5;
2243done:
2244	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2245
2246	if (!bwn_has_hwpctl(mac)) {
2247		lo->rfatt.array = rfatt0;
2248		lo->rfatt.len = N(rfatt0);
2249		lo->rfatt.min = 0;
2250		lo->rfatt.max = 9;
2251		goto genbbatt;
2252	}
2253	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2254		lo->rfatt.array = rfatt1;
2255		lo->rfatt.len = N(rfatt1);
2256		lo->rfatt.min = 0;
2257		lo->rfatt.max = 14;
2258		goto genbbatt;
2259	}
2260	lo->rfatt.array = rfatt2;
2261	lo->rfatt.len = N(rfatt2);
2262	lo->rfatt.min = 0;
2263	lo->rfatt.max = 9;
2264genbbatt:
2265	lo->bbatt.array = bbatt_0;
2266	lo->bbatt.len = N(bbatt_0);
2267	lo->bbatt.min = 0;
2268	lo->bbatt.max = 8;
2269
2270	BWN_READ_4(mac, BWN_MACCTL);
2271	if (phy->rev == 1) {
2272		phy->gmode = 0;
2273		bwn_reset_core(mac, 0);
2274		bwn_phy_g_init_sub(mac);
2275		phy->gmode = 1;
2276		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2277	}
2278	return (0);
2279}
2280
2281static uint16_t
2282bwn_phy_g_txctl(struct bwn_mac *mac)
2283{
2284	struct bwn_phy *phy = &mac->mac_phy;
2285
2286	if (phy->rf_ver != 0x2050)
2287		return (0);
2288	if (phy->rf_rev == 1)
2289		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2290	if (phy->rf_rev < 6)
2291		return (BWN_TXCTL_PA2DB);
2292	if (phy->rf_rev == 8)
2293		return (BWN_TXCTL_TXMIX);
2294	return (0);
2295}
2296
2297static int
2298bwn_phy_g_init(struct bwn_mac *mac)
2299{
2300
2301	bwn_phy_g_init_sub(mac);
2302	return (0);
2303}
2304
2305static void
2306bwn_phy_g_exit(struct bwn_mac *mac)
2307{
2308	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2309	struct bwn_lo_calib *cal, *tmp;
2310
2311	if (lo == NULL)
2312		return;
2313	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2314		TAILQ_REMOVE(&lo->calib_list, cal, list);
2315		free(cal, M_DEVBUF);
2316	}
2317}
2318
2319static uint16_t
2320bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2321{
2322
2323	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2324	return (BWN_READ_2(mac, BWN_PHYDATA));
2325}
2326
2327static void
2328bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2329{
2330
2331	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2332	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2333}
2334
2335static uint16_t
2336bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2337{
2338
2339	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2340	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2341	return (BWN_READ_2(mac, BWN_RFDATALO));
2342}
2343
2344static void
2345bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2346{
2347
2348	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2349	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2350	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2351}
2352
2353static int
2354bwn_phy_g_hwpctl(struct bwn_mac *mac)
2355{
2356
2357	return (mac->mac_phy.rev >= 6);
2358}
2359
2360static void
2361bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2362{
2363	struct bwn_phy *phy = &mac->mac_phy;
2364	struct bwn_phy_g *pg = &phy->phy_g;
2365	unsigned int channel;
2366	uint16_t rfover, rfoverval;
2367
2368	if (on) {
2369		if (phy->rf_on)
2370			return;
2371
2372		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2373		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2374		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2375		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2376			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2377			    pg->pg_radioctx_over);
2378			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2379			    pg->pg_radioctx_overval);
2380			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2381		}
2382		channel = phy->chan;
2383		bwn_phy_g_switch_chan(mac, 6, 1);
2384		bwn_phy_g_switch_chan(mac, channel, 0);
2385		return;
2386	}
2387
2388	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2389	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2390	pg->pg_radioctx_over = rfover;
2391	pg->pg_radioctx_overval = rfoverval;
2392	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2393	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2394	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2395}
2396
2397static int
2398bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2399{
2400
2401	if ((newchan < 1) || (newchan > 14))
2402		return (EINVAL);
2403	bwn_phy_g_switch_chan(mac, newchan, 0);
2404
2405	return (0);
2406}
2407
2408static uint32_t
2409bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2410{
2411
2412	return (1);
2413}
2414
2415static void
2416bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2417{
2418	struct bwn_phy *phy = &mac->mac_phy;
2419	uint64_t hf;
2420	int autodiv = 0;
2421	uint16_t tmp;
2422
2423	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2424		autodiv = 1;
2425
2426	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2427	bwn_hf_write(mac, hf);
2428
2429	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2430	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2431	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2432		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2433
2434	if (autodiv) {
2435		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2436		if (antenna == BWN_ANTAUTO1)
2437			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2438		else
2439			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2440		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2441	}
2442	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2443	if (autodiv)
2444		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2445	else
2446		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2447	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2448	if (phy->rev >= 2) {
2449		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2450		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2451		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2452		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2453		    0x15);
2454		if (phy->rev == 2)
2455			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2456		else
2457			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2458			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2459			    8);
2460	}
2461	if (phy->rev >= 6)
2462		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2463
2464	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2465	bwn_hf_write(mac, hf);
2466}
2467
2468static int
2469bwn_phy_g_im(struct bwn_mac *mac, int mode)
2470{
2471	struct bwn_phy *phy = &mac->mac_phy;
2472	struct bwn_phy_g *pg = &phy->phy_g;
2473
2474	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2475	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2476
2477	if (phy->rev == 0 || !phy->gmode)
2478		return (ENODEV);
2479
2480	pg->pg_aci_wlan_automatic = 0;
2481	return (0);
2482}
2483
2484static int
2485bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2486{
2487	struct bwn_phy *phy = &mac->mac_phy;
2488	struct bwn_phy_g *pg = &phy->phy_g;
2489	struct bwn_softc *sc = mac->mac_sc;
2490	unsigned int tssi;
2491	int cck, ofdm;
2492	int power;
2493	int rfatt, bbatt;
2494	unsigned int max;
2495
2496	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2497
2498	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2499	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2500	if (cck < 0 && ofdm < 0) {
2501		if (ignore_tssi == 0)
2502			return (BWN_TXPWR_RES_DONE);
2503		cck = 0;
2504		ofdm = 0;
2505	}
2506	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2507	if (pg->pg_avgtssi != 0xff)
2508		tssi = (tssi + pg->pg_avgtssi) / 2;
2509	pg->pg_avgtssi = tssi;
2510	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2511
2512	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2513	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2514		max -= 3;
2515	if (max >= 120) {
2516		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2517		max = 80;
2518		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2519	}
2520
2521	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2522	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2523	     tssi, 0x00), 0x3f)]);
2524	if (power == 0)
2525		return (BWN_TXPWR_RES_DONE);
2526
2527	rfatt = -((power + 7) / 8);
2528	bbatt = (-(power / 2)) - (4 * rfatt);
2529	if ((rfatt == 0) && (bbatt == 0))
2530		return (BWN_TXPWR_RES_DONE);
2531	pg->pg_bbatt_delta = bbatt;
2532	pg->pg_rfatt_delta = rfatt;
2533	return (BWN_TXPWR_RES_NEED_ADJUST);
2534}
2535
2536static void
2537bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2538{
2539	struct bwn_phy *phy = &mac->mac_phy;
2540	struct bwn_phy_g *pg = &phy->phy_g;
2541	struct bwn_softc *sc = mac->mac_sc;
2542	int rfatt, bbatt;
2543	uint8_t txctl;
2544
2545	bwn_mac_suspend(mac);
2546
2547	BWN_ASSERT_LOCKED(sc);
2548
2549	bbatt = pg->pg_bbatt.att;
2550	bbatt += pg->pg_bbatt_delta;
2551	rfatt = pg->pg_rfatt.att;
2552	rfatt += pg->pg_rfatt_delta;
2553
2554	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2555	txctl = pg->pg_txctl;
2556	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2557		if (rfatt <= 1) {
2558			if (txctl == 0) {
2559				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2560				rfatt += 2;
2561				bbatt += 2;
2562			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2563			    BWN_BFL_PACTRL) {
2564				bbatt += 4 * (rfatt - 2);
2565				rfatt = 2;
2566			}
2567		} else if (rfatt > 4 && txctl) {
2568			txctl = 0;
2569			if (bbatt < 3) {
2570				rfatt -= 3;
2571				bbatt += 2;
2572			} else {
2573				rfatt -= 2;
2574				bbatt -= 2;
2575			}
2576		}
2577	}
2578	pg->pg_txctl = txctl;
2579	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2580	pg->pg_rfatt.att = rfatt;
2581	pg->pg_bbatt.att = bbatt;
2582
2583	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2584
2585	bwn_phy_lock(mac);
2586	bwn_rf_lock(mac);
2587	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2588	    pg->pg_txctl);
2589	bwn_rf_unlock(mac);
2590	bwn_phy_unlock(mac);
2591
2592	bwn_mac_enable(mac);
2593}
2594
2595static void
2596bwn_phy_g_task_15s(struct bwn_mac *mac)
2597{
2598	struct bwn_phy *phy = &mac->mac_phy;
2599	struct bwn_phy_g *pg = &phy->phy_g;
2600	struct bwn_softc *sc = mac->mac_sc;
2601	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2602	unsigned long expire, now;
2603	struct bwn_lo_calib *cal, *tmp;
2604	uint8_t expired = 0;
2605
2606	bwn_mac_suspend(mac);
2607
2608	if (lo == NULL)
2609		goto fail;
2610
2611	BWN_GETTIME(now);
2612	if (bwn_has_hwpctl(mac)) {
2613		expire = now - BWN_LO_PWRVEC_EXPIRE;
2614		if (time_before(lo->pwr_vec_read_time, expire)) {
2615			bwn_lo_get_powervector(mac);
2616			bwn_phy_g_dc_lookup_init(mac, 0);
2617		}
2618		goto fail;
2619	}
2620
2621	expire = now - BWN_LO_CALIB_EXPIRE;
2622	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2623		if (!time_before(cal->calib_time, expire))
2624			continue;
2625		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2626		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2627			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2628			expired = 1;
2629		}
2630
2631		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2632		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2633		    cal->ctl.i, cal->ctl.q);
2634
2635		TAILQ_REMOVE(&lo->calib_list, cal, list);
2636		free(cal, M_DEVBUF);
2637	}
2638	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2639		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2640		    &pg->pg_rfatt);
2641		if (cal == NULL) {
2642			device_printf(sc->sc_dev,
2643			    "failed to recalibrate LO\n");
2644			goto fail;
2645		}
2646		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2647		bwn_lo_write(mac, &cal->ctl);
2648	}
2649
2650fail:
2651	bwn_mac_enable(mac);
2652}
2653
2654static void
2655bwn_phy_g_task_60s(struct bwn_mac *mac)
2656{
2657	struct bwn_phy *phy = &mac->mac_phy;
2658	struct bwn_softc *sc = mac->mac_sc;
2659	uint8_t old = phy->chan;
2660
2661	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2662		return;
2663
2664	bwn_mac_suspend(mac);
2665	bwn_nrssi_slope_11g(mac);
2666	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2667		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2668		bwn_switch_channel(mac, old);
2669	}
2670	bwn_mac_enable(mac);
2671}
2672
2673static void
2674bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2675{
2676
2677	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2678}
2679
2680static int
2681bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2682	const struct ieee80211_bpf_params *params)
2683{
2684	struct ieee80211com *ic = ni->ni_ic;
2685	struct bwn_softc *sc = ic->ic_softc;
2686	struct bwn_mac *mac = sc->sc_curmac;
2687
2688	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
2689	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2690		ieee80211_free_node(ni);
2691		m_freem(m);
2692		return (ENETDOWN);
2693	}
2694
2695	BWN_LOCK(sc);
2696	if (bwn_tx_isfull(sc, m)) {
2697		ieee80211_free_node(ni);
2698		m_freem(m);
2699		BWN_UNLOCK(sc);
2700		return (ENOBUFS);
2701	}
2702
2703	if (bwn_tx_start(sc, ni, m) != 0) {
2704		if (ni != NULL)
2705			ieee80211_free_node(ni);
2706	}
2707	sc->sc_watchdog_timer = 5;
2708	BWN_UNLOCK(sc);
2709	return (0);
2710}
2711
2712/*
2713 * Callback from the 802.11 layer to update the slot time
2714 * based on the current setting.  We use it to notify the
2715 * firmware of ERP changes and the f/w takes care of things
2716 * like slot time and preamble.
2717 */
2718static void
2719bwn_updateslot(struct ieee80211com *ic)
2720{
2721	struct bwn_softc *sc = ic->ic_softc;
2722	struct bwn_mac *mac;
2723
2724	BWN_LOCK(sc);
2725	if (sc->sc_flags & BWN_FLAG_RUNNING) {
2726		mac = (struct bwn_mac *)sc->sc_curmac;
2727		bwn_set_slot_time(mac,
2728		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2729	}
2730	BWN_UNLOCK(sc);
2731}
2732
2733/*
2734 * Callback from the 802.11 layer after a promiscuous mode change.
2735 * Note this interface does not check the operating mode as this
2736 * is an internal callback and we are expected to honor the current
2737 * state (e.g. this is used for setting the interface in promiscuous
2738 * mode when operating in hostap mode to do ACS).
2739 */
2740static void
2741bwn_update_promisc(struct ieee80211com *ic)
2742{
2743	struct bwn_softc *sc = ic->ic_softc;
2744	struct bwn_mac *mac = sc->sc_curmac;
2745
2746	BWN_LOCK(sc);
2747	mac = sc->sc_curmac;
2748	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2749		if (ic->ic_promisc > 0)
2750			sc->sc_filters |= BWN_MACCTL_PROMISC;
2751		else
2752			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2753		bwn_set_opmode(mac);
2754	}
2755	BWN_UNLOCK(sc);
2756}
2757
2758/*
2759 * Callback from the 802.11 layer to update WME parameters.
2760 */
2761static int
2762bwn_wme_update(struct ieee80211com *ic)
2763{
2764	struct bwn_softc *sc = ic->ic_softc;
2765	struct bwn_mac *mac = sc->sc_curmac;
2766	struct wmeParams *wmep;
2767	int i;
2768
2769	BWN_LOCK(sc);
2770	mac = sc->sc_curmac;
2771	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2772		bwn_mac_suspend(mac);
2773		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2774			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2775			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2776		}
2777		bwn_mac_enable(mac);
2778	}
2779	BWN_UNLOCK(sc);
2780	return (0);
2781}
2782
2783static void
2784bwn_scan_start(struct ieee80211com *ic)
2785{
2786	struct bwn_softc *sc = ic->ic_softc;
2787	struct bwn_mac *mac;
2788
2789	BWN_LOCK(sc);
2790	mac = sc->sc_curmac;
2791	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2792		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2793		bwn_set_opmode(mac);
2794		/* disable CFP update during scan */
2795		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2796	}
2797	BWN_UNLOCK(sc);
2798}
2799
2800static void
2801bwn_scan_end(struct ieee80211com *ic)
2802{
2803	struct bwn_softc *sc = ic->ic_softc;
2804	struct bwn_mac *mac;
2805
2806	BWN_LOCK(sc);
2807	mac = sc->sc_curmac;
2808	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2809		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2810		bwn_set_opmode(mac);
2811		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2812	}
2813	BWN_UNLOCK(sc);
2814}
2815
2816static void
2817bwn_set_channel(struct ieee80211com *ic)
2818{
2819	struct bwn_softc *sc = ic->ic_softc;
2820	struct bwn_mac *mac = sc->sc_curmac;
2821	struct bwn_phy *phy = &mac->mac_phy;
2822	int chan, error;
2823
2824	BWN_LOCK(sc);
2825
2826	error = bwn_switch_band(sc, ic->ic_curchan);
2827	if (error)
2828		goto fail;
2829	bwn_mac_suspend(mac);
2830	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2831	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2832	if (chan != phy->chan)
2833		bwn_switch_channel(mac, chan);
2834
2835	/* TX power level */
2836	if (ic->ic_curchan->ic_maxpower != 0 &&
2837	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2838		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2839		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2840		    BWN_TXPWR_IGNORE_TSSI);
2841	}
2842
2843	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2844	if (phy->set_antenna)
2845		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2846
2847	if (sc->sc_rf_enabled != phy->rf_on) {
2848		if (sc->sc_rf_enabled) {
2849			bwn_rf_turnon(mac);
2850			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2851				device_printf(sc->sc_dev,
2852				    "please turn on the RF switch\n");
2853		} else
2854			bwn_rf_turnoff(mac);
2855	}
2856
2857	bwn_mac_enable(mac);
2858
2859fail:
2860	/*
2861	 * Setup radio tap channel freq and flags
2862	 */
2863	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2864		htole16(ic->ic_curchan->ic_freq);
2865	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2866		htole16(ic->ic_curchan->ic_flags & 0xffff);
2867
2868	BWN_UNLOCK(sc);
2869}
2870
2871static struct ieee80211vap *
2872bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2873    enum ieee80211_opmode opmode, int flags,
2874    const uint8_t bssid[IEEE80211_ADDR_LEN],
2875    const uint8_t mac[IEEE80211_ADDR_LEN])
2876{
2877	struct ieee80211vap *vap;
2878	struct bwn_vap *bvp;
2879
2880	switch (opmode) {
2881	case IEEE80211_M_HOSTAP:
2882	case IEEE80211_M_MBSS:
2883	case IEEE80211_M_STA:
2884	case IEEE80211_M_WDS:
2885	case IEEE80211_M_MONITOR:
2886	case IEEE80211_M_IBSS:
2887	case IEEE80211_M_AHDEMO:
2888		break;
2889	default:
2890		return (NULL);
2891	}
2892
2893	bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
2894	vap = &bvp->bv_vap;
2895	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
2896	/* override with driver methods */
2897	bvp->bv_newstate = vap->iv_newstate;
2898	vap->iv_newstate = bwn_newstate;
2899
2900	/* override max aid so sta's cannot assoc when we're out of sta id's */
2901	vap->iv_max_aid = BWN_STAID_MAX;
2902
2903	ieee80211_ratectl_init(vap);
2904
2905	/* complete setup */
2906	ieee80211_vap_attach(vap, ieee80211_media_change,
2907	    ieee80211_media_status, mac);
2908	return (vap);
2909}
2910
2911static void
2912bwn_vap_delete(struct ieee80211vap *vap)
2913{
2914	struct bwn_vap *bvp = BWN_VAP(vap);
2915
2916	ieee80211_ratectl_deinit(vap);
2917	ieee80211_vap_detach(vap);
2918	free(bvp, M_80211_VAP);
2919}
2920
2921static int
2922bwn_init(struct bwn_softc *sc)
2923{
2924	struct bwn_mac *mac;
2925	int error;
2926
2927	BWN_ASSERT_LOCKED(sc);
2928
2929	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
2930	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
2931	sc->sc_filters = 0;
2932	bwn_wme_clear(sc);
2933	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
2934	sc->sc_rf_enabled = 1;
2935
2936	mac = sc->sc_curmac;
2937	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
2938		error = bwn_core_init(mac);
2939		if (error != 0)
2940			return (error);
2941	}
2942	if (mac->mac_status == BWN_MAC_STATUS_INITED)
2943		bwn_core_start(mac);
2944
2945	bwn_set_opmode(mac);
2946	bwn_set_pretbtt(mac);
2947	bwn_spu_setdelay(mac, 0);
2948	bwn_set_macaddr(mac);
2949
2950	sc->sc_flags |= BWN_FLAG_RUNNING;
2951	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
2952	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
2953
2954	return (0);
2955}
2956
2957static void
2958bwn_stop(struct bwn_softc *sc)
2959{
2960	struct bwn_mac *mac = sc->sc_curmac;
2961
2962	BWN_ASSERT_LOCKED(sc);
2963
2964	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
2965		/* XXX FIXME opmode not based on VAP */
2966		bwn_set_opmode(mac);
2967		bwn_set_macaddr(mac);
2968	}
2969
2970	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
2971		bwn_core_stop(mac);
2972
2973	callout_stop(&sc->sc_led_blink_ch);
2974	sc->sc_led_blinking = 0;
2975
2976	bwn_core_exit(mac);
2977	sc->sc_rf_enabled = 0;
2978
2979	sc->sc_flags &= ~BWN_FLAG_RUNNING;
2980}
2981
2982static void
2983bwn_wme_clear(struct bwn_softc *sc)
2984{
2985#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
2986	struct wmeParams *p;
2987	unsigned int i;
2988
2989	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
2990	    ("%s:%d: fail", __func__, __LINE__));
2991
2992	for (i = 0; i < N(sc->sc_wmeParams); i++) {
2993		p = &(sc->sc_wmeParams[i]);
2994
2995		switch (bwn_wme_shm_offsets[i]) {
2996		case BWN_WME_VOICE:
2997			p->wmep_txopLimit = 0;
2998			p->wmep_aifsn = 2;
2999			/* XXX FIXME: log2(cwmin) */
3000			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3001			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3002			break;
3003		case BWN_WME_VIDEO:
3004			p->wmep_txopLimit = 0;
3005			p->wmep_aifsn = 2;
3006			/* XXX FIXME: log2(cwmin) */
3007			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3008			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3009			break;
3010		case BWN_WME_BESTEFFORT:
3011			p->wmep_txopLimit = 0;
3012			p->wmep_aifsn = 3;
3013			/* XXX FIXME: log2(cwmin) */
3014			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3015			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3016			break;
3017		case BWN_WME_BACKGROUND:
3018			p->wmep_txopLimit = 0;
3019			p->wmep_aifsn = 7;
3020			/* XXX FIXME: log2(cwmin) */
3021			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3022			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3023			break;
3024		default:
3025			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3026		}
3027	}
3028}
3029
3030static int
3031bwn_core_init(struct bwn_mac *mac)
3032{
3033	struct bwn_softc *sc = mac->mac_sc;
3034	uint64_t hf;
3035	int error;
3036
3037	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3038	    ("%s:%d: fail", __func__, __LINE__));
3039
3040	siba_powerup(sc->sc_dev, 0);
3041	if (!siba_dev_isup(sc->sc_dev))
3042		bwn_reset_core(mac,
3043		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3044
3045	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3046	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3047	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3048	BWN_GETTIME(mac->mac_phy.nexttime);
3049	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3050	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3051	mac->mac_stats.link_noise = -95;
3052	mac->mac_reason_intr = 0;
3053	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3054	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3055#ifdef BWN_DEBUG
3056	if (sc->sc_debug & BWN_DEBUG_XMIT)
3057		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3058#endif
3059	mac->mac_suspended = 1;
3060	mac->mac_task_state = 0;
3061	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3062
3063	mac->mac_phy.init_pre(mac);
3064
3065	siba_pcicore_intr(sc->sc_dev);
3066
3067	siba_fix_imcfglobug(sc->sc_dev);
3068	bwn_bt_disable(mac);
3069	if (mac->mac_phy.prepare_hw) {
3070		error = mac->mac_phy.prepare_hw(mac);
3071		if (error)
3072			goto fail0;
3073	}
3074	error = bwn_chip_init(mac);
3075	if (error)
3076		goto fail0;
3077	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3078	    siba_get_revid(sc->sc_dev));
3079	hf = bwn_hf_read(mac);
3080	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3081		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3082		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3083			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3084		if (mac->mac_phy.rev == 1)
3085			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3086	}
3087	if (mac->mac_phy.rf_ver == 0x2050) {
3088		if (mac->mac_phy.rf_rev < 6)
3089			hf |= BWN_HF_FORCE_VCO_RECALC;
3090		if (mac->mac_phy.rf_rev == 6)
3091			hf |= BWN_HF_4318_TSSI;
3092	}
3093	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3094		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3095	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3096	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3097		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3098	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3099	bwn_hf_write(mac, hf);
3100
3101	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3102	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3103	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3104	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3105
3106	bwn_rate_init(mac);
3107	bwn_set_phytxctl(mac);
3108
3109	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3110	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3111	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3112
3113	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3114		bwn_pio_init(mac);
3115	else
3116		bwn_dma_init(mac);
3117	bwn_wme_init(mac);
3118	bwn_spu_setdelay(mac, 1);
3119	bwn_bt_enable(mac);
3120
3121	siba_powerup(sc->sc_dev,
3122	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3123	bwn_set_macaddr(mac);
3124	bwn_crypt_init(mac);
3125
3126	/* XXX LED initializatin */
3127
3128	mac->mac_status = BWN_MAC_STATUS_INITED;
3129
3130	return (error);
3131
3132fail0:
3133	siba_powerdown(sc->sc_dev);
3134	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3135	    ("%s:%d: fail", __func__, __LINE__));
3136	return (error);
3137}
3138
3139static void
3140bwn_core_start(struct bwn_mac *mac)
3141{
3142	struct bwn_softc *sc = mac->mac_sc;
3143	uint32_t tmp;
3144
3145	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3146	    ("%s:%d: fail", __func__, __LINE__));
3147
3148	if (siba_get_revid(sc->sc_dev) < 5)
3149		return;
3150
3151	while (1) {
3152		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3153		if (!(tmp & 0x00000001))
3154			break;
3155		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3156	}
3157
3158	bwn_mac_enable(mac);
3159	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3160	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3161
3162	mac->mac_status = BWN_MAC_STATUS_STARTED;
3163}
3164
3165static void
3166bwn_core_exit(struct bwn_mac *mac)
3167{
3168	struct bwn_softc *sc = mac->mac_sc;
3169	uint32_t macctl;
3170
3171	BWN_ASSERT_LOCKED(mac->mac_sc);
3172
3173	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3174	    ("%s:%d: fail", __func__, __LINE__));
3175
3176	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3177		return;
3178	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3179
3180	macctl = BWN_READ_4(mac, BWN_MACCTL);
3181	macctl &= ~BWN_MACCTL_MCODE_RUN;
3182	macctl |= BWN_MACCTL_MCODE_JMP0;
3183	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3184
3185	bwn_dma_stop(mac);
3186	bwn_pio_stop(mac);
3187	bwn_chip_exit(mac);
3188	mac->mac_phy.switch_analog(mac, 0);
3189	siba_dev_down(sc->sc_dev, 0);
3190	siba_powerdown(sc->sc_dev);
3191}
3192
3193static void
3194bwn_bt_disable(struct bwn_mac *mac)
3195{
3196	struct bwn_softc *sc = mac->mac_sc;
3197
3198	(void)sc;
3199	/* XXX do nothing yet */
3200}
3201
3202static int
3203bwn_chip_init(struct bwn_mac *mac)
3204{
3205	struct bwn_softc *sc = mac->mac_sc;
3206	struct bwn_phy *phy = &mac->mac_phy;
3207	uint32_t macctl;
3208	int error;
3209
3210	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3211	if (phy->gmode)
3212		macctl |= BWN_MACCTL_GMODE;
3213	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3214
3215	error = bwn_fw_fillinfo(mac);
3216	if (error)
3217		return (error);
3218	error = bwn_fw_loaducode(mac);
3219	if (error)
3220		return (error);
3221
3222	error = bwn_gpio_init(mac);
3223	if (error)
3224		return (error);
3225
3226	error = bwn_fw_loadinitvals(mac);
3227	if (error) {
3228		siba_gpio_set(sc->sc_dev, 0);
3229		return (error);
3230	}
3231	phy->switch_analog(mac, 1);
3232	error = bwn_phy_init(mac);
3233	if (error) {
3234		siba_gpio_set(sc->sc_dev, 0);
3235		return (error);
3236	}
3237	if (phy->set_im)
3238		phy->set_im(mac, BWN_IMMODE_NONE);
3239	if (phy->set_antenna)
3240		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3241	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3242
3243	if (phy->type == BWN_PHYTYPE_B)
3244		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3245	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3246	if (siba_get_revid(sc->sc_dev) < 5)
3247		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3248
3249	BWN_WRITE_4(mac, BWN_MACCTL,
3250	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3251	BWN_WRITE_4(mac, BWN_MACCTL,
3252	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3253	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3254
3255	bwn_set_opmode(mac);
3256	if (siba_get_revid(sc->sc_dev) < 3) {
3257		BWN_WRITE_2(mac, 0x060e, 0x0000);
3258		BWN_WRITE_2(mac, 0x0610, 0x8000);
3259		BWN_WRITE_2(mac, 0x0604, 0x0000);
3260		BWN_WRITE_2(mac, 0x0606, 0x0200);
3261	} else {
3262		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3263		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3264	}
3265	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3266	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3267	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3268	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3269	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3270	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3271	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3272	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3273	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3274	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3275	return (error);
3276}
3277
3278/* read hostflags */
3279static uint64_t
3280bwn_hf_read(struct bwn_mac *mac)
3281{
3282	uint64_t ret;
3283
3284	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3285	ret <<= 16;
3286	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3287	ret <<= 16;
3288	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3289	return (ret);
3290}
3291
3292static void
3293bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3294{
3295
3296	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3297	    (value & 0x00000000ffffull));
3298	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3299	    (value & 0x0000ffff0000ull) >> 16);
3300	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3301	    (value & 0xffff00000000ULL) >> 32);
3302}
3303
3304static void
3305bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3306{
3307
3308	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3309	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3310}
3311
3312static void
3313bwn_rate_init(struct bwn_mac *mac)
3314{
3315
3316	switch (mac->mac_phy.type) {
3317	case BWN_PHYTYPE_A:
3318	case BWN_PHYTYPE_G:
3319	case BWN_PHYTYPE_LP:
3320	case BWN_PHYTYPE_N:
3321		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3322		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3323		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3324		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3325		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3326		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3327		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3328		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3329			break;
3330		/* FALLTHROUGH */
3331	case BWN_PHYTYPE_B:
3332		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3333		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3334		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3335		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3336		break;
3337	default:
3338		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3339	}
3340}
3341
3342static void
3343bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3344{
3345	uint16_t offset;
3346
3347	if (ofdm) {
3348		offset = 0x480;
3349		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3350	} else {
3351		offset = 0x4c0;
3352		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3353	}
3354	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3355	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3356}
3357
3358static uint8_t
3359bwn_plcp_getcck(const uint8_t bitrate)
3360{
3361
3362	switch (bitrate) {
3363	case BWN_CCK_RATE_1MB:
3364		return (0x0a);
3365	case BWN_CCK_RATE_2MB:
3366		return (0x14);
3367	case BWN_CCK_RATE_5MB:
3368		return (0x37);
3369	case BWN_CCK_RATE_11MB:
3370		return (0x6e);
3371	}
3372	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3373	return (0);
3374}
3375
3376static uint8_t
3377bwn_plcp_getofdm(const uint8_t bitrate)
3378{
3379
3380	switch (bitrate) {
3381	case BWN_OFDM_RATE_6MB:
3382		return (0xb);
3383	case BWN_OFDM_RATE_9MB:
3384		return (0xf);
3385	case BWN_OFDM_RATE_12MB:
3386		return (0xa);
3387	case BWN_OFDM_RATE_18MB:
3388		return (0xe);
3389	case BWN_OFDM_RATE_24MB:
3390		return (0x9);
3391	case BWN_OFDM_RATE_36MB:
3392		return (0xd);
3393	case BWN_OFDM_RATE_48MB:
3394		return (0x8);
3395	case BWN_OFDM_RATE_54MB:
3396		return (0xc);
3397	}
3398	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3399	return (0);
3400}
3401
3402static void
3403bwn_set_phytxctl(struct bwn_mac *mac)
3404{
3405	uint16_t ctl;
3406
3407	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3408	    BWN_TX_PHY_TXPWR);
3409	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3410	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3411	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3412}
3413
3414static void
3415bwn_pio_init(struct bwn_mac *mac)
3416{
3417	struct bwn_pio *pio = &mac->mac_method.pio;
3418
3419	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3420	    & ~BWN_MACCTL_BIGENDIAN);
3421	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3422
3423	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3424	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3425	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3426	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3427	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3428	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3429}
3430
3431static void
3432bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3433    int index)
3434{
3435	struct bwn_pio_txpkt *tp;
3436	struct bwn_softc *sc = mac->mac_sc;
3437	unsigned int i;
3438
3439	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3440	tq->tq_index = index;
3441
3442	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3443	if (siba_get_revid(sc->sc_dev) >= 8)
3444		tq->tq_size = 1920;
3445	else {
3446		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3447		tq->tq_size -= 80;
3448	}
3449
3450	TAILQ_INIT(&tq->tq_pktlist);
3451	for (i = 0; i < N(tq->tq_pkts); i++) {
3452		tp = &(tq->tq_pkts[i]);
3453		tp->tp_index = i;
3454		tp->tp_queue = tq;
3455		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3456	}
3457}
3458
3459static uint16_t
3460bwn_pio_idx2base(struct bwn_mac *mac, int index)
3461{
3462	struct bwn_softc *sc = mac->mac_sc;
3463	static const uint16_t bases[] = {
3464		BWN_PIO_BASE0,
3465		BWN_PIO_BASE1,
3466		BWN_PIO_BASE2,
3467		BWN_PIO_BASE3,
3468		BWN_PIO_BASE4,
3469		BWN_PIO_BASE5,
3470		BWN_PIO_BASE6,
3471		BWN_PIO_BASE7,
3472	};
3473	static const uint16_t bases_rev11[] = {
3474		BWN_PIO11_BASE0,
3475		BWN_PIO11_BASE1,
3476		BWN_PIO11_BASE2,
3477		BWN_PIO11_BASE3,
3478		BWN_PIO11_BASE4,
3479		BWN_PIO11_BASE5,
3480	};
3481
3482	if (siba_get_revid(sc->sc_dev) >= 11) {
3483		if (index >= N(bases_rev11))
3484			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3485		return (bases_rev11[index]);
3486	}
3487	if (index >= N(bases))
3488		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3489	return (bases[index]);
3490}
3491
3492static void
3493bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3494    int index)
3495{
3496	struct bwn_softc *sc = mac->mac_sc;
3497
3498	prq->prq_mac = mac;
3499	prq->prq_rev = siba_get_revid(sc->sc_dev);
3500	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3501	bwn_dma_rxdirectfifo(mac, index, 1);
3502}
3503
3504static void
3505bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3506{
3507	if (tq == NULL)
3508		return;
3509	bwn_pio_cancel_tx_packets(tq);
3510}
3511
3512static void
3513bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3514{
3515
3516	bwn_destroy_pioqueue_tx(pio);
3517}
3518
3519static uint16_t
3520bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3521    uint16_t offset)
3522{
3523
3524	return (BWN_READ_2(mac, tq->tq_base + offset));
3525}
3526
3527static void
3528bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3529{
3530	uint32_t ctl;
3531	int type;
3532	uint16_t base;
3533
3534	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3535	base = bwn_dma_base(type, idx);
3536	if (type == BWN_DMA_64BIT) {
3537		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3538		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3539		if (enable)
3540			ctl |= BWN_DMA64_RXDIRECTFIFO;
3541		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3542	} else {
3543		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3544		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3545		if (enable)
3546			ctl |= BWN_DMA32_RXDIRECTFIFO;
3547		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3548	}
3549}
3550
3551static uint64_t
3552bwn_dma_mask(struct bwn_mac *mac)
3553{
3554	uint32_t tmp;
3555	uint16_t base;
3556
3557	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3558	if (tmp & SIBA_TGSHIGH_DMA64)
3559		return (BWN_DMA_BIT_MASK(64));
3560	base = bwn_dma_base(0, 0);
3561	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3562	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3563	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3564		return (BWN_DMA_BIT_MASK(32));
3565
3566	return (BWN_DMA_BIT_MASK(30));
3567}
3568
3569static int
3570bwn_dma_mask2type(uint64_t dmamask)
3571{
3572
3573	if (dmamask == BWN_DMA_BIT_MASK(30))
3574		return (BWN_DMA_30BIT);
3575	if (dmamask == BWN_DMA_BIT_MASK(32))
3576		return (BWN_DMA_32BIT);
3577	if (dmamask == BWN_DMA_BIT_MASK(64))
3578		return (BWN_DMA_64BIT);
3579	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3580	return (BWN_DMA_30BIT);
3581}
3582
3583static void
3584bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3585{
3586	struct bwn_pio_txpkt *tp;
3587	unsigned int i;
3588
3589	for (i = 0; i < N(tq->tq_pkts); i++) {
3590		tp = &(tq->tq_pkts[i]);
3591		if (tp->tp_m) {
3592			m_freem(tp->tp_m);
3593			tp->tp_m = NULL;
3594		}
3595	}
3596}
3597
3598static uint16_t
3599bwn_dma_base(int type, int controller_idx)
3600{
3601	static const uint16_t map64[] = {
3602		BWN_DMA64_BASE0,
3603		BWN_DMA64_BASE1,
3604		BWN_DMA64_BASE2,
3605		BWN_DMA64_BASE3,
3606		BWN_DMA64_BASE4,
3607		BWN_DMA64_BASE5,
3608	};
3609	static const uint16_t map32[] = {
3610		BWN_DMA32_BASE0,
3611		BWN_DMA32_BASE1,
3612		BWN_DMA32_BASE2,
3613		BWN_DMA32_BASE3,
3614		BWN_DMA32_BASE4,
3615		BWN_DMA32_BASE5,
3616	};
3617
3618	if (type == BWN_DMA_64BIT) {
3619		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3620		    ("%s:%d: fail", __func__, __LINE__));
3621		return (map64[controller_idx]);
3622	}
3623	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3624	    ("%s:%d: fail", __func__, __LINE__));
3625	return (map32[controller_idx]);
3626}
3627
3628static void
3629bwn_dma_init(struct bwn_mac *mac)
3630{
3631	struct bwn_dma *dma = &mac->mac_method.dma;
3632
3633	/* setup TX DMA channels. */
3634	bwn_dma_setup(dma->wme[WME_AC_BK]);
3635	bwn_dma_setup(dma->wme[WME_AC_BE]);
3636	bwn_dma_setup(dma->wme[WME_AC_VI]);
3637	bwn_dma_setup(dma->wme[WME_AC_VO]);
3638	bwn_dma_setup(dma->mcast);
3639	/* setup RX DMA channel. */
3640	bwn_dma_setup(dma->rx);
3641}
3642
3643static struct bwn_dma_ring *
3644bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3645    int for_tx, int type)
3646{
3647	struct bwn_dma *dma = &mac->mac_method.dma;
3648	struct bwn_dma_ring *dr;
3649	struct bwn_dmadesc_generic *desc;
3650	struct bwn_dmadesc_meta *mt;
3651	struct bwn_softc *sc = mac->mac_sc;
3652	int error, i;
3653
3654	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3655	if (dr == NULL)
3656		goto out;
3657	dr->dr_numslots = BWN_RXRING_SLOTS;
3658	if (for_tx)
3659		dr->dr_numslots = BWN_TXRING_SLOTS;
3660
3661	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3662	    M_DEVBUF, M_NOWAIT | M_ZERO);
3663	if (dr->dr_meta == NULL)
3664		goto fail0;
3665
3666	dr->dr_type = type;
3667	dr->dr_mac = mac;
3668	dr->dr_base = bwn_dma_base(type, controller_index);
3669	dr->dr_index = controller_index;
3670	if (type == BWN_DMA_64BIT) {
3671		dr->getdesc = bwn_dma_64_getdesc;
3672		dr->setdesc = bwn_dma_64_setdesc;
3673		dr->start_transfer = bwn_dma_64_start_transfer;
3674		dr->suspend = bwn_dma_64_suspend;
3675		dr->resume = bwn_dma_64_resume;
3676		dr->get_curslot = bwn_dma_64_get_curslot;
3677		dr->set_curslot = bwn_dma_64_set_curslot;
3678	} else {
3679		dr->getdesc = bwn_dma_32_getdesc;
3680		dr->setdesc = bwn_dma_32_setdesc;
3681		dr->start_transfer = bwn_dma_32_start_transfer;
3682		dr->suspend = bwn_dma_32_suspend;
3683		dr->resume = bwn_dma_32_resume;
3684		dr->get_curslot = bwn_dma_32_get_curslot;
3685		dr->set_curslot = bwn_dma_32_set_curslot;
3686	}
3687	if (for_tx) {
3688		dr->dr_tx = 1;
3689		dr->dr_curslot = -1;
3690	} else {
3691		if (dr->dr_index == 0) {
3692			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3693			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3694		} else
3695			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3696	}
3697
3698	error = bwn_dma_allocringmemory(dr);
3699	if (error)
3700		goto fail2;
3701
3702	if (for_tx) {
3703		/*
3704		 * Assumption: BWN_TXRING_SLOTS can be divided by
3705		 * BWN_TX_SLOTS_PER_FRAME
3706		 */
3707		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3708		    ("%s:%d: fail", __func__, __LINE__));
3709
3710		dr->dr_txhdr_cache =
3711		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3712			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3713		KASSERT(dr->dr_txhdr_cache != NULL,
3714		    ("%s:%d: fail", __func__, __LINE__));
3715
3716		/*
3717		 * Create TX ring DMA stuffs
3718		 */
3719		error = bus_dma_tag_create(dma->parent_dtag,
3720				    BWN_ALIGN, 0,
3721				    BUS_SPACE_MAXADDR,
3722				    BUS_SPACE_MAXADDR,
3723				    NULL, NULL,
3724				    BWN_HDRSIZE(mac),
3725				    1,
3726				    BUS_SPACE_MAXSIZE_32BIT,
3727				    0,
3728				    NULL, NULL,
3729				    &dr->dr_txring_dtag);
3730		if (error) {
3731			device_printf(sc->sc_dev,
3732			    "can't create TX ring DMA tag: TODO frees\n");
3733			goto fail1;
3734		}
3735
3736		for (i = 0; i < dr->dr_numslots; i += 2) {
3737			dr->getdesc(dr, i, &desc, &mt);
3738
3739			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3740			mt->mt_m = NULL;
3741			mt->mt_ni = NULL;
3742			mt->mt_islast = 0;
3743			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3744			    &mt->mt_dmap);
3745			if (error) {
3746				device_printf(sc->sc_dev,
3747				     "can't create RX buf DMA map\n");
3748				goto fail1;
3749			}
3750
3751			dr->getdesc(dr, i + 1, &desc, &mt);
3752
3753			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3754			mt->mt_m = NULL;
3755			mt->mt_ni = NULL;
3756			mt->mt_islast = 1;
3757			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3758			    &mt->mt_dmap);
3759			if (error) {
3760				device_printf(sc->sc_dev,
3761				     "can't create RX buf DMA map\n");
3762				goto fail1;
3763			}
3764		}
3765	} else {
3766		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3767		    &dr->dr_spare_dmap);
3768		if (error) {
3769			device_printf(sc->sc_dev,
3770			    "can't create RX buf DMA map\n");
3771			goto out;		/* XXX wrong! */
3772		}
3773
3774		for (i = 0; i < dr->dr_numslots; i++) {
3775			dr->getdesc(dr, i, &desc, &mt);
3776
3777			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3778			    &mt->mt_dmap);
3779			if (error) {
3780				device_printf(sc->sc_dev,
3781				    "can't create RX buf DMA map\n");
3782				goto out;	/* XXX wrong! */
3783			}
3784			error = bwn_dma_newbuf(dr, desc, mt, 1);
3785			if (error) {
3786				device_printf(sc->sc_dev,
3787				    "failed to allocate RX buf\n");
3788				goto out;	/* XXX wrong! */
3789			}
3790		}
3791
3792		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3793		    BUS_DMASYNC_PREWRITE);
3794
3795		dr->dr_usedslot = dr->dr_numslots;
3796	}
3797
3798      out:
3799	return (dr);
3800
3801fail2:
3802	free(dr->dr_txhdr_cache, M_DEVBUF);
3803fail1:
3804	free(dr->dr_meta, M_DEVBUF);
3805fail0:
3806	free(dr, M_DEVBUF);
3807	return (NULL);
3808}
3809
3810static void
3811bwn_dma_ringfree(struct bwn_dma_ring **dr)
3812{
3813
3814	if (dr == NULL)
3815		return;
3816
3817	bwn_dma_free_descbufs(*dr);
3818	bwn_dma_free_ringmemory(*dr);
3819
3820	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3821	free((*dr)->dr_meta, M_DEVBUF);
3822	free(*dr, M_DEVBUF);
3823
3824	*dr = NULL;
3825}
3826
3827static void
3828bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3829    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3830{
3831	struct bwn_dmadesc32 *desc;
3832
3833	*meta = &(dr->dr_meta[slot]);
3834	desc = dr->dr_ring_descbase;
3835	desc = &(desc[slot]);
3836
3837	*gdesc = (struct bwn_dmadesc_generic *)desc;
3838}
3839
3840static void
3841bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3842    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3843    int start, int end, int irq)
3844{
3845	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3846	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3847	uint32_t addr, addrext, ctl;
3848	int slot;
3849
3850	slot = (int)(&(desc->dma.dma32) - descbase);
3851	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3852	    ("%s:%d: fail", __func__, __LINE__));
3853
3854	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3855	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3856	addr |= siba_dma_translation(sc->sc_dev);
3857	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3858	if (slot == dr->dr_numslots - 1)
3859		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3860	if (start)
3861		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3862	if (end)
3863		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3864	if (irq)
3865		ctl |= BWN_DMA32_DCTL_IRQ;
3866	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3867	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3868
3869	desc->dma.dma32.control = htole32(ctl);
3870	desc->dma.dma32.address = htole32(addr);
3871}
3872
3873static void
3874bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3875{
3876
3877	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3878	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3879}
3880
3881static void
3882bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3883{
3884
3885	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3886	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3887}
3888
3889static void
3890bwn_dma_32_resume(struct bwn_dma_ring *dr)
3891{
3892
3893	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3894	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3895}
3896
3897static int
3898bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3899{
3900	uint32_t val;
3901
3902	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
3903	val &= BWN_DMA32_RXDPTR;
3904
3905	return (val / sizeof(struct bwn_dmadesc32));
3906}
3907
3908static void
3909bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
3910{
3911
3912	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
3913	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
3914}
3915
3916static void
3917bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
3918    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3919{
3920	struct bwn_dmadesc64 *desc;
3921
3922	*meta = &(dr->dr_meta[slot]);
3923	desc = dr->dr_ring_descbase;
3924	desc = &(desc[slot]);
3925
3926	*gdesc = (struct bwn_dmadesc_generic *)desc;
3927}
3928
3929static void
3930bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
3931    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3932    int start, int end, int irq)
3933{
3934	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
3935	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3936	int slot;
3937	uint32_t ctl0 = 0, ctl1 = 0;
3938	uint32_t addrlo, addrhi;
3939	uint32_t addrext;
3940
3941	slot = (int)(&(desc->dma.dma64) - descbase);
3942	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3943	    ("%s:%d: fail", __func__, __LINE__));
3944
3945	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
3946	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
3947	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
3948	    30;
3949	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
3950	if (slot == dr->dr_numslots - 1)
3951		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
3952	if (start)
3953		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
3954	if (end)
3955		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
3956	if (irq)
3957		ctl0 |= BWN_DMA64_DCTL0_IRQ;
3958	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
3959	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
3960	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
3961
3962	desc->dma.dma64.control0 = htole32(ctl0);
3963	desc->dma.dma64.control1 = htole32(ctl1);
3964	desc->dma.dma64.address_low = htole32(addrlo);
3965	desc->dma.dma64.address_high = htole32(addrhi);
3966}
3967
3968static void
3969bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
3970{
3971
3972	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
3973	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3974}
3975
3976static void
3977bwn_dma_64_suspend(struct bwn_dma_ring *dr)
3978{
3979
3980	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3981	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
3982}
3983
3984static void
3985bwn_dma_64_resume(struct bwn_dma_ring *dr)
3986{
3987
3988	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3989	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
3990}
3991
3992static int
3993bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
3994{
3995	uint32_t val;
3996
3997	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
3998	val &= BWN_DMA64_RXSTATDPTR;
3999
4000	return (val / sizeof(struct bwn_dmadesc64));
4001}
4002
4003static void
4004bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4005{
4006
4007	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4008	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4009}
4010
4011static int
4012bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4013{
4014	struct bwn_mac *mac = dr->dr_mac;
4015	struct bwn_dma *dma = &mac->mac_method.dma;
4016	struct bwn_softc *sc = mac->mac_sc;
4017	int error;
4018
4019	error = bus_dma_tag_create(dma->parent_dtag,
4020			    BWN_ALIGN, 0,
4021			    BUS_SPACE_MAXADDR,
4022			    BUS_SPACE_MAXADDR,
4023			    NULL, NULL,
4024			    BWN_DMA_RINGMEMSIZE,
4025			    1,
4026			    BUS_SPACE_MAXSIZE_32BIT,
4027			    0,
4028			    NULL, NULL,
4029			    &dr->dr_ring_dtag);
4030	if (error) {
4031		device_printf(sc->sc_dev,
4032		    "can't create TX ring DMA tag: TODO frees\n");
4033		return (-1);
4034	}
4035
4036	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4037	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4038	    &dr->dr_ring_dmap);
4039	if (error) {
4040		device_printf(sc->sc_dev,
4041		    "can't allocate DMA mem: TODO frees\n");
4042		return (-1);
4043	}
4044	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4045	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4046	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4047	if (error) {
4048		device_printf(sc->sc_dev,
4049		    "can't load DMA mem: TODO free\n");
4050		return (-1);
4051	}
4052
4053	return (0);
4054}
4055
4056static void
4057bwn_dma_setup(struct bwn_dma_ring *dr)
4058{
4059	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4060	uint64_t ring64;
4061	uint32_t addrext, ring32, value;
4062	uint32_t trans = siba_dma_translation(sc->sc_dev);
4063
4064	if (dr->dr_tx) {
4065		dr->dr_curslot = -1;
4066
4067		if (dr->dr_type == BWN_DMA_64BIT) {
4068			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4069			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4070			    >> 30;
4071			value = BWN_DMA64_TXENABLE;
4072			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4073			    & BWN_DMA64_TXADDREXT_MASK;
4074			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4075			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4076			    (ring64 & 0xffffffff));
4077			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4078			    ((ring64 >> 32) &
4079			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4080		} else {
4081			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4082			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4083			value = BWN_DMA32_TXENABLE;
4084			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4085			    & BWN_DMA32_TXADDREXT_MASK;
4086			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4087			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4088			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4089		}
4090		return;
4091	}
4092
4093	/*
4094	 * set for RX
4095	 */
4096	dr->dr_usedslot = dr->dr_numslots;
4097
4098	if (dr->dr_type == BWN_DMA_64BIT) {
4099		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4100		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4101		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4102		value |= BWN_DMA64_RXENABLE;
4103		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4104		    & BWN_DMA64_RXADDREXT_MASK;
4105		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4106		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4107		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4108		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4109		    | (trans << 1));
4110		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4111		    sizeof(struct bwn_dmadesc64));
4112	} else {
4113		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4114		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4115		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4116		value |= BWN_DMA32_RXENABLE;
4117		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4118		    & BWN_DMA32_RXADDREXT_MASK;
4119		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4120		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4121		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4122		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4123		    sizeof(struct bwn_dmadesc32));
4124	}
4125}
4126
4127static void
4128bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4129{
4130
4131	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4132	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4133	    dr->dr_ring_dmap);
4134}
4135
4136static void
4137bwn_dma_cleanup(struct bwn_dma_ring *dr)
4138{
4139
4140	if (dr->dr_tx) {
4141		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4142		if (dr->dr_type == BWN_DMA_64BIT) {
4143			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4144			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4145		} else
4146			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4147	} else {
4148		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4149		if (dr->dr_type == BWN_DMA_64BIT) {
4150			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4151			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4152		} else
4153			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4154	}
4155}
4156
4157static void
4158bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4159{
4160	struct bwn_dmadesc_generic *desc;
4161	struct bwn_dmadesc_meta *meta;
4162	struct bwn_mac *mac = dr->dr_mac;
4163	struct bwn_dma *dma = &mac->mac_method.dma;
4164	struct bwn_softc *sc = mac->mac_sc;
4165	int i;
4166
4167	if (!dr->dr_usedslot)
4168		return;
4169	for (i = 0; i < dr->dr_numslots; i++) {
4170		dr->getdesc(dr, i, &desc, &meta);
4171
4172		if (meta->mt_m == NULL) {
4173			if (!dr->dr_tx)
4174				device_printf(sc->sc_dev, "%s: not TX?\n",
4175				    __func__);
4176			continue;
4177		}
4178		if (dr->dr_tx) {
4179			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4180				bus_dmamap_unload(dr->dr_txring_dtag,
4181				    meta->mt_dmap);
4182			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4183				bus_dmamap_unload(dma->txbuf_dtag,
4184				    meta->mt_dmap);
4185		} else
4186			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4187		bwn_dma_free_descbuf(dr, meta);
4188	}
4189}
4190
4191static int
4192bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4193    int type)
4194{
4195	struct bwn_softc *sc = mac->mac_sc;
4196	uint32_t value;
4197	int i;
4198	uint16_t offset;
4199
4200	for (i = 0; i < 10; i++) {
4201		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4202		    BWN_DMA32_TXSTATUS;
4203		value = BWN_READ_4(mac, base + offset);
4204		if (type == BWN_DMA_64BIT) {
4205			value &= BWN_DMA64_TXSTAT;
4206			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4207			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4208			    value == BWN_DMA64_TXSTAT_STOPPED)
4209				break;
4210		} else {
4211			value &= BWN_DMA32_TXSTATE;
4212			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4213			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4214			    value == BWN_DMA32_TXSTAT_STOPPED)
4215				break;
4216		}
4217		DELAY(1000);
4218	}
4219	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4220	BWN_WRITE_4(mac, base + offset, 0);
4221	for (i = 0; i < 10; i++) {
4222		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4223						   BWN_DMA32_TXSTATUS;
4224		value = BWN_READ_4(mac, base + offset);
4225		if (type == BWN_DMA_64BIT) {
4226			value &= BWN_DMA64_TXSTAT;
4227			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4228				i = -1;
4229				break;
4230			}
4231		} else {
4232			value &= BWN_DMA32_TXSTATE;
4233			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4234				i = -1;
4235				break;
4236			}
4237		}
4238		DELAY(1000);
4239	}
4240	if (i != -1) {
4241		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4242		return (ENODEV);
4243	}
4244	DELAY(1000);
4245
4246	return (0);
4247}
4248
4249static int
4250bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4251    int type)
4252{
4253	struct bwn_softc *sc = mac->mac_sc;
4254	uint32_t value;
4255	int i;
4256	uint16_t offset;
4257
4258	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4259	BWN_WRITE_4(mac, base + offset, 0);
4260	for (i = 0; i < 10; i++) {
4261		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4262		    BWN_DMA32_RXSTATUS;
4263		value = BWN_READ_4(mac, base + offset);
4264		if (type == BWN_DMA_64BIT) {
4265			value &= BWN_DMA64_RXSTAT;
4266			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4267				i = -1;
4268				break;
4269			}
4270		} else {
4271			value &= BWN_DMA32_RXSTATE;
4272			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4273				i = -1;
4274				break;
4275			}
4276		}
4277		DELAY(1000);
4278	}
4279	if (i != -1) {
4280		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4281		return (ENODEV);
4282	}
4283
4284	return (0);
4285}
4286
4287static void
4288bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4289    struct bwn_dmadesc_meta *meta)
4290{
4291
4292	if (meta->mt_m != NULL) {
4293		m_freem(meta->mt_m);
4294		meta->mt_m = NULL;
4295	}
4296	if (meta->mt_ni != NULL) {
4297		ieee80211_free_node(meta->mt_ni);
4298		meta->mt_ni = NULL;
4299	}
4300}
4301
4302static void
4303bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4304{
4305	struct bwn_rxhdr4 *rxhdr;
4306	unsigned char *frame;
4307
4308	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4309	rxhdr->frame_len = 0;
4310
4311	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4312	    sizeof(struct bwn_plcp6) + 2,
4313	    ("%s:%d: fail", __func__, __LINE__));
4314	frame = mtod(m, char *) + dr->dr_frameoffset;
4315	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4316}
4317
4318static uint8_t
4319bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4320{
4321	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4322
4323	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4324	    == 0xff);
4325}
4326
4327static void
4328bwn_wme_init(struct bwn_mac *mac)
4329{
4330
4331	bwn_wme_load(mac);
4332
4333	/* enable WME support. */
4334	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4335	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4336	    BWN_IFSCTL_USE_EDCF);
4337}
4338
4339static void
4340bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4341{
4342	struct bwn_softc *sc = mac->mac_sc;
4343	struct ieee80211com *ic = &sc->sc_ic;
4344	uint16_t delay;	/* microsec */
4345
4346	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4347	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4348		delay = 500;
4349	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4350		delay = max(delay, (uint16_t)2400);
4351
4352	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4353}
4354
4355static void
4356bwn_bt_enable(struct bwn_mac *mac)
4357{
4358	struct bwn_softc *sc = mac->mac_sc;
4359	uint64_t hf;
4360
4361	if (bwn_bluetooth == 0)
4362		return;
4363	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4364		return;
4365	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4366		return;
4367
4368	hf = bwn_hf_read(mac);
4369	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4370		hf |= BWN_HF_BT_COEXISTALT;
4371	else
4372		hf |= BWN_HF_BT_COEXIST;
4373	bwn_hf_write(mac, hf);
4374}
4375
4376static void
4377bwn_set_macaddr(struct bwn_mac *mac)
4378{
4379
4380	bwn_mac_write_bssid(mac);
4381	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
4382	    mac->mac_sc->sc_ic.ic_macaddr);
4383}
4384
4385static void
4386bwn_clear_keys(struct bwn_mac *mac)
4387{
4388	int i;
4389
4390	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4391		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4392		    ("%s:%d: fail", __func__, __LINE__));
4393
4394		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4395		    NULL, BWN_SEC_KEYSIZE, NULL);
4396		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4397			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4398			    NULL, BWN_SEC_KEYSIZE, NULL);
4399		}
4400		mac->mac_key[i].keyconf = NULL;
4401	}
4402}
4403
4404static void
4405bwn_crypt_init(struct bwn_mac *mac)
4406{
4407	struct bwn_softc *sc = mac->mac_sc;
4408
4409	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4410	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4411	    ("%s:%d: fail", __func__, __LINE__));
4412	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4413	mac->mac_ktp *= 2;
4414	if (siba_get_revid(sc->sc_dev) >= 5)
4415		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4416	bwn_clear_keys(mac);
4417}
4418
4419static void
4420bwn_chip_exit(struct bwn_mac *mac)
4421{
4422	struct bwn_softc *sc = mac->mac_sc;
4423
4424	bwn_phy_exit(mac);
4425	siba_gpio_set(sc->sc_dev, 0);
4426}
4427
4428static int
4429bwn_fw_fillinfo(struct bwn_mac *mac)
4430{
4431	int error;
4432
4433	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4434	if (error == 0)
4435		return (0);
4436	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4437	if (error == 0)
4438		return (0);
4439	return (error);
4440}
4441
4442static int
4443bwn_gpio_init(struct bwn_mac *mac)
4444{
4445	struct bwn_softc *sc = mac->mac_sc;
4446	uint32_t mask = 0x1f, set = 0xf, value;
4447
4448	BWN_WRITE_4(mac, BWN_MACCTL,
4449	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4450	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4451	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4452
4453	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4454		mask |= 0x0060;
4455		set |= 0x0060;
4456	}
4457	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4458		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4459		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4460		mask |= 0x0200;
4461		set |= 0x0200;
4462	}
4463	if (siba_get_revid(sc->sc_dev) >= 2)
4464		mask |= 0x0010;
4465
4466	value = siba_gpio_get(sc->sc_dev);
4467	if (value == -1)
4468		return (0);
4469	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4470
4471	return (0);
4472}
4473
4474static int
4475bwn_fw_loadinitvals(struct bwn_mac *mac)
4476{
4477#define	GETFWOFFSET(fwp, offset)				\
4478	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4479	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4480	const struct bwn_fwhdr *hdr;
4481	struct bwn_fw *fw = &mac->mac_fw;
4482	int error;
4483
4484	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4485	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4486	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4487	if (error)
4488		return (error);
4489	if (fw->initvals_band.fw) {
4490		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4491		error = bwn_fwinitvals_write(mac,
4492		    GETFWOFFSET(fw->initvals_band, hdr_len),
4493		    be32toh(hdr->size),
4494		    fw->initvals_band.fw->datasize - hdr_len);
4495	}
4496	return (error);
4497#undef GETFWOFFSET
4498}
4499
4500static int
4501bwn_phy_init(struct bwn_mac *mac)
4502{
4503	struct bwn_softc *sc = mac->mac_sc;
4504	int error;
4505
4506	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4507	mac->mac_phy.rf_onoff(mac, 1);
4508	error = mac->mac_phy.init(mac);
4509	if (error) {
4510		device_printf(sc->sc_dev, "PHY init failed\n");
4511		goto fail0;
4512	}
4513	error = bwn_switch_channel(mac,
4514	    mac->mac_phy.get_default_chan(mac));
4515	if (error) {
4516		device_printf(sc->sc_dev,
4517		    "failed to switch default channel\n");
4518		goto fail1;
4519	}
4520	return (0);
4521fail1:
4522	if (mac->mac_phy.exit)
4523		mac->mac_phy.exit(mac);
4524fail0:
4525	mac->mac_phy.rf_onoff(mac, 0);
4526
4527	return (error);
4528}
4529
4530static void
4531bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4532{
4533	uint16_t ant;
4534	uint16_t tmp;
4535
4536	ant = bwn_ant2phy(antenna);
4537
4538	/* For ACK/CTS */
4539	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4540	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4541	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4542	/* For Probe Resposes */
4543	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4544	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4545	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4546}
4547
4548static void
4549bwn_set_opmode(struct bwn_mac *mac)
4550{
4551	struct bwn_softc *sc = mac->mac_sc;
4552	struct ieee80211com *ic = &sc->sc_ic;
4553	uint32_t ctl;
4554	uint16_t cfp_pretbtt;
4555
4556	ctl = BWN_READ_4(mac, BWN_MACCTL);
4557	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4558	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4559	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4560	ctl |= BWN_MACCTL_STA;
4561
4562	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4563	    ic->ic_opmode == IEEE80211_M_MBSS)
4564		ctl |= BWN_MACCTL_HOSTAP;
4565	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4566		ctl &= ~BWN_MACCTL_STA;
4567	ctl |= sc->sc_filters;
4568
4569	if (siba_get_revid(sc->sc_dev) <= 4)
4570		ctl |= BWN_MACCTL_PROMISC;
4571
4572	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4573
4574	cfp_pretbtt = 2;
4575	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4576		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4577		    siba_get_chiprev(sc->sc_dev) == 3)
4578			cfp_pretbtt = 100;
4579		else
4580			cfp_pretbtt = 50;
4581	}
4582	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4583}
4584
4585static int
4586bwn_dma_gettype(struct bwn_mac *mac)
4587{
4588	uint32_t tmp;
4589	uint16_t base;
4590
4591	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4592	if (tmp & SIBA_TGSHIGH_DMA64)
4593		return (BWN_DMA_64BIT);
4594	base = bwn_dma_base(0, 0);
4595	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4596	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4597	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4598		return (BWN_DMA_32BIT);
4599
4600	return (BWN_DMA_30BIT);
4601}
4602
4603static void
4604bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4605{
4606	if (!error) {
4607		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4608		*((bus_addr_t *)arg) = seg->ds_addr;
4609	}
4610}
4611
4612static void
4613bwn_phy_g_init_sub(struct bwn_mac *mac)
4614{
4615	struct bwn_phy *phy = &mac->mac_phy;
4616	struct bwn_phy_g *pg = &phy->phy_g;
4617	struct bwn_softc *sc = mac->mac_sc;
4618	uint16_t i, tmp;
4619
4620	if (phy->rev == 1)
4621		bwn_phy_init_b5(mac);
4622	else
4623		bwn_phy_init_b6(mac);
4624
4625	if (phy->rev >= 2 || phy->gmode)
4626		bwn_phy_init_a(mac);
4627
4628	if (phy->rev >= 2) {
4629		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4630		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4631	}
4632	if (phy->rev == 2) {
4633		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4634		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4635	}
4636	if (phy->rev > 5) {
4637		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4638		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4639	}
4640	if (phy->gmode || phy->rev >= 2) {
4641		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4642		tmp &= BWN_PHYVER_VERSION;
4643		if (tmp == 3 || tmp == 5) {
4644			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4645			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4646		}
4647		if (tmp == 5) {
4648			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4649			    0x1f00);
4650		}
4651	}
4652	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4653		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4654	if (phy->rf_rev == 8) {
4655		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4656		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4657	}
4658	if (BWN_HAS_LOOPBACK(phy))
4659		bwn_loopback_calcgain(mac);
4660
4661	if (phy->rf_rev != 8) {
4662		if (pg->pg_initval == 0xffff)
4663			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4664		else
4665			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4666	}
4667	bwn_lo_g_init(mac);
4668	if (BWN_HAS_TXMAG(phy)) {
4669		BWN_RF_WRITE(mac, 0x52,
4670		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4671		    | pg->pg_loctl.tx_bias |
4672		    pg->pg_loctl.tx_magn);
4673	} else {
4674		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4675	}
4676	if (phy->rev >= 6) {
4677		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4678		    (pg->pg_loctl.tx_bias << 12));
4679	}
4680	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4681		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4682	else
4683		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4684	if (phy->rev < 2)
4685		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4686	else
4687		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4688	if (phy->gmode || phy->rev >= 2) {
4689		bwn_lo_g_adjust(mac);
4690		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4691	}
4692
4693	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4694		for (i = 0; i < 64; i++) {
4695			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4696			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4697			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4698			    -32), 31));
4699		}
4700		bwn_nrssi_threshold(mac);
4701	} else if (phy->gmode || phy->rev >= 2) {
4702		if (pg->pg_nrssi[0] == -1000) {
4703			KASSERT(pg->pg_nrssi[1] == -1000,
4704			    ("%s:%d: fail", __func__, __LINE__));
4705			bwn_nrssi_slope_11g(mac);
4706		} else
4707			bwn_nrssi_threshold(mac);
4708	}
4709	if (phy->rf_rev == 8)
4710		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4711	bwn_phy_hwpctl_init(mac);
4712	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4713	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4714		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4715		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4716	}
4717}
4718
4719static uint8_t
4720bwn_has_hwpctl(struct bwn_mac *mac)
4721{
4722
4723	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4724		return (0);
4725	return (mac->mac_phy.use_hwpctl(mac));
4726}
4727
4728static void
4729bwn_phy_init_b5(struct bwn_mac *mac)
4730{
4731	struct bwn_phy *phy = &mac->mac_phy;
4732	struct bwn_phy_g *pg = &phy->phy_g;
4733	struct bwn_softc *sc = mac->mac_sc;
4734	uint16_t offset, value;
4735	uint8_t old_channel;
4736
4737	if (phy->analog == 1)
4738		BWN_RF_SET(mac, 0x007a, 0x0050);
4739	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4740	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4741		value = 0x2120;
4742		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4743			BWN_PHY_WRITE(mac, offset, value);
4744			value += 0x202;
4745		}
4746	}
4747	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4748	if (phy->rf_ver == 0x2050)
4749		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4750
4751	if (phy->gmode || phy->rev >= 2) {
4752		if (phy->rf_ver == 0x2050) {
4753			BWN_RF_SET(mac, 0x007a, 0x0020);
4754			BWN_RF_SET(mac, 0x0051, 0x0004);
4755		}
4756		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4757
4758		BWN_PHY_SET(mac, 0x0802, 0x0100);
4759		BWN_PHY_SET(mac, 0x042b, 0x2000);
4760
4761		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4762
4763		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4764		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4765		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4766	}
4767
4768	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4769		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4770
4771	if (phy->analog == 1) {
4772		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4773		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4774		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4775		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4776		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4777	} else
4778		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4779	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4780	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4781
4782	if (phy->analog == 1)
4783		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4784	else
4785		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4786
4787	if (phy->analog == 0)
4788		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4789
4790	old_channel = phy->chan;
4791	bwn_phy_g_switch_chan(mac, 7, 0);
4792
4793	if (phy->rf_ver != 0x2050) {
4794		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4795		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4796	}
4797
4798	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4799	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4800
4801	if (phy->rf_ver == 0x2050) {
4802		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4803		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4804	}
4805
4806	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4807	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4808	BWN_RF_SET(mac, 0x007a, 0x0007);
4809
4810	bwn_phy_g_switch_chan(mac, old_channel, 0);
4811	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4812	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4813	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4814
4815	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4816	    pg->pg_txctl);
4817
4818	if (phy->rf_ver == 0x2050)
4819		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4820
4821	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4822}
4823
4824static void
4825bwn_loopback_calcgain(struct bwn_mac *mac)
4826{
4827	struct bwn_phy *phy = &mac->mac_phy;
4828	struct bwn_phy_g *pg = &phy->phy_g;
4829	struct bwn_softc *sc = mac->mac_sc;
4830	uint16_t backup_phy[16] = { 0 };
4831	uint16_t backup_radio[3];
4832	uint16_t backup_bband;
4833	uint16_t i, j, loop_i_max;
4834	uint16_t trsw_rx;
4835	uint16_t loop1_outer_done, loop1_inner_done;
4836
4837	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4838	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4839	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4840	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4841	if (phy->rev != 1) {
4842		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4843		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4844	}
4845	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4846	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4847	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4848	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4849	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4850	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4851	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4852	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4853	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4854	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4855	backup_bband = pg->pg_bbatt.att;
4856	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4857	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4858	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4859
4860	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4861	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4862	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4863	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4864	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4865	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4866	if (phy->rev != 1) {
4867		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4868		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4869		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4870		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4871	}
4872	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4873	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4874	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4875	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4876
4877	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4878	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4879	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4880
4881	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4882	if (phy->rev != 1) {
4883		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4884		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4885	}
4886	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4887
4888	if (phy->rf_rev == 8)
4889		BWN_RF_WRITE(mac, 0x43, 0x000f);
4890	else {
4891		BWN_RF_WRITE(mac, 0x52, 0);
4892		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4893	}
4894	bwn_phy_g_set_bbatt(mac, 11);
4895
4896	if (phy->rev >= 3)
4897		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4898	else
4899		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4900	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
4901
4902	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
4903	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
4904
4905	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
4906	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
4907
4908	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
4909		if (phy->rev >= 7) {
4910			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
4911			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
4912		}
4913	}
4914	BWN_RF_MASK(mac, 0x7a, 0x00f7);
4915
4916	j = 0;
4917	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
4918	for (i = 0; i < loop_i_max; i++) {
4919		for (j = 0; j < 16; j++) {
4920			BWN_RF_WRITE(mac, 0x43, i);
4921			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
4922			    (j << 8));
4923			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4924			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4925			DELAY(20);
4926			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4927				goto done0;
4928		}
4929	}
4930done0:
4931	loop1_outer_done = i;
4932	loop1_inner_done = j;
4933	if (j >= 8) {
4934		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
4935		trsw_rx = 0x1b;
4936		for (j = j - 8; j < 16; j++) {
4937			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
4938			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4939			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4940			DELAY(20);
4941			trsw_rx -= 3;
4942			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4943				goto done1;
4944		}
4945	} else
4946		trsw_rx = 0x18;
4947done1:
4948
4949	if (phy->rev != 1) {
4950		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
4951		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
4952	}
4953	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
4954	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
4955	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
4956	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
4957	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
4958	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
4959	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
4960	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
4961	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
4962
4963	bwn_phy_g_set_bbatt(mac, backup_bband);
4964
4965	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
4966	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
4967	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
4968
4969	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
4970	DELAY(10);
4971	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
4972	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
4973	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
4974	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
4975
4976	pg->pg_max_lb_gain =
4977	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
4978	pg->pg_trsw_rx_gain = trsw_rx * 2;
4979}
4980
4981static uint16_t
4982bwn_rf_init_bcm2050(struct bwn_mac *mac)
4983{
4984	struct bwn_phy *phy = &mac->mac_phy;
4985	uint32_t tmp1 = 0, tmp2 = 0;
4986	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
4987	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
4988	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
4989	static const uint8_t rcc_table[] = {
4990		0x02, 0x03, 0x01, 0x0f,
4991		0x06, 0x07, 0x05, 0x0f,
4992		0x0a, 0x0b, 0x09, 0x0f,
4993		0x0e, 0x0f, 0x0d, 0x0f,
4994	};
4995
4996	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
4997	    rfoverval = rfover = cck3 = 0;
4998	radio0 = BWN_RF_READ(mac, 0x43);
4999	radio1 = BWN_RF_READ(mac, 0x51);
5000	radio2 = BWN_RF_READ(mac, 0x52);
5001	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5002	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5003	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5004	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5005
5006	if (phy->type == BWN_PHYTYPE_B) {
5007		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5008		reg0 = BWN_READ_2(mac, 0x3ec);
5009
5010		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5011		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5012	} else if (phy->gmode || phy->rev >= 2) {
5013		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5014		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5015		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5016		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5017		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5018		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5019
5020		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5021		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5022		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5023		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5024		if (BWN_HAS_LOOPBACK(phy)) {
5025			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5026			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5027			if (phy->rev >= 3)
5028				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5029			else
5030				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5031			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5032		}
5033
5034		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5035		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5036			BWN_LPD(0, 1, 1)));
5037		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5038		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5039	}
5040	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5041
5042	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5043	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5044	reg1 = BWN_READ_2(mac, 0x3e6);
5045	reg2 = BWN_READ_2(mac, 0x3f4);
5046
5047	if (phy->analog == 0)
5048		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5049	else {
5050		if (phy->analog >= 2)
5051			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5052		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5053		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5054	}
5055
5056	reg = BWN_RF_READ(mac, 0x60);
5057	index = (reg & 0x001e) >> 1;
5058	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5059
5060	if (phy->type == BWN_PHYTYPE_B)
5061		BWN_RF_WRITE(mac, 0x78, 0x26);
5062	if (phy->gmode || phy->rev >= 2) {
5063		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5064		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5065			BWN_LPD(0, 1, 1)));
5066	}
5067	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5068	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5069	if (phy->gmode || phy->rev >= 2) {
5070		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5071		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5072			BWN_LPD(0, 0, 1)));
5073	}
5074	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5075	BWN_RF_SET(mac, 0x51, 0x0004);
5076	if (phy->rf_rev == 8)
5077		BWN_RF_WRITE(mac, 0x43, 0x1f);
5078	else {
5079		BWN_RF_WRITE(mac, 0x52, 0);
5080		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5081	}
5082	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5083
5084	for (i = 0; i < 16; i++) {
5085		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5086		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5087		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5088		if (phy->gmode || phy->rev >= 2) {
5089			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5090			    bwn_rf_2050_rfoverval(mac,
5091				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5092		}
5093		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5094		DELAY(10);
5095		if (phy->gmode || phy->rev >= 2) {
5096			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5097			    bwn_rf_2050_rfoverval(mac,
5098				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5099		}
5100		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5101		DELAY(10);
5102		if (phy->gmode || phy->rev >= 2) {
5103			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5104			    bwn_rf_2050_rfoverval(mac,
5105				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5106		}
5107		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5108		DELAY(20);
5109		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5110		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5111		if (phy->gmode || phy->rev >= 2) {
5112			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5113			    bwn_rf_2050_rfoverval(mac,
5114				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5115		}
5116		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5117	}
5118	DELAY(10);
5119
5120	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5121	tmp1++;
5122	tmp1 >>= 9;
5123
5124	for (i = 0; i < 16; i++) {
5125		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5126		BWN_RF_WRITE(mac, 0x78, radio78);
5127		DELAY(10);
5128		for (j = 0; j < 16; j++) {
5129			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5130			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5131			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5132			if (phy->gmode || phy->rev >= 2) {
5133				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5134				    bwn_rf_2050_rfoverval(mac,
5135					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5136			}
5137			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5138			DELAY(10);
5139			if (phy->gmode || phy->rev >= 2) {
5140				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5141				    bwn_rf_2050_rfoverval(mac,
5142					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5143			}
5144			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5145			DELAY(10);
5146			if (phy->gmode || phy->rev >= 2) {
5147				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5148				    bwn_rf_2050_rfoverval(mac,
5149					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5150			}
5151			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5152			DELAY(10);
5153			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5154			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5155			if (phy->gmode || phy->rev >= 2) {
5156				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5157				    bwn_rf_2050_rfoverval(mac,
5158					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5159			}
5160			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5161		}
5162		tmp2++;
5163		tmp2 >>= 8;
5164		if (tmp1 < tmp2)
5165			break;
5166	}
5167
5168	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5169	BWN_RF_WRITE(mac, 0x51, radio1);
5170	BWN_RF_WRITE(mac, 0x52, radio2);
5171	BWN_RF_WRITE(mac, 0x43, radio0);
5172	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5173	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5174	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5175	BWN_WRITE_2(mac, 0x3e6, reg1);
5176	if (phy->analog != 0)
5177		BWN_WRITE_2(mac, 0x3f4, reg2);
5178	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5179	bwn_spu_workaround(mac, phy->chan);
5180	if (phy->type == BWN_PHYTYPE_B) {
5181		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5182		BWN_WRITE_2(mac, 0x3ec, reg0);
5183	} else if (phy->gmode) {
5184		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5185			    BWN_READ_2(mac, BWN_PHY_RADIO)
5186			    & 0x7fff);
5187		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5188		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5189		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5190		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5191			      analogoverval);
5192		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5193		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5194		if (BWN_HAS_LOOPBACK(phy)) {
5195			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5196			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5197		}
5198	}
5199
5200	return ((i > 15) ? radio78 : rcc);
5201}
5202
5203static void
5204bwn_phy_init_b6(struct bwn_mac *mac)
5205{
5206	struct bwn_phy *phy = &mac->mac_phy;
5207	struct bwn_phy_g *pg = &phy->phy_g;
5208	struct bwn_softc *sc = mac->mac_sc;
5209	uint16_t offset, val;
5210	uint8_t old_channel;
5211
5212	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5213	    ("%s:%d: fail", __func__, __LINE__));
5214
5215	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5216	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5217	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5218		BWN_RF_WRITE(mac, 0x51, 0x37);
5219		BWN_RF_WRITE(mac, 0x52, 0x70);
5220		BWN_RF_WRITE(mac, 0x53, 0xb3);
5221		BWN_RF_WRITE(mac, 0x54, 0x9b);
5222		BWN_RF_WRITE(mac, 0x5a, 0x88);
5223		BWN_RF_WRITE(mac, 0x5b, 0x88);
5224		BWN_RF_WRITE(mac, 0x5d, 0x88);
5225		BWN_RF_WRITE(mac, 0x5e, 0x88);
5226		BWN_RF_WRITE(mac, 0x7d, 0x88);
5227		bwn_hf_write(mac,
5228		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5229	}
5230	if (phy->rf_rev == 8) {
5231		BWN_RF_WRITE(mac, 0x51, 0);
5232		BWN_RF_WRITE(mac, 0x52, 0x40);
5233		BWN_RF_WRITE(mac, 0x53, 0xb7);
5234		BWN_RF_WRITE(mac, 0x54, 0x98);
5235		BWN_RF_WRITE(mac, 0x5a, 0x88);
5236		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5237		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5238		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5239			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5240			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5241		} else {
5242			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5243			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5244		}
5245		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5246		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5247		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5248		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5249	}
5250	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5251		BWN_PHY_WRITE(mac, offset, val);
5252		val -= 0x0202;
5253	}
5254	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5255		BWN_PHY_WRITE(mac, offset, val);
5256		val -= 0x0202;
5257	}
5258	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5259		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5260		val += 0x0202;
5261	}
5262	if (phy->type == BWN_PHYTYPE_G) {
5263		BWN_RF_SET(mac, 0x007a, 0x0020);
5264		BWN_RF_SET(mac, 0x0051, 0x0004);
5265		BWN_PHY_SET(mac, 0x0802, 0x0100);
5266		BWN_PHY_SET(mac, 0x042b, 0x2000);
5267		BWN_PHY_WRITE(mac, 0x5b, 0);
5268		BWN_PHY_WRITE(mac, 0x5c, 0);
5269	}
5270
5271	old_channel = phy->chan;
5272	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5273
5274	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5275	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5276	DELAY(40);
5277	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5278		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5279		BWN_RF_WRITE(mac, 0x50, 0x20);
5280	}
5281	if (phy->rf_rev <= 2) {
5282		BWN_RF_WRITE(mac, 0x7c, 0x20);
5283		BWN_RF_WRITE(mac, 0x5a, 0x70);
5284		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5285		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5286	}
5287	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5288
5289	bwn_phy_g_switch_chan(mac, old_channel, 0);
5290
5291	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5292	if (phy->rf_rev >= 6)
5293		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5294	else
5295		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5296	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5297	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5298	    pg->pg_txctl);
5299	if (phy->rf_rev <= 5)
5300		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5301	if (phy->rf_rev <= 2)
5302		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5303
5304	if (phy->analog == 4) {
5305		BWN_WRITE_2(mac, 0x3e4, 9);
5306		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5307	} else
5308		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5309	if (phy->type == BWN_PHYTYPE_B)
5310		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5311	else if (phy->type == BWN_PHYTYPE_G)
5312		BWN_WRITE_2(mac, 0x03e6, 0x0);
5313}
5314
5315static void
5316bwn_phy_init_a(struct bwn_mac *mac)
5317{
5318	struct bwn_phy *phy = &mac->mac_phy;
5319	struct bwn_softc *sc = mac->mac_sc;
5320
5321	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5322	    ("%s:%d: fail", __func__, __LINE__));
5323
5324	if (phy->rev >= 6) {
5325		if (phy->type == BWN_PHYTYPE_A)
5326			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5327		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5328			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5329		else
5330			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5331	}
5332
5333	bwn_wa_init(mac);
5334
5335	if (phy->type == BWN_PHYTYPE_G &&
5336	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5337		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5338}
5339
5340static void
5341bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5342{
5343	int i;
5344
5345	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5346		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5347}
5348
5349static void
5350bwn_wa_agc(struct bwn_mac *mac)
5351{
5352	struct bwn_phy *phy = &mac->mac_phy;
5353
5354	if (phy->rev == 1) {
5355		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5356		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5357		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5358		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5359		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5360		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5361		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5362		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5363		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5364	} else {
5365		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5366		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5367		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5368		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5369	}
5370
5371	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5372	    0x5700);
5373	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5374	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5375	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5376	BWN_RF_SET(mac, 0x7a, 0x0008);
5377	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5378	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5379	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5380	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5381	if (phy->rev == 1)
5382		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5383	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5384	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5385	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5386	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5387	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5388	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5389	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5390	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5391	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5392	if (phy->rev == 1) {
5393		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5394		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5395	} else {
5396		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5397		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5398		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5399		if (phy->rev >= 6) {
5400			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5401			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5402			    (uint16_t)~0xf000, 0x3000);
5403		}
5404	}
5405	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5406	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5407	if (phy->rev == 1) {
5408		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5409		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5410		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5411		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5412		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5413		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5414		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5415		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5416	} else {
5417		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5418		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5419		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5420		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5421	}
5422	if (phy->rev >= 6) {
5423		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5424		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5425	}
5426	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5427}
5428
5429static void
5430bwn_wa_grev1(struct bwn_mac *mac)
5431{
5432	struct bwn_phy *phy = &mac->mac_phy;
5433	int i;
5434	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5435	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5436	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5437
5438	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5439
5440	/* init CRSTHRES and ANTDWELL */
5441	if (phy->rev == 1) {
5442		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5443	} else if (phy->rev == 2) {
5444		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5445		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5446		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5447	} else {
5448		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5449		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5450		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5451		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5452	}
5453	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5454	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5455	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5456
5457	/* XXX support PHY-A??? */
5458	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5459		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5460		    bwn_tab_finefreqg[i]);
5461
5462	/* XXX support PHY-A??? */
5463	if (phy->rev == 1)
5464		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5465			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5466			    bwn_tab_noise_g1[i]);
5467	else
5468		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5469			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5470			    bwn_tab_noise_g2[i]);
5471
5472
5473	for (i = 0; i < N(bwn_tab_rotor); i++)
5474		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5475		    bwn_tab_rotor[i]);
5476
5477	/* XXX support PHY-A??? */
5478	if (phy->rev >= 6) {
5479		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5480		    BWN_PHY_ENCORE_EN)
5481			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5482		else
5483			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5484	} else
5485		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5486
5487	for (i = 0; i < N(bwn_tab_retard); i++)
5488		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5489		    bwn_tab_retard[i]);
5490
5491	if (phy->rev == 1) {
5492		for (i = 0; i < 16; i++)
5493			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5494			    i, 0x0020);
5495	} else {
5496		for (i = 0; i < 32; i++)
5497			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5498	}
5499
5500	bwn_wa_agc(mac);
5501}
5502
5503static void
5504bwn_wa_grev26789(struct bwn_mac *mac)
5505{
5506	struct bwn_phy *phy = &mac->mac_phy;
5507	int i;
5508	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5509	uint16_t ofdmrev;
5510
5511	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5512
5513	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5514
5515	/* init CRSTHRES and ANTDWELL */
5516	if (phy->rev == 1)
5517		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5518	else if (phy->rev == 2) {
5519		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5520		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5521		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5522	} else {
5523		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5524		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5525		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5526		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5527	}
5528
5529	for (i = 0; i < 64; i++)
5530		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5531
5532	/* XXX support PHY-A??? */
5533	if (phy->rev == 1)
5534		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5535			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5536			    bwn_tab_noise_g1[i]);
5537	else
5538		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5539			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5540			    bwn_tab_noise_g2[i]);
5541
5542	/* XXX support PHY-A??? */
5543	if (phy->rev >= 6) {
5544		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5545		    BWN_PHY_ENCORE_EN)
5546			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5547		else
5548			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5549	} else
5550		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5551
5552	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5553		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5554		    bwn_tab_sigmasqr2[i]);
5555
5556	if (phy->rev == 1) {
5557		for (i = 0; i < 16; i++)
5558			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5559			    0x0020);
5560	} else {
5561		for (i = 0; i < 32; i++)
5562			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5563	}
5564
5565	bwn_wa_agc(mac);
5566
5567	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5568	if (ofdmrev > 2) {
5569		if (phy->type == BWN_PHYTYPE_A)
5570			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5571		else
5572			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5573	} else {
5574		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5575		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5576		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5577	}
5578
5579	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5580	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5581}
5582
5583static void
5584bwn_wa_init(struct bwn_mac *mac)
5585{
5586	struct bwn_phy *phy = &mac->mac_phy;
5587	struct bwn_softc *sc = mac->mac_sc;
5588
5589	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5590
5591	switch (phy->rev) {
5592	case 1:
5593		bwn_wa_grev1(mac);
5594		break;
5595	case 2:
5596	case 6:
5597	case 7:
5598	case 8:
5599	case 9:
5600		bwn_wa_grev26789(mac);
5601		break;
5602	default:
5603		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5604	}
5605
5606	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5607	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5608	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5609		if (phy->rev < 2) {
5610			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5611			    0x0002);
5612			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5613			    0x0001);
5614		} else {
5615			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5616			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5617			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5618			     BWN_BFL_EXTLNA) &&
5619			    (phy->rev >= 7)) {
5620				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5621				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5622				    0x0020, 0x0001);
5623				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5624				    0x0021, 0x0001);
5625				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5626				    0x0022, 0x0001);
5627				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5628				    0x0023, 0x0000);
5629				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5630				    0x0000, 0x0000);
5631				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5632				    0x0003, 0x0002);
5633			}
5634		}
5635	}
5636	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5637		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5638		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5639	}
5640
5641	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5642	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5643}
5644
5645static void
5646bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5647    uint16_t value)
5648{
5649	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5650	uint16_t addr;
5651
5652	addr = table + offset;
5653	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5654	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5655		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5656		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5657	}
5658	pg->pg_ofdmtab_addr = addr;
5659	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5660}
5661
5662static void
5663bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5664    uint32_t value)
5665{
5666	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5667	uint16_t addr;
5668
5669	addr = table + offset;
5670	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5671	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5672		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5673		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5674	}
5675	pg->pg_ofdmtab_addr = addr;
5676
5677	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5678	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5679}
5680
5681static void
5682bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5683    uint16_t value)
5684{
5685
5686	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5687	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5688}
5689
5690static void
5691bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5692{
5693	struct bwn_phy *phy = &mac->mac_phy;
5694	struct bwn_softc *sc = mac->mac_sc;
5695	unsigned int i, max_loop;
5696	uint16_t value;
5697	uint32_t buffer[5] = {
5698		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5699	};
5700
5701	if (ofdm) {
5702		max_loop = 0x1e;
5703		buffer[0] = 0x000201cc;
5704	} else {
5705		max_loop = 0xfa;
5706		buffer[0] = 0x000b846e;
5707	}
5708
5709	BWN_ASSERT_LOCKED(mac->mac_sc);
5710
5711	for (i = 0; i < 5; i++)
5712		bwn_ram_write(mac, i * 4, buffer[i]);
5713
5714	BWN_WRITE_2(mac, 0x0568, 0x0000);
5715	BWN_WRITE_2(mac, 0x07c0,
5716	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5717	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5718	BWN_WRITE_2(mac, 0x050c, value);
5719	if (phy->type == BWN_PHYTYPE_LP)
5720		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5721	BWN_WRITE_2(mac, 0x0508, 0x0000);
5722	BWN_WRITE_2(mac, 0x050a, 0x0000);
5723	BWN_WRITE_2(mac, 0x054c, 0x0000);
5724	BWN_WRITE_2(mac, 0x056a, 0x0014);
5725	BWN_WRITE_2(mac, 0x0568, 0x0826);
5726	BWN_WRITE_2(mac, 0x0500, 0x0000);
5727	if (phy->type == BWN_PHYTYPE_LP)
5728		BWN_WRITE_2(mac, 0x0502, 0x0050);
5729	else
5730		BWN_WRITE_2(mac, 0x0502, 0x0030);
5731
5732	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5733		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5734	for (i = 0x00; i < max_loop; i++) {
5735		value = BWN_READ_2(mac, 0x050e);
5736		if (value & 0x0080)
5737			break;
5738		DELAY(10);
5739	}
5740	for (i = 0x00; i < 0x0a; i++) {
5741		value = BWN_READ_2(mac, 0x050e);
5742		if (value & 0x0400)
5743			break;
5744		DELAY(10);
5745	}
5746	for (i = 0x00; i < 0x19; i++) {
5747		value = BWN_READ_2(mac, 0x0690);
5748		if (!(value & 0x0100))
5749			break;
5750		DELAY(10);
5751	}
5752	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5753		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5754}
5755
5756static void
5757bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5758{
5759	uint32_t macctl;
5760
5761	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5762
5763	macctl = BWN_READ_4(mac, BWN_MACCTL);
5764	if (macctl & BWN_MACCTL_BIGENDIAN)
5765		printf("TODO: need swap\n");
5766
5767	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5768	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5769	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5770}
5771
5772static void
5773bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5774{
5775	uint16_t value;
5776
5777	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5778	    ("%s:%d: fail", __func__, __LINE__));
5779
5780	value = (uint8_t) (ctl->q);
5781	value |= ((uint8_t) (ctl->i)) << 8;
5782	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5783}
5784
5785static uint16_t
5786bwn_lo_calcfeed(struct bwn_mac *mac,
5787    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5788{
5789	struct bwn_phy *phy = &mac->mac_phy;
5790	struct bwn_softc *sc = mac->mac_sc;
5791	uint16_t rfover;
5792	uint16_t feedthrough;
5793
5794	if (phy->gmode) {
5795		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5796		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5797
5798		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5799		    ("%s:%d: fail", __func__, __LINE__));
5800		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5801		    ("%s:%d: fail", __func__, __LINE__));
5802
5803		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5804
5805		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5806		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5807		    phy->rev > 6)
5808			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5809
5810		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5811		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5812		DELAY(10);
5813		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5814		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5815		DELAY(10);
5816		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5817		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5818		DELAY(10);
5819		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5820	} else {
5821		pga |= BWN_PHY_PGACTL_UNKNOWN;
5822		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5823		DELAY(10);
5824		pga |= BWN_PHY_PGACTL_LOWBANDW;
5825		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5826		DELAY(10);
5827		pga |= BWN_PHY_PGACTL_LPF;
5828		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5829	}
5830	DELAY(21);
5831	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5832
5833	return (feedthrough);
5834}
5835
5836static uint16_t
5837bwn_lo_txctl_regtable(struct bwn_mac *mac,
5838    uint16_t *value, uint16_t *pad_mix_gain)
5839{
5840	struct bwn_phy *phy = &mac->mac_phy;
5841	uint16_t reg, v, padmix;
5842
5843	if (phy->type == BWN_PHYTYPE_B) {
5844		v = 0x30;
5845		if (phy->rf_rev <= 5) {
5846			reg = 0x43;
5847			padmix = 0;
5848		} else {
5849			reg = 0x52;
5850			padmix = 5;
5851		}
5852	} else {
5853		if (phy->rev >= 2 && phy->rf_rev == 8) {
5854			reg = 0x43;
5855			v = 0x10;
5856			padmix = 2;
5857		} else {
5858			reg = 0x52;
5859			v = 0x30;
5860			padmix = 5;
5861		}
5862	}
5863	if (value)
5864		*value = v;
5865	if (pad_mix_gain)
5866		*pad_mix_gain = padmix;
5867
5868	return (reg);
5869}
5870
5871static void
5872bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5873{
5874	struct bwn_phy *phy = &mac->mac_phy;
5875	struct bwn_phy_g *pg = &phy->phy_g;
5876	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5877	uint16_t reg, mask;
5878	uint16_t trsw_rx, pga;
5879	uint16_t rf_pctl_reg;
5880
5881	static const uint8_t tx_bias_values[] = {
5882		0x09, 0x08, 0x0a, 0x01, 0x00,
5883		0x02, 0x05, 0x04, 0x06,
5884	};
5885	static const uint8_t tx_magn_values[] = {
5886		0x70, 0x40,
5887	};
5888
5889	if (!BWN_HAS_LOOPBACK(phy)) {
5890		rf_pctl_reg = 6;
5891		trsw_rx = 2;
5892		pga = 0;
5893	} else {
5894		int lb_gain;
5895
5896		trsw_rx = 0;
5897		lb_gain = pg->pg_max_lb_gain / 2;
5898		if (lb_gain > 10) {
5899			rf_pctl_reg = 0;
5900			pga = abs(10 - lb_gain) / 6;
5901			pga = MIN(MAX(pga, 0), 15);
5902		} else {
5903			int cmp_val;
5904			int tmp;
5905
5906			pga = 0;
5907			cmp_val = 0x24;
5908			if ((phy->rev >= 2) &&
5909			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
5910				cmp_val = 0x3c;
5911			tmp = lb_gain;
5912			if ((10 - lb_gain) < cmp_val)
5913				tmp = (10 - lb_gain);
5914			if (tmp < 0)
5915				tmp += 6;
5916			else
5917				tmp += 3;
5918			cmp_val /= 4;
5919			tmp /= 4;
5920			if (tmp >= cmp_val)
5921				rf_pctl_reg = cmp_val;
5922			else
5923				rf_pctl_reg = tmp;
5924		}
5925	}
5926	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
5927	bwn_phy_g_set_bbatt(mac, 2);
5928
5929	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
5930	mask = ~mask;
5931	BWN_RF_MASK(mac, reg, mask);
5932
5933	if (BWN_HAS_TXMAG(phy)) {
5934		int i, j;
5935		int feedthrough;
5936		int min_feedth = 0xffff;
5937		uint8_t tx_magn, tx_bias;
5938
5939		for (i = 0; i < N(tx_magn_values); i++) {
5940			tx_magn = tx_magn_values[i];
5941			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
5942			for (j = 0; j < N(tx_bias_values); j++) {
5943				tx_bias = tx_bias_values[j];
5944				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
5945				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
5946				    trsw_rx);
5947				if (feedthrough < min_feedth) {
5948					lo->tx_bias = tx_bias;
5949					lo->tx_magn = tx_magn;
5950					min_feedth = feedthrough;
5951				}
5952				if (lo->tx_bias == 0)
5953					break;
5954			}
5955			BWN_RF_WRITE(mac, 0x52,
5956					  (BWN_RF_READ(mac, 0x52)
5957					   & 0xff00) | lo->tx_bias | lo->
5958					  tx_magn);
5959		}
5960	} else {
5961		lo->tx_magn = 0;
5962		lo->tx_bias = 0;
5963		BWN_RF_MASK(mac, 0x52, 0xfff0);
5964	}
5965
5966	BWN_GETTIME(lo->txctl_measured_time);
5967}
5968
5969static void
5970bwn_lo_get_powervector(struct bwn_mac *mac)
5971{
5972	struct bwn_phy *phy = &mac->mac_phy;
5973	struct bwn_phy_g *pg = &phy->phy_g;
5974	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5975	int i;
5976	uint64_t tmp;
5977	uint64_t power_vector = 0;
5978
5979	for (i = 0; i < 8; i += 2) {
5980		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
5981		power_vector |= (tmp << (i * 8));
5982		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
5983	}
5984	if (power_vector)
5985		lo->power_vector = power_vector;
5986
5987	BWN_GETTIME(lo->pwr_vec_read_time);
5988}
5989
5990static void
5991bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
5992    int use_trsw_rx)
5993{
5994	struct bwn_phy *phy = &mac->mac_phy;
5995	struct bwn_phy_g *pg = &phy->phy_g;
5996	uint16_t tmp;
5997
5998	if (max_rx_gain < 0)
5999		max_rx_gain = 0;
6000
6001	if (BWN_HAS_LOOPBACK(phy)) {
6002		int trsw_rx = 0;
6003		int trsw_rx_gain;
6004
6005		if (use_trsw_rx) {
6006			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6007			if (max_rx_gain >= trsw_rx_gain) {
6008				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6009				trsw_rx = 0x20;
6010			}
6011		} else
6012			trsw_rx_gain = max_rx_gain;
6013		if (trsw_rx_gain < 9) {
6014			pg->pg_lna_lod_gain = 0;
6015		} else {
6016			pg->pg_lna_lod_gain = 1;
6017			trsw_rx_gain -= 8;
6018		}
6019		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6020		pg->pg_pga_gain = trsw_rx_gain / 3;
6021		if (pg->pg_pga_gain >= 5) {
6022			pg->pg_pga_gain -= 5;
6023			pg->pg_lna_gain = 2;
6024		} else
6025			pg->pg_lna_gain = 0;
6026	} else {
6027		pg->pg_lna_gain = 0;
6028		pg->pg_trsw_rx_gain = 0x20;
6029		if (max_rx_gain >= 0x14) {
6030			pg->pg_lna_lod_gain = 1;
6031			pg->pg_pga_gain = 2;
6032		} else if (max_rx_gain >= 0x12) {
6033			pg->pg_lna_lod_gain = 1;
6034			pg->pg_pga_gain = 1;
6035		} else if (max_rx_gain >= 0xf) {
6036			pg->pg_lna_lod_gain = 1;
6037			pg->pg_pga_gain = 0;
6038		} else {
6039			pg->pg_lna_lod_gain = 0;
6040			pg->pg_pga_gain = 0;
6041		}
6042	}
6043
6044	tmp = BWN_RF_READ(mac, 0x7a);
6045	if (pg->pg_lna_lod_gain == 0)
6046		tmp &= ~0x0008;
6047	else
6048		tmp |= 0x0008;
6049	BWN_RF_WRITE(mac, 0x7a, tmp);
6050}
6051
6052static void
6053bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6054{
6055	struct bwn_phy *phy = &mac->mac_phy;
6056	struct bwn_phy_g *pg = &phy->phy_g;
6057	struct bwn_softc *sc = mac->mac_sc;
6058	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6059	struct timespec ts;
6060	uint16_t tmp;
6061
6062	if (bwn_has_hwpctl(mac)) {
6063		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6064		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6065		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6066		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6067		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6068
6069		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6070		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6071		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6072		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6073	}
6074	if (phy->type == BWN_PHYTYPE_B &&
6075	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6076		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6077		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6078	}
6079	if (phy->rev >= 2) {
6080		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6081		sav->phy_analogoverval =
6082		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6083		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6084		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6085		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6086		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6087		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6088
6089		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6090		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6091		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6092		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6093		if (phy->type == BWN_PHYTYPE_G) {
6094			if ((phy->rev >= 7) &&
6095			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6096			     BWN_BFL_EXTLNA)) {
6097				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6098			} else {
6099				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6100			}
6101		} else {
6102			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6103		}
6104		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6105	}
6106	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6107	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6108	sav->rf0 = BWN_RF_READ(mac, 0x43);
6109	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6110	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6111	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6112	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6113	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6114
6115	if (!BWN_HAS_TXMAG(phy)) {
6116		sav->rf2 = BWN_RF_READ(mac, 0x52);
6117		sav->rf2 &= 0x00f0;
6118	}
6119	if (phy->type == BWN_PHYTYPE_B) {
6120		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6121		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6122		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6123		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6124	} else {
6125		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6126			    | 0x8000);
6127	}
6128	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6129		    & 0xf000);
6130
6131	tmp =
6132	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6133	BWN_PHY_WRITE(mac, tmp, 0x007f);
6134
6135	tmp = sav->phy_syncctl;
6136	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6137	tmp = sav->rf1;
6138	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6139
6140	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6141	if (phy->type == BWN_PHYTYPE_G ||
6142	    (phy->type == BWN_PHYTYPE_B &&
6143	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6144		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6145	} else
6146		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6147	if (phy->rev >= 2)
6148		bwn_dummy_transmission(mac, 0, 1);
6149	bwn_phy_g_switch_chan(mac, 6, 0);
6150	BWN_RF_READ(mac, 0x51);
6151	if (phy->type == BWN_PHYTYPE_G)
6152		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6153
6154	nanouptime(&ts);
6155	if (time_before(lo->txctl_measured_time,
6156	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6157		bwn_lo_measure_txctl_values(mac);
6158
6159	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6160		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6161	else {
6162		if (phy->type == BWN_PHYTYPE_B)
6163			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6164		else
6165			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6166	}
6167}
6168
6169static void
6170bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6171{
6172	struct bwn_phy *phy = &mac->mac_phy;
6173	struct bwn_phy_g *pg = &phy->phy_g;
6174	uint16_t tmp;
6175
6176	if (phy->rev >= 2) {
6177		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6178		tmp = (pg->pg_pga_gain << 8);
6179		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6180		DELAY(5);
6181		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6182		DELAY(2);
6183		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6184	} else {
6185		tmp = (pg->pg_pga_gain | 0xefa0);
6186		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6187	}
6188	if (phy->type == BWN_PHYTYPE_G) {
6189		if (phy->rev >= 3)
6190			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6191		else
6192			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6193		if (phy->rev >= 2)
6194			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6195		else
6196			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6197	}
6198	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6199	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6200	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6201	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6202	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6203	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6204	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6205	if (!BWN_HAS_TXMAG(phy)) {
6206		tmp = sav->rf2;
6207		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6208	}
6209	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6210	if (phy->type == BWN_PHYTYPE_B &&
6211	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6212		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6213		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6214	}
6215	if (phy->rev >= 2) {
6216		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6217		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6218			      sav->phy_analogoverval);
6219		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6220		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6221		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6222		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6223		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6224	}
6225	if (bwn_has_hwpctl(mac)) {
6226		tmp = (sav->phy_lomask & 0xbfff);
6227		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6228		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6229		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6230		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6231		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6232	}
6233	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6234}
6235
6236static int
6237bwn_lo_probe_loctl(struct bwn_mac *mac,
6238    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6239{
6240	struct bwn_phy *phy = &mac->mac_phy;
6241	struct bwn_phy_g *pg = &phy->phy_g;
6242	struct bwn_loctl orig, test;
6243	struct bwn_loctl prev = { -100, -100 };
6244	static const struct bwn_loctl modifiers[] = {
6245		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6246		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6247	};
6248	int begin, end, lower = 0, i;
6249	uint16_t feedth;
6250
6251	if (d->curstate == 0) {
6252		begin = 1;
6253		end = 8;
6254	} else if (d->curstate % 2 == 0) {
6255		begin = d->curstate - 1;
6256		end = d->curstate + 1;
6257	} else {
6258		begin = d->curstate - 2;
6259		end = d->curstate + 2;
6260	}
6261	if (begin < 1)
6262		begin += 8;
6263	if (end > 8)
6264		end -= 8;
6265
6266	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6267	i = begin;
6268	d->curstate = i;
6269	while (1) {
6270		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6271		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6272		test.i += modifiers[i - 1].i * d->multipler;
6273		test.q += modifiers[i - 1].q * d->multipler;
6274		if ((test.i != prev.i || test.q != prev.q) &&
6275		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6276			bwn_lo_write(mac, &test);
6277			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6278			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6279			if (feedth < d->feedth) {
6280				memcpy(probe, &test,
6281				    sizeof(struct bwn_loctl));
6282				lower = 1;
6283				d->feedth = feedth;
6284				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6285					break;
6286			}
6287		}
6288		memcpy(&prev, &test, sizeof(prev));
6289		if (i == end)
6290			break;
6291		if (i == 8)
6292			i = 1;
6293		else
6294			i++;
6295		d->curstate = i;
6296	}
6297
6298	return (lower);
6299}
6300
6301static void
6302bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6303{
6304	struct bwn_phy *phy = &mac->mac_phy;
6305	struct bwn_phy_g *pg = &phy->phy_g;
6306	struct bwn_lo_g_sm d;
6307	struct bwn_loctl probe;
6308	int lower, repeat, cnt = 0;
6309	uint16_t feedth;
6310
6311	d.nmeasure = 0;
6312	d.multipler = 1;
6313	if (BWN_HAS_LOOPBACK(phy))
6314		d.multipler = 3;
6315
6316	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6317	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6318
6319	do {
6320		bwn_lo_write(mac, &d.loctl);
6321		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6322		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6323		if (feedth < 0x258) {
6324			if (feedth >= 0x12c)
6325				*rxgain += 6;
6326			else
6327				*rxgain += 3;
6328			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6329			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6330		}
6331		d.feedth = feedth;
6332		d.curstate = 0;
6333		do {
6334			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6335			    ("%s:%d: fail", __func__, __LINE__));
6336			memcpy(&probe, &d.loctl,
6337			       sizeof(struct bwn_loctl));
6338			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6339			if (!lower)
6340				break;
6341			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6342				break;
6343			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6344			d.nmeasure++;
6345		} while (d.nmeasure < 24);
6346		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6347
6348		if (BWN_HAS_LOOPBACK(phy)) {
6349			if (d.feedth > 0x1194)
6350				*rxgain -= 6;
6351			else if (d.feedth < 0x5dc)
6352				*rxgain += 3;
6353			if (cnt == 0) {
6354				if (d.feedth <= 0x5dc) {
6355					d.multipler = 1;
6356					cnt++;
6357				} else
6358					d.multipler = 2;
6359			} else if (cnt == 2)
6360				d.multipler = 1;
6361		}
6362		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6363	} while (++cnt < repeat);
6364}
6365
6366static struct bwn_lo_calib *
6367bwn_lo_calibset(struct bwn_mac *mac,
6368    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6369{
6370	struct bwn_phy *phy = &mac->mac_phy;
6371	struct bwn_phy_g *pg = &phy->phy_g;
6372	struct bwn_loctl loctl = { 0, 0 };
6373	struct bwn_lo_calib *cal;
6374	struct bwn_lo_g_value sval = { 0 };
6375	int rxgain;
6376	uint16_t pad, reg, value;
6377
6378	sval.old_channel = phy->chan;
6379	bwn_mac_suspend(mac);
6380	bwn_lo_save(mac, &sval);
6381
6382	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6383	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6384	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6385
6386	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6387	if (rfatt->padmix)
6388		rxgain -= pad;
6389	if (BWN_HAS_LOOPBACK(phy))
6390		rxgain += pg->pg_max_lb_gain;
6391	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6392	bwn_phy_g_set_bbatt(mac, bbatt->att);
6393	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6394
6395	bwn_lo_restore(mac, &sval);
6396	bwn_mac_enable(mac);
6397
6398	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6399	if (!cal) {
6400		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6401		return (NULL);
6402	}
6403	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6404	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6405	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6406
6407	BWN_GETTIME(cal->calib_time);
6408
6409	return (cal);
6410}
6411
6412static struct bwn_lo_calib *
6413bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6414    const struct bwn_rfatt *rfatt)
6415{
6416	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6417	struct bwn_lo_calib *c;
6418
6419	TAILQ_FOREACH(c, &lo->calib_list, list) {
6420		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6421			continue;
6422		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6423			continue;
6424		return (c);
6425	}
6426
6427	c = bwn_lo_calibset(mac, bbatt, rfatt);
6428	if (!c)
6429		return (NULL);
6430	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6431
6432	return (c);
6433}
6434
6435static void
6436bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6437{
6438	struct bwn_phy *phy = &mac->mac_phy;
6439	struct bwn_phy_g *pg = &phy->phy_g;
6440	struct bwn_softc *sc = mac->mac_sc;
6441	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6442	const struct bwn_rfatt *rfatt;
6443	const struct bwn_bbatt *bbatt;
6444	uint64_t pvector;
6445	int i;
6446	int rf_offset, bb_offset;
6447	uint8_t changed = 0;
6448
6449	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6450	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6451	    ("%s:%d: fail", __func__, __LINE__));
6452
6453	pvector = lo->power_vector;
6454	if (!update && !pvector)
6455		return;
6456
6457	bwn_mac_suspend(mac);
6458
6459	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6460		struct bwn_lo_calib *cal;
6461		int idx;
6462		uint16_t val;
6463
6464		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6465			continue;
6466		bb_offset = i / lo->rfatt.len;
6467		rf_offset = i % lo->rfatt.len;
6468		bbatt = &(lo->bbatt.array[bb_offset]);
6469		rfatt = &(lo->rfatt.array[rf_offset]);
6470
6471		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6472		if (!cal) {
6473			device_printf(sc->sc_dev, "LO: Could not "
6474			    "calibrate DC table entry\n");
6475			continue;
6476		}
6477		val = (uint8_t)(cal->ctl.q);
6478		val |= ((uint8_t)(cal->ctl.i)) << 4;
6479		free(cal, M_DEVBUF);
6480
6481		idx = i / 2;
6482		if (i % 2)
6483			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6484			    | ((val & 0x00ff) << 8);
6485		else
6486			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6487			    | (val & 0x00ff);
6488		changed = 1;
6489	}
6490	if (changed) {
6491		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6492			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6493	}
6494	bwn_mac_enable(mac);
6495}
6496
6497static void
6498bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6499{
6500
6501	if (!rf->padmix)
6502		return;
6503	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6504		rf->att = 4;
6505}
6506
6507static void
6508bwn_lo_g_adjust(struct bwn_mac *mac)
6509{
6510	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6511	struct bwn_lo_calib *cal;
6512	struct bwn_rfatt rf;
6513
6514	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6515	bwn_lo_fixup_rfatt(&rf);
6516
6517	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6518	if (!cal)
6519		return;
6520	bwn_lo_write(mac, &cal->ctl);
6521}
6522
6523static void
6524bwn_lo_g_init(struct bwn_mac *mac)
6525{
6526
6527	if (!bwn_has_hwpctl(mac))
6528		return;
6529
6530	bwn_lo_get_powervector(mac);
6531	bwn_phy_g_dc_lookup_init(mac, 1);
6532}
6533
6534static void
6535bwn_mac_suspend(struct bwn_mac *mac)
6536{
6537	struct bwn_softc *sc = mac->mac_sc;
6538	int i;
6539	uint32_t tmp;
6540
6541	KASSERT(mac->mac_suspended >= 0,
6542	    ("%s:%d: fail", __func__, __LINE__));
6543
6544	if (mac->mac_suspended == 0) {
6545		bwn_psctl(mac, BWN_PS_AWAKE);
6546		BWN_WRITE_4(mac, BWN_MACCTL,
6547			    BWN_READ_4(mac, BWN_MACCTL)
6548			    & ~BWN_MACCTL_ON);
6549		BWN_READ_4(mac, BWN_MACCTL);
6550		for (i = 35; i; i--) {
6551			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6552			if (tmp & BWN_INTR_MAC_SUSPENDED)
6553				goto out;
6554			DELAY(10);
6555		}
6556		for (i = 40; i; i--) {
6557			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6558			if (tmp & BWN_INTR_MAC_SUSPENDED)
6559				goto out;
6560			DELAY(1000);
6561		}
6562		device_printf(sc->sc_dev, "MAC suspend failed\n");
6563	}
6564out:
6565	mac->mac_suspended++;
6566}
6567
6568static void
6569bwn_mac_enable(struct bwn_mac *mac)
6570{
6571	struct bwn_softc *sc = mac->mac_sc;
6572	uint16_t state;
6573
6574	state = bwn_shm_read_2(mac, BWN_SHARED,
6575	    BWN_SHARED_UCODESTAT);
6576	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6577	    state != BWN_SHARED_UCODESTAT_SLEEP)
6578		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6579
6580	mac->mac_suspended--;
6581	KASSERT(mac->mac_suspended >= 0,
6582	    ("%s:%d: fail", __func__, __LINE__));
6583	if (mac->mac_suspended == 0) {
6584		BWN_WRITE_4(mac, BWN_MACCTL,
6585		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6586		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6587		BWN_READ_4(mac, BWN_MACCTL);
6588		BWN_READ_4(mac, BWN_INTR_REASON);
6589		bwn_psctl(mac, 0);
6590	}
6591}
6592
6593static void
6594bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6595{
6596	struct bwn_softc *sc = mac->mac_sc;
6597	int i;
6598	uint16_t ucstat;
6599
6600	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6601	    ("%s:%d: fail", __func__, __LINE__));
6602	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6603	    ("%s:%d: fail", __func__, __LINE__));
6604
6605	/* XXX forcibly awake and hwps-off */
6606
6607	BWN_WRITE_4(mac, BWN_MACCTL,
6608	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6609	    ~BWN_MACCTL_HWPS);
6610	BWN_READ_4(mac, BWN_MACCTL);
6611	if (siba_get_revid(sc->sc_dev) >= 5) {
6612		for (i = 0; i < 100; i++) {
6613			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6614			    BWN_SHARED_UCODESTAT);
6615			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6616				break;
6617			DELAY(10);
6618		}
6619	}
6620}
6621
6622static int16_t
6623bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6624{
6625
6626	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6627	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6628}
6629
6630static void
6631bwn_nrssi_threshold(struct bwn_mac *mac)
6632{
6633	struct bwn_phy *phy = &mac->mac_phy;
6634	struct bwn_phy_g *pg = &phy->phy_g;
6635	struct bwn_softc *sc = mac->mac_sc;
6636	int32_t a, b;
6637	int16_t tmp16;
6638	uint16_t tmpu16;
6639
6640	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6641
6642	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6643		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6644			a = 0x13;
6645			b = 0x12;
6646		} else {
6647			a = 0xe;
6648			b = 0x11;
6649		}
6650
6651		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6652		a += (pg->pg_nrssi[0] << 6);
6653		a += (a < 32) ? 31 : 32;
6654		a = a >> 6;
6655		a = MIN(MAX(a, -31), 31);
6656
6657		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6658		b += (pg->pg_nrssi[0] << 6);
6659		if (b < 32)
6660			b += 31;
6661		else
6662			b += 32;
6663		b = b >> 6;
6664		b = MIN(MAX(b, -31), 31);
6665
6666		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6667		tmpu16 |= ((uint32_t)b & 0x0000003f);
6668		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6669		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6670		return;
6671	}
6672
6673	tmp16 = bwn_nrssi_read(mac, 0x20);
6674	if (tmp16 >= 0x20)
6675		tmp16 -= 0x40;
6676	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6677}
6678
6679static void
6680bwn_nrssi_slope_11g(struct bwn_mac *mac)
6681{
6682#define	SAVE_RF_MAX		3
6683#define	SAVE_PHY_COMM_MAX	4
6684#define	SAVE_PHY3_MAX		8
6685	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6686		{ 0x7a, 0x52, 0x43 };
6687	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6688		{ 0x15, 0x5a, 0x59, 0x58 };
6689	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6690		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6691		0x0801, 0x0060, 0x0014, 0x0478
6692	};
6693	struct bwn_phy *phy = &mac->mac_phy;
6694	struct bwn_phy_g *pg = &phy->phy_g;
6695	int32_t i, tmp32, phy3_idx = 0;
6696	uint16_t delta, tmp;
6697	uint16_t save_rf[SAVE_RF_MAX];
6698	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6699	uint16_t save_phy3[SAVE_PHY3_MAX];
6700	uint16_t ant_div, phy0, chan_ex;
6701	int16_t nrssi0, nrssi1;
6702
6703	KASSERT(phy->type == BWN_PHYTYPE_G,
6704	    ("%s:%d: fail", __func__, __LINE__));
6705
6706	if (phy->rf_rev >= 9)
6707		return;
6708	if (phy->rf_rev == 8)
6709		bwn_nrssi_offset(mac);
6710
6711	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6712	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6713
6714	/*
6715	 * Save RF/PHY registers for later restoration
6716	 */
6717	ant_div = BWN_READ_2(mac, 0x03e2);
6718	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6719	for (i = 0; i < SAVE_RF_MAX; ++i)
6720		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6721	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6722		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6723
6724	phy0 = BWN_READ_2(mac, BWN_PHY0);
6725	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6726	if (phy->rev >= 3) {
6727		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6728			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6729		BWN_PHY_WRITE(mac, 0x002e, 0);
6730		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6731		switch (phy->rev) {
6732		case 4:
6733		case 6:
6734		case 7:
6735			BWN_PHY_SET(mac, 0x0478, 0x0100);
6736			BWN_PHY_SET(mac, 0x0801, 0x0040);
6737			break;
6738		case 3:
6739		case 5:
6740			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6741			break;
6742		}
6743		BWN_PHY_SET(mac, 0x0060, 0x0040);
6744		BWN_PHY_SET(mac, 0x0014, 0x0200);
6745	}
6746	/*
6747	 * Calculate nrssi0
6748	 */
6749	BWN_RF_SET(mac, 0x007a, 0x0070);
6750	bwn_set_all_gains(mac, 0, 8, 0);
6751	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6752	if (phy->rev >= 2) {
6753		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6754		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6755	}
6756	BWN_RF_SET(mac, 0x007a, 0x0080);
6757	DELAY(20);
6758
6759	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6760	if (nrssi0 >= 0x0020)
6761		nrssi0 -= 0x0040;
6762
6763	/*
6764	 * Calculate nrssi1
6765	 */
6766	BWN_RF_MASK(mac, 0x007a, 0x007f);
6767	if (phy->rev >= 2)
6768		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6769
6770	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6771	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6772	BWN_RF_SET(mac, 0x007a, 0x000f);
6773	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6774	if (phy->rev >= 2) {
6775		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6776		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6777	}
6778
6779	bwn_set_all_gains(mac, 3, 0, 1);
6780	if (phy->rf_rev == 8) {
6781		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6782	} else {
6783		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6784		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6785		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6786		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6787	}
6788	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6789	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6790	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6791	DELAY(20);
6792	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6793
6794	/*
6795	 * Install calculated narrow RSSI values
6796	 */
6797	if (nrssi1 >= 0x0020)
6798		nrssi1 -= 0x0040;
6799	if (nrssi0 == nrssi1)
6800		pg->pg_nrssi_slope = 0x00010000;
6801	else
6802		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6803	if (nrssi0 >= -4) {
6804		pg->pg_nrssi[0] = nrssi1;
6805		pg->pg_nrssi[1] = nrssi0;
6806	}
6807
6808	/*
6809	 * Restore saved RF/PHY registers
6810	 */
6811	if (phy->rev >= 3) {
6812		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6813			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6814			    save_phy3[phy3_idx]);
6815		}
6816	}
6817	if (phy->rev >= 2) {
6818		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6819		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6820	}
6821
6822	for (i = 0; i < SAVE_RF_MAX; ++i)
6823		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6824
6825	BWN_WRITE_2(mac, 0x03e2, ant_div);
6826	BWN_WRITE_2(mac, 0x03e6, phy0);
6827	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6828
6829	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6830		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6831
6832	bwn_spu_workaround(mac, phy->chan);
6833	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6834	bwn_set_original_gains(mac);
6835	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6836	if (phy->rev >= 3) {
6837		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6838			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6839			    save_phy3[phy3_idx]);
6840		}
6841	}
6842
6843	delta = 0x1f - pg->pg_nrssi[0];
6844	for (i = 0; i < 64; i++) {
6845		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6846		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6847		pg->pg_nrssi_lt[i] = tmp32;
6848	}
6849
6850	bwn_nrssi_threshold(mac);
6851#undef SAVE_RF_MAX
6852#undef SAVE_PHY_COMM_MAX
6853#undef SAVE_PHY3_MAX
6854}
6855
6856static void
6857bwn_nrssi_offset(struct bwn_mac *mac)
6858{
6859#define	SAVE_RF_MAX		2
6860#define	SAVE_PHY_COMM_MAX	10
6861#define	SAVE_PHY6_MAX		8
6862	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6863		{ 0x7a, 0x43 };
6864	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6865		0x0001, 0x0811, 0x0812, 0x0814,
6866		0x0815, 0x005a, 0x0059, 0x0058,
6867		0x000a, 0x0003
6868	};
6869	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6870		0x002e, 0x002f, 0x080f, 0x0810,
6871		0x0801, 0x0060, 0x0014, 0x0478
6872	};
6873	struct bwn_phy *phy = &mac->mac_phy;
6874	int i, phy6_idx = 0;
6875	uint16_t save_rf[SAVE_RF_MAX];
6876	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6877	uint16_t save_phy6[SAVE_PHY6_MAX];
6878	int16_t nrssi;
6879	uint16_t saved = 0xffff;
6880
6881	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6882		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6883	for (i = 0; i < SAVE_RF_MAX; ++i)
6884		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6885
6886	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6887	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6888	BWN_PHY_SET(mac, 0x0811, 0x000c);
6889	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6890	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6891	if (phy->rev >= 6) {
6892		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6893			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6894
6895		BWN_PHY_WRITE(mac, 0x002e, 0);
6896		BWN_PHY_WRITE(mac, 0x002f, 0);
6897		BWN_PHY_WRITE(mac, 0x080f, 0);
6898		BWN_PHY_WRITE(mac, 0x0810, 0);
6899		BWN_PHY_SET(mac, 0x0478, 0x0100);
6900		BWN_PHY_SET(mac, 0x0801, 0x0040);
6901		BWN_PHY_SET(mac, 0x0060, 0x0040);
6902		BWN_PHY_SET(mac, 0x0014, 0x0200);
6903	}
6904	BWN_RF_SET(mac, 0x007a, 0x0070);
6905	BWN_RF_SET(mac, 0x007a, 0x0080);
6906	DELAY(30);
6907
6908	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6909	if (nrssi >= 0x20)
6910		nrssi -= 0x40;
6911	if (nrssi == 31) {
6912		for (i = 7; i >= 4; i--) {
6913			BWN_RF_WRITE(mac, 0x007b, i);
6914			DELAY(20);
6915			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
6916			    0x003f);
6917			if (nrssi >= 0x20)
6918				nrssi -= 0x40;
6919			if (nrssi < 31 && saved == 0xffff)
6920				saved = i;
6921		}
6922		if (saved == 0xffff)
6923			saved = 4;
6924	} else {
6925		BWN_RF_MASK(mac, 0x007a, 0x007f);
6926		if (phy->rev != 1) {
6927			BWN_PHY_SET(mac, 0x0814, 0x0001);
6928			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
6929		}
6930		BWN_PHY_SET(mac, 0x0811, 0x000c);
6931		BWN_PHY_SET(mac, 0x0812, 0x000c);
6932		BWN_PHY_SET(mac, 0x0811, 0x0030);
6933		BWN_PHY_SET(mac, 0x0812, 0x0030);
6934		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6935		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6936		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6937		if (phy->rev == 0)
6938			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
6939		else
6940			BWN_PHY_SET(mac, 0x000a, 0x2000);
6941		if (phy->rev != 1) {
6942			BWN_PHY_SET(mac, 0x0814, 0x0004);
6943			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
6944		}
6945		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6946		BWN_RF_SET(mac, 0x007a, 0x000f);
6947		bwn_set_all_gains(mac, 3, 0, 1);
6948		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
6949		DELAY(30);
6950		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6951		if (nrssi >= 0x20)
6952			nrssi -= 0x40;
6953		if (nrssi == -32) {
6954			for (i = 0; i < 4; i++) {
6955				BWN_RF_WRITE(mac, 0x007b, i);
6956				DELAY(20);
6957				nrssi = (int16_t)((BWN_PHY_READ(mac,
6958				    0x047f) >> 8) & 0x003f);
6959				if (nrssi >= 0x20)
6960					nrssi -= 0x40;
6961				if (nrssi > -31 && saved == 0xffff)
6962					saved = i;
6963			}
6964			if (saved == 0xffff)
6965				saved = 3;
6966		} else
6967			saved = 0;
6968	}
6969	BWN_RF_WRITE(mac, 0x007b, saved);
6970
6971	/*
6972	 * Restore saved RF/PHY registers
6973	 */
6974	if (phy->rev >= 6) {
6975		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
6976			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6977			    save_phy6[phy6_idx]);
6978		}
6979	}
6980	if (phy->rev != 1) {
6981		for (i = 3; i < 5; i++)
6982			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
6983			    save_phy_comm[i]);
6984	}
6985	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
6986		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6987
6988	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
6989		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6990
6991	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
6992	BWN_PHY_SET(mac, 0x0429, 0x8000);
6993	bwn_set_original_gains(mac);
6994	if (phy->rev >= 6) {
6995		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
6996			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6997			    save_phy6[phy6_idx]);
6998		}
6999	}
7000
7001	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7002	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7003	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7004}
7005
7006static void
7007bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7008    int16_t third)
7009{
7010	struct bwn_phy *phy = &mac->mac_phy;
7011	uint16_t i;
7012	uint16_t start = 0x08, end = 0x18;
7013	uint16_t tmp;
7014	uint16_t table;
7015
7016	if (phy->rev <= 1) {
7017		start = 0x10;
7018		end = 0x20;
7019	}
7020
7021	table = BWN_OFDMTAB_GAINX;
7022	if (phy->rev <= 1)
7023		table = BWN_OFDMTAB_GAINX_R1;
7024	for (i = 0; i < 4; i++)
7025		bwn_ofdmtab_write_2(mac, table, i, first);
7026
7027	for (i = start; i < end; i++)
7028		bwn_ofdmtab_write_2(mac, table, i, second);
7029
7030	if (third != -1) {
7031		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7032		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7033		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7034		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7035	}
7036	bwn_dummy_transmission(mac, 0, 1);
7037}
7038
7039static void
7040bwn_set_original_gains(struct bwn_mac *mac)
7041{
7042	struct bwn_phy *phy = &mac->mac_phy;
7043	uint16_t i, tmp;
7044	uint16_t table;
7045	uint16_t start = 0x0008, end = 0x0018;
7046
7047	if (phy->rev <= 1) {
7048		start = 0x0010;
7049		end = 0x0020;
7050	}
7051
7052	table = BWN_OFDMTAB_GAINX;
7053	if (phy->rev <= 1)
7054		table = BWN_OFDMTAB_GAINX_R1;
7055	for (i = 0; i < 4; i++) {
7056		tmp = (i & 0xfffc);
7057		tmp |= (i & 0x0001) << 1;
7058		tmp |= (i & 0x0002) >> 1;
7059
7060		bwn_ofdmtab_write_2(mac, table, i, tmp);
7061	}
7062
7063	for (i = start; i < end; i++)
7064		bwn_ofdmtab_write_2(mac, table, i, i - start);
7065
7066	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7067	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7068	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7069	bwn_dummy_transmission(mac, 0, 1);
7070}
7071
7072static void
7073bwn_phy_hwpctl_init(struct bwn_mac *mac)
7074{
7075	struct bwn_phy *phy = &mac->mac_phy;
7076	struct bwn_phy_g *pg = &phy->phy_g;
7077	struct bwn_rfatt old_rfatt, rfatt;
7078	struct bwn_bbatt old_bbatt, bbatt;
7079	struct bwn_softc *sc = mac->mac_sc;
7080	uint8_t old_txctl = 0;
7081
7082	KASSERT(phy->type == BWN_PHYTYPE_G,
7083	    ("%s:%d: fail", __func__, __LINE__));
7084
7085	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7086	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7087		return;
7088
7089	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7090
7091	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7092
7093	if (!phy->gmode)
7094		return;
7095	bwn_hwpctl_early_init(mac);
7096	if (pg->pg_curtssi == 0) {
7097		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7098			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7099		} else {
7100			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7101			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7102			old_txctl = pg->pg_txctl;
7103
7104			bbatt.att = 11;
7105			if (phy->rf_rev == 8) {
7106				rfatt.att = 15;
7107				rfatt.padmix = 1;
7108			} else {
7109				rfatt.att = 9;
7110				rfatt.padmix = 0;
7111			}
7112			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7113		}
7114		bwn_dummy_transmission(mac, 0, 1);
7115		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7116		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7117			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7118		else
7119			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7120			    &old_rfatt, old_txctl);
7121	}
7122	bwn_hwpctl_init_gphy(mac);
7123
7124	/* clear TSSI */
7125	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7126	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7127	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7128	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7129}
7130
7131static void
7132bwn_hwpctl_early_init(struct bwn_mac *mac)
7133{
7134	struct bwn_phy *phy = &mac->mac_phy;
7135
7136	if (!bwn_has_hwpctl(mac)) {
7137		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7138		return;
7139	}
7140
7141	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7142	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7143	BWN_PHY_SET(mac, 0x047c, 0x0002);
7144	BWN_PHY_SET(mac, 0x047a, 0xf000);
7145	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7146		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7147		BWN_PHY_SET(mac, 0x005d, 0x8000);
7148		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7149		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7150		BWN_PHY_SET(mac, 0x0036, 0x0400);
7151	} else {
7152		BWN_PHY_SET(mac, 0x0036, 0x0200);
7153		BWN_PHY_SET(mac, 0x0036, 0x0400);
7154		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7155		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7156		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7157		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7158		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7159	}
7160}
7161
7162static void
7163bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7164{
7165	struct bwn_phy *phy = &mac->mac_phy;
7166	struct bwn_phy_g *pg = &phy->phy_g;
7167	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7168	int i;
7169	uint16_t nr_written = 0, tmp, value;
7170	uint8_t rf, bb;
7171
7172	if (!bwn_has_hwpctl(mac)) {
7173		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7174		return;
7175	}
7176
7177	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7178	    (pg->pg_idletssi - pg->pg_curtssi));
7179	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7180	    (pg->pg_idletssi - pg->pg_curtssi));
7181
7182	for (i = 0; i < 32; i++)
7183		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7184	for (i = 32; i < 64; i++)
7185		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7186	for (i = 0; i < 64; i += 2) {
7187		value = (uint16_t) pg->pg_tssi2dbm[i];
7188		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7189		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7190	}
7191
7192	for (rf = 0; rf < lo->rfatt.len; rf++) {
7193		for (bb = 0; bb < lo->bbatt.len; bb++) {
7194			if (nr_written >= 0x40)
7195				return;
7196			tmp = lo->bbatt.array[bb].att;
7197			tmp <<= 8;
7198			if (phy->rf_rev == 8)
7199				tmp |= 0x50;
7200			else
7201				tmp |= 0x40;
7202			tmp |= lo->rfatt.array[rf].att;
7203			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7204			nr_written++;
7205		}
7206	}
7207
7208	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7209	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7210
7211	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7212	BWN_PHY_SET(mac, 0x0478, 0x0800);
7213	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7214	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7215
7216	bwn_phy_g_dc_lookup_init(mac, 1);
7217	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7218}
7219
7220static void
7221bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7222{
7223	struct bwn_softc *sc = mac->mac_sc;
7224
7225	if (spu != 0)
7226		bwn_spu_workaround(mac, channel);
7227
7228	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7229
7230	if (channel == 14) {
7231		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7232			bwn_hf_write(mac,
7233			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7234		else
7235			bwn_hf_write(mac,
7236			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7237		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7238		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7239		return;
7240	}
7241
7242	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7243	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7244}
7245
7246static uint16_t
7247bwn_phy_g_chan2freq(uint8_t channel)
7248{
7249	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7250
7251	KASSERT(channel >= 1 && channel <= 14,
7252	    ("%s:%d: fail", __func__, __LINE__));
7253
7254	return (bwn_phy_g_rf_channels[channel - 1]);
7255}
7256
7257static void
7258bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7259    const struct bwn_rfatt *rfatt, uint8_t txctl)
7260{
7261	struct bwn_phy *phy = &mac->mac_phy;
7262	struct bwn_phy_g *pg = &phy->phy_g;
7263	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7264	uint16_t bb, rf;
7265	uint16_t tx_bias, tx_magn;
7266
7267	bb = bbatt->att;
7268	rf = rfatt->att;
7269	tx_bias = lo->tx_bias;
7270	tx_magn = lo->tx_magn;
7271	if (tx_bias == 0xff)
7272		tx_bias = 0;
7273
7274	pg->pg_txctl = txctl;
7275	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7276	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7277	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7278	bwn_phy_g_set_bbatt(mac, bb);
7279	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7280	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7281		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7282	else {
7283		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7284		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7285	}
7286	if (BWN_HAS_TXMAG(phy))
7287		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7288	else
7289		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7290	bwn_lo_g_adjust(mac);
7291}
7292
7293static void
7294bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7295    uint16_t bbatt)
7296{
7297	struct bwn_phy *phy = &mac->mac_phy;
7298
7299	if (phy->analog == 0) {
7300		BWN_WRITE_2(mac, BWN_PHY0,
7301		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7302		return;
7303	}
7304	if (phy->analog > 1) {
7305		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7306		return;
7307	}
7308	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7309}
7310
7311static uint16_t
7312bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7313{
7314	struct bwn_phy *phy = &mac->mac_phy;
7315	struct bwn_phy_g *pg = &phy->phy_g;
7316	struct bwn_softc *sc = mac->mac_sc;
7317	int max_lb_gain;
7318	uint16_t extlna;
7319	uint16_t i;
7320
7321	if (phy->gmode == 0)
7322		return (0);
7323
7324	if (BWN_HAS_LOOPBACK(phy)) {
7325		max_lb_gain = pg->pg_max_lb_gain;
7326		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7327		if (max_lb_gain >= 0x46) {
7328			extlna = 0x3000;
7329			max_lb_gain -= 0x46;
7330		} else if (max_lb_gain >= 0x3a) {
7331			extlna = 0x1000;
7332			max_lb_gain -= 0x3a;
7333		} else if (max_lb_gain >= 0x2e) {
7334			extlna = 0x2000;
7335			max_lb_gain -= 0x2e;
7336		} else {
7337			extlna = 0;
7338			max_lb_gain -= 0x10;
7339		}
7340
7341		for (i = 0; i < 16; i++) {
7342			max_lb_gain -= (i * 6);
7343			if (max_lb_gain < 6)
7344				break;
7345		}
7346
7347		if ((phy->rev < 7) ||
7348		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7349			if (reg == BWN_PHY_RFOVER) {
7350				return (0x1b3);
7351			} else if (reg == BWN_PHY_RFOVERVAL) {
7352				extlna |= (i << 8);
7353				switch (lpd) {
7354				case BWN_LPD(0, 1, 1):
7355					return (0x0f92);
7356				case BWN_LPD(0, 0, 1):
7357				case BWN_LPD(1, 0, 1):
7358					return (0x0092 | extlna);
7359				case BWN_LPD(1, 0, 0):
7360					return (0x0093 | extlna);
7361				}
7362				KASSERT(0 == 1,
7363				    ("%s:%d: fail", __func__, __LINE__));
7364			}
7365			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7366		} else {
7367			if (reg == BWN_PHY_RFOVER)
7368				return (0x9b3);
7369			if (reg == BWN_PHY_RFOVERVAL) {
7370				if (extlna)
7371					extlna |= 0x8000;
7372				extlna |= (i << 8);
7373				switch (lpd) {
7374				case BWN_LPD(0, 1, 1):
7375					return (0x8f92);
7376				case BWN_LPD(0, 0, 1):
7377					return (0x8092 | extlna);
7378				case BWN_LPD(1, 0, 1):
7379					return (0x2092 | extlna);
7380				case BWN_LPD(1, 0, 0):
7381					return (0x2093 | extlna);
7382				}
7383				KASSERT(0 == 1,
7384				    ("%s:%d: fail", __func__, __LINE__));
7385			}
7386			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7387		}
7388		return (0);
7389	}
7390
7391	if ((phy->rev < 7) ||
7392	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7393		if (reg == BWN_PHY_RFOVER) {
7394			return (0x1b3);
7395		} else if (reg == BWN_PHY_RFOVERVAL) {
7396			switch (lpd) {
7397			case BWN_LPD(0, 1, 1):
7398				return (0x0fb2);
7399			case BWN_LPD(0, 0, 1):
7400				return (0x00b2);
7401			case BWN_LPD(1, 0, 1):
7402				return (0x30b2);
7403			case BWN_LPD(1, 0, 0):
7404				return (0x30b3);
7405			}
7406			KASSERT(0 == 1,
7407			    ("%s:%d: fail", __func__, __LINE__));
7408		}
7409		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7410	} else {
7411		if (reg == BWN_PHY_RFOVER) {
7412			return (0x9b3);
7413		} else if (reg == BWN_PHY_RFOVERVAL) {
7414			switch (lpd) {
7415			case BWN_LPD(0, 1, 1):
7416				return (0x8fb2);
7417			case BWN_LPD(0, 0, 1):
7418				return (0x80b2);
7419			case BWN_LPD(1, 0, 1):
7420				return (0x20b2);
7421			case BWN_LPD(1, 0, 0):
7422				return (0x20b3);
7423			}
7424			KASSERT(0 == 1,
7425			    ("%s:%d: fail", __func__, __LINE__));
7426		}
7427		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7428	}
7429	return (0);
7430}
7431
7432static void
7433bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7434{
7435
7436	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7437		return;
7438	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7439	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7440	DELAY(1000);
7441	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7442}
7443
7444static int
7445bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7446{
7447	struct bwn_softc *sc = mac->mac_sc;
7448	struct bwn_fw *fw = &mac->mac_fw;
7449	const uint8_t rev = siba_get_revid(sc->sc_dev);
7450	const char *filename;
7451	uint32_t high;
7452	int error;
7453
7454	/* microcode */
7455	if (rev >= 5 && rev <= 10)
7456		filename = "ucode5";
7457	else if (rev >= 11 && rev <= 12)
7458		filename = "ucode11";
7459	else if (rev == 13)
7460		filename = "ucode13";
7461	else if (rev == 14)
7462		filename = "ucode14";
7463	else if (rev >= 15)
7464		filename = "ucode15";
7465	else {
7466		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7467		bwn_release_firmware(mac);
7468		return (EOPNOTSUPP);
7469	}
7470	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7471	if (error) {
7472		bwn_release_firmware(mac);
7473		return (error);
7474	}
7475
7476	/* PCM */
7477	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7478	if (rev >= 5 && rev <= 10) {
7479		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7480		if (error == ENOENT)
7481			fw->no_pcmfile = 1;
7482		else if (error) {
7483			bwn_release_firmware(mac);
7484			return (error);
7485		}
7486	} else if (rev < 11) {
7487		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7488		return (EOPNOTSUPP);
7489	}
7490
7491	/* initvals */
7492	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7493	switch (mac->mac_phy.type) {
7494	case BWN_PHYTYPE_A:
7495		if (rev < 5 || rev > 10)
7496			goto fail1;
7497		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7498			filename = "a0g1initvals5";
7499		else
7500			filename = "a0g0initvals5";
7501		break;
7502	case BWN_PHYTYPE_G:
7503		if (rev >= 5 && rev <= 10)
7504			filename = "b0g0initvals5";
7505		else if (rev >= 13)
7506			filename = "b0g0initvals13";
7507		else
7508			goto fail1;
7509		break;
7510	case BWN_PHYTYPE_LP:
7511		if (rev == 13)
7512			filename = "lp0initvals13";
7513		else if (rev == 14)
7514			filename = "lp0initvals14";
7515		else if (rev >= 15)
7516			filename = "lp0initvals15";
7517		else
7518			goto fail1;
7519		break;
7520	case BWN_PHYTYPE_N:
7521		if (rev >= 11 && rev <= 12)
7522			filename = "n0initvals11";
7523		else
7524			goto fail1;
7525		break;
7526	default:
7527		goto fail1;
7528	}
7529	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7530	if (error) {
7531		bwn_release_firmware(mac);
7532		return (error);
7533	}
7534
7535	/* bandswitch initvals */
7536	switch (mac->mac_phy.type) {
7537	case BWN_PHYTYPE_A:
7538		if (rev >= 5 && rev <= 10) {
7539			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7540				filename = "a0g1bsinitvals5";
7541			else
7542				filename = "a0g0bsinitvals5";
7543		} else if (rev >= 11)
7544			filename = NULL;
7545		else
7546			goto fail1;
7547		break;
7548	case BWN_PHYTYPE_G:
7549		if (rev >= 5 && rev <= 10)
7550			filename = "b0g0bsinitvals5";
7551		else if (rev >= 11)
7552			filename = NULL;
7553		else
7554			goto fail1;
7555		break;
7556	case BWN_PHYTYPE_LP:
7557		if (rev == 13)
7558			filename = "lp0bsinitvals13";
7559		else if (rev == 14)
7560			filename = "lp0bsinitvals14";
7561		else if (rev >= 15)
7562			filename = "lp0bsinitvals15";
7563		else
7564			goto fail1;
7565		break;
7566	case BWN_PHYTYPE_N:
7567		if (rev >= 11 && rev <= 12)
7568			filename = "n0bsinitvals11";
7569		else
7570			goto fail1;
7571		break;
7572	default:
7573		goto fail1;
7574	}
7575	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7576	if (error) {
7577		bwn_release_firmware(mac);
7578		return (error);
7579	}
7580	return (0);
7581fail1:
7582	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7583	bwn_release_firmware(mac);
7584	return (EOPNOTSUPP);
7585}
7586
7587static int
7588bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7589    const char *name, struct bwn_fwfile *bfw)
7590{
7591	const struct bwn_fwhdr *hdr;
7592	struct bwn_softc *sc = mac->mac_sc;
7593	const struct firmware *fw;
7594	char namebuf[64];
7595
7596	if (name == NULL) {
7597		bwn_do_release_fw(bfw);
7598		return (0);
7599	}
7600	if (bfw->filename != NULL) {
7601		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7602			return (0);
7603		bwn_do_release_fw(bfw);
7604	}
7605
7606	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7607	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7608	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7609	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7610	fw = firmware_get(namebuf);
7611	if (fw == NULL) {
7612		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7613		    namebuf);
7614		return (ENOENT);
7615	}
7616	if (fw->datasize < sizeof(struct bwn_fwhdr))
7617		goto fail;
7618	hdr = (const struct bwn_fwhdr *)(fw->data);
7619	switch (hdr->type) {
7620	case BWN_FWTYPE_UCODE:
7621	case BWN_FWTYPE_PCM:
7622		if (be32toh(hdr->size) !=
7623		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7624			goto fail;
7625		/* FALLTHROUGH */
7626	case BWN_FWTYPE_IV:
7627		if (hdr->ver != 1)
7628			goto fail;
7629		break;
7630	default:
7631		goto fail;
7632	}
7633	bfw->filename = name;
7634	bfw->fw = fw;
7635	bfw->type = type;
7636	return (0);
7637fail:
7638	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7639	if (fw != NULL)
7640		firmware_put(fw, FIRMWARE_UNLOAD);
7641	return (EPROTO);
7642}
7643
7644static void
7645bwn_release_firmware(struct bwn_mac *mac)
7646{
7647
7648	bwn_do_release_fw(&mac->mac_fw.ucode);
7649	bwn_do_release_fw(&mac->mac_fw.pcm);
7650	bwn_do_release_fw(&mac->mac_fw.initvals);
7651	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7652}
7653
7654static void
7655bwn_do_release_fw(struct bwn_fwfile *bfw)
7656{
7657
7658	if (bfw->fw != NULL)
7659		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7660	bfw->fw = NULL;
7661	bfw->filename = NULL;
7662}
7663
7664static int
7665bwn_fw_loaducode(struct bwn_mac *mac)
7666{
7667#define	GETFWOFFSET(fwp, offset)	\
7668	((const uint32_t *)((const char *)fwp.fw->data + offset))
7669#define	GETFWSIZE(fwp, offset)	\
7670	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7671	struct bwn_softc *sc = mac->mac_sc;
7672	const uint32_t *data;
7673	unsigned int i;
7674	uint32_t ctl;
7675	uint16_t date, fwcaps, time;
7676	int error = 0;
7677
7678	ctl = BWN_READ_4(mac, BWN_MACCTL);
7679	ctl |= BWN_MACCTL_MCODE_JMP0;
7680	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7681	    __LINE__));
7682	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7683	for (i = 0; i < 64; i++)
7684		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7685	for (i = 0; i < 4096; i += 2)
7686		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7687
7688	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7689	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7690	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7691	     i++) {
7692		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7693		DELAY(10);
7694	}
7695
7696	if (mac->mac_fw.pcm.fw) {
7697		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7698		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7699		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7700		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7701		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7702		    sizeof(struct bwn_fwhdr)); i++) {
7703			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7704			DELAY(10);
7705		}
7706	}
7707
7708	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7709	BWN_WRITE_4(mac, BWN_MACCTL,
7710	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7711	    BWN_MACCTL_MCODE_RUN);
7712
7713	for (i = 0; i < 21; i++) {
7714		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7715			break;
7716		if (i >= 20) {
7717			device_printf(sc->sc_dev, "ucode timeout\n");
7718			error = ENXIO;
7719			goto error;
7720		}
7721		DELAY(50000);
7722	}
7723	BWN_READ_4(mac, BWN_INTR_REASON);
7724
7725	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7726	if (mac->mac_fw.rev <= 0x128) {
7727		device_printf(sc->sc_dev, "the firmware is too old\n");
7728		error = EOPNOTSUPP;
7729		goto error;
7730	}
7731	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7732	    BWN_SHARED_UCODE_PATCH);
7733	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7734	mac->mac_fw.opensource = (date == 0xffff);
7735	if (bwn_wme != 0)
7736		mac->mac_flags |= BWN_MAC_FLAG_WME;
7737	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7738
7739	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7740	if (mac->mac_fw.opensource == 0) {
7741		device_printf(sc->sc_dev,
7742		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7743		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7744		if (mac->mac_fw.no_pcmfile)
7745			device_printf(sc->sc_dev,
7746			    "no HW crypto acceleration due to pcm5\n");
7747	} else {
7748		mac->mac_fw.patch = time;
7749		fwcaps = bwn_fwcaps_read(mac);
7750		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7751			device_printf(sc->sc_dev,
7752			    "disabling HW crypto acceleration\n");
7753			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7754		}
7755		if (!(fwcaps & BWN_FWCAPS_WME)) {
7756			device_printf(sc->sc_dev, "disabling WME support\n");
7757			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7758		}
7759	}
7760
7761	if (BWN_ISOLDFMT(mac))
7762		device_printf(sc->sc_dev, "using old firmware image\n");
7763
7764	return (0);
7765
7766error:
7767	BWN_WRITE_4(mac, BWN_MACCTL,
7768	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7769	    BWN_MACCTL_MCODE_JMP0);
7770
7771	return (error);
7772#undef GETFWSIZE
7773#undef GETFWOFFSET
7774}
7775
7776/* OpenFirmware only */
7777static uint16_t
7778bwn_fwcaps_read(struct bwn_mac *mac)
7779{
7780
7781	KASSERT(mac->mac_fw.opensource == 1,
7782	    ("%s:%d: fail", __func__, __LINE__));
7783	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7784}
7785
7786static int
7787bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7788    size_t count, size_t array_size)
7789{
7790#define	GET_NEXTIV16(iv)						\
7791	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7792	    sizeof(uint16_t) + sizeof(uint16_t)))
7793#define	GET_NEXTIV32(iv)						\
7794	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7795	    sizeof(uint16_t) + sizeof(uint32_t)))
7796	struct bwn_softc *sc = mac->mac_sc;
7797	const struct bwn_fwinitvals *iv;
7798	uint16_t offset;
7799	size_t i;
7800	uint8_t bit32;
7801
7802	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7803	    ("%s:%d: fail", __func__, __LINE__));
7804	iv = ivals;
7805	for (i = 0; i < count; i++) {
7806		if (array_size < sizeof(iv->offset_size))
7807			goto fail;
7808		array_size -= sizeof(iv->offset_size);
7809		offset = be16toh(iv->offset_size);
7810		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7811		offset &= BWN_FWINITVALS_OFFSET_MASK;
7812		if (offset >= 0x1000)
7813			goto fail;
7814		if (bit32) {
7815			if (array_size < sizeof(iv->data.d32))
7816				goto fail;
7817			array_size -= sizeof(iv->data.d32);
7818			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7819			iv = GET_NEXTIV32(iv);
7820		} else {
7821
7822			if (array_size < sizeof(iv->data.d16))
7823				goto fail;
7824			array_size -= sizeof(iv->data.d16);
7825			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7826
7827			iv = GET_NEXTIV16(iv);
7828		}
7829	}
7830	if (array_size != 0)
7831		goto fail;
7832	return (0);
7833fail:
7834	device_printf(sc->sc_dev, "initvals: invalid format\n");
7835	return (EPROTO);
7836#undef GET_NEXTIV16
7837#undef GET_NEXTIV32
7838}
7839
7840static int
7841bwn_switch_channel(struct bwn_mac *mac, int chan)
7842{
7843	struct bwn_phy *phy = &(mac->mac_phy);
7844	struct bwn_softc *sc = mac->mac_sc;
7845	struct ieee80211com *ic = &sc->sc_ic;
7846	uint16_t channelcookie, savedcookie;
7847	int error;
7848
7849	if (chan == 0xffff)
7850		chan = phy->get_default_chan(mac);
7851
7852	channelcookie = chan;
7853	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7854		channelcookie |= 0x100;
7855	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7856	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7857	error = phy->switch_channel(mac, chan);
7858	if (error)
7859		goto fail;
7860
7861	mac->mac_phy.chan = chan;
7862	DELAY(8000);
7863	return (0);
7864fail:
7865	device_printf(sc->sc_dev, "failed to switch channel\n");
7866	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7867	return (error);
7868}
7869
7870static uint16_t
7871bwn_ant2phy(int antenna)
7872{
7873
7874	switch (antenna) {
7875	case BWN_ANT0:
7876		return (BWN_TX_PHY_ANT0);
7877	case BWN_ANT1:
7878		return (BWN_TX_PHY_ANT1);
7879	case BWN_ANT2:
7880		return (BWN_TX_PHY_ANT2);
7881	case BWN_ANT3:
7882		return (BWN_TX_PHY_ANT3);
7883	case BWN_ANTAUTO:
7884		return (BWN_TX_PHY_ANT01AUTO);
7885	}
7886	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7887	return (0);
7888}
7889
7890static void
7891bwn_wme_load(struct bwn_mac *mac)
7892{
7893	struct bwn_softc *sc = mac->mac_sc;
7894	int i;
7895
7896	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7897	    ("%s:%d: fail", __func__, __LINE__));
7898
7899	bwn_mac_suspend(mac);
7900	for (i = 0; i < N(sc->sc_wmeParams); i++)
7901		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
7902		    bwn_wme_shm_offsets[i]);
7903	bwn_mac_enable(mac);
7904}
7905
7906static void
7907bwn_wme_loadparams(struct bwn_mac *mac,
7908    const struct wmeParams *p, uint16_t shm_offset)
7909{
7910#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
7911	struct bwn_softc *sc = mac->mac_sc;
7912	uint16_t params[BWN_NR_WMEPARAMS];
7913	int slot, tmp;
7914	unsigned int i;
7915
7916	slot = BWN_READ_2(mac, BWN_RNG) &
7917	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7918
7919	memset(&params, 0, sizeof(params));
7920
7921	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
7922	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
7923	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
7924
7925	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
7926	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7927	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
7928	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7929	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
7930	params[BWN_WMEPARAM_BSLOTS] = slot;
7931	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
7932
7933	for (i = 0; i < N(params); i++) {
7934		if (i == BWN_WMEPARAM_STATUS) {
7935			tmp = bwn_shm_read_2(mac, BWN_SHARED,
7936			    shm_offset + (i * 2));
7937			tmp |= 0x100;
7938			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7939			    tmp);
7940		} else {
7941			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7942			    params[i]);
7943		}
7944	}
7945}
7946
7947static void
7948bwn_mac_write_bssid(struct bwn_mac *mac)
7949{
7950	struct bwn_softc *sc = mac->mac_sc;
7951	uint32_t tmp;
7952	int i;
7953	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
7954
7955	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
7956	memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
7957	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
7958	    IEEE80211_ADDR_LEN);
7959
7960	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
7961		tmp = (uint32_t) (mac_bssid[i + 0]);
7962		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
7963		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
7964		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
7965		bwn_ram_write(mac, 0x20 + i, tmp);
7966	}
7967}
7968
7969static void
7970bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
7971    const uint8_t *macaddr)
7972{
7973	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
7974	uint16_t data;
7975
7976	if (!mac)
7977		macaddr = zero;
7978
7979	offset |= 0x0020;
7980	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
7981
7982	data = macaddr[0];
7983	data |= macaddr[1] << 8;
7984	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7985	data = macaddr[2];
7986	data |= macaddr[3] << 8;
7987	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7988	data = macaddr[4];
7989	data |= macaddr[5] << 8;
7990	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7991}
7992
7993static void
7994bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
7995    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
7996{
7997	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
7998	uint8_t per_sta_keys_start = 8;
7999
8000	if (BWN_SEC_NEWAPI(mac))
8001		per_sta_keys_start = 4;
8002
8003	KASSERT(index < mac->mac_max_nr_keys,
8004	    ("%s:%d: fail", __func__, __LINE__));
8005	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8006	    ("%s:%d: fail", __func__, __LINE__));
8007
8008	if (index >= per_sta_keys_start)
8009		bwn_key_macwrite(mac, index, NULL);
8010	if (key)
8011		memcpy(buf, key, key_len);
8012	bwn_key_write(mac, index, algorithm, buf);
8013	if (index >= per_sta_keys_start)
8014		bwn_key_macwrite(mac, index, mac_addr);
8015
8016	mac->mac_key[index].algorithm = algorithm;
8017}
8018
8019static void
8020bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8021{
8022	struct bwn_softc *sc = mac->mac_sc;
8023	uint32_t addrtmp[2] = { 0, 0 };
8024	uint8_t start = 8;
8025
8026	if (BWN_SEC_NEWAPI(mac))
8027		start = 4;
8028
8029	KASSERT(index >= start,
8030	    ("%s:%d: fail", __func__, __LINE__));
8031	index -= start;
8032
8033	if (addr) {
8034		addrtmp[0] = addr[0];
8035		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8036		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8037		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8038		addrtmp[1] = addr[4];
8039		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8040	}
8041
8042	if (siba_get_revid(sc->sc_dev) >= 5) {
8043		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8044		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8045	} else {
8046		if (index >= 8) {
8047			bwn_shm_write_4(mac, BWN_SHARED,
8048			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8049			bwn_shm_write_2(mac, BWN_SHARED,
8050			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8051		}
8052	}
8053}
8054
8055static void
8056bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8057    const uint8_t *key)
8058{
8059	unsigned int i;
8060	uint32_t offset;
8061	uint16_t kidx, value;
8062
8063	kidx = BWN_SEC_KEY2FW(mac, index);
8064	bwn_shm_write_2(mac, BWN_SHARED,
8065	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8066
8067	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8068	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8069		value = key[i];
8070		value |= (uint16_t)(key[i + 1]) << 8;
8071		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8072	}
8073}
8074
8075static void
8076bwn_phy_exit(struct bwn_mac *mac)
8077{
8078
8079	mac->mac_phy.rf_onoff(mac, 0);
8080	if (mac->mac_phy.exit != NULL)
8081		mac->mac_phy.exit(mac);
8082}
8083
8084static void
8085bwn_dma_free(struct bwn_mac *mac)
8086{
8087	struct bwn_dma *dma;
8088
8089	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8090		return;
8091	dma = &mac->mac_method.dma;
8092
8093	bwn_dma_ringfree(&dma->rx);
8094	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8095	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8096	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8097	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8098	bwn_dma_ringfree(&dma->mcast);
8099}
8100
8101static void
8102bwn_core_stop(struct bwn_mac *mac)
8103{
8104	struct bwn_softc *sc = mac->mac_sc;
8105
8106	BWN_ASSERT_LOCKED(sc);
8107
8108	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8109		return;
8110
8111	callout_stop(&sc->sc_rfswitch_ch);
8112	callout_stop(&sc->sc_task_ch);
8113	callout_stop(&sc->sc_watchdog_ch);
8114	sc->sc_watchdog_timer = 0;
8115	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8116	BWN_READ_4(mac, BWN_INTR_MASK);
8117	bwn_mac_suspend(mac);
8118
8119	mac->mac_status = BWN_MAC_STATUS_INITED;
8120}
8121
8122static int
8123bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8124{
8125	struct bwn_mac *up_dev = NULL;
8126	struct bwn_mac *down_dev;
8127	struct bwn_mac *mac;
8128	int err, status;
8129	uint8_t gmode;
8130
8131	BWN_ASSERT_LOCKED(sc);
8132
8133	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8134		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8135		    mac->mac_phy.supports_2ghz) {
8136			up_dev = mac;
8137			gmode = 1;
8138		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8139		    mac->mac_phy.supports_5ghz) {
8140			up_dev = mac;
8141			gmode = 0;
8142		} else {
8143			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8144			return (EINVAL);
8145		}
8146		if (up_dev != NULL)
8147			break;
8148	}
8149	if (up_dev == NULL) {
8150		device_printf(sc->sc_dev, "Could not find a device\n");
8151		return (ENODEV);
8152	}
8153	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8154		return (0);
8155
8156	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8157	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8158
8159	down_dev = sc->sc_curmac;
8160	status = down_dev->mac_status;
8161	if (status >= BWN_MAC_STATUS_STARTED)
8162		bwn_core_stop(down_dev);
8163	if (status >= BWN_MAC_STATUS_INITED)
8164		bwn_core_exit(down_dev);
8165
8166	if (down_dev != up_dev)
8167		bwn_phy_reset(down_dev);
8168
8169	up_dev->mac_phy.gmode = gmode;
8170	if (status >= BWN_MAC_STATUS_INITED) {
8171		err = bwn_core_init(up_dev);
8172		if (err) {
8173			device_printf(sc->sc_dev,
8174			    "fatal: failed to initialize for %s-GHz\n",
8175			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8176			goto fail;
8177		}
8178	}
8179	if (status >= BWN_MAC_STATUS_STARTED)
8180		bwn_core_start(up_dev);
8181	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8182	sc->sc_curmac = up_dev;
8183
8184	return (0);
8185fail:
8186	sc->sc_curmac = NULL;
8187	return (err);
8188}
8189
8190static void
8191bwn_rf_turnon(struct bwn_mac *mac)
8192{
8193
8194	bwn_mac_suspend(mac);
8195	mac->mac_phy.rf_onoff(mac, 1);
8196	mac->mac_phy.rf_on = 1;
8197	bwn_mac_enable(mac);
8198}
8199
8200static void
8201bwn_rf_turnoff(struct bwn_mac *mac)
8202{
8203
8204	bwn_mac_suspend(mac);
8205	mac->mac_phy.rf_onoff(mac, 0);
8206	mac->mac_phy.rf_on = 0;
8207	bwn_mac_enable(mac);
8208}
8209
8210static void
8211bwn_phy_reset(struct bwn_mac *mac)
8212{
8213	struct bwn_softc *sc = mac->mac_sc;
8214
8215	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8216	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8217	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8218	DELAY(1000);
8219	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8220	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8221	    BWN_TGSLOW_PHYRESET);
8222	DELAY(1000);
8223}
8224
8225static int
8226bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8227{
8228	struct bwn_vap *bvp = BWN_VAP(vap);
8229	struct ieee80211com *ic= vap->iv_ic;
8230	enum ieee80211_state ostate = vap->iv_state;
8231	struct bwn_softc *sc = ic->ic_softc;
8232	struct bwn_mac *mac = sc->sc_curmac;
8233	int error;
8234
8235	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8236	    ieee80211_state_name[vap->iv_state],
8237	    ieee80211_state_name[nstate]);
8238
8239	error = bvp->bv_newstate(vap, nstate, arg);
8240	if (error != 0)
8241		return (error);
8242
8243	BWN_LOCK(sc);
8244
8245	bwn_led_newstate(mac, nstate);
8246
8247	/*
8248	 * Clear the BSSID when we stop a STA
8249	 */
8250	if (vap->iv_opmode == IEEE80211_M_STA) {
8251		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8252			/*
8253			 * Clear out the BSSID.  If we reassociate to
8254			 * the same AP, this will reinialize things
8255			 * correctly...
8256			 */
8257			if (ic->ic_opmode == IEEE80211_M_STA &&
8258			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8259				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8260				bwn_set_macaddr(mac);
8261			}
8262		}
8263	}
8264
8265	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8266	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8267		/* XXX nothing to do? */
8268	} else if (nstate == IEEE80211_S_RUN) {
8269		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8270		bwn_set_opmode(mac);
8271		bwn_set_pretbtt(mac);
8272		bwn_spu_setdelay(mac, 0);
8273		bwn_set_macaddr(mac);
8274	}
8275
8276	BWN_UNLOCK(sc);
8277
8278	return (error);
8279}
8280
8281static void
8282bwn_set_pretbtt(struct bwn_mac *mac)
8283{
8284	struct bwn_softc *sc = mac->mac_sc;
8285	struct ieee80211com *ic = &sc->sc_ic;
8286	uint16_t pretbtt;
8287
8288	if (ic->ic_opmode == IEEE80211_M_IBSS)
8289		pretbtt = 2;
8290	else
8291		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8292	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8293	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8294}
8295
8296static int
8297bwn_intr(void *arg)
8298{
8299	struct bwn_mac *mac = arg;
8300	struct bwn_softc *sc = mac->mac_sc;
8301	uint32_t reason;
8302
8303	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8304	    (sc->sc_flags & BWN_FLAG_INVALID))
8305		return (FILTER_STRAY);
8306
8307	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8308	if (reason == 0xffffffff)	/* shared IRQ */
8309		return (FILTER_STRAY);
8310	reason &= mac->mac_intr_mask;
8311	if (reason == 0)
8312		return (FILTER_HANDLED);
8313
8314	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8315	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8316	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8317	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8318	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8319	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8320	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8321	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8322	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8323	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8324	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8325
8326	/* Disable interrupts. */
8327	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8328
8329	mac->mac_reason_intr = reason;
8330
8331	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8332	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8333
8334	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8335	return (FILTER_HANDLED);
8336}
8337
8338static void
8339bwn_intrtask(void *arg, int npending)
8340{
8341	struct bwn_mac *mac = arg;
8342	struct bwn_softc *sc = mac->mac_sc;
8343	uint32_t merged = 0;
8344	int i, tx = 0, rx = 0;
8345
8346	BWN_LOCK(sc);
8347	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8348	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8349		BWN_UNLOCK(sc);
8350		return;
8351	}
8352
8353	for (i = 0; i < N(mac->mac_reason); i++)
8354		merged |= mac->mac_reason[i];
8355
8356	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8357		device_printf(sc->sc_dev, "MAC trans error\n");
8358
8359	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8360		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8361		mac->mac_phy.txerrors--;
8362		if (mac->mac_phy.txerrors == 0) {
8363			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8364			bwn_restart(mac, "PHY TX errors");
8365		}
8366	}
8367
8368	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8369		if (merged & BWN_DMAINTR_FATALMASK) {
8370			device_printf(sc->sc_dev,
8371			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8372			    mac->mac_reason[0], mac->mac_reason[1],
8373			    mac->mac_reason[2], mac->mac_reason[3],
8374			    mac->mac_reason[4], mac->mac_reason[5]);
8375			bwn_restart(mac, "DMA error");
8376			BWN_UNLOCK(sc);
8377			return;
8378		}
8379		if (merged & BWN_DMAINTR_NONFATALMASK) {
8380			device_printf(sc->sc_dev,
8381			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8382			    mac->mac_reason[0], mac->mac_reason[1],
8383			    mac->mac_reason[2], mac->mac_reason[3],
8384			    mac->mac_reason[4], mac->mac_reason[5]);
8385		}
8386	}
8387
8388	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8389		bwn_intr_ucode_debug(mac);
8390	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8391		bwn_intr_tbtt_indication(mac);
8392	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8393		bwn_intr_atim_end(mac);
8394	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8395		bwn_intr_beacon(mac);
8396	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8397		bwn_intr_pmq(mac);
8398	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8399		bwn_intr_noise(mac);
8400
8401	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8402		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8403			bwn_dma_rx(mac->mac_method.dma.rx);
8404			rx = 1;
8405		}
8406	} else
8407		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8408
8409	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8410	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8411	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8412	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8413	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8414
8415	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8416		bwn_intr_txeof(mac);
8417		tx = 1;
8418	}
8419
8420	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8421
8422	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8423		int evt = BWN_LED_EVENT_NONE;
8424
8425		if (tx && rx) {
8426			if (sc->sc_rx_rate > sc->sc_tx_rate)
8427				evt = BWN_LED_EVENT_RX;
8428			else
8429				evt = BWN_LED_EVENT_TX;
8430		} else if (tx) {
8431			evt = BWN_LED_EVENT_TX;
8432		} else if (rx) {
8433			evt = BWN_LED_EVENT_RX;
8434		} else if (rx == 0) {
8435			evt = BWN_LED_EVENT_POLL;
8436		}
8437
8438		if (evt != BWN_LED_EVENT_NONE)
8439			bwn_led_event(mac, evt);
8440       }
8441
8442	if (mbufq_first(&sc->sc_snd) != NULL)
8443		bwn_start(sc);
8444
8445	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8446	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8447
8448	BWN_UNLOCK(sc);
8449}
8450
8451static void
8452bwn_restart(struct bwn_mac *mac, const char *msg)
8453{
8454	struct bwn_softc *sc = mac->mac_sc;
8455	struct ieee80211com *ic = &sc->sc_ic;
8456
8457	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8458		return;
8459
8460	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8461	ieee80211_runtask(ic, &mac->mac_hwreset);
8462}
8463
8464static void
8465bwn_intr_ucode_debug(struct bwn_mac *mac)
8466{
8467	struct bwn_softc *sc = mac->mac_sc;
8468	uint16_t reason;
8469
8470	if (mac->mac_fw.opensource == 0)
8471		return;
8472
8473	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8474	switch (reason) {
8475	case BWN_DEBUGINTR_PANIC:
8476		bwn_handle_fwpanic(mac);
8477		break;
8478	case BWN_DEBUGINTR_DUMP_SHM:
8479		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8480		break;
8481	case BWN_DEBUGINTR_DUMP_REGS:
8482		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8483		break;
8484	case BWN_DEBUGINTR_MARKER:
8485		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8486		break;
8487	default:
8488		device_printf(sc->sc_dev,
8489		    "ucode debug unknown reason: %#x\n", reason);
8490	}
8491
8492	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8493	    BWN_DEBUGINTR_ACK);
8494}
8495
8496static void
8497bwn_intr_tbtt_indication(struct bwn_mac *mac)
8498{
8499	struct bwn_softc *sc = mac->mac_sc;
8500	struct ieee80211com *ic = &sc->sc_ic;
8501
8502	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8503		bwn_psctl(mac, 0);
8504	if (ic->ic_opmode == IEEE80211_M_IBSS)
8505		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8506}
8507
8508static void
8509bwn_intr_atim_end(struct bwn_mac *mac)
8510{
8511
8512	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8513		BWN_WRITE_4(mac, BWN_MACCMD,
8514		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8515		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8516	}
8517}
8518
8519static void
8520bwn_intr_beacon(struct bwn_mac *mac)
8521{
8522	struct bwn_softc *sc = mac->mac_sc;
8523	struct ieee80211com *ic = &sc->sc_ic;
8524	uint32_t cmd, beacon0, beacon1;
8525
8526	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8527	    ic->ic_opmode == IEEE80211_M_MBSS)
8528		return;
8529
8530	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8531
8532	cmd = BWN_READ_4(mac, BWN_MACCMD);
8533	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8534	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8535
8536	if (beacon0 && beacon1) {
8537		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8538		mac->mac_intr_mask |= BWN_INTR_BEACON;
8539		return;
8540	}
8541
8542	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8543		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8544		bwn_load_beacon0(mac);
8545		bwn_load_beacon1(mac);
8546		cmd = BWN_READ_4(mac, BWN_MACCMD);
8547		cmd |= BWN_MACCMD_BEACON0_VALID;
8548		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8549	} else {
8550		if (!beacon0) {
8551			bwn_load_beacon0(mac);
8552			cmd = BWN_READ_4(mac, BWN_MACCMD);
8553			cmd |= BWN_MACCMD_BEACON0_VALID;
8554			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8555		} else if (!beacon1) {
8556			bwn_load_beacon1(mac);
8557			cmd = BWN_READ_4(mac, BWN_MACCMD);
8558			cmd |= BWN_MACCMD_BEACON1_VALID;
8559			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8560		}
8561	}
8562}
8563
8564static void
8565bwn_intr_pmq(struct bwn_mac *mac)
8566{
8567	uint32_t tmp;
8568
8569	while (1) {
8570		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8571		if (!(tmp & 0x00000008))
8572			break;
8573	}
8574	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8575}
8576
8577static void
8578bwn_intr_noise(struct bwn_mac *mac)
8579{
8580	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8581	uint16_t tmp;
8582	uint8_t noise[4];
8583	uint8_t i, j;
8584	int32_t average;
8585
8586	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8587		return;
8588
8589	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8590	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8591	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8592	    noise[3] == 0x7f)
8593		goto new;
8594
8595	KASSERT(mac->mac_noise.noi_nsamples < 8,
8596	    ("%s:%d: fail", __func__, __LINE__));
8597	i = mac->mac_noise.noi_nsamples;
8598	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8599	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8600	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8601	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8602	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8603	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8604	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8605	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8606	mac->mac_noise.noi_nsamples++;
8607	if (mac->mac_noise.noi_nsamples == 8) {
8608		average = 0;
8609		for (i = 0; i < 8; i++) {
8610			for (j = 0; j < 4; j++)
8611				average += mac->mac_noise.noi_samples[i][j];
8612		}
8613		average = (((average / 32) * 125) + 64) / 128;
8614		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8615		if (tmp >= 8)
8616			average += 2;
8617		else
8618			average -= 25;
8619		average -= (tmp == 8) ? 72 : 48;
8620
8621		mac->mac_stats.link_noise = average;
8622		mac->mac_noise.noi_running = 0;
8623		return;
8624	}
8625new:
8626	bwn_noise_gensample(mac);
8627}
8628
8629static int
8630bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8631{
8632	struct bwn_mac *mac = prq->prq_mac;
8633	struct bwn_softc *sc = mac->mac_sc;
8634	unsigned int i;
8635
8636	BWN_ASSERT_LOCKED(sc);
8637
8638	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8639		return (0);
8640
8641	for (i = 0; i < 5000; i++) {
8642		if (bwn_pio_rxeof(prq) == 0)
8643			break;
8644	}
8645	if (i >= 5000)
8646		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8647	return ((i > 0) ? 1 : 0);
8648}
8649
8650static void
8651bwn_dma_rx(struct bwn_dma_ring *dr)
8652{
8653	int slot, curslot;
8654
8655	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8656	curslot = dr->get_curslot(dr);
8657	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8658	    ("%s:%d: fail", __func__, __LINE__));
8659
8660	slot = dr->dr_curslot;
8661	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8662		bwn_dma_rxeof(dr, &slot);
8663
8664	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8665	    BUS_DMASYNC_PREWRITE);
8666
8667	dr->set_curslot(dr, slot);
8668	dr->dr_curslot = slot;
8669}
8670
8671static void
8672bwn_intr_txeof(struct bwn_mac *mac)
8673{
8674	struct bwn_txstatus stat;
8675	uint32_t stat0, stat1;
8676	uint16_t tmp;
8677
8678	BWN_ASSERT_LOCKED(mac->mac_sc);
8679
8680	while (1) {
8681		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8682		if (!(stat0 & 0x00000001))
8683			break;
8684		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8685
8686		stat.cookie = (stat0 >> 16);
8687		stat.seq = (stat1 & 0x0000ffff);
8688		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8689		tmp = (stat0 & 0x0000ffff);
8690		stat.framecnt = ((tmp & 0xf000) >> 12);
8691		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8692		stat.sreason = ((tmp & 0x001c) >> 2);
8693		stat.pm = (tmp & 0x0080) ? 1 : 0;
8694		stat.im = (tmp & 0x0040) ? 1 : 0;
8695		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8696		stat.ack = (tmp & 0x0002) ? 1 : 0;
8697
8698		bwn_handle_txeof(mac, &stat);
8699	}
8700}
8701
8702static void
8703bwn_hwreset(void *arg, int npending)
8704{
8705	struct bwn_mac *mac = arg;
8706	struct bwn_softc *sc = mac->mac_sc;
8707	int error = 0;
8708	int prev_status;
8709
8710	BWN_LOCK(sc);
8711
8712	prev_status = mac->mac_status;
8713	if (prev_status >= BWN_MAC_STATUS_STARTED)
8714		bwn_core_stop(mac);
8715	if (prev_status >= BWN_MAC_STATUS_INITED)
8716		bwn_core_exit(mac);
8717
8718	if (prev_status >= BWN_MAC_STATUS_INITED) {
8719		error = bwn_core_init(mac);
8720		if (error)
8721			goto out;
8722	}
8723	if (prev_status >= BWN_MAC_STATUS_STARTED)
8724		bwn_core_start(mac);
8725out:
8726	if (error) {
8727		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8728		sc->sc_curmac = NULL;
8729	}
8730	BWN_UNLOCK(sc);
8731}
8732
8733static void
8734bwn_handle_fwpanic(struct bwn_mac *mac)
8735{
8736	struct bwn_softc *sc = mac->mac_sc;
8737	uint16_t reason;
8738
8739	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8740	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8741
8742	if (reason == BWN_FWPANIC_RESTART)
8743		bwn_restart(mac, "ucode panic");
8744}
8745
8746static void
8747bwn_load_beacon0(struct bwn_mac *mac)
8748{
8749
8750	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8751}
8752
8753static void
8754bwn_load_beacon1(struct bwn_mac *mac)
8755{
8756
8757	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8758}
8759
8760static uint32_t
8761bwn_jssi_read(struct bwn_mac *mac)
8762{
8763	uint32_t val = 0;
8764
8765	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8766	val <<= 16;
8767	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8768
8769	return (val);
8770}
8771
8772static void
8773bwn_noise_gensample(struct bwn_mac *mac)
8774{
8775	uint32_t jssi = 0x7f7f7f7f;
8776
8777	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8778	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8779	BWN_WRITE_4(mac, BWN_MACCMD,
8780	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8781}
8782
8783static int
8784bwn_dma_freeslot(struct bwn_dma_ring *dr)
8785{
8786	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8787
8788	return (dr->dr_numslots - dr->dr_usedslot);
8789}
8790
8791static int
8792bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8793{
8794	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8795
8796	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8797	    ("%s:%d: fail", __func__, __LINE__));
8798	if (slot == dr->dr_numslots - 1)
8799		return (0);
8800	return (slot + 1);
8801}
8802
8803static void
8804bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8805{
8806	struct bwn_mac *mac = dr->dr_mac;
8807	struct bwn_softc *sc = mac->mac_sc;
8808	struct bwn_dma *dma = &mac->mac_method.dma;
8809	struct bwn_dmadesc_generic *desc;
8810	struct bwn_dmadesc_meta *meta;
8811	struct bwn_rxhdr4 *rxhdr;
8812	struct mbuf *m;
8813	uint32_t macstat;
8814	int32_t tmp;
8815	int cnt = 0;
8816	uint16_t len;
8817
8818	dr->getdesc(dr, *slot, &desc, &meta);
8819
8820	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8821	m = meta->mt_m;
8822
8823	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8824		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8825		return;
8826	}
8827
8828	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8829	len = le16toh(rxhdr->frame_len);
8830	if (len <= 0) {
8831		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8832		return;
8833	}
8834	if (bwn_dma_check_redzone(dr, m)) {
8835		device_printf(sc->sc_dev, "redzone error.\n");
8836		bwn_dma_set_redzone(dr, m);
8837		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8838		    BUS_DMASYNC_PREWRITE);
8839		return;
8840	}
8841	if (len > dr->dr_rx_bufsize) {
8842		tmp = len;
8843		while (1) {
8844			dr->getdesc(dr, *slot, &desc, &meta);
8845			bwn_dma_set_redzone(dr, meta->mt_m);
8846			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8847			    BUS_DMASYNC_PREWRITE);
8848			*slot = bwn_dma_nextslot(dr, *slot);
8849			cnt++;
8850			tmp -= dr->dr_rx_bufsize;
8851			if (tmp <= 0)
8852				break;
8853		}
8854		device_printf(sc->sc_dev, "too small buffer "
8855		       "(len %u buffer %u dropped %d)\n",
8856		       len, dr->dr_rx_bufsize, cnt);
8857		return;
8858	}
8859	macstat = le32toh(rxhdr->mac_status);
8860	if (macstat & BWN_RX_MAC_FCSERR) {
8861		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8862			device_printf(sc->sc_dev, "RX drop\n");
8863			return;
8864		}
8865	}
8866
8867	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8868	m_adj(m, dr->dr_frameoffset);
8869
8870	bwn_rxeof(dr->dr_mac, m, rxhdr);
8871}
8872
8873static void
8874bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8875{
8876	struct bwn_dma_ring *dr;
8877	struct bwn_dmadesc_generic *desc;
8878	struct bwn_dmadesc_meta *meta;
8879	struct bwn_pio_txqueue *tq;
8880	struct bwn_pio_txpkt *tp = NULL;
8881	struct bwn_softc *sc = mac->mac_sc;
8882	struct bwn_stats *stats = &mac->mac_stats;
8883	struct ieee80211_node *ni;
8884	struct ieee80211vap *vap;
8885	int retrycnt = 0, slot;
8886
8887	BWN_ASSERT_LOCKED(mac->mac_sc);
8888
8889	if (status->im)
8890		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8891	if (status->ampdu)
8892		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
8893	if (status->rtscnt) {
8894		if (status->rtscnt == 0xf)
8895			stats->rtsfail++;
8896		else
8897			stats->rts++;
8898	}
8899
8900	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8901		if (status->ack) {
8902			dr = bwn_dma_parse_cookie(mac, status,
8903			    status->cookie, &slot);
8904			if (dr == NULL) {
8905				device_printf(sc->sc_dev,
8906				    "failed to parse cookie\n");
8907				return;
8908			}
8909			while (1) {
8910				dr->getdesc(dr, slot, &desc, &meta);
8911				if (meta->mt_islast) {
8912					ni = meta->mt_ni;
8913					vap = ni->ni_vap;
8914					ieee80211_ratectl_tx_complete(vap, ni,
8915					    status->ack ?
8916					      IEEE80211_RATECTL_TX_SUCCESS :
8917					      IEEE80211_RATECTL_TX_FAILURE,
8918					    &retrycnt, 0);
8919					break;
8920				}
8921				slot = bwn_dma_nextslot(dr, slot);
8922			}
8923		}
8924		bwn_dma_handle_txeof(mac, status);
8925	} else {
8926		if (status->ack) {
8927			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
8928			if (tq == NULL) {
8929				device_printf(sc->sc_dev,
8930				    "failed to parse cookie\n");
8931				return;
8932			}
8933			ni = tp->tp_ni;
8934			vap = ni->ni_vap;
8935			ieee80211_ratectl_tx_complete(vap, ni,
8936			    status->ack ?
8937			      IEEE80211_RATECTL_TX_SUCCESS :
8938			      IEEE80211_RATECTL_TX_FAILURE,
8939			    &retrycnt, 0);
8940		}
8941		bwn_pio_handle_txeof(mac, status);
8942	}
8943
8944	bwn_phy_txpower_check(mac, 0);
8945}
8946
8947static uint8_t
8948bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
8949{
8950	struct bwn_mac *mac = prq->prq_mac;
8951	struct bwn_softc *sc = mac->mac_sc;
8952	struct bwn_rxhdr4 rxhdr;
8953	struct mbuf *m;
8954	uint32_t ctl32, macstat, v32;
8955	unsigned int i, padding;
8956	uint16_t ctl16, len, totlen, v16;
8957	unsigned char *mp;
8958	char *data;
8959
8960	memset(&rxhdr, 0, sizeof(rxhdr));
8961
8962	if (prq->prq_rev >= 8) {
8963		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8964		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
8965			return (0);
8966		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
8967		    BWN_PIO8_RXCTL_FRAMEREADY);
8968		for (i = 0; i < 10; i++) {
8969			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8970			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
8971				goto ready;
8972			DELAY(10);
8973		}
8974	} else {
8975		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8976		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
8977			return (0);
8978		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
8979		    BWN_PIO_RXCTL_FRAMEREADY);
8980		for (i = 0; i < 10; i++) {
8981			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8982			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
8983				goto ready;
8984			DELAY(10);
8985		}
8986	}
8987	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
8988	return (1);
8989ready:
8990	if (prq->prq_rev >= 8)
8991		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8992		    prq->prq_base + BWN_PIO8_RXDATA);
8993	else
8994		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8995		    prq->prq_base + BWN_PIO_RXDATA);
8996	len = le16toh(rxhdr.frame_len);
8997	if (len > 0x700) {
8998		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
8999		goto error;
9000	}
9001	if (len == 0) {
9002		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9003		goto error;
9004	}
9005
9006	macstat = le32toh(rxhdr.mac_status);
9007	if (macstat & BWN_RX_MAC_FCSERR) {
9008		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9009			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9010			goto error;
9011		}
9012	}
9013
9014	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9015	totlen = len + padding;
9016	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9017	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9018	if (m == NULL) {
9019		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9020		goto error;
9021	}
9022	mp = mtod(m, unsigned char *);
9023	if (prq->prq_rev >= 8) {
9024		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9025		    prq->prq_base + BWN_PIO8_RXDATA);
9026		if (totlen & 3) {
9027			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9028			data = &(mp[totlen - 1]);
9029			switch (totlen & 3) {
9030			case 3:
9031				*data = (v32 >> 16);
9032				data--;
9033			case 2:
9034				*data = (v32 >> 8);
9035				data--;
9036			case 1:
9037				*data = v32;
9038			}
9039		}
9040	} else {
9041		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9042		    prq->prq_base + BWN_PIO_RXDATA);
9043		if (totlen & 1) {
9044			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9045			mp[totlen - 1] = v16;
9046		}
9047	}
9048
9049	m->m_len = m->m_pkthdr.len = totlen;
9050
9051	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9052
9053	return (1);
9054error:
9055	if (prq->prq_rev >= 8)
9056		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9057		    BWN_PIO8_RXCTL_DATAREADY);
9058	else
9059		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9060	return (1);
9061}
9062
9063static int
9064bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9065    struct bwn_dmadesc_meta *meta, int init)
9066{
9067	struct bwn_mac *mac = dr->dr_mac;
9068	struct bwn_dma *dma = &mac->mac_method.dma;
9069	struct bwn_rxhdr4 *hdr;
9070	bus_dmamap_t map;
9071	bus_addr_t paddr;
9072	struct mbuf *m;
9073	int error;
9074
9075	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9076	if (m == NULL) {
9077		error = ENOBUFS;
9078
9079		/*
9080		 * If the NIC is up and running, we need to:
9081		 * - Clear RX buffer's header.
9082		 * - Restore RX descriptor settings.
9083		 */
9084		if (init)
9085			return (error);
9086		else
9087			goto back;
9088	}
9089	m->m_len = m->m_pkthdr.len = MCLBYTES;
9090
9091	bwn_dma_set_redzone(dr, m);
9092
9093	/*
9094	 * Try to load RX buf into temporary DMA map
9095	 */
9096	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9097	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9098	if (error) {
9099		m_freem(m);
9100
9101		/*
9102		 * See the comment above
9103		 */
9104		if (init)
9105			return (error);
9106		else
9107			goto back;
9108	}
9109
9110	if (!init)
9111		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9112	meta->mt_m = m;
9113	meta->mt_paddr = paddr;
9114
9115	/*
9116	 * Swap RX buf's DMA map with the loaded temporary one
9117	 */
9118	map = meta->mt_dmap;
9119	meta->mt_dmap = dr->dr_spare_dmap;
9120	dr->dr_spare_dmap = map;
9121
9122back:
9123	/*
9124	 * Clear RX buf header
9125	 */
9126	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9127	bzero(hdr, sizeof(*hdr));
9128	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9129	    BUS_DMASYNC_PREWRITE);
9130
9131	/*
9132	 * Setup RX buf descriptor
9133	 */
9134	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9135	    sizeof(*hdr), 0, 0, 0);
9136	return (error);
9137}
9138
9139static void
9140bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9141		 bus_size_t mapsz __unused, int error)
9142{
9143
9144	if (!error) {
9145		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9146		*((bus_addr_t *)arg) = seg->ds_addr;
9147	}
9148}
9149
9150static int
9151bwn_hwrate2ieeerate(int rate)
9152{
9153
9154	switch (rate) {
9155	case BWN_CCK_RATE_1MB:
9156		return (2);
9157	case BWN_CCK_RATE_2MB:
9158		return (4);
9159	case BWN_CCK_RATE_5MB:
9160		return (11);
9161	case BWN_CCK_RATE_11MB:
9162		return (22);
9163	case BWN_OFDM_RATE_6MB:
9164		return (12);
9165	case BWN_OFDM_RATE_9MB:
9166		return (18);
9167	case BWN_OFDM_RATE_12MB:
9168		return (24);
9169	case BWN_OFDM_RATE_18MB:
9170		return (36);
9171	case BWN_OFDM_RATE_24MB:
9172		return (48);
9173	case BWN_OFDM_RATE_36MB:
9174		return (72);
9175	case BWN_OFDM_RATE_48MB:
9176		return (96);
9177	case BWN_OFDM_RATE_54MB:
9178		return (108);
9179	default:
9180		printf("Ooops\n");
9181		return (0);
9182	}
9183}
9184
9185static void
9186bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9187{
9188	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9189	struct bwn_plcp6 *plcp;
9190	struct bwn_softc *sc = mac->mac_sc;
9191	struct ieee80211_frame_min *wh;
9192	struct ieee80211_node *ni;
9193	struct ieee80211com *ic = &sc->sc_ic;
9194	uint32_t macstat;
9195	int padding, rate, rssi = 0, noise = 0, type;
9196	uint16_t phytype, phystat0, phystat3, chanstat;
9197	unsigned char *mp = mtod(m, unsigned char *);
9198	static int rx_mac_dec_rpt = 0;
9199
9200	BWN_ASSERT_LOCKED(sc);
9201
9202	phystat0 = le16toh(rxhdr->phy_status0);
9203	phystat3 = le16toh(rxhdr->phy_status3);
9204	macstat = le32toh(rxhdr->mac_status);
9205	chanstat = le16toh(rxhdr->channel);
9206	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9207
9208	if (macstat & BWN_RX_MAC_FCSERR)
9209		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9210	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9211		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9212	if (macstat & BWN_RX_MAC_DECERR)
9213		goto drop;
9214
9215	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9216	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9217		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9218		    m->m_pkthdr.len);
9219		goto drop;
9220	}
9221	plcp = (struct bwn_plcp6 *)(mp + padding);
9222	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9223	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9224		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9225		    m->m_pkthdr.len);
9226		goto drop;
9227	}
9228	wh = mtod(m, struct ieee80211_frame_min *);
9229
9230	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9231		device_printf(sc->sc_dev,
9232		    "RX decryption attempted (old %d keyidx %#x)\n",
9233		    BWN_ISOLDFMT(mac),
9234		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9235
9236	/* XXX calculating RSSI & noise & antenna */
9237
9238	if (phystat0 & BWN_RX_PHYST0_OFDM)
9239		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9240		    phytype == BWN_PHYTYPE_A);
9241	else
9242		rate = bwn_plcp_get_cckrate(mac, plcp);
9243	if (rate == -1) {
9244		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9245			goto drop;
9246	}
9247	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9248
9249	/* RX radio tap */
9250	if (ieee80211_radiotap_active(ic))
9251		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9252	m_adj(m, -IEEE80211_CRC_LEN);
9253
9254	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9255	noise = mac->mac_stats.link_noise;
9256
9257	BWN_UNLOCK(sc);
9258
9259	ni = ieee80211_find_rxnode(ic, wh);
9260	if (ni != NULL) {
9261		type = ieee80211_input(ni, m, rssi, noise);
9262		ieee80211_free_node(ni);
9263	} else
9264		type = ieee80211_input_all(ic, m, rssi, noise);
9265
9266	BWN_LOCK(sc);
9267	return;
9268drop:
9269	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9270}
9271
9272static void
9273bwn_dma_handle_txeof(struct bwn_mac *mac,
9274    const struct bwn_txstatus *status)
9275{
9276	struct bwn_dma *dma = &mac->mac_method.dma;
9277	struct bwn_dma_ring *dr;
9278	struct bwn_dmadesc_generic *desc;
9279	struct bwn_dmadesc_meta *meta;
9280	struct bwn_softc *sc = mac->mac_sc;
9281	int slot;
9282
9283	BWN_ASSERT_LOCKED(sc);
9284
9285	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9286	if (dr == NULL) {
9287		device_printf(sc->sc_dev, "failed to parse cookie\n");
9288		return;
9289	}
9290	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9291
9292	while (1) {
9293		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9294		    ("%s:%d: fail", __func__, __LINE__));
9295		dr->getdesc(dr, slot, &desc, &meta);
9296
9297		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9298			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9299		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9300			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9301
9302		if (meta->mt_islast) {
9303			KASSERT(meta->mt_m != NULL,
9304			    ("%s:%d: fail", __func__, __LINE__));
9305
9306			ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
9307			meta->mt_ni = NULL;
9308			meta->mt_m = NULL;
9309		} else
9310			KASSERT(meta->mt_m == NULL,
9311			    ("%s:%d: fail", __func__, __LINE__));
9312
9313		dr->dr_usedslot--;
9314		if (meta->mt_islast)
9315			break;
9316		slot = bwn_dma_nextslot(dr, slot);
9317	}
9318	sc->sc_watchdog_timer = 0;
9319	if (dr->dr_stop) {
9320		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9321		    ("%s:%d: fail", __func__, __LINE__));
9322		dr->dr_stop = 0;
9323	}
9324}
9325
9326static void
9327bwn_pio_handle_txeof(struct bwn_mac *mac,
9328    const struct bwn_txstatus *status)
9329{
9330	struct bwn_pio_txqueue *tq;
9331	struct bwn_pio_txpkt *tp = NULL;
9332	struct bwn_softc *sc = mac->mac_sc;
9333
9334	BWN_ASSERT_LOCKED(sc);
9335
9336	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9337	if (tq == NULL)
9338		return;
9339
9340	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9341	tq->tq_free++;
9342
9343	if (tp->tp_ni != NULL) {
9344		/*
9345		 * Do any tx complete callback.  Note this must
9346		 * be done before releasing the node reference.
9347		 */
9348		if (tp->tp_m->m_flags & M_TXCB)
9349			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9350		ieee80211_free_node(tp->tp_ni);
9351		tp->tp_ni = NULL;
9352	}
9353	m_freem(tp->tp_m);
9354	tp->tp_m = NULL;
9355	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9356
9357	sc->sc_watchdog_timer = 0;
9358}
9359
9360static void
9361bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9362{
9363	struct bwn_softc *sc = mac->mac_sc;
9364	struct bwn_phy *phy = &mac->mac_phy;
9365	struct ieee80211com *ic = &sc->sc_ic;
9366	unsigned long now;
9367	int result;
9368
9369	BWN_GETTIME(now);
9370
9371	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9372		return;
9373	phy->nexttime = now + 2 * 1000;
9374
9375	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9376	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9377		return;
9378
9379	if (phy->recalc_txpwr != NULL) {
9380		result = phy->recalc_txpwr(mac,
9381		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9382		if (result == BWN_TXPWR_RES_DONE)
9383			return;
9384		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9385		    ("%s: fail", __func__));
9386		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9387
9388		ieee80211_runtask(ic, &mac->mac_txpower);
9389	}
9390}
9391
9392static uint16_t
9393bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9394{
9395
9396	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9397}
9398
9399static uint32_t
9400bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9401{
9402
9403	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9404}
9405
9406static void
9407bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9408{
9409
9410	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9411}
9412
9413static void
9414bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9415{
9416
9417	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9418}
9419
9420static int
9421bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9422{
9423
9424	switch (rate) {
9425	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9426	case 12:
9427		return (BWN_OFDM_RATE_6MB);
9428	case 18:
9429		return (BWN_OFDM_RATE_9MB);
9430	case 24:
9431		return (BWN_OFDM_RATE_12MB);
9432	case 36:
9433		return (BWN_OFDM_RATE_18MB);
9434	case 48:
9435		return (BWN_OFDM_RATE_24MB);
9436	case 72:
9437		return (BWN_OFDM_RATE_36MB);
9438	case 96:
9439		return (BWN_OFDM_RATE_48MB);
9440	case 108:
9441		return (BWN_OFDM_RATE_54MB);
9442	/* CCK rates (NB: not IEEE std, device-specific) */
9443	case 2:
9444		return (BWN_CCK_RATE_1MB);
9445	case 4:
9446		return (BWN_CCK_RATE_2MB);
9447	case 11:
9448		return (BWN_CCK_RATE_5MB);
9449	case 22:
9450		return (BWN_CCK_RATE_11MB);
9451	}
9452
9453	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9454	return (BWN_CCK_RATE_1MB);
9455}
9456
9457static int
9458bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9459    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9460{
9461	const struct bwn_phy *phy = &mac->mac_phy;
9462	struct bwn_softc *sc = mac->mac_sc;
9463	struct ieee80211_frame *wh;
9464	struct ieee80211_frame *protwh;
9465	struct ieee80211_frame_cts *cts;
9466	struct ieee80211_frame_rts *rts;
9467	const struct ieee80211_txparam *tp;
9468	struct ieee80211vap *vap = ni->ni_vap;
9469	struct ieee80211com *ic = &sc->sc_ic;
9470	struct mbuf *mprot;
9471	unsigned int len;
9472	uint32_t macctl = 0;
9473	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9474	uint16_t phyctl = 0;
9475	uint8_t rate, rate_fb;
9476
9477	wh = mtod(m, struct ieee80211_frame *);
9478	memset(txhdr, 0, sizeof(*txhdr));
9479
9480	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9481	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9482	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9483
9484	/*
9485	 * Find TX rate
9486	 */
9487	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9488	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9489		rate = rate_fb = tp->mgmtrate;
9490	else if (ismcast)
9491		rate = rate_fb = tp->mcastrate;
9492	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9493		rate = rate_fb = tp->ucastrate;
9494	else {
9495		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9496		rate = ni->ni_txrate;
9497
9498		if (rix > 0)
9499			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9500			    IEEE80211_RATE_VAL;
9501		else
9502			rate_fb = rate;
9503	}
9504
9505	sc->sc_tx_rate = rate;
9506
9507	rate = bwn_ieeerate2hwrate(sc, rate);
9508	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9509
9510	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9511	    bwn_plcp_getcck(rate);
9512	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9513	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9514
9515	if ((rate_fb == rate) ||
9516	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9517	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9518		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9519	else
9520		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9521		    m->m_pkthdr.len, rate, isshort);
9522
9523	/* XXX TX encryption */
9524	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9525	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9526	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9527	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9528	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9529	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9530
9531	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9532	    BWN_TX_EFT_FB_CCK;
9533	txhdr->chan = phy->chan;
9534	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9535	    BWN_TX_PHY_ENC_CCK;
9536	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9537	     rate == BWN_CCK_RATE_11MB))
9538		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9539
9540	/* XXX TX antenna selection */
9541
9542	switch (bwn_antenna_sanitize(mac, 0)) {
9543	case 0:
9544		phyctl |= BWN_TX_PHY_ANT01AUTO;
9545		break;
9546	case 1:
9547		phyctl |= BWN_TX_PHY_ANT0;
9548		break;
9549	case 2:
9550		phyctl |= BWN_TX_PHY_ANT1;
9551		break;
9552	case 3:
9553		phyctl |= BWN_TX_PHY_ANT2;
9554		break;
9555	case 4:
9556		phyctl |= BWN_TX_PHY_ANT3;
9557		break;
9558	default:
9559		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9560	}
9561
9562	if (!ismcast)
9563		macctl |= BWN_TX_MAC_ACK;
9564
9565	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9566	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9567	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9568		macctl |= BWN_TX_MAC_LONGFRAME;
9569
9570	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9571		/* XXX RTS rate is always 1MB??? */
9572		rts_rate = BWN_CCK_RATE_1MB;
9573		rts_rate_fb = bwn_get_fbrate(rts_rate);
9574
9575		protdur = ieee80211_compute_duration(ic->ic_rt,
9576		    m->m_pkthdr.len, rate, isshort) +
9577		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9578
9579		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9580			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9581			    (txhdr->body.old.rts_frame) :
9582			    (txhdr->body.new.rts_frame));
9583			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9584			    protdur);
9585			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9586			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9587			    mprot->m_pkthdr.len);
9588			m_freem(mprot);
9589			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9590			len = sizeof(struct ieee80211_frame_cts);
9591		} else {
9592			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9593			    (txhdr->body.old.rts_frame) :
9594			    (txhdr->body.new.rts_frame));
9595			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9596			    isshort);
9597			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9598			    wh->i_addr2, protdur);
9599			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9600			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9601			    mprot->m_pkthdr.len);
9602			m_freem(mprot);
9603			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9604			len = sizeof(struct ieee80211_frame_rts);
9605		}
9606		len += IEEE80211_CRC_LEN;
9607		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9608		    &txhdr->body.old.rts_plcp :
9609		    &txhdr->body.new.rts_plcp), len, rts_rate);
9610		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9611		    rts_rate_fb);
9612
9613		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9614		    (&txhdr->body.old.rts_frame) :
9615		    (&txhdr->body.new.rts_frame));
9616		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9617
9618		if (BWN_ISOFDMRATE(rts_rate)) {
9619			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9620			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9621		} else {
9622			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9623			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9624		}
9625		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9626		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9627	}
9628
9629	if (BWN_ISOLDFMT(mac))
9630		txhdr->body.old.cookie = htole16(cookie);
9631	else
9632		txhdr->body.new.cookie = htole16(cookie);
9633
9634	txhdr->macctl = htole32(macctl);
9635	txhdr->phyctl = htole16(phyctl);
9636
9637	/*
9638	 * TX radio tap
9639	 */
9640	if (ieee80211_radiotap_active_vap(vap)) {
9641		sc->sc_tx_th.wt_flags = 0;
9642		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
9643			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9644		if (isshort &&
9645		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9646		     rate == BWN_CCK_RATE_11MB))
9647			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9648		sc->sc_tx_th.wt_rate = rate;
9649
9650		ieee80211_radiotap_tx(vap, m);
9651	}
9652
9653	return (0);
9654}
9655
9656static void
9657bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9658    const uint8_t rate)
9659{
9660	uint32_t d, plen;
9661	uint8_t *raw = plcp->o.raw;
9662
9663	if (BWN_ISOFDMRATE(rate)) {
9664		d = bwn_plcp_getofdm(rate);
9665		KASSERT(!(octets & 0xf000),
9666		    ("%s:%d: fail", __func__, __LINE__));
9667		d |= (octets << 5);
9668		plcp->o.data = htole32(d);
9669	} else {
9670		plen = octets * 16 / rate;
9671		if ((octets * 16 % rate) > 0) {
9672			plen++;
9673			if ((rate == BWN_CCK_RATE_11MB)
9674			    && ((octets * 8 % 11) < 4)) {
9675				raw[1] = 0x84;
9676			} else
9677				raw[1] = 0x04;
9678		} else
9679			raw[1] = 0x04;
9680		plcp->o.data |= htole32(plen << 16);
9681		raw[0] = bwn_plcp_getcck(rate);
9682	}
9683}
9684
9685static uint8_t
9686bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9687{
9688	struct bwn_softc *sc = mac->mac_sc;
9689	uint8_t mask;
9690
9691	if (n == 0)
9692		return (0);
9693	if (mac->mac_phy.gmode)
9694		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9695	else
9696		mask = siba_sprom_get_ant_a(sc->sc_dev);
9697	if (!(mask & (1 << (n - 1))))
9698		return (0);
9699	return (n);
9700}
9701
9702static uint8_t
9703bwn_get_fbrate(uint8_t bitrate)
9704{
9705	switch (bitrate) {
9706	case BWN_CCK_RATE_1MB:
9707		return (BWN_CCK_RATE_1MB);
9708	case BWN_CCK_RATE_2MB:
9709		return (BWN_CCK_RATE_1MB);
9710	case BWN_CCK_RATE_5MB:
9711		return (BWN_CCK_RATE_2MB);
9712	case BWN_CCK_RATE_11MB:
9713		return (BWN_CCK_RATE_5MB);
9714	case BWN_OFDM_RATE_6MB:
9715		return (BWN_CCK_RATE_5MB);
9716	case BWN_OFDM_RATE_9MB:
9717		return (BWN_OFDM_RATE_6MB);
9718	case BWN_OFDM_RATE_12MB:
9719		return (BWN_OFDM_RATE_9MB);
9720	case BWN_OFDM_RATE_18MB:
9721		return (BWN_OFDM_RATE_12MB);
9722	case BWN_OFDM_RATE_24MB:
9723		return (BWN_OFDM_RATE_18MB);
9724	case BWN_OFDM_RATE_36MB:
9725		return (BWN_OFDM_RATE_24MB);
9726	case BWN_OFDM_RATE_48MB:
9727		return (BWN_OFDM_RATE_36MB);
9728	case BWN_OFDM_RATE_54MB:
9729		return (BWN_OFDM_RATE_48MB);
9730	}
9731	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9732	return (0);
9733}
9734
9735static uint32_t
9736bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9737    uint32_t ctl, const void *_data, int len)
9738{
9739	struct bwn_softc *sc = mac->mac_sc;
9740	uint32_t value = 0;
9741	const uint8_t *data = _data;
9742
9743	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9744	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9745	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9746
9747	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9748	    tq->tq_base + BWN_PIO8_TXDATA);
9749	if (len & 3) {
9750		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9751		    BWN_PIO8_TXCTL_24_31);
9752		data = &(data[len - 1]);
9753		switch (len & 3) {
9754		case 3:
9755			ctl |= BWN_PIO8_TXCTL_16_23;
9756			value |= (uint32_t)(*data) << 16;
9757			data--;
9758		case 2:
9759			ctl |= BWN_PIO8_TXCTL_8_15;
9760			value |= (uint32_t)(*data) << 8;
9761			data--;
9762		case 1:
9763			value |= (uint32_t)(*data);
9764		}
9765		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9766		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9767	}
9768
9769	return (ctl);
9770}
9771
9772static void
9773bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9774    uint16_t offset, uint32_t value)
9775{
9776
9777	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9778}
9779
9780static uint16_t
9781bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9782    uint16_t ctl, const void *_data, int len)
9783{
9784	struct bwn_softc *sc = mac->mac_sc;
9785	const uint8_t *data = _data;
9786
9787	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9788	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9789
9790	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9791	    tq->tq_base + BWN_PIO_TXDATA);
9792	if (len & 1) {
9793		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9794		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9795		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9796	}
9797
9798	return (ctl);
9799}
9800
9801static uint16_t
9802bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9803    uint16_t ctl, struct mbuf *m0)
9804{
9805	int i, j = 0;
9806	uint16_t data = 0;
9807	const uint8_t *buf;
9808	struct mbuf *m = m0;
9809
9810	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9811	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9812
9813	for (; m != NULL; m = m->m_next) {
9814		buf = mtod(m, const uint8_t *);
9815		for (i = 0; i < m->m_len; i++) {
9816			if (!((j++) % 2))
9817				data |= buf[i];
9818			else {
9819				data |= (buf[i] << 8);
9820				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9821				data = 0;
9822			}
9823		}
9824	}
9825	if (m0->m_pkthdr.len % 2) {
9826		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9827		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9828		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9829	}
9830
9831	return (ctl);
9832}
9833
9834static void
9835bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9836{
9837
9838	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9839		return;
9840	BWN_WRITE_2(mac, 0x684, 510 + time);
9841	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9842}
9843
9844static struct bwn_dma_ring *
9845bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9846{
9847
9848	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9849		return (mac->mac_method.dma.wme[WME_AC_BE]);
9850
9851	switch (prio) {
9852	case 3:
9853		return (mac->mac_method.dma.wme[WME_AC_VO]);
9854	case 2:
9855		return (mac->mac_method.dma.wme[WME_AC_VI]);
9856	case 0:
9857		return (mac->mac_method.dma.wme[WME_AC_BE]);
9858	case 1:
9859		return (mac->mac_method.dma.wme[WME_AC_BK]);
9860	}
9861	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9862	return (NULL);
9863}
9864
9865static int
9866bwn_dma_getslot(struct bwn_dma_ring *dr)
9867{
9868	int slot;
9869
9870	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
9871
9872	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9873	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
9874	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
9875
9876	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
9877	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
9878	dr->dr_curslot = slot;
9879	dr->dr_usedslot++;
9880
9881	return (slot);
9882}
9883
9884static int
9885bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
9886{
9887	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
9888	unsigned int a, b, c, d;
9889	unsigned int avg;
9890	uint32_t tmp;
9891
9892	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
9893	a = tmp & 0xff;
9894	b = (tmp >> 8) & 0xff;
9895	c = (tmp >> 16) & 0xff;
9896	d = (tmp >> 24) & 0xff;
9897	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
9898	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
9899		return (ENOENT);
9900	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
9901	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
9902	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
9903
9904	if (ofdm) {
9905		a = (a + 32) & 0x3f;
9906		b = (b + 32) & 0x3f;
9907		c = (c + 32) & 0x3f;
9908		d = (d + 32) & 0x3f;
9909	}
9910
9911	avg = (a + b + c + d + 2) / 4;
9912	if (ofdm) {
9913		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
9914		    & BWN_HF_4DB_CCK_POWERBOOST)
9915			avg = (avg >= 13) ? (avg - 13) : 0;
9916	}
9917	return (avg);
9918}
9919
9920static void
9921bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
9922{
9923	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
9924	int rfatt = *rfattp;
9925	int bbatt = *bbattp;
9926
9927	while (1) {
9928		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
9929			break;
9930		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
9931			break;
9932		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
9933			break;
9934		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
9935			break;
9936		if (bbatt > lo->bbatt.max) {
9937			bbatt -= 4;
9938			rfatt += 1;
9939			continue;
9940		}
9941		if (bbatt < lo->bbatt.min) {
9942			bbatt += 4;
9943			rfatt -= 1;
9944			continue;
9945		}
9946		if (rfatt > lo->rfatt.max) {
9947			rfatt -= 1;
9948			bbatt += 4;
9949			continue;
9950		}
9951		if (rfatt < lo->rfatt.min) {
9952			rfatt += 1;
9953			bbatt -= 4;
9954			continue;
9955		}
9956		break;
9957	}
9958
9959	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
9960	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
9961}
9962
9963static void
9964bwn_phy_lock(struct bwn_mac *mac)
9965{
9966	struct bwn_softc *sc = mac->mac_sc;
9967	struct ieee80211com *ic = &sc->sc_ic;
9968
9969	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9970	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9971
9972	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9973		bwn_psctl(mac, BWN_PS_AWAKE);
9974}
9975
9976static void
9977bwn_phy_unlock(struct bwn_mac *mac)
9978{
9979	struct bwn_softc *sc = mac->mac_sc;
9980	struct ieee80211com *ic = &sc->sc_ic;
9981
9982	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9983	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9984
9985	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9986		bwn_psctl(mac, 0);
9987}
9988
9989static void
9990bwn_rf_lock(struct bwn_mac *mac)
9991{
9992
9993	BWN_WRITE_4(mac, BWN_MACCTL,
9994	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
9995	BWN_READ_4(mac, BWN_MACCTL);
9996	DELAY(10);
9997}
9998
9999static void
10000bwn_rf_unlock(struct bwn_mac *mac)
10001{
10002
10003	BWN_READ_2(mac, BWN_PHYVER);
10004	BWN_WRITE_4(mac, BWN_MACCTL,
10005	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10006}
10007
10008static struct bwn_pio_txqueue *
10009bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10010    struct bwn_pio_txpkt **pack)
10011{
10012	struct bwn_pio *pio = &mac->mac_method.pio;
10013	struct bwn_pio_txqueue *tq = NULL;
10014	unsigned int index;
10015
10016	switch (cookie & 0xf000) {
10017	case 0x1000:
10018		tq = &pio->wme[WME_AC_BK];
10019		break;
10020	case 0x2000:
10021		tq = &pio->wme[WME_AC_BE];
10022		break;
10023	case 0x3000:
10024		tq = &pio->wme[WME_AC_VI];
10025		break;
10026	case 0x4000:
10027		tq = &pio->wme[WME_AC_VO];
10028		break;
10029	case 0x5000:
10030		tq = &pio->mcast;
10031		break;
10032	}
10033	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10034	if (tq == NULL)
10035		return (NULL);
10036	index = (cookie & 0x0fff);
10037	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10038	if (index >= N(tq->tq_pkts))
10039		return (NULL);
10040	*pack = &tq->tq_pkts[index];
10041	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10042	return (tq);
10043}
10044
10045static void
10046bwn_txpwr(void *arg, int npending)
10047{
10048	struct bwn_mac *mac = arg;
10049	struct bwn_softc *sc = mac->mac_sc;
10050
10051	BWN_LOCK(sc);
10052	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10053	    mac->mac_phy.set_txpwr != NULL)
10054		mac->mac_phy.set_txpwr(mac);
10055	BWN_UNLOCK(sc);
10056}
10057
10058static void
10059bwn_task_15s(struct bwn_mac *mac)
10060{
10061	uint16_t reg;
10062
10063	if (mac->mac_fw.opensource) {
10064		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10065		if (reg) {
10066			bwn_restart(mac, "fw watchdog");
10067			return;
10068		}
10069		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10070	}
10071	if (mac->mac_phy.task_15s)
10072		mac->mac_phy.task_15s(mac);
10073
10074	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10075}
10076
10077static void
10078bwn_task_30s(struct bwn_mac *mac)
10079{
10080
10081	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10082		return;
10083	mac->mac_noise.noi_running = 1;
10084	mac->mac_noise.noi_nsamples = 0;
10085
10086	bwn_noise_gensample(mac);
10087}
10088
10089static void
10090bwn_task_60s(struct bwn_mac *mac)
10091{
10092
10093	if (mac->mac_phy.task_60s)
10094		mac->mac_phy.task_60s(mac);
10095	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10096}
10097
10098static void
10099bwn_tasks(void *arg)
10100{
10101	struct bwn_mac *mac = arg;
10102	struct bwn_softc *sc = mac->mac_sc;
10103
10104	BWN_ASSERT_LOCKED(sc);
10105	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10106		return;
10107
10108	if (mac->mac_task_state % 4 == 0)
10109		bwn_task_60s(mac);
10110	if (mac->mac_task_state % 2 == 0)
10111		bwn_task_30s(mac);
10112	bwn_task_15s(mac);
10113
10114	mac->mac_task_state++;
10115	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10116}
10117
10118static int
10119bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10120{
10121	struct bwn_softc *sc = mac->mac_sc;
10122
10123	KASSERT(a == 0, ("not support APHY\n"));
10124
10125	switch (plcp->o.raw[0] & 0xf) {
10126	case 0xb:
10127		return (BWN_OFDM_RATE_6MB);
10128	case 0xf:
10129		return (BWN_OFDM_RATE_9MB);
10130	case 0xa:
10131		return (BWN_OFDM_RATE_12MB);
10132	case 0xe:
10133		return (BWN_OFDM_RATE_18MB);
10134	case 0x9:
10135		return (BWN_OFDM_RATE_24MB);
10136	case 0xd:
10137		return (BWN_OFDM_RATE_36MB);
10138	case 0x8:
10139		return (BWN_OFDM_RATE_48MB);
10140	case 0xc:
10141		return (BWN_OFDM_RATE_54MB);
10142	}
10143	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10144	    plcp->o.raw[0] & 0xf);
10145	return (-1);
10146}
10147
10148static int
10149bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10150{
10151	struct bwn_softc *sc = mac->mac_sc;
10152
10153	switch (plcp->o.raw[0]) {
10154	case 0x0a:
10155		return (BWN_CCK_RATE_1MB);
10156	case 0x14:
10157		return (BWN_CCK_RATE_2MB);
10158	case 0x37:
10159		return (BWN_CCK_RATE_5MB);
10160	case 0x6e:
10161		return (BWN_CCK_RATE_11MB);
10162	}
10163	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10164	return (-1);
10165}
10166
10167static void
10168bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10169    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10170    int rssi, int noise)
10171{
10172	struct bwn_softc *sc = mac->mac_sc;
10173	const struct ieee80211_frame_min *wh;
10174	uint64_t tsf;
10175	uint16_t low_mactime_now;
10176
10177	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10178		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10179
10180	wh = mtod(m, const struct ieee80211_frame_min *);
10181	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
10182		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10183
10184	bwn_tsf_read(mac, &tsf);
10185	low_mactime_now = tsf;
10186	tsf = tsf & ~0xffffULL;
10187	tsf += le16toh(rxhdr->mac_time);
10188	if (low_mactime_now < le16toh(rxhdr->mac_time))
10189		tsf -= 0x10000;
10190
10191	sc->sc_rx_th.wr_tsf = tsf;
10192	sc->sc_rx_th.wr_rate = rate;
10193	sc->sc_rx_th.wr_antsignal = rssi;
10194	sc->sc_rx_th.wr_antnoise = noise;
10195}
10196
10197static void
10198bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10199{
10200	uint32_t low, high;
10201
10202	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10203	    ("%s:%d: fail", __func__, __LINE__));
10204
10205	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10206	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10207	*tsf = high;
10208	*tsf <<= 32;
10209	*tsf |= low;
10210}
10211
10212static int
10213bwn_dma_attach(struct bwn_mac *mac)
10214{
10215	struct bwn_dma *dma = &mac->mac_method.dma;
10216	struct bwn_softc *sc = mac->mac_sc;
10217	bus_addr_t lowaddr = 0;
10218	int error;
10219
10220	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10221		return (0);
10222
10223	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10224
10225	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10226
10227	dma->dmatype = bwn_dma_gettype(mac);
10228	if (dma->dmatype == BWN_DMA_30BIT)
10229		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10230	else if (dma->dmatype == BWN_DMA_32BIT)
10231		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10232	else
10233		lowaddr = BUS_SPACE_MAXADDR;
10234
10235	/*
10236	 * Create top level DMA tag
10237	 */
10238	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10239			       BWN_ALIGN, 0,		/* alignment, bounds */
10240			       lowaddr,			/* lowaddr */
10241			       BUS_SPACE_MAXADDR,	/* highaddr */
10242			       NULL, NULL,		/* filter, filterarg */
10243			       BUS_SPACE_MAXSIZE,	/* maxsize */
10244			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10245			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10246			       0,			/* flags */
10247			       NULL, NULL,		/* lockfunc, lockarg */
10248			       &dma->parent_dtag);
10249	if (error) {
10250		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10251		return (error);
10252	}
10253
10254	/*
10255	 * Create TX/RX mbuf DMA tag
10256	 */
10257	error = bus_dma_tag_create(dma->parent_dtag,
10258				1,
10259				0,
10260				BUS_SPACE_MAXADDR,
10261				BUS_SPACE_MAXADDR,
10262				NULL, NULL,
10263				MCLBYTES,
10264				1,
10265				BUS_SPACE_MAXSIZE_32BIT,
10266				0,
10267				NULL, NULL,
10268				&dma->rxbuf_dtag);
10269	if (error) {
10270		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10271		goto fail0;
10272	}
10273	error = bus_dma_tag_create(dma->parent_dtag,
10274				1,
10275				0,
10276				BUS_SPACE_MAXADDR,
10277				BUS_SPACE_MAXADDR,
10278				NULL, NULL,
10279				MCLBYTES,
10280				1,
10281				BUS_SPACE_MAXSIZE_32BIT,
10282				0,
10283				NULL, NULL,
10284				&dma->txbuf_dtag);
10285	if (error) {
10286		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10287		goto fail1;
10288	}
10289
10290	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10291	if (!dma->wme[WME_AC_BK])
10292		goto fail2;
10293
10294	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10295	if (!dma->wme[WME_AC_BE])
10296		goto fail3;
10297
10298	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10299	if (!dma->wme[WME_AC_VI])
10300		goto fail4;
10301
10302	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10303	if (!dma->wme[WME_AC_VO])
10304		goto fail5;
10305
10306	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10307	if (!dma->mcast)
10308		goto fail6;
10309	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10310	if (!dma->rx)
10311		goto fail7;
10312
10313	return (error);
10314
10315fail7:	bwn_dma_ringfree(&dma->mcast);
10316fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10317fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10318fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10319fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10320fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10321fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10322fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10323	return (error);
10324}
10325
10326static struct bwn_dma_ring *
10327bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10328    uint16_t cookie, int *slot)
10329{
10330	struct bwn_dma *dma = &mac->mac_method.dma;
10331	struct bwn_dma_ring *dr;
10332	struct bwn_softc *sc = mac->mac_sc;
10333
10334	BWN_ASSERT_LOCKED(mac->mac_sc);
10335
10336	switch (cookie & 0xf000) {
10337	case 0x1000:
10338		dr = dma->wme[WME_AC_BK];
10339		break;
10340	case 0x2000:
10341		dr = dma->wme[WME_AC_BE];
10342		break;
10343	case 0x3000:
10344		dr = dma->wme[WME_AC_VI];
10345		break;
10346	case 0x4000:
10347		dr = dma->wme[WME_AC_VO];
10348		break;
10349	case 0x5000:
10350		dr = dma->mcast;
10351		break;
10352	default:
10353		dr = NULL;
10354		KASSERT(0 == 1,
10355		    ("invalid cookie value %d", cookie & 0xf000));
10356	}
10357	*slot = (cookie & 0x0fff);
10358	if (*slot < 0 || *slot >= dr->dr_numslots) {
10359		/*
10360		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10361		 * that it occurs events which have same H/W sequence numbers.
10362		 * When it's occurred just prints a WARNING msgs and ignores.
10363		 */
10364		KASSERT(status->seq == dma->lastseq,
10365		    ("%s:%d: fail", __func__, __LINE__));
10366		device_printf(sc->sc_dev,
10367		    "out of slot ranges (0 < %d < %d)\n", *slot,
10368		    dr->dr_numslots);
10369		return (NULL);
10370	}
10371	dma->lastseq = status->seq;
10372	return (dr);
10373}
10374
10375static void
10376bwn_dma_stop(struct bwn_mac *mac)
10377{
10378	struct bwn_dma *dma;
10379
10380	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10381		return;
10382	dma = &mac->mac_method.dma;
10383
10384	bwn_dma_ringstop(&dma->rx);
10385	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10386	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10387	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10388	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10389	bwn_dma_ringstop(&dma->mcast);
10390}
10391
10392static void
10393bwn_dma_ringstop(struct bwn_dma_ring **dr)
10394{
10395
10396	if (dr == NULL)
10397		return;
10398
10399	bwn_dma_cleanup(*dr);
10400}
10401
10402static void
10403bwn_pio_stop(struct bwn_mac *mac)
10404{
10405	struct bwn_pio *pio;
10406
10407	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10408		return;
10409	pio = &mac->mac_method.pio;
10410
10411	bwn_destroy_queue_tx(&pio->mcast);
10412	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10413	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10414	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10415	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10416}
10417
10418static void
10419bwn_led_attach(struct bwn_mac *mac)
10420{
10421	struct bwn_softc *sc = mac->mac_sc;
10422	const uint8_t *led_act = NULL;
10423	uint16_t val[BWN_LED_MAX];
10424	int i;
10425
10426	sc->sc_led_idle = (2350 * hz) / 1000;
10427	sc->sc_led_blink = 1;
10428
10429	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10430		if (siba_get_pci_subvendor(sc->sc_dev) ==
10431		    bwn_vendor_led_act[i].vid) {
10432			led_act = bwn_vendor_led_act[i].led_act;
10433			break;
10434		}
10435	}
10436	if (led_act == NULL)
10437		led_act = bwn_default_led_act;
10438
10439	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10440	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10441	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10442	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10443
10444	for (i = 0; i < BWN_LED_MAX; ++i) {
10445		struct bwn_led *led = &sc->sc_leds[i];
10446
10447		if (val[i] == 0xff) {
10448			led->led_act = led_act[i];
10449		} else {
10450			if (val[i] & BWN_LED_ACT_LOW)
10451				led->led_flags |= BWN_LED_F_ACTLOW;
10452			led->led_act = val[i] & BWN_LED_ACT_MASK;
10453		}
10454		led->led_mask = (1 << i);
10455
10456		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10457		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10458		    led->led_act == BWN_LED_ACT_BLINK) {
10459			led->led_flags |= BWN_LED_F_BLINK;
10460			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10461				led->led_flags |= BWN_LED_F_POLLABLE;
10462			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10463				led->led_flags |= BWN_LED_F_SLOW;
10464
10465			if (sc->sc_blink_led == NULL) {
10466				sc->sc_blink_led = led;
10467				if (led->led_flags & BWN_LED_F_SLOW)
10468					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10469			}
10470		}
10471
10472		DPRINTF(sc, BWN_DEBUG_LED,
10473		    "%dth led, act %d, lowact %d\n", i,
10474		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10475	}
10476	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10477}
10478
10479static __inline uint16_t
10480bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10481{
10482
10483	if (led->led_flags & BWN_LED_F_ACTLOW)
10484		on = !on;
10485	if (on)
10486		val |= led->led_mask;
10487	else
10488		val &= ~led->led_mask;
10489	return val;
10490}
10491
10492static void
10493bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10494{
10495	struct bwn_softc *sc = mac->mac_sc;
10496	struct ieee80211com *ic = &sc->sc_ic;
10497	uint16_t val;
10498	int i;
10499
10500	if (nstate == IEEE80211_S_INIT) {
10501		callout_stop(&sc->sc_led_blink_ch);
10502		sc->sc_led_blinking = 0;
10503	}
10504
10505	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
10506		return;
10507
10508	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10509	for (i = 0; i < BWN_LED_MAX; ++i) {
10510		struct bwn_led *led = &sc->sc_leds[i];
10511		int on;
10512
10513		if (led->led_act == BWN_LED_ACT_UNKN ||
10514		    led->led_act == BWN_LED_ACT_NULL)
10515			continue;
10516
10517		if ((led->led_flags & BWN_LED_F_BLINK) &&
10518		    nstate != IEEE80211_S_INIT)
10519			continue;
10520
10521		switch (led->led_act) {
10522		case BWN_LED_ACT_ON:    /* Always on */
10523			on = 1;
10524			break;
10525		case BWN_LED_ACT_OFF:   /* Always off */
10526		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10527			on = 0;
10528			break;
10529		default:
10530			on = 1;
10531			switch (nstate) {
10532			case IEEE80211_S_INIT:
10533				on = 0;
10534				break;
10535			case IEEE80211_S_RUN:
10536				if (led->led_act == BWN_LED_ACT_11G &&
10537				    ic->ic_curmode != IEEE80211_MODE_11G)
10538					on = 0;
10539				break;
10540			default:
10541				if (led->led_act == BWN_LED_ACT_ASSOC)
10542					on = 0;
10543				break;
10544			}
10545			break;
10546		}
10547
10548		val = bwn_led_onoff(led, val, on);
10549	}
10550	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10551}
10552
10553static void
10554bwn_led_event(struct bwn_mac *mac, int event)
10555{
10556	struct bwn_softc *sc = mac->mac_sc;
10557	struct bwn_led *led = sc->sc_blink_led;
10558	int rate;
10559
10560	if (event == BWN_LED_EVENT_POLL) {
10561		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10562			return;
10563		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10564			return;
10565	}
10566
10567	sc->sc_led_ticks = ticks;
10568	if (sc->sc_led_blinking)
10569		return;
10570
10571	switch (event) {
10572	case BWN_LED_EVENT_RX:
10573		rate = sc->sc_rx_rate;
10574		break;
10575	case BWN_LED_EVENT_TX:
10576		rate = sc->sc_tx_rate;
10577		break;
10578	case BWN_LED_EVENT_POLL:
10579		rate = 0;
10580		break;
10581	default:
10582		panic("unknown LED event %d\n", event);
10583		break;
10584	}
10585	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10586	    bwn_led_duration[rate].off_dur);
10587}
10588
10589static void
10590bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10591{
10592	struct bwn_softc *sc = mac->mac_sc;
10593	struct bwn_led *led = sc->sc_blink_led;
10594	uint16_t val;
10595
10596	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10597	val = bwn_led_onoff(led, val, 1);
10598	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10599
10600	if (led->led_flags & BWN_LED_F_SLOW) {
10601		BWN_LED_SLOWDOWN(on_dur);
10602		BWN_LED_SLOWDOWN(off_dur);
10603	}
10604
10605	sc->sc_led_blinking = 1;
10606	sc->sc_led_blink_offdur = off_dur;
10607
10608	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10609}
10610
10611static void
10612bwn_led_blink_next(void *arg)
10613{
10614	struct bwn_mac *mac = arg;
10615	struct bwn_softc *sc = mac->mac_sc;
10616	uint16_t val;
10617
10618	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10619	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10620	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10621
10622	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10623	    bwn_led_blink_end, mac);
10624}
10625
10626static void
10627bwn_led_blink_end(void *arg)
10628{
10629	struct bwn_mac *mac = arg;
10630	struct bwn_softc *sc = mac->mac_sc;
10631
10632	sc->sc_led_blinking = 0;
10633}
10634
10635static int
10636bwn_suspend(device_t dev)
10637{
10638	struct bwn_softc *sc = device_get_softc(dev);
10639
10640	BWN_LOCK(sc);
10641	bwn_stop(sc);
10642	BWN_UNLOCK(sc);
10643	return (0);
10644}
10645
10646static int
10647bwn_resume(device_t dev)
10648{
10649	struct bwn_softc *sc = device_get_softc(dev);
10650	int error = EDOOFUS;
10651
10652	BWN_LOCK(sc);
10653	if (sc->sc_ic.ic_nrunning > 0)
10654		error = bwn_init(sc);
10655	BWN_UNLOCK(sc);
10656	if (error == 0)
10657		ieee80211_start_all(&sc->sc_ic);
10658	return (0);
10659}
10660
10661static void
10662bwn_rfswitch(void *arg)
10663{
10664	struct bwn_softc *sc = arg;
10665	struct bwn_mac *mac = sc->sc_curmac;
10666	int cur = 0, prev = 0;
10667
10668	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10669	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10670
10671	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10672		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10673			& BWN_RF_HWENABLED_HI_MASK))
10674			cur = 1;
10675	} else {
10676		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10677		    & BWN_RF_HWENABLED_LO_MASK)
10678			cur = 1;
10679	}
10680
10681	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10682		prev = 1;
10683
10684	if (cur != prev) {
10685		if (cur)
10686			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10687		else
10688			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10689
10690		device_printf(sc->sc_dev,
10691		    "status of RF switch is changed to %s\n",
10692		    cur ? "ON" : "OFF");
10693		if (cur != mac->mac_phy.rf_on) {
10694			if (cur)
10695				bwn_rf_turnon(mac);
10696			else
10697				bwn_rf_turnoff(mac);
10698		}
10699	}
10700
10701	callout_schedule(&sc->sc_rfswitch_ch, hz);
10702}
10703
10704static void
10705bwn_phy_lp_init_pre(struct bwn_mac *mac)
10706{
10707	struct bwn_phy *phy = &mac->mac_phy;
10708	struct bwn_phy_lp *plp = &phy->phy_lp;
10709
10710	plp->plp_antenna = BWN_ANT_DEFAULT;
10711}
10712
10713static int
10714bwn_phy_lp_init(struct bwn_mac *mac)
10715{
10716	static const struct bwn_stxtable tables[] = {
10717		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10718		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10719		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10720		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10721		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10722		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10723		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10724		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10725		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10726		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10727		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10728		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10729		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10730		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10731		{ 2, 11, 0x40, 0, 0x0f }
10732	};
10733	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10734	struct bwn_softc *sc = mac->mac_sc;
10735	const struct bwn_stxtable *st;
10736	struct ieee80211com *ic = &sc->sc_ic;
10737	int i, error;
10738	uint16_t tmp;
10739
10740	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10741	bwn_phy_lp_bbinit(mac);
10742
10743	/* initialize RF */
10744	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10745	DELAY(1);
10746	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10747	DELAY(1);
10748
10749	if (mac->mac_phy.rf_ver == 0x2062)
10750		bwn_phy_lp_b2062_init(mac);
10751	else {
10752		bwn_phy_lp_b2063_init(mac);
10753
10754		/* synchronize stx table. */
10755		for (i = 0; i < N(tables); i++) {
10756			st = &tables[i];
10757			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10758			tmp >>= st->st_rfshift;
10759			tmp <<= st->st_physhift;
10760			BWN_PHY_SETMASK(mac,
10761			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10762			    ~(st->st_mask << st->st_physhift), tmp);
10763		}
10764
10765		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10766		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10767	}
10768
10769	/* calibrate RC */
10770	if (mac->mac_phy.rev >= 2)
10771		bwn_phy_lp_rxcal_r2(mac);
10772	else if (!plp->plp_rccap) {
10773		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10774			bwn_phy_lp_rccal_r12(mac);
10775	} else
10776		bwn_phy_lp_set_rccap(mac);
10777
10778	error = bwn_phy_lp_switch_channel(mac, 7);
10779	if (error)
10780		device_printf(sc->sc_dev,
10781		    "failed to change channel 7 (%d)\n", error);
10782	bwn_phy_lp_txpctl_init(mac);
10783	bwn_phy_lp_calib(mac);
10784	return (0);
10785}
10786
10787static uint16_t
10788bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10789{
10790
10791	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10792	return (BWN_READ_2(mac, BWN_PHYDATA));
10793}
10794
10795static void
10796bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10797{
10798
10799	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10800	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10801}
10802
10803static void
10804bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10805    uint16_t set)
10806{
10807
10808	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10809	BWN_WRITE_2(mac, BWN_PHYDATA,
10810	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10811}
10812
10813static uint16_t
10814bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10815{
10816
10817	KASSERT(reg != 1, ("unaccessible register %d", reg));
10818	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10819		reg |= 0x100;
10820	if (mac->mac_phy.rev >= 2)
10821		reg |= 0x200;
10822	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10823	return BWN_READ_2(mac, BWN_RFDATALO);
10824}
10825
10826static void
10827bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10828{
10829
10830	KASSERT(reg != 1, ("unaccessible register %d", reg));
10831	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10832	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10833}
10834
10835static void
10836bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10837{
10838
10839	if (on) {
10840		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10841		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10842		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10843		return;
10844	}
10845
10846	if (mac->mac_phy.rev >= 2) {
10847		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10848		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10849		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10850		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10851		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10852		return;
10853	}
10854
10855	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10856	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10857	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10858	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10859}
10860
10861static int
10862bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10863{
10864	struct bwn_phy *phy = &mac->mac_phy;
10865	struct bwn_phy_lp *plp = &phy->phy_lp;
10866	int error;
10867
10868	if (phy->rf_ver == 0x2063) {
10869		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
10870		if (error)
10871			return (error);
10872	} else {
10873		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
10874		if (error)
10875			return (error);
10876		bwn_phy_lp_set_anafilter(mac, chan);
10877		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
10878	}
10879
10880	plp->plp_chan = chan;
10881	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
10882	return (0);
10883}
10884
10885static uint32_t
10886bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
10887{
10888	struct bwn_softc *sc = mac->mac_sc;
10889	struct ieee80211com *ic = &sc->sc_ic;
10890
10891	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
10892}
10893
10894static void
10895bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
10896{
10897	struct bwn_phy *phy = &mac->mac_phy;
10898	struct bwn_phy_lp *plp = &phy->phy_lp;
10899
10900	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
10901		return;
10902
10903	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
10904	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
10905	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
10906	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
10907	plp->plp_antenna = antenna;
10908}
10909
10910static void
10911bwn_phy_lp_task_60s(struct bwn_mac *mac)
10912{
10913
10914	bwn_phy_lp_calib(mac);
10915}
10916
10917static void
10918bwn_phy_lp_readsprom(struct bwn_mac *mac)
10919{
10920	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10921	struct bwn_softc *sc = mac->mac_sc;
10922	struct ieee80211com *ic = &sc->sc_ic;
10923
10924	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
10925		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
10926		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
10927		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
10928		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
10929		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
10930		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
10931		return;
10932	}
10933
10934	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
10935	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
10936	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
10937	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
10938	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
10939	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
10940	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
10941	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
10942}
10943
10944static void
10945bwn_phy_lp_bbinit(struct bwn_mac *mac)
10946{
10947
10948	bwn_phy_lp_tblinit(mac);
10949	if (mac->mac_phy.rev >= 2)
10950		bwn_phy_lp_bbinit_r2(mac);
10951	else
10952		bwn_phy_lp_bbinit_r01(mac);
10953}
10954
10955static void
10956bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
10957{
10958	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
10959	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
10960	struct bwn_softc *sc = mac->mac_sc;
10961	struct ieee80211com *ic = &sc->sc_ic;
10962
10963	bwn_phy_lp_set_txgain(mac,
10964	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
10965	bwn_phy_lp_set_bbmult(mac, 150);
10966}
10967
10968static void
10969bwn_phy_lp_calib(struct bwn_mac *mac)
10970{
10971	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10972	struct bwn_softc *sc = mac->mac_sc;
10973	struct ieee80211com *ic = &sc->sc_ic;
10974	const struct bwn_rxcompco *rc = NULL;
10975	struct bwn_txgain ogain;
10976	int i, omode, oafeovr, orf, obbmult;
10977	uint8_t mode, fc = 0;
10978
10979	if (plp->plp_chanfullcal != plp->plp_chan) {
10980		plp->plp_chanfullcal = plp->plp_chan;
10981		fc = 1;
10982	}
10983
10984	bwn_mac_suspend(mac);
10985
10986	/* BlueTooth Coexistance Override */
10987	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
10988	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
10989
10990	if (mac->mac_phy.rev >= 2)
10991		bwn_phy_lp_digflt_save(mac);
10992	bwn_phy_lp_get_txpctlmode(mac);
10993	mode = plp->plp_txpctlmode;
10994	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
10995	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
10996		bwn_phy_lp_bugfix(mac);
10997	if (mac->mac_phy.rev >= 2 && fc == 1) {
10998		bwn_phy_lp_get_txpctlmode(mac);
10999		omode = plp->plp_txpctlmode;
11000		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11001		if (oafeovr)
11002			ogain = bwn_phy_lp_get_txgain(mac);
11003		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11004		obbmult = bwn_phy_lp_get_bbmult(mac);
11005		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11006		if (oafeovr)
11007			bwn_phy_lp_set_txgain(mac, &ogain);
11008		bwn_phy_lp_set_bbmult(mac, obbmult);
11009		bwn_phy_lp_set_txpctlmode(mac, omode);
11010		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11011	}
11012	bwn_phy_lp_set_txpctlmode(mac, mode);
11013	if (mac->mac_phy.rev >= 2)
11014		bwn_phy_lp_digflt_restore(mac);
11015
11016	/* do RX IQ Calculation; assumes that noise is true. */
11017	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11018		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11019			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11020				rc = &bwn_rxcompco_5354[i];
11021		}
11022	} else if (mac->mac_phy.rev >= 2)
11023		rc = &bwn_rxcompco_r2;
11024	else {
11025		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11026			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11027				rc = &bwn_rxcompco_r12[i];
11028		}
11029	}
11030	if (rc == NULL)
11031		goto fail;
11032
11033	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11034	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11035
11036	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11037
11038	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11039		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11040		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11041	} else {
11042		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11043		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11044	}
11045
11046	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11047	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11048	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11049	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11050	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11051	bwn_phy_lp_set_deaf(mac, 0);
11052	/* XXX no checking return value? */
11053	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11054	bwn_phy_lp_clear_deaf(mac, 0);
11055	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11056	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11057	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11058
11059	/* disable RX GAIN override. */
11060	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11061	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11062	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11063	if (mac->mac_phy.rev >= 2) {
11064		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11065		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11066			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11067			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11068		}
11069	} else {
11070		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11071	}
11072
11073	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11074	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11075fail:
11076	bwn_mac_enable(mac);
11077}
11078
11079static void
11080bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11081{
11082
11083	if (on) {
11084		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11085		return;
11086	}
11087
11088	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11089	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11090}
11091
11092static int
11093bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11094{
11095	static const struct bwn_b206x_chan *bc = NULL;
11096	struct bwn_softc *sc = mac->mac_sc;
11097	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11098	    tmp[6];
11099	uint16_t old, scale, tmp16;
11100	int i, div;
11101
11102	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11103		if (bwn_b2063_chantable[i].bc_chan == chan) {
11104			bc = &bwn_b2063_chantable[i];
11105			break;
11106		}
11107	}
11108	if (bc == NULL)
11109		return (EINVAL);
11110
11111	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11112	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11113	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11114	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11115	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11116	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11117	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11118	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11119	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11120	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11121	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11122	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11123
11124	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11125	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11126
11127	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11128	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11129	freqref = freqxtal * 3;
11130	div = (freqxtal <= 26000000 ? 1 : 2);
11131	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11132	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11133		999999) / 1000000) + 1;
11134
11135	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11136	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11137	    0xfff8, timeout >> 2);
11138	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11139	    0xff9f,timeout << 5);
11140	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11141
11142	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11143	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11144	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11145
11146	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11147	    (timeoutref + 1)) - 1;
11148	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11149	    0xf0, count >> 8);
11150	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11151
11152	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11153	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11154	while (tmp[1] >= freqref) {
11155		tmp[0]++;
11156		tmp[1] -= freqref;
11157	}
11158	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11159	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11160	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11161	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11162	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11163
11164	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11165	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11166	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11167	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11168
11169	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11170	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11171
11172	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11173		scale = 1;
11174		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11175	} else {
11176		scale = 0;
11177		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11178	}
11179	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11180	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11181
11182	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11183	    (scale + 1);
11184	if (tmp[5] > 150)
11185		tmp[5] = 0;
11186
11187	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11188	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11189
11190	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11191	if (freqxtal > 26000000)
11192		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11193	else
11194		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11195
11196	if (val[0] == 45)
11197		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11198	else
11199		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11200
11201	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11202	DELAY(1);
11203	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11204
11205	/* VCO Calibration */
11206	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11207	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11208	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11209	DELAY(1);
11210	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11211	DELAY(1);
11212	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11213	DELAY(1);
11214	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11215	DELAY(300);
11216	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11217
11218	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11219	return (0);
11220}
11221
11222static int
11223bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11224{
11225	struct bwn_softc *sc = mac->mac_sc;
11226	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11227	const struct bwn_b206x_chan *bc = NULL;
11228	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11229	uint32_t tmp[9];
11230	int i;
11231
11232	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11233		if (bwn_b2062_chantable[i].bc_chan == chan) {
11234			bc = &bwn_b2062_chantable[i];
11235			break;
11236		}
11237	}
11238
11239	if (bc == NULL)
11240		return (EINVAL);
11241
11242	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11243	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11244	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11245	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11246	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11247	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11248	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11249	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11250	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11251	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11252
11253	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11254	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11255	bwn_phy_lp_b2062_reset_pllbias(mac);
11256	tmp[0] = freqxtal / 1000;
11257	tmp[1] = plp->plp_div * 1000;
11258	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11259	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11260		tmp[2] *= 2;
11261	tmp[3] = 48 * tmp[0];
11262	tmp[5] = tmp[2] / tmp[3];
11263	tmp[6] = tmp[2] % tmp[3];
11264	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11265	tmp[4] = tmp[6] * 0x100;
11266	tmp[5] = tmp[4] / tmp[3];
11267	tmp[6] = tmp[4] % tmp[3];
11268	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11269	tmp[4] = tmp[6] * 0x100;
11270	tmp[5] = tmp[4] / tmp[3];
11271	tmp[6] = tmp[4] % tmp[3];
11272	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11273	tmp[4] = tmp[6] * 0x100;
11274	tmp[5] = tmp[4] / tmp[3];
11275	tmp[6] = tmp[4] % tmp[3];
11276	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11277	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11278	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11279	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11280	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11281	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11282
11283	bwn_phy_lp_b2062_vco_calib(mac);
11284	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11285		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11286		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11287		bwn_phy_lp_b2062_reset_pllbias(mac);
11288		bwn_phy_lp_b2062_vco_calib(mac);
11289		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11290			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11291			return (EIO);
11292		}
11293	}
11294	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11295	return (0);
11296}
11297
11298static void
11299bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11300{
11301	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11302	uint16_t tmp = (channel == 14);
11303
11304	if (mac->mac_phy.rev < 2) {
11305		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11306		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11307			bwn_phy_lp_set_rccap(mac);
11308		return;
11309	}
11310
11311	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11312}
11313
11314static void
11315bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11316{
11317	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11318	struct bwn_softc *sc = mac->mac_sc;
11319	struct ieee80211com *ic = &sc->sc_ic;
11320	uint16_t iso, tmp[3];
11321
11322	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11323
11324	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11325		iso = plp->plp_txisoband_m;
11326	else if (freq <= 5320)
11327		iso = plp->plp_txisoband_l;
11328	else if (freq <= 5700)
11329		iso = plp->plp_txisoband_m;
11330	else
11331		iso = plp->plp_txisoband_h;
11332
11333	tmp[0] = ((iso - 26) / 12) << 12;
11334	tmp[1] = tmp[0] + 0x1000;
11335	tmp[2] = tmp[0] + 0x2000;
11336
11337	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11338	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11339}
11340
11341static void
11342bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11343{
11344	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11345	int i;
11346	static const uint16_t addr[] = {
11347		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11348		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11349		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11350		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11351		BWN_PHY_OFDM(0xcf),
11352	};
11353	static const uint16_t val[] = {
11354		0xde5e, 0xe832, 0xe331, 0x4d26,
11355		0x0026, 0x1420, 0x0020, 0xfe08,
11356		0x0008,
11357	};
11358
11359	for (i = 0; i < N(addr); i++) {
11360		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11361		BWN_PHY_WRITE(mac, addr[i], val[i]);
11362	}
11363}
11364
11365static void
11366bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11367{
11368	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11369	struct bwn_softc *sc = mac->mac_sc;
11370	uint16_t ctl;
11371
11372	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11373	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11374	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11375		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11376		break;
11377	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11378		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11379		break;
11380	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11381		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11382		break;
11383	default:
11384		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11385		device_printf(sc->sc_dev, "unknown command mode\n");
11386		break;
11387	}
11388}
11389
11390static void
11391bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11392{
11393	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11394	uint16_t ctl;
11395	uint8_t old;
11396
11397	bwn_phy_lp_get_txpctlmode(mac);
11398	old = plp->plp_txpctlmode;
11399	if (old == mode)
11400		return;
11401	plp->plp_txpctlmode = mode;
11402
11403	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11404		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11405		    plp->plp_tssiidx);
11406		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11407		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11408
11409		/* disable TX GAIN override */
11410		if (mac->mac_phy.rev < 2)
11411			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11412		else {
11413			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11414			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11415		}
11416		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11417
11418		plp->plp_txpwridx = -1;
11419	}
11420	if (mac->mac_phy.rev >= 2) {
11421		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11422			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11423		else
11424			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11425	}
11426
11427	/* writes TX Power Control mode */
11428	switch (plp->plp_txpctlmode) {
11429	case BWN_PHYLP_TXPCTL_OFF:
11430		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11431		break;
11432	case BWN_PHYLP_TXPCTL_ON_HW:
11433		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11434		break;
11435	case BWN_PHYLP_TXPCTL_ON_SW:
11436		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11437		break;
11438	default:
11439		ctl = 0;
11440		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11441	}
11442	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11443	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11444}
11445
11446static void
11447bwn_phy_lp_bugfix(struct bwn_mac *mac)
11448{
11449	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11450	struct bwn_softc *sc = mac->mac_sc;
11451	const unsigned int size = 256;
11452	struct bwn_txgain tg;
11453	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11454	uint16_t tssinpt, tssiidx, value[2];
11455	uint8_t mode;
11456	int8_t txpwridx;
11457
11458	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11459	    M_NOWAIT | M_ZERO);
11460	if (tabs == NULL) {
11461		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11462		return;
11463	}
11464
11465	bwn_phy_lp_get_txpctlmode(mac);
11466	mode = plp->plp_txpctlmode;
11467	txpwridx = plp->plp_txpwridx;
11468	tssinpt = plp->plp_tssinpt;
11469	tssiidx = plp->plp_tssiidx;
11470
11471	bwn_tab_read_multi(mac,
11472	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11473	    BWN_TAB_4(7, 0x140), size, tabs);
11474
11475	bwn_phy_lp_tblinit(mac);
11476	bwn_phy_lp_bbinit(mac);
11477	bwn_phy_lp_txpctl_init(mac);
11478	bwn_phy_lp_rf_onoff(mac, 1);
11479	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11480
11481	bwn_tab_write_multi(mac,
11482	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11483	    BWN_TAB_4(7, 0x140), size, tabs);
11484
11485	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11486	plp->plp_tssinpt = tssinpt;
11487	plp->plp_tssiidx = tssiidx;
11488	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11489	if (txpwridx != -1) {
11490		/* set TX power by index */
11491		plp->plp_txpwridx = txpwridx;
11492		bwn_phy_lp_get_txpctlmode(mac);
11493		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11494			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11495		if (mac->mac_phy.rev >= 2) {
11496			rxcomp = bwn_tab_read(mac,
11497			    BWN_TAB_4(7, txpwridx + 320));
11498			txgain = bwn_tab_read(mac,
11499			    BWN_TAB_4(7, txpwridx + 192));
11500			tg.tg_pad = (txgain >> 16) & 0xff;
11501			tg.tg_gm = txgain & 0xff;
11502			tg.tg_pga = (txgain >> 8) & 0xff;
11503			tg.tg_dac = (rxcomp >> 28) & 0xff;
11504			bwn_phy_lp_set_txgain(mac, &tg);
11505		} else {
11506			rxcomp = bwn_tab_read(mac,
11507			    BWN_TAB_4(10, txpwridx + 320));
11508			txgain = bwn_tab_read(mac,
11509			    BWN_TAB_4(10, txpwridx + 192));
11510			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11511			    0xf800, (txgain >> 4) & 0x7fff);
11512			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11513			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11514		}
11515		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11516
11517		/* set TX IQCC */
11518		value[0] = (rxcomp >> 10) & 0x3ff;
11519		value[1] = rxcomp & 0x3ff;
11520		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11521
11522		coeff = bwn_tab_read(mac,
11523		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11524		    BWN_TAB_4(10, txpwridx + 448));
11525		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11526		if (mac->mac_phy.rev >= 2) {
11527			rfpwr = bwn_tab_read(mac,
11528			    BWN_TAB_4(7, txpwridx + 576));
11529			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11530			    rfpwr & 0xffff);
11531		}
11532		bwn_phy_lp_set_txgain_override(mac);
11533	}
11534	if (plp->plp_rccap)
11535		bwn_phy_lp_set_rccap(mac);
11536	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11537	bwn_phy_lp_set_txpctlmode(mac, mode);
11538	free(tabs, M_DEVBUF);
11539}
11540
11541static void
11542bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11543{
11544	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11545	int i;
11546	static const uint16_t addr[] = {
11547		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11548		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11549		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11550		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11551		BWN_PHY_OFDM(0xcf),
11552	};
11553
11554	for (i = 0; i < N(addr); i++)
11555		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11556}
11557
11558static void
11559bwn_phy_lp_tblinit(struct bwn_mac *mac)
11560{
11561	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11562
11563	if (mac->mac_phy.rev < 2) {
11564		bwn_phy_lp_tblinit_r01(mac);
11565		bwn_phy_lp_tblinit_txgain(mac);
11566		bwn_phy_lp_set_gaintbl(mac, freq);
11567		return;
11568	}
11569
11570	bwn_phy_lp_tblinit_r2(mac);
11571	bwn_phy_lp_tblinit_txgain(mac);
11572}
11573
11574struct bwn_wpair {
11575	uint16_t		reg;
11576	uint16_t		value;
11577};
11578
11579struct bwn_smpair {
11580	uint16_t		offset;
11581	uint16_t		mask;
11582	uint16_t		set;
11583};
11584
11585static void
11586bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11587{
11588	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11589	struct bwn_softc *sc = mac->mac_sc;
11590	struct ieee80211com *ic = &sc->sc_ic;
11591	static const struct bwn_wpair v1[] = {
11592		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11593		{ BWN_PHY_AFE_CTL, 0x8800 },
11594		{ BWN_PHY_AFE_CTL_OVR, 0 },
11595		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11596		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11597		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11598		{ BWN_PHY_OFDM(0xf9), 0 },
11599		{ BWN_PHY_TR_LOOKUP_1, 0 }
11600	};
11601	static const struct bwn_smpair v2[] = {
11602		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11603		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11604		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11605		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11606		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11607	};
11608	static const struct bwn_smpair v3[] = {
11609		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11610		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11611		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11612		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11613		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11614		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11615		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11616		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11617		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11618		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11619
11620	};
11621	int i;
11622
11623	for (i = 0; i < N(v1); i++)
11624		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11625	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11626	for (i = 0; i < N(v2); i++)
11627		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11628
11629	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11630	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11631	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11632	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11633		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11634		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11635	} else {
11636		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11637	}
11638	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11639	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11640	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11641	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11642	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11643	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11644	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11645	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11646	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11647	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11648	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11649	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11650	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11651		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11652		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11653	} else {
11654		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11655		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11656	}
11657	for (i = 0; i < N(v3); i++)
11658		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11659	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11660	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11661		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11662		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11663	}
11664
11665	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11666		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11667		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11668		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11669		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11670		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11671		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11672	} else
11673		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11674
11675	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11676	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11677	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11678	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11679	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11680	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11681	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11682	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11683	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11684
11685	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11686	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11687		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11688		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11689		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11690	}
11691
11692	bwn_phy_lp_digflt_save(mac);
11693}
11694
11695static void
11696bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11697{
11698	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11699	struct bwn_softc *sc = mac->mac_sc;
11700	struct ieee80211com *ic = &sc->sc_ic;
11701	static const struct bwn_smpair v1[] = {
11702		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11703		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11704		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11705		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11706		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11707		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11708		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11709	};
11710	static const struct bwn_smpair v2[] = {
11711		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11712		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11713		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11714		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11715		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11716		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11717		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11718		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11719		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11720		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11721		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11722		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11723		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11724		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11725		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11726		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11727	};
11728	static const struct bwn_smpair v3[] = {
11729		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11730		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11731		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11732		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11733		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11734		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11735		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11736		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11737	};
11738	static const struct bwn_smpair v4[] = {
11739		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11740		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11741		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11742		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11743		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11744		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11745		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11746		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11747	};
11748	static const struct bwn_smpair v5[] = {
11749		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11750		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11751		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11752		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11753		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11754		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11755		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11756		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11757	};
11758	int i;
11759	uint16_t tmp, tmp2;
11760
11761	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11762	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11763	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11764	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11765	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11766	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11767	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11768	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11769	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11770	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11771	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11772	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11773	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11774	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11775	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11776	for (i = 0; i < N(v1); i++)
11777		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11778	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11779	    0xff00, plp->plp_rxpwroffset);
11780	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11781	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11782	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11783		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11784		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11785		if (mac->mac_phy.rev == 0)
11786			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11787			    0xffcf, 0x0010);
11788		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11789	} else {
11790		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11791		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11792		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11793	}
11794	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11795	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11796	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11797		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11798	else
11799		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11800	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11801	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11802	    0xfff9, (plp->plp_bxarch << 1));
11803	if (mac->mac_phy.rev == 1 &&
11804	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11805		for (i = 0; i < N(v2); i++)
11806			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11807			    v2[i].set);
11808	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11809	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11810	    ((mac->mac_phy.rev == 0) &&
11811	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11812		for (i = 0; i < N(v3); i++)
11813			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11814			    v3[i].set);
11815	} else if (mac->mac_phy.rev == 1 ||
11816		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11817		for (i = 0; i < N(v4); i++)
11818			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11819			    v4[i].set);
11820	} else {
11821		for (i = 0; i < N(v5); i++)
11822			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11823			    v5[i].set);
11824	}
11825	if (mac->mac_phy.rev == 1 &&
11826	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11827		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11828		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11829		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11830		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11831	}
11832	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11833	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11834	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11835		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11836		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11837		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11838		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11839	}
11840	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11841		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11842		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11843		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11844		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11845		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11846		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11847		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11848		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11849	} else {
11850		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11851		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11852	}
11853	if (mac->mac_phy.rev == 1) {
11854		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11855		tmp2 = (tmp & 0x03e0) >> 5;
11856		tmp2 |= tmp2 << 5;
11857		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
11858		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
11859		tmp2 = (tmp & 0x1f00) >> 8;
11860		tmp2 |= tmp2 << 5;
11861		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
11862		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
11863		tmp2 = tmp & 0x00ff;
11864		tmp2 |= tmp << 8;
11865		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
11866	}
11867}
11868
11869struct bwn_b2062_freq {
11870	uint16_t		freq;
11871	uint8_t			value[6];
11872};
11873
11874static void
11875bwn_phy_lp_b2062_init(struct bwn_mac *mac)
11876{
11877#define	CALC_CTL7(freq, div)						\
11878	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
11879#define	CALC_CTL18(freq, div)						\
11880	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
11881#define	CALC_CTL19(freq, div)						\
11882	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
11883	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11884	struct bwn_softc *sc = mac->mac_sc;
11885	struct ieee80211com *ic = &sc->sc_ic;
11886	static const struct bwn_b2062_freq freqdata_tab[] = {
11887		{ 12000, { 6, 6, 6, 6, 10, 6 } },
11888		{ 13000, { 4, 4, 4, 4, 11, 7 } },
11889		{ 14400, { 3, 3, 3, 3, 12, 7 } },
11890		{ 16200, { 3, 3, 3, 3, 13, 8 } },
11891		{ 18000, { 2, 2, 2, 2, 14, 8 } },
11892		{ 19200, { 1, 1, 1, 1, 14, 9 } }
11893	};
11894	static const struct bwn_wpair v1[] = {
11895		{ BWN_B2062_N_TXCTL3, 0 },
11896		{ BWN_B2062_N_TXCTL4, 0 },
11897		{ BWN_B2062_N_TXCTL5, 0 },
11898		{ BWN_B2062_N_TXCTL6, 0 },
11899		{ BWN_B2062_N_PDNCTL0, 0x40 },
11900		{ BWN_B2062_N_PDNCTL0, 0 },
11901		{ BWN_B2062_N_CALIB_TS, 0x10 },
11902		{ BWN_B2062_N_CALIB_TS, 0 }
11903	};
11904	const struct bwn_b2062_freq *f = NULL;
11905	uint32_t xtalfreq, ref;
11906	unsigned int i;
11907
11908	bwn_phy_lp_b2062_tblinit(mac);
11909
11910	for (i = 0; i < N(v1); i++)
11911		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
11912	if (mac->mac_phy.rev > 0)
11913		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
11914		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
11915	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11916		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
11917	else
11918		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
11919
11920	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
11921	    ("%s:%d: fail", __func__, __LINE__));
11922	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11923	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
11924
11925	if (xtalfreq <= 30000000) {
11926		plp->plp_div = 1;
11927		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
11928	} else {
11929		plp->plp_div = 2;
11930		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
11931	}
11932
11933	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
11934	    CALC_CTL7(xtalfreq, plp->plp_div));
11935	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
11936	    CALC_CTL18(xtalfreq, plp->plp_div));
11937	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
11938	    CALC_CTL19(xtalfreq, plp->plp_div));
11939
11940	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
11941	ref &= 0xffff;
11942	for (i = 0; i < N(freqdata_tab); i++) {
11943		if (ref < freqdata_tab[i].freq) {
11944			f = &freqdata_tab[i];
11945			break;
11946		}
11947	}
11948	if (f == NULL)
11949		f = &freqdata_tab[N(freqdata_tab) - 1];
11950	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
11951	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
11952	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
11953	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
11954	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
11955	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
11956#undef CALC_CTL7
11957#undef CALC_CTL18
11958#undef CALC_CTL19
11959}
11960
11961static void
11962bwn_phy_lp_b2063_init(struct bwn_mac *mac)
11963{
11964
11965	bwn_phy_lp_b2063_tblinit(mac);
11966	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
11967	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
11968	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
11969	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
11970	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
11971	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
11972	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
11973	if (mac->mac_phy.rev == 2) {
11974		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
11975		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
11976		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
11977	} else {
11978		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
11979		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
11980	}
11981}
11982
11983static void
11984bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
11985{
11986	struct bwn_softc *sc = mac->mac_sc;
11987	static const struct bwn_wpair v1[] = {
11988		{ BWN_B2063_RX_BB_SP8, 0x0 },
11989		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
11990		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
11991		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
11992		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
11993		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
11994		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
11995		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
11996	};
11997	static const struct bwn_wpair v2[] = {
11998		{ BWN_B2063_TX_BB_SP3, 0x0 },
11999		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12000		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12001		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12002		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12003	};
12004	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12005	int i;
12006	uint8_t tmp;
12007
12008	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12009
12010	for (i = 0; i < 2; i++)
12011		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12012	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12013	for (i = 2; i < N(v1); i++)
12014		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12015	for (i = 0; i < 10000; i++) {
12016		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12017			break;
12018		DELAY(1000);
12019	}
12020
12021	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12022		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12023
12024	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12025
12026	for (i = 0; i < N(v2); i++)
12027		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12028	if (freqxtal == 24000000) {
12029		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12030		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12031	} else {
12032		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12033		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12034	}
12035	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12036	for (i = 0; i < 10000; i++) {
12037		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12038			break;
12039		DELAY(1000);
12040	}
12041	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12042		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12043	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12044}
12045
12046static void
12047bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12048{
12049	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12050	struct bwn_softc *sc = mac->mac_sc;
12051	struct bwn_phy_lp_iq_est ie;
12052	struct bwn_txgain tx_gains;
12053	static const uint32_t pwrtbl[21] = {
12054		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12055		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12056		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12057		0x0004c, 0x0002c, 0x0001a,
12058	};
12059	uint32_t npwr, ipwr, sqpwr, tmp;
12060	int loopback, i, j, sum, error;
12061	uint16_t save[7];
12062	uint8_t txo, bbmult, txpctlmode;
12063
12064	error = bwn_phy_lp_switch_channel(mac, 7);
12065	if (error)
12066		device_printf(sc->sc_dev,
12067		    "failed to change channel to 7 (%d)\n", error);
12068	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12069	bbmult = bwn_phy_lp_get_bbmult(mac);
12070	if (txo)
12071		tx_gains = bwn_phy_lp_get_txgain(mac);
12072
12073	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12074	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12075	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12076	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12077	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12078	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12079	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12080
12081	bwn_phy_lp_get_txpctlmode(mac);
12082	txpctlmode = plp->plp_txpctlmode;
12083	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12084
12085	/* disable CRS */
12086	bwn_phy_lp_set_deaf(mac, 1);
12087	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12088	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12089	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12090	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12091	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12092	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12093	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12094	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12095	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12096	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12097	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12098	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12099	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12100	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12101	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12102	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12103	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12104	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12105	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12106	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12107	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12108	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12109	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12110	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12111
12112	loopback = bwn_phy_lp_loopback(mac);
12113	if (loopback == -1)
12114		goto done;
12115	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12116	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12117	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12118	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12119	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12120
12121	tmp = 0;
12122	memset(&ie, 0, sizeof(ie));
12123	for (i = 128; i <= 159; i++) {
12124		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12125		sum = 0;
12126		for (j = 5; j <= 25; j++) {
12127			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12128			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12129				goto done;
12130			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12131			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12132			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12133			    12);
12134			sum += ((ipwr - npwr) * (ipwr - npwr));
12135			if ((i == 128) || (sum < tmp)) {
12136				plp->plp_rccap = i;
12137				tmp = sum;
12138			}
12139		}
12140	}
12141	bwn_phy_lp_ddfs_turnoff(mac);
12142done:
12143	/* restore CRS */
12144	bwn_phy_lp_clear_deaf(mac, 1);
12145	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12146	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12147
12148	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12149	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12150	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12151	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12152	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12153	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12154	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12155
12156	bwn_phy_lp_set_bbmult(mac, bbmult);
12157	if (txo)
12158		bwn_phy_lp_set_txgain(mac, &tx_gains);
12159	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12160	if (plp->plp_rccap)
12161		bwn_phy_lp_set_rccap(mac);
12162}
12163
12164static void
12165bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12166{
12167	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12168	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12169
12170	if (mac->mac_phy.rev == 1)
12171		rc_cap = MIN(rc_cap + 5, 15);
12172
12173	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12174	    MAX(plp->plp_rccap - 4, 0x80));
12175	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12176	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12177	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12178}
12179
12180static uint32_t
12181bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12182{
12183	uint32_t i, q, r;
12184
12185	if (div == 0)
12186		return (0);
12187
12188	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12189		q <<= 1;
12190		if (r << 1 >= div) {
12191			q++;
12192			r = (r << 1) - div;
12193		}
12194	}
12195	if (r << 1 >= div)
12196		q++;
12197	return (q);
12198}
12199
12200static void
12201bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12202{
12203	struct bwn_softc *sc = mac->mac_sc;
12204
12205	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12206	DELAY(20);
12207	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12208		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12209		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12210	} else {
12211		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12212	}
12213	DELAY(5);
12214}
12215
12216static void
12217bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12218{
12219
12220	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12221	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12222	DELAY(200);
12223}
12224
12225static void
12226bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12227{
12228#define	FLAG_A	0x01
12229#define	FLAG_G	0x02
12230	struct bwn_softc *sc = mac->mac_sc;
12231	struct ieee80211com *ic = &sc->sc_ic;
12232	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12233		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12234		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12235		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12236		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12237		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12238		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12239		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12240		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12241		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12242		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12243		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12244		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12245		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12246		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12247		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12248		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12249		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12250		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12251		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12252		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12253		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12254		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12255		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12256		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12257		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12258		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12259		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12260		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12261		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12262		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12263		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12264		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12265		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12266		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12267		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12268		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12269		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12270		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12271		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12272		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12273		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12274		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12275		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12276		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12277		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12278		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12279		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12280	};
12281	const struct bwn_b206x_rfinit_entry *br;
12282	unsigned int i;
12283
12284	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12285		br = &bwn_b2062_init_tab[i];
12286		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12287			if (br->br_flags & FLAG_G)
12288				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12289		} else {
12290			if (br->br_flags & FLAG_A)
12291				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12292		}
12293	}
12294#undef FLAG_A
12295#undef FLAG_B
12296}
12297
12298static void
12299bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12300{
12301#define	FLAG_A	0x01
12302#define	FLAG_G	0x02
12303	struct bwn_softc *sc = mac->mac_sc;
12304	struct ieee80211com *ic = &sc->sc_ic;
12305	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12306		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12307		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12308		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12309		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12310		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12311		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12312		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12313		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12314		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12315		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12316		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12317		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12318		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12319		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12320		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12321		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12322		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12323		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12324		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12325		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12326		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12327		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12328		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12329		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12330		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12331		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12332		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12333		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12334		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12335		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12336		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12337		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12338		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12339		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12340		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12341		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12342		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12343		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12344		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12345		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12346		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12347		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12348	};
12349	const struct bwn_b206x_rfinit_entry *br;
12350	unsigned int i;
12351
12352	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12353		br = &bwn_b2063_init_tab[i];
12354		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12355			if (br->br_flags & FLAG_G)
12356				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12357		} else {
12358			if (br->br_flags & FLAG_A)
12359				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12360		}
12361	}
12362#undef FLAG_A
12363#undef FLAG_B
12364}
12365
12366static void
12367bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12368    int count, void *_data)
12369{
12370	unsigned int i;
12371	uint32_t offset, type;
12372	uint8_t *data = _data;
12373
12374	type = BWN_TAB_GETTYPE(typenoffset);
12375	offset = BWN_TAB_GETOFFSET(typenoffset);
12376	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12377
12378	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12379
12380	for (i = 0; i < count; i++) {
12381		switch (type) {
12382		case BWN_TAB_8BIT:
12383			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12384			data++;
12385			break;
12386		case BWN_TAB_16BIT:
12387			*((uint16_t *)data) = BWN_PHY_READ(mac,
12388			    BWN_PHY_TABLEDATALO);
12389			data += 2;
12390			break;
12391		case BWN_TAB_32BIT:
12392			*((uint32_t *)data) = BWN_PHY_READ(mac,
12393			    BWN_PHY_TABLEDATAHI);
12394			*((uint32_t *)data) <<= 16;
12395			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12396			    BWN_PHY_TABLEDATALO);
12397			data += 4;
12398			break;
12399		default:
12400			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12401		}
12402	}
12403}
12404
12405static void
12406bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12407    int count, const void *_data)
12408{
12409	uint32_t offset, type, value;
12410	const uint8_t *data = _data;
12411	unsigned int i;
12412
12413	type = BWN_TAB_GETTYPE(typenoffset);
12414	offset = BWN_TAB_GETOFFSET(typenoffset);
12415	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12416
12417	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12418
12419	for (i = 0; i < count; i++) {
12420		switch (type) {
12421		case BWN_TAB_8BIT:
12422			value = *data;
12423			data++;
12424			KASSERT(!(value & ~0xff),
12425			    ("%s:%d: fail", __func__, __LINE__));
12426			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12427			break;
12428		case BWN_TAB_16BIT:
12429			value = *((const uint16_t *)data);
12430			data += 2;
12431			KASSERT(!(value & ~0xffff),
12432			    ("%s:%d: fail", __func__, __LINE__));
12433			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12434			break;
12435		case BWN_TAB_32BIT:
12436			value = *((const uint32_t *)data);
12437			data += 4;
12438			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12439			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12440			break;
12441		default:
12442			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12443		}
12444	}
12445}
12446
12447static struct bwn_txgain
12448bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12449{
12450	struct bwn_txgain tg;
12451	uint16_t tmp;
12452
12453	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12454	if (mac->mac_phy.rev < 2) {
12455		tmp = BWN_PHY_READ(mac,
12456		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12457		tg.tg_gm = tmp & 0x0007;
12458		tg.tg_pga = (tmp & 0x0078) >> 3;
12459		tg.tg_pad = (tmp & 0x780) >> 7;
12460		return (tg);
12461	}
12462
12463	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12464	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12465	tg.tg_gm = tmp & 0xff;
12466	tg.tg_pga = (tmp >> 8) & 0xff;
12467	return (tg);
12468}
12469
12470static uint8_t
12471bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12472{
12473
12474	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12475}
12476
12477static void
12478bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12479{
12480	uint16_t pa;
12481
12482	if (mac->mac_phy.rev < 2) {
12483		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12484		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12485		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12486		bwn_phy_lp_set_txgain_override(mac);
12487		return;
12488	}
12489
12490	pa = bwn_phy_lp_get_pa_gain(mac);
12491	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12492	    (tg->tg_pga << 8) | tg->tg_gm);
12493	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12494	    tg->tg_pad | (pa << 6));
12495	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12496	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12497	    tg->tg_pad | (pa << 8));
12498	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12499	bwn_phy_lp_set_txgain_override(mac);
12500}
12501
12502static void
12503bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12504{
12505
12506	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12507}
12508
12509static void
12510bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12511{
12512	uint16_t trsw = (tx << 1) | rx;
12513
12514	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12515	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12516}
12517
12518static void
12519bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12520{
12521	struct bwn_softc *sc = mac->mac_sc;
12522	struct ieee80211com *ic = &sc->sc_ic;
12523	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12524
12525	if (mac->mac_phy.rev < 2) {
12526		trsw = gain & 0x1;
12527		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12528		ext_lna = (gain & 2) >> 1;
12529
12530		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12531		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12532		    0xfbff, ext_lna << 10);
12533		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12534		    0xf7ff, ext_lna << 11);
12535		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12536	} else {
12537		low_gain = gain & 0xffff;
12538		high_gain = (gain >> 16) & 0xf;
12539		ext_lna = (gain >> 21) & 0x1;
12540		trsw = ~(gain >> 20) & 0x1;
12541
12542		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12543		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12544		    0xfdff, ext_lna << 9);
12545		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12546		    0xfbff, ext_lna << 10);
12547		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12548		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12549		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12550			tmp = (gain >> 2) & 0x3;
12551			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12552			    0xe7ff, tmp<<11);
12553			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12554			    tmp << 3);
12555		}
12556	}
12557
12558	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12559	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12560	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12561	if (mac->mac_phy.rev >= 2) {
12562		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12563		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12564			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12565			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12566		}
12567		return;
12568	}
12569	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12570}
12571
12572static void
12573bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12574{
12575	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12576
12577	if (user)
12578		plp->plp_crsusr_off = 1;
12579	else
12580		plp->plp_crssys_off = 1;
12581
12582	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12583}
12584
12585static void
12586bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12587{
12588	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12589	struct bwn_softc *sc = mac->mac_sc;
12590	struct ieee80211com *ic = &sc->sc_ic;
12591
12592	if (user)
12593		plp->plp_crsusr_off = 0;
12594	else
12595		plp->plp_crssys_off = 0;
12596
12597	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12598		return;
12599
12600	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12601		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12602	else
12603		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12604}
12605
12606static unsigned int
12607bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12608{
12609	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12610	static uint8_t sqrt_table[256] = {
12611		10, 14, 17, 20, 22, 24, 26, 28,
12612		30, 31, 33, 34, 36, 37, 38, 40,
12613		41, 42, 43, 44, 45, 46, 47, 48,
12614		50, 50, 51, 52, 53, 54, 55, 56,
12615		57, 58, 59, 60, 60, 61, 62, 63,
12616		64, 64, 65, 66, 67, 67, 68, 69,
12617		70, 70, 71, 72, 72, 73, 74, 74,
12618		75, 76, 76, 77, 78, 78, 79, 80,
12619		80, 81, 81, 82, 83, 83, 84, 84,
12620		85, 86, 86, 87, 87, 88, 88, 89,
12621		90, 90, 91, 91, 92, 92, 93, 93,
12622		94, 94, 95, 95, 96, 96, 97, 97,
12623		98, 98, 99, 100, 100, 100, 101, 101,
12624		102, 102, 103, 103, 104, 104, 105, 105,
12625		106, 106, 107, 107, 108, 108, 109, 109,
12626		110, 110, 110, 111, 111, 112, 112, 113,
12627		113, 114, 114, 114, 115, 115, 116, 116,
12628		117, 117, 117, 118, 118, 119, 119, 120,
12629		120, 120, 121, 121, 122, 122, 122, 123,
12630		123, 124, 124, 124, 125, 125, 126, 126,
12631		126, 127, 127, 128, 128, 128, 129, 129,
12632		130, 130, 130, 131, 131, 131, 132, 132,
12633		133, 133, 133, 134, 134, 134, 135, 135,
12634		136, 136, 136, 137, 137, 137, 138, 138,
12635		138, 139, 139, 140, 140, 140, 141, 141,
12636		141, 142, 142, 142, 143, 143, 143, 144,
12637		144, 144, 145, 145, 145, 146, 146, 146,
12638		147, 147, 147, 148, 148, 148, 149, 149,
12639		150, 150, 150, 150, 151, 151, 151, 152,
12640		152, 152, 153, 153, 153, 154, 154, 154,
12641		155, 155, 155, 156, 156, 156, 157, 157,
12642		157, 158, 158, 158, 159, 159, 159, 160
12643	};
12644
12645	if (x == 0)
12646		return (0);
12647	if (x >= 256) {
12648		unsigned int tmp;
12649
12650		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12651			/* do nothing */ ;
12652		return (tmp);
12653	}
12654	return (sqrt_table[x - 1] / 10);
12655}
12656
12657static int
12658bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12659{
12660#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12661	int _t;								\
12662	_t = _x - 20;							\
12663	if (_t >= 0) {							\
12664		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12665	} else {							\
12666		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12667	}								\
12668} while (0)
12669#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12670	int _t;								\
12671	_t = _x - 11;							\
12672	if (_t >= 0)							\
12673		_v = (_y << (31 - _x)) / (_z >> _t);			\
12674	else								\
12675		_v = (_y << (31 - _x)) / (_z << -_t);			\
12676} while (0)
12677	struct bwn_phy_lp_iq_est ie;
12678	uint16_t v0, v1;
12679	int tmp[2], ret;
12680
12681	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12682	v0 = v1 >> 8;
12683	v1 |= 0xff;
12684
12685	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12686	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12687
12688	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12689	if (ret == 0)
12690		goto done;
12691
12692	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12693		ret = 0;
12694		goto done;
12695	}
12696
12697	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12698	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12699
12700	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12701	v0 = tmp[0] >> 3;
12702	v1 = tmp[1] >> 4;
12703done:
12704	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12705	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12706	return ret;
12707#undef CALC_COEFF
12708#undef CALC_COEFF2
12709}
12710
12711static void
12712bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12713{
12714	static const uint16_t noisescale[] = {
12715		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12716		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12717		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12718		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12719		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12720	};
12721	static const uint16_t crsgainnft[] = {
12722		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12723		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12724		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12725		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12726		0x013d,
12727	};
12728	static const uint16_t filterctl[] = {
12729		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12730		0xff53, 0x0127,
12731	};
12732	static const uint32_t psctl[] = {
12733		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12734		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12735		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12736		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12737		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12738		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12739		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12740		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12741	};
12742	static const uint16_t ofdmcckgain_r0[] = {
12743		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12744		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12745		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12746		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12747		0x755d,
12748	};
12749	static const uint16_t ofdmcckgain_r1[] = {
12750		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12751		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12752		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12753		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12754		0x755d,
12755	};
12756	static const uint16_t gaindelta[] = {
12757		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12758		0x0000,
12759	};
12760	static const uint32_t txpwrctl[] = {
12761		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12762		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12763		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12764		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12765		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12766		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12767		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12768		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12769		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12770		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12771		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12772		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12773		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12774		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12775		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12776		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12777		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12778		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12779		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12780		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12781		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12782		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12783		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12784		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12785		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12786		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12787		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12788		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12789		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12790		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12791		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12792		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12793		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12794		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12795		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12796		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12797		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12798		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12799		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12800		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12801		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12802		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12803		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12804		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12805		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12806		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12807		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12808		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12809		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12810		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12811		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12812		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12813		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12814		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12815		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12816		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12817		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12818		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12819		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12820		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12821		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12822		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12823		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12824		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12825		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12826		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12827		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12828		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12829		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12830		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12831		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12832		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12833		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12834		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12835		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12836		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12837		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12838		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12839		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12840		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12841		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12842		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12843		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12844		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12845		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12846		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12847		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12848		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12849		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12850		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
12851		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
12852		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
12853		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
12854		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
12855		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
12856		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
12857		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
12858		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
12859		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
12860		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
12861		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
12862		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
12863		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
12864		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
12865		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
12866		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
12867		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
12868		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
12869		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
12870		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
12871		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
12872		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
12873		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
12874		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
12875		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
12876		0x00000702,
12877	};
12878
12879	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
12880
12881	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
12882	    bwn_tab_sigsq_tbl);
12883	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
12884	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
12885	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
12886	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
12887	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
12888	    bwn_tab_pllfrac_tbl);
12889	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
12890	    bwn_tabl_iqlocal_tbl);
12891	if (mac->mac_phy.rev == 0) {
12892		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
12893		    ofdmcckgain_r0);
12894		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
12895		    ofdmcckgain_r0);
12896	} else {
12897		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
12898		    ofdmcckgain_r1);
12899		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
12900		    ofdmcckgain_r1);
12901	}
12902	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
12903	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
12904}
12905
12906static void
12907bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
12908{
12909	struct bwn_softc *sc = mac->mac_sc;
12910	int i;
12911	static const uint16_t noisescale[] = {
12912		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12913		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12914		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12915		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12916		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12917		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12918		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
12919	};
12920	static const uint32_t filterctl[] = {
12921		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
12922		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
12923	};
12924	static const uint32_t psctl[] = {
12925		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
12926		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
12927		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
12928		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
12929	};
12930	static const uint32_t gainidx[] = {
12931		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12932		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12933		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
12935		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
12936		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
12937		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
12938		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
12939		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
12940		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
12941		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
12942		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
12943		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
12944		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
12945		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
12946		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12948		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12949		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
12950		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
12951		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
12952		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
12953		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
12954		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
12955		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
12956		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
12957		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
12958		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
12959		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
12960		0x0000001a, 0x64ca55ad, 0x0000001a
12961	};
12962	static const uint16_t auxgainidx[] = {
12963		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12964		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
12965		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
12966		0x0004, 0x0016
12967	};
12968	static const uint16_t swctl[] = {
12969		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12970		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12971		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
12972		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
12973		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12974		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12975		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
12976		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
12977	};
12978	static const uint8_t hf[] = {
12979		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
12980		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
12981	};
12982	static const uint32_t gainval[] = {
12983		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
12984		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
12985		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
12986		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
12987		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
12988		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
12989		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12990		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12991		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
12992		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
12993		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
12994		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
12995		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
12996		0x000000f1, 0x00000000, 0x00000000
12997	};
12998	static const uint16_t gain[] = {
12999		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13000		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13001		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13002		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13003		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13004		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13005		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13006		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13007		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13008		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13009		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13010		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13011	};
13012	static const uint32_t papdeps[] = {
13013		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13014		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13015		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13016		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13017		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13018		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13019		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13020		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13021		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13022		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13023		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13024		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13025		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13026	};
13027	static const uint32_t papdmult[] = {
13028		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13029		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13030		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13031		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13032		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13033		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13034		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13035		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13036		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13037		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13038		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13039		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13040		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13041	};
13042	static const uint32_t gainidx_a0[] = {
13043		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13044		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13045		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13046		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13047		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13048		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13049		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13050		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13051		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13052		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13053		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13054		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13055		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13056	};
13057	static const uint16_t auxgainidx_a0[] = {
13058		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13059		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13060		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13061		0x0002, 0x0014
13062	};
13063	static const uint32_t gainval_a0[] = {
13064		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13065		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13066		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13067		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13068		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13069		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13070		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13071		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13072		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13073		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13074		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13075		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13076		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13077		0x000000f7, 0x00000000, 0x00000000
13078	};
13079	static const uint16_t gain_a0[] = {
13080		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13081		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13082		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13083		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13084		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13085		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13086		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13087		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13088		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13089		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13090		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13091		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13092	};
13093
13094	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13095
13096	for (i = 0; i < 704; i++)
13097		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13098
13099	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13100	    bwn_tab_sigsq_tbl);
13101	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13102	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13103	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13104	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13105	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13106	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13107	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13108	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13109	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13110	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13111	    bwn_tab_pllfrac_tbl);
13112	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13113	    bwn_tabl_iqlocal_tbl);
13114	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13115	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13116
13117	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13118	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13119		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13120		    gainidx_a0);
13121		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13122		    auxgainidx_a0);
13123		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13124		    gainval_a0);
13125		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13126	}
13127}
13128
13129static void
13130bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13131{
13132	struct bwn_softc *sc = mac->mac_sc;
13133	struct ieee80211com *ic = &sc->sc_ic;
13134	static struct bwn_txgain_entry txgain_r2[] = {
13135		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13136		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13137		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13138		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13139		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13140		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13141		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13142		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13143		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13144		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13145		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13146		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13147		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13148		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13149		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13150		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13151		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13152		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13153		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13154		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13155		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13156		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13157		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13158		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13159		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13160		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13161		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13162		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13163		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13164		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13165		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13166		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13167		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13168		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13169		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13170		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13171		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13172		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13173		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13174		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13175		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13176		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13177		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13178		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13179		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13180		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13181		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13182		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13183		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13184		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13185		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13186		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13187		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13188		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13189		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13190		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13191		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13192		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13193		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13194		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13195		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13196		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13197		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13198		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13199	};
13200	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13201		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13202		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13203		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13204		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13205		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13206		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13207		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13208		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13209		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13210		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13211		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13212		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13213		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13214		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13215		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13216		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13217		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13218		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13219		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13220		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13221		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13222		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13223		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13224		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13225		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13226		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13227		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13228		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13229		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13230		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13231		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13232		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13233		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13234		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13235		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13236		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13237		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13238		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13239		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13240		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13241		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13242		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13243		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13244		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13245		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13246		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13247		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13248		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13249		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13250		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13251		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13252		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13253		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13254		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13255		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13256		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13257		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13258		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13259		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13260		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13261		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13262		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13263		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13264		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13265	};
13266	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13267		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13268		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13269		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13270		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13271		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13272		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13273		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13274		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13275		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13276		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13277		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13278		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13279		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13280		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13281		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13282		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13283		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13284		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13285		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13286		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13287		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13288		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13289		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13290		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13291		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13292		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13293		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13294		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13295		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13296		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13297		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13298		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13299		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13300		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13301		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13302		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13303		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13304		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13305		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13306		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13307		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13308		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13309		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13310		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13311		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13312		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13313		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13314		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13315		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13316		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13317		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13318		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13319		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13320		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13321		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13322		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13323		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13324		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13325		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13326		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13327		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13328		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13329		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13330		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13331	};
13332	static struct bwn_txgain_entry txgain_r0[] = {
13333		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13334		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13335		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13336		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13337		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13338		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13339		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13340		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13341		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13342		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13343		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13344		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13345		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13346		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13347		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13348		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13349		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13350		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13351		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13352		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13353		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13354		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13355		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13356		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13357		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13358		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13359		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13360		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13361		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13362		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13363		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13364		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13365		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13366		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13367		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13368		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13369		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13370		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13371		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13372		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13373		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13374		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13375		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13376		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13377		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13378		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13379		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13380		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13381		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13382		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13383		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13384		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13385		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13386		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13387		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13388		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13389		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13390		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13391		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13392		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13393		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13394		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13395		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13396		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13397	};
13398	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13399		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13400		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13401		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13402		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13403		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13404		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13405		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13406		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13407		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13408		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13409		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13410		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13411		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13412		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13413		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13414		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13415		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13416		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13417		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13418		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13419		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13420		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13421		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13422		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13423		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13424		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13425		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13426		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13427		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13428		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13429		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13430		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13431		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13432		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13433		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13434		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13435		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13436		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13437		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13438		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13439		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13440		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13441		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13442		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13443		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13444		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13445		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13446		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13447		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13448		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13449		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13450		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13451		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13452		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13453		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13454		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13455		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13456		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13457		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13458		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13459		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13460		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13461		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13462		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13463	};
13464	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13465		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13466		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13467		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13468		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13469		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13470		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13471		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13472		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13473		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13474		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13475		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13476		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13477		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13478		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13479		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13480		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13481		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13482		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13483		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13484		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13485		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13486		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13487		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13488		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13489		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13490		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13491		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13492		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13493		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13494		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13495		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13496		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13497		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13498		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13499		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13500		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13501		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13502		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13503		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13504		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13505		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13506		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13507		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13508		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13509		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13510		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13511		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13512		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13513		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13514		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13515		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13516		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13517		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13518		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13519		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13520		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13521		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13522		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13523		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13524		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13525		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13526		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13527		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13528		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13529	};
13530	static struct bwn_txgain_entry txgain_r1[] = {
13531		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13532		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13533		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13534		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13535		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13536		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13537		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13538		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13539		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13540		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13541		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13542		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13543		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13544		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13545		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13546		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13547		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13548		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13549		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13550		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13551		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13552		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13553		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13554		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13555		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13556		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13557		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13558		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13559		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13560		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13561		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13562		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13563		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13564		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13565		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13566		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13567		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13568		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13569		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13570		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13571		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13572		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13573		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13574		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13575		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13576		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13577		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13578		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13579		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13580		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13581		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13582		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13583		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13584		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13585		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13586		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13587		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13588		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13589		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13590		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13591		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13592		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13593		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13594		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13595		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13596		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13597		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13598		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13599		{ 7, 11, 6, 0, 71 }
13600	};
13601	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13602		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13603		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13604		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13605		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13606		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13607		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13608		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13609		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13610		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13611		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13612		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13613		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13614		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13615		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13616		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13617		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13618		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13619		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13620		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13621		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13622		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13623		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13624		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13625		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13626		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13627		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13628		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13629		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13630		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13631		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13632		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13633		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13634		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13635		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13636		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13637		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13638		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13639		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13640		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13641		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13642		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13643		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13644		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13645		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13646		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13647		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13648		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13649		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13650		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13651		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13652		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13653		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13654		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13655		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13656		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13657		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13658		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13659		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13660		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13661		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13662		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13663		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13664		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13665		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13666	};
13667	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13668		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13669		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13670		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13671		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13672		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13673		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13674		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13675		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13676		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13677		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13678		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13679		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13680		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13681		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13682		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13683		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13684		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13685		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13686		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13687		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13688		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13689		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13690		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13691		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13692		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13693		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13694		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13695		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13696		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13697		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13698		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13699		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13700		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13701		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13702		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13703		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13704		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13705		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13706		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13707		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13708		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13709		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13710		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13711		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13712		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13713		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13714		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13715		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13716		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13717		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13718		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13719		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13720		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13721		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13722		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13723		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13724		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13725		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13726		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13727		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13728		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13729		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13730		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13731		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13732	};
13733
13734	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13735		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13736			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13737		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13738			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13739			    txgain_2ghz_r2);
13740		else
13741			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13742			    txgain_5ghz_r2);
13743		return;
13744	}
13745
13746	if (mac->mac_phy.rev == 0) {
13747		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13748		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13749			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13750		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13751			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13752			    txgain_2ghz_r0);
13753		else
13754			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13755			    txgain_5ghz_r0);
13756		return;
13757	}
13758
13759	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13760	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13761		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13762	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13763		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13764	else
13765		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13766}
13767
13768static void
13769bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13770{
13771	uint32_t offset, type;
13772
13773	type = BWN_TAB_GETTYPE(typeoffset);
13774	offset = BWN_TAB_GETOFFSET(typeoffset);
13775	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13776
13777	switch (type) {
13778	case BWN_TAB_8BIT:
13779		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13780		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13781		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13782		break;
13783	case BWN_TAB_16BIT:
13784		KASSERT(!(value & ~0xffff),
13785		    ("%s:%d: fail", __func__, __LINE__));
13786		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13787		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13788		break;
13789	case BWN_TAB_32BIT:
13790		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13791		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13792		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13793		break;
13794	default:
13795		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13796	}
13797}
13798
13799static int
13800bwn_phy_lp_loopback(struct bwn_mac *mac)
13801{
13802	struct bwn_phy_lp_iq_est ie;
13803	int i, index = -1;
13804	uint32_t tmp;
13805
13806	memset(&ie, 0, sizeof(ie));
13807
13808	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13809	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13810	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13811	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13812	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13813	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13814	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13815	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13816	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13817	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13818	for (i = 0; i < 32; i++) {
13819		bwn_phy_lp_set_rxgain_idx(mac, i);
13820		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13821		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13822			continue;
13823		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13824		if ((tmp > 4000) && (tmp < 10000)) {
13825			index = i;
13826			break;
13827		}
13828	}
13829	bwn_phy_lp_ddfs_turnoff(mac);
13830	return (index);
13831}
13832
13833static void
13834bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13835{
13836
13837	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13838}
13839
13840static void
13841bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13842    int incr1, int incr2, int scale_idx)
13843{
13844
13845	bwn_phy_lp_ddfs_turnoff(mac);
13846	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13847	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13848	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13849	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13850	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
13851	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
13852	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
13853	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
13854	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
13855	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
13856}
13857
13858static uint8_t
13859bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
13860    struct bwn_phy_lp_iq_est *ie)
13861{
13862	int i;
13863
13864	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
13865	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
13866	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
13867	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
13868	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
13869
13870	for (i = 0; i < 500; i++) {
13871		if (!(BWN_PHY_READ(mac,
13872		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
13873			break;
13874		DELAY(1000);
13875	}
13876	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
13877		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13878		return 0;
13879	}
13880
13881	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
13882	ie->ie_iqprod <<= 16;
13883	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
13884	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
13885	ie->ie_ipwr <<= 16;
13886	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
13887	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
13888	ie->ie_qpwr <<= 16;
13889	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
13890
13891	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13892	return 1;
13893}
13894
13895static uint32_t
13896bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
13897{
13898	uint32_t offset, type, value;
13899
13900	type = BWN_TAB_GETTYPE(typeoffset);
13901	offset = BWN_TAB_GETOFFSET(typeoffset);
13902	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13903
13904	switch (type) {
13905	case BWN_TAB_8BIT:
13906		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13907		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
13908		break;
13909	case BWN_TAB_16BIT:
13910		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13911		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13912		break;
13913	case BWN_TAB_32BIT:
13914		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13915		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
13916		value <<= 16;
13917		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13918		break;
13919	default:
13920		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13921		value = 0;
13922	}
13923
13924	return (value);
13925}
13926
13927static void
13928bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
13929{
13930
13931	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
13932	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
13933}
13934
13935static void
13936bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
13937{
13938	uint16_t ctl;
13939
13940	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
13941	ctl |= dac << 7;
13942	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
13943}
13944
13945static void
13946bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
13947{
13948
13949	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
13950	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
13951}
13952
13953static void
13954bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
13955{
13956
13957	if (mac->mac_phy.rev < 2)
13958		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
13959	else {
13960		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
13961		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
13962	}
13963	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
13964}
13965
13966static uint16_t
13967bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
13968{
13969
13970	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
13971}
13972
13973static uint8_t
13974bwn_nbits(int32_t val)
13975{
13976	uint32_t tmp;
13977	uint8_t nbits = 0;
13978
13979	for (tmp = abs(val); tmp != 0; tmp >>= 1)
13980		nbits++;
13981	return (nbits);
13982}
13983
13984static void
13985bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
13986    struct bwn_txgain_entry *table)
13987{
13988	int i;
13989
13990	for (i = offset; i < count; i++)
13991		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
13992}
13993
13994static void
13995bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
13996    struct bwn_txgain_entry data)
13997{
13998
13999	if (mac->mac_phy.rev >= 2)
14000		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14001	else
14002		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14003}
14004
14005static void
14006bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14007    struct bwn_txgain_entry te)
14008{
14009	struct bwn_softc *sc = mac->mac_sc;
14010	struct ieee80211com *ic = &sc->sc_ic;
14011	uint32_t tmp;
14012
14013	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14014
14015	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14016	if (mac->mac_phy.rev >= 3) {
14017		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14018		    (0x10 << 24) : (0x70 << 24));
14019	} else {
14020		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14021		    (0x14 << 24) : (0x7f << 24));
14022	}
14023	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14024	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14025	    te.te_bbmult << 20 | te.te_dac << 28);
14026}
14027
14028static void
14029bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14030    struct bwn_txgain_entry te)
14031{
14032
14033	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14034
14035	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14036	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14037	    te.te_dac);
14038	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14039}
14040
14041static void
14042bwn_sysctl_node(struct bwn_softc *sc)
14043{
14044	device_t dev = sc->sc_dev;
14045	struct bwn_mac *mac;
14046	struct bwn_stats *stats;
14047
14048	/* XXX assume that count of MAC is only 1. */
14049
14050	if ((mac = sc->sc_curmac) == NULL)
14051		return;
14052	stats = &mac->mac_stats;
14053
14054	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14055	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14056	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14057	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14058	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14059	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14060	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14061	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14062	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14063
14064#ifdef BWN_DEBUG
14065	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14066	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14067	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14068#endif
14069}
14070
14071static device_method_t bwn_methods[] = {
14072	/* Device interface */
14073	DEVMETHOD(device_probe,		bwn_probe),
14074	DEVMETHOD(device_attach,	bwn_attach),
14075	DEVMETHOD(device_detach,	bwn_detach),
14076	DEVMETHOD(device_suspend,	bwn_suspend),
14077	DEVMETHOD(device_resume,	bwn_resume),
14078	DEVMETHOD_END
14079};
14080static driver_t bwn_driver = {
14081	"bwn",
14082	bwn_methods,
14083	sizeof(struct bwn_softc)
14084};
14085static devclass_t bwn_devclass;
14086DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14087MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14088MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14089MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14090MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14091