if_bwn.c revision 292165
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 292165 2015-12-13 20:48:24Z avos $");
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	int error;
2688
2689	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
2690	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2691		m_freem(m);
2692		return (ENETDOWN);
2693	}
2694
2695	BWN_LOCK(sc);
2696	if (bwn_tx_isfull(sc, m)) {
2697		m_freem(m);
2698		BWN_UNLOCK(sc);
2699		return (ENOBUFS);
2700	}
2701
2702	error = bwn_tx_start(sc, ni, m);
2703	if (error == 0)
2704		sc->sc_watchdog_timer = 5;
2705	BWN_UNLOCK(sc);
2706	return (error);
2707}
2708
2709/*
2710 * Callback from the 802.11 layer to update the slot time
2711 * based on the current setting.  We use it to notify the
2712 * firmware of ERP changes and the f/w takes care of things
2713 * like slot time and preamble.
2714 */
2715static void
2716bwn_updateslot(struct ieee80211com *ic)
2717{
2718	struct bwn_softc *sc = ic->ic_softc;
2719	struct bwn_mac *mac;
2720
2721	BWN_LOCK(sc);
2722	if (sc->sc_flags & BWN_FLAG_RUNNING) {
2723		mac = (struct bwn_mac *)sc->sc_curmac;
2724		bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic));
2725	}
2726	BWN_UNLOCK(sc);
2727}
2728
2729/*
2730 * Callback from the 802.11 layer after a promiscuous mode change.
2731 * Note this interface does not check the operating mode as this
2732 * is an internal callback and we are expected to honor the current
2733 * state (e.g. this is used for setting the interface in promiscuous
2734 * mode when operating in hostap mode to do ACS).
2735 */
2736static void
2737bwn_update_promisc(struct ieee80211com *ic)
2738{
2739	struct bwn_softc *sc = ic->ic_softc;
2740	struct bwn_mac *mac = sc->sc_curmac;
2741
2742	BWN_LOCK(sc);
2743	mac = sc->sc_curmac;
2744	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2745		if (ic->ic_promisc > 0)
2746			sc->sc_filters |= BWN_MACCTL_PROMISC;
2747		else
2748			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2749		bwn_set_opmode(mac);
2750	}
2751	BWN_UNLOCK(sc);
2752}
2753
2754/*
2755 * Callback from the 802.11 layer to update WME parameters.
2756 */
2757static int
2758bwn_wme_update(struct ieee80211com *ic)
2759{
2760	struct bwn_softc *sc = ic->ic_softc;
2761	struct bwn_mac *mac = sc->sc_curmac;
2762	struct wmeParams *wmep;
2763	int i;
2764
2765	BWN_LOCK(sc);
2766	mac = sc->sc_curmac;
2767	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2768		bwn_mac_suspend(mac);
2769		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2770			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2771			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2772		}
2773		bwn_mac_enable(mac);
2774	}
2775	BWN_UNLOCK(sc);
2776	return (0);
2777}
2778
2779static void
2780bwn_scan_start(struct ieee80211com *ic)
2781{
2782	struct bwn_softc *sc = ic->ic_softc;
2783	struct bwn_mac *mac;
2784
2785	BWN_LOCK(sc);
2786	mac = sc->sc_curmac;
2787	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2788		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2789		bwn_set_opmode(mac);
2790		/* disable CFP update during scan */
2791		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2792	}
2793	BWN_UNLOCK(sc);
2794}
2795
2796static void
2797bwn_scan_end(struct ieee80211com *ic)
2798{
2799	struct bwn_softc *sc = ic->ic_softc;
2800	struct bwn_mac *mac;
2801
2802	BWN_LOCK(sc);
2803	mac = sc->sc_curmac;
2804	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2805		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2806		bwn_set_opmode(mac);
2807		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2808	}
2809	BWN_UNLOCK(sc);
2810}
2811
2812static void
2813bwn_set_channel(struct ieee80211com *ic)
2814{
2815	struct bwn_softc *sc = ic->ic_softc;
2816	struct bwn_mac *mac = sc->sc_curmac;
2817	struct bwn_phy *phy = &mac->mac_phy;
2818	int chan, error;
2819
2820	BWN_LOCK(sc);
2821
2822	error = bwn_switch_band(sc, ic->ic_curchan);
2823	if (error)
2824		goto fail;
2825	bwn_mac_suspend(mac);
2826	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2827	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2828	if (chan != phy->chan)
2829		bwn_switch_channel(mac, chan);
2830
2831	/* TX power level */
2832	if (ic->ic_curchan->ic_maxpower != 0 &&
2833	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2834		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2835		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2836		    BWN_TXPWR_IGNORE_TSSI);
2837	}
2838
2839	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2840	if (phy->set_antenna)
2841		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2842
2843	if (sc->sc_rf_enabled != phy->rf_on) {
2844		if (sc->sc_rf_enabled) {
2845			bwn_rf_turnon(mac);
2846			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2847				device_printf(sc->sc_dev,
2848				    "please turn on the RF switch\n");
2849		} else
2850			bwn_rf_turnoff(mac);
2851	}
2852
2853	bwn_mac_enable(mac);
2854
2855fail:
2856	/*
2857	 * Setup radio tap channel freq and flags
2858	 */
2859	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2860		htole16(ic->ic_curchan->ic_freq);
2861	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2862		htole16(ic->ic_curchan->ic_flags & 0xffff);
2863
2864	BWN_UNLOCK(sc);
2865}
2866
2867static struct ieee80211vap *
2868bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2869    enum ieee80211_opmode opmode, int flags,
2870    const uint8_t bssid[IEEE80211_ADDR_LEN],
2871    const uint8_t mac[IEEE80211_ADDR_LEN])
2872{
2873	struct ieee80211vap *vap;
2874	struct bwn_vap *bvp;
2875
2876	switch (opmode) {
2877	case IEEE80211_M_HOSTAP:
2878	case IEEE80211_M_MBSS:
2879	case IEEE80211_M_STA:
2880	case IEEE80211_M_WDS:
2881	case IEEE80211_M_MONITOR:
2882	case IEEE80211_M_IBSS:
2883	case IEEE80211_M_AHDEMO:
2884		break;
2885	default:
2886		return (NULL);
2887	}
2888
2889	bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
2890	vap = &bvp->bv_vap;
2891	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
2892	/* override with driver methods */
2893	bvp->bv_newstate = vap->iv_newstate;
2894	vap->iv_newstate = bwn_newstate;
2895
2896	/* override max aid so sta's cannot assoc when we're out of sta id's */
2897	vap->iv_max_aid = BWN_STAID_MAX;
2898
2899	ieee80211_ratectl_init(vap);
2900
2901	/* complete setup */
2902	ieee80211_vap_attach(vap, ieee80211_media_change,
2903	    ieee80211_media_status, mac);
2904	return (vap);
2905}
2906
2907static void
2908bwn_vap_delete(struct ieee80211vap *vap)
2909{
2910	struct bwn_vap *bvp = BWN_VAP(vap);
2911
2912	ieee80211_ratectl_deinit(vap);
2913	ieee80211_vap_detach(vap);
2914	free(bvp, M_80211_VAP);
2915}
2916
2917static int
2918bwn_init(struct bwn_softc *sc)
2919{
2920	struct bwn_mac *mac;
2921	int error;
2922
2923	BWN_ASSERT_LOCKED(sc);
2924
2925	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
2926	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
2927	sc->sc_filters = 0;
2928	bwn_wme_clear(sc);
2929	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
2930	sc->sc_rf_enabled = 1;
2931
2932	mac = sc->sc_curmac;
2933	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
2934		error = bwn_core_init(mac);
2935		if (error != 0)
2936			return (error);
2937	}
2938	if (mac->mac_status == BWN_MAC_STATUS_INITED)
2939		bwn_core_start(mac);
2940
2941	bwn_set_opmode(mac);
2942	bwn_set_pretbtt(mac);
2943	bwn_spu_setdelay(mac, 0);
2944	bwn_set_macaddr(mac);
2945
2946	sc->sc_flags |= BWN_FLAG_RUNNING;
2947	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
2948	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
2949
2950	return (0);
2951}
2952
2953static void
2954bwn_stop(struct bwn_softc *sc)
2955{
2956	struct bwn_mac *mac = sc->sc_curmac;
2957
2958	BWN_ASSERT_LOCKED(sc);
2959
2960	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
2961		/* XXX FIXME opmode not based on VAP */
2962		bwn_set_opmode(mac);
2963		bwn_set_macaddr(mac);
2964	}
2965
2966	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
2967		bwn_core_stop(mac);
2968
2969	callout_stop(&sc->sc_led_blink_ch);
2970	sc->sc_led_blinking = 0;
2971
2972	bwn_core_exit(mac);
2973	sc->sc_rf_enabled = 0;
2974
2975	sc->sc_flags &= ~BWN_FLAG_RUNNING;
2976}
2977
2978static void
2979bwn_wme_clear(struct bwn_softc *sc)
2980{
2981#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
2982	struct wmeParams *p;
2983	unsigned int i;
2984
2985	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
2986	    ("%s:%d: fail", __func__, __LINE__));
2987
2988	for (i = 0; i < N(sc->sc_wmeParams); i++) {
2989		p = &(sc->sc_wmeParams[i]);
2990
2991		switch (bwn_wme_shm_offsets[i]) {
2992		case BWN_WME_VOICE:
2993			p->wmep_txopLimit = 0;
2994			p->wmep_aifsn = 2;
2995			/* XXX FIXME: log2(cwmin) */
2996			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
2997			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
2998			break;
2999		case BWN_WME_VIDEO:
3000			p->wmep_txopLimit = 0;
3001			p->wmep_aifsn = 2;
3002			/* XXX FIXME: log2(cwmin) */
3003			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3004			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3005			break;
3006		case BWN_WME_BESTEFFORT:
3007			p->wmep_txopLimit = 0;
3008			p->wmep_aifsn = 3;
3009			/* XXX FIXME: log2(cwmin) */
3010			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3011			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3012			break;
3013		case BWN_WME_BACKGROUND:
3014			p->wmep_txopLimit = 0;
3015			p->wmep_aifsn = 7;
3016			/* XXX FIXME: log2(cwmin) */
3017			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3018			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3019			break;
3020		default:
3021			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3022		}
3023	}
3024}
3025
3026static int
3027bwn_core_init(struct bwn_mac *mac)
3028{
3029	struct bwn_softc *sc = mac->mac_sc;
3030	uint64_t hf;
3031	int error;
3032
3033	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3034	    ("%s:%d: fail", __func__, __LINE__));
3035
3036	siba_powerup(sc->sc_dev, 0);
3037	if (!siba_dev_isup(sc->sc_dev))
3038		bwn_reset_core(mac,
3039		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3040
3041	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3042	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3043	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3044	BWN_GETTIME(mac->mac_phy.nexttime);
3045	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3046	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3047	mac->mac_stats.link_noise = -95;
3048	mac->mac_reason_intr = 0;
3049	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3050	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3051#ifdef BWN_DEBUG
3052	if (sc->sc_debug & BWN_DEBUG_XMIT)
3053		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3054#endif
3055	mac->mac_suspended = 1;
3056	mac->mac_task_state = 0;
3057	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3058
3059	mac->mac_phy.init_pre(mac);
3060
3061	siba_pcicore_intr(sc->sc_dev);
3062
3063	siba_fix_imcfglobug(sc->sc_dev);
3064	bwn_bt_disable(mac);
3065	if (mac->mac_phy.prepare_hw) {
3066		error = mac->mac_phy.prepare_hw(mac);
3067		if (error)
3068			goto fail0;
3069	}
3070	error = bwn_chip_init(mac);
3071	if (error)
3072		goto fail0;
3073	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3074	    siba_get_revid(sc->sc_dev));
3075	hf = bwn_hf_read(mac);
3076	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3077		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3078		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3079			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3080		if (mac->mac_phy.rev == 1)
3081			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3082	}
3083	if (mac->mac_phy.rf_ver == 0x2050) {
3084		if (mac->mac_phy.rf_rev < 6)
3085			hf |= BWN_HF_FORCE_VCO_RECALC;
3086		if (mac->mac_phy.rf_rev == 6)
3087			hf |= BWN_HF_4318_TSSI;
3088	}
3089	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3090		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3091	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3092	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3093		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3094	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3095	bwn_hf_write(mac, hf);
3096
3097	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3098	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3099	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3100	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3101
3102	bwn_rate_init(mac);
3103	bwn_set_phytxctl(mac);
3104
3105	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3106	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3107	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3108
3109	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3110		bwn_pio_init(mac);
3111	else
3112		bwn_dma_init(mac);
3113	bwn_wme_init(mac);
3114	bwn_spu_setdelay(mac, 1);
3115	bwn_bt_enable(mac);
3116
3117	siba_powerup(sc->sc_dev,
3118	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3119	bwn_set_macaddr(mac);
3120	bwn_crypt_init(mac);
3121
3122	/* XXX LED initializatin */
3123
3124	mac->mac_status = BWN_MAC_STATUS_INITED;
3125
3126	return (error);
3127
3128fail0:
3129	siba_powerdown(sc->sc_dev);
3130	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3131	    ("%s:%d: fail", __func__, __LINE__));
3132	return (error);
3133}
3134
3135static void
3136bwn_core_start(struct bwn_mac *mac)
3137{
3138	struct bwn_softc *sc = mac->mac_sc;
3139	uint32_t tmp;
3140
3141	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3142	    ("%s:%d: fail", __func__, __LINE__));
3143
3144	if (siba_get_revid(sc->sc_dev) < 5)
3145		return;
3146
3147	while (1) {
3148		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3149		if (!(tmp & 0x00000001))
3150			break;
3151		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3152	}
3153
3154	bwn_mac_enable(mac);
3155	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3156	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3157
3158	mac->mac_status = BWN_MAC_STATUS_STARTED;
3159}
3160
3161static void
3162bwn_core_exit(struct bwn_mac *mac)
3163{
3164	struct bwn_softc *sc = mac->mac_sc;
3165	uint32_t macctl;
3166
3167	BWN_ASSERT_LOCKED(mac->mac_sc);
3168
3169	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3170	    ("%s:%d: fail", __func__, __LINE__));
3171
3172	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3173		return;
3174	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3175
3176	macctl = BWN_READ_4(mac, BWN_MACCTL);
3177	macctl &= ~BWN_MACCTL_MCODE_RUN;
3178	macctl |= BWN_MACCTL_MCODE_JMP0;
3179	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3180
3181	bwn_dma_stop(mac);
3182	bwn_pio_stop(mac);
3183	bwn_chip_exit(mac);
3184	mac->mac_phy.switch_analog(mac, 0);
3185	siba_dev_down(sc->sc_dev, 0);
3186	siba_powerdown(sc->sc_dev);
3187}
3188
3189static void
3190bwn_bt_disable(struct bwn_mac *mac)
3191{
3192	struct bwn_softc *sc = mac->mac_sc;
3193
3194	(void)sc;
3195	/* XXX do nothing yet */
3196}
3197
3198static int
3199bwn_chip_init(struct bwn_mac *mac)
3200{
3201	struct bwn_softc *sc = mac->mac_sc;
3202	struct bwn_phy *phy = &mac->mac_phy;
3203	uint32_t macctl;
3204	int error;
3205
3206	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3207	if (phy->gmode)
3208		macctl |= BWN_MACCTL_GMODE;
3209	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3210
3211	error = bwn_fw_fillinfo(mac);
3212	if (error)
3213		return (error);
3214	error = bwn_fw_loaducode(mac);
3215	if (error)
3216		return (error);
3217
3218	error = bwn_gpio_init(mac);
3219	if (error)
3220		return (error);
3221
3222	error = bwn_fw_loadinitvals(mac);
3223	if (error) {
3224		siba_gpio_set(sc->sc_dev, 0);
3225		return (error);
3226	}
3227	phy->switch_analog(mac, 1);
3228	error = bwn_phy_init(mac);
3229	if (error) {
3230		siba_gpio_set(sc->sc_dev, 0);
3231		return (error);
3232	}
3233	if (phy->set_im)
3234		phy->set_im(mac, BWN_IMMODE_NONE);
3235	if (phy->set_antenna)
3236		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3237	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3238
3239	if (phy->type == BWN_PHYTYPE_B)
3240		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3241	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3242	if (siba_get_revid(sc->sc_dev) < 5)
3243		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3244
3245	BWN_WRITE_4(mac, BWN_MACCTL,
3246	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3247	BWN_WRITE_4(mac, BWN_MACCTL,
3248	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3249	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3250
3251	bwn_set_opmode(mac);
3252	if (siba_get_revid(sc->sc_dev) < 3) {
3253		BWN_WRITE_2(mac, 0x060e, 0x0000);
3254		BWN_WRITE_2(mac, 0x0610, 0x8000);
3255		BWN_WRITE_2(mac, 0x0604, 0x0000);
3256		BWN_WRITE_2(mac, 0x0606, 0x0200);
3257	} else {
3258		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3259		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3260	}
3261	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3262	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3263	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3264	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3265	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3266	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3267	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3268	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3269	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3270	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3271	return (error);
3272}
3273
3274/* read hostflags */
3275static uint64_t
3276bwn_hf_read(struct bwn_mac *mac)
3277{
3278	uint64_t ret;
3279
3280	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3281	ret <<= 16;
3282	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3283	ret <<= 16;
3284	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3285	return (ret);
3286}
3287
3288static void
3289bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3290{
3291
3292	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3293	    (value & 0x00000000ffffull));
3294	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3295	    (value & 0x0000ffff0000ull) >> 16);
3296	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3297	    (value & 0xffff00000000ULL) >> 32);
3298}
3299
3300static void
3301bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3302{
3303
3304	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3305	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3306}
3307
3308static void
3309bwn_rate_init(struct bwn_mac *mac)
3310{
3311
3312	switch (mac->mac_phy.type) {
3313	case BWN_PHYTYPE_A:
3314	case BWN_PHYTYPE_G:
3315	case BWN_PHYTYPE_LP:
3316	case BWN_PHYTYPE_N:
3317		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3318		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3319		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3320		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3321		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3322		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3323		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3324		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3325			break;
3326		/* FALLTHROUGH */
3327	case BWN_PHYTYPE_B:
3328		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3329		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3330		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3331		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3332		break;
3333	default:
3334		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3335	}
3336}
3337
3338static void
3339bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3340{
3341	uint16_t offset;
3342
3343	if (ofdm) {
3344		offset = 0x480;
3345		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3346	} else {
3347		offset = 0x4c0;
3348		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3349	}
3350	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3351	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3352}
3353
3354static uint8_t
3355bwn_plcp_getcck(const uint8_t bitrate)
3356{
3357
3358	switch (bitrate) {
3359	case BWN_CCK_RATE_1MB:
3360		return (0x0a);
3361	case BWN_CCK_RATE_2MB:
3362		return (0x14);
3363	case BWN_CCK_RATE_5MB:
3364		return (0x37);
3365	case BWN_CCK_RATE_11MB:
3366		return (0x6e);
3367	}
3368	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3369	return (0);
3370}
3371
3372static uint8_t
3373bwn_plcp_getofdm(const uint8_t bitrate)
3374{
3375
3376	switch (bitrate) {
3377	case BWN_OFDM_RATE_6MB:
3378		return (0xb);
3379	case BWN_OFDM_RATE_9MB:
3380		return (0xf);
3381	case BWN_OFDM_RATE_12MB:
3382		return (0xa);
3383	case BWN_OFDM_RATE_18MB:
3384		return (0xe);
3385	case BWN_OFDM_RATE_24MB:
3386		return (0x9);
3387	case BWN_OFDM_RATE_36MB:
3388		return (0xd);
3389	case BWN_OFDM_RATE_48MB:
3390		return (0x8);
3391	case BWN_OFDM_RATE_54MB:
3392		return (0xc);
3393	}
3394	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3395	return (0);
3396}
3397
3398static void
3399bwn_set_phytxctl(struct bwn_mac *mac)
3400{
3401	uint16_t ctl;
3402
3403	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3404	    BWN_TX_PHY_TXPWR);
3405	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3406	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3407	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3408}
3409
3410static void
3411bwn_pio_init(struct bwn_mac *mac)
3412{
3413	struct bwn_pio *pio = &mac->mac_method.pio;
3414
3415	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3416	    & ~BWN_MACCTL_BIGENDIAN);
3417	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3418
3419	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3420	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3421	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3422	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3423	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3424	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3425}
3426
3427static void
3428bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3429    int index)
3430{
3431	struct bwn_pio_txpkt *tp;
3432	struct bwn_softc *sc = mac->mac_sc;
3433	unsigned int i;
3434
3435	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3436	tq->tq_index = index;
3437
3438	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3439	if (siba_get_revid(sc->sc_dev) >= 8)
3440		tq->tq_size = 1920;
3441	else {
3442		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3443		tq->tq_size -= 80;
3444	}
3445
3446	TAILQ_INIT(&tq->tq_pktlist);
3447	for (i = 0; i < N(tq->tq_pkts); i++) {
3448		tp = &(tq->tq_pkts[i]);
3449		tp->tp_index = i;
3450		tp->tp_queue = tq;
3451		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3452	}
3453}
3454
3455static uint16_t
3456bwn_pio_idx2base(struct bwn_mac *mac, int index)
3457{
3458	struct bwn_softc *sc = mac->mac_sc;
3459	static const uint16_t bases[] = {
3460		BWN_PIO_BASE0,
3461		BWN_PIO_BASE1,
3462		BWN_PIO_BASE2,
3463		BWN_PIO_BASE3,
3464		BWN_PIO_BASE4,
3465		BWN_PIO_BASE5,
3466		BWN_PIO_BASE6,
3467		BWN_PIO_BASE7,
3468	};
3469	static const uint16_t bases_rev11[] = {
3470		BWN_PIO11_BASE0,
3471		BWN_PIO11_BASE1,
3472		BWN_PIO11_BASE2,
3473		BWN_PIO11_BASE3,
3474		BWN_PIO11_BASE4,
3475		BWN_PIO11_BASE5,
3476	};
3477
3478	if (siba_get_revid(sc->sc_dev) >= 11) {
3479		if (index >= N(bases_rev11))
3480			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3481		return (bases_rev11[index]);
3482	}
3483	if (index >= N(bases))
3484		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3485	return (bases[index]);
3486}
3487
3488static void
3489bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3490    int index)
3491{
3492	struct bwn_softc *sc = mac->mac_sc;
3493
3494	prq->prq_mac = mac;
3495	prq->prq_rev = siba_get_revid(sc->sc_dev);
3496	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3497	bwn_dma_rxdirectfifo(mac, index, 1);
3498}
3499
3500static void
3501bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3502{
3503	if (tq == NULL)
3504		return;
3505	bwn_pio_cancel_tx_packets(tq);
3506}
3507
3508static void
3509bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3510{
3511
3512	bwn_destroy_pioqueue_tx(pio);
3513}
3514
3515static uint16_t
3516bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3517    uint16_t offset)
3518{
3519
3520	return (BWN_READ_2(mac, tq->tq_base + offset));
3521}
3522
3523static void
3524bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3525{
3526	uint32_t ctl;
3527	int type;
3528	uint16_t base;
3529
3530	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3531	base = bwn_dma_base(type, idx);
3532	if (type == BWN_DMA_64BIT) {
3533		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3534		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3535		if (enable)
3536			ctl |= BWN_DMA64_RXDIRECTFIFO;
3537		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3538	} else {
3539		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3540		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3541		if (enable)
3542			ctl |= BWN_DMA32_RXDIRECTFIFO;
3543		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3544	}
3545}
3546
3547static uint64_t
3548bwn_dma_mask(struct bwn_mac *mac)
3549{
3550	uint32_t tmp;
3551	uint16_t base;
3552
3553	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3554	if (tmp & SIBA_TGSHIGH_DMA64)
3555		return (BWN_DMA_BIT_MASK(64));
3556	base = bwn_dma_base(0, 0);
3557	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3558	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3559	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3560		return (BWN_DMA_BIT_MASK(32));
3561
3562	return (BWN_DMA_BIT_MASK(30));
3563}
3564
3565static int
3566bwn_dma_mask2type(uint64_t dmamask)
3567{
3568
3569	if (dmamask == BWN_DMA_BIT_MASK(30))
3570		return (BWN_DMA_30BIT);
3571	if (dmamask == BWN_DMA_BIT_MASK(32))
3572		return (BWN_DMA_32BIT);
3573	if (dmamask == BWN_DMA_BIT_MASK(64))
3574		return (BWN_DMA_64BIT);
3575	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3576	return (BWN_DMA_30BIT);
3577}
3578
3579static void
3580bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3581{
3582	struct bwn_pio_txpkt *tp;
3583	unsigned int i;
3584
3585	for (i = 0; i < N(tq->tq_pkts); i++) {
3586		tp = &(tq->tq_pkts[i]);
3587		if (tp->tp_m) {
3588			m_freem(tp->tp_m);
3589			tp->tp_m = NULL;
3590		}
3591	}
3592}
3593
3594static uint16_t
3595bwn_dma_base(int type, int controller_idx)
3596{
3597	static const uint16_t map64[] = {
3598		BWN_DMA64_BASE0,
3599		BWN_DMA64_BASE1,
3600		BWN_DMA64_BASE2,
3601		BWN_DMA64_BASE3,
3602		BWN_DMA64_BASE4,
3603		BWN_DMA64_BASE5,
3604	};
3605	static const uint16_t map32[] = {
3606		BWN_DMA32_BASE0,
3607		BWN_DMA32_BASE1,
3608		BWN_DMA32_BASE2,
3609		BWN_DMA32_BASE3,
3610		BWN_DMA32_BASE4,
3611		BWN_DMA32_BASE5,
3612	};
3613
3614	if (type == BWN_DMA_64BIT) {
3615		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3616		    ("%s:%d: fail", __func__, __LINE__));
3617		return (map64[controller_idx]);
3618	}
3619	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3620	    ("%s:%d: fail", __func__, __LINE__));
3621	return (map32[controller_idx]);
3622}
3623
3624static void
3625bwn_dma_init(struct bwn_mac *mac)
3626{
3627	struct bwn_dma *dma = &mac->mac_method.dma;
3628
3629	/* setup TX DMA channels. */
3630	bwn_dma_setup(dma->wme[WME_AC_BK]);
3631	bwn_dma_setup(dma->wme[WME_AC_BE]);
3632	bwn_dma_setup(dma->wme[WME_AC_VI]);
3633	bwn_dma_setup(dma->wme[WME_AC_VO]);
3634	bwn_dma_setup(dma->mcast);
3635	/* setup RX DMA channel. */
3636	bwn_dma_setup(dma->rx);
3637}
3638
3639static struct bwn_dma_ring *
3640bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3641    int for_tx, int type)
3642{
3643	struct bwn_dma *dma = &mac->mac_method.dma;
3644	struct bwn_dma_ring *dr;
3645	struct bwn_dmadesc_generic *desc;
3646	struct bwn_dmadesc_meta *mt;
3647	struct bwn_softc *sc = mac->mac_sc;
3648	int error, i;
3649
3650	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3651	if (dr == NULL)
3652		goto out;
3653	dr->dr_numslots = BWN_RXRING_SLOTS;
3654	if (for_tx)
3655		dr->dr_numslots = BWN_TXRING_SLOTS;
3656
3657	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3658	    M_DEVBUF, M_NOWAIT | M_ZERO);
3659	if (dr->dr_meta == NULL)
3660		goto fail0;
3661
3662	dr->dr_type = type;
3663	dr->dr_mac = mac;
3664	dr->dr_base = bwn_dma_base(type, controller_index);
3665	dr->dr_index = controller_index;
3666	if (type == BWN_DMA_64BIT) {
3667		dr->getdesc = bwn_dma_64_getdesc;
3668		dr->setdesc = bwn_dma_64_setdesc;
3669		dr->start_transfer = bwn_dma_64_start_transfer;
3670		dr->suspend = bwn_dma_64_suspend;
3671		dr->resume = bwn_dma_64_resume;
3672		dr->get_curslot = bwn_dma_64_get_curslot;
3673		dr->set_curslot = bwn_dma_64_set_curslot;
3674	} else {
3675		dr->getdesc = bwn_dma_32_getdesc;
3676		dr->setdesc = bwn_dma_32_setdesc;
3677		dr->start_transfer = bwn_dma_32_start_transfer;
3678		dr->suspend = bwn_dma_32_suspend;
3679		dr->resume = bwn_dma_32_resume;
3680		dr->get_curslot = bwn_dma_32_get_curslot;
3681		dr->set_curslot = bwn_dma_32_set_curslot;
3682	}
3683	if (for_tx) {
3684		dr->dr_tx = 1;
3685		dr->dr_curslot = -1;
3686	} else {
3687		if (dr->dr_index == 0) {
3688			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3689			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3690		} else
3691			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3692	}
3693
3694	error = bwn_dma_allocringmemory(dr);
3695	if (error)
3696		goto fail2;
3697
3698	if (for_tx) {
3699		/*
3700		 * Assumption: BWN_TXRING_SLOTS can be divided by
3701		 * BWN_TX_SLOTS_PER_FRAME
3702		 */
3703		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3704		    ("%s:%d: fail", __func__, __LINE__));
3705
3706		dr->dr_txhdr_cache =
3707		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3708			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3709		KASSERT(dr->dr_txhdr_cache != NULL,
3710		    ("%s:%d: fail", __func__, __LINE__));
3711
3712		/*
3713		 * Create TX ring DMA stuffs
3714		 */
3715		error = bus_dma_tag_create(dma->parent_dtag,
3716				    BWN_ALIGN, 0,
3717				    BUS_SPACE_MAXADDR,
3718				    BUS_SPACE_MAXADDR,
3719				    NULL, NULL,
3720				    BWN_HDRSIZE(mac),
3721				    1,
3722				    BUS_SPACE_MAXSIZE_32BIT,
3723				    0,
3724				    NULL, NULL,
3725				    &dr->dr_txring_dtag);
3726		if (error) {
3727			device_printf(sc->sc_dev,
3728			    "can't create TX ring DMA tag: TODO frees\n");
3729			goto fail1;
3730		}
3731
3732		for (i = 0; i < dr->dr_numslots; i += 2) {
3733			dr->getdesc(dr, i, &desc, &mt);
3734
3735			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3736			mt->mt_m = NULL;
3737			mt->mt_ni = NULL;
3738			mt->mt_islast = 0;
3739			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3740			    &mt->mt_dmap);
3741			if (error) {
3742				device_printf(sc->sc_dev,
3743				     "can't create RX buf DMA map\n");
3744				goto fail1;
3745			}
3746
3747			dr->getdesc(dr, i + 1, &desc, &mt);
3748
3749			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3750			mt->mt_m = NULL;
3751			mt->mt_ni = NULL;
3752			mt->mt_islast = 1;
3753			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3754			    &mt->mt_dmap);
3755			if (error) {
3756				device_printf(sc->sc_dev,
3757				     "can't create RX buf DMA map\n");
3758				goto fail1;
3759			}
3760		}
3761	} else {
3762		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3763		    &dr->dr_spare_dmap);
3764		if (error) {
3765			device_printf(sc->sc_dev,
3766			    "can't create RX buf DMA map\n");
3767			goto out;		/* XXX wrong! */
3768		}
3769
3770		for (i = 0; i < dr->dr_numslots; i++) {
3771			dr->getdesc(dr, i, &desc, &mt);
3772
3773			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3774			    &mt->mt_dmap);
3775			if (error) {
3776				device_printf(sc->sc_dev,
3777				    "can't create RX buf DMA map\n");
3778				goto out;	/* XXX wrong! */
3779			}
3780			error = bwn_dma_newbuf(dr, desc, mt, 1);
3781			if (error) {
3782				device_printf(sc->sc_dev,
3783				    "failed to allocate RX buf\n");
3784				goto out;	/* XXX wrong! */
3785			}
3786		}
3787
3788		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3789		    BUS_DMASYNC_PREWRITE);
3790
3791		dr->dr_usedslot = dr->dr_numslots;
3792	}
3793
3794      out:
3795	return (dr);
3796
3797fail2:
3798	free(dr->dr_txhdr_cache, M_DEVBUF);
3799fail1:
3800	free(dr->dr_meta, M_DEVBUF);
3801fail0:
3802	free(dr, M_DEVBUF);
3803	return (NULL);
3804}
3805
3806static void
3807bwn_dma_ringfree(struct bwn_dma_ring **dr)
3808{
3809
3810	if (dr == NULL)
3811		return;
3812
3813	bwn_dma_free_descbufs(*dr);
3814	bwn_dma_free_ringmemory(*dr);
3815
3816	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3817	free((*dr)->dr_meta, M_DEVBUF);
3818	free(*dr, M_DEVBUF);
3819
3820	*dr = NULL;
3821}
3822
3823static void
3824bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3825    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3826{
3827	struct bwn_dmadesc32 *desc;
3828
3829	*meta = &(dr->dr_meta[slot]);
3830	desc = dr->dr_ring_descbase;
3831	desc = &(desc[slot]);
3832
3833	*gdesc = (struct bwn_dmadesc_generic *)desc;
3834}
3835
3836static void
3837bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3838    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3839    int start, int end, int irq)
3840{
3841	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3842	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3843	uint32_t addr, addrext, ctl;
3844	int slot;
3845
3846	slot = (int)(&(desc->dma.dma32) - descbase);
3847	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3848	    ("%s:%d: fail", __func__, __LINE__));
3849
3850	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3851	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3852	addr |= siba_dma_translation(sc->sc_dev);
3853	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3854	if (slot == dr->dr_numslots - 1)
3855		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3856	if (start)
3857		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3858	if (end)
3859		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3860	if (irq)
3861		ctl |= BWN_DMA32_DCTL_IRQ;
3862	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3863	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3864
3865	desc->dma.dma32.control = htole32(ctl);
3866	desc->dma.dma32.address = htole32(addr);
3867}
3868
3869static void
3870bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3871{
3872
3873	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3874	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3875}
3876
3877static void
3878bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3879{
3880
3881	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3882	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3883}
3884
3885static void
3886bwn_dma_32_resume(struct bwn_dma_ring *dr)
3887{
3888
3889	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3890	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3891}
3892
3893static int
3894bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3895{
3896	uint32_t val;
3897
3898	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
3899	val &= BWN_DMA32_RXDPTR;
3900
3901	return (val / sizeof(struct bwn_dmadesc32));
3902}
3903
3904static void
3905bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
3906{
3907
3908	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
3909	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
3910}
3911
3912static void
3913bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
3914    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3915{
3916	struct bwn_dmadesc64 *desc;
3917
3918	*meta = &(dr->dr_meta[slot]);
3919	desc = dr->dr_ring_descbase;
3920	desc = &(desc[slot]);
3921
3922	*gdesc = (struct bwn_dmadesc_generic *)desc;
3923}
3924
3925static void
3926bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
3927    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3928    int start, int end, int irq)
3929{
3930	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
3931	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3932	int slot;
3933	uint32_t ctl0 = 0, ctl1 = 0;
3934	uint32_t addrlo, addrhi;
3935	uint32_t addrext;
3936
3937	slot = (int)(&(desc->dma.dma64) - descbase);
3938	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3939	    ("%s:%d: fail", __func__, __LINE__));
3940
3941	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
3942	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
3943	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
3944	    30;
3945	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
3946	if (slot == dr->dr_numslots - 1)
3947		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
3948	if (start)
3949		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
3950	if (end)
3951		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
3952	if (irq)
3953		ctl0 |= BWN_DMA64_DCTL0_IRQ;
3954	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
3955	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
3956	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
3957
3958	desc->dma.dma64.control0 = htole32(ctl0);
3959	desc->dma.dma64.control1 = htole32(ctl1);
3960	desc->dma.dma64.address_low = htole32(addrlo);
3961	desc->dma.dma64.address_high = htole32(addrhi);
3962}
3963
3964static void
3965bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
3966{
3967
3968	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
3969	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3970}
3971
3972static void
3973bwn_dma_64_suspend(struct bwn_dma_ring *dr)
3974{
3975
3976	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3977	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
3978}
3979
3980static void
3981bwn_dma_64_resume(struct bwn_dma_ring *dr)
3982{
3983
3984	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3985	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
3986}
3987
3988static int
3989bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
3990{
3991	uint32_t val;
3992
3993	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
3994	val &= BWN_DMA64_RXSTATDPTR;
3995
3996	return (val / sizeof(struct bwn_dmadesc64));
3997}
3998
3999static void
4000bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4001{
4002
4003	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4004	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4005}
4006
4007static int
4008bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4009{
4010	struct bwn_mac *mac = dr->dr_mac;
4011	struct bwn_dma *dma = &mac->mac_method.dma;
4012	struct bwn_softc *sc = mac->mac_sc;
4013	int error;
4014
4015	error = bus_dma_tag_create(dma->parent_dtag,
4016			    BWN_ALIGN, 0,
4017			    BUS_SPACE_MAXADDR,
4018			    BUS_SPACE_MAXADDR,
4019			    NULL, NULL,
4020			    BWN_DMA_RINGMEMSIZE,
4021			    1,
4022			    BUS_SPACE_MAXSIZE_32BIT,
4023			    0,
4024			    NULL, NULL,
4025			    &dr->dr_ring_dtag);
4026	if (error) {
4027		device_printf(sc->sc_dev,
4028		    "can't create TX ring DMA tag: TODO frees\n");
4029		return (-1);
4030	}
4031
4032	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4033	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4034	    &dr->dr_ring_dmap);
4035	if (error) {
4036		device_printf(sc->sc_dev,
4037		    "can't allocate DMA mem: TODO frees\n");
4038		return (-1);
4039	}
4040	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4041	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4042	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4043	if (error) {
4044		device_printf(sc->sc_dev,
4045		    "can't load DMA mem: TODO free\n");
4046		return (-1);
4047	}
4048
4049	return (0);
4050}
4051
4052static void
4053bwn_dma_setup(struct bwn_dma_ring *dr)
4054{
4055	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4056	uint64_t ring64;
4057	uint32_t addrext, ring32, value;
4058	uint32_t trans = siba_dma_translation(sc->sc_dev);
4059
4060	if (dr->dr_tx) {
4061		dr->dr_curslot = -1;
4062
4063		if (dr->dr_type == BWN_DMA_64BIT) {
4064			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4065			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4066			    >> 30;
4067			value = BWN_DMA64_TXENABLE;
4068			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4069			    & BWN_DMA64_TXADDREXT_MASK;
4070			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4071			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4072			    (ring64 & 0xffffffff));
4073			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4074			    ((ring64 >> 32) &
4075			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4076		} else {
4077			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4078			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4079			value = BWN_DMA32_TXENABLE;
4080			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4081			    & BWN_DMA32_TXADDREXT_MASK;
4082			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4083			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4084			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4085		}
4086		return;
4087	}
4088
4089	/*
4090	 * set for RX
4091	 */
4092	dr->dr_usedslot = dr->dr_numslots;
4093
4094	if (dr->dr_type == BWN_DMA_64BIT) {
4095		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4096		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4097		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4098		value |= BWN_DMA64_RXENABLE;
4099		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4100		    & BWN_DMA64_RXADDREXT_MASK;
4101		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4102		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4103		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4104		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4105		    | (trans << 1));
4106		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4107		    sizeof(struct bwn_dmadesc64));
4108	} else {
4109		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4110		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4111		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4112		value |= BWN_DMA32_RXENABLE;
4113		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4114		    & BWN_DMA32_RXADDREXT_MASK;
4115		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4116		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4117		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4118		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4119		    sizeof(struct bwn_dmadesc32));
4120	}
4121}
4122
4123static void
4124bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4125{
4126
4127	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4128	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4129	    dr->dr_ring_dmap);
4130}
4131
4132static void
4133bwn_dma_cleanup(struct bwn_dma_ring *dr)
4134{
4135
4136	if (dr->dr_tx) {
4137		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4138		if (dr->dr_type == BWN_DMA_64BIT) {
4139			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4140			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4141		} else
4142			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4143	} else {
4144		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4145		if (dr->dr_type == BWN_DMA_64BIT) {
4146			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4147			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4148		} else
4149			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4150	}
4151}
4152
4153static void
4154bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4155{
4156	struct bwn_dmadesc_generic *desc;
4157	struct bwn_dmadesc_meta *meta;
4158	struct bwn_mac *mac = dr->dr_mac;
4159	struct bwn_dma *dma = &mac->mac_method.dma;
4160	struct bwn_softc *sc = mac->mac_sc;
4161	int i;
4162
4163	if (!dr->dr_usedslot)
4164		return;
4165	for (i = 0; i < dr->dr_numslots; i++) {
4166		dr->getdesc(dr, i, &desc, &meta);
4167
4168		if (meta->mt_m == NULL) {
4169			if (!dr->dr_tx)
4170				device_printf(sc->sc_dev, "%s: not TX?\n",
4171				    __func__);
4172			continue;
4173		}
4174		if (dr->dr_tx) {
4175			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4176				bus_dmamap_unload(dr->dr_txring_dtag,
4177				    meta->mt_dmap);
4178			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4179				bus_dmamap_unload(dma->txbuf_dtag,
4180				    meta->mt_dmap);
4181		} else
4182			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4183		bwn_dma_free_descbuf(dr, meta);
4184	}
4185}
4186
4187static int
4188bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4189    int type)
4190{
4191	struct bwn_softc *sc = mac->mac_sc;
4192	uint32_t value;
4193	int i;
4194	uint16_t offset;
4195
4196	for (i = 0; i < 10; i++) {
4197		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4198		    BWN_DMA32_TXSTATUS;
4199		value = BWN_READ_4(mac, base + offset);
4200		if (type == BWN_DMA_64BIT) {
4201			value &= BWN_DMA64_TXSTAT;
4202			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4203			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4204			    value == BWN_DMA64_TXSTAT_STOPPED)
4205				break;
4206		} else {
4207			value &= BWN_DMA32_TXSTATE;
4208			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4209			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4210			    value == BWN_DMA32_TXSTAT_STOPPED)
4211				break;
4212		}
4213		DELAY(1000);
4214	}
4215	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4216	BWN_WRITE_4(mac, base + offset, 0);
4217	for (i = 0; i < 10; i++) {
4218		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4219						   BWN_DMA32_TXSTATUS;
4220		value = BWN_READ_4(mac, base + offset);
4221		if (type == BWN_DMA_64BIT) {
4222			value &= BWN_DMA64_TXSTAT;
4223			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4224				i = -1;
4225				break;
4226			}
4227		} else {
4228			value &= BWN_DMA32_TXSTATE;
4229			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4230				i = -1;
4231				break;
4232			}
4233		}
4234		DELAY(1000);
4235	}
4236	if (i != -1) {
4237		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4238		return (ENODEV);
4239	}
4240	DELAY(1000);
4241
4242	return (0);
4243}
4244
4245static int
4246bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4247    int type)
4248{
4249	struct bwn_softc *sc = mac->mac_sc;
4250	uint32_t value;
4251	int i;
4252	uint16_t offset;
4253
4254	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4255	BWN_WRITE_4(mac, base + offset, 0);
4256	for (i = 0; i < 10; i++) {
4257		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4258		    BWN_DMA32_RXSTATUS;
4259		value = BWN_READ_4(mac, base + offset);
4260		if (type == BWN_DMA_64BIT) {
4261			value &= BWN_DMA64_RXSTAT;
4262			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4263				i = -1;
4264				break;
4265			}
4266		} else {
4267			value &= BWN_DMA32_RXSTATE;
4268			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4269				i = -1;
4270				break;
4271			}
4272		}
4273		DELAY(1000);
4274	}
4275	if (i != -1) {
4276		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4277		return (ENODEV);
4278	}
4279
4280	return (0);
4281}
4282
4283static void
4284bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4285    struct bwn_dmadesc_meta *meta)
4286{
4287
4288	if (meta->mt_m != NULL) {
4289		m_freem(meta->mt_m);
4290		meta->mt_m = NULL;
4291	}
4292	if (meta->mt_ni != NULL) {
4293		ieee80211_free_node(meta->mt_ni);
4294		meta->mt_ni = NULL;
4295	}
4296}
4297
4298static void
4299bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4300{
4301	struct bwn_rxhdr4 *rxhdr;
4302	unsigned char *frame;
4303
4304	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4305	rxhdr->frame_len = 0;
4306
4307	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4308	    sizeof(struct bwn_plcp6) + 2,
4309	    ("%s:%d: fail", __func__, __LINE__));
4310	frame = mtod(m, char *) + dr->dr_frameoffset;
4311	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4312}
4313
4314static uint8_t
4315bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4316{
4317	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4318
4319	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4320	    == 0xff);
4321}
4322
4323static void
4324bwn_wme_init(struct bwn_mac *mac)
4325{
4326
4327	bwn_wme_load(mac);
4328
4329	/* enable WME support. */
4330	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4331	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4332	    BWN_IFSCTL_USE_EDCF);
4333}
4334
4335static void
4336bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4337{
4338	struct bwn_softc *sc = mac->mac_sc;
4339	struct ieee80211com *ic = &sc->sc_ic;
4340	uint16_t delay;	/* microsec */
4341
4342	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4343	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4344		delay = 500;
4345	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4346		delay = max(delay, (uint16_t)2400);
4347
4348	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4349}
4350
4351static void
4352bwn_bt_enable(struct bwn_mac *mac)
4353{
4354	struct bwn_softc *sc = mac->mac_sc;
4355	uint64_t hf;
4356
4357	if (bwn_bluetooth == 0)
4358		return;
4359	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4360		return;
4361	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4362		return;
4363
4364	hf = bwn_hf_read(mac);
4365	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4366		hf |= BWN_HF_BT_COEXISTALT;
4367	else
4368		hf |= BWN_HF_BT_COEXIST;
4369	bwn_hf_write(mac, hf);
4370}
4371
4372static void
4373bwn_set_macaddr(struct bwn_mac *mac)
4374{
4375
4376	bwn_mac_write_bssid(mac);
4377	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
4378	    mac->mac_sc->sc_ic.ic_macaddr);
4379}
4380
4381static void
4382bwn_clear_keys(struct bwn_mac *mac)
4383{
4384	int i;
4385
4386	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4387		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4388		    ("%s:%d: fail", __func__, __LINE__));
4389
4390		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4391		    NULL, BWN_SEC_KEYSIZE, NULL);
4392		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4393			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4394			    NULL, BWN_SEC_KEYSIZE, NULL);
4395		}
4396		mac->mac_key[i].keyconf = NULL;
4397	}
4398}
4399
4400static void
4401bwn_crypt_init(struct bwn_mac *mac)
4402{
4403	struct bwn_softc *sc = mac->mac_sc;
4404
4405	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4406	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4407	    ("%s:%d: fail", __func__, __LINE__));
4408	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4409	mac->mac_ktp *= 2;
4410	if (siba_get_revid(sc->sc_dev) >= 5)
4411		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4412	bwn_clear_keys(mac);
4413}
4414
4415static void
4416bwn_chip_exit(struct bwn_mac *mac)
4417{
4418	struct bwn_softc *sc = mac->mac_sc;
4419
4420	bwn_phy_exit(mac);
4421	siba_gpio_set(sc->sc_dev, 0);
4422}
4423
4424static int
4425bwn_fw_fillinfo(struct bwn_mac *mac)
4426{
4427	int error;
4428
4429	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4430	if (error == 0)
4431		return (0);
4432	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4433	if (error == 0)
4434		return (0);
4435	return (error);
4436}
4437
4438static int
4439bwn_gpio_init(struct bwn_mac *mac)
4440{
4441	struct bwn_softc *sc = mac->mac_sc;
4442	uint32_t mask = 0x1f, set = 0xf, value;
4443
4444	BWN_WRITE_4(mac, BWN_MACCTL,
4445	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4446	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4447	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4448
4449	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4450		mask |= 0x0060;
4451		set |= 0x0060;
4452	}
4453	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4454		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4455		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4456		mask |= 0x0200;
4457		set |= 0x0200;
4458	}
4459	if (siba_get_revid(sc->sc_dev) >= 2)
4460		mask |= 0x0010;
4461
4462	value = siba_gpio_get(sc->sc_dev);
4463	if (value == -1)
4464		return (0);
4465	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4466
4467	return (0);
4468}
4469
4470static int
4471bwn_fw_loadinitvals(struct bwn_mac *mac)
4472{
4473#define	GETFWOFFSET(fwp, offset)				\
4474	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4475	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4476	const struct bwn_fwhdr *hdr;
4477	struct bwn_fw *fw = &mac->mac_fw;
4478	int error;
4479
4480	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4481	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4482	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4483	if (error)
4484		return (error);
4485	if (fw->initvals_band.fw) {
4486		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4487		error = bwn_fwinitvals_write(mac,
4488		    GETFWOFFSET(fw->initvals_band, hdr_len),
4489		    be32toh(hdr->size),
4490		    fw->initvals_band.fw->datasize - hdr_len);
4491	}
4492	return (error);
4493#undef GETFWOFFSET
4494}
4495
4496static int
4497bwn_phy_init(struct bwn_mac *mac)
4498{
4499	struct bwn_softc *sc = mac->mac_sc;
4500	int error;
4501
4502	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4503	mac->mac_phy.rf_onoff(mac, 1);
4504	error = mac->mac_phy.init(mac);
4505	if (error) {
4506		device_printf(sc->sc_dev, "PHY init failed\n");
4507		goto fail0;
4508	}
4509	error = bwn_switch_channel(mac,
4510	    mac->mac_phy.get_default_chan(mac));
4511	if (error) {
4512		device_printf(sc->sc_dev,
4513		    "failed to switch default channel\n");
4514		goto fail1;
4515	}
4516	return (0);
4517fail1:
4518	if (mac->mac_phy.exit)
4519		mac->mac_phy.exit(mac);
4520fail0:
4521	mac->mac_phy.rf_onoff(mac, 0);
4522
4523	return (error);
4524}
4525
4526static void
4527bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4528{
4529	uint16_t ant;
4530	uint16_t tmp;
4531
4532	ant = bwn_ant2phy(antenna);
4533
4534	/* For ACK/CTS */
4535	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4536	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4537	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4538	/* For Probe Resposes */
4539	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4540	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4541	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4542}
4543
4544static void
4545bwn_set_opmode(struct bwn_mac *mac)
4546{
4547	struct bwn_softc *sc = mac->mac_sc;
4548	struct ieee80211com *ic = &sc->sc_ic;
4549	uint32_t ctl;
4550	uint16_t cfp_pretbtt;
4551
4552	ctl = BWN_READ_4(mac, BWN_MACCTL);
4553	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4554	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4555	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4556	ctl |= BWN_MACCTL_STA;
4557
4558	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4559	    ic->ic_opmode == IEEE80211_M_MBSS)
4560		ctl |= BWN_MACCTL_HOSTAP;
4561	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4562		ctl &= ~BWN_MACCTL_STA;
4563	ctl |= sc->sc_filters;
4564
4565	if (siba_get_revid(sc->sc_dev) <= 4)
4566		ctl |= BWN_MACCTL_PROMISC;
4567
4568	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4569
4570	cfp_pretbtt = 2;
4571	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4572		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4573		    siba_get_chiprev(sc->sc_dev) == 3)
4574			cfp_pretbtt = 100;
4575		else
4576			cfp_pretbtt = 50;
4577	}
4578	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4579}
4580
4581static int
4582bwn_dma_gettype(struct bwn_mac *mac)
4583{
4584	uint32_t tmp;
4585	uint16_t base;
4586
4587	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4588	if (tmp & SIBA_TGSHIGH_DMA64)
4589		return (BWN_DMA_64BIT);
4590	base = bwn_dma_base(0, 0);
4591	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4592	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4593	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4594		return (BWN_DMA_32BIT);
4595
4596	return (BWN_DMA_30BIT);
4597}
4598
4599static void
4600bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4601{
4602	if (!error) {
4603		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4604		*((bus_addr_t *)arg) = seg->ds_addr;
4605	}
4606}
4607
4608static void
4609bwn_phy_g_init_sub(struct bwn_mac *mac)
4610{
4611	struct bwn_phy *phy = &mac->mac_phy;
4612	struct bwn_phy_g *pg = &phy->phy_g;
4613	struct bwn_softc *sc = mac->mac_sc;
4614	uint16_t i, tmp;
4615
4616	if (phy->rev == 1)
4617		bwn_phy_init_b5(mac);
4618	else
4619		bwn_phy_init_b6(mac);
4620
4621	if (phy->rev >= 2 || phy->gmode)
4622		bwn_phy_init_a(mac);
4623
4624	if (phy->rev >= 2) {
4625		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4626		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4627	}
4628	if (phy->rev == 2) {
4629		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4630		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4631	}
4632	if (phy->rev > 5) {
4633		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4634		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4635	}
4636	if (phy->gmode || phy->rev >= 2) {
4637		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4638		tmp &= BWN_PHYVER_VERSION;
4639		if (tmp == 3 || tmp == 5) {
4640			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4641			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4642		}
4643		if (tmp == 5) {
4644			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4645			    0x1f00);
4646		}
4647	}
4648	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4649		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4650	if (phy->rf_rev == 8) {
4651		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4652		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4653	}
4654	if (BWN_HAS_LOOPBACK(phy))
4655		bwn_loopback_calcgain(mac);
4656
4657	if (phy->rf_rev != 8) {
4658		if (pg->pg_initval == 0xffff)
4659			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4660		else
4661			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4662	}
4663	bwn_lo_g_init(mac);
4664	if (BWN_HAS_TXMAG(phy)) {
4665		BWN_RF_WRITE(mac, 0x52,
4666		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4667		    | pg->pg_loctl.tx_bias |
4668		    pg->pg_loctl.tx_magn);
4669	} else {
4670		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4671	}
4672	if (phy->rev >= 6) {
4673		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4674		    (pg->pg_loctl.tx_bias << 12));
4675	}
4676	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4677		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4678	else
4679		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4680	if (phy->rev < 2)
4681		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4682	else
4683		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4684	if (phy->gmode || phy->rev >= 2) {
4685		bwn_lo_g_adjust(mac);
4686		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4687	}
4688
4689	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4690		for (i = 0; i < 64; i++) {
4691			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4692			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4693			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4694			    -32), 31));
4695		}
4696		bwn_nrssi_threshold(mac);
4697	} else if (phy->gmode || phy->rev >= 2) {
4698		if (pg->pg_nrssi[0] == -1000) {
4699			KASSERT(pg->pg_nrssi[1] == -1000,
4700			    ("%s:%d: fail", __func__, __LINE__));
4701			bwn_nrssi_slope_11g(mac);
4702		} else
4703			bwn_nrssi_threshold(mac);
4704	}
4705	if (phy->rf_rev == 8)
4706		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4707	bwn_phy_hwpctl_init(mac);
4708	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4709	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4710		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4711		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4712	}
4713}
4714
4715static uint8_t
4716bwn_has_hwpctl(struct bwn_mac *mac)
4717{
4718
4719	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4720		return (0);
4721	return (mac->mac_phy.use_hwpctl(mac));
4722}
4723
4724static void
4725bwn_phy_init_b5(struct bwn_mac *mac)
4726{
4727	struct bwn_phy *phy = &mac->mac_phy;
4728	struct bwn_phy_g *pg = &phy->phy_g;
4729	struct bwn_softc *sc = mac->mac_sc;
4730	uint16_t offset, value;
4731	uint8_t old_channel;
4732
4733	if (phy->analog == 1)
4734		BWN_RF_SET(mac, 0x007a, 0x0050);
4735	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4736	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4737		value = 0x2120;
4738		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4739			BWN_PHY_WRITE(mac, offset, value);
4740			value += 0x202;
4741		}
4742	}
4743	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4744	if (phy->rf_ver == 0x2050)
4745		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4746
4747	if (phy->gmode || phy->rev >= 2) {
4748		if (phy->rf_ver == 0x2050) {
4749			BWN_RF_SET(mac, 0x007a, 0x0020);
4750			BWN_RF_SET(mac, 0x0051, 0x0004);
4751		}
4752		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4753
4754		BWN_PHY_SET(mac, 0x0802, 0x0100);
4755		BWN_PHY_SET(mac, 0x042b, 0x2000);
4756
4757		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4758
4759		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4760		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4761		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4762	}
4763
4764	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4765		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4766
4767	if (phy->analog == 1) {
4768		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4769		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4770		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4771		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4772		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4773	} else
4774		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4775	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4776	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4777
4778	if (phy->analog == 1)
4779		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4780	else
4781		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4782
4783	if (phy->analog == 0)
4784		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4785
4786	old_channel = phy->chan;
4787	bwn_phy_g_switch_chan(mac, 7, 0);
4788
4789	if (phy->rf_ver != 0x2050) {
4790		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4791		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4792	}
4793
4794	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4795	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4796
4797	if (phy->rf_ver == 0x2050) {
4798		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4799		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4800	}
4801
4802	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4803	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4804	BWN_RF_SET(mac, 0x007a, 0x0007);
4805
4806	bwn_phy_g_switch_chan(mac, old_channel, 0);
4807	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4808	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4809	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4810
4811	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4812	    pg->pg_txctl);
4813
4814	if (phy->rf_ver == 0x2050)
4815		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4816
4817	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4818}
4819
4820static void
4821bwn_loopback_calcgain(struct bwn_mac *mac)
4822{
4823	struct bwn_phy *phy = &mac->mac_phy;
4824	struct bwn_phy_g *pg = &phy->phy_g;
4825	struct bwn_softc *sc = mac->mac_sc;
4826	uint16_t backup_phy[16] = { 0 };
4827	uint16_t backup_radio[3];
4828	uint16_t backup_bband;
4829	uint16_t i, j, loop_i_max;
4830	uint16_t trsw_rx;
4831	uint16_t loop1_outer_done, loop1_inner_done;
4832
4833	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4834	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4835	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4836	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4837	if (phy->rev != 1) {
4838		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4839		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4840	}
4841	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4842	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4843	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4844	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4845	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4846	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4847	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4848	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4849	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4850	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4851	backup_bband = pg->pg_bbatt.att;
4852	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4853	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4854	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4855
4856	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4857	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4858	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4859	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4860	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4861	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4862	if (phy->rev != 1) {
4863		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4864		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4865		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4866		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4867	}
4868	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4869	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4870	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4871	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4872
4873	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4874	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4875	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4876
4877	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4878	if (phy->rev != 1) {
4879		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4880		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4881	}
4882	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4883
4884	if (phy->rf_rev == 8)
4885		BWN_RF_WRITE(mac, 0x43, 0x000f);
4886	else {
4887		BWN_RF_WRITE(mac, 0x52, 0);
4888		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4889	}
4890	bwn_phy_g_set_bbatt(mac, 11);
4891
4892	if (phy->rev >= 3)
4893		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4894	else
4895		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4896	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
4897
4898	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
4899	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
4900
4901	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
4902	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
4903
4904	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
4905		if (phy->rev >= 7) {
4906			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
4907			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
4908		}
4909	}
4910	BWN_RF_MASK(mac, 0x7a, 0x00f7);
4911
4912	j = 0;
4913	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
4914	for (i = 0; i < loop_i_max; i++) {
4915		for (j = 0; j < 16; j++) {
4916			BWN_RF_WRITE(mac, 0x43, i);
4917			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
4918			    (j << 8));
4919			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4920			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4921			DELAY(20);
4922			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4923				goto done0;
4924		}
4925	}
4926done0:
4927	loop1_outer_done = i;
4928	loop1_inner_done = j;
4929	if (j >= 8) {
4930		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
4931		trsw_rx = 0x1b;
4932		for (j = j - 8; j < 16; j++) {
4933			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
4934			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4935			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4936			DELAY(20);
4937			trsw_rx -= 3;
4938			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4939				goto done1;
4940		}
4941	} else
4942		trsw_rx = 0x18;
4943done1:
4944
4945	if (phy->rev != 1) {
4946		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
4947		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
4948	}
4949	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
4950	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
4951	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
4952	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
4953	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
4954	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
4955	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
4956	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
4957	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
4958
4959	bwn_phy_g_set_bbatt(mac, backup_bband);
4960
4961	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
4962	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
4963	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
4964
4965	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
4966	DELAY(10);
4967	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
4968	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
4969	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
4970	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
4971
4972	pg->pg_max_lb_gain =
4973	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
4974	pg->pg_trsw_rx_gain = trsw_rx * 2;
4975}
4976
4977static uint16_t
4978bwn_rf_init_bcm2050(struct bwn_mac *mac)
4979{
4980	struct bwn_phy *phy = &mac->mac_phy;
4981	uint32_t tmp1 = 0, tmp2 = 0;
4982	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
4983	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
4984	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
4985	static const uint8_t rcc_table[] = {
4986		0x02, 0x03, 0x01, 0x0f,
4987		0x06, 0x07, 0x05, 0x0f,
4988		0x0a, 0x0b, 0x09, 0x0f,
4989		0x0e, 0x0f, 0x0d, 0x0f,
4990	};
4991
4992	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
4993	    rfoverval = rfover = cck3 = 0;
4994	radio0 = BWN_RF_READ(mac, 0x43);
4995	radio1 = BWN_RF_READ(mac, 0x51);
4996	radio2 = BWN_RF_READ(mac, 0x52);
4997	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4998	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4999	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5000	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5001
5002	if (phy->type == BWN_PHYTYPE_B) {
5003		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5004		reg0 = BWN_READ_2(mac, 0x3ec);
5005
5006		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5007		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5008	} else if (phy->gmode || phy->rev >= 2) {
5009		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5010		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5011		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5012		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5013		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5014		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5015
5016		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5017		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5018		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5019		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5020		if (BWN_HAS_LOOPBACK(phy)) {
5021			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5022			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5023			if (phy->rev >= 3)
5024				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5025			else
5026				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5027			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5028		}
5029
5030		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5031		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5032			BWN_LPD(0, 1, 1)));
5033		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5034		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5035	}
5036	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5037
5038	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5039	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5040	reg1 = BWN_READ_2(mac, 0x3e6);
5041	reg2 = BWN_READ_2(mac, 0x3f4);
5042
5043	if (phy->analog == 0)
5044		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5045	else {
5046		if (phy->analog >= 2)
5047			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5048		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5049		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5050	}
5051
5052	reg = BWN_RF_READ(mac, 0x60);
5053	index = (reg & 0x001e) >> 1;
5054	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5055
5056	if (phy->type == BWN_PHYTYPE_B)
5057		BWN_RF_WRITE(mac, 0x78, 0x26);
5058	if (phy->gmode || phy->rev >= 2) {
5059		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5060		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5061			BWN_LPD(0, 1, 1)));
5062	}
5063	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5064	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5065	if (phy->gmode || phy->rev >= 2) {
5066		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5067		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5068			BWN_LPD(0, 0, 1)));
5069	}
5070	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5071	BWN_RF_SET(mac, 0x51, 0x0004);
5072	if (phy->rf_rev == 8)
5073		BWN_RF_WRITE(mac, 0x43, 0x1f);
5074	else {
5075		BWN_RF_WRITE(mac, 0x52, 0);
5076		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5077	}
5078	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5079
5080	for (i = 0; i < 16; i++) {
5081		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5082		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5083		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5084		if (phy->gmode || phy->rev >= 2) {
5085			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5086			    bwn_rf_2050_rfoverval(mac,
5087				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5088		}
5089		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5090		DELAY(10);
5091		if (phy->gmode || phy->rev >= 2) {
5092			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5093			    bwn_rf_2050_rfoverval(mac,
5094				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5095		}
5096		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5097		DELAY(10);
5098		if (phy->gmode || phy->rev >= 2) {
5099			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5100			    bwn_rf_2050_rfoverval(mac,
5101				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5102		}
5103		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5104		DELAY(20);
5105		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5106		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5107		if (phy->gmode || phy->rev >= 2) {
5108			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5109			    bwn_rf_2050_rfoverval(mac,
5110				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5111		}
5112		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5113	}
5114	DELAY(10);
5115
5116	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5117	tmp1++;
5118	tmp1 >>= 9;
5119
5120	for (i = 0; i < 16; i++) {
5121		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5122		BWN_RF_WRITE(mac, 0x78, radio78);
5123		DELAY(10);
5124		for (j = 0; j < 16; j++) {
5125			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5126			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5127			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5128			if (phy->gmode || phy->rev >= 2) {
5129				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5130				    bwn_rf_2050_rfoverval(mac,
5131					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5132			}
5133			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5134			DELAY(10);
5135			if (phy->gmode || phy->rev >= 2) {
5136				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5137				    bwn_rf_2050_rfoverval(mac,
5138					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5139			}
5140			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5141			DELAY(10);
5142			if (phy->gmode || phy->rev >= 2) {
5143				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5144				    bwn_rf_2050_rfoverval(mac,
5145					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5146			}
5147			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5148			DELAY(10);
5149			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5150			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5151			if (phy->gmode || phy->rev >= 2) {
5152				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5153				    bwn_rf_2050_rfoverval(mac,
5154					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5155			}
5156			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5157		}
5158		tmp2++;
5159		tmp2 >>= 8;
5160		if (tmp1 < tmp2)
5161			break;
5162	}
5163
5164	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5165	BWN_RF_WRITE(mac, 0x51, radio1);
5166	BWN_RF_WRITE(mac, 0x52, radio2);
5167	BWN_RF_WRITE(mac, 0x43, radio0);
5168	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5169	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5170	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5171	BWN_WRITE_2(mac, 0x3e6, reg1);
5172	if (phy->analog != 0)
5173		BWN_WRITE_2(mac, 0x3f4, reg2);
5174	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5175	bwn_spu_workaround(mac, phy->chan);
5176	if (phy->type == BWN_PHYTYPE_B) {
5177		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5178		BWN_WRITE_2(mac, 0x3ec, reg0);
5179	} else if (phy->gmode) {
5180		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5181			    BWN_READ_2(mac, BWN_PHY_RADIO)
5182			    & 0x7fff);
5183		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5184		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5185		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5186		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5187			      analogoverval);
5188		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5189		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5190		if (BWN_HAS_LOOPBACK(phy)) {
5191			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5192			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5193		}
5194	}
5195
5196	return ((i > 15) ? radio78 : rcc);
5197}
5198
5199static void
5200bwn_phy_init_b6(struct bwn_mac *mac)
5201{
5202	struct bwn_phy *phy = &mac->mac_phy;
5203	struct bwn_phy_g *pg = &phy->phy_g;
5204	struct bwn_softc *sc = mac->mac_sc;
5205	uint16_t offset, val;
5206	uint8_t old_channel;
5207
5208	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5209	    ("%s:%d: fail", __func__, __LINE__));
5210
5211	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5212	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5213	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5214		BWN_RF_WRITE(mac, 0x51, 0x37);
5215		BWN_RF_WRITE(mac, 0x52, 0x70);
5216		BWN_RF_WRITE(mac, 0x53, 0xb3);
5217		BWN_RF_WRITE(mac, 0x54, 0x9b);
5218		BWN_RF_WRITE(mac, 0x5a, 0x88);
5219		BWN_RF_WRITE(mac, 0x5b, 0x88);
5220		BWN_RF_WRITE(mac, 0x5d, 0x88);
5221		BWN_RF_WRITE(mac, 0x5e, 0x88);
5222		BWN_RF_WRITE(mac, 0x7d, 0x88);
5223		bwn_hf_write(mac,
5224		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5225	}
5226	if (phy->rf_rev == 8) {
5227		BWN_RF_WRITE(mac, 0x51, 0);
5228		BWN_RF_WRITE(mac, 0x52, 0x40);
5229		BWN_RF_WRITE(mac, 0x53, 0xb7);
5230		BWN_RF_WRITE(mac, 0x54, 0x98);
5231		BWN_RF_WRITE(mac, 0x5a, 0x88);
5232		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5233		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5234		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5235			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5236			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5237		} else {
5238			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5239			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5240		}
5241		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5242		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5243		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5244		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5245	}
5246	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5247		BWN_PHY_WRITE(mac, offset, val);
5248		val -= 0x0202;
5249	}
5250	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5251		BWN_PHY_WRITE(mac, offset, val);
5252		val -= 0x0202;
5253	}
5254	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5255		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5256		val += 0x0202;
5257	}
5258	if (phy->type == BWN_PHYTYPE_G) {
5259		BWN_RF_SET(mac, 0x007a, 0x0020);
5260		BWN_RF_SET(mac, 0x0051, 0x0004);
5261		BWN_PHY_SET(mac, 0x0802, 0x0100);
5262		BWN_PHY_SET(mac, 0x042b, 0x2000);
5263		BWN_PHY_WRITE(mac, 0x5b, 0);
5264		BWN_PHY_WRITE(mac, 0x5c, 0);
5265	}
5266
5267	old_channel = phy->chan;
5268	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5269
5270	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5271	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5272	DELAY(40);
5273	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5274		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5275		BWN_RF_WRITE(mac, 0x50, 0x20);
5276	}
5277	if (phy->rf_rev <= 2) {
5278		BWN_RF_WRITE(mac, 0x7c, 0x20);
5279		BWN_RF_WRITE(mac, 0x5a, 0x70);
5280		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5281		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5282	}
5283	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5284
5285	bwn_phy_g_switch_chan(mac, old_channel, 0);
5286
5287	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5288	if (phy->rf_rev >= 6)
5289		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5290	else
5291		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5292	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5293	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5294	    pg->pg_txctl);
5295	if (phy->rf_rev <= 5)
5296		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5297	if (phy->rf_rev <= 2)
5298		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5299
5300	if (phy->analog == 4) {
5301		BWN_WRITE_2(mac, 0x3e4, 9);
5302		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5303	} else
5304		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5305	if (phy->type == BWN_PHYTYPE_B)
5306		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5307	else if (phy->type == BWN_PHYTYPE_G)
5308		BWN_WRITE_2(mac, 0x03e6, 0x0);
5309}
5310
5311static void
5312bwn_phy_init_a(struct bwn_mac *mac)
5313{
5314	struct bwn_phy *phy = &mac->mac_phy;
5315	struct bwn_softc *sc = mac->mac_sc;
5316
5317	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5318	    ("%s:%d: fail", __func__, __LINE__));
5319
5320	if (phy->rev >= 6) {
5321		if (phy->type == BWN_PHYTYPE_A)
5322			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5323		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5324			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5325		else
5326			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5327	}
5328
5329	bwn_wa_init(mac);
5330
5331	if (phy->type == BWN_PHYTYPE_G &&
5332	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5333		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5334}
5335
5336static void
5337bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5338{
5339	int i;
5340
5341	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5342		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5343}
5344
5345static void
5346bwn_wa_agc(struct bwn_mac *mac)
5347{
5348	struct bwn_phy *phy = &mac->mac_phy;
5349
5350	if (phy->rev == 1) {
5351		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5352		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5353		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5354		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5355		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5356		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5357		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5358		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5359		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5360	} else {
5361		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5362		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5363		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5364		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5365	}
5366
5367	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5368	    0x5700);
5369	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5370	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5371	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5372	BWN_RF_SET(mac, 0x7a, 0x0008);
5373	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5374	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5375	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5376	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5377	if (phy->rev == 1)
5378		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5379	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5380	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5381	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5382	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5383	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5384	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5385	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5386	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5387	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5388	if (phy->rev == 1) {
5389		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5390		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5391	} else {
5392		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5393		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5394		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5395		if (phy->rev >= 6) {
5396			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5397			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5398			    (uint16_t)~0xf000, 0x3000);
5399		}
5400	}
5401	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5402	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5403	if (phy->rev == 1) {
5404		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5405		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5406		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5407		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5408		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5409		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5410		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5411		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5412	} else {
5413		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5414		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5415		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5416		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5417	}
5418	if (phy->rev >= 6) {
5419		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5420		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5421	}
5422	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5423}
5424
5425static void
5426bwn_wa_grev1(struct bwn_mac *mac)
5427{
5428	struct bwn_phy *phy = &mac->mac_phy;
5429	int i;
5430	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5431	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5432	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5433
5434	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5435
5436	/* init CRSTHRES and ANTDWELL */
5437	if (phy->rev == 1) {
5438		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5439	} else if (phy->rev == 2) {
5440		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5441		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5442		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5443	} else {
5444		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5445		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5446		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5447		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5448	}
5449	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5450	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5451	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5452
5453	/* XXX support PHY-A??? */
5454	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5455		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5456		    bwn_tab_finefreqg[i]);
5457
5458	/* XXX support PHY-A??? */
5459	if (phy->rev == 1)
5460		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5461			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5462			    bwn_tab_noise_g1[i]);
5463	else
5464		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5465			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5466			    bwn_tab_noise_g2[i]);
5467
5468
5469	for (i = 0; i < N(bwn_tab_rotor); i++)
5470		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5471		    bwn_tab_rotor[i]);
5472
5473	/* XXX support PHY-A??? */
5474	if (phy->rev >= 6) {
5475		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5476		    BWN_PHY_ENCORE_EN)
5477			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5478		else
5479			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5480	} else
5481		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5482
5483	for (i = 0; i < N(bwn_tab_retard); i++)
5484		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5485		    bwn_tab_retard[i]);
5486
5487	if (phy->rev == 1) {
5488		for (i = 0; i < 16; i++)
5489			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5490			    i, 0x0020);
5491	} else {
5492		for (i = 0; i < 32; i++)
5493			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5494	}
5495
5496	bwn_wa_agc(mac);
5497}
5498
5499static void
5500bwn_wa_grev26789(struct bwn_mac *mac)
5501{
5502	struct bwn_phy *phy = &mac->mac_phy;
5503	int i;
5504	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5505	uint16_t ofdmrev;
5506
5507	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5508
5509	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5510
5511	/* init CRSTHRES and ANTDWELL */
5512	if (phy->rev == 1)
5513		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5514	else if (phy->rev == 2) {
5515		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5516		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5517		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5518	} else {
5519		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5520		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5521		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5522		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5523	}
5524
5525	for (i = 0; i < 64; i++)
5526		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5527
5528	/* XXX support PHY-A??? */
5529	if (phy->rev == 1)
5530		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5531			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5532			    bwn_tab_noise_g1[i]);
5533	else
5534		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5535			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5536			    bwn_tab_noise_g2[i]);
5537
5538	/* XXX support PHY-A??? */
5539	if (phy->rev >= 6) {
5540		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5541		    BWN_PHY_ENCORE_EN)
5542			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5543		else
5544			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5545	} else
5546		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5547
5548	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5549		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5550		    bwn_tab_sigmasqr2[i]);
5551
5552	if (phy->rev == 1) {
5553		for (i = 0; i < 16; i++)
5554			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5555			    0x0020);
5556	} else {
5557		for (i = 0; i < 32; i++)
5558			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5559	}
5560
5561	bwn_wa_agc(mac);
5562
5563	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5564	if (ofdmrev > 2) {
5565		if (phy->type == BWN_PHYTYPE_A)
5566			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5567		else
5568			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5569	} else {
5570		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5571		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5572		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5573	}
5574
5575	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5576	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5577}
5578
5579static void
5580bwn_wa_init(struct bwn_mac *mac)
5581{
5582	struct bwn_phy *phy = &mac->mac_phy;
5583	struct bwn_softc *sc = mac->mac_sc;
5584
5585	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5586
5587	switch (phy->rev) {
5588	case 1:
5589		bwn_wa_grev1(mac);
5590		break;
5591	case 2:
5592	case 6:
5593	case 7:
5594	case 8:
5595	case 9:
5596		bwn_wa_grev26789(mac);
5597		break;
5598	default:
5599		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5600	}
5601
5602	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5603	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5604	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5605		if (phy->rev < 2) {
5606			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5607			    0x0002);
5608			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5609			    0x0001);
5610		} else {
5611			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5612			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5613			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5614			     BWN_BFL_EXTLNA) &&
5615			    (phy->rev >= 7)) {
5616				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5617				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5618				    0x0020, 0x0001);
5619				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5620				    0x0021, 0x0001);
5621				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5622				    0x0022, 0x0001);
5623				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5624				    0x0023, 0x0000);
5625				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5626				    0x0000, 0x0000);
5627				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5628				    0x0003, 0x0002);
5629			}
5630		}
5631	}
5632	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5633		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5634		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5635	}
5636
5637	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5638	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5639}
5640
5641static void
5642bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5643    uint16_t value)
5644{
5645	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5646	uint16_t addr;
5647
5648	addr = table + offset;
5649	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5650	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5651		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5652		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5653	}
5654	pg->pg_ofdmtab_addr = addr;
5655	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5656}
5657
5658static void
5659bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5660    uint32_t value)
5661{
5662	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5663	uint16_t addr;
5664
5665	addr = table + offset;
5666	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5667	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5668		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5669		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5670	}
5671	pg->pg_ofdmtab_addr = addr;
5672
5673	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5674	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5675}
5676
5677static void
5678bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5679    uint16_t value)
5680{
5681
5682	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5683	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5684}
5685
5686static void
5687bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5688{
5689	struct bwn_phy *phy = &mac->mac_phy;
5690	struct bwn_softc *sc = mac->mac_sc;
5691	unsigned int i, max_loop;
5692	uint16_t value;
5693	uint32_t buffer[5] = {
5694		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5695	};
5696
5697	if (ofdm) {
5698		max_loop = 0x1e;
5699		buffer[0] = 0x000201cc;
5700	} else {
5701		max_loop = 0xfa;
5702		buffer[0] = 0x000b846e;
5703	}
5704
5705	BWN_ASSERT_LOCKED(mac->mac_sc);
5706
5707	for (i = 0; i < 5; i++)
5708		bwn_ram_write(mac, i * 4, buffer[i]);
5709
5710	BWN_WRITE_2(mac, 0x0568, 0x0000);
5711	BWN_WRITE_2(mac, 0x07c0,
5712	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5713	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5714	BWN_WRITE_2(mac, 0x050c, value);
5715	if (phy->type == BWN_PHYTYPE_LP)
5716		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5717	BWN_WRITE_2(mac, 0x0508, 0x0000);
5718	BWN_WRITE_2(mac, 0x050a, 0x0000);
5719	BWN_WRITE_2(mac, 0x054c, 0x0000);
5720	BWN_WRITE_2(mac, 0x056a, 0x0014);
5721	BWN_WRITE_2(mac, 0x0568, 0x0826);
5722	BWN_WRITE_2(mac, 0x0500, 0x0000);
5723	if (phy->type == BWN_PHYTYPE_LP)
5724		BWN_WRITE_2(mac, 0x0502, 0x0050);
5725	else
5726		BWN_WRITE_2(mac, 0x0502, 0x0030);
5727
5728	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5729		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5730	for (i = 0x00; i < max_loop; i++) {
5731		value = BWN_READ_2(mac, 0x050e);
5732		if (value & 0x0080)
5733			break;
5734		DELAY(10);
5735	}
5736	for (i = 0x00; i < 0x0a; i++) {
5737		value = BWN_READ_2(mac, 0x050e);
5738		if (value & 0x0400)
5739			break;
5740		DELAY(10);
5741	}
5742	for (i = 0x00; i < 0x19; i++) {
5743		value = BWN_READ_2(mac, 0x0690);
5744		if (!(value & 0x0100))
5745			break;
5746		DELAY(10);
5747	}
5748	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5749		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5750}
5751
5752static void
5753bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5754{
5755	uint32_t macctl;
5756
5757	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5758
5759	macctl = BWN_READ_4(mac, BWN_MACCTL);
5760	if (macctl & BWN_MACCTL_BIGENDIAN)
5761		printf("TODO: need swap\n");
5762
5763	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5764	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5765	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5766}
5767
5768static void
5769bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5770{
5771	uint16_t value;
5772
5773	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5774	    ("%s:%d: fail", __func__, __LINE__));
5775
5776	value = (uint8_t) (ctl->q);
5777	value |= ((uint8_t) (ctl->i)) << 8;
5778	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5779}
5780
5781static uint16_t
5782bwn_lo_calcfeed(struct bwn_mac *mac,
5783    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5784{
5785	struct bwn_phy *phy = &mac->mac_phy;
5786	struct bwn_softc *sc = mac->mac_sc;
5787	uint16_t rfover;
5788	uint16_t feedthrough;
5789
5790	if (phy->gmode) {
5791		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5792		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5793
5794		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5795		    ("%s:%d: fail", __func__, __LINE__));
5796		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5797		    ("%s:%d: fail", __func__, __LINE__));
5798
5799		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5800
5801		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5802		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5803		    phy->rev > 6)
5804			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5805
5806		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5807		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5808		DELAY(10);
5809		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5810		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5811		DELAY(10);
5812		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5813		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5814		DELAY(10);
5815		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5816	} else {
5817		pga |= BWN_PHY_PGACTL_UNKNOWN;
5818		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5819		DELAY(10);
5820		pga |= BWN_PHY_PGACTL_LOWBANDW;
5821		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5822		DELAY(10);
5823		pga |= BWN_PHY_PGACTL_LPF;
5824		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5825	}
5826	DELAY(21);
5827	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5828
5829	return (feedthrough);
5830}
5831
5832static uint16_t
5833bwn_lo_txctl_regtable(struct bwn_mac *mac,
5834    uint16_t *value, uint16_t *pad_mix_gain)
5835{
5836	struct bwn_phy *phy = &mac->mac_phy;
5837	uint16_t reg, v, padmix;
5838
5839	if (phy->type == BWN_PHYTYPE_B) {
5840		v = 0x30;
5841		if (phy->rf_rev <= 5) {
5842			reg = 0x43;
5843			padmix = 0;
5844		} else {
5845			reg = 0x52;
5846			padmix = 5;
5847		}
5848	} else {
5849		if (phy->rev >= 2 && phy->rf_rev == 8) {
5850			reg = 0x43;
5851			v = 0x10;
5852			padmix = 2;
5853		} else {
5854			reg = 0x52;
5855			v = 0x30;
5856			padmix = 5;
5857		}
5858	}
5859	if (value)
5860		*value = v;
5861	if (pad_mix_gain)
5862		*pad_mix_gain = padmix;
5863
5864	return (reg);
5865}
5866
5867static void
5868bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5869{
5870	struct bwn_phy *phy = &mac->mac_phy;
5871	struct bwn_phy_g *pg = &phy->phy_g;
5872	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5873	uint16_t reg, mask;
5874	uint16_t trsw_rx, pga;
5875	uint16_t rf_pctl_reg;
5876
5877	static const uint8_t tx_bias_values[] = {
5878		0x09, 0x08, 0x0a, 0x01, 0x00,
5879		0x02, 0x05, 0x04, 0x06,
5880	};
5881	static const uint8_t tx_magn_values[] = {
5882		0x70, 0x40,
5883	};
5884
5885	if (!BWN_HAS_LOOPBACK(phy)) {
5886		rf_pctl_reg = 6;
5887		trsw_rx = 2;
5888		pga = 0;
5889	} else {
5890		int lb_gain;
5891
5892		trsw_rx = 0;
5893		lb_gain = pg->pg_max_lb_gain / 2;
5894		if (lb_gain > 10) {
5895			rf_pctl_reg = 0;
5896			pga = abs(10 - lb_gain) / 6;
5897			pga = MIN(MAX(pga, 0), 15);
5898		} else {
5899			int cmp_val;
5900			int tmp;
5901
5902			pga = 0;
5903			cmp_val = 0x24;
5904			if ((phy->rev >= 2) &&
5905			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
5906				cmp_val = 0x3c;
5907			tmp = lb_gain;
5908			if ((10 - lb_gain) < cmp_val)
5909				tmp = (10 - lb_gain);
5910			if (tmp < 0)
5911				tmp += 6;
5912			else
5913				tmp += 3;
5914			cmp_val /= 4;
5915			tmp /= 4;
5916			if (tmp >= cmp_val)
5917				rf_pctl_reg = cmp_val;
5918			else
5919				rf_pctl_reg = tmp;
5920		}
5921	}
5922	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
5923	bwn_phy_g_set_bbatt(mac, 2);
5924
5925	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
5926	mask = ~mask;
5927	BWN_RF_MASK(mac, reg, mask);
5928
5929	if (BWN_HAS_TXMAG(phy)) {
5930		int i, j;
5931		int feedthrough;
5932		int min_feedth = 0xffff;
5933		uint8_t tx_magn, tx_bias;
5934
5935		for (i = 0; i < N(tx_magn_values); i++) {
5936			tx_magn = tx_magn_values[i];
5937			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
5938			for (j = 0; j < N(tx_bias_values); j++) {
5939				tx_bias = tx_bias_values[j];
5940				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
5941				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
5942				    trsw_rx);
5943				if (feedthrough < min_feedth) {
5944					lo->tx_bias = tx_bias;
5945					lo->tx_magn = tx_magn;
5946					min_feedth = feedthrough;
5947				}
5948				if (lo->tx_bias == 0)
5949					break;
5950			}
5951			BWN_RF_WRITE(mac, 0x52,
5952					  (BWN_RF_READ(mac, 0x52)
5953					   & 0xff00) | lo->tx_bias | lo->
5954					  tx_magn);
5955		}
5956	} else {
5957		lo->tx_magn = 0;
5958		lo->tx_bias = 0;
5959		BWN_RF_MASK(mac, 0x52, 0xfff0);
5960	}
5961
5962	BWN_GETTIME(lo->txctl_measured_time);
5963}
5964
5965static void
5966bwn_lo_get_powervector(struct bwn_mac *mac)
5967{
5968	struct bwn_phy *phy = &mac->mac_phy;
5969	struct bwn_phy_g *pg = &phy->phy_g;
5970	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5971	int i;
5972	uint64_t tmp;
5973	uint64_t power_vector = 0;
5974
5975	for (i = 0; i < 8; i += 2) {
5976		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
5977		power_vector |= (tmp << (i * 8));
5978		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
5979	}
5980	if (power_vector)
5981		lo->power_vector = power_vector;
5982
5983	BWN_GETTIME(lo->pwr_vec_read_time);
5984}
5985
5986static void
5987bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
5988    int use_trsw_rx)
5989{
5990	struct bwn_phy *phy = &mac->mac_phy;
5991	struct bwn_phy_g *pg = &phy->phy_g;
5992	uint16_t tmp;
5993
5994	if (max_rx_gain < 0)
5995		max_rx_gain = 0;
5996
5997	if (BWN_HAS_LOOPBACK(phy)) {
5998		int trsw_rx = 0;
5999		int trsw_rx_gain;
6000
6001		if (use_trsw_rx) {
6002			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6003			if (max_rx_gain >= trsw_rx_gain) {
6004				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6005				trsw_rx = 0x20;
6006			}
6007		} else
6008			trsw_rx_gain = max_rx_gain;
6009		if (trsw_rx_gain < 9) {
6010			pg->pg_lna_lod_gain = 0;
6011		} else {
6012			pg->pg_lna_lod_gain = 1;
6013			trsw_rx_gain -= 8;
6014		}
6015		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6016		pg->pg_pga_gain = trsw_rx_gain / 3;
6017		if (pg->pg_pga_gain >= 5) {
6018			pg->pg_pga_gain -= 5;
6019			pg->pg_lna_gain = 2;
6020		} else
6021			pg->pg_lna_gain = 0;
6022	} else {
6023		pg->pg_lna_gain = 0;
6024		pg->pg_trsw_rx_gain = 0x20;
6025		if (max_rx_gain >= 0x14) {
6026			pg->pg_lna_lod_gain = 1;
6027			pg->pg_pga_gain = 2;
6028		} else if (max_rx_gain >= 0x12) {
6029			pg->pg_lna_lod_gain = 1;
6030			pg->pg_pga_gain = 1;
6031		} else if (max_rx_gain >= 0xf) {
6032			pg->pg_lna_lod_gain = 1;
6033			pg->pg_pga_gain = 0;
6034		} else {
6035			pg->pg_lna_lod_gain = 0;
6036			pg->pg_pga_gain = 0;
6037		}
6038	}
6039
6040	tmp = BWN_RF_READ(mac, 0x7a);
6041	if (pg->pg_lna_lod_gain == 0)
6042		tmp &= ~0x0008;
6043	else
6044		tmp |= 0x0008;
6045	BWN_RF_WRITE(mac, 0x7a, tmp);
6046}
6047
6048static void
6049bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6050{
6051	struct bwn_phy *phy = &mac->mac_phy;
6052	struct bwn_phy_g *pg = &phy->phy_g;
6053	struct bwn_softc *sc = mac->mac_sc;
6054	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6055	struct timespec ts;
6056	uint16_t tmp;
6057
6058	if (bwn_has_hwpctl(mac)) {
6059		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6060		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6061		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6062		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6063		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6064
6065		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6066		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6067		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6068		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6069	}
6070	if (phy->type == BWN_PHYTYPE_B &&
6071	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6072		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6073		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6074	}
6075	if (phy->rev >= 2) {
6076		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6077		sav->phy_analogoverval =
6078		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6079		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6080		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6081		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6082		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6083		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6084
6085		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6086		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6087		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6088		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6089		if (phy->type == BWN_PHYTYPE_G) {
6090			if ((phy->rev >= 7) &&
6091			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6092			     BWN_BFL_EXTLNA)) {
6093				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6094			} else {
6095				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6096			}
6097		} else {
6098			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6099		}
6100		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6101	}
6102	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6103	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6104	sav->rf0 = BWN_RF_READ(mac, 0x43);
6105	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6106	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6107	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6108	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6109	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6110
6111	if (!BWN_HAS_TXMAG(phy)) {
6112		sav->rf2 = BWN_RF_READ(mac, 0x52);
6113		sav->rf2 &= 0x00f0;
6114	}
6115	if (phy->type == BWN_PHYTYPE_B) {
6116		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6117		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6118		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6119		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6120	} else {
6121		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6122			    | 0x8000);
6123	}
6124	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6125		    & 0xf000);
6126
6127	tmp =
6128	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6129	BWN_PHY_WRITE(mac, tmp, 0x007f);
6130
6131	tmp = sav->phy_syncctl;
6132	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6133	tmp = sav->rf1;
6134	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6135
6136	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6137	if (phy->type == BWN_PHYTYPE_G ||
6138	    (phy->type == BWN_PHYTYPE_B &&
6139	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6140		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6141	} else
6142		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6143	if (phy->rev >= 2)
6144		bwn_dummy_transmission(mac, 0, 1);
6145	bwn_phy_g_switch_chan(mac, 6, 0);
6146	BWN_RF_READ(mac, 0x51);
6147	if (phy->type == BWN_PHYTYPE_G)
6148		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6149
6150	nanouptime(&ts);
6151	if (time_before(lo->txctl_measured_time,
6152	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6153		bwn_lo_measure_txctl_values(mac);
6154
6155	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6156		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6157	else {
6158		if (phy->type == BWN_PHYTYPE_B)
6159			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6160		else
6161			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6162	}
6163}
6164
6165static void
6166bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6167{
6168	struct bwn_phy *phy = &mac->mac_phy;
6169	struct bwn_phy_g *pg = &phy->phy_g;
6170	uint16_t tmp;
6171
6172	if (phy->rev >= 2) {
6173		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6174		tmp = (pg->pg_pga_gain << 8);
6175		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6176		DELAY(5);
6177		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6178		DELAY(2);
6179		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6180	} else {
6181		tmp = (pg->pg_pga_gain | 0xefa0);
6182		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6183	}
6184	if (phy->type == BWN_PHYTYPE_G) {
6185		if (phy->rev >= 3)
6186			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6187		else
6188			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6189		if (phy->rev >= 2)
6190			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6191		else
6192			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6193	}
6194	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6195	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6196	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6197	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6198	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6199	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6200	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6201	if (!BWN_HAS_TXMAG(phy)) {
6202		tmp = sav->rf2;
6203		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6204	}
6205	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6206	if (phy->type == BWN_PHYTYPE_B &&
6207	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6208		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6209		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6210	}
6211	if (phy->rev >= 2) {
6212		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6213		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6214			      sav->phy_analogoverval);
6215		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6216		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6217		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6218		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6219		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6220	}
6221	if (bwn_has_hwpctl(mac)) {
6222		tmp = (sav->phy_lomask & 0xbfff);
6223		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6224		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6225		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6226		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6227		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6228	}
6229	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6230}
6231
6232static int
6233bwn_lo_probe_loctl(struct bwn_mac *mac,
6234    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6235{
6236	struct bwn_phy *phy = &mac->mac_phy;
6237	struct bwn_phy_g *pg = &phy->phy_g;
6238	struct bwn_loctl orig, test;
6239	struct bwn_loctl prev = { -100, -100 };
6240	static const struct bwn_loctl modifiers[] = {
6241		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6242		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6243	};
6244	int begin, end, lower = 0, i;
6245	uint16_t feedth;
6246
6247	if (d->curstate == 0) {
6248		begin = 1;
6249		end = 8;
6250	} else if (d->curstate % 2 == 0) {
6251		begin = d->curstate - 1;
6252		end = d->curstate + 1;
6253	} else {
6254		begin = d->curstate - 2;
6255		end = d->curstate + 2;
6256	}
6257	if (begin < 1)
6258		begin += 8;
6259	if (end > 8)
6260		end -= 8;
6261
6262	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6263	i = begin;
6264	d->curstate = i;
6265	while (1) {
6266		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6267		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6268		test.i += modifiers[i - 1].i * d->multipler;
6269		test.q += modifiers[i - 1].q * d->multipler;
6270		if ((test.i != prev.i || test.q != prev.q) &&
6271		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6272			bwn_lo_write(mac, &test);
6273			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6274			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6275			if (feedth < d->feedth) {
6276				memcpy(probe, &test,
6277				    sizeof(struct bwn_loctl));
6278				lower = 1;
6279				d->feedth = feedth;
6280				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6281					break;
6282			}
6283		}
6284		memcpy(&prev, &test, sizeof(prev));
6285		if (i == end)
6286			break;
6287		if (i == 8)
6288			i = 1;
6289		else
6290			i++;
6291		d->curstate = i;
6292	}
6293
6294	return (lower);
6295}
6296
6297static void
6298bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6299{
6300	struct bwn_phy *phy = &mac->mac_phy;
6301	struct bwn_phy_g *pg = &phy->phy_g;
6302	struct bwn_lo_g_sm d;
6303	struct bwn_loctl probe;
6304	int lower, repeat, cnt = 0;
6305	uint16_t feedth;
6306
6307	d.nmeasure = 0;
6308	d.multipler = 1;
6309	if (BWN_HAS_LOOPBACK(phy))
6310		d.multipler = 3;
6311
6312	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6313	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6314
6315	do {
6316		bwn_lo_write(mac, &d.loctl);
6317		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6318		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6319		if (feedth < 0x258) {
6320			if (feedth >= 0x12c)
6321				*rxgain += 6;
6322			else
6323				*rxgain += 3;
6324			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6325			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6326		}
6327		d.feedth = feedth;
6328		d.curstate = 0;
6329		do {
6330			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6331			    ("%s:%d: fail", __func__, __LINE__));
6332			memcpy(&probe, &d.loctl,
6333			       sizeof(struct bwn_loctl));
6334			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6335			if (!lower)
6336				break;
6337			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6338				break;
6339			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6340			d.nmeasure++;
6341		} while (d.nmeasure < 24);
6342		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6343
6344		if (BWN_HAS_LOOPBACK(phy)) {
6345			if (d.feedth > 0x1194)
6346				*rxgain -= 6;
6347			else if (d.feedth < 0x5dc)
6348				*rxgain += 3;
6349			if (cnt == 0) {
6350				if (d.feedth <= 0x5dc) {
6351					d.multipler = 1;
6352					cnt++;
6353				} else
6354					d.multipler = 2;
6355			} else if (cnt == 2)
6356				d.multipler = 1;
6357		}
6358		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6359	} while (++cnt < repeat);
6360}
6361
6362static struct bwn_lo_calib *
6363bwn_lo_calibset(struct bwn_mac *mac,
6364    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6365{
6366	struct bwn_phy *phy = &mac->mac_phy;
6367	struct bwn_phy_g *pg = &phy->phy_g;
6368	struct bwn_loctl loctl = { 0, 0 };
6369	struct bwn_lo_calib *cal;
6370	struct bwn_lo_g_value sval = { 0 };
6371	int rxgain;
6372	uint16_t pad, reg, value;
6373
6374	sval.old_channel = phy->chan;
6375	bwn_mac_suspend(mac);
6376	bwn_lo_save(mac, &sval);
6377
6378	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6379	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6380	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6381
6382	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6383	if (rfatt->padmix)
6384		rxgain -= pad;
6385	if (BWN_HAS_LOOPBACK(phy))
6386		rxgain += pg->pg_max_lb_gain;
6387	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6388	bwn_phy_g_set_bbatt(mac, bbatt->att);
6389	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6390
6391	bwn_lo_restore(mac, &sval);
6392	bwn_mac_enable(mac);
6393
6394	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6395	if (!cal) {
6396		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6397		return (NULL);
6398	}
6399	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6400	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6401	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6402
6403	BWN_GETTIME(cal->calib_time);
6404
6405	return (cal);
6406}
6407
6408static struct bwn_lo_calib *
6409bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6410    const struct bwn_rfatt *rfatt)
6411{
6412	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6413	struct bwn_lo_calib *c;
6414
6415	TAILQ_FOREACH(c, &lo->calib_list, list) {
6416		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6417			continue;
6418		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6419			continue;
6420		return (c);
6421	}
6422
6423	c = bwn_lo_calibset(mac, bbatt, rfatt);
6424	if (!c)
6425		return (NULL);
6426	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6427
6428	return (c);
6429}
6430
6431static void
6432bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6433{
6434	struct bwn_phy *phy = &mac->mac_phy;
6435	struct bwn_phy_g *pg = &phy->phy_g;
6436	struct bwn_softc *sc = mac->mac_sc;
6437	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6438	const struct bwn_rfatt *rfatt;
6439	const struct bwn_bbatt *bbatt;
6440	uint64_t pvector;
6441	int i;
6442	int rf_offset, bb_offset;
6443	uint8_t changed = 0;
6444
6445	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6446	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6447	    ("%s:%d: fail", __func__, __LINE__));
6448
6449	pvector = lo->power_vector;
6450	if (!update && !pvector)
6451		return;
6452
6453	bwn_mac_suspend(mac);
6454
6455	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6456		struct bwn_lo_calib *cal;
6457		int idx;
6458		uint16_t val;
6459
6460		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6461			continue;
6462		bb_offset = i / lo->rfatt.len;
6463		rf_offset = i % lo->rfatt.len;
6464		bbatt = &(lo->bbatt.array[bb_offset]);
6465		rfatt = &(lo->rfatt.array[rf_offset]);
6466
6467		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6468		if (!cal) {
6469			device_printf(sc->sc_dev, "LO: Could not "
6470			    "calibrate DC table entry\n");
6471			continue;
6472		}
6473		val = (uint8_t)(cal->ctl.q);
6474		val |= ((uint8_t)(cal->ctl.i)) << 4;
6475		free(cal, M_DEVBUF);
6476
6477		idx = i / 2;
6478		if (i % 2)
6479			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6480			    | ((val & 0x00ff) << 8);
6481		else
6482			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6483			    | (val & 0x00ff);
6484		changed = 1;
6485	}
6486	if (changed) {
6487		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6488			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6489	}
6490	bwn_mac_enable(mac);
6491}
6492
6493static void
6494bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6495{
6496
6497	if (!rf->padmix)
6498		return;
6499	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6500		rf->att = 4;
6501}
6502
6503static void
6504bwn_lo_g_adjust(struct bwn_mac *mac)
6505{
6506	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6507	struct bwn_lo_calib *cal;
6508	struct bwn_rfatt rf;
6509
6510	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6511	bwn_lo_fixup_rfatt(&rf);
6512
6513	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6514	if (!cal)
6515		return;
6516	bwn_lo_write(mac, &cal->ctl);
6517}
6518
6519static void
6520bwn_lo_g_init(struct bwn_mac *mac)
6521{
6522
6523	if (!bwn_has_hwpctl(mac))
6524		return;
6525
6526	bwn_lo_get_powervector(mac);
6527	bwn_phy_g_dc_lookup_init(mac, 1);
6528}
6529
6530static void
6531bwn_mac_suspend(struct bwn_mac *mac)
6532{
6533	struct bwn_softc *sc = mac->mac_sc;
6534	int i;
6535	uint32_t tmp;
6536
6537	KASSERT(mac->mac_suspended >= 0,
6538	    ("%s:%d: fail", __func__, __LINE__));
6539
6540	if (mac->mac_suspended == 0) {
6541		bwn_psctl(mac, BWN_PS_AWAKE);
6542		BWN_WRITE_4(mac, BWN_MACCTL,
6543			    BWN_READ_4(mac, BWN_MACCTL)
6544			    & ~BWN_MACCTL_ON);
6545		BWN_READ_4(mac, BWN_MACCTL);
6546		for (i = 35; i; i--) {
6547			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6548			if (tmp & BWN_INTR_MAC_SUSPENDED)
6549				goto out;
6550			DELAY(10);
6551		}
6552		for (i = 40; i; i--) {
6553			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6554			if (tmp & BWN_INTR_MAC_SUSPENDED)
6555				goto out;
6556			DELAY(1000);
6557		}
6558		device_printf(sc->sc_dev, "MAC suspend failed\n");
6559	}
6560out:
6561	mac->mac_suspended++;
6562}
6563
6564static void
6565bwn_mac_enable(struct bwn_mac *mac)
6566{
6567	struct bwn_softc *sc = mac->mac_sc;
6568	uint16_t state;
6569
6570	state = bwn_shm_read_2(mac, BWN_SHARED,
6571	    BWN_SHARED_UCODESTAT);
6572	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6573	    state != BWN_SHARED_UCODESTAT_SLEEP)
6574		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6575
6576	mac->mac_suspended--;
6577	KASSERT(mac->mac_suspended >= 0,
6578	    ("%s:%d: fail", __func__, __LINE__));
6579	if (mac->mac_suspended == 0) {
6580		BWN_WRITE_4(mac, BWN_MACCTL,
6581		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6582		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6583		BWN_READ_4(mac, BWN_MACCTL);
6584		BWN_READ_4(mac, BWN_INTR_REASON);
6585		bwn_psctl(mac, 0);
6586	}
6587}
6588
6589static void
6590bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6591{
6592	struct bwn_softc *sc = mac->mac_sc;
6593	int i;
6594	uint16_t ucstat;
6595
6596	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6597	    ("%s:%d: fail", __func__, __LINE__));
6598	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6599	    ("%s:%d: fail", __func__, __LINE__));
6600
6601	/* XXX forcibly awake and hwps-off */
6602
6603	BWN_WRITE_4(mac, BWN_MACCTL,
6604	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6605	    ~BWN_MACCTL_HWPS);
6606	BWN_READ_4(mac, BWN_MACCTL);
6607	if (siba_get_revid(sc->sc_dev) >= 5) {
6608		for (i = 0; i < 100; i++) {
6609			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6610			    BWN_SHARED_UCODESTAT);
6611			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6612				break;
6613			DELAY(10);
6614		}
6615	}
6616}
6617
6618static int16_t
6619bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6620{
6621
6622	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6623	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6624}
6625
6626static void
6627bwn_nrssi_threshold(struct bwn_mac *mac)
6628{
6629	struct bwn_phy *phy = &mac->mac_phy;
6630	struct bwn_phy_g *pg = &phy->phy_g;
6631	struct bwn_softc *sc = mac->mac_sc;
6632	int32_t a, b;
6633	int16_t tmp16;
6634	uint16_t tmpu16;
6635
6636	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6637
6638	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6639		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6640			a = 0x13;
6641			b = 0x12;
6642		} else {
6643			a = 0xe;
6644			b = 0x11;
6645		}
6646
6647		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6648		a += (pg->pg_nrssi[0] << 6);
6649		a += (a < 32) ? 31 : 32;
6650		a = a >> 6;
6651		a = MIN(MAX(a, -31), 31);
6652
6653		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6654		b += (pg->pg_nrssi[0] << 6);
6655		if (b < 32)
6656			b += 31;
6657		else
6658			b += 32;
6659		b = b >> 6;
6660		b = MIN(MAX(b, -31), 31);
6661
6662		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6663		tmpu16 |= ((uint32_t)b & 0x0000003f);
6664		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6665		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6666		return;
6667	}
6668
6669	tmp16 = bwn_nrssi_read(mac, 0x20);
6670	if (tmp16 >= 0x20)
6671		tmp16 -= 0x40;
6672	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6673}
6674
6675static void
6676bwn_nrssi_slope_11g(struct bwn_mac *mac)
6677{
6678#define	SAVE_RF_MAX		3
6679#define	SAVE_PHY_COMM_MAX	4
6680#define	SAVE_PHY3_MAX		8
6681	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6682		{ 0x7a, 0x52, 0x43 };
6683	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6684		{ 0x15, 0x5a, 0x59, 0x58 };
6685	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6686		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6687		0x0801, 0x0060, 0x0014, 0x0478
6688	};
6689	struct bwn_phy *phy = &mac->mac_phy;
6690	struct bwn_phy_g *pg = &phy->phy_g;
6691	int32_t i, tmp32, phy3_idx = 0;
6692	uint16_t delta, tmp;
6693	uint16_t save_rf[SAVE_RF_MAX];
6694	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6695	uint16_t save_phy3[SAVE_PHY3_MAX];
6696	uint16_t ant_div, phy0, chan_ex;
6697	int16_t nrssi0, nrssi1;
6698
6699	KASSERT(phy->type == BWN_PHYTYPE_G,
6700	    ("%s:%d: fail", __func__, __LINE__));
6701
6702	if (phy->rf_rev >= 9)
6703		return;
6704	if (phy->rf_rev == 8)
6705		bwn_nrssi_offset(mac);
6706
6707	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6708	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6709
6710	/*
6711	 * Save RF/PHY registers for later restoration
6712	 */
6713	ant_div = BWN_READ_2(mac, 0x03e2);
6714	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6715	for (i = 0; i < SAVE_RF_MAX; ++i)
6716		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6717	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6718		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6719
6720	phy0 = BWN_READ_2(mac, BWN_PHY0);
6721	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6722	if (phy->rev >= 3) {
6723		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6724			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6725		BWN_PHY_WRITE(mac, 0x002e, 0);
6726		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6727		switch (phy->rev) {
6728		case 4:
6729		case 6:
6730		case 7:
6731			BWN_PHY_SET(mac, 0x0478, 0x0100);
6732			BWN_PHY_SET(mac, 0x0801, 0x0040);
6733			break;
6734		case 3:
6735		case 5:
6736			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6737			break;
6738		}
6739		BWN_PHY_SET(mac, 0x0060, 0x0040);
6740		BWN_PHY_SET(mac, 0x0014, 0x0200);
6741	}
6742	/*
6743	 * Calculate nrssi0
6744	 */
6745	BWN_RF_SET(mac, 0x007a, 0x0070);
6746	bwn_set_all_gains(mac, 0, 8, 0);
6747	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6748	if (phy->rev >= 2) {
6749		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6750		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6751	}
6752	BWN_RF_SET(mac, 0x007a, 0x0080);
6753	DELAY(20);
6754
6755	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6756	if (nrssi0 >= 0x0020)
6757		nrssi0 -= 0x0040;
6758
6759	/*
6760	 * Calculate nrssi1
6761	 */
6762	BWN_RF_MASK(mac, 0x007a, 0x007f);
6763	if (phy->rev >= 2)
6764		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6765
6766	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6767	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6768	BWN_RF_SET(mac, 0x007a, 0x000f);
6769	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6770	if (phy->rev >= 2) {
6771		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6772		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6773	}
6774
6775	bwn_set_all_gains(mac, 3, 0, 1);
6776	if (phy->rf_rev == 8) {
6777		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6778	} else {
6779		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6780		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6781		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6782		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6783	}
6784	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6785	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6786	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6787	DELAY(20);
6788	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6789
6790	/*
6791	 * Install calculated narrow RSSI values
6792	 */
6793	if (nrssi1 >= 0x0020)
6794		nrssi1 -= 0x0040;
6795	if (nrssi0 == nrssi1)
6796		pg->pg_nrssi_slope = 0x00010000;
6797	else
6798		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6799	if (nrssi0 >= -4) {
6800		pg->pg_nrssi[0] = nrssi1;
6801		pg->pg_nrssi[1] = nrssi0;
6802	}
6803
6804	/*
6805	 * Restore saved RF/PHY registers
6806	 */
6807	if (phy->rev >= 3) {
6808		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6809			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6810			    save_phy3[phy3_idx]);
6811		}
6812	}
6813	if (phy->rev >= 2) {
6814		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6815		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6816	}
6817
6818	for (i = 0; i < SAVE_RF_MAX; ++i)
6819		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6820
6821	BWN_WRITE_2(mac, 0x03e2, ant_div);
6822	BWN_WRITE_2(mac, 0x03e6, phy0);
6823	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6824
6825	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6826		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6827
6828	bwn_spu_workaround(mac, phy->chan);
6829	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6830	bwn_set_original_gains(mac);
6831	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6832	if (phy->rev >= 3) {
6833		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6834			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6835			    save_phy3[phy3_idx]);
6836		}
6837	}
6838
6839	delta = 0x1f - pg->pg_nrssi[0];
6840	for (i = 0; i < 64; i++) {
6841		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6842		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6843		pg->pg_nrssi_lt[i] = tmp32;
6844	}
6845
6846	bwn_nrssi_threshold(mac);
6847#undef SAVE_RF_MAX
6848#undef SAVE_PHY_COMM_MAX
6849#undef SAVE_PHY3_MAX
6850}
6851
6852static void
6853bwn_nrssi_offset(struct bwn_mac *mac)
6854{
6855#define	SAVE_RF_MAX		2
6856#define	SAVE_PHY_COMM_MAX	10
6857#define	SAVE_PHY6_MAX		8
6858	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6859		{ 0x7a, 0x43 };
6860	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6861		0x0001, 0x0811, 0x0812, 0x0814,
6862		0x0815, 0x005a, 0x0059, 0x0058,
6863		0x000a, 0x0003
6864	};
6865	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6866		0x002e, 0x002f, 0x080f, 0x0810,
6867		0x0801, 0x0060, 0x0014, 0x0478
6868	};
6869	struct bwn_phy *phy = &mac->mac_phy;
6870	int i, phy6_idx = 0;
6871	uint16_t save_rf[SAVE_RF_MAX];
6872	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6873	uint16_t save_phy6[SAVE_PHY6_MAX];
6874	int16_t nrssi;
6875	uint16_t saved = 0xffff;
6876
6877	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6878		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6879	for (i = 0; i < SAVE_RF_MAX; ++i)
6880		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6881
6882	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6883	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6884	BWN_PHY_SET(mac, 0x0811, 0x000c);
6885	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6886	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6887	if (phy->rev >= 6) {
6888		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6889			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6890
6891		BWN_PHY_WRITE(mac, 0x002e, 0);
6892		BWN_PHY_WRITE(mac, 0x002f, 0);
6893		BWN_PHY_WRITE(mac, 0x080f, 0);
6894		BWN_PHY_WRITE(mac, 0x0810, 0);
6895		BWN_PHY_SET(mac, 0x0478, 0x0100);
6896		BWN_PHY_SET(mac, 0x0801, 0x0040);
6897		BWN_PHY_SET(mac, 0x0060, 0x0040);
6898		BWN_PHY_SET(mac, 0x0014, 0x0200);
6899	}
6900	BWN_RF_SET(mac, 0x007a, 0x0070);
6901	BWN_RF_SET(mac, 0x007a, 0x0080);
6902	DELAY(30);
6903
6904	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6905	if (nrssi >= 0x20)
6906		nrssi -= 0x40;
6907	if (nrssi == 31) {
6908		for (i = 7; i >= 4; i--) {
6909			BWN_RF_WRITE(mac, 0x007b, i);
6910			DELAY(20);
6911			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
6912			    0x003f);
6913			if (nrssi >= 0x20)
6914				nrssi -= 0x40;
6915			if (nrssi < 31 && saved == 0xffff)
6916				saved = i;
6917		}
6918		if (saved == 0xffff)
6919			saved = 4;
6920	} else {
6921		BWN_RF_MASK(mac, 0x007a, 0x007f);
6922		if (phy->rev != 1) {
6923			BWN_PHY_SET(mac, 0x0814, 0x0001);
6924			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
6925		}
6926		BWN_PHY_SET(mac, 0x0811, 0x000c);
6927		BWN_PHY_SET(mac, 0x0812, 0x000c);
6928		BWN_PHY_SET(mac, 0x0811, 0x0030);
6929		BWN_PHY_SET(mac, 0x0812, 0x0030);
6930		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6931		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6932		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6933		if (phy->rev == 0)
6934			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
6935		else
6936			BWN_PHY_SET(mac, 0x000a, 0x2000);
6937		if (phy->rev != 1) {
6938			BWN_PHY_SET(mac, 0x0814, 0x0004);
6939			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
6940		}
6941		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6942		BWN_RF_SET(mac, 0x007a, 0x000f);
6943		bwn_set_all_gains(mac, 3, 0, 1);
6944		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
6945		DELAY(30);
6946		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6947		if (nrssi >= 0x20)
6948			nrssi -= 0x40;
6949		if (nrssi == -32) {
6950			for (i = 0; i < 4; i++) {
6951				BWN_RF_WRITE(mac, 0x007b, i);
6952				DELAY(20);
6953				nrssi = (int16_t)((BWN_PHY_READ(mac,
6954				    0x047f) >> 8) & 0x003f);
6955				if (nrssi >= 0x20)
6956					nrssi -= 0x40;
6957				if (nrssi > -31 && saved == 0xffff)
6958					saved = i;
6959			}
6960			if (saved == 0xffff)
6961				saved = 3;
6962		} else
6963			saved = 0;
6964	}
6965	BWN_RF_WRITE(mac, 0x007b, saved);
6966
6967	/*
6968	 * Restore saved RF/PHY registers
6969	 */
6970	if (phy->rev >= 6) {
6971		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
6972			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6973			    save_phy6[phy6_idx]);
6974		}
6975	}
6976	if (phy->rev != 1) {
6977		for (i = 3; i < 5; i++)
6978			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
6979			    save_phy_comm[i]);
6980	}
6981	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
6982		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6983
6984	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
6985		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6986
6987	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
6988	BWN_PHY_SET(mac, 0x0429, 0x8000);
6989	bwn_set_original_gains(mac);
6990	if (phy->rev >= 6) {
6991		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
6992			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6993			    save_phy6[phy6_idx]);
6994		}
6995	}
6996
6997	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
6998	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
6999	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7000}
7001
7002static void
7003bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7004    int16_t third)
7005{
7006	struct bwn_phy *phy = &mac->mac_phy;
7007	uint16_t i;
7008	uint16_t start = 0x08, end = 0x18;
7009	uint16_t tmp;
7010	uint16_t table;
7011
7012	if (phy->rev <= 1) {
7013		start = 0x10;
7014		end = 0x20;
7015	}
7016
7017	table = BWN_OFDMTAB_GAINX;
7018	if (phy->rev <= 1)
7019		table = BWN_OFDMTAB_GAINX_R1;
7020	for (i = 0; i < 4; i++)
7021		bwn_ofdmtab_write_2(mac, table, i, first);
7022
7023	for (i = start; i < end; i++)
7024		bwn_ofdmtab_write_2(mac, table, i, second);
7025
7026	if (third != -1) {
7027		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7028		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7029		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7030		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7031	}
7032	bwn_dummy_transmission(mac, 0, 1);
7033}
7034
7035static void
7036bwn_set_original_gains(struct bwn_mac *mac)
7037{
7038	struct bwn_phy *phy = &mac->mac_phy;
7039	uint16_t i, tmp;
7040	uint16_t table;
7041	uint16_t start = 0x0008, end = 0x0018;
7042
7043	if (phy->rev <= 1) {
7044		start = 0x0010;
7045		end = 0x0020;
7046	}
7047
7048	table = BWN_OFDMTAB_GAINX;
7049	if (phy->rev <= 1)
7050		table = BWN_OFDMTAB_GAINX_R1;
7051	for (i = 0; i < 4; i++) {
7052		tmp = (i & 0xfffc);
7053		tmp |= (i & 0x0001) << 1;
7054		tmp |= (i & 0x0002) >> 1;
7055
7056		bwn_ofdmtab_write_2(mac, table, i, tmp);
7057	}
7058
7059	for (i = start; i < end; i++)
7060		bwn_ofdmtab_write_2(mac, table, i, i - start);
7061
7062	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7063	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7064	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7065	bwn_dummy_transmission(mac, 0, 1);
7066}
7067
7068static void
7069bwn_phy_hwpctl_init(struct bwn_mac *mac)
7070{
7071	struct bwn_phy *phy = &mac->mac_phy;
7072	struct bwn_phy_g *pg = &phy->phy_g;
7073	struct bwn_rfatt old_rfatt, rfatt;
7074	struct bwn_bbatt old_bbatt, bbatt;
7075	struct bwn_softc *sc = mac->mac_sc;
7076	uint8_t old_txctl = 0;
7077
7078	KASSERT(phy->type == BWN_PHYTYPE_G,
7079	    ("%s:%d: fail", __func__, __LINE__));
7080
7081	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7082	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7083		return;
7084
7085	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7086
7087	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7088
7089	if (!phy->gmode)
7090		return;
7091	bwn_hwpctl_early_init(mac);
7092	if (pg->pg_curtssi == 0) {
7093		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7094			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7095		} else {
7096			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7097			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7098			old_txctl = pg->pg_txctl;
7099
7100			bbatt.att = 11;
7101			if (phy->rf_rev == 8) {
7102				rfatt.att = 15;
7103				rfatt.padmix = 1;
7104			} else {
7105				rfatt.att = 9;
7106				rfatt.padmix = 0;
7107			}
7108			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7109		}
7110		bwn_dummy_transmission(mac, 0, 1);
7111		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7112		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7113			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7114		else
7115			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7116			    &old_rfatt, old_txctl);
7117	}
7118	bwn_hwpctl_init_gphy(mac);
7119
7120	/* clear TSSI */
7121	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7122	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7123	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7124	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7125}
7126
7127static void
7128bwn_hwpctl_early_init(struct bwn_mac *mac)
7129{
7130	struct bwn_phy *phy = &mac->mac_phy;
7131
7132	if (!bwn_has_hwpctl(mac)) {
7133		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7134		return;
7135	}
7136
7137	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7138	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7139	BWN_PHY_SET(mac, 0x047c, 0x0002);
7140	BWN_PHY_SET(mac, 0x047a, 0xf000);
7141	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7142		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7143		BWN_PHY_SET(mac, 0x005d, 0x8000);
7144		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7145		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7146		BWN_PHY_SET(mac, 0x0036, 0x0400);
7147	} else {
7148		BWN_PHY_SET(mac, 0x0036, 0x0200);
7149		BWN_PHY_SET(mac, 0x0036, 0x0400);
7150		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7151		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7152		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7153		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7154		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7155	}
7156}
7157
7158static void
7159bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7160{
7161	struct bwn_phy *phy = &mac->mac_phy;
7162	struct bwn_phy_g *pg = &phy->phy_g;
7163	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7164	int i;
7165	uint16_t nr_written = 0, tmp, value;
7166	uint8_t rf, bb;
7167
7168	if (!bwn_has_hwpctl(mac)) {
7169		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7170		return;
7171	}
7172
7173	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7174	    (pg->pg_idletssi - pg->pg_curtssi));
7175	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7176	    (pg->pg_idletssi - pg->pg_curtssi));
7177
7178	for (i = 0; i < 32; i++)
7179		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7180	for (i = 32; i < 64; i++)
7181		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7182	for (i = 0; i < 64; i += 2) {
7183		value = (uint16_t) pg->pg_tssi2dbm[i];
7184		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7185		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7186	}
7187
7188	for (rf = 0; rf < lo->rfatt.len; rf++) {
7189		for (bb = 0; bb < lo->bbatt.len; bb++) {
7190			if (nr_written >= 0x40)
7191				return;
7192			tmp = lo->bbatt.array[bb].att;
7193			tmp <<= 8;
7194			if (phy->rf_rev == 8)
7195				tmp |= 0x50;
7196			else
7197				tmp |= 0x40;
7198			tmp |= lo->rfatt.array[rf].att;
7199			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7200			nr_written++;
7201		}
7202	}
7203
7204	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7205	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7206
7207	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7208	BWN_PHY_SET(mac, 0x0478, 0x0800);
7209	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7210	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7211
7212	bwn_phy_g_dc_lookup_init(mac, 1);
7213	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7214}
7215
7216static void
7217bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7218{
7219	struct bwn_softc *sc = mac->mac_sc;
7220
7221	if (spu != 0)
7222		bwn_spu_workaround(mac, channel);
7223
7224	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7225
7226	if (channel == 14) {
7227		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7228			bwn_hf_write(mac,
7229			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7230		else
7231			bwn_hf_write(mac,
7232			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7233		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7234		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7235		return;
7236	}
7237
7238	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7239	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7240}
7241
7242static uint16_t
7243bwn_phy_g_chan2freq(uint8_t channel)
7244{
7245	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7246
7247	KASSERT(channel >= 1 && channel <= 14,
7248	    ("%s:%d: fail", __func__, __LINE__));
7249
7250	return (bwn_phy_g_rf_channels[channel - 1]);
7251}
7252
7253static void
7254bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7255    const struct bwn_rfatt *rfatt, uint8_t txctl)
7256{
7257	struct bwn_phy *phy = &mac->mac_phy;
7258	struct bwn_phy_g *pg = &phy->phy_g;
7259	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7260	uint16_t bb, rf;
7261	uint16_t tx_bias, tx_magn;
7262
7263	bb = bbatt->att;
7264	rf = rfatt->att;
7265	tx_bias = lo->tx_bias;
7266	tx_magn = lo->tx_magn;
7267	if (tx_bias == 0xff)
7268		tx_bias = 0;
7269
7270	pg->pg_txctl = txctl;
7271	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7272	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7273	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7274	bwn_phy_g_set_bbatt(mac, bb);
7275	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7276	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7277		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7278	else {
7279		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7280		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7281	}
7282	if (BWN_HAS_TXMAG(phy))
7283		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7284	else
7285		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7286	bwn_lo_g_adjust(mac);
7287}
7288
7289static void
7290bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7291    uint16_t bbatt)
7292{
7293	struct bwn_phy *phy = &mac->mac_phy;
7294
7295	if (phy->analog == 0) {
7296		BWN_WRITE_2(mac, BWN_PHY0,
7297		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7298		return;
7299	}
7300	if (phy->analog > 1) {
7301		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7302		return;
7303	}
7304	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7305}
7306
7307static uint16_t
7308bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7309{
7310	struct bwn_phy *phy = &mac->mac_phy;
7311	struct bwn_phy_g *pg = &phy->phy_g;
7312	struct bwn_softc *sc = mac->mac_sc;
7313	int max_lb_gain;
7314	uint16_t extlna;
7315	uint16_t i;
7316
7317	if (phy->gmode == 0)
7318		return (0);
7319
7320	if (BWN_HAS_LOOPBACK(phy)) {
7321		max_lb_gain = pg->pg_max_lb_gain;
7322		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7323		if (max_lb_gain >= 0x46) {
7324			extlna = 0x3000;
7325			max_lb_gain -= 0x46;
7326		} else if (max_lb_gain >= 0x3a) {
7327			extlna = 0x1000;
7328			max_lb_gain -= 0x3a;
7329		} else if (max_lb_gain >= 0x2e) {
7330			extlna = 0x2000;
7331			max_lb_gain -= 0x2e;
7332		} else {
7333			extlna = 0;
7334			max_lb_gain -= 0x10;
7335		}
7336
7337		for (i = 0; i < 16; i++) {
7338			max_lb_gain -= (i * 6);
7339			if (max_lb_gain < 6)
7340				break;
7341		}
7342
7343		if ((phy->rev < 7) ||
7344		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7345			if (reg == BWN_PHY_RFOVER) {
7346				return (0x1b3);
7347			} else if (reg == BWN_PHY_RFOVERVAL) {
7348				extlna |= (i << 8);
7349				switch (lpd) {
7350				case BWN_LPD(0, 1, 1):
7351					return (0x0f92);
7352				case BWN_LPD(0, 0, 1):
7353				case BWN_LPD(1, 0, 1):
7354					return (0x0092 | extlna);
7355				case BWN_LPD(1, 0, 0):
7356					return (0x0093 | extlna);
7357				}
7358				KASSERT(0 == 1,
7359				    ("%s:%d: fail", __func__, __LINE__));
7360			}
7361			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7362		} else {
7363			if (reg == BWN_PHY_RFOVER)
7364				return (0x9b3);
7365			if (reg == BWN_PHY_RFOVERVAL) {
7366				if (extlna)
7367					extlna |= 0x8000;
7368				extlna |= (i << 8);
7369				switch (lpd) {
7370				case BWN_LPD(0, 1, 1):
7371					return (0x8f92);
7372				case BWN_LPD(0, 0, 1):
7373					return (0x8092 | extlna);
7374				case BWN_LPD(1, 0, 1):
7375					return (0x2092 | extlna);
7376				case BWN_LPD(1, 0, 0):
7377					return (0x2093 | extlna);
7378				}
7379				KASSERT(0 == 1,
7380				    ("%s:%d: fail", __func__, __LINE__));
7381			}
7382			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7383		}
7384		return (0);
7385	}
7386
7387	if ((phy->rev < 7) ||
7388	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7389		if (reg == BWN_PHY_RFOVER) {
7390			return (0x1b3);
7391		} else if (reg == BWN_PHY_RFOVERVAL) {
7392			switch (lpd) {
7393			case BWN_LPD(0, 1, 1):
7394				return (0x0fb2);
7395			case BWN_LPD(0, 0, 1):
7396				return (0x00b2);
7397			case BWN_LPD(1, 0, 1):
7398				return (0x30b2);
7399			case BWN_LPD(1, 0, 0):
7400				return (0x30b3);
7401			}
7402			KASSERT(0 == 1,
7403			    ("%s:%d: fail", __func__, __LINE__));
7404		}
7405		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7406	} else {
7407		if (reg == BWN_PHY_RFOVER) {
7408			return (0x9b3);
7409		} else if (reg == BWN_PHY_RFOVERVAL) {
7410			switch (lpd) {
7411			case BWN_LPD(0, 1, 1):
7412				return (0x8fb2);
7413			case BWN_LPD(0, 0, 1):
7414				return (0x80b2);
7415			case BWN_LPD(1, 0, 1):
7416				return (0x20b2);
7417			case BWN_LPD(1, 0, 0):
7418				return (0x20b3);
7419			}
7420			KASSERT(0 == 1,
7421			    ("%s:%d: fail", __func__, __LINE__));
7422		}
7423		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7424	}
7425	return (0);
7426}
7427
7428static void
7429bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7430{
7431
7432	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7433		return;
7434	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7435	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7436	DELAY(1000);
7437	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7438}
7439
7440static int
7441bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7442{
7443	struct bwn_softc *sc = mac->mac_sc;
7444	struct bwn_fw *fw = &mac->mac_fw;
7445	const uint8_t rev = siba_get_revid(sc->sc_dev);
7446	const char *filename;
7447	uint32_t high;
7448	int error;
7449
7450	/* microcode */
7451	if (rev >= 5 && rev <= 10)
7452		filename = "ucode5";
7453	else if (rev >= 11 && rev <= 12)
7454		filename = "ucode11";
7455	else if (rev == 13)
7456		filename = "ucode13";
7457	else if (rev == 14)
7458		filename = "ucode14";
7459	else if (rev >= 15)
7460		filename = "ucode15";
7461	else {
7462		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7463		bwn_release_firmware(mac);
7464		return (EOPNOTSUPP);
7465	}
7466	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7467	if (error) {
7468		bwn_release_firmware(mac);
7469		return (error);
7470	}
7471
7472	/* PCM */
7473	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7474	if (rev >= 5 && rev <= 10) {
7475		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7476		if (error == ENOENT)
7477			fw->no_pcmfile = 1;
7478		else if (error) {
7479			bwn_release_firmware(mac);
7480			return (error);
7481		}
7482	} else if (rev < 11) {
7483		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7484		return (EOPNOTSUPP);
7485	}
7486
7487	/* initvals */
7488	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7489	switch (mac->mac_phy.type) {
7490	case BWN_PHYTYPE_A:
7491		if (rev < 5 || rev > 10)
7492			goto fail1;
7493		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7494			filename = "a0g1initvals5";
7495		else
7496			filename = "a0g0initvals5";
7497		break;
7498	case BWN_PHYTYPE_G:
7499		if (rev >= 5 && rev <= 10)
7500			filename = "b0g0initvals5";
7501		else if (rev >= 13)
7502			filename = "b0g0initvals13";
7503		else
7504			goto fail1;
7505		break;
7506	case BWN_PHYTYPE_LP:
7507		if (rev == 13)
7508			filename = "lp0initvals13";
7509		else if (rev == 14)
7510			filename = "lp0initvals14";
7511		else if (rev >= 15)
7512			filename = "lp0initvals15";
7513		else
7514			goto fail1;
7515		break;
7516	case BWN_PHYTYPE_N:
7517		if (rev >= 11 && rev <= 12)
7518			filename = "n0initvals11";
7519		else
7520			goto fail1;
7521		break;
7522	default:
7523		goto fail1;
7524	}
7525	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7526	if (error) {
7527		bwn_release_firmware(mac);
7528		return (error);
7529	}
7530
7531	/* bandswitch initvals */
7532	switch (mac->mac_phy.type) {
7533	case BWN_PHYTYPE_A:
7534		if (rev >= 5 && rev <= 10) {
7535			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7536				filename = "a0g1bsinitvals5";
7537			else
7538				filename = "a0g0bsinitvals5";
7539		} else if (rev >= 11)
7540			filename = NULL;
7541		else
7542			goto fail1;
7543		break;
7544	case BWN_PHYTYPE_G:
7545		if (rev >= 5 && rev <= 10)
7546			filename = "b0g0bsinitvals5";
7547		else if (rev >= 11)
7548			filename = NULL;
7549		else
7550			goto fail1;
7551		break;
7552	case BWN_PHYTYPE_LP:
7553		if (rev == 13)
7554			filename = "lp0bsinitvals13";
7555		else if (rev == 14)
7556			filename = "lp0bsinitvals14";
7557		else if (rev >= 15)
7558			filename = "lp0bsinitvals15";
7559		else
7560			goto fail1;
7561		break;
7562	case BWN_PHYTYPE_N:
7563		if (rev >= 11 && rev <= 12)
7564			filename = "n0bsinitvals11";
7565		else
7566			goto fail1;
7567		break;
7568	default:
7569		goto fail1;
7570	}
7571	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7572	if (error) {
7573		bwn_release_firmware(mac);
7574		return (error);
7575	}
7576	return (0);
7577fail1:
7578	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7579	bwn_release_firmware(mac);
7580	return (EOPNOTSUPP);
7581}
7582
7583static int
7584bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7585    const char *name, struct bwn_fwfile *bfw)
7586{
7587	const struct bwn_fwhdr *hdr;
7588	struct bwn_softc *sc = mac->mac_sc;
7589	const struct firmware *fw;
7590	char namebuf[64];
7591
7592	if (name == NULL) {
7593		bwn_do_release_fw(bfw);
7594		return (0);
7595	}
7596	if (bfw->filename != NULL) {
7597		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7598			return (0);
7599		bwn_do_release_fw(bfw);
7600	}
7601
7602	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7603	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7604	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7605	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7606	fw = firmware_get(namebuf);
7607	if (fw == NULL) {
7608		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7609		    namebuf);
7610		return (ENOENT);
7611	}
7612	if (fw->datasize < sizeof(struct bwn_fwhdr))
7613		goto fail;
7614	hdr = (const struct bwn_fwhdr *)(fw->data);
7615	switch (hdr->type) {
7616	case BWN_FWTYPE_UCODE:
7617	case BWN_FWTYPE_PCM:
7618		if (be32toh(hdr->size) !=
7619		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7620			goto fail;
7621		/* FALLTHROUGH */
7622	case BWN_FWTYPE_IV:
7623		if (hdr->ver != 1)
7624			goto fail;
7625		break;
7626	default:
7627		goto fail;
7628	}
7629	bfw->filename = name;
7630	bfw->fw = fw;
7631	bfw->type = type;
7632	return (0);
7633fail:
7634	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7635	if (fw != NULL)
7636		firmware_put(fw, FIRMWARE_UNLOAD);
7637	return (EPROTO);
7638}
7639
7640static void
7641bwn_release_firmware(struct bwn_mac *mac)
7642{
7643
7644	bwn_do_release_fw(&mac->mac_fw.ucode);
7645	bwn_do_release_fw(&mac->mac_fw.pcm);
7646	bwn_do_release_fw(&mac->mac_fw.initvals);
7647	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7648}
7649
7650static void
7651bwn_do_release_fw(struct bwn_fwfile *bfw)
7652{
7653
7654	if (bfw->fw != NULL)
7655		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7656	bfw->fw = NULL;
7657	bfw->filename = NULL;
7658}
7659
7660static int
7661bwn_fw_loaducode(struct bwn_mac *mac)
7662{
7663#define	GETFWOFFSET(fwp, offset)	\
7664	((const uint32_t *)((const char *)fwp.fw->data + offset))
7665#define	GETFWSIZE(fwp, offset)	\
7666	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7667	struct bwn_softc *sc = mac->mac_sc;
7668	const uint32_t *data;
7669	unsigned int i;
7670	uint32_t ctl;
7671	uint16_t date, fwcaps, time;
7672	int error = 0;
7673
7674	ctl = BWN_READ_4(mac, BWN_MACCTL);
7675	ctl |= BWN_MACCTL_MCODE_JMP0;
7676	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7677	    __LINE__));
7678	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7679	for (i = 0; i < 64; i++)
7680		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7681	for (i = 0; i < 4096; i += 2)
7682		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7683
7684	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7685	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7686	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7687	     i++) {
7688		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7689		DELAY(10);
7690	}
7691
7692	if (mac->mac_fw.pcm.fw) {
7693		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7694		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7695		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7696		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7697		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7698		    sizeof(struct bwn_fwhdr)); i++) {
7699			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7700			DELAY(10);
7701		}
7702	}
7703
7704	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7705	BWN_WRITE_4(mac, BWN_MACCTL,
7706	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7707	    BWN_MACCTL_MCODE_RUN);
7708
7709	for (i = 0; i < 21; i++) {
7710		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7711			break;
7712		if (i >= 20) {
7713			device_printf(sc->sc_dev, "ucode timeout\n");
7714			error = ENXIO;
7715			goto error;
7716		}
7717		DELAY(50000);
7718	}
7719	BWN_READ_4(mac, BWN_INTR_REASON);
7720
7721	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7722	if (mac->mac_fw.rev <= 0x128) {
7723		device_printf(sc->sc_dev, "the firmware is too old\n");
7724		error = EOPNOTSUPP;
7725		goto error;
7726	}
7727	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7728	    BWN_SHARED_UCODE_PATCH);
7729	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7730	mac->mac_fw.opensource = (date == 0xffff);
7731	if (bwn_wme != 0)
7732		mac->mac_flags |= BWN_MAC_FLAG_WME;
7733	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7734
7735	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7736	if (mac->mac_fw.opensource == 0) {
7737		device_printf(sc->sc_dev,
7738		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7739		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7740		if (mac->mac_fw.no_pcmfile)
7741			device_printf(sc->sc_dev,
7742			    "no HW crypto acceleration due to pcm5\n");
7743	} else {
7744		mac->mac_fw.patch = time;
7745		fwcaps = bwn_fwcaps_read(mac);
7746		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7747			device_printf(sc->sc_dev,
7748			    "disabling HW crypto acceleration\n");
7749			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7750		}
7751		if (!(fwcaps & BWN_FWCAPS_WME)) {
7752			device_printf(sc->sc_dev, "disabling WME support\n");
7753			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7754		}
7755	}
7756
7757	if (BWN_ISOLDFMT(mac))
7758		device_printf(sc->sc_dev, "using old firmware image\n");
7759
7760	return (0);
7761
7762error:
7763	BWN_WRITE_4(mac, BWN_MACCTL,
7764	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7765	    BWN_MACCTL_MCODE_JMP0);
7766
7767	return (error);
7768#undef GETFWSIZE
7769#undef GETFWOFFSET
7770}
7771
7772/* OpenFirmware only */
7773static uint16_t
7774bwn_fwcaps_read(struct bwn_mac *mac)
7775{
7776
7777	KASSERT(mac->mac_fw.opensource == 1,
7778	    ("%s:%d: fail", __func__, __LINE__));
7779	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7780}
7781
7782static int
7783bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7784    size_t count, size_t array_size)
7785{
7786#define	GET_NEXTIV16(iv)						\
7787	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7788	    sizeof(uint16_t) + sizeof(uint16_t)))
7789#define	GET_NEXTIV32(iv)						\
7790	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7791	    sizeof(uint16_t) + sizeof(uint32_t)))
7792	struct bwn_softc *sc = mac->mac_sc;
7793	const struct bwn_fwinitvals *iv;
7794	uint16_t offset;
7795	size_t i;
7796	uint8_t bit32;
7797
7798	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7799	    ("%s:%d: fail", __func__, __LINE__));
7800	iv = ivals;
7801	for (i = 0; i < count; i++) {
7802		if (array_size < sizeof(iv->offset_size))
7803			goto fail;
7804		array_size -= sizeof(iv->offset_size);
7805		offset = be16toh(iv->offset_size);
7806		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7807		offset &= BWN_FWINITVALS_OFFSET_MASK;
7808		if (offset >= 0x1000)
7809			goto fail;
7810		if (bit32) {
7811			if (array_size < sizeof(iv->data.d32))
7812				goto fail;
7813			array_size -= sizeof(iv->data.d32);
7814			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7815			iv = GET_NEXTIV32(iv);
7816		} else {
7817
7818			if (array_size < sizeof(iv->data.d16))
7819				goto fail;
7820			array_size -= sizeof(iv->data.d16);
7821			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7822
7823			iv = GET_NEXTIV16(iv);
7824		}
7825	}
7826	if (array_size != 0)
7827		goto fail;
7828	return (0);
7829fail:
7830	device_printf(sc->sc_dev, "initvals: invalid format\n");
7831	return (EPROTO);
7832#undef GET_NEXTIV16
7833#undef GET_NEXTIV32
7834}
7835
7836static int
7837bwn_switch_channel(struct bwn_mac *mac, int chan)
7838{
7839	struct bwn_phy *phy = &(mac->mac_phy);
7840	struct bwn_softc *sc = mac->mac_sc;
7841	struct ieee80211com *ic = &sc->sc_ic;
7842	uint16_t channelcookie, savedcookie;
7843	int error;
7844
7845	if (chan == 0xffff)
7846		chan = phy->get_default_chan(mac);
7847
7848	channelcookie = chan;
7849	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7850		channelcookie |= 0x100;
7851	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7852	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7853	error = phy->switch_channel(mac, chan);
7854	if (error)
7855		goto fail;
7856
7857	mac->mac_phy.chan = chan;
7858	DELAY(8000);
7859	return (0);
7860fail:
7861	device_printf(sc->sc_dev, "failed to switch channel\n");
7862	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7863	return (error);
7864}
7865
7866static uint16_t
7867bwn_ant2phy(int antenna)
7868{
7869
7870	switch (antenna) {
7871	case BWN_ANT0:
7872		return (BWN_TX_PHY_ANT0);
7873	case BWN_ANT1:
7874		return (BWN_TX_PHY_ANT1);
7875	case BWN_ANT2:
7876		return (BWN_TX_PHY_ANT2);
7877	case BWN_ANT3:
7878		return (BWN_TX_PHY_ANT3);
7879	case BWN_ANTAUTO:
7880		return (BWN_TX_PHY_ANT01AUTO);
7881	}
7882	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7883	return (0);
7884}
7885
7886static void
7887bwn_wme_load(struct bwn_mac *mac)
7888{
7889	struct bwn_softc *sc = mac->mac_sc;
7890	int i;
7891
7892	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7893	    ("%s:%d: fail", __func__, __LINE__));
7894
7895	bwn_mac_suspend(mac);
7896	for (i = 0; i < N(sc->sc_wmeParams); i++)
7897		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
7898		    bwn_wme_shm_offsets[i]);
7899	bwn_mac_enable(mac);
7900}
7901
7902static void
7903bwn_wme_loadparams(struct bwn_mac *mac,
7904    const struct wmeParams *p, uint16_t shm_offset)
7905{
7906#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
7907	struct bwn_softc *sc = mac->mac_sc;
7908	uint16_t params[BWN_NR_WMEPARAMS];
7909	int slot, tmp;
7910	unsigned int i;
7911
7912	slot = BWN_READ_2(mac, BWN_RNG) &
7913	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7914
7915	memset(&params, 0, sizeof(params));
7916
7917	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
7918	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
7919	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
7920
7921	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
7922	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7923	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
7924	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7925	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
7926	params[BWN_WMEPARAM_BSLOTS] = slot;
7927	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
7928
7929	for (i = 0; i < N(params); i++) {
7930		if (i == BWN_WMEPARAM_STATUS) {
7931			tmp = bwn_shm_read_2(mac, BWN_SHARED,
7932			    shm_offset + (i * 2));
7933			tmp |= 0x100;
7934			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7935			    tmp);
7936		} else {
7937			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7938			    params[i]);
7939		}
7940	}
7941}
7942
7943static void
7944bwn_mac_write_bssid(struct bwn_mac *mac)
7945{
7946	struct bwn_softc *sc = mac->mac_sc;
7947	uint32_t tmp;
7948	int i;
7949	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
7950
7951	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
7952	memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
7953	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
7954	    IEEE80211_ADDR_LEN);
7955
7956	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
7957		tmp = (uint32_t) (mac_bssid[i + 0]);
7958		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
7959		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
7960		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
7961		bwn_ram_write(mac, 0x20 + i, tmp);
7962	}
7963}
7964
7965static void
7966bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
7967    const uint8_t *macaddr)
7968{
7969	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
7970	uint16_t data;
7971
7972	if (!mac)
7973		macaddr = zero;
7974
7975	offset |= 0x0020;
7976	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
7977
7978	data = macaddr[0];
7979	data |= macaddr[1] << 8;
7980	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7981	data = macaddr[2];
7982	data |= macaddr[3] << 8;
7983	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7984	data = macaddr[4];
7985	data |= macaddr[5] << 8;
7986	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7987}
7988
7989static void
7990bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
7991    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
7992{
7993	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
7994	uint8_t per_sta_keys_start = 8;
7995
7996	if (BWN_SEC_NEWAPI(mac))
7997		per_sta_keys_start = 4;
7998
7999	KASSERT(index < mac->mac_max_nr_keys,
8000	    ("%s:%d: fail", __func__, __LINE__));
8001	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8002	    ("%s:%d: fail", __func__, __LINE__));
8003
8004	if (index >= per_sta_keys_start)
8005		bwn_key_macwrite(mac, index, NULL);
8006	if (key)
8007		memcpy(buf, key, key_len);
8008	bwn_key_write(mac, index, algorithm, buf);
8009	if (index >= per_sta_keys_start)
8010		bwn_key_macwrite(mac, index, mac_addr);
8011
8012	mac->mac_key[index].algorithm = algorithm;
8013}
8014
8015static void
8016bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8017{
8018	struct bwn_softc *sc = mac->mac_sc;
8019	uint32_t addrtmp[2] = { 0, 0 };
8020	uint8_t start = 8;
8021
8022	if (BWN_SEC_NEWAPI(mac))
8023		start = 4;
8024
8025	KASSERT(index >= start,
8026	    ("%s:%d: fail", __func__, __LINE__));
8027	index -= start;
8028
8029	if (addr) {
8030		addrtmp[0] = addr[0];
8031		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8032		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8033		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8034		addrtmp[1] = addr[4];
8035		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8036	}
8037
8038	if (siba_get_revid(sc->sc_dev) >= 5) {
8039		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8040		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8041	} else {
8042		if (index >= 8) {
8043			bwn_shm_write_4(mac, BWN_SHARED,
8044			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8045			bwn_shm_write_2(mac, BWN_SHARED,
8046			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8047		}
8048	}
8049}
8050
8051static void
8052bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8053    const uint8_t *key)
8054{
8055	unsigned int i;
8056	uint32_t offset;
8057	uint16_t kidx, value;
8058
8059	kidx = BWN_SEC_KEY2FW(mac, index);
8060	bwn_shm_write_2(mac, BWN_SHARED,
8061	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8062
8063	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8064	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8065		value = key[i];
8066		value |= (uint16_t)(key[i + 1]) << 8;
8067		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8068	}
8069}
8070
8071static void
8072bwn_phy_exit(struct bwn_mac *mac)
8073{
8074
8075	mac->mac_phy.rf_onoff(mac, 0);
8076	if (mac->mac_phy.exit != NULL)
8077		mac->mac_phy.exit(mac);
8078}
8079
8080static void
8081bwn_dma_free(struct bwn_mac *mac)
8082{
8083	struct bwn_dma *dma;
8084
8085	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8086		return;
8087	dma = &mac->mac_method.dma;
8088
8089	bwn_dma_ringfree(&dma->rx);
8090	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8091	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8092	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8093	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8094	bwn_dma_ringfree(&dma->mcast);
8095}
8096
8097static void
8098bwn_core_stop(struct bwn_mac *mac)
8099{
8100	struct bwn_softc *sc = mac->mac_sc;
8101
8102	BWN_ASSERT_LOCKED(sc);
8103
8104	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8105		return;
8106
8107	callout_stop(&sc->sc_rfswitch_ch);
8108	callout_stop(&sc->sc_task_ch);
8109	callout_stop(&sc->sc_watchdog_ch);
8110	sc->sc_watchdog_timer = 0;
8111	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8112	BWN_READ_4(mac, BWN_INTR_MASK);
8113	bwn_mac_suspend(mac);
8114
8115	mac->mac_status = BWN_MAC_STATUS_INITED;
8116}
8117
8118static int
8119bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8120{
8121	struct bwn_mac *up_dev = NULL;
8122	struct bwn_mac *down_dev;
8123	struct bwn_mac *mac;
8124	int err, status;
8125	uint8_t gmode;
8126
8127	BWN_ASSERT_LOCKED(sc);
8128
8129	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8130		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8131		    mac->mac_phy.supports_2ghz) {
8132			up_dev = mac;
8133			gmode = 1;
8134		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8135		    mac->mac_phy.supports_5ghz) {
8136			up_dev = mac;
8137			gmode = 0;
8138		} else {
8139			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8140			return (EINVAL);
8141		}
8142		if (up_dev != NULL)
8143			break;
8144	}
8145	if (up_dev == NULL) {
8146		device_printf(sc->sc_dev, "Could not find a device\n");
8147		return (ENODEV);
8148	}
8149	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8150		return (0);
8151
8152	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8153	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8154
8155	down_dev = sc->sc_curmac;
8156	status = down_dev->mac_status;
8157	if (status >= BWN_MAC_STATUS_STARTED)
8158		bwn_core_stop(down_dev);
8159	if (status >= BWN_MAC_STATUS_INITED)
8160		bwn_core_exit(down_dev);
8161
8162	if (down_dev != up_dev)
8163		bwn_phy_reset(down_dev);
8164
8165	up_dev->mac_phy.gmode = gmode;
8166	if (status >= BWN_MAC_STATUS_INITED) {
8167		err = bwn_core_init(up_dev);
8168		if (err) {
8169			device_printf(sc->sc_dev,
8170			    "fatal: failed to initialize for %s-GHz\n",
8171			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8172			goto fail;
8173		}
8174	}
8175	if (status >= BWN_MAC_STATUS_STARTED)
8176		bwn_core_start(up_dev);
8177	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8178	sc->sc_curmac = up_dev;
8179
8180	return (0);
8181fail:
8182	sc->sc_curmac = NULL;
8183	return (err);
8184}
8185
8186static void
8187bwn_rf_turnon(struct bwn_mac *mac)
8188{
8189
8190	bwn_mac_suspend(mac);
8191	mac->mac_phy.rf_onoff(mac, 1);
8192	mac->mac_phy.rf_on = 1;
8193	bwn_mac_enable(mac);
8194}
8195
8196static void
8197bwn_rf_turnoff(struct bwn_mac *mac)
8198{
8199
8200	bwn_mac_suspend(mac);
8201	mac->mac_phy.rf_onoff(mac, 0);
8202	mac->mac_phy.rf_on = 0;
8203	bwn_mac_enable(mac);
8204}
8205
8206static void
8207bwn_phy_reset(struct bwn_mac *mac)
8208{
8209	struct bwn_softc *sc = mac->mac_sc;
8210
8211	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8212	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8213	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8214	DELAY(1000);
8215	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8216	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8217	    BWN_TGSLOW_PHYRESET);
8218	DELAY(1000);
8219}
8220
8221static int
8222bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8223{
8224	struct bwn_vap *bvp = BWN_VAP(vap);
8225	struct ieee80211com *ic= vap->iv_ic;
8226	enum ieee80211_state ostate = vap->iv_state;
8227	struct bwn_softc *sc = ic->ic_softc;
8228	struct bwn_mac *mac = sc->sc_curmac;
8229	int error;
8230
8231	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8232	    ieee80211_state_name[vap->iv_state],
8233	    ieee80211_state_name[nstate]);
8234
8235	error = bvp->bv_newstate(vap, nstate, arg);
8236	if (error != 0)
8237		return (error);
8238
8239	BWN_LOCK(sc);
8240
8241	bwn_led_newstate(mac, nstate);
8242
8243	/*
8244	 * Clear the BSSID when we stop a STA
8245	 */
8246	if (vap->iv_opmode == IEEE80211_M_STA) {
8247		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8248			/*
8249			 * Clear out the BSSID.  If we reassociate to
8250			 * the same AP, this will reinialize things
8251			 * correctly...
8252			 */
8253			if (ic->ic_opmode == IEEE80211_M_STA &&
8254			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8255				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8256				bwn_set_macaddr(mac);
8257			}
8258		}
8259	}
8260
8261	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8262	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8263		/* XXX nothing to do? */
8264	} else if (nstate == IEEE80211_S_RUN) {
8265		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8266		bwn_set_opmode(mac);
8267		bwn_set_pretbtt(mac);
8268		bwn_spu_setdelay(mac, 0);
8269		bwn_set_macaddr(mac);
8270	}
8271
8272	BWN_UNLOCK(sc);
8273
8274	return (error);
8275}
8276
8277static void
8278bwn_set_pretbtt(struct bwn_mac *mac)
8279{
8280	struct bwn_softc *sc = mac->mac_sc;
8281	struct ieee80211com *ic = &sc->sc_ic;
8282	uint16_t pretbtt;
8283
8284	if (ic->ic_opmode == IEEE80211_M_IBSS)
8285		pretbtt = 2;
8286	else
8287		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8288	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8289	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8290}
8291
8292static int
8293bwn_intr(void *arg)
8294{
8295	struct bwn_mac *mac = arg;
8296	struct bwn_softc *sc = mac->mac_sc;
8297	uint32_t reason;
8298
8299	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8300	    (sc->sc_flags & BWN_FLAG_INVALID))
8301		return (FILTER_STRAY);
8302
8303	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8304	if (reason == 0xffffffff)	/* shared IRQ */
8305		return (FILTER_STRAY);
8306	reason &= mac->mac_intr_mask;
8307	if (reason == 0)
8308		return (FILTER_HANDLED);
8309
8310	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8311	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8312	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8313	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8314	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8315	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8316	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8317	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8318	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8319	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8320	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8321
8322	/* Disable interrupts. */
8323	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8324
8325	mac->mac_reason_intr = reason;
8326
8327	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8328	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8329
8330	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8331	return (FILTER_HANDLED);
8332}
8333
8334static void
8335bwn_intrtask(void *arg, int npending)
8336{
8337	struct bwn_mac *mac = arg;
8338	struct bwn_softc *sc = mac->mac_sc;
8339	uint32_t merged = 0;
8340	int i, tx = 0, rx = 0;
8341
8342	BWN_LOCK(sc);
8343	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8344	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8345		BWN_UNLOCK(sc);
8346		return;
8347	}
8348
8349	for (i = 0; i < N(mac->mac_reason); i++)
8350		merged |= mac->mac_reason[i];
8351
8352	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8353		device_printf(sc->sc_dev, "MAC trans error\n");
8354
8355	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8356		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8357		mac->mac_phy.txerrors--;
8358		if (mac->mac_phy.txerrors == 0) {
8359			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8360			bwn_restart(mac, "PHY TX errors");
8361		}
8362	}
8363
8364	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8365		if (merged & BWN_DMAINTR_FATALMASK) {
8366			device_printf(sc->sc_dev,
8367			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8368			    mac->mac_reason[0], mac->mac_reason[1],
8369			    mac->mac_reason[2], mac->mac_reason[3],
8370			    mac->mac_reason[4], mac->mac_reason[5]);
8371			bwn_restart(mac, "DMA error");
8372			BWN_UNLOCK(sc);
8373			return;
8374		}
8375		if (merged & BWN_DMAINTR_NONFATALMASK) {
8376			device_printf(sc->sc_dev,
8377			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8378			    mac->mac_reason[0], mac->mac_reason[1],
8379			    mac->mac_reason[2], mac->mac_reason[3],
8380			    mac->mac_reason[4], mac->mac_reason[5]);
8381		}
8382	}
8383
8384	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8385		bwn_intr_ucode_debug(mac);
8386	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8387		bwn_intr_tbtt_indication(mac);
8388	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8389		bwn_intr_atim_end(mac);
8390	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8391		bwn_intr_beacon(mac);
8392	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8393		bwn_intr_pmq(mac);
8394	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8395		bwn_intr_noise(mac);
8396
8397	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8398		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8399			bwn_dma_rx(mac->mac_method.dma.rx);
8400			rx = 1;
8401		}
8402	} else
8403		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8404
8405	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8406	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8407	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8408	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8409	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8410
8411	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8412		bwn_intr_txeof(mac);
8413		tx = 1;
8414	}
8415
8416	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8417
8418	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8419		int evt = BWN_LED_EVENT_NONE;
8420
8421		if (tx && rx) {
8422			if (sc->sc_rx_rate > sc->sc_tx_rate)
8423				evt = BWN_LED_EVENT_RX;
8424			else
8425				evt = BWN_LED_EVENT_TX;
8426		} else if (tx) {
8427			evt = BWN_LED_EVENT_TX;
8428		} else if (rx) {
8429			evt = BWN_LED_EVENT_RX;
8430		} else if (rx == 0) {
8431			evt = BWN_LED_EVENT_POLL;
8432		}
8433
8434		if (evt != BWN_LED_EVENT_NONE)
8435			bwn_led_event(mac, evt);
8436       }
8437
8438	if (mbufq_first(&sc->sc_snd) != NULL)
8439		bwn_start(sc);
8440
8441	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8442	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8443
8444	BWN_UNLOCK(sc);
8445}
8446
8447static void
8448bwn_restart(struct bwn_mac *mac, const char *msg)
8449{
8450	struct bwn_softc *sc = mac->mac_sc;
8451	struct ieee80211com *ic = &sc->sc_ic;
8452
8453	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8454		return;
8455
8456	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8457	ieee80211_runtask(ic, &mac->mac_hwreset);
8458}
8459
8460static void
8461bwn_intr_ucode_debug(struct bwn_mac *mac)
8462{
8463	struct bwn_softc *sc = mac->mac_sc;
8464	uint16_t reason;
8465
8466	if (mac->mac_fw.opensource == 0)
8467		return;
8468
8469	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8470	switch (reason) {
8471	case BWN_DEBUGINTR_PANIC:
8472		bwn_handle_fwpanic(mac);
8473		break;
8474	case BWN_DEBUGINTR_DUMP_SHM:
8475		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8476		break;
8477	case BWN_DEBUGINTR_DUMP_REGS:
8478		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8479		break;
8480	case BWN_DEBUGINTR_MARKER:
8481		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8482		break;
8483	default:
8484		device_printf(sc->sc_dev,
8485		    "ucode debug unknown reason: %#x\n", reason);
8486	}
8487
8488	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8489	    BWN_DEBUGINTR_ACK);
8490}
8491
8492static void
8493bwn_intr_tbtt_indication(struct bwn_mac *mac)
8494{
8495	struct bwn_softc *sc = mac->mac_sc;
8496	struct ieee80211com *ic = &sc->sc_ic;
8497
8498	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8499		bwn_psctl(mac, 0);
8500	if (ic->ic_opmode == IEEE80211_M_IBSS)
8501		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8502}
8503
8504static void
8505bwn_intr_atim_end(struct bwn_mac *mac)
8506{
8507
8508	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8509		BWN_WRITE_4(mac, BWN_MACCMD,
8510		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8511		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8512	}
8513}
8514
8515static void
8516bwn_intr_beacon(struct bwn_mac *mac)
8517{
8518	struct bwn_softc *sc = mac->mac_sc;
8519	struct ieee80211com *ic = &sc->sc_ic;
8520	uint32_t cmd, beacon0, beacon1;
8521
8522	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8523	    ic->ic_opmode == IEEE80211_M_MBSS)
8524		return;
8525
8526	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8527
8528	cmd = BWN_READ_4(mac, BWN_MACCMD);
8529	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8530	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8531
8532	if (beacon0 && beacon1) {
8533		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8534		mac->mac_intr_mask |= BWN_INTR_BEACON;
8535		return;
8536	}
8537
8538	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8539		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8540		bwn_load_beacon0(mac);
8541		bwn_load_beacon1(mac);
8542		cmd = BWN_READ_4(mac, BWN_MACCMD);
8543		cmd |= BWN_MACCMD_BEACON0_VALID;
8544		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8545	} else {
8546		if (!beacon0) {
8547			bwn_load_beacon0(mac);
8548			cmd = BWN_READ_4(mac, BWN_MACCMD);
8549			cmd |= BWN_MACCMD_BEACON0_VALID;
8550			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8551		} else if (!beacon1) {
8552			bwn_load_beacon1(mac);
8553			cmd = BWN_READ_4(mac, BWN_MACCMD);
8554			cmd |= BWN_MACCMD_BEACON1_VALID;
8555			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8556		}
8557	}
8558}
8559
8560static void
8561bwn_intr_pmq(struct bwn_mac *mac)
8562{
8563	uint32_t tmp;
8564
8565	while (1) {
8566		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8567		if (!(tmp & 0x00000008))
8568			break;
8569	}
8570	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8571}
8572
8573static void
8574bwn_intr_noise(struct bwn_mac *mac)
8575{
8576	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8577	uint16_t tmp;
8578	uint8_t noise[4];
8579	uint8_t i, j;
8580	int32_t average;
8581
8582	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8583		return;
8584
8585	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8586	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8587	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8588	    noise[3] == 0x7f)
8589		goto new;
8590
8591	KASSERT(mac->mac_noise.noi_nsamples < 8,
8592	    ("%s:%d: fail", __func__, __LINE__));
8593	i = mac->mac_noise.noi_nsamples;
8594	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8595	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8596	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8597	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8598	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8599	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8600	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8601	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8602	mac->mac_noise.noi_nsamples++;
8603	if (mac->mac_noise.noi_nsamples == 8) {
8604		average = 0;
8605		for (i = 0; i < 8; i++) {
8606			for (j = 0; j < 4; j++)
8607				average += mac->mac_noise.noi_samples[i][j];
8608		}
8609		average = (((average / 32) * 125) + 64) / 128;
8610		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8611		if (tmp >= 8)
8612			average += 2;
8613		else
8614			average -= 25;
8615		average -= (tmp == 8) ? 72 : 48;
8616
8617		mac->mac_stats.link_noise = average;
8618		mac->mac_noise.noi_running = 0;
8619		return;
8620	}
8621new:
8622	bwn_noise_gensample(mac);
8623}
8624
8625static int
8626bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8627{
8628	struct bwn_mac *mac = prq->prq_mac;
8629	struct bwn_softc *sc = mac->mac_sc;
8630	unsigned int i;
8631
8632	BWN_ASSERT_LOCKED(sc);
8633
8634	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8635		return (0);
8636
8637	for (i = 0; i < 5000; i++) {
8638		if (bwn_pio_rxeof(prq) == 0)
8639			break;
8640	}
8641	if (i >= 5000)
8642		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8643	return ((i > 0) ? 1 : 0);
8644}
8645
8646static void
8647bwn_dma_rx(struct bwn_dma_ring *dr)
8648{
8649	int slot, curslot;
8650
8651	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8652	curslot = dr->get_curslot(dr);
8653	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8654	    ("%s:%d: fail", __func__, __LINE__));
8655
8656	slot = dr->dr_curslot;
8657	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8658		bwn_dma_rxeof(dr, &slot);
8659
8660	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8661	    BUS_DMASYNC_PREWRITE);
8662
8663	dr->set_curslot(dr, slot);
8664	dr->dr_curslot = slot;
8665}
8666
8667static void
8668bwn_intr_txeof(struct bwn_mac *mac)
8669{
8670	struct bwn_txstatus stat;
8671	uint32_t stat0, stat1;
8672	uint16_t tmp;
8673
8674	BWN_ASSERT_LOCKED(mac->mac_sc);
8675
8676	while (1) {
8677		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8678		if (!(stat0 & 0x00000001))
8679			break;
8680		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8681
8682		stat.cookie = (stat0 >> 16);
8683		stat.seq = (stat1 & 0x0000ffff);
8684		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8685		tmp = (stat0 & 0x0000ffff);
8686		stat.framecnt = ((tmp & 0xf000) >> 12);
8687		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8688		stat.sreason = ((tmp & 0x001c) >> 2);
8689		stat.pm = (tmp & 0x0080) ? 1 : 0;
8690		stat.im = (tmp & 0x0040) ? 1 : 0;
8691		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8692		stat.ack = (tmp & 0x0002) ? 1 : 0;
8693
8694		bwn_handle_txeof(mac, &stat);
8695	}
8696}
8697
8698static void
8699bwn_hwreset(void *arg, int npending)
8700{
8701	struct bwn_mac *mac = arg;
8702	struct bwn_softc *sc = mac->mac_sc;
8703	int error = 0;
8704	int prev_status;
8705
8706	BWN_LOCK(sc);
8707
8708	prev_status = mac->mac_status;
8709	if (prev_status >= BWN_MAC_STATUS_STARTED)
8710		bwn_core_stop(mac);
8711	if (prev_status >= BWN_MAC_STATUS_INITED)
8712		bwn_core_exit(mac);
8713
8714	if (prev_status >= BWN_MAC_STATUS_INITED) {
8715		error = bwn_core_init(mac);
8716		if (error)
8717			goto out;
8718	}
8719	if (prev_status >= BWN_MAC_STATUS_STARTED)
8720		bwn_core_start(mac);
8721out:
8722	if (error) {
8723		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8724		sc->sc_curmac = NULL;
8725	}
8726	BWN_UNLOCK(sc);
8727}
8728
8729static void
8730bwn_handle_fwpanic(struct bwn_mac *mac)
8731{
8732	struct bwn_softc *sc = mac->mac_sc;
8733	uint16_t reason;
8734
8735	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8736	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8737
8738	if (reason == BWN_FWPANIC_RESTART)
8739		bwn_restart(mac, "ucode panic");
8740}
8741
8742static void
8743bwn_load_beacon0(struct bwn_mac *mac)
8744{
8745
8746	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8747}
8748
8749static void
8750bwn_load_beacon1(struct bwn_mac *mac)
8751{
8752
8753	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8754}
8755
8756static uint32_t
8757bwn_jssi_read(struct bwn_mac *mac)
8758{
8759	uint32_t val = 0;
8760
8761	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8762	val <<= 16;
8763	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8764
8765	return (val);
8766}
8767
8768static void
8769bwn_noise_gensample(struct bwn_mac *mac)
8770{
8771	uint32_t jssi = 0x7f7f7f7f;
8772
8773	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8774	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8775	BWN_WRITE_4(mac, BWN_MACCMD,
8776	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8777}
8778
8779static int
8780bwn_dma_freeslot(struct bwn_dma_ring *dr)
8781{
8782	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8783
8784	return (dr->dr_numslots - dr->dr_usedslot);
8785}
8786
8787static int
8788bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8789{
8790	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8791
8792	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8793	    ("%s:%d: fail", __func__, __LINE__));
8794	if (slot == dr->dr_numslots - 1)
8795		return (0);
8796	return (slot + 1);
8797}
8798
8799static void
8800bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8801{
8802	struct bwn_mac *mac = dr->dr_mac;
8803	struct bwn_softc *sc = mac->mac_sc;
8804	struct bwn_dma *dma = &mac->mac_method.dma;
8805	struct bwn_dmadesc_generic *desc;
8806	struct bwn_dmadesc_meta *meta;
8807	struct bwn_rxhdr4 *rxhdr;
8808	struct mbuf *m;
8809	uint32_t macstat;
8810	int32_t tmp;
8811	int cnt = 0;
8812	uint16_t len;
8813
8814	dr->getdesc(dr, *slot, &desc, &meta);
8815
8816	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8817	m = meta->mt_m;
8818
8819	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8820		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8821		return;
8822	}
8823
8824	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8825	len = le16toh(rxhdr->frame_len);
8826	if (len <= 0) {
8827		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8828		return;
8829	}
8830	if (bwn_dma_check_redzone(dr, m)) {
8831		device_printf(sc->sc_dev, "redzone error.\n");
8832		bwn_dma_set_redzone(dr, m);
8833		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8834		    BUS_DMASYNC_PREWRITE);
8835		return;
8836	}
8837	if (len > dr->dr_rx_bufsize) {
8838		tmp = len;
8839		while (1) {
8840			dr->getdesc(dr, *slot, &desc, &meta);
8841			bwn_dma_set_redzone(dr, meta->mt_m);
8842			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8843			    BUS_DMASYNC_PREWRITE);
8844			*slot = bwn_dma_nextslot(dr, *slot);
8845			cnt++;
8846			tmp -= dr->dr_rx_bufsize;
8847			if (tmp <= 0)
8848				break;
8849		}
8850		device_printf(sc->sc_dev, "too small buffer "
8851		       "(len %u buffer %u dropped %d)\n",
8852		       len, dr->dr_rx_bufsize, cnt);
8853		return;
8854	}
8855	macstat = le32toh(rxhdr->mac_status);
8856	if (macstat & BWN_RX_MAC_FCSERR) {
8857		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8858			device_printf(sc->sc_dev, "RX drop\n");
8859			return;
8860		}
8861	}
8862
8863	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8864	m_adj(m, dr->dr_frameoffset);
8865
8866	bwn_rxeof(dr->dr_mac, m, rxhdr);
8867}
8868
8869static void
8870bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8871{
8872	struct bwn_dma_ring *dr;
8873	struct bwn_dmadesc_generic *desc;
8874	struct bwn_dmadesc_meta *meta;
8875	struct bwn_pio_txqueue *tq;
8876	struct bwn_pio_txpkt *tp = NULL;
8877	struct bwn_softc *sc = mac->mac_sc;
8878	struct bwn_stats *stats = &mac->mac_stats;
8879	struct ieee80211_node *ni;
8880	struct ieee80211vap *vap;
8881	int retrycnt = 0, slot;
8882
8883	BWN_ASSERT_LOCKED(mac->mac_sc);
8884
8885	if (status->im)
8886		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8887	if (status->ampdu)
8888		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
8889	if (status->rtscnt) {
8890		if (status->rtscnt == 0xf)
8891			stats->rtsfail++;
8892		else
8893			stats->rts++;
8894	}
8895
8896	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8897		if (status->ack) {
8898			dr = bwn_dma_parse_cookie(mac, status,
8899			    status->cookie, &slot);
8900			if (dr == NULL) {
8901				device_printf(sc->sc_dev,
8902				    "failed to parse cookie\n");
8903				return;
8904			}
8905			while (1) {
8906				dr->getdesc(dr, slot, &desc, &meta);
8907				if (meta->mt_islast) {
8908					ni = meta->mt_ni;
8909					vap = ni->ni_vap;
8910					ieee80211_ratectl_tx_complete(vap, ni,
8911					    status->ack ?
8912					      IEEE80211_RATECTL_TX_SUCCESS :
8913					      IEEE80211_RATECTL_TX_FAILURE,
8914					    &retrycnt, 0);
8915					break;
8916				}
8917				slot = bwn_dma_nextslot(dr, slot);
8918			}
8919		}
8920		bwn_dma_handle_txeof(mac, status);
8921	} else {
8922		if (status->ack) {
8923			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
8924			if (tq == NULL) {
8925				device_printf(sc->sc_dev,
8926				    "failed to parse cookie\n");
8927				return;
8928			}
8929			ni = tp->tp_ni;
8930			vap = ni->ni_vap;
8931			ieee80211_ratectl_tx_complete(vap, ni,
8932			    status->ack ?
8933			      IEEE80211_RATECTL_TX_SUCCESS :
8934			      IEEE80211_RATECTL_TX_FAILURE,
8935			    &retrycnt, 0);
8936		}
8937		bwn_pio_handle_txeof(mac, status);
8938	}
8939
8940	bwn_phy_txpower_check(mac, 0);
8941}
8942
8943static uint8_t
8944bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
8945{
8946	struct bwn_mac *mac = prq->prq_mac;
8947	struct bwn_softc *sc = mac->mac_sc;
8948	struct bwn_rxhdr4 rxhdr;
8949	struct mbuf *m;
8950	uint32_t ctl32, macstat, v32;
8951	unsigned int i, padding;
8952	uint16_t ctl16, len, totlen, v16;
8953	unsigned char *mp;
8954	char *data;
8955
8956	memset(&rxhdr, 0, sizeof(rxhdr));
8957
8958	if (prq->prq_rev >= 8) {
8959		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8960		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
8961			return (0);
8962		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
8963		    BWN_PIO8_RXCTL_FRAMEREADY);
8964		for (i = 0; i < 10; i++) {
8965			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8966			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
8967				goto ready;
8968			DELAY(10);
8969		}
8970	} else {
8971		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8972		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
8973			return (0);
8974		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
8975		    BWN_PIO_RXCTL_FRAMEREADY);
8976		for (i = 0; i < 10; i++) {
8977			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8978			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
8979				goto ready;
8980			DELAY(10);
8981		}
8982	}
8983	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
8984	return (1);
8985ready:
8986	if (prq->prq_rev >= 8)
8987		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8988		    prq->prq_base + BWN_PIO8_RXDATA);
8989	else
8990		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8991		    prq->prq_base + BWN_PIO_RXDATA);
8992	len = le16toh(rxhdr.frame_len);
8993	if (len > 0x700) {
8994		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
8995		goto error;
8996	}
8997	if (len == 0) {
8998		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
8999		goto error;
9000	}
9001
9002	macstat = le32toh(rxhdr.mac_status);
9003	if (macstat & BWN_RX_MAC_FCSERR) {
9004		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9005			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9006			goto error;
9007		}
9008	}
9009
9010	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9011	totlen = len + padding;
9012	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9013	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9014	if (m == NULL) {
9015		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9016		goto error;
9017	}
9018	mp = mtod(m, unsigned char *);
9019	if (prq->prq_rev >= 8) {
9020		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9021		    prq->prq_base + BWN_PIO8_RXDATA);
9022		if (totlen & 3) {
9023			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9024			data = &(mp[totlen - 1]);
9025			switch (totlen & 3) {
9026			case 3:
9027				*data = (v32 >> 16);
9028				data--;
9029			case 2:
9030				*data = (v32 >> 8);
9031				data--;
9032			case 1:
9033				*data = v32;
9034			}
9035		}
9036	} else {
9037		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9038		    prq->prq_base + BWN_PIO_RXDATA);
9039		if (totlen & 1) {
9040			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9041			mp[totlen - 1] = v16;
9042		}
9043	}
9044
9045	m->m_len = m->m_pkthdr.len = totlen;
9046
9047	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9048
9049	return (1);
9050error:
9051	if (prq->prq_rev >= 8)
9052		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9053		    BWN_PIO8_RXCTL_DATAREADY);
9054	else
9055		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9056	return (1);
9057}
9058
9059static int
9060bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9061    struct bwn_dmadesc_meta *meta, int init)
9062{
9063	struct bwn_mac *mac = dr->dr_mac;
9064	struct bwn_dma *dma = &mac->mac_method.dma;
9065	struct bwn_rxhdr4 *hdr;
9066	bus_dmamap_t map;
9067	bus_addr_t paddr;
9068	struct mbuf *m;
9069	int error;
9070
9071	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9072	if (m == NULL) {
9073		error = ENOBUFS;
9074
9075		/*
9076		 * If the NIC is up and running, we need to:
9077		 * - Clear RX buffer's header.
9078		 * - Restore RX descriptor settings.
9079		 */
9080		if (init)
9081			return (error);
9082		else
9083			goto back;
9084	}
9085	m->m_len = m->m_pkthdr.len = MCLBYTES;
9086
9087	bwn_dma_set_redzone(dr, m);
9088
9089	/*
9090	 * Try to load RX buf into temporary DMA map
9091	 */
9092	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9093	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9094	if (error) {
9095		m_freem(m);
9096
9097		/*
9098		 * See the comment above
9099		 */
9100		if (init)
9101			return (error);
9102		else
9103			goto back;
9104	}
9105
9106	if (!init)
9107		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9108	meta->mt_m = m;
9109	meta->mt_paddr = paddr;
9110
9111	/*
9112	 * Swap RX buf's DMA map with the loaded temporary one
9113	 */
9114	map = meta->mt_dmap;
9115	meta->mt_dmap = dr->dr_spare_dmap;
9116	dr->dr_spare_dmap = map;
9117
9118back:
9119	/*
9120	 * Clear RX buf header
9121	 */
9122	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9123	bzero(hdr, sizeof(*hdr));
9124	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9125	    BUS_DMASYNC_PREWRITE);
9126
9127	/*
9128	 * Setup RX buf descriptor
9129	 */
9130	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9131	    sizeof(*hdr), 0, 0, 0);
9132	return (error);
9133}
9134
9135static void
9136bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9137		 bus_size_t mapsz __unused, int error)
9138{
9139
9140	if (!error) {
9141		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9142		*((bus_addr_t *)arg) = seg->ds_addr;
9143	}
9144}
9145
9146static int
9147bwn_hwrate2ieeerate(int rate)
9148{
9149
9150	switch (rate) {
9151	case BWN_CCK_RATE_1MB:
9152		return (2);
9153	case BWN_CCK_RATE_2MB:
9154		return (4);
9155	case BWN_CCK_RATE_5MB:
9156		return (11);
9157	case BWN_CCK_RATE_11MB:
9158		return (22);
9159	case BWN_OFDM_RATE_6MB:
9160		return (12);
9161	case BWN_OFDM_RATE_9MB:
9162		return (18);
9163	case BWN_OFDM_RATE_12MB:
9164		return (24);
9165	case BWN_OFDM_RATE_18MB:
9166		return (36);
9167	case BWN_OFDM_RATE_24MB:
9168		return (48);
9169	case BWN_OFDM_RATE_36MB:
9170		return (72);
9171	case BWN_OFDM_RATE_48MB:
9172		return (96);
9173	case BWN_OFDM_RATE_54MB:
9174		return (108);
9175	default:
9176		printf("Ooops\n");
9177		return (0);
9178	}
9179}
9180
9181static void
9182bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9183{
9184	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9185	struct bwn_plcp6 *plcp;
9186	struct bwn_softc *sc = mac->mac_sc;
9187	struct ieee80211_frame_min *wh;
9188	struct ieee80211_node *ni;
9189	struct ieee80211com *ic = &sc->sc_ic;
9190	uint32_t macstat;
9191	int padding, rate, rssi = 0, noise = 0, type;
9192	uint16_t phytype, phystat0, phystat3, chanstat;
9193	unsigned char *mp = mtod(m, unsigned char *);
9194	static int rx_mac_dec_rpt = 0;
9195
9196	BWN_ASSERT_LOCKED(sc);
9197
9198	phystat0 = le16toh(rxhdr->phy_status0);
9199	phystat3 = le16toh(rxhdr->phy_status3);
9200	macstat = le32toh(rxhdr->mac_status);
9201	chanstat = le16toh(rxhdr->channel);
9202	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9203
9204	if (macstat & BWN_RX_MAC_FCSERR)
9205		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9206	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9207		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9208	if (macstat & BWN_RX_MAC_DECERR)
9209		goto drop;
9210
9211	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9212	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9213		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9214		    m->m_pkthdr.len);
9215		goto drop;
9216	}
9217	plcp = (struct bwn_plcp6 *)(mp + padding);
9218	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9219	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9220		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9221		    m->m_pkthdr.len);
9222		goto drop;
9223	}
9224	wh = mtod(m, struct ieee80211_frame_min *);
9225
9226	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9227		device_printf(sc->sc_dev,
9228		    "RX decryption attempted (old %d keyidx %#x)\n",
9229		    BWN_ISOLDFMT(mac),
9230		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9231
9232	/* XXX calculating RSSI & noise & antenna */
9233
9234	if (phystat0 & BWN_RX_PHYST0_OFDM)
9235		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9236		    phytype == BWN_PHYTYPE_A);
9237	else
9238		rate = bwn_plcp_get_cckrate(mac, plcp);
9239	if (rate == -1) {
9240		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9241			goto drop;
9242	}
9243	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9244
9245	/* RX radio tap */
9246	if (ieee80211_radiotap_active(ic))
9247		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9248	m_adj(m, -IEEE80211_CRC_LEN);
9249
9250	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9251	noise = mac->mac_stats.link_noise;
9252
9253	BWN_UNLOCK(sc);
9254
9255	ni = ieee80211_find_rxnode(ic, wh);
9256	if (ni != NULL) {
9257		type = ieee80211_input(ni, m, rssi, noise);
9258		ieee80211_free_node(ni);
9259	} else
9260		type = ieee80211_input_all(ic, m, rssi, noise);
9261
9262	BWN_LOCK(sc);
9263	return;
9264drop:
9265	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9266}
9267
9268static void
9269bwn_dma_handle_txeof(struct bwn_mac *mac,
9270    const struct bwn_txstatus *status)
9271{
9272	struct bwn_dma *dma = &mac->mac_method.dma;
9273	struct bwn_dma_ring *dr;
9274	struct bwn_dmadesc_generic *desc;
9275	struct bwn_dmadesc_meta *meta;
9276	struct bwn_softc *sc = mac->mac_sc;
9277	int slot;
9278
9279	BWN_ASSERT_LOCKED(sc);
9280
9281	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9282	if (dr == NULL) {
9283		device_printf(sc->sc_dev, "failed to parse cookie\n");
9284		return;
9285	}
9286	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9287
9288	while (1) {
9289		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9290		    ("%s:%d: fail", __func__, __LINE__));
9291		dr->getdesc(dr, slot, &desc, &meta);
9292
9293		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9294			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9295		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9296			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9297
9298		if (meta->mt_islast) {
9299			KASSERT(meta->mt_m != NULL,
9300			    ("%s:%d: fail", __func__, __LINE__));
9301
9302			ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
9303			meta->mt_ni = NULL;
9304			meta->mt_m = NULL;
9305		} else
9306			KASSERT(meta->mt_m == NULL,
9307			    ("%s:%d: fail", __func__, __LINE__));
9308
9309		dr->dr_usedslot--;
9310		if (meta->mt_islast)
9311			break;
9312		slot = bwn_dma_nextslot(dr, slot);
9313	}
9314	sc->sc_watchdog_timer = 0;
9315	if (dr->dr_stop) {
9316		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9317		    ("%s:%d: fail", __func__, __LINE__));
9318		dr->dr_stop = 0;
9319	}
9320}
9321
9322static void
9323bwn_pio_handle_txeof(struct bwn_mac *mac,
9324    const struct bwn_txstatus *status)
9325{
9326	struct bwn_pio_txqueue *tq;
9327	struct bwn_pio_txpkt *tp = NULL;
9328	struct bwn_softc *sc = mac->mac_sc;
9329
9330	BWN_ASSERT_LOCKED(sc);
9331
9332	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9333	if (tq == NULL)
9334		return;
9335
9336	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9337	tq->tq_free++;
9338
9339	if (tp->tp_ni != NULL) {
9340		/*
9341		 * Do any tx complete callback.  Note this must
9342		 * be done before releasing the node reference.
9343		 */
9344		if (tp->tp_m->m_flags & M_TXCB)
9345			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9346		ieee80211_free_node(tp->tp_ni);
9347		tp->tp_ni = NULL;
9348	}
9349	m_freem(tp->tp_m);
9350	tp->tp_m = NULL;
9351	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9352
9353	sc->sc_watchdog_timer = 0;
9354}
9355
9356static void
9357bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9358{
9359	struct bwn_softc *sc = mac->mac_sc;
9360	struct bwn_phy *phy = &mac->mac_phy;
9361	struct ieee80211com *ic = &sc->sc_ic;
9362	unsigned long now;
9363	int result;
9364
9365	BWN_GETTIME(now);
9366
9367	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9368		return;
9369	phy->nexttime = now + 2 * 1000;
9370
9371	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9372	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9373		return;
9374
9375	if (phy->recalc_txpwr != NULL) {
9376		result = phy->recalc_txpwr(mac,
9377		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9378		if (result == BWN_TXPWR_RES_DONE)
9379			return;
9380		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9381		    ("%s: fail", __func__));
9382		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9383
9384		ieee80211_runtask(ic, &mac->mac_txpower);
9385	}
9386}
9387
9388static uint16_t
9389bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9390{
9391
9392	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9393}
9394
9395static uint32_t
9396bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9397{
9398
9399	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9400}
9401
9402static void
9403bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9404{
9405
9406	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9407}
9408
9409static void
9410bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9411{
9412
9413	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9414}
9415
9416static int
9417bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9418{
9419
9420	switch (rate) {
9421	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9422	case 12:
9423		return (BWN_OFDM_RATE_6MB);
9424	case 18:
9425		return (BWN_OFDM_RATE_9MB);
9426	case 24:
9427		return (BWN_OFDM_RATE_12MB);
9428	case 36:
9429		return (BWN_OFDM_RATE_18MB);
9430	case 48:
9431		return (BWN_OFDM_RATE_24MB);
9432	case 72:
9433		return (BWN_OFDM_RATE_36MB);
9434	case 96:
9435		return (BWN_OFDM_RATE_48MB);
9436	case 108:
9437		return (BWN_OFDM_RATE_54MB);
9438	/* CCK rates (NB: not IEEE std, device-specific) */
9439	case 2:
9440		return (BWN_CCK_RATE_1MB);
9441	case 4:
9442		return (BWN_CCK_RATE_2MB);
9443	case 11:
9444		return (BWN_CCK_RATE_5MB);
9445	case 22:
9446		return (BWN_CCK_RATE_11MB);
9447	}
9448
9449	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9450	return (BWN_CCK_RATE_1MB);
9451}
9452
9453static int
9454bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9455    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9456{
9457	const struct bwn_phy *phy = &mac->mac_phy;
9458	struct bwn_softc *sc = mac->mac_sc;
9459	struct ieee80211_frame *wh;
9460	struct ieee80211_frame *protwh;
9461	struct ieee80211_frame_cts *cts;
9462	struct ieee80211_frame_rts *rts;
9463	const struct ieee80211_txparam *tp;
9464	struct ieee80211vap *vap = ni->ni_vap;
9465	struct ieee80211com *ic = &sc->sc_ic;
9466	struct mbuf *mprot;
9467	unsigned int len;
9468	uint32_t macctl = 0;
9469	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9470	uint16_t phyctl = 0;
9471	uint8_t rate, rate_fb;
9472
9473	wh = mtod(m, struct ieee80211_frame *);
9474	memset(txhdr, 0, sizeof(*txhdr));
9475
9476	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9477	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9478	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9479
9480	/*
9481	 * Find TX rate
9482	 */
9483	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9484	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9485		rate = rate_fb = tp->mgmtrate;
9486	else if (ismcast)
9487		rate = rate_fb = tp->mcastrate;
9488	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9489		rate = rate_fb = tp->ucastrate;
9490	else {
9491		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9492		rate = ni->ni_txrate;
9493
9494		if (rix > 0)
9495			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9496			    IEEE80211_RATE_VAL;
9497		else
9498			rate_fb = rate;
9499	}
9500
9501	sc->sc_tx_rate = rate;
9502
9503	rate = bwn_ieeerate2hwrate(sc, rate);
9504	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9505
9506	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9507	    bwn_plcp_getcck(rate);
9508	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9509	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9510
9511	if ((rate_fb == rate) ||
9512	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9513	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9514		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9515	else
9516		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9517		    m->m_pkthdr.len, rate, isshort);
9518
9519	/* XXX TX encryption */
9520	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9521	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9522	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9523	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9524	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9525	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9526
9527	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9528	    BWN_TX_EFT_FB_CCK;
9529	txhdr->chan = phy->chan;
9530	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9531	    BWN_TX_PHY_ENC_CCK;
9532	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9533	     rate == BWN_CCK_RATE_11MB))
9534		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9535
9536	/* XXX TX antenna selection */
9537
9538	switch (bwn_antenna_sanitize(mac, 0)) {
9539	case 0:
9540		phyctl |= BWN_TX_PHY_ANT01AUTO;
9541		break;
9542	case 1:
9543		phyctl |= BWN_TX_PHY_ANT0;
9544		break;
9545	case 2:
9546		phyctl |= BWN_TX_PHY_ANT1;
9547		break;
9548	case 3:
9549		phyctl |= BWN_TX_PHY_ANT2;
9550		break;
9551	case 4:
9552		phyctl |= BWN_TX_PHY_ANT3;
9553		break;
9554	default:
9555		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9556	}
9557
9558	if (!ismcast)
9559		macctl |= BWN_TX_MAC_ACK;
9560
9561	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9562	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9563	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9564		macctl |= BWN_TX_MAC_LONGFRAME;
9565
9566	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9567		/* XXX RTS rate is always 1MB??? */
9568		rts_rate = BWN_CCK_RATE_1MB;
9569		rts_rate_fb = bwn_get_fbrate(rts_rate);
9570
9571		protdur = ieee80211_compute_duration(ic->ic_rt,
9572		    m->m_pkthdr.len, rate, isshort) +
9573		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9574
9575		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9576			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9577			    (txhdr->body.old.rts_frame) :
9578			    (txhdr->body.new.rts_frame));
9579			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9580			    protdur);
9581			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9582			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9583			    mprot->m_pkthdr.len);
9584			m_freem(mprot);
9585			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9586			len = sizeof(struct ieee80211_frame_cts);
9587		} else {
9588			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9589			    (txhdr->body.old.rts_frame) :
9590			    (txhdr->body.new.rts_frame));
9591			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9592			    isshort);
9593			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9594			    wh->i_addr2, protdur);
9595			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9596			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9597			    mprot->m_pkthdr.len);
9598			m_freem(mprot);
9599			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9600			len = sizeof(struct ieee80211_frame_rts);
9601		}
9602		len += IEEE80211_CRC_LEN;
9603		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9604		    &txhdr->body.old.rts_plcp :
9605		    &txhdr->body.new.rts_plcp), len, rts_rate);
9606		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9607		    rts_rate_fb);
9608
9609		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9610		    (&txhdr->body.old.rts_frame) :
9611		    (&txhdr->body.new.rts_frame));
9612		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9613
9614		if (BWN_ISOFDMRATE(rts_rate)) {
9615			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9616			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9617		} else {
9618			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9619			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9620		}
9621		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9622		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9623	}
9624
9625	if (BWN_ISOLDFMT(mac))
9626		txhdr->body.old.cookie = htole16(cookie);
9627	else
9628		txhdr->body.new.cookie = htole16(cookie);
9629
9630	txhdr->macctl = htole32(macctl);
9631	txhdr->phyctl = htole16(phyctl);
9632
9633	/*
9634	 * TX radio tap
9635	 */
9636	if (ieee80211_radiotap_active_vap(vap)) {
9637		sc->sc_tx_th.wt_flags = 0;
9638		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
9639			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9640		if (isshort &&
9641		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9642		     rate == BWN_CCK_RATE_11MB))
9643			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9644		sc->sc_tx_th.wt_rate = rate;
9645
9646		ieee80211_radiotap_tx(vap, m);
9647	}
9648
9649	return (0);
9650}
9651
9652static void
9653bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9654    const uint8_t rate)
9655{
9656	uint32_t d, plen;
9657	uint8_t *raw = plcp->o.raw;
9658
9659	if (BWN_ISOFDMRATE(rate)) {
9660		d = bwn_plcp_getofdm(rate);
9661		KASSERT(!(octets & 0xf000),
9662		    ("%s:%d: fail", __func__, __LINE__));
9663		d |= (octets << 5);
9664		plcp->o.data = htole32(d);
9665	} else {
9666		plen = octets * 16 / rate;
9667		if ((octets * 16 % rate) > 0) {
9668			plen++;
9669			if ((rate == BWN_CCK_RATE_11MB)
9670			    && ((octets * 8 % 11) < 4)) {
9671				raw[1] = 0x84;
9672			} else
9673				raw[1] = 0x04;
9674		} else
9675			raw[1] = 0x04;
9676		plcp->o.data |= htole32(plen << 16);
9677		raw[0] = bwn_plcp_getcck(rate);
9678	}
9679}
9680
9681static uint8_t
9682bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9683{
9684	struct bwn_softc *sc = mac->mac_sc;
9685	uint8_t mask;
9686
9687	if (n == 0)
9688		return (0);
9689	if (mac->mac_phy.gmode)
9690		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9691	else
9692		mask = siba_sprom_get_ant_a(sc->sc_dev);
9693	if (!(mask & (1 << (n - 1))))
9694		return (0);
9695	return (n);
9696}
9697
9698static uint8_t
9699bwn_get_fbrate(uint8_t bitrate)
9700{
9701	switch (bitrate) {
9702	case BWN_CCK_RATE_1MB:
9703		return (BWN_CCK_RATE_1MB);
9704	case BWN_CCK_RATE_2MB:
9705		return (BWN_CCK_RATE_1MB);
9706	case BWN_CCK_RATE_5MB:
9707		return (BWN_CCK_RATE_2MB);
9708	case BWN_CCK_RATE_11MB:
9709		return (BWN_CCK_RATE_5MB);
9710	case BWN_OFDM_RATE_6MB:
9711		return (BWN_CCK_RATE_5MB);
9712	case BWN_OFDM_RATE_9MB:
9713		return (BWN_OFDM_RATE_6MB);
9714	case BWN_OFDM_RATE_12MB:
9715		return (BWN_OFDM_RATE_9MB);
9716	case BWN_OFDM_RATE_18MB:
9717		return (BWN_OFDM_RATE_12MB);
9718	case BWN_OFDM_RATE_24MB:
9719		return (BWN_OFDM_RATE_18MB);
9720	case BWN_OFDM_RATE_36MB:
9721		return (BWN_OFDM_RATE_24MB);
9722	case BWN_OFDM_RATE_48MB:
9723		return (BWN_OFDM_RATE_36MB);
9724	case BWN_OFDM_RATE_54MB:
9725		return (BWN_OFDM_RATE_48MB);
9726	}
9727	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9728	return (0);
9729}
9730
9731static uint32_t
9732bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9733    uint32_t ctl, const void *_data, int len)
9734{
9735	struct bwn_softc *sc = mac->mac_sc;
9736	uint32_t value = 0;
9737	const uint8_t *data = _data;
9738
9739	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9740	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9741	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9742
9743	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9744	    tq->tq_base + BWN_PIO8_TXDATA);
9745	if (len & 3) {
9746		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9747		    BWN_PIO8_TXCTL_24_31);
9748		data = &(data[len - 1]);
9749		switch (len & 3) {
9750		case 3:
9751			ctl |= BWN_PIO8_TXCTL_16_23;
9752			value |= (uint32_t)(*data) << 16;
9753			data--;
9754		case 2:
9755			ctl |= BWN_PIO8_TXCTL_8_15;
9756			value |= (uint32_t)(*data) << 8;
9757			data--;
9758		case 1:
9759			value |= (uint32_t)(*data);
9760		}
9761		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9762		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9763	}
9764
9765	return (ctl);
9766}
9767
9768static void
9769bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9770    uint16_t offset, uint32_t value)
9771{
9772
9773	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9774}
9775
9776static uint16_t
9777bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9778    uint16_t ctl, const void *_data, int len)
9779{
9780	struct bwn_softc *sc = mac->mac_sc;
9781	const uint8_t *data = _data;
9782
9783	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9784	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9785
9786	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9787	    tq->tq_base + BWN_PIO_TXDATA);
9788	if (len & 1) {
9789		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9790		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9791		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9792	}
9793
9794	return (ctl);
9795}
9796
9797static uint16_t
9798bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9799    uint16_t ctl, struct mbuf *m0)
9800{
9801	int i, j = 0;
9802	uint16_t data = 0;
9803	const uint8_t *buf;
9804	struct mbuf *m = m0;
9805
9806	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9807	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9808
9809	for (; m != NULL; m = m->m_next) {
9810		buf = mtod(m, const uint8_t *);
9811		for (i = 0; i < m->m_len; i++) {
9812			if (!((j++) % 2))
9813				data |= buf[i];
9814			else {
9815				data |= (buf[i] << 8);
9816				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9817				data = 0;
9818			}
9819		}
9820	}
9821	if (m0->m_pkthdr.len % 2) {
9822		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9823		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9824		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9825	}
9826
9827	return (ctl);
9828}
9829
9830static void
9831bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9832{
9833
9834	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9835		return;
9836	BWN_WRITE_2(mac, 0x684, 510 + time);
9837	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9838}
9839
9840static struct bwn_dma_ring *
9841bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9842{
9843
9844	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9845		return (mac->mac_method.dma.wme[WME_AC_BE]);
9846
9847	switch (prio) {
9848	case 3:
9849		return (mac->mac_method.dma.wme[WME_AC_VO]);
9850	case 2:
9851		return (mac->mac_method.dma.wme[WME_AC_VI]);
9852	case 0:
9853		return (mac->mac_method.dma.wme[WME_AC_BE]);
9854	case 1:
9855		return (mac->mac_method.dma.wme[WME_AC_BK]);
9856	}
9857	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9858	return (NULL);
9859}
9860
9861static int
9862bwn_dma_getslot(struct bwn_dma_ring *dr)
9863{
9864	int slot;
9865
9866	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
9867
9868	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9869	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
9870	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
9871
9872	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
9873	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
9874	dr->dr_curslot = slot;
9875	dr->dr_usedslot++;
9876
9877	return (slot);
9878}
9879
9880static int
9881bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
9882{
9883	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
9884	unsigned int a, b, c, d;
9885	unsigned int avg;
9886	uint32_t tmp;
9887
9888	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
9889	a = tmp & 0xff;
9890	b = (tmp >> 8) & 0xff;
9891	c = (tmp >> 16) & 0xff;
9892	d = (tmp >> 24) & 0xff;
9893	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
9894	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
9895		return (ENOENT);
9896	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
9897	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
9898	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
9899
9900	if (ofdm) {
9901		a = (a + 32) & 0x3f;
9902		b = (b + 32) & 0x3f;
9903		c = (c + 32) & 0x3f;
9904		d = (d + 32) & 0x3f;
9905	}
9906
9907	avg = (a + b + c + d + 2) / 4;
9908	if (ofdm) {
9909		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
9910		    & BWN_HF_4DB_CCK_POWERBOOST)
9911			avg = (avg >= 13) ? (avg - 13) : 0;
9912	}
9913	return (avg);
9914}
9915
9916static void
9917bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
9918{
9919	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
9920	int rfatt = *rfattp;
9921	int bbatt = *bbattp;
9922
9923	while (1) {
9924		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
9925			break;
9926		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
9927			break;
9928		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
9929			break;
9930		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
9931			break;
9932		if (bbatt > lo->bbatt.max) {
9933			bbatt -= 4;
9934			rfatt += 1;
9935			continue;
9936		}
9937		if (bbatt < lo->bbatt.min) {
9938			bbatt += 4;
9939			rfatt -= 1;
9940			continue;
9941		}
9942		if (rfatt > lo->rfatt.max) {
9943			rfatt -= 1;
9944			bbatt += 4;
9945			continue;
9946		}
9947		if (rfatt < lo->rfatt.min) {
9948			rfatt += 1;
9949			bbatt -= 4;
9950			continue;
9951		}
9952		break;
9953	}
9954
9955	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
9956	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
9957}
9958
9959static void
9960bwn_phy_lock(struct bwn_mac *mac)
9961{
9962	struct bwn_softc *sc = mac->mac_sc;
9963	struct ieee80211com *ic = &sc->sc_ic;
9964
9965	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9966	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9967
9968	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9969		bwn_psctl(mac, BWN_PS_AWAKE);
9970}
9971
9972static void
9973bwn_phy_unlock(struct bwn_mac *mac)
9974{
9975	struct bwn_softc *sc = mac->mac_sc;
9976	struct ieee80211com *ic = &sc->sc_ic;
9977
9978	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9979	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9980
9981	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9982		bwn_psctl(mac, 0);
9983}
9984
9985static void
9986bwn_rf_lock(struct bwn_mac *mac)
9987{
9988
9989	BWN_WRITE_4(mac, BWN_MACCTL,
9990	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
9991	BWN_READ_4(mac, BWN_MACCTL);
9992	DELAY(10);
9993}
9994
9995static void
9996bwn_rf_unlock(struct bwn_mac *mac)
9997{
9998
9999	BWN_READ_2(mac, BWN_PHYVER);
10000	BWN_WRITE_4(mac, BWN_MACCTL,
10001	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10002}
10003
10004static struct bwn_pio_txqueue *
10005bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10006    struct bwn_pio_txpkt **pack)
10007{
10008	struct bwn_pio *pio = &mac->mac_method.pio;
10009	struct bwn_pio_txqueue *tq = NULL;
10010	unsigned int index;
10011
10012	switch (cookie & 0xf000) {
10013	case 0x1000:
10014		tq = &pio->wme[WME_AC_BK];
10015		break;
10016	case 0x2000:
10017		tq = &pio->wme[WME_AC_BE];
10018		break;
10019	case 0x3000:
10020		tq = &pio->wme[WME_AC_VI];
10021		break;
10022	case 0x4000:
10023		tq = &pio->wme[WME_AC_VO];
10024		break;
10025	case 0x5000:
10026		tq = &pio->mcast;
10027		break;
10028	}
10029	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10030	if (tq == NULL)
10031		return (NULL);
10032	index = (cookie & 0x0fff);
10033	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10034	if (index >= N(tq->tq_pkts))
10035		return (NULL);
10036	*pack = &tq->tq_pkts[index];
10037	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10038	return (tq);
10039}
10040
10041static void
10042bwn_txpwr(void *arg, int npending)
10043{
10044	struct bwn_mac *mac = arg;
10045	struct bwn_softc *sc = mac->mac_sc;
10046
10047	BWN_LOCK(sc);
10048	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10049	    mac->mac_phy.set_txpwr != NULL)
10050		mac->mac_phy.set_txpwr(mac);
10051	BWN_UNLOCK(sc);
10052}
10053
10054static void
10055bwn_task_15s(struct bwn_mac *mac)
10056{
10057	uint16_t reg;
10058
10059	if (mac->mac_fw.opensource) {
10060		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10061		if (reg) {
10062			bwn_restart(mac, "fw watchdog");
10063			return;
10064		}
10065		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10066	}
10067	if (mac->mac_phy.task_15s)
10068		mac->mac_phy.task_15s(mac);
10069
10070	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10071}
10072
10073static void
10074bwn_task_30s(struct bwn_mac *mac)
10075{
10076
10077	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10078		return;
10079	mac->mac_noise.noi_running = 1;
10080	mac->mac_noise.noi_nsamples = 0;
10081
10082	bwn_noise_gensample(mac);
10083}
10084
10085static void
10086bwn_task_60s(struct bwn_mac *mac)
10087{
10088
10089	if (mac->mac_phy.task_60s)
10090		mac->mac_phy.task_60s(mac);
10091	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10092}
10093
10094static void
10095bwn_tasks(void *arg)
10096{
10097	struct bwn_mac *mac = arg;
10098	struct bwn_softc *sc = mac->mac_sc;
10099
10100	BWN_ASSERT_LOCKED(sc);
10101	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10102		return;
10103
10104	if (mac->mac_task_state % 4 == 0)
10105		bwn_task_60s(mac);
10106	if (mac->mac_task_state % 2 == 0)
10107		bwn_task_30s(mac);
10108	bwn_task_15s(mac);
10109
10110	mac->mac_task_state++;
10111	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10112}
10113
10114static int
10115bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10116{
10117	struct bwn_softc *sc = mac->mac_sc;
10118
10119	KASSERT(a == 0, ("not support APHY\n"));
10120
10121	switch (plcp->o.raw[0] & 0xf) {
10122	case 0xb:
10123		return (BWN_OFDM_RATE_6MB);
10124	case 0xf:
10125		return (BWN_OFDM_RATE_9MB);
10126	case 0xa:
10127		return (BWN_OFDM_RATE_12MB);
10128	case 0xe:
10129		return (BWN_OFDM_RATE_18MB);
10130	case 0x9:
10131		return (BWN_OFDM_RATE_24MB);
10132	case 0xd:
10133		return (BWN_OFDM_RATE_36MB);
10134	case 0x8:
10135		return (BWN_OFDM_RATE_48MB);
10136	case 0xc:
10137		return (BWN_OFDM_RATE_54MB);
10138	}
10139	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10140	    plcp->o.raw[0] & 0xf);
10141	return (-1);
10142}
10143
10144static int
10145bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10146{
10147	struct bwn_softc *sc = mac->mac_sc;
10148
10149	switch (plcp->o.raw[0]) {
10150	case 0x0a:
10151		return (BWN_CCK_RATE_1MB);
10152	case 0x14:
10153		return (BWN_CCK_RATE_2MB);
10154	case 0x37:
10155		return (BWN_CCK_RATE_5MB);
10156	case 0x6e:
10157		return (BWN_CCK_RATE_11MB);
10158	}
10159	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10160	return (-1);
10161}
10162
10163static void
10164bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10165    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10166    int rssi, int noise)
10167{
10168	struct bwn_softc *sc = mac->mac_sc;
10169	const struct ieee80211_frame_min *wh;
10170	uint64_t tsf;
10171	uint16_t low_mactime_now;
10172
10173	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10174		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10175
10176	wh = mtod(m, const struct ieee80211_frame_min *);
10177	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
10178		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10179
10180	bwn_tsf_read(mac, &tsf);
10181	low_mactime_now = tsf;
10182	tsf = tsf & ~0xffffULL;
10183	tsf += le16toh(rxhdr->mac_time);
10184	if (low_mactime_now < le16toh(rxhdr->mac_time))
10185		tsf -= 0x10000;
10186
10187	sc->sc_rx_th.wr_tsf = tsf;
10188	sc->sc_rx_th.wr_rate = rate;
10189	sc->sc_rx_th.wr_antsignal = rssi;
10190	sc->sc_rx_th.wr_antnoise = noise;
10191}
10192
10193static void
10194bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10195{
10196	uint32_t low, high;
10197
10198	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10199	    ("%s:%d: fail", __func__, __LINE__));
10200
10201	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10202	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10203	*tsf = high;
10204	*tsf <<= 32;
10205	*tsf |= low;
10206}
10207
10208static int
10209bwn_dma_attach(struct bwn_mac *mac)
10210{
10211	struct bwn_dma *dma = &mac->mac_method.dma;
10212	struct bwn_softc *sc = mac->mac_sc;
10213	bus_addr_t lowaddr = 0;
10214	int error;
10215
10216	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10217		return (0);
10218
10219	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10220
10221	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10222
10223	dma->dmatype = bwn_dma_gettype(mac);
10224	if (dma->dmatype == BWN_DMA_30BIT)
10225		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10226	else if (dma->dmatype == BWN_DMA_32BIT)
10227		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10228	else
10229		lowaddr = BUS_SPACE_MAXADDR;
10230
10231	/*
10232	 * Create top level DMA tag
10233	 */
10234	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10235			       BWN_ALIGN, 0,		/* alignment, bounds */
10236			       lowaddr,			/* lowaddr */
10237			       BUS_SPACE_MAXADDR,	/* highaddr */
10238			       NULL, NULL,		/* filter, filterarg */
10239			       BUS_SPACE_MAXSIZE,	/* maxsize */
10240			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10241			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10242			       0,			/* flags */
10243			       NULL, NULL,		/* lockfunc, lockarg */
10244			       &dma->parent_dtag);
10245	if (error) {
10246		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10247		return (error);
10248	}
10249
10250	/*
10251	 * Create TX/RX mbuf DMA tag
10252	 */
10253	error = bus_dma_tag_create(dma->parent_dtag,
10254				1,
10255				0,
10256				BUS_SPACE_MAXADDR,
10257				BUS_SPACE_MAXADDR,
10258				NULL, NULL,
10259				MCLBYTES,
10260				1,
10261				BUS_SPACE_MAXSIZE_32BIT,
10262				0,
10263				NULL, NULL,
10264				&dma->rxbuf_dtag);
10265	if (error) {
10266		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10267		goto fail0;
10268	}
10269	error = bus_dma_tag_create(dma->parent_dtag,
10270				1,
10271				0,
10272				BUS_SPACE_MAXADDR,
10273				BUS_SPACE_MAXADDR,
10274				NULL, NULL,
10275				MCLBYTES,
10276				1,
10277				BUS_SPACE_MAXSIZE_32BIT,
10278				0,
10279				NULL, NULL,
10280				&dma->txbuf_dtag);
10281	if (error) {
10282		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10283		goto fail1;
10284	}
10285
10286	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10287	if (!dma->wme[WME_AC_BK])
10288		goto fail2;
10289
10290	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10291	if (!dma->wme[WME_AC_BE])
10292		goto fail3;
10293
10294	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10295	if (!dma->wme[WME_AC_VI])
10296		goto fail4;
10297
10298	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10299	if (!dma->wme[WME_AC_VO])
10300		goto fail5;
10301
10302	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10303	if (!dma->mcast)
10304		goto fail6;
10305	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10306	if (!dma->rx)
10307		goto fail7;
10308
10309	return (error);
10310
10311fail7:	bwn_dma_ringfree(&dma->mcast);
10312fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10313fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10314fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10315fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10316fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10317fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10318fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10319	return (error);
10320}
10321
10322static struct bwn_dma_ring *
10323bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10324    uint16_t cookie, int *slot)
10325{
10326	struct bwn_dma *dma = &mac->mac_method.dma;
10327	struct bwn_dma_ring *dr;
10328	struct bwn_softc *sc = mac->mac_sc;
10329
10330	BWN_ASSERT_LOCKED(mac->mac_sc);
10331
10332	switch (cookie & 0xf000) {
10333	case 0x1000:
10334		dr = dma->wme[WME_AC_BK];
10335		break;
10336	case 0x2000:
10337		dr = dma->wme[WME_AC_BE];
10338		break;
10339	case 0x3000:
10340		dr = dma->wme[WME_AC_VI];
10341		break;
10342	case 0x4000:
10343		dr = dma->wme[WME_AC_VO];
10344		break;
10345	case 0x5000:
10346		dr = dma->mcast;
10347		break;
10348	default:
10349		dr = NULL;
10350		KASSERT(0 == 1,
10351		    ("invalid cookie value %d", cookie & 0xf000));
10352	}
10353	*slot = (cookie & 0x0fff);
10354	if (*slot < 0 || *slot >= dr->dr_numslots) {
10355		/*
10356		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10357		 * that it occurs events which have same H/W sequence numbers.
10358		 * When it's occurred just prints a WARNING msgs and ignores.
10359		 */
10360		KASSERT(status->seq == dma->lastseq,
10361		    ("%s:%d: fail", __func__, __LINE__));
10362		device_printf(sc->sc_dev,
10363		    "out of slot ranges (0 < %d < %d)\n", *slot,
10364		    dr->dr_numslots);
10365		return (NULL);
10366	}
10367	dma->lastseq = status->seq;
10368	return (dr);
10369}
10370
10371static void
10372bwn_dma_stop(struct bwn_mac *mac)
10373{
10374	struct bwn_dma *dma;
10375
10376	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10377		return;
10378	dma = &mac->mac_method.dma;
10379
10380	bwn_dma_ringstop(&dma->rx);
10381	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10382	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10383	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10384	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10385	bwn_dma_ringstop(&dma->mcast);
10386}
10387
10388static void
10389bwn_dma_ringstop(struct bwn_dma_ring **dr)
10390{
10391
10392	if (dr == NULL)
10393		return;
10394
10395	bwn_dma_cleanup(*dr);
10396}
10397
10398static void
10399bwn_pio_stop(struct bwn_mac *mac)
10400{
10401	struct bwn_pio *pio;
10402
10403	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10404		return;
10405	pio = &mac->mac_method.pio;
10406
10407	bwn_destroy_queue_tx(&pio->mcast);
10408	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10409	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10410	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10411	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10412}
10413
10414static void
10415bwn_led_attach(struct bwn_mac *mac)
10416{
10417	struct bwn_softc *sc = mac->mac_sc;
10418	const uint8_t *led_act = NULL;
10419	uint16_t val[BWN_LED_MAX];
10420	int i;
10421
10422	sc->sc_led_idle = (2350 * hz) / 1000;
10423	sc->sc_led_blink = 1;
10424
10425	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10426		if (siba_get_pci_subvendor(sc->sc_dev) ==
10427		    bwn_vendor_led_act[i].vid) {
10428			led_act = bwn_vendor_led_act[i].led_act;
10429			break;
10430		}
10431	}
10432	if (led_act == NULL)
10433		led_act = bwn_default_led_act;
10434
10435	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10436	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10437	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10438	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10439
10440	for (i = 0; i < BWN_LED_MAX; ++i) {
10441		struct bwn_led *led = &sc->sc_leds[i];
10442
10443		if (val[i] == 0xff) {
10444			led->led_act = led_act[i];
10445		} else {
10446			if (val[i] & BWN_LED_ACT_LOW)
10447				led->led_flags |= BWN_LED_F_ACTLOW;
10448			led->led_act = val[i] & BWN_LED_ACT_MASK;
10449		}
10450		led->led_mask = (1 << i);
10451
10452		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10453		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10454		    led->led_act == BWN_LED_ACT_BLINK) {
10455			led->led_flags |= BWN_LED_F_BLINK;
10456			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10457				led->led_flags |= BWN_LED_F_POLLABLE;
10458			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10459				led->led_flags |= BWN_LED_F_SLOW;
10460
10461			if (sc->sc_blink_led == NULL) {
10462				sc->sc_blink_led = led;
10463				if (led->led_flags & BWN_LED_F_SLOW)
10464					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10465			}
10466		}
10467
10468		DPRINTF(sc, BWN_DEBUG_LED,
10469		    "%dth led, act %d, lowact %d\n", i,
10470		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10471	}
10472	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10473}
10474
10475static __inline uint16_t
10476bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10477{
10478
10479	if (led->led_flags & BWN_LED_F_ACTLOW)
10480		on = !on;
10481	if (on)
10482		val |= led->led_mask;
10483	else
10484		val &= ~led->led_mask;
10485	return val;
10486}
10487
10488static void
10489bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10490{
10491	struct bwn_softc *sc = mac->mac_sc;
10492	struct ieee80211com *ic = &sc->sc_ic;
10493	uint16_t val;
10494	int i;
10495
10496	if (nstate == IEEE80211_S_INIT) {
10497		callout_stop(&sc->sc_led_blink_ch);
10498		sc->sc_led_blinking = 0;
10499	}
10500
10501	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
10502		return;
10503
10504	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10505	for (i = 0; i < BWN_LED_MAX; ++i) {
10506		struct bwn_led *led = &sc->sc_leds[i];
10507		int on;
10508
10509		if (led->led_act == BWN_LED_ACT_UNKN ||
10510		    led->led_act == BWN_LED_ACT_NULL)
10511			continue;
10512
10513		if ((led->led_flags & BWN_LED_F_BLINK) &&
10514		    nstate != IEEE80211_S_INIT)
10515			continue;
10516
10517		switch (led->led_act) {
10518		case BWN_LED_ACT_ON:    /* Always on */
10519			on = 1;
10520			break;
10521		case BWN_LED_ACT_OFF:   /* Always off */
10522		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10523			on = 0;
10524			break;
10525		default:
10526			on = 1;
10527			switch (nstate) {
10528			case IEEE80211_S_INIT:
10529				on = 0;
10530				break;
10531			case IEEE80211_S_RUN:
10532				if (led->led_act == BWN_LED_ACT_11G &&
10533				    ic->ic_curmode != IEEE80211_MODE_11G)
10534					on = 0;
10535				break;
10536			default:
10537				if (led->led_act == BWN_LED_ACT_ASSOC)
10538					on = 0;
10539				break;
10540			}
10541			break;
10542		}
10543
10544		val = bwn_led_onoff(led, val, on);
10545	}
10546	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10547}
10548
10549static void
10550bwn_led_event(struct bwn_mac *mac, int event)
10551{
10552	struct bwn_softc *sc = mac->mac_sc;
10553	struct bwn_led *led = sc->sc_blink_led;
10554	int rate;
10555
10556	if (event == BWN_LED_EVENT_POLL) {
10557		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10558			return;
10559		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10560			return;
10561	}
10562
10563	sc->sc_led_ticks = ticks;
10564	if (sc->sc_led_blinking)
10565		return;
10566
10567	switch (event) {
10568	case BWN_LED_EVENT_RX:
10569		rate = sc->sc_rx_rate;
10570		break;
10571	case BWN_LED_EVENT_TX:
10572		rate = sc->sc_tx_rate;
10573		break;
10574	case BWN_LED_EVENT_POLL:
10575		rate = 0;
10576		break;
10577	default:
10578		panic("unknown LED event %d\n", event);
10579		break;
10580	}
10581	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10582	    bwn_led_duration[rate].off_dur);
10583}
10584
10585static void
10586bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10587{
10588	struct bwn_softc *sc = mac->mac_sc;
10589	struct bwn_led *led = sc->sc_blink_led;
10590	uint16_t val;
10591
10592	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10593	val = bwn_led_onoff(led, val, 1);
10594	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10595
10596	if (led->led_flags & BWN_LED_F_SLOW) {
10597		BWN_LED_SLOWDOWN(on_dur);
10598		BWN_LED_SLOWDOWN(off_dur);
10599	}
10600
10601	sc->sc_led_blinking = 1;
10602	sc->sc_led_blink_offdur = off_dur;
10603
10604	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10605}
10606
10607static void
10608bwn_led_blink_next(void *arg)
10609{
10610	struct bwn_mac *mac = arg;
10611	struct bwn_softc *sc = mac->mac_sc;
10612	uint16_t val;
10613
10614	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10615	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10616	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10617
10618	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10619	    bwn_led_blink_end, mac);
10620}
10621
10622static void
10623bwn_led_blink_end(void *arg)
10624{
10625	struct bwn_mac *mac = arg;
10626	struct bwn_softc *sc = mac->mac_sc;
10627
10628	sc->sc_led_blinking = 0;
10629}
10630
10631static int
10632bwn_suspend(device_t dev)
10633{
10634	struct bwn_softc *sc = device_get_softc(dev);
10635
10636	BWN_LOCK(sc);
10637	bwn_stop(sc);
10638	BWN_UNLOCK(sc);
10639	return (0);
10640}
10641
10642static int
10643bwn_resume(device_t dev)
10644{
10645	struct bwn_softc *sc = device_get_softc(dev);
10646	int error = EDOOFUS;
10647
10648	BWN_LOCK(sc);
10649	if (sc->sc_ic.ic_nrunning > 0)
10650		error = bwn_init(sc);
10651	BWN_UNLOCK(sc);
10652	if (error == 0)
10653		ieee80211_start_all(&sc->sc_ic);
10654	return (0);
10655}
10656
10657static void
10658bwn_rfswitch(void *arg)
10659{
10660	struct bwn_softc *sc = arg;
10661	struct bwn_mac *mac = sc->sc_curmac;
10662	int cur = 0, prev = 0;
10663
10664	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10665	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10666
10667	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10668		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10669			& BWN_RF_HWENABLED_HI_MASK))
10670			cur = 1;
10671	} else {
10672		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10673		    & BWN_RF_HWENABLED_LO_MASK)
10674			cur = 1;
10675	}
10676
10677	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10678		prev = 1;
10679
10680	if (cur != prev) {
10681		if (cur)
10682			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10683		else
10684			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10685
10686		device_printf(sc->sc_dev,
10687		    "status of RF switch is changed to %s\n",
10688		    cur ? "ON" : "OFF");
10689		if (cur != mac->mac_phy.rf_on) {
10690			if (cur)
10691				bwn_rf_turnon(mac);
10692			else
10693				bwn_rf_turnoff(mac);
10694		}
10695	}
10696
10697	callout_schedule(&sc->sc_rfswitch_ch, hz);
10698}
10699
10700static void
10701bwn_phy_lp_init_pre(struct bwn_mac *mac)
10702{
10703	struct bwn_phy *phy = &mac->mac_phy;
10704	struct bwn_phy_lp *plp = &phy->phy_lp;
10705
10706	plp->plp_antenna = BWN_ANT_DEFAULT;
10707}
10708
10709static int
10710bwn_phy_lp_init(struct bwn_mac *mac)
10711{
10712	static const struct bwn_stxtable tables[] = {
10713		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10714		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10715		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10716		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10717		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10718		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10719		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10720		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10721		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10722		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10723		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10724		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10725		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10726		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10727		{ 2, 11, 0x40, 0, 0x0f }
10728	};
10729	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10730	struct bwn_softc *sc = mac->mac_sc;
10731	const struct bwn_stxtable *st;
10732	struct ieee80211com *ic = &sc->sc_ic;
10733	int i, error;
10734	uint16_t tmp;
10735
10736	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10737	bwn_phy_lp_bbinit(mac);
10738
10739	/* initialize RF */
10740	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10741	DELAY(1);
10742	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10743	DELAY(1);
10744
10745	if (mac->mac_phy.rf_ver == 0x2062)
10746		bwn_phy_lp_b2062_init(mac);
10747	else {
10748		bwn_phy_lp_b2063_init(mac);
10749
10750		/* synchronize stx table. */
10751		for (i = 0; i < N(tables); i++) {
10752			st = &tables[i];
10753			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10754			tmp >>= st->st_rfshift;
10755			tmp <<= st->st_physhift;
10756			BWN_PHY_SETMASK(mac,
10757			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10758			    ~(st->st_mask << st->st_physhift), tmp);
10759		}
10760
10761		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10762		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10763	}
10764
10765	/* calibrate RC */
10766	if (mac->mac_phy.rev >= 2)
10767		bwn_phy_lp_rxcal_r2(mac);
10768	else if (!plp->plp_rccap) {
10769		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10770			bwn_phy_lp_rccal_r12(mac);
10771	} else
10772		bwn_phy_lp_set_rccap(mac);
10773
10774	error = bwn_phy_lp_switch_channel(mac, 7);
10775	if (error)
10776		device_printf(sc->sc_dev,
10777		    "failed to change channel 7 (%d)\n", error);
10778	bwn_phy_lp_txpctl_init(mac);
10779	bwn_phy_lp_calib(mac);
10780	return (0);
10781}
10782
10783static uint16_t
10784bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10785{
10786
10787	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10788	return (BWN_READ_2(mac, BWN_PHYDATA));
10789}
10790
10791static void
10792bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10793{
10794
10795	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10796	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10797}
10798
10799static void
10800bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10801    uint16_t set)
10802{
10803
10804	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10805	BWN_WRITE_2(mac, BWN_PHYDATA,
10806	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10807}
10808
10809static uint16_t
10810bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10811{
10812
10813	KASSERT(reg != 1, ("unaccessible register %d", reg));
10814	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10815		reg |= 0x100;
10816	if (mac->mac_phy.rev >= 2)
10817		reg |= 0x200;
10818	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10819	return BWN_READ_2(mac, BWN_RFDATALO);
10820}
10821
10822static void
10823bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10824{
10825
10826	KASSERT(reg != 1, ("unaccessible register %d", reg));
10827	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10828	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10829}
10830
10831static void
10832bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10833{
10834
10835	if (on) {
10836		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10837		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10838		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10839		return;
10840	}
10841
10842	if (mac->mac_phy.rev >= 2) {
10843		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10844		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10845		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10846		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10847		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10848		return;
10849	}
10850
10851	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10852	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10853	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10854	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10855}
10856
10857static int
10858bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10859{
10860	struct bwn_phy *phy = &mac->mac_phy;
10861	struct bwn_phy_lp *plp = &phy->phy_lp;
10862	int error;
10863
10864	if (phy->rf_ver == 0x2063) {
10865		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
10866		if (error)
10867			return (error);
10868	} else {
10869		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
10870		if (error)
10871			return (error);
10872		bwn_phy_lp_set_anafilter(mac, chan);
10873		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
10874	}
10875
10876	plp->plp_chan = chan;
10877	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
10878	return (0);
10879}
10880
10881static uint32_t
10882bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
10883{
10884	struct bwn_softc *sc = mac->mac_sc;
10885	struct ieee80211com *ic = &sc->sc_ic;
10886
10887	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
10888}
10889
10890static void
10891bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
10892{
10893	struct bwn_phy *phy = &mac->mac_phy;
10894	struct bwn_phy_lp *plp = &phy->phy_lp;
10895
10896	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
10897		return;
10898
10899	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
10900	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
10901	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
10902	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
10903	plp->plp_antenna = antenna;
10904}
10905
10906static void
10907bwn_phy_lp_task_60s(struct bwn_mac *mac)
10908{
10909
10910	bwn_phy_lp_calib(mac);
10911}
10912
10913static void
10914bwn_phy_lp_readsprom(struct bwn_mac *mac)
10915{
10916	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10917	struct bwn_softc *sc = mac->mac_sc;
10918	struct ieee80211com *ic = &sc->sc_ic;
10919
10920	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
10921		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
10922		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
10923		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
10924		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
10925		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
10926		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
10927		return;
10928	}
10929
10930	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
10931	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
10932	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
10933	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
10934	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
10935	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
10936	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
10937	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
10938}
10939
10940static void
10941bwn_phy_lp_bbinit(struct bwn_mac *mac)
10942{
10943
10944	bwn_phy_lp_tblinit(mac);
10945	if (mac->mac_phy.rev >= 2)
10946		bwn_phy_lp_bbinit_r2(mac);
10947	else
10948		bwn_phy_lp_bbinit_r01(mac);
10949}
10950
10951static void
10952bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
10953{
10954	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
10955	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
10956	struct bwn_softc *sc = mac->mac_sc;
10957	struct ieee80211com *ic = &sc->sc_ic;
10958
10959	bwn_phy_lp_set_txgain(mac,
10960	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
10961	bwn_phy_lp_set_bbmult(mac, 150);
10962}
10963
10964static void
10965bwn_phy_lp_calib(struct bwn_mac *mac)
10966{
10967	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10968	struct bwn_softc *sc = mac->mac_sc;
10969	struct ieee80211com *ic = &sc->sc_ic;
10970	const struct bwn_rxcompco *rc = NULL;
10971	struct bwn_txgain ogain;
10972	int i, omode, oafeovr, orf, obbmult;
10973	uint8_t mode, fc = 0;
10974
10975	if (plp->plp_chanfullcal != plp->plp_chan) {
10976		plp->plp_chanfullcal = plp->plp_chan;
10977		fc = 1;
10978	}
10979
10980	bwn_mac_suspend(mac);
10981
10982	/* BlueTooth Coexistance Override */
10983	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
10984	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
10985
10986	if (mac->mac_phy.rev >= 2)
10987		bwn_phy_lp_digflt_save(mac);
10988	bwn_phy_lp_get_txpctlmode(mac);
10989	mode = plp->plp_txpctlmode;
10990	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
10991	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
10992		bwn_phy_lp_bugfix(mac);
10993	if (mac->mac_phy.rev >= 2 && fc == 1) {
10994		bwn_phy_lp_get_txpctlmode(mac);
10995		omode = plp->plp_txpctlmode;
10996		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
10997		if (oafeovr)
10998			ogain = bwn_phy_lp_get_txgain(mac);
10999		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11000		obbmult = bwn_phy_lp_get_bbmult(mac);
11001		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11002		if (oafeovr)
11003			bwn_phy_lp_set_txgain(mac, &ogain);
11004		bwn_phy_lp_set_bbmult(mac, obbmult);
11005		bwn_phy_lp_set_txpctlmode(mac, omode);
11006		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11007	}
11008	bwn_phy_lp_set_txpctlmode(mac, mode);
11009	if (mac->mac_phy.rev >= 2)
11010		bwn_phy_lp_digflt_restore(mac);
11011
11012	/* do RX IQ Calculation; assumes that noise is true. */
11013	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11014		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11015			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11016				rc = &bwn_rxcompco_5354[i];
11017		}
11018	} else if (mac->mac_phy.rev >= 2)
11019		rc = &bwn_rxcompco_r2;
11020	else {
11021		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11022			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11023				rc = &bwn_rxcompco_r12[i];
11024		}
11025	}
11026	if (rc == NULL)
11027		goto fail;
11028
11029	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11030	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11031
11032	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11033
11034	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11035		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11036		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11037	} else {
11038		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11039		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11040	}
11041
11042	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11043	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11044	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11045	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11046	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11047	bwn_phy_lp_set_deaf(mac, 0);
11048	/* XXX no checking return value? */
11049	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11050	bwn_phy_lp_clear_deaf(mac, 0);
11051	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11052	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11053	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11054
11055	/* disable RX GAIN override. */
11056	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11057	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11058	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11059	if (mac->mac_phy.rev >= 2) {
11060		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11061		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11062			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11063			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11064		}
11065	} else {
11066		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11067	}
11068
11069	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11070	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11071fail:
11072	bwn_mac_enable(mac);
11073}
11074
11075static void
11076bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11077{
11078
11079	if (on) {
11080		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11081		return;
11082	}
11083
11084	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11085	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11086}
11087
11088static int
11089bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11090{
11091	static const struct bwn_b206x_chan *bc = NULL;
11092	struct bwn_softc *sc = mac->mac_sc;
11093	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11094	    tmp[6];
11095	uint16_t old, scale, tmp16;
11096	int i, div;
11097
11098	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11099		if (bwn_b2063_chantable[i].bc_chan == chan) {
11100			bc = &bwn_b2063_chantable[i];
11101			break;
11102		}
11103	}
11104	if (bc == NULL)
11105		return (EINVAL);
11106
11107	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11108	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11109	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11110	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11111	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11112	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11113	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11114	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11115	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11116	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11117	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11118	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11119
11120	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11121	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11122
11123	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11124	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11125	freqref = freqxtal * 3;
11126	div = (freqxtal <= 26000000 ? 1 : 2);
11127	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11128	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11129		999999) / 1000000) + 1;
11130
11131	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11132	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11133	    0xfff8, timeout >> 2);
11134	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11135	    0xff9f,timeout << 5);
11136	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11137
11138	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11139	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11140	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11141
11142	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11143	    (timeoutref + 1)) - 1;
11144	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11145	    0xf0, count >> 8);
11146	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11147
11148	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11149	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11150	while (tmp[1] >= freqref) {
11151		tmp[0]++;
11152		tmp[1] -= freqref;
11153	}
11154	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11155	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11156	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11157	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11158	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11159
11160	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11161	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11162	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11163	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11164
11165	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11166	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11167
11168	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11169		scale = 1;
11170		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11171	} else {
11172		scale = 0;
11173		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11174	}
11175	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11176	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11177
11178	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11179	    (scale + 1);
11180	if (tmp[5] > 150)
11181		tmp[5] = 0;
11182
11183	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11184	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11185
11186	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11187	if (freqxtal > 26000000)
11188		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11189	else
11190		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11191
11192	if (val[0] == 45)
11193		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11194	else
11195		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11196
11197	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11198	DELAY(1);
11199	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11200
11201	/* VCO Calibration */
11202	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11203	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11204	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11205	DELAY(1);
11206	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11207	DELAY(1);
11208	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11209	DELAY(1);
11210	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11211	DELAY(300);
11212	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11213
11214	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11215	return (0);
11216}
11217
11218static int
11219bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11220{
11221	struct bwn_softc *sc = mac->mac_sc;
11222	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11223	const struct bwn_b206x_chan *bc = NULL;
11224	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11225	uint32_t tmp[9];
11226	int i;
11227
11228	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11229		if (bwn_b2062_chantable[i].bc_chan == chan) {
11230			bc = &bwn_b2062_chantable[i];
11231			break;
11232		}
11233	}
11234
11235	if (bc == NULL)
11236		return (EINVAL);
11237
11238	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11239	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11240	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11241	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11242	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11243	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11244	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11245	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11246	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11247	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11248
11249	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11250	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11251	bwn_phy_lp_b2062_reset_pllbias(mac);
11252	tmp[0] = freqxtal / 1000;
11253	tmp[1] = plp->plp_div * 1000;
11254	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11255	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11256		tmp[2] *= 2;
11257	tmp[3] = 48 * tmp[0];
11258	tmp[5] = tmp[2] / tmp[3];
11259	tmp[6] = tmp[2] % tmp[3];
11260	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11261	tmp[4] = tmp[6] * 0x100;
11262	tmp[5] = tmp[4] / tmp[3];
11263	tmp[6] = tmp[4] % tmp[3];
11264	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, 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_RFPLLCTL28, 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_RFPLLCTL29,
11273	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11274	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11275	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11276	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11277	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11278
11279	bwn_phy_lp_b2062_vco_calib(mac);
11280	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11281		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11282		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11283		bwn_phy_lp_b2062_reset_pllbias(mac);
11284		bwn_phy_lp_b2062_vco_calib(mac);
11285		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11286			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11287			return (EIO);
11288		}
11289	}
11290	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11291	return (0);
11292}
11293
11294static void
11295bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11296{
11297	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11298	uint16_t tmp = (channel == 14);
11299
11300	if (mac->mac_phy.rev < 2) {
11301		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11302		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11303			bwn_phy_lp_set_rccap(mac);
11304		return;
11305	}
11306
11307	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11308}
11309
11310static void
11311bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11312{
11313	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11314	struct bwn_softc *sc = mac->mac_sc;
11315	struct ieee80211com *ic = &sc->sc_ic;
11316	uint16_t iso, tmp[3];
11317
11318	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11319
11320	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11321		iso = plp->plp_txisoband_m;
11322	else if (freq <= 5320)
11323		iso = plp->plp_txisoband_l;
11324	else if (freq <= 5700)
11325		iso = plp->plp_txisoband_m;
11326	else
11327		iso = plp->plp_txisoband_h;
11328
11329	tmp[0] = ((iso - 26) / 12) << 12;
11330	tmp[1] = tmp[0] + 0x1000;
11331	tmp[2] = tmp[0] + 0x2000;
11332
11333	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11334	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11335}
11336
11337static void
11338bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11339{
11340	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11341	int i;
11342	static const uint16_t addr[] = {
11343		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11344		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11345		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11346		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11347		BWN_PHY_OFDM(0xcf),
11348	};
11349	static const uint16_t val[] = {
11350		0xde5e, 0xe832, 0xe331, 0x4d26,
11351		0x0026, 0x1420, 0x0020, 0xfe08,
11352		0x0008,
11353	};
11354
11355	for (i = 0; i < N(addr); i++) {
11356		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11357		BWN_PHY_WRITE(mac, addr[i], val[i]);
11358	}
11359}
11360
11361static void
11362bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11363{
11364	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11365	struct bwn_softc *sc = mac->mac_sc;
11366	uint16_t ctl;
11367
11368	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11369	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11370	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11371		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11372		break;
11373	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11374		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11375		break;
11376	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11377		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11378		break;
11379	default:
11380		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11381		device_printf(sc->sc_dev, "unknown command mode\n");
11382		break;
11383	}
11384}
11385
11386static void
11387bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11388{
11389	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11390	uint16_t ctl;
11391	uint8_t old;
11392
11393	bwn_phy_lp_get_txpctlmode(mac);
11394	old = plp->plp_txpctlmode;
11395	if (old == mode)
11396		return;
11397	plp->plp_txpctlmode = mode;
11398
11399	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11400		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11401		    plp->plp_tssiidx);
11402		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11403		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11404
11405		/* disable TX GAIN override */
11406		if (mac->mac_phy.rev < 2)
11407			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11408		else {
11409			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11410			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11411		}
11412		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11413
11414		plp->plp_txpwridx = -1;
11415	}
11416	if (mac->mac_phy.rev >= 2) {
11417		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11418			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11419		else
11420			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11421	}
11422
11423	/* writes TX Power Control mode */
11424	switch (plp->plp_txpctlmode) {
11425	case BWN_PHYLP_TXPCTL_OFF:
11426		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11427		break;
11428	case BWN_PHYLP_TXPCTL_ON_HW:
11429		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11430		break;
11431	case BWN_PHYLP_TXPCTL_ON_SW:
11432		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11433		break;
11434	default:
11435		ctl = 0;
11436		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11437	}
11438	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11439	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11440}
11441
11442static void
11443bwn_phy_lp_bugfix(struct bwn_mac *mac)
11444{
11445	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11446	struct bwn_softc *sc = mac->mac_sc;
11447	const unsigned int size = 256;
11448	struct bwn_txgain tg;
11449	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11450	uint16_t tssinpt, tssiidx, value[2];
11451	uint8_t mode;
11452	int8_t txpwridx;
11453
11454	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11455	    M_NOWAIT | M_ZERO);
11456	if (tabs == NULL) {
11457		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11458		return;
11459	}
11460
11461	bwn_phy_lp_get_txpctlmode(mac);
11462	mode = plp->plp_txpctlmode;
11463	txpwridx = plp->plp_txpwridx;
11464	tssinpt = plp->plp_tssinpt;
11465	tssiidx = plp->plp_tssiidx;
11466
11467	bwn_tab_read_multi(mac,
11468	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11469	    BWN_TAB_4(7, 0x140), size, tabs);
11470
11471	bwn_phy_lp_tblinit(mac);
11472	bwn_phy_lp_bbinit(mac);
11473	bwn_phy_lp_txpctl_init(mac);
11474	bwn_phy_lp_rf_onoff(mac, 1);
11475	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11476
11477	bwn_tab_write_multi(mac,
11478	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11479	    BWN_TAB_4(7, 0x140), size, tabs);
11480
11481	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11482	plp->plp_tssinpt = tssinpt;
11483	plp->plp_tssiidx = tssiidx;
11484	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11485	if (txpwridx != -1) {
11486		/* set TX power by index */
11487		plp->plp_txpwridx = txpwridx;
11488		bwn_phy_lp_get_txpctlmode(mac);
11489		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11490			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11491		if (mac->mac_phy.rev >= 2) {
11492			rxcomp = bwn_tab_read(mac,
11493			    BWN_TAB_4(7, txpwridx + 320));
11494			txgain = bwn_tab_read(mac,
11495			    BWN_TAB_4(7, txpwridx + 192));
11496			tg.tg_pad = (txgain >> 16) & 0xff;
11497			tg.tg_gm = txgain & 0xff;
11498			tg.tg_pga = (txgain >> 8) & 0xff;
11499			tg.tg_dac = (rxcomp >> 28) & 0xff;
11500			bwn_phy_lp_set_txgain(mac, &tg);
11501		} else {
11502			rxcomp = bwn_tab_read(mac,
11503			    BWN_TAB_4(10, txpwridx + 320));
11504			txgain = bwn_tab_read(mac,
11505			    BWN_TAB_4(10, txpwridx + 192));
11506			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11507			    0xf800, (txgain >> 4) & 0x7fff);
11508			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11509			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11510		}
11511		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11512
11513		/* set TX IQCC */
11514		value[0] = (rxcomp >> 10) & 0x3ff;
11515		value[1] = rxcomp & 0x3ff;
11516		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11517
11518		coeff = bwn_tab_read(mac,
11519		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11520		    BWN_TAB_4(10, txpwridx + 448));
11521		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11522		if (mac->mac_phy.rev >= 2) {
11523			rfpwr = bwn_tab_read(mac,
11524			    BWN_TAB_4(7, txpwridx + 576));
11525			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11526			    rfpwr & 0xffff);
11527		}
11528		bwn_phy_lp_set_txgain_override(mac);
11529	}
11530	if (plp->plp_rccap)
11531		bwn_phy_lp_set_rccap(mac);
11532	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11533	bwn_phy_lp_set_txpctlmode(mac, mode);
11534	free(tabs, M_DEVBUF);
11535}
11536
11537static void
11538bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11539{
11540	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11541	int i;
11542	static const uint16_t addr[] = {
11543		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11544		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11545		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11546		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11547		BWN_PHY_OFDM(0xcf),
11548	};
11549
11550	for (i = 0; i < N(addr); i++)
11551		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11552}
11553
11554static void
11555bwn_phy_lp_tblinit(struct bwn_mac *mac)
11556{
11557	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11558
11559	if (mac->mac_phy.rev < 2) {
11560		bwn_phy_lp_tblinit_r01(mac);
11561		bwn_phy_lp_tblinit_txgain(mac);
11562		bwn_phy_lp_set_gaintbl(mac, freq);
11563		return;
11564	}
11565
11566	bwn_phy_lp_tblinit_r2(mac);
11567	bwn_phy_lp_tblinit_txgain(mac);
11568}
11569
11570struct bwn_wpair {
11571	uint16_t		reg;
11572	uint16_t		value;
11573};
11574
11575struct bwn_smpair {
11576	uint16_t		offset;
11577	uint16_t		mask;
11578	uint16_t		set;
11579};
11580
11581static void
11582bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11583{
11584	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11585	struct bwn_softc *sc = mac->mac_sc;
11586	struct ieee80211com *ic = &sc->sc_ic;
11587	static const struct bwn_wpair v1[] = {
11588		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11589		{ BWN_PHY_AFE_CTL, 0x8800 },
11590		{ BWN_PHY_AFE_CTL_OVR, 0 },
11591		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11592		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11593		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11594		{ BWN_PHY_OFDM(0xf9), 0 },
11595		{ BWN_PHY_TR_LOOKUP_1, 0 }
11596	};
11597	static const struct bwn_smpair v2[] = {
11598		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11599		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11600		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11601		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11602		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11603	};
11604	static const struct bwn_smpair v3[] = {
11605		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11606		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11607		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11608		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11609		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11610		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11611		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11612		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11613		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11614		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11615
11616	};
11617	int i;
11618
11619	for (i = 0; i < N(v1); i++)
11620		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11621	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11622	for (i = 0; i < N(v2); i++)
11623		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11624
11625	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11626	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11627	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11628	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11629		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11630		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11631	} else {
11632		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11633	}
11634	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11635	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11636	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11637	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11638	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11639	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11640	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11641	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11642	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11643	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11644	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11645	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11646	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11647		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11648		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11649	} else {
11650		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11651		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11652	}
11653	for (i = 0; i < N(v3); i++)
11654		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11655	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11656	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11657		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11658		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11659	}
11660
11661	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11662		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11663		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11664		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11665		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11666		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11667		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11668	} else
11669		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11670
11671	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11672	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11673	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11674	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11675	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11676	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11677	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11678	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11679	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11680
11681	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11682	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11683		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11684		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11685		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11686	}
11687
11688	bwn_phy_lp_digflt_save(mac);
11689}
11690
11691static void
11692bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11693{
11694	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11695	struct bwn_softc *sc = mac->mac_sc;
11696	struct ieee80211com *ic = &sc->sc_ic;
11697	static const struct bwn_smpair v1[] = {
11698		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11699		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11700		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11701		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11702		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11703		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11704		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11705	};
11706	static const struct bwn_smpair v2[] = {
11707		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11708		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11709		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11710		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11711		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11712		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11713		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11714		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11715		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11716		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11717		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11718		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11719		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11720		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11721		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11722		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11723	};
11724	static const struct bwn_smpair v3[] = {
11725		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11726		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11727		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11728		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11729		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11730		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11731		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11732		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11733	};
11734	static const struct bwn_smpair v4[] = {
11735		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11736		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11737		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11738		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11739		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11740		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11741		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11742		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11743	};
11744	static const struct bwn_smpair v5[] = {
11745		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11746		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11747		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11748		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11749		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11750		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11751		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11752		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11753	};
11754	int i;
11755	uint16_t tmp, tmp2;
11756
11757	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11758	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11759	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11760	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11761	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11762	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11763	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11764	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11765	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11766	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11767	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11768	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11769	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11770	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11771	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11772	for (i = 0; i < N(v1); i++)
11773		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11774	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11775	    0xff00, plp->plp_rxpwroffset);
11776	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11777	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11778	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11779		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11780		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11781		if (mac->mac_phy.rev == 0)
11782			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11783			    0xffcf, 0x0010);
11784		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11785	} else {
11786		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11787		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11788		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11789	}
11790	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11791	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11792	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11793		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11794	else
11795		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11796	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11797	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11798	    0xfff9, (plp->plp_bxarch << 1));
11799	if (mac->mac_phy.rev == 1 &&
11800	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11801		for (i = 0; i < N(v2); i++)
11802			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11803			    v2[i].set);
11804	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11805	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11806	    ((mac->mac_phy.rev == 0) &&
11807	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11808		for (i = 0; i < N(v3); i++)
11809			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11810			    v3[i].set);
11811	} else if (mac->mac_phy.rev == 1 ||
11812		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11813		for (i = 0; i < N(v4); i++)
11814			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11815			    v4[i].set);
11816	} else {
11817		for (i = 0; i < N(v5); i++)
11818			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11819			    v5[i].set);
11820	}
11821	if (mac->mac_phy.rev == 1 &&
11822	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11823		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11824		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11825		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11826		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11827	}
11828	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11829	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11830	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11831		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11832		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11833		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11834		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11835	}
11836	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11837		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11838		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11839		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11840		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11841		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11842		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11843		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11844		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11845	} else {
11846		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11847		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11848	}
11849	if (mac->mac_phy.rev == 1) {
11850		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11851		tmp2 = (tmp & 0x03e0) >> 5;
11852		tmp2 |= tmp2 << 5;
11853		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
11854		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
11855		tmp2 = (tmp & 0x1f00) >> 8;
11856		tmp2 |= tmp2 << 5;
11857		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
11858		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
11859		tmp2 = tmp & 0x00ff;
11860		tmp2 |= tmp << 8;
11861		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
11862	}
11863}
11864
11865struct bwn_b2062_freq {
11866	uint16_t		freq;
11867	uint8_t			value[6];
11868};
11869
11870static void
11871bwn_phy_lp_b2062_init(struct bwn_mac *mac)
11872{
11873#define	CALC_CTL7(freq, div)						\
11874	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
11875#define	CALC_CTL18(freq, div)						\
11876	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
11877#define	CALC_CTL19(freq, div)						\
11878	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
11879	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11880	struct bwn_softc *sc = mac->mac_sc;
11881	struct ieee80211com *ic = &sc->sc_ic;
11882	static const struct bwn_b2062_freq freqdata_tab[] = {
11883		{ 12000, { 6, 6, 6, 6, 10, 6 } },
11884		{ 13000, { 4, 4, 4, 4, 11, 7 } },
11885		{ 14400, { 3, 3, 3, 3, 12, 7 } },
11886		{ 16200, { 3, 3, 3, 3, 13, 8 } },
11887		{ 18000, { 2, 2, 2, 2, 14, 8 } },
11888		{ 19200, { 1, 1, 1, 1, 14, 9 } }
11889	};
11890	static const struct bwn_wpair v1[] = {
11891		{ BWN_B2062_N_TXCTL3, 0 },
11892		{ BWN_B2062_N_TXCTL4, 0 },
11893		{ BWN_B2062_N_TXCTL5, 0 },
11894		{ BWN_B2062_N_TXCTL6, 0 },
11895		{ BWN_B2062_N_PDNCTL0, 0x40 },
11896		{ BWN_B2062_N_PDNCTL0, 0 },
11897		{ BWN_B2062_N_CALIB_TS, 0x10 },
11898		{ BWN_B2062_N_CALIB_TS, 0 }
11899	};
11900	const struct bwn_b2062_freq *f = NULL;
11901	uint32_t xtalfreq, ref;
11902	unsigned int i;
11903
11904	bwn_phy_lp_b2062_tblinit(mac);
11905
11906	for (i = 0; i < N(v1); i++)
11907		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
11908	if (mac->mac_phy.rev > 0)
11909		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
11910		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
11911	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11912		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
11913	else
11914		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
11915
11916	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
11917	    ("%s:%d: fail", __func__, __LINE__));
11918	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11919	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
11920
11921	if (xtalfreq <= 30000000) {
11922		plp->plp_div = 1;
11923		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
11924	} else {
11925		plp->plp_div = 2;
11926		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
11927	}
11928
11929	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
11930	    CALC_CTL7(xtalfreq, plp->plp_div));
11931	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
11932	    CALC_CTL18(xtalfreq, plp->plp_div));
11933	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
11934	    CALC_CTL19(xtalfreq, plp->plp_div));
11935
11936	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
11937	ref &= 0xffff;
11938	for (i = 0; i < N(freqdata_tab); i++) {
11939		if (ref < freqdata_tab[i].freq) {
11940			f = &freqdata_tab[i];
11941			break;
11942		}
11943	}
11944	if (f == NULL)
11945		f = &freqdata_tab[N(freqdata_tab) - 1];
11946	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
11947	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
11948	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
11949	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
11950	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
11951	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
11952#undef CALC_CTL7
11953#undef CALC_CTL18
11954#undef CALC_CTL19
11955}
11956
11957static void
11958bwn_phy_lp_b2063_init(struct bwn_mac *mac)
11959{
11960
11961	bwn_phy_lp_b2063_tblinit(mac);
11962	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
11963	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
11964	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
11965	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
11966	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
11967	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
11968	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
11969	if (mac->mac_phy.rev == 2) {
11970		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
11971		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
11972		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
11973	} else {
11974		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
11975		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
11976	}
11977}
11978
11979static void
11980bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
11981{
11982	struct bwn_softc *sc = mac->mac_sc;
11983	static const struct bwn_wpair v1[] = {
11984		{ BWN_B2063_RX_BB_SP8, 0x0 },
11985		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
11986		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
11987		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
11988		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
11989		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
11990		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
11991		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
11992	};
11993	static const struct bwn_wpair v2[] = {
11994		{ BWN_B2063_TX_BB_SP3, 0x0 },
11995		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
11996		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
11997		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
11998		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
11999	};
12000	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12001	int i;
12002	uint8_t tmp;
12003
12004	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12005
12006	for (i = 0; i < 2; i++)
12007		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12008	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12009	for (i = 2; i < N(v1); i++)
12010		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12011	for (i = 0; i < 10000; i++) {
12012		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12013			break;
12014		DELAY(1000);
12015	}
12016
12017	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12018		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12019
12020	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12021
12022	for (i = 0; i < N(v2); i++)
12023		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12024	if (freqxtal == 24000000) {
12025		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12026		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12027	} else {
12028		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12029		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12030	}
12031	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12032	for (i = 0; i < 10000; i++) {
12033		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12034			break;
12035		DELAY(1000);
12036	}
12037	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12038		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12039	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12040}
12041
12042static void
12043bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12044{
12045	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12046	struct bwn_softc *sc = mac->mac_sc;
12047	struct bwn_phy_lp_iq_est ie;
12048	struct bwn_txgain tx_gains;
12049	static const uint32_t pwrtbl[21] = {
12050		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12051		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12052		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12053		0x0004c, 0x0002c, 0x0001a,
12054	};
12055	uint32_t npwr, ipwr, sqpwr, tmp;
12056	int loopback, i, j, sum, error;
12057	uint16_t save[7];
12058	uint8_t txo, bbmult, txpctlmode;
12059
12060	error = bwn_phy_lp_switch_channel(mac, 7);
12061	if (error)
12062		device_printf(sc->sc_dev,
12063		    "failed to change channel to 7 (%d)\n", error);
12064	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12065	bbmult = bwn_phy_lp_get_bbmult(mac);
12066	if (txo)
12067		tx_gains = bwn_phy_lp_get_txgain(mac);
12068
12069	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12070	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12071	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12072	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12073	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12074	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12075	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12076
12077	bwn_phy_lp_get_txpctlmode(mac);
12078	txpctlmode = plp->plp_txpctlmode;
12079	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12080
12081	/* disable CRS */
12082	bwn_phy_lp_set_deaf(mac, 1);
12083	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12084	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12085	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12086	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12087	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12088	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12089	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12090	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12091	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12092	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12093	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12094	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12095	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12096	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12097	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12098	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12099	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12100	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12101	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12102	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12103	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12104	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12105	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12106	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12107
12108	loopback = bwn_phy_lp_loopback(mac);
12109	if (loopback == -1)
12110		goto done;
12111	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12112	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12113	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12114	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12115	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12116
12117	tmp = 0;
12118	memset(&ie, 0, sizeof(ie));
12119	for (i = 128; i <= 159; i++) {
12120		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12121		sum = 0;
12122		for (j = 5; j <= 25; j++) {
12123			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12124			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12125				goto done;
12126			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12127			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12128			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12129			    12);
12130			sum += ((ipwr - npwr) * (ipwr - npwr));
12131			if ((i == 128) || (sum < tmp)) {
12132				plp->plp_rccap = i;
12133				tmp = sum;
12134			}
12135		}
12136	}
12137	bwn_phy_lp_ddfs_turnoff(mac);
12138done:
12139	/* restore CRS */
12140	bwn_phy_lp_clear_deaf(mac, 1);
12141	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12142	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12143
12144	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12145	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12146	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12147	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12148	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12149	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12150	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12151
12152	bwn_phy_lp_set_bbmult(mac, bbmult);
12153	if (txo)
12154		bwn_phy_lp_set_txgain(mac, &tx_gains);
12155	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12156	if (plp->plp_rccap)
12157		bwn_phy_lp_set_rccap(mac);
12158}
12159
12160static void
12161bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12162{
12163	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12164	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12165
12166	if (mac->mac_phy.rev == 1)
12167		rc_cap = MIN(rc_cap + 5, 15);
12168
12169	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12170	    MAX(plp->plp_rccap - 4, 0x80));
12171	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12172	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12173	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12174}
12175
12176static uint32_t
12177bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12178{
12179	uint32_t i, q, r;
12180
12181	if (div == 0)
12182		return (0);
12183
12184	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12185		q <<= 1;
12186		if (r << 1 >= div) {
12187			q++;
12188			r = (r << 1) - div;
12189		}
12190	}
12191	if (r << 1 >= div)
12192		q++;
12193	return (q);
12194}
12195
12196static void
12197bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12198{
12199	struct bwn_softc *sc = mac->mac_sc;
12200
12201	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12202	DELAY(20);
12203	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12204		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12205		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12206	} else {
12207		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12208	}
12209	DELAY(5);
12210}
12211
12212static void
12213bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12214{
12215
12216	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12217	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12218	DELAY(200);
12219}
12220
12221static void
12222bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12223{
12224#define	FLAG_A	0x01
12225#define	FLAG_G	0x02
12226	struct bwn_softc *sc = mac->mac_sc;
12227	struct ieee80211com *ic = &sc->sc_ic;
12228	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12229		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12230		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12231		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12232		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12233		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12234		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12235		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12236		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12237		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12238		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12239		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12240		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12241		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12242		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12243		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12244		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12245		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12246		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12247		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12248		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12249		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12250		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12251		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12252		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12253		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12254		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12255		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12256		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12257		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12258		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12259		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12260		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12261		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12262		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12263		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12264		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12265		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12266		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12267		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12268		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12269		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12270		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12271		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12272		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12273		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12274		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12275		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12276	};
12277	const struct bwn_b206x_rfinit_entry *br;
12278	unsigned int i;
12279
12280	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12281		br = &bwn_b2062_init_tab[i];
12282		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12283			if (br->br_flags & FLAG_G)
12284				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12285		} else {
12286			if (br->br_flags & FLAG_A)
12287				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12288		}
12289	}
12290#undef FLAG_A
12291#undef FLAG_B
12292}
12293
12294static void
12295bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12296{
12297#define	FLAG_A	0x01
12298#define	FLAG_G	0x02
12299	struct bwn_softc *sc = mac->mac_sc;
12300	struct ieee80211com *ic = &sc->sc_ic;
12301	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12302		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12303		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12304		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12305		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12306		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12307		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12308		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12309		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12310		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12311		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12312		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12313		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12314		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12315		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12316		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12317		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12318		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12319		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12320		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12321		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12322		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12323		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12324		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12325		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12326		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12327		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12328		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12329		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12330		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12331		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12332		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12333		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12334		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12335		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12336		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12337		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12338		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12339		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12340		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12341		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12342		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12343		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12344	};
12345	const struct bwn_b206x_rfinit_entry *br;
12346	unsigned int i;
12347
12348	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12349		br = &bwn_b2063_init_tab[i];
12350		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12351			if (br->br_flags & FLAG_G)
12352				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12353		} else {
12354			if (br->br_flags & FLAG_A)
12355				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12356		}
12357	}
12358#undef FLAG_A
12359#undef FLAG_B
12360}
12361
12362static void
12363bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12364    int count, void *_data)
12365{
12366	unsigned int i;
12367	uint32_t offset, type;
12368	uint8_t *data = _data;
12369
12370	type = BWN_TAB_GETTYPE(typenoffset);
12371	offset = BWN_TAB_GETOFFSET(typenoffset);
12372	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12373
12374	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12375
12376	for (i = 0; i < count; i++) {
12377		switch (type) {
12378		case BWN_TAB_8BIT:
12379			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12380			data++;
12381			break;
12382		case BWN_TAB_16BIT:
12383			*((uint16_t *)data) = BWN_PHY_READ(mac,
12384			    BWN_PHY_TABLEDATALO);
12385			data += 2;
12386			break;
12387		case BWN_TAB_32BIT:
12388			*((uint32_t *)data) = BWN_PHY_READ(mac,
12389			    BWN_PHY_TABLEDATAHI);
12390			*((uint32_t *)data) <<= 16;
12391			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12392			    BWN_PHY_TABLEDATALO);
12393			data += 4;
12394			break;
12395		default:
12396			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12397		}
12398	}
12399}
12400
12401static void
12402bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12403    int count, const void *_data)
12404{
12405	uint32_t offset, type, value;
12406	const uint8_t *data = _data;
12407	unsigned int i;
12408
12409	type = BWN_TAB_GETTYPE(typenoffset);
12410	offset = BWN_TAB_GETOFFSET(typenoffset);
12411	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12412
12413	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12414
12415	for (i = 0; i < count; i++) {
12416		switch (type) {
12417		case BWN_TAB_8BIT:
12418			value = *data;
12419			data++;
12420			KASSERT(!(value & ~0xff),
12421			    ("%s:%d: fail", __func__, __LINE__));
12422			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12423			break;
12424		case BWN_TAB_16BIT:
12425			value = *((const uint16_t *)data);
12426			data += 2;
12427			KASSERT(!(value & ~0xffff),
12428			    ("%s:%d: fail", __func__, __LINE__));
12429			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12430			break;
12431		case BWN_TAB_32BIT:
12432			value = *((const uint32_t *)data);
12433			data += 4;
12434			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12435			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12436			break;
12437		default:
12438			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12439		}
12440	}
12441}
12442
12443static struct bwn_txgain
12444bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12445{
12446	struct bwn_txgain tg;
12447	uint16_t tmp;
12448
12449	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12450	if (mac->mac_phy.rev < 2) {
12451		tmp = BWN_PHY_READ(mac,
12452		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12453		tg.tg_gm = tmp & 0x0007;
12454		tg.tg_pga = (tmp & 0x0078) >> 3;
12455		tg.tg_pad = (tmp & 0x780) >> 7;
12456		return (tg);
12457	}
12458
12459	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12460	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12461	tg.tg_gm = tmp & 0xff;
12462	tg.tg_pga = (tmp >> 8) & 0xff;
12463	return (tg);
12464}
12465
12466static uint8_t
12467bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12468{
12469
12470	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12471}
12472
12473static void
12474bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12475{
12476	uint16_t pa;
12477
12478	if (mac->mac_phy.rev < 2) {
12479		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12480		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12481		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12482		bwn_phy_lp_set_txgain_override(mac);
12483		return;
12484	}
12485
12486	pa = bwn_phy_lp_get_pa_gain(mac);
12487	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12488	    (tg->tg_pga << 8) | tg->tg_gm);
12489	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12490	    tg->tg_pad | (pa << 6));
12491	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12492	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12493	    tg->tg_pad | (pa << 8));
12494	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12495	bwn_phy_lp_set_txgain_override(mac);
12496}
12497
12498static void
12499bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12500{
12501
12502	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12503}
12504
12505static void
12506bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12507{
12508	uint16_t trsw = (tx << 1) | rx;
12509
12510	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12511	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12512}
12513
12514static void
12515bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12516{
12517	struct bwn_softc *sc = mac->mac_sc;
12518	struct ieee80211com *ic = &sc->sc_ic;
12519	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12520
12521	if (mac->mac_phy.rev < 2) {
12522		trsw = gain & 0x1;
12523		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12524		ext_lna = (gain & 2) >> 1;
12525
12526		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12527		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12528		    0xfbff, ext_lna << 10);
12529		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12530		    0xf7ff, ext_lna << 11);
12531		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12532	} else {
12533		low_gain = gain & 0xffff;
12534		high_gain = (gain >> 16) & 0xf;
12535		ext_lna = (gain >> 21) & 0x1;
12536		trsw = ~(gain >> 20) & 0x1;
12537
12538		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12539		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12540		    0xfdff, ext_lna << 9);
12541		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12542		    0xfbff, ext_lna << 10);
12543		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12544		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12545		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12546			tmp = (gain >> 2) & 0x3;
12547			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12548			    0xe7ff, tmp<<11);
12549			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12550			    tmp << 3);
12551		}
12552	}
12553
12554	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12555	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12556	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12557	if (mac->mac_phy.rev >= 2) {
12558		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12559		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12560			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12561			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12562		}
12563		return;
12564	}
12565	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12566}
12567
12568static void
12569bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12570{
12571	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12572
12573	if (user)
12574		plp->plp_crsusr_off = 1;
12575	else
12576		plp->plp_crssys_off = 1;
12577
12578	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12579}
12580
12581static void
12582bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12583{
12584	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12585	struct bwn_softc *sc = mac->mac_sc;
12586	struct ieee80211com *ic = &sc->sc_ic;
12587
12588	if (user)
12589		plp->plp_crsusr_off = 0;
12590	else
12591		plp->plp_crssys_off = 0;
12592
12593	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12594		return;
12595
12596	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12597		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12598	else
12599		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12600}
12601
12602static unsigned int
12603bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12604{
12605	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12606	static uint8_t sqrt_table[256] = {
12607		10, 14, 17, 20, 22, 24, 26, 28,
12608		30, 31, 33, 34, 36, 37, 38, 40,
12609		41, 42, 43, 44, 45, 46, 47, 48,
12610		50, 50, 51, 52, 53, 54, 55, 56,
12611		57, 58, 59, 60, 60, 61, 62, 63,
12612		64, 64, 65, 66, 67, 67, 68, 69,
12613		70, 70, 71, 72, 72, 73, 74, 74,
12614		75, 76, 76, 77, 78, 78, 79, 80,
12615		80, 81, 81, 82, 83, 83, 84, 84,
12616		85, 86, 86, 87, 87, 88, 88, 89,
12617		90, 90, 91, 91, 92, 92, 93, 93,
12618		94, 94, 95, 95, 96, 96, 97, 97,
12619		98, 98, 99, 100, 100, 100, 101, 101,
12620		102, 102, 103, 103, 104, 104, 105, 105,
12621		106, 106, 107, 107, 108, 108, 109, 109,
12622		110, 110, 110, 111, 111, 112, 112, 113,
12623		113, 114, 114, 114, 115, 115, 116, 116,
12624		117, 117, 117, 118, 118, 119, 119, 120,
12625		120, 120, 121, 121, 122, 122, 122, 123,
12626		123, 124, 124, 124, 125, 125, 126, 126,
12627		126, 127, 127, 128, 128, 128, 129, 129,
12628		130, 130, 130, 131, 131, 131, 132, 132,
12629		133, 133, 133, 134, 134, 134, 135, 135,
12630		136, 136, 136, 137, 137, 137, 138, 138,
12631		138, 139, 139, 140, 140, 140, 141, 141,
12632		141, 142, 142, 142, 143, 143, 143, 144,
12633		144, 144, 145, 145, 145, 146, 146, 146,
12634		147, 147, 147, 148, 148, 148, 149, 149,
12635		150, 150, 150, 150, 151, 151, 151, 152,
12636		152, 152, 153, 153, 153, 154, 154, 154,
12637		155, 155, 155, 156, 156, 156, 157, 157,
12638		157, 158, 158, 158, 159, 159, 159, 160
12639	};
12640
12641	if (x == 0)
12642		return (0);
12643	if (x >= 256) {
12644		unsigned int tmp;
12645
12646		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12647			/* do nothing */ ;
12648		return (tmp);
12649	}
12650	return (sqrt_table[x - 1] / 10);
12651}
12652
12653static int
12654bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12655{
12656#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12657	int _t;								\
12658	_t = _x - 20;							\
12659	if (_t >= 0) {							\
12660		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12661	} else {							\
12662		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12663	}								\
12664} while (0)
12665#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12666	int _t;								\
12667	_t = _x - 11;							\
12668	if (_t >= 0)							\
12669		_v = (_y << (31 - _x)) / (_z >> _t);			\
12670	else								\
12671		_v = (_y << (31 - _x)) / (_z << -_t);			\
12672} while (0)
12673	struct bwn_phy_lp_iq_est ie;
12674	uint16_t v0, v1;
12675	int tmp[2], ret;
12676
12677	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12678	v0 = v1 >> 8;
12679	v1 |= 0xff;
12680
12681	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12682	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12683
12684	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12685	if (ret == 0)
12686		goto done;
12687
12688	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12689		ret = 0;
12690		goto done;
12691	}
12692
12693	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12694	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12695
12696	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12697	v0 = tmp[0] >> 3;
12698	v1 = tmp[1] >> 4;
12699done:
12700	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12701	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12702	return ret;
12703#undef CALC_COEFF
12704#undef CALC_COEFF2
12705}
12706
12707static void
12708bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12709{
12710	static const uint16_t noisescale[] = {
12711		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12712		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12713		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12714		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12715		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12716	};
12717	static const uint16_t crsgainnft[] = {
12718		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12719		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12720		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12721		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12722		0x013d,
12723	};
12724	static const uint16_t filterctl[] = {
12725		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12726		0xff53, 0x0127,
12727	};
12728	static const uint32_t psctl[] = {
12729		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12730		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12731		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12732		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12733		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12734		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12735		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12736		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12737	};
12738	static const uint16_t ofdmcckgain_r0[] = {
12739		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12740		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12741		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12742		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12743		0x755d,
12744	};
12745	static const uint16_t ofdmcckgain_r1[] = {
12746		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12747		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12748		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12749		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12750		0x755d,
12751	};
12752	static const uint16_t gaindelta[] = {
12753		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12754		0x0000,
12755	};
12756	static const uint32_t txpwrctl[] = {
12757		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12758		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12759		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12760		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12761		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12762		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12763		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12764		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12765		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12766		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12767		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12768		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12769		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12770		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12771		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12772		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12773		0x00000000, 0x00000000, 0x00000000, 0x00000000, 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, 0x000075a0, 0x000075a0, 0x000075a1,
12796		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12797		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12798		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12799		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12800		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12801		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12802		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12803		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12804		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12805		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12806		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12807		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12808		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12809		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12810		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12811		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12812		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12813		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12814		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12815		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12816		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12817		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12818		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12819		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12820		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12821		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12822		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12823		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12824		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
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, 0x000000ff, 0x000002fc,
12847		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
12848		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
12849		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
12850		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
12851		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
12852		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
12853		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
12854		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
12855		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
12856		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
12857		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
12858		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
12859		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
12860		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
12861		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
12862		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
12863		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
12864		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
12865		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
12866		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
12867		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
12868		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
12869		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
12870		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
12871		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
12872		0x00000702,
12873	};
12874
12875	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
12876
12877	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
12878	    bwn_tab_sigsq_tbl);
12879	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
12880	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
12881	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
12882	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
12883	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
12884	    bwn_tab_pllfrac_tbl);
12885	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
12886	    bwn_tabl_iqlocal_tbl);
12887	if (mac->mac_phy.rev == 0) {
12888		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
12889		    ofdmcckgain_r0);
12890		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
12891		    ofdmcckgain_r0);
12892	} else {
12893		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
12894		    ofdmcckgain_r1);
12895		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
12896		    ofdmcckgain_r1);
12897	}
12898	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
12899	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
12900}
12901
12902static void
12903bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
12904{
12905	struct bwn_softc *sc = mac->mac_sc;
12906	int i;
12907	static const uint16_t noisescale[] = {
12908		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12909		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12910		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12911		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12912		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12913		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12914		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
12915	};
12916	static const uint32_t filterctl[] = {
12917		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
12918		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
12919	};
12920	static const uint32_t psctl[] = {
12921		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
12922		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
12923		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
12924		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
12925	};
12926	static const uint32_t gainidx[] = {
12927		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
12931		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
12932		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
12933		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
12934		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
12935		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
12936		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
12937		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
12938		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
12939		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
12940		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
12941		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
12942		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
12946		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
12947		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
12948		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
12949		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
12950		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
12951		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
12952		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
12953		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
12954		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
12955		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
12956		0x0000001a, 0x64ca55ad, 0x0000001a
12957	};
12958	static const uint16_t auxgainidx[] = {
12959		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12960		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
12961		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
12962		0x0004, 0x0016
12963	};
12964	static const uint16_t swctl[] = {
12965		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12966		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12967		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
12968		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
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	};
12974	static const uint8_t hf[] = {
12975		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
12976		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
12977	};
12978	static const uint32_t gainval[] = {
12979		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
12980		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
12981		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
12982		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
12983		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
12984		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
12985		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12986		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12987		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
12988		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
12989		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
12990		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
12991		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
12992		0x000000f1, 0x00000000, 0x00000000
12993	};
12994	static const uint16_t gain[] = {
12995		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
12996		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
12997		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
12998		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
12999		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13000		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13001		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13002		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13003		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13004		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13005		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13006		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13007	};
13008	static const uint32_t papdeps[] = {
13009		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13010		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13011		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13012		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13013		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13014		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13015		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13016		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13017		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13018		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13019		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13020		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13021		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13022	};
13023	static const uint32_t papdmult[] = {
13024		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13025		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13026		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13027		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13028		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13029		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13030		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13031		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13032		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13033		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13034		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13035		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13036		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13037	};
13038	static const uint32_t gainidx_a0[] = {
13039		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13040		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13041		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13042		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13043		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13044		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13045		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13046		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13047		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13048		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13049		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13050		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13051		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13052	};
13053	static const uint16_t auxgainidx_a0[] = {
13054		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13055		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13056		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13057		0x0002, 0x0014
13058	};
13059	static const uint32_t gainval_a0[] = {
13060		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13061		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13062		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13063		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13064		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13065		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13066		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13067		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13068		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13069		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13070		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13071		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13072		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13073		0x000000f7, 0x00000000, 0x00000000
13074	};
13075	static const uint16_t gain_a0[] = {
13076		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13077		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13078		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13079		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13080		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13081		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13082		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13083		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13084		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13085		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13086		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13087		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13088	};
13089
13090	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13091
13092	for (i = 0; i < 704; i++)
13093		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13094
13095	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13096	    bwn_tab_sigsq_tbl);
13097	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13098	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13099	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13100	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13101	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13102	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13103	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13104	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13105	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13106	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13107	    bwn_tab_pllfrac_tbl);
13108	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13109	    bwn_tabl_iqlocal_tbl);
13110	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13111	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13112
13113	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13114	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13115		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13116		    gainidx_a0);
13117		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13118		    auxgainidx_a0);
13119		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13120		    gainval_a0);
13121		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13122	}
13123}
13124
13125static void
13126bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13127{
13128	struct bwn_softc *sc = mac->mac_sc;
13129	struct ieee80211com *ic = &sc->sc_ic;
13130	static struct bwn_txgain_entry txgain_r2[] = {
13131		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13132		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13133		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13134		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13135		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13136		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13137		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13138		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13139		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13140		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13141		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13142		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13143		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13144		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13145		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13146		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13147		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13148		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13149		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13150		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13151		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13152		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13153		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13154		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13155		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13156		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13157		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13158		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13159		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13160		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13161		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13162		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13163		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13164		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13165		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13166		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13167		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13168		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13169		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13170		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13171		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13172		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13173		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13174		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13175		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13176		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13177		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13178		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13179		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13180		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13181		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13182		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13183		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13184		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13185		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13186		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13187		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13188		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13189		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13190		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13191		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13192		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13193		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13194		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13195	};
13196	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13197		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13198		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13199		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13200		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13201		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13202		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13203		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13204		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13205		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13206		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13207		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13208		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13209		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13210		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13211		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13212		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13213		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13214		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13215		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13216		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13217		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13218		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13219		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13220		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13221		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13222		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13223		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13224		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13225		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13226		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13227		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13228		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13229		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13230		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13231		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13232		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13233		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13234		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13235		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13236		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13237		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13238		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13239		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13240		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13241		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13242		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13243		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13244		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13245		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13246		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13247		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13248		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13249		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13250		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13251		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13252		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13253		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13254		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13255		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13256		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13257		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13258		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13259		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13260		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13261	};
13262	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13263		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13264		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13265		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13266		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13267		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13268		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13269		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13270		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13271		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13272		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13273		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13274		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13275		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13276		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13277		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13278		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13279		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13280		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13281		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13282		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13283		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13284		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13285		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13286		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13287		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13288		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13289		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13290		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13291		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13292		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13293		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13294		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13295		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13296		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13297		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13298		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13299		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13300		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13301		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13302		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13303		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13304		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13305		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13306		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13307		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13308		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13309		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13310		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13311		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13312		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13313		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13314		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13315		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13316		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13317		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13318		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13319		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13320		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13321		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13322		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13323		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13324		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13325		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13326		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13327	};
13328	static struct bwn_txgain_entry txgain_r0[] = {
13329		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13330		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13331		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13332		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13333		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13334		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13335		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13336		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13337		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13338		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13339		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13340		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13341		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13342		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13343		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13344		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13345		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13346		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13347		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13348		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13349		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13350		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13351		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13352		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13353		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13354		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13355		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13356		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13357		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13358		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13359		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13360		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13361		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13362		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13363		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13364		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13365		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13366		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13367		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13368		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13369		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13370		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13371		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13372		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13373		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13374		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13375		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13376		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13377		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13378		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13379		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13380		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13381		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13382		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13383		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13384		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13385		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13386		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13387		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13388		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13389		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13390		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13391		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13392		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13393	};
13394	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13395		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13396		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13397		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13398		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13399		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13400		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13401		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13402		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13403		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13404		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13405		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13406		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13407		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13408		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13409		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13410		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13411		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13412		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13413		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13414		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13415		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13416		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13417		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13418		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13419		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13420		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13421		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13422		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13423		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13424		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13425		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13426		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13427		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13428		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13429		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13430		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13431		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13432		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13433		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13434		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13435		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13436		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13437		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13438		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13439		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13440		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13441		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13442		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13443		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13444		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13445		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13446		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13447		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13448		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13449		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13450		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13451		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13452		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13453		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13454		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13455		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13456		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13457		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13458		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13459	};
13460	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13461		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13462		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13463		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13464		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13465		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13466		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13467		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13468		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13469		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13470		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13471		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13472		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13473		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13474		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13475		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13476		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13477		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13478		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13479		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13480		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13481		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13482		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13483		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13484		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13485		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13486		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13487		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13488		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13489		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13490		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13491		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13492		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13493		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13494		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13495		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13496		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13497		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13498		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13499		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13500		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13501		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13502		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13503		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13504		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13505		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13506		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13507		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13508		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13509		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13510		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13511		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13512		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13513		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13514		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13515		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13516		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13517		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13518		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13519		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13520		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13521		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13522		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13523		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13524		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13525	};
13526	static struct bwn_txgain_entry txgain_r1[] = {
13527		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13528		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13529		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13530		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13531		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13532		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13533		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13534		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13535		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13536		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13537		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13538		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13539		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13540		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13541		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13542		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13543		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13544		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13545		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13546		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13547		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13548		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13549		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13550		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13551		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13552		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13553		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13554		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13555		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13556		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13557		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13558		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13559		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13560		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13561		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13562		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13563		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13564		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13565		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13566		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13567		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13568		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13569		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13570		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13571		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13572		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13573		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13574		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13575		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13576		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13577		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13578		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13579		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13580		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13581		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13582		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13583		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13584		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13585		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13586		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13587		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13588		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13589		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13590		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13591		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13592		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13593		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13594		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13595		{ 7, 11, 6, 0, 71 }
13596	};
13597	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13598		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13599		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13600		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13601		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13602		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13603		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13604		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13605		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13606		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13607		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13608		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13609		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13610		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13611		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13612		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13613		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13614		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13615		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13616		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13617		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13618		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13619		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13620		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13621		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13622		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13623		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13624		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13625		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13626		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13627		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13628		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13629		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13630		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13631		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13632		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13633		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13634		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13635		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13636		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13637		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13638		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13639		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13640		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13641		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13642		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13643		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13644		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13645		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13646		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13647		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13648		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13649		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13650		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13651		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13652		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13653		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13654		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13655		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13656		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13657		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13658		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13659		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13660		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13661		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13662	};
13663	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13664		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13665		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13666		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13667		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13668		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13669		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13670		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13671		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13672		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13673		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13674		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13675		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13676		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13677		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13678		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13679		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13680		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13681		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13682		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13683		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13684		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13685		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13686		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13687		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13688		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13689		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13690		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13691		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13692		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13693		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13694		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13695		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13696		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13697		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13698		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13699		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13700		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13701		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13702		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13703		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13704		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13705		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13706		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13707		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13708		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13709		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13710		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13711		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13712		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13713		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13714		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13715		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13716		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13717		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13718		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13719		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13720		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13721		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13722		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13723		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13724		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13725		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13726		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13727		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13728	};
13729
13730	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13731		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13732			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13733		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13734			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13735			    txgain_2ghz_r2);
13736		else
13737			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13738			    txgain_5ghz_r2);
13739		return;
13740	}
13741
13742	if (mac->mac_phy.rev == 0) {
13743		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13744		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13745			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13746		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13747			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13748			    txgain_2ghz_r0);
13749		else
13750			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13751			    txgain_5ghz_r0);
13752		return;
13753	}
13754
13755	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13756	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13757		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13758	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13759		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13760	else
13761		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13762}
13763
13764static void
13765bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13766{
13767	uint32_t offset, type;
13768
13769	type = BWN_TAB_GETTYPE(typeoffset);
13770	offset = BWN_TAB_GETOFFSET(typeoffset);
13771	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13772
13773	switch (type) {
13774	case BWN_TAB_8BIT:
13775		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13776		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13777		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13778		break;
13779	case BWN_TAB_16BIT:
13780		KASSERT(!(value & ~0xffff),
13781		    ("%s:%d: fail", __func__, __LINE__));
13782		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13783		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13784		break;
13785	case BWN_TAB_32BIT:
13786		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13787		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13788		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13789		break;
13790	default:
13791		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13792	}
13793}
13794
13795static int
13796bwn_phy_lp_loopback(struct bwn_mac *mac)
13797{
13798	struct bwn_phy_lp_iq_est ie;
13799	int i, index = -1;
13800	uint32_t tmp;
13801
13802	memset(&ie, 0, sizeof(ie));
13803
13804	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13805	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13806	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13807	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13808	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13809	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13810	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13811	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13812	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13813	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13814	for (i = 0; i < 32; i++) {
13815		bwn_phy_lp_set_rxgain_idx(mac, i);
13816		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13817		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13818			continue;
13819		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13820		if ((tmp > 4000) && (tmp < 10000)) {
13821			index = i;
13822			break;
13823		}
13824	}
13825	bwn_phy_lp_ddfs_turnoff(mac);
13826	return (index);
13827}
13828
13829static void
13830bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13831{
13832
13833	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13834}
13835
13836static void
13837bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13838    int incr1, int incr2, int scale_idx)
13839{
13840
13841	bwn_phy_lp_ddfs_turnoff(mac);
13842	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13843	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13844	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13845	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13846	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
13847	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
13848	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
13849	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
13850	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
13851	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
13852}
13853
13854static uint8_t
13855bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
13856    struct bwn_phy_lp_iq_est *ie)
13857{
13858	int i;
13859
13860	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
13861	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
13862	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
13863	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
13864	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
13865
13866	for (i = 0; i < 500; i++) {
13867		if (!(BWN_PHY_READ(mac,
13868		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
13869			break;
13870		DELAY(1000);
13871	}
13872	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
13873		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13874		return 0;
13875	}
13876
13877	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
13878	ie->ie_iqprod <<= 16;
13879	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
13880	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
13881	ie->ie_ipwr <<= 16;
13882	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
13883	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
13884	ie->ie_qpwr <<= 16;
13885	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
13886
13887	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13888	return 1;
13889}
13890
13891static uint32_t
13892bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
13893{
13894	uint32_t offset, type, value;
13895
13896	type = BWN_TAB_GETTYPE(typeoffset);
13897	offset = BWN_TAB_GETOFFSET(typeoffset);
13898	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13899
13900	switch (type) {
13901	case BWN_TAB_8BIT:
13902		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13903		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
13904		break;
13905	case BWN_TAB_16BIT:
13906		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13907		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13908		break;
13909	case BWN_TAB_32BIT:
13910		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13911		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
13912		value <<= 16;
13913		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13914		break;
13915	default:
13916		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13917		value = 0;
13918	}
13919
13920	return (value);
13921}
13922
13923static void
13924bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
13925{
13926
13927	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
13928	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
13929}
13930
13931static void
13932bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
13933{
13934	uint16_t ctl;
13935
13936	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
13937	ctl |= dac << 7;
13938	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
13939}
13940
13941static void
13942bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
13943{
13944
13945	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
13946	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
13947}
13948
13949static void
13950bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
13951{
13952
13953	if (mac->mac_phy.rev < 2)
13954		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
13955	else {
13956		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
13957		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
13958	}
13959	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
13960}
13961
13962static uint16_t
13963bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
13964{
13965
13966	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
13967}
13968
13969static uint8_t
13970bwn_nbits(int32_t val)
13971{
13972	uint32_t tmp;
13973	uint8_t nbits = 0;
13974
13975	for (tmp = abs(val); tmp != 0; tmp >>= 1)
13976		nbits++;
13977	return (nbits);
13978}
13979
13980static void
13981bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
13982    struct bwn_txgain_entry *table)
13983{
13984	int i;
13985
13986	for (i = offset; i < count; i++)
13987		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
13988}
13989
13990static void
13991bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
13992    struct bwn_txgain_entry data)
13993{
13994
13995	if (mac->mac_phy.rev >= 2)
13996		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
13997	else
13998		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
13999}
14000
14001static void
14002bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14003    struct bwn_txgain_entry te)
14004{
14005	struct bwn_softc *sc = mac->mac_sc;
14006	struct ieee80211com *ic = &sc->sc_ic;
14007	uint32_t tmp;
14008
14009	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14010
14011	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14012	if (mac->mac_phy.rev >= 3) {
14013		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14014		    (0x10 << 24) : (0x70 << 24));
14015	} else {
14016		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14017		    (0x14 << 24) : (0x7f << 24));
14018	}
14019	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14020	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14021	    te.te_bbmult << 20 | te.te_dac << 28);
14022}
14023
14024static void
14025bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14026    struct bwn_txgain_entry te)
14027{
14028
14029	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14030
14031	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14032	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14033	    te.te_dac);
14034	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14035}
14036
14037static void
14038bwn_sysctl_node(struct bwn_softc *sc)
14039{
14040	device_t dev = sc->sc_dev;
14041	struct bwn_mac *mac;
14042	struct bwn_stats *stats;
14043
14044	/* XXX assume that count of MAC is only 1. */
14045
14046	if ((mac = sc->sc_curmac) == NULL)
14047		return;
14048	stats = &mac->mac_stats;
14049
14050	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14051	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14052	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14053	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14054	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14055	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14056	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14057	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14058	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14059
14060#ifdef BWN_DEBUG
14061	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14062	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14063	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14064#endif
14065}
14066
14067static device_method_t bwn_methods[] = {
14068	/* Device interface */
14069	DEVMETHOD(device_probe,		bwn_probe),
14070	DEVMETHOD(device_attach,	bwn_attach),
14071	DEVMETHOD(device_detach,	bwn_detach),
14072	DEVMETHOD(device_suspend,	bwn_suspend),
14073	DEVMETHOD(device_resume,	bwn_resume),
14074	DEVMETHOD_END
14075};
14076static driver_t bwn_driver = {
14077	"bwn",
14078	bwn_methods,
14079	sizeof(struct bwn_softc)
14080};
14081static devclass_t bwn_devclass;
14082DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14083MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14084MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14085MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14086MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14087