if_bwn.c revision 289165
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 289165 2015-10-12 04:55:20Z adrian $");
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,
2725		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2726	}
2727	BWN_UNLOCK(sc);
2728}
2729
2730/*
2731 * Callback from the 802.11 layer after a promiscuous mode change.
2732 * Note this interface does not check the operating mode as this
2733 * is an internal callback and we are expected to honor the current
2734 * state (e.g. this is used for setting the interface in promiscuous
2735 * mode when operating in hostap mode to do ACS).
2736 */
2737static void
2738bwn_update_promisc(struct ieee80211com *ic)
2739{
2740	struct bwn_softc *sc = ic->ic_softc;
2741	struct bwn_mac *mac = sc->sc_curmac;
2742
2743	BWN_LOCK(sc);
2744	mac = sc->sc_curmac;
2745	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2746		if (ic->ic_promisc > 0)
2747			sc->sc_filters |= BWN_MACCTL_PROMISC;
2748		else
2749			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2750		bwn_set_opmode(mac);
2751	}
2752	BWN_UNLOCK(sc);
2753}
2754
2755/*
2756 * Callback from the 802.11 layer to update WME parameters.
2757 */
2758static int
2759bwn_wme_update(struct ieee80211com *ic)
2760{
2761	struct bwn_softc *sc = ic->ic_softc;
2762	struct bwn_mac *mac = sc->sc_curmac;
2763	struct wmeParams *wmep;
2764	int i;
2765
2766	BWN_LOCK(sc);
2767	mac = sc->sc_curmac;
2768	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2769		bwn_mac_suspend(mac);
2770		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2771			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2772			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2773		}
2774		bwn_mac_enable(mac);
2775	}
2776	BWN_UNLOCK(sc);
2777	return (0);
2778}
2779
2780static void
2781bwn_scan_start(struct ieee80211com *ic)
2782{
2783	struct bwn_softc *sc = ic->ic_softc;
2784	struct bwn_mac *mac;
2785
2786	BWN_LOCK(sc);
2787	mac = sc->sc_curmac;
2788	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2789		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2790		bwn_set_opmode(mac);
2791		/* disable CFP update during scan */
2792		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2793	}
2794	BWN_UNLOCK(sc);
2795}
2796
2797static void
2798bwn_scan_end(struct ieee80211com *ic)
2799{
2800	struct bwn_softc *sc = ic->ic_softc;
2801	struct bwn_mac *mac;
2802
2803	BWN_LOCK(sc);
2804	mac = sc->sc_curmac;
2805	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2806		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2807		bwn_set_opmode(mac);
2808		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2809	}
2810	BWN_UNLOCK(sc);
2811}
2812
2813static void
2814bwn_set_channel(struct ieee80211com *ic)
2815{
2816	struct bwn_softc *sc = ic->ic_softc;
2817	struct bwn_mac *mac = sc->sc_curmac;
2818	struct bwn_phy *phy = &mac->mac_phy;
2819	int chan, error;
2820
2821	BWN_LOCK(sc);
2822
2823	error = bwn_switch_band(sc, ic->ic_curchan);
2824	if (error)
2825		goto fail;
2826	bwn_mac_suspend(mac);
2827	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2828	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2829	if (chan != phy->chan)
2830		bwn_switch_channel(mac, chan);
2831
2832	/* TX power level */
2833	if (ic->ic_curchan->ic_maxpower != 0 &&
2834	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2835		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2836		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2837		    BWN_TXPWR_IGNORE_TSSI);
2838	}
2839
2840	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2841	if (phy->set_antenna)
2842		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2843
2844	if (sc->sc_rf_enabled != phy->rf_on) {
2845		if (sc->sc_rf_enabled) {
2846			bwn_rf_turnon(mac);
2847			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2848				device_printf(sc->sc_dev,
2849				    "please turn on the RF switch\n");
2850		} else
2851			bwn_rf_turnoff(mac);
2852	}
2853
2854	bwn_mac_enable(mac);
2855
2856fail:
2857	/*
2858	 * Setup radio tap channel freq and flags
2859	 */
2860	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2861		htole16(ic->ic_curchan->ic_freq);
2862	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2863		htole16(ic->ic_curchan->ic_flags & 0xffff);
2864
2865	BWN_UNLOCK(sc);
2866}
2867
2868static struct ieee80211vap *
2869bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2870    enum ieee80211_opmode opmode, int flags,
2871    const uint8_t bssid[IEEE80211_ADDR_LEN],
2872    const uint8_t mac[IEEE80211_ADDR_LEN])
2873{
2874	struct ieee80211vap *vap;
2875	struct bwn_vap *bvp;
2876
2877	switch (opmode) {
2878	case IEEE80211_M_HOSTAP:
2879	case IEEE80211_M_MBSS:
2880	case IEEE80211_M_STA:
2881	case IEEE80211_M_WDS:
2882	case IEEE80211_M_MONITOR:
2883	case IEEE80211_M_IBSS:
2884	case IEEE80211_M_AHDEMO:
2885		break;
2886	default:
2887		return (NULL);
2888	}
2889
2890	bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
2891	vap = &bvp->bv_vap;
2892	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
2893	/* override with driver methods */
2894	bvp->bv_newstate = vap->iv_newstate;
2895	vap->iv_newstate = bwn_newstate;
2896
2897	/* override max aid so sta's cannot assoc when we're out of sta id's */
2898	vap->iv_max_aid = BWN_STAID_MAX;
2899
2900	ieee80211_ratectl_init(vap);
2901
2902	/* complete setup */
2903	ieee80211_vap_attach(vap, ieee80211_media_change,
2904	    ieee80211_media_status, mac);
2905	return (vap);
2906}
2907
2908static void
2909bwn_vap_delete(struct ieee80211vap *vap)
2910{
2911	struct bwn_vap *bvp = BWN_VAP(vap);
2912
2913	ieee80211_ratectl_deinit(vap);
2914	ieee80211_vap_detach(vap);
2915	free(bvp, M_80211_VAP);
2916}
2917
2918static int
2919bwn_init(struct bwn_softc *sc)
2920{
2921	struct bwn_mac *mac;
2922	int error;
2923
2924	BWN_ASSERT_LOCKED(sc);
2925
2926	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
2927	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
2928	sc->sc_filters = 0;
2929	bwn_wme_clear(sc);
2930	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
2931	sc->sc_rf_enabled = 1;
2932
2933	mac = sc->sc_curmac;
2934	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
2935		error = bwn_core_init(mac);
2936		if (error != 0)
2937			return (error);
2938	}
2939	if (mac->mac_status == BWN_MAC_STATUS_INITED)
2940		bwn_core_start(mac);
2941
2942	bwn_set_opmode(mac);
2943	bwn_set_pretbtt(mac);
2944	bwn_spu_setdelay(mac, 0);
2945	bwn_set_macaddr(mac);
2946
2947	sc->sc_flags |= BWN_FLAG_RUNNING;
2948	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
2949	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
2950
2951	return (0);
2952}
2953
2954static void
2955bwn_stop(struct bwn_softc *sc)
2956{
2957	struct bwn_mac *mac = sc->sc_curmac;
2958
2959	BWN_ASSERT_LOCKED(sc);
2960
2961	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
2962		/* XXX FIXME opmode not based on VAP */
2963		bwn_set_opmode(mac);
2964		bwn_set_macaddr(mac);
2965	}
2966
2967	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
2968		bwn_core_stop(mac);
2969
2970	callout_stop(&sc->sc_led_blink_ch);
2971	sc->sc_led_blinking = 0;
2972
2973	bwn_core_exit(mac);
2974	sc->sc_rf_enabled = 0;
2975
2976	sc->sc_flags &= ~BWN_FLAG_RUNNING;
2977}
2978
2979static void
2980bwn_wme_clear(struct bwn_softc *sc)
2981{
2982#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
2983	struct wmeParams *p;
2984	unsigned int i;
2985
2986	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
2987	    ("%s:%d: fail", __func__, __LINE__));
2988
2989	for (i = 0; i < N(sc->sc_wmeParams); i++) {
2990		p = &(sc->sc_wmeParams[i]);
2991
2992		switch (bwn_wme_shm_offsets[i]) {
2993		case BWN_WME_VOICE:
2994			p->wmep_txopLimit = 0;
2995			p->wmep_aifsn = 2;
2996			/* XXX FIXME: log2(cwmin) */
2997			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
2998			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
2999			break;
3000		case BWN_WME_VIDEO:
3001			p->wmep_txopLimit = 0;
3002			p->wmep_aifsn = 2;
3003			/* XXX FIXME: log2(cwmin) */
3004			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3005			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3006			break;
3007		case BWN_WME_BESTEFFORT:
3008			p->wmep_txopLimit = 0;
3009			p->wmep_aifsn = 3;
3010			/* XXX FIXME: log2(cwmin) */
3011			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3012			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3013			break;
3014		case BWN_WME_BACKGROUND:
3015			p->wmep_txopLimit = 0;
3016			p->wmep_aifsn = 7;
3017			/* XXX FIXME: log2(cwmin) */
3018			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3019			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3020			break;
3021		default:
3022			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3023		}
3024	}
3025}
3026
3027static int
3028bwn_core_init(struct bwn_mac *mac)
3029{
3030	struct bwn_softc *sc = mac->mac_sc;
3031	uint64_t hf;
3032	int error;
3033
3034	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3035	    ("%s:%d: fail", __func__, __LINE__));
3036
3037	siba_powerup(sc->sc_dev, 0);
3038	if (!siba_dev_isup(sc->sc_dev))
3039		bwn_reset_core(mac,
3040		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3041
3042	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3043	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3044	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3045	BWN_GETTIME(mac->mac_phy.nexttime);
3046	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3047	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3048	mac->mac_stats.link_noise = -95;
3049	mac->mac_reason_intr = 0;
3050	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3051	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3052#ifdef BWN_DEBUG
3053	if (sc->sc_debug & BWN_DEBUG_XMIT)
3054		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3055#endif
3056	mac->mac_suspended = 1;
3057	mac->mac_task_state = 0;
3058	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3059
3060	mac->mac_phy.init_pre(mac);
3061
3062	siba_pcicore_intr(sc->sc_dev);
3063
3064	siba_fix_imcfglobug(sc->sc_dev);
3065	bwn_bt_disable(mac);
3066	if (mac->mac_phy.prepare_hw) {
3067		error = mac->mac_phy.prepare_hw(mac);
3068		if (error)
3069			goto fail0;
3070	}
3071	error = bwn_chip_init(mac);
3072	if (error)
3073		goto fail0;
3074	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3075	    siba_get_revid(sc->sc_dev));
3076	hf = bwn_hf_read(mac);
3077	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3078		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3079		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3080			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3081		if (mac->mac_phy.rev == 1)
3082			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3083	}
3084	if (mac->mac_phy.rf_ver == 0x2050) {
3085		if (mac->mac_phy.rf_rev < 6)
3086			hf |= BWN_HF_FORCE_VCO_RECALC;
3087		if (mac->mac_phy.rf_rev == 6)
3088			hf |= BWN_HF_4318_TSSI;
3089	}
3090	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3091		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3092	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3093	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3094		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3095	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3096	bwn_hf_write(mac, hf);
3097
3098	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3099	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3100	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3101	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3102
3103	bwn_rate_init(mac);
3104	bwn_set_phytxctl(mac);
3105
3106	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3107	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3108	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3109
3110	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3111		bwn_pio_init(mac);
3112	else
3113		bwn_dma_init(mac);
3114	bwn_wme_init(mac);
3115	bwn_spu_setdelay(mac, 1);
3116	bwn_bt_enable(mac);
3117
3118	siba_powerup(sc->sc_dev,
3119	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3120	bwn_set_macaddr(mac);
3121	bwn_crypt_init(mac);
3122
3123	/* XXX LED initializatin */
3124
3125	mac->mac_status = BWN_MAC_STATUS_INITED;
3126
3127	return (error);
3128
3129fail0:
3130	siba_powerdown(sc->sc_dev);
3131	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3132	    ("%s:%d: fail", __func__, __LINE__));
3133	return (error);
3134}
3135
3136static void
3137bwn_core_start(struct bwn_mac *mac)
3138{
3139	struct bwn_softc *sc = mac->mac_sc;
3140	uint32_t tmp;
3141
3142	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3143	    ("%s:%d: fail", __func__, __LINE__));
3144
3145	if (siba_get_revid(sc->sc_dev) < 5)
3146		return;
3147
3148	while (1) {
3149		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3150		if (!(tmp & 0x00000001))
3151			break;
3152		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3153	}
3154
3155	bwn_mac_enable(mac);
3156	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3157	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3158
3159	mac->mac_status = BWN_MAC_STATUS_STARTED;
3160}
3161
3162static void
3163bwn_core_exit(struct bwn_mac *mac)
3164{
3165	struct bwn_softc *sc = mac->mac_sc;
3166	uint32_t macctl;
3167
3168	BWN_ASSERT_LOCKED(mac->mac_sc);
3169
3170	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3171	    ("%s:%d: fail", __func__, __LINE__));
3172
3173	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3174		return;
3175	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3176
3177	macctl = BWN_READ_4(mac, BWN_MACCTL);
3178	macctl &= ~BWN_MACCTL_MCODE_RUN;
3179	macctl |= BWN_MACCTL_MCODE_JMP0;
3180	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3181
3182	bwn_dma_stop(mac);
3183	bwn_pio_stop(mac);
3184	bwn_chip_exit(mac);
3185	mac->mac_phy.switch_analog(mac, 0);
3186	siba_dev_down(sc->sc_dev, 0);
3187	siba_powerdown(sc->sc_dev);
3188}
3189
3190static void
3191bwn_bt_disable(struct bwn_mac *mac)
3192{
3193	struct bwn_softc *sc = mac->mac_sc;
3194
3195	(void)sc;
3196	/* XXX do nothing yet */
3197}
3198
3199static int
3200bwn_chip_init(struct bwn_mac *mac)
3201{
3202	struct bwn_softc *sc = mac->mac_sc;
3203	struct bwn_phy *phy = &mac->mac_phy;
3204	uint32_t macctl;
3205	int error;
3206
3207	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3208	if (phy->gmode)
3209		macctl |= BWN_MACCTL_GMODE;
3210	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3211
3212	error = bwn_fw_fillinfo(mac);
3213	if (error)
3214		return (error);
3215	error = bwn_fw_loaducode(mac);
3216	if (error)
3217		return (error);
3218
3219	error = bwn_gpio_init(mac);
3220	if (error)
3221		return (error);
3222
3223	error = bwn_fw_loadinitvals(mac);
3224	if (error) {
3225		siba_gpio_set(sc->sc_dev, 0);
3226		return (error);
3227	}
3228	phy->switch_analog(mac, 1);
3229	error = bwn_phy_init(mac);
3230	if (error) {
3231		siba_gpio_set(sc->sc_dev, 0);
3232		return (error);
3233	}
3234	if (phy->set_im)
3235		phy->set_im(mac, BWN_IMMODE_NONE);
3236	if (phy->set_antenna)
3237		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3238	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3239
3240	if (phy->type == BWN_PHYTYPE_B)
3241		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3242	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3243	if (siba_get_revid(sc->sc_dev) < 5)
3244		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3245
3246	BWN_WRITE_4(mac, BWN_MACCTL,
3247	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3248	BWN_WRITE_4(mac, BWN_MACCTL,
3249	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3250	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3251
3252	bwn_set_opmode(mac);
3253	if (siba_get_revid(sc->sc_dev) < 3) {
3254		BWN_WRITE_2(mac, 0x060e, 0x0000);
3255		BWN_WRITE_2(mac, 0x0610, 0x8000);
3256		BWN_WRITE_2(mac, 0x0604, 0x0000);
3257		BWN_WRITE_2(mac, 0x0606, 0x0200);
3258	} else {
3259		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3260		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3261	}
3262	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3263	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3264	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3265	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3266	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3267	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3268	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3269	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3270	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3271	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3272	return (error);
3273}
3274
3275/* read hostflags */
3276static uint64_t
3277bwn_hf_read(struct bwn_mac *mac)
3278{
3279	uint64_t ret;
3280
3281	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3282	ret <<= 16;
3283	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3284	ret <<= 16;
3285	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3286	return (ret);
3287}
3288
3289static void
3290bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3291{
3292
3293	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3294	    (value & 0x00000000ffffull));
3295	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3296	    (value & 0x0000ffff0000ull) >> 16);
3297	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3298	    (value & 0xffff00000000ULL) >> 32);
3299}
3300
3301static void
3302bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3303{
3304
3305	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3306	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3307}
3308
3309static void
3310bwn_rate_init(struct bwn_mac *mac)
3311{
3312
3313	switch (mac->mac_phy.type) {
3314	case BWN_PHYTYPE_A:
3315	case BWN_PHYTYPE_G:
3316	case BWN_PHYTYPE_LP:
3317	case BWN_PHYTYPE_N:
3318		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3319		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3320		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3321		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3322		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3323		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3324		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3325		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3326			break;
3327		/* FALLTHROUGH */
3328	case BWN_PHYTYPE_B:
3329		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3330		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3331		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3332		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3333		break;
3334	default:
3335		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3336	}
3337}
3338
3339static void
3340bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3341{
3342	uint16_t offset;
3343
3344	if (ofdm) {
3345		offset = 0x480;
3346		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3347	} else {
3348		offset = 0x4c0;
3349		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3350	}
3351	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3352	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3353}
3354
3355static uint8_t
3356bwn_plcp_getcck(const uint8_t bitrate)
3357{
3358
3359	switch (bitrate) {
3360	case BWN_CCK_RATE_1MB:
3361		return (0x0a);
3362	case BWN_CCK_RATE_2MB:
3363		return (0x14);
3364	case BWN_CCK_RATE_5MB:
3365		return (0x37);
3366	case BWN_CCK_RATE_11MB:
3367		return (0x6e);
3368	}
3369	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3370	return (0);
3371}
3372
3373static uint8_t
3374bwn_plcp_getofdm(const uint8_t bitrate)
3375{
3376
3377	switch (bitrate) {
3378	case BWN_OFDM_RATE_6MB:
3379		return (0xb);
3380	case BWN_OFDM_RATE_9MB:
3381		return (0xf);
3382	case BWN_OFDM_RATE_12MB:
3383		return (0xa);
3384	case BWN_OFDM_RATE_18MB:
3385		return (0xe);
3386	case BWN_OFDM_RATE_24MB:
3387		return (0x9);
3388	case BWN_OFDM_RATE_36MB:
3389		return (0xd);
3390	case BWN_OFDM_RATE_48MB:
3391		return (0x8);
3392	case BWN_OFDM_RATE_54MB:
3393		return (0xc);
3394	}
3395	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3396	return (0);
3397}
3398
3399static void
3400bwn_set_phytxctl(struct bwn_mac *mac)
3401{
3402	uint16_t ctl;
3403
3404	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3405	    BWN_TX_PHY_TXPWR);
3406	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3407	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3408	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3409}
3410
3411static void
3412bwn_pio_init(struct bwn_mac *mac)
3413{
3414	struct bwn_pio *pio = &mac->mac_method.pio;
3415
3416	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3417	    & ~BWN_MACCTL_BIGENDIAN);
3418	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3419
3420	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3421	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3422	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3423	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3424	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3425	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3426}
3427
3428static void
3429bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3430    int index)
3431{
3432	struct bwn_pio_txpkt *tp;
3433	struct bwn_softc *sc = mac->mac_sc;
3434	unsigned int i;
3435
3436	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3437	tq->tq_index = index;
3438
3439	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3440	if (siba_get_revid(sc->sc_dev) >= 8)
3441		tq->tq_size = 1920;
3442	else {
3443		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3444		tq->tq_size -= 80;
3445	}
3446
3447	TAILQ_INIT(&tq->tq_pktlist);
3448	for (i = 0; i < N(tq->tq_pkts); i++) {
3449		tp = &(tq->tq_pkts[i]);
3450		tp->tp_index = i;
3451		tp->tp_queue = tq;
3452		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3453	}
3454}
3455
3456static uint16_t
3457bwn_pio_idx2base(struct bwn_mac *mac, int index)
3458{
3459	struct bwn_softc *sc = mac->mac_sc;
3460	static const uint16_t bases[] = {
3461		BWN_PIO_BASE0,
3462		BWN_PIO_BASE1,
3463		BWN_PIO_BASE2,
3464		BWN_PIO_BASE3,
3465		BWN_PIO_BASE4,
3466		BWN_PIO_BASE5,
3467		BWN_PIO_BASE6,
3468		BWN_PIO_BASE7,
3469	};
3470	static const uint16_t bases_rev11[] = {
3471		BWN_PIO11_BASE0,
3472		BWN_PIO11_BASE1,
3473		BWN_PIO11_BASE2,
3474		BWN_PIO11_BASE3,
3475		BWN_PIO11_BASE4,
3476		BWN_PIO11_BASE5,
3477	};
3478
3479	if (siba_get_revid(sc->sc_dev) >= 11) {
3480		if (index >= N(bases_rev11))
3481			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3482		return (bases_rev11[index]);
3483	}
3484	if (index >= N(bases))
3485		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3486	return (bases[index]);
3487}
3488
3489static void
3490bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3491    int index)
3492{
3493	struct bwn_softc *sc = mac->mac_sc;
3494
3495	prq->prq_mac = mac;
3496	prq->prq_rev = siba_get_revid(sc->sc_dev);
3497	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3498	bwn_dma_rxdirectfifo(mac, index, 1);
3499}
3500
3501static void
3502bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3503{
3504	if (tq == NULL)
3505		return;
3506	bwn_pio_cancel_tx_packets(tq);
3507}
3508
3509static void
3510bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3511{
3512
3513	bwn_destroy_pioqueue_tx(pio);
3514}
3515
3516static uint16_t
3517bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3518    uint16_t offset)
3519{
3520
3521	return (BWN_READ_2(mac, tq->tq_base + offset));
3522}
3523
3524static void
3525bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3526{
3527	uint32_t ctl;
3528	int type;
3529	uint16_t base;
3530
3531	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3532	base = bwn_dma_base(type, idx);
3533	if (type == BWN_DMA_64BIT) {
3534		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3535		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3536		if (enable)
3537			ctl |= BWN_DMA64_RXDIRECTFIFO;
3538		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3539	} else {
3540		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3541		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3542		if (enable)
3543			ctl |= BWN_DMA32_RXDIRECTFIFO;
3544		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3545	}
3546}
3547
3548static uint64_t
3549bwn_dma_mask(struct bwn_mac *mac)
3550{
3551	uint32_t tmp;
3552	uint16_t base;
3553
3554	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3555	if (tmp & SIBA_TGSHIGH_DMA64)
3556		return (BWN_DMA_BIT_MASK(64));
3557	base = bwn_dma_base(0, 0);
3558	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3559	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3560	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3561		return (BWN_DMA_BIT_MASK(32));
3562
3563	return (BWN_DMA_BIT_MASK(30));
3564}
3565
3566static int
3567bwn_dma_mask2type(uint64_t dmamask)
3568{
3569
3570	if (dmamask == BWN_DMA_BIT_MASK(30))
3571		return (BWN_DMA_30BIT);
3572	if (dmamask == BWN_DMA_BIT_MASK(32))
3573		return (BWN_DMA_32BIT);
3574	if (dmamask == BWN_DMA_BIT_MASK(64))
3575		return (BWN_DMA_64BIT);
3576	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3577	return (BWN_DMA_30BIT);
3578}
3579
3580static void
3581bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3582{
3583	struct bwn_pio_txpkt *tp;
3584	unsigned int i;
3585
3586	for (i = 0; i < N(tq->tq_pkts); i++) {
3587		tp = &(tq->tq_pkts[i]);
3588		if (tp->tp_m) {
3589			m_freem(tp->tp_m);
3590			tp->tp_m = NULL;
3591		}
3592	}
3593}
3594
3595static uint16_t
3596bwn_dma_base(int type, int controller_idx)
3597{
3598	static const uint16_t map64[] = {
3599		BWN_DMA64_BASE0,
3600		BWN_DMA64_BASE1,
3601		BWN_DMA64_BASE2,
3602		BWN_DMA64_BASE3,
3603		BWN_DMA64_BASE4,
3604		BWN_DMA64_BASE5,
3605	};
3606	static const uint16_t map32[] = {
3607		BWN_DMA32_BASE0,
3608		BWN_DMA32_BASE1,
3609		BWN_DMA32_BASE2,
3610		BWN_DMA32_BASE3,
3611		BWN_DMA32_BASE4,
3612		BWN_DMA32_BASE5,
3613	};
3614
3615	if (type == BWN_DMA_64BIT) {
3616		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3617		    ("%s:%d: fail", __func__, __LINE__));
3618		return (map64[controller_idx]);
3619	}
3620	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3621	    ("%s:%d: fail", __func__, __LINE__));
3622	return (map32[controller_idx]);
3623}
3624
3625static void
3626bwn_dma_init(struct bwn_mac *mac)
3627{
3628	struct bwn_dma *dma = &mac->mac_method.dma;
3629
3630	/* setup TX DMA channels. */
3631	bwn_dma_setup(dma->wme[WME_AC_BK]);
3632	bwn_dma_setup(dma->wme[WME_AC_BE]);
3633	bwn_dma_setup(dma->wme[WME_AC_VI]);
3634	bwn_dma_setup(dma->wme[WME_AC_VO]);
3635	bwn_dma_setup(dma->mcast);
3636	/* setup RX DMA channel. */
3637	bwn_dma_setup(dma->rx);
3638}
3639
3640static struct bwn_dma_ring *
3641bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3642    int for_tx, int type)
3643{
3644	struct bwn_dma *dma = &mac->mac_method.dma;
3645	struct bwn_dma_ring *dr;
3646	struct bwn_dmadesc_generic *desc;
3647	struct bwn_dmadesc_meta *mt;
3648	struct bwn_softc *sc = mac->mac_sc;
3649	int error, i;
3650
3651	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3652	if (dr == NULL)
3653		goto out;
3654	dr->dr_numslots = BWN_RXRING_SLOTS;
3655	if (for_tx)
3656		dr->dr_numslots = BWN_TXRING_SLOTS;
3657
3658	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3659	    M_DEVBUF, M_NOWAIT | M_ZERO);
3660	if (dr->dr_meta == NULL)
3661		goto fail0;
3662
3663	dr->dr_type = type;
3664	dr->dr_mac = mac;
3665	dr->dr_base = bwn_dma_base(type, controller_index);
3666	dr->dr_index = controller_index;
3667	if (type == BWN_DMA_64BIT) {
3668		dr->getdesc = bwn_dma_64_getdesc;
3669		dr->setdesc = bwn_dma_64_setdesc;
3670		dr->start_transfer = bwn_dma_64_start_transfer;
3671		dr->suspend = bwn_dma_64_suspend;
3672		dr->resume = bwn_dma_64_resume;
3673		dr->get_curslot = bwn_dma_64_get_curslot;
3674		dr->set_curslot = bwn_dma_64_set_curslot;
3675	} else {
3676		dr->getdesc = bwn_dma_32_getdesc;
3677		dr->setdesc = bwn_dma_32_setdesc;
3678		dr->start_transfer = bwn_dma_32_start_transfer;
3679		dr->suspend = bwn_dma_32_suspend;
3680		dr->resume = bwn_dma_32_resume;
3681		dr->get_curslot = bwn_dma_32_get_curslot;
3682		dr->set_curslot = bwn_dma_32_set_curslot;
3683	}
3684	if (for_tx) {
3685		dr->dr_tx = 1;
3686		dr->dr_curslot = -1;
3687	} else {
3688		if (dr->dr_index == 0) {
3689			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3690			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3691		} else
3692			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3693	}
3694
3695	error = bwn_dma_allocringmemory(dr);
3696	if (error)
3697		goto fail2;
3698
3699	if (for_tx) {
3700		/*
3701		 * Assumption: BWN_TXRING_SLOTS can be divided by
3702		 * BWN_TX_SLOTS_PER_FRAME
3703		 */
3704		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3705		    ("%s:%d: fail", __func__, __LINE__));
3706
3707		dr->dr_txhdr_cache =
3708		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3709			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3710		KASSERT(dr->dr_txhdr_cache != NULL,
3711		    ("%s:%d: fail", __func__, __LINE__));
3712
3713		/*
3714		 * Create TX ring DMA stuffs
3715		 */
3716		error = bus_dma_tag_create(dma->parent_dtag,
3717				    BWN_ALIGN, 0,
3718				    BUS_SPACE_MAXADDR,
3719				    BUS_SPACE_MAXADDR,
3720				    NULL, NULL,
3721				    BWN_HDRSIZE(mac),
3722				    1,
3723				    BUS_SPACE_MAXSIZE_32BIT,
3724				    0,
3725				    NULL, NULL,
3726				    &dr->dr_txring_dtag);
3727		if (error) {
3728			device_printf(sc->sc_dev,
3729			    "can't create TX ring DMA tag: TODO frees\n");
3730			goto fail1;
3731		}
3732
3733		for (i = 0; i < dr->dr_numslots; i += 2) {
3734			dr->getdesc(dr, i, &desc, &mt);
3735
3736			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3737			mt->mt_m = NULL;
3738			mt->mt_ni = NULL;
3739			mt->mt_islast = 0;
3740			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3741			    &mt->mt_dmap);
3742			if (error) {
3743				device_printf(sc->sc_dev,
3744				     "can't create RX buf DMA map\n");
3745				goto fail1;
3746			}
3747
3748			dr->getdesc(dr, i + 1, &desc, &mt);
3749
3750			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3751			mt->mt_m = NULL;
3752			mt->mt_ni = NULL;
3753			mt->mt_islast = 1;
3754			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3755			    &mt->mt_dmap);
3756			if (error) {
3757				device_printf(sc->sc_dev,
3758				     "can't create RX buf DMA map\n");
3759				goto fail1;
3760			}
3761		}
3762	} else {
3763		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3764		    &dr->dr_spare_dmap);
3765		if (error) {
3766			device_printf(sc->sc_dev,
3767			    "can't create RX buf DMA map\n");
3768			goto out;		/* XXX wrong! */
3769		}
3770
3771		for (i = 0; i < dr->dr_numslots; i++) {
3772			dr->getdesc(dr, i, &desc, &mt);
3773
3774			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3775			    &mt->mt_dmap);
3776			if (error) {
3777				device_printf(sc->sc_dev,
3778				    "can't create RX buf DMA map\n");
3779				goto out;	/* XXX wrong! */
3780			}
3781			error = bwn_dma_newbuf(dr, desc, mt, 1);
3782			if (error) {
3783				device_printf(sc->sc_dev,
3784				    "failed to allocate RX buf\n");
3785				goto out;	/* XXX wrong! */
3786			}
3787		}
3788
3789		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3790		    BUS_DMASYNC_PREWRITE);
3791
3792		dr->dr_usedslot = dr->dr_numslots;
3793	}
3794
3795      out:
3796	return (dr);
3797
3798fail2:
3799	free(dr->dr_txhdr_cache, M_DEVBUF);
3800fail1:
3801	free(dr->dr_meta, M_DEVBUF);
3802fail0:
3803	free(dr, M_DEVBUF);
3804	return (NULL);
3805}
3806
3807static void
3808bwn_dma_ringfree(struct bwn_dma_ring **dr)
3809{
3810
3811	if (dr == NULL)
3812		return;
3813
3814	bwn_dma_free_descbufs(*dr);
3815	bwn_dma_free_ringmemory(*dr);
3816
3817	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3818	free((*dr)->dr_meta, M_DEVBUF);
3819	free(*dr, M_DEVBUF);
3820
3821	*dr = NULL;
3822}
3823
3824static void
3825bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3826    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3827{
3828	struct bwn_dmadesc32 *desc;
3829
3830	*meta = &(dr->dr_meta[slot]);
3831	desc = dr->dr_ring_descbase;
3832	desc = &(desc[slot]);
3833
3834	*gdesc = (struct bwn_dmadesc_generic *)desc;
3835}
3836
3837static void
3838bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3839    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3840    int start, int end, int irq)
3841{
3842	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3843	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3844	uint32_t addr, addrext, ctl;
3845	int slot;
3846
3847	slot = (int)(&(desc->dma.dma32) - descbase);
3848	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3849	    ("%s:%d: fail", __func__, __LINE__));
3850
3851	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3852	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3853	addr |= siba_dma_translation(sc->sc_dev);
3854	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3855	if (slot == dr->dr_numslots - 1)
3856		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3857	if (start)
3858		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3859	if (end)
3860		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3861	if (irq)
3862		ctl |= BWN_DMA32_DCTL_IRQ;
3863	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3864	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3865
3866	desc->dma.dma32.control = htole32(ctl);
3867	desc->dma.dma32.address = htole32(addr);
3868}
3869
3870static void
3871bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3872{
3873
3874	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3875	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3876}
3877
3878static void
3879bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3880{
3881
3882	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3883	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3884}
3885
3886static void
3887bwn_dma_32_resume(struct bwn_dma_ring *dr)
3888{
3889
3890	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3891	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3892}
3893
3894static int
3895bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3896{
3897	uint32_t val;
3898
3899	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
3900	val &= BWN_DMA32_RXDPTR;
3901
3902	return (val / sizeof(struct bwn_dmadesc32));
3903}
3904
3905static void
3906bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
3907{
3908
3909	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
3910	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
3911}
3912
3913static void
3914bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
3915    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3916{
3917	struct bwn_dmadesc64 *desc;
3918
3919	*meta = &(dr->dr_meta[slot]);
3920	desc = dr->dr_ring_descbase;
3921	desc = &(desc[slot]);
3922
3923	*gdesc = (struct bwn_dmadesc_generic *)desc;
3924}
3925
3926static void
3927bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
3928    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3929    int start, int end, int irq)
3930{
3931	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
3932	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3933	int slot;
3934	uint32_t ctl0 = 0, ctl1 = 0;
3935	uint32_t addrlo, addrhi;
3936	uint32_t addrext;
3937
3938	slot = (int)(&(desc->dma.dma64) - descbase);
3939	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3940	    ("%s:%d: fail", __func__, __LINE__));
3941
3942	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
3943	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
3944	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
3945	    30;
3946	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
3947	if (slot == dr->dr_numslots - 1)
3948		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
3949	if (start)
3950		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
3951	if (end)
3952		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
3953	if (irq)
3954		ctl0 |= BWN_DMA64_DCTL0_IRQ;
3955	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
3956	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
3957	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
3958
3959	desc->dma.dma64.control0 = htole32(ctl0);
3960	desc->dma.dma64.control1 = htole32(ctl1);
3961	desc->dma.dma64.address_low = htole32(addrlo);
3962	desc->dma.dma64.address_high = htole32(addrhi);
3963}
3964
3965static void
3966bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
3967{
3968
3969	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
3970	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3971}
3972
3973static void
3974bwn_dma_64_suspend(struct bwn_dma_ring *dr)
3975{
3976
3977	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3978	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
3979}
3980
3981static void
3982bwn_dma_64_resume(struct bwn_dma_ring *dr)
3983{
3984
3985	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3986	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
3987}
3988
3989static int
3990bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
3991{
3992	uint32_t val;
3993
3994	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
3995	val &= BWN_DMA64_RXSTATDPTR;
3996
3997	return (val / sizeof(struct bwn_dmadesc64));
3998}
3999
4000static void
4001bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4002{
4003
4004	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4005	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4006}
4007
4008static int
4009bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4010{
4011	struct bwn_mac *mac = dr->dr_mac;
4012	struct bwn_dma *dma = &mac->mac_method.dma;
4013	struct bwn_softc *sc = mac->mac_sc;
4014	int error;
4015
4016	error = bus_dma_tag_create(dma->parent_dtag,
4017			    BWN_ALIGN, 0,
4018			    BUS_SPACE_MAXADDR,
4019			    BUS_SPACE_MAXADDR,
4020			    NULL, NULL,
4021			    BWN_DMA_RINGMEMSIZE,
4022			    1,
4023			    BUS_SPACE_MAXSIZE_32BIT,
4024			    0,
4025			    NULL, NULL,
4026			    &dr->dr_ring_dtag);
4027	if (error) {
4028		device_printf(sc->sc_dev,
4029		    "can't create TX ring DMA tag: TODO frees\n");
4030		return (-1);
4031	}
4032
4033	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4034	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4035	    &dr->dr_ring_dmap);
4036	if (error) {
4037		device_printf(sc->sc_dev,
4038		    "can't allocate DMA mem: TODO frees\n");
4039		return (-1);
4040	}
4041	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4042	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4043	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4044	if (error) {
4045		device_printf(sc->sc_dev,
4046		    "can't load DMA mem: TODO free\n");
4047		return (-1);
4048	}
4049
4050	return (0);
4051}
4052
4053static void
4054bwn_dma_setup(struct bwn_dma_ring *dr)
4055{
4056	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4057	uint64_t ring64;
4058	uint32_t addrext, ring32, value;
4059	uint32_t trans = siba_dma_translation(sc->sc_dev);
4060
4061	if (dr->dr_tx) {
4062		dr->dr_curslot = -1;
4063
4064		if (dr->dr_type == BWN_DMA_64BIT) {
4065			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4066			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4067			    >> 30;
4068			value = BWN_DMA64_TXENABLE;
4069			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4070			    & BWN_DMA64_TXADDREXT_MASK;
4071			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4072			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4073			    (ring64 & 0xffffffff));
4074			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4075			    ((ring64 >> 32) &
4076			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4077		} else {
4078			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4079			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4080			value = BWN_DMA32_TXENABLE;
4081			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4082			    & BWN_DMA32_TXADDREXT_MASK;
4083			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4084			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4085			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4086		}
4087		return;
4088	}
4089
4090	/*
4091	 * set for RX
4092	 */
4093	dr->dr_usedslot = dr->dr_numslots;
4094
4095	if (dr->dr_type == BWN_DMA_64BIT) {
4096		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4097		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4098		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4099		value |= BWN_DMA64_RXENABLE;
4100		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4101		    & BWN_DMA64_RXADDREXT_MASK;
4102		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4103		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4104		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4105		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4106		    | (trans << 1));
4107		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4108		    sizeof(struct bwn_dmadesc64));
4109	} else {
4110		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4111		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4112		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4113		value |= BWN_DMA32_RXENABLE;
4114		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4115		    & BWN_DMA32_RXADDREXT_MASK;
4116		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4117		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4118		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4119		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4120		    sizeof(struct bwn_dmadesc32));
4121	}
4122}
4123
4124static void
4125bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4126{
4127
4128	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4129	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4130	    dr->dr_ring_dmap);
4131}
4132
4133static void
4134bwn_dma_cleanup(struct bwn_dma_ring *dr)
4135{
4136
4137	if (dr->dr_tx) {
4138		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4139		if (dr->dr_type == BWN_DMA_64BIT) {
4140			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4141			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4142		} else
4143			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4144	} else {
4145		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4146		if (dr->dr_type == BWN_DMA_64BIT) {
4147			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4148			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4149		} else
4150			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4151	}
4152}
4153
4154static void
4155bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4156{
4157	struct bwn_dmadesc_generic *desc;
4158	struct bwn_dmadesc_meta *meta;
4159	struct bwn_mac *mac = dr->dr_mac;
4160	struct bwn_dma *dma = &mac->mac_method.dma;
4161	struct bwn_softc *sc = mac->mac_sc;
4162	int i;
4163
4164	if (!dr->dr_usedslot)
4165		return;
4166	for (i = 0; i < dr->dr_numslots; i++) {
4167		dr->getdesc(dr, i, &desc, &meta);
4168
4169		if (meta->mt_m == NULL) {
4170			if (!dr->dr_tx)
4171				device_printf(sc->sc_dev, "%s: not TX?\n",
4172				    __func__);
4173			continue;
4174		}
4175		if (dr->dr_tx) {
4176			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4177				bus_dmamap_unload(dr->dr_txring_dtag,
4178				    meta->mt_dmap);
4179			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4180				bus_dmamap_unload(dma->txbuf_dtag,
4181				    meta->mt_dmap);
4182		} else
4183			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4184		bwn_dma_free_descbuf(dr, meta);
4185	}
4186}
4187
4188static int
4189bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4190    int type)
4191{
4192	struct bwn_softc *sc = mac->mac_sc;
4193	uint32_t value;
4194	int i;
4195	uint16_t offset;
4196
4197	for (i = 0; i < 10; i++) {
4198		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4199		    BWN_DMA32_TXSTATUS;
4200		value = BWN_READ_4(mac, base + offset);
4201		if (type == BWN_DMA_64BIT) {
4202			value &= BWN_DMA64_TXSTAT;
4203			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4204			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4205			    value == BWN_DMA64_TXSTAT_STOPPED)
4206				break;
4207		} else {
4208			value &= BWN_DMA32_TXSTATE;
4209			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4210			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4211			    value == BWN_DMA32_TXSTAT_STOPPED)
4212				break;
4213		}
4214		DELAY(1000);
4215	}
4216	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4217	BWN_WRITE_4(mac, base + offset, 0);
4218	for (i = 0; i < 10; i++) {
4219		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4220						   BWN_DMA32_TXSTATUS;
4221		value = BWN_READ_4(mac, base + offset);
4222		if (type == BWN_DMA_64BIT) {
4223			value &= BWN_DMA64_TXSTAT;
4224			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4225				i = -1;
4226				break;
4227			}
4228		} else {
4229			value &= BWN_DMA32_TXSTATE;
4230			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4231				i = -1;
4232				break;
4233			}
4234		}
4235		DELAY(1000);
4236	}
4237	if (i != -1) {
4238		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4239		return (ENODEV);
4240	}
4241	DELAY(1000);
4242
4243	return (0);
4244}
4245
4246static int
4247bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4248    int type)
4249{
4250	struct bwn_softc *sc = mac->mac_sc;
4251	uint32_t value;
4252	int i;
4253	uint16_t offset;
4254
4255	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4256	BWN_WRITE_4(mac, base + offset, 0);
4257	for (i = 0; i < 10; i++) {
4258		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4259		    BWN_DMA32_RXSTATUS;
4260		value = BWN_READ_4(mac, base + offset);
4261		if (type == BWN_DMA_64BIT) {
4262			value &= BWN_DMA64_RXSTAT;
4263			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4264				i = -1;
4265				break;
4266			}
4267		} else {
4268			value &= BWN_DMA32_RXSTATE;
4269			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4270				i = -1;
4271				break;
4272			}
4273		}
4274		DELAY(1000);
4275	}
4276	if (i != -1) {
4277		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4278		return (ENODEV);
4279	}
4280
4281	return (0);
4282}
4283
4284static void
4285bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4286    struct bwn_dmadesc_meta *meta)
4287{
4288
4289	if (meta->mt_m != NULL) {
4290		m_freem(meta->mt_m);
4291		meta->mt_m = NULL;
4292	}
4293	if (meta->mt_ni != NULL) {
4294		ieee80211_free_node(meta->mt_ni);
4295		meta->mt_ni = NULL;
4296	}
4297}
4298
4299static void
4300bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4301{
4302	struct bwn_rxhdr4 *rxhdr;
4303	unsigned char *frame;
4304
4305	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4306	rxhdr->frame_len = 0;
4307
4308	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4309	    sizeof(struct bwn_plcp6) + 2,
4310	    ("%s:%d: fail", __func__, __LINE__));
4311	frame = mtod(m, char *) + dr->dr_frameoffset;
4312	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4313}
4314
4315static uint8_t
4316bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4317{
4318	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4319
4320	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4321	    == 0xff);
4322}
4323
4324static void
4325bwn_wme_init(struct bwn_mac *mac)
4326{
4327
4328	bwn_wme_load(mac);
4329
4330	/* enable WME support. */
4331	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4332	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4333	    BWN_IFSCTL_USE_EDCF);
4334}
4335
4336static void
4337bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4338{
4339	struct bwn_softc *sc = mac->mac_sc;
4340	struct ieee80211com *ic = &sc->sc_ic;
4341	uint16_t delay;	/* microsec */
4342
4343	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4344	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4345		delay = 500;
4346	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4347		delay = max(delay, (uint16_t)2400);
4348
4349	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4350}
4351
4352static void
4353bwn_bt_enable(struct bwn_mac *mac)
4354{
4355	struct bwn_softc *sc = mac->mac_sc;
4356	uint64_t hf;
4357
4358	if (bwn_bluetooth == 0)
4359		return;
4360	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4361		return;
4362	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4363		return;
4364
4365	hf = bwn_hf_read(mac);
4366	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4367		hf |= BWN_HF_BT_COEXISTALT;
4368	else
4369		hf |= BWN_HF_BT_COEXIST;
4370	bwn_hf_write(mac, hf);
4371}
4372
4373static void
4374bwn_set_macaddr(struct bwn_mac *mac)
4375{
4376
4377	bwn_mac_write_bssid(mac);
4378	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
4379	    mac->mac_sc->sc_ic.ic_macaddr);
4380}
4381
4382static void
4383bwn_clear_keys(struct bwn_mac *mac)
4384{
4385	int i;
4386
4387	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4388		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4389		    ("%s:%d: fail", __func__, __LINE__));
4390
4391		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4392		    NULL, BWN_SEC_KEYSIZE, NULL);
4393		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4394			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4395			    NULL, BWN_SEC_KEYSIZE, NULL);
4396		}
4397		mac->mac_key[i].keyconf = NULL;
4398	}
4399}
4400
4401static void
4402bwn_crypt_init(struct bwn_mac *mac)
4403{
4404	struct bwn_softc *sc = mac->mac_sc;
4405
4406	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4407	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4408	    ("%s:%d: fail", __func__, __LINE__));
4409	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4410	mac->mac_ktp *= 2;
4411	if (siba_get_revid(sc->sc_dev) >= 5)
4412		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4413	bwn_clear_keys(mac);
4414}
4415
4416static void
4417bwn_chip_exit(struct bwn_mac *mac)
4418{
4419	struct bwn_softc *sc = mac->mac_sc;
4420
4421	bwn_phy_exit(mac);
4422	siba_gpio_set(sc->sc_dev, 0);
4423}
4424
4425static int
4426bwn_fw_fillinfo(struct bwn_mac *mac)
4427{
4428	int error;
4429
4430	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4431	if (error == 0)
4432		return (0);
4433	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4434	if (error == 0)
4435		return (0);
4436	return (error);
4437}
4438
4439static int
4440bwn_gpio_init(struct bwn_mac *mac)
4441{
4442	struct bwn_softc *sc = mac->mac_sc;
4443	uint32_t mask = 0x1f, set = 0xf, value;
4444
4445	BWN_WRITE_4(mac, BWN_MACCTL,
4446	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4447	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4448	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4449
4450	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4451		mask |= 0x0060;
4452		set |= 0x0060;
4453	}
4454	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4455		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4456		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4457		mask |= 0x0200;
4458		set |= 0x0200;
4459	}
4460	if (siba_get_revid(sc->sc_dev) >= 2)
4461		mask |= 0x0010;
4462
4463	value = siba_gpio_get(sc->sc_dev);
4464	if (value == -1)
4465		return (0);
4466	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4467
4468	return (0);
4469}
4470
4471static int
4472bwn_fw_loadinitvals(struct bwn_mac *mac)
4473{
4474#define	GETFWOFFSET(fwp, offset)				\
4475	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4476	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4477	const struct bwn_fwhdr *hdr;
4478	struct bwn_fw *fw = &mac->mac_fw;
4479	int error;
4480
4481	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4482	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4483	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4484	if (error)
4485		return (error);
4486	if (fw->initvals_band.fw) {
4487		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4488		error = bwn_fwinitvals_write(mac,
4489		    GETFWOFFSET(fw->initvals_band, hdr_len),
4490		    be32toh(hdr->size),
4491		    fw->initvals_band.fw->datasize - hdr_len);
4492	}
4493	return (error);
4494#undef GETFWOFFSET
4495}
4496
4497static int
4498bwn_phy_init(struct bwn_mac *mac)
4499{
4500	struct bwn_softc *sc = mac->mac_sc;
4501	int error;
4502
4503	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4504	mac->mac_phy.rf_onoff(mac, 1);
4505	error = mac->mac_phy.init(mac);
4506	if (error) {
4507		device_printf(sc->sc_dev, "PHY init failed\n");
4508		goto fail0;
4509	}
4510	error = bwn_switch_channel(mac,
4511	    mac->mac_phy.get_default_chan(mac));
4512	if (error) {
4513		device_printf(sc->sc_dev,
4514		    "failed to switch default channel\n");
4515		goto fail1;
4516	}
4517	return (0);
4518fail1:
4519	if (mac->mac_phy.exit)
4520		mac->mac_phy.exit(mac);
4521fail0:
4522	mac->mac_phy.rf_onoff(mac, 0);
4523
4524	return (error);
4525}
4526
4527static void
4528bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4529{
4530	uint16_t ant;
4531	uint16_t tmp;
4532
4533	ant = bwn_ant2phy(antenna);
4534
4535	/* For ACK/CTS */
4536	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4537	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4538	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4539	/* For Probe Resposes */
4540	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4541	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4542	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4543}
4544
4545static void
4546bwn_set_opmode(struct bwn_mac *mac)
4547{
4548	struct bwn_softc *sc = mac->mac_sc;
4549	struct ieee80211com *ic = &sc->sc_ic;
4550	uint32_t ctl;
4551	uint16_t cfp_pretbtt;
4552
4553	ctl = BWN_READ_4(mac, BWN_MACCTL);
4554	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4555	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4556	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4557	ctl |= BWN_MACCTL_STA;
4558
4559	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4560	    ic->ic_opmode == IEEE80211_M_MBSS)
4561		ctl |= BWN_MACCTL_HOSTAP;
4562	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4563		ctl &= ~BWN_MACCTL_STA;
4564	ctl |= sc->sc_filters;
4565
4566	if (siba_get_revid(sc->sc_dev) <= 4)
4567		ctl |= BWN_MACCTL_PROMISC;
4568
4569	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4570
4571	cfp_pretbtt = 2;
4572	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4573		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4574		    siba_get_chiprev(sc->sc_dev) == 3)
4575			cfp_pretbtt = 100;
4576		else
4577			cfp_pretbtt = 50;
4578	}
4579	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4580}
4581
4582static int
4583bwn_dma_gettype(struct bwn_mac *mac)
4584{
4585	uint32_t tmp;
4586	uint16_t base;
4587
4588	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4589	if (tmp & SIBA_TGSHIGH_DMA64)
4590		return (BWN_DMA_64BIT);
4591	base = bwn_dma_base(0, 0);
4592	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4593	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4594	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4595		return (BWN_DMA_32BIT);
4596
4597	return (BWN_DMA_30BIT);
4598}
4599
4600static void
4601bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4602{
4603	if (!error) {
4604		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4605		*((bus_addr_t *)arg) = seg->ds_addr;
4606	}
4607}
4608
4609static void
4610bwn_phy_g_init_sub(struct bwn_mac *mac)
4611{
4612	struct bwn_phy *phy = &mac->mac_phy;
4613	struct bwn_phy_g *pg = &phy->phy_g;
4614	struct bwn_softc *sc = mac->mac_sc;
4615	uint16_t i, tmp;
4616
4617	if (phy->rev == 1)
4618		bwn_phy_init_b5(mac);
4619	else
4620		bwn_phy_init_b6(mac);
4621
4622	if (phy->rev >= 2 || phy->gmode)
4623		bwn_phy_init_a(mac);
4624
4625	if (phy->rev >= 2) {
4626		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4627		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4628	}
4629	if (phy->rev == 2) {
4630		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4631		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4632	}
4633	if (phy->rev > 5) {
4634		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4635		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4636	}
4637	if (phy->gmode || phy->rev >= 2) {
4638		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4639		tmp &= BWN_PHYVER_VERSION;
4640		if (tmp == 3 || tmp == 5) {
4641			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4642			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4643		}
4644		if (tmp == 5) {
4645			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4646			    0x1f00);
4647		}
4648	}
4649	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4650		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4651	if (phy->rf_rev == 8) {
4652		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4653		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4654	}
4655	if (BWN_HAS_LOOPBACK(phy))
4656		bwn_loopback_calcgain(mac);
4657
4658	if (phy->rf_rev != 8) {
4659		if (pg->pg_initval == 0xffff)
4660			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4661		else
4662			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4663	}
4664	bwn_lo_g_init(mac);
4665	if (BWN_HAS_TXMAG(phy)) {
4666		BWN_RF_WRITE(mac, 0x52,
4667		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4668		    | pg->pg_loctl.tx_bias |
4669		    pg->pg_loctl.tx_magn);
4670	} else {
4671		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4672	}
4673	if (phy->rev >= 6) {
4674		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4675		    (pg->pg_loctl.tx_bias << 12));
4676	}
4677	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4678		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4679	else
4680		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4681	if (phy->rev < 2)
4682		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4683	else
4684		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4685	if (phy->gmode || phy->rev >= 2) {
4686		bwn_lo_g_adjust(mac);
4687		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4688	}
4689
4690	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4691		for (i = 0; i < 64; i++) {
4692			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4693			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4694			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4695			    -32), 31));
4696		}
4697		bwn_nrssi_threshold(mac);
4698	} else if (phy->gmode || phy->rev >= 2) {
4699		if (pg->pg_nrssi[0] == -1000) {
4700			KASSERT(pg->pg_nrssi[1] == -1000,
4701			    ("%s:%d: fail", __func__, __LINE__));
4702			bwn_nrssi_slope_11g(mac);
4703		} else
4704			bwn_nrssi_threshold(mac);
4705	}
4706	if (phy->rf_rev == 8)
4707		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4708	bwn_phy_hwpctl_init(mac);
4709	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4710	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4711		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4712		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4713	}
4714}
4715
4716static uint8_t
4717bwn_has_hwpctl(struct bwn_mac *mac)
4718{
4719
4720	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4721		return (0);
4722	return (mac->mac_phy.use_hwpctl(mac));
4723}
4724
4725static void
4726bwn_phy_init_b5(struct bwn_mac *mac)
4727{
4728	struct bwn_phy *phy = &mac->mac_phy;
4729	struct bwn_phy_g *pg = &phy->phy_g;
4730	struct bwn_softc *sc = mac->mac_sc;
4731	uint16_t offset, value;
4732	uint8_t old_channel;
4733
4734	if (phy->analog == 1)
4735		BWN_RF_SET(mac, 0x007a, 0x0050);
4736	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4737	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4738		value = 0x2120;
4739		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4740			BWN_PHY_WRITE(mac, offset, value);
4741			value += 0x202;
4742		}
4743	}
4744	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4745	if (phy->rf_ver == 0x2050)
4746		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4747
4748	if (phy->gmode || phy->rev >= 2) {
4749		if (phy->rf_ver == 0x2050) {
4750			BWN_RF_SET(mac, 0x007a, 0x0020);
4751			BWN_RF_SET(mac, 0x0051, 0x0004);
4752		}
4753		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4754
4755		BWN_PHY_SET(mac, 0x0802, 0x0100);
4756		BWN_PHY_SET(mac, 0x042b, 0x2000);
4757
4758		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4759
4760		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4761		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4762		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4763	}
4764
4765	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4766		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4767
4768	if (phy->analog == 1) {
4769		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4770		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4771		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4772		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4773		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4774	} else
4775		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4776	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4777	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4778
4779	if (phy->analog == 1)
4780		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4781	else
4782		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4783
4784	if (phy->analog == 0)
4785		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4786
4787	old_channel = phy->chan;
4788	bwn_phy_g_switch_chan(mac, 7, 0);
4789
4790	if (phy->rf_ver != 0x2050) {
4791		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4792		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4793	}
4794
4795	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4796	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4797
4798	if (phy->rf_ver == 0x2050) {
4799		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4800		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4801	}
4802
4803	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4804	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4805	BWN_RF_SET(mac, 0x007a, 0x0007);
4806
4807	bwn_phy_g_switch_chan(mac, old_channel, 0);
4808	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4809	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4810	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4811
4812	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4813	    pg->pg_txctl);
4814
4815	if (phy->rf_ver == 0x2050)
4816		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4817
4818	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4819}
4820
4821static void
4822bwn_loopback_calcgain(struct bwn_mac *mac)
4823{
4824	struct bwn_phy *phy = &mac->mac_phy;
4825	struct bwn_phy_g *pg = &phy->phy_g;
4826	struct bwn_softc *sc = mac->mac_sc;
4827	uint16_t backup_phy[16] = { 0 };
4828	uint16_t backup_radio[3];
4829	uint16_t backup_bband;
4830	uint16_t i, j, loop_i_max;
4831	uint16_t trsw_rx;
4832	uint16_t loop1_outer_done, loop1_inner_done;
4833
4834	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4835	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4836	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4837	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4838	if (phy->rev != 1) {
4839		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4840		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4841	}
4842	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4843	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4844	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4845	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4846	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4847	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4848	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4849	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4850	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4851	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4852	backup_bband = pg->pg_bbatt.att;
4853	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4854	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4855	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4856
4857	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4858	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4859	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4860	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4861	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4862	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4863	if (phy->rev != 1) {
4864		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4865		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4866		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4867		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4868	}
4869	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4870	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4871	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4872	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4873
4874	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4875	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4876	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4877
4878	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4879	if (phy->rev != 1) {
4880		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4881		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4882	}
4883	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4884
4885	if (phy->rf_rev == 8)
4886		BWN_RF_WRITE(mac, 0x43, 0x000f);
4887	else {
4888		BWN_RF_WRITE(mac, 0x52, 0);
4889		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4890	}
4891	bwn_phy_g_set_bbatt(mac, 11);
4892
4893	if (phy->rev >= 3)
4894		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4895	else
4896		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4897	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
4898
4899	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
4900	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
4901
4902	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
4903	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
4904
4905	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
4906		if (phy->rev >= 7) {
4907			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
4908			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
4909		}
4910	}
4911	BWN_RF_MASK(mac, 0x7a, 0x00f7);
4912
4913	j = 0;
4914	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
4915	for (i = 0; i < loop_i_max; i++) {
4916		for (j = 0; j < 16; j++) {
4917			BWN_RF_WRITE(mac, 0x43, i);
4918			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
4919			    (j << 8));
4920			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4921			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4922			DELAY(20);
4923			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4924				goto done0;
4925		}
4926	}
4927done0:
4928	loop1_outer_done = i;
4929	loop1_inner_done = j;
4930	if (j >= 8) {
4931		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
4932		trsw_rx = 0x1b;
4933		for (j = j - 8; j < 16; j++) {
4934			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
4935			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4936			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4937			DELAY(20);
4938			trsw_rx -= 3;
4939			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4940				goto done1;
4941		}
4942	} else
4943		trsw_rx = 0x18;
4944done1:
4945
4946	if (phy->rev != 1) {
4947		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
4948		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
4949	}
4950	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
4951	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
4952	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
4953	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
4954	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
4955	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
4956	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
4957	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
4958	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
4959
4960	bwn_phy_g_set_bbatt(mac, backup_bband);
4961
4962	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
4963	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
4964	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
4965
4966	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
4967	DELAY(10);
4968	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
4969	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
4970	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
4971	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
4972
4973	pg->pg_max_lb_gain =
4974	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
4975	pg->pg_trsw_rx_gain = trsw_rx * 2;
4976}
4977
4978static uint16_t
4979bwn_rf_init_bcm2050(struct bwn_mac *mac)
4980{
4981	struct bwn_phy *phy = &mac->mac_phy;
4982	uint32_t tmp1 = 0, tmp2 = 0;
4983	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
4984	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
4985	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
4986	static const uint8_t rcc_table[] = {
4987		0x02, 0x03, 0x01, 0x0f,
4988		0x06, 0x07, 0x05, 0x0f,
4989		0x0a, 0x0b, 0x09, 0x0f,
4990		0x0e, 0x0f, 0x0d, 0x0f,
4991	};
4992
4993	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
4994	    rfoverval = rfover = cck3 = 0;
4995	radio0 = BWN_RF_READ(mac, 0x43);
4996	radio1 = BWN_RF_READ(mac, 0x51);
4997	radio2 = BWN_RF_READ(mac, 0x52);
4998	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4999	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5000	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5001	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5002
5003	if (phy->type == BWN_PHYTYPE_B) {
5004		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5005		reg0 = BWN_READ_2(mac, 0x3ec);
5006
5007		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5008		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5009	} else if (phy->gmode || phy->rev >= 2) {
5010		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5011		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5012		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5013		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5014		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5015		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5016
5017		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5018		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5019		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5020		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5021		if (BWN_HAS_LOOPBACK(phy)) {
5022			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5023			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5024			if (phy->rev >= 3)
5025				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5026			else
5027				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5028			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5029		}
5030
5031		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5032		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5033			BWN_LPD(0, 1, 1)));
5034		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5035		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5036	}
5037	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5038
5039	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5040	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5041	reg1 = BWN_READ_2(mac, 0x3e6);
5042	reg2 = BWN_READ_2(mac, 0x3f4);
5043
5044	if (phy->analog == 0)
5045		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5046	else {
5047		if (phy->analog >= 2)
5048			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5049		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5050		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5051	}
5052
5053	reg = BWN_RF_READ(mac, 0x60);
5054	index = (reg & 0x001e) >> 1;
5055	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5056
5057	if (phy->type == BWN_PHYTYPE_B)
5058		BWN_RF_WRITE(mac, 0x78, 0x26);
5059	if (phy->gmode || phy->rev >= 2) {
5060		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5061		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5062			BWN_LPD(0, 1, 1)));
5063	}
5064	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5065	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5066	if (phy->gmode || phy->rev >= 2) {
5067		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5068		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5069			BWN_LPD(0, 0, 1)));
5070	}
5071	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5072	BWN_RF_SET(mac, 0x51, 0x0004);
5073	if (phy->rf_rev == 8)
5074		BWN_RF_WRITE(mac, 0x43, 0x1f);
5075	else {
5076		BWN_RF_WRITE(mac, 0x52, 0);
5077		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5078	}
5079	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5080
5081	for (i = 0; i < 16; i++) {
5082		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5083		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5084		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5085		if (phy->gmode || phy->rev >= 2) {
5086			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5087			    bwn_rf_2050_rfoverval(mac,
5088				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5089		}
5090		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5091		DELAY(10);
5092		if (phy->gmode || phy->rev >= 2) {
5093			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5094			    bwn_rf_2050_rfoverval(mac,
5095				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5096		}
5097		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5098		DELAY(10);
5099		if (phy->gmode || phy->rev >= 2) {
5100			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5101			    bwn_rf_2050_rfoverval(mac,
5102				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5103		}
5104		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5105		DELAY(20);
5106		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5107		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5108		if (phy->gmode || phy->rev >= 2) {
5109			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5110			    bwn_rf_2050_rfoverval(mac,
5111				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5112		}
5113		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5114	}
5115	DELAY(10);
5116
5117	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5118	tmp1++;
5119	tmp1 >>= 9;
5120
5121	for (i = 0; i < 16; i++) {
5122		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5123		BWN_RF_WRITE(mac, 0x78, radio78);
5124		DELAY(10);
5125		for (j = 0; j < 16; j++) {
5126			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5127			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5128			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5129			if (phy->gmode || phy->rev >= 2) {
5130				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5131				    bwn_rf_2050_rfoverval(mac,
5132					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5133			}
5134			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5135			DELAY(10);
5136			if (phy->gmode || phy->rev >= 2) {
5137				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5138				    bwn_rf_2050_rfoverval(mac,
5139					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5140			}
5141			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5142			DELAY(10);
5143			if (phy->gmode || phy->rev >= 2) {
5144				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5145				    bwn_rf_2050_rfoverval(mac,
5146					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5147			}
5148			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5149			DELAY(10);
5150			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5151			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5152			if (phy->gmode || phy->rev >= 2) {
5153				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5154				    bwn_rf_2050_rfoverval(mac,
5155					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5156			}
5157			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5158		}
5159		tmp2++;
5160		tmp2 >>= 8;
5161		if (tmp1 < tmp2)
5162			break;
5163	}
5164
5165	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5166	BWN_RF_WRITE(mac, 0x51, radio1);
5167	BWN_RF_WRITE(mac, 0x52, radio2);
5168	BWN_RF_WRITE(mac, 0x43, radio0);
5169	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5170	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5171	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5172	BWN_WRITE_2(mac, 0x3e6, reg1);
5173	if (phy->analog != 0)
5174		BWN_WRITE_2(mac, 0x3f4, reg2);
5175	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5176	bwn_spu_workaround(mac, phy->chan);
5177	if (phy->type == BWN_PHYTYPE_B) {
5178		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5179		BWN_WRITE_2(mac, 0x3ec, reg0);
5180	} else if (phy->gmode) {
5181		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5182			    BWN_READ_2(mac, BWN_PHY_RADIO)
5183			    & 0x7fff);
5184		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5185		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5186		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5187		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5188			      analogoverval);
5189		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5190		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5191		if (BWN_HAS_LOOPBACK(phy)) {
5192			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5193			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5194		}
5195	}
5196
5197	return ((i > 15) ? radio78 : rcc);
5198}
5199
5200static void
5201bwn_phy_init_b6(struct bwn_mac *mac)
5202{
5203	struct bwn_phy *phy = &mac->mac_phy;
5204	struct bwn_phy_g *pg = &phy->phy_g;
5205	struct bwn_softc *sc = mac->mac_sc;
5206	uint16_t offset, val;
5207	uint8_t old_channel;
5208
5209	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5210	    ("%s:%d: fail", __func__, __LINE__));
5211
5212	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5213	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5214	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5215		BWN_RF_WRITE(mac, 0x51, 0x37);
5216		BWN_RF_WRITE(mac, 0x52, 0x70);
5217		BWN_RF_WRITE(mac, 0x53, 0xb3);
5218		BWN_RF_WRITE(mac, 0x54, 0x9b);
5219		BWN_RF_WRITE(mac, 0x5a, 0x88);
5220		BWN_RF_WRITE(mac, 0x5b, 0x88);
5221		BWN_RF_WRITE(mac, 0x5d, 0x88);
5222		BWN_RF_WRITE(mac, 0x5e, 0x88);
5223		BWN_RF_WRITE(mac, 0x7d, 0x88);
5224		bwn_hf_write(mac,
5225		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5226	}
5227	if (phy->rf_rev == 8) {
5228		BWN_RF_WRITE(mac, 0x51, 0);
5229		BWN_RF_WRITE(mac, 0x52, 0x40);
5230		BWN_RF_WRITE(mac, 0x53, 0xb7);
5231		BWN_RF_WRITE(mac, 0x54, 0x98);
5232		BWN_RF_WRITE(mac, 0x5a, 0x88);
5233		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5234		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5235		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5236			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5237			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5238		} else {
5239			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5240			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5241		}
5242		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5243		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5244		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5245		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5246	}
5247	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5248		BWN_PHY_WRITE(mac, offset, val);
5249		val -= 0x0202;
5250	}
5251	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5252		BWN_PHY_WRITE(mac, offset, val);
5253		val -= 0x0202;
5254	}
5255	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5256		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5257		val += 0x0202;
5258	}
5259	if (phy->type == BWN_PHYTYPE_G) {
5260		BWN_RF_SET(mac, 0x007a, 0x0020);
5261		BWN_RF_SET(mac, 0x0051, 0x0004);
5262		BWN_PHY_SET(mac, 0x0802, 0x0100);
5263		BWN_PHY_SET(mac, 0x042b, 0x2000);
5264		BWN_PHY_WRITE(mac, 0x5b, 0);
5265		BWN_PHY_WRITE(mac, 0x5c, 0);
5266	}
5267
5268	old_channel = phy->chan;
5269	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5270
5271	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5272	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5273	DELAY(40);
5274	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5275		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5276		BWN_RF_WRITE(mac, 0x50, 0x20);
5277	}
5278	if (phy->rf_rev <= 2) {
5279		BWN_RF_WRITE(mac, 0x7c, 0x20);
5280		BWN_RF_WRITE(mac, 0x5a, 0x70);
5281		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5282		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5283	}
5284	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5285
5286	bwn_phy_g_switch_chan(mac, old_channel, 0);
5287
5288	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5289	if (phy->rf_rev >= 6)
5290		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5291	else
5292		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5293	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5294	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5295	    pg->pg_txctl);
5296	if (phy->rf_rev <= 5)
5297		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5298	if (phy->rf_rev <= 2)
5299		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5300
5301	if (phy->analog == 4) {
5302		BWN_WRITE_2(mac, 0x3e4, 9);
5303		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5304	} else
5305		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5306	if (phy->type == BWN_PHYTYPE_B)
5307		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5308	else if (phy->type == BWN_PHYTYPE_G)
5309		BWN_WRITE_2(mac, 0x03e6, 0x0);
5310}
5311
5312static void
5313bwn_phy_init_a(struct bwn_mac *mac)
5314{
5315	struct bwn_phy *phy = &mac->mac_phy;
5316	struct bwn_softc *sc = mac->mac_sc;
5317
5318	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5319	    ("%s:%d: fail", __func__, __LINE__));
5320
5321	if (phy->rev >= 6) {
5322		if (phy->type == BWN_PHYTYPE_A)
5323			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5324		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5325			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5326		else
5327			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5328	}
5329
5330	bwn_wa_init(mac);
5331
5332	if (phy->type == BWN_PHYTYPE_G &&
5333	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5334		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5335}
5336
5337static void
5338bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5339{
5340	int i;
5341
5342	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5343		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5344}
5345
5346static void
5347bwn_wa_agc(struct bwn_mac *mac)
5348{
5349	struct bwn_phy *phy = &mac->mac_phy;
5350
5351	if (phy->rev == 1) {
5352		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5353		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5354		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5355		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5356		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5357		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5358		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5359		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5360		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5361	} else {
5362		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5363		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5364		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5365		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5366	}
5367
5368	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5369	    0x5700);
5370	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5371	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5372	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5373	BWN_RF_SET(mac, 0x7a, 0x0008);
5374	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5375	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5376	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5377	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5378	if (phy->rev == 1)
5379		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5380	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5381	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5382	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5383	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5384	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5385	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5386	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5387	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5388	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5389	if (phy->rev == 1) {
5390		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5391		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5392	} else {
5393		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5394		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5395		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5396		if (phy->rev >= 6) {
5397			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5398			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5399			    (uint16_t)~0xf000, 0x3000);
5400		}
5401	}
5402	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5403	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5404	if (phy->rev == 1) {
5405		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5406		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5407		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5408		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5409		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5410		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5411		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5412		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5413	} else {
5414		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5415		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5416		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5417		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5418	}
5419	if (phy->rev >= 6) {
5420		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5421		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5422	}
5423	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5424}
5425
5426static void
5427bwn_wa_grev1(struct bwn_mac *mac)
5428{
5429	struct bwn_phy *phy = &mac->mac_phy;
5430	int i;
5431	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5432	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5433	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5434
5435	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5436
5437	/* init CRSTHRES and ANTDWELL */
5438	if (phy->rev == 1) {
5439		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5440	} else if (phy->rev == 2) {
5441		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5442		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5443		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5444	} else {
5445		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5446		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5447		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5448		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5449	}
5450	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5451	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5452	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5453
5454	/* XXX support PHY-A??? */
5455	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5456		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5457		    bwn_tab_finefreqg[i]);
5458
5459	/* XXX support PHY-A??? */
5460	if (phy->rev == 1)
5461		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5462			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5463			    bwn_tab_noise_g1[i]);
5464	else
5465		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5466			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5467			    bwn_tab_noise_g2[i]);
5468
5469
5470	for (i = 0; i < N(bwn_tab_rotor); i++)
5471		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5472		    bwn_tab_rotor[i]);
5473
5474	/* XXX support PHY-A??? */
5475	if (phy->rev >= 6) {
5476		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5477		    BWN_PHY_ENCORE_EN)
5478			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5479		else
5480			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5481	} else
5482		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5483
5484	for (i = 0; i < N(bwn_tab_retard); i++)
5485		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5486		    bwn_tab_retard[i]);
5487
5488	if (phy->rev == 1) {
5489		for (i = 0; i < 16; i++)
5490			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5491			    i, 0x0020);
5492	} else {
5493		for (i = 0; i < 32; i++)
5494			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5495	}
5496
5497	bwn_wa_agc(mac);
5498}
5499
5500static void
5501bwn_wa_grev26789(struct bwn_mac *mac)
5502{
5503	struct bwn_phy *phy = &mac->mac_phy;
5504	int i;
5505	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5506	uint16_t ofdmrev;
5507
5508	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5509
5510	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5511
5512	/* init CRSTHRES and ANTDWELL */
5513	if (phy->rev == 1)
5514		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5515	else if (phy->rev == 2) {
5516		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5517		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5518		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5519	} else {
5520		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5521		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5522		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5523		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5524	}
5525
5526	for (i = 0; i < 64; i++)
5527		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5528
5529	/* XXX support PHY-A??? */
5530	if (phy->rev == 1)
5531		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5532			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5533			    bwn_tab_noise_g1[i]);
5534	else
5535		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5536			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5537			    bwn_tab_noise_g2[i]);
5538
5539	/* XXX support PHY-A??? */
5540	if (phy->rev >= 6) {
5541		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5542		    BWN_PHY_ENCORE_EN)
5543			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5544		else
5545			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5546	} else
5547		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5548
5549	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5550		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5551		    bwn_tab_sigmasqr2[i]);
5552
5553	if (phy->rev == 1) {
5554		for (i = 0; i < 16; i++)
5555			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5556			    0x0020);
5557	} else {
5558		for (i = 0; i < 32; i++)
5559			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5560	}
5561
5562	bwn_wa_agc(mac);
5563
5564	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5565	if (ofdmrev > 2) {
5566		if (phy->type == BWN_PHYTYPE_A)
5567			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5568		else
5569			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5570	} else {
5571		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5572		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5573		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5574	}
5575
5576	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5577	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5578}
5579
5580static void
5581bwn_wa_init(struct bwn_mac *mac)
5582{
5583	struct bwn_phy *phy = &mac->mac_phy;
5584	struct bwn_softc *sc = mac->mac_sc;
5585
5586	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5587
5588	switch (phy->rev) {
5589	case 1:
5590		bwn_wa_grev1(mac);
5591		break;
5592	case 2:
5593	case 6:
5594	case 7:
5595	case 8:
5596	case 9:
5597		bwn_wa_grev26789(mac);
5598		break;
5599	default:
5600		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5601	}
5602
5603	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5604	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5605	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5606		if (phy->rev < 2) {
5607			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5608			    0x0002);
5609			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5610			    0x0001);
5611		} else {
5612			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5613			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5614			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5615			     BWN_BFL_EXTLNA) &&
5616			    (phy->rev >= 7)) {
5617				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5618				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5619				    0x0020, 0x0001);
5620				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5621				    0x0021, 0x0001);
5622				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5623				    0x0022, 0x0001);
5624				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5625				    0x0023, 0x0000);
5626				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5627				    0x0000, 0x0000);
5628				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5629				    0x0003, 0x0002);
5630			}
5631		}
5632	}
5633	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5634		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5635		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5636	}
5637
5638	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5639	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5640}
5641
5642static void
5643bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5644    uint16_t value)
5645{
5646	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5647	uint16_t addr;
5648
5649	addr = table + offset;
5650	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5651	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5652		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5653		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5654	}
5655	pg->pg_ofdmtab_addr = addr;
5656	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5657}
5658
5659static void
5660bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5661    uint32_t value)
5662{
5663	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5664	uint16_t addr;
5665
5666	addr = table + offset;
5667	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5668	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5669		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5670		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5671	}
5672	pg->pg_ofdmtab_addr = addr;
5673
5674	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5675	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5676}
5677
5678static void
5679bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5680    uint16_t value)
5681{
5682
5683	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5684	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5685}
5686
5687static void
5688bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5689{
5690	struct bwn_phy *phy = &mac->mac_phy;
5691	struct bwn_softc *sc = mac->mac_sc;
5692	unsigned int i, max_loop;
5693	uint16_t value;
5694	uint32_t buffer[5] = {
5695		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5696	};
5697
5698	if (ofdm) {
5699		max_loop = 0x1e;
5700		buffer[0] = 0x000201cc;
5701	} else {
5702		max_loop = 0xfa;
5703		buffer[0] = 0x000b846e;
5704	}
5705
5706	BWN_ASSERT_LOCKED(mac->mac_sc);
5707
5708	for (i = 0; i < 5; i++)
5709		bwn_ram_write(mac, i * 4, buffer[i]);
5710
5711	BWN_WRITE_2(mac, 0x0568, 0x0000);
5712	BWN_WRITE_2(mac, 0x07c0,
5713	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5714	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5715	BWN_WRITE_2(mac, 0x050c, value);
5716	if (phy->type == BWN_PHYTYPE_LP)
5717		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5718	BWN_WRITE_2(mac, 0x0508, 0x0000);
5719	BWN_WRITE_2(mac, 0x050a, 0x0000);
5720	BWN_WRITE_2(mac, 0x054c, 0x0000);
5721	BWN_WRITE_2(mac, 0x056a, 0x0014);
5722	BWN_WRITE_2(mac, 0x0568, 0x0826);
5723	BWN_WRITE_2(mac, 0x0500, 0x0000);
5724	if (phy->type == BWN_PHYTYPE_LP)
5725		BWN_WRITE_2(mac, 0x0502, 0x0050);
5726	else
5727		BWN_WRITE_2(mac, 0x0502, 0x0030);
5728
5729	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5730		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5731	for (i = 0x00; i < max_loop; i++) {
5732		value = BWN_READ_2(mac, 0x050e);
5733		if (value & 0x0080)
5734			break;
5735		DELAY(10);
5736	}
5737	for (i = 0x00; i < 0x0a; i++) {
5738		value = BWN_READ_2(mac, 0x050e);
5739		if (value & 0x0400)
5740			break;
5741		DELAY(10);
5742	}
5743	for (i = 0x00; i < 0x19; i++) {
5744		value = BWN_READ_2(mac, 0x0690);
5745		if (!(value & 0x0100))
5746			break;
5747		DELAY(10);
5748	}
5749	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5750		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5751}
5752
5753static void
5754bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5755{
5756	uint32_t macctl;
5757
5758	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5759
5760	macctl = BWN_READ_4(mac, BWN_MACCTL);
5761	if (macctl & BWN_MACCTL_BIGENDIAN)
5762		printf("TODO: need swap\n");
5763
5764	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5765	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5766	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5767}
5768
5769static void
5770bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5771{
5772	uint16_t value;
5773
5774	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5775	    ("%s:%d: fail", __func__, __LINE__));
5776
5777	value = (uint8_t) (ctl->q);
5778	value |= ((uint8_t) (ctl->i)) << 8;
5779	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5780}
5781
5782static uint16_t
5783bwn_lo_calcfeed(struct bwn_mac *mac,
5784    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5785{
5786	struct bwn_phy *phy = &mac->mac_phy;
5787	struct bwn_softc *sc = mac->mac_sc;
5788	uint16_t rfover;
5789	uint16_t feedthrough;
5790
5791	if (phy->gmode) {
5792		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5793		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5794
5795		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5796		    ("%s:%d: fail", __func__, __LINE__));
5797		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5798		    ("%s:%d: fail", __func__, __LINE__));
5799
5800		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5801
5802		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5803		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5804		    phy->rev > 6)
5805			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5806
5807		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5808		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5809		DELAY(10);
5810		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5811		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5812		DELAY(10);
5813		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5814		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5815		DELAY(10);
5816		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5817	} else {
5818		pga |= BWN_PHY_PGACTL_UNKNOWN;
5819		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5820		DELAY(10);
5821		pga |= BWN_PHY_PGACTL_LOWBANDW;
5822		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5823		DELAY(10);
5824		pga |= BWN_PHY_PGACTL_LPF;
5825		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5826	}
5827	DELAY(21);
5828	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5829
5830	return (feedthrough);
5831}
5832
5833static uint16_t
5834bwn_lo_txctl_regtable(struct bwn_mac *mac,
5835    uint16_t *value, uint16_t *pad_mix_gain)
5836{
5837	struct bwn_phy *phy = &mac->mac_phy;
5838	uint16_t reg, v, padmix;
5839
5840	if (phy->type == BWN_PHYTYPE_B) {
5841		v = 0x30;
5842		if (phy->rf_rev <= 5) {
5843			reg = 0x43;
5844			padmix = 0;
5845		} else {
5846			reg = 0x52;
5847			padmix = 5;
5848		}
5849	} else {
5850		if (phy->rev >= 2 && phy->rf_rev == 8) {
5851			reg = 0x43;
5852			v = 0x10;
5853			padmix = 2;
5854		} else {
5855			reg = 0x52;
5856			v = 0x30;
5857			padmix = 5;
5858		}
5859	}
5860	if (value)
5861		*value = v;
5862	if (pad_mix_gain)
5863		*pad_mix_gain = padmix;
5864
5865	return (reg);
5866}
5867
5868static void
5869bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5870{
5871	struct bwn_phy *phy = &mac->mac_phy;
5872	struct bwn_phy_g *pg = &phy->phy_g;
5873	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5874	uint16_t reg, mask;
5875	uint16_t trsw_rx, pga;
5876	uint16_t rf_pctl_reg;
5877
5878	static const uint8_t tx_bias_values[] = {
5879		0x09, 0x08, 0x0a, 0x01, 0x00,
5880		0x02, 0x05, 0x04, 0x06,
5881	};
5882	static const uint8_t tx_magn_values[] = {
5883		0x70, 0x40,
5884	};
5885
5886	if (!BWN_HAS_LOOPBACK(phy)) {
5887		rf_pctl_reg = 6;
5888		trsw_rx = 2;
5889		pga = 0;
5890	} else {
5891		int lb_gain;
5892
5893		trsw_rx = 0;
5894		lb_gain = pg->pg_max_lb_gain / 2;
5895		if (lb_gain > 10) {
5896			rf_pctl_reg = 0;
5897			pga = abs(10 - lb_gain) / 6;
5898			pga = MIN(MAX(pga, 0), 15);
5899		} else {
5900			int cmp_val;
5901			int tmp;
5902
5903			pga = 0;
5904			cmp_val = 0x24;
5905			if ((phy->rev >= 2) &&
5906			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
5907				cmp_val = 0x3c;
5908			tmp = lb_gain;
5909			if ((10 - lb_gain) < cmp_val)
5910				tmp = (10 - lb_gain);
5911			if (tmp < 0)
5912				tmp += 6;
5913			else
5914				tmp += 3;
5915			cmp_val /= 4;
5916			tmp /= 4;
5917			if (tmp >= cmp_val)
5918				rf_pctl_reg = cmp_val;
5919			else
5920				rf_pctl_reg = tmp;
5921		}
5922	}
5923	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
5924	bwn_phy_g_set_bbatt(mac, 2);
5925
5926	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
5927	mask = ~mask;
5928	BWN_RF_MASK(mac, reg, mask);
5929
5930	if (BWN_HAS_TXMAG(phy)) {
5931		int i, j;
5932		int feedthrough;
5933		int min_feedth = 0xffff;
5934		uint8_t tx_magn, tx_bias;
5935
5936		for (i = 0; i < N(tx_magn_values); i++) {
5937			tx_magn = tx_magn_values[i];
5938			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
5939			for (j = 0; j < N(tx_bias_values); j++) {
5940				tx_bias = tx_bias_values[j];
5941				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
5942				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
5943				    trsw_rx);
5944				if (feedthrough < min_feedth) {
5945					lo->tx_bias = tx_bias;
5946					lo->tx_magn = tx_magn;
5947					min_feedth = feedthrough;
5948				}
5949				if (lo->tx_bias == 0)
5950					break;
5951			}
5952			BWN_RF_WRITE(mac, 0x52,
5953					  (BWN_RF_READ(mac, 0x52)
5954					   & 0xff00) | lo->tx_bias | lo->
5955					  tx_magn);
5956		}
5957	} else {
5958		lo->tx_magn = 0;
5959		lo->tx_bias = 0;
5960		BWN_RF_MASK(mac, 0x52, 0xfff0);
5961	}
5962
5963	BWN_GETTIME(lo->txctl_measured_time);
5964}
5965
5966static void
5967bwn_lo_get_powervector(struct bwn_mac *mac)
5968{
5969	struct bwn_phy *phy = &mac->mac_phy;
5970	struct bwn_phy_g *pg = &phy->phy_g;
5971	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5972	int i;
5973	uint64_t tmp;
5974	uint64_t power_vector = 0;
5975
5976	for (i = 0; i < 8; i += 2) {
5977		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
5978		power_vector |= (tmp << (i * 8));
5979		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
5980	}
5981	if (power_vector)
5982		lo->power_vector = power_vector;
5983
5984	BWN_GETTIME(lo->pwr_vec_read_time);
5985}
5986
5987static void
5988bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
5989    int use_trsw_rx)
5990{
5991	struct bwn_phy *phy = &mac->mac_phy;
5992	struct bwn_phy_g *pg = &phy->phy_g;
5993	uint16_t tmp;
5994
5995	if (max_rx_gain < 0)
5996		max_rx_gain = 0;
5997
5998	if (BWN_HAS_LOOPBACK(phy)) {
5999		int trsw_rx = 0;
6000		int trsw_rx_gain;
6001
6002		if (use_trsw_rx) {
6003			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6004			if (max_rx_gain >= trsw_rx_gain) {
6005				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6006				trsw_rx = 0x20;
6007			}
6008		} else
6009			trsw_rx_gain = max_rx_gain;
6010		if (trsw_rx_gain < 9) {
6011			pg->pg_lna_lod_gain = 0;
6012		} else {
6013			pg->pg_lna_lod_gain = 1;
6014			trsw_rx_gain -= 8;
6015		}
6016		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6017		pg->pg_pga_gain = trsw_rx_gain / 3;
6018		if (pg->pg_pga_gain >= 5) {
6019			pg->pg_pga_gain -= 5;
6020			pg->pg_lna_gain = 2;
6021		} else
6022			pg->pg_lna_gain = 0;
6023	} else {
6024		pg->pg_lna_gain = 0;
6025		pg->pg_trsw_rx_gain = 0x20;
6026		if (max_rx_gain >= 0x14) {
6027			pg->pg_lna_lod_gain = 1;
6028			pg->pg_pga_gain = 2;
6029		} else if (max_rx_gain >= 0x12) {
6030			pg->pg_lna_lod_gain = 1;
6031			pg->pg_pga_gain = 1;
6032		} else if (max_rx_gain >= 0xf) {
6033			pg->pg_lna_lod_gain = 1;
6034			pg->pg_pga_gain = 0;
6035		} else {
6036			pg->pg_lna_lod_gain = 0;
6037			pg->pg_pga_gain = 0;
6038		}
6039	}
6040
6041	tmp = BWN_RF_READ(mac, 0x7a);
6042	if (pg->pg_lna_lod_gain == 0)
6043		tmp &= ~0x0008;
6044	else
6045		tmp |= 0x0008;
6046	BWN_RF_WRITE(mac, 0x7a, tmp);
6047}
6048
6049static void
6050bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6051{
6052	struct bwn_phy *phy = &mac->mac_phy;
6053	struct bwn_phy_g *pg = &phy->phy_g;
6054	struct bwn_softc *sc = mac->mac_sc;
6055	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6056	struct timespec ts;
6057	uint16_t tmp;
6058
6059	if (bwn_has_hwpctl(mac)) {
6060		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6061		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6062		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6063		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6064		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6065
6066		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6067		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6068		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6069		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6070	}
6071	if (phy->type == BWN_PHYTYPE_B &&
6072	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6073		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6074		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6075	}
6076	if (phy->rev >= 2) {
6077		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6078		sav->phy_analogoverval =
6079		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6080		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6081		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6082		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6083		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6084		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6085
6086		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6087		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6088		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6089		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6090		if (phy->type == BWN_PHYTYPE_G) {
6091			if ((phy->rev >= 7) &&
6092			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6093			     BWN_BFL_EXTLNA)) {
6094				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6095			} else {
6096				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6097			}
6098		} else {
6099			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6100		}
6101		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6102	}
6103	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6104	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6105	sav->rf0 = BWN_RF_READ(mac, 0x43);
6106	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6107	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6108	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6109	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6110	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6111
6112	if (!BWN_HAS_TXMAG(phy)) {
6113		sav->rf2 = BWN_RF_READ(mac, 0x52);
6114		sav->rf2 &= 0x00f0;
6115	}
6116	if (phy->type == BWN_PHYTYPE_B) {
6117		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6118		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6119		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6120		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6121	} else {
6122		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6123			    | 0x8000);
6124	}
6125	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6126		    & 0xf000);
6127
6128	tmp =
6129	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6130	BWN_PHY_WRITE(mac, tmp, 0x007f);
6131
6132	tmp = sav->phy_syncctl;
6133	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6134	tmp = sav->rf1;
6135	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6136
6137	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6138	if (phy->type == BWN_PHYTYPE_G ||
6139	    (phy->type == BWN_PHYTYPE_B &&
6140	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6141		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6142	} else
6143		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6144	if (phy->rev >= 2)
6145		bwn_dummy_transmission(mac, 0, 1);
6146	bwn_phy_g_switch_chan(mac, 6, 0);
6147	BWN_RF_READ(mac, 0x51);
6148	if (phy->type == BWN_PHYTYPE_G)
6149		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6150
6151	nanouptime(&ts);
6152	if (time_before(lo->txctl_measured_time,
6153	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6154		bwn_lo_measure_txctl_values(mac);
6155
6156	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6157		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6158	else {
6159		if (phy->type == BWN_PHYTYPE_B)
6160			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6161		else
6162			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6163	}
6164}
6165
6166static void
6167bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6168{
6169	struct bwn_phy *phy = &mac->mac_phy;
6170	struct bwn_phy_g *pg = &phy->phy_g;
6171	uint16_t tmp;
6172
6173	if (phy->rev >= 2) {
6174		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6175		tmp = (pg->pg_pga_gain << 8);
6176		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6177		DELAY(5);
6178		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6179		DELAY(2);
6180		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6181	} else {
6182		tmp = (pg->pg_pga_gain | 0xefa0);
6183		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6184	}
6185	if (phy->type == BWN_PHYTYPE_G) {
6186		if (phy->rev >= 3)
6187			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6188		else
6189			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6190		if (phy->rev >= 2)
6191			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6192		else
6193			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6194	}
6195	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6196	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6197	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6198	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6199	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6200	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6201	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6202	if (!BWN_HAS_TXMAG(phy)) {
6203		tmp = sav->rf2;
6204		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6205	}
6206	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6207	if (phy->type == BWN_PHYTYPE_B &&
6208	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6209		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6210		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6211	}
6212	if (phy->rev >= 2) {
6213		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6214		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6215			      sav->phy_analogoverval);
6216		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6217		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6218		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6219		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6220		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6221	}
6222	if (bwn_has_hwpctl(mac)) {
6223		tmp = (sav->phy_lomask & 0xbfff);
6224		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6225		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6226		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6227		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6228		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6229	}
6230	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6231}
6232
6233static int
6234bwn_lo_probe_loctl(struct bwn_mac *mac,
6235    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6236{
6237	struct bwn_phy *phy = &mac->mac_phy;
6238	struct bwn_phy_g *pg = &phy->phy_g;
6239	struct bwn_loctl orig, test;
6240	struct bwn_loctl prev = { -100, -100 };
6241	static const struct bwn_loctl modifiers[] = {
6242		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6243		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6244	};
6245	int begin, end, lower = 0, i;
6246	uint16_t feedth;
6247
6248	if (d->curstate == 0) {
6249		begin = 1;
6250		end = 8;
6251	} else if (d->curstate % 2 == 0) {
6252		begin = d->curstate - 1;
6253		end = d->curstate + 1;
6254	} else {
6255		begin = d->curstate - 2;
6256		end = d->curstate + 2;
6257	}
6258	if (begin < 1)
6259		begin += 8;
6260	if (end > 8)
6261		end -= 8;
6262
6263	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6264	i = begin;
6265	d->curstate = i;
6266	while (1) {
6267		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6268		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6269		test.i += modifiers[i - 1].i * d->multipler;
6270		test.q += modifiers[i - 1].q * d->multipler;
6271		if ((test.i != prev.i || test.q != prev.q) &&
6272		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6273			bwn_lo_write(mac, &test);
6274			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6275			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6276			if (feedth < d->feedth) {
6277				memcpy(probe, &test,
6278				    sizeof(struct bwn_loctl));
6279				lower = 1;
6280				d->feedth = feedth;
6281				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6282					break;
6283			}
6284		}
6285		memcpy(&prev, &test, sizeof(prev));
6286		if (i == end)
6287			break;
6288		if (i == 8)
6289			i = 1;
6290		else
6291			i++;
6292		d->curstate = i;
6293	}
6294
6295	return (lower);
6296}
6297
6298static void
6299bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6300{
6301	struct bwn_phy *phy = &mac->mac_phy;
6302	struct bwn_phy_g *pg = &phy->phy_g;
6303	struct bwn_lo_g_sm d;
6304	struct bwn_loctl probe;
6305	int lower, repeat, cnt = 0;
6306	uint16_t feedth;
6307
6308	d.nmeasure = 0;
6309	d.multipler = 1;
6310	if (BWN_HAS_LOOPBACK(phy))
6311		d.multipler = 3;
6312
6313	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6314	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6315
6316	do {
6317		bwn_lo_write(mac, &d.loctl);
6318		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6319		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6320		if (feedth < 0x258) {
6321			if (feedth >= 0x12c)
6322				*rxgain += 6;
6323			else
6324				*rxgain += 3;
6325			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6326			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6327		}
6328		d.feedth = feedth;
6329		d.curstate = 0;
6330		do {
6331			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6332			    ("%s:%d: fail", __func__, __LINE__));
6333			memcpy(&probe, &d.loctl,
6334			       sizeof(struct bwn_loctl));
6335			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6336			if (!lower)
6337				break;
6338			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6339				break;
6340			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6341			d.nmeasure++;
6342		} while (d.nmeasure < 24);
6343		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6344
6345		if (BWN_HAS_LOOPBACK(phy)) {
6346			if (d.feedth > 0x1194)
6347				*rxgain -= 6;
6348			else if (d.feedth < 0x5dc)
6349				*rxgain += 3;
6350			if (cnt == 0) {
6351				if (d.feedth <= 0x5dc) {
6352					d.multipler = 1;
6353					cnt++;
6354				} else
6355					d.multipler = 2;
6356			} else if (cnt == 2)
6357				d.multipler = 1;
6358		}
6359		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6360	} while (++cnt < repeat);
6361}
6362
6363static struct bwn_lo_calib *
6364bwn_lo_calibset(struct bwn_mac *mac,
6365    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6366{
6367	struct bwn_phy *phy = &mac->mac_phy;
6368	struct bwn_phy_g *pg = &phy->phy_g;
6369	struct bwn_loctl loctl = { 0, 0 };
6370	struct bwn_lo_calib *cal;
6371	struct bwn_lo_g_value sval = { 0 };
6372	int rxgain;
6373	uint16_t pad, reg, value;
6374
6375	sval.old_channel = phy->chan;
6376	bwn_mac_suspend(mac);
6377	bwn_lo_save(mac, &sval);
6378
6379	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6380	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6381	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6382
6383	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6384	if (rfatt->padmix)
6385		rxgain -= pad;
6386	if (BWN_HAS_LOOPBACK(phy))
6387		rxgain += pg->pg_max_lb_gain;
6388	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6389	bwn_phy_g_set_bbatt(mac, bbatt->att);
6390	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6391
6392	bwn_lo_restore(mac, &sval);
6393	bwn_mac_enable(mac);
6394
6395	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6396	if (!cal) {
6397		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6398		return (NULL);
6399	}
6400	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6401	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6402	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6403
6404	BWN_GETTIME(cal->calib_time);
6405
6406	return (cal);
6407}
6408
6409static struct bwn_lo_calib *
6410bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6411    const struct bwn_rfatt *rfatt)
6412{
6413	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6414	struct bwn_lo_calib *c;
6415
6416	TAILQ_FOREACH(c, &lo->calib_list, list) {
6417		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6418			continue;
6419		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6420			continue;
6421		return (c);
6422	}
6423
6424	c = bwn_lo_calibset(mac, bbatt, rfatt);
6425	if (!c)
6426		return (NULL);
6427	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6428
6429	return (c);
6430}
6431
6432static void
6433bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6434{
6435	struct bwn_phy *phy = &mac->mac_phy;
6436	struct bwn_phy_g *pg = &phy->phy_g;
6437	struct bwn_softc *sc = mac->mac_sc;
6438	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6439	const struct bwn_rfatt *rfatt;
6440	const struct bwn_bbatt *bbatt;
6441	uint64_t pvector;
6442	int i;
6443	int rf_offset, bb_offset;
6444	uint8_t changed = 0;
6445
6446	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6447	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6448	    ("%s:%d: fail", __func__, __LINE__));
6449
6450	pvector = lo->power_vector;
6451	if (!update && !pvector)
6452		return;
6453
6454	bwn_mac_suspend(mac);
6455
6456	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6457		struct bwn_lo_calib *cal;
6458		int idx;
6459		uint16_t val;
6460
6461		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6462			continue;
6463		bb_offset = i / lo->rfatt.len;
6464		rf_offset = i % lo->rfatt.len;
6465		bbatt = &(lo->bbatt.array[bb_offset]);
6466		rfatt = &(lo->rfatt.array[rf_offset]);
6467
6468		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6469		if (!cal) {
6470			device_printf(sc->sc_dev, "LO: Could not "
6471			    "calibrate DC table entry\n");
6472			continue;
6473		}
6474		val = (uint8_t)(cal->ctl.q);
6475		val |= ((uint8_t)(cal->ctl.i)) << 4;
6476		free(cal, M_DEVBUF);
6477
6478		idx = i / 2;
6479		if (i % 2)
6480			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6481			    | ((val & 0x00ff) << 8);
6482		else
6483			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6484			    | (val & 0x00ff);
6485		changed = 1;
6486	}
6487	if (changed) {
6488		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6489			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6490	}
6491	bwn_mac_enable(mac);
6492}
6493
6494static void
6495bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6496{
6497
6498	if (!rf->padmix)
6499		return;
6500	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6501		rf->att = 4;
6502}
6503
6504static void
6505bwn_lo_g_adjust(struct bwn_mac *mac)
6506{
6507	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6508	struct bwn_lo_calib *cal;
6509	struct bwn_rfatt rf;
6510
6511	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6512	bwn_lo_fixup_rfatt(&rf);
6513
6514	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6515	if (!cal)
6516		return;
6517	bwn_lo_write(mac, &cal->ctl);
6518}
6519
6520static void
6521bwn_lo_g_init(struct bwn_mac *mac)
6522{
6523
6524	if (!bwn_has_hwpctl(mac))
6525		return;
6526
6527	bwn_lo_get_powervector(mac);
6528	bwn_phy_g_dc_lookup_init(mac, 1);
6529}
6530
6531static void
6532bwn_mac_suspend(struct bwn_mac *mac)
6533{
6534	struct bwn_softc *sc = mac->mac_sc;
6535	int i;
6536	uint32_t tmp;
6537
6538	KASSERT(mac->mac_suspended >= 0,
6539	    ("%s:%d: fail", __func__, __LINE__));
6540
6541	if (mac->mac_suspended == 0) {
6542		bwn_psctl(mac, BWN_PS_AWAKE);
6543		BWN_WRITE_4(mac, BWN_MACCTL,
6544			    BWN_READ_4(mac, BWN_MACCTL)
6545			    & ~BWN_MACCTL_ON);
6546		BWN_READ_4(mac, BWN_MACCTL);
6547		for (i = 35; i; i--) {
6548			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6549			if (tmp & BWN_INTR_MAC_SUSPENDED)
6550				goto out;
6551			DELAY(10);
6552		}
6553		for (i = 40; i; i--) {
6554			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6555			if (tmp & BWN_INTR_MAC_SUSPENDED)
6556				goto out;
6557			DELAY(1000);
6558		}
6559		device_printf(sc->sc_dev, "MAC suspend failed\n");
6560	}
6561out:
6562	mac->mac_suspended++;
6563}
6564
6565static void
6566bwn_mac_enable(struct bwn_mac *mac)
6567{
6568	struct bwn_softc *sc = mac->mac_sc;
6569	uint16_t state;
6570
6571	state = bwn_shm_read_2(mac, BWN_SHARED,
6572	    BWN_SHARED_UCODESTAT);
6573	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6574	    state != BWN_SHARED_UCODESTAT_SLEEP)
6575		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6576
6577	mac->mac_suspended--;
6578	KASSERT(mac->mac_suspended >= 0,
6579	    ("%s:%d: fail", __func__, __LINE__));
6580	if (mac->mac_suspended == 0) {
6581		BWN_WRITE_4(mac, BWN_MACCTL,
6582		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6583		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6584		BWN_READ_4(mac, BWN_MACCTL);
6585		BWN_READ_4(mac, BWN_INTR_REASON);
6586		bwn_psctl(mac, 0);
6587	}
6588}
6589
6590static void
6591bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6592{
6593	struct bwn_softc *sc = mac->mac_sc;
6594	int i;
6595	uint16_t ucstat;
6596
6597	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6598	    ("%s:%d: fail", __func__, __LINE__));
6599	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6600	    ("%s:%d: fail", __func__, __LINE__));
6601
6602	/* XXX forcibly awake and hwps-off */
6603
6604	BWN_WRITE_4(mac, BWN_MACCTL,
6605	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6606	    ~BWN_MACCTL_HWPS);
6607	BWN_READ_4(mac, BWN_MACCTL);
6608	if (siba_get_revid(sc->sc_dev) >= 5) {
6609		for (i = 0; i < 100; i++) {
6610			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6611			    BWN_SHARED_UCODESTAT);
6612			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6613				break;
6614			DELAY(10);
6615		}
6616	}
6617}
6618
6619static int16_t
6620bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6621{
6622
6623	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6624	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6625}
6626
6627static void
6628bwn_nrssi_threshold(struct bwn_mac *mac)
6629{
6630	struct bwn_phy *phy = &mac->mac_phy;
6631	struct bwn_phy_g *pg = &phy->phy_g;
6632	struct bwn_softc *sc = mac->mac_sc;
6633	int32_t a, b;
6634	int16_t tmp16;
6635	uint16_t tmpu16;
6636
6637	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6638
6639	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6640		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6641			a = 0x13;
6642			b = 0x12;
6643		} else {
6644			a = 0xe;
6645			b = 0x11;
6646		}
6647
6648		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6649		a += (pg->pg_nrssi[0] << 6);
6650		a += (a < 32) ? 31 : 32;
6651		a = a >> 6;
6652		a = MIN(MAX(a, -31), 31);
6653
6654		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6655		b += (pg->pg_nrssi[0] << 6);
6656		if (b < 32)
6657			b += 31;
6658		else
6659			b += 32;
6660		b = b >> 6;
6661		b = MIN(MAX(b, -31), 31);
6662
6663		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6664		tmpu16 |= ((uint32_t)b & 0x0000003f);
6665		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6666		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6667		return;
6668	}
6669
6670	tmp16 = bwn_nrssi_read(mac, 0x20);
6671	if (tmp16 >= 0x20)
6672		tmp16 -= 0x40;
6673	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6674}
6675
6676static void
6677bwn_nrssi_slope_11g(struct bwn_mac *mac)
6678{
6679#define	SAVE_RF_MAX		3
6680#define	SAVE_PHY_COMM_MAX	4
6681#define	SAVE_PHY3_MAX		8
6682	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6683		{ 0x7a, 0x52, 0x43 };
6684	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6685		{ 0x15, 0x5a, 0x59, 0x58 };
6686	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6687		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6688		0x0801, 0x0060, 0x0014, 0x0478
6689	};
6690	struct bwn_phy *phy = &mac->mac_phy;
6691	struct bwn_phy_g *pg = &phy->phy_g;
6692	int32_t i, tmp32, phy3_idx = 0;
6693	uint16_t delta, tmp;
6694	uint16_t save_rf[SAVE_RF_MAX];
6695	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6696	uint16_t save_phy3[SAVE_PHY3_MAX];
6697	uint16_t ant_div, phy0, chan_ex;
6698	int16_t nrssi0, nrssi1;
6699
6700	KASSERT(phy->type == BWN_PHYTYPE_G,
6701	    ("%s:%d: fail", __func__, __LINE__));
6702
6703	if (phy->rf_rev >= 9)
6704		return;
6705	if (phy->rf_rev == 8)
6706		bwn_nrssi_offset(mac);
6707
6708	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6709	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6710
6711	/*
6712	 * Save RF/PHY registers for later restoration
6713	 */
6714	ant_div = BWN_READ_2(mac, 0x03e2);
6715	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6716	for (i = 0; i < SAVE_RF_MAX; ++i)
6717		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6718	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6719		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6720
6721	phy0 = BWN_READ_2(mac, BWN_PHY0);
6722	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6723	if (phy->rev >= 3) {
6724		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6725			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6726		BWN_PHY_WRITE(mac, 0x002e, 0);
6727		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6728		switch (phy->rev) {
6729		case 4:
6730		case 6:
6731		case 7:
6732			BWN_PHY_SET(mac, 0x0478, 0x0100);
6733			BWN_PHY_SET(mac, 0x0801, 0x0040);
6734			break;
6735		case 3:
6736		case 5:
6737			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6738			break;
6739		}
6740		BWN_PHY_SET(mac, 0x0060, 0x0040);
6741		BWN_PHY_SET(mac, 0x0014, 0x0200);
6742	}
6743	/*
6744	 * Calculate nrssi0
6745	 */
6746	BWN_RF_SET(mac, 0x007a, 0x0070);
6747	bwn_set_all_gains(mac, 0, 8, 0);
6748	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6749	if (phy->rev >= 2) {
6750		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6751		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6752	}
6753	BWN_RF_SET(mac, 0x007a, 0x0080);
6754	DELAY(20);
6755
6756	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6757	if (nrssi0 >= 0x0020)
6758		nrssi0 -= 0x0040;
6759
6760	/*
6761	 * Calculate nrssi1
6762	 */
6763	BWN_RF_MASK(mac, 0x007a, 0x007f);
6764	if (phy->rev >= 2)
6765		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6766
6767	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6768	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6769	BWN_RF_SET(mac, 0x007a, 0x000f);
6770	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6771	if (phy->rev >= 2) {
6772		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6773		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6774	}
6775
6776	bwn_set_all_gains(mac, 3, 0, 1);
6777	if (phy->rf_rev == 8) {
6778		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6779	} else {
6780		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6781		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6782		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6783		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6784	}
6785	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6786	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6787	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6788	DELAY(20);
6789	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6790
6791	/*
6792	 * Install calculated narrow RSSI values
6793	 */
6794	if (nrssi1 >= 0x0020)
6795		nrssi1 -= 0x0040;
6796	if (nrssi0 == nrssi1)
6797		pg->pg_nrssi_slope = 0x00010000;
6798	else
6799		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6800	if (nrssi0 >= -4) {
6801		pg->pg_nrssi[0] = nrssi1;
6802		pg->pg_nrssi[1] = nrssi0;
6803	}
6804
6805	/*
6806	 * Restore saved RF/PHY registers
6807	 */
6808	if (phy->rev >= 3) {
6809		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6810			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6811			    save_phy3[phy3_idx]);
6812		}
6813	}
6814	if (phy->rev >= 2) {
6815		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6816		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6817	}
6818
6819	for (i = 0; i < SAVE_RF_MAX; ++i)
6820		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6821
6822	BWN_WRITE_2(mac, 0x03e2, ant_div);
6823	BWN_WRITE_2(mac, 0x03e6, phy0);
6824	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6825
6826	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6827		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6828
6829	bwn_spu_workaround(mac, phy->chan);
6830	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6831	bwn_set_original_gains(mac);
6832	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6833	if (phy->rev >= 3) {
6834		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6835			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6836			    save_phy3[phy3_idx]);
6837		}
6838	}
6839
6840	delta = 0x1f - pg->pg_nrssi[0];
6841	for (i = 0; i < 64; i++) {
6842		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6843		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6844		pg->pg_nrssi_lt[i] = tmp32;
6845	}
6846
6847	bwn_nrssi_threshold(mac);
6848#undef SAVE_RF_MAX
6849#undef SAVE_PHY_COMM_MAX
6850#undef SAVE_PHY3_MAX
6851}
6852
6853static void
6854bwn_nrssi_offset(struct bwn_mac *mac)
6855{
6856#define	SAVE_RF_MAX		2
6857#define	SAVE_PHY_COMM_MAX	10
6858#define	SAVE_PHY6_MAX		8
6859	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6860		{ 0x7a, 0x43 };
6861	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6862		0x0001, 0x0811, 0x0812, 0x0814,
6863		0x0815, 0x005a, 0x0059, 0x0058,
6864		0x000a, 0x0003
6865	};
6866	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6867		0x002e, 0x002f, 0x080f, 0x0810,
6868		0x0801, 0x0060, 0x0014, 0x0478
6869	};
6870	struct bwn_phy *phy = &mac->mac_phy;
6871	int i, phy6_idx = 0;
6872	uint16_t save_rf[SAVE_RF_MAX];
6873	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6874	uint16_t save_phy6[SAVE_PHY6_MAX];
6875	int16_t nrssi;
6876	uint16_t saved = 0xffff;
6877
6878	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6879		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6880	for (i = 0; i < SAVE_RF_MAX; ++i)
6881		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6882
6883	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6884	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6885	BWN_PHY_SET(mac, 0x0811, 0x000c);
6886	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6887	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6888	if (phy->rev >= 6) {
6889		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6890			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6891
6892		BWN_PHY_WRITE(mac, 0x002e, 0);
6893		BWN_PHY_WRITE(mac, 0x002f, 0);
6894		BWN_PHY_WRITE(mac, 0x080f, 0);
6895		BWN_PHY_WRITE(mac, 0x0810, 0);
6896		BWN_PHY_SET(mac, 0x0478, 0x0100);
6897		BWN_PHY_SET(mac, 0x0801, 0x0040);
6898		BWN_PHY_SET(mac, 0x0060, 0x0040);
6899		BWN_PHY_SET(mac, 0x0014, 0x0200);
6900	}
6901	BWN_RF_SET(mac, 0x007a, 0x0070);
6902	BWN_RF_SET(mac, 0x007a, 0x0080);
6903	DELAY(30);
6904
6905	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6906	if (nrssi >= 0x20)
6907		nrssi -= 0x40;
6908	if (nrssi == 31) {
6909		for (i = 7; i >= 4; i--) {
6910			BWN_RF_WRITE(mac, 0x007b, i);
6911			DELAY(20);
6912			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
6913			    0x003f);
6914			if (nrssi >= 0x20)
6915				nrssi -= 0x40;
6916			if (nrssi < 31 && saved == 0xffff)
6917				saved = i;
6918		}
6919		if (saved == 0xffff)
6920			saved = 4;
6921	} else {
6922		BWN_RF_MASK(mac, 0x007a, 0x007f);
6923		if (phy->rev != 1) {
6924			BWN_PHY_SET(mac, 0x0814, 0x0001);
6925			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
6926		}
6927		BWN_PHY_SET(mac, 0x0811, 0x000c);
6928		BWN_PHY_SET(mac, 0x0812, 0x000c);
6929		BWN_PHY_SET(mac, 0x0811, 0x0030);
6930		BWN_PHY_SET(mac, 0x0812, 0x0030);
6931		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6932		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6933		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6934		if (phy->rev == 0)
6935			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
6936		else
6937			BWN_PHY_SET(mac, 0x000a, 0x2000);
6938		if (phy->rev != 1) {
6939			BWN_PHY_SET(mac, 0x0814, 0x0004);
6940			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
6941		}
6942		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6943		BWN_RF_SET(mac, 0x007a, 0x000f);
6944		bwn_set_all_gains(mac, 3, 0, 1);
6945		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
6946		DELAY(30);
6947		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6948		if (nrssi >= 0x20)
6949			nrssi -= 0x40;
6950		if (nrssi == -32) {
6951			for (i = 0; i < 4; i++) {
6952				BWN_RF_WRITE(mac, 0x007b, i);
6953				DELAY(20);
6954				nrssi = (int16_t)((BWN_PHY_READ(mac,
6955				    0x047f) >> 8) & 0x003f);
6956				if (nrssi >= 0x20)
6957					nrssi -= 0x40;
6958				if (nrssi > -31 && saved == 0xffff)
6959					saved = i;
6960			}
6961			if (saved == 0xffff)
6962				saved = 3;
6963		} else
6964			saved = 0;
6965	}
6966	BWN_RF_WRITE(mac, 0x007b, saved);
6967
6968	/*
6969	 * Restore saved RF/PHY registers
6970	 */
6971	if (phy->rev >= 6) {
6972		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
6973			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6974			    save_phy6[phy6_idx]);
6975		}
6976	}
6977	if (phy->rev != 1) {
6978		for (i = 3; i < 5; i++)
6979			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
6980			    save_phy_comm[i]);
6981	}
6982	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
6983		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6984
6985	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
6986		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6987
6988	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
6989	BWN_PHY_SET(mac, 0x0429, 0x8000);
6990	bwn_set_original_gains(mac);
6991	if (phy->rev >= 6) {
6992		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
6993			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6994			    save_phy6[phy6_idx]);
6995		}
6996	}
6997
6998	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
6999	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7000	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7001}
7002
7003static void
7004bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7005    int16_t third)
7006{
7007	struct bwn_phy *phy = &mac->mac_phy;
7008	uint16_t i;
7009	uint16_t start = 0x08, end = 0x18;
7010	uint16_t tmp;
7011	uint16_t table;
7012
7013	if (phy->rev <= 1) {
7014		start = 0x10;
7015		end = 0x20;
7016	}
7017
7018	table = BWN_OFDMTAB_GAINX;
7019	if (phy->rev <= 1)
7020		table = BWN_OFDMTAB_GAINX_R1;
7021	for (i = 0; i < 4; i++)
7022		bwn_ofdmtab_write_2(mac, table, i, first);
7023
7024	for (i = start; i < end; i++)
7025		bwn_ofdmtab_write_2(mac, table, i, second);
7026
7027	if (third != -1) {
7028		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7029		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7030		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7031		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7032	}
7033	bwn_dummy_transmission(mac, 0, 1);
7034}
7035
7036static void
7037bwn_set_original_gains(struct bwn_mac *mac)
7038{
7039	struct bwn_phy *phy = &mac->mac_phy;
7040	uint16_t i, tmp;
7041	uint16_t table;
7042	uint16_t start = 0x0008, end = 0x0018;
7043
7044	if (phy->rev <= 1) {
7045		start = 0x0010;
7046		end = 0x0020;
7047	}
7048
7049	table = BWN_OFDMTAB_GAINX;
7050	if (phy->rev <= 1)
7051		table = BWN_OFDMTAB_GAINX_R1;
7052	for (i = 0; i < 4; i++) {
7053		tmp = (i & 0xfffc);
7054		tmp |= (i & 0x0001) << 1;
7055		tmp |= (i & 0x0002) >> 1;
7056
7057		bwn_ofdmtab_write_2(mac, table, i, tmp);
7058	}
7059
7060	for (i = start; i < end; i++)
7061		bwn_ofdmtab_write_2(mac, table, i, i - start);
7062
7063	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7064	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7065	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7066	bwn_dummy_transmission(mac, 0, 1);
7067}
7068
7069static void
7070bwn_phy_hwpctl_init(struct bwn_mac *mac)
7071{
7072	struct bwn_phy *phy = &mac->mac_phy;
7073	struct bwn_phy_g *pg = &phy->phy_g;
7074	struct bwn_rfatt old_rfatt, rfatt;
7075	struct bwn_bbatt old_bbatt, bbatt;
7076	struct bwn_softc *sc = mac->mac_sc;
7077	uint8_t old_txctl = 0;
7078
7079	KASSERT(phy->type == BWN_PHYTYPE_G,
7080	    ("%s:%d: fail", __func__, __LINE__));
7081
7082	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7083	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7084		return;
7085
7086	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7087
7088	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7089
7090	if (!phy->gmode)
7091		return;
7092	bwn_hwpctl_early_init(mac);
7093	if (pg->pg_curtssi == 0) {
7094		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7095			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7096		} else {
7097			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7098			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7099			old_txctl = pg->pg_txctl;
7100
7101			bbatt.att = 11;
7102			if (phy->rf_rev == 8) {
7103				rfatt.att = 15;
7104				rfatt.padmix = 1;
7105			} else {
7106				rfatt.att = 9;
7107				rfatt.padmix = 0;
7108			}
7109			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7110		}
7111		bwn_dummy_transmission(mac, 0, 1);
7112		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7113		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7114			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7115		else
7116			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7117			    &old_rfatt, old_txctl);
7118	}
7119	bwn_hwpctl_init_gphy(mac);
7120
7121	/* clear TSSI */
7122	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7123	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7124	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7125	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7126}
7127
7128static void
7129bwn_hwpctl_early_init(struct bwn_mac *mac)
7130{
7131	struct bwn_phy *phy = &mac->mac_phy;
7132
7133	if (!bwn_has_hwpctl(mac)) {
7134		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7135		return;
7136	}
7137
7138	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7139	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7140	BWN_PHY_SET(mac, 0x047c, 0x0002);
7141	BWN_PHY_SET(mac, 0x047a, 0xf000);
7142	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7143		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7144		BWN_PHY_SET(mac, 0x005d, 0x8000);
7145		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7146		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7147		BWN_PHY_SET(mac, 0x0036, 0x0400);
7148	} else {
7149		BWN_PHY_SET(mac, 0x0036, 0x0200);
7150		BWN_PHY_SET(mac, 0x0036, 0x0400);
7151		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7152		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7153		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7154		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7155		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7156	}
7157}
7158
7159static void
7160bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7161{
7162	struct bwn_phy *phy = &mac->mac_phy;
7163	struct bwn_phy_g *pg = &phy->phy_g;
7164	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7165	int i;
7166	uint16_t nr_written = 0, tmp, value;
7167	uint8_t rf, bb;
7168
7169	if (!bwn_has_hwpctl(mac)) {
7170		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7171		return;
7172	}
7173
7174	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7175	    (pg->pg_idletssi - pg->pg_curtssi));
7176	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7177	    (pg->pg_idletssi - pg->pg_curtssi));
7178
7179	for (i = 0; i < 32; i++)
7180		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7181	for (i = 32; i < 64; i++)
7182		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7183	for (i = 0; i < 64; i += 2) {
7184		value = (uint16_t) pg->pg_tssi2dbm[i];
7185		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7186		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7187	}
7188
7189	for (rf = 0; rf < lo->rfatt.len; rf++) {
7190		for (bb = 0; bb < lo->bbatt.len; bb++) {
7191			if (nr_written >= 0x40)
7192				return;
7193			tmp = lo->bbatt.array[bb].att;
7194			tmp <<= 8;
7195			if (phy->rf_rev == 8)
7196				tmp |= 0x50;
7197			else
7198				tmp |= 0x40;
7199			tmp |= lo->rfatt.array[rf].att;
7200			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7201			nr_written++;
7202		}
7203	}
7204
7205	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7206	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7207
7208	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7209	BWN_PHY_SET(mac, 0x0478, 0x0800);
7210	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7211	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7212
7213	bwn_phy_g_dc_lookup_init(mac, 1);
7214	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7215}
7216
7217static void
7218bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7219{
7220	struct bwn_softc *sc = mac->mac_sc;
7221
7222	if (spu != 0)
7223		bwn_spu_workaround(mac, channel);
7224
7225	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7226
7227	if (channel == 14) {
7228		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7229			bwn_hf_write(mac,
7230			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7231		else
7232			bwn_hf_write(mac,
7233			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7234		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7235		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7236		return;
7237	}
7238
7239	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7240	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7241}
7242
7243static uint16_t
7244bwn_phy_g_chan2freq(uint8_t channel)
7245{
7246	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7247
7248	KASSERT(channel >= 1 && channel <= 14,
7249	    ("%s:%d: fail", __func__, __LINE__));
7250
7251	return (bwn_phy_g_rf_channels[channel - 1]);
7252}
7253
7254static void
7255bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7256    const struct bwn_rfatt *rfatt, uint8_t txctl)
7257{
7258	struct bwn_phy *phy = &mac->mac_phy;
7259	struct bwn_phy_g *pg = &phy->phy_g;
7260	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7261	uint16_t bb, rf;
7262	uint16_t tx_bias, tx_magn;
7263
7264	bb = bbatt->att;
7265	rf = rfatt->att;
7266	tx_bias = lo->tx_bias;
7267	tx_magn = lo->tx_magn;
7268	if (tx_bias == 0xff)
7269		tx_bias = 0;
7270
7271	pg->pg_txctl = txctl;
7272	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7273	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7274	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7275	bwn_phy_g_set_bbatt(mac, bb);
7276	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7277	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7278		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7279	else {
7280		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7281		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7282	}
7283	if (BWN_HAS_TXMAG(phy))
7284		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7285	else
7286		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7287	bwn_lo_g_adjust(mac);
7288}
7289
7290static void
7291bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7292    uint16_t bbatt)
7293{
7294	struct bwn_phy *phy = &mac->mac_phy;
7295
7296	if (phy->analog == 0) {
7297		BWN_WRITE_2(mac, BWN_PHY0,
7298		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7299		return;
7300	}
7301	if (phy->analog > 1) {
7302		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7303		return;
7304	}
7305	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7306}
7307
7308static uint16_t
7309bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7310{
7311	struct bwn_phy *phy = &mac->mac_phy;
7312	struct bwn_phy_g *pg = &phy->phy_g;
7313	struct bwn_softc *sc = mac->mac_sc;
7314	int max_lb_gain;
7315	uint16_t extlna;
7316	uint16_t i;
7317
7318	if (phy->gmode == 0)
7319		return (0);
7320
7321	if (BWN_HAS_LOOPBACK(phy)) {
7322		max_lb_gain = pg->pg_max_lb_gain;
7323		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7324		if (max_lb_gain >= 0x46) {
7325			extlna = 0x3000;
7326			max_lb_gain -= 0x46;
7327		} else if (max_lb_gain >= 0x3a) {
7328			extlna = 0x1000;
7329			max_lb_gain -= 0x3a;
7330		} else if (max_lb_gain >= 0x2e) {
7331			extlna = 0x2000;
7332			max_lb_gain -= 0x2e;
7333		} else {
7334			extlna = 0;
7335			max_lb_gain -= 0x10;
7336		}
7337
7338		for (i = 0; i < 16; i++) {
7339			max_lb_gain -= (i * 6);
7340			if (max_lb_gain < 6)
7341				break;
7342		}
7343
7344		if ((phy->rev < 7) ||
7345		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7346			if (reg == BWN_PHY_RFOVER) {
7347				return (0x1b3);
7348			} else if (reg == BWN_PHY_RFOVERVAL) {
7349				extlna |= (i << 8);
7350				switch (lpd) {
7351				case BWN_LPD(0, 1, 1):
7352					return (0x0f92);
7353				case BWN_LPD(0, 0, 1):
7354				case BWN_LPD(1, 0, 1):
7355					return (0x0092 | extlna);
7356				case BWN_LPD(1, 0, 0):
7357					return (0x0093 | extlna);
7358				}
7359				KASSERT(0 == 1,
7360				    ("%s:%d: fail", __func__, __LINE__));
7361			}
7362			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7363		} else {
7364			if (reg == BWN_PHY_RFOVER)
7365				return (0x9b3);
7366			if (reg == BWN_PHY_RFOVERVAL) {
7367				if (extlna)
7368					extlna |= 0x8000;
7369				extlna |= (i << 8);
7370				switch (lpd) {
7371				case BWN_LPD(0, 1, 1):
7372					return (0x8f92);
7373				case BWN_LPD(0, 0, 1):
7374					return (0x8092 | extlna);
7375				case BWN_LPD(1, 0, 1):
7376					return (0x2092 | extlna);
7377				case BWN_LPD(1, 0, 0):
7378					return (0x2093 | extlna);
7379				}
7380				KASSERT(0 == 1,
7381				    ("%s:%d: fail", __func__, __LINE__));
7382			}
7383			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7384		}
7385		return (0);
7386	}
7387
7388	if ((phy->rev < 7) ||
7389	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7390		if (reg == BWN_PHY_RFOVER) {
7391			return (0x1b3);
7392		} else if (reg == BWN_PHY_RFOVERVAL) {
7393			switch (lpd) {
7394			case BWN_LPD(0, 1, 1):
7395				return (0x0fb2);
7396			case BWN_LPD(0, 0, 1):
7397				return (0x00b2);
7398			case BWN_LPD(1, 0, 1):
7399				return (0x30b2);
7400			case BWN_LPD(1, 0, 0):
7401				return (0x30b3);
7402			}
7403			KASSERT(0 == 1,
7404			    ("%s:%d: fail", __func__, __LINE__));
7405		}
7406		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7407	} else {
7408		if (reg == BWN_PHY_RFOVER) {
7409			return (0x9b3);
7410		} else if (reg == BWN_PHY_RFOVERVAL) {
7411			switch (lpd) {
7412			case BWN_LPD(0, 1, 1):
7413				return (0x8fb2);
7414			case BWN_LPD(0, 0, 1):
7415				return (0x80b2);
7416			case BWN_LPD(1, 0, 1):
7417				return (0x20b2);
7418			case BWN_LPD(1, 0, 0):
7419				return (0x20b3);
7420			}
7421			KASSERT(0 == 1,
7422			    ("%s:%d: fail", __func__, __LINE__));
7423		}
7424		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7425	}
7426	return (0);
7427}
7428
7429static void
7430bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7431{
7432
7433	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7434		return;
7435	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7436	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7437	DELAY(1000);
7438	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7439}
7440
7441static int
7442bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7443{
7444	struct bwn_softc *sc = mac->mac_sc;
7445	struct bwn_fw *fw = &mac->mac_fw;
7446	const uint8_t rev = siba_get_revid(sc->sc_dev);
7447	const char *filename;
7448	uint32_t high;
7449	int error;
7450
7451	/* microcode */
7452	if (rev >= 5 && rev <= 10)
7453		filename = "ucode5";
7454	else if (rev >= 11 && rev <= 12)
7455		filename = "ucode11";
7456	else if (rev == 13)
7457		filename = "ucode13";
7458	else if (rev == 14)
7459		filename = "ucode14";
7460	else if (rev >= 15)
7461		filename = "ucode15";
7462	else {
7463		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7464		bwn_release_firmware(mac);
7465		return (EOPNOTSUPP);
7466	}
7467	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7468	if (error) {
7469		bwn_release_firmware(mac);
7470		return (error);
7471	}
7472
7473	/* PCM */
7474	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7475	if (rev >= 5 && rev <= 10) {
7476		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7477		if (error == ENOENT)
7478			fw->no_pcmfile = 1;
7479		else if (error) {
7480			bwn_release_firmware(mac);
7481			return (error);
7482		}
7483	} else if (rev < 11) {
7484		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7485		return (EOPNOTSUPP);
7486	}
7487
7488	/* initvals */
7489	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7490	switch (mac->mac_phy.type) {
7491	case BWN_PHYTYPE_A:
7492		if (rev < 5 || rev > 10)
7493			goto fail1;
7494		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7495			filename = "a0g1initvals5";
7496		else
7497			filename = "a0g0initvals5";
7498		break;
7499	case BWN_PHYTYPE_G:
7500		if (rev >= 5 && rev <= 10)
7501			filename = "b0g0initvals5";
7502		else if (rev >= 13)
7503			filename = "b0g0initvals13";
7504		else
7505			goto fail1;
7506		break;
7507	case BWN_PHYTYPE_LP:
7508		if (rev == 13)
7509			filename = "lp0initvals13";
7510		else if (rev == 14)
7511			filename = "lp0initvals14";
7512		else if (rev >= 15)
7513			filename = "lp0initvals15";
7514		else
7515			goto fail1;
7516		break;
7517	case BWN_PHYTYPE_N:
7518		if (rev >= 11 && rev <= 12)
7519			filename = "n0initvals11";
7520		else
7521			goto fail1;
7522		break;
7523	default:
7524		goto fail1;
7525	}
7526	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7527	if (error) {
7528		bwn_release_firmware(mac);
7529		return (error);
7530	}
7531
7532	/* bandswitch initvals */
7533	switch (mac->mac_phy.type) {
7534	case BWN_PHYTYPE_A:
7535		if (rev >= 5 && rev <= 10) {
7536			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7537				filename = "a0g1bsinitvals5";
7538			else
7539				filename = "a0g0bsinitvals5";
7540		} else if (rev >= 11)
7541			filename = NULL;
7542		else
7543			goto fail1;
7544		break;
7545	case BWN_PHYTYPE_G:
7546		if (rev >= 5 && rev <= 10)
7547			filename = "b0g0bsinitvals5";
7548		else if (rev >= 11)
7549			filename = NULL;
7550		else
7551			goto fail1;
7552		break;
7553	case BWN_PHYTYPE_LP:
7554		if (rev == 13)
7555			filename = "lp0bsinitvals13";
7556		else if (rev == 14)
7557			filename = "lp0bsinitvals14";
7558		else if (rev >= 15)
7559			filename = "lp0bsinitvals15";
7560		else
7561			goto fail1;
7562		break;
7563	case BWN_PHYTYPE_N:
7564		if (rev >= 11 && rev <= 12)
7565			filename = "n0bsinitvals11";
7566		else
7567			goto fail1;
7568		break;
7569	default:
7570		goto fail1;
7571	}
7572	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7573	if (error) {
7574		bwn_release_firmware(mac);
7575		return (error);
7576	}
7577	return (0);
7578fail1:
7579	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7580	bwn_release_firmware(mac);
7581	return (EOPNOTSUPP);
7582}
7583
7584static int
7585bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7586    const char *name, struct bwn_fwfile *bfw)
7587{
7588	const struct bwn_fwhdr *hdr;
7589	struct bwn_softc *sc = mac->mac_sc;
7590	const struct firmware *fw;
7591	char namebuf[64];
7592
7593	if (name == NULL) {
7594		bwn_do_release_fw(bfw);
7595		return (0);
7596	}
7597	if (bfw->filename != NULL) {
7598		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7599			return (0);
7600		bwn_do_release_fw(bfw);
7601	}
7602
7603	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7604	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7605	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7606	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7607	fw = firmware_get(namebuf);
7608	if (fw == NULL) {
7609		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7610		    namebuf);
7611		return (ENOENT);
7612	}
7613	if (fw->datasize < sizeof(struct bwn_fwhdr))
7614		goto fail;
7615	hdr = (const struct bwn_fwhdr *)(fw->data);
7616	switch (hdr->type) {
7617	case BWN_FWTYPE_UCODE:
7618	case BWN_FWTYPE_PCM:
7619		if (be32toh(hdr->size) !=
7620		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7621			goto fail;
7622		/* FALLTHROUGH */
7623	case BWN_FWTYPE_IV:
7624		if (hdr->ver != 1)
7625			goto fail;
7626		break;
7627	default:
7628		goto fail;
7629	}
7630	bfw->filename = name;
7631	bfw->fw = fw;
7632	bfw->type = type;
7633	return (0);
7634fail:
7635	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7636	if (fw != NULL)
7637		firmware_put(fw, FIRMWARE_UNLOAD);
7638	return (EPROTO);
7639}
7640
7641static void
7642bwn_release_firmware(struct bwn_mac *mac)
7643{
7644
7645	bwn_do_release_fw(&mac->mac_fw.ucode);
7646	bwn_do_release_fw(&mac->mac_fw.pcm);
7647	bwn_do_release_fw(&mac->mac_fw.initvals);
7648	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7649}
7650
7651static void
7652bwn_do_release_fw(struct bwn_fwfile *bfw)
7653{
7654
7655	if (bfw->fw != NULL)
7656		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7657	bfw->fw = NULL;
7658	bfw->filename = NULL;
7659}
7660
7661static int
7662bwn_fw_loaducode(struct bwn_mac *mac)
7663{
7664#define	GETFWOFFSET(fwp, offset)	\
7665	((const uint32_t *)((const char *)fwp.fw->data + offset))
7666#define	GETFWSIZE(fwp, offset)	\
7667	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7668	struct bwn_softc *sc = mac->mac_sc;
7669	const uint32_t *data;
7670	unsigned int i;
7671	uint32_t ctl;
7672	uint16_t date, fwcaps, time;
7673	int error = 0;
7674
7675	ctl = BWN_READ_4(mac, BWN_MACCTL);
7676	ctl |= BWN_MACCTL_MCODE_JMP0;
7677	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7678	    __LINE__));
7679	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7680	for (i = 0; i < 64; i++)
7681		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7682	for (i = 0; i < 4096; i += 2)
7683		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7684
7685	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7686	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7687	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7688	     i++) {
7689		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7690		DELAY(10);
7691	}
7692
7693	if (mac->mac_fw.pcm.fw) {
7694		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7695		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7696		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7697		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7698		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7699		    sizeof(struct bwn_fwhdr)); i++) {
7700			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7701			DELAY(10);
7702		}
7703	}
7704
7705	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7706	BWN_WRITE_4(mac, BWN_MACCTL,
7707	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7708	    BWN_MACCTL_MCODE_RUN);
7709
7710	for (i = 0; i < 21; i++) {
7711		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7712			break;
7713		if (i >= 20) {
7714			device_printf(sc->sc_dev, "ucode timeout\n");
7715			error = ENXIO;
7716			goto error;
7717		}
7718		DELAY(50000);
7719	}
7720	BWN_READ_4(mac, BWN_INTR_REASON);
7721
7722	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7723	if (mac->mac_fw.rev <= 0x128) {
7724		device_printf(sc->sc_dev, "the firmware is too old\n");
7725		error = EOPNOTSUPP;
7726		goto error;
7727	}
7728	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7729	    BWN_SHARED_UCODE_PATCH);
7730	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7731	mac->mac_fw.opensource = (date == 0xffff);
7732	if (bwn_wme != 0)
7733		mac->mac_flags |= BWN_MAC_FLAG_WME;
7734	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7735
7736	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7737	if (mac->mac_fw.opensource == 0) {
7738		device_printf(sc->sc_dev,
7739		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7740		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7741		if (mac->mac_fw.no_pcmfile)
7742			device_printf(sc->sc_dev,
7743			    "no HW crypto acceleration due to pcm5\n");
7744	} else {
7745		mac->mac_fw.patch = time;
7746		fwcaps = bwn_fwcaps_read(mac);
7747		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7748			device_printf(sc->sc_dev,
7749			    "disabling HW crypto acceleration\n");
7750			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7751		}
7752		if (!(fwcaps & BWN_FWCAPS_WME)) {
7753			device_printf(sc->sc_dev, "disabling WME support\n");
7754			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7755		}
7756	}
7757
7758	if (BWN_ISOLDFMT(mac))
7759		device_printf(sc->sc_dev, "using old firmware image\n");
7760
7761	return (0);
7762
7763error:
7764	BWN_WRITE_4(mac, BWN_MACCTL,
7765	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7766	    BWN_MACCTL_MCODE_JMP0);
7767
7768	return (error);
7769#undef GETFWSIZE
7770#undef GETFWOFFSET
7771}
7772
7773/* OpenFirmware only */
7774static uint16_t
7775bwn_fwcaps_read(struct bwn_mac *mac)
7776{
7777
7778	KASSERT(mac->mac_fw.opensource == 1,
7779	    ("%s:%d: fail", __func__, __LINE__));
7780	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7781}
7782
7783static int
7784bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7785    size_t count, size_t array_size)
7786{
7787#define	GET_NEXTIV16(iv)						\
7788	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7789	    sizeof(uint16_t) + sizeof(uint16_t)))
7790#define	GET_NEXTIV32(iv)						\
7791	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7792	    sizeof(uint16_t) + sizeof(uint32_t)))
7793	struct bwn_softc *sc = mac->mac_sc;
7794	const struct bwn_fwinitvals *iv;
7795	uint16_t offset;
7796	size_t i;
7797	uint8_t bit32;
7798
7799	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7800	    ("%s:%d: fail", __func__, __LINE__));
7801	iv = ivals;
7802	for (i = 0; i < count; i++) {
7803		if (array_size < sizeof(iv->offset_size))
7804			goto fail;
7805		array_size -= sizeof(iv->offset_size);
7806		offset = be16toh(iv->offset_size);
7807		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7808		offset &= BWN_FWINITVALS_OFFSET_MASK;
7809		if (offset >= 0x1000)
7810			goto fail;
7811		if (bit32) {
7812			if (array_size < sizeof(iv->data.d32))
7813				goto fail;
7814			array_size -= sizeof(iv->data.d32);
7815			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7816			iv = GET_NEXTIV32(iv);
7817		} else {
7818
7819			if (array_size < sizeof(iv->data.d16))
7820				goto fail;
7821			array_size -= sizeof(iv->data.d16);
7822			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7823
7824			iv = GET_NEXTIV16(iv);
7825		}
7826	}
7827	if (array_size != 0)
7828		goto fail;
7829	return (0);
7830fail:
7831	device_printf(sc->sc_dev, "initvals: invalid format\n");
7832	return (EPROTO);
7833#undef GET_NEXTIV16
7834#undef GET_NEXTIV32
7835}
7836
7837static int
7838bwn_switch_channel(struct bwn_mac *mac, int chan)
7839{
7840	struct bwn_phy *phy = &(mac->mac_phy);
7841	struct bwn_softc *sc = mac->mac_sc;
7842	struct ieee80211com *ic = &sc->sc_ic;
7843	uint16_t channelcookie, savedcookie;
7844	int error;
7845
7846	if (chan == 0xffff)
7847		chan = phy->get_default_chan(mac);
7848
7849	channelcookie = chan;
7850	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7851		channelcookie |= 0x100;
7852	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7853	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7854	error = phy->switch_channel(mac, chan);
7855	if (error)
7856		goto fail;
7857
7858	mac->mac_phy.chan = chan;
7859	DELAY(8000);
7860	return (0);
7861fail:
7862	device_printf(sc->sc_dev, "failed to switch channel\n");
7863	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7864	return (error);
7865}
7866
7867static uint16_t
7868bwn_ant2phy(int antenna)
7869{
7870
7871	switch (antenna) {
7872	case BWN_ANT0:
7873		return (BWN_TX_PHY_ANT0);
7874	case BWN_ANT1:
7875		return (BWN_TX_PHY_ANT1);
7876	case BWN_ANT2:
7877		return (BWN_TX_PHY_ANT2);
7878	case BWN_ANT3:
7879		return (BWN_TX_PHY_ANT3);
7880	case BWN_ANTAUTO:
7881		return (BWN_TX_PHY_ANT01AUTO);
7882	}
7883	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7884	return (0);
7885}
7886
7887static void
7888bwn_wme_load(struct bwn_mac *mac)
7889{
7890	struct bwn_softc *sc = mac->mac_sc;
7891	int i;
7892
7893	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7894	    ("%s:%d: fail", __func__, __LINE__));
7895
7896	bwn_mac_suspend(mac);
7897	for (i = 0; i < N(sc->sc_wmeParams); i++)
7898		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
7899		    bwn_wme_shm_offsets[i]);
7900	bwn_mac_enable(mac);
7901}
7902
7903static void
7904bwn_wme_loadparams(struct bwn_mac *mac,
7905    const struct wmeParams *p, uint16_t shm_offset)
7906{
7907#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
7908	struct bwn_softc *sc = mac->mac_sc;
7909	uint16_t params[BWN_NR_WMEPARAMS];
7910	int slot, tmp;
7911	unsigned int i;
7912
7913	slot = BWN_READ_2(mac, BWN_RNG) &
7914	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7915
7916	memset(&params, 0, sizeof(params));
7917
7918	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
7919	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
7920	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
7921
7922	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
7923	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7924	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
7925	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7926	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
7927	params[BWN_WMEPARAM_BSLOTS] = slot;
7928	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
7929
7930	for (i = 0; i < N(params); i++) {
7931		if (i == BWN_WMEPARAM_STATUS) {
7932			tmp = bwn_shm_read_2(mac, BWN_SHARED,
7933			    shm_offset + (i * 2));
7934			tmp |= 0x100;
7935			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7936			    tmp);
7937		} else {
7938			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7939			    params[i]);
7940		}
7941	}
7942}
7943
7944static void
7945bwn_mac_write_bssid(struct bwn_mac *mac)
7946{
7947	struct bwn_softc *sc = mac->mac_sc;
7948	uint32_t tmp;
7949	int i;
7950	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
7951
7952	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
7953	memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
7954	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
7955	    IEEE80211_ADDR_LEN);
7956
7957	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
7958		tmp = (uint32_t) (mac_bssid[i + 0]);
7959		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
7960		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
7961		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
7962		bwn_ram_write(mac, 0x20 + i, tmp);
7963	}
7964}
7965
7966static void
7967bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
7968    const uint8_t *macaddr)
7969{
7970	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
7971	uint16_t data;
7972
7973	if (!mac)
7974		macaddr = zero;
7975
7976	offset |= 0x0020;
7977	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
7978
7979	data = macaddr[0];
7980	data |= macaddr[1] << 8;
7981	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7982	data = macaddr[2];
7983	data |= macaddr[3] << 8;
7984	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7985	data = macaddr[4];
7986	data |= macaddr[5] << 8;
7987	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7988}
7989
7990static void
7991bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
7992    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
7993{
7994	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
7995	uint8_t per_sta_keys_start = 8;
7996
7997	if (BWN_SEC_NEWAPI(mac))
7998		per_sta_keys_start = 4;
7999
8000	KASSERT(index < mac->mac_max_nr_keys,
8001	    ("%s:%d: fail", __func__, __LINE__));
8002	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8003	    ("%s:%d: fail", __func__, __LINE__));
8004
8005	if (index >= per_sta_keys_start)
8006		bwn_key_macwrite(mac, index, NULL);
8007	if (key)
8008		memcpy(buf, key, key_len);
8009	bwn_key_write(mac, index, algorithm, buf);
8010	if (index >= per_sta_keys_start)
8011		bwn_key_macwrite(mac, index, mac_addr);
8012
8013	mac->mac_key[index].algorithm = algorithm;
8014}
8015
8016static void
8017bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8018{
8019	struct bwn_softc *sc = mac->mac_sc;
8020	uint32_t addrtmp[2] = { 0, 0 };
8021	uint8_t start = 8;
8022
8023	if (BWN_SEC_NEWAPI(mac))
8024		start = 4;
8025
8026	KASSERT(index >= start,
8027	    ("%s:%d: fail", __func__, __LINE__));
8028	index -= start;
8029
8030	if (addr) {
8031		addrtmp[0] = addr[0];
8032		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8033		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8034		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8035		addrtmp[1] = addr[4];
8036		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8037	}
8038
8039	if (siba_get_revid(sc->sc_dev) >= 5) {
8040		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8041		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8042	} else {
8043		if (index >= 8) {
8044			bwn_shm_write_4(mac, BWN_SHARED,
8045			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8046			bwn_shm_write_2(mac, BWN_SHARED,
8047			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8048		}
8049	}
8050}
8051
8052static void
8053bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8054    const uint8_t *key)
8055{
8056	unsigned int i;
8057	uint32_t offset;
8058	uint16_t kidx, value;
8059
8060	kidx = BWN_SEC_KEY2FW(mac, index);
8061	bwn_shm_write_2(mac, BWN_SHARED,
8062	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8063
8064	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8065	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8066		value = key[i];
8067		value |= (uint16_t)(key[i + 1]) << 8;
8068		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8069	}
8070}
8071
8072static void
8073bwn_phy_exit(struct bwn_mac *mac)
8074{
8075
8076	mac->mac_phy.rf_onoff(mac, 0);
8077	if (mac->mac_phy.exit != NULL)
8078		mac->mac_phy.exit(mac);
8079}
8080
8081static void
8082bwn_dma_free(struct bwn_mac *mac)
8083{
8084	struct bwn_dma *dma;
8085
8086	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8087		return;
8088	dma = &mac->mac_method.dma;
8089
8090	bwn_dma_ringfree(&dma->rx);
8091	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8092	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8093	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8094	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8095	bwn_dma_ringfree(&dma->mcast);
8096}
8097
8098static void
8099bwn_core_stop(struct bwn_mac *mac)
8100{
8101	struct bwn_softc *sc = mac->mac_sc;
8102
8103	BWN_ASSERT_LOCKED(sc);
8104
8105	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8106		return;
8107
8108	callout_stop(&sc->sc_rfswitch_ch);
8109	callout_stop(&sc->sc_task_ch);
8110	callout_stop(&sc->sc_watchdog_ch);
8111	sc->sc_watchdog_timer = 0;
8112	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8113	BWN_READ_4(mac, BWN_INTR_MASK);
8114	bwn_mac_suspend(mac);
8115
8116	mac->mac_status = BWN_MAC_STATUS_INITED;
8117}
8118
8119static int
8120bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8121{
8122	struct bwn_mac *up_dev = NULL;
8123	struct bwn_mac *down_dev;
8124	struct bwn_mac *mac;
8125	int err, status;
8126	uint8_t gmode;
8127
8128	BWN_ASSERT_LOCKED(sc);
8129
8130	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8131		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8132		    mac->mac_phy.supports_2ghz) {
8133			up_dev = mac;
8134			gmode = 1;
8135		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8136		    mac->mac_phy.supports_5ghz) {
8137			up_dev = mac;
8138			gmode = 0;
8139		} else {
8140			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8141			return (EINVAL);
8142		}
8143		if (up_dev != NULL)
8144			break;
8145	}
8146	if (up_dev == NULL) {
8147		device_printf(sc->sc_dev, "Could not find a device\n");
8148		return (ENODEV);
8149	}
8150	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8151		return (0);
8152
8153	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8154	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8155
8156	down_dev = sc->sc_curmac;
8157	status = down_dev->mac_status;
8158	if (status >= BWN_MAC_STATUS_STARTED)
8159		bwn_core_stop(down_dev);
8160	if (status >= BWN_MAC_STATUS_INITED)
8161		bwn_core_exit(down_dev);
8162
8163	if (down_dev != up_dev)
8164		bwn_phy_reset(down_dev);
8165
8166	up_dev->mac_phy.gmode = gmode;
8167	if (status >= BWN_MAC_STATUS_INITED) {
8168		err = bwn_core_init(up_dev);
8169		if (err) {
8170			device_printf(sc->sc_dev,
8171			    "fatal: failed to initialize for %s-GHz\n",
8172			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8173			goto fail;
8174		}
8175	}
8176	if (status >= BWN_MAC_STATUS_STARTED)
8177		bwn_core_start(up_dev);
8178	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8179	sc->sc_curmac = up_dev;
8180
8181	return (0);
8182fail:
8183	sc->sc_curmac = NULL;
8184	return (err);
8185}
8186
8187static void
8188bwn_rf_turnon(struct bwn_mac *mac)
8189{
8190
8191	bwn_mac_suspend(mac);
8192	mac->mac_phy.rf_onoff(mac, 1);
8193	mac->mac_phy.rf_on = 1;
8194	bwn_mac_enable(mac);
8195}
8196
8197static void
8198bwn_rf_turnoff(struct bwn_mac *mac)
8199{
8200
8201	bwn_mac_suspend(mac);
8202	mac->mac_phy.rf_onoff(mac, 0);
8203	mac->mac_phy.rf_on = 0;
8204	bwn_mac_enable(mac);
8205}
8206
8207static void
8208bwn_phy_reset(struct bwn_mac *mac)
8209{
8210	struct bwn_softc *sc = mac->mac_sc;
8211
8212	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8213	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8214	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8215	DELAY(1000);
8216	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8217	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8218	    BWN_TGSLOW_PHYRESET);
8219	DELAY(1000);
8220}
8221
8222static int
8223bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8224{
8225	struct bwn_vap *bvp = BWN_VAP(vap);
8226	struct ieee80211com *ic= vap->iv_ic;
8227	enum ieee80211_state ostate = vap->iv_state;
8228	struct bwn_softc *sc = ic->ic_softc;
8229	struct bwn_mac *mac = sc->sc_curmac;
8230	int error;
8231
8232	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8233	    ieee80211_state_name[vap->iv_state],
8234	    ieee80211_state_name[nstate]);
8235
8236	error = bvp->bv_newstate(vap, nstate, arg);
8237	if (error != 0)
8238		return (error);
8239
8240	BWN_LOCK(sc);
8241
8242	bwn_led_newstate(mac, nstate);
8243
8244	/*
8245	 * Clear the BSSID when we stop a STA
8246	 */
8247	if (vap->iv_opmode == IEEE80211_M_STA) {
8248		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8249			/*
8250			 * Clear out the BSSID.  If we reassociate to
8251			 * the same AP, this will reinialize things
8252			 * correctly...
8253			 */
8254			if (ic->ic_opmode == IEEE80211_M_STA &&
8255			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8256				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8257				bwn_set_macaddr(mac);
8258			}
8259		}
8260	}
8261
8262	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8263	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8264		/* XXX nothing to do? */
8265	} else if (nstate == IEEE80211_S_RUN) {
8266		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8267		bwn_set_opmode(mac);
8268		bwn_set_pretbtt(mac);
8269		bwn_spu_setdelay(mac, 0);
8270		bwn_set_macaddr(mac);
8271	}
8272
8273	BWN_UNLOCK(sc);
8274
8275	return (error);
8276}
8277
8278static void
8279bwn_set_pretbtt(struct bwn_mac *mac)
8280{
8281	struct bwn_softc *sc = mac->mac_sc;
8282	struct ieee80211com *ic = &sc->sc_ic;
8283	uint16_t pretbtt;
8284
8285	if (ic->ic_opmode == IEEE80211_M_IBSS)
8286		pretbtt = 2;
8287	else
8288		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8289	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8290	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8291}
8292
8293static int
8294bwn_intr(void *arg)
8295{
8296	struct bwn_mac *mac = arg;
8297	struct bwn_softc *sc = mac->mac_sc;
8298	uint32_t reason;
8299
8300	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8301	    (sc->sc_flags & BWN_FLAG_INVALID))
8302		return (FILTER_STRAY);
8303
8304	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8305	if (reason == 0xffffffff)	/* shared IRQ */
8306		return (FILTER_STRAY);
8307	reason &= mac->mac_intr_mask;
8308	if (reason == 0)
8309		return (FILTER_HANDLED);
8310
8311	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8312	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8313	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8314	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8315	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8316	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8317	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8318	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8319	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8320	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8321	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8322
8323	/* Disable interrupts. */
8324	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8325
8326	mac->mac_reason_intr = reason;
8327
8328	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8329	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8330
8331	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8332	return (FILTER_HANDLED);
8333}
8334
8335static void
8336bwn_intrtask(void *arg, int npending)
8337{
8338	struct bwn_mac *mac = arg;
8339	struct bwn_softc *sc = mac->mac_sc;
8340	uint32_t merged = 0;
8341	int i, tx = 0, rx = 0;
8342
8343	BWN_LOCK(sc);
8344	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8345	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8346		BWN_UNLOCK(sc);
8347		return;
8348	}
8349
8350	for (i = 0; i < N(mac->mac_reason); i++)
8351		merged |= mac->mac_reason[i];
8352
8353	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8354		device_printf(sc->sc_dev, "MAC trans error\n");
8355
8356	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8357		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8358		mac->mac_phy.txerrors--;
8359		if (mac->mac_phy.txerrors == 0) {
8360			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8361			bwn_restart(mac, "PHY TX errors");
8362		}
8363	}
8364
8365	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8366		if (merged & BWN_DMAINTR_FATALMASK) {
8367			device_printf(sc->sc_dev,
8368			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8369			    mac->mac_reason[0], mac->mac_reason[1],
8370			    mac->mac_reason[2], mac->mac_reason[3],
8371			    mac->mac_reason[4], mac->mac_reason[5]);
8372			bwn_restart(mac, "DMA error");
8373			BWN_UNLOCK(sc);
8374			return;
8375		}
8376		if (merged & BWN_DMAINTR_NONFATALMASK) {
8377			device_printf(sc->sc_dev,
8378			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8379			    mac->mac_reason[0], mac->mac_reason[1],
8380			    mac->mac_reason[2], mac->mac_reason[3],
8381			    mac->mac_reason[4], mac->mac_reason[5]);
8382		}
8383	}
8384
8385	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8386		bwn_intr_ucode_debug(mac);
8387	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8388		bwn_intr_tbtt_indication(mac);
8389	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8390		bwn_intr_atim_end(mac);
8391	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8392		bwn_intr_beacon(mac);
8393	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8394		bwn_intr_pmq(mac);
8395	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8396		bwn_intr_noise(mac);
8397
8398	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8399		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8400			bwn_dma_rx(mac->mac_method.dma.rx);
8401			rx = 1;
8402		}
8403	} else
8404		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8405
8406	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8407	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8408	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8409	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8410	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8411
8412	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8413		bwn_intr_txeof(mac);
8414		tx = 1;
8415	}
8416
8417	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8418
8419	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8420		int evt = BWN_LED_EVENT_NONE;
8421
8422		if (tx && rx) {
8423			if (sc->sc_rx_rate > sc->sc_tx_rate)
8424				evt = BWN_LED_EVENT_RX;
8425			else
8426				evt = BWN_LED_EVENT_TX;
8427		} else if (tx) {
8428			evt = BWN_LED_EVENT_TX;
8429		} else if (rx) {
8430			evt = BWN_LED_EVENT_RX;
8431		} else if (rx == 0) {
8432			evt = BWN_LED_EVENT_POLL;
8433		}
8434
8435		if (evt != BWN_LED_EVENT_NONE)
8436			bwn_led_event(mac, evt);
8437       }
8438
8439	if (mbufq_first(&sc->sc_snd) != NULL)
8440		bwn_start(sc);
8441
8442	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8443	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8444
8445	BWN_UNLOCK(sc);
8446}
8447
8448static void
8449bwn_restart(struct bwn_mac *mac, const char *msg)
8450{
8451	struct bwn_softc *sc = mac->mac_sc;
8452	struct ieee80211com *ic = &sc->sc_ic;
8453
8454	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8455		return;
8456
8457	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8458	ieee80211_runtask(ic, &mac->mac_hwreset);
8459}
8460
8461static void
8462bwn_intr_ucode_debug(struct bwn_mac *mac)
8463{
8464	struct bwn_softc *sc = mac->mac_sc;
8465	uint16_t reason;
8466
8467	if (mac->mac_fw.opensource == 0)
8468		return;
8469
8470	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8471	switch (reason) {
8472	case BWN_DEBUGINTR_PANIC:
8473		bwn_handle_fwpanic(mac);
8474		break;
8475	case BWN_DEBUGINTR_DUMP_SHM:
8476		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8477		break;
8478	case BWN_DEBUGINTR_DUMP_REGS:
8479		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8480		break;
8481	case BWN_DEBUGINTR_MARKER:
8482		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8483		break;
8484	default:
8485		device_printf(sc->sc_dev,
8486		    "ucode debug unknown reason: %#x\n", reason);
8487	}
8488
8489	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8490	    BWN_DEBUGINTR_ACK);
8491}
8492
8493static void
8494bwn_intr_tbtt_indication(struct bwn_mac *mac)
8495{
8496	struct bwn_softc *sc = mac->mac_sc;
8497	struct ieee80211com *ic = &sc->sc_ic;
8498
8499	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8500		bwn_psctl(mac, 0);
8501	if (ic->ic_opmode == IEEE80211_M_IBSS)
8502		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8503}
8504
8505static void
8506bwn_intr_atim_end(struct bwn_mac *mac)
8507{
8508
8509	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8510		BWN_WRITE_4(mac, BWN_MACCMD,
8511		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8512		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8513	}
8514}
8515
8516static void
8517bwn_intr_beacon(struct bwn_mac *mac)
8518{
8519	struct bwn_softc *sc = mac->mac_sc;
8520	struct ieee80211com *ic = &sc->sc_ic;
8521	uint32_t cmd, beacon0, beacon1;
8522
8523	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8524	    ic->ic_opmode == IEEE80211_M_MBSS)
8525		return;
8526
8527	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8528
8529	cmd = BWN_READ_4(mac, BWN_MACCMD);
8530	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8531	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8532
8533	if (beacon0 && beacon1) {
8534		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8535		mac->mac_intr_mask |= BWN_INTR_BEACON;
8536		return;
8537	}
8538
8539	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8540		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8541		bwn_load_beacon0(mac);
8542		bwn_load_beacon1(mac);
8543		cmd = BWN_READ_4(mac, BWN_MACCMD);
8544		cmd |= BWN_MACCMD_BEACON0_VALID;
8545		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8546	} else {
8547		if (!beacon0) {
8548			bwn_load_beacon0(mac);
8549			cmd = BWN_READ_4(mac, BWN_MACCMD);
8550			cmd |= BWN_MACCMD_BEACON0_VALID;
8551			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8552		} else if (!beacon1) {
8553			bwn_load_beacon1(mac);
8554			cmd = BWN_READ_4(mac, BWN_MACCMD);
8555			cmd |= BWN_MACCMD_BEACON1_VALID;
8556			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8557		}
8558	}
8559}
8560
8561static void
8562bwn_intr_pmq(struct bwn_mac *mac)
8563{
8564	uint32_t tmp;
8565
8566	while (1) {
8567		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8568		if (!(tmp & 0x00000008))
8569			break;
8570	}
8571	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8572}
8573
8574static void
8575bwn_intr_noise(struct bwn_mac *mac)
8576{
8577	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8578	uint16_t tmp;
8579	uint8_t noise[4];
8580	uint8_t i, j;
8581	int32_t average;
8582
8583	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8584		return;
8585
8586	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8587	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8588	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8589	    noise[3] == 0x7f)
8590		goto new;
8591
8592	KASSERT(mac->mac_noise.noi_nsamples < 8,
8593	    ("%s:%d: fail", __func__, __LINE__));
8594	i = mac->mac_noise.noi_nsamples;
8595	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8596	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8597	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8598	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8599	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8600	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8601	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8602	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8603	mac->mac_noise.noi_nsamples++;
8604	if (mac->mac_noise.noi_nsamples == 8) {
8605		average = 0;
8606		for (i = 0; i < 8; i++) {
8607			for (j = 0; j < 4; j++)
8608				average += mac->mac_noise.noi_samples[i][j];
8609		}
8610		average = (((average / 32) * 125) + 64) / 128;
8611		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8612		if (tmp >= 8)
8613			average += 2;
8614		else
8615			average -= 25;
8616		average -= (tmp == 8) ? 72 : 48;
8617
8618		mac->mac_stats.link_noise = average;
8619		mac->mac_noise.noi_running = 0;
8620		return;
8621	}
8622new:
8623	bwn_noise_gensample(mac);
8624}
8625
8626static int
8627bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8628{
8629	struct bwn_mac *mac = prq->prq_mac;
8630	struct bwn_softc *sc = mac->mac_sc;
8631	unsigned int i;
8632
8633	BWN_ASSERT_LOCKED(sc);
8634
8635	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8636		return (0);
8637
8638	for (i = 0; i < 5000; i++) {
8639		if (bwn_pio_rxeof(prq) == 0)
8640			break;
8641	}
8642	if (i >= 5000)
8643		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8644	return ((i > 0) ? 1 : 0);
8645}
8646
8647static void
8648bwn_dma_rx(struct bwn_dma_ring *dr)
8649{
8650	int slot, curslot;
8651
8652	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8653	curslot = dr->get_curslot(dr);
8654	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8655	    ("%s:%d: fail", __func__, __LINE__));
8656
8657	slot = dr->dr_curslot;
8658	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8659		bwn_dma_rxeof(dr, &slot);
8660
8661	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8662	    BUS_DMASYNC_PREWRITE);
8663
8664	dr->set_curslot(dr, slot);
8665	dr->dr_curslot = slot;
8666}
8667
8668static void
8669bwn_intr_txeof(struct bwn_mac *mac)
8670{
8671	struct bwn_txstatus stat;
8672	uint32_t stat0, stat1;
8673	uint16_t tmp;
8674
8675	BWN_ASSERT_LOCKED(mac->mac_sc);
8676
8677	while (1) {
8678		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8679		if (!(stat0 & 0x00000001))
8680			break;
8681		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8682
8683		stat.cookie = (stat0 >> 16);
8684		stat.seq = (stat1 & 0x0000ffff);
8685		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8686		tmp = (stat0 & 0x0000ffff);
8687		stat.framecnt = ((tmp & 0xf000) >> 12);
8688		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8689		stat.sreason = ((tmp & 0x001c) >> 2);
8690		stat.pm = (tmp & 0x0080) ? 1 : 0;
8691		stat.im = (tmp & 0x0040) ? 1 : 0;
8692		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8693		stat.ack = (tmp & 0x0002) ? 1 : 0;
8694
8695		bwn_handle_txeof(mac, &stat);
8696	}
8697}
8698
8699static void
8700bwn_hwreset(void *arg, int npending)
8701{
8702	struct bwn_mac *mac = arg;
8703	struct bwn_softc *sc = mac->mac_sc;
8704	int error = 0;
8705	int prev_status;
8706
8707	BWN_LOCK(sc);
8708
8709	prev_status = mac->mac_status;
8710	if (prev_status >= BWN_MAC_STATUS_STARTED)
8711		bwn_core_stop(mac);
8712	if (prev_status >= BWN_MAC_STATUS_INITED)
8713		bwn_core_exit(mac);
8714
8715	if (prev_status >= BWN_MAC_STATUS_INITED) {
8716		error = bwn_core_init(mac);
8717		if (error)
8718			goto out;
8719	}
8720	if (prev_status >= BWN_MAC_STATUS_STARTED)
8721		bwn_core_start(mac);
8722out:
8723	if (error) {
8724		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8725		sc->sc_curmac = NULL;
8726	}
8727	BWN_UNLOCK(sc);
8728}
8729
8730static void
8731bwn_handle_fwpanic(struct bwn_mac *mac)
8732{
8733	struct bwn_softc *sc = mac->mac_sc;
8734	uint16_t reason;
8735
8736	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8737	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8738
8739	if (reason == BWN_FWPANIC_RESTART)
8740		bwn_restart(mac, "ucode panic");
8741}
8742
8743static void
8744bwn_load_beacon0(struct bwn_mac *mac)
8745{
8746
8747	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8748}
8749
8750static void
8751bwn_load_beacon1(struct bwn_mac *mac)
8752{
8753
8754	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8755}
8756
8757static uint32_t
8758bwn_jssi_read(struct bwn_mac *mac)
8759{
8760	uint32_t val = 0;
8761
8762	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8763	val <<= 16;
8764	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8765
8766	return (val);
8767}
8768
8769static void
8770bwn_noise_gensample(struct bwn_mac *mac)
8771{
8772	uint32_t jssi = 0x7f7f7f7f;
8773
8774	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8775	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8776	BWN_WRITE_4(mac, BWN_MACCMD,
8777	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8778}
8779
8780static int
8781bwn_dma_freeslot(struct bwn_dma_ring *dr)
8782{
8783	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8784
8785	return (dr->dr_numslots - dr->dr_usedslot);
8786}
8787
8788static int
8789bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8790{
8791	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8792
8793	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8794	    ("%s:%d: fail", __func__, __LINE__));
8795	if (slot == dr->dr_numslots - 1)
8796		return (0);
8797	return (slot + 1);
8798}
8799
8800static void
8801bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8802{
8803	struct bwn_mac *mac = dr->dr_mac;
8804	struct bwn_softc *sc = mac->mac_sc;
8805	struct bwn_dma *dma = &mac->mac_method.dma;
8806	struct bwn_dmadesc_generic *desc;
8807	struct bwn_dmadesc_meta *meta;
8808	struct bwn_rxhdr4 *rxhdr;
8809	struct mbuf *m;
8810	uint32_t macstat;
8811	int32_t tmp;
8812	int cnt = 0;
8813	uint16_t len;
8814
8815	dr->getdesc(dr, *slot, &desc, &meta);
8816
8817	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8818	m = meta->mt_m;
8819
8820	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8821		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8822		return;
8823	}
8824
8825	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8826	len = le16toh(rxhdr->frame_len);
8827	if (len <= 0) {
8828		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8829		return;
8830	}
8831	if (bwn_dma_check_redzone(dr, m)) {
8832		device_printf(sc->sc_dev, "redzone error.\n");
8833		bwn_dma_set_redzone(dr, m);
8834		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8835		    BUS_DMASYNC_PREWRITE);
8836		return;
8837	}
8838	if (len > dr->dr_rx_bufsize) {
8839		tmp = len;
8840		while (1) {
8841			dr->getdesc(dr, *slot, &desc, &meta);
8842			bwn_dma_set_redzone(dr, meta->mt_m);
8843			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8844			    BUS_DMASYNC_PREWRITE);
8845			*slot = bwn_dma_nextslot(dr, *slot);
8846			cnt++;
8847			tmp -= dr->dr_rx_bufsize;
8848			if (tmp <= 0)
8849				break;
8850		}
8851		device_printf(sc->sc_dev, "too small buffer "
8852		       "(len %u buffer %u dropped %d)\n",
8853		       len, dr->dr_rx_bufsize, cnt);
8854		return;
8855	}
8856	macstat = le32toh(rxhdr->mac_status);
8857	if (macstat & BWN_RX_MAC_FCSERR) {
8858		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8859			device_printf(sc->sc_dev, "RX drop\n");
8860			return;
8861		}
8862	}
8863
8864	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8865	m_adj(m, dr->dr_frameoffset);
8866
8867	bwn_rxeof(dr->dr_mac, m, rxhdr);
8868}
8869
8870static void
8871bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8872{
8873	struct bwn_dma_ring *dr;
8874	struct bwn_dmadesc_generic *desc;
8875	struct bwn_dmadesc_meta *meta;
8876	struct bwn_pio_txqueue *tq;
8877	struct bwn_pio_txpkt *tp = NULL;
8878	struct bwn_softc *sc = mac->mac_sc;
8879	struct bwn_stats *stats = &mac->mac_stats;
8880	struct ieee80211_node *ni;
8881	struct ieee80211vap *vap;
8882	int retrycnt = 0, slot;
8883
8884	BWN_ASSERT_LOCKED(mac->mac_sc);
8885
8886	if (status->im)
8887		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8888	if (status->ampdu)
8889		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
8890	if (status->rtscnt) {
8891		if (status->rtscnt == 0xf)
8892			stats->rtsfail++;
8893		else
8894			stats->rts++;
8895	}
8896
8897	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8898		if (status->ack) {
8899			dr = bwn_dma_parse_cookie(mac, status,
8900			    status->cookie, &slot);
8901			if (dr == NULL) {
8902				device_printf(sc->sc_dev,
8903				    "failed to parse cookie\n");
8904				return;
8905			}
8906			while (1) {
8907				dr->getdesc(dr, slot, &desc, &meta);
8908				if (meta->mt_islast) {
8909					ni = meta->mt_ni;
8910					vap = ni->ni_vap;
8911					ieee80211_ratectl_tx_complete(vap, ni,
8912					    status->ack ?
8913					      IEEE80211_RATECTL_TX_SUCCESS :
8914					      IEEE80211_RATECTL_TX_FAILURE,
8915					    &retrycnt, 0);
8916					break;
8917				}
8918				slot = bwn_dma_nextslot(dr, slot);
8919			}
8920		}
8921		bwn_dma_handle_txeof(mac, status);
8922	} else {
8923		if (status->ack) {
8924			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
8925			if (tq == NULL) {
8926				device_printf(sc->sc_dev,
8927				    "failed to parse cookie\n");
8928				return;
8929			}
8930			ni = tp->tp_ni;
8931			vap = ni->ni_vap;
8932			ieee80211_ratectl_tx_complete(vap, ni,
8933			    status->ack ?
8934			      IEEE80211_RATECTL_TX_SUCCESS :
8935			      IEEE80211_RATECTL_TX_FAILURE,
8936			    &retrycnt, 0);
8937		}
8938		bwn_pio_handle_txeof(mac, status);
8939	}
8940
8941	bwn_phy_txpower_check(mac, 0);
8942}
8943
8944static uint8_t
8945bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
8946{
8947	struct bwn_mac *mac = prq->prq_mac;
8948	struct bwn_softc *sc = mac->mac_sc;
8949	struct bwn_rxhdr4 rxhdr;
8950	struct mbuf *m;
8951	uint32_t ctl32, macstat, v32;
8952	unsigned int i, padding;
8953	uint16_t ctl16, len, totlen, v16;
8954	unsigned char *mp;
8955	char *data;
8956
8957	memset(&rxhdr, 0, sizeof(rxhdr));
8958
8959	if (prq->prq_rev >= 8) {
8960		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8961		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
8962			return (0);
8963		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
8964		    BWN_PIO8_RXCTL_FRAMEREADY);
8965		for (i = 0; i < 10; i++) {
8966			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8967			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
8968				goto ready;
8969			DELAY(10);
8970		}
8971	} else {
8972		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8973		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
8974			return (0);
8975		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
8976		    BWN_PIO_RXCTL_FRAMEREADY);
8977		for (i = 0; i < 10; i++) {
8978			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8979			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
8980				goto ready;
8981			DELAY(10);
8982		}
8983	}
8984	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
8985	return (1);
8986ready:
8987	if (prq->prq_rev >= 8)
8988		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8989		    prq->prq_base + BWN_PIO8_RXDATA);
8990	else
8991		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8992		    prq->prq_base + BWN_PIO_RXDATA);
8993	len = le16toh(rxhdr.frame_len);
8994	if (len > 0x700) {
8995		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
8996		goto error;
8997	}
8998	if (len == 0) {
8999		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9000		goto error;
9001	}
9002
9003	macstat = le32toh(rxhdr.mac_status);
9004	if (macstat & BWN_RX_MAC_FCSERR) {
9005		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9006			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9007			goto error;
9008		}
9009	}
9010
9011	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9012	totlen = len + padding;
9013	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9014	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9015	if (m == NULL) {
9016		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9017		goto error;
9018	}
9019	mp = mtod(m, unsigned char *);
9020	if (prq->prq_rev >= 8) {
9021		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9022		    prq->prq_base + BWN_PIO8_RXDATA);
9023		if (totlen & 3) {
9024			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9025			data = &(mp[totlen - 1]);
9026			switch (totlen & 3) {
9027			case 3:
9028				*data = (v32 >> 16);
9029				data--;
9030			case 2:
9031				*data = (v32 >> 8);
9032				data--;
9033			case 1:
9034				*data = v32;
9035			}
9036		}
9037	} else {
9038		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9039		    prq->prq_base + BWN_PIO_RXDATA);
9040		if (totlen & 1) {
9041			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9042			mp[totlen - 1] = v16;
9043		}
9044	}
9045
9046	m->m_len = m->m_pkthdr.len = totlen;
9047
9048	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9049
9050	return (1);
9051error:
9052	if (prq->prq_rev >= 8)
9053		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9054		    BWN_PIO8_RXCTL_DATAREADY);
9055	else
9056		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9057	return (1);
9058}
9059
9060static int
9061bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9062    struct bwn_dmadesc_meta *meta, int init)
9063{
9064	struct bwn_mac *mac = dr->dr_mac;
9065	struct bwn_dma *dma = &mac->mac_method.dma;
9066	struct bwn_rxhdr4 *hdr;
9067	bus_dmamap_t map;
9068	bus_addr_t paddr;
9069	struct mbuf *m;
9070	int error;
9071
9072	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9073	if (m == NULL) {
9074		error = ENOBUFS;
9075
9076		/*
9077		 * If the NIC is up and running, we need to:
9078		 * - Clear RX buffer's header.
9079		 * - Restore RX descriptor settings.
9080		 */
9081		if (init)
9082			return (error);
9083		else
9084			goto back;
9085	}
9086	m->m_len = m->m_pkthdr.len = MCLBYTES;
9087
9088	bwn_dma_set_redzone(dr, m);
9089
9090	/*
9091	 * Try to load RX buf into temporary DMA map
9092	 */
9093	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9094	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9095	if (error) {
9096		m_freem(m);
9097
9098		/*
9099		 * See the comment above
9100		 */
9101		if (init)
9102			return (error);
9103		else
9104			goto back;
9105	}
9106
9107	if (!init)
9108		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9109	meta->mt_m = m;
9110	meta->mt_paddr = paddr;
9111
9112	/*
9113	 * Swap RX buf's DMA map with the loaded temporary one
9114	 */
9115	map = meta->mt_dmap;
9116	meta->mt_dmap = dr->dr_spare_dmap;
9117	dr->dr_spare_dmap = map;
9118
9119back:
9120	/*
9121	 * Clear RX buf header
9122	 */
9123	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9124	bzero(hdr, sizeof(*hdr));
9125	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9126	    BUS_DMASYNC_PREWRITE);
9127
9128	/*
9129	 * Setup RX buf descriptor
9130	 */
9131	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9132	    sizeof(*hdr), 0, 0, 0);
9133	return (error);
9134}
9135
9136static void
9137bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9138		 bus_size_t mapsz __unused, int error)
9139{
9140
9141	if (!error) {
9142		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9143		*((bus_addr_t *)arg) = seg->ds_addr;
9144	}
9145}
9146
9147static int
9148bwn_hwrate2ieeerate(int rate)
9149{
9150
9151	switch (rate) {
9152	case BWN_CCK_RATE_1MB:
9153		return (2);
9154	case BWN_CCK_RATE_2MB:
9155		return (4);
9156	case BWN_CCK_RATE_5MB:
9157		return (11);
9158	case BWN_CCK_RATE_11MB:
9159		return (22);
9160	case BWN_OFDM_RATE_6MB:
9161		return (12);
9162	case BWN_OFDM_RATE_9MB:
9163		return (18);
9164	case BWN_OFDM_RATE_12MB:
9165		return (24);
9166	case BWN_OFDM_RATE_18MB:
9167		return (36);
9168	case BWN_OFDM_RATE_24MB:
9169		return (48);
9170	case BWN_OFDM_RATE_36MB:
9171		return (72);
9172	case BWN_OFDM_RATE_48MB:
9173		return (96);
9174	case BWN_OFDM_RATE_54MB:
9175		return (108);
9176	default:
9177		printf("Ooops\n");
9178		return (0);
9179	}
9180}
9181
9182static void
9183bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9184{
9185	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9186	struct bwn_plcp6 *plcp;
9187	struct bwn_softc *sc = mac->mac_sc;
9188	struct ieee80211_frame_min *wh;
9189	struct ieee80211_node *ni;
9190	struct ieee80211com *ic = &sc->sc_ic;
9191	uint32_t macstat;
9192	int padding, rate, rssi = 0, noise = 0, type;
9193	uint16_t phytype, phystat0, phystat3, chanstat;
9194	unsigned char *mp = mtod(m, unsigned char *);
9195	static int rx_mac_dec_rpt = 0;
9196
9197	BWN_ASSERT_LOCKED(sc);
9198
9199	phystat0 = le16toh(rxhdr->phy_status0);
9200	phystat3 = le16toh(rxhdr->phy_status3);
9201	macstat = le32toh(rxhdr->mac_status);
9202	chanstat = le16toh(rxhdr->channel);
9203	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9204
9205	if (macstat & BWN_RX_MAC_FCSERR)
9206		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9207	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9208		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9209	if (macstat & BWN_RX_MAC_DECERR)
9210		goto drop;
9211
9212	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9213	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9214		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9215		    m->m_pkthdr.len);
9216		goto drop;
9217	}
9218	plcp = (struct bwn_plcp6 *)(mp + padding);
9219	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9220	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9221		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9222		    m->m_pkthdr.len);
9223		goto drop;
9224	}
9225	wh = mtod(m, struct ieee80211_frame_min *);
9226
9227	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9228		device_printf(sc->sc_dev,
9229		    "RX decryption attempted (old %d keyidx %#x)\n",
9230		    BWN_ISOLDFMT(mac),
9231		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9232
9233	/* XXX calculating RSSI & noise & antenna */
9234
9235	if (phystat0 & BWN_RX_PHYST0_OFDM)
9236		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9237		    phytype == BWN_PHYTYPE_A);
9238	else
9239		rate = bwn_plcp_get_cckrate(mac, plcp);
9240	if (rate == -1) {
9241		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9242			goto drop;
9243	}
9244	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9245
9246	/* RX radio tap */
9247	if (ieee80211_radiotap_active(ic))
9248		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9249	m_adj(m, -IEEE80211_CRC_LEN);
9250
9251	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9252	noise = mac->mac_stats.link_noise;
9253
9254	BWN_UNLOCK(sc);
9255
9256	ni = ieee80211_find_rxnode(ic, wh);
9257	if (ni != NULL) {
9258		type = ieee80211_input(ni, m, rssi, noise);
9259		ieee80211_free_node(ni);
9260	} else
9261		type = ieee80211_input_all(ic, m, rssi, noise);
9262
9263	BWN_LOCK(sc);
9264	return;
9265drop:
9266	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9267}
9268
9269static void
9270bwn_dma_handle_txeof(struct bwn_mac *mac,
9271    const struct bwn_txstatus *status)
9272{
9273	struct bwn_dma *dma = &mac->mac_method.dma;
9274	struct bwn_dma_ring *dr;
9275	struct bwn_dmadesc_generic *desc;
9276	struct bwn_dmadesc_meta *meta;
9277	struct bwn_softc *sc = mac->mac_sc;
9278	int slot;
9279
9280	BWN_ASSERT_LOCKED(sc);
9281
9282	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9283	if (dr == NULL) {
9284		device_printf(sc->sc_dev, "failed to parse cookie\n");
9285		return;
9286	}
9287	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9288
9289	while (1) {
9290		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9291		    ("%s:%d: fail", __func__, __LINE__));
9292		dr->getdesc(dr, slot, &desc, &meta);
9293
9294		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9295			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9296		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9297			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9298
9299		if (meta->mt_islast) {
9300			KASSERT(meta->mt_m != NULL,
9301			    ("%s:%d: fail", __func__, __LINE__));
9302
9303			ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
9304			meta->mt_ni = NULL;
9305			meta->mt_m = NULL;
9306		} else
9307			KASSERT(meta->mt_m == NULL,
9308			    ("%s:%d: fail", __func__, __LINE__));
9309
9310		dr->dr_usedslot--;
9311		if (meta->mt_islast)
9312			break;
9313		slot = bwn_dma_nextslot(dr, slot);
9314	}
9315	sc->sc_watchdog_timer = 0;
9316	if (dr->dr_stop) {
9317		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9318		    ("%s:%d: fail", __func__, __LINE__));
9319		dr->dr_stop = 0;
9320	}
9321}
9322
9323static void
9324bwn_pio_handle_txeof(struct bwn_mac *mac,
9325    const struct bwn_txstatus *status)
9326{
9327	struct bwn_pio_txqueue *tq;
9328	struct bwn_pio_txpkt *tp = NULL;
9329	struct bwn_softc *sc = mac->mac_sc;
9330
9331	BWN_ASSERT_LOCKED(sc);
9332
9333	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9334	if (tq == NULL)
9335		return;
9336
9337	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9338	tq->tq_free++;
9339
9340	if (tp->tp_ni != NULL) {
9341		/*
9342		 * Do any tx complete callback.  Note this must
9343		 * be done before releasing the node reference.
9344		 */
9345		if (tp->tp_m->m_flags & M_TXCB)
9346			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9347		ieee80211_free_node(tp->tp_ni);
9348		tp->tp_ni = NULL;
9349	}
9350	m_freem(tp->tp_m);
9351	tp->tp_m = NULL;
9352	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9353
9354	sc->sc_watchdog_timer = 0;
9355}
9356
9357static void
9358bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9359{
9360	struct bwn_softc *sc = mac->mac_sc;
9361	struct bwn_phy *phy = &mac->mac_phy;
9362	struct ieee80211com *ic = &sc->sc_ic;
9363	unsigned long now;
9364	int result;
9365
9366	BWN_GETTIME(now);
9367
9368	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9369		return;
9370	phy->nexttime = now + 2 * 1000;
9371
9372	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9373	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9374		return;
9375
9376	if (phy->recalc_txpwr != NULL) {
9377		result = phy->recalc_txpwr(mac,
9378		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9379		if (result == BWN_TXPWR_RES_DONE)
9380			return;
9381		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9382		    ("%s: fail", __func__));
9383		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9384
9385		ieee80211_runtask(ic, &mac->mac_txpower);
9386	}
9387}
9388
9389static uint16_t
9390bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9391{
9392
9393	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9394}
9395
9396static uint32_t
9397bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9398{
9399
9400	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9401}
9402
9403static void
9404bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9405{
9406
9407	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9408}
9409
9410static void
9411bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9412{
9413
9414	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9415}
9416
9417static int
9418bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9419{
9420
9421	switch (rate) {
9422	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9423	case 12:
9424		return (BWN_OFDM_RATE_6MB);
9425	case 18:
9426		return (BWN_OFDM_RATE_9MB);
9427	case 24:
9428		return (BWN_OFDM_RATE_12MB);
9429	case 36:
9430		return (BWN_OFDM_RATE_18MB);
9431	case 48:
9432		return (BWN_OFDM_RATE_24MB);
9433	case 72:
9434		return (BWN_OFDM_RATE_36MB);
9435	case 96:
9436		return (BWN_OFDM_RATE_48MB);
9437	case 108:
9438		return (BWN_OFDM_RATE_54MB);
9439	/* CCK rates (NB: not IEEE std, device-specific) */
9440	case 2:
9441		return (BWN_CCK_RATE_1MB);
9442	case 4:
9443		return (BWN_CCK_RATE_2MB);
9444	case 11:
9445		return (BWN_CCK_RATE_5MB);
9446	case 22:
9447		return (BWN_CCK_RATE_11MB);
9448	}
9449
9450	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9451	return (BWN_CCK_RATE_1MB);
9452}
9453
9454static int
9455bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9456    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9457{
9458	const struct bwn_phy *phy = &mac->mac_phy;
9459	struct bwn_softc *sc = mac->mac_sc;
9460	struct ieee80211_frame *wh;
9461	struct ieee80211_frame *protwh;
9462	struct ieee80211_frame_cts *cts;
9463	struct ieee80211_frame_rts *rts;
9464	const struct ieee80211_txparam *tp;
9465	struct ieee80211vap *vap = ni->ni_vap;
9466	struct ieee80211com *ic = &sc->sc_ic;
9467	struct mbuf *mprot;
9468	unsigned int len;
9469	uint32_t macctl = 0;
9470	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9471	uint16_t phyctl = 0;
9472	uint8_t rate, rate_fb;
9473
9474	wh = mtod(m, struct ieee80211_frame *);
9475	memset(txhdr, 0, sizeof(*txhdr));
9476
9477	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9478	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9479	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9480
9481	/*
9482	 * Find TX rate
9483	 */
9484	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9485	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9486		rate = rate_fb = tp->mgmtrate;
9487	else if (ismcast)
9488		rate = rate_fb = tp->mcastrate;
9489	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9490		rate = rate_fb = tp->ucastrate;
9491	else {
9492		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9493		rate = ni->ni_txrate;
9494
9495		if (rix > 0)
9496			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9497			    IEEE80211_RATE_VAL;
9498		else
9499			rate_fb = rate;
9500	}
9501
9502	sc->sc_tx_rate = rate;
9503
9504	rate = bwn_ieeerate2hwrate(sc, rate);
9505	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9506
9507	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9508	    bwn_plcp_getcck(rate);
9509	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9510	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9511
9512	if ((rate_fb == rate) ||
9513	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9514	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9515		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9516	else
9517		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9518		    m->m_pkthdr.len, rate, isshort);
9519
9520	/* XXX TX encryption */
9521	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9522	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9523	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9524	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9525	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9526	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9527
9528	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9529	    BWN_TX_EFT_FB_CCK;
9530	txhdr->chan = phy->chan;
9531	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9532	    BWN_TX_PHY_ENC_CCK;
9533	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9534	     rate == BWN_CCK_RATE_11MB))
9535		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9536
9537	/* XXX TX antenna selection */
9538
9539	switch (bwn_antenna_sanitize(mac, 0)) {
9540	case 0:
9541		phyctl |= BWN_TX_PHY_ANT01AUTO;
9542		break;
9543	case 1:
9544		phyctl |= BWN_TX_PHY_ANT0;
9545		break;
9546	case 2:
9547		phyctl |= BWN_TX_PHY_ANT1;
9548		break;
9549	case 3:
9550		phyctl |= BWN_TX_PHY_ANT2;
9551		break;
9552	case 4:
9553		phyctl |= BWN_TX_PHY_ANT3;
9554		break;
9555	default:
9556		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9557	}
9558
9559	if (!ismcast)
9560		macctl |= BWN_TX_MAC_ACK;
9561
9562	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9563	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9564	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9565		macctl |= BWN_TX_MAC_LONGFRAME;
9566
9567	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9568		/* XXX RTS rate is always 1MB??? */
9569		rts_rate = BWN_CCK_RATE_1MB;
9570		rts_rate_fb = bwn_get_fbrate(rts_rate);
9571
9572		protdur = ieee80211_compute_duration(ic->ic_rt,
9573		    m->m_pkthdr.len, rate, isshort) +
9574		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9575
9576		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9577			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9578			    (txhdr->body.old.rts_frame) :
9579			    (txhdr->body.new.rts_frame));
9580			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9581			    protdur);
9582			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9583			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9584			    mprot->m_pkthdr.len);
9585			m_freem(mprot);
9586			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9587			len = sizeof(struct ieee80211_frame_cts);
9588		} else {
9589			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9590			    (txhdr->body.old.rts_frame) :
9591			    (txhdr->body.new.rts_frame));
9592			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9593			    isshort);
9594			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9595			    wh->i_addr2, protdur);
9596			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9597			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9598			    mprot->m_pkthdr.len);
9599			m_freem(mprot);
9600			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9601			len = sizeof(struct ieee80211_frame_rts);
9602		}
9603		len += IEEE80211_CRC_LEN;
9604		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9605		    &txhdr->body.old.rts_plcp :
9606		    &txhdr->body.new.rts_plcp), len, rts_rate);
9607		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9608		    rts_rate_fb);
9609
9610		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9611		    (&txhdr->body.old.rts_frame) :
9612		    (&txhdr->body.new.rts_frame));
9613		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9614
9615		if (BWN_ISOFDMRATE(rts_rate)) {
9616			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9617			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9618		} else {
9619			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9620			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9621		}
9622		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9623		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9624	}
9625
9626	if (BWN_ISOLDFMT(mac))
9627		txhdr->body.old.cookie = htole16(cookie);
9628	else
9629		txhdr->body.new.cookie = htole16(cookie);
9630
9631	txhdr->macctl = htole32(macctl);
9632	txhdr->phyctl = htole16(phyctl);
9633
9634	/*
9635	 * TX radio tap
9636	 */
9637	if (ieee80211_radiotap_active_vap(vap)) {
9638		sc->sc_tx_th.wt_flags = 0;
9639		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
9640			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9641		if (isshort &&
9642		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9643		     rate == BWN_CCK_RATE_11MB))
9644			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9645		sc->sc_tx_th.wt_rate = rate;
9646
9647		ieee80211_radiotap_tx(vap, m);
9648	}
9649
9650	return (0);
9651}
9652
9653static void
9654bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9655    const uint8_t rate)
9656{
9657	uint32_t d, plen;
9658	uint8_t *raw = plcp->o.raw;
9659
9660	if (BWN_ISOFDMRATE(rate)) {
9661		d = bwn_plcp_getofdm(rate);
9662		KASSERT(!(octets & 0xf000),
9663		    ("%s:%d: fail", __func__, __LINE__));
9664		d |= (octets << 5);
9665		plcp->o.data = htole32(d);
9666	} else {
9667		plen = octets * 16 / rate;
9668		if ((octets * 16 % rate) > 0) {
9669			plen++;
9670			if ((rate == BWN_CCK_RATE_11MB)
9671			    && ((octets * 8 % 11) < 4)) {
9672				raw[1] = 0x84;
9673			} else
9674				raw[1] = 0x04;
9675		} else
9676			raw[1] = 0x04;
9677		plcp->o.data |= htole32(plen << 16);
9678		raw[0] = bwn_plcp_getcck(rate);
9679	}
9680}
9681
9682static uint8_t
9683bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9684{
9685	struct bwn_softc *sc = mac->mac_sc;
9686	uint8_t mask;
9687
9688	if (n == 0)
9689		return (0);
9690	if (mac->mac_phy.gmode)
9691		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9692	else
9693		mask = siba_sprom_get_ant_a(sc->sc_dev);
9694	if (!(mask & (1 << (n - 1))))
9695		return (0);
9696	return (n);
9697}
9698
9699static uint8_t
9700bwn_get_fbrate(uint8_t bitrate)
9701{
9702	switch (bitrate) {
9703	case BWN_CCK_RATE_1MB:
9704		return (BWN_CCK_RATE_1MB);
9705	case BWN_CCK_RATE_2MB:
9706		return (BWN_CCK_RATE_1MB);
9707	case BWN_CCK_RATE_5MB:
9708		return (BWN_CCK_RATE_2MB);
9709	case BWN_CCK_RATE_11MB:
9710		return (BWN_CCK_RATE_5MB);
9711	case BWN_OFDM_RATE_6MB:
9712		return (BWN_CCK_RATE_5MB);
9713	case BWN_OFDM_RATE_9MB:
9714		return (BWN_OFDM_RATE_6MB);
9715	case BWN_OFDM_RATE_12MB:
9716		return (BWN_OFDM_RATE_9MB);
9717	case BWN_OFDM_RATE_18MB:
9718		return (BWN_OFDM_RATE_12MB);
9719	case BWN_OFDM_RATE_24MB:
9720		return (BWN_OFDM_RATE_18MB);
9721	case BWN_OFDM_RATE_36MB:
9722		return (BWN_OFDM_RATE_24MB);
9723	case BWN_OFDM_RATE_48MB:
9724		return (BWN_OFDM_RATE_36MB);
9725	case BWN_OFDM_RATE_54MB:
9726		return (BWN_OFDM_RATE_48MB);
9727	}
9728	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9729	return (0);
9730}
9731
9732static uint32_t
9733bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9734    uint32_t ctl, const void *_data, int len)
9735{
9736	struct bwn_softc *sc = mac->mac_sc;
9737	uint32_t value = 0;
9738	const uint8_t *data = _data;
9739
9740	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9741	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9742	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9743
9744	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9745	    tq->tq_base + BWN_PIO8_TXDATA);
9746	if (len & 3) {
9747		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9748		    BWN_PIO8_TXCTL_24_31);
9749		data = &(data[len - 1]);
9750		switch (len & 3) {
9751		case 3:
9752			ctl |= BWN_PIO8_TXCTL_16_23;
9753			value |= (uint32_t)(*data) << 16;
9754			data--;
9755		case 2:
9756			ctl |= BWN_PIO8_TXCTL_8_15;
9757			value |= (uint32_t)(*data) << 8;
9758			data--;
9759		case 1:
9760			value |= (uint32_t)(*data);
9761		}
9762		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9763		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9764	}
9765
9766	return (ctl);
9767}
9768
9769static void
9770bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9771    uint16_t offset, uint32_t value)
9772{
9773
9774	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9775}
9776
9777static uint16_t
9778bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9779    uint16_t ctl, const void *_data, int len)
9780{
9781	struct bwn_softc *sc = mac->mac_sc;
9782	const uint8_t *data = _data;
9783
9784	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9785	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9786
9787	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9788	    tq->tq_base + BWN_PIO_TXDATA);
9789	if (len & 1) {
9790		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9791		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9792		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9793	}
9794
9795	return (ctl);
9796}
9797
9798static uint16_t
9799bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9800    uint16_t ctl, struct mbuf *m0)
9801{
9802	int i, j = 0;
9803	uint16_t data = 0;
9804	const uint8_t *buf;
9805	struct mbuf *m = m0;
9806
9807	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9808	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9809
9810	for (; m != NULL; m = m->m_next) {
9811		buf = mtod(m, const uint8_t *);
9812		for (i = 0; i < m->m_len; i++) {
9813			if (!((j++) % 2))
9814				data |= buf[i];
9815			else {
9816				data |= (buf[i] << 8);
9817				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9818				data = 0;
9819			}
9820		}
9821	}
9822	if (m0->m_pkthdr.len % 2) {
9823		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9824		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9825		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9826	}
9827
9828	return (ctl);
9829}
9830
9831static void
9832bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9833{
9834
9835	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9836		return;
9837	BWN_WRITE_2(mac, 0x684, 510 + time);
9838	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9839}
9840
9841static struct bwn_dma_ring *
9842bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9843{
9844
9845	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9846		return (mac->mac_method.dma.wme[WME_AC_BE]);
9847
9848	switch (prio) {
9849	case 3:
9850		return (mac->mac_method.dma.wme[WME_AC_VO]);
9851	case 2:
9852		return (mac->mac_method.dma.wme[WME_AC_VI]);
9853	case 0:
9854		return (mac->mac_method.dma.wme[WME_AC_BE]);
9855	case 1:
9856		return (mac->mac_method.dma.wme[WME_AC_BK]);
9857	}
9858	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9859	return (NULL);
9860}
9861
9862static int
9863bwn_dma_getslot(struct bwn_dma_ring *dr)
9864{
9865	int slot;
9866
9867	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
9868
9869	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9870	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
9871	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
9872
9873	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
9874	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
9875	dr->dr_curslot = slot;
9876	dr->dr_usedslot++;
9877
9878	return (slot);
9879}
9880
9881static int
9882bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
9883{
9884	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
9885	unsigned int a, b, c, d;
9886	unsigned int avg;
9887	uint32_t tmp;
9888
9889	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
9890	a = tmp & 0xff;
9891	b = (tmp >> 8) & 0xff;
9892	c = (tmp >> 16) & 0xff;
9893	d = (tmp >> 24) & 0xff;
9894	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
9895	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
9896		return (ENOENT);
9897	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
9898	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
9899	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
9900
9901	if (ofdm) {
9902		a = (a + 32) & 0x3f;
9903		b = (b + 32) & 0x3f;
9904		c = (c + 32) & 0x3f;
9905		d = (d + 32) & 0x3f;
9906	}
9907
9908	avg = (a + b + c + d + 2) / 4;
9909	if (ofdm) {
9910		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
9911		    & BWN_HF_4DB_CCK_POWERBOOST)
9912			avg = (avg >= 13) ? (avg - 13) : 0;
9913	}
9914	return (avg);
9915}
9916
9917static void
9918bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
9919{
9920	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
9921	int rfatt = *rfattp;
9922	int bbatt = *bbattp;
9923
9924	while (1) {
9925		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
9926			break;
9927		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
9928			break;
9929		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
9930			break;
9931		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
9932			break;
9933		if (bbatt > lo->bbatt.max) {
9934			bbatt -= 4;
9935			rfatt += 1;
9936			continue;
9937		}
9938		if (bbatt < lo->bbatt.min) {
9939			bbatt += 4;
9940			rfatt -= 1;
9941			continue;
9942		}
9943		if (rfatt > lo->rfatt.max) {
9944			rfatt -= 1;
9945			bbatt += 4;
9946			continue;
9947		}
9948		if (rfatt < lo->rfatt.min) {
9949			rfatt += 1;
9950			bbatt -= 4;
9951			continue;
9952		}
9953		break;
9954	}
9955
9956	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
9957	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
9958}
9959
9960static void
9961bwn_phy_lock(struct bwn_mac *mac)
9962{
9963	struct bwn_softc *sc = mac->mac_sc;
9964	struct ieee80211com *ic = &sc->sc_ic;
9965
9966	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9967	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9968
9969	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9970		bwn_psctl(mac, BWN_PS_AWAKE);
9971}
9972
9973static void
9974bwn_phy_unlock(struct bwn_mac *mac)
9975{
9976	struct bwn_softc *sc = mac->mac_sc;
9977	struct ieee80211com *ic = &sc->sc_ic;
9978
9979	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9980	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9981
9982	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9983		bwn_psctl(mac, 0);
9984}
9985
9986static void
9987bwn_rf_lock(struct bwn_mac *mac)
9988{
9989
9990	BWN_WRITE_4(mac, BWN_MACCTL,
9991	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
9992	BWN_READ_4(mac, BWN_MACCTL);
9993	DELAY(10);
9994}
9995
9996static void
9997bwn_rf_unlock(struct bwn_mac *mac)
9998{
9999
10000	BWN_READ_2(mac, BWN_PHYVER);
10001	BWN_WRITE_4(mac, BWN_MACCTL,
10002	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10003}
10004
10005static struct bwn_pio_txqueue *
10006bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10007    struct bwn_pio_txpkt **pack)
10008{
10009	struct bwn_pio *pio = &mac->mac_method.pio;
10010	struct bwn_pio_txqueue *tq = NULL;
10011	unsigned int index;
10012
10013	switch (cookie & 0xf000) {
10014	case 0x1000:
10015		tq = &pio->wme[WME_AC_BK];
10016		break;
10017	case 0x2000:
10018		tq = &pio->wme[WME_AC_BE];
10019		break;
10020	case 0x3000:
10021		tq = &pio->wme[WME_AC_VI];
10022		break;
10023	case 0x4000:
10024		tq = &pio->wme[WME_AC_VO];
10025		break;
10026	case 0x5000:
10027		tq = &pio->mcast;
10028		break;
10029	}
10030	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10031	if (tq == NULL)
10032		return (NULL);
10033	index = (cookie & 0x0fff);
10034	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10035	if (index >= N(tq->tq_pkts))
10036		return (NULL);
10037	*pack = &tq->tq_pkts[index];
10038	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10039	return (tq);
10040}
10041
10042static void
10043bwn_txpwr(void *arg, int npending)
10044{
10045	struct bwn_mac *mac = arg;
10046	struct bwn_softc *sc = mac->mac_sc;
10047
10048	BWN_LOCK(sc);
10049	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10050	    mac->mac_phy.set_txpwr != NULL)
10051		mac->mac_phy.set_txpwr(mac);
10052	BWN_UNLOCK(sc);
10053}
10054
10055static void
10056bwn_task_15s(struct bwn_mac *mac)
10057{
10058	uint16_t reg;
10059
10060	if (mac->mac_fw.opensource) {
10061		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10062		if (reg) {
10063			bwn_restart(mac, "fw watchdog");
10064			return;
10065		}
10066		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10067	}
10068	if (mac->mac_phy.task_15s)
10069		mac->mac_phy.task_15s(mac);
10070
10071	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10072}
10073
10074static void
10075bwn_task_30s(struct bwn_mac *mac)
10076{
10077
10078	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10079		return;
10080	mac->mac_noise.noi_running = 1;
10081	mac->mac_noise.noi_nsamples = 0;
10082
10083	bwn_noise_gensample(mac);
10084}
10085
10086static void
10087bwn_task_60s(struct bwn_mac *mac)
10088{
10089
10090	if (mac->mac_phy.task_60s)
10091		mac->mac_phy.task_60s(mac);
10092	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10093}
10094
10095static void
10096bwn_tasks(void *arg)
10097{
10098	struct bwn_mac *mac = arg;
10099	struct bwn_softc *sc = mac->mac_sc;
10100
10101	BWN_ASSERT_LOCKED(sc);
10102	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10103		return;
10104
10105	if (mac->mac_task_state % 4 == 0)
10106		bwn_task_60s(mac);
10107	if (mac->mac_task_state % 2 == 0)
10108		bwn_task_30s(mac);
10109	bwn_task_15s(mac);
10110
10111	mac->mac_task_state++;
10112	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10113}
10114
10115static int
10116bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10117{
10118	struct bwn_softc *sc = mac->mac_sc;
10119
10120	KASSERT(a == 0, ("not support APHY\n"));
10121
10122	switch (plcp->o.raw[0] & 0xf) {
10123	case 0xb:
10124		return (BWN_OFDM_RATE_6MB);
10125	case 0xf:
10126		return (BWN_OFDM_RATE_9MB);
10127	case 0xa:
10128		return (BWN_OFDM_RATE_12MB);
10129	case 0xe:
10130		return (BWN_OFDM_RATE_18MB);
10131	case 0x9:
10132		return (BWN_OFDM_RATE_24MB);
10133	case 0xd:
10134		return (BWN_OFDM_RATE_36MB);
10135	case 0x8:
10136		return (BWN_OFDM_RATE_48MB);
10137	case 0xc:
10138		return (BWN_OFDM_RATE_54MB);
10139	}
10140	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10141	    plcp->o.raw[0] & 0xf);
10142	return (-1);
10143}
10144
10145static int
10146bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10147{
10148	struct bwn_softc *sc = mac->mac_sc;
10149
10150	switch (plcp->o.raw[0]) {
10151	case 0x0a:
10152		return (BWN_CCK_RATE_1MB);
10153	case 0x14:
10154		return (BWN_CCK_RATE_2MB);
10155	case 0x37:
10156		return (BWN_CCK_RATE_5MB);
10157	case 0x6e:
10158		return (BWN_CCK_RATE_11MB);
10159	}
10160	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10161	return (-1);
10162}
10163
10164static void
10165bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10166    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10167    int rssi, int noise)
10168{
10169	struct bwn_softc *sc = mac->mac_sc;
10170	const struct ieee80211_frame_min *wh;
10171	uint64_t tsf;
10172	uint16_t low_mactime_now;
10173
10174	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10175		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10176
10177	wh = mtod(m, const struct ieee80211_frame_min *);
10178	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
10179		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10180
10181	bwn_tsf_read(mac, &tsf);
10182	low_mactime_now = tsf;
10183	tsf = tsf & ~0xffffULL;
10184	tsf += le16toh(rxhdr->mac_time);
10185	if (low_mactime_now < le16toh(rxhdr->mac_time))
10186		tsf -= 0x10000;
10187
10188	sc->sc_rx_th.wr_tsf = tsf;
10189	sc->sc_rx_th.wr_rate = rate;
10190	sc->sc_rx_th.wr_antsignal = rssi;
10191	sc->sc_rx_th.wr_antnoise = noise;
10192}
10193
10194static void
10195bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10196{
10197	uint32_t low, high;
10198
10199	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10200	    ("%s:%d: fail", __func__, __LINE__));
10201
10202	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10203	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10204	*tsf = high;
10205	*tsf <<= 32;
10206	*tsf |= low;
10207}
10208
10209static int
10210bwn_dma_attach(struct bwn_mac *mac)
10211{
10212	struct bwn_dma *dma = &mac->mac_method.dma;
10213	struct bwn_softc *sc = mac->mac_sc;
10214	bus_addr_t lowaddr = 0;
10215	int error;
10216
10217	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10218		return (0);
10219
10220	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10221
10222	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10223
10224	dma->dmatype = bwn_dma_gettype(mac);
10225	if (dma->dmatype == BWN_DMA_30BIT)
10226		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10227	else if (dma->dmatype == BWN_DMA_32BIT)
10228		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10229	else
10230		lowaddr = BUS_SPACE_MAXADDR;
10231
10232	/*
10233	 * Create top level DMA tag
10234	 */
10235	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10236			       BWN_ALIGN, 0,		/* alignment, bounds */
10237			       lowaddr,			/* lowaddr */
10238			       BUS_SPACE_MAXADDR,	/* highaddr */
10239			       NULL, NULL,		/* filter, filterarg */
10240			       BUS_SPACE_MAXSIZE,	/* maxsize */
10241			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10242			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10243			       0,			/* flags */
10244			       NULL, NULL,		/* lockfunc, lockarg */
10245			       &dma->parent_dtag);
10246	if (error) {
10247		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10248		return (error);
10249	}
10250
10251	/*
10252	 * Create TX/RX mbuf DMA tag
10253	 */
10254	error = bus_dma_tag_create(dma->parent_dtag,
10255				1,
10256				0,
10257				BUS_SPACE_MAXADDR,
10258				BUS_SPACE_MAXADDR,
10259				NULL, NULL,
10260				MCLBYTES,
10261				1,
10262				BUS_SPACE_MAXSIZE_32BIT,
10263				0,
10264				NULL, NULL,
10265				&dma->rxbuf_dtag);
10266	if (error) {
10267		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10268		goto fail0;
10269	}
10270	error = bus_dma_tag_create(dma->parent_dtag,
10271				1,
10272				0,
10273				BUS_SPACE_MAXADDR,
10274				BUS_SPACE_MAXADDR,
10275				NULL, NULL,
10276				MCLBYTES,
10277				1,
10278				BUS_SPACE_MAXSIZE_32BIT,
10279				0,
10280				NULL, NULL,
10281				&dma->txbuf_dtag);
10282	if (error) {
10283		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10284		goto fail1;
10285	}
10286
10287	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10288	if (!dma->wme[WME_AC_BK])
10289		goto fail2;
10290
10291	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10292	if (!dma->wme[WME_AC_BE])
10293		goto fail3;
10294
10295	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10296	if (!dma->wme[WME_AC_VI])
10297		goto fail4;
10298
10299	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10300	if (!dma->wme[WME_AC_VO])
10301		goto fail5;
10302
10303	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10304	if (!dma->mcast)
10305		goto fail6;
10306	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10307	if (!dma->rx)
10308		goto fail7;
10309
10310	return (error);
10311
10312fail7:	bwn_dma_ringfree(&dma->mcast);
10313fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10314fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10315fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10316fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10317fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10318fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10319fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10320	return (error);
10321}
10322
10323static struct bwn_dma_ring *
10324bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10325    uint16_t cookie, int *slot)
10326{
10327	struct bwn_dma *dma = &mac->mac_method.dma;
10328	struct bwn_dma_ring *dr;
10329	struct bwn_softc *sc = mac->mac_sc;
10330
10331	BWN_ASSERT_LOCKED(mac->mac_sc);
10332
10333	switch (cookie & 0xf000) {
10334	case 0x1000:
10335		dr = dma->wme[WME_AC_BK];
10336		break;
10337	case 0x2000:
10338		dr = dma->wme[WME_AC_BE];
10339		break;
10340	case 0x3000:
10341		dr = dma->wme[WME_AC_VI];
10342		break;
10343	case 0x4000:
10344		dr = dma->wme[WME_AC_VO];
10345		break;
10346	case 0x5000:
10347		dr = dma->mcast;
10348		break;
10349	default:
10350		dr = NULL;
10351		KASSERT(0 == 1,
10352		    ("invalid cookie value %d", cookie & 0xf000));
10353	}
10354	*slot = (cookie & 0x0fff);
10355	if (*slot < 0 || *slot >= dr->dr_numslots) {
10356		/*
10357		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10358		 * that it occurs events which have same H/W sequence numbers.
10359		 * When it's occurred just prints a WARNING msgs and ignores.
10360		 */
10361		KASSERT(status->seq == dma->lastseq,
10362		    ("%s:%d: fail", __func__, __LINE__));
10363		device_printf(sc->sc_dev,
10364		    "out of slot ranges (0 < %d < %d)\n", *slot,
10365		    dr->dr_numslots);
10366		return (NULL);
10367	}
10368	dma->lastseq = status->seq;
10369	return (dr);
10370}
10371
10372static void
10373bwn_dma_stop(struct bwn_mac *mac)
10374{
10375	struct bwn_dma *dma;
10376
10377	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10378		return;
10379	dma = &mac->mac_method.dma;
10380
10381	bwn_dma_ringstop(&dma->rx);
10382	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10383	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10384	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10385	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10386	bwn_dma_ringstop(&dma->mcast);
10387}
10388
10389static void
10390bwn_dma_ringstop(struct bwn_dma_ring **dr)
10391{
10392
10393	if (dr == NULL)
10394		return;
10395
10396	bwn_dma_cleanup(*dr);
10397}
10398
10399static void
10400bwn_pio_stop(struct bwn_mac *mac)
10401{
10402	struct bwn_pio *pio;
10403
10404	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10405		return;
10406	pio = &mac->mac_method.pio;
10407
10408	bwn_destroy_queue_tx(&pio->mcast);
10409	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10410	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10411	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10412	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10413}
10414
10415static void
10416bwn_led_attach(struct bwn_mac *mac)
10417{
10418	struct bwn_softc *sc = mac->mac_sc;
10419	const uint8_t *led_act = NULL;
10420	uint16_t val[BWN_LED_MAX];
10421	int i;
10422
10423	sc->sc_led_idle = (2350 * hz) / 1000;
10424	sc->sc_led_blink = 1;
10425
10426	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10427		if (siba_get_pci_subvendor(sc->sc_dev) ==
10428		    bwn_vendor_led_act[i].vid) {
10429			led_act = bwn_vendor_led_act[i].led_act;
10430			break;
10431		}
10432	}
10433	if (led_act == NULL)
10434		led_act = bwn_default_led_act;
10435
10436	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10437	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10438	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10439	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10440
10441	for (i = 0; i < BWN_LED_MAX; ++i) {
10442		struct bwn_led *led = &sc->sc_leds[i];
10443
10444		if (val[i] == 0xff) {
10445			led->led_act = led_act[i];
10446		} else {
10447			if (val[i] & BWN_LED_ACT_LOW)
10448				led->led_flags |= BWN_LED_F_ACTLOW;
10449			led->led_act = val[i] & BWN_LED_ACT_MASK;
10450		}
10451		led->led_mask = (1 << i);
10452
10453		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10454		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10455		    led->led_act == BWN_LED_ACT_BLINK) {
10456			led->led_flags |= BWN_LED_F_BLINK;
10457			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10458				led->led_flags |= BWN_LED_F_POLLABLE;
10459			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10460				led->led_flags |= BWN_LED_F_SLOW;
10461
10462			if (sc->sc_blink_led == NULL) {
10463				sc->sc_blink_led = led;
10464				if (led->led_flags & BWN_LED_F_SLOW)
10465					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10466			}
10467		}
10468
10469		DPRINTF(sc, BWN_DEBUG_LED,
10470		    "%dth led, act %d, lowact %d\n", i,
10471		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10472	}
10473	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10474}
10475
10476static __inline uint16_t
10477bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10478{
10479
10480	if (led->led_flags & BWN_LED_F_ACTLOW)
10481		on = !on;
10482	if (on)
10483		val |= led->led_mask;
10484	else
10485		val &= ~led->led_mask;
10486	return val;
10487}
10488
10489static void
10490bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10491{
10492	struct bwn_softc *sc = mac->mac_sc;
10493	struct ieee80211com *ic = &sc->sc_ic;
10494	uint16_t val;
10495	int i;
10496
10497	if (nstate == IEEE80211_S_INIT) {
10498		callout_stop(&sc->sc_led_blink_ch);
10499		sc->sc_led_blinking = 0;
10500	}
10501
10502	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
10503		return;
10504
10505	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10506	for (i = 0; i < BWN_LED_MAX; ++i) {
10507		struct bwn_led *led = &sc->sc_leds[i];
10508		int on;
10509
10510		if (led->led_act == BWN_LED_ACT_UNKN ||
10511		    led->led_act == BWN_LED_ACT_NULL)
10512			continue;
10513
10514		if ((led->led_flags & BWN_LED_F_BLINK) &&
10515		    nstate != IEEE80211_S_INIT)
10516			continue;
10517
10518		switch (led->led_act) {
10519		case BWN_LED_ACT_ON:    /* Always on */
10520			on = 1;
10521			break;
10522		case BWN_LED_ACT_OFF:   /* Always off */
10523		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10524			on = 0;
10525			break;
10526		default:
10527			on = 1;
10528			switch (nstate) {
10529			case IEEE80211_S_INIT:
10530				on = 0;
10531				break;
10532			case IEEE80211_S_RUN:
10533				if (led->led_act == BWN_LED_ACT_11G &&
10534				    ic->ic_curmode != IEEE80211_MODE_11G)
10535					on = 0;
10536				break;
10537			default:
10538				if (led->led_act == BWN_LED_ACT_ASSOC)
10539					on = 0;
10540				break;
10541			}
10542			break;
10543		}
10544
10545		val = bwn_led_onoff(led, val, on);
10546	}
10547	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10548}
10549
10550static void
10551bwn_led_event(struct bwn_mac *mac, int event)
10552{
10553	struct bwn_softc *sc = mac->mac_sc;
10554	struct bwn_led *led = sc->sc_blink_led;
10555	int rate;
10556
10557	if (event == BWN_LED_EVENT_POLL) {
10558		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10559			return;
10560		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10561			return;
10562	}
10563
10564	sc->sc_led_ticks = ticks;
10565	if (sc->sc_led_blinking)
10566		return;
10567
10568	switch (event) {
10569	case BWN_LED_EVENT_RX:
10570		rate = sc->sc_rx_rate;
10571		break;
10572	case BWN_LED_EVENT_TX:
10573		rate = sc->sc_tx_rate;
10574		break;
10575	case BWN_LED_EVENT_POLL:
10576		rate = 0;
10577		break;
10578	default:
10579		panic("unknown LED event %d\n", event);
10580		break;
10581	}
10582	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10583	    bwn_led_duration[rate].off_dur);
10584}
10585
10586static void
10587bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10588{
10589	struct bwn_softc *sc = mac->mac_sc;
10590	struct bwn_led *led = sc->sc_blink_led;
10591	uint16_t val;
10592
10593	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10594	val = bwn_led_onoff(led, val, 1);
10595	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10596
10597	if (led->led_flags & BWN_LED_F_SLOW) {
10598		BWN_LED_SLOWDOWN(on_dur);
10599		BWN_LED_SLOWDOWN(off_dur);
10600	}
10601
10602	sc->sc_led_blinking = 1;
10603	sc->sc_led_blink_offdur = off_dur;
10604
10605	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10606}
10607
10608static void
10609bwn_led_blink_next(void *arg)
10610{
10611	struct bwn_mac *mac = arg;
10612	struct bwn_softc *sc = mac->mac_sc;
10613	uint16_t val;
10614
10615	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10616	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10617	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10618
10619	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10620	    bwn_led_blink_end, mac);
10621}
10622
10623static void
10624bwn_led_blink_end(void *arg)
10625{
10626	struct bwn_mac *mac = arg;
10627	struct bwn_softc *sc = mac->mac_sc;
10628
10629	sc->sc_led_blinking = 0;
10630}
10631
10632static int
10633bwn_suspend(device_t dev)
10634{
10635	struct bwn_softc *sc = device_get_softc(dev);
10636
10637	BWN_LOCK(sc);
10638	bwn_stop(sc);
10639	BWN_UNLOCK(sc);
10640	return (0);
10641}
10642
10643static int
10644bwn_resume(device_t dev)
10645{
10646	struct bwn_softc *sc = device_get_softc(dev);
10647	int error = EDOOFUS;
10648
10649	BWN_LOCK(sc);
10650	if (sc->sc_ic.ic_nrunning > 0)
10651		error = bwn_init(sc);
10652	BWN_UNLOCK(sc);
10653	if (error == 0)
10654		ieee80211_start_all(&sc->sc_ic);
10655	return (0);
10656}
10657
10658static void
10659bwn_rfswitch(void *arg)
10660{
10661	struct bwn_softc *sc = arg;
10662	struct bwn_mac *mac = sc->sc_curmac;
10663	int cur = 0, prev = 0;
10664
10665	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10666	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10667
10668	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10669		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10670			& BWN_RF_HWENABLED_HI_MASK))
10671			cur = 1;
10672	} else {
10673		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10674		    & BWN_RF_HWENABLED_LO_MASK)
10675			cur = 1;
10676	}
10677
10678	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10679		prev = 1;
10680
10681	if (cur != prev) {
10682		if (cur)
10683			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10684		else
10685			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10686
10687		device_printf(sc->sc_dev,
10688		    "status of RF switch is changed to %s\n",
10689		    cur ? "ON" : "OFF");
10690		if (cur != mac->mac_phy.rf_on) {
10691			if (cur)
10692				bwn_rf_turnon(mac);
10693			else
10694				bwn_rf_turnoff(mac);
10695		}
10696	}
10697
10698	callout_schedule(&sc->sc_rfswitch_ch, hz);
10699}
10700
10701static void
10702bwn_phy_lp_init_pre(struct bwn_mac *mac)
10703{
10704	struct bwn_phy *phy = &mac->mac_phy;
10705	struct bwn_phy_lp *plp = &phy->phy_lp;
10706
10707	plp->plp_antenna = BWN_ANT_DEFAULT;
10708}
10709
10710static int
10711bwn_phy_lp_init(struct bwn_mac *mac)
10712{
10713	static const struct bwn_stxtable tables[] = {
10714		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10715		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10716		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10717		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10718		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10719		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10720		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10721		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10722		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10723		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10724		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10725		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10726		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10727		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10728		{ 2, 11, 0x40, 0, 0x0f }
10729	};
10730	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10731	struct bwn_softc *sc = mac->mac_sc;
10732	const struct bwn_stxtable *st;
10733	struct ieee80211com *ic = &sc->sc_ic;
10734	int i, error;
10735	uint16_t tmp;
10736
10737	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10738	bwn_phy_lp_bbinit(mac);
10739
10740	/* initialize RF */
10741	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10742	DELAY(1);
10743	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10744	DELAY(1);
10745
10746	if (mac->mac_phy.rf_ver == 0x2062)
10747		bwn_phy_lp_b2062_init(mac);
10748	else {
10749		bwn_phy_lp_b2063_init(mac);
10750
10751		/* synchronize stx table. */
10752		for (i = 0; i < N(tables); i++) {
10753			st = &tables[i];
10754			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10755			tmp >>= st->st_rfshift;
10756			tmp <<= st->st_physhift;
10757			BWN_PHY_SETMASK(mac,
10758			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10759			    ~(st->st_mask << st->st_physhift), tmp);
10760		}
10761
10762		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10763		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10764	}
10765
10766	/* calibrate RC */
10767	if (mac->mac_phy.rev >= 2)
10768		bwn_phy_lp_rxcal_r2(mac);
10769	else if (!plp->plp_rccap) {
10770		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10771			bwn_phy_lp_rccal_r12(mac);
10772	} else
10773		bwn_phy_lp_set_rccap(mac);
10774
10775	error = bwn_phy_lp_switch_channel(mac, 7);
10776	if (error)
10777		device_printf(sc->sc_dev,
10778		    "failed to change channel 7 (%d)\n", error);
10779	bwn_phy_lp_txpctl_init(mac);
10780	bwn_phy_lp_calib(mac);
10781	return (0);
10782}
10783
10784static uint16_t
10785bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10786{
10787
10788	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10789	return (BWN_READ_2(mac, BWN_PHYDATA));
10790}
10791
10792static void
10793bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10794{
10795
10796	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10797	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10798}
10799
10800static void
10801bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10802    uint16_t set)
10803{
10804
10805	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10806	BWN_WRITE_2(mac, BWN_PHYDATA,
10807	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10808}
10809
10810static uint16_t
10811bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10812{
10813
10814	KASSERT(reg != 1, ("unaccessible register %d", reg));
10815	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10816		reg |= 0x100;
10817	if (mac->mac_phy.rev >= 2)
10818		reg |= 0x200;
10819	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10820	return BWN_READ_2(mac, BWN_RFDATALO);
10821}
10822
10823static void
10824bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10825{
10826
10827	KASSERT(reg != 1, ("unaccessible register %d", reg));
10828	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10829	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10830}
10831
10832static void
10833bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10834{
10835
10836	if (on) {
10837		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10838		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10839		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10840		return;
10841	}
10842
10843	if (mac->mac_phy.rev >= 2) {
10844		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10845		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10846		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10847		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10848		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10849		return;
10850	}
10851
10852	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10853	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10854	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10855	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10856}
10857
10858static int
10859bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10860{
10861	struct bwn_phy *phy = &mac->mac_phy;
10862	struct bwn_phy_lp *plp = &phy->phy_lp;
10863	int error;
10864
10865	if (phy->rf_ver == 0x2063) {
10866		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
10867		if (error)
10868			return (error);
10869	} else {
10870		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
10871		if (error)
10872			return (error);
10873		bwn_phy_lp_set_anafilter(mac, chan);
10874		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
10875	}
10876
10877	plp->plp_chan = chan;
10878	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
10879	return (0);
10880}
10881
10882static uint32_t
10883bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
10884{
10885	struct bwn_softc *sc = mac->mac_sc;
10886	struct ieee80211com *ic = &sc->sc_ic;
10887
10888	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
10889}
10890
10891static void
10892bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
10893{
10894	struct bwn_phy *phy = &mac->mac_phy;
10895	struct bwn_phy_lp *plp = &phy->phy_lp;
10896
10897	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
10898		return;
10899
10900	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
10901	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
10902	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
10903	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
10904	plp->plp_antenna = antenna;
10905}
10906
10907static void
10908bwn_phy_lp_task_60s(struct bwn_mac *mac)
10909{
10910
10911	bwn_phy_lp_calib(mac);
10912}
10913
10914static void
10915bwn_phy_lp_readsprom(struct bwn_mac *mac)
10916{
10917	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10918	struct bwn_softc *sc = mac->mac_sc;
10919	struct ieee80211com *ic = &sc->sc_ic;
10920
10921	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
10922		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
10923		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
10924		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
10925		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
10926		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
10927		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
10928		return;
10929	}
10930
10931	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
10932	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
10933	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
10934	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
10935	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
10936	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
10937	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
10938	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
10939}
10940
10941static void
10942bwn_phy_lp_bbinit(struct bwn_mac *mac)
10943{
10944
10945	bwn_phy_lp_tblinit(mac);
10946	if (mac->mac_phy.rev >= 2)
10947		bwn_phy_lp_bbinit_r2(mac);
10948	else
10949		bwn_phy_lp_bbinit_r01(mac);
10950}
10951
10952static void
10953bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
10954{
10955	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
10956	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
10957	struct bwn_softc *sc = mac->mac_sc;
10958	struct ieee80211com *ic = &sc->sc_ic;
10959
10960	bwn_phy_lp_set_txgain(mac,
10961	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
10962	bwn_phy_lp_set_bbmult(mac, 150);
10963}
10964
10965static void
10966bwn_phy_lp_calib(struct bwn_mac *mac)
10967{
10968	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10969	struct bwn_softc *sc = mac->mac_sc;
10970	struct ieee80211com *ic = &sc->sc_ic;
10971	const struct bwn_rxcompco *rc = NULL;
10972	struct bwn_txgain ogain;
10973	int i, omode, oafeovr, orf, obbmult;
10974	uint8_t mode, fc = 0;
10975
10976	if (plp->plp_chanfullcal != plp->plp_chan) {
10977		plp->plp_chanfullcal = plp->plp_chan;
10978		fc = 1;
10979	}
10980
10981	bwn_mac_suspend(mac);
10982
10983	/* BlueTooth Coexistance Override */
10984	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
10985	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
10986
10987	if (mac->mac_phy.rev >= 2)
10988		bwn_phy_lp_digflt_save(mac);
10989	bwn_phy_lp_get_txpctlmode(mac);
10990	mode = plp->plp_txpctlmode;
10991	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
10992	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
10993		bwn_phy_lp_bugfix(mac);
10994	if (mac->mac_phy.rev >= 2 && fc == 1) {
10995		bwn_phy_lp_get_txpctlmode(mac);
10996		omode = plp->plp_txpctlmode;
10997		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
10998		if (oafeovr)
10999			ogain = bwn_phy_lp_get_txgain(mac);
11000		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11001		obbmult = bwn_phy_lp_get_bbmult(mac);
11002		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11003		if (oafeovr)
11004			bwn_phy_lp_set_txgain(mac, &ogain);
11005		bwn_phy_lp_set_bbmult(mac, obbmult);
11006		bwn_phy_lp_set_txpctlmode(mac, omode);
11007		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11008	}
11009	bwn_phy_lp_set_txpctlmode(mac, mode);
11010	if (mac->mac_phy.rev >= 2)
11011		bwn_phy_lp_digflt_restore(mac);
11012
11013	/* do RX IQ Calculation; assumes that noise is true. */
11014	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11015		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11016			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11017				rc = &bwn_rxcompco_5354[i];
11018		}
11019	} else if (mac->mac_phy.rev >= 2)
11020		rc = &bwn_rxcompco_r2;
11021	else {
11022		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11023			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11024				rc = &bwn_rxcompco_r12[i];
11025		}
11026	}
11027	if (rc == NULL)
11028		goto fail;
11029
11030	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11031	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11032
11033	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11034
11035	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11036		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11037		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11038	} else {
11039		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11040		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11041	}
11042
11043	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11044	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11045	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11046	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11047	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11048	bwn_phy_lp_set_deaf(mac, 0);
11049	/* XXX no checking return value? */
11050	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11051	bwn_phy_lp_clear_deaf(mac, 0);
11052	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11053	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11054	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11055
11056	/* disable RX GAIN override. */
11057	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11058	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11059	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11060	if (mac->mac_phy.rev >= 2) {
11061		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11062		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11063			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11064			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11065		}
11066	} else {
11067		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11068	}
11069
11070	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11071	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11072fail:
11073	bwn_mac_enable(mac);
11074}
11075
11076static void
11077bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11078{
11079
11080	if (on) {
11081		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11082		return;
11083	}
11084
11085	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11086	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11087}
11088
11089static int
11090bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11091{
11092	static const struct bwn_b206x_chan *bc = NULL;
11093	struct bwn_softc *sc = mac->mac_sc;
11094	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11095	    tmp[6];
11096	uint16_t old, scale, tmp16;
11097	int i, div;
11098
11099	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11100		if (bwn_b2063_chantable[i].bc_chan == chan) {
11101			bc = &bwn_b2063_chantable[i];
11102			break;
11103		}
11104	}
11105	if (bc == NULL)
11106		return (EINVAL);
11107
11108	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11109	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11110	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11111	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11112	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11113	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11114	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11115	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11116	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11117	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11118	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11119	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11120
11121	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11122	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11123
11124	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11125	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11126	freqref = freqxtal * 3;
11127	div = (freqxtal <= 26000000 ? 1 : 2);
11128	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11129	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11130		999999) / 1000000) + 1;
11131
11132	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11133	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11134	    0xfff8, timeout >> 2);
11135	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11136	    0xff9f,timeout << 5);
11137	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11138
11139	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11140	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11141	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11142
11143	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11144	    (timeoutref + 1)) - 1;
11145	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11146	    0xf0, count >> 8);
11147	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11148
11149	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11150	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11151	while (tmp[1] >= freqref) {
11152		tmp[0]++;
11153		tmp[1] -= freqref;
11154	}
11155	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11156	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11157	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11158	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11159	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11160
11161	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11162	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11163	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11164	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11165
11166	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11167	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11168
11169	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11170		scale = 1;
11171		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11172	} else {
11173		scale = 0;
11174		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11175	}
11176	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11177	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11178
11179	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11180	    (scale + 1);
11181	if (tmp[5] > 150)
11182		tmp[5] = 0;
11183
11184	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11185	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11186
11187	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11188	if (freqxtal > 26000000)
11189		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11190	else
11191		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11192
11193	if (val[0] == 45)
11194		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11195	else
11196		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11197
11198	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11199	DELAY(1);
11200	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11201
11202	/* VCO Calibration */
11203	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11204	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11205	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11206	DELAY(1);
11207	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11208	DELAY(1);
11209	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11210	DELAY(1);
11211	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11212	DELAY(300);
11213	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11214
11215	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11216	return (0);
11217}
11218
11219static int
11220bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11221{
11222	struct bwn_softc *sc = mac->mac_sc;
11223	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11224	const struct bwn_b206x_chan *bc = NULL;
11225	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11226	uint32_t tmp[9];
11227	int i;
11228
11229	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11230		if (bwn_b2062_chantable[i].bc_chan == chan) {
11231			bc = &bwn_b2062_chantable[i];
11232			break;
11233		}
11234	}
11235
11236	if (bc == NULL)
11237		return (EINVAL);
11238
11239	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11240	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11241	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11242	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11243	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11244	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11245	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11246	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11247	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11248	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11249
11250	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11251	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11252	bwn_phy_lp_b2062_reset_pllbias(mac);
11253	tmp[0] = freqxtal / 1000;
11254	tmp[1] = plp->plp_div * 1000;
11255	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11256	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11257		tmp[2] *= 2;
11258	tmp[3] = 48 * tmp[0];
11259	tmp[5] = tmp[2] / tmp[3];
11260	tmp[6] = tmp[2] % tmp[3];
11261	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11262	tmp[4] = tmp[6] * 0x100;
11263	tmp[5] = tmp[4] / tmp[3];
11264	tmp[6] = tmp[4] % tmp[3];
11265	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11266	tmp[4] = tmp[6] * 0x100;
11267	tmp[5] = tmp[4] / tmp[3];
11268	tmp[6] = tmp[4] % tmp[3];
11269	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11270	tmp[4] = tmp[6] * 0x100;
11271	tmp[5] = tmp[4] / tmp[3];
11272	tmp[6] = tmp[4] % tmp[3];
11273	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11274	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11275	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11276	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11277	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11278	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11279
11280	bwn_phy_lp_b2062_vco_calib(mac);
11281	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11282		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11283		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11284		bwn_phy_lp_b2062_reset_pllbias(mac);
11285		bwn_phy_lp_b2062_vco_calib(mac);
11286		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11287			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11288			return (EIO);
11289		}
11290	}
11291	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11292	return (0);
11293}
11294
11295static void
11296bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11297{
11298	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11299	uint16_t tmp = (channel == 14);
11300
11301	if (mac->mac_phy.rev < 2) {
11302		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11303		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11304			bwn_phy_lp_set_rccap(mac);
11305		return;
11306	}
11307
11308	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11309}
11310
11311static void
11312bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11313{
11314	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11315	struct bwn_softc *sc = mac->mac_sc;
11316	struct ieee80211com *ic = &sc->sc_ic;
11317	uint16_t iso, tmp[3];
11318
11319	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11320
11321	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11322		iso = plp->plp_txisoband_m;
11323	else if (freq <= 5320)
11324		iso = plp->plp_txisoband_l;
11325	else if (freq <= 5700)
11326		iso = plp->plp_txisoband_m;
11327	else
11328		iso = plp->plp_txisoband_h;
11329
11330	tmp[0] = ((iso - 26) / 12) << 12;
11331	tmp[1] = tmp[0] + 0x1000;
11332	tmp[2] = tmp[0] + 0x2000;
11333
11334	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11335	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11336}
11337
11338static void
11339bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11340{
11341	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11342	int i;
11343	static const uint16_t addr[] = {
11344		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11345		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11346		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11347		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11348		BWN_PHY_OFDM(0xcf),
11349	};
11350	static const uint16_t val[] = {
11351		0xde5e, 0xe832, 0xe331, 0x4d26,
11352		0x0026, 0x1420, 0x0020, 0xfe08,
11353		0x0008,
11354	};
11355
11356	for (i = 0; i < N(addr); i++) {
11357		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11358		BWN_PHY_WRITE(mac, addr[i], val[i]);
11359	}
11360}
11361
11362static void
11363bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11364{
11365	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11366	struct bwn_softc *sc = mac->mac_sc;
11367	uint16_t ctl;
11368
11369	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11370	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11371	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11372		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11373		break;
11374	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11375		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11376		break;
11377	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11378		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11379		break;
11380	default:
11381		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11382		device_printf(sc->sc_dev, "unknown command mode\n");
11383		break;
11384	}
11385}
11386
11387static void
11388bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11389{
11390	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11391	uint16_t ctl;
11392	uint8_t old;
11393
11394	bwn_phy_lp_get_txpctlmode(mac);
11395	old = plp->plp_txpctlmode;
11396	if (old == mode)
11397		return;
11398	plp->plp_txpctlmode = mode;
11399
11400	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11401		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11402		    plp->plp_tssiidx);
11403		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11404		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11405
11406		/* disable TX GAIN override */
11407		if (mac->mac_phy.rev < 2)
11408			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11409		else {
11410			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11411			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11412		}
11413		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11414
11415		plp->plp_txpwridx = -1;
11416	}
11417	if (mac->mac_phy.rev >= 2) {
11418		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11419			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11420		else
11421			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11422	}
11423
11424	/* writes TX Power Control mode */
11425	switch (plp->plp_txpctlmode) {
11426	case BWN_PHYLP_TXPCTL_OFF:
11427		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11428		break;
11429	case BWN_PHYLP_TXPCTL_ON_HW:
11430		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11431		break;
11432	case BWN_PHYLP_TXPCTL_ON_SW:
11433		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11434		break;
11435	default:
11436		ctl = 0;
11437		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11438	}
11439	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11440	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11441}
11442
11443static void
11444bwn_phy_lp_bugfix(struct bwn_mac *mac)
11445{
11446	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11447	struct bwn_softc *sc = mac->mac_sc;
11448	const unsigned int size = 256;
11449	struct bwn_txgain tg;
11450	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11451	uint16_t tssinpt, tssiidx, value[2];
11452	uint8_t mode;
11453	int8_t txpwridx;
11454
11455	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11456	    M_NOWAIT | M_ZERO);
11457	if (tabs == NULL) {
11458		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11459		return;
11460	}
11461
11462	bwn_phy_lp_get_txpctlmode(mac);
11463	mode = plp->plp_txpctlmode;
11464	txpwridx = plp->plp_txpwridx;
11465	tssinpt = plp->plp_tssinpt;
11466	tssiidx = plp->plp_tssiidx;
11467
11468	bwn_tab_read_multi(mac,
11469	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11470	    BWN_TAB_4(7, 0x140), size, tabs);
11471
11472	bwn_phy_lp_tblinit(mac);
11473	bwn_phy_lp_bbinit(mac);
11474	bwn_phy_lp_txpctl_init(mac);
11475	bwn_phy_lp_rf_onoff(mac, 1);
11476	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11477
11478	bwn_tab_write_multi(mac,
11479	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11480	    BWN_TAB_4(7, 0x140), size, tabs);
11481
11482	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11483	plp->plp_tssinpt = tssinpt;
11484	plp->plp_tssiidx = tssiidx;
11485	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11486	if (txpwridx != -1) {
11487		/* set TX power by index */
11488		plp->plp_txpwridx = txpwridx;
11489		bwn_phy_lp_get_txpctlmode(mac);
11490		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11491			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11492		if (mac->mac_phy.rev >= 2) {
11493			rxcomp = bwn_tab_read(mac,
11494			    BWN_TAB_4(7, txpwridx + 320));
11495			txgain = bwn_tab_read(mac,
11496			    BWN_TAB_4(7, txpwridx + 192));
11497			tg.tg_pad = (txgain >> 16) & 0xff;
11498			tg.tg_gm = txgain & 0xff;
11499			tg.tg_pga = (txgain >> 8) & 0xff;
11500			tg.tg_dac = (rxcomp >> 28) & 0xff;
11501			bwn_phy_lp_set_txgain(mac, &tg);
11502		} else {
11503			rxcomp = bwn_tab_read(mac,
11504			    BWN_TAB_4(10, txpwridx + 320));
11505			txgain = bwn_tab_read(mac,
11506			    BWN_TAB_4(10, txpwridx + 192));
11507			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11508			    0xf800, (txgain >> 4) & 0x7fff);
11509			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11510			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11511		}
11512		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11513
11514		/* set TX IQCC */
11515		value[0] = (rxcomp >> 10) & 0x3ff;
11516		value[1] = rxcomp & 0x3ff;
11517		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11518
11519		coeff = bwn_tab_read(mac,
11520		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11521		    BWN_TAB_4(10, txpwridx + 448));
11522		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11523		if (mac->mac_phy.rev >= 2) {
11524			rfpwr = bwn_tab_read(mac,
11525			    BWN_TAB_4(7, txpwridx + 576));
11526			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11527			    rfpwr & 0xffff);
11528		}
11529		bwn_phy_lp_set_txgain_override(mac);
11530	}
11531	if (plp->plp_rccap)
11532		bwn_phy_lp_set_rccap(mac);
11533	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11534	bwn_phy_lp_set_txpctlmode(mac, mode);
11535	free(tabs, M_DEVBUF);
11536}
11537
11538static void
11539bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11540{
11541	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11542	int i;
11543	static const uint16_t addr[] = {
11544		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11545		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11546		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11547		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11548		BWN_PHY_OFDM(0xcf),
11549	};
11550
11551	for (i = 0; i < N(addr); i++)
11552		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11553}
11554
11555static void
11556bwn_phy_lp_tblinit(struct bwn_mac *mac)
11557{
11558	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11559
11560	if (mac->mac_phy.rev < 2) {
11561		bwn_phy_lp_tblinit_r01(mac);
11562		bwn_phy_lp_tblinit_txgain(mac);
11563		bwn_phy_lp_set_gaintbl(mac, freq);
11564		return;
11565	}
11566
11567	bwn_phy_lp_tblinit_r2(mac);
11568	bwn_phy_lp_tblinit_txgain(mac);
11569}
11570
11571struct bwn_wpair {
11572	uint16_t		reg;
11573	uint16_t		value;
11574};
11575
11576struct bwn_smpair {
11577	uint16_t		offset;
11578	uint16_t		mask;
11579	uint16_t		set;
11580};
11581
11582static void
11583bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11584{
11585	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11586	struct bwn_softc *sc = mac->mac_sc;
11587	struct ieee80211com *ic = &sc->sc_ic;
11588	static const struct bwn_wpair v1[] = {
11589		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11590		{ BWN_PHY_AFE_CTL, 0x8800 },
11591		{ BWN_PHY_AFE_CTL_OVR, 0 },
11592		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11593		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11594		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11595		{ BWN_PHY_OFDM(0xf9), 0 },
11596		{ BWN_PHY_TR_LOOKUP_1, 0 }
11597	};
11598	static const struct bwn_smpair v2[] = {
11599		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11600		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11601		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11602		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11603		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11604	};
11605	static const struct bwn_smpair v3[] = {
11606		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11607		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11608		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11609		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11610		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11611		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11612		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11613		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11614		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11615		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11616
11617	};
11618	int i;
11619
11620	for (i = 0; i < N(v1); i++)
11621		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11622	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11623	for (i = 0; i < N(v2); i++)
11624		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11625
11626	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11627	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11628	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11629	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11630		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11631		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11632	} else {
11633		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11634	}
11635	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11636	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11637	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11638	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11639	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11640	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11641	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11642	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11643	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11644	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11645	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11646	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11647	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11648		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11649		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11650	} else {
11651		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11652		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11653	}
11654	for (i = 0; i < N(v3); i++)
11655		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11656	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11657	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11658		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11659		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11660	}
11661
11662	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11663		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11664		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11665		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11666		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11667		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11668		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11669	} else
11670		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11671
11672	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11673	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11674	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11675	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11676	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11677	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11678	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11679	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11680	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11681
11682	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11683	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11684		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11685		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11686		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11687	}
11688
11689	bwn_phy_lp_digflt_save(mac);
11690}
11691
11692static void
11693bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11694{
11695	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11696	struct bwn_softc *sc = mac->mac_sc;
11697	struct ieee80211com *ic = &sc->sc_ic;
11698	static const struct bwn_smpair v1[] = {
11699		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11700		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11701		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11702		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11703		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11704		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11705		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11706	};
11707	static const struct bwn_smpair v2[] = {
11708		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11709		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11710		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11711		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11712		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11713		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11714		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11715		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11716		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11717		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11718		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11719		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11720		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11721		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11722		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11723		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11724	};
11725	static const struct bwn_smpair v3[] = {
11726		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11727		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11728		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11729		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11730		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11731		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11732		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11733		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11734	};
11735	static const struct bwn_smpair v4[] = {
11736		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11737		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11738		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11739		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11740		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11741		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11742		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11743		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11744	};
11745	static const struct bwn_smpair v5[] = {
11746		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11747		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11748		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11749		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11750		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11751		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11752		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11753		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11754	};
11755	int i;
11756	uint16_t tmp, tmp2;
11757
11758	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11759	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11760	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11761	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11762	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11763	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11764	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11765	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11766	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11767	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11768	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11769	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11770	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11771	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11772	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11773	for (i = 0; i < N(v1); i++)
11774		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11775	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11776	    0xff00, plp->plp_rxpwroffset);
11777	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11778	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11779	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11780		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11781		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11782		if (mac->mac_phy.rev == 0)
11783			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11784			    0xffcf, 0x0010);
11785		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11786	} else {
11787		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11788		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11789		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11790	}
11791	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11792	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11793	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11794		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11795	else
11796		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11797	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11798	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11799	    0xfff9, (plp->plp_bxarch << 1));
11800	if (mac->mac_phy.rev == 1 &&
11801	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11802		for (i = 0; i < N(v2); i++)
11803			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11804			    v2[i].set);
11805	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11806	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11807	    ((mac->mac_phy.rev == 0) &&
11808	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11809		for (i = 0; i < N(v3); i++)
11810			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11811			    v3[i].set);
11812	} else if (mac->mac_phy.rev == 1 ||
11813		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11814		for (i = 0; i < N(v4); i++)
11815			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11816			    v4[i].set);
11817	} else {
11818		for (i = 0; i < N(v5); i++)
11819			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11820			    v5[i].set);
11821	}
11822	if (mac->mac_phy.rev == 1 &&
11823	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11824		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11825		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11826		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11827		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11828	}
11829	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11830	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11831	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11832		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11833		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11834		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11835		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11836	}
11837	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11838		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11839		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11840		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11841		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11842		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11843		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11844		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11845		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11846	} else {
11847		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11848		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11849	}
11850	if (mac->mac_phy.rev == 1) {
11851		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11852		tmp2 = (tmp & 0x03e0) >> 5;
11853		tmp2 |= tmp2 << 5;
11854		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
11855		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
11856		tmp2 = (tmp & 0x1f00) >> 8;
11857		tmp2 |= tmp2 << 5;
11858		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
11859		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
11860		tmp2 = tmp & 0x00ff;
11861		tmp2 |= tmp << 8;
11862		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
11863	}
11864}
11865
11866struct bwn_b2062_freq {
11867	uint16_t		freq;
11868	uint8_t			value[6];
11869};
11870
11871static void
11872bwn_phy_lp_b2062_init(struct bwn_mac *mac)
11873{
11874#define	CALC_CTL7(freq, div)						\
11875	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
11876#define	CALC_CTL18(freq, div)						\
11877	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
11878#define	CALC_CTL19(freq, div)						\
11879	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
11880	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11881	struct bwn_softc *sc = mac->mac_sc;
11882	struct ieee80211com *ic = &sc->sc_ic;
11883	static const struct bwn_b2062_freq freqdata_tab[] = {
11884		{ 12000, { 6, 6, 6, 6, 10, 6 } },
11885		{ 13000, { 4, 4, 4, 4, 11, 7 } },
11886		{ 14400, { 3, 3, 3, 3, 12, 7 } },
11887		{ 16200, { 3, 3, 3, 3, 13, 8 } },
11888		{ 18000, { 2, 2, 2, 2, 14, 8 } },
11889		{ 19200, { 1, 1, 1, 1, 14, 9 } }
11890	};
11891	static const struct bwn_wpair v1[] = {
11892		{ BWN_B2062_N_TXCTL3, 0 },
11893		{ BWN_B2062_N_TXCTL4, 0 },
11894		{ BWN_B2062_N_TXCTL5, 0 },
11895		{ BWN_B2062_N_TXCTL6, 0 },
11896		{ BWN_B2062_N_PDNCTL0, 0x40 },
11897		{ BWN_B2062_N_PDNCTL0, 0 },
11898		{ BWN_B2062_N_CALIB_TS, 0x10 },
11899		{ BWN_B2062_N_CALIB_TS, 0 }
11900	};
11901	const struct bwn_b2062_freq *f = NULL;
11902	uint32_t xtalfreq, ref;
11903	unsigned int i;
11904
11905	bwn_phy_lp_b2062_tblinit(mac);
11906
11907	for (i = 0; i < N(v1); i++)
11908		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
11909	if (mac->mac_phy.rev > 0)
11910		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
11911		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
11912	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11913		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
11914	else
11915		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
11916
11917	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
11918	    ("%s:%d: fail", __func__, __LINE__));
11919	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11920	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
11921
11922	if (xtalfreq <= 30000000) {
11923		plp->plp_div = 1;
11924		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
11925	} else {
11926		plp->plp_div = 2;
11927		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
11928	}
11929
11930	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
11931	    CALC_CTL7(xtalfreq, plp->plp_div));
11932	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
11933	    CALC_CTL18(xtalfreq, plp->plp_div));
11934	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
11935	    CALC_CTL19(xtalfreq, plp->plp_div));
11936
11937	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
11938	ref &= 0xffff;
11939	for (i = 0; i < N(freqdata_tab); i++) {
11940		if (ref < freqdata_tab[i].freq) {
11941			f = &freqdata_tab[i];
11942			break;
11943		}
11944	}
11945	if (f == NULL)
11946		f = &freqdata_tab[N(freqdata_tab) - 1];
11947	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
11948	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
11949	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
11950	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
11951	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
11952	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
11953#undef CALC_CTL7
11954#undef CALC_CTL18
11955#undef CALC_CTL19
11956}
11957
11958static void
11959bwn_phy_lp_b2063_init(struct bwn_mac *mac)
11960{
11961
11962	bwn_phy_lp_b2063_tblinit(mac);
11963	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
11964	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
11965	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
11966	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
11967	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
11968	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
11969	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
11970	if (mac->mac_phy.rev == 2) {
11971		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
11972		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
11973		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
11974	} else {
11975		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
11976		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
11977	}
11978}
11979
11980static void
11981bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
11982{
11983	struct bwn_softc *sc = mac->mac_sc;
11984	static const struct bwn_wpair v1[] = {
11985		{ BWN_B2063_RX_BB_SP8, 0x0 },
11986		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
11987		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
11988		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
11989		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
11990		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
11991		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
11992		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
11993	};
11994	static const struct bwn_wpair v2[] = {
11995		{ BWN_B2063_TX_BB_SP3, 0x0 },
11996		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
11997		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
11998		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
11999		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12000	};
12001	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12002	int i;
12003	uint8_t tmp;
12004
12005	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12006
12007	for (i = 0; i < 2; i++)
12008		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12009	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12010	for (i = 2; i < N(v1); i++)
12011		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12012	for (i = 0; i < 10000; i++) {
12013		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12014			break;
12015		DELAY(1000);
12016	}
12017
12018	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12019		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12020
12021	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12022
12023	for (i = 0; i < N(v2); i++)
12024		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12025	if (freqxtal == 24000000) {
12026		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12027		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12028	} else {
12029		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12030		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12031	}
12032	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12033	for (i = 0; i < 10000; i++) {
12034		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12035			break;
12036		DELAY(1000);
12037	}
12038	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12039		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12040	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12041}
12042
12043static void
12044bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12045{
12046	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12047	struct bwn_softc *sc = mac->mac_sc;
12048	struct bwn_phy_lp_iq_est ie;
12049	struct bwn_txgain tx_gains;
12050	static const uint32_t pwrtbl[21] = {
12051		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12052		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12053		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12054		0x0004c, 0x0002c, 0x0001a,
12055	};
12056	uint32_t npwr, ipwr, sqpwr, tmp;
12057	int loopback, i, j, sum, error;
12058	uint16_t save[7];
12059	uint8_t txo, bbmult, txpctlmode;
12060
12061	error = bwn_phy_lp_switch_channel(mac, 7);
12062	if (error)
12063		device_printf(sc->sc_dev,
12064		    "failed to change channel to 7 (%d)\n", error);
12065	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12066	bbmult = bwn_phy_lp_get_bbmult(mac);
12067	if (txo)
12068		tx_gains = bwn_phy_lp_get_txgain(mac);
12069
12070	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12071	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12072	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12073	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12074	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12075	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12076	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12077
12078	bwn_phy_lp_get_txpctlmode(mac);
12079	txpctlmode = plp->plp_txpctlmode;
12080	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12081
12082	/* disable CRS */
12083	bwn_phy_lp_set_deaf(mac, 1);
12084	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12085	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12086	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12087	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12088	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12089	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12090	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12091	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12092	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12093	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12094	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12095	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12096	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12097	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12098	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12099	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12100	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12101	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12102	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12103	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12104	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12105	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12106	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12107	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12108
12109	loopback = bwn_phy_lp_loopback(mac);
12110	if (loopback == -1)
12111		goto done;
12112	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12113	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12114	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12115	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12116	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12117
12118	tmp = 0;
12119	memset(&ie, 0, sizeof(ie));
12120	for (i = 128; i <= 159; i++) {
12121		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12122		sum = 0;
12123		for (j = 5; j <= 25; j++) {
12124			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12125			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12126				goto done;
12127			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12128			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12129			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12130			    12);
12131			sum += ((ipwr - npwr) * (ipwr - npwr));
12132			if ((i == 128) || (sum < tmp)) {
12133				plp->plp_rccap = i;
12134				tmp = sum;
12135			}
12136		}
12137	}
12138	bwn_phy_lp_ddfs_turnoff(mac);
12139done:
12140	/* restore CRS */
12141	bwn_phy_lp_clear_deaf(mac, 1);
12142	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12143	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12144
12145	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12146	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12147	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12148	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12149	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12150	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12151	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12152
12153	bwn_phy_lp_set_bbmult(mac, bbmult);
12154	if (txo)
12155		bwn_phy_lp_set_txgain(mac, &tx_gains);
12156	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12157	if (plp->plp_rccap)
12158		bwn_phy_lp_set_rccap(mac);
12159}
12160
12161static void
12162bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12163{
12164	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12165	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12166
12167	if (mac->mac_phy.rev == 1)
12168		rc_cap = MIN(rc_cap + 5, 15);
12169
12170	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12171	    MAX(plp->plp_rccap - 4, 0x80));
12172	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12173	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12174	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12175}
12176
12177static uint32_t
12178bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12179{
12180	uint32_t i, q, r;
12181
12182	if (div == 0)
12183		return (0);
12184
12185	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12186		q <<= 1;
12187		if (r << 1 >= div) {
12188			q++;
12189			r = (r << 1) - div;
12190		}
12191	}
12192	if (r << 1 >= div)
12193		q++;
12194	return (q);
12195}
12196
12197static void
12198bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12199{
12200	struct bwn_softc *sc = mac->mac_sc;
12201
12202	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12203	DELAY(20);
12204	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12205		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12206		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12207	} else {
12208		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12209	}
12210	DELAY(5);
12211}
12212
12213static void
12214bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12215{
12216
12217	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12218	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12219	DELAY(200);
12220}
12221
12222static void
12223bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12224{
12225#define	FLAG_A	0x01
12226#define	FLAG_G	0x02
12227	struct bwn_softc *sc = mac->mac_sc;
12228	struct ieee80211com *ic = &sc->sc_ic;
12229	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12230		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12231		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12232		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12233		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12234		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12235		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12236		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12237		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12238		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12239		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12240		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12241		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12242		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12243		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12244		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12245		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12246		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12247		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12248		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12249		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12250		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12251		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12252		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12253		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12254		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12255		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12256		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12257		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12258		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12259		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12260		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12261		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12262		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12263		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12264		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12265		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12266		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12267		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12268		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12269		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12270		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12271		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12272		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12273		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12274		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12275		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12276		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12277	};
12278	const struct bwn_b206x_rfinit_entry *br;
12279	unsigned int i;
12280
12281	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12282		br = &bwn_b2062_init_tab[i];
12283		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12284			if (br->br_flags & FLAG_G)
12285				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12286		} else {
12287			if (br->br_flags & FLAG_A)
12288				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12289		}
12290	}
12291#undef FLAG_A
12292#undef FLAG_B
12293}
12294
12295static void
12296bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12297{
12298#define	FLAG_A	0x01
12299#define	FLAG_G	0x02
12300	struct bwn_softc *sc = mac->mac_sc;
12301	struct ieee80211com *ic = &sc->sc_ic;
12302	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12303		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12304		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12305		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12306		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12307		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12308		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12309		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12310		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12311		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12312		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12313		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12314		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12315		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12316		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12317		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12318		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12319		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12320		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12321		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12322		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12323		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12324		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12325		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12326		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12327		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12328		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12329		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12330		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12331		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12332		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12333		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12334		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12335		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12336		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12337		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12338		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12339		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12340		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12341		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12342		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12343		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12344		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12345	};
12346	const struct bwn_b206x_rfinit_entry *br;
12347	unsigned int i;
12348
12349	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12350		br = &bwn_b2063_init_tab[i];
12351		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12352			if (br->br_flags & FLAG_G)
12353				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12354		} else {
12355			if (br->br_flags & FLAG_A)
12356				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12357		}
12358	}
12359#undef FLAG_A
12360#undef FLAG_B
12361}
12362
12363static void
12364bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12365    int count, void *_data)
12366{
12367	unsigned int i;
12368	uint32_t offset, type;
12369	uint8_t *data = _data;
12370
12371	type = BWN_TAB_GETTYPE(typenoffset);
12372	offset = BWN_TAB_GETOFFSET(typenoffset);
12373	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12374
12375	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12376
12377	for (i = 0; i < count; i++) {
12378		switch (type) {
12379		case BWN_TAB_8BIT:
12380			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12381			data++;
12382			break;
12383		case BWN_TAB_16BIT:
12384			*((uint16_t *)data) = BWN_PHY_READ(mac,
12385			    BWN_PHY_TABLEDATALO);
12386			data += 2;
12387			break;
12388		case BWN_TAB_32BIT:
12389			*((uint32_t *)data) = BWN_PHY_READ(mac,
12390			    BWN_PHY_TABLEDATAHI);
12391			*((uint32_t *)data) <<= 16;
12392			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12393			    BWN_PHY_TABLEDATALO);
12394			data += 4;
12395			break;
12396		default:
12397			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12398		}
12399	}
12400}
12401
12402static void
12403bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12404    int count, const void *_data)
12405{
12406	uint32_t offset, type, value;
12407	const uint8_t *data = _data;
12408	unsigned int i;
12409
12410	type = BWN_TAB_GETTYPE(typenoffset);
12411	offset = BWN_TAB_GETOFFSET(typenoffset);
12412	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12413
12414	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12415
12416	for (i = 0; i < count; i++) {
12417		switch (type) {
12418		case BWN_TAB_8BIT:
12419			value = *data;
12420			data++;
12421			KASSERT(!(value & ~0xff),
12422			    ("%s:%d: fail", __func__, __LINE__));
12423			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12424			break;
12425		case BWN_TAB_16BIT:
12426			value = *((const uint16_t *)data);
12427			data += 2;
12428			KASSERT(!(value & ~0xffff),
12429			    ("%s:%d: fail", __func__, __LINE__));
12430			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12431			break;
12432		case BWN_TAB_32BIT:
12433			value = *((const uint32_t *)data);
12434			data += 4;
12435			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12436			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12437			break;
12438		default:
12439			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12440		}
12441	}
12442}
12443
12444static struct bwn_txgain
12445bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12446{
12447	struct bwn_txgain tg;
12448	uint16_t tmp;
12449
12450	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12451	if (mac->mac_phy.rev < 2) {
12452		tmp = BWN_PHY_READ(mac,
12453		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12454		tg.tg_gm = tmp & 0x0007;
12455		tg.tg_pga = (tmp & 0x0078) >> 3;
12456		tg.tg_pad = (tmp & 0x780) >> 7;
12457		return (tg);
12458	}
12459
12460	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12461	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12462	tg.tg_gm = tmp & 0xff;
12463	tg.tg_pga = (tmp >> 8) & 0xff;
12464	return (tg);
12465}
12466
12467static uint8_t
12468bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12469{
12470
12471	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12472}
12473
12474static void
12475bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12476{
12477	uint16_t pa;
12478
12479	if (mac->mac_phy.rev < 2) {
12480		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12481		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12482		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12483		bwn_phy_lp_set_txgain_override(mac);
12484		return;
12485	}
12486
12487	pa = bwn_phy_lp_get_pa_gain(mac);
12488	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12489	    (tg->tg_pga << 8) | tg->tg_gm);
12490	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12491	    tg->tg_pad | (pa << 6));
12492	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12493	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12494	    tg->tg_pad | (pa << 8));
12495	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12496	bwn_phy_lp_set_txgain_override(mac);
12497}
12498
12499static void
12500bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12501{
12502
12503	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12504}
12505
12506static void
12507bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12508{
12509	uint16_t trsw = (tx << 1) | rx;
12510
12511	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12512	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12513}
12514
12515static void
12516bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12517{
12518	struct bwn_softc *sc = mac->mac_sc;
12519	struct ieee80211com *ic = &sc->sc_ic;
12520	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12521
12522	if (mac->mac_phy.rev < 2) {
12523		trsw = gain & 0x1;
12524		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12525		ext_lna = (gain & 2) >> 1;
12526
12527		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12528		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12529		    0xfbff, ext_lna << 10);
12530		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12531		    0xf7ff, ext_lna << 11);
12532		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12533	} else {
12534		low_gain = gain & 0xffff;
12535		high_gain = (gain >> 16) & 0xf;
12536		ext_lna = (gain >> 21) & 0x1;
12537		trsw = ~(gain >> 20) & 0x1;
12538
12539		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12540		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12541		    0xfdff, ext_lna << 9);
12542		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12543		    0xfbff, ext_lna << 10);
12544		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12545		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12546		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12547			tmp = (gain >> 2) & 0x3;
12548			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12549			    0xe7ff, tmp<<11);
12550			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12551			    tmp << 3);
12552		}
12553	}
12554
12555	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12556	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12557	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12558	if (mac->mac_phy.rev >= 2) {
12559		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12560		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12561			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12562			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12563		}
12564		return;
12565	}
12566	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12567}
12568
12569static void
12570bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12571{
12572	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12573
12574	if (user)
12575		plp->plp_crsusr_off = 1;
12576	else
12577		plp->plp_crssys_off = 1;
12578
12579	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12580}
12581
12582static void
12583bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12584{
12585	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12586	struct bwn_softc *sc = mac->mac_sc;
12587	struct ieee80211com *ic = &sc->sc_ic;
12588
12589	if (user)
12590		plp->plp_crsusr_off = 0;
12591	else
12592		plp->plp_crssys_off = 0;
12593
12594	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12595		return;
12596
12597	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12598		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12599	else
12600		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12601}
12602
12603static unsigned int
12604bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12605{
12606	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12607	static uint8_t sqrt_table[256] = {
12608		10, 14, 17, 20, 22, 24, 26, 28,
12609		30, 31, 33, 34, 36, 37, 38, 40,
12610		41, 42, 43, 44, 45, 46, 47, 48,
12611		50, 50, 51, 52, 53, 54, 55, 56,
12612		57, 58, 59, 60, 60, 61, 62, 63,
12613		64, 64, 65, 66, 67, 67, 68, 69,
12614		70, 70, 71, 72, 72, 73, 74, 74,
12615		75, 76, 76, 77, 78, 78, 79, 80,
12616		80, 81, 81, 82, 83, 83, 84, 84,
12617		85, 86, 86, 87, 87, 88, 88, 89,
12618		90, 90, 91, 91, 92, 92, 93, 93,
12619		94, 94, 95, 95, 96, 96, 97, 97,
12620		98, 98, 99, 100, 100, 100, 101, 101,
12621		102, 102, 103, 103, 104, 104, 105, 105,
12622		106, 106, 107, 107, 108, 108, 109, 109,
12623		110, 110, 110, 111, 111, 112, 112, 113,
12624		113, 114, 114, 114, 115, 115, 116, 116,
12625		117, 117, 117, 118, 118, 119, 119, 120,
12626		120, 120, 121, 121, 122, 122, 122, 123,
12627		123, 124, 124, 124, 125, 125, 126, 126,
12628		126, 127, 127, 128, 128, 128, 129, 129,
12629		130, 130, 130, 131, 131, 131, 132, 132,
12630		133, 133, 133, 134, 134, 134, 135, 135,
12631		136, 136, 136, 137, 137, 137, 138, 138,
12632		138, 139, 139, 140, 140, 140, 141, 141,
12633		141, 142, 142, 142, 143, 143, 143, 144,
12634		144, 144, 145, 145, 145, 146, 146, 146,
12635		147, 147, 147, 148, 148, 148, 149, 149,
12636		150, 150, 150, 150, 151, 151, 151, 152,
12637		152, 152, 153, 153, 153, 154, 154, 154,
12638		155, 155, 155, 156, 156, 156, 157, 157,
12639		157, 158, 158, 158, 159, 159, 159, 160
12640	};
12641
12642	if (x == 0)
12643		return (0);
12644	if (x >= 256) {
12645		unsigned int tmp;
12646
12647		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12648			/* do nothing */ ;
12649		return (tmp);
12650	}
12651	return (sqrt_table[x - 1] / 10);
12652}
12653
12654static int
12655bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12656{
12657#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12658	int _t;								\
12659	_t = _x - 20;							\
12660	if (_t >= 0) {							\
12661		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12662	} else {							\
12663		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12664	}								\
12665} while (0)
12666#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12667	int _t;								\
12668	_t = _x - 11;							\
12669	if (_t >= 0)							\
12670		_v = (_y << (31 - _x)) / (_z >> _t);			\
12671	else								\
12672		_v = (_y << (31 - _x)) / (_z << -_t);			\
12673} while (0)
12674	struct bwn_phy_lp_iq_est ie;
12675	uint16_t v0, v1;
12676	int tmp[2], ret;
12677
12678	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12679	v0 = v1 >> 8;
12680	v1 |= 0xff;
12681
12682	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12683	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12684
12685	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12686	if (ret == 0)
12687		goto done;
12688
12689	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12690		ret = 0;
12691		goto done;
12692	}
12693
12694	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12695	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12696
12697	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12698	v0 = tmp[0] >> 3;
12699	v1 = tmp[1] >> 4;
12700done:
12701	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12702	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12703	return ret;
12704#undef CALC_COEFF
12705#undef CALC_COEFF2
12706}
12707
12708static void
12709bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12710{
12711	static const uint16_t noisescale[] = {
12712		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12713		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12714		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12715		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12716		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12717	};
12718	static const uint16_t crsgainnft[] = {
12719		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12720		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12721		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12722		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12723		0x013d,
12724	};
12725	static const uint16_t filterctl[] = {
12726		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12727		0xff53, 0x0127,
12728	};
12729	static const uint32_t psctl[] = {
12730		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12731		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12732		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12733		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12734		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12735		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12736		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12737		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12738	};
12739	static const uint16_t ofdmcckgain_r0[] = {
12740		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12741		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12742		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12743		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12744		0x755d,
12745	};
12746	static const uint16_t ofdmcckgain_r1[] = {
12747		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12748		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12749		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12750		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12751		0x755d,
12752	};
12753	static const uint16_t gaindelta[] = {
12754		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12755		0x0000,
12756	};
12757	static const uint32_t txpwrctl[] = {
12758		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12759		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12760		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12761		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12762		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12763		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12764		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12765		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12766		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12767		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12768		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12769		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12770		0x00000014, 0x00000013, 0x00000012, 0x00000011, 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, 0x00000000, 0x00000000, 0x00000000,
12796		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12797		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12798		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12799		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12800		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12801		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12802		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12803		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12804		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12805		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12806		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12807		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12808		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12809		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12810		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12811		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12812		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12813		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12814		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12815		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12816		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12817		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12818		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12819		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12820		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12821		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12822		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12823		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12824		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12825		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12826		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12827		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12828		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12829		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12830		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12831		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12832		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12833		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12834		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12835		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12836		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12837		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12838		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12839		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12840		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12841		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12842		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12843		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12844		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12845		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12846		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12847		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
12848		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
12849		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
12850		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
12851		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
12852		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
12853		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
12854		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
12855		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
12856		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
12857		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
12858		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
12859		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
12860		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
12861		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
12862		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
12863		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
12864		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
12865		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
12866		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
12867		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
12868		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
12869		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
12870		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
12871		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
12872		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
12873		0x00000702,
12874	};
12875
12876	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
12877
12878	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
12879	    bwn_tab_sigsq_tbl);
12880	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
12881	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
12882	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
12883	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
12884	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
12885	    bwn_tab_pllfrac_tbl);
12886	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
12887	    bwn_tabl_iqlocal_tbl);
12888	if (mac->mac_phy.rev == 0) {
12889		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
12890		    ofdmcckgain_r0);
12891		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
12892		    ofdmcckgain_r0);
12893	} else {
12894		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
12895		    ofdmcckgain_r1);
12896		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
12897		    ofdmcckgain_r1);
12898	}
12899	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
12900	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
12901}
12902
12903static void
12904bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
12905{
12906	struct bwn_softc *sc = mac->mac_sc;
12907	int i;
12908	static const uint16_t noisescale[] = {
12909		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12910		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12911		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12912		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12913		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12914		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12915		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
12916	};
12917	static const uint32_t filterctl[] = {
12918		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
12919		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
12920	};
12921	static const uint32_t psctl[] = {
12922		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
12923		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
12924		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
12925		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
12926	};
12927	static const uint32_t gainidx[] = {
12928		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
12932		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
12933		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
12934		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
12935		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
12936		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
12937		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
12938		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
12939		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
12940		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
12941		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
12942		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
12943		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
12947		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
12948		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
12949		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
12950		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
12951		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
12952		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
12953		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
12954		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
12955		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
12956		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
12957		0x0000001a, 0x64ca55ad, 0x0000001a
12958	};
12959	static const uint16_t auxgainidx[] = {
12960		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12961		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
12962		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
12963		0x0004, 0x0016
12964	};
12965	static const uint16_t swctl[] = {
12966		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12967		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12968		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
12969		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
12970		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12971		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12972		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
12973		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
12974	};
12975	static const uint8_t hf[] = {
12976		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
12977		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
12978	};
12979	static const uint32_t gainval[] = {
12980		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
12981		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
12982		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
12983		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
12984		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
12985		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
12986		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12987		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12988		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
12989		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
12990		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
12991		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
12992		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
12993		0x000000f1, 0x00000000, 0x00000000
12994	};
12995	static const uint16_t gain[] = {
12996		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
12997		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
12998		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
12999		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13000		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13001		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 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		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13008	};
13009	static const uint32_t papdeps[] = {
13010		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13011		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13012		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13013		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13014		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13015		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13016		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13017		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13018		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13019		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13020		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13021		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13022		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13023	};
13024	static const uint32_t papdmult[] = {
13025		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13026		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13027		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13028		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13029		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13030		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13031		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13032		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13033		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13034		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13035		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13036		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13037		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13038	};
13039	static const uint32_t gainidx_a0[] = {
13040		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13041		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13042		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13043		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13044		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13045		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13046		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13047		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13048		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13049		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13050		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13051		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13052		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13053	};
13054	static const uint16_t auxgainidx_a0[] = {
13055		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13056		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13057		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13058		0x0002, 0x0014
13059	};
13060	static const uint32_t gainval_a0[] = {
13061		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13062		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13063		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13064		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13065		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13066		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13067		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13068		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13069		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13070		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13071		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13072		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13073		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13074		0x000000f7, 0x00000000, 0x00000000
13075	};
13076	static const uint16_t gain_a0[] = {
13077		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13078		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13079		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13080		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13081		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13082		0x035f, 0x075f, 0x0b5f, 0x0f5f, 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		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13089	};
13090
13091	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13092
13093	for (i = 0; i < 704; i++)
13094		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13095
13096	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13097	    bwn_tab_sigsq_tbl);
13098	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13099	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13100	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13101	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13102	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13103	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13104	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13105	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13106	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13107	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13108	    bwn_tab_pllfrac_tbl);
13109	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13110	    bwn_tabl_iqlocal_tbl);
13111	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13112	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13113
13114	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13115	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13116		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13117		    gainidx_a0);
13118		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13119		    auxgainidx_a0);
13120		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13121		    gainval_a0);
13122		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13123	}
13124}
13125
13126static void
13127bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13128{
13129	struct bwn_softc *sc = mac->mac_sc;
13130	struct ieee80211com *ic = &sc->sc_ic;
13131	static struct bwn_txgain_entry txgain_r2[] = {
13132		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13133		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13134		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13135		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13136		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13137		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13138		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13139		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13140		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13141		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13142		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13143		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13144		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13145		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13146		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13147		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13148		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13149		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13150		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13151		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13152		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13153		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13154		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13155		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13156		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13157		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13158		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13159		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13160		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13161		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13162		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13163		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13164		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13165		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13166		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13167		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13168		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13169		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13170		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13171		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13172		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13173		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13174		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13175		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13176		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13177		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13178		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13179		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13180		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13181		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13182		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13183		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13184		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13185		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13186		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13187		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13188		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13189		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13190		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13191		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13192		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13193		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13194		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13195		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13196	};
13197	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13198		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13199		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13200		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13201		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13202		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13203		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13204		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13205		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13206		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13207		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13208		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13209		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13210		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13211		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13212		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13213		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13214		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13215		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13216		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13217		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13218		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13219		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13220		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13221		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13222		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13223		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13224		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13225		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13226		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13227		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13228		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13229		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13230		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13231		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13232		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13233		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13234		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13235		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13236		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13237		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13238		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13239		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13240		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13241		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13242		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13243		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13244		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13245		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13246		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13247		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13248		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13249		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13250		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13251		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13252		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13253		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13254		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13255		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13256		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13257		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13258		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13259		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13260		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13261		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13262	};
13263	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13264		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13265		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13266		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13267		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13268		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13269		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13270		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13271		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13272		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13273		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13274		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13275		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13276		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13277		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13278		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13279		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13280		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13281		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13282		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13283		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13284		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13285		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13286		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13287		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13288		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13289		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13290		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13291		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13292		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13293		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13294		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13295		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13296		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13297		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13298		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13299		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13300		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13301		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13302		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13303		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13304		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13305		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13306		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13307		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13308		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13309		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13310		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13311		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13312		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13313		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13314		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13315		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13316		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13317		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13318		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13319		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13320		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13321		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13322		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13323		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13324		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13325		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13326		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13327		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13328	};
13329	static struct bwn_txgain_entry txgain_r0[] = {
13330		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13331		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13332		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13333		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13334		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13335		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13336		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13337		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13338		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13339		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13340		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13341		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13342		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13343		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13344		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13345		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13346		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13347		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13348		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13349		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13350		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13351		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13352		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13353		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13354		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13355		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13356		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13357		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13358		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13359		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13360		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13361		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13362		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13363		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13364		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13365		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13366		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13367		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13368		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13369		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13370		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13371		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13372		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13373		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13374		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13375		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13376		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13377		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13378		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13379		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13380		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13381		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13382		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13383		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13384		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13385		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13386		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13387		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13388		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13389		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13390		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13391		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13392		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13393		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13394	};
13395	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13396		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13397		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13398		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13399		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13400		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13401		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13402		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13403		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13404		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13405		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13406		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13407		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13408		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13409		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13410		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13411		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13412		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13413		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13414		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13415		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13416		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13417		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13418		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13419		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13420		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13421		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13422		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13423		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13424		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13425		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13426		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13427		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13428		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13429		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13430		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13431		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13432		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13433		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13434		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13435		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13436		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13437		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13438		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13439		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13440		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13441		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13442		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13443		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13444		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13445		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13446		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13447		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13448		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13449		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13450		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13451		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13452		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13453		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13454		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13455		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13456		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13457		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13458		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13459		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13460	};
13461	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13462		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13463		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13464		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13465		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13466		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13467		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13468		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13469		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13470		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13471		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13472		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13473		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13474		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13475		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13476		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13477		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13478		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13479		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13480		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13481		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13482		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13483		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13484		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13485		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13486		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13487		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13488		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13489		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13490		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13491		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13492		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13493		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13494		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13495		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13496		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13497		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13498		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13499		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13500		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13501		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13502		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13503		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13504		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13505		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13506		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13507		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13508		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13509		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13510		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13511		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13512		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13513		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13514		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13515		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13516		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13517		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13518		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13519		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13520		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13521		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13522		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13523		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13524		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13525		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13526	};
13527	static struct bwn_txgain_entry txgain_r1[] = {
13528		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13529		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13530		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13531		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13532		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13533		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13534		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13535		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13536		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13537		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13538		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13539		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13540		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13541		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13542		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13543		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13544		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13545		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13546		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13547		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13548		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13549		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13550		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13551		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13552		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13553		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13554		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13555		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13556		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13557		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13558		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13559		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13560		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13561		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13562		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13563		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13564		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13565		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13566		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13567		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13568		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13569		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13570		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13571		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13572		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13573		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13574		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13575		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13576		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13577		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13578		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13579		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13580		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13581		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13582		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13583		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13584		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13585		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13586		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13587		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13588		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13589		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13590		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13591		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13592		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13593		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13594		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13595		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13596		{ 7, 11, 6, 0, 71 }
13597	};
13598	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13599		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13600		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13601		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13602		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13603		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13604		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13605		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13606		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13607		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13608		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13609		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13610		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13611		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13612		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13613		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13614		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13615		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13616		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13617		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13618		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13619		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13620		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13621		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13622		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13623		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13624		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13625		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13626		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13627		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13628		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13629		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13630		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13631		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13632		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13633		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13634		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13635		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13636		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13637		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13638		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13639		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13640		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13641		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13642		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13643		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13644		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13645		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13646		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13647		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13648		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13649		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13650		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13651		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13652		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13653		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13654		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13655		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13656		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13657		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13658		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13659		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13660		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13661		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13662		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13663	};
13664	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13665		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13666		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13667		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13668		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13669		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13670		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13671		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13672		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13673		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13674		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13675		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13676		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13677		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13678		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13679		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13680		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13681		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13682		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13683		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13684		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13685		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13686		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13687		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13688		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13689		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13690		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13691		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13692		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13693		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13694		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13695		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13696		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13697		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13698		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13699		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13700		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13701		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13702		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13703		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13704		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13705		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13706		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13707		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13708		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13709		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13710		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13711		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13712		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13713		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13714		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13715		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13716		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13717		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13718		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13719		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13720		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13721		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13722		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13723		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13724		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13725		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13726		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13727		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13728		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13729	};
13730
13731	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13732		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13733			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13734		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13735			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13736			    txgain_2ghz_r2);
13737		else
13738			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13739			    txgain_5ghz_r2);
13740		return;
13741	}
13742
13743	if (mac->mac_phy.rev == 0) {
13744		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13745		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13746			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13747		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13748			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13749			    txgain_2ghz_r0);
13750		else
13751			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13752			    txgain_5ghz_r0);
13753		return;
13754	}
13755
13756	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13757	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13758		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13759	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13760		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13761	else
13762		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13763}
13764
13765static void
13766bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13767{
13768	uint32_t offset, type;
13769
13770	type = BWN_TAB_GETTYPE(typeoffset);
13771	offset = BWN_TAB_GETOFFSET(typeoffset);
13772	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13773
13774	switch (type) {
13775	case BWN_TAB_8BIT:
13776		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13777		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13778		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13779		break;
13780	case BWN_TAB_16BIT:
13781		KASSERT(!(value & ~0xffff),
13782		    ("%s:%d: fail", __func__, __LINE__));
13783		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13784		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13785		break;
13786	case BWN_TAB_32BIT:
13787		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13788		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13789		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13790		break;
13791	default:
13792		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13793	}
13794}
13795
13796static int
13797bwn_phy_lp_loopback(struct bwn_mac *mac)
13798{
13799	struct bwn_phy_lp_iq_est ie;
13800	int i, index = -1;
13801	uint32_t tmp;
13802
13803	memset(&ie, 0, sizeof(ie));
13804
13805	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13806	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13807	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13808	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13809	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13810	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13811	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13812	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13813	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13814	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13815	for (i = 0; i < 32; i++) {
13816		bwn_phy_lp_set_rxgain_idx(mac, i);
13817		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13818		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13819			continue;
13820		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13821		if ((tmp > 4000) && (tmp < 10000)) {
13822			index = i;
13823			break;
13824		}
13825	}
13826	bwn_phy_lp_ddfs_turnoff(mac);
13827	return (index);
13828}
13829
13830static void
13831bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13832{
13833
13834	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13835}
13836
13837static void
13838bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13839    int incr1, int incr2, int scale_idx)
13840{
13841
13842	bwn_phy_lp_ddfs_turnoff(mac);
13843	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13844	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13845	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13846	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13847	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
13848	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
13849	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
13850	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
13851	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
13852	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
13853}
13854
13855static uint8_t
13856bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
13857    struct bwn_phy_lp_iq_est *ie)
13858{
13859	int i;
13860
13861	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
13862	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
13863	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
13864	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
13865	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
13866
13867	for (i = 0; i < 500; i++) {
13868		if (!(BWN_PHY_READ(mac,
13869		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
13870			break;
13871		DELAY(1000);
13872	}
13873	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
13874		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13875		return 0;
13876	}
13877
13878	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
13879	ie->ie_iqprod <<= 16;
13880	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
13881	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
13882	ie->ie_ipwr <<= 16;
13883	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
13884	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
13885	ie->ie_qpwr <<= 16;
13886	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
13887
13888	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13889	return 1;
13890}
13891
13892static uint32_t
13893bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
13894{
13895	uint32_t offset, type, value;
13896
13897	type = BWN_TAB_GETTYPE(typeoffset);
13898	offset = BWN_TAB_GETOFFSET(typeoffset);
13899	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13900
13901	switch (type) {
13902	case BWN_TAB_8BIT:
13903		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13904		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
13905		break;
13906	case BWN_TAB_16BIT:
13907		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13908		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13909		break;
13910	case BWN_TAB_32BIT:
13911		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13912		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
13913		value <<= 16;
13914		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13915		break;
13916	default:
13917		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13918		value = 0;
13919	}
13920
13921	return (value);
13922}
13923
13924static void
13925bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
13926{
13927
13928	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
13929	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
13930}
13931
13932static void
13933bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
13934{
13935	uint16_t ctl;
13936
13937	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
13938	ctl |= dac << 7;
13939	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
13940}
13941
13942static void
13943bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
13944{
13945
13946	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
13947	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
13948}
13949
13950static void
13951bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
13952{
13953
13954	if (mac->mac_phy.rev < 2)
13955		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
13956	else {
13957		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
13958		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
13959	}
13960	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
13961}
13962
13963static uint16_t
13964bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
13965{
13966
13967	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
13968}
13969
13970static uint8_t
13971bwn_nbits(int32_t val)
13972{
13973	uint32_t tmp;
13974	uint8_t nbits = 0;
13975
13976	for (tmp = abs(val); tmp != 0; tmp >>= 1)
13977		nbits++;
13978	return (nbits);
13979}
13980
13981static void
13982bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
13983    struct bwn_txgain_entry *table)
13984{
13985	int i;
13986
13987	for (i = offset; i < count; i++)
13988		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
13989}
13990
13991static void
13992bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
13993    struct bwn_txgain_entry data)
13994{
13995
13996	if (mac->mac_phy.rev >= 2)
13997		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
13998	else
13999		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14000}
14001
14002static void
14003bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14004    struct bwn_txgain_entry te)
14005{
14006	struct bwn_softc *sc = mac->mac_sc;
14007	struct ieee80211com *ic = &sc->sc_ic;
14008	uint32_t tmp;
14009
14010	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14011
14012	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14013	if (mac->mac_phy.rev >= 3) {
14014		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14015		    (0x10 << 24) : (0x70 << 24));
14016	} else {
14017		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14018		    (0x14 << 24) : (0x7f << 24));
14019	}
14020	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14021	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14022	    te.te_bbmult << 20 | te.te_dac << 28);
14023}
14024
14025static void
14026bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14027    struct bwn_txgain_entry te)
14028{
14029
14030	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14031
14032	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14033	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14034	    te.te_dac);
14035	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14036}
14037
14038static void
14039bwn_sysctl_node(struct bwn_softc *sc)
14040{
14041	device_t dev = sc->sc_dev;
14042	struct bwn_mac *mac;
14043	struct bwn_stats *stats;
14044
14045	/* XXX assume that count of MAC is only 1. */
14046
14047	if ((mac = sc->sc_curmac) == NULL)
14048		return;
14049	stats = &mac->mac_stats;
14050
14051	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14052	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14053	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14054	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14055	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14056	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14057	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14058	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14059	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14060
14061#ifdef BWN_DEBUG
14062	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14063	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14064	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14065#endif
14066}
14067
14068static device_method_t bwn_methods[] = {
14069	/* Device interface */
14070	DEVMETHOD(device_probe,		bwn_probe),
14071	DEVMETHOD(device_attach,	bwn_attach),
14072	DEVMETHOD(device_detach,	bwn_detach),
14073	DEVMETHOD(device_suspend,	bwn_suspend),
14074	DEVMETHOD(device_resume,	bwn_resume),
14075	DEVMETHOD_END
14076};
14077static driver_t bwn_driver = {
14078	"bwn",
14079	bwn_methods,
14080	sizeof(struct bwn_softc)
14081};
14082static devclass_t bwn_devclass;
14083DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14084MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14085MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14086MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14087MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14088