if_bwn.c revision 205141
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 205141 2010-03-14 02:13:11Z weongyo $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_amrr.h>
71#include <net80211/ieee80211_phy.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77
78/*
79 * Tunable & sysctl variables.
80 */
81
82#ifdef BWN_DEBUG
83static	int bwn_debug = 0;
84SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85    "Broadcom debugging printfs");
86TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87enum {
88	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106	BWN_DEBUG_ANY		= 0xffffffff
107};
108#define	DPRINTF(sc, m, fmt, ...) do {			\
109	if (sc->sc_debug & (m))				\
110		printf(fmt, __VA_ARGS__);		\
111} while (0)
112#else
113#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114#endif
115
116static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118    "uses Bad Frames Preemption");
119static int	bwn_bluetooth = 1;
120SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121    "turns on Bluetooth Coexistence");
122static int	bwn_hwpctl = 0;
123SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124    "uses H/W power control");
125static int	bwn_msi_disable = 0;		/* MSI disabled  */
126TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127static int	bwn_usedma = 1;
128SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129    "uses DMA");
130TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131static int	bwn_wme = 1;
132SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133    "uses WME support");
134
135static int	bwn_attach_pre(struct bwn_softc *);
136static int	bwn_attach_post(struct bwn_softc *);
137static void	bwn_sprom_bugfixes(device_t);
138static void	bwn_init(void *);
139static int	bwn_init_locked(struct bwn_softc *);
140static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141static void	bwn_start(struct ifnet *);
142static int	bwn_attach_core(struct bwn_mac *);
143static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144static int	bwn_phy_getinfo(struct bwn_mac *, int);
145static int	bwn_chiptest(struct bwn_mac *);
146static int	bwn_setup_channels(struct bwn_mac *, int, int);
147static int	bwn_phy_g_attach(struct bwn_mac *);
148static void	bwn_phy_g_detach(struct bwn_mac *);
149static void	bwn_phy_g_init_pre(struct bwn_mac *);
150static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151static int	bwn_phy_g_init(struct bwn_mac *);
152static void	bwn_phy_g_exit(struct bwn_mac *);
153static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155		    uint16_t);
156static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158		    uint16_t);
159static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164static int	bwn_phy_g_im(struct bwn_mac *, int);
165static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167static void	bwn_phy_g_task_15s(struct bwn_mac *);
168static void	bwn_phy_g_task_60s(struct bwn_mac *);
169static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173		    uint16_t);
174static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176		    uint32_t);
177static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178		    uint16_t);
179static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180		    const struct bwn_channelinfo *, int);
181static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182		    const struct ieee80211_bpf_params *);
183static void	bwn_newassoc(struct ieee80211_node *, int);
184static void	bwn_updateslot(struct ifnet *);
185static void	bwn_update_promisc(struct ifnet *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189		    const uint8_t [IEEE80211_ADDR_LEN]);
190static void	bwn_wme_clear(struct bwn_softc *);
191static void	bwn_wme_load(struct bwn_mac *);
192static void	bwn_wme_loadparams(struct bwn_mac *,
193		    const struct wmeParams *, uint16_t);
194static void	bwn_node_cleanup(struct ieee80211_node *);
195static void	bwn_scan_start(struct ieee80211com *);
196static void	bwn_scan_end(struct ieee80211com *);
197static void	bwn_set_channel(struct ieee80211com *);
198static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199		    const char [IFNAMSIZ], int, int,
200		    int, const uint8_t [IEEE80211_ADDR_LEN],
201		    const uint8_t [IEEE80211_ADDR_LEN]);
202static void	bwn_vap_delete(struct ieee80211vap *);
203static void	bwn_stop(struct bwn_softc *, int);
204static void	bwn_stop_locked(struct bwn_softc *, int);
205static int	bwn_core_init(struct bwn_mac *);
206static void	bwn_core_start(struct bwn_mac *);
207static void	bwn_core_exit(struct bwn_mac *);
208static void	bwn_bt_disable(struct bwn_mac *);
209static int	bwn_chip_init(struct bwn_mac *);
210static uint64_t	bwn_hf_read(struct bwn_mac *);
211static void	bwn_hf_write(struct bwn_mac *, uint64_t);
212static void	bwn_set_txretry(struct bwn_mac *, int, int);
213static void	bwn_rate_init(struct bwn_mac *);
214static void	bwn_set_phytxctl(struct bwn_mac *);
215static void	bwn_spu_setdelay(struct bwn_mac *, int);
216static void	bwn_bt_enable(struct bwn_mac *);
217static void	bwn_set_macaddr(struct bwn_mac *);
218static void	bwn_crypt_init(struct bwn_mac *);
219static void	bwn_chip_exit(struct bwn_mac *);
220static int	bwn_fw_fillinfo(struct bwn_mac *);
221static int	bwn_fw_loaducode(struct bwn_mac *);
222static int	bwn_gpio_init(struct bwn_mac *);
223static int	bwn_fw_loadinitvals(struct bwn_mac *);
224static int	bwn_phy_init(struct bwn_mac *);
225static void	bwn_set_txantenna(struct bwn_mac *, int);
226static void	bwn_set_opmode(struct bwn_mac *);
227static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
228static uint8_t	bwn_plcp_getcck(const uint8_t);
229static uint8_t	bwn_plcp_getofdm(const uint8_t);
230static void	bwn_pio_init(struct bwn_mac *);
231static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
232static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
233		    int);
234static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
235		    struct bwn_pio_rxqueue *, int);
236static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
237static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
238		    uint16_t);
239static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
240static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
241static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
242static void	bwn_pio_handle_txeof(struct bwn_mac *,
243		    const struct bwn_txstatus *);
244static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
245static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
246static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
247		    uint16_t);
248static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
249		    uint32_t);
250static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
251		    struct mbuf *);
252static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
253static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
254		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
255static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
256		    uint16_t, uint32_t);
257static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
258		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
259static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
260		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
261static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
262		    uint16_t, struct bwn_pio_txpkt **);
263static void	bwn_dma_init(struct bwn_mac *);
264static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
265static int	bwn_dma_mask2type(uint64_t);
266static uint64_t	bwn_dma_mask(struct bwn_mac *);
267static uint16_t	bwn_dma_base(int, int);
268static void	bwn_dma_ringfree(struct bwn_dma_ring **);
269static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
270		    int, struct bwn_dmadesc_generic **,
271		    struct bwn_dmadesc_meta **);
272static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
273		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
274		    int, int);
275static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
276static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
277static void	bwn_dma_32_resume(struct bwn_dma_ring *);
278static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
279static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
280static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
281		    int, struct bwn_dmadesc_generic **,
282		    struct bwn_dmadesc_meta **);
283static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
284		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
285		    int, int);
286static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
287static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
288static void	bwn_dma_64_resume(struct bwn_dma_ring *);
289static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
290static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
291static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
292static void	bwn_dma_setup(struct bwn_dma_ring *);
293static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
294static void	bwn_dma_cleanup(struct bwn_dma_ring *);
295static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
296static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
297static void	bwn_dma_rx(struct bwn_dma_ring *);
298static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
299static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
300		    struct bwn_dmadesc_meta *);
301static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
302static int	bwn_dma_gettype(struct bwn_mac *);
303static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
304static int	bwn_dma_freeslot(struct bwn_dma_ring *);
305static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
306static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
307static int	bwn_dma_newbuf(struct bwn_dma_ring *,
308		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
309		    int);
310static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
311		    bus_size_t, int);
312static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
313static void	bwn_dma_handle_txeof(struct bwn_mac *,
314		    const struct bwn_txstatus *);
315static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
316		    struct mbuf *);
317static int	bwn_dma_getslot(struct bwn_dma_ring *);
318static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
319		    uint8_t);
320static int	bwn_dma_attach(struct bwn_mac *);
321static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
322		    int, int, int);
323static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
324		    const struct bwn_txstatus *, uint16_t, int *);
325static void	bwn_dma_free(struct bwn_mac *);
326static void	bwn_phy_g_init_sub(struct bwn_mac *);
327static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
328static void	bwn_phy_init_b5(struct bwn_mac *);
329static void	bwn_phy_init_b6(struct bwn_mac *);
330static void	bwn_phy_init_a(struct bwn_mac *);
331static void	bwn_loopback_calcgain(struct bwn_mac *);
332static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
333static void	bwn_lo_g_init(struct bwn_mac *);
334static void	bwn_lo_g_adjust(struct bwn_mac *);
335static void	bwn_lo_get_powervector(struct bwn_mac *);
336static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
337		    const struct bwn_bbatt *, const struct bwn_rfatt *);
338static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
339static void	bwn_phy_hwpctl_init(struct bwn_mac *);
340static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
341static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
342		    const struct bwn_bbatt *, const struct bwn_rfatt *,
343		    uint8_t);
344static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
345static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
346static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
347static void	bwn_wa_init(struct bwn_mac *);
348static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
349		    uint16_t);
350static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
351static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
352		    uint32_t);
353static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
354		    uint16_t);
355static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
356static void	bwn_mac_suspend(struct bwn_mac *);
357static void	bwn_mac_enable(struct bwn_mac *);
358static void	bwn_psctl(struct bwn_mac *, uint32_t);
359static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
360static void	bwn_nrssi_offset(struct bwn_mac *);
361static void	bwn_nrssi_threshold(struct bwn_mac *);
362static void	bwn_nrssi_slope_11g(struct bwn_mac *);
363static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
364		    int16_t);
365static void	bwn_set_original_gains(struct bwn_mac *);
366static void	bwn_hwpctl_early_init(struct bwn_mac *);
367static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
368static uint16_t	bwn_phy_g_chan2freq(uint8_t);
369static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
370static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
371		    const char *, struct bwn_fwfile *);
372static void	bwn_release_firmware(struct bwn_mac *);
373static void	bwn_do_release_fw(struct bwn_fwfile *);
374static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
375static int	bwn_fwinitvals_write(struct bwn_mac *,
376		    const struct bwn_fwinitvals *, size_t, size_t);
377static int	bwn_switch_channel(struct bwn_mac *, int);
378static uint16_t	bwn_ant2phy(int);
379static void	bwn_mac_write_bssid(struct bwn_mac *);
380static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
381		    const uint8_t *);
382static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
383		    const uint8_t *, size_t, const uint8_t *);
384static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
385		    const uint8_t *);
386static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
387		    const uint8_t *);
388static void	bwn_phy_exit(struct bwn_mac *);
389static void	bwn_core_stop(struct bwn_mac *);
390static int	bwn_switch_band(struct bwn_softc *,
391		    struct ieee80211_channel *);
392static void	bwn_phy_reset(struct bwn_mac *);
393static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
394static void	bwn_set_pretbtt(struct bwn_mac *);
395static int	bwn_intr(void *);
396static void	bwn_intrtask(void *, int);
397static void	bwn_restart(struct bwn_mac *, const char *);
398static void	bwn_intr_ucode_debug(struct bwn_mac *);
399static void	bwn_intr_tbtt_indication(struct bwn_mac *);
400static void	bwn_intr_atim_end(struct bwn_mac *);
401static void	bwn_intr_beacon(struct bwn_mac *);
402static void	bwn_intr_pmq(struct bwn_mac *);
403static void	bwn_intr_noise(struct bwn_mac *);
404static void	bwn_intr_txeof(struct bwn_mac *);
405static void	bwn_hwreset(void *, int);
406static void	bwn_handle_fwpanic(struct bwn_mac *);
407static void	bwn_load_beacon0(struct bwn_mac *);
408static void	bwn_load_beacon1(struct bwn_mac *);
409static uint32_t	bwn_jssi_read(struct bwn_mac *);
410static void	bwn_noise_gensample(struct bwn_mac *);
411static void	bwn_handle_txeof(struct bwn_mac *,
412		    const struct bwn_txstatus *);
413static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
414static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
415static void	bwn_start_locked(struct ifnet *);
416static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
417		    struct mbuf *);
418static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
419static int	bwn_set_txhdr(struct bwn_mac *,
420		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
421		    uint16_t);
422static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
423		    const uint8_t);
424static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
425static uint8_t	bwn_get_fbrate(uint8_t);
426static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
427static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
428static void	bwn_phy_lock(struct bwn_mac *);
429static void	bwn_phy_unlock(struct bwn_mac *);
430static void	bwn_rf_lock(struct bwn_mac *);
431static void	bwn_rf_unlock(struct bwn_mac *);
432static void	bwn_txpwr(void *, int);
433static void	bwn_tasks(void *);
434static void	bwn_task_15s(struct bwn_mac *);
435static void	bwn_task_30s(struct bwn_mac *);
436static void	bwn_task_60s(struct bwn_mac *);
437static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
438		    uint8_t);
439static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
440static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
441		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
442		    int, int);
443static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
444static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
445static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
446static void	bwn_watchdog(void *);
447static void	bwn_dma_stop(struct bwn_mac *);
448static void	bwn_pio_stop(struct bwn_mac *);
449static void	bwn_dma_ringstop(struct bwn_dma_ring **);
450static void	bwn_led_attach(struct bwn_mac *);
451static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
452static void	bwn_led_event(struct bwn_mac *, int);
453static void	bwn_led_blink_start(struct bwn_mac *, int, int);
454static void	bwn_led_blink_next(void *);
455static void	bwn_led_blink_end(void *);
456static void	bwn_rfswitch(void *);
457static void	bwn_rf_turnon(struct bwn_mac *);
458static void	bwn_rf_turnoff(struct bwn_mac *);
459static void	bwn_phy_lp_init_pre(struct bwn_mac *);
460static int	bwn_phy_lp_init(struct bwn_mac *);
461static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
462static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
463static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
464		    uint16_t);
465static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
466static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
467static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
468static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
469static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
470static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
471static void	bwn_phy_lp_task_60s(struct bwn_mac *);
472static void	bwn_phy_lp_readsprom(struct bwn_mac *);
473static void	bwn_phy_lp_bbinit(struct bwn_mac *);
474static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
475static void	bwn_phy_lp_calib(struct bwn_mac *);
476static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
477static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
478static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
479static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
480static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
481static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
482static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
483static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
484static void	bwn_phy_lp_bugfix(struct bwn_mac *);
485static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
486static void	bwn_phy_lp_tblinit(struct bwn_mac *);
487static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
488static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
489static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
490static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
491static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
492static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
493static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
494static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
495static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
496static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
497static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
498		    const void *);
499static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
500static struct bwn_txgain
501		bwn_phy_lp_get_txgain(struct bwn_mac *);
502static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
503static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
504static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
505static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
506static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
507static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
508static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
509static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
510static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
511static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
512static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
513static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
514static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
515static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
516static int	bwn_phy_lp_loopback(struct bwn_mac *);
517static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
518static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
519		    int);
520static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
521		    struct bwn_phy_lp_iq_est *);
522static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
523static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
524static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
525static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
526static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
527static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
528static uint8_t	bwn_nbits(int32_t);
529static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
530		    struct bwn_txgain_entry *);
531static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
532		    struct bwn_txgain_entry);
533static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
534		    struct bwn_txgain_entry);
535static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
536		    struct bwn_txgain_entry);
537static void	bwn_sysctl_node(struct bwn_softc *);
538
539static struct resource_spec bwn_res_spec_legacy[] = {
540	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
541	{ -1,			0,		0 }
542};
543
544static struct resource_spec bwn_res_spec_msi[] = {
545	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
546	{ -1,			0,		0 }
547};
548
549static const struct bwn_channelinfo bwn_chantable_bg = {
550	.channels = {
551		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
552		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
553		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
554		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
555		{ 2472, 13, 30 }, { 2484, 14, 30 } },
556	.nchannels = 14
557};
558
559static const struct bwn_channelinfo bwn_chantable_a = {
560	.channels = {
561		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
562		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
563		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
564		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
565		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
566		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
567		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
568		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
569		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
570		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
571		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
572		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
573		{ 6080, 216, 30 } },
574	.nchannels = 37
575};
576
577static const struct bwn_channelinfo bwn_chantable_n = {
578	.channels = {
579		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
580		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
581		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
582		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
583		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
584		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
585		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
586		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
587		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
588		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
589		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
590		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
591		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
592		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
593		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
594		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
595		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
596		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
597		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
598		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
599		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
600		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
601		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
602		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
603		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
604		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
605		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
606		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
607		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
608		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
609		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
610		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
611		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
612		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
613		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
614		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
615		{ 6130, 226, 30 }, { 6140, 228, 30 } },
616	.nchannels = 110
617};
618
619static const uint8_t bwn_b2063_chantable_data[33][12] = {
620	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
626	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
627	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
628	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
629	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
630	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
631	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
632	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
633	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
634	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
635	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
636	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
637	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
638	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
639	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
640	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
641	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
642	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
643	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
645	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
646	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
647	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
648	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
649	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
651	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
652	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
653};
654
655static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
656	{ 1, 2412, bwn_b2063_chantable_data[0] },
657	{ 2, 2417, bwn_b2063_chantable_data[0] },
658	{ 3, 2422, bwn_b2063_chantable_data[0] },
659	{ 4, 2427, bwn_b2063_chantable_data[1] },
660	{ 5, 2432, bwn_b2063_chantable_data[1] },
661	{ 6, 2437, bwn_b2063_chantable_data[1] },
662	{ 7, 2442, bwn_b2063_chantable_data[1] },
663	{ 8, 2447, bwn_b2063_chantable_data[1] },
664	{ 9, 2452, bwn_b2063_chantable_data[2] },
665	{ 10, 2457, bwn_b2063_chantable_data[2] },
666	{ 11, 2462, bwn_b2063_chantable_data[3] },
667	{ 12, 2467, bwn_b2063_chantable_data[3] },
668	{ 13, 2472, bwn_b2063_chantable_data[3] },
669	{ 14, 2484, bwn_b2063_chantable_data[4] },
670	{ 34, 5170, bwn_b2063_chantable_data[5] },
671	{ 36, 5180, bwn_b2063_chantable_data[6] },
672	{ 38, 5190, bwn_b2063_chantable_data[7] },
673	{ 40, 5200, bwn_b2063_chantable_data[8] },
674	{ 42, 5210, bwn_b2063_chantable_data[9] },
675	{ 44, 5220, bwn_b2063_chantable_data[10] },
676	{ 46, 5230, bwn_b2063_chantable_data[11] },
677	{ 48, 5240, bwn_b2063_chantable_data[12] },
678	{ 52, 5260, bwn_b2063_chantable_data[13] },
679	{ 56, 5280, bwn_b2063_chantable_data[14] },
680	{ 60, 5300, bwn_b2063_chantable_data[14] },
681	{ 64, 5320, bwn_b2063_chantable_data[15] },
682	{ 100, 5500, bwn_b2063_chantable_data[16] },
683	{ 104, 5520, bwn_b2063_chantable_data[17] },
684	{ 108, 5540, bwn_b2063_chantable_data[18] },
685	{ 112, 5560, bwn_b2063_chantable_data[19] },
686	{ 116, 5580, bwn_b2063_chantable_data[20] },
687	{ 120, 5600, bwn_b2063_chantable_data[21] },
688	{ 124, 5620, bwn_b2063_chantable_data[21] },
689	{ 128, 5640, bwn_b2063_chantable_data[22] },
690	{ 132, 5660, bwn_b2063_chantable_data[22] },
691	{ 136, 5680, bwn_b2063_chantable_data[22] },
692	{ 140, 5700, bwn_b2063_chantable_data[23] },
693	{ 149, 5745, bwn_b2063_chantable_data[23] },
694	{ 153, 5765, bwn_b2063_chantable_data[23] },
695	{ 157, 5785, bwn_b2063_chantable_data[23] },
696	{ 161, 5805, bwn_b2063_chantable_data[23] },
697	{ 165, 5825, bwn_b2063_chantable_data[23] },
698	{ 184, 4920, bwn_b2063_chantable_data[24] },
699	{ 188, 4940, bwn_b2063_chantable_data[25] },
700	{ 192, 4960, bwn_b2063_chantable_data[26] },
701	{ 196, 4980, bwn_b2063_chantable_data[27] },
702	{ 200, 5000, bwn_b2063_chantable_data[28] },
703	{ 204, 5020, bwn_b2063_chantable_data[29] },
704	{ 208, 5040, bwn_b2063_chantable_data[30] },
705	{ 212, 5060, bwn_b2063_chantable_data[31] },
706	{ 216, 5080, bwn_b2063_chantable_data[32] }
707};
708
709static const uint8_t bwn_b2062_chantable_data[22][12] = {
710	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
711	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
721	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
731	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
732};
733
734static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
735	{ 1, 2412, bwn_b2062_chantable_data[0] },
736	{ 2, 2417, bwn_b2062_chantable_data[0] },
737	{ 3, 2422, bwn_b2062_chantable_data[0] },
738	{ 4, 2427, bwn_b2062_chantable_data[0] },
739	{ 5, 2432, bwn_b2062_chantable_data[0] },
740	{ 6, 2437, bwn_b2062_chantable_data[0] },
741	{ 7, 2442, bwn_b2062_chantable_data[0] },
742	{ 8, 2447, bwn_b2062_chantable_data[0] },
743	{ 9, 2452, bwn_b2062_chantable_data[0] },
744	{ 10, 2457, bwn_b2062_chantable_data[0] },
745	{ 11, 2462, bwn_b2062_chantable_data[0] },
746	{ 12, 2467, bwn_b2062_chantable_data[0] },
747	{ 13, 2472, bwn_b2062_chantable_data[0] },
748	{ 14, 2484, bwn_b2062_chantable_data[0] },
749	{ 34, 5170, bwn_b2062_chantable_data[1] },
750	{ 38, 5190, bwn_b2062_chantable_data[2] },
751	{ 42, 5210, bwn_b2062_chantable_data[2] },
752	{ 46, 5230, bwn_b2062_chantable_data[3] },
753	{ 36, 5180, bwn_b2062_chantable_data[4] },
754	{ 40, 5200, bwn_b2062_chantable_data[5] },
755	{ 44, 5220, bwn_b2062_chantable_data[6] },
756	{ 48, 5240, bwn_b2062_chantable_data[3] },
757	{ 52, 5260, bwn_b2062_chantable_data[3] },
758	{ 56, 5280, bwn_b2062_chantable_data[3] },
759	{ 60, 5300, bwn_b2062_chantable_data[7] },
760	{ 64, 5320, bwn_b2062_chantable_data[8] },
761	{ 100, 5500, bwn_b2062_chantable_data[9] },
762	{ 104, 5520, bwn_b2062_chantable_data[10] },
763	{ 108, 5540, bwn_b2062_chantable_data[10] },
764	{ 112, 5560, bwn_b2062_chantable_data[10] },
765	{ 116, 5580, bwn_b2062_chantable_data[11] },
766	{ 120, 5600, bwn_b2062_chantable_data[12] },
767	{ 124, 5620, bwn_b2062_chantable_data[12] },
768	{ 128, 5640, bwn_b2062_chantable_data[12] },
769	{ 132, 5660, bwn_b2062_chantable_data[12] },
770	{ 136, 5680, bwn_b2062_chantable_data[12] },
771	{ 140, 5700, bwn_b2062_chantable_data[12] },
772	{ 149, 5745, bwn_b2062_chantable_data[12] },
773	{ 153, 5765, bwn_b2062_chantable_data[12] },
774	{ 157, 5785, bwn_b2062_chantable_data[12] },
775	{ 161, 5805, bwn_b2062_chantable_data[12] },
776	{ 165, 5825, bwn_b2062_chantable_data[12] },
777	{ 184, 4920, bwn_b2062_chantable_data[13] },
778	{ 188, 4940, bwn_b2062_chantable_data[14] },
779	{ 192, 4960, bwn_b2062_chantable_data[15] },
780	{ 196, 4980, bwn_b2062_chantable_data[16] },
781	{ 200, 5000, bwn_b2062_chantable_data[17] },
782	{ 204, 5020, bwn_b2062_chantable_data[18] },
783	{ 208, 5040, bwn_b2062_chantable_data[19] },
784	{ 212, 5060, bwn_b2062_chantable_data[20] },
785	{ 216, 5080, bwn_b2062_chantable_data[21] }
786};
787
788/* for LP PHY */
789static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
790	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
791	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
792	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
793	{ 13, -66, 13 }, { 14, -66, 13 },
794};
795
796/* for LP PHY */
797static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
798	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
799	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
800	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
801	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
802	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
803	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
804	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
805	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
806	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
807	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
808	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
809	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
810	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
811};
812
813static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
814
815static const uint8_t bwn_tab_sigsq_tbl[] = {
816	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
817	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
818	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
819	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
820	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
821	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
822};
823
824static const uint8_t bwn_tab_pllfrac_tbl[] = {
825	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
826	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
827};
828
829static const uint16_t bwn_tabl_iqlocal_tbl[] = {
830	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
831	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
832	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
833	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
834	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
835	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
836	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
840	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
842};
843
844static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
845static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
846static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
847static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
848static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
849const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
850
851#define	VENDOR_LED_ACT(vendor)				\
852{							\
853	.vid = PCI_VENDOR_##vendor,			\
854	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
855}
856
857static const struct {
858	uint16_t	vid;
859	uint8_t		led_act[BWN_LED_MAX];
860} bwn_vendor_led_act[] = {
861	VENDOR_LED_ACT(COMPAQ),
862	VENDOR_LED_ACT(ASUSTEK)
863};
864
865static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
866	{ BWN_VENDOR_LED_ACT_DEFAULT };
867
868#undef VENDOR_LED_ACT
869
870static const struct {
871	int		on_dur;
872	int		off_dur;
873} bwn_led_duration[109] = {
874	[0]	= { 400, 100 },
875	[2]	= { 150, 75 },
876	[4]	= { 90, 45 },
877	[11]	= { 66, 34 },
878	[12]	= { 53, 26 },
879	[18]	= { 42, 21 },
880	[22]	= { 35, 17 },
881	[24]	= { 32, 16 },
882	[36]	= { 21, 10 },
883	[48]	= { 16, 8 },
884	[72]	= { 11, 5 },
885	[96]	= { 9, 4 },
886	[108]	= { 7, 3 }
887};
888
889static const uint16_t bwn_wme_shm_offsets[] = {
890	[0] = BWN_WME_BESTEFFORT,
891	[1] = BWN_WME_BACKGROUND,
892	[2] = BWN_WME_VOICE,
893	[3] = BWN_WME_VIDEO,
894};
895
896static const struct siba_devid bwn_devs[] = {
897	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
898	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
899	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
900	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
901	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
902	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
903	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
904	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
905	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
906};
907
908static int
909bwn_probe(device_t dev)
910{
911	int i;
912
913	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
914		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
915		    siba_get_device(dev) == bwn_devs[i].sd_device &&
916		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
917			return (BUS_PROBE_DEFAULT);
918	}
919
920	return (ENXIO);
921}
922
923static int
924bwn_attach(device_t dev)
925{
926	struct bwn_mac *mac;
927	struct bwn_softc *sc = device_get_softc(dev);
928	int error, i, msic, reg;
929
930	sc->sc_dev = dev;
931#ifdef BWN_DEBUG
932	sc->sc_debug = bwn_debug;
933#endif
934
935	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
936		error = bwn_attach_pre(sc);
937		if (error != 0)
938			return (error);
939		bwn_sprom_bugfixes(dev);
940		sc->sc_flags |= BWN_FLAG_ATTACHED;
941	}
942
943	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
944		if (siba_get_pci_device(dev) != 0x4313 &&
945		    siba_get_pci_device(dev) != 0x431a &&
946		    siba_get_pci_device(dev) != 0x4321) {
947			device_printf(sc->sc_dev,
948			    "skip 802.11 cores\n");
949			return (ENODEV);
950		}
951	}
952
953	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
954	    M_NOWAIT | M_ZERO);
955	if (mac == NULL)
956		return (ENOMEM);
957	mac->mac_sc = sc;
958	mac->mac_status = BWN_MAC_STATUS_UNINIT;
959	if (bwn_bfp != 0)
960		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
961
962	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
963	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
964	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
965
966	error = bwn_attach_core(mac);
967	if (error)
968		goto fail0;
969	bwn_led_attach(mac);
970
971	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
972	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
973	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
974	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
975	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
976	    mac->mac_phy.rf_rev);
977	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
978		device_printf(sc->sc_dev, "DMA (%d bits)\n",
979		    mac->mac_method.dma.dmatype);
980	else
981		device_printf(sc->sc_dev, "PIO\n");
982
983	/*
984	 * setup PCI resources and interrupt.
985	 */
986	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
987		msic = pci_msi_count(dev);
988		if (bootverbose)
989			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
990	} else
991		msic = 0;
992
993	mac->mac_intr_spec = bwn_res_spec_legacy;
994	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
995		if (pci_alloc_msi(dev, &msic) == 0) {
996			device_printf(sc->sc_dev,
997			    "Using %d MSI messages\n", msic);
998			mac->mac_intr_spec = bwn_res_spec_msi;
999			mac->mac_msi = 1;
1000		}
1001	}
1002
1003	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1004	    mac->mac_res_irq);
1005	if (error) {
1006		device_printf(sc->sc_dev,
1007		    "couldn't allocate IRQ resources (%d)\n", error);
1008		goto fail1;
1009	}
1010
1011	if (mac->mac_msi == 0)
1012		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1013		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1014		    &mac->mac_intrhand[0]);
1015	else {
1016		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1017			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1018			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1019			    &mac->mac_intrhand[i]);
1020			if (error != 0) {
1021				device_printf(sc->sc_dev,
1022				    "couldn't setup interrupt (%d)\n", error);
1023				break;
1024			}
1025		}
1026	}
1027
1028	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1029
1030	/*
1031	 * calls attach-post routine
1032	 */
1033	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1034		bwn_attach_post(sc);
1035
1036	return (0);
1037fail1:
1038	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1039		pci_release_msi(dev);
1040fail0:
1041	free(mac, M_DEVBUF);
1042	return (error);
1043}
1044
1045static int
1046bwn_is_valid_ether_addr(uint8_t *addr)
1047{
1048	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1049
1050	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1051		return (FALSE);
1052
1053	return (TRUE);
1054}
1055
1056static int
1057bwn_attach_post(struct bwn_softc *sc)
1058{
1059	struct ieee80211com *ic;
1060	struct ifnet *ifp = sc->sc_ifp;
1061
1062	ic = ifp->if_l2com;
1063	ic->ic_ifp = ifp;
1064	/* XXX not right but it's not used anywhere important */
1065	ic->ic_phytype = IEEE80211_T_OFDM;
1066	ic->ic_opmode = IEEE80211_M_STA;
1067	ic->ic_caps =
1068		  IEEE80211_C_STA		/* station mode supported */
1069		| IEEE80211_C_MONITOR		/* monitor mode */
1070		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1071		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1072		| IEEE80211_C_SHSLOT		/* short slot time supported */
1073		| IEEE80211_C_WME		/* WME/WMM supported */
1074		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1075		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1076		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1077		;
1078
1079	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1080
1081	/* call MI attach routine. */
1082	ieee80211_ifattach(ic,
1083	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1084	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1085	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1086
1087	ic->ic_headroom = sizeof(struct bwn_txhdr);
1088
1089	/* override default methods */
1090	ic->ic_raw_xmit = bwn_raw_xmit;
1091	ic->ic_newassoc = bwn_newassoc;
1092	ic->ic_updateslot = bwn_updateslot;
1093	ic->ic_update_promisc = bwn_update_promisc;
1094	ic->ic_wme.wme_update = bwn_wme_update;
1095
1096	ic->ic_node_alloc = bwn_node_alloc;
1097	sc->sc_node_cleanup = ic->ic_node_cleanup;
1098	ic->ic_node_cleanup = bwn_node_cleanup;
1099
1100	ic->ic_scan_start = bwn_scan_start;
1101	ic->ic_scan_end = bwn_scan_end;
1102	ic->ic_set_channel = bwn_set_channel;
1103
1104	ic->ic_vap_create = bwn_vap_create;
1105	ic->ic_vap_delete = bwn_vap_delete;
1106
1107	ieee80211_radiotap_attach(ic,
1108	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1109	    BWN_TX_RADIOTAP_PRESENT,
1110	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1111	    BWN_RX_RADIOTAP_PRESENT);
1112
1113	bwn_sysctl_node(sc);
1114
1115	if (bootverbose)
1116		ieee80211_announce(ic);
1117	return (0);
1118}
1119
1120static void
1121bwn_phy_detach(struct bwn_mac *mac)
1122{
1123
1124	if (mac->mac_phy.detach != NULL)
1125		mac->mac_phy.detach(mac);
1126}
1127
1128static int
1129bwn_detach(device_t dev)
1130{
1131	struct bwn_softc *sc = device_get_softc(dev);
1132	struct bwn_mac *mac = sc->sc_curmac;
1133	struct ifnet *ifp = sc->sc_ifp;
1134	struct ieee80211com *ic = ifp->if_l2com;
1135	int i;
1136
1137	sc->sc_flags |= BWN_FLAG_INVALID;
1138
1139	if (device_is_attached(sc->sc_dev)) {
1140		bwn_stop(sc, 1);
1141		bwn_dma_free(mac);
1142		callout_drain(&sc->sc_led_blink_ch);
1143		callout_drain(&sc->sc_rfswitch_ch);
1144		callout_drain(&sc->sc_task_ch);
1145		callout_drain(&sc->sc_watchdog_ch);
1146		bwn_phy_detach(mac);
1147		if (ifp != NULL) {
1148			ieee80211_draintask(ic, &mac->mac_hwreset);
1149			ieee80211_draintask(ic, &mac->mac_txpower);
1150			ieee80211_ifdetach(ic);
1151			if_free(ifp);
1152		}
1153	}
1154	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1155	taskqueue_free(sc->sc_tq);
1156
1157	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1158		if (mac->mac_intrhand[i] != NULL) {
1159			bus_teardown_intr(dev, mac->mac_res_irq[i],
1160			    mac->mac_intrhand[i]);
1161			mac->mac_intrhand[i] = NULL;
1162		}
1163	}
1164	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1165	if (mac->mac_msi != 0)
1166		pci_release_msi(dev);
1167
1168	BWN_LOCK_DESTROY(sc);
1169	return (0);
1170}
1171
1172static int
1173bwn_attach_pre(struct bwn_softc *sc)
1174{
1175	struct ifnet *ifp;
1176	int error = 0;
1177
1178	BWN_LOCK_INIT(sc);
1179	TAILQ_INIT(&sc->sc_maclist);
1180	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1181	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1182	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1183
1184	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1185		taskqueue_thread_enqueue, &sc->sc_tq);
1186	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1187		"%s taskq", device_get_nameunit(sc->sc_dev));
1188
1189	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1190	if (ifp == NULL) {
1191		device_printf(sc->sc_dev, "can not if_alloc()\n");
1192		error = ENOSPC;
1193		goto fail;
1194	}
1195
1196	/* set these up early for if_printf use */
1197	if_initname(ifp, device_get_name(sc->sc_dev),
1198	    device_get_unit(sc->sc_dev));
1199
1200	ifp->if_softc = sc;
1201	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1202	ifp->if_init = bwn_init;
1203	ifp->if_ioctl = bwn_ioctl;
1204	ifp->if_start = bwn_start;
1205	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1206	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1207	IFQ_SET_READY(&ifp->if_snd);
1208
1209	return (0);
1210
1211fail:	BWN_LOCK_DESTROY(sc);
1212	return (error);
1213}
1214
1215static void
1216bwn_sprom_bugfixes(device_t dev)
1217{
1218#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1219	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1220	 (siba_get_pci_device(dev) == _device) &&			\
1221	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1222	 (siba_get_pci_subdevice(dev) == _subdevice))
1223
1224	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1225	    siba_get_pci_subdevice(dev) == 0x4e &&
1226	    siba_get_pci_revid(dev) > 0x40)
1227		siba_sprom_set_bf_lo(dev,
1228		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1229	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1230	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1231		siba_sprom_set_bf_lo(dev,
1232		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1233	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1234		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1235		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1236		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1237		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1238		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1239		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1240		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1241			siba_sprom_set_bf_lo(dev,
1242			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1243	}
1244#undef	BWN_ISDEV
1245}
1246
1247static int
1248bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1249{
1250#define	IS_RUNNING(ifp) \
1251	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1252	struct bwn_softc *sc = ifp->if_softc;
1253	struct ieee80211com *ic = ifp->if_l2com;
1254	struct ifreq *ifr = (struct ifreq *)data;
1255	int error = 0, startall;
1256
1257	switch (cmd) {
1258	case SIOCSIFFLAGS:
1259		startall = 0;
1260		if (IS_RUNNING(ifp)) {
1261			bwn_update_promisc(ifp);
1262		} else if (ifp->if_flags & IFF_UP) {
1263			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1264				bwn_init(sc);
1265				startall = 1;
1266			}
1267		} else
1268			bwn_stop(sc, 1);
1269		if (startall)
1270			ieee80211_start_all(ic);
1271		break;
1272	case SIOCGIFMEDIA:
1273		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1274		break;
1275	case SIOCGIFADDR:
1276		error = ether_ioctl(ifp, cmd, data);
1277		break;
1278	default:
1279		error = EINVAL;
1280		break;
1281	}
1282	return (error);
1283}
1284
1285static void
1286bwn_start(struct ifnet *ifp)
1287{
1288	struct bwn_softc *sc = ifp->if_softc;
1289
1290	BWN_LOCK(sc);
1291	bwn_start_locked(ifp);
1292	BWN_UNLOCK(sc);
1293}
1294
1295static void
1296bwn_start_locked(struct ifnet *ifp)
1297{
1298	struct bwn_softc *sc = ifp->if_softc;
1299	struct bwn_mac *mac = sc->sc_curmac;
1300	struct ieee80211_frame *wh;
1301	struct ieee80211_node *ni;
1302	struct ieee80211_key *k;
1303	struct mbuf *m;
1304
1305	BWN_ASSERT_LOCKED(sc);
1306
1307	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1308	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1309		return;
1310
1311	for (;;) {
1312		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1313		if (m == NULL)
1314			break;
1315
1316		if (bwn_tx_isfull(sc, m))
1317			break;
1318		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1319		if (ni == NULL) {
1320			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1321			m_freem(m);
1322			ifp->if_oerrors++;
1323			continue;
1324		}
1325		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1326		wh = mtod(m, struct ieee80211_frame *);
1327		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1328			k = ieee80211_crypto_encap(ni, m);
1329			if (k == NULL) {
1330				ieee80211_free_node(ni);
1331				m_freem(m);
1332				ifp->if_oerrors++;
1333				continue;
1334			}
1335		}
1336		wh = NULL;	/* Catch any invalid use */
1337
1338		if (bwn_tx_start(sc, ni, m) != 0) {
1339			if (ni != NULL)
1340				ieee80211_free_node(ni);
1341			ifp->if_oerrors++;
1342			continue;
1343		}
1344
1345		sc->sc_watchdog_timer = 5;
1346	}
1347}
1348
1349static int
1350bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1351{
1352	struct bwn_dma_ring *dr;
1353	struct bwn_mac *mac = sc->sc_curmac;
1354	struct bwn_pio_txqueue *tq;
1355	struct ifnet *ifp = sc->sc_ifp;
1356	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1357
1358	BWN_ASSERT_LOCKED(sc);
1359
1360	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1361		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1362		if (dr->dr_stop == 1 ||
1363		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1364			dr->dr_stop = 1;
1365			goto full;
1366		}
1367	} else {
1368		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1369		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1370		    pktlen > (tq->tq_size - tq->tq_used)) {
1371			tq->tq_stop = 1;
1372			goto full;
1373		}
1374	}
1375	return (0);
1376full:
1377	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1378	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1379	return (1);
1380}
1381
1382static int
1383bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1384{
1385	struct bwn_mac *mac = sc->sc_curmac;
1386	int error;
1387
1388	BWN_ASSERT_LOCKED(sc);
1389
1390	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1391		m_freem(m);
1392		return (ENXIO);
1393	}
1394
1395	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1396	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1397	if (error) {
1398		m_freem(m);
1399		return (error);
1400	}
1401	return (0);
1402}
1403
1404static int
1405bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1406{
1407	struct bwn_pio_txpkt *tp;
1408	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1409	struct bwn_softc *sc = mac->mac_sc;
1410	struct bwn_txhdr txhdr;
1411	struct mbuf *m_new;
1412	uint32_t ctl32;
1413	int error;
1414	uint16_t ctl16;
1415
1416	BWN_ASSERT_LOCKED(sc);
1417
1418	/* XXX TODO send packets after DTIM */
1419
1420	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1421	tp = TAILQ_FIRST(&tq->tq_pktlist);
1422	tp->tp_ni = ni;
1423	tp->tp_m = m;
1424
1425	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1426	if (error) {
1427		device_printf(sc->sc_dev, "tx fail\n");
1428		return (error);
1429	}
1430
1431	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1432	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1433	tq->tq_free--;
1434
1435	if (siba_get_revid(sc->sc_dev) >= 8) {
1436		/*
1437		 * XXX please removes m_defrag(9)
1438		 */
1439		m_new = m_defrag(m, M_DONTWAIT);
1440		if (m_new == NULL) {
1441			device_printf(sc->sc_dev,
1442			    "%s: can't defrag TX buffer\n",
1443			    __func__);
1444			return (ENOBUFS);
1445		}
1446		if (m_new->m_next != NULL)
1447			device_printf(sc->sc_dev,
1448			    "TODO: fragmented packets for PIO\n");
1449		tp->tp_m = m_new;
1450
1451		/* send HEADER */
1452		ctl32 = bwn_pio_write_multi_4(mac, tq,
1453		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1454			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1455		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1456		/* send BODY */
1457		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1458		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1459		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1460		    ctl32 | BWN_PIO8_TXCTL_EOF);
1461	} else {
1462		ctl16 = bwn_pio_write_multi_2(mac, tq,
1463		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1464			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1465		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1466		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1467		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1468		    ctl16 | BWN_PIO_TXCTL_EOF);
1469	}
1470
1471	return (0);
1472}
1473
1474static struct bwn_pio_txqueue *
1475bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1476{
1477
1478	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1479		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1480
1481	switch (prio) {
1482	case 0:
1483		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1484	case 1:
1485		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1486	case 2:
1487		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1488	case 3:
1489		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1490	}
1491	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1492	return (NULL);
1493}
1494
1495static int
1496bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1497{
1498#define	BWN_GET_TXHDRCACHE(slot)					\
1499	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1500	struct bwn_dma *dma = &mac->mac_method.dma;
1501	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1502	struct bwn_dmadesc_generic *desc;
1503	struct bwn_dmadesc_meta *mt;
1504	struct bwn_softc *sc = mac->mac_sc;
1505	struct ifnet *ifp = sc->sc_ifp;
1506	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1507	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1508
1509	BWN_ASSERT_LOCKED(sc);
1510	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1511
1512	/* XXX send after DTIM */
1513
1514	slot = bwn_dma_getslot(dr);
1515	dr->getdesc(dr, slot, &desc, &mt);
1516	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1517	    ("%s:%d: fail", __func__, __LINE__));
1518
1519	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1520	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1521	    BWN_DMA_COOKIE(dr, slot));
1522	if (error)
1523		goto fail;
1524	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1525	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1526	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1527	if (error) {
1528		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1529		    __func__, error);
1530		goto fail;
1531	}
1532	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1533	    BUS_DMASYNC_PREWRITE);
1534	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1535	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1536	    BUS_DMASYNC_PREWRITE);
1537
1538	slot = bwn_dma_getslot(dr);
1539	dr->getdesc(dr, slot, &desc, &mt);
1540	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1541	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1542	mt->mt_m = m;
1543	mt->mt_ni = ni;
1544
1545	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1546	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1547	if (error && error != EFBIG) {
1548		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1549		    __func__, error);
1550		goto fail;
1551	}
1552	if (error) {    /* error == EFBIG */
1553		struct mbuf *m_new;
1554
1555		m_new = m_defrag(m, M_DONTWAIT);
1556		if (m_new == NULL) {
1557			if_printf(ifp, "%s: can't defrag TX buffer\n",
1558			    __func__);
1559			error = ENOBUFS;
1560			goto fail;
1561		} else {
1562			m = m_new;
1563		}
1564
1565		mt->mt_m = m;
1566		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1567		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1568		if (error) {
1569			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1570			    __func__, error);
1571			goto fail;
1572		}
1573	}
1574	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1575	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1576	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1577	    BUS_DMASYNC_PREWRITE);
1578
1579	/* XXX send after DTIM */
1580
1581	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1582	return (0);
1583fail:
1584	dr->dr_curslot = backup[0];
1585	dr->dr_usedslot = backup[1];
1586	return (error);
1587#undef BWN_GET_TXHDRCACHE
1588}
1589
1590static void
1591bwn_watchdog(void *arg)
1592{
1593	struct bwn_softc *sc = arg;
1594	struct ifnet *ifp = sc->sc_ifp;
1595
1596	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1597		if_printf(ifp, "device timeout\n");
1598		ifp->if_oerrors++;
1599	}
1600	callout_schedule(&sc->sc_watchdog_ch, hz);
1601}
1602
1603static int
1604bwn_attach_core(struct bwn_mac *mac)
1605{
1606	struct bwn_softc *sc = mac->mac_sc;
1607	int error, have_bg = 0, have_a = 0;
1608	uint32_t high;
1609
1610	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1611	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1612
1613	siba_powerup(sc->sc_dev, 0);
1614
1615	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1616	bwn_reset_core(mac,
1617	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1618	error = bwn_phy_getinfo(mac, high);
1619	if (error)
1620		goto fail;
1621
1622	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1623	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1624	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1625	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1626	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1627		have_a = have_bg = 0;
1628		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1629			have_a = 1;
1630		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1631		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1632		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1633			have_bg = 1;
1634		else
1635			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1636			    mac->mac_phy.type));
1637	}
1638	/* XXX turns off PHY A because it's not supported */
1639	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1640	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1641		have_a = 0;
1642		have_bg = 1;
1643	}
1644
1645	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1646		mac->mac_phy.attach = bwn_phy_g_attach;
1647		mac->mac_phy.detach = bwn_phy_g_detach;
1648		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1649		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1650		mac->mac_phy.init = bwn_phy_g_init;
1651		mac->mac_phy.exit = bwn_phy_g_exit;
1652		mac->mac_phy.phy_read = bwn_phy_g_read;
1653		mac->mac_phy.phy_write = bwn_phy_g_write;
1654		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1655		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1656		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1657		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1658		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1659		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1660		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1661		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1662		mac->mac_phy.set_im = bwn_phy_g_im;
1663		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1664		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1665		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1666		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1667	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1668		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1669		mac->mac_phy.init = bwn_phy_lp_init;
1670		mac->mac_phy.phy_read = bwn_phy_lp_read;
1671		mac->mac_phy.phy_write = bwn_phy_lp_write;
1672		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1673		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1674		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1675		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1676		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1677		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1678		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1679		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1680		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1681	} else {
1682		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1683		    mac->mac_phy.type);
1684		error = ENXIO;
1685		goto fail;
1686	}
1687
1688	mac->mac_phy.gmode = have_bg;
1689	if (mac->mac_phy.attach != NULL) {
1690		error = mac->mac_phy.attach(mac);
1691		if (error) {
1692			device_printf(sc->sc_dev, "failed\n");
1693			goto fail;
1694		}
1695	}
1696
1697	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1698
1699	error = bwn_chiptest(mac);
1700	if (error)
1701		goto fail;
1702	error = bwn_setup_channels(mac, have_bg, have_a);
1703	if (error) {
1704		device_printf(sc->sc_dev, "failed to setup channels\n");
1705		goto fail;
1706	}
1707
1708	if (sc->sc_curmac == NULL)
1709		sc->sc_curmac = mac;
1710
1711	error = bwn_dma_attach(mac);
1712	if (error != 0) {
1713		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1714		goto fail;
1715	}
1716
1717	mac->mac_phy.switch_analog(mac, 0);
1718
1719	siba_dev_down(sc->sc_dev, 0);
1720fail:
1721	siba_powerdown(sc->sc_dev);
1722	return (error);
1723}
1724
1725static void
1726bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1727{
1728	struct bwn_softc *sc = mac->mac_sc;
1729	uint32_t low, ctl;
1730
1731	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1732
1733	siba_dev_up(sc->sc_dev, flags);
1734	DELAY(2000);
1735
1736	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1737	    ~BWN_TGSLOW_PHYRESET;
1738	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1739	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1740	DELAY(1000);
1741	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1742	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1743	DELAY(1000);
1744
1745	if (mac->mac_phy.switch_analog != NULL)
1746		mac->mac_phy.switch_analog(mac, 1);
1747
1748	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1749	if (flags & BWN_TGSLOW_SUPPORT_G)
1750		ctl |= BWN_MACCTL_GMODE;
1751	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1752}
1753
1754static int
1755bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1756{
1757	struct bwn_phy *phy = &mac->mac_phy;
1758	struct bwn_softc *sc = mac->mac_sc;
1759	uint32_t tmp;
1760
1761	/* PHY */
1762	tmp = BWN_READ_2(mac, BWN_PHYVER);
1763	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1764	phy->rf_on = 1;
1765	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1766	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1767	phy->rev = (tmp & BWN_PHYVER_VERSION);
1768	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1769	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1770		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1771	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1772	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1773	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1774		goto unsupphy;
1775
1776	/* RADIO */
1777	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1778		if (siba_get_chiprev(sc->sc_dev) == 0)
1779			tmp = 0x3205017f;
1780		else if (siba_get_chiprev(sc->sc_dev) == 1)
1781			tmp = 0x4205017f;
1782		else
1783			tmp = 0x5205017f;
1784	} else {
1785		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1786		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1787		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1788		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1789	}
1790	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1791	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1792	phy->rf_manuf = (tmp & 0x00000fff);
1793	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1794		goto unsupradio;
1795	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1796	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1797	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1798	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1799	    (phy->type == BWN_PHYTYPE_N &&
1800	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1801	    (phy->type == BWN_PHYTYPE_LP &&
1802	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1803		goto unsupradio;
1804
1805	return (0);
1806unsupphy:
1807	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1808	    "analog %#x)\n",
1809	    phy->type, phy->rev, phy->analog);
1810	return (ENXIO);
1811unsupradio:
1812	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1813	    "rev %#x)\n",
1814	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1815	return (ENXIO);
1816}
1817
1818static int
1819bwn_chiptest(struct bwn_mac *mac)
1820{
1821#define	TESTVAL0	0x55aaaa55
1822#define	TESTVAL1	0xaa5555aa
1823	struct bwn_softc *sc = mac->mac_sc;
1824	uint32_t v, backup;
1825
1826	BWN_LOCK(sc);
1827
1828	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1829
1830	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1831	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1832		goto error;
1833	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1834	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1835		goto error;
1836
1837	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1838
1839	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1840	    (siba_get_revid(sc->sc_dev) <= 10)) {
1841		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1842		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1843		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1844			goto error;
1845		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1846			goto error;
1847	}
1848	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1849
1850	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1851	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1852		goto error;
1853
1854	BWN_UNLOCK(sc);
1855	return (0);
1856error:
1857	BWN_UNLOCK(sc);
1858	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1859	return (ENODEV);
1860}
1861
1862#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1863#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1864
1865static int
1866bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1867{
1868	struct bwn_softc *sc = mac->mac_sc;
1869	struct ifnet *ifp = sc->sc_ifp;
1870	struct ieee80211com *ic = ifp->if_l2com;
1871
1872	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1873	ic->ic_nchans = 0;
1874
1875	if (have_bg)
1876		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1877		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1878	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1879		if (have_a)
1880			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1881			    &ic->ic_nchans, &bwn_chantable_n,
1882			    IEEE80211_CHAN_HTA);
1883	} else {
1884		if (have_a)
1885			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1886			    &ic->ic_nchans, &bwn_chantable_a,
1887			    IEEE80211_CHAN_A);
1888	}
1889
1890	mac->mac_phy.supports_2ghz = have_bg;
1891	mac->mac_phy.supports_5ghz = have_a;
1892
1893	return (ic->ic_nchans == 0 ? ENXIO : 0);
1894}
1895
1896static uint32_t
1897bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1898{
1899	uint32_t ret;
1900
1901	BWN_ASSERT_LOCKED(mac->mac_sc);
1902
1903	if (way == BWN_SHARED) {
1904		KASSERT((offset & 0x0001) == 0,
1905		    ("%s:%d warn", __func__, __LINE__));
1906		if (offset & 0x0003) {
1907			bwn_shm_ctlword(mac, way, offset >> 2);
1908			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1909			ret <<= 16;
1910			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1911			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1912			goto out;
1913		}
1914		offset >>= 2;
1915	}
1916	bwn_shm_ctlword(mac, way, offset);
1917	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1918out:
1919	return (ret);
1920}
1921
1922static uint16_t
1923bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1924{
1925	uint16_t ret;
1926
1927	BWN_ASSERT_LOCKED(mac->mac_sc);
1928
1929	if (way == BWN_SHARED) {
1930		KASSERT((offset & 0x0001) == 0,
1931		    ("%s:%d warn", __func__, __LINE__));
1932		if (offset & 0x0003) {
1933			bwn_shm_ctlword(mac, way, offset >> 2);
1934			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1935			goto out;
1936		}
1937		offset >>= 2;
1938	}
1939	bwn_shm_ctlword(mac, way, offset);
1940	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1941out:
1942
1943	return (ret);
1944}
1945
1946static void
1947bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1948    uint16_t offset)
1949{
1950	uint32_t control;
1951
1952	control = way;
1953	control <<= 16;
1954	control |= offset;
1955	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1956}
1957
1958static void
1959bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1960    uint32_t value)
1961{
1962	BWN_ASSERT_LOCKED(mac->mac_sc);
1963
1964	if (way == BWN_SHARED) {
1965		KASSERT((offset & 0x0001) == 0,
1966		    ("%s:%d warn", __func__, __LINE__));
1967		if (offset & 0x0003) {
1968			bwn_shm_ctlword(mac, way, offset >> 2);
1969			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1970				    (value >> 16) & 0xffff);
1971			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1972			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1973			return;
1974		}
1975		offset >>= 2;
1976	}
1977	bwn_shm_ctlword(mac, way, offset);
1978	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1979}
1980
1981static void
1982bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1983    uint16_t value)
1984{
1985	BWN_ASSERT_LOCKED(mac->mac_sc);
1986
1987	if (way == BWN_SHARED) {
1988		KASSERT((offset & 0x0001) == 0,
1989		    ("%s:%d warn", __func__, __LINE__));
1990		if (offset & 0x0003) {
1991			bwn_shm_ctlword(mac, way, offset >> 2);
1992			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1993			return;
1994		}
1995		offset >>= 2;
1996	}
1997	bwn_shm_ctlword(mac, way, offset);
1998	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1999}
2000
2001static void
2002bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2003    int txpow)
2004{
2005
2006	c->ic_freq = freq;
2007	c->ic_flags = flags;
2008	c->ic_ieee = ieee;
2009	c->ic_minpower = 0;
2010	c->ic_maxpower = 2 * txpow;
2011	c->ic_maxregpower = txpow;
2012}
2013
2014static void
2015bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2016    const struct bwn_channelinfo *ci, int flags)
2017{
2018	struct ieee80211_channel *c;
2019	int i;
2020
2021	c = &chans[*nchans];
2022
2023	for (i = 0; i < ci->nchannels; i++) {
2024		const struct bwn_channel *hc;
2025
2026		hc = &ci->channels[i];
2027		if (*nchans >= maxchans)
2028			break;
2029		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2030		c++, (*nchans)++;
2031		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2032			/* g channel have a separate b-only entry */
2033			if (*nchans >= maxchans)
2034				break;
2035			c[0] = c[-1];
2036			c[-1].ic_flags = IEEE80211_CHAN_B;
2037			c++, (*nchans)++;
2038		}
2039		if (flags == IEEE80211_CHAN_HTG) {
2040			/* HT g channel have a separate g-only entry */
2041			if (*nchans >= maxchans)
2042				break;
2043			c[-1].ic_flags = IEEE80211_CHAN_G;
2044			c[0] = c[-1];
2045			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2046			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2047			c++, (*nchans)++;
2048		}
2049		if (flags == IEEE80211_CHAN_HTA) {
2050			/* HT a channel have a separate a-only entry */
2051			if (*nchans >= maxchans)
2052				break;
2053			c[-1].ic_flags = IEEE80211_CHAN_A;
2054			c[0] = c[-1];
2055			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2056			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2057			c++, (*nchans)++;
2058		}
2059	}
2060}
2061
2062static int
2063bwn_phy_g_attach(struct bwn_mac *mac)
2064{
2065	struct bwn_softc *sc = mac->mac_sc;
2066	struct bwn_phy *phy = &mac->mac_phy;
2067	struct bwn_phy_g *pg = &phy->phy_g;
2068	unsigned int i;
2069	int16_t pab0, pab1, pab2;
2070	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2071	int8_t bg;
2072
2073	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2074	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2075	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2076	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2077
2078	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2079		device_printf(sc->sc_dev, "not supported anymore\n");
2080
2081	pg->pg_flags = 0;
2082	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2083	    pab2 == -1) {
2084		pg->pg_idletssi = 52;
2085		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2086		return (0);
2087	}
2088
2089	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2090	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2091	if (pg->pg_tssi2dbm == NULL) {
2092		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2093		return (ENOMEM);
2094	}
2095	for (i = 0; i < 64; i++) {
2096		int32_t m1, m2, f, q, delta;
2097		int8_t j = 0;
2098
2099		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2100		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2101		f = 256;
2102
2103		do {
2104			if (j > 15) {
2105				device_printf(sc->sc_dev,
2106				    "failed to generate tssi2dBm\n");
2107				free(pg->pg_tssi2dbm, M_DEVBUF);
2108				return (ENOMEM);
2109			}
2110			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2111			    f, 2048);
2112			delta = abs(q - f);
2113			f = q;
2114			j++;
2115		} while (delta >= 2);
2116
2117		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2118		    128);
2119	}
2120
2121	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2122	return (0);
2123}
2124
2125static void
2126bwn_phy_g_detach(struct bwn_mac *mac)
2127{
2128	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2129
2130	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2131		free(pg->pg_tssi2dbm, M_DEVBUF);
2132		pg->pg_tssi2dbm = NULL;
2133	}
2134	pg->pg_flags = 0;
2135}
2136
2137static void
2138bwn_phy_g_init_pre(struct bwn_mac *mac)
2139{
2140	struct bwn_phy *phy = &mac->mac_phy;
2141	struct bwn_phy_g *pg = &phy->phy_g;
2142	void *tssi2dbm;
2143	int idletssi;
2144	unsigned int i;
2145
2146	tssi2dbm = pg->pg_tssi2dbm;
2147	idletssi = pg->pg_idletssi;
2148
2149	memset(pg, 0, sizeof(*pg));
2150
2151	pg->pg_tssi2dbm = tssi2dbm;
2152	pg->pg_idletssi = idletssi;
2153
2154	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2155
2156	for (i = 0; i < N(pg->pg_nrssi); i++)
2157		pg->pg_nrssi[i] = -1000;
2158	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2159		pg->pg_nrssi_lt[i] = i;
2160	pg->pg_lofcal = 0xffff;
2161	pg->pg_initval = 0xffff;
2162	pg->pg_immode = BWN_IMMODE_NONE;
2163	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2164	pg->pg_avgtssi = 0xff;
2165
2166	pg->pg_loctl.tx_bias = 0xff;
2167	TAILQ_INIT(&pg->pg_loctl.calib_list);
2168}
2169
2170static int
2171bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2172{
2173	struct bwn_phy *phy = &mac->mac_phy;
2174	struct bwn_phy_g *pg = &phy->phy_g;
2175	struct bwn_softc *sc = mac->mac_sc;
2176	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2177	static const struct bwn_rfatt rfatt0[] = {
2178		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2179		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2180		{ 3, 1 }, { 4, 1 }
2181	};
2182	static const struct bwn_rfatt rfatt1[] = {
2183		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2184		{ 14, 1 }
2185	};
2186	static const struct bwn_rfatt rfatt2[] = {
2187		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2188		{ 9, 1 }
2189	};
2190	static const struct bwn_bbatt bbatt_0[] = {
2191		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2192	};
2193
2194	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2195
2196	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2197		pg->pg_bbatt.att = 0;
2198	else
2199		pg->pg_bbatt.att = 2;
2200
2201	/* prepare Radio Attenuation */
2202	pg->pg_rfatt.padmix = 0;
2203
2204	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2205	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2206		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2207			pg->pg_rfatt.att = 2;
2208			goto done;
2209		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2210			pg->pg_rfatt.att = 3;
2211			goto done;
2212		}
2213	}
2214
2215	if (phy->type == BWN_PHYTYPE_A) {
2216		pg->pg_rfatt.att = 0x60;
2217		goto done;
2218	}
2219
2220	switch (phy->rf_ver) {
2221	case 0x2050:
2222		switch (phy->rf_rev) {
2223		case 0:
2224			pg->pg_rfatt.att = 5;
2225			goto done;
2226		case 1:
2227			if (phy->type == BWN_PHYTYPE_G) {
2228				if (siba_get_pci_subvendor(sc->sc_dev) ==
2229				    SIBA_BOARDVENDOR_BCM &&
2230				    siba_get_pci_subdevice(sc->sc_dev) ==
2231				    SIBA_BOARD_BCM4309G &&
2232				    siba_get_pci_revid(sc->sc_dev) >= 30)
2233					pg->pg_rfatt.att = 3;
2234				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2235				    SIBA_BOARDVENDOR_BCM &&
2236				    siba_get_pci_subdevice(sc->sc_dev) ==
2237				    SIBA_BOARD_BU4306)
2238					pg->pg_rfatt.att = 3;
2239				else
2240					pg->pg_rfatt.att = 1;
2241			} else {
2242				if (siba_get_pci_subvendor(sc->sc_dev) ==
2243				    SIBA_BOARDVENDOR_BCM &&
2244				    siba_get_pci_subdevice(sc->sc_dev) ==
2245				    SIBA_BOARD_BCM4309G &&
2246				    siba_get_pci_revid(sc->sc_dev) >= 30)
2247					pg->pg_rfatt.att = 7;
2248				else
2249					pg->pg_rfatt.att = 6;
2250			}
2251			goto done;
2252		case 2:
2253			if (phy->type == BWN_PHYTYPE_G) {
2254				if (siba_get_pci_subvendor(sc->sc_dev) ==
2255				    SIBA_BOARDVENDOR_BCM &&
2256				    siba_get_pci_subdevice(sc->sc_dev) ==
2257				    SIBA_BOARD_BCM4309G &&
2258				    siba_get_pci_revid(sc->sc_dev) >= 30)
2259					pg->pg_rfatt.att = 3;
2260				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2261				    SIBA_BOARDVENDOR_BCM &&
2262				    siba_get_pci_subdevice(sc->sc_dev) ==
2263				    SIBA_BOARD_BU4306)
2264					pg->pg_rfatt.att = 5;
2265				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2266					pg->pg_rfatt.att = 4;
2267				else
2268					pg->pg_rfatt.att = 3;
2269			} else
2270				pg->pg_rfatt.att = 6;
2271			goto done;
2272		case 3:
2273			pg->pg_rfatt.att = 5;
2274			goto done;
2275		case 4:
2276		case 5:
2277			pg->pg_rfatt.att = 1;
2278			goto done;
2279		case 6:
2280		case 7:
2281			pg->pg_rfatt.att = 5;
2282			goto done;
2283		case 8:
2284			pg->pg_rfatt.att = 0xa;
2285			pg->pg_rfatt.padmix = 1;
2286			goto done;
2287		case 9:
2288		default:
2289			pg->pg_rfatt.att = 5;
2290			goto done;
2291		}
2292		break;
2293	case 0x2053:
2294		switch (phy->rf_rev) {
2295		case 1:
2296			pg->pg_rfatt.att = 6;
2297			goto done;
2298		}
2299		break;
2300	}
2301	pg->pg_rfatt.att = 5;
2302done:
2303	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2304
2305	if (!bwn_has_hwpctl(mac)) {
2306		lo->rfatt.array = rfatt0;
2307		lo->rfatt.len = N(rfatt0);
2308		lo->rfatt.min = 0;
2309		lo->rfatt.max = 9;
2310		goto genbbatt;
2311	}
2312	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2313		lo->rfatt.array = rfatt1;
2314		lo->rfatt.len = N(rfatt1);
2315		lo->rfatt.min = 0;
2316		lo->rfatt.max = 14;
2317		goto genbbatt;
2318	}
2319	lo->rfatt.array = rfatt2;
2320	lo->rfatt.len = N(rfatt2);
2321	lo->rfatt.min = 0;
2322	lo->rfatt.max = 9;
2323genbbatt:
2324	lo->bbatt.array = bbatt_0;
2325	lo->bbatt.len = N(bbatt_0);
2326	lo->bbatt.min = 0;
2327	lo->bbatt.max = 8;
2328
2329	BWN_READ_4(mac, BWN_MACCTL);
2330	if (phy->rev == 1) {
2331		phy->gmode = 0;
2332		bwn_reset_core(mac, 0);
2333		bwn_phy_g_init_sub(mac);
2334		phy->gmode = 1;
2335		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2336	}
2337	return (0);
2338}
2339
2340static uint16_t
2341bwn_phy_g_txctl(struct bwn_mac *mac)
2342{
2343	struct bwn_phy *phy = &mac->mac_phy;
2344
2345	if (phy->rf_ver != 0x2050)
2346		return (0);
2347	if (phy->rf_rev == 1)
2348		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2349	if (phy->rf_rev < 6)
2350		return (BWN_TXCTL_PA2DB);
2351	if (phy->rf_rev == 8)
2352		return (BWN_TXCTL_TXMIX);
2353	return (0);
2354}
2355
2356static int
2357bwn_phy_g_init(struct bwn_mac *mac)
2358{
2359
2360	bwn_phy_g_init_sub(mac);
2361	return (0);
2362}
2363
2364static void
2365bwn_phy_g_exit(struct bwn_mac *mac)
2366{
2367	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2368	struct bwn_lo_calib *cal, *tmp;
2369
2370	if (lo == NULL)
2371		return;
2372	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2373		TAILQ_REMOVE(&lo->calib_list, cal, list);
2374		free(cal, M_DEVBUF);
2375	}
2376}
2377
2378static uint16_t
2379bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2380{
2381
2382	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2383	return (BWN_READ_2(mac, BWN_PHYDATA));
2384}
2385
2386static void
2387bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2388{
2389
2390	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2391	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2392}
2393
2394static uint16_t
2395bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2396{
2397
2398	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2399	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2400	return (BWN_READ_2(mac, BWN_RFDATALO));
2401}
2402
2403static void
2404bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2405{
2406
2407	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2408	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2409	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2410}
2411
2412static int
2413bwn_phy_g_hwpctl(struct bwn_mac *mac)
2414{
2415
2416	return (mac->mac_phy.rev >= 6);
2417}
2418
2419static void
2420bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2421{
2422	struct bwn_phy *phy = &mac->mac_phy;
2423	struct bwn_phy_g *pg = &phy->phy_g;
2424	unsigned int channel;
2425	uint16_t rfover, rfoverval;
2426
2427	if (on) {
2428		if (phy->rf_on)
2429			return;
2430
2431		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2432		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2433		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2434		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2435			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2436			    pg->pg_radioctx_over);
2437			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2438			    pg->pg_radioctx_overval);
2439			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2440		}
2441		channel = phy->chan;
2442		bwn_phy_g_switch_chan(mac, 6, 1);
2443		bwn_phy_g_switch_chan(mac, channel, 0);
2444		return;
2445	}
2446
2447	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2448	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2449	pg->pg_radioctx_over = rfover;
2450	pg->pg_radioctx_overval = rfoverval;
2451	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2452	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2453	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2454}
2455
2456static int
2457bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2458{
2459
2460	if ((newchan < 1) || (newchan > 14))
2461		return (EINVAL);
2462	bwn_phy_g_switch_chan(mac, newchan, 0);
2463
2464	return (0);
2465}
2466
2467static uint32_t
2468bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2469{
2470
2471	return (1);
2472}
2473
2474static void
2475bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2476{
2477	struct bwn_phy *phy = &mac->mac_phy;
2478	uint64_t hf;
2479	int autodiv = 0;
2480	uint16_t tmp;
2481
2482	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2483		autodiv = 1;
2484
2485	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2486	bwn_hf_write(mac, hf);
2487
2488	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2489	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2490	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2491		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2492
2493	if (autodiv) {
2494		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2495		if (antenna == BWN_ANTAUTO1)
2496			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2497		else
2498			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2499		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2500	}
2501	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2502	if (autodiv)
2503		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2504	else
2505		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2506	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2507	if (phy->rev >= 2) {
2508		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2509		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2510		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2511		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2512		    0x15);
2513		if (phy->rev == 2)
2514			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2515		else
2516			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2517			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2518			    8);
2519	}
2520	if (phy->rev >= 6)
2521		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2522
2523	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2524	bwn_hf_write(mac, hf);
2525}
2526
2527static int
2528bwn_phy_g_im(struct bwn_mac *mac, int mode)
2529{
2530	struct bwn_phy *phy = &mac->mac_phy;
2531	struct bwn_phy_g *pg = &phy->phy_g;
2532
2533	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2534	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2535
2536	if (phy->rev == 0 || !phy->gmode)
2537		return (ENODEV);
2538
2539	pg->pg_aci_wlan_automatic = 0;
2540	return (0);
2541}
2542
2543static int
2544bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2545{
2546	struct bwn_phy *phy = &mac->mac_phy;
2547	struct bwn_phy_g *pg = &phy->phy_g;
2548	struct bwn_softc *sc = mac->mac_sc;
2549	unsigned int tssi;
2550	int cck, ofdm;
2551	int power;
2552	int rfatt, bbatt;
2553	unsigned int max;
2554
2555	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2556
2557	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2558	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2559	if (cck < 0 && ofdm < 0) {
2560		if (ignore_tssi == 0)
2561			return (BWN_TXPWR_RES_DONE);
2562		cck = 0;
2563		ofdm = 0;
2564	}
2565	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2566	if (pg->pg_avgtssi != 0xff)
2567		tssi = (tssi + pg->pg_avgtssi) / 2;
2568	pg->pg_avgtssi = tssi;
2569	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2570
2571	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2572	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2573		max -= 3;
2574	if (max >= 120) {
2575		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2576		max = 80;
2577		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2578	}
2579
2580	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2581	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2582	     tssi, 0x00), 0x3f)]);
2583	if (power == 0)
2584		return (BWN_TXPWR_RES_DONE);
2585
2586	rfatt = -((power + 7) / 8);
2587	bbatt = (-(power / 2)) - (4 * rfatt);
2588	if ((rfatt == 0) && (bbatt == 0))
2589		return (BWN_TXPWR_RES_DONE);
2590	pg->pg_bbatt_delta = bbatt;
2591	pg->pg_rfatt_delta = rfatt;
2592	return (BWN_TXPWR_RES_NEED_ADJUST);
2593}
2594
2595static void
2596bwn_phy_g_set_txpwr(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	int rfatt, bbatt;
2602	uint8_t txctl;
2603
2604	bwn_mac_suspend(mac);
2605
2606	BWN_ASSERT_LOCKED(sc);
2607
2608	bbatt = pg->pg_bbatt.att;
2609	bbatt += pg->pg_bbatt_delta;
2610	rfatt = pg->pg_rfatt.att;
2611	rfatt += pg->pg_rfatt_delta;
2612
2613	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2614	txctl = pg->pg_txctl;
2615	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2616		if (rfatt <= 1) {
2617			if (txctl == 0) {
2618				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2619				rfatt += 2;
2620				bbatt += 2;
2621			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2622			    BWN_BFL_PACTRL) {
2623				bbatt += 4 * (rfatt - 2);
2624				rfatt = 2;
2625			}
2626		} else if (rfatt > 4 && txctl) {
2627			txctl = 0;
2628			if (bbatt < 3) {
2629				rfatt -= 3;
2630				bbatt += 2;
2631			} else {
2632				rfatt -= 2;
2633				bbatt -= 2;
2634			}
2635		}
2636	}
2637	pg->pg_txctl = txctl;
2638	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2639	pg->pg_rfatt.att = rfatt;
2640	pg->pg_bbatt.att = bbatt;
2641
2642	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2643
2644	bwn_phy_lock(mac);
2645	bwn_rf_lock(mac);
2646	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2647	    pg->pg_txctl);
2648	bwn_rf_unlock(mac);
2649	bwn_phy_unlock(mac);
2650
2651	bwn_mac_enable(mac);
2652}
2653
2654static void
2655bwn_phy_g_task_15s(struct bwn_mac *mac)
2656{
2657	struct bwn_phy *phy = &mac->mac_phy;
2658	struct bwn_phy_g *pg = &phy->phy_g;
2659	struct bwn_softc *sc = mac->mac_sc;
2660	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2661	unsigned long expire, now;
2662	struct bwn_lo_calib *cal, *tmp;
2663	uint8_t expired = 0;
2664
2665	bwn_mac_suspend(mac);
2666
2667	if (lo == NULL)
2668		goto fail;
2669
2670	BWN_GETTIME(now);
2671	if (bwn_has_hwpctl(mac)) {
2672		expire = now - BWN_LO_PWRVEC_EXPIRE;
2673		if (time_before(lo->pwr_vec_read_time, expire)) {
2674			bwn_lo_get_powervector(mac);
2675			bwn_phy_g_dc_lookup_init(mac, 0);
2676		}
2677		goto fail;
2678	}
2679
2680	expire = now - BWN_LO_CALIB_EXPIRE;
2681	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2682		if (!time_before(cal->calib_time, expire))
2683			continue;
2684		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2685		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2686			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2687			expired = 1;
2688		}
2689
2690		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2691		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2692		    cal->ctl.i, cal->ctl.q);
2693
2694		TAILQ_REMOVE(&lo->calib_list, cal, list);
2695		free(cal, M_DEVBUF);
2696	}
2697	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2698		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2699		    &pg->pg_rfatt);
2700		if (cal == NULL) {
2701			device_printf(sc->sc_dev,
2702			    "failed to recalibrate LO\n");
2703			goto fail;
2704		}
2705		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2706		bwn_lo_write(mac, &cal->ctl);
2707	}
2708
2709fail:
2710	bwn_mac_enable(mac);
2711}
2712
2713static void
2714bwn_phy_g_task_60s(struct bwn_mac *mac)
2715{
2716	struct bwn_phy *phy = &mac->mac_phy;
2717	struct bwn_softc *sc = mac->mac_sc;
2718	uint8_t old = phy->chan;
2719
2720	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2721		return;
2722
2723	bwn_mac_suspend(mac);
2724	bwn_nrssi_slope_11g(mac);
2725	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2726		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2727		bwn_switch_channel(mac, old);
2728	}
2729	bwn_mac_enable(mac);
2730}
2731
2732static void
2733bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2734{
2735
2736	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2737}
2738
2739static int
2740bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2741	const struct ieee80211_bpf_params *params)
2742{
2743	struct ieee80211com *ic = ni->ni_ic;
2744	struct ifnet *ifp = ic->ic_ifp;
2745	struct bwn_softc *sc = ifp->if_softc;
2746	struct bwn_mac *mac = sc->sc_curmac;
2747
2748	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2749	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2750		ieee80211_free_node(ni);
2751		m_freem(m);
2752		return (ENETDOWN);
2753	}
2754
2755	BWN_LOCK(sc);
2756	if (bwn_tx_isfull(sc, m)) {
2757		ieee80211_free_node(ni);
2758		m_freem(m);
2759		ifp->if_oerrors++;
2760		BWN_UNLOCK(sc);
2761		return (ENOBUFS);
2762	}
2763
2764	if (bwn_tx_start(sc, ni, m) != 0) {
2765		if (ni != NULL)
2766			ieee80211_free_node(ni);
2767		ifp->if_oerrors++;
2768	}
2769	sc->sc_watchdog_timer = 5;
2770	BWN_UNLOCK(sc);
2771	return (0);
2772}
2773
2774/*
2775 * Setup driver-specific state for a newly associated node.
2776 * Note that we're called also on a re-associate, the isnew
2777 * param tells us if this is the first time or not.
2778 */
2779static void
2780bwn_newassoc(struct ieee80211_node *ni, int isnew)
2781{
2782	struct ieee80211vap *vap = ni->ni_vap;
2783
2784	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2785	    &BWN_NODE(ni)->bn_amn, ni);
2786}
2787
2788/*
2789 * Callback from the 802.11 layer to update the slot time
2790 * based on the current setting.  We use it to notify the
2791 * firmware of ERP changes and the f/w takes care of things
2792 * like slot time and preamble.
2793 */
2794static void
2795bwn_updateslot(struct ifnet *ifp)
2796{
2797	struct bwn_softc *sc = ifp->if_softc;
2798	struct ieee80211com *ic = ifp->if_l2com;
2799	struct bwn_mac *mac;
2800
2801	BWN_LOCK(sc);
2802	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2803		mac = (struct bwn_mac *)sc->sc_curmac;
2804		bwn_set_slot_time(mac,
2805		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2806	}
2807	BWN_UNLOCK(sc);
2808}
2809
2810/*
2811 * Callback from the 802.11 layer after a promiscuous mode change.
2812 * Note this interface does not check the operating mode as this
2813 * is an internal callback and we are expected to honor the current
2814 * state (e.g. this is used for setting the interface in promiscuous
2815 * mode when operating in hostap mode to do ACS).
2816 */
2817static void
2818bwn_update_promisc(struct ifnet *ifp)
2819{
2820	struct bwn_softc *sc = ifp->if_softc;
2821	struct bwn_mac *mac = sc->sc_curmac;
2822
2823	BWN_LOCK(sc);
2824	mac = sc->sc_curmac;
2825	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2826		if (ifp->if_flags & IFF_PROMISC)
2827			sc->sc_filters |= BWN_MACCTL_PROMISC;
2828		else
2829			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2830		bwn_set_opmode(mac);
2831	}
2832	BWN_UNLOCK(sc);
2833}
2834
2835/*
2836 * Callback from the 802.11 layer to update WME parameters.
2837 */
2838static int
2839bwn_wme_update(struct ieee80211com *ic)
2840{
2841	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2842	struct bwn_mac *mac = sc->sc_curmac;
2843	struct wmeParams *wmep;
2844	int i;
2845
2846	BWN_LOCK(sc);
2847	mac = sc->sc_curmac;
2848	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2849		bwn_mac_suspend(mac);
2850		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2851			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2852			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2853		}
2854		bwn_mac_enable(mac);
2855	}
2856	BWN_UNLOCK(sc);
2857	return (0);
2858}
2859
2860static struct ieee80211_node *
2861bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2862{
2863	struct ieee80211com *ic = vap->iv_ic;
2864	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2865	const size_t space = sizeof(struct bwn_node);
2866	struct bwn_node *bn;
2867
2868	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2869	if (bn == NULL) {
2870		/* XXX stat+msg */
2871		return (NULL);
2872	}
2873	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2874	return (&bn->bn_node);
2875}
2876
2877static void
2878bwn_node_cleanup(struct ieee80211_node *ni)
2879{
2880	struct ieee80211com *ic = ni->ni_ic;
2881	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2882
2883	sc->sc_node_cleanup(ni);
2884}
2885
2886static void
2887bwn_scan_start(struct ieee80211com *ic)
2888{
2889	struct ifnet *ifp = ic->ic_ifp;
2890	struct bwn_softc *sc = ifp->if_softc;
2891	struct bwn_mac *mac;
2892
2893	BWN_LOCK(sc);
2894	mac = sc->sc_curmac;
2895	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2896		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2897		bwn_set_opmode(mac);
2898		/* disable CFP update during scan */
2899		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2900	}
2901	BWN_UNLOCK(sc);
2902}
2903
2904static void
2905bwn_scan_end(struct ieee80211com *ic)
2906{
2907	struct ifnet *ifp = ic->ic_ifp;
2908	struct bwn_softc *sc = ifp->if_softc;
2909	struct bwn_mac *mac;
2910
2911	BWN_LOCK(sc);
2912	mac = sc->sc_curmac;
2913	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2914		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2915		bwn_set_opmode(mac);
2916		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2917	}
2918	BWN_UNLOCK(sc);
2919}
2920
2921static void
2922bwn_set_channel(struct ieee80211com *ic)
2923{
2924	struct ifnet *ifp = ic->ic_ifp;
2925	struct bwn_softc *sc = ifp->if_softc;
2926	struct bwn_mac *mac = sc->sc_curmac;
2927	struct bwn_phy *phy = &mac->mac_phy;
2928	int chan, error;
2929
2930	BWN_LOCK(sc);
2931
2932	error = bwn_switch_band(sc, ic->ic_curchan);
2933	if (error)
2934		goto fail;;
2935	bwn_mac_suspend(mac);
2936	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2937	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2938	if (chan != phy->chan)
2939		bwn_switch_channel(mac, chan);
2940
2941	/* TX power level */
2942	if (ic->ic_curchan->ic_maxpower != 0 &&
2943	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2944		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2945		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2946		    BWN_TXPWR_IGNORE_TSSI);
2947	}
2948
2949	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2950	if (phy->set_antenna)
2951		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2952
2953	if (sc->sc_rf_enabled != phy->rf_on) {
2954		if (sc->sc_rf_enabled) {
2955			bwn_rf_turnon(mac);
2956			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2957				device_printf(sc->sc_dev,
2958				    "please turns on the RF switch\n");
2959		} else
2960			bwn_rf_turnoff(mac);
2961	}
2962
2963	bwn_mac_enable(mac);
2964
2965fail:
2966	/*
2967	 * Setup radio tap channel freq and flags
2968	 */
2969	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2970		htole16(ic->ic_curchan->ic_freq);
2971	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2972		htole16(ic->ic_curchan->ic_flags & 0xffff);
2973
2974	BWN_UNLOCK(sc);
2975}
2976
2977static struct ieee80211vap *
2978bwn_vap_create(struct ieee80211com *ic,
2979	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2980	const uint8_t bssid[IEEE80211_ADDR_LEN],
2981	const uint8_t mac0[IEEE80211_ADDR_LEN])
2982{
2983	struct ifnet *ifp = ic->ic_ifp;
2984	struct bwn_softc *sc = ifp->if_softc;
2985	struct ieee80211vap *vap;
2986	struct bwn_vap *bvp;
2987	uint8_t mac[IEEE80211_ADDR_LEN];
2988
2989	IEEE80211_ADDR_COPY(mac, mac0);
2990	switch (opmode) {
2991	case IEEE80211_M_HOSTAP:
2992	case IEEE80211_M_MBSS:
2993	case IEEE80211_M_STA:
2994	case IEEE80211_M_WDS:
2995	case IEEE80211_M_MONITOR:
2996	case IEEE80211_M_IBSS:
2997	case IEEE80211_M_AHDEMO:
2998		break;
2999	default:
3000		return (NULL);
3001	}
3002
3003	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3004
3005	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3006	    M_80211_VAP, M_NOWAIT | M_ZERO);
3007	if (bvp == NULL) {
3008		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3009		return (NULL);
3010	}
3011	vap = &bvp->bv_vap;
3012	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3013	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3014	/* override with driver methods */
3015	bvp->bv_newstate = vap->iv_newstate;
3016	vap->iv_newstate = bwn_newstate;
3017
3018	/* override max aid so sta's cannot assoc when we're out of sta id's */
3019	vap->iv_max_aid = BWN_STAID_MAX;
3020
3021	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3022	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3023	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3024	    500 /*ms*/);
3025
3026	/* complete setup */
3027	ieee80211_vap_attach(vap, ieee80211_media_change,
3028	    ieee80211_media_status);
3029	return (vap);
3030}
3031
3032static void
3033bwn_vap_delete(struct ieee80211vap *vap)
3034{
3035	struct bwn_vap *bvp = BWN_VAP(vap);
3036
3037	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3038	ieee80211_vap_detach(vap);
3039	free(bvp, M_80211_VAP);
3040}
3041
3042static void
3043bwn_init(void *arg)
3044{
3045	struct bwn_softc *sc = arg;
3046	struct ifnet *ifp = sc->sc_ifp;
3047	struct ieee80211com *ic = ifp->if_l2com;
3048	int error = 0;
3049
3050	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3051		__func__, ifp->if_flags);
3052
3053	BWN_LOCK(sc);
3054	error = bwn_init_locked(sc);
3055	BWN_UNLOCK(sc);
3056
3057	if (error == 0)
3058		ieee80211_start_all(ic);	/* start all vap's */
3059}
3060
3061static int
3062bwn_init_locked(struct bwn_softc *sc)
3063{
3064	struct bwn_mac *mac;
3065	struct ifnet *ifp = sc->sc_ifp;
3066	int error;
3067
3068	BWN_ASSERT_LOCKED(sc);
3069
3070	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3071	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3072	sc->sc_filters = 0;
3073	bwn_wme_clear(sc);
3074	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3075	sc->sc_rf_enabled = 1;
3076
3077	mac = sc->sc_curmac;
3078	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3079		error = bwn_core_init(mac);
3080		if (error != 0)
3081			return (error);
3082	}
3083	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3084		bwn_core_start(mac);
3085
3086	bwn_set_opmode(mac);
3087	bwn_set_pretbtt(mac);
3088	bwn_spu_setdelay(mac, 0);
3089	bwn_set_macaddr(mac);
3090
3091	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3092	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3093	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3094
3095	return (0);
3096}
3097
3098static void
3099bwn_stop(struct bwn_softc *sc, int statechg)
3100{
3101
3102	BWN_LOCK(sc);
3103	bwn_stop_locked(sc, statechg);
3104	BWN_UNLOCK(sc);
3105}
3106
3107static void
3108bwn_stop_locked(struct bwn_softc *sc, int statechg)
3109{
3110	struct bwn_mac *mac = sc->sc_curmac;
3111	struct ifnet *ifp = sc->sc_ifp;
3112
3113	BWN_ASSERT_LOCKED(sc);
3114
3115	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3116		/* XXX FIXME opmode not based on VAP */
3117		bwn_set_opmode(mac);
3118		bwn_set_macaddr(mac);
3119	}
3120
3121	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3122		bwn_core_stop(mac);
3123
3124	callout_stop(&sc->sc_led_blink_ch);
3125	sc->sc_led_blinking = 0;
3126
3127	bwn_core_exit(mac);
3128	sc->sc_rf_enabled = 0;
3129
3130	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3131}
3132
3133static void
3134bwn_wme_clear(struct bwn_softc *sc)
3135{
3136#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3137	struct wmeParams *p;
3138	unsigned int i;
3139
3140	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3141	    ("%s:%d: fail", __func__, __LINE__));
3142
3143	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3144		p = &(sc->sc_wmeParams[i]);
3145
3146		switch (bwn_wme_shm_offsets[i]) {
3147		case BWN_WME_VOICE:
3148			p->wmep_txopLimit = 0;
3149			p->wmep_aifsn = 2;
3150			/* XXX FIXME: log2(cwmin) */
3151			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3152			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3153			break;
3154		case BWN_WME_VIDEO:
3155			p->wmep_txopLimit = 0;
3156			p->wmep_aifsn = 2;
3157			/* XXX FIXME: log2(cwmin) */
3158			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3159			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3160			break;
3161		case BWN_WME_BESTEFFORT:
3162			p->wmep_txopLimit = 0;
3163			p->wmep_aifsn = 3;
3164			/* XXX FIXME: log2(cwmin) */
3165			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3166			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3167			break;
3168		case BWN_WME_BACKGROUND:
3169			p->wmep_txopLimit = 0;
3170			p->wmep_aifsn = 7;
3171			/* XXX FIXME: log2(cwmin) */
3172			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3173			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3174			break;
3175		default:
3176			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3177		}
3178	}
3179}
3180
3181static int
3182bwn_core_init(struct bwn_mac *mac)
3183{
3184	struct bwn_softc *sc = mac->mac_sc;
3185	uint64_t hf;
3186	int error;
3187
3188	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3189	    ("%s:%d: fail", __func__, __LINE__));
3190
3191	siba_powerup(sc->sc_dev, 0);
3192	if (!siba_dev_isup(sc->sc_dev))
3193		bwn_reset_core(mac,
3194		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3195
3196	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3197	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3198	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3199	BWN_GETTIME(mac->mac_phy.nexttime);
3200	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3201	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3202	mac->mac_stats.link_noise = -95;
3203	mac->mac_reason_intr = 0;
3204	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3205	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3206#ifdef BWN_DEBUG
3207	if (sc->sc_debug & BWN_DEBUG_XMIT)
3208		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3209#endif
3210	mac->mac_suspended = 1;
3211	mac->mac_task_state = 0;
3212	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3213
3214	mac->mac_phy.init_pre(mac);
3215
3216	siba_pcicore_intr(sc->sc_dev);
3217
3218	siba_fix_imcfglobug(sc->sc_dev);
3219	bwn_bt_disable(mac);
3220	if (mac->mac_phy.prepare_hw) {
3221		error = mac->mac_phy.prepare_hw(mac);
3222		if (error)
3223			goto fail0;
3224	}
3225	error = bwn_chip_init(mac);
3226	if (error)
3227		goto fail0;
3228	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3229	    siba_get_revid(sc->sc_dev));
3230	hf = bwn_hf_read(mac);
3231	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3232		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3233		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3234			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3235		if (mac->mac_phy.rev == 1)
3236			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3237	}
3238	if (mac->mac_phy.rf_ver == 0x2050) {
3239		if (mac->mac_phy.rf_rev < 6)
3240			hf |= BWN_HF_FORCE_VCO_RECALC;
3241		if (mac->mac_phy.rf_rev == 6)
3242			hf |= BWN_HF_4318_TSSI;
3243	}
3244	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3245		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3246	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3247	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3248		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3249	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3250	bwn_hf_write(mac, hf);
3251
3252	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3253	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3254	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3255	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3256
3257	bwn_rate_init(mac);
3258	bwn_set_phytxctl(mac);
3259
3260	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3261	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3262	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3263
3264	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3265		bwn_pio_init(mac);
3266	else
3267		bwn_dma_init(mac);
3268	if (error)
3269		goto fail1;
3270	bwn_wme_init(mac);
3271	bwn_spu_setdelay(mac, 1);
3272	bwn_bt_enable(mac);
3273
3274	siba_powerup(sc->sc_dev,
3275	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3276	bwn_set_macaddr(mac);
3277	bwn_crypt_init(mac);
3278
3279	/* XXX LED initializatin */
3280
3281	mac->mac_status = BWN_MAC_STATUS_INITED;
3282
3283	return (error);
3284
3285fail1:
3286	bwn_chip_exit(mac);
3287fail0:
3288	siba_powerdown(sc->sc_dev);
3289	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3290	    ("%s:%d: fail", __func__, __LINE__));
3291	return (error);
3292}
3293
3294static void
3295bwn_core_start(struct bwn_mac *mac)
3296{
3297	struct bwn_softc *sc = mac->mac_sc;
3298	uint32_t tmp;
3299
3300	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3301	    ("%s:%d: fail", __func__, __LINE__));
3302
3303	if (siba_get_revid(sc->sc_dev) < 5)
3304		return;
3305
3306	while (1) {
3307		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3308		if (!(tmp & 0x00000001))
3309			break;
3310		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3311	}
3312
3313	bwn_mac_enable(mac);
3314	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3315	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3316
3317	mac->mac_status = BWN_MAC_STATUS_STARTED;
3318}
3319
3320static void
3321bwn_core_exit(struct bwn_mac *mac)
3322{
3323	struct bwn_softc *sc = mac->mac_sc;
3324	uint32_t macctl;
3325
3326	BWN_ASSERT_LOCKED(mac->mac_sc);
3327
3328	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3329	    ("%s:%d: fail", __func__, __LINE__));
3330
3331	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3332		return;
3333	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3334
3335	macctl = BWN_READ_4(mac, BWN_MACCTL);
3336	macctl &= ~BWN_MACCTL_MCODE_RUN;
3337	macctl |= BWN_MACCTL_MCODE_JMP0;
3338	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3339
3340	bwn_dma_stop(mac);
3341	bwn_pio_stop(mac);
3342	bwn_chip_exit(mac);
3343	mac->mac_phy.switch_analog(mac, 0);
3344	siba_dev_down(sc->sc_dev, 0);
3345	siba_powerdown(sc->sc_dev);
3346}
3347
3348static void
3349bwn_bt_disable(struct bwn_mac *mac)
3350{
3351	struct bwn_softc *sc = mac->mac_sc;
3352
3353	(void)sc;
3354	/* XXX do nothing yet */
3355}
3356
3357static int
3358bwn_chip_init(struct bwn_mac *mac)
3359{
3360	struct bwn_softc *sc = mac->mac_sc;
3361	struct bwn_phy *phy = &mac->mac_phy;
3362	uint32_t macctl;
3363	int error;
3364
3365	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3366	if (phy->gmode)
3367		macctl |= BWN_MACCTL_GMODE;
3368	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3369
3370	error = bwn_fw_fillinfo(mac);
3371	if (error)
3372		return (error);
3373	error = bwn_fw_loaducode(mac);
3374	if (error)
3375		return (error);
3376
3377	error = bwn_gpio_init(mac);
3378	if (error)
3379		return (error);
3380
3381	error = bwn_fw_loadinitvals(mac);
3382	if (error) {
3383		siba_gpio_set(sc->sc_dev, 0);
3384		return (error);
3385	}
3386	phy->switch_analog(mac, 1);
3387	error = bwn_phy_init(mac);
3388	if (error) {
3389		siba_gpio_set(sc->sc_dev, 0);
3390		return (error);
3391	}
3392	if (phy->set_im)
3393		phy->set_im(mac, BWN_IMMODE_NONE);
3394	if (phy->set_antenna)
3395		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3396	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3397
3398	if (phy->type == BWN_PHYTYPE_B)
3399		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3400	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3401	if (siba_get_revid(sc->sc_dev) < 5)
3402		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3403
3404	BWN_WRITE_4(mac, BWN_MACCTL,
3405	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3406	BWN_WRITE_4(mac, BWN_MACCTL,
3407	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3408	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3409
3410	bwn_set_opmode(mac);
3411	if (siba_get_revid(sc->sc_dev) < 3) {
3412		BWN_WRITE_2(mac, 0x060e, 0x0000);
3413		BWN_WRITE_2(mac, 0x0610, 0x8000);
3414		BWN_WRITE_2(mac, 0x0604, 0x0000);
3415		BWN_WRITE_2(mac, 0x0606, 0x0200);
3416	} else {
3417		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3418		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3419	}
3420	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3421	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3422	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3423	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3424	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3425	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3426	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3427	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3428	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3429	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3430	return (error);
3431}
3432
3433/* read hostflags */
3434static uint64_t
3435bwn_hf_read(struct bwn_mac *mac)
3436{
3437	uint64_t ret;
3438
3439	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3440	ret <<= 16;
3441	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3442	ret <<= 16;
3443	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3444	return (ret);
3445}
3446
3447static void
3448bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3449{
3450
3451	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3452	    (value & 0x00000000ffffull));
3453	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3454	    (value & 0x0000ffff0000ull) >> 16);
3455	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3456	    (value & 0xffff00000000ULL) >> 32);
3457}
3458
3459static void
3460bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3461{
3462
3463	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3464	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3465}
3466
3467static void
3468bwn_rate_init(struct bwn_mac *mac)
3469{
3470
3471	switch (mac->mac_phy.type) {
3472	case BWN_PHYTYPE_A:
3473	case BWN_PHYTYPE_G:
3474	case BWN_PHYTYPE_LP:
3475	case BWN_PHYTYPE_N:
3476		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3477		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3478		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3479		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3480		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3481		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3482		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3483		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3484			break;
3485		/* FALLTHROUGH */
3486	case BWN_PHYTYPE_B:
3487		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3488		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3489		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3490		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3491		break;
3492	default:
3493		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3494	}
3495}
3496
3497static void
3498bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3499{
3500	uint16_t offset;
3501
3502	if (ofdm) {
3503		offset = 0x480;
3504		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3505	} else {
3506		offset = 0x4c0;
3507		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3508	}
3509	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3510	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3511}
3512
3513static uint8_t
3514bwn_plcp_getcck(const uint8_t bitrate)
3515{
3516
3517	switch (bitrate) {
3518	case BWN_CCK_RATE_1MB:
3519		return (0x0a);
3520	case BWN_CCK_RATE_2MB:
3521		return (0x14);
3522	case BWN_CCK_RATE_5MB:
3523		return (0x37);
3524	case BWN_CCK_RATE_11MB:
3525		return (0x6e);
3526	}
3527	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3528	return (0);
3529}
3530
3531static uint8_t
3532bwn_plcp_getofdm(const uint8_t bitrate)
3533{
3534
3535	switch (bitrate) {
3536	case BWN_OFDM_RATE_6MB:
3537		return (0xb);
3538	case BWN_OFDM_RATE_9MB:
3539		return (0xf);
3540	case BWN_OFDM_RATE_12MB:
3541		return (0xa);
3542	case BWN_OFDM_RATE_18MB:
3543		return (0xe);
3544	case BWN_OFDM_RATE_24MB:
3545		return (0x9);
3546	case BWN_OFDM_RATE_36MB:
3547		return (0xd);
3548	case BWN_OFDM_RATE_48MB:
3549		return (0x8);
3550	case BWN_OFDM_RATE_54MB:
3551		return (0xc);
3552	}
3553	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3554	return (0);
3555}
3556
3557static void
3558bwn_set_phytxctl(struct bwn_mac *mac)
3559{
3560	uint16_t ctl;
3561
3562	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3563	    BWN_TX_PHY_TXPWR);
3564	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3565	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3566	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3567}
3568
3569static void
3570bwn_pio_init(struct bwn_mac *mac)
3571{
3572	struct bwn_pio *pio = &mac->mac_method.pio;
3573
3574	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3575	    & ~BWN_MACCTL_BIGENDIAN);
3576	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3577
3578	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3579	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3580	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3581	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3582	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3583	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3584}
3585
3586static void
3587bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3588    int index)
3589{
3590	struct bwn_pio_txpkt *tp;
3591	struct bwn_softc *sc = mac->mac_sc;
3592	unsigned int i;
3593
3594	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3595	tq->tq_index = index;
3596
3597	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3598	if (siba_get_revid(sc->sc_dev) >= 8)
3599		tq->tq_size = 1920;
3600	else {
3601		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3602		tq->tq_size -= 80;
3603	}
3604
3605	TAILQ_INIT(&tq->tq_pktlist);
3606	for (i = 0; i < N(tq->tq_pkts); i++) {
3607		tp = &(tq->tq_pkts[i]);
3608		tp->tp_index = i;
3609		tp->tp_queue = tq;
3610		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3611	}
3612}
3613
3614static uint16_t
3615bwn_pio_idx2base(struct bwn_mac *mac, int index)
3616{
3617	struct bwn_softc *sc = mac->mac_sc;
3618	static const uint16_t bases[] = {
3619		BWN_PIO_BASE0,
3620		BWN_PIO_BASE1,
3621		BWN_PIO_BASE2,
3622		BWN_PIO_BASE3,
3623		BWN_PIO_BASE4,
3624		BWN_PIO_BASE5,
3625		BWN_PIO_BASE6,
3626		BWN_PIO_BASE7,
3627	};
3628	static const uint16_t bases_rev11[] = {
3629		BWN_PIO11_BASE0,
3630		BWN_PIO11_BASE1,
3631		BWN_PIO11_BASE2,
3632		BWN_PIO11_BASE3,
3633		BWN_PIO11_BASE4,
3634		BWN_PIO11_BASE5,
3635	};
3636
3637	if (siba_get_revid(sc->sc_dev) >= 11) {
3638		if (index >= N(bases_rev11))
3639			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3640		return (bases_rev11[index]);
3641	}
3642	if (index >= N(bases))
3643		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3644	return (bases[index]);
3645}
3646
3647static void
3648bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3649    int index)
3650{
3651	struct bwn_softc *sc = mac->mac_sc;
3652
3653	prq->prq_mac = mac;
3654	prq->prq_rev = siba_get_revid(sc->sc_dev);
3655	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3656	bwn_dma_rxdirectfifo(mac, index, 1);
3657}
3658
3659static void
3660bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3661{
3662	if (tq == NULL)
3663		return;
3664	bwn_pio_cancel_tx_packets(tq);
3665}
3666
3667static void
3668bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3669{
3670
3671	bwn_destroy_pioqueue_tx(pio);
3672}
3673
3674static uint16_t
3675bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3676    uint16_t offset)
3677{
3678
3679	return (BWN_READ_2(mac, tq->tq_base + offset));
3680}
3681
3682static void
3683bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3684{
3685	uint32_t ctl;
3686	int type;
3687	uint16_t base;
3688
3689	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3690	base = bwn_dma_base(type, idx);
3691	if (type == BWN_DMA_64BIT) {
3692		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3693		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3694		if (enable)
3695			ctl |= BWN_DMA64_RXDIRECTFIFO;
3696		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3697	} else {
3698		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3699		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3700		if (enable)
3701			ctl |= BWN_DMA32_RXDIRECTFIFO;
3702		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3703	}
3704}
3705
3706static uint64_t
3707bwn_dma_mask(struct bwn_mac *mac)
3708{
3709	uint32_t tmp;
3710	uint16_t base;
3711
3712	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3713	if (tmp & SIBA_TGSHIGH_DMA64)
3714		return (BWN_DMA_BIT_MASK(64));
3715	base = bwn_dma_base(0, 0);
3716	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3717	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3718	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3719		return (BWN_DMA_BIT_MASK(32));
3720
3721	return (BWN_DMA_BIT_MASK(30));
3722}
3723
3724static int
3725bwn_dma_mask2type(uint64_t dmamask)
3726{
3727
3728	if (dmamask == BWN_DMA_BIT_MASK(30))
3729		return (BWN_DMA_30BIT);
3730	if (dmamask == BWN_DMA_BIT_MASK(32))
3731		return (BWN_DMA_32BIT);
3732	if (dmamask == BWN_DMA_BIT_MASK(64))
3733		return (BWN_DMA_64BIT);
3734	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3735	return (BWN_DMA_30BIT);
3736}
3737
3738static void
3739bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3740{
3741	struct bwn_pio_txpkt *tp;
3742	unsigned int i;
3743
3744	for (i = 0; i < N(tq->tq_pkts); i++) {
3745		tp = &(tq->tq_pkts[i]);
3746		if (tp->tp_m) {
3747			m_freem(tp->tp_m);
3748			tp->tp_m = NULL;
3749		}
3750	}
3751}
3752
3753static uint16_t
3754bwn_dma_base(int type, int controller_idx)
3755{
3756	static const uint16_t map64[] = {
3757		BWN_DMA64_BASE0,
3758		BWN_DMA64_BASE1,
3759		BWN_DMA64_BASE2,
3760		BWN_DMA64_BASE3,
3761		BWN_DMA64_BASE4,
3762		BWN_DMA64_BASE5,
3763	};
3764	static const uint16_t map32[] = {
3765		BWN_DMA32_BASE0,
3766		BWN_DMA32_BASE1,
3767		BWN_DMA32_BASE2,
3768		BWN_DMA32_BASE3,
3769		BWN_DMA32_BASE4,
3770		BWN_DMA32_BASE5,
3771	};
3772
3773	if (type == BWN_DMA_64BIT) {
3774		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3775		    ("%s:%d: fail", __func__, __LINE__));
3776		return (map64[controller_idx]);
3777	}
3778	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3779	    ("%s:%d: fail", __func__, __LINE__));
3780	return (map32[controller_idx]);
3781}
3782
3783static void
3784bwn_dma_init(struct bwn_mac *mac)
3785{
3786	struct bwn_dma *dma = &mac->mac_method.dma;
3787
3788	/* setup TX DMA channels. */
3789	bwn_dma_setup(dma->wme[WME_AC_BK]);
3790	bwn_dma_setup(dma->wme[WME_AC_BE]);
3791	bwn_dma_setup(dma->wme[WME_AC_VI]);
3792	bwn_dma_setup(dma->wme[WME_AC_VO]);
3793	bwn_dma_setup(dma->mcast);
3794	/* setup RX DMA channel. */
3795	bwn_dma_setup(dma->rx);
3796}
3797
3798static struct bwn_dma_ring *
3799bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3800    int for_tx, int type)
3801{
3802	struct bwn_dma *dma = &mac->mac_method.dma;
3803	struct bwn_dma_ring *dr;
3804	struct bwn_dmadesc_generic *desc;
3805	struct bwn_dmadesc_meta *mt;
3806	struct bwn_softc *sc = mac->mac_sc;
3807	int error, i;
3808
3809	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3810	if (dr == NULL)
3811		goto out;
3812	dr->dr_numslots = BWN_RXRING_SLOTS;
3813	if (for_tx)
3814		dr->dr_numslots = BWN_TXRING_SLOTS;
3815
3816	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3817	    M_DEVBUF, M_NOWAIT | M_ZERO);
3818	if (dr->dr_meta == NULL)
3819		goto fail0;
3820
3821	dr->dr_type = type;
3822	dr->dr_mac = mac;
3823	dr->dr_base = bwn_dma_base(type, controller_index);
3824	dr->dr_index = controller_index;
3825	if (type == BWN_DMA_64BIT) {
3826		dr->getdesc = bwn_dma_64_getdesc;
3827		dr->setdesc = bwn_dma_64_setdesc;
3828		dr->start_transfer = bwn_dma_64_start_transfer;
3829		dr->suspend = bwn_dma_64_suspend;
3830		dr->resume = bwn_dma_64_resume;
3831		dr->get_curslot = bwn_dma_64_get_curslot;
3832		dr->set_curslot = bwn_dma_64_set_curslot;
3833	} else {
3834		dr->getdesc = bwn_dma_32_getdesc;
3835		dr->setdesc = bwn_dma_32_setdesc;
3836		dr->start_transfer = bwn_dma_32_start_transfer;
3837		dr->suspend = bwn_dma_32_suspend;
3838		dr->resume = bwn_dma_32_resume;
3839		dr->get_curslot = bwn_dma_32_get_curslot;
3840		dr->set_curslot = bwn_dma_32_set_curslot;
3841	}
3842	if (for_tx) {
3843		dr->dr_tx = 1;
3844		dr->dr_curslot = -1;
3845	} else {
3846		if (dr->dr_index == 0) {
3847			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3848			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3849		} else
3850			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3851	}
3852
3853	error = bwn_dma_allocringmemory(dr);
3854	if (error)
3855		goto fail2;
3856
3857	if (for_tx) {
3858		/*
3859		 * Assumption: BWN_TXRING_SLOTS can be divided by
3860		 * BWN_TX_SLOTS_PER_FRAME
3861		 */
3862		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3863		    ("%s:%d: fail", __func__, __LINE__));
3864
3865		dr->dr_txhdr_cache =
3866		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3867			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3868		KASSERT(dr->dr_txhdr_cache != NULL,
3869		    ("%s:%d: fail", __func__, __LINE__));
3870
3871		/*
3872		 * Create TX ring DMA stuffs
3873		 */
3874		error = bus_dma_tag_create(dma->parent_dtag,
3875				    BWN_ALIGN, 0,
3876				    BUS_SPACE_MAXADDR,
3877				    BUS_SPACE_MAXADDR,
3878				    NULL, NULL,
3879				    BWN_HDRSIZE(mac),
3880				    1,
3881				    BUS_SPACE_MAXSIZE_32BIT,
3882				    0,
3883				    NULL, NULL,
3884				    &dr->dr_txring_dtag);
3885		if (error) {
3886			device_printf(sc->sc_dev,
3887			    "can't create TX ring DMA tag: TODO frees\n");
3888			goto fail1;
3889		}
3890
3891		for (i = 0; i < dr->dr_numslots; i += 2) {
3892			dr->getdesc(dr, i, &desc, &mt);
3893
3894			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3895			mt->mt_m = NULL;
3896			mt->mt_ni = NULL;
3897			mt->mt_islast = 0;
3898			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3899			    &mt->mt_dmap);
3900			if (error) {
3901				device_printf(sc->sc_dev,
3902				     "can't create RX buf DMA map\n");
3903				goto fail1;
3904			}
3905
3906			dr->getdesc(dr, i + 1, &desc, &mt);
3907
3908			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3909			mt->mt_m = NULL;
3910			mt->mt_ni = NULL;
3911			mt->mt_islast = 1;
3912			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3913			    &mt->mt_dmap);
3914			if (error) {
3915				device_printf(sc->sc_dev,
3916				     "can't create RX buf DMA map\n");
3917				goto fail1;
3918			}
3919		}
3920	} else {
3921		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3922		    &dr->dr_spare_dmap);
3923		if (error) {
3924			device_printf(sc->sc_dev,
3925			    "can't create RX buf DMA map\n");
3926			goto out;		/* XXX wrong! */
3927		}
3928
3929		for (i = 0; i < dr->dr_numslots; i++) {
3930			dr->getdesc(dr, i, &desc, &mt);
3931
3932			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3933			    &mt->mt_dmap);
3934			if (error) {
3935				device_printf(sc->sc_dev,
3936				    "can't create RX buf DMA map\n");
3937				goto out;	/* XXX wrong! */
3938			}
3939			error = bwn_dma_newbuf(dr, desc, mt, 1);
3940			if (error) {
3941				device_printf(sc->sc_dev,
3942				    "failed to allocate RX buf\n");
3943				goto out;	/* XXX wrong! */
3944			}
3945		}
3946
3947		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3948		    BUS_DMASYNC_PREWRITE);
3949
3950		dr->dr_usedslot = dr->dr_numslots;
3951	}
3952
3953      out:
3954	return (dr);
3955
3956fail2:
3957	free(dr->dr_txhdr_cache, M_DEVBUF);
3958fail1:
3959	free(dr->dr_meta, M_DEVBUF);
3960fail0:
3961	free(dr, M_DEVBUF);
3962	return (NULL);
3963}
3964
3965static void
3966bwn_dma_ringfree(struct bwn_dma_ring **dr)
3967{
3968
3969	if (dr == NULL)
3970		return;
3971
3972	bwn_dma_free_descbufs(*dr);
3973	bwn_dma_free_ringmemory(*dr);
3974
3975	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3976	free((*dr)->dr_meta, M_DEVBUF);
3977	free(*dr, M_DEVBUF);
3978
3979	*dr = NULL;
3980}
3981
3982static void
3983bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3984    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3985{
3986	struct bwn_dmadesc32 *desc;
3987
3988	*meta = &(dr->dr_meta[slot]);
3989	desc = dr->dr_ring_descbase;
3990	desc = &(desc[slot]);
3991
3992	*gdesc = (struct bwn_dmadesc_generic *)desc;
3993}
3994
3995static void
3996bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3997    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3998    int start, int end, int irq)
3999{
4000	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
4001	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4002	uint32_t addr, addrext, ctl;
4003	int slot;
4004
4005	slot = (int)(&(desc->dma.dma32) - descbase);
4006	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4007	    ("%s:%d: fail", __func__, __LINE__));
4008
4009	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4010	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4011	addr |= siba_dma_translation(sc->sc_dev);
4012	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4013	if (slot == dr->dr_numslots - 1)
4014		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4015	if (start)
4016		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4017	if (end)
4018		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4019	if (irq)
4020		ctl |= BWN_DMA32_DCTL_IRQ;
4021	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4022	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4023
4024	desc->dma.dma32.control = htole32(ctl);
4025	desc->dma.dma32.address = htole32(addr);
4026}
4027
4028static void
4029bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4030{
4031
4032	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4033	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4034}
4035
4036static void
4037bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4038{
4039
4040	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4041	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4042}
4043
4044static void
4045bwn_dma_32_resume(struct bwn_dma_ring *dr)
4046{
4047
4048	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4049	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4050}
4051
4052static int
4053bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4054{
4055	uint32_t val;
4056
4057	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4058	val &= BWN_DMA32_RXDPTR;
4059
4060	return (val / sizeof(struct bwn_dmadesc32));
4061}
4062
4063static void
4064bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4065{
4066
4067	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4068	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4069}
4070
4071static void
4072bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4073    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4074{
4075	struct bwn_dmadesc64 *desc;
4076
4077	*meta = &(dr->dr_meta[slot]);
4078	desc = dr->dr_ring_descbase;
4079	desc = &(desc[slot]);
4080
4081	*gdesc = (struct bwn_dmadesc_generic *)desc;
4082}
4083
4084static void
4085bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4086    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4087    int start, int end, int irq)
4088{
4089	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4090	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4091	int slot;
4092	uint32_t ctl0 = 0, ctl1 = 0;
4093	uint32_t addrlo, addrhi;
4094	uint32_t addrext;
4095
4096	slot = (int)(&(desc->dma.dma64) - descbase);
4097	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4098	    ("%s:%d: fail", __func__, __LINE__));
4099
4100	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4101	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4102	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4103	    30;
4104	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4105	if (slot == dr->dr_numslots - 1)
4106		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4107	if (start)
4108		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4109	if (end)
4110		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4111	if (irq)
4112		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4113	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4114	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4115	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4116
4117	desc->dma.dma64.control0 = htole32(ctl0);
4118	desc->dma.dma64.control1 = htole32(ctl1);
4119	desc->dma.dma64.address_low = htole32(addrlo);
4120	desc->dma.dma64.address_high = htole32(addrhi);
4121}
4122
4123static void
4124bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4125{
4126
4127	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4128	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4129}
4130
4131static void
4132bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4133{
4134
4135	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4136	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4137}
4138
4139static void
4140bwn_dma_64_resume(struct bwn_dma_ring *dr)
4141{
4142
4143	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4144	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4145}
4146
4147static int
4148bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4149{
4150	uint32_t val;
4151
4152	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4153	val &= BWN_DMA64_RXSTATDPTR;
4154
4155	return (val / sizeof(struct bwn_dmadesc64));
4156}
4157
4158static void
4159bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4160{
4161
4162	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4163	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4164}
4165
4166static int
4167bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4168{
4169	struct bwn_mac *mac = dr->dr_mac;
4170	struct bwn_dma *dma = &mac->mac_method.dma;
4171	struct bwn_softc *sc = mac->mac_sc;
4172	int error;
4173
4174	error = bus_dma_tag_create(dma->parent_dtag,
4175			    BWN_ALIGN, 0,
4176			    BUS_SPACE_MAXADDR,
4177			    BUS_SPACE_MAXADDR,
4178			    NULL, NULL,
4179			    BWN_DMA_RINGMEMSIZE,
4180			    1,
4181			    BUS_SPACE_MAXSIZE_32BIT,
4182			    0,
4183			    NULL, NULL,
4184			    &dr->dr_ring_dtag);
4185	if (error) {
4186		device_printf(sc->sc_dev,
4187		    "can't create TX ring DMA tag: TODO frees\n");
4188		return (-1);
4189	}
4190
4191	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4192	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4193	    &dr->dr_ring_dmap);
4194	if (error) {
4195		device_printf(sc->sc_dev,
4196		    "can't allocate DMA mem: TODO frees\n");
4197		return (-1);
4198	}
4199	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4200	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4201	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4202	if (error) {
4203		device_printf(sc->sc_dev,
4204		    "can't load DMA mem: TODO free\n");
4205		return (-1);
4206	}
4207
4208	return (0);
4209}
4210
4211static void
4212bwn_dma_setup(struct bwn_dma_ring *dr)
4213{
4214	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4215	uint64_t ring64;
4216	uint32_t addrext, ring32, value;
4217	uint32_t trans = siba_dma_translation(sc->sc_dev);
4218
4219	if (dr->dr_tx) {
4220		dr->dr_curslot = -1;
4221
4222		if (dr->dr_type == BWN_DMA_64BIT) {
4223			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4224			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4225			    >> 30;
4226			value = BWN_DMA64_TXENABLE;
4227			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4228			    & BWN_DMA64_TXADDREXT_MASK;
4229			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4230			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4231			    (ring64 & 0xffffffff));
4232			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4233			    ((ring64 >> 32) &
4234			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4235		} else {
4236			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4237			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4238			value = BWN_DMA32_TXENABLE;
4239			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4240			    & BWN_DMA32_TXADDREXT_MASK;
4241			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4242			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4243			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4244		}
4245		return;
4246	}
4247
4248	/*
4249	 * set for RX
4250	 */
4251	dr->dr_usedslot = dr->dr_numslots;
4252
4253	if (dr->dr_type == BWN_DMA_64BIT) {
4254		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4255		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4256		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4257		value |= BWN_DMA64_RXENABLE;
4258		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4259		    & BWN_DMA64_RXADDREXT_MASK;
4260		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4261		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4262		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4263		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4264		    | (trans << 1));
4265		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4266		    sizeof(struct bwn_dmadesc64));
4267	} else {
4268		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4269		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4270		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4271		value |= BWN_DMA32_RXENABLE;
4272		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4273		    & BWN_DMA32_RXADDREXT_MASK;
4274		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4275		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4276		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4277		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4278		    sizeof(struct bwn_dmadesc32));
4279	}
4280}
4281
4282static void
4283bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4284{
4285
4286	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4287	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4288	    dr->dr_ring_dmap);
4289}
4290
4291static void
4292bwn_dma_cleanup(struct bwn_dma_ring *dr)
4293{
4294
4295	if (dr->dr_tx) {
4296		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4297		if (dr->dr_type == BWN_DMA_64BIT) {
4298			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4299			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4300		} else
4301			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4302	} else {
4303		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4304		if (dr->dr_type == BWN_DMA_64BIT) {
4305			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4306			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4307		} else
4308			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4309	}
4310}
4311
4312static void
4313bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4314{
4315	struct bwn_dmadesc_generic *desc;
4316	struct bwn_dmadesc_meta *meta;
4317	struct bwn_mac *mac = dr->dr_mac;
4318	struct bwn_dma *dma = &mac->mac_method.dma;
4319	struct bwn_softc *sc = mac->mac_sc;
4320	int i;
4321
4322	if (!dr->dr_usedslot)
4323		return;
4324	for (i = 0; i < dr->dr_numslots; i++) {
4325		dr->getdesc(dr, i, &desc, &meta);
4326
4327		if (meta->mt_m == NULL) {
4328			if (!dr->dr_tx)
4329				device_printf(sc->sc_dev, "%s: not TX?\n",
4330				    __func__);
4331			continue;
4332		}
4333		if (dr->dr_tx) {
4334			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4335				bus_dmamap_unload(dr->dr_txring_dtag,
4336				    meta->mt_dmap);
4337			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4338				bus_dmamap_unload(dma->txbuf_dtag,
4339				    meta->mt_dmap);
4340		} else
4341			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4342		bwn_dma_free_descbuf(dr, meta);
4343	}
4344}
4345
4346static int
4347bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4348    int type)
4349{
4350	struct bwn_softc *sc = mac->mac_sc;
4351	uint32_t value;
4352	int i;
4353	uint16_t offset;
4354
4355	for (i = 0; i < 10; i++) {
4356		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4357		    BWN_DMA32_TXSTATUS;
4358		value = BWN_READ_4(mac, base + offset);
4359		if (type == BWN_DMA_64BIT) {
4360			value &= BWN_DMA64_TXSTAT;
4361			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4362			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4363			    value == BWN_DMA64_TXSTAT_STOPPED)
4364				break;
4365		} else {
4366			value &= BWN_DMA32_TXSTATE;
4367			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4368			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4369			    value == BWN_DMA32_TXSTAT_STOPPED)
4370				break;
4371		}
4372		DELAY(1000);
4373	}
4374	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4375	BWN_WRITE_4(mac, base + offset, 0);
4376	for (i = 0; i < 10; i++) {
4377		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4378						   BWN_DMA32_TXSTATUS;
4379		value = BWN_READ_4(mac, base + offset);
4380		if (type == BWN_DMA_64BIT) {
4381			value &= BWN_DMA64_TXSTAT;
4382			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4383				i = -1;
4384				break;
4385			}
4386		} else {
4387			value &= BWN_DMA32_TXSTATE;
4388			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4389				i = -1;
4390				break;
4391			}
4392		}
4393		DELAY(1000);
4394	}
4395	if (i != -1) {
4396		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4397		return (ENODEV);
4398	}
4399	DELAY(1000);
4400
4401	return (0);
4402}
4403
4404static int
4405bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4406    int type)
4407{
4408	struct bwn_softc *sc = mac->mac_sc;
4409	uint32_t value;
4410	int i;
4411	uint16_t offset;
4412
4413	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4414	BWN_WRITE_4(mac, base + offset, 0);
4415	for (i = 0; i < 10; i++) {
4416		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4417		    BWN_DMA32_RXSTATUS;
4418		value = BWN_READ_4(mac, base + offset);
4419		if (type == BWN_DMA_64BIT) {
4420			value &= BWN_DMA64_RXSTAT;
4421			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4422				i = -1;
4423				break;
4424			}
4425		} else {
4426			value &= BWN_DMA32_RXSTATE;
4427			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4428				i = -1;
4429				break;
4430			}
4431		}
4432		DELAY(1000);
4433	}
4434	if (i != -1) {
4435		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4436		return (ENODEV);
4437	}
4438
4439	return (0);
4440}
4441
4442static void
4443bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4444    struct bwn_dmadesc_meta *meta)
4445{
4446
4447	if (meta->mt_m != NULL) {
4448		m_freem(meta->mt_m);
4449		meta->mt_m = NULL;
4450	}
4451	if (meta->mt_ni != NULL) {
4452		ieee80211_free_node(meta->mt_ni);
4453		meta->mt_ni = NULL;
4454	}
4455}
4456
4457static void
4458bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4459{
4460	struct bwn_rxhdr4 *rxhdr;
4461	unsigned char *frame;
4462
4463	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4464	rxhdr->frame_len = 0;
4465
4466	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4467	    sizeof(struct bwn_plcp6) + 2,
4468	    ("%s:%d: fail", __func__, __LINE__));
4469	frame = mtod(m, char *) + dr->dr_frameoffset;
4470	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4471}
4472
4473static uint8_t
4474bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4475{
4476	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4477
4478	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4479	    == 0xff);
4480}
4481
4482static void
4483bwn_wme_init(struct bwn_mac *mac)
4484{
4485
4486	bwn_wme_load(mac);
4487
4488	/* enable WME support. */
4489	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4490	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4491	    BWN_IFSCTL_USE_EDCF);
4492}
4493
4494static void
4495bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4496{
4497	struct bwn_softc *sc = mac->mac_sc;
4498	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4499	uint16_t delay;	/* microsec */
4500
4501	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4502	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4503		delay = 500;
4504	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4505		delay = max(delay, (uint16_t)2400);
4506
4507	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4508}
4509
4510static void
4511bwn_bt_enable(struct bwn_mac *mac)
4512{
4513	struct bwn_softc *sc = mac->mac_sc;
4514	uint64_t hf;
4515
4516	if (bwn_bluetooth == 0)
4517		return;
4518	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4519		return;
4520	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4521		return;
4522
4523	hf = bwn_hf_read(mac);
4524	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4525		hf |= BWN_HF_BT_COEXISTALT;
4526	else
4527		hf |= BWN_HF_BT_COEXIST;
4528	bwn_hf_write(mac, hf);
4529}
4530
4531static void
4532bwn_set_macaddr(struct bwn_mac *mac)
4533{
4534
4535	bwn_mac_write_bssid(mac);
4536	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4537}
4538
4539static void
4540bwn_clear_keys(struct bwn_mac *mac)
4541{
4542	int i;
4543
4544	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4545		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4546		    ("%s:%d: fail", __func__, __LINE__));
4547
4548		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4549		    NULL, BWN_SEC_KEYSIZE, NULL);
4550		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4551			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4552			    NULL, BWN_SEC_KEYSIZE, NULL);
4553		}
4554		mac->mac_key[i].keyconf = NULL;
4555	}
4556}
4557
4558static void
4559bwn_crypt_init(struct bwn_mac *mac)
4560{
4561	struct bwn_softc *sc = mac->mac_sc;
4562
4563	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4564	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4565	    ("%s:%d: fail", __func__, __LINE__));
4566	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4567	mac->mac_ktp *= 2;
4568	if (siba_get_revid(sc->sc_dev) >= 5)
4569		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4570	bwn_clear_keys(mac);
4571}
4572
4573static void
4574bwn_chip_exit(struct bwn_mac *mac)
4575{
4576	struct bwn_softc *sc = mac->mac_sc;
4577
4578	bwn_phy_exit(mac);
4579	siba_gpio_set(sc->sc_dev, 0);
4580}
4581
4582static int
4583bwn_fw_fillinfo(struct bwn_mac *mac)
4584{
4585	int error;
4586
4587	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4588	if (error == 0)
4589		return (0);
4590	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4591	if (error == 0)
4592		return (0);
4593	return (error);
4594}
4595
4596static int
4597bwn_gpio_init(struct bwn_mac *mac)
4598{
4599	struct bwn_softc *sc = mac->mac_sc;
4600	uint32_t mask = 0x1f, set = 0xf, value;
4601
4602	BWN_WRITE_4(mac, BWN_MACCTL,
4603	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4604	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4605	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4606
4607	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4608		mask |= 0x0060;
4609		set |= 0x0060;
4610	}
4611	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4612		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4613		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4614		mask |= 0x0200;
4615		set |= 0x0200;
4616	}
4617	if (siba_get_revid(sc->sc_dev) >= 2)
4618		mask |= 0x0010;
4619
4620	value = siba_gpio_get(sc->sc_dev);
4621	if (value == -1)
4622		return (0);
4623	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4624
4625	return (0);
4626}
4627
4628static int
4629bwn_fw_loadinitvals(struct bwn_mac *mac)
4630{
4631#define	GETFWOFFSET(fwp, offset)				\
4632	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4633	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4634	const struct bwn_fwhdr *hdr;
4635	struct bwn_fw *fw = &mac->mac_fw;
4636	int error;
4637
4638	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4639	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4640	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4641	if (error)
4642		return (error);
4643	if (fw->initvals_band.fw) {
4644		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4645		error = bwn_fwinitvals_write(mac,
4646		    GETFWOFFSET(fw->initvals_band, hdr_len),
4647		    be32toh(hdr->size),
4648		    fw->initvals_band.fw->datasize - hdr_len);
4649	}
4650	return (error);
4651#undef GETFWOFFSET
4652}
4653
4654static int
4655bwn_phy_init(struct bwn_mac *mac)
4656{
4657	struct bwn_softc *sc = mac->mac_sc;
4658	int error;
4659
4660	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4661	mac->mac_phy.rf_onoff(mac, 1);
4662	error = mac->mac_phy.init(mac);
4663	if (error) {
4664		device_printf(sc->sc_dev, "PHY init failed\n");
4665		goto fail0;
4666	}
4667	error = bwn_switch_channel(mac,
4668	    mac->mac_phy.get_default_chan(mac));
4669	if (error) {
4670		device_printf(sc->sc_dev,
4671		    "failed to switch default channel\n");
4672		goto fail1;
4673	}
4674	return (0);
4675fail1:
4676	if (mac->mac_phy.exit)
4677		mac->mac_phy.exit(mac);
4678fail0:
4679	mac->mac_phy.rf_onoff(mac, 0);
4680
4681	return (error);
4682}
4683
4684static void
4685bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4686{
4687	uint16_t ant;
4688	uint16_t tmp;
4689
4690	ant = bwn_ant2phy(antenna);
4691
4692	/* For ACK/CTS */
4693	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4694	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4695	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4696	/* For Probe Resposes */
4697	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4698	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4699	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4700}
4701
4702static void
4703bwn_set_opmode(struct bwn_mac *mac)
4704{
4705	struct bwn_softc *sc = mac->mac_sc;
4706	struct ifnet *ifp = sc->sc_ifp;
4707	struct ieee80211com *ic = ifp->if_l2com;
4708	uint32_t ctl;
4709	uint16_t cfp_pretbtt;
4710
4711	ctl = BWN_READ_4(mac, BWN_MACCTL);
4712	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4713	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4714	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4715	ctl |= BWN_MACCTL_STA;
4716
4717	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4718	    ic->ic_opmode == IEEE80211_M_MBSS)
4719		ctl |= BWN_MACCTL_HOSTAP;
4720	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4721		ctl &= ~BWN_MACCTL_STA;
4722	ctl |= sc->sc_filters;
4723
4724	if (siba_get_revid(sc->sc_dev) <= 4)
4725		ctl |= BWN_MACCTL_PROMISC;
4726
4727	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4728
4729	cfp_pretbtt = 2;
4730	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4731		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4732		    siba_get_chiprev(sc->sc_dev) == 3)
4733			cfp_pretbtt = 100;
4734		else
4735			cfp_pretbtt = 50;
4736	}
4737	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4738}
4739
4740static int
4741bwn_dma_gettype(struct bwn_mac *mac)
4742{
4743	uint32_t tmp;
4744	uint16_t base;
4745
4746	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4747	if (tmp & SIBA_TGSHIGH_DMA64)
4748		return (BWN_DMA_64BIT);
4749	base = bwn_dma_base(0, 0);
4750	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4751	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4752	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4753		return (BWN_DMA_32BIT);
4754
4755	return (BWN_DMA_30BIT);
4756}
4757
4758static void
4759bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4760{
4761	if (!error) {
4762		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4763		*((bus_addr_t *)arg) = seg->ds_addr;
4764	}
4765}
4766
4767static void
4768bwn_phy_g_init_sub(struct bwn_mac *mac)
4769{
4770	struct bwn_phy *phy = &mac->mac_phy;
4771	struct bwn_phy_g *pg = &phy->phy_g;
4772	struct bwn_softc *sc = mac->mac_sc;
4773	uint16_t i, tmp;
4774
4775	if (phy->rev == 1)
4776		bwn_phy_init_b5(mac);
4777	else
4778		bwn_phy_init_b6(mac);
4779
4780	if (phy->rev >= 2 || phy->gmode)
4781		bwn_phy_init_a(mac);
4782
4783	if (phy->rev >= 2) {
4784		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4785		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4786	}
4787	if (phy->rev == 2) {
4788		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4789		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4790	}
4791	if (phy->rev > 5) {
4792		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4793		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4794	}
4795	if (phy->gmode || phy->rev >= 2) {
4796		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4797		tmp &= BWN_PHYVER_VERSION;
4798		if (tmp == 3 || tmp == 5) {
4799			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4800			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4801		}
4802		if (tmp == 5) {
4803			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4804			    0x1f00);
4805		}
4806	}
4807	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4808		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4809	if (phy->rf_rev == 8) {
4810		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4811		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4812	}
4813	if (BWN_HAS_LOOPBACK(phy))
4814		bwn_loopback_calcgain(mac);
4815
4816	if (phy->rf_rev != 8) {
4817		if (pg->pg_initval == 0xffff)
4818			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4819		else
4820			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4821	}
4822	bwn_lo_g_init(mac);
4823	if (BWN_HAS_TXMAG(phy)) {
4824		BWN_RF_WRITE(mac, 0x52,
4825		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4826		    | pg->pg_loctl.tx_bias |
4827		    pg->pg_loctl.tx_magn);
4828	} else {
4829		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4830	}
4831	if (phy->rev >= 6) {
4832		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4833		    (pg->pg_loctl.tx_bias << 12));
4834	}
4835	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4836		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4837	else
4838		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4839	if (phy->rev < 2)
4840		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4841	else
4842		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4843	if (phy->gmode || phy->rev >= 2) {
4844		bwn_lo_g_adjust(mac);
4845		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4846	}
4847
4848	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4849		for (i = 0; i < 64; i++) {
4850			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4851			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4852			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4853			    -32), 31));
4854		}
4855		bwn_nrssi_threshold(mac);
4856	} else if (phy->gmode || phy->rev >= 2) {
4857		if (pg->pg_nrssi[0] == -1000) {
4858			KASSERT(pg->pg_nrssi[1] == -1000,
4859			    ("%s:%d: fail", __func__, __LINE__));
4860			bwn_nrssi_slope_11g(mac);
4861		} else
4862			bwn_nrssi_threshold(mac);
4863	}
4864	if (phy->rf_rev == 8)
4865		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4866	bwn_phy_hwpctl_init(mac);
4867	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4868	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4869		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4870		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4871	}
4872}
4873
4874static uint8_t
4875bwn_has_hwpctl(struct bwn_mac *mac)
4876{
4877
4878	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4879		return (0);
4880	return (mac->mac_phy.use_hwpctl(mac));
4881}
4882
4883static void
4884bwn_phy_init_b5(struct bwn_mac *mac)
4885{
4886	struct bwn_phy *phy = &mac->mac_phy;
4887	struct bwn_phy_g *pg = &phy->phy_g;
4888	struct bwn_softc *sc = mac->mac_sc;
4889	uint16_t offset, value;
4890	uint8_t old_channel;
4891
4892	if (phy->analog == 1)
4893		BWN_RF_SET(mac, 0x007a, 0x0050);
4894	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4895	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4896		value = 0x2120;
4897		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4898			BWN_PHY_WRITE(mac, offset, value);
4899			value += 0x202;
4900		}
4901	}
4902	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4903	if (phy->rf_ver == 0x2050)
4904		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4905
4906	if (phy->gmode || phy->rev >= 2) {
4907		if (phy->rf_ver == 0x2050) {
4908			BWN_RF_SET(mac, 0x007a, 0x0020);
4909			BWN_RF_SET(mac, 0x0051, 0x0004);
4910		}
4911		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4912
4913		BWN_PHY_SET(mac, 0x0802, 0x0100);
4914		BWN_PHY_SET(mac, 0x042b, 0x2000);
4915
4916		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4917
4918		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4919		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4920		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4921	}
4922
4923	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4924		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4925
4926	if (phy->analog == 1) {
4927		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4928		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4929		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4930		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4931		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4932	} else
4933		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4934	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4935	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4936
4937	if (phy->analog == 1)
4938		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4939	else
4940		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4941
4942	if (phy->analog == 0)
4943		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4944
4945	old_channel = phy->chan;
4946	bwn_phy_g_switch_chan(mac, 7, 0);
4947
4948	if (phy->rf_ver != 0x2050) {
4949		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4950		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4951	}
4952
4953	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4954	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4955
4956	if (phy->rf_ver == 0x2050) {
4957		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4958		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4959	}
4960
4961	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4962	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4963	BWN_RF_SET(mac, 0x007a, 0x0007);
4964
4965	bwn_phy_g_switch_chan(mac, old_channel, 0);
4966	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4967	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4968	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4969
4970	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4971	    pg->pg_txctl);
4972
4973	if (phy->rf_ver == 0x2050)
4974		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4975
4976	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4977}
4978
4979static void
4980bwn_loopback_calcgain(struct bwn_mac *mac)
4981{
4982	struct bwn_phy *phy = &mac->mac_phy;
4983	struct bwn_phy_g *pg = &phy->phy_g;
4984	struct bwn_softc *sc = mac->mac_sc;
4985	uint16_t backup_phy[16] = { 0 };
4986	uint16_t backup_radio[3];
4987	uint16_t backup_bband;
4988	uint16_t i, j, loop_i_max;
4989	uint16_t trsw_rx;
4990	uint16_t loop1_outer_done, loop1_inner_done;
4991
4992	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4993	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4994	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4995	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4996	if (phy->rev != 1) {
4997		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4998		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4999	}
5000	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5001	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5002	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5003	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5004	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5005	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5006	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5007	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5008	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5009	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5010	backup_bband = pg->pg_bbatt.att;
5011	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5012	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5013	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5014
5015	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5016	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5017	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5018	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5019	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5020	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5021	if (phy->rev != 1) {
5022		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5023		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5024		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5025		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5026	}
5027	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5028	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5029	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5030	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5031
5032	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5033	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5034	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5035
5036	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5037	if (phy->rev != 1) {
5038		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5039		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5040	}
5041	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5042
5043	if (phy->rf_rev == 8)
5044		BWN_RF_WRITE(mac, 0x43, 0x000f);
5045	else {
5046		BWN_RF_WRITE(mac, 0x52, 0);
5047		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5048	}
5049	bwn_phy_g_set_bbatt(mac, 11);
5050
5051	if (phy->rev >= 3)
5052		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5053	else
5054		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5055	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5056
5057	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5058	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5059
5060	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5061	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5062
5063	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5064		if (phy->rev >= 7) {
5065			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5066			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5067		}
5068	}
5069	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5070
5071	j = 0;
5072	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5073	for (i = 0; i < loop_i_max; i++) {
5074		for (j = 0; j < 16; j++) {
5075			BWN_RF_WRITE(mac, 0x43, i);
5076			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5077			    (j << 8));
5078			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5079			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5080			DELAY(20);
5081			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5082				goto done0;
5083		}
5084	}
5085done0:
5086	loop1_outer_done = i;
5087	loop1_inner_done = j;
5088	if (j >= 8) {
5089		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5090		trsw_rx = 0x1b;
5091		for (j = j - 8; j < 16; j++) {
5092			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5093			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5094			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5095			DELAY(20);
5096			trsw_rx -= 3;
5097			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5098				goto done1;
5099		}
5100	} else
5101		trsw_rx = 0x18;
5102done1:
5103
5104	if (phy->rev != 1) {
5105		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5106		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5107	}
5108	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5109	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5110	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5111	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5112	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5113	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5114	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5115	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5116	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5117
5118	bwn_phy_g_set_bbatt(mac, backup_bband);
5119
5120	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5121	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5122	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5123
5124	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5125	DELAY(10);
5126	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5127	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5128	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5129	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5130
5131	pg->pg_max_lb_gain =
5132	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5133	pg->pg_trsw_rx_gain = trsw_rx * 2;
5134}
5135
5136static uint16_t
5137bwn_rf_init_bcm2050(struct bwn_mac *mac)
5138{
5139	struct bwn_phy *phy = &mac->mac_phy;
5140	uint32_t tmp1 = 0, tmp2 = 0;
5141	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5142	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5143	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5144	static const uint8_t rcc_table[] = {
5145		0x02, 0x03, 0x01, 0x0f,
5146		0x06, 0x07, 0x05, 0x0f,
5147		0x0a, 0x0b, 0x09, 0x0f,
5148		0x0e, 0x0f, 0x0d, 0x0f,
5149	};
5150
5151	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5152	    rfoverval = rfover = cck3 = 0;
5153	radio0 = BWN_RF_READ(mac, 0x43);
5154	radio1 = BWN_RF_READ(mac, 0x51);
5155	radio2 = BWN_RF_READ(mac, 0x52);
5156	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5157	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5158	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5159	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5160
5161	if (phy->type == BWN_PHYTYPE_B) {
5162		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5163		reg0 = BWN_READ_2(mac, 0x3ec);
5164
5165		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5166		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5167	} else if (phy->gmode || phy->rev >= 2) {
5168		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5169		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5170		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5171		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5172		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5173		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5174
5175		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5176		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5177		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5178		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5179		if (BWN_HAS_LOOPBACK(phy)) {
5180			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5181			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5182			if (phy->rev >= 3)
5183				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5184			else
5185				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5186			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5187		}
5188
5189		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5190		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5191			BWN_LPD(0, 1, 1)));
5192		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5193		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5194	}
5195	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5196
5197	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5198	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5199	reg1 = BWN_READ_2(mac, 0x3e6);
5200	reg2 = BWN_READ_2(mac, 0x3f4);
5201
5202	if (phy->analog == 0)
5203		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5204	else {
5205		if (phy->analog >= 2)
5206			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5207		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5208		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5209	}
5210
5211	reg = BWN_RF_READ(mac, 0x60);
5212	index = (reg & 0x001e) >> 1;
5213	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5214
5215	if (phy->type == BWN_PHYTYPE_B)
5216		BWN_RF_WRITE(mac, 0x78, 0x26);
5217	if (phy->gmode || phy->rev >= 2) {
5218		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5219		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5220			BWN_LPD(0, 1, 1)));
5221	}
5222	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5223	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5224	if (phy->gmode || phy->rev >= 2) {
5225		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5226		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5227			BWN_LPD(0, 0, 1)));
5228	}
5229	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5230	BWN_RF_SET(mac, 0x51, 0x0004);
5231	if (phy->rf_rev == 8)
5232		BWN_RF_WRITE(mac, 0x43, 0x1f);
5233	else {
5234		BWN_RF_WRITE(mac, 0x52, 0);
5235		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5236	}
5237	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5238
5239	for (i = 0; i < 16; i++) {
5240		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5241		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5242		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5243		if (phy->gmode || phy->rev >= 2) {
5244			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5245			    bwn_rf_2050_rfoverval(mac,
5246				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5247		}
5248		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5249		DELAY(10);
5250		if (phy->gmode || phy->rev >= 2) {
5251			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5252			    bwn_rf_2050_rfoverval(mac,
5253				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5254		}
5255		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5256		DELAY(10);
5257		if (phy->gmode || phy->rev >= 2) {
5258			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5259			    bwn_rf_2050_rfoverval(mac,
5260				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5261		}
5262		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5263		DELAY(20);
5264		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5265		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5266		if (phy->gmode || phy->rev >= 2) {
5267			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5268			    bwn_rf_2050_rfoverval(mac,
5269				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5270		}
5271		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5272	}
5273	DELAY(10);
5274
5275	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5276	tmp1++;
5277	tmp1 >>= 9;
5278
5279	for (i = 0; i < 16; i++) {
5280		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5281		BWN_RF_WRITE(mac, 0x78, radio78);
5282		DELAY(10);
5283		for (j = 0; j < 16; j++) {
5284			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5285			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5286			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5287			if (phy->gmode || phy->rev >= 2) {
5288				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5289				    bwn_rf_2050_rfoverval(mac,
5290					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5291			}
5292			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5293			DELAY(10);
5294			if (phy->gmode || phy->rev >= 2) {
5295				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5296				    bwn_rf_2050_rfoverval(mac,
5297					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5298			}
5299			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5300			DELAY(10);
5301			if (phy->gmode || phy->rev >= 2) {
5302				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5303				    bwn_rf_2050_rfoverval(mac,
5304					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5305			}
5306			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5307			DELAY(10);
5308			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5309			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5310			if (phy->gmode || phy->rev >= 2) {
5311				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5312				    bwn_rf_2050_rfoverval(mac,
5313					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5314			}
5315			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5316		}
5317		tmp2++;
5318		tmp2 >>= 8;
5319		if (tmp1 < tmp2)
5320			break;
5321	}
5322
5323	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5324	BWN_RF_WRITE(mac, 0x51, radio1);
5325	BWN_RF_WRITE(mac, 0x52, radio2);
5326	BWN_RF_WRITE(mac, 0x43, radio0);
5327	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5328	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5329	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5330	BWN_WRITE_2(mac, 0x3e6, reg1);
5331	if (phy->analog != 0)
5332		BWN_WRITE_2(mac, 0x3f4, reg2);
5333	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5334	bwn_spu_workaround(mac, phy->chan);
5335	if (phy->type == BWN_PHYTYPE_B) {
5336		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5337		BWN_WRITE_2(mac, 0x3ec, reg0);
5338	} else if (phy->gmode) {
5339		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5340			    BWN_READ_2(mac, BWN_PHY_RADIO)
5341			    & 0x7fff);
5342		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5343		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5344		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5345		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5346			      analogoverval);
5347		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5348		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5349		if (BWN_HAS_LOOPBACK(phy)) {
5350			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5351			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5352		}
5353	}
5354
5355	return ((i > 15) ? radio78 : rcc);
5356}
5357
5358static void
5359bwn_phy_init_b6(struct bwn_mac *mac)
5360{
5361	struct bwn_phy *phy = &mac->mac_phy;
5362	struct bwn_phy_g *pg = &phy->phy_g;
5363	struct bwn_softc *sc = mac->mac_sc;
5364	uint16_t offset, val;
5365	uint8_t old_channel;
5366
5367	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5368	    ("%s:%d: fail", __func__, __LINE__));
5369
5370	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5371	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5372	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5373		BWN_RF_WRITE(mac, 0x51, 0x37);
5374		BWN_RF_WRITE(mac, 0x52, 0x70);
5375		BWN_RF_WRITE(mac, 0x53, 0xb3);
5376		BWN_RF_WRITE(mac, 0x54, 0x9b);
5377		BWN_RF_WRITE(mac, 0x5a, 0x88);
5378		BWN_RF_WRITE(mac, 0x5b, 0x88);
5379		BWN_RF_WRITE(mac, 0x5d, 0x88);
5380		BWN_RF_WRITE(mac, 0x5e, 0x88);
5381		BWN_RF_WRITE(mac, 0x7d, 0x88);
5382		bwn_hf_write(mac,
5383		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5384	}
5385	if (phy->rf_rev == 8) {
5386		BWN_RF_WRITE(mac, 0x51, 0);
5387		BWN_RF_WRITE(mac, 0x52, 0x40);
5388		BWN_RF_WRITE(mac, 0x53, 0xb7);
5389		BWN_RF_WRITE(mac, 0x54, 0x98);
5390		BWN_RF_WRITE(mac, 0x5a, 0x88);
5391		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5392		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5393		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5394			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5395			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5396		} else {
5397			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5398			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5399		}
5400		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5401		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5402		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5403		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5404	}
5405	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5406		BWN_PHY_WRITE(mac, offset, val);
5407		val -= 0x0202;
5408	}
5409	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5410		BWN_PHY_WRITE(mac, offset, val);
5411		val -= 0x0202;
5412	}
5413	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5414		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5415		val += 0x0202;
5416	}
5417	if (phy->type == BWN_PHYTYPE_G) {
5418		BWN_RF_SET(mac, 0x007a, 0x0020);
5419		BWN_RF_SET(mac, 0x0051, 0x0004);
5420		BWN_PHY_SET(mac, 0x0802, 0x0100);
5421		BWN_PHY_SET(mac, 0x042b, 0x2000);
5422		BWN_PHY_WRITE(mac, 0x5b, 0);
5423		BWN_PHY_WRITE(mac, 0x5c, 0);
5424	}
5425
5426	old_channel = phy->chan;
5427	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5428
5429	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5430	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5431	DELAY(40);
5432	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5433		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5434		BWN_RF_WRITE(mac, 0x50, 0x20);
5435	}
5436	if (phy->rf_rev <= 2) {
5437		BWN_RF_WRITE(mac, 0x7c, 0x20);
5438		BWN_RF_WRITE(mac, 0x5a, 0x70);
5439		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5440		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5441	}
5442	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5443
5444	bwn_phy_g_switch_chan(mac, old_channel, 0);
5445
5446	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5447	if (phy->rf_rev >= 6)
5448		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5449	else
5450		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5451	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5452	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5453	    pg->pg_txctl);
5454	if (phy->rf_rev <= 5)
5455		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5456	if (phy->rf_rev <= 2)
5457		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5458
5459	if (phy->analog == 4) {
5460		BWN_WRITE_2(mac, 0x3e4, 9);
5461		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5462	} else
5463		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5464	if (phy->type == BWN_PHYTYPE_B)
5465		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5466	else if (phy->type == BWN_PHYTYPE_G)
5467		BWN_WRITE_2(mac, 0x03e6, 0x0);
5468}
5469
5470static void
5471bwn_phy_init_a(struct bwn_mac *mac)
5472{
5473	struct bwn_phy *phy = &mac->mac_phy;
5474	struct bwn_softc *sc = mac->mac_sc;
5475
5476	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5477	    ("%s:%d: fail", __func__, __LINE__));
5478
5479	if (phy->rev >= 6) {
5480		if (phy->type == BWN_PHYTYPE_A)
5481			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5482		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5483			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5484		else
5485			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5486	}
5487
5488	bwn_wa_init(mac);
5489
5490	if (phy->type == BWN_PHYTYPE_G &&
5491	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5492		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5493}
5494
5495static void
5496bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5497{
5498	int i;
5499
5500	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5501		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5502}
5503
5504static void
5505bwn_wa_agc(struct bwn_mac *mac)
5506{
5507	struct bwn_phy *phy = &mac->mac_phy;
5508
5509	if (phy->rev == 1) {
5510		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5511		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5512		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5513		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5514		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5515		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5516		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5517		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5518		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5519	} else {
5520		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5521		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5522		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5523		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5524	}
5525
5526	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5527	    0x5700);
5528	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5529	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5530	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5531	BWN_RF_SET(mac, 0x7a, 0x0008);
5532	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5533	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5534	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5535	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5536	if (phy->rev == 1)
5537		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5538	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5539	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5540	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5541	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5542	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5543	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5544	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5545	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5546	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5547	if (phy->rev == 1) {
5548		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5549		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5550	} else {
5551		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5552		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5553		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5554		if (phy->rev >= 6) {
5555			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5556			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5557			    (uint16_t)~0xf000, 0x3000);
5558		}
5559	}
5560	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5561	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5562	if (phy->rev == 1) {
5563		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5564		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5565		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5566		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5567		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5568		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5569		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5570		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5571	} else {
5572		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5573		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5574		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5575		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5576	}
5577	if (phy->rev >= 6) {
5578		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5579		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5580	}
5581	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5582}
5583
5584static void
5585bwn_wa_grev1(struct bwn_mac *mac)
5586{
5587	struct bwn_phy *phy = &mac->mac_phy;
5588	int i;
5589	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5590	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5591	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5592
5593	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5594
5595	/* init CRSTHRES and ANTDWELL */
5596	if (phy->rev == 1) {
5597		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5598	} else if (phy->rev == 2) {
5599		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5600		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5601		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5602	} else {
5603		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5604		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5605		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5606		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5607	}
5608	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5609	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5610	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5611
5612	/* XXX support PHY-A??? */
5613	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5614		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5615		    bwn_tab_finefreqg[i]);
5616
5617	/* XXX support PHY-A??? */
5618	if (phy->rev == 1)
5619		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5620			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5621			    bwn_tab_noise_g1[i]);
5622	else
5623		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5624			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5625			    bwn_tab_noise_g2[i]);
5626
5627
5628	for (i = 0; i < N(bwn_tab_rotor); i++)
5629		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5630		    bwn_tab_rotor[i]);
5631
5632	/* XXX support PHY-A??? */
5633	if (phy->rev >= 6) {
5634		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5635		    BWN_PHY_ENCORE_EN)
5636			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5637		else
5638			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5639	} else
5640		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5641
5642	for (i = 0; i < N(bwn_tab_retard); i++)
5643		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5644		    bwn_tab_retard[i]);
5645
5646	if (phy->rev == 1) {
5647		for (i = 0; i < 16; i++)
5648			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5649			    i, 0x0020);
5650	} else {
5651		for (i = 0; i < 32; i++)
5652			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5653	}
5654
5655	bwn_wa_agc(mac);
5656}
5657
5658static void
5659bwn_wa_grev26789(struct bwn_mac *mac)
5660{
5661	struct bwn_phy *phy = &mac->mac_phy;
5662	int i;
5663	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5664	uint16_t ofdmrev;
5665
5666	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5667
5668	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5669
5670	/* init CRSTHRES and ANTDWELL */
5671	if (phy->rev == 1)
5672		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5673	else if (phy->rev == 2) {
5674		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5675		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5676		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5677	} else {
5678		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5679		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5680		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5681		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5682	}
5683
5684	for (i = 0; i < 64; i++)
5685		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5686
5687	/* XXX support PHY-A??? */
5688	if (phy->rev == 1)
5689		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5690			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5691			    bwn_tab_noise_g1[i]);
5692	else
5693		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5694			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5695			    bwn_tab_noise_g2[i]);
5696
5697	/* XXX support PHY-A??? */
5698	if (phy->rev >= 6) {
5699		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5700		    BWN_PHY_ENCORE_EN)
5701			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5702		else
5703			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5704	} else
5705		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5706
5707	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5708		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5709		    bwn_tab_sigmasqr2[i]);
5710
5711	if (phy->rev == 1) {
5712		for (i = 0; i < 16; i++)
5713			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5714			    0x0020);
5715	} else {
5716		for (i = 0; i < 32; i++)
5717			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5718	}
5719
5720	bwn_wa_agc(mac);
5721
5722	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5723	if (ofdmrev > 2) {
5724		if (phy->type == BWN_PHYTYPE_A)
5725			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5726		else
5727			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5728	} else {
5729		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5730		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5731		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5732	}
5733
5734	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5735	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5736}
5737
5738static void
5739bwn_wa_init(struct bwn_mac *mac)
5740{
5741	struct bwn_phy *phy = &mac->mac_phy;
5742	struct bwn_softc *sc = mac->mac_sc;
5743
5744	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5745
5746	switch (phy->rev) {
5747	case 1:
5748		bwn_wa_grev1(mac);
5749		break;
5750	case 2:
5751	case 6:
5752	case 7:
5753	case 8:
5754	case 9:
5755		bwn_wa_grev26789(mac);
5756		break;
5757	default:
5758		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5759	}
5760
5761	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5762	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5763	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5764		if (phy->rev < 2) {
5765			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5766			    0x0002);
5767			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5768			    0x0001);
5769		} else {
5770			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5771			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5772			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5773			     BWN_BFL_EXTLNA) &&
5774			    (phy->rev >= 7)) {
5775				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5776				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5777				    0x0020, 0x0001);
5778				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5779				    0x0021, 0x0001);
5780				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5781				    0x0022, 0x0001);
5782				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5783				    0x0023, 0x0000);
5784				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5785				    0x0000, 0x0000);
5786				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5787				    0x0003, 0x0002);
5788			}
5789		}
5790	}
5791	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5792		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5793		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5794	}
5795
5796	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5797	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5798}
5799
5800static void
5801bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5802    uint16_t value)
5803{
5804	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5805	uint16_t addr;
5806
5807	addr = table + offset;
5808	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5809	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5810		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5811		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5812	}
5813	pg->pg_ofdmtab_addr = addr;
5814	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5815}
5816
5817static void
5818bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5819    uint32_t value)
5820{
5821	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5822	uint16_t addr;
5823
5824	addr = table + offset;
5825	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5826	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5827		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5828		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5829	}
5830	pg->pg_ofdmtab_addr = addr;
5831
5832	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5833	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5834}
5835
5836static void
5837bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5838    uint16_t value)
5839{
5840
5841	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5842	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5843}
5844
5845static void
5846bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5847{
5848	struct bwn_phy *phy = &mac->mac_phy;
5849	struct bwn_softc *sc = mac->mac_sc;
5850	unsigned int i, max_loop;
5851	uint16_t value;
5852	uint32_t buffer[5] = {
5853		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5854	};
5855
5856	if (ofdm) {
5857		max_loop = 0x1e;
5858		buffer[0] = 0x000201cc;
5859	} else {
5860		max_loop = 0xfa;
5861		buffer[0] = 0x000b846e;
5862	}
5863
5864	BWN_ASSERT_LOCKED(mac->mac_sc);
5865
5866	for (i = 0; i < 5; i++)
5867		bwn_ram_write(mac, i * 4, buffer[i]);
5868
5869	BWN_WRITE_2(mac, 0x0568, 0x0000);
5870	BWN_WRITE_2(mac, 0x07c0,
5871	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5872	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5873	BWN_WRITE_2(mac, 0x050c, value);
5874	if (phy->type == BWN_PHYTYPE_LP)
5875		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5876	BWN_WRITE_2(mac, 0x0508, 0x0000);
5877	BWN_WRITE_2(mac, 0x050a, 0x0000);
5878	BWN_WRITE_2(mac, 0x054c, 0x0000);
5879	BWN_WRITE_2(mac, 0x056a, 0x0014);
5880	BWN_WRITE_2(mac, 0x0568, 0x0826);
5881	BWN_WRITE_2(mac, 0x0500, 0x0000);
5882	if (phy->type == BWN_PHYTYPE_LP)
5883		BWN_WRITE_2(mac, 0x0502, 0x0050);
5884	else
5885		BWN_WRITE_2(mac, 0x0502, 0x0030);
5886
5887	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5888		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5889	for (i = 0x00; i < max_loop; i++) {
5890		value = BWN_READ_2(mac, 0x050e);
5891		if (value & 0x0080)
5892			break;
5893		DELAY(10);
5894	}
5895	for (i = 0x00; i < 0x0a; i++) {
5896		value = BWN_READ_2(mac, 0x050e);
5897		if (value & 0x0400)
5898			break;
5899		DELAY(10);
5900	}
5901	for (i = 0x00; i < 0x19; i++) {
5902		value = BWN_READ_2(mac, 0x0690);
5903		if (!(value & 0x0100))
5904			break;
5905		DELAY(10);
5906	}
5907	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5908		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5909}
5910
5911static void
5912bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5913{
5914	uint32_t macctl;
5915
5916	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5917
5918	macctl = BWN_READ_4(mac, BWN_MACCTL);
5919	if (macctl & BWN_MACCTL_BIGENDIAN)
5920		printf("TODO: need swap\n");
5921
5922	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5923	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5924	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5925}
5926
5927static void
5928bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5929{
5930	uint16_t value;
5931
5932	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5933	    ("%s:%d: fail", __func__, __LINE__));
5934
5935	value = (uint8_t) (ctl->q);
5936	value |= ((uint8_t) (ctl->i)) << 8;
5937	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5938}
5939
5940static uint16_t
5941bwn_lo_calcfeed(struct bwn_mac *mac,
5942    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5943{
5944	struct bwn_phy *phy = &mac->mac_phy;
5945	struct bwn_softc *sc = mac->mac_sc;
5946	uint16_t rfover;
5947	uint16_t feedthrough;
5948
5949	if (phy->gmode) {
5950		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5951		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5952
5953		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5954		    ("%s:%d: fail", __func__, __LINE__));
5955		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5956		    ("%s:%d: fail", __func__, __LINE__));
5957
5958		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5959
5960		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5961		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5962		    phy->rev > 6)
5963			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5964
5965		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5966		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5967		DELAY(10);
5968		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5969		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5970		DELAY(10);
5971		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5972		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5973		DELAY(10);
5974		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5975	} else {
5976		pga |= BWN_PHY_PGACTL_UNKNOWN;
5977		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5978		DELAY(10);
5979		pga |= BWN_PHY_PGACTL_LOWBANDW;
5980		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5981		DELAY(10);
5982		pga |= BWN_PHY_PGACTL_LPF;
5983		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5984	}
5985	DELAY(21);
5986	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5987
5988	return (feedthrough);
5989}
5990
5991static uint16_t
5992bwn_lo_txctl_regtable(struct bwn_mac *mac,
5993    uint16_t *value, uint16_t *pad_mix_gain)
5994{
5995	struct bwn_phy *phy = &mac->mac_phy;
5996	uint16_t reg, v, padmix;
5997
5998	if (phy->type == BWN_PHYTYPE_B) {
5999		v = 0x30;
6000		if (phy->rf_rev <= 5) {
6001			reg = 0x43;
6002			padmix = 0;
6003		} else {
6004			reg = 0x52;
6005			padmix = 5;
6006		}
6007	} else {
6008		if (phy->rev >= 2 && phy->rf_rev == 8) {
6009			reg = 0x43;
6010			v = 0x10;
6011			padmix = 2;
6012		} else {
6013			reg = 0x52;
6014			v = 0x30;
6015			padmix = 5;
6016		}
6017	}
6018	if (value)
6019		*value = v;
6020	if (pad_mix_gain)
6021		*pad_mix_gain = padmix;
6022
6023	return (reg);
6024}
6025
6026static void
6027bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6028{
6029	struct bwn_phy *phy = &mac->mac_phy;
6030	struct bwn_phy_g *pg = &phy->phy_g;
6031	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6032	uint16_t reg, mask;
6033	uint16_t trsw_rx, pga;
6034	uint16_t rf_pctl_reg;
6035
6036	static const uint8_t tx_bias_values[] = {
6037		0x09, 0x08, 0x0a, 0x01, 0x00,
6038		0x02, 0x05, 0x04, 0x06,
6039	};
6040	static const uint8_t tx_magn_values[] = {
6041		0x70, 0x40,
6042	};
6043
6044	if (!BWN_HAS_LOOPBACK(phy)) {
6045		rf_pctl_reg = 6;
6046		trsw_rx = 2;
6047		pga = 0;
6048	} else {
6049		int lb_gain;
6050
6051		trsw_rx = 0;
6052		lb_gain = pg->pg_max_lb_gain / 2;
6053		if (lb_gain > 10) {
6054			rf_pctl_reg = 0;
6055			pga = abs(10 - lb_gain) / 6;
6056			pga = MIN(MAX(pga, 0), 15);
6057		} else {
6058			int cmp_val;
6059			int tmp;
6060
6061			pga = 0;
6062			cmp_val = 0x24;
6063			if ((phy->rev >= 2) &&
6064			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6065				cmp_val = 0x3c;
6066			tmp = lb_gain;
6067			if ((10 - lb_gain) < cmp_val)
6068				tmp = (10 - lb_gain);
6069			if (tmp < 0)
6070				tmp += 6;
6071			else
6072				tmp += 3;
6073			cmp_val /= 4;
6074			tmp /= 4;
6075			if (tmp >= cmp_val)
6076				rf_pctl_reg = cmp_val;
6077			else
6078				rf_pctl_reg = tmp;
6079		}
6080	}
6081	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6082	bwn_phy_g_set_bbatt(mac, 2);
6083
6084	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6085	mask = ~mask;
6086	BWN_RF_MASK(mac, reg, mask);
6087
6088	if (BWN_HAS_TXMAG(phy)) {
6089		int i, j;
6090		int feedthrough;
6091		int min_feedth = 0xffff;
6092		uint8_t tx_magn, tx_bias;
6093
6094		for (i = 0; i < N(tx_magn_values); i++) {
6095			tx_magn = tx_magn_values[i];
6096			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6097			for (j = 0; j < N(tx_bias_values); j++) {
6098				tx_bias = tx_bias_values[j];
6099				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6100				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6101				    trsw_rx);
6102				if (feedthrough < min_feedth) {
6103					lo->tx_bias = tx_bias;
6104					lo->tx_magn = tx_magn;
6105					min_feedth = feedthrough;
6106				}
6107				if (lo->tx_bias == 0)
6108					break;
6109			}
6110			BWN_RF_WRITE(mac, 0x52,
6111					  (BWN_RF_READ(mac, 0x52)
6112					   & 0xff00) | lo->tx_bias | lo->
6113					  tx_magn);
6114		}
6115	} else {
6116		lo->tx_magn = 0;
6117		lo->tx_bias = 0;
6118		BWN_RF_MASK(mac, 0x52, 0xfff0);
6119	}
6120
6121	BWN_GETTIME(lo->txctl_measured_time);
6122}
6123
6124static void
6125bwn_lo_get_powervector(struct bwn_mac *mac)
6126{
6127	struct bwn_phy *phy = &mac->mac_phy;
6128	struct bwn_phy_g *pg = &phy->phy_g;
6129	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6130	int i;
6131	uint64_t tmp;
6132	uint64_t power_vector = 0;
6133
6134	for (i = 0; i < 8; i += 2) {
6135		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6136		power_vector |= (tmp << (i * 8));
6137		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6138	}
6139	if (power_vector)
6140		lo->power_vector = power_vector;
6141
6142	BWN_GETTIME(lo->pwr_vec_read_time);
6143}
6144
6145static void
6146bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6147    int use_trsw_rx)
6148{
6149	struct bwn_phy *phy = &mac->mac_phy;
6150	struct bwn_phy_g *pg = &phy->phy_g;
6151	uint16_t tmp;
6152
6153	if (max_rx_gain < 0)
6154		max_rx_gain = 0;
6155
6156	if (BWN_HAS_LOOPBACK(phy)) {
6157		int trsw_rx = 0;
6158		int trsw_rx_gain;
6159
6160		if (use_trsw_rx) {
6161			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6162			if (max_rx_gain >= trsw_rx_gain) {
6163				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6164				trsw_rx = 0x20;
6165			}
6166		} else
6167			trsw_rx_gain = max_rx_gain;
6168		if (trsw_rx_gain < 9) {
6169			pg->pg_lna_lod_gain = 0;
6170		} else {
6171			pg->pg_lna_lod_gain = 1;
6172			trsw_rx_gain -= 8;
6173		}
6174		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6175		pg->pg_pga_gain = trsw_rx_gain / 3;
6176		if (pg->pg_pga_gain >= 5) {
6177			pg->pg_pga_gain -= 5;
6178			pg->pg_lna_gain = 2;
6179		} else
6180			pg->pg_lna_gain = 0;
6181	} else {
6182		pg->pg_lna_gain = 0;
6183		pg->pg_trsw_rx_gain = 0x20;
6184		if (max_rx_gain >= 0x14) {
6185			pg->pg_lna_lod_gain = 1;
6186			pg->pg_pga_gain = 2;
6187		} else if (max_rx_gain >= 0x12) {
6188			pg->pg_lna_lod_gain = 1;
6189			pg->pg_pga_gain = 1;
6190		} else if (max_rx_gain >= 0xf) {
6191			pg->pg_lna_lod_gain = 1;
6192			pg->pg_pga_gain = 0;
6193		} else {
6194			pg->pg_lna_lod_gain = 0;
6195			pg->pg_pga_gain = 0;
6196		}
6197	}
6198
6199	tmp = BWN_RF_READ(mac, 0x7a);
6200	if (pg->pg_lna_lod_gain == 0)
6201		tmp &= ~0x0008;
6202	else
6203		tmp |= 0x0008;
6204	BWN_RF_WRITE(mac, 0x7a, tmp);
6205}
6206
6207static void
6208bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6209{
6210	struct bwn_phy *phy = &mac->mac_phy;
6211	struct bwn_phy_g *pg = &phy->phy_g;
6212	struct bwn_softc *sc = mac->mac_sc;
6213	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6214	struct timespec ts;
6215	uint16_t tmp;
6216
6217	if (bwn_has_hwpctl(mac)) {
6218		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6219		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6220		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6221		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6222		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6223
6224		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6225		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6226		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6227		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6228	}
6229	if (phy->type == BWN_PHYTYPE_B &&
6230	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6231		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6232		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6233	}
6234	if (phy->rev >= 2) {
6235		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6236		sav->phy_analogoverval =
6237		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6238		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6239		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6240		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6241		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6242		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6243
6244		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6245		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6246		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6247		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6248		if (phy->type == BWN_PHYTYPE_G) {
6249			if ((phy->rev >= 7) &&
6250			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6251			     BWN_BFL_EXTLNA)) {
6252				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6253			} else {
6254				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6255			}
6256		} else {
6257			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6258		}
6259		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6260	}
6261	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6262	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6263	sav->rf0 = BWN_RF_READ(mac, 0x43);
6264	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6265	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6266	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6267	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6268	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6269
6270	if (!BWN_HAS_TXMAG(phy)) {
6271		sav->rf2 = BWN_RF_READ(mac, 0x52);
6272		sav->rf2 &= 0x00f0;
6273	}
6274	if (phy->type == BWN_PHYTYPE_B) {
6275		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6276		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6277		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6278		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6279	} else {
6280		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6281			    | 0x8000);
6282	}
6283	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6284		    & 0xf000);
6285
6286	tmp =
6287	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6288	BWN_PHY_WRITE(mac, tmp, 0x007f);
6289
6290	tmp = sav->phy_syncctl;
6291	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6292	tmp = sav->rf1;
6293	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6294
6295	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6296	if (phy->type == BWN_PHYTYPE_G ||
6297	    (phy->type == BWN_PHYTYPE_B &&
6298	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6299		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6300	} else
6301		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6302	if (phy->rev >= 2)
6303		bwn_dummy_transmission(mac, 0, 1);
6304	bwn_phy_g_switch_chan(mac, 6, 0);
6305	BWN_RF_READ(mac, 0x51);
6306	if (phy->type == BWN_PHYTYPE_G)
6307		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6308
6309	nanouptime(&ts);
6310	if (time_before(lo->txctl_measured_time,
6311	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6312		bwn_lo_measure_txctl_values(mac);
6313
6314	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6315		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6316	else {
6317		if (phy->type == BWN_PHYTYPE_B)
6318			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6319		else
6320			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6321	}
6322}
6323
6324static void
6325bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6326{
6327	struct bwn_phy *phy = &mac->mac_phy;
6328	struct bwn_phy_g *pg = &phy->phy_g;
6329	uint16_t tmp;
6330
6331	if (phy->rev >= 2) {
6332		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6333		tmp = (pg->pg_pga_gain << 8);
6334		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6335		DELAY(5);
6336		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6337		DELAY(2);
6338		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6339	} else {
6340		tmp = (pg->pg_pga_gain | 0xefa0);
6341		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6342	}
6343	if (phy->type == BWN_PHYTYPE_G) {
6344		if (phy->rev >= 3)
6345			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6346		else
6347			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6348		if (phy->rev >= 2)
6349			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6350		else
6351			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6352	}
6353	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6354	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6355	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6356	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6357	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6358	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6359	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6360	if (!BWN_HAS_TXMAG(phy)) {
6361		tmp = sav->rf2;
6362		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6363	}
6364	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6365	if (phy->type == BWN_PHYTYPE_B &&
6366	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6367		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6368		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6369	}
6370	if (phy->rev >= 2) {
6371		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6372		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6373			      sav->phy_analogoverval);
6374		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6375		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6376		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6377		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6378		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6379	}
6380	if (bwn_has_hwpctl(mac)) {
6381		tmp = (sav->phy_lomask & 0xbfff);
6382		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6383		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6384		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6385		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6386		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6387	}
6388	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6389}
6390
6391static int
6392bwn_lo_probe_loctl(struct bwn_mac *mac,
6393    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6394{
6395	struct bwn_phy *phy = &mac->mac_phy;
6396	struct bwn_phy_g *pg = &phy->phy_g;
6397	struct bwn_loctl orig, test;
6398	struct bwn_loctl prev = { -100, -100 };
6399	static const struct bwn_loctl modifiers[] = {
6400		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6401		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6402	};
6403	int begin, end, lower = 0, i;
6404	uint16_t feedth;
6405
6406	if (d->curstate == 0) {
6407		begin = 1;
6408		end = 8;
6409	} else if (d->curstate % 2 == 0) {
6410		begin = d->curstate - 1;
6411		end = d->curstate + 1;
6412	} else {
6413		begin = d->curstate - 2;
6414		end = d->curstate + 2;
6415	}
6416	if (begin < 1)
6417		begin += 8;
6418	if (end > 8)
6419		end -= 8;
6420
6421	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6422	i = begin;
6423	d->curstate = i;
6424	while (1) {
6425		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6426		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6427		test.i += modifiers[i - 1].i * d->multipler;
6428		test.q += modifiers[i - 1].q * d->multipler;
6429		if ((test.i != prev.i || test.q != prev.q) &&
6430		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6431			bwn_lo_write(mac, &test);
6432			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6433			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6434			if (feedth < d->feedth) {
6435				memcpy(probe, &test,
6436				    sizeof(struct bwn_loctl));
6437				lower = 1;
6438				d->feedth = feedth;
6439				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6440					break;
6441			}
6442		}
6443		memcpy(&prev, &test, sizeof(prev));
6444		if (i == end)
6445			break;
6446		if (i == 8)
6447			i = 1;
6448		else
6449			i++;
6450		d->curstate = i;
6451	}
6452
6453	return (lower);
6454}
6455
6456static void
6457bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6458{
6459	struct bwn_phy *phy = &mac->mac_phy;
6460	struct bwn_phy_g *pg = &phy->phy_g;
6461	struct bwn_lo_g_sm d;
6462	struct bwn_loctl probe;
6463	int lower, repeat, cnt = 0;
6464	uint16_t feedth;
6465
6466	d.nmeasure = 0;
6467	d.multipler = 1;
6468	if (BWN_HAS_LOOPBACK(phy))
6469		d.multipler = 3;
6470
6471	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6472	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6473
6474	do {
6475		bwn_lo_write(mac, &d.loctl);
6476		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6477		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6478		if (feedth < 0x258) {
6479			if (feedth >= 0x12c)
6480				*rxgain += 6;
6481			else
6482				*rxgain += 3;
6483			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6484			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6485		}
6486		d.feedth = feedth;
6487		d.curstate = 0;
6488		do {
6489			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6490			    ("%s:%d: fail", __func__, __LINE__));
6491			memcpy(&probe, &d.loctl,
6492			       sizeof(struct bwn_loctl));
6493			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6494			if (!lower)
6495				break;
6496			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6497				break;
6498			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6499			d.nmeasure++;
6500		} while (d.nmeasure < 24);
6501		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6502
6503		if (BWN_HAS_LOOPBACK(phy)) {
6504			if (d.feedth > 0x1194)
6505				*rxgain -= 6;
6506			else if (d.feedth < 0x5dc)
6507				*rxgain += 3;
6508			if (cnt == 0) {
6509				if (d.feedth <= 0x5dc) {
6510					d.multipler = 1;
6511					cnt++;
6512				} else
6513					d.multipler = 2;
6514			} else if (cnt == 2)
6515				d.multipler = 1;
6516		}
6517		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6518	} while (++cnt < repeat);
6519}
6520
6521static struct bwn_lo_calib *
6522bwn_lo_calibset(struct bwn_mac *mac,
6523    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6524{
6525	struct bwn_phy *phy = &mac->mac_phy;
6526	struct bwn_phy_g *pg = &phy->phy_g;
6527	struct bwn_loctl loctl = { 0, 0 };
6528	struct bwn_lo_calib *cal;
6529	struct bwn_lo_g_value sval = { 0 };
6530	int rxgain;
6531	uint16_t pad, reg, value;
6532
6533	sval.old_channel = phy->chan;
6534	bwn_mac_suspend(mac);
6535	bwn_lo_save(mac, &sval);
6536
6537	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6538	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6539	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6540
6541	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6542	if (rfatt->padmix)
6543		rxgain -= pad;
6544	if (BWN_HAS_LOOPBACK(phy))
6545		rxgain += pg->pg_max_lb_gain;
6546	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6547	bwn_phy_g_set_bbatt(mac, bbatt->att);
6548	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6549
6550	bwn_lo_restore(mac, &sval);
6551	bwn_mac_enable(mac);
6552
6553	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6554	if (!cal) {
6555		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6556		return (NULL);
6557	}
6558	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6559	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6560	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6561
6562	BWN_GETTIME(cal->calib_time);
6563
6564	return (cal);
6565}
6566
6567static struct bwn_lo_calib *
6568bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6569    const struct bwn_rfatt *rfatt)
6570{
6571	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6572	struct bwn_lo_calib *c;
6573
6574	TAILQ_FOREACH(c, &lo->calib_list, list) {
6575		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6576			continue;
6577		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6578			continue;
6579		return (c);
6580	}
6581
6582	c = bwn_lo_calibset(mac, bbatt, rfatt);
6583	if (!c)
6584		return (NULL);
6585	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6586
6587	return (c);
6588}
6589
6590static void
6591bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6592{
6593	struct bwn_phy *phy = &mac->mac_phy;
6594	struct bwn_phy_g *pg = &phy->phy_g;
6595	struct bwn_softc *sc = mac->mac_sc;
6596	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6597	const struct bwn_rfatt *rfatt;
6598	const struct bwn_bbatt *bbatt;
6599	uint64_t pvector;
6600	int i;
6601	int rf_offset, bb_offset;
6602	uint8_t changed = 0;
6603
6604	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6605	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6606	    ("%s:%d: fail", __func__, __LINE__));
6607
6608	pvector = lo->power_vector;
6609	if (!update && !pvector)
6610		return;
6611
6612	bwn_mac_suspend(mac);
6613
6614	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6615		struct bwn_lo_calib *cal;
6616		int idx;
6617		uint16_t val;
6618
6619		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6620			continue;
6621		bb_offset = i / lo->rfatt.len;
6622		rf_offset = i % lo->rfatt.len;
6623		bbatt = &(lo->bbatt.array[bb_offset]);
6624		rfatt = &(lo->rfatt.array[rf_offset]);
6625
6626		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6627		if (!cal) {
6628			device_printf(sc->sc_dev, "LO: Could not "
6629			    "calibrate DC table entry\n");
6630			continue;
6631		}
6632		val = (uint8_t)(cal->ctl.q);
6633		val |= ((uint8_t)(cal->ctl.i)) << 4;
6634		free(cal, M_DEVBUF);
6635
6636		idx = i / 2;
6637		if (i % 2)
6638			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6639			    | ((val & 0x00ff) << 8);
6640		else
6641			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6642			    | (val & 0x00ff);
6643		changed = 1;
6644	}
6645	if (changed) {
6646		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6647			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6648	}
6649	bwn_mac_enable(mac);
6650}
6651
6652static void
6653bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6654{
6655
6656	if (!rf->padmix)
6657		return;
6658	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6659		rf->att = 4;
6660}
6661
6662static void
6663bwn_lo_g_adjust(struct bwn_mac *mac)
6664{
6665	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6666	struct bwn_lo_calib *cal;
6667	struct bwn_rfatt rf;
6668
6669	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6670	bwn_lo_fixup_rfatt(&rf);
6671
6672	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6673	if (!cal)
6674		return;
6675	bwn_lo_write(mac, &cal->ctl);
6676}
6677
6678static void
6679bwn_lo_g_init(struct bwn_mac *mac)
6680{
6681
6682	if (!bwn_has_hwpctl(mac))
6683		return;
6684
6685	bwn_lo_get_powervector(mac);
6686	bwn_phy_g_dc_lookup_init(mac, 1);
6687}
6688
6689static void
6690bwn_mac_suspend(struct bwn_mac *mac)
6691{
6692	struct bwn_softc *sc = mac->mac_sc;
6693	int i;
6694	uint32_t tmp;
6695
6696	KASSERT(mac->mac_suspended >= 0,
6697	    ("%s:%d: fail", __func__, __LINE__));
6698
6699	if (mac->mac_suspended == 0) {
6700		bwn_psctl(mac, BWN_PS_AWAKE);
6701		BWN_WRITE_4(mac, BWN_MACCTL,
6702			    BWN_READ_4(mac, BWN_MACCTL)
6703			    & ~BWN_MACCTL_ON);
6704		BWN_READ_4(mac, BWN_MACCTL);
6705		for (i = 35; i; i--) {
6706			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6707			if (tmp & BWN_INTR_MAC_SUSPENDED)
6708				goto out;
6709			DELAY(10);
6710		}
6711		for (i = 40; i; i--) {
6712			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6713			if (tmp & BWN_INTR_MAC_SUSPENDED)
6714				goto out;
6715			DELAY(1000);
6716		}
6717		device_printf(sc->sc_dev, "MAC suspend failed\n");
6718	}
6719out:
6720	mac->mac_suspended++;
6721}
6722
6723static void
6724bwn_mac_enable(struct bwn_mac *mac)
6725{
6726	struct bwn_softc *sc = mac->mac_sc;
6727	uint16_t state;
6728
6729	state = bwn_shm_read_2(mac, BWN_SHARED,
6730	    BWN_SHARED_UCODESTAT);
6731	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6732	    state != BWN_SHARED_UCODESTAT_SLEEP)
6733		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6734
6735	mac->mac_suspended--;
6736	KASSERT(mac->mac_suspended >= 0,
6737	    ("%s:%d: fail", __func__, __LINE__));
6738	if (mac->mac_suspended == 0) {
6739		BWN_WRITE_4(mac, BWN_MACCTL,
6740		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6741		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6742		BWN_READ_4(mac, BWN_MACCTL);
6743		BWN_READ_4(mac, BWN_INTR_REASON);
6744		bwn_psctl(mac, 0);
6745	}
6746}
6747
6748static void
6749bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6750{
6751	struct bwn_softc *sc = mac->mac_sc;
6752	int i;
6753	uint16_t ucstat;
6754
6755	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6756	    ("%s:%d: fail", __func__, __LINE__));
6757	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6758	    ("%s:%d: fail", __func__, __LINE__));
6759
6760	/* XXX forcibly awake and hwps-off */
6761
6762	BWN_WRITE_4(mac, BWN_MACCTL,
6763	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6764	    ~BWN_MACCTL_HWPS);
6765	BWN_READ_4(mac, BWN_MACCTL);
6766	if (siba_get_revid(sc->sc_dev) >= 5) {
6767		for (i = 0; i < 100; i++) {
6768			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6769			    BWN_SHARED_UCODESTAT);
6770			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6771				break;
6772			DELAY(10);
6773		}
6774	}
6775}
6776
6777static int16_t
6778bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6779{
6780
6781	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6782	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6783}
6784
6785static void
6786bwn_nrssi_threshold(struct bwn_mac *mac)
6787{
6788	struct bwn_phy *phy = &mac->mac_phy;
6789	struct bwn_phy_g *pg = &phy->phy_g;
6790	struct bwn_softc *sc = mac->mac_sc;
6791	int32_t a, b;
6792	int16_t tmp16;
6793	uint16_t tmpu16;
6794
6795	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6796
6797	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6798		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6799			a = 0x13;
6800			b = 0x12;
6801		} else {
6802			a = 0xe;
6803			b = 0x11;
6804		}
6805
6806		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6807		a += (pg->pg_nrssi[0] << 6);
6808		a += (a < 32) ? 31 : 32;
6809		a = a >> 6;
6810		a = MIN(MAX(a, -31), 31);
6811
6812		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6813		b += (pg->pg_nrssi[0] << 6);
6814		if (b < 32)
6815			b += 31;
6816		else
6817			b += 32;
6818		b = b >> 6;
6819		b = MIN(MAX(b, -31), 31);
6820
6821		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6822		tmpu16 |= ((uint32_t)b & 0x0000003f);
6823		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6824		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6825		return;
6826	}
6827
6828	tmp16 = bwn_nrssi_read(mac, 0x20);
6829	if (tmp16 >= 0x20)
6830		tmp16 -= 0x40;
6831	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6832}
6833
6834static void
6835bwn_nrssi_slope_11g(struct bwn_mac *mac)
6836{
6837#define	SAVE_RF_MAX		3
6838#define	SAVE_PHY_COMM_MAX	4
6839#define	SAVE_PHY3_MAX		8
6840	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6841		{ 0x7a, 0x52, 0x43 };
6842	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6843		{ 0x15, 0x5a, 0x59, 0x58 };
6844	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6845		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6846		0x0801, 0x0060, 0x0014, 0x0478
6847	};
6848	struct bwn_phy *phy = &mac->mac_phy;
6849	struct bwn_phy_g *pg = &phy->phy_g;
6850	int32_t i, tmp32, phy3_idx = 0;
6851	uint16_t delta, tmp;
6852	uint16_t save_rf[SAVE_RF_MAX];
6853	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6854	uint16_t save_phy3[SAVE_PHY3_MAX];
6855	uint16_t ant_div, phy0, chan_ex;
6856	int16_t nrssi0, nrssi1;
6857
6858	KASSERT(phy->type == BWN_PHYTYPE_G,
6859	    ("%s:%d: fail", __func__, __LINE__));
6860
6861	if (phy->rf_rev >= 9)
6862		return;
6863	if (phy->rf_rev == 8)
6864		bwn_nrssi_offset(mac);
6865
6866	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6867	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6868
6869	/*
6870	 * Save RF/PHY registers for later restoration
6871	 */
6872	ant_div = BWN_READ_2(mac, 0x03e2);
6873	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6874	for (i = 0; i < SAVE_RF_MAX; ++i)
6875		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6876	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6877		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6878
6879	phy0 = BWN_READ_2(mac, BWN_PHY0);
6880	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6881	if (phy->rev >= 3) {
6882		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6883			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6884		BWN_PHY_WRITE(mac, 0x002e, 0);
6885		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6886		switch (phy->rev) {
6887		case 4:
6888		case 6:
6889		case 7:
6890			BWN_PHY_SET(mac, 0x0478, 0x0100);
6891			BWN_PHY_SET(mac, 0x0801, 0x0040);
6892			break;
6893		case 3:
6894		case 5:
6895			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6896			break;
6897		}
6898		BWN_PHY_SET(mac, 0x0060, 0x0040);
6899		BWN_PHY_SET(mac, 0x0014, 0x0200);
6900	}
6901	/*
6902	 * Calculate nrssi0
6903	 */
6904	BWN_RF_SET(mac, 0x007a, 0x0070);
6905	bwn_set_all_gains(mac, 0, 8, 0);
6906	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6907	if (phy->rev >= 2) {
6908		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6909		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6910	}
6911	BWN_RF_SET(mac, 0x007a, 0x0080);
6912	DELAY(20);
6913
6914	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6915	if (nrssi0 >= 0x0020)
6916		nrssi0 -= 0x0040;
6917
6918	/*
6919	 * Calculate nrssi1
6920	 */
6921	BWN_RF_MASK(mac, 0x007a, 0x007f);
6922	if (phy->rev >= 2)
6923		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6924
6925	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6926	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6927	BWN_RF_SET(mac, 0x007a, 0x000f);
6928	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6929	if (phy->rev >= 2) {
6930		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6931		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6932	}
6933
6934	bwn_set_all_gains(mac, 3, 0, 1);
6935	if (phy->rf_rev == 8) {
6936		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6937	} else {
6938		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6939		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6940		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6941		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6942	}
6943	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6944	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6945	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6946	DELAY(20);
6947	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6948
6949	/*
6950	 * Install calculated narrow RSSI values
6951	 */
6952	if (nrssi1 >= 0x0020)
6953		nrssi1 -= 0x0040;
6954	if (nrssi0 == nrssi1)
6955		pg->pg_nrssi_slope = 0x00010000;
6956	else
6957		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6958	if (nrssi0 >= -4) {
6959		pg->pg_nrssi[0] = nrssi1;
6960		pg->pg_nrssi[1] = nrssi0;
6961	}
6962
6963	/*
6964	 * Restore saved RF/PHY registers
6965	 */
6966	if (phy->rev >= 3) {
6967		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6968			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6969			    save_phy3[phy3_idx]);
6970		}
6971	}
6972	if (phy->rev >= 2) {
6973		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6974		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6975	}
6976
6977	for (i = 0; i < SAVE_RF_MAX; ++i)
6978		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6979
6980	BWN_WRITE_2(mac, 0x03e2, ant_div);
6981	BWN_WRITE_2(mac, 0x03e6, phy0);
6982	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6983
6984	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6985		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6986
6987	bwn_spu_workaround(mac, phy->chan);
6988	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6989	bwn_set_original_gains(mac);
6990	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6991	if (phy->rev >= 3) {
6992		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6993			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6994			    save_phy3[phy3_idx]);
6995		}
6996	}
6997
6998	delta = 0x1f - pg->pg_nrssi[0];
6999	for (i = 0; i < 64; i++) {
7000		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
7001		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7002		pg->pg_nrssi_lt[i] = tmp32;
7003	}
7004
7005	bwn_nrssi_threshold(mac);
7006#undef SAVE_RF_MAX
7007#undef SAVE_PHY_COMM_MAX
7008#undef SAVE_PHY3_MAX
7009}
7010
7011static void
7012bwn_nrssi_offset(struct bwn_mac *mac)
7013{
7014#define	SAVE_RF_MAX		2
7015#define	SAVE_PHY_COMM_MAX	10
7016#define	SAVE_PHY6_MAX		8
7017	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7018		{ 0x7a, 0x43 };
7019	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7020		0x0001, 0x0811, 0x0812, 0x0814,
7021		0x0815, 0x005a, 0x0059, 0x0058,
7022		0x000a, 0x0003
7023	};
7024	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7025		0x002e, 0x002f, 0x080f, 0x0810,
7026		0x0801, 0x0060, 0x0014, 0x0478
7027	};
7028	struct bwn_phy *phy = &mac->mac_phy;
7029	int i, phy6_idx = 0;
7030	uint16_t save_rf[SAVE_RF_MAX];
7031	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7032	uint16_t save_phy6[SAVE_PHY6_MAX];
7033	int16_t nrssi;
7034	uint16_t saved = 0xffff;
7035
7036	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7037		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7038	for (i = 0; i < SAVE_RF_MAX; ++i)
7039		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7040
7041	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7042	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7043	BWN_PHY_SET(mac, 0x0811, 0x000c);
7044	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7045	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7046	if (phy->rev >= 6) {
7047		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7048			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7049
7050		BWN_PHY_WRITE(mac, 0x002e, 0);
7051		BWN_PHY_WRITE(mac, 0x002f, 0);
7052		BWN_PHY_WRITE(mac, 0x080f, 0);
7053		BWN_PHY_WRITE(mac, 0x0810, 0);
7054		BWN_PHY_SET(mac, 0x0478, 0x0100);
7055		BWN_PHY_SET(mac, 0x0801, 0x0040);
7056		BWN_PHY_SET(mac, 0x0060, 0x0040);
7057		BWN_PHY_SET(mac, 0x0014, 0x0200);
7058	}
7059	BWN_RF_SET(mac, 0x007a, 0x0070);
7060	BWN_RF_SET(mac, 0x007a, 0x0080);
7061	DELAY(30);
7062
7063	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7064	if (nrssi >= 0x20)
7065		nrssi -= 0x40;
7066	if (nrssi == 31) {
7067		for (i = 7; i >= 4; i--) {
7068			BWN_RF_WRITE(mac, 0x007b, i);
7069			DELAY(20);
7070			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7071			    0x003f);
7072			if (nrssi >= 0x20)
7073				nrssi -= 0x40;
7074			if (nrssi < 31 && saved == 0xffff)
7075				saved = i;
7076		}
7077		if (saved == 0xffff)
7078			saved = 4;
7079	} else {
7080		BWN_RF_MASK(mac, 0x007a, 0x007f);
7081		if (phy->rev != 1) {
7082			BWN_PHY_SET(mac, 0x0814, 0x0001);
7083			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7084		}
7085		BWN_PHY_SET(mac, 0x0811, 0x000c);
7086		BWN_PHY_SET(mac, 0x0812, 0x000c);
7087		BWN_PHY_SET(mac, 0x0811, 0x0030);
7088		BWN_PHY_SET(mac, 0x0812, 0x0030);
7089		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7090		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7091		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7092		if (phy->rev == 0)
7093			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7094		else
7095			BWN_PHY_SET(mac, 0x000a, 0x2000);
7096		if (phy->rev != 1) {
7097			BWN_PHY_SET(mac, 0x0814, 0x0004);
7098			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7099		}
7100		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7101		BWN_RF_SET(mac, 0x007a, 0x000f);
7102		bwn_set_all_gains(mac, 3, 0, 1);
7103		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7104		DELAY(30);
7105		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7106		if (nrssi >= 0x20)
7107			nrssi -= 0x40;
7108		if (nrssi == -32) {
7109			for (i = 0; i < 4; i++) {
7110				BWN_RF_WRITE(mac, 0x007b, i);
7111				DELAY(20);
7112				nrssi = (int16_t)((BWN_PHY_READ(mac,
7113				    0x047f) >> 8) & 0x003f);
7114				if (nrssi >= 0x20)
7115					nrssi -= 0x40;
7116				if (nrssi > -31 && saved == 0xffff)
7117					saved = i;
7118			}
7119			if (saved == 0xffff)
7120				saved = 3;
7121		} else
7122			saved = 0;
7123	}
7124	BWN_RF_WRITE(mac, 0x007b, saved);
7125
7126	/*
7127	 * Restore saved RF/PHY registers
7128	 */
7129	if (phy->rev >= 6) {
7130		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7131			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7132			    save_phy6[phy6_idx]);
7133		}
7134	}
7135	if (phy->rev != 1) {
7136		for (i = 3; i < 5; i++)
7137			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7138			    save_phy_comm[i]);
7139	}
7140	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7141		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7142
7143	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7144		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7145
7146	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7147	BWN_PHY_SET(mac, 0x0429, 0x8000);
7148	bwn_set_original_gains(mac);
7149	if (phy->rev >= 6) {
7150		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7151			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7152			    save_phy6[phy6_idx]);
7153		}
7154	}
7155
7156	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7157	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7158	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7159}
7160
7161static void
7162bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7163    int16_t third)
7164{
7165	struct bwn_phy *phy = &mac->mac_phy;
7166	uint16_t i;
7167	uint16_t start = 0x08, end = 0x18;
7168	uint16_t tmp;
7169	uint16_t table;
7170
7171	if (phy->rev <= 1) {
7172		start = 0x10;
7173		end = 0x20;
7174	}
7175
7176	table = BWN_OFDMTAB_GAINX;
7177	if (phy->rev <= 1)
7178		table = BWN_OFDMTAB_GAINX_R1;
7179	for (i = 0; i < 4; i++)
7180		bwn_ofdmtab_write_2(mac, table, i, first);
7181
7182	for (i = start; i < end; i++)
7183		bwn_ofdmtab_write_2(mac, table, i, second);
7184
7185	if (third != -1) {
7186		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7187		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7188		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7189		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7190	}
7191	bwn_dummy_transmission(mac, 0, 1);
7192}
7193
7194static void
7195bwn_set_original_gains(struct bwn_mac *mac)
7196{
7197	struct bwn_phy *phy = &mac->mac_phy;
7198	uint16_t i, tmp;
7199	uint16_t table;
7200	uint16_t start = 0x0008, end = 0x0018;
7201
7202	if (phy->rev <= 1) {
7203		start = 0x0010;
7204		end = 0x0020;
7205	}
7206
7207	table = BWN_OFDMTAB_GAINX;
7208	if (phy->rev <= 1)
7209		table = BWN_OFDMTAB_GAINX_R1;
7210	for (i = 0; i < 4; i++) {
7211		tmp = (i & 0xfffc);
7212		tmp |= (i & 0x0001) << 1;
7213		tmp |= (i & 0x0002) >> 1;
7214
7215		bwn_ofdmtab_write_2(mac, table, i, tmp);
7216	}
7217
7218	for (i = start; i < end; i++)
7219		bwn_ofdmtab_write_2(mac, table, i, i - start);
7220
7221	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7222	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7223	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7224	bwn_dummy_transmission(mac, 0, 1);
7225}
7226
7227static void
7228bwn_phy_hwpctl_init(struct bwn_mac *mac)
7229{
7230	struct bwn_phy *phy = &mac->mac_phy;
7231	struct bwn_phy_g *pg = &phy->phy_g;
7232	struct bwn_rfatt old_rfatt, rfatt;
7233	struct bwn_bbatt old_bbatt, bbatt;
7234	struct bwn_softc *sc = mac->mac_sc;
7235	uint8_t old_txctl = 0;
7236
7237	KASSERT(phy->type == BWN_PHYTYPE_G,
7238	    ("%s:%d: fail", __func__, __LINE__));
7239
7240	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7241	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7242		return;
7243
7244	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7245
7246	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7247
7248	if (!phy->gmode)
7249		return;
7250	bwn_hwpctl_early_init(mac);
7251	if (pg->pg_curtssi == 0) {
7252		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7253			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7254		} else {
7255			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7256			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7257			old_txctl = pg->pg_txctl;
7258
7259			bbatt.att = 11;
7260			if (phy->rf_rev == 8) {
7261				rfatt.att = 15;
7262				rfatt.padmix = 1;
7263			} else {
7264				rfatt.att = 9;
7265				rfatt.padmix = 0;
7266			}
7267			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7268		}
7269		bwn_dummy_transmission(mac, 0, 1);
7270		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7271		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7272			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7273		else
7274			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7275			    &old_rfatt, old_txctl);
7276	}
7277	bwn_hwpctl_init_gphy(mac);
7278
7279	/* clear TSSI */
7280	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7281	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7282	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7283	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7284}
7285
7286static void
7287bwn_hwpctl_early_init(struct bwn_mac *mac)
7288{
7289	struct bwn_phy *phy = &mac->mac_phy;
7290
7291	if (!bwn_has_hwpctl(mac)) {
7292		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7293		return;
7294	}
7295
7296	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7297	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7298	BWN_PHY_SET(mac, 0x047c, 0x0002);
7299	BWN_PHY_SET(mac, 0x047a, 0xf000);
7300	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7301		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7302		BWN_PHY_SET(mac, 0x005d, 0x8000);
7303		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7304		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7305		BWN_PHY_SET(mac, 0x0036, 0x0400);
7306	} else {
7307		BWN_PHY_SET(mac, 0x0036, 0x0200);
7308		BWN_PHY_SET(mac, 0x0036, 0x0400);
7309		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7310		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7311		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7312		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7313		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7314	}
7315}
7316
7317static void
7318bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7319{
7320	struct bwn_phy *phy = &mac->mac_phy;
7321	struct bwn_phy_g *pg = &phy->phy_g;
7322	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7323	int i;
7324	uint16_t nr_written = 0, tmp, value;
7325	uint8_t rf, bb;
7326
7327	if (!bwn_has_hwpctl(mac)) {
7328		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7329		return;
7330	}
7331
7332	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7333	    (pg->pg_idletssi - pg->pg_curtssi));
7334	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7335	    (pg->pg_idletssi - pg->pg_curtssi));
7336
7337	for (i = 0; i < 32; i++)
7338		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7339	for (i = 32; i < 64; i++)
7340		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7341	for (i = 0; i < 64; i += 2) {
7342		value = (uint16_t) pg->pg_tssi2dbm[i];
7343		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7344		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7345	}
7346
7347	for (rf = 0; rf < lo->rfatt.len; rf++) {
7348		for (bb = 0; bb < lo->bbatt.len; bb++) {
7349			if (nr_written >= 0x40)
7350				return;
7351			tmp = lo->bbatt.array[bb].att;
7352			tmp <<= 8;
7353			if (phy->rf_rev == 8)
7354				tmp |= 0x50;
7355			else
7356				tmp |= 0x40;
7357			tmp |= lo->rfatt.array[rf].att;
7358			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7359			nr_written++;
7360		}
7361	}
7362
7363	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7364	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7365
7366	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7367	BWN_PHY_SET(mac, 0x0478, 0x0800);
7368	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7369	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7370
7371	bwn_phy_g_dc_lookup_init(mac, 1);
7372	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7373}
7374
7375static void
7376bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7377{
7378	struct bwn_softc *sc = mac->mac_sc;
7379
7380	if (spu != 0)
7381		bwn_spu_workaround(mac, channel);
7382
7383	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7384
7385	if (channel == 14) {
7386		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7387			bwn_hf_write(mac,
7388			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7389		else
7390			bwn_hf_write(mac,
7391			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7392		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7393		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7394		return;
7395	}
7396
7397	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7398	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7399}
7400
7401static uint16_t
7402bwn_phy_g_chan2freq(uint8_t channel)
7403{
7404	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7405
7406	KASSERT(channel >= 1 && channel <= 14,
7407	    ("%s:%d: fail", __func__, __LINE__));
7408
7409	return (bwn_phy_g_rf_channels[channel - 1]);
7410}
7411
7412static void
7413bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7414    const struct bwn_rfatt *rfatt, uint8_t txctl)
7415{
7416	struct bwn_phy *phy = &mac->mac_phy;
7417	struct bwn_phy_g *pg = &phy->phy_g;
7418	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7419	uint16_t bb, rf;
7420	uint16_t tx_bias, tx_magn;
7421
7422	bb = bbatt->att;
7423	rf = rfatt->att;
7424	tx_bias = lo->tx_bias;
7425	tx_magn = lo->tx_magn;
7426	if (tx_bias == 0xff)
7427		tx_bias = 0;
7428
7429	pg->pg_txctl = txctl;
7430	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7431	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7432	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7433	bwn_phy_g_set_bbatt(mac, bb);
7434	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7435	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7436		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7437	else {
7438		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7439		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7440	}
7441	if (BWN_HAS_TXMAG(phy))
7442		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7443	else
7444		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7445	bwn_lo_g_adjust(mac);
7446}
7447
7448static void
7449bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7450    uint16_t bbatt)
7451{
7452	struct bwn_phy *phy = &mac->mac_phy;
7453
7454	if (phy->analog == 0) {
7455		BWN_WRITE_2(mac, BWN_PHY0,
7456		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7457		return;
7458	}
7459	if (phy->analog > 1) {
7460		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7461		return;
7462	}
7463	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7464}
7465
7466static uint16_t
7467bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7468{
7469	struct bwn_phy *phy = &mac->mac_phy;
7470	struct bwn_phy_g *pg = &phy->phy_g;
7471	struct bwn_softc *sc = mac->mac_sc;
7472	int max_lb_gain;
7473	uint16_t extlna;
7474	uint16_t i;
7475
7476	if (phy->gmode == 0)
7477		return (0);
7478
7479	if (BWN_HAS_LOOPBACK(phy)) {
7480		max_lb_gain = pg->pg_max_lb_gain;
7481		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7482		if (max_lb_gain >= 0x46) {
7483			extlna = 0x3000;
7484			max_lb_gain -= 0x46;
7485		} else if (max_lb_gain >= 0x3a) {
7486			extlna = 0x1000;
7487			max_lb_gain -= 0x3a;
7488		} else if (max_lb_gain >= 0x2e) {
7489			extlna = 0x2000;
7490			max_lb_gain -= 0x2e;
7491		} else {
7492			extlna = 0;
7493			max_lb_gain -= 0x10;
7494		}
7495
7496		for (i = 0; i < 16; i++) {
7497			max_lb_gain -= (i * 6);
7498			if (max_lb_gain < 6)
7499				break;
7500		}
7501
7502		if ((phy->rev < 7) ||
7503		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7504			if (reg == BWN_PHY_RFOVER) {
7505				return (0x1b3);
7506			} else if (reg == BWN_PHY_RFOVERVAL) {
7507				extlna |= (i << 8);
7508				switch (lpd) {
7509				case BWN_LPD(0, 1, 1):
7510					return (0x0f92);
7511				case BWN_LPD(0, 0, 1):
7512				case BWN_LPD(1, 0, 1):
7513					return (0x0092 | extlna);
7514				case BWN_LPD(1, 0, 0):
7515					return (0x0093 | extlna);
7516				}
7517				KASSERT(0 == 1,
7518				    ("%s:%d: fail", __func__, __LINE__));
7519			}
7520			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7521		} else {
7522			if (reg == BWN_PHY_RFOVER)
7523				return (0x9b3);
7524			if (reg == BWN_PHY_RFOVERVAL) {
7525				if (extlna)
7526					extlna |= 0x8000;
7527				extlna |= (i << 8);
7528				switch (lpd) {
7529				case BWN_LPD(0, 1, 1):
7530					return (0x8f92);
7531				case BWN_LPD(0, 0, 1):
7532					return (0x8092 | extlna);
7533				case BWN_LPD(1, 0, 1):
7534					return (0x2092 | extlna);
7535				case BWN_LPD(1, 0, 0):
7536					return (0x2093 | extlna);
7537				}
7538				KASSERT(0 == 1,
7539				    ("%s:%d: fail", __func__, __LINE__));
7540			}
7541			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7542		}
7543		return (0);
7544	}
7545
7546	if ((phy->rev < 7) ||
7547	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7548		if (reg == BWN_PHY_RFOVER) {
7549			return (0x1b3);
7550		} else if (reg == BWN_PHY_RFOVERVAL) {
7551			switch (lpd) {
7552			case BWN_LPD(0, 1, 1):
7553				return (0x0fb2);
7554			case BWN_LPD(0, 0, 1):
7555				return (0x00b2);
7556			case BWN_LPD(1, 0, 1):
7557				return (0x30b2);
7558			case BWN_LPD(1, 0, 0):
7559				return (0x30b3);
7560			}
7561			KASSERT(0 == 1,
7562			    ("%s:%d: fail", __func__, __LINE__));
7563		}
7564		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7565	} else {
7566		if (reg == BWN_PHY_RFOVER) {
7567			return (0x9b3);
7568		} else if (reg == BWN_PHY_RFOVERVAL) {
7569			switch (lpd) {
7570			case BWN_LPD(0, 1, 1):
7571				return (0x8fb2);
7572			case BWN_LPD(0, 0, 1):
7573				return (0x80b2);
7574			case BWN_LPD(1, 0, 1):
7575				return (0x20b2);
7576			case BWN_LPD(1, 0, 0):
7577				return (0x20b3);
7578			}
7579			KASSERT(0 == 1,
7580			    ("%s:%d: fail", __func__, __LINE__));
7581		}
7582		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7583	}
7584	return (0);
7585}
7586
7587static void
7588bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7589{
7590
7591	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7592		return;
7593	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7594	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7595	DELAY(1000);
7596	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7597}
7598
7599static int
7600bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7601{
7602	struct bwn_softc *sc = mac->mac_sc;
7603	struct bwn_fw *fw = &mac->mac_fw;
7604	const uint8_t rev = siba_get_revid(sc->sc_dev);
7605	const char *filename;
7606	uint32_t high;
7607	int error;
7608
7609	/* microcode */
7610	if (rev >= 5 && rev <= 10)
7611		filename = "ucode5";
7612	else if (rev >= 11 && rev <= 12)
7613		filename = "ucode11";
7614	else if (rev == 13)
7615		filename = "ucode13";
7616	else if (rev == 14)
7617		filename = "ucode14";
7618	else if (rev >= 15)
7619		filename = "ucode15";
7620	else {
7621		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7622		bwn_release_firmware(mac);
7623		return (EOPNOTSUPP);
7624	}
7625	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7626	if (error) {
7627		bwn_release_firmware(mac);
7628		return (error);
7629	}
7630
7631	/* PCM */
7632	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7633	if (rev >= 5 && rev <= 10) {
7634		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7635		if (error == ENOENT)
7636			fw->no_pcmfile = 1;
7637		else if (error) {
7638			bwn_release_firmware(mac);
7639			return (error);
7640		}
7641	} else if (rev < 11) {
7642		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7643		return (EOPNOTSUPP);
7644	}
7645
7646	/* initvals */
7647	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7648	switch (mac->mac_phy.type) {
7649	case BWN_PHYTYPE_A:
7650		if (rev < 5 || rev > 10)
7651			goto fail1;
7652		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7653			filename = "a0g1initvals5";
7654		else
7655			filename = "a0g0initvals5";
7656		break;
7657	case BWN_PHYTYPE_G:
7658		if (rev >= 5 && rev <= 10)
7659			filename = "b0g0initvals5";
7660		else if (rev >= 13)
7661			filename = "b0g0initvals13";
7662		else
7663			goto fail1;
7664		break;
7665	case BWN_PHYTYPE_LP:
7666		if (rev == 13)
7667			filename = "lp0initvals13";
7668		else if (rev == 14)
7669			filename = "lp0initvals14";
7670		else if (rev >= 15)
7671			filename = "lp0initvals15";
7672		else
7673			goto fail1;
7674		break;
7675	case BWN_PHYTYPE_N:
7676		if (rev >= 11 && rev <= 12)
7677			filename = "n0initvals11";
7678		else
7679			goto fail1;
7680		break;
7681	default:
7682		goto fail1;
7683	}
7684	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7685	if (error) {
7686		bwn_release_firmware(mac);
7687		return (error);
7688	}
7689
7690	/* bandswitch initvals */
7691	switch (mac->mac_phy.type) {
7692	case BWN_PHYTYPE_A:
7693		if (rev >= 5 && rev <= 10) {
7694			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7695				filename = "a0g1bsinitvals5";
7696			else
7697				filename = "a0g0bsinitvals5";
7698		} else if (rev >= 11)
7699			filename = NULL;
7700		else
7701			goto fail1;
7702		break;
7703	case BWN_PHYTYPE_G:
7704		if (rev >= 5 && rev <= 10)
7705			filename = "b0g0bsinitvals5";
7706		else if (rev >= 11)
7707			filename = NULL;
7708		else
7709			goto fail1;
7710		break;
7711	case BWN_PHYTYPE_LP:
7712		if (rev == 13)
7713			filename = "lp0bsinitvals13";
7714		else if (rev == 14)
7715			filename = "lp0bsinitvals14";
7716		else if (rev >= 15)
7717			filename = "lp0bsinitvals15";
7718		else
7719			goto fail1;
7720		break;
7721	case BWN_PHYTYPE_N:
7722		if (rev >= 11 && rev <= 12)
7723			filename = "n0bsinitvals11";
7724		else
7725			goto fail1;
7726		break;
7727	default:
7728		goto fail1;
7729	}
7730	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7731	if (error) {
7732		bwn_release_firmware(mac);
7733		return (error);
7734	}
7735	return (0);
7736fail1:
7737	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7738	bwn_release_firmware(mac);
7739	return (EOPNOTSUPP);
7740}
7741
7742static int
7743bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7744    const char *name, struct bwn_fwfile *bfw)
7745{
7746	const struct bwn_fwhdr *hdr;
7747	struct bwn_softc *sc = mac->mac_sc;
7748	const struct firmware *fw;
7749	char namebuf[64];
7750
7751	if (name == NULL) {
7752		bwn_do_release_fw(bfw);
7753		return (0);
7754	}
7755	if (bfw->filename != NULL) {
7756		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7757			return (0);
7758		bwn_do_release_fw(bfw);
7759	}
7760
7761	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7762	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7763	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7764	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7765	fw = firmware_get(namebuf);
7766	if (fw == NULL) {
7767		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7768		    namebuf);
7769		return (ENOENT);
7770	}
7771	if (fw->datasize < sizeof(struct bwn_fwhdr))
7772		goto fail;
7773	hdr = (const struct bwn_fwhdr *)(fw->data);
7774	switch (hdr->type) {
7775	case BWN_FWTYPE_UCODE:
7776	case BWN_FWTYPE_PCM:
7777		if (be32toh(hdr->size) !=
7778		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7779			goto fail;
7780		/* FALLTHROUGH */
7781	case BWN_FWTYPE_IV:
7782		if (hdr->ver != 1)
7783			goto fail;
7784		break;
7785	default:
7786		goto fail;
7787	}
7788	bfw->filename = name;
7789	bfw->fw = fw;
7790	bfw->type = type;
7791	return (0);
7792fail:
7793	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7794	if (fw != NULL)
7795		firmware_put(fw, FIRMWARE_UNLOAD);
7796	return (EPROTO);
7797}
7798
7799static void
7800bwn_release_firmware(struct bwn_mac *mac)
7801{
7802
7803	bwn_do_release_fw(&mac->mac_fw.ucode);
7804	bwn_do_release_fw(&mac->mac_fw.pcm);
7805	bwn_do_release_fw(&mac->mac_fw.initvals);
7806	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7807}
7808
7809static void
7810bwn_do_release_fw(struct bwn_fwfile *bfw)
7811{
7812
7813	if (bfw->fw != NULL)
7814		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7815	bfw->fw = NULL;
7816	bfw->filename = NULL;
7817}
7818
7819static int
7820bwn_fw_loaducode(struct bwn_mac *mac)
7821{
7822#define	GETFWOFFSET(fwp, offset)	\
7823	((const uint32_t *)((const char *)fwp.fw->data + offset))
7824#define	GETFWSIZE(fwp, offset)	\
7825	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7826	struct bwn_softc *sc = mac->mac_sc;
7827	const uint32_t *data;
7828	unsigned int i;
7829	uint32_t ctl;
7830	uint16_t date, fwcaps, time;
7831	int error = 0;
7832
7833	ctl = BWN_READ_4(mac, BWN_MACCTL);
7834	ctl |= BWN_MACCTL_MCODE_JMP0;
7835	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7836	    __LINE__));
7837	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7838	for (i = 0; i < 64; i++)
7839		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7840	for (i = 0; i < 4096; i += 2)
7841		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7842
7843	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7844	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7845	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7846	     i++) {
7847		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7848		DELAY(10);
7849	}
7850
7851	if (mac->mac_fw.pcm.fw) {
7852		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7853		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7854		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7855		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7856		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7857		    sizeof(struct bwn_fwhdr)); i++) {
7858			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7859			DELAY(10);
7860		}
7861	}
7862
7863	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7864	BWN_WRITE_4(mac, BWN_MACCTL,
7865	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7866	    BWN_MACCTL_MCODE_RUN);
7867
7868	for (i = 0; i < 21; i++) {
7869		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7870			break;
7871		if (i >= 20) {
7872			device_printf(sc->sc_dev, "ucode timeout\n");
7873			error = ENXIO;
7874			goto error;
7875		}
7876		DELAY(50000);
7877	}
7878	BWN_READ_4(mac, BWN_INTR_REASON);
7879
7880	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7881	if (mac->mac_fw.rev <= 0x128) {
7882		device_printf(sc->sc_dev, "the firmware is too old\n");
7883		error = EOPNOTSUPP;
7884		goto error;
7885	}
7886	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7887	    BWN_SHARED_UCODE_PATCH);
7888	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7889	mac->mac_fw.opensource = (date == 0xffff);
7890	if (bwn_wme != 0)
7891		mac->mac_flags |= BWN_MAC_FLAG_WME;
7892	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7893
7894	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7895	if (mac->mac_fw.opensource == 0) {
7896		device_printf(sc->sc_dev,
7897		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7898		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7899		if (mac->mac_fw.no_pcmfile)
7900			device_printf(sc->sc_dev,
7901			    "no HW crypto acceleration due to pcm5\n");
7902	} else {
7903		mac->mac_fw.patch = time;
7904		fwcaps = bwn_fwcaps_read(mac);
7905		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7906			device_printf(sc->sc_dev,
7907			    "disabling HW crypto acceleration\n");
7908			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7909		}
7910		if (!(fwcaps & BWN_FWCAPS_WME)) {
7911			device_printf(sc->sc_dev, "disabling WME support\n");
7912			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7913		}
7914	}
7915
7916	if (BWN_ISOLDFMT(mac))
7917		device_printf(sc->sc_dev, "using old firmware image\n");
7918
7919	return (0);
7920
7921error:
7922	BWN_WRITE_4(mac, BWN_MACCTL,
7923	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7924	    BWN_MACCTL_MCODE_JMP0);
7925
7926	return (error);
7927#undef GETFWSIZE
7928#undef GETFWOFFSET
7929}
7930
7931/* OpenFirmware only */
7932static uint16_t
7933bwn_fwcaps_read(struct bwn_mac *mac)
7934{
7935
7936	KASSERT(mac->mac_fw.opensource == 1,
7937	    ("%s:%d: fail", __func__, __LINE__));
7938	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7939}
7940
7941static int
7942bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7943    size_t count, size_t array_size)
7944{
7945#define	GET_NEXTIV16(iv)						\
7946	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7947	    sizeof(uint16_t) + sizeof(uint16_t)))
7948#define	GET_NEXTIV32(iv)						\
7949	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7950	    sizeof(uint16_t) + sizeof(uint32_t)))
7951	struct bwn_softc *sc = mac->mac_sc;
7952	const struct bwn_fwinitvals *iv;
7953	uint16_t offset;
7954	size_t i;
7955	uint8_t bit32;
7956
7957	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7958	    ("%s:%d: fail", __func__, __LINE__));
7959	iv = ivals;
7960	for (i = 0; i < count; i++) {
7961		if (array_size < sizeof(iv->offset_size))
7962			goto fail;
7963		array_size -= sizeof(iv->offset_size);
7964		offset = be16toh(iv->offset_size);
7965		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7966		offset &= BWN_FWINITVALS_OFFSET_MASK;
7967		if (offset >= 0x1000)
7968			goto fail;
7969		if (bit32) {
7970			if (array_size < sizeof(iv->data.d32))
7971				goto fail;
7972			array_size -= sizeof(iv->data.d32);
7973			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7974			iv = GET_NEXTIV32(iv);
7975		} else {
7976
7977			if (array_size < sizeof(iv->data.d16))
7978				goto fail;
7979			array_size -= sizeof(iv->data.d16);
7980			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7981
7982			iv = GET_NEXTIV16(iv);
7983		}
7984	}
7985	if (array_size != 0)
7986		goto fail;
7987	return (0);
7988fail:
7989	device_printf(sc->sc_dev, "initvals: invalid format\n");
7990	return (EPROTO);
7991#undef GET_NEXTIV16
7992#undef GET_NEXTIV32
7993}
7994
7995static int
7996bwn_switch_channel(struct bwn_mac *mac, int chan)
7997{
7998	struct bwn_phy *phy = &(mac->mac_phy);
7999	struct bwn_softc *sc = mac->mac_sc;
8000	struct ifnet *ifp = sc->sc_ifp;
8001	struct ieee80211com *ic = ifp->if_l2com;
8002	uint16_t channelcookie, savedcookie;
8003	int error;
8004
8005	if (chan == 0xffff)
8006		chan = phy->get_default_chan(mac);
8007
8008	channelcookie = chan;
8009	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8010		channelcookie |= 0x100;
8011	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8012	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8013	error = phy->switch_channel(mac, chan);
8014	if (error)
8015		goto fail;
8016
8017	mac->mac_phy.chan = chan;
8018	DELAY(8000);
8019	return (0);
8020fail:
8021	device_printf(sc->sc_dev, "failed to switch channel\n");
8022	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8023	return (error);
8024}
8025
8026static uint16_t
8027bwn_ant2phy(int antenna)
8028{
8029
8030	switch (antenna) {
8031	case BWN_ANT0:
8032		return (BWN_TX_PHY_ANT0);
8033	case BWN_ANT1:
8034		return (BWN_TX_PHY_ANT1);
8035	case BWN_ANT2:
8036		return (BWN_TX_PHY_ANT2);
8037	case BWN_ANT3:
8038		return (BWN_TX_PHY_ANT3);
8039	case BWN_ANTAUTO:
8040		return (BWN_TX_PHY_ANT01AUTO);
8041	}
8042	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8043	return (0);
8044}
8045
8046static void
8047bwn_wme_load(struct bwn_mac *mac)
8048{
8049	struct bwn_softc *sc = mac->mac_sc;
8050	int i;
8051
8052	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8053	    ("%s:%d: fail", __func__, __LINE__));
8054
8055	bwn_mac_suspend(mac);
8056	for (i = 0; i < N(sc->sc_wmeParams); i++)
8057		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8058		    bwn_wme_shm_offsets[i]);
8059	bwn_mac_enable(mac);
8060}
8061
8062static void
8063bwn_wme_loadparams(struct bwn_mac *mac,
8064    const struct wmeParams *p, uint16_t shm_offset)
8065{
8066#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8067	struct bwn_softc *sc = mac->mac_sc;
8068	uint16_t params[BWN_NR_WMEPARAMS];
8069	int slot, tmp;
8070	unsigned int i;
8071
8072	slot = BWN_READ_2(mac, BWN_RNG) &
8073	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8074
8075	memset(&params, 0, sizeof(params));
8076
8077	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8078	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8079	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8080
8081	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8082	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8083	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8084	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8085	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8086	params[BWN_WMEPARAM_BSLOTS] = slot;
8087	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8088
8089	for (i = 0; i < N(params); i++) {
8090		if (i == BWN_WMEPARAM_STATUS) {
8091			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8092			    shm_offset + (i * 2));
8093			tmp |= 0x100;
8094			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8095			    tmp);
8096		} else {
8097			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8098			    params[i]);
8099		}
8100	}
8101}
8102
8103static void
8104bwn_mac_write_bssid(struct bwn_mac *mac)
8105{
8106	struct bwn_softc *sc = mac->mac_sc;
8107	uint32_t tmp;
8108	int i;
8109	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8110
8111	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8112	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8113	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8114	    IEEE80211_ADDR_LEN);
8115
8116	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8117		tmp = (uint32_t) (mac_bssid[i + 0]);
8118		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8119		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8120		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8121		bwn_ram_write(mac, 0x20 + i, tmp);
8122	}
8123}
8124
8125static void
8126bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8127    const uint8_t *macaddr)
8128{
8129	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8130	uint16_t data;
8131
8132	if (!mac)
8133		macaddr = zero;
8134
8135	offset |= 0x0020;
8136	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8137
8138	data = macaddr[0];
8139	data |= macaddr[1] << 8;
8140	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8141	data = macaddr[2];
8142	data |= macaddr[3] << 8;
8143	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8144	data = macaddr[4];
8145	data |= macaddr[5] << 8;
8146	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8147}
8148
8149static void
8150bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8151    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8152{
8153	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8154	uint8_t per_sta_keys_start = 8;
8155
8156	if (BWN_SEC_NEWAPI(mac))
8157		per_sta_keys_start = 4;
8158
8159	KASSERT(index < mac->mac_max_nr_keys,
8160	    ("%s:%d: fail", __func__, __LINE__));
8161	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8162	    ("%s:%d: fail", __func__, __LINE__));
8163
8164	if (index >= per_sta_keys_start)
8165		bwn_key_macwrite(mac, index, NULL);
8166	if (key)
8167		memcpy(buf, key, key_len);
8168	bwn_key_write(mac, index, algorithm, buf);
8169	if (index >= per_sta_keys_start)
8170		bwn_key_macwrite(mac, index, mac_addr);
8171
8172	mac->mac_key[index].algorithm = algorithm;
8173}
8174
8175static void
8176bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8177{
8178	struct bwn_softc *sc = mac->mac_sc;
8179	uint32_t addrtmp[2] = { 0, 0 };
8180	uint8_t start = 8;
8181
8182	if (BWN_SEC_NEWAPI(mac))
8183		start = 4;
8184
8185	KASSERT(index >= start,
8186	    ("%s:%d: fail", __func__, __LINE__));
8187	index -= start;
8188
8189	if (addr) {
8190		addrtmp[0] = addr[0];
8191		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8192		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8193		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8194		addrtmp[1] = addr[4];
8195		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8196	}
8197
8198	if (siba_get_revid(sc->sc_dev) >= 5) {
8199		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8200		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8201	} else {
8202		if (index >= 8) {
8203			bwn_shm_write_4(mac, BWN_SHARED,
8204			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8205			bwn_shm_write_2(mac, BWN_SHARED,
8206			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8207		}
8208	}
8209}
8210
8211static void
8212bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8213    const uint8_t *key)
8214{
8215	unsigned int i;
8216	uint32_t offset;
8217	uint16_t kidx, value;
8218
8219	kidx = BWN_SEC_KEY2FW(mac, index);
8220	bwn_shm_write_2(mac, BWN_SHARED,
8221	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8222
8223	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8224	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8225		value = key[i];
8226		value |= (uint16_t)(key[i + 1]) << 8;
8227		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8228	}
8229}
8230
8231static void
8232bwn_phy_exit(struct bwn_mac *mac)
8233{
8234
8235	mac->mac_phy.rf_onoff(mac, 0);
8236	if (mac->mac_phy.exit != NULL)
8237		mac->mac_phy.exit(mac);
8238}
8239
8240static void
8241bwn_dma_free(struct bwn_mac *mac)
8242{
8243	struct bwn_dma *dma;
8244
8245	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8246		return;
8247	dma = &mac->mac_method.dma;
8248
8249	bwn_dma_ringfree(&dma->rx);
8250	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8251	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8252	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8253	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8254	bwn_dma_ringfree(&dma->mcast);
8255}
8256
8257static void
8258bwn_core_stop(struct bwn_mac *mac)
8259{
8260	struct bwn_softc *sc = mac->mac_sc;
8261
8262	BWN_ASSERT_LOCKED(sc);
8263
8264	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8265		return;
8266
8267	callout_stop(&sc->sc_rfswitch_ch);
8268	callout_stop(&sc->sc_task_ch);
8269	callout_stop(&sc->sc_watchdog_ch);
8270	sc->sc_watchdog_timer = 0;
8271	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8272	BWN_READ_4(mac, BWN_INTR_MASK);
8273	bwn_mac_suspend(mac);
8274
8275	mac->mac_status = BWN_MAC_STATUS_INITED;
8276}
8277
8278static int
8279bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8280{
8281	struct bwn_mac *up_dev = NULL;
8282	struct bwn_mac *down_dev;
8283	struct bwn_mac *mac;
8284	int err, status;
8285	uint8_t gmode;
8286
8287	BWN_ASSERT_LOCKED(sc);
8288
8289	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8290		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8291		    mac->mac_phy.supports_2ghz) {
8292			up_dev = mac;
8293			gmode = 1;
8294		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8295		    mac->mac_phy.supports_5ghz) {
8296			up_dev = mac;
8297			gmode = 0;
8298		} else {
8299			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8300			return (EINVAL);
8301		}
8302		if (up_dev != NULL)
8303			break;
8304	}
8305	if (up_dev == NULL) {
8306		device_printf(sc->sc_dev, "Could not find a device\n");
8307		return (ENODEV);
8308	}
8309	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8310		return (0);
8311
8312	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8313	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8314
8315	down_dev = sc->sc_curmac;;
8316	status = down_dev->mac_status;
8317	if (status >= BWN_MAC_STATUS_STARTED)
8318		bwn_core_stop(down_dev);
8319	if (status >= BWN_MAC_STATUS_INITED)
8320		bwn_core_exit(down_dev);
8321
8322	if (down_dev != up_dev)
8323		bwn_phy_reset(down_dev);
8324
8325	up_dev->mac_phy.gmode = gmode;
8326	if (status >= BWN_MAC_STATUS_INITED) {
8327		err = bwn_core_init(up_dev);
8328		if (err) {
8329			device_printf(sc->sc_dev,
8330			    "fatal: failed to initialize for %s-GHz\n",
8331			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8332			goto fail;
8333		}
8334	}
8335	if (status >= BWN_MAC_STATUS_STARTED)
8336		bwn_core_start(up_dev);
8337	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8338	sc->sc_curmac = up_dev;
8339
8340	return (0);
8341fail:
8342	sc->sc_curmac = NULL;
8343	return (err);
8344}
8345
8346static void
8347bwn_rf_turnon(struct bwn_mac *mac)
8348{
8349
8350	bwn_mac_suspend(mac);
8351	mac->mac_phy.rf_onoff(mac, 1);
8352	mac->mac_phy.rf_on = 1;
8353	bwn_mac_enable(mac);
8354}
8355
8356static void
8357bwn_rf_turnoff(struct bwn_mac *mac)
8358{
8359
8360	bwn_mac_suspend(mac);
8361	mac->mac_phy.rf_onoff(mac, 0);
8362	mac->mac_phy.rf_on = 0;
8363	bwn_mac_enable(mac);
8364}
8365
8366static void
8367bwn_phy_reset(struct bwn_mac *mac)
8368{
8369	struct bwn_softc *sc = mac->mac_sc;
8370
8371	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8372	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8373	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8374	DELAY(1000);
8375	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8376	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8377	    BWN_TGSLOW_PHYRESET);
8378	DELAY(1000);
8379}
8380
8381static int
8382bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8383{
8384	struct bwn_vap *bvp = BWN_VAP(vap);
8385	struct ieee80211com *ic= vap->iv_ic;
8386	struct ifnet *ifp = ic->ic_ifp;
8387	enum ieee80211_state ostate = vap->iv_state;
8388	struct bwn_softc *sc = ifp->if_softc;
8389	struct bwn_mac *mac = sc->sc_curmac;
8390	int error;
8391
8392	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8393	    ieee80211_state_name[vap->iv_state],
8394	    ieee80211_state_name[nstate]);
8395
8396	error = bvp->bv_newstate(vap, nstate, arg);
8397	if (error != 0)
8398		return (error);
8399
8400	BWN_LOCK(sc);
8401
8402	bwn_led_newstate(mac, nstate);
8403
8404	/*
8405	 * Clear the BSSID when we stop a STA
8406	 */
8407	if (vap->iv_opmode == IEEE80211_M_STA) {
8408		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8409			/*
8410			 * Clear out the BSSID.  If we reassociate to
8411			 * the same AP, this will reinialize things
8412			 * correctly...
8413			 */
8414			if (ic->ic_opmode == IEEE80211_M_STA &&
8415			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8416				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8417				bwn_set_macaddr(mac);
8418			}
8419		}
8420	}
8421
8422	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8423	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8424		/* XXX nothing to do? */
8425	} else if (nstate == IEEE80211_S_RUN) {
8426		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8427		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8428		bwn_set_opmode(mac);
8429		bwn_set_pretbtt(mac);
8430		bwn_spu_setdelay(mac, 0);
8431		bwn_set_macaddr(mac);
8432	}
8433
8434	BWN_UNLOCK(sc);
8435
8436	return (error);
8437}
8438
8439static void
8440bwn_set_pretbtt(struct bwn_mac *mac)
8441{
8442	struct bwn_softc *sc = mac->mac_sc;
8443	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8444	uint16_t pretbtt;
8445
8446	if (ic->ic_opmode == IEEE80211_M_IBSS)
8447		pretbtt = 2;
8448	else
8449		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8450	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8451	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8452}
8453
8454static int
8455bwn_intr(void *arg)
8456{
8457	struct bwn_mac *mac = arg;
8458	struct bwn_softc *sc = mac->mac_sc;
8459	uint32_t reason;
8460
8461	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8462	    (sc->sc_flags & BWN_FLAG_INVALID))
8463		return (FILTER_STRAY);
8464
8465	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8466	if (reason == 0xffffffff)	/* shared IRQ */
8467		return (FILTER_STRAY);
8468	reason &= mac->mac_intr_mask;
8469	if (reason == 0)
8470		return (FILTER_HANDLED);
8471
8472	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8473	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8474	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8475	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8476	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8477	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8478	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8479	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8480	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8481	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8482	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8483
8484	/* Disable interrupts. */
8485	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8486
8487	mac->mac_reason_intr = reason;
8488
8489	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8490	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8491
8492	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8493	return (FILTER_HANDLED);
8494}
8495
8496static void
8497bwn_intrtask(void *arg, int npending)
8498{
8499	struct bwn_mac *mac = arg;
8500	struct bwn_softc *sc = mac->mac_sc;
8501	struct ifnet *ifp = sc->sc_ifp;
8502	uint32_t merged = 0;
8503	int i, tx = 0, rx = 0;
8504
8505	BWN_LOCK(sc);
8506	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8507	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8508		BWN_UNLOCK(sc);
8509		return;
8510	}
8511
8512	for (i = 0; i < N(mac->mac_reason); i++)
8513		merged |= mac->mac_reason[i];
8514
8515	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8516		device_printf(sc->sc_dev, "MAC trans error\n");
8517
8518	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8519		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8520		mac->mac_phy.txerrors--;
8521		if (mac->mac_phy.txerrors == 0) {
8522			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8523			bwn_restart(mac, "PHY TX errors");
8524		}
8525	}
8526
8527	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8528		if (merged & BWN_DMAINTR_FATALMASK) {
8529			device_printf(sc->sc_dev,
8530			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8531			    mac->mac_reason[0], mac->mac_reason[1],
8532			    mac->mac_reason[2], mac->mac_reason[3],
8533			    mac->mac_reason[4], mac->mac_reason[5]);
8534			bwn_restart(mac, "DMA error");
8535			BWN_UNLOCK(sc);
8536			return;
8537		}
8538		if (merged & BWN_DMAINTR_NONFATALMASK) {
8539			device_printf(sc->sc_dev,
8540			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8541			    mac->mac_reason[0], mac->mac_reason[1],
8542			    mac->mac_reason[2], mac->mac_reason[3],
8543			    mac->mac_reason[4], mac->mac_reason[5]);
8544		}
8545	}
8546
8547	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8548		bwn_intr_ucode_debug(mac);
8549	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8550		bwn_intr_tbtt_indication(mac);
8551	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8552		bwn_intr_atim_end(mac);
8553	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8554		bwn_intr_beacon(mac);
8555	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8556		bwn_intr_pmq(mac);
8557	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8558		bwn_intr_noise(mac);
8559
8560	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8561		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8562			bwn_dma_rx(mac->mac_method.dma.rx);
8563			rx = 1;
8564		}
8565	} else
8566		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8567
8568	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8569	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8570	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8571	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8572	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8573
8574	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8575		bwn_intr_txeof(mac);
8576		tx = 1;
8577	}
8578
8579	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8580
8581	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8582		int evt = BWN_LED_EVENT_NONE;
8583
8584		if (tx && rx) {
8585			if (sc->sc_rx_rate > sc->sc_tx_rate)
8586				evt = BWN_LED_EVENT_RX;
8587			else
8588				evt = BWN_LED_EVENT_TX;
8589		} else if (tx) {
8590			evt = BWN_LED_EVENT_TX;
8591		} else if (rx) {
8592			evt = BWN_LED_EVENT_RX;
8593		} else if (rx == 0) {
8594			evt = BWN_LED_EVENT_POLL;
8595		}
8596
8597		if (evt != BWN_LED_EVENT_NONE)
8598			bwn_led_event(mac, evt);
8599       }
8600
8601	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8602		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8603			bwn_start_locked(ifp);
8604	}
8605
8606	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8607	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8608
8609	BWN_UNLOCK(sc);
8610}
8611
8612static void
8613bwn_restart(struct bwn_mac *mac, const char *msg)
8614{
8615	struct bwn_softc *sc = mac->mac_sc;
8616	struct ifnet *ifp = sc->sc_ifp;
8617	struct ieee80211com *ic = ifp->if_l2com;
8618
8619	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8620		return;
8621
8622	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8623	ieee80211_runtask(ic, &mac->mac_hwreset);
8624}
8625
8626static void
8627bwn_intr_ucode_debug(struct bwn_mac *mac)
8628{
8629	struct bwn_softc *sc = mac->mac_sc;
8630	uint16_t reason;
8631
8632	if (mac->mac_fw.opensource == 0)
8633		return;
8634
8635	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8636	switch (reason) {
8637	case BWN_DEBUGINTR_PANIC:
8638		bwn_handle_fwpanic(mac);
8639		break;
8640	case BWN_DEBUGINTR_DUMP_SHM:
8641		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8642		break;
8643	case BWN_DEBUGINTR_DUMP_REGS:
8644		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8645		break;
8646	case BWN_DEBUGINTR_MARKER:
8647		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8648		break;
8649	default:
8650		device_printf(sc->sc_dev,
8651		    "ucode debug unknown reason: %#x\n", reason);
8652	}
8653
8654	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8655	    BWN_DEBUGINTR_ACK);
8656}
8657
8658static void
8659bwn_intr_tbtt_indication(struct bwn_mac *mac)
8660{
8661	struct bwn_softc *sc = mac->mac_sc;
8662	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8663
8664	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8665		bwn_psctl(mac, 0);
8666	if (ic->ic_opmode == IEEE80211_M_IBSS)
8667		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8668}
8669
8670static void
8671bwn_intr_atim_end(struct bwn_mac *mac)
8672{
8673
8674	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8675		BWN_WRITE_4(mac, BWN_MACCMD,
8676		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8677		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8678	}
8679}
8680
8681static void
8682bwn_intr_beacon(struct bwn_mac *mac)
8683{
8684	struct bwn_softc *sc = mac->mac_sc;
8685	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8686	uint32_t cmd, beacon0, beacon1;
8687
8688	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8689	    ic->ic_opmode == IEEE80211_M_MBSS)
8690		return;
8691
8692	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8693
8694	cmd = BWN_READ_4(mac, BWN_MACCMD);
8695	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8696	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8697
8698	if (beacon0 && beacon1) {
8699		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8700		mac->mac_intr_mask |= BWN_INTR_BEACON;
8701		return;
8702	}
8703
8704	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8705		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8706		bwn_load_beacon0(mac);
8707		bwn_load_beacon1(mac);
8708		cmd = BWN_READ_4(mac, BWN_MACCMD);
8709		cmd |= BWN_MACCMD_BEACON0_VALID;
8710		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8711	} else {
8712		if (!beacon0) {
8713			bwn_load_beacon0(mac);
8714			cmd = BWN_READ_4(mac, BWN_MACCMD);
8715			cmd |= BWN_MACCMD_BEACON0_VALID;
8716			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8717		} else if (!beacon1) {
8718			bwn_load_beacon1(mac);
8719			cmd = BWN_READ_4(mac, BWN_MACCMD);
8720			cmd |= BWN_MACCMD_BEACON1_VALID;
8721			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8722		}
8723	}
8724}
8725
8726static void
8727bwn_intr_pmq(struct bwn_mac *mac)
8728{
8729	uint32_t tmp;
8730
8731	while (1) {
8732		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8733		if (!(tmp & 0x00000008))
8734			break;
8735	}
8736	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8737}
8738
8739static void
8740bwn_intr_noise(struct bwn_mac *mac)
8741{
8742	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8743	uint16_t tmp;
8744	uint8_t noise[4];
8745	uint8_t i, j;
8746	int32_t average;
8747
8748	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8749		return;
8750
8751	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8752	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8753	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8754	    noise[3] == 0x7f)
8755		goto new;
8756
8757	KASSERT(mac->mac_noise.noi_nsamples < 8,
8758	    ("%s:%d: fail", __func__, __LINE__));
8759	i = mac->mac_noise.noi_nsamples;
8760	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8761	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8762	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8763	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8764	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8765	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8766	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8767	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8768	mac->mac_noise.noi_nsamples++;
8769	if (mac->mac_noise.noi_nsamples == 8) {
8770		average = 0;
8771		for (i = 0; i < 8; i++) {
8772			for (j = 0; j < 4; j++)
8773				average += mac->mac_noise.noi_samples[i][j];
8774		}
8775		average = (((average / 32) * 125) + 64) / 128;
8776		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8777		if (tmp >= 8)
8778			average += 2;
8779		else
8780			average -= 25;
8781		average -= (tmp == 8) ? 72 : 48;
8782
8783		mac->mac_stats.link_noise = average;
8784		mac->mac_noise.noi_running = 0;
8785		return;
8786	}
8787new:
8788	bwn_noise_gensample(mac);
8789}
8790
8791static int
8792bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8793{
8794	struct bwn_mac *mac = prq->prq_mac;
8795	struct bwn_softc *sc = mac->mac_sc;
8796	unsigned int i;
8797
8798	BWN_ASSERT_LOCKED(sc);
8799
8800	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8801		return (0);
8802
8803	for (i = 0; i < 5000; i++) {
8804		if (bwn_pio_rxeof(prq) == 0)
8805			break;
8806	}
8807	if (i >= 5000)
8808		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8809	return ((i > 0) ? 1 : 0);
8810}
8811
8812static void
8813bwn_dma_rx(struct bwn_dma_ring *dr)
8814{
8815	int slot, curslot;
8816
8817	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8818	curslot = dr->get_curslot(dr);
8819	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8820	    ("%s:%d: fail", __func__, __LINE__));
8821
8822	slot = dr->dr_curslot;
8823	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8824		bwn_dma_rxeof(dr, &slot);
8825
8826	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8827	    BUS_DMASYNC_PREWRITE);
8828
8829	dr->set_curslot(dr, slot);
8830	dr->dr_curslot = slot;
8831}
8832
8833static void
8834bwn_intr_txeof(struct bwn_mac *mac)
8835{
8836	struct bwn_txstatus stat;
8837	uint32_t stat0, stat1;
8838	uint16_t tmp;
8839
8840	BWN_ASSERT_LOCKED(mac->mac_sc);
8841
8842	while (1) {
8843		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8844		if (!(stat0 & 0x00000001))
8845			break;
8846		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8847
8848		stat.cookie = (stat0 >> 16);
8849		stat.seq = (stat1 & 0x0000ffff);
8850		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8851		tmp = (stat0 & 0x0000ffff);
8852		stat.framecnt = ((tmp & 0xf000) >> 12);
8853		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8854		stat.sreason = ((tmp & 0x001c) >> 2);
8855		stat.pm = (tmp & 0x0080) ? 1 : 0;
8856		stat.im = (tmp & 0x0040) ? 1 : 0;
8857		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8858		stat.ack = (tmp & 0x0002) ? 1 : 0;
8859
8860		bwn_handle_txeof(mac, &stat);
8861	}
8862}
8863
8864static void
8865bwn_hwreset(void *arg, int npending)
8866{
8867	struct bwn_mac *mac = arg;
8868	struct bwn_softc *sc = mac->mac_sc;
8869	int error = 0;
8870	int prev_status;
8871
8872	BWN_LOCK(sc);
8873
8874	prev_status = mac->mac_status;
8875	if (prev_status >= BWN_MAC_STATUS_STARTED)
8876		bwn_core_stop(mac);
8877	if (prev_status >= BWN_MAC_STATUS_INITED)
8878		bwn_core_exit(mac);
8879
8880	if (prev_status >= BWN_MAC_STATUS_INITED) {
8881		error = bwn_core_init(mac);
8882		if (error)
8883			goto out;
8884	}
8885	if (prev_status >= BWN_MAC_STATUS_STARTED)
8886		bwn_core_start(mac);
8887out:
8888	if (error) {
8889		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8890		sc->sc_curmac = NULL;
8891	}
8892	BWN_UNLOCK(sc);
8893}
8894
8895static void
8896bwn_handle_fwpanic(struct bwn_mac *mac)
8897{
8898	struct bwn_softc *sc = mac->mac_sc;
8899	uint16_t reason;
8900
8901	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8902	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8903
8904	if (reason == BWN_FWPANIC_RESTART)
8905		bwn_restart(mac, "ucode panic");
8906}
8907
8908static void
8909bwn_load_beacon0(struct bwn_mac *mac)
8910{
8911
8912	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8913}
8914
8915static void
8916bwn_load_beacon1(struct bwn_mac *mac)
8917{
8918
8919	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8920}
8921
8922static uint32_t
8923bwn_jssi_read(struct bwn_mac *mac)
8924{
8925	uint32_t val = 0;
8926
8927	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8928	val <<= 16;
8929	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8930
8931	return (val);
8932}
8933
8934static void
8935bwn_noise_gensample(struct bwn_mac *mac)
8936{
8937	uint32_t jssi = 0x7f7f7f7f;
8938
8939	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8940	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8941	BWN_WRITE_4(mac, BWN_MACCMD,
8942	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8943}
8944
8945static int
8946bwn_dma_freeslot(struct bwn_dma_ring *dr)
8947{
8948	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8949
8950	return (dr->dr_numslots - dr->dr_usedslot);
8951}
8952
8953static int
8954bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8955{
8956	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8957
8958	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8959	    ("%s:%d: fail", __func__, __LINE__));
8960	if (slot == dr->dr_numslots - 1)
8961		return (0);
8962	return (slot + 1);
8963}
8964
8965static void
8966bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8967{
8968	struct bwn_mac *mac = dr->dr_mac;
8969	struct bwn_softc *sc = mac->mac_sc;
8970	struct bwn_dma *dma = &mac->mac_method.dma;
8971	struct bwn_dmadesc_generic *desc;
8972	struct bwn_dmadesc_meta *meta;
8973	struct bwn_rxhdr4 *rxhdr;
8974	struct ifnet *ifp = sc->sc_ifp;
8975	struct mbuf *m;
8976	uint32_t macstat;
8977	int32_t tmp;
8978	int cnt = 0;
8979	uint16_t len;
8980
8981	dr->getdesc(dr, *slot, &desc, &meta);
8982
8983	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8984	m = meta->mt_m;
8985
8986	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8987		ifp->if_ierrors++;
8988		return;
8989	}
8990
8991	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8992	len = le16toh(rxhdr->frame_len);
8993	if (len <= 0) {
8994		ifp->if_ierrors++;
8995		return;
8996	}
8997	if (bwn_dma_check_redzone(dr, m)) {
8998		device_printf(sc->sc_dev, "redzone error.\n");
8999		bwn_dma_set_redzone(dr, m);
9000		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9001		    BUS_DMASYNC_PREWRITE);
9002		return;
9003	}
9004	if (len > dr->dr_rx_bufsize) {
9005		tmp = len;
9006		while (1) {
9007			dr->getdesc(dr, *slot, &desc, &meta);
9008			bwn_dma_set_redzone(dr, meta->mt_m);
9009			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9010			    BUS_DMASYNC_PREWRITE);
9011			*slot = bwn_dma_nextslot(dr, *slot);
9012			cnt++;
9013			tmp -= dr->dr_rx_bufsize;
9014			if (tmp <= 0)
9015				break;
9016		}
9017		device_printf(sc->sc_dev, "too small buffer "
9018		       "(len %u buffer %u dropped %d)\n",
9019		       len, dr->dr_rx_bufsize, cnt);
9020		return;
9021	}
9022	macstat = le32toh(rxhdr->mac_status);
9023	if (macstat & BWN_RX_MAC_FCSERR) {
9024		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9025			device_printf(sc->sc_dev, "RX drop\n");
9026			return;
9027		}
9028	}
9029
9030	m->m_pkthdr.rcvif = ifp;
9031	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9032	m_adj(m, dr->dr_frameoffset);
9033
9034	bwn_rxeof(dr->dr_mac, m, rxhdr);
9035}
9036
9037static void
9038bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9039{
9040	struct bwn_dma_ring *dr;
9041	struct bwn_dmadesc_generic *desc;
9042	struct bwn_dmadesc_meta *meta;
9043	struct bwn_node *bn;
9044	struct bwn_pio_txqueue *tq;
9045	struct bwn_pio_txpkt *tp = NULL;
9046	struct bwn_softc *sc = mac->mac_sc;
9047	struct bwn_stats *stats = &mac->mac_stats;
9048	struct ieee80211_node *ni;
9049	int slot;
9050
9051	BWN_ASSERT_LOCKED(mac->mac_sc);
9052
9053	if (status->im)
9054		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9055	if (status->ampdu)
9056		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9057	if (status->rtscnt) {
9058		if (status->rtscnt == 0xf)
9059			stats->rtsfail++;
9060		else
9061			stats->rts++;
9062	}
9063
9064	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9065		if (status->ack) {
9066			dr = bwn_dma_parse_cookie(mac, status,
9067			    status->cookie, &slot);
9068			if (dr == NULL) {
9069				device_printf(sc->sc_dev,
9070				    "failed to parse cookie\n");
9071				return;
9072			}
9073			while (1) {
9074				dr->getdesc(dr, slot, &desc, &meta);
9075				if (meta->mt_islast) {
9076					ni = meta->mt_ni;
9077					bn = (struct bwn_node *)ni;
9078					ieee80211_amrr_tx_complete(&bn->bn_amn,
9079					    status->ack, 0);
9080					break;
9081				}
9082				slot = bwn_dma_nextslot(dr, slot);
9083			}
9084		}
9085		bwn_dma_handle_txeof(mac, status);
9086	} else {
9087		if (status->ack) {
9088			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9089			if (tq == NULL) {
9090				device_printf(sc->sc_dev,
9091				    "failed to parse cookie\n");
9092				return;
9093			}
9094			ni = tp->tp_ni;
9095			bn = (struct bwn_node *)ni;
9096			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9097		}
9098		bwn_pio_handle_txeof(mac, status);
9099	}
9100
9101	bwn_phy_txpower_check(mac, 0);
9102}
9103
9104static uint8_t
9105bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9106{
9107	struct bwn_mac *mac = prq->prq_mac;
9108	struct bwn_softc *sc = mac->mac_sc;
9109	struct bwn_rxhdr4 rxhdr;
9110	struct ifnet *ifp = sc->sc_ifp;
9111	struct mbuf *m;
9112	uint32_t ctl32, macstat, v32;
9113	unsigned int i, padding;
9114	uint16_t ctl16, len, v16;
9115	unsigned char *mp;
9116	char *data;
9117
9118	memset(&rxhdr, 0, sizeof(rxhdr));
9119
9120	if (prq->prq_rev >= 8) {
9121		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9122		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9123			return (0);
9124		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9125		    BWN_PIO8_RXCTL_FRAMEREADY);
9126		for (i = 0; i < 10; i++) {
9127			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9128			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9129				goto ready;
9130			DELAY(10);
9131		}
9132	} else {
9133		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9134		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9135			return (0);
9136		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9137		    BWN_PIO_RXCTL_FRAMEREADY);
9138		for (i = 0; i < 10; i++) {
9139			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9140			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9141				goto ready;
9142			DELAY(10);
9143		}
9144	}
9145	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9146	return (1);
9147ready:
9148	if (prq->prq_rev >= 8)
9149		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9150		    prq->prq_base + BWN_PIO8_RXDATA);
9151	else
9152		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9153		    prq->prq_base + BWN_PIO_RXDATA);
9154	len = le16toh(rxhdr.frame_len);
9155	if (len > 0x700) {
9156		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9157		goto error;
9158	}
9159	if (len == 0) {
9160		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9161		goto error;
9162	}
9163
9164	macstat = le32toh(rxhdr.mac_status);
9165	if (macstat & BWN_RX_MAC_FCSERR) {
9166		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9167			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9168			goto error;
9169		}
9170	}
9171
9172	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9173	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9174	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9175	if (m == NULL) {
9176		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9177		goto error;
9178	}
9179	mp = mtod(m, unsigned char *);
9180	if (prq->prq_rev >= 8) {
9181		siba_read_multi_4(sc->sc_dev, mp + padding, (len & ~3),
9182		    prq->prq_base + BWN_PIO8_RXDATA);
9183		if (len & 3) {
9184			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9185			data = &(mp[len + padding - 1]);
9186			switch (len & 3) {
9187			case 3:
9188				*data = (v32 >> 16);
9189				data--;
9190			case 2:
9191				*data = (v32 >> 8);
9192				data--;
9193			case 1:
9194				*data = v32;
9195			}
9196		}
9197	} else {
9198		siba_read_multi_2(sc->sc_dev, mp + padding, (len & ~1),
9199		    prq->prq_base + BWN_PIO_RXDATA);
9200		if (len & 1) {
9201			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9202			mp[len + padding - 1] = v16;
9203		}
9204	}
9205
9206	m->m_pkthdr.rcvif = ifp;
9207	m->m_len = m->m_pkthdr.len = len + padding;
9208
9209	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9210
9211	return (1);
9212error:
9213	if (prq->prq_rev >= 8)
9214		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9215		    BWN_PIO8_RXCTL_DATAREADY);
9216	else
9217		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9218	return (1);
9219}
9220
9221static int
9222bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9223    struct bwn_dmadesc_meta *meta, int init)
9224{
9225	struct bwn_mac *mac = dr->dr_mac;
9226	struct bwn_dma *dma = &mac->mac_method.dma;
9227	struct bwn_rxhdr4 *hdr;
9228	bus_dmamap_t map;
9229	bus_addr_t paddr;
9230	struct mbuf *m;
9231	int error;
9232
9233	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9234	if (m == NULL) {
9235		error = ENOBUFS;
9236
9237		/*
9238		 * If the NIC is up and running, we need to:
9239		 * - Clear RX buffer's header.
9240		 * - Restore RX descriptor settings.
9241		 */
9242		if (init)
9243			return (error);
9244		else
9245			goto back;
9246	}
9247	m->m_len = m->m_pkthdr.len = MCLBYTES;
9248
9249	bwn_dma_set_redzone(dr, m);
9250
9251	/*
9252	 * Try to load RX buf into temporary DMA map
9253	 */
9254	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9255	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9256	if (error) {
9257		m_freem(m);
9258
9259		/*
9260		 * See the comment above
9261		 */
9262		if (init)
9263			return (error);
9264		else
9265			goto back;
9266	}
9267
9268	if (!init)
9269		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9270	meta->mt_m = m;
9271	meta->mt_paddr = paddr;
9272
9273	/*
9274	 * Swap RX buf's DMA map with the loaded temporary one
9275	 */
9276	map = meta->mt_dmap;
9277	meta->mt_dmap = dr->dr_spare_dmap;
9278	dr->dr_spare_dmap = map;
9279
9280back:
9281	/*
9282	 * Clear RX buf header
9283	 */
9284	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9285	bzero(hdr, sizeof(*hdr));
9286	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9287	    BUS_DMASYNC_PREWRITE);
9288
9289	/*
9290	 * Setup RX buf descriptor
9291	 */
9292	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9293	    sizeof(*hdr), 0, 0, 0);
9294	return (error);
9295}
9296
9297static void
9298bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9299		 bus_size_t mapsz __unused, int error)
9300{
9301
9302	if (!error) {
9303		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9304		*((bus_addr_t *)arg) = seg->ds_addr;
9305	}
9306}
9307
9308static int
9309bwn_hwrate2ieeerate(int rate)
9310{
9311
9312	switch (rate) {
9313	case BWN_CCK_RATE_1MB:
9314		return (2);
9315	case BWN_CCK_RATE_2MB:
9316		return (4);
9317	case BWN_CCK_RATE_5MB:
9318		return (11);
9319	case BWN_CCK_RATE_11MB:
9320		return (22);
9321	case BWN_OFDM_RATE_6MB:
9322		return (12);
9323	case BWN_OFDM_RATE_9MB:
9324		return (18);
9325	case BWN_OFDM_RATE_12MB:
9326		return (24);
9327	case BWN_OFDM_RATE_18MB:
9328		return (36);
9329	case BWN_OFDM_RATE_24MB:
9330		return (48);
9331	case BWN_OFDM_RATE_36MB:
9332		return (72);
9333	case BWN_OFDM_RATE_48MB:
9334		return (96);
9335	case BWN_OFDM_RATE_54MB:
9336		return (108);
9337	default:
9338		printf("Ooops\n");
9339		return (0);
9340	}
9341}
9342
9343static void
9344bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9345{
9346	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9347	struct bwn_plcp6 *plcp;
9348	struct bwn_softc *sc = mac->mac_sc;
9349	struct ieee80211_frame_min *wh;
9350	struct ieee80211_node *ni;
9351	struct ifnet *ifp = sc->sc_ifp;
9352	struct ieee80211com *ic = ifp->if_l2com;
9353	uint32_t macstat;
9354	int padding, rate, rssi = 0, noise = 0, type;
9355	uint16_t phytype, phystat0, phystat3, chanstat;
9356	unsigned char *mp = mtod(m, unsigned char *);
9357	static int rx_mac_dec_rpt = 0;
9358
9359	BWN_ASSERT_LOCKED(sc);
9360
9361	phystat0 = le16toh(rxhdr->phy_status0);
9362	phystat3 = le16toh(rxhdr->phy_status3);
9363	macstat = le32toh(rxhdr->mac_status);
9364	chanstat = le16toh(rxhdr->channel);
9365	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9366
9367	if (macstat & BWN_RX_MAC_FCSERR)
9368		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9369	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9370		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9371	if (macstat & BWN_RX_MAC_DECERR)
9372		goto drop;
9373
9374	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9375	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9376		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9377		    m->m_pkthdr.len);
9378		goto drop;
9379	}
9380	plcp = (struct bwn_plcp6 *)(mp + padding);
9381	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9382	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9383		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9384		    m->m_pkthdr.len);
9385		goto drop;
9386	}
9387	wh = mtod(m, struct ieee80211_frame_min *);
9388
9389	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9390		device_printf(sc->sc_dev,
9391		    "RX decryption attempted (old %d keyidx %#x)\n",
9392		    BWN_ISOLDFMT(mac),
9393		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9394
9395	/* XXX calculating RSSI & noise & antenna */
9396
9397	if (phystat0 & BWN_RX_PHYST0_OFDM)
9398		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9399		    phytype == BWN_PHYTYPE_A);
9400	else
9401		rate = bwn_plcp_get_cckrate(mac, plcp);
9402	if (rate == -1) {
9403		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9404			goto drop;
9405	}
9406	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9407
9408	/* RX radio tap */
9409	if (ieee80211_radiotap_active(ic))
9410		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9411	m_adj(m, -IEEE80211_CRC_LEN);
9412
9413	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9414	noise = mac->mac_stats.link_noise;
9415
9416	BWN_UNLOCK(sc);
9417
9418	ni = ieee80211_find_rxnode(ic, wh);
9419	if (ni != NULL) {
9420		type = ieee80211_input(ni, m, rssi, noise);
9421		ieee80211_free_node(ni);
9422	} else
9423		type = ieee80211_input_all(ic, m, rssi, noise);
9424
9425	BWN_LOCK(sc);
9426	return;
9427drop:
9428	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9429}
9430
9431static void
9432bwn_dma_handle_txeof(struct bwn_mac *mac,
9433    const struct bwn_txstatus *status)
9434{
9435	struct bwn_dma *dma = &mac->mac_method.dma;
9436	struct bwn_dma_ring *dr;
9437	struct bwn_dmadesc_generic *desc;
9438	struct bwn_dmadesc_meta *meta;
9439	struct bwn_softc *sc = mac->mac_sc;
9440	struct ieee80211_node *ni;
9441	struct ifnet *ifp = sc->sc_ifp;
9442	struct mbuf *m;
9443	int slot;
9444
9445	BWN_ASSERT_LOCKED(sc);
9446
9447	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9448	if (dr == NULL) {
9449		device_printf(sc->sc_dev, "failed to parse cookie\n");
9450		return;
9451	}
9452	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9453
9454	while (1) {
9455		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9456		    ("%s:%d: fail", __func__, __LINE__));
9457		dr->getdesc(dr, slot, &desc, &meta);
9458
9459		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9460			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9461		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9462			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9463
9464		if (meta->mt_islast) {
9465			KASSERT(meta->mt_m != NULL,
9466			    ("%s:%d: fail", __func__, __LINE__));
9467
9468			ni = meta->mt_ni;
9469			m = meta->mt_m;
9470			if (ni != NULL) {
9471				/*
9472				 * Do any tx complete callback. Note this must
9473				 * be done before releasing the node reference.
9474				 */
9475				if (m->m_flags & M_TXCB)
9476					ieee80211_process_callback(ni, m, 0);
9477				ieee80211_free_node(ni);
9478				meta->mt_ni = NULL;
9479			}
9480			m_freem(m);
9481			meta->mt_m = NULL;
9482		} else {
9483			KASSERT(meta->mt_m == NULL,
9484			    ("%s:%d: fail", __func__, __LINE__));
9485		}
9486
9487		dr->dr_usedslot--;
9488		if (meta->mt_islast) {
9489			ifp->if_opackets++;
9490			break;
9491		}
9492		slot = bwn_dma_nextslot(dr, slot);
9493	}
9494	sc->sc_watchdog_timer = 0;
9495	if (dr->dr_stop) {
9496		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9497		    ("%s:%d: fail", __func__, __LINE__));
9498		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9499		dr->dr_stop = 0;
9500	}
9501}
9502
9503static void
9504bwn_pio_handle_txeof(struct bwn_mac *mac,
9505    const struct bwn_txstatus *status)
9506{
9507	struct bwn_pio_txqueue *tq;
9508	struct bwn_pio_txpkt *tp = NULL;
9509	struct bwn_softc *sc = mac->mac_sc;
9510	struct ifnet *ifp = sc->sc_ifp;
9511
9512	BWN_ASSERT_LOCKED(sc);
9513
9514	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9515	if (tq == NULL)
9516		return;
9517
9518	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9519	tq->tq_free++;
9520
9521	if (tp->tp_ni != NULL) {
9522		/*
9523		 * Do any tx complete callback.  Note this must
9524		 * be done before releasing the node reference.
9525		 */
9526		if (tp->tp_m->m_flags & M_TXCB)
9527			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9528		ieee80211_free_node(tp->tp_ni);
9529		tp->tp_ni = NULL;
9530	}
9531	m_freem(tp->tp_m);
9532	tp->tp_m = NULL;
9533	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9534
9535	ifp->if_opackets++;
9536
9537	sc->sc_watchdog_timer = 0;
9538	if (tq->tq_stop) {
9539		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9540		tq->tq_stop = 0;
9541	}
9542}
9543
9544static void
9545bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9546{
9547	struct bwn_softc *sc = mac->mac_sc;
9548	struct bwn_phy *phy = &mac->mac_phy;
9549	struct ifnet *ifp = sc->sc_ifp;
9550	struct ieee80211com *ic = ifp->if_l2com;
9551	unsigned long now;
9552	int result;
9553
9554	BWN_GETTIME(now);
9555
9556	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9557		return;
9558	phy->nexttime = now + 2 * 1000;
9559
9560	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9561	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9562		return;
9563
9564	if (phy->recalc_txpwr != NULL) {
9565		result = phy->recalc_txpwr(mac,
9566		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9567		if (result == BWN_TXPWR_RES_DONE)
9568			return;
9569		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9570		    ("%s: fail", __func__));
9571		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9572
9573		ieee80211_runtask(ic, &mac->mac_txpower);
9574	}
9575}
9576
9577static uint16_t
9578bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9579{
9580
9581	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9582}
9583
9584static uint32_t
9585bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9586{
9587
9588	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9589}
9590
9591static void
9592bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9593{
9594
9595	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9596}
9597
9598static void
9599bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9600{
9601
9602	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9603}
9604
9605static int
9606bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9607{
9608
9609	switch (rate) {
9610	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9611	case 12:
9612		return (BWN_OFDM_RATE_6MB);
9613	case 18:
9614		return (BWN_OFDM_RATE_9MB);
9615	case 24:
9616		return (BWN_OFDM_RATE_12MB);
9617	case 36:
9618		return (BWN_OFDM_RATE_18MB);
9619	case 48:
9620		return (BWN_OFDM_RATE_24MB);
9621	case 72:
9622		return (BWN_OFDM_RATE_36MB);
9623	case 96:
9624		return (BWN_OFDM_RATE_48MB);
9625	case 108:
9626		return (BWN_OFDM_RATE_54MB);
9627	/* CCK rates (NB: not IEEE std, device-specific) */
9628	case 2:
9629		return (BWN_CCK_RATE_1MB);
9630	case 4:
9631		return (BWN_CCK_RATE_2MB);
9632	case 11:
9633		return (BWN_CCK_RATE_5MB);
9634	case 22:
9635		return (BWN_CCK_RATE_11MB);
9636	}
9637
9638	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9639	return (BWN_CCK_RATE_1MB);
9640}
9641
9642static int
9643bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9644    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9645{
9646	const struct bwn_phy *phy = &mac->mac_phy;
9647	struct bwn_softc *sc = mac->mac_sc;
9648	struct ieee80211_frame *wh;
9649	struct ieee80211_frame *protwh;
9650	struct ieee80211_frame_cts *cts;
9651	struct ieee80211_frame_rts *rts;
9652	const struct ieee80211_txparam *tp;
9653	struct ieee80211vap *vap = ni->ni_vap;
9654	struct ifnet *ifp = sc->sc_ifp;
9655	struct ieee80211com *ic = ifp->if_l2com;
9656	struct mbuf *mprot;
9657	unsigned int len;
9658	uint32_t macctl = 0;
9659	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9660	uint16_t phyctl = 0;
9661	uint8_t rate, rate_fb;
9662
9663	wh = mtod(m, struct ieee80211_frame *);
9664	memset(txhdr, 0, sizeof(*txhdr));
9665
9666	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9667	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9668	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9669
9670	/*
9671	 * Find TX rate
9672	 */
9673	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9674	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9675		rate = rate_fb = tp->mgmtrate;
9676	else if (ismcast)
9677		rate = rate_fb = tp->mcastrate;
9678	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9679		rate = rate_fb = tp->ucastrate;
9680	else {
9681		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9682		rate = ni->ni_txrate;
9683
9684		if (rix > 0)
9685			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9686			    IEEE80211_RATE_VAL;
9687		else
9688			rate_fb = rate;
9689	}
9690
9691	sc->sc_tx_rate = rate;
9692
9693	rate = bwn_ieeerate2hwrate(sc, rate);
9694	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9695
9696	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9697	    bwn_plcp_getcck(rate);
9698	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9699	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9700
9701	if ((rate_fb == rate) ||
9702	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9703	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9704		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9705	else
9706		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9707		    m->m_pkthdr.len, rate, isshort);
9708
9709	/* XXX TX encryption */
9710	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9711	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9712	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9713	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9714	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9715	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9716
9717	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9718	    BWN_TX_EFT_FB_CCK;
9719	txhdr->chan = phy->chan;
9720	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9721	    BWN_TX_PHY_ENC_CCK;
9722	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9723	     rate == BWN_CCK_RATE_11MB))
9724		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9725
9726	/* XXX TX antenna selection */
9727
9728	switch (bwn_antenna_sanitize(mac, 0)) {
9729	case 0:
9730		phyctl |= BWN_TX_PHY_ANT01AUTO;
9731		break;
9732	case 1:
9733		phyctl |= BWN_TX_PHY_ANT0;
9734		break;
9735	case 2:
9736		phyctl |= BWN_TX_PHY_ANT1;
9737		break;
9738	case 3:
9739		phyctl |= BWN_TX_PHY_ANT2;
9740		break;
9741	case 4:
9742		phyctl |= BWN_TX_PHY_ANT3;
9743		break;
9744	default:
9745		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9746	}
9747
9748	if (!ismcast)
9749		macctl |= BWN_TX_MAC_ACK;
9750
9751	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9752	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9753	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9754		macctl |= BWN_TX_MAC_LONGFRAME;
9755
9756	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9757		/* XXX RTS rate is always 1MB??? */
9758		rts_rate = BWN_CCK_RATE_1MB;
9759		rts_rate_fb = bwn_get_fbrate(rts_rate);
9760
9761		protdur = ieee80211_compute_duration(ic->ic_rt,
9762		    m->m_pkthdr.len, rate, isshort) +
9763		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9764
9765		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9766			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9767			    (txhdr->body.old.rts_frame) :
9768			    (txhdr->body.new.rts_frame));
9769			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9770			    protdur);
9771			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9772			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9773			    mprot->m_pkthdr.len);
9774			m_freem(mprot);
9775			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9776			len = sizeof(struct ieee80211_frame_cts);
9777		} else {
9778			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9779			    (txhdr->body.old.rts_frame) :
9780			    (txhdr->body.new.rts_frame));
9781			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9782			    isshort);
9783			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9784			    wh->i_addr2, protdur);
9785			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9786			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9787			    mprot->m_pkthdr.len);
9788			m_freem(mprot);
9789			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9790			len = sizeof(struct ieee80211_frame_rts);
9791		}
9792		len += IEEE80211_CRC_LEN;
9793		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9794		    &txhdr->body.old.rts_plcp :
9795		    &txhdr->body.new.rts_plcp), len, rts_rate);
9796		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9797		    rts_rate_fb);
9798
9799		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9800		    (&txhdr->body.old.rts_frame) :
9801		    (&txhdr->body.new.rts_frame));
9802		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9803
9804		if (BWN_ISOFDMRATE(rts_rate)) {
9805			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9806			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9807		} else {
9808			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9809			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9810		}
9811		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9812		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9813	}
9814
9815	if (BWN_ISOLDFMT(mac))
9816		txhdr->body.old.cookie = htole16(cookie);
9817	else
9818		txhdr->body.new.cookie = htole16(cookie);
9819
9820	txhdr->macctl = htole32(macctl);
9821	txhdr->phyctl = htole16(phyctl);
9822
9823	/*
9824	 * TX radio tap
9825	 */
9826	if (ieee80211_radiotap_active_vap(vap)) {
9827		sc->sc_tx_th.wt_flags = 0;
9828		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9829			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9830		if (isshort &&
9831		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9832		     rate == BWN_CCK_RATE_11MB))
9833			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9834		sc->sc_tx_th.wt_rate = rate;
9835
9836		ieee80211_radiotap_tx(vap, m);
9837	}
9838
9839	return (0);
9840}
9841
9842static void
9843bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9844    const uint8_t rate)
9845{
9846	uint32_t d, plen;
9847	uint8_t *raw = plcp->o.raw;
9848
9849	if (BWN_ISOFDMRATE(rate)) {
9850		d = bwn_plcp_getofdm(rate);
9851		KASSERT(!(octets & 0xf000),
9852		    ("%s:%d: fail", __func__, __LINE__));
9853		d |= (octets << 5);
9854		plcp->o.data = htole32(d);
9855	} else {
9856		plen = octets * 16 / rate;
9857		if ((octets * 16 % rate) > 0) {
9858			plen++;
9859			if ((rate == BWN_CCK_RATE_11MB)
9860			    && ((octets * 8 % 11) < 4)) {
9861				raw[1] = 0x84;
9862			} else
9863				raw[1] = 0x04;
9864		} else
9865			raw[1] = 0x04;
9866		plcp->o.data |= htole32(plen << 16);
9867		raw[0] = bwn_plcp_getcck(rate);
9868	}
9869}
9870
9871static uint8_t
9872bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9873{
9874	struct bwn_softc *sc = mac->mac_sc;
9875	uint8_t mask;
9876
9877	if (n == 0)
9878		return (0);
9879	if (mac->mac_phy.gmode)
9880		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9881	else
9882		mask = siba_sprom_get_ant_a(sc->sc_dev);
9883	if (!(mask & (1 << (n - 1))))
9884		return (0);
9885	return (n);
9886}
9887
9888static uint8_t
9889bwn_get_fbrate(uint8_t bitrate)
9890{
9891	switch (bitrate) {
9892	case BWN_CCK_RATE_1MB:
9893		return (BWN_CCK_RATE_1MB);
9894	case BWN_CCK_RATE_2MB:
9895		return (BWN_CCK_RATE_1MB);
9896	case BWN_CCK_RATE_5MB:
9897		return (BWN_CCK_RATE_2MB);
9898	case BWN_CCK_RATE_11MB:
9899		return (BWN_CCK_RATE_5MB);
9900	case BWN_OFDM_RATE_6MB:
9901		return (BWN_CCK_RATE_5MB);
9902	case BWN_OFDM_RATE_9MB:
9903		return (BWN_OFDM_RATE_6MB);
9904	case BWN_OFDM_RATE_12MB:
9905		return (BWN_OFDM_RATE_9MB);
9906	case BWN_OFDM_RATE_18MB:
9907		return (BWN_OFDM_RATE_12MB);
9908	case BWN_OFDM_RATE_24MB:
9909		return (BWN_OFDM_RATE_18MB);
9910	case BWN_OFDM_RATE_36MB:
9911		return (BWN_OFDM_RATE_24MB);
9912	case BWN_OFDM_RATE_48MB:
9913		return (BWN_OFDM_RATE_36MB);
9914	case BWN_OFDM_RATE_54MB:
9915		return (BWN_OFDM_RATE_48MB);
9916	}
9917	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9918	return (0);
9919}
9920
9921static uint32_t
9922bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9923    uint32_t ctl, const void *_data, int len)
9924{
9925	struct bwn_softc *sc = mac->mac_sc;
9926	uint32_t value = 0;
9927	const uint8_t *data = _data;
9928
9929	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9930	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9931	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9932
9933	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9934	    tq->tq_base + BWN_PIO8_TXDATA);
9935	if (len & 3) {
9936		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9937		    BWN_PIO8_TXCTL_24_31);
9938		data = &(data[len - 1]);
9939		switch (len & 3) {
9940		case 3:
9941			ctl |= BWN_PIO8_TXCTL_16_23;
9942			value |= (uint32_t)(*data) << 16;
9943			data--;
9944		case 2:
9945			ctl |= BWN_PIO8_TXCTL_8_15;
9946			value |= (uint32_t)(*data) << 8;
9947			data--;
9948		case 1:
9949			value |= (uint32_t)(*data);
9950		}
9951		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9952		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9953	}
9954
9955	return (ctl);
9956}
9957
9958static void
9959bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9960    uint16_t offset, uint32_t value)
9961{
9962
9963	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9964}
9965
9966static uint16_t
9967bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9968    uint16_t ctl, const void *_data, int len)
9969{
9970	struct bwn_softc *sc = mac->mac_sc;
9971	const uint8_t *data = _data;
9972
9973	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9974	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9975
9976	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9977	    tq->tq_base + BWN_PIO_TXDATA);
9978	if (len & 1) {
9979		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9980		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9981		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9982	}
9983
9984	return (ctl);
9985}
9986
9987static uint16_t
9988bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9989    uint16_t ctl, struct mbuf *m0)
9990{
9991	int i, j = 0;
9992	uint16_t data = 0;
9993	const uint8_t *buf;
9994	struct mbuf *m = m0;
9995
9996	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9997	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9998
9999	for (; m != NULL; m = m->m_next) {
10000		buf = mtod(m, const uint8_t *);
10001		for (i = 0; i < m->m_len; i++) {
10002			if (!((j++) % 2))
10003				data |= buf[i];
10004			else {
10005				data |= (buf[i] << 8);
10006				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10007				data = 0;
10008			}
10009		}
10010	}
10011	if (m0->m_pkthdr.len % 2) {
10012		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10013		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10014		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10015	}
10016
10017	return (ctl);
10018}
10019
10020static void
10021bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10022{
10023
10024	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10025		return;
10026	BWN_WRITE_2(mac, 0x684, 510 + time);
10027	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10028}
10029
10030static struct bwn_dma_ring *
10031bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10032{
10033
10034	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10035		return (mac->mac_method.dma.wme[WME_AC_BE]);
10036
10037	switch (prio) {
10038	case 3:
10039		return (mac->mac_method.dma.wme[WME_AC_VO]);
10040	case 2:
10041		return (mac->mac_method.dma.wme[WME_AC_VI]);
10042	case 0:
10043		return (mac->mac_method.dma.wme[WME_AC_BE]);
10044	case 1:
10045		return (mac->mac_method.dma.wme[WME_AC_BK]);
10046	}
10047	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10048	return (NULL);
10049}
10050
10051static int
10052bwn_dma_getslot(struct bwn_dma_ring *dr)
10053{
10054	int slot;
10055
10056	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10057
10058	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10059	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10060	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10061
10062	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10063	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10064	dr->dr_curslot = slot;
10065	dr->dr_usedslot++;
10066
10067	return (slot);
10068}
10069
10070static int
10071bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10072{
10073	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10074	unsigned int a, b, c, d;
10075	unsigned int avg;
10076	uint32_t tmp;
10077
10078	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10079	a = tmp & 0xff;
10080	b = (tmp >> 8) & 0xff;
10081	c = (tmp >> 16) & 0xff;
10082	d = (tmp >> 24) & 0xff;
10083	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10084	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10085		return (ENOENT);
10086	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10087	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10088	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10089
10090	if (ofdm) {
10091		a = (a + 32) & 0x3f;
10092		b = (b + 32) & 0x3f;
10093		c = (c + 32) & 0x3f;
10094		d = (d + 32) & 0x3f;
10095	}
10096
10097	avg = (a + b + c + d + 2) / 4;
10098	if (ofdm) {
10099		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10100		    & BWN_HF_4DB_CCK_POWERBOOST)
10101			avg = (avg >= 13) ? (avg - 13) : 0;
10102	}
10103	return (avg);
10104}
10105
10106static void
10107bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10108{
10109	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10110	int rfatt = *rfattp;
10111	int bbatt = *bbattp;
10112
10113	while (1) {
10114		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10115			break;
10116		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10117			break;
10118		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10119			break;
10120		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10121			break;
10122		if (bbatt > lo->bbatt.max) {
10123			bbatt -= 4;
10124			rfatt += 1;
10125			continue;
10126		}
10127		if (bbatt < lo->bbatt.min) {
10128			bbatt += 4;
10129			rfatt -= 1;
10130			continue;
10131		}
10132		if (rfatt > lo->rfatt.max) {
10133			rfatt -= 1;
10134			bbatt += 4;
10135			continue;
10136		}
10137		if (rfatt < lo->rfatt.min) {
10138			rfatt += 1;
10139			bbatt -= 4;
10140			continue;
10141		}
10142		break;
10143	}
10144
10145	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10146	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10147}
10148
10149static void
10150bwn_phy_lock(struct bwn_mac *mac)
10151{
10152	struct bwn_softc *sc = mac->mac_sc;
10153	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10154
10155	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10156	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10157
10158	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10159		bwn_psctl(mac, BWN_PS_AWAKE);
10160}
10161
10162static void
10163bwn_phy_unlock(struct bwn_mac *mac)
10164{
10165	struct bwn_softc *sc = mac->mac_sc;
10166	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10167
10168	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10169	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10170
10171	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10172		bwn_psctl(mac, 0);
10173}
10174
10175static void
10176bwn_rf_lock(struct bwn_mac *mac)
10177{
10178
10179	BWN_WRITE_4(mac, BWN_MACCTL,
10180	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10181	BWN_READ_4(mac, BWN_MACCTL);
10182	DELAY(10);
10183}
10184
10185static void
10186bwn_rf_unlock(struct bwn_mac *mac)
10187{
10188
10189	BWN_READ_2(mac, BWN_PHYVER);
10190	BWN_WRITE_4(mac, BWN_MACCTL,
10191	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10192}
10193
10194static struct bwn_pio_txqueue *
10195bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10196    struct bwn_pio_txpkt **pack)
10197{
10198	struct bwn_pio *pio = &mac->mac_method.pio;
10199	struct bwn_pio_txqueue *tq = NULL;
10200	unsigned int index;
10201
10202	switch (cookie & 0xf000) {
10203	case 0x1000:
10204		tq = &pio->wme[WME_AC_BK];
10205		break;
10206	case 0x2000:
10207		tq = &pio->wme[WME_AC_BE];
10208		break;
10209	case 0x3000:
10210		tq = &pio->wme[WME_AC_VI];
10211		break;
10212	case 0x4000:
10213		tq = &pio->wme[WME_AC_VO];
10214		break;
10215	case 0x5000:
10216		tq = &pio->mcast;
10217		break;
10218	}
10219	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10220	if (tq == NULL)
10221		return (NULL);
10222	index = (cookie & 0x0fff);
10223	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10224	if (index >= N(tq->tq_pkts))
10225		return (NULL);
10226	*pack = &tq->tq_pkts[index];
10227	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10228	return (tq);
10229}
10230
10231static void
10232bwn_txpwr(void *arg, int npending)
10233{
10234	struct bwn_mac *mac = arg;
10235	struct bwn_softc *sc = mac->mac_sc;
10236
10237	BWN_LOCK(sc);
10238	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10239	    mac->mac_phy.set_txpwr != NULL)
10240		mac->mac_phy.set_txpwr(mac);
10241	BWN_UNLOCK(sc);
10242}
10243
10244static void
10245bwn_task_15s(struct bwn_mac *mac)
10246{
10247	uint16_t reg;
10248
10249	if (mac->mac_fw.opensource) {
10250		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10251		if (reg) {
10252			bwn_restart(mac, "fw watchdog");
10253			return;
10254		}
10255		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10256	}
10257	if (mac->mac_phy.task_15s)
10258		mac->mac_phy.task_15s(mac);
10259
10260	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10261}
10262
10263static void
10264bwn_task_30s(struct bwn_mac *mac)
10265{
10266
10267	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10268		return;
10269	mac->mac_noise.noi_running = 1;
10270	mac->mac_noise.noi_nsamples = 0;
10271
10272	bwn_noise_gensample(mac);
10273}
10274
10275static void
10276bwn_task_60s(struct bwn_mac *mac)
10277{
10278
10279	if (mac->mac_phy.task_60s)
10280		mac->mac_phy.task_60s(mac);
10281	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10282}
10283
10284static void
10285bwn_tasks(void *arg)
10286{
10287	struct bwn_mac *mac = arg;
10288	struct bwn_softc *sc = mac->mac_sc;
10289
10290	BWN_ASSERT_LOCKED(sc);
10291	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10292		return;
10293
10294	if (mac->mac_task_state % 4 == 0)
10295		bwn_task_60s(mac);
10296	if (mac->mac_task_state % 2 == 0)
10297		bwn_task_30s(mac);
10298	bwn_task_15s(mac);
10299
10300	mac->mac_task_state++;
10301	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10302}
10303
10304static int
10305bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10306{
10307	struct bwn_softc *sc = mac->mac_sc;
10308
10309	KASSERT(a == 0, ("not support APHY\n"));
10310
10311	switch (plcp->o.raw[0] & 0xf) {
10312	case 0xb:
10313		return (BWN_OFDM_RATE_6MB);
10314	case 0xf:
10315		return (BWN_OFDM_RATE_9MB);
10316	case 0xa:
10317		return (BWN_OFDM_RATE_12MB);
10318	case 0xe:
10319		return (BWN_OFDM_RATE_18MB);
10320	case 0x9:
10321		return (BWN_OFDM_RATE_24MB);
10322	case 0xd:
10323		return (BWN_OFDM_RATE_36MB);
10324	case 0x8:
10325		return (BWN_OFDM_RATE_48MB);
10326	case 0xc:
10327		return (BWN_OFDM_RATE_54MB);
10328	}
10329	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10330	    plcp->o.raw[0] & 0xf);
10331	return (-1);
10332}
10333
10334static int
10335bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10336{
10337	struct bwn_softc *sc = mac->mac_sc;
10338
10339	switch (plcp->o.raw[0]) {
10340	case 0x0a:
10341		return (BWN_CCK_RATE_1MB);
10342	case 0x14:
10343		return (BWN_CCK_RATE_2MB);
10344	case 0x37:
10345		return (BWN_CCK_RATE_5MB);
10346	case 0x6e:
10347		return (BWN_CCK_RATE_11MB);
10348	}
10349	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10350	return (-1);
10351}
10352
10353static void
10354bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10355    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10356    int rssi, int noise)
10357{
10358	struct bwn_softc *sc = mac->mac_sc;
10359	const struct ieee80211_frame_min *wh;
10360	uint64_t tsf;
10361	uint16_t low_mactime_now;
10362
10363	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10364		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10365
10366	wh = mtod(m, const struct ieee80211_frame_min *);
10367	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10368		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10369
10370	bwn_tsf_read(mac, &tsf);
10371	low_mactime_now = tsf;
10372	tsf = tsf & ~0xffffULL;
10373	tsf += le16toh(rxhdr->mac_time);
10374	if (low_mactime_now < le16toh(rxhdr->mac_time))
10375		tsf -= 0x10000;
10376
10377	sc->sc_rx_th.wr_tsf = tsf;
10378	sc->sc_rx_th.wr_rate = rate;
10379	sc->sc_rx_th.wr_antsignal = rssi;
10380	sc->sc_rx_th.wr_antnoise = noise;
10381}
10382
10383static void
10384bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10385{
10386	uint32_t low, high;
10387
10388	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10389	    ("%s:%d: fail", __func__, __LINE__));
10390
10391	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10392	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10393	*tsf = high;
10394	*tsf <<= 32;
10395	*tsf |= low;
10396}
10397
10398static int
10399bwn_dma_attach(struct bwn_mac *mac)
10400{
10401	struct bwn_dma *dma = &mac->mac_method.dma;
10402	struct bwn_softc *sc = mac->mac_sc;
10403	bus_addr_t lowaddr = 0;
10404	int error;
10405
10406	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10407		return (0);
10408
10409	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10410
10411	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10412
10413	dma->dmatype = bwn_dma_gettype(mac);
10414	if (dma->dmatype == BWN_DMA_30BIT)
10415		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10416	else if (dma->dmatype == BWN_DMA_32BIT)
10417		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10418	else
10419		lowaddr = BUS_SPACE_MAXADDR;
10420
10421	/*
10422	 * Create top level DMA tag
10423	 */
10424	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10425			       BWN_ALIGN, 0,		/* alignment, bounds */
10426			       lowaddr,			/* lowaddr */
10427			       BUS_SPACE_MAXADDR,	/* highaddr */
10428			       NULL, NULL,		/* filter, filterarg */
10429			       MAXBSIZE,		/* maxsize */
10430			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10431			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10432			       0,			/* flags */
10433			       NULL, NULL,		/* lockfunc, lockarg */
10434			       &dma->parent_dtag);
10435	if (error) {
10436		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10437		return (error);
10438	}
10439
10440	/*
10441	 * Create TX/RX mbuf DMA tag
10442	 */
10443	error = bus_dma_tag_create(dma->parent_dtag,
10444				1,
10445				0,
10446				BUS_SPACE_MAXADDR,
10447				BUS_SPACE_MAXADDR,
10448				NULL, NULL,
10449				MCLBYTES,
10450				1,
10451				BUS_SPACE_MAXSIZE_32BIT,
10452				0,
10453				NULL, NULL,
10454				&dma->rxbuf_dtag);
10455	if (error) {
10456		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10457		goto fail0;
10458	}
10459	error = bus_dma_tag_create(dma->parent_dtag,
10460				1,
10461				0,
10462				BUS_SPACE_MAXADDR,
10463				BUS_SPACE_MAXADDR,
10464				NULL, NULL,
10465				MCLBYTES,
10466				1,
10467				BUS_SPACE_MAXSIZE_32BIT,
10468				0,
10469				NULL, NULL,
10470				&dma->txbuf_dtag);
10471	if (error) {
10472		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10473		goto fail1;
10474	}
10475
10476	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10477	if (!dma->wme[WME_AC_BK])
10478		goto fail2;
10479
10480	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10481	if (!dma->wme[WME_AC_BE])
10482		goto fail3;
10483
10484	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10485	if (!dma->wme[WME_AC_VI])
10486		goto fail4;
10487
10488	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10489	if (!dma->wme[WME_AC_VO])
10490		goto fail5;
10491
10492	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10493	if (!dma->mcast)
10494		goto fail6;
10495	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10496	if (!dma->rx)
10497		goto fail7;
10498
10499	return (error);
10500
10501fail7:	bwn_dma_ringfree(&dma->mcast);
10502fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10503fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10504fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10505fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10506fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10507fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10508fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10509	return (error);
10510}
10511
10512static struct bwn_dma_ring *
10513bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10514    uint16_t cookie, int *slot)
10515{
10516	struct bwn_dma *dma = &mac->mac_method.dma;
10517	struct bwn_dma_ring *dr;
10518	struct bwn_softc *sc = mac->mac_sc;
10519
10520	BWN_ASSERT_LOCKED(mac->mac_sc);
10521
10522	switch (cookie & 0xf000) {
10523	case 0x1000:
10524		dr = dma->wme[WME_AC_BK];
10525		break;
10526	case 0x2000:
10527		dr = dma->wme[WME_AC_BE];
10528		break;
10529	case 0x3000:
10530		dr = dma->wme[WME_AC_VI];
10531		break;
10532	case 0x4000:
10533		dr = dma->wme[WME_AC_VO];
10534		break;
10535	case 0x5000:
10536		dr = dma->mcast;
10537		break;
10538	default:
10539		dr = NULL;
10540		KASSERT(0 == 1,
10541		    ("invalid cookie value %d", cookie & 0xf000));
10542	}
10543	*slot = (cookie & 0x0fff);
10544	if (*slot < 0 || *slot >= dr->dr_numslots) {
10545		/*
10546		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10547		 * that it occurs events which have same H/W sequence numbers.
10548		 * When it's occurred just prints a WARNING msgs and ignores.
10549		 */
10550		KASSERT(status->seq == dma->lastseq,
10551		    ("%s:%d: fail", __func__, __LINE__));
10552		device_printf(sc->sc_dev,
10553		    "out of slot ranges (0 < %d < %d)\n", *slot,
10554		    dr->dr_numslots);
10555		return (NULL);
10556	}
10557	dma->lastseq = status->seq;
10558	return (dr);
10559}
10560
10561static void
10562bwn_dma_stop(struct bwn_mac *mac)
10563{
10564	struct bwn_dma *dma;
10565
10566	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10567		return;
10568	dma = &mac->mac_method.dma;
10569
10570	bwn_dma_ringstop(&dma->rx);
10571	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10572	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10573	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10574	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10575	bwn_dma_ringstop(&dma->mcast);
10576}
10577
10578static void
10579bwn_dma_ringstop(struct bwn_dma_ring **dr)
10580{
10581
10582	if (dr == NULL)
10583		return;
10584
10585	bwn_dma_cleanup(*dr);
10586}
10587
10588static void
10589bwn_pio_stop(struct bwn_mac *mac)
10590{
10591	struct bwn_pio *pio;
10592
10593	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10594		return;
10595	pio = &mac->mac_method.pio;
10596
10597	bwn_destroy_queue_tx(&pio->mcast);
10598	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10599	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10600	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10601	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10602}
10603
10604static void
10605bwn_led_attach(struct bwn_mac *mac)
10606{
10607	struct bwn_softc *sc = mac->mac_sc;
10608	const uint8_t *led_act = NULL;
10609	uint16_t val[BWN_LED_MAX];
10610	int i;
10611
10612	sc->sc_led_idle = (2350 * hz) / 1000;
10613	sc->sc_led_blink = 1;
10614
10615	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10616		if (siba_get_pci_subvendor(sc->sc_dev) ==
10617		    bwn_vendor_led_act[i].vid) {
10618			led_act = bwn_vendor_led_act[i].led_act;
10619			break;
10620		}
10621	}
10622	if (led_act == NULL)
10623		led_act = bwn_default_led_act;
10624
10625	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10626	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10627	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10628	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10629
10630	for (i = 0; i < BWN_LED_MAX; ++i) {
10631		struct bwn_led *led = &sc->sc_leds[i];
10632
10633		if (val[i] == 0xff) {
10634			led->led_act = led_act[i];
10635		} else {
10636			if (val[i] & BWN_LED_ACT_LOW)
10637				led->led_flags |= BWN_LED_F_ACTLOW;
10638			led->led_act = val[i] & BWN_LED_ACT_MASK;
10639		}
10640		led->led_mask = (1 << i);
10641
10642		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10643		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10644		    led->led_act == BWN_LED_ACT_BLINK) {
10645			led->led_flags |= BWN_LED_F_BLINK;
10646			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10647				led->led_flags |= BWN_LED_F_POLLABLE;
10648			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10649				led->led_flags |= BWN_LED_F_SLOW;
10650
10651			if (sc->sc_blink_led == NULL) {
10652				sc->sc_blink_led = led;
10653				if (led->led_flags & BWN_LED_F_SLOW)
10654					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10655			}
10656		}
10657
10658		DPRINTF(sc, BWN_DEBUG_LED,
10659		    "%dth led, act %d, lowact %d\n", i,
10660		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10661	}
10662	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10663}
10664
10665static __inline uint16_t
10666bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10667{
10668
10669	if (led->led_flags & BWN_LED_F_ACTLOW)
10670		on = !on;
10671	if (on)
10672		val |= led->led_mask;
10673	else
10674		val &= ~led->led_mask;
10675	return val;
10676}
10677
10678static void
10679bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10680{
10681	struct bwn_softc *sc = mac->mac_sc;
10682	struct ifnet *ifp = sc->sc_ifp;
10683	struct ieee80211com *ic = ifp->if_l2com;
10684	uint16_t val;
10685	int i;
10686
10687	if (nstate == IEEE80211_S_INIT) {
10688		callout_stop(&sc->sc_led_blink_ch);
10689		sc->sc_led_blinking = 0;
10690	}
10691
10692	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10693		return;
10694
10695	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10696	for (i = 0; i < BWN_LED_MAX; ++i) {
10697		struct bwn_led *led = &sc->sc_leds[i];
10698		int on;
10699
10700		if (led->led_act == BWN_LED_ACT_UNKN ||
10701		    led->led_act == BWN_LED_ACT_NULL)
10702			continue;
10703
10704		if ((led->led_flags & BWN_LED_F_BLINK) &&
10705		    nstate != IEEE80211_S_INIT)
10706			continue;
10707
10708		switch (led->led_act) {
10709		case BWN_LED_ACT_ON:    /* Always on */
10710			on = 1;
10711			break;
10712		case BWN_LED_ACT_OFF:   /* Always off */
10713		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10714			on = 0;
10715			break;
10716		default:
10717			on = 1;
10718			switch (nstate) {
10719			case IEEE80211_S_INIT:
10720				on = 0;
10721				break;
10722			case IEEE80211_S_RUN:
10723				if (led->led_act == BWN_LED_ACT_11G &&
10724				    ic->ic_curmode != IEEE80211_MODE_11G)
10725					on = 0;
10726				break;
10727			default:
10728				if (led->led_act == BWN_LED_ACT_ASSOC)
10729					on = 0;
10730				break;
10731			}
10732			break;
10733		}
10734
10735		val = bwn_led_onoff(led, val, on);
10736	}
10737	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10738}
10739
10740static void
10741bwn_led_event(struct bwn_mac *mac, int event)
10742{
10743	struct bwn_softc *sc = mac->mac_sc;
10744	struct bwn_led *led = sc->sc_blink_led;
10745	int rate;
10746
10747	if (event == BWN_LED_EVENT_POLL) {
10748		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10749			return;
10750		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10751			return;
10752	}
10753
10754	sc->sc_led_ticks = ticks;
10755	if (sc->sc_led_blinking)
10756		return;
10757
10758	switch (event) {
10759	case BWN_LED_EVENT_RX:
10760		rate = sc->sc_rx_rate;
10761		break;
10762	case BWN_LED_EVENT_TX:
10763		rate = sc->sc_tx_rate;
10764		break;
10765	case BWN_LED_EVENT_POLL:
10766		rate = 0;
10767		break;
10768	default:
10769		panic("unknown LED event %d\n", event);
10770		break;
10771	}
10772	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10773	    bwn_led_duration[rate].off_dur);
10774}
10775
10776static void
10777bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10778{
10779	struct bwn_softc *sc = mac->mac_sc;
10780	struct bwn_led *led = sc->sc_blink_led;
10781	uint16_t val;
10782
10783	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10784	val = bwn_led_onoff(led, val, 1);
10785	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10786
10787	if (led->led_flags & BWN_LED_F_SLOW) {
10788		BWN_LED_SLOWDOWN(on_dur);
10789		BWN_LED_SLOWDOWN(off_dur);
10790	}
10791
10792	sc->sc_led_blinking = 1;
10793	sc->sc_led_blink_offdur = off_dur;
10794
10795	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10796}
10797
10798static void
10799bwn_led_blink_next(void *arg)
10800{
10801	struct bwn_mac *mac = arg;
10802	struct bwn_softc *sc = mac->mac_sc;
10803	uint16_t val;
10804
10805	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10806	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10807	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10808
10809	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10810	    bwn_led_blink_end, mac);
10811}
10812
10813static void
10814bwn_led_blink_end(void *arg)
10815{
10816	struct bwn_mac *mac = arg;
10817	struct bwn_softc *sc = mac->mac_sc;
10818
10819	sc->sc_led_blinking = 0;
10820}
10821
10822static int
10823bwn_suspend(device_t dev)
10824{
10825	struct bwn_softc *sc = device_get_softc(dev);
10826
10827	bwn_stop(sc, 1);
10828	return (0);
10829}
10830
10831static int
10832bwn_resume(device_t dev)
10833{
10834	struct bwn_softc *sc = device_get_softc(dev);
10835	struct ifnet *ifp = sc->sc_ifp;
10836
10837	if (ifp->if_flags & IFF_UP)
10838		bwn_init(sc);
10839	return (0);
10840}
10841
10842static void
10843bwn_rfswitch(void *arg)
10844{
10845	struct bwn_softc *sc = arg;
10846	struct bwn_mac *mac = sc->sc_curmac;
10847	int cur = 0, prev = 0;
10848
10849	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10850	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10851
10852	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10853		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10854			& BWN_RF_HWENABLED_HI_MASK))
10855			cur = 1;
10856	} else {
10857		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10858		    & BWN_RF_HWENABLED_LO_MASK)
10859			cur = 1;
10860	}
10861
10862	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10863		prev = 1;
10864
10865	if (cur != prev) {
10866		if (cur)
10867			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10868		else
10869			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10870
10871		device_printf(sc->sc_dev,
10872		    "status of RF switch is changed to %s\n",
10873		    cur ? "ON" : "OFF");
10874		if (cur != mac->mac_phy.rf_on) {
10875			if (cur)
10876				bwn_rf_turnon(mac);
10877			else
10878				bwn_rf_turnoff(mac);
10879		}
10880	}
10881
10882	callout_schedule(&sc->sc_rfswitch_ch, hz);
10883}
10884
10885static void
10886bwn_phy_lp_init_pre(struct bwn_mac *mac)
10887{
10888	struct bwn_phy *phy = &mac->mac_phy;
10889	struct bwn_phy_lp *plp = &phy->phy_lp;
10890
10891	plp->plp_antenna = BWN_ANT_DEFAULT;
10892}
10893
10894static int
10895bwn_phy_lp_init(struct bwn_mac *mac)
10896{
10897	static const struct bwn_stxtable tables[] = {
10898		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10899		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10900		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10901		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10902		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10903		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10904		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10905		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10906		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10907		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10908		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10909		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10910		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10911		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10912		{ 2, 11, 0x40, 0, 0x0f }
10913	};
10914	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10915	struct bwn_softc *sc = mac->mac_sc;
10916	const struct bwn_stxtable *st;
10917	struct ifnet *ifp = sc->sc_ifp;
10918	struct ieee80211com *ic = ifp->if_l2com;
10919	int i, error;
10920	uint16_t tmp;
10921
10922	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10923	bwn_phy_lp_bbinit(mac);
10924
10925	/* initialize RF */
10926	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10927	DELAY(1);
10928	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10929	DELAY(1);
10930
10931	if (mac->mac_phy.rf_ver == 0x2062)
10932		bwn_phy_lp_b2062_init(mac);
10933	else {
10934		bwn_phy_lp_b2063_init(mac);
10935
10936		/* synchronize stx table. */
10937		for (i = 0; i < N(tables); i++) {
10938			st = &tables[i];
10939			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10940			tmp >>= st->st_rfshift;
10941			tmp <<= st->st_physhift;
10942			BWN_PHY_SETMASK(mac,
10943			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10944			    ~(st->st_mask << st->st_physhift), tmp);
10945		}
10946
10947		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10948		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10949	}
10950
10951	/* calibrate RC */
10952	if (mac->mac_phy.rev >= 2)
10953		bwn_phy_lp_rxcal_r2(mac);
10954	else if (!plp->plp_rccap) {
10955		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10956			bwn_phy_lp_rccal_r12(mac);
10957	} else
10958		bwn_phy_lp_set_rccap(mac);
10959
10960	error = bwn_phy_lp_switch_channel(mac, 7);
10961	if (error)
10962		device_printf(sc->sc_dev,
10963		    "failed to change channel 7 (%d)\n", error);
10964	bwn_phy_lp_txpctl_init(mac);
10965	bwn_phy_lp_calib(mac);
10966	return (0);
10967}
10968
10969static uint16_t
10970bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10971{
10972
10973	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10974	return (BWN_READ_2(mac, BWN_PHYDATA));
10975}
10976
10977static void
10978bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10979{
10980
10981	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10982	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10983}
10984
10985static void
10986bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10987    uint16_t set)
10988{
10989
10990	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10991	BWN_WRITE_2(mac, BWN_PHYDATA,
10992	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10993}
10994
10995static uint16_t
10996bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10997{
10998
10999	KASSERT(reg != 1, ("unaccessible register %d", reg));
11000	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11001		reg |= 0x100;
11002	if (mac->mac_phy.rev >= 2)
11003		reg |= 0x200;
11004	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11005	return BWN_READ_2(mac, BWN_RFDATALO);
11006}
11007
11008static void
11009bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11010{
11011
11012	KASSERT(reg != 1, ("unaccessible register %d", reg));
11013	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11014	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11015}
11016
11017static void
11018bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11019{
11020
11021	if (on) {
11022		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11023		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11024		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11025		return;
11026	}
11027
11028	if (mac->mac_phy.rev >= 2) {
11029		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11030		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11031		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11032		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11033		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11034		return;
11035	}
11036
11037	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11038	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11039	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11040	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11041}
11042
11043static int
11044bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11045{
11046	struct bwn_phy *phy = &mac->mac_phy;
11047	struct bwn_phy_lp *plp = &phy->phy_lp;
11048	int error;
11049
11050	if (phy->rf_ver == 0x2063) {
11051		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11052		if (error)
11053			return (error);
11054	} else {
11055		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11056		if (error)
11057			return (error);
11058		bwn_phy_lp_set_anafilter(mac, chan);
11059		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11060	}
11061
11062	plp->plp_chan = chan;
11063	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11064	return (0);
11065}
11066
11067static uint32_t
11068bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11069{
11070	struct bwn_softc *sc = mac->mac_sc;
11071	struct ifnet *ifp = sc->sc_ifp;
11072	struct ieee80211com *ic = ifp->if_l2com;
11073
11074	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11075}
11076
11077static void
11078bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11079{
11080	struct bwn_phy *phy = &mac->mac_phy;
11081	struct bwn_phy_lp *plp = &phy->phy_lp;
11082
11083	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11084		return;
11085
11086	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11087	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11088	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11089	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11090	plp->plp_antenna = antenna;
11091}
11092
11093static void
11094bwn_phy_lp_task_60s(struct bwn_mac *mac)
11095{
11096
11097	bwn_phy_lp_calib(mac);
11098}
11099
11100static void
11101bwn_phy_lp_readsprom(struct bwn_mac *mac)
11102{
11103	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11104	struct bwn_softc *sc = mac->mac_sc;
11105	struct ifnet *ifp = sc->sc_ifp;
11106	struct ieee80211com *ic = ifp->if_l2com;
11107
11108	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11109		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11110		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11111		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11112		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11113		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11114		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11115		return;
11116	}
11117
11118	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11119	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11120	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11121	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11122	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11123	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11124	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11125	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11126}
11127
11128static void
11129bwn_phy_lp_bbinit(struct bwn_mac *mac)
11130{
11131
11132	bwn_phy_lp_tblinit(mac);
11133	if (mac->mac_phy.rev >= 2)
11134		bwn_phy_lp_bbinit_r2(mac);
11135	else
11136		bwn_phy_lp_bbinit_r01(mac);
11137}
11138
11139static void
11140bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11141{
11142	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11143	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11144	struct bwn_softc *sc = mac->mac_sc;
11145	struct ifnet *ifp = sc->sc_ifp;
11146	struct ieee80211com *ic = ifp->if_l2com;
11147
11148	bwn_phy_lp_set_txgain(mac,
11149	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11150	bwn_phy_lp_set_bbmult(mac, 150);
11151}
11152
11153static void
11154bwn_phy_lp_calib(struct bwn_mac *mac)
11155{
11156	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11157	struct bwn_softc *sc = mac->mac_sc;
11158	struct ifnet *ifp = sc->sc_ifp;
11159	struct ieee80211com *ic = ifp->if_l2com;
11160	const struct bwn_rxcompco *rc = NULL;
11161	struct bwn_txgain ogain;
11162	int i, omode, oafeovr, orf, obbmult;
11163	uint8_t mode, fc = 0;
11164
11165	if (plp->plp_chanfullcal != plp->plp_chan) {
11166		plp->plp_chanfullcal = plp->plp_chan;
11167		fc = 1;
11168	}
11169
11170	bwn_mac_suspend(mac);
11171
11172	/* BlueTooth Coexistance Override */
11173	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11174	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11175
11176	if (mac->mac_phy.rev >= 2)
11177		bwn_phy_lp_digflt_save(mac);
11178	bwn_phy_lp_get_txpctlmode(mac);
11179	mode = plp->plp_txpctlmode;
11180	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11181	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11182		bwn_phy_lp_bugfix(mac);
11183	if (mac->mac_phy.rev >= 2 && fc == 1) {
11184		bwn_phy_lp_get_txpctlmode(mac);
11185		omode = plp->plp_txpctlmode;
11186		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11187		if (oafeovr)
11188			ogain = bwn_phy_lp_get_txgain(mac);
11189		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11190		obbmult = bwn_phy_lp_get_bbmult(mac);
11191		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11192		if (oafeovr)
11193			bwn_phy_lp_set_txgain(mac, &ogain);
11194		bwn_phy_lp_set_bbmult(mac, obbmult);
11195		bwn_phy_lp_set_txpctlmode(mac, omode);
11196		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11197	}
11198	bwn_phy_lp_set_txpctlmode(mac, mode);
11199	if (mac->mac_phy.rev >= 2)
11200		bwn_phy_lp_digflt_restore(mac);
11201
11202	/* do RX IQ Calculation; assumes that noise is true. */
11203	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11204		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11205			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11206				rc = &bwn_rxcompco_5354[i];
11207		}
11208	} else if (mac->mac_phy.rev >= 2)
11209		rc = &bwn_rxcompco_r2;
11210	else {
11211		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11212			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11213				rc = &bwn_rxcompco_r12[i];
11214		}
11215	}
11216	if (rc == NULL)
11217		goto fail;
11218
11219	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11220	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11221
11222	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11223
11224	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11225		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11226		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11227	} else {
11228		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11229		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11230	}
11231
11232	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11233	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11234	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11235	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11236	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11237	bwn_phy_lp_set_deaf(mac, 0);
11238	/* XXX no checking return value? */
11239	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11240	bwn_phy_lp_clear_deaf(mac, 0);
11241	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11242	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11243	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11244
11245	/* disable RX GAIN override. */
11246	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11247	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11248	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11249	if (mac->mac_phy.rev >= 2) {
11250		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11251		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11252			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11253			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11254		}
11255	} else {
11256		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11257	}
11258
11259	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11260	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11261fail:
11262	bwn_mac_enable(mac);
11263}
11264
11265static void
11266bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11267{
11268
11269	if (on) {
11270		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11271		return;
11272	}
11273
11274	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11275	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11276}
11277
11278static int
11279bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11280{
11281	static const struct bwn_b206x_chan *bc = NULL;
11282	struct bwn_softc *sc = mac->mac_sc;
11283	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11284	    tmp[6];
11285	uint16_t old, scale, tmp16;
11286	int i, div;
11287
11288	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11289		if (bwn_b2063_chantable[i].bc_chan == chan) {
11290			bc = &bwn_b2063_chantable[i];
11291			break;
11292		}
11293	}
11294	if (bc == NULL)
11295		return (EINVAL);
11296
11297	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11298	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11299	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11300	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11301	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11302	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11303	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11304	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11305	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11306	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11307	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11308	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11309
11310	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11311	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11312
11313	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11314	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11315	freqref = freqxtal * 3;
11316	div = (freqxtal <= 26000000 ? 1 : 2);
11317	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11318	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11319		999999) / 1000000) + 1;
11320
11321	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11322	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11323	    0xfff8, timeout >> 2);
11324	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11325	    0xff9f,timeout << 5);
11326	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11327
11328	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11329	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11330	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11331
11332	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11333	    (timeoutref + 1)) - 1;
11334	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11335	    0xf0, count >> 8);
11336	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11337
11338	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11339	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11340	while (tmp[1] >= freqref) {
11341		tmp[0]++;
11342		tmp[1] -= freqref;
11343	}
11344	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11345	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11346	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11347	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11348	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11349
11350	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11351	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11352	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11353	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11354
11355	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11356	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11357
11358	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11359		scale = 1;
11360		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11361	} else {
11362		scale = 0;
11363		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11364	}
11365	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11366	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11367
11368	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11369	    (scale + 1);
11370	if (tmp[5] > 150)
11371		tmp[5] = 0;
11372
11373	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11374	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11375
11376	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11377	if (freqxtal > 26000000)
11378		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11379	else
11380		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11381
11382	if (val[0] == 45)
11383		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11384	else
11385		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11386
11387	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11388	DELAY(1);
11389	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11390
11391	/* VCO Calibration */
11392	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11393	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11394	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11395	DELAY(1);
11396	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11397	DELAY(1);
11398	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11399	DELAY(1);
11400	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11401	DELAY(300);
11402	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11403
11404	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11405	return (0);
11406}
11407
11408static int
11409bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11410{
11411	struct bwn_softc *sc = mac->mac_sc;
11412	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11413	const struct bwn_b206x_chan *bc = NULL;
11414	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11415	uint32_t tmp[9];
11416	int i;
11417
11418	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11419		if (bwn_b2062_chantable[i].bc_chan == chan) {
11420			bc = &bwn_b2062_chantable[i];
11421			break;
11422		}
11423	}
11424
11425	if (bc == NULL)
11426		return (EINVAL);
11427
11428	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11429	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11430	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11431	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11432	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11433	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11434	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11435	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11436	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11437	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11438
11439	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11440	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11441	bwn_phy_lp_b2062_reset_pllbias(mac);
11442	tmp[0] = freqxtal / 1000;
11443	tmp[1] = plp->plp_div * 1000;
11444	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11445	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11446		tmp[2] *= 2;
11447	tmp[3] = 48 * tmp[0];
11448	tmp[5] = tmp[2] / tmp[3];
11449	tmp[6] = tmp[2] % tmp[3];
11450	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11451	tmp[4] = tmp[6] * 0x100;
11452	tmp[5] = tmp[4] / tmp[3];
11453	tmp[6] = tmp[4] % tmp[3];
11454	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11455	tmp[4] = tmp[6] * 0x100;
11456	tmp[5] = tmp[4] / tmp[3];
11457	tmp[6] = tmp[4] % tmp[3];
11458	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11459	tmp[4] = tmp[6] * 0x100;
11460	tmp[5] = tmp[4] / tmp[3];
11461	tmp[6] = tmp[4] % tmp[3];
11462	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11463	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11464	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11465	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11466	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11467	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11468
11469	bwn_phy_lp_b2062_vco_calib(mac);
11470	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11471		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11472		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11473		bwn_phy_lp_b2062_reset_pllbias(mac);
11474		bwn_phy_lp_b2062_vco_calib(mac);
11475		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11476			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11477			return (EIO);
11478		}
11479	}
11480	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11481	return (0);
11482}
11483
11484static void
11485bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11486{
11487	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11488	uint16_t tmp = (channel == 14);
11489
11490	if (mac->mac_phy.rev < 2) {
11491		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11492		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11493			bwn_phy_lp_set_rccap(mac);
11494		return;
11495	}
11496
11497	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11498}
11499
11500static void
11501bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11502{
11503	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11504	struct bwn_softc *sc = mac->mac_sc;
11505	struct ifnet *ifp = sc->sc_ifp;
11506	struct ieee80211com *ic = ifp->if_l2com;
11507	uint16_t iso, tmp[3];
11508
11509	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11510
11511	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11512		iso = plp->plp_txisoband_m;
11513	else if (freq <= 5320)
11514		iso = plp->plp_txisoband_l;
11515	else if (freq <= 5700)
11516		iso = plp->plp_txisoband_m;
11517	else
11518		iso = plp->plp_txisoband_h;
11519
11520	tmp[0] = ((iso - 26) / 12) << 12;
11521	tmp[1] = tmp[0] + 0x1000;
11522	tmp[2] = tmp[0] + 0x2000;
11523
11524	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11525	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11526}
11527
11528static void
11529bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11530{
11531	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11532	int i;
11533	static const uint16_t addr[] = {
11534		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11535		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11536		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11537		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11538		BWN_PHY_OFDM(0xcf),
11539	};
11540	static const uint16_t val[] = {
11541		0xde5e, 0xe832, 0xe331, 0x4d26,
11542		0x0026, 0x1420, 0x0020, 0xfe08,
11543		0x0008,
11544	};
11545
11546	for (i = 0; i < N(addr); i++) {
11547		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11548		BWN_PHY_WRITE(mac, addr[i], val[i]);
11549	}
11550}
11551
11552static void
11553bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11554{
11555	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11556	struct bwn_softc *sc = mac->mac_sc;
11557	uint16_t ctl;
11558
11559	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11560	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11561	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11562		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11563		break;
11564	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11565		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11566		break;
11567	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11568		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11569		break;
11570	default:
11571		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11572		device_printf(sc->sc_dev, "unknown command mode\n");
11573		break;
11574	}
11575}
11576
11577static void
11578bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11579{
11580	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11581	uint16_t ctl;
11582	uint8_t old;
11583
11584	bwn_phy_lp_get_txpctlmode(mac);
11585	old = plp->plp_txpctlmode;
11586	if (old == mode)
11587		return;
11588	plp->plp_txpctlmode = mode;
11589
11590	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11591		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11592		    plp->plp_tssiidx);
11593		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11594		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11595
11596		/* disable TX GAIN override */
11597		if (mac->mac_phy.rev < 2)
11598			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11599		else {
11600			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11601			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11602		}
11603		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11604
11605		plp->plp_txpwridx = -1;
11606	}
11607	if (mac->mac_phy.rev >= 2) {
11608		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11609			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11610		else
11611			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11612	}
11613
11614	/* writes TX Power Control mode */
11615	switch (plp->plp_txpctlmode) {
11616	case BWN_PHYLP_TXPCTL_OFF:
11617		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11618		break;
11619	case BWN_PHYLP_TXPCTL_ON_HW:
11620		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11621		break;
11622	case BWN_PHYLP_TXPCTL_ON_SW:
11623		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11624		break;
11625	default:
11626		ctl = 0;
11627		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11628	}
11629	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11630	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11631}
11632
11633static void
11634bwn_phy_lp_bugfix(struct bwn_mac *mac)
11635{
11636	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11637	struct bwn_softc *sc = mac->mac_sc;
11638	const unsigned int size = 256;
11639	struct bwn_txgain tg;
11640	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11641	uint16_t tssinpt, tssiidx, value[2];
11642	uint8_t mode;
11643	int8_t txpwridx;
11644
11645	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11646	    M_NOWAIT | M_ZERO);
11647	if (tabs == NULL) {
11648		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11649		return;
11650	}
11651
11652	bwn_phy_lp_get_txpctlmode(mac);
11653	mode = plp->plp_txpctlmode;
11654	txpwridx = plp->plp_txpwridx;
11655	tssinpt = plp->plp_tssinpt;
11656	tssiidx = plp->plp_tssiidx;
11657
11658	bwn_tab_read_multi(mac,
11659	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11660	    BWN_TAB_4(7, 0x140), size, tabs);
11661
11662	bwn_phy_lp_tblinit(mac);
11663	bwn_phy_lp_bbinit(mac);
11664	bwn_phy_lp_txpctl_init(mac);
11665	bwn_phy_lp_rf_onoff(mac, 1);
11666	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11667
11668	bwn_tab_write_multi(mac,
11669	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11670	    BWN_TAB_4(7, 0x140), size, tabs);
11671
11672	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11673	plp->plp_tssinpt = tssinpt;
11674	plp->plp_tssiidx = tssiidx;
11675	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11676	if (txpwridx != -1) {
11677		/* set TX power by index */
11678		plp->plp_txpwridx = txpwridx;
11679		bwn_phy_lp_get_txpctlmode(mac);
11680		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11681			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11682		if (mac->mac_phy.rev >= 2) {
11683			rxcomp = bwn_tab_read(mac,
11684			    BWN_TAB_4(7, txpwridx + 320));
11685			txgain = bwn_tab_read(mac,
11686			    BWN_TAB_4(7, txpwridx + 192));
11687			tg.tg_pad = (txgain >> 16) & 0xff;
11688			tg.tg_gm = txgain & 0xff;
11689			tg.tg_pga = (txgain >> 8) & 0xff;
11690			tg.tg_dac = (rxcomp >> 28) & 0xff;
11691			bwn_phy_lp_set_txgain(mac, &tg);
11692		} else {
11693			rxcomp = bwn_tab_read(mac,
11694			    BWN_TAB_4(10, txpwridx + 320));
11695			txgain = bwn_tab_read(mac,
11696			    BWN_TAB_4(10, txpwridx + 192));
11697			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11698			    0xf800, (txgain >> 4) & 0x7fff);
11699			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11700			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11701		}
11702		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11703
11704		/* set TX IQCC */
11705		value[0] = (rxcomp >> 10) & 0x3ff;
11706		value[1] = rxcomp & 0x3ff;
11707		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11708
11709		coeff = bwn_tab_read(mac,
11710		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11711		    BWN_TAB_4(10, txpwridx + 448));
11712		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11713		if (mac->mac_phy.rev >= 2) {
11714			rfpwr = bwn_tab_read(mac,
11715			    BWN_TAB_4(7, txpwridx + 576));
11716			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11717			    rfpwr & 0xffff);
11718		}
11719		bwn_phy_lp_set_txgain_override(mac);
11720	}
11721	if (plp->plp_rccap)
11722		bwn_phy_lp_set_rccap(mac);
11723	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11724	bwn_phy_lp_set_txpctlmode(mac, mode);
11725	free(tabs, M_DEVBUF);
11726}
11727
11728static void
11729bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11730{
11731	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11732	int i;
11733	static const uint16_t addr[] = {
11734		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11735		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11736		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11737		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11738		BWN_PHY_OFDM(0xcf),
11739	};
11740
11741	for (i = 0; i < N(addr); i++)
11742		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11743}
11744
11745static void
11746bwn_phy_lp_tblinit(struct bwn_mac *mac)
11747{
11748	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11749
11750	if (mac->mac_phy.rev < 2) {
11751		bwn_phy_lp_tblinit_r01(mac);
11752		bwn_phy_lp_tblinit_txgain(mac);
11753		bwn_phy_lp_set_gaintbl(mac, freq);
11754		return;
11755	}
11756
11757	bwn_phy_lp_tblinit_r2(mac);
11758	bwn_phy_lp_tblinit_txgain(mac);
11759}
11760
11761struct bwn_wpair {
11762	uint16_t		reg;
11763	uint16_t		value;
11764};
11765
11766struct bwn_smpair {
11767	uint16_t		offset;
11768	uint16_t		mask;
11769	uint16_t		set;
11770};
11771
11772static void
11773bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11774{
11775	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11776	struct bwn_softc *sc = mac->mac_sc;
11777	struct ifnet *ifp = sc->sc_ifp;
11778	struct ieee80211com *ic = ifp->if_l2com;
11779	static const struct bwn_wpair v1[] = {
11780		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11781		{ BWN_PHY_AFE_CTL, 0x8800 },
11782		{ BWN_PHY_AFE_CTL_OVR, 0 },
11783		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11784		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11785		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11786		{ BWN_PHY_OFDM(0xf9), 0 },
11787		{ BWN_PHY_TR_LOOKUP_1, 0 }
11788	};
11789	static const struct bwn_smpair v2[] = {
11790		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11791		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11792		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11793		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11794		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11795	};
11796	static const struct bwn_smpair v3[] = {
11797		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11798		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11799		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11800		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11801		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11802		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11803		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11804		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11805		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11806		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11807
11808	};
11809	int i;
11810
11811	for (i = 0; i < N(v1); i++)
11812		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11813	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11814	for (i = 0; i < N(v2); i++)
11815		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11816
11817	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11818	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11819	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11820	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11821		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11822		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11823	} else {
11824		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11825	}
11826	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11827	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11828	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11829	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11830	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11831	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11832	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11833	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11834	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11835	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11836	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11837	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11838	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11839		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11840		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11841	} else {
11842		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11843		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11844	}
11845	for (i = 0; i < N(v3); i++)
11846		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11847	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11848	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11849		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11850		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11851	}
11852
11853	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11854		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11855		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11856		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11857		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11858		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11859		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11860	} else
11861		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11862
11863	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11864	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11865	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11866	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11867	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11868	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11869	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11870	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11871	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11872
11873	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11874	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11875		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11876		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11877		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11878	}
11879
11880	bwn_phy_lp_digflt_save(mac);
11881}
11882
11883static void
11884bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11885{
11886	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11887	struct bwn_softc *sc = mac->mac_sc;
11888	struct ifnet *ifp = sc->sc_ifp;
11889	struct ieee80211com *ic = ifp->if_l2com;
11890	static const struct bwn_smpair v1[] = {
11891		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11892		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11893		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11894		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11895		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11896		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11897		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11898	};
11899	static const struct bwn_smpair v2[] = {
11900		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11901		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11902		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11903		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11904		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11905		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11906		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11907		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11908		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11909		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11910		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11911		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11912		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11913		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11914		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11915		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11916	};
11917	static const struct bwn_smpair v3[] = {
11918		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11919		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11920		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11921		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11922		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11923		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11924		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11925		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11926	};
11927	static const struct bwn_smpair v4[] = {
11928		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11929		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11930		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11931		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11932		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11933		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11934		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11935		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11936	};
11937	static const struct bwn_smpair v5[] = {
11938		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11939		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11940		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11941		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11942		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11943		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11944		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11945		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11946	};
11947	int i;
11948	uint16_t tmp, tmp2;
11949
11950	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11951	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11952	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11953	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11954	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11955	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11956	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11957	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11958	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11959	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11960	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11961	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11962	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11963	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11964	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11965	for (i = 0; i < N(v1); i++)
11966		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11967	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11968	    0xff00, plp->plp_rxpwroffset);
11969	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11970	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11971	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11972		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11973		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11974		if (mac->mac_phy.rev == 0)
11975			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11976			    0xffcf, 0x0010);
11977		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11978	} else {
11979		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11980		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11981		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11982	}
11983	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11984	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11985	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11986		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11987	else
11988		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11989	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11990	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11991	    0xfff9, (plp->plp_bxarch << 1));
11992	if (mac->mac_phy.rev == 1 &&
11993	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11994		for (i = 0; i < N(v2); i++)
11995			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11996			    v2[i].set);
11997	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11998	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11999	    ((mac->mac_phy.rev == 0) &&
12000	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
12001		for (i = 0; i < N(v3); i++)
12002			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12003			    v3[i].set);
12004	} else if (mac->mac_phy.rev == 1 ||
12005		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
12006		for (i = 0; i < N(v4); i++)
12007			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12008			    v4[i].set);
12009	} else {
12010		for (i = 0; i < N(v5); i++)
12011			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12012			    v5[i].set);
12013	}
12014	if (mac->mac_phy.rev == 1 &&
12015	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
12016		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12017		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12018		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12019		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12020	}
12021	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
12022	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
12023	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
12024		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12025		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12026		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12027		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12028	}
12029	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12030		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12031		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12032		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12033		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12034		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12035		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12036		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12037		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12038	} else {
12039		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12040		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12041	}
12042	if (mac->mac_phy.rev == 1) {
12043		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12044		tmp2 = (tmp & 0x03e0) >> 5;
12045		tmp2 |= tmp2 << 5;
12046		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12047		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12048		tmp2 = (tmp & 0x1f00) >> 8;
12049		tmp2 |= tmp2 << 5;
12050		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12051		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12052		tmp2 = tmp & 0x00ff;
12053		tmp2 |= tmp << 8;
12054		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12055	}
12056}
12057
12058struct bwn_b2062_freq {
12059	uint16_t		freq;
12060	uint8_t			value[6];
12061};
12062
12063static void
12064bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12065{
12066#define	CALC_CTL7(freq, div)						\
12067	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12068#define	CALC_CTL18(freq, div)						\
12069	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12070#define	CALC_CTL19(freq, div)						\
12071	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12072	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12073	struct bwn_softc *sc = mac->mac_sc;
12074	struct ifnet *ifp = sc->sc_ifp;
12075	struct ieee80211com *ic = ifp->if_l2com;
12076	static const struct bwn_b2062_freq freqdata_tab[] = {
12077		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12078		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12079		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12080		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12081		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12082		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12083	};
12084	static const struct bwn_wpair v1[] = {
12085		{ BWN_B2062_N_TXCTL3, 0 },
12086		{ BWN_B2062_N_TXCTL4, 0 },
12087		{ BWN_B2062_N_TXCTL5, 0 },
12088		{ BWN_B2062_N_TXCTL6, 0 },
12089		{ BWN_B2062_N_PDNCTL0, 0x40 },
12090		{ BWN_B2062_N_PDNCTL0, 0 },
12091		{ BWN_B2062_N_CALIB_TS, 0x10 },
12092		{ BWN_B2062_N_CALIB_TS, 0 }
12093	};
12094	const struct bwn_b2062_freq *f = NULL;
12095	uint32_t xtalfreq, ref;
12096	unsigned int i;
12097
12098	bwn_phy_lp_b2062_tblinit(mac);
12099
12100	for (i = 0; i < N(v1); i++)
12101		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12102	if (mac->mac_phy.rev > 0)
12103		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12104		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12105	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12106		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12107	else
12108		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12109
12110	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12111	    ("%s:%d: fail", __func__, __LINE__));
12112	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12113	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12114
12115	if (xtalfreq <= 30000000) {
12116		plp->plp_div = 1;
12117		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12118	} else {
12119		plp->plp_div = 2;
12120		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12121	}
12122
12123	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12124	    CALC_CTL7(xtalfreq, plp->plp_div));
12125	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12126	    CALC_CTL18(xtalfreq, plp->plp_div));
12127	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12128	    CALC_CTL19(xtalfreq, plp->plp_div));
12129
12130	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12131	ref &= 0xffff;
12132	for (i = 0; i < N(freqdata_tab); i++) {
12133		if (ref < freqdata_tab[i].freq) {
12134			f = &freqdata_tab[i];
12135			break;
12136		}
12137	}
12138	if (f == NULL)
12139		f = &freqdata_tab[N(freqdata_tab) - 1];
12140	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12141	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12142	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12143	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12144	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12145	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12146#undef CALC_CTL7
12147#undef CALC_CTL18
12148#undef CALC_CTL19
12149}
12150
12151static void
12152bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12153{
12154
12155	bwn_phy_lp_b2063_tblinit(mac);
12156	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12157	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12158	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12159	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12160	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12161	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12162	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12163	if (mac->mac_phy.rev == 2) {
12164		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12165		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12166		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12167	} else {
12168		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12169		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12170	}
12171}
12172
12173static void
12174bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12175{
12176	struct bwn_softc *sc = mac->mac_sc;
12177	static const struct bwn_wpair v1[] = {
12178		{ BWN_B2063_RX_BB_SP8, 0x0 },
12179		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12180		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12181		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12182		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12183		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12184		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12185		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12186	};
12187	static const struct bwn_wpair v2[] = {
12188		{ BWN_B2063_TX_BB_SP3, 0x0 },
12189		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12190		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12191		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12192		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12193	};
12194	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12195	int i;
12196	uint8_t tmp;
12197
12198	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12199
12200	for (i = 0; i < 2; i++)
12201		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12202	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12203	for (i = 2; i < N(v1); i++)
12204		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12205	for (i = 0; i < 10000; i++) {
12206		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12207			break;
12208		DELAY(1000);
12209	}
12210
12211	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12212		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12213
12214	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12215
12216	for (i = 0; i < N(v2); i++)
12217		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12218	if (freqxtal == 24000000) {
12219		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12220		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12221	} else {
12222		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12223		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12224	}
12225	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12226	for (i = 0; i < 10000; i++) {
12227		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12228			break;
12229		DELAY(1000);
12230	}
12231	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12232		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12233	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12234}
12235
12236static void
12237bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12238{
12239	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12240	struct bwn_softc *sc = mac->mac_sc;
12241	struct bwn_phy_lp_iq_est ie;
12242	struct bwn_txgain tx_gains;
12243	static const uint32_t pwrtbl[21] = {
12244		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12245		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12246		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12247		0x0004c, 0x0002c, 0x0001a,
12248	};
12249	uint32_t npwr, ipwr, sqpwr, tmp;
12250	int loopback, i, j, sum, error;
12251	uint16_t save[7];
12252	uint8_t txo, bbmult, txpctlmode;
12253
12254	error = bwn_phy_lp_switch_channel(mac, 7);
12255	if (error)
12256		device_printf(sc->sc_dev,
12257		    "failed to change channel to 7 (%d)\n", error);
12258	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12259	bbmult = bwn_phy_lp_get_bbmult(mac);
12260	if (txo)
12261		tx_gains = bwn_phy_lp_get_txgain(mac);
12262
12263	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12264	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12265	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12266	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12267	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12268	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12269	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12270
12271	bwn_phy_lp_get_txpctlmode(mac);
12272	txpctlmode = plp->plp_txpctlmode;
12273	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12274
12275	/* disable CRS */
12276	bwn_phy_lp_set_deaf(mac, 1);
12277	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12278	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12279	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12280	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12281	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12282	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12283	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12284	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12285	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12286	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12287	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12288	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12289	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12290	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12291	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12292	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12293	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12294	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12295	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12296	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12297	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12298	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12299	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12300	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12301
12302	loopback = bwn_phy_lp_loopback(mac);
12303	if (loopback == -1)
12304		goto done;
12305	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12306	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12307	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12308	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12309	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12310
12311	tmp = 0;
12312	memset(&ie, 0, sizeof(ie));
12313	for (i = 128; i <= 159; i++) {
12314		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12315		sum = 0;
12316		for (j = 5; j <= 25; j++) {
12317			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12318			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12319				goto done;
12320			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12321			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12322			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12323			    12);
12324			sum += ((ipwr - npwr) * (ipwr - npwr));
12325			if ((i == 128) || (sum < tmp)) {
12326				plp->plp_rccap = i;
12327				tmp = sum;
12328			}
12329		}
12330	}
12331	bwn_phy_lp_ddfs_turnoff(mac);
12332done:
12333	/* restore CRS */
12334	bwn_phy_lp_clear_deaf(mac, 1);
12335	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12336	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12337
12338	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12339	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12340	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12341	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12342	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12343	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12344	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12345
12346	bwn_phy_lp_set_bbmult(mac, bbmult);
12347	if (txo)
12348		bwn_phy_lp_set_txgain(mac, &tx_gains);
12349	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12350	if (plp->plp_rccap)
12351		bwn_phy_lp_set_rccap(mac);
12352}
12353
12354static void
12355bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12356{
12357	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12358	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12359
12360	if (mac->mac_phy.rev == 1)
12361		rc_cap = MIN(rc_cap + 5, 15);
12362
12363	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12364	    MAX(plp->plp_rccap - 4, 0x80));
12365	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12366	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12367	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12368}
12369
12370static uint32_t
12371bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12372{
12373	uint32_t i, q, r;
12374
12375	if (div == 0)
12376		return (0);
12377
12378	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12379		q <<= 1;
12380		if (r << 1 >= div) {
12381			q++;
12382			r = (r << 1) - div;
12383		}
12384	}
12385	if (r << 1 >= div)
12386		q++;
12387	return (q);
12388}
12389
12390static void
12391bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12392{
12393	struct bwn_softc *sc = mac->mac_sc;
12394
12395	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12396	DELAY(20);
12397	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12398		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12399		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12400	} else {
12401		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12402	}
12403	DELAY(5);
12404}
12405
12406static void
12407bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12408{
12409
12410	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12411	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12412	DELAY(200);
12413}
12414
12415static void
12416bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12417{
12418#define	FLAG_A	0x01
12419#define	FLAG_G	0x02
12420	struct bwn_softc *sc = mac->mac_sc;
12421	struct ifnet *ifp = sc->sc_ifp;
12422	struct ieee80211com *ic = ifp->if_l2com;
12423	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12424		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12425		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12426		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12427		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12428		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12429		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12430		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12431		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12432		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12433		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12434		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12435		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12436		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12437		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12438		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12439		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12440		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12441		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12442		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12443		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12444		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12445		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12446		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12447		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12448		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12449		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12450		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12451		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12452		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12453		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12454		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12455		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12456		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12457		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12458		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12459		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12460		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12461		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12462		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12463		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12464		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12465		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12466		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12467		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12468		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12469		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12470		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12471	};
12472	const struct bwn_b206x_rfinit_entry *br;
12473	unsigned int i;
12474
12475	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12476		br = &bwn_b2062_init_tab[i];
12477		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12478			if (br->br_flags & FLAG_G)
12479				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12480		} else {
12481			if (br->br_flags & FLAG_A)
12482				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12483		}
12484	}
12485#undef FLAG_A
12486#undef FLAG_B
12487}
12488
12489static void
12490bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12491{
12492#define	FLAG_A	0x01
12493#define	FLAG_G	0x02
12494	struct bwn_softc *sc = mac->mac_sc;
12495	struct ifnet *ifp = sc->sc_ifp;
12496	struct ieee80211com *ic = ifp->if_l2com;
12497	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12498		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12499		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12500		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12501		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12502		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12503		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12504		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12505		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12506		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12507		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12508		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12509		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12510		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12511		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12512		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12513		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12514		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12515		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12516		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12517		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12518		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12519		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12520		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12521		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12522		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12523		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12524		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12525		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12526		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12527		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12528		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12529		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12530		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12531		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12532		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12533		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12534		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12535		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12536		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12537		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12538		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12539		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12540	};
12541	const struct bwn_b206x_rfinit_entry *br;
12542	unsigned int i;
12543
12544	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12545		br = &bwn_b2063_init_tab[i];
12546		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12547			if (br->br_flags & FLAG_G)
12548				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12549		} else {
12550			if (br->br_flags & FLAG_A)
12551				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12552		}
12553	}
12554#undef FLAG_A
12555#undef FLAG_B
12556}
12557
12558static void
12559bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12560    int count, void *_data)
12561{
12562	unsigned int i;
12563	uint32_t offset, type;
12564	uint8_t *data = _data;
12565
12566	type = BWN_TAB_GETTYPE(typenoffset);
12567	offset = BWN_TAB_GETOFFSET(typenoffset);
12568	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12569
12570	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12571
12572	for (i = 0; i < count; i++) {
12573		switch (type) {
12574		case BWN_TAB_8BIT:
12575			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12576			data++;
12577			break;
12578		case BWN_TAB_16BIT:
12579			*((uint16_t *)data) = BWN_PHY_READ(mac,
12580			    BWN_PHY_TABLEDATALO);
12581			data += 2;
12582			break;
12583		case BWN_TAB_32BIT:
12584			*((uint32_t *)data) = BWN_PHY_READ(mac,
12585			    BWN_PHY_TABLEDATAHI);
12586			*((uint32_t *)data) <<= 16;
12587			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12588			    BWN_PHY_TABLEDATALO);
12589			data += 4;
12590			break;
12591		default:
12592			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12593		}
12594	}
12595}
12596
12597static void
12598bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12599    int count, const void *_data)
12600{
12601	uint32_t offset, type, value;
12602	const uint8_t *data = _data;
12603	unsigned int i;
12604
12605	type = BWN_TAB_GETTYPE(typenoffset);
12606	offset = BWN_TAB_GETOFFSET(typenoffset);
12607	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12608
12609	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12610
12611	for (i = 0; i < count; i++) {
12612		switch (type) {
12613		case BWN_TAB_8BIT:
12614			value = *data;
12615			data++;
12616			KASSERT(!(value & ~0xff),
12617			    ("%s:%d: fail", __func__, __LINE__));
12618			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12619			break;
12620		case BWN_TAB_16BIT:
12621			value = *((const uint16_t *)data);
12622			data += 2;
12623			KASSERT(!(value & ~0xffff),
12624			    ("%s:%d: fail", __func__, __LINE__));
12625			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12626			break;
12627		case BWN_TAB_32BIT:
12628			value = *((const uint32_t *)data);
12629			data += 4;
12630			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12631			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12632			break;
12633		default:
12634			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12635		}
12636	}
12637}
12638
12639static struct bwn_txgain
12640bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12641{
12642	struct bwn_txgain tg;
12643	uint16_t tmp;
12644
12645	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12646	if (mac->mac_phy.rev < 2) {
12647		tmp = BWN_PHY_READ(mac,
12648		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12649		tg.tg_gm = tmp & 0x0007;
12650		tg.tg_pga = (tmp & 0x0078) >> 3;
12651		tg.tg_pad = (tmp & 0x780) >> 7;
12652		return (tg);
12653	}
12654
12655	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12656	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12657	tg.tg_gm = tmp & 0xff;
12658	tg.tg_pga = (tmp >> 8) & 0xff;
12659	return (tg);
12660}
12661
12662static uint8_t
12663bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12664{
12665
12666	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12667}
12668
12669static void
12670bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12671{
12672	uint16_t pa;
12673
12674	if (mac->mac_phy.rev < 2) {
12675		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12676		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12677		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12678		bwn_phy_lp_set_txgain_override(mac);
12679		return;
12680	}
12681
12682	pa = bwn_phy_lp_get_pa_gain(mac);
12683	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12684	    (tg->tg_pga << 8) | tg->tg_gm);
12685	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12686	    tg->tg_pad | (pa << 6));
12687	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12688	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12689	    tg->tg_pad | (pa << 8));
12690	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12691	bwn_phy_lp_set_txgain_override(mac);
12692}
12693
12694static void
12695bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12696{
12697
12698	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12699}
12700
12701static void
12702bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12703{
12704	uint16_t trsw = (tx << 1) | rx;
12705
12706	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12707	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12708}
12709
12710static void
12711bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12712{
12713	struct bwn_softc *sc = mac->mac_sc;
12714	struct ifnet *ifp = sc->sc_ifp;
12715	struct ieee80211com *ic = ifp->if_l2com;
12716	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12717
12718	if (mac->mac_phy.rev < 2) {
12719		trsw = gain & 0x1;
12720		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12721		ext_lna = (gain & 2) >> 1;
12722
12723		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12724		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12725		    0xfbff, ext_lna << 10);
12726		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12727		    0xf7ff, ext_lna << 11);
12728		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12729	} else {
12730		low_gain = gain & 0xffff;
12731		high_gain = (gain >> 16) & 0xf;
12732		ext_lna = (gain >> 21) & 0x1;
12733		trsw = ~(gain >> 20) & 0x1;
12734
12735		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12736		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12737		    0xfdff, ext_lna << 9);
12738		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12739		    0xfbff, ext_lna << 10);
12740		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12741		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12742		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12743			tmp = (gain >> 2) & 0x3;
12744			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12745			    0xe7ff, tmp<<11);
12746			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12747			    tmp << 3);
12748		}
12749	}
12750
12751	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12752	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12753	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12754	if (mac->mac_phy.rev >= 2) {
12755		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12756		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12757			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12758			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12759		}
12760		return;
12761	}
12762	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12763}
12764
12765static void
12766bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12767{
12768	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12769
12770	if (user)
12771		plp->plp_crsusr_off = 1;
12772	else
12773		plp->plp_crssys_off = 1;
12774
12775	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12776}
12777
12778static void
12779bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12780{
12781	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12782	struct bwn_softc *sc = mac->mac_sc;
12783	struct ifnet *ifp = sc->sc_ifp;
12784	struct ieee80211com *ic = ifp->if_l2com;
12785
12786	if (user)
12787		plp->plp_crsusr_off = 0;
12788	else
12789		plp->plp_crssys_off = 0;
12790
12791	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12792		return;
12793
12794	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12795		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12796	else
12797		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12798}
12799
12800static unsigned int
12801bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12802{
12803	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12804	static uint8_t sqrt_table[256] = {
12805		10, 14, 17, 20, 22, 24, 26, 28,
12806		30, 31, 33, 34, 36, 37, 38, 40,
12807		41, 42, 43, 44, 45, 46, 47, 48,
12808		50, 50, 51, 52, 53, 54, 55, 56,
12809		57, 58, 59, 60, 60, 61, 62, 63,
12810		64, 64, 65, 66, 67, 67, 68, 69,
12811		70, 70, 71, 72, 72, 73, 74, 74,
12812		75, 76, 76, 77, 78, 78, 79, 80,
12813		80, 81, 81, 82, 83, 83, 84, 84,
12814		85, 86, 86, 87, 87, 88, 88, 89,
12815		90, 90, 91, 91, 92, 92, 93, 93,
12816		94, 94, 95, 95, 96, 96, 97, 97,
12817		98, 98, 99, 100, 100, 100, 101, 101,
12818		102, 102, 103, 103, 104, 104, 105, 105,
12819		106, 106, 107, 107, 108, 108, 109, 109,
12820		110, 110, 110, 111, 111, 112, 112, 113,
12821		113, 114, 114, 114, 115, 115, 116, 116,
12822		117, 117, 117, 118, 118, 119, 119, 120,
12823		120, 120, 121, 121, 122, 122, 122, 123,
12824		123, 124, 124, 124, 125, 125, 126, 126,
12825		126, 127, 127, 128, 128, 128, 129, 129,
12826		130, 130, 130, 131, 131, 131, 132, 132,
12827		133, 133, 133, 134, 134, 134, 135, 135,
12828		136, 136, 136, 137, 137, 137, 138, 138,
12829		138, 139, 139, 140, 140, 140, 141, 141,
12830		141, 142, 142, 142, 143, 143, 143, 144,
12831		144, 144, 145, 145, 145, 146, 146, 146,
12832		147, 147, 147, 148, 148, 148, 149, 149,
12833		150, 150, 150, 150, 151, 151, 151, 152,
12834		152, 152, 153, 153, 153, 154, 154, 154,
12835		155, 155, 155, 156, 156, 156, 157, 157,
12836		157, 158, 158, 158, 159, 159, 159, 160
12837	};
12838
12839	if (x == 0)
12840		return (0);
12841	if (x >= 256) {
12842		unsigned int tmp;
12843
12844		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12845			/* do nothing */ ;
12846		return (tmp);
12847	}
12848	return (sqrt_table[x - 1] / 10);
12849}
12850
12851static int
12852bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12853{
12854#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12855	int _t;								\
12856	_t = _x - 20;							\
12857	if (_t >= 0) {							\
12858		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12859	} else {							\
12860		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12861	}								\
12862} while (0)
12863#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12864	int _t;								\
12865	_t = _x - 11;							\
12866	if (_t >= 0)							\
12867		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12868	else								\
12869		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12870} while (0)
12871	struct bwn_phy_lp_iq_est ie;
12872	uint16_t v0, v1;
12873	int tmp[2], ret;
12874
12875	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12876	v0 = v1 >> 8;
12877	v1 |= 0xff;
12878
12879	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12880	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12881
12882	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12883	if (ret == 0)
12884		goto done;
12885
12886	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12887		ret = 0;
12888		goto done;
12889	}
12890
12891	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12892	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12893
12894	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12895	v0 = tmp[0] >> 3;
12896	v1 = tmp[1] >> 4;
12897done:
12898	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12899	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12900	return ret;
12901#undef CALC_COEFF
12902#undef CALC_COEFF2
12903}
12904
12905static void
12906bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12907{
12908	static const uint16_t noisescale[] = {
12909		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12910		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12911		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12912		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12913		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12914	};
12915	static const uint16_t crsgainnft[] = {
12916		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12917		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12918		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12919		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12920		0x013d,
12921	};
12922	static const uint16_t filterctl[] = {
12923		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12924		0xff53, 0x0127,
12925	};
12926	static const uint32_t psctl[] = {
12927		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12928		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12929		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12930		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12931		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12932		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12933		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12934		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12935	};
12936	static const uint16_t ofdmcckgain_r0[] = {
12937		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12938		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12939		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12940		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12941		0x755d,
12942	};
12943	static const uint16_t ofdmcckgain_r1[] = {
12944		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12945		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12946		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12947		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12948		0x755d,
12949	};
12950	static const uint16_t gaindelta[] = {
12951		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12952		0x0000,
12953	};
12954	static const uint32_t txpwrctl[] = {
12955		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12956		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12957		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12958		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12959		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12960		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12961		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12962		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12963		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12964		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12965		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12966		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12967		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12968		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12969		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12970		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12971		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12972		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12973		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12974		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12975		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12976		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12977		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12978		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12979		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12980		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12981		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12982		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12983		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12984		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12985		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12986		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12987		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12988		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12989		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12990		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12991		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12992		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12993		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12994		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12995		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12996		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12997		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12998		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12999		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13000		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13001		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13002		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13003		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13004		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13005		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13006		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13007		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13008		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13009		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13010		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13011		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13012		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13013		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13014		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13015		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13016		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13017		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13018		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13019		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13020		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13021		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13022		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13023		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13024		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13025		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13026		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13027		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13028		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13029		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13030		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13031		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13032		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13033		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13034		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13035		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13036		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13037		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13038		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13039		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13040		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13041		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13042		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13043		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13044		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13045		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13046		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13047		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13048		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13049		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13050		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13051		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13052		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13053		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13054		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13055		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13056		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13057		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13058		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13059		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13060		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13061		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13062		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13063		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13064		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13065		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13066		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13067		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13068		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13069		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13070		0x00000702,
13071	};
13072
13073	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13074
13075	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13076	    bwn_tab_sigsq_tbl);
13077	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13078	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13079	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13080	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13081	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13082	    bwn_tab_pllfrac_tbl);
13083	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13084	    bwn_tabl_iqlocal_tbl);
13085	if (mac->mac_phy.rev == 0) {
13086		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13087		    ofdmcckgain_r0);
13088		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13089		    ofdmcckgain_r0);
13090	} else {
13091		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13092		    ofdmcckgain_r1);
13093		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13094		    ofdmcckgain_r1);
13095	}
13096	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13097	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13098}
13099
13100static void
13101bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13102{
13103	struct bwn_softc *sc = mac->mac_sc;
13104	int i;
13105	static const uint16_t noisescale[] = {
13106		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13107		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13108		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13109		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13110		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13111		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13112		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13113	};
13114	static const uint32_t filterctl[] = {
13115		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13116		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13117	};
13118	static const uint32_t psctl[] = {
13119		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13120		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13121		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13122		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13123	};
13124	static const uint32_t gainidx[] = {
13125		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13126		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13127		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13128		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13129		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13130		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13131		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13132		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13133		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13134		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13135		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13136		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13137		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13138		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13139		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13140		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13141		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13142		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13143		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13144		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13145		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13146		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13147		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13148		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13149		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13150		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13151		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13152		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13153		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13154		0x0000001a, 0x64ca55ad, 0x0000001a
13155	};
13156	static const uint16_t auxgainidx[] = {
13157		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13159		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13160		0x0004, 0x0016
13161	};
13162	static const uint16_t swctl[] = {
13163		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13164		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13165		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13166		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13167		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13168		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13169		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13170		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13171	};
13172	static const uint8_t hf[] = {
13173		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13174		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13175	};
13176	static const uint32_t gainval[] = {
13177		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13178		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13179		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13180		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13181		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13182		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13183		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13184		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13185		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13186		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13187		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13188		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13189		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13190		0x000000f1, 0x00000000, 0x00000000
13191	};
13192	static const uint16_t gain[] = {
13193		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13194		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13195		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13196		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13197		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13198		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13199		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13200		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13201		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13202		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13203		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13204		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13205	};
13206	static const uint32_t papdeps[] = {
13207		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13208		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13209		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13210		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13211		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13212		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13213		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13214		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13215		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13216		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13217		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13218		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13219		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13220	};
13221	static const uint32_t papdmult[] = {
13222		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13223		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13224		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13225		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13226		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13227		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13228		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13229		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13230		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13231		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13232		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13233		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13234		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13235	};
13236	static const uint32_t gainidx_a0[] = {
13237		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13238		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13239		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13240		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13241		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13242		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13243		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13244		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13245		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13246		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13247		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13248		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13249		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13250	};
13251	static const uint16_t auxgainidx_a0[] = {
13252		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13253		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13254		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13255		0x0002, 0x0014
13256	};
13257	static const uint32_t gainval_a0[] = {
13258		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13259		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13260		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13261		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13262		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13263		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13264		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13265		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13266		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13267		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13268		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13269		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13270		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13271		0x000000f7, 0x00000000, 0x00000000
13272	};
13273	static const uint16_t gain_a0[] = {
13274		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13275		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13276		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13277		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13278		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13279		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13280		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13281		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13282		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13283		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13284		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13285		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13286	};
13287
13288	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13289
13290	for (i = 0; i < 704; i++)
13291		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13292
13293	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13294	    bwn_tab_sigsq_tbl);
13295	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13296	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13297	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13298	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13299	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13300	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13301	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13302	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13303	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13304	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13305	    bwn_tab_pllfrac_tbl);
13306	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13307	    bwn_tabl_iqlocal_tbl);
13308	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13309	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13310
13311	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13312	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13313		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13314		    gainidx_a0);
13315		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13316		    auxgainidx_a0);
13317		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13318		    gainval_a0);
13319		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13320	}
13321}
13322
13323static void
13324bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13325{
13326	struct bwn_softc *sc = mac->mac_sc;
13327	struct ifnet *ifp = sc->sc_ifp;
13328	struct ieee80211com *ic = ifp->if_l2com;
13329	static struct bwn_txgain_entry txgain_r2[] = {
13330		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13331		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13332		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13333		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13334		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13335		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13336		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13337		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13338		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13339		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13340		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13341		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13342		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13343		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13344		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13345		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13346		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13347		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13348		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13349		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13350		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13351		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13352		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13353		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13354		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13355		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13356		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13357		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13358		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13359		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13360		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13361		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13362		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13363		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13364		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13365		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13366		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13367		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13368		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13369		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13370		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13371		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13372		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13373		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13374		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13375		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13376		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13377		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13378		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13379		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13380		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13381		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13382		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13383		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13384		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13385		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13386		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13387		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13388		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13389		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13390		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13391		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13392		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13393		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13394	};
13395	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13396		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13397		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13398		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13399		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13400		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13401		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13402		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13403		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13404		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13405		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13406		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13407		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13408		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13409		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13410		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13411		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13412		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13413		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13414		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13415		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13416		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13417		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13418		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13419		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13420		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13421		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13422		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13423		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13424		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13425		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13426		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13427		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13428		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13429		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13430		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13431		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13432		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13433		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13434		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13435		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13436		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13437		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13438		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13439		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13440		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13441		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13442		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13443		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13444		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13445		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13446		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13447		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13448		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13449		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13450		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13451		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13452		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13453		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13454		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13455		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13456		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13457		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13458		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13459		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13460	};
13461	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13462		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13463		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13464		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13465		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13466		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13467		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13468		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13469		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13470		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13471		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13472		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13473		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13474		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13475		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13476		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13477		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13478		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13479		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13480		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13481		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13482		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13483		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13484		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13485		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13486		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13487		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13488		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13489		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13490		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13491		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13492		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13493		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13494		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13495		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13496		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13497		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13498		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13499		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13500		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13501		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13502		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13503		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13504		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13505		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13506		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13507		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13508		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13509		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13510		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13511		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13512		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13513		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13514		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13515		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13516		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13517		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13518		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13519		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13520		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13521		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13522		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13523		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13524		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13525		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13526	};
13527	static struct bwn_txgain_entry txgain_r0[] = {
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, 13, 0, 68 },
13547		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13548		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13549		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13550		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13551		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13552		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13553		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13554		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13555		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13556		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13557		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13558		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13559		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13560		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13561		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13562		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13563		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13564		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13565		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13566		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13567		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13568		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13569		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13570		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13571		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13572		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13573		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13574		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13575		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13576		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13577		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13578		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13579		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13580		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13581		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13582		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13583		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13584		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13585		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13586		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13587		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13588		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13589		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13590		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13591		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13592	};
13593	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13594		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13595		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13596		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13597		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13598		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13599		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13600		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13601		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13602		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13603		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13604		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13605		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13606		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13607		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13608		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13609		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13610		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13611		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13612		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13613		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13614		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13615		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13616		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13617		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13618		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13619		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13620		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13621		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13622		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13623		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13624		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13625		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13626		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13627		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13628		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13629		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13630		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13631		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13632		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13633		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13634		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13635		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13636		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13637		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13638		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13639		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13640		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13641		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13642		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13643		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13644		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13645		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13646		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13647		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13648		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13649		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13650		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13651		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13652		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13653		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13654		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13655		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13656		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13657		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13658	};
13659	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13660		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13661		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13662		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13663		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13664		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13665		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13666		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13667		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13668		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13669		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13670		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13671		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13672		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13673		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13674		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13675		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13676		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13677		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13678		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13679		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13680		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13681		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13682		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13683		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13684		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13685		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13686		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13687		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13688		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13689		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13690		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13691		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13692		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13693		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13694		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13695		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13696		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13697		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13698		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13699		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13700		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13701		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13702		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13703		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13704		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13705		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13706		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13707		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13708		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13709		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13710		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13711		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13712		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13713		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13714		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13715		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13716		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13717		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13718		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13719		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13720		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13721		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13722		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13723		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13724	};
13725	static struct bwn_txgain_entry txgain_r1[] = {
13726		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13727		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13728		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13729		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13730		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13731		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13732		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13733		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13734		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13735		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13736		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13737		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13738		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13739		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13740		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13741		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13742		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13743		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13744		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13745		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13746		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13747		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13748		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13749		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13750		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13751		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13752		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13753		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13754		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13755		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13756		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13757		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13758		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13759		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13760		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13761		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13762		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13763		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13764		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13765		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13766		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13767		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13768		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13769		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13770		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13771		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13772		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13773		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13774		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13775		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13776		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13777		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13778		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13779		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13780		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13781		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13782		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13783		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13784		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13785		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13786		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13787		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13788		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13789		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13790		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13791		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13792		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13793		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13794		{ 7, 11, 6, 0, 71 }
13795	};
13796	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13797		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13798		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13799		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13800		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13801		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13802		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13803		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13804		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13805		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13806		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13807		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13808		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13809		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13810		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13811		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13812		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13813		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13814		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13815		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13816		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13817		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13818		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13819		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13820		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13821		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13822		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13823		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13824		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13825		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13826		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13827		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13828		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13829		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13830		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13831		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13832		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13833		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13834		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13835		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13836		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13837		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13838		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13839		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13840		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13841		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13842		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13843		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13844		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13845		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13846		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13847		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13848		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13849		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13850		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13851		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13852		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13853		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13854		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13855		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13856		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13857		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13858		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13859		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13860		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13861	};
13862	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13863		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13864		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13865		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13866		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13867		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13868		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13869		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13870		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13871		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13872		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13873		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13874		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13875		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13876		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13877		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13878		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13879		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13880		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13881		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13882		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13883		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13884		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13885		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13886		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13887		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13888		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13889		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13890		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13891		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13892		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13893		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13894		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13895		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13896		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13897		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13898		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13899		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13900		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13901		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13902		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13903		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13904		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13905		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13906		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13907		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13908		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13909		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13910		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13911		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13912		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13913		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13914		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13915		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13916		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13917		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13918		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13919		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13920		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13921		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13922		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13923		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13924		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13925		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13926		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13927	};
13928
13929	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13930		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13931			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13932		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13933			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13934			    txgain_2ghz_r2);
13935		else
13936			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13937			    txgain_5ghz_r2);
13938		return;
13939	}
13940
13941	if (mac->mac_phy.rev == 0) {
13942		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13943		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13944			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13945		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13946			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13947			    txgain_2ghz_r0);
13948		else
13949			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13950			    txgain_5ghz_r0);
13951		return;
13952	}
13953
13954	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13955	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13956		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13957	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13958		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13959	else
13960		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13961}
13962
13963static void
13964bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13965{
13966	uint32_t offset, type;
13967
13968	type = BWN_TAB_GETTYPE(typeoffset);
13969	offset = BWN_TAB_GETOFFSET(typeoffset);
13970	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13971
13972	switch (type) {
13973	case BWN_TAB_8BIT:
13974		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13975		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13976		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13977		break;
13978	case BWN_TAB_16BIT:
13979		KASSERT(!(value & ~0xffff),
13980		    ("%s:%d: fail", __func__, __LINE__));
13981		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13982		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13983		break;
13984	case BWN_TAB_32BIT:
13985		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13986		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13987		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13988		break;
13989	default:
13990		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13991	}
13992}
13993
13994static int
13995bwn_phy_lp_loopback(struct bwn_mac *mac)
13996{
13997	struct bwn_phy_lp_iq_est ie;
13998	int i, index = -1;
13999	uint32_t tmp;
14000
14001	memset(&ie, 0, sizeof(ie));
14002
14003	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14004	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14005	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14006	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14007	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14008	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14009	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14010	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14011	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14012	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14013	for (i = 0; i < 32; i++) {
14014		bwn_phy_lp_set_rxgain_idx(mac, i);
14015		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14016		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14017			continue;
14018		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14019		if ((tmp > 4000) && (tmp < 10000)) {
14020			index = i;
14021			break;
14022		}
14023	}
14024	bwn_phy_lp_ddfs_turnoff(mac);
14025	return (index);
14026}
14027
14028static void
14029bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14030{
14031
14032	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14033}
14034
14035static void
14036bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14037    int incr1, int incr2, int scale_idx)
14038{
14039
14040	bwn_phy_lp_ddfs_turnoff(mac);
14041	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14042	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14043	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14044	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14045	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14046	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14047	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14048	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14049	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14050	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14051}
14052
14053static uint8_t
14054bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14055    struct bwn_phy_lp_iq_est *ie)
14056{
14057	int i;
14058
14059	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14060	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14061	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14062	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14063	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14064
14065	for (i = 0; i < 500; i++) {
14066		if (!(BWN_PHY_READ(mac,
14067		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14068			break;
14069		DELAY(1000);
14070	}
14071	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14072		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14073		return 0;
14074	}
14075
14076	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14077	ie->ie_iqprod <<= 16;
14078	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14079	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14080	ie->ie_ipwr <<= 16;
14081	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14082	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14083	ie->ie_qpwr <<= 16;
14084	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14085
14086	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14087	return 1;
14088}
14089
14090static uint32_t
14091bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14092{
14093	uint32_t offset, type, value;
14094
14095	type = BWN_TAB_GETTYPE(typeoffset);
14096	offset = BWN_TAB_GETOFFSET(typeoffset);
14097	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14098
14099	switch (type) {
14100	case BWN_TAB_8BIT:
14101		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14102		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14103		break;
14104	case BWN_TAB_16BIT:
14105		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14106		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14107		break;
14108	case BWN_TAB_32BIT:
14109		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14110		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14111		value <<= 16;
14112		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14113		break;
14114	default:
14115		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14116		value = 0;
14117	}
14118
14119	return (value);
14120}
14121
14122static void
14123bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14124{
14125
14126	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14127	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14128}
14129
14130static void
14131bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14132{
14133	uint16_t ctl;
14134
14135	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14136	ctl |= dac << 7;
14137	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14138}
14139
14140static void
14141bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14142{
14143
14144	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14145	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14146}
14147
14148static void
14149bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14150{
14151
14152	if (mac->mac_phy.rev < 2)
14153		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14154	else {
14155		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14156		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14157	}
14158	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14159}
14160
14161static uint16_t
14162bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14163{
14164
14165	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14166}
14167
14168static uint8_t
14169bwn_nbits(int32_t val)
14170{
14171	uint32_t tmp;
14172	uint8_t nbits = 0;
14173
14174	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14175		nbits++;
14176	return (nbits);
14177}
14178
14179static void
14180bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14181    struct bwn_txgain_entry *table)
14182{
14183	int i;
14184
14185	for (i = offset; i < count; i++)
14186		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14187}
14188
14189static void
14190bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14191    struct bwn_txgain_entry data)
14192{
14193
14194	if (mac->mac_phy.rev >= 2)
14195		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14196	else
14197		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14198}
14199
14200static void
14201bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14202    struct bwn_txgain_entry te)
14203{
14204	struct bwn_softc *sc = mac->mac_sc;
14205	struct ifnet *ifp = sc->sc_ifp;
14206	struct ieee80211com *ic = ifp->if_l2com;
14207	uint32_t tmp;
14208
14209	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14210
14211	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14212	if (mac->mac_phy.rev >= 3) {
14213		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14214		    (0x10 << 24) : (0x70 << 24));
14215	} else {
14216		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14217		    (0x14 << 24) : (0x7f << 24));
14218	}
14219	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14220	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14221	    te.te_bbmult << 20 | te.te_dac << 28);
14222}
14223
14224static void
14225bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14226    struct bwn_txgain_entry te)
14227{
14228
14229	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14230
14231	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14232	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14233	    te.te_dac);
14234	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14235}
14236
14237static void
14238bwn_sysctl_node(struct bwn_softc *sc)
14239{
14240	device_t dev = sc->sc_dev;
14241	struct bwn_mac *mac;
14242	struct bwn_stats *stats;
14243
14244	/* XXX assume that count of MAC is only 1. */
14245
14246	if ((mac = sc->sc_curmac) == NULL)
14247		return;
14248	stats = &mac->mac_stats;
14249
14250	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14251	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14252	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14253	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14254	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14255	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14256	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14257	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14258	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14259
14260#ifdef BWN_DEBUG
14261	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14262	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14263	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14264#endif
14265}
14266
14267static device_method_t bwn_methods[] = {
14268	/* Device interface */
14269	DEVMETHOD(device_probe,		bwn_probe),
14270	DEVMETHOD(device_attach,	bwn_attach),
14271	DEVMETHOD(device_detach,	bwn_detach),
14272	DEVMETHOD(device_suspend,	bwn_suspend),
14273	DEVMETHOD(device_resume,	bwn_resume),
14274	KOBJMETHOD_END
14275};
14276static driver_t bwn_driver = {
14277	"bwn",
14278	bwn_methods,
14279	sizeof(struct bwn_softc)
14280};
14281static devclass_t bwn_devclass;
14282DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14283MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14284MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14285MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14286MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14287