if_bwn.c revision 204436
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 204436 2010-02-27 23:04:29Z weongyo $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_amrr.h>
71#include <net80211/ieee80211_phy.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77
78/*
79 * Tunable & sysctl variables.
80 */
81
82#ifdef BWN_DEBUG
83static	int bwn_debug = 0;
84SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85    "Broadcom debugging printfs");
86TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87enum {
88	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106	BWN_DEBUG_ANY		= 0xffffffff
107};
108#define	DPRINTF(sc, m, fmt, ...) do {			\
109	if (sc->sc_debug & (m))				\
110		printf(fmt, __VA_ARGS__);		\
111} while (0)
112#else
113#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114#endif
115
116static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118    "uses Bad Frames Preemption");
119static int	bwn_bluetooth = 1;
120SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121    "turns on Bluetooth Coexistence");
122static int	bwn_hwpctl = 0;
123SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124    "uses H/W power control");
125static int	bwn_msi_disable = 0;		/* MSI disabled  */
126TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127static int	bwn_usedma = 1;
128SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129    "uses DMA");
130TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131static int	bwn_wme = 1;
132SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133    "uses WME support");
134
135static int	bwn_attach_pre(struct bwn_softc *);
136static int	bwn_attach_post(struct bwn_softc *);
137static void	bwn_sprom_bugfixes(struct siba_softc *);
138static void	bwn_init(void *);
139static int	bwn_init_locked(struct bwn_softc *);
140static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141static void	bwn_start(struct ifnet *);
142static int	bwn_attach_core(struct bwn_mac *);
143static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144static int	bwn_phy_getinfo(struct bwn_mac *, int);
145static int	bwn_chiptest(struct bwn_mac *);
146static int	bwn_setup_channels(struct bwn_mac *, int, int);
147static int	bwn_phy_g_attach(struct bwn_mac *);
148static void	bwn_phy_g_detach(struct bwn_mac *);
149static void	bwn_phy_g_init_pre(struct bwn_mac *);
150static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151static int	bwn_phy_g_init(struct bwn_mac *);
152static void	bwn_phy_g_exit(struct bwn_mac *);
153static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155		    uint16_t);
156static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158		    uint16_t);
159static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164static int	bwn_phy_g_im(struct bwn_mac *, int);
165static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167static void	bwn_phy_g_task_15s(struct bwn_mac *);
168static void	bwn_phy_g_task_60s(struct bwn_mac *);
169static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173		    uint16_t);
174static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176		    uint32_t);
177static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178		    uint16_t);
179static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180		    const struct bwn_channelinfo *, int);
181static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182		    const struct ieee80211_bpf_params *);
183static void	bwn_newassoc(struct ieee80211_node *, int);
184static void	bwn_updateslot(struct ifnet *);
185static void	bwn_update_promisc(struct ifnet *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189		    const uint8_t [IEEE80211_ADDR_LEN]);
190static void	bwn_wme_clear(struct bwn_softc *);
191static void	bwn_wme_load(struct bwn_mac *);
192static void	bwn_wme_loadparams(struct bwn_mac *,
193		    const struct wmeParams *, uint16_t);
194static void	bwn_node_cleanup(struct ieee80211_node *);
195static void	bwn_scan_start(struct ieee80211com *);
196static void	bwn_scan_end(struct ieee80211com *);
197static void	bwn_set_channel(struct ieee80211com *);
198static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199		    const char [IFNAMSIZ], int, int,
200		    int, const uint8_t [IEEE80211_ADDR_LEN],
201		    const uint8_t [IEEE80211_ADDR_LEN]);
202static void	bwn_vap_delete(struct ieee80211vap *);
203static void	bwn_stop(struct bwn_softc *, int);
204static void	bwn_stop_locked(struct bwn_softc *, int);
205static int	bwn_core_init(struct bwn_mac *);
206static void	bwn_core_start(struct bwn_mac *);
207static void	bwn_core_exit(struct bwn_mac *);
208static void	bwn_fix_imcfglobug(struct bwn_mac *);
209static void	bwn_bt_disable(struct bwn_mac *);
210static int	bwn_chip_init(struct bwn_mac *);
211static uint64_t	bwn_hf_read(struct bwn_mac *);
212static void	bwn_hf_write(struct bwn_mac *, uint64_t);
213static void	bwn_set_txretry(struct bwn_mac *, int, int);
214static void	bwn_rate_init(struct bwn_mac *);
215static void	bwn_set_phytxctl(struct bwn_mac *);
216static void	bwn_spu_setdelay(struct bwn_mac *, int);
217static void	bwn_bt_enable(struct bwn_mac *);
218static void	bwn_set_macaddr(struct bwn_mac *);
219static void	bwn_crypt_init(struct bwn_mac *);
220static void	bwn_chip_exit(struct bwn_mac *);
221static int	bwn_fw_fillinfo(struct bwn_mac *);
222static int	bwn_fw_loaducode(struct bwn_mac *);
223static int	bwn_gpio_init(struct bwn_mac *);
224static int	bwn_fw_loadinitvals(struct bwn_mac *);
225static int	bwn_phy_init(struct bwn_mac *);
226static void	bwn_set_txantenna(struct bwn_mac *, int);
227static void	bwn_set_opmode(struct bwn_mac *);
228static void	bwn_gpio_cleanup(struct bwn_mac *);
229static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
230static uint8_t	bwn_plcp_getcck(const uint8_t);
231static uint8_t	bwn_plcp_getofdm(const uint8_t);
232static void	bwn_pio_init(struct bwn_mac *);
233static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
234static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
235		    int);
236static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
237		    struct bwn_pio_rxqueue *, int);
238static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
239static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
240		    uint16_t);
241static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
242static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
243static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
244static void	bwn_pio_handle_txeof(struct bwn_mac *,
245		    const struct bwn_txstatus *);
246static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
247static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
248static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
249		    uint16_t);
250static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
251		    uint32_t);
252static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
253		    struct mbuf *);
254static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
255static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
256		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
257static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
258		    uint16_t, uint32_t);
259static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
260		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
261static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
262		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
263static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
264		    uint16_t, struct bwn_pio_txpkt **);
265static void	bwn_dma_init(struct bwn_mac *);
266static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
267static int	bwn_dma_mask2type(uint64_t);
268static uint64_t	bwn_dma_mask(struct bwn_mac *);
269static uint16_t	bwn_dma_base(int, int);
270static void	bwn_dma_ringfree(struct bwn_dma_ring **);
271static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
272		    int, struct bwn_dmadesc_generic **,
273		    struct bwn_dmadesc_meta **);
274static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
275		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
276		    int, int);
277static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
278static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
279static void	bwn_dma_32_resume(struct bwn_dma_ring *);
280static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
281static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
282static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
283		    int, struct bwn_dmadesc_generic **,
284		    struct bwn_dmadesc_meta **);
285static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
286		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
287		    int, int);
288static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
289static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
290static void	bwn_dma_64_resume(struct bwn_dma_ring *);
291static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
292static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
293static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
294static void	bwn_dma_setup(struct bwn_dma_ring *);
295static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
296static void	bwn_dma_cleanup(struct bwn_dma_ring *);
297static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
298static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
299static void	bwn_dma_rx(struct bwn_dma_ring *);
300static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
301static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
302		    struct bwn_dmadesc_meta *);
303static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
304static int	bwn_dma_gettype(struct bwn_mac *);
305static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
306static int	bwn_dma_freeslot(struct bwn_dma_ring *);
307static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
308static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
309static int	bwn_dma_newbuf(struct bwn_dma_ring *,
310		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
311		    int);
312static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
313		    bus_size_t, int);
314static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
315static void	bwn_dma_handle_txeof(struct bwn_mac *,
316		    const struct bwn_txstatus *);
317static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
318		    struct mbuf *);
319static int	bwn_dma_getslot(struct bwn_dma_ring *);
320static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
321		    uint8_t);
322static int	bwn_dma_attach(struct bwn_mac *);
323static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
324		    int, int, int);
325static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
326		    const struct bwn_txstatus *, uint16_t, int *);
327static void	bwn_dma_free(struct bwn_mac *);
328static void	bwn_phy_g_init_sub(struct bwn_mac *);
329static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
330static void	bwn_phy_init_b5(struct bwn_mac *);
331static void	bwn_phy_init_b6(struct bwn_mac *);
332static void	bwn_phy_init_a(struct bwn_mac *);
333static void	bwn_loopback_calcgain(struct bwn_mac *);
334static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
335static void	bwn_lo_g_init(struct bwn_mac *);
336static void	bwn_lo_g_adjust(struct bwn_mac *);
337static void	bwn_lo_get_powervector(struct bwn_mac *);
338static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
339		    const struct bwn_bbatt *, const struct bwn_rfatt *);
340static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
341static void	bwn_phy_hwpctl_init(struct bwn_mac *);
342static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
343static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
344		    const struct bwn_bbatt *, const struct bwn_rfatt *,
345		    uint8_t);
346static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
347static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
348static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
349static void	bwn_wa_init(struct bwn_mac *);
350static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
351		    uint16_t);
352static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
353static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
354		    uint32_t);
355static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
356		    uint16_t);
357static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
358static void	bwn_mac_suspend(struct bwn_mac *);
359static void	bwn_mac_enable(struct bwn_mac *);
360static void	bwn_psctl(struct bwn_mac *, uint32_t);
361static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
362static void	bwn_nrssi_offset(struct bwn_mac *);
363static void	bwn_nrssi_threshold(struct bwn_mac *);
364static void	bwn_nrssi_slope_11g(struct bwn_mac *);
365static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
366		    int16_t);
367static void	bwn_set_original_gains(struct bwn_mac *);
368static void	bwn_hwpctl_early_init(struct bwn_mac *);
369static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
370static uint16_t	bwn_phy_g_chan2freq(uint8_t);
371static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
372static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
373		    const char *, struct bwn_fwfile *);
374static void	bwn_release_firmware(struct bwn_mac *);
375static void	bwn_do_release_fw(struct bwn_fwfile *);
376static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
377static int	bwn_fwinitvals_write(struct bwn_mac *,
378		    const struct bwn_fwinitvals *, size_t, size_t);
379static int	bwn_switch_channel(struct bwn_mac *, int);
380static uint16_t	bwn_ant2phy(int);
381static void	bwn_mac_write_bssid(struct bwn_mac *);
382static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
383		    const uint8_t *);
384static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
385		    const uint8_t *, size_t, const uint8_t *);
386static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
387		    const uint8_t *);
388static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
389		    const uint8_t *);
390static void	bwn_phy_exit(struct bwn_mac *);
391static void	bwn_core_stop(struct bwn_mac *);
392static int	bwn_switch_band(struct bwn_softc *,
393		    struct ieee80211_channel *);
394static void	bwn_phy_reset(struct bwn_mac *);
395static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
396static void	bwn_set_pretbtt(struct bwn_mac *);
397static int	bwn_intr(void *);
398static void	bwn_intrtask(void *, int);
399static void	bwn_restart(struct bwn_mac *, const char *);
400static void	bwn_intr_ucode_debug(struct bwn_mac *);
401static void	bwn_intr_tbtt_indication(struct bwn_mac *);
402static void	bwn_intr_atim_end(struct bwn_mac *);
403static void	bwn_intr_beacon(struct bwn_mac *);
404static void	bwn_intr_pmq(struct bwn_mac *);
405static void	bwn_intr_noise(struct bwn_mac *);
406static void	bwn_intr_txeof(struct bwn_mac *);
407static void	bwn_hwreset(void *, int);
408static void	bwn_handle_fwpanic(struct bwn_mac *);
409static void	bwn_load_beacon0(struct bwn_mac *);
410static void	bwn_load_beacon1(struct bwn_mac *);
411static uint32_t	bwn_jssi_read(struct bwn_mac *);
412static void	bwn_noise_gensample(struct bwn_mac *);
413static void	bwn_handle_txeof(struct bwn_mac *,
414		    const struct bwn_txstatus *);
415static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
416static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
417static void	bwn_start_locked(struct ifnet *);
418static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
419		    struct mbuf *);
420static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
421static int	bwn_set_txhdr(struct bwn_mac *,
422		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
423		    uint16_t);
424static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
425		    const uint8_t);
426static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
427static uint8_t	bwn_get_fbrate(uint8_t);
428static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
429static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
430static void	bwn_phy_lock(struct bwn_mac *);
431static void	bwn_phy_unlock(struct bwn_mac *);
432static void	bwn_rf_lock(struct bwn_mac *);
433static void	bwn_rf_unlock(struct bwn_mac *);
434static void	bwn_txpwr(void *, int);
435static void	bwn_tasks(void *);
436static void	bwn_task_15s(struct bwn_mac *);
437static void	bwn_task_30s(struct bwn_mac *);
438static void	bwn_task_60s(struct bwn_mac *);
439static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
440		    uint8_t);
441static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
442static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
443		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
444		    int, int);
445static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
446static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
447static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
448static void	bwn_watchdog(void *);
449static void	bwn_dma_stop(struct bwn_mac *);
450static void	bwn_pio_stop(struct bwn_mac *);
451static void	bwn_dma_ringstop(struct bwn_dma_ring **);
452static void	bwn_led_attach(struct bwn_mac *);
453static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
454static void	bwn_led_event(struct bwn_mac *, int);
455static void	bwn_led_blink_start(struct bwn_mac *, int, int);
456static void	bwn_led_blink_next(void *);
457static void	bwn_led_blink_end(void *);
458static void	bwn_rfswitch(void *);
459static void	bwn_rf_turnon(struct bwn_mac *);
460static void	bwn_rf_turnoff(struct bwn_mac *);
461static void	bwn_phy_lp_init_pre(struct bwn_mac *);
462static int	bwn_phy_lp_init(struct bwn_mac *);
463static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
464static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
465static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
466		    uint16_t);
467static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
468static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
469static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
470static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
471static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
472static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
473static void	bwn_phy_lp_task_60s(struct bwn_mac *);
474static void	bwn_phy_lp_readsprom(struct bwn_mac *);
475static void	bwn_phy_lp_bbinit(struct bwn_mac *);
476static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
477static void	bwn_phy_lp_calib(struct bwn_mac *);
478static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
479static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
480static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
481static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
482static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
483static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
484static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
485static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
486static void	bwn_phy_lp_bugfix(struct bwn_mac *);
487static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
488static void	bwn_phy_lp_tblinit(struct bwn_mac *);
489static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
490static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
491static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
492static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
493static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
494static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
495static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
496static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
497static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
498static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
499static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
500		    const void *);
501static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
502static struct bwn_txgain
503		bwn_phy_lp_get_txgain(struct bwn_mac *);
504static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
505static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
506static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
507static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
508static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
509static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
510static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
511static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
512static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
513static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
514static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
515static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
516static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
517static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
518static int	bwn_phy_lp_loopback(struct bwn_mac *);
519static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
520static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
521		    int);
522static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
523		    struct bwn_phy_lp_iq_est *);
524static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
525static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
526static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
527static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
528static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
529static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
530static uint8_t	bwn_nbits(int32_t);
531static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
532		    struct bwn_txgain_entry *);
533static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
534		    struct bwn_txgain_entry);
535static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
536		    struct bwn_txgain_entry);
537static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
538		    struct bwn_txgain_entry);
539static void	bwn_sysctl_node(struct bwn_softc *);
540
541static struct resource_spec bwn_res_spec_legacy[] = {
542	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
543	{ -1,			0,		0 }
544};
545
546static struct resource_spec bwn_res_spec_msi[] = {
547	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
548	{ -1,			0,		0 }
549};
550
551static const struct bwn_channelinfo bwn_chantable_bg = {
552	.channels = {
553		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
554		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
555		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
556		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
557		{ 2472, 13, 30 }, { 2484, 14, 30 } },
558	.nchannels = 14
559};
560
561static const struct bwn_channelinfo bwn_chantable_a = {
562	.channels = {
563		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
564		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
565		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
566		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
567		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
568		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
569		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
570		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
571		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
572		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
573		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
574		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
575		{ 6080, 216, 30 } },
576	.nchannels = 37
577};
578
579static const struct bwn_channelinfo bwn_chantable_n = {
580	.channels = {
581		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
582		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
583		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
584		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
585		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
586		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
587		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
588		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
589		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
590		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
591		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
592		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
593		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
594		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
595		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
596		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
597		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
598		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
599		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
600		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
601		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
602		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
603		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
604		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
605		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
606		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
607		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
608		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
609		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
610		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
611		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
612		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
613		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
614		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
615		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
616		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
617		{ 6130, 226, 30 }, { 6140, 228, 30 } },
618	.nchannels = 110
619};
620
621static const uint8_t bwn_b2063_chantable_data[33][12] = {
622	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
626	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
627	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
628	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
629	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
630	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
631	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
632	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
633	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
634	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
635	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
636	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
637	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
638	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
639	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
640	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
641	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
642	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
643	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
645	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
646	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
647	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
648	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
649	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
651	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
652	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
653	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
654	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
655};
656
657static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
658	{ 1, 2412, bwn_b2063_chantable_data[0] },
659	{ 2, 2417, bwn_b2063_chantable_data[0] },
660	{ 3, 2422, bwn_b2063_chantable_data[0] },
661	{ 4, 2427, bwn_b2063_chantable_data[1] },
662	{ 5, 2432, bwn_b2063_chantable_data[1] },
663	{ 6, 2437, bwn_b2063_chantable_data[1] },
664	{ 7, 2442, bwn_b2063_chantable_data[1] },
665	{ 8, 2447, bwn_b2063_chantable_data[1] },
666	{ 9, 2452, bwn_b2063_chantable_data[2] },
667	{ 10, 2457, bwn_b2063_chantable_data[2] },
668	{ 11, 2462, bwn_b2063_chantable_data[3] },
669	{ 12, 2467, bwn_b2063_chantable_data[3] },
670	{ 13, 2472, bwn_b2063_chantable_data[3] },
671	{ 14, 2484, bwn_b2063_chantable_data[4] },
672	{ 34, 5170, bwn_b2063_chantable_data[5] },
673	{ 36, 5180, bwn_b2063_chantable_data[6] },
674	{ 38, 5190, bwn_b2063_chantable_data[7] },
675	{ 40, 5200, bwn_b2063_chantable_data[8] },
676	{ 42, 5210, bwn_b2063_chantable_data[9] },
677	{ 44, 5220, bwn_b2063_chantable_data[10] },
678	{ 46, 5230, bwn_b2063_chantable_data[11] },
679	{ 48, 5240, bwn_b2063_chantable_data[12] },
680	{ 52, 5260, bwn_b2063_chantable_data[13] },
681	{ 56, 5280, bwn_b2063_chantable_data[14] },
682	{ 60, 5300, bwn_b2063_chantable_data[14] },
683	{ 64, 5320, bwn_b2063_chantable_data[15] },
684	{ 100, 5500, bwn_b2063_chantable_data[16] },
685	{ 104, 5520, bwn_b2063_chantable_data[17] },
686	{ 108, 5540, bwn_b2063_chantable_data[18] },
687	{ 112, 5560, bwn_b2063_chantable_data[19] },
688	{ 116, 5580, bwn_b2063_chantable_data[20] },
689	{ 120, 5600, bwn_b2063_chantable_data[21] },
690	{ 124, 5620, bwn_b2063_chantable_data[21] },
691	{ 128, 5640, bwn_b2063_chantable_data[22] },
692	{ 132, 5660, bwn_b2063_chantable_data[22] },
693	{ 136, 5680, bwn_b2063_chantable_data[22] },
694	{ 140, 5700, bwn_b2063_chantable_data[23] },
695	{ 149, 5745, bwn_b2063_chantable_data[23] },
696	{ 153, 5765, bwn_b2063_chantable_data[23] },
697	{ 157, 5785, bwn_b2063_chantable_data[23] },
698	{ 161, 5805, bwn_b2063_chantable_data[23] },
699	{ 165, 5825, bwn_b2063_chantable_data[23] },
700	{ 184, 4920, bwn_b2063_chantable_data[24] },
701	{ 188, 4940, bwn_b2063_chantable_data[25] },
702	{ 192, 4960, bwn_b2063_chantable_data[26] },
703	{ 196, 4980, bwn_b2063_chantable_data[27] },
704	{ 200, 5000, bwn_b2063_chantable_data[28] },
705	{ 204, 5020, bwn_b2063_chantable_data[29] },
706	{ 208, 5040, bwn_b2063_chantable_data[30] },
707	{ 212, 5060, bwn_b2063_chantable_data[31] },
708	{ 216, 5080, bwn_b2063_chantable_data[32] }
709};
710
711static const uint8_t bwn_b2062_chantable_data[22][12] = {
712	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
713	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
720	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
721	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
724	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
725	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
731	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
732	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
733	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
734};
735
736static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
737	{ 1, 2412, bwn_b2062_chantable_data[0] },
738	{ 2, 2417, bwn_b2062_chantable_data[0] },
739	{ 3, 2422, bwn_b2062_chantable_data[0] },
740	{ 4, 2427, bwn_b2062_chantable_data[0] },
741	{ 5, 2432, bwn_b2062_chantable_data[0] },
742	{ 6, 2437, bwn_b2062_chantable_data[0] },
743	{ 7, 2442, bwn_b2062_chantable_data[0] },
744	{ 8, 2447, bwn_b2062_chantable_data[0] },
745	{ 9, 2452, bwn_b2062_chantable_data[0] },
746	{ 10, 2457, bwn_b2062_chantable_data[0] },
747	{ 11, 2462, bwn_b2062_chantable_data[0] },
748	{ 12, 2467, bwn_b2062_chantable_data[0] },
749	{ 13, 2472, bwn_b2062_chantable_data[0] },
750	{ 14, 2484, bwn_b2062_chantable_data[0] },
751	{ 34, 5170, bwn_b2062_chantable_data[1] },
752	{ 38, 5190, bwn_b2062_chantable_data[2] },
753	{ 42, 5210, bwn_b2062_chantable_data[2] },
754	{ 46, 5230, bwn_b2062_chantable_data[3] },
755	{ 36, 5180, bwn_b2062_chantable_data[4] },
756	{ 40, 5200, bwn_b2062_chantable_data[5] },
757	{ 44, 5220, bwn_b2062_chantable_data[6] },
758	{ 48, 5240, bwn_b2062_chantable_data[3] },
759	{ 52, 5260, bwn_b2062_chantable_data[3] },
760	{ 56, 5280, bwn_b2062_chantable_data[3] },
761	{ 60, 5300, bwn_b2062_chantable_data[7] },
762	{ 64, 5320, bwn_b2062_chantable_data[8] },
763	{ 100, 5500, bwn_b2062_chantable_data[9] },
764	{ 104, 5520, bwn_b2062_chantable_data[10] },
765	{ 108, 5540, bwn_b2062_chantable_data[10] },
766	{ 112, 5560, bwn_b2062_chantable_data[10] },
767	{ 116, 5580, bwn_b2062_chantable_data[11] },
768	{ 120, 5600, bwn_b2062_chantable_data[12] },
769	{ 124, 5620, bwn_b2062_chantable_data[12] },
770	{ 128, 5640, bwn_b2062_chantable_data[12] },
771	{ 132, 5660, bwn_b2062_chantable_data[12] },
772	{ 136, 5680, bwn_b2062_chantable_data[12] },
773	{ 140, 5700, bwn_b2062_chantable_data[12] },
774	{ 149, 5745, bwn_b2062_chantable_data[12] },
775	{ 153, 5765, bwn_b2062_chantable_data[12] },
776	{ 157, 5785, bwn_b2062_chantable_data[12] },
777	{ 161, 5805, bwn_b2062_chantable_data[12] },
778	{ 165, 5825, bwn_b2062_chantable_data[12] },
779	{ 184, 4920, bwn_b2062_chantable_data[13] },
780	{ 188, 4940, bwn_b2062_chantable_data[14] },
781	{ 192, 4960, bwn_b2062_chantable_data[15] },
782	{ 196, 4980, bwn_b2062_chantable_data[16] },
783	{ 200, 5000, bwn_b2062_chantable_data[17] },
784	{ 204, 5020, bwn_b2062_chantable_data[18] },
785	{ 208, 5040, bwn_b2062_chantable_data[19] },
786	{ 212, 5060, bwn_b2062_chantable_data[20] },
787	{ 216, 5080, bwn_b2062_chantable_data[21] }
788};
789
790/* for LP PHY */
791static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
792	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
793	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
794	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
795	{ 13, -66, 13 }, { 14, -66, 13 },
796};
797
798/* for LP PHY */
799static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
800	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
801	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
802	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
803	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
804	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
805	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
806	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
807	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
808	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
809	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
810	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
811	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
812	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
813};
814
815static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
816
817static const uint8_t bwn_tab_sigsq_tbl[] = {
818	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
819	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
820	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
821	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
822	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
823	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
824};
825
826static const uint8_t bwn_tab_pllfrac_tbl[] = {
827	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
828	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
829};
830
831static const uint16_t bwn_tabl_iqlocal_tbl[] = {
832	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
833	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
836	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
837	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
840	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
842	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
843	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
844};
845
846static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
847static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
848static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
849static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
850static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
851const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
852
853#define	VENDOR_LED_ACT(vendor)				\
854{							\
855	.vid = PCI_VENDOR_##vendor,			\
856	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
857}
858
859static const struct {
860	uint16_t	vid;
861	uint8_t		led_act[BWN_LED_MAX];
862} bwn_vendor_led_act[] = {
863	VENDOR_LED_ACT(COMPAQ),
864	VENDOR_LED_ACT(ASUSTEK)
865};
866
867static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
868	{ BWN_VENDOR_LED_ACT_DEFAULT };
869
870#undef VENDOR_LED_ACT
871
872static const struct {
873	int		on_dur;
874	int		off_dur;
875} bwn_led_duration[109] = {
876	[0]	= { 400, 100 },
877	[2]	= { 150, 75 },
878	[4]	= { 90, 45 },
879	[11]	= { 66, 34 },
880	[12]	= { 53, 26 },
881	[18]	= { 42, 21 },
882	[22]	= { 35, 17 },
883	[24]	= { 32, 16 },
884	[36]	= { 21, 10 },
885	[48]	= { 16, 8 },
886	[72]	= { 11, 5 },
887	[96]	= { 9, 4 },
888	[108]	= { 7, 3 }
889};
890
891static const uint16_t bwn_wme_shm_offsets[] = {
892	[0] = BWN_WME_BESTEFFORT,
893	[1] = BWN_WME_BACKGROUND,
894	[2] = BWN_WME_VOICE,
895	[3] = BWN_WME_VIDEO,
896};
897
898static const struct siba_devid bwn_devs[] = {
899	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
900	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
901	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
902	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
903	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
904	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
905	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
906	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
907	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
908};
909
910static int
911bwn_probe(device_t dev)
912{
913	struct siba_dev_softc *sd = device_get_ivars(dev);
914	int i;
915
916	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
917		if (sd->sd_id.sd_vendor == bwn_devs[i].sd_vendor &&
918		    sd->sd_id.sd_device == bwn_devs[i].sd_device &&
919		    sd->sd_id.sd_rev == bwn_devs[i].sd_rev)
920			return (BUS_PROBE_DEFAULT);
921	}
922
923	return (ENXIO);
924}
925
926static int
927bwn_attach(device_t dev)
928{
929	struct bwn_mac *mac;
930	struct bwn_softc *sc = device_get_softc(dev);
931	struct siba_dev_softc *sd = device_get_ivars(dev);
932	struct siba_softc *siba = sd->sd_bus;
933	int error, i, msic, reg;
934
935	sc->sc_dev = dev;
936	sc->sc_sd = sd;
937#ifdef BWN_DEBUG
938	sc->sc_debug = bwn_debug;
939#endif
940
941	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
942		error = bwn_attach_pre(sc);
943		if (error != 0)
944			return (error);
945		bwn_sprom_bugfixes(sd->sd_bus);
946		sc->sc_flags |= BWN_FLAG_ATTACHED;
947	}
948
949	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
950		if (siba->siba_pci_did != 0x4313 &&
951		    siba->siba_pci_did != 0x431a &&
952		    siba->siba_pci_did != 0x4321) {
953			device_printf(sc->sc_dev,
954			    "skip 802.11 cores\n");
955			return (ENODEV);
956		}
957	}
958
959	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
960	    M_NOWAIT | M_ZERO);
961	if (mac == NULL)
962		return (ENOMEM);
963	mac->mac_sc = sc;
964	mac->mac_sd = sd;
965	mac->mac_status = BWN_MAC_STATUS_UNINIT;
966	if (bwn_bfp != 0)
967		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
968
969	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
970	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
971	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
972
973	error = bwn_attach_core(mac);
974	if (error)
975		goto fail0;
976	bwn_led_attach(mac);
977
978	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
979	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
980	    sd->sd_bus->siba_chipid, sd->sd_id.sd_rev,
981	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
982	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
983	    mac->mac_phy.rf_rev);
984	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
985		device_printf(sc->sc_dev, "DMA (%d bits)\n",
986		    mac->mac_method.dma.dmatype);
987	else
988		device_printf(sc->sc_dev, "PIO\n");
989
990	/*
991	 * setup PCI resources and interrupt.
992	 */
993	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
994		msic = pci_msi_count(dev);
995		if (bootverbose)
996			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
997	} else
998		msic = 0;
999
1000	mac->mac_intr_spec = bwn_res_spec_legacy;
1001	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
1002		if (pci_alloc_msi(dev, &msic) == 0) {
1003			device_printf(sc->sc_dev,
1004			    "Using %d MSI messages\n", msic);
1005			mac->mac_intr_spec = bwn_res_spec_msi;
1006			mac->mac_msi = 1;
1007		}
1008	}
1009
1010	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1011	    mac->mac_res_irq);
1012	if (error) {
1013		device_printf(sc->sc_dev,
1014		    "couldn't allocate IRQ resources (%d)\n", error);
1015		goto fail1;
1016	}
1017
1018	if (mac->mac_msi == 0)
1019		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1020		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1021		    &mac->mac_intrhand[0]);
1022	else {
1023		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1024			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1025			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1026			    &mac->mac_intrhand[i]);
1027			if (error != 0) {
1028				device_printf(sc->sc_dev,
1029				    "couldn't setup interrupt (%d)\n", error);
1030				break;
1031			}
1032		}
1033	}
1034
1035	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1036
1037	/*
1038	 * calls attach-post routine
1039	 */
1040	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1041		bwn_attach_post(sc);
1042
1043	return (0);
1044fail1:
1045	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1046		pci_release_msi(dev);
1047fail0:
1048	free(mac, M_DEVBUF);
1049	return (error);
1050}
1051
1052static int
1053bwn_is_valid_ether_addr(uint8_t *addr)
1054{
1055	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1056
1057	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1058		return (FALSE);
1059
1060	return (TRUE);
1061}
1062
1063static int
1064bwn_attach_post(struct bwn_softc *sc)
1065{
1066	struct ieee80211com *ic;
1067	struct ifnet *ifp = sc->sc_ifp;
1068	struct siba_dev_softc *sd = sc->sc_sd;
1069	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
1070
1071	ic = ifp->if_l2com;
1072	ic->ic_ifp = ifp;
1073	/* XXX not right but it's not used anywhere important */
1074	ic->ic_phytype = IEEE80211_T_OFDM;
1075	ic->ic_opmode = IEEE80211_M_STA;
1076	ic->ic_caps =
1077		  IEEE80211_C_STA		/* station mode supported */
1078		| IEEE80211_C_MONITOR		/* monitor mode */
1079		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1080		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1081		| IEEE80211_C_SHSLOT		/* short slot time supported */
1082		| IEEE80211_C_WME		/* WME/WMM supported */
1083		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1084		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1085		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1086		;
1087
1088	/* call MI attach routine. */
1089	ieee80211_ifattach(ic,
1090	    bwn_is_valid_ether_addr(sprom->mac_80211a) ? sprom->mac_80211a :
1091	    sprom->mac_80211bg);
1092
1093	ic->ic_headroom = sizeof(struct bwn_txhdr);
1094
1095	/* override default methods */
1096	ic->ic_raw_xmit = bwn_raw_xmit;
1097	ic->ic_newassoc = bwn_newassoc;
1098	ic->ic_updateslot = bwn_updateslot;
1099	ic->ic_update_promisc = bwn_update_promisc;
1100	ic->ic_wme.wme_update = bwn_wme_update;
1101
1102	ic->ic_node_alloc = bwn_node_alloc;
1103	sc->sc_node_cleanup = ic->ic_node_cleanup;
1104	ic->ic_node_cleanup = bwn_node_cleanup;
1105
1106	ic->ic_scan_start = bwn_scan_start;
1107	ic->ic_scan_end = bwn_scan_end;
1108	ic->ic_set_channel = bwn_set_channel;
1109
1110	ic->ic_vap_create = bwn_vap_create;
1111	ic->ic_vap_delete = bwn_vap_delete;
1112
1113	ieee80211_radiotap_attach(ic,
1114	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1115	    BWN_TX_RADIOTAP_PRESENT,
1116	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1117	    BWN_RX_RADIOTAP_PRESENT);
1118
1119	bwn_sysctl_node(sc);
1120
1121	if (bootverbose)
1122		ieee80211_announce(ic);
1123	return (0);
1124}
1125
1126static void
1127bwn_phy_detach(struct bwn_mac *mac)
1128{
1129
1130	if (mac->mac_phy.detach != NULL)
1131		mac->mac_phy.detach(mac);
1132}
1133
1134static int
1135bwn_detach(device_t dev)
1136{
1137	struct bwn_softc *sc = device_get_softc(dev);
1138	struct bwn_mac *mac = sc->sc_curmac;
1139	struct ifnet *ifp = sc->sc_ifp;
1140	struct ieee80211com *ic = ifp->if_l2com;
1141	int i;
1142
1143	sc->sc_flags |= BWN_FLAG_INVALID;
1144
1145	if (device_is_attached(sc->sc_dev)) {
1146		bwn_stop(sc, 1);
1147		bwn_dma_free(mac);
1148		callout_drain(&sc->sc_led_blink_ch);
1149		callout_drain(&sc->sc_rfswitch_ch);
1150		callout_drain(&sc->sc_task_ch);
1151		callout_drain(&sc->sc_watchdog_ch);
1152		bwn_phy_detach(mac);
1153		if (ifp != NULL) {
1154			ieee80211_draintask(ic, &mac->mac_hwreset);
1155			ieee80211_draintask(ic, &mac->mac_txpower);
1156			ieee80211_ifdetach(ic);
1157			if_free(ifp);
1158		}
1159	}
1160	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1161	taskqueue_free(sc->sc_tq);
1162
1163	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1164		if (mac->mac_intrhand[i] != NULL) {
1165			bus_teardown_intr(dev, mac->mac_res_irq[i],
1166			    mac->mac_intrhand[i]);
1167			mac->mac_intrhand[i] = NULL;
1168		}
1169	}
1170	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1171	if (mac->mac_msi != 0)
1172		pci_release_msi(dev);
1173
1174	BWN_LOCK_DESTROY(sc);
1175	return (0);
1176}
1177
1178static int
1179bwn_attach_pre(struct bwn_softc *sc)
1180{
1181	struct ifnet *ifp;
1182	int error = 0;
1183
1184	BWN_LOCK_INIT(sc);
1185	TAILQ_INIT(&sc->sc_maclist);
1186	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1187	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1188	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1189
1190	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1191		taskqueue_thread_enqueue, &sc->sc_tq);
1192	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1193		"%s taskq", device_get_nameunit(sc->sc_dev));
1194
1195	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1196	if (ifp == NULL) {
1197		device_printf(sc->sc_dev, "can not if_alloc()\n");
1198		error = ENOSPC;
1199		goto fail;
1200	}
1201
1202	/* set these up early for if_printf use */
1203	if_initname(ifp, device_get_name(sc->sc_dev),
1204	    device_get_unit(sc->sc_dev));
1205
1206	ifp->if_softc = sc;
1207	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1208	ifp->if_init = bwn_init;
1209	ifp->if_ioctl = bwn_ioctl;
1210	ifp->if_start = bwn_start;
1211	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1212	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1213	IFQ_SET_READY(&ifp->if_snd);
1214
1215	return (0);
1216
1217fail:	BWN_LOCK_DESTROY(sc);
1218	return (error);
1219}
1220
1221static void
1222bwn_sprom_bugfixes(struct siba_softc *siba)
1223{
1224#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1225	((siba->siba_pci_vid == PCI_VENDOR_##_vendor) &&		\
1226	 (siba->siba_pci_did == _device) &&				\
1227	 (siba->siba_pci_subvid == PCI_VENDOR_##_subvendor) &&		\
1228	 (siba->siba_pci_subdid == _subdevice))
1229
1230	if (siba->siba_board_vendor == PCI_VENDOR_APPLE &&
1231	    siba->siba_board_type == 0x4e && siba->siba_board_rev > 0x40)
1232		siba->siba_sprom.bf_lo |= BWN_BFL_PACTRL;
1233	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_DELL &&
1234	    siba->siba_chipid == 0x4301 && siba->siba_board_rev == 0x74)
1235		siba->siba_sprom.bf_lo |= BWN_BFL_BTCOEXIST;
1236	if (siba->siba_type == SIBA_TYPE_PCI) {
1237		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1238		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1239		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1240		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1241		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1242		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1243		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1244			siba->siba_sprom.bf_lo &= ~BWN_BFL_BTCOEXIST;
1245	}
1246#undef	BWN_ISDEV
1247}
1248
1249static int
1250bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1251{
1252#define	IS_RUNNING(ifp) \
1253	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1254	struct bwn_softc *sc = ifp->if_softc;
1255	struct ieee80211com *ic = ifp->if_l2com;
1256	struct ifreq *ifr = (struct ifreq *)data;
1257	int error = 0, startall;
1258
1259	switch (cmd) {
1260	case SIOCSIFFLAGS:
1261		startall = 0;
1262		if (IS_RUNNING(ifp)) {
1263			bwn_update_promisc(ifp);
1264		} else if (ifp->if_flags & IFF_UP) {
1265			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1266				bwn_init(sc);
1267				startall = 1;
1268			}
1269		} else
1270			bwn_stop(sc, 1);
1271		if (startall)
1272			ieee80211_start_all(ic);
1273		break;
1274	case SIOCGIFMEDIA:
1275		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1276		break;
1277	case SIOCGIFADDR:
1278		error = ether_ioctl(ifp, cmd, data);
1279		break;
1280	default:
1281		error = EINVAL;
1282		break;
1283	}
1284	return (error);
1285}
1286
1287static void
1288bwn_start(struct ifnet *ifp)
1289{
1290	struct bwn_softc *sc = ifp->if_softc;
1291
1292	BWN_LOCK(sc);
1293	bwn_start_locked(ifp);
1294	BWN_UNLOCK(sc);
1295}
1296
1297static void
1298bwn_start_locked(struct ifnet *ifp)
1299{
1300	struct bwn_softc *sc = ifp->if_softc;
1301	struct bwn_mac *mac = sc->sc_curmac;
1302	struct ieee80211_frame *wh;
1303	struct ieee80211_node *ni;
1304	struct ieee80211_key *k;
1305	struct mbuf *m;
1306
1307	BWN_ASSERT_LOCKED(sc);
1308
1309	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1310	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1311		return;
1312
1313	for (;;) {
1314		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1315		if (m == NULL)
1316			break;
1317
1318		if (bwn_tx_isfull(sc, m))
1319			break;
1320		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1321		if (ni == NULL) {
1322			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1323			m_freem(m);
1324			ifp->if_oerrors++;
1325			continue;
1326		}
1327		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1328		wh = mtod(m, struct ieee80211_frame *);
1329		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1330			k = ieee80211_crypto_encap(ni, m);
1331			if (k == NULL) {
1332				ieee80211_free_node(ni);
1333				m_freem(m);
1334				ifp->if_oerrors++;
1335				continue;
1336			}
1337		}
1338		wh = NULL;	/* Catch any invalid use */
1339
1340		if (bwn_tx_start(sc, ni, m) != 0) {
1341			if (ni != NULL)
1342				ieee80211_free_node(ni);
1343			ifp->if_oerrors++;
1344			continue;
1345		}
1346
1347		sc->sc_watchdog_timer = 5;
1348	}
1349}
1350
1351static int
1352bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1353{
1354	struct bwn_dma_ring *dr;
1355	struct bwn_mac *mac = sc->sc_curmac;
1356	struct bwn_pio_txqueue *tq;
1357	struct ifnet *ifp = sc->sc_ifp;
1358	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1359
1360	BWN_ASSERT_LOCKED(sc);
1361
1362	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1363		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1364		if (dr->dr_stop == 1 ||
1365		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1366			dr->dr_stop = 1;
1367			goto full;
1368		}
1369	} else {
1370		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1371		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1372		    pktlen > (tq->tq_size - tq->tq_used)) {
1373			tq->tq_stop = 1;
1374			goto full;
1375		}
1376	}
1377	return (0);
1378full:
1379	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1380	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1381	return (1);
1382}
1383
1384static int
1385bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1386{
1387	struct bwn_mac *mac = sc->sc_curmac;
1388	int error;
1389
1390	BWN_ASSERT_LOCKED(sc);
1391
1392	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1393		m_freem(m);
1394		return (ENXIO);
1395	}
1396
1397	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1398	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1399	if (error) {
1400		m_freem(m);
1401		return (error);
1402	}
1403	return (0);
1404}
1405
1406static int
1407bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1408{
1409	struct bwn_pio_txpkt *tp;
1410	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1411	struct bwn_softc *sc = mac->mac_sc;
1412	struct bwn_txhdr txhdr;
1413	struct mbuf *m_new;
1414	uint32_t ctl32;
1415	int error;
1416	uint16_t ctl16;
1417
1418	BWN_ASSERT_LOCKED(sc);
1419
1420	/* XXX TODO send packets after DTIM */
1421
1422	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1423	tp = TAILQ_FIRST(&tq->tq_pktlist);
1424	tp->tp_ni = ni;
1425	tp->tp_m = m;
1426
1427	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1428	if (error) {
1429		device_printf(sc->sc_dev, "tx fail\n");
1430		return (error);
1431	}
1432
1433	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1434	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1435	tq->tq_free--;
1436
1437	if (mac->mac_sd->sd_id.sd_rev >= 8) {
1438		/*
1439		 * XXX please removes m_defrag(9)
1440		 */
1441		m_new = m_defrag(m, M_DONTWAIT);
1442		if (m_new == NULL) {
1443			device_printf(sc->sc_dev,
1444			    "%s: can't defrag TX buffer\n",
1445			    __func__);
1446			return (ENOBUFS);
1447		}
1448		if (m_new->m_next != NULL)
1449			device_printf(sc->sc_dev,
1450			    "TODO: fragmented packets for PIO\n");
1451		tp->tp_m = m_new;
1452
1453		/* send HEADER */
1454		ctl32 = bwn_pio_write_multi_4(mac, tq,
1455		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1456			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1457		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1458		/* send BODY */
1459		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1460		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1461		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1462		    ctl32 | BWN_PIO8_TXCTL_EOF);
1463	} else {
1464		ctl16 = bwn_pio_write_multi_2(mac, tq,
1465		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1466			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1467		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1468		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1469		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1470		    ctl16 | BWN_PIO_TXCTL_EOF);
1471	}
1472
1473	return (0);
1474}
1475
1476static struct bwn_pio_txqueue *
1477bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1478{
1479
1480	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1481		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1482
1483	switch (prio) {
1484	case 0:
1485		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1486	case 1:
1487		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1488	case 2:
1489		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1490	case 3:
1491		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1492	}
1493	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1494	return (NULL);
1495}
1496
1497static int
1498bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1499{
1500#define	BWN_GET_TXHDRCACHE(slot)					\
1501	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1502	struct bwn_dma *dma = &mac->mac_method.dma;
1503	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1504	struct bwn_dmadesc_generic *desc;
1505	struct bwn_dmadesc_meta *mt;
1506	struct bwn_softc *sc = mac->mac_sc;
1507	struct ifnet *ifp = sc->sc_ifp;
1508	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1509	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1510
1511	BWN_ASSERT_LOCKED(sc);
1512	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1513
1514	/* XXX send after DTIM */
1515
1516	slot = bwn_dma_getslot(dr);
1517	dr->getdesc(dr, slot, &desc, &mt);
1518	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1519	    ("%s:%d: fail", __func__, __LINE__));
1520
1521	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1522	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1523	    BWN_DMA_COOKIE(dr, slot));
1524	if (error)
1525		goto fail;
1526	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1527	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1528	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1529	if (error) {
1530		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1531		    __func__, error);
1532		goto fail;
1533	}
1534	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1535	    BUS_DMASYNC_PREWRITE);
1536	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1537	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1538	    BUS_DMASYNC_PREWRITE);
1539
1540	slot = bwn_dma_getslot(dr);
1541	dr->getdesc(dr, slot, &desc, &mt);
1542	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1543	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1544	mt->mt_m = m;
1545	mt->mt_ni = ni;
1546
1547	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1548	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1549	if (error && error != EFBIG) {
1550		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1551		    __func__, error);
1552		goto fail;
1553	}
1554	if (error) {    /* error == EFBIG */
1555		struct mbuf *m_new;
1556
1557		m_new = m_defrag(m, M_DONTWAIT);
1558		if (m_new == NULL) {
1559			if_printf(ifp, "%s: can't defrag TX buffer\n",
1560			    __func__);
1561			error = ENOBUFS;
1562			goto fail;
1563		} else {
1564			m = m_new;
1565		}
1566
1567		mt->mt_m = m;
1568		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1569		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1570		if (error) {
1571			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1572			    __func__, error);
1573			goto fail;
1574		}
1575	}
1576	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1577	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1578	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1579	    BUS_DMASYNC_PREWRITE);
1580
1581	/* XXX send after DTIM */
1582
1583	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1584	return (0);
1585fail:
1586	dr->dr_curslot = backup[0];
1587	dr->dr_usedslot = backup[1];
1588	return (error);
1589#undef BWN_GET_TXHDRCACHE
1590}
1591
1592static void
1593bwn_watchdog(void *arg)
1594{
1595	struct bwn_softc *sc = arg;
1596	struct ifnet *ifp = sc->sc_ifp;
1597
1598	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1599		if_printf(ifp, "device timeout\n");
1600		ifp->if_oerrors++;
1601	}
1602	callout_schedule(&sc->sc_watchdog_ch, hz);
1603}
1604
1605static int
1606bwn_attach_core(struct bwn_mac *mac)
1607{
1608	struct bwn_softc *sc = mac->mac_sc;
1609	struct siba_dev_softc *sd = mac->mac_sd;
1610	struct siba_softc *siba = sd->sd_bus;
1611	int error, have_bg = 0, have_a = 0;
1612	uint32_t high;
1613
1614	KASSERT(sd->sd_id.sd_rev >= 5,
1615	    ("unsupported revision %d", sd->sd_id.sd_rev));
1616
1617	siba_powerup(siba, 0);
1618
1619	high = siba_read_4(sd, SIBA_TGSHIGH);
1620	bwn_reset_core(mac,
1621	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1622	error = bwn_phy_getinfo(mac, high);
1623	if (error)
1624		goto fail;
1625
1626	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1627	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1628	if (siba->siba_pci_did != 0x4312 && siba->siba_pci_did != 0x4319 &&
1629	    siba->siba_pci_did != 0x4324) {
1630		have_a = have_bg = 0;
1631		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1632			have_a = 1;
1633		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1634		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1635		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1636			have_bg = 1;
1637		else
1638			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1639			    mac->mac_phy.type));
1640	}
1641	/* XXX turns off PHY A because it's not supported */
1642	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1643	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1644		have_a = 0;
1645		have_bg = 1;
1646	}
1647
1648	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1649		mac->mac_phy.attach = bwn_phy_g_attach;
1650		mac->mac_phy.detach = bwn_phy_g_detach;
1651		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1652		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1653		mac->mac_phy.init = bwn_phy_g_init;
1654		mac->mac_phy.exit = bwn_phy_g_exit;
1655		mac->mac_phy.phy_read = bwn_phy_g_read;
1656		mac->mac_phy.phy_write = bwn_phy_g_write;
1657		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1658		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1659		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1660		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1661		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1662		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1663		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1664		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1665		mac->mac_phy.set_im = bwn_phy_g_im;
1666		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1667		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1668		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1669		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1670	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1671		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1672		mac->mac_phy.init = bwn_phy_lp_init;
1673		mac->mac_phy.phy_read = bwn_phy_lp_read;
1674		mac->mac_phy.phy_write = bwn_phy_lp_write;
1675		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1676		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1677		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1678		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1679		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1680		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1681		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1682		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1683		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1684	} else {
1685		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1686		    mac->mac_phy.type);
1687		error = ENXIO;
1688		goto fail;
1689	}
1690
1691	mac->mac_phy.gmode = have_bg;
1692	if (mac->mac_phy.attach != NULL) {
1693		error = mac->mac_phy.attach(mac);
1694		if (error) {
1695			device_printf(sc->sc_dev, "failed\n");
1696			goto fail;
1697		}
1698	}
1699
1700	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1701
1702	error = bwn_chiptest(mac);
1703	if (error)
1704		goto fail;
1705	error = bwn_setup_channels(mac, have_bg, have_a);
1706	if (error) {
1707		device_printf(sc->sc_dev, "failed to setup channels\n");
1708		goto fail;
1709	}
1710
1711	if (sc->sc_curmac == NULL)
1712		sc->sc_curmac = mac;
1713
1714	error = bwn_dma_attach(mac);
1715	if (error != 0) {
1716		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1717		goto fail;
1718	}
1719
1720	mac->mac_phy.switch_analog(mac, 0);
1721
1722	siba_dev_down(sd, 0);
1723fail:
1724	siba_powerdown(siba);
1725	return (error);
1726}
1727
1728static void
1729bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1730{
1731	struct siba_dev_softc *sd = mac->mac_sd;
1732	uint32_t low, ctl;
1733
1734	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1735
1736	siba_dev_up(sd, flags);
1737	DELAY(2000);
1738
1739	low = (siba_read_4(sd, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1740	    ~BWN_TGSLOW_PHYRESET;
1741	siba_write_4(sd, SIBA_TGSLOW, low);
1742	siba_read_4(sd, SIBA_TGSLOW);
1743	DELAY(1000);
1744	siba_write_4(sd, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1745	siba_read_4(sd, SIBA_TGSLOW);
1746	DELAY(1000);
1747
1748	if (mac->mac_phy.switch_analog != NULL)
1749		mac->mac_phy.switch_analog(mac, 1);
1750
1751	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1752	if (flags & BWN_TGSLOW_SUPPORT_G)
1753		ctl |= BWN_MACCTL_GMODE;
1754	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1755}
1756
1757static int
1758bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1759{
1760	struct bwn_phy *phy = &mac->mac_phy;
1761	struct bwn_softc *sc = mac->mac_sc;
1762	struct siba_dev_softc *sd = mac->mac_sd;
1763	struct siba_softc *siba = sd->sd_bus;
1764	uint32_t tmp;
1765
1766	/* PHY */
1767	tmp = BWN_READ_2(mac, BWN_PHYVER);
1768	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1769	phy->rf_on = 1;
1770	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1771	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1772	phy->rev = (tmp & BWN_PHYVER_VERSION);
1773	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1774	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1775		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1776	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1777	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1778	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1779		goto unsupphy;
1780
1781	/* RADIO */
1782	if (siba->siba_chipid == 0x4317) {
1783		if (siba->siba_chiprev == 0)
1784			tmp = 0x3205017f;
1785		else if (siba->siba_chiprev == 1)
1786			tmp = 0x4205017f;
1787		else
1788			tmp = 0x5205017f;
1789	} else {
1790		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1791		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1792		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1793		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1794	}
1795	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1796	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1797	phy->rf_manuf = (tmp & 0x00000fff);
1798	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1799		goto unsupradio;
1800	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1801	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1802	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1803	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1804	    (phy->type == BWN_PHYTYPE_N &&
1805	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1806	    (phy->type == BWN_PHYTYPE_LP &&
1807	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1808		goto unsupradio;
1809
1810	return (0);
1811unsupphy:
1812	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1813	    "analog %#x)\n",
1814	    phy->type, phy->rev, phy->analog);
1815	return (ENXIO);
1816unsupradio:
1817	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1818	    "rev %#x)\n",
1819	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1820	return (ENXIO);
1821}
1822
1823static int
1824bwn_chiptest(struct bwn_mac *mac)
1825{
1826#define	TESTVAL0	0x55aaaa55
1827#define	TESTVAL1	0xaa5555aa
1828	struct bwn_softc *sc = mac->mac_sc;
1829	struct siba_dev_softc *sd = mac->mac_sd;
1830	uint32_t v, backup;
1831
1832	BWN_LOCK(sc);
1833
1834	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1835
1836	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1837	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1838		goto error;
1839	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1840	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1841		goto error;
1842
1843	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1844
1845	if ((sd->sd_id.sd_rev >= 3) && (sd->sd_id.sd_rev <= 10)) {
1846		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1847		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1848		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1849			goto error;
1850		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1851			goto error;
1852	}
1853	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1854
1855	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1856	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1857		goto error;
1858
1859	BWN_UNLOCK(sc);
1860	return (0);
1861error:
1862	BWN_UNLOCK(sc);
1863	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1864	return (ENODEV);
1865}
1866
1867#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1868#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1869
1870static int
1871bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1872{
1873	struct bwn_softc *sc = mac->mac_sc;
1874	struct ifnet *ifp = sc->sc_ifp;
1875	struct ieee80211com *ic = ifp->if_l2com;
1876
1877	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1878	ic->ic_nchans = 0;
1879
1880	if (have_bg)
1881		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1882		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1883	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1884		if (have_a)
1885			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1886			    &ic->ic_nchans, &bwn_chantable_n,
1887			    IEEE80211_CHAN_HTA);
1888	} else {
1889		if (have_a)
1890			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1891			    &ic->ic_nchans, &bwn_chantable_a,
1892			    IEEE80211_CHAN_A);
1893	}
1894
1895	mac->mac_phy.supports_2ghz = have_bg;
1896	mac->mac_phy.supports_5ghz = have_a;
1897
1898	return (ic->ic_nchans == 0 ? ENXIO : 0);
1899}
1900
1901static uint32_t
1902bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1903{
1904	uint32_t ret;
1905
1906	BWN_ASSERT_LOCKED(mac->mac_sc);
1907
1908	if (way == BWN_SHARED) {
1909		KASSERT((offset & 0x0001) == 0,
1910		    ("%s:%d warn", __func__, __LINE__));
1911		if (offset & 0x0003) {
1912			bwn_shm_ctlword(mac, way, offset >> 2);
1913			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1914			ret <<= 16;
1915			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1916			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1917			goto out;
1918		}
1919		offset >>= 2;
1920	}
1921	bwn_shm_ctlword(mac, way, offset);
1922	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1923out:
1924	return (ret);
1925}
1926
1927static uint16_t
1928bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1929{
1930	uint16_t ret;
1931
1932	BWN_ASSERT_LOCKED(mac->mac_sc);
1933
1934	if (way == BWN_SHARED) {
1935		KASSERT((offset & 0x0001) == 0,
1936		    ("%s:%d warn", __func__, __LINE__));
1937		if (offset & 0x0003) {
1938			bwn_shm_ctlword(mac, way, offset >> 2);
1939			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1940			goto out;
1941		}
1942		offset >>= 2;
1943	}
1944	bwn_shm_ctlword(mac, way, offset);
1945	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1946out:
1947
1948	return (ret);
1949}
1950
1951static void
1952bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1953    uint16_t offset)
1954{
1955	uint32_t control;
1956
1957	control = way;
1958	control <<= 16;
1959	control |= offset;
1960	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1961}
1962
1963static void
1964bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1965    uint32_t value)
1966{
1967	BWN_ASSERT_LOCKED(mac->mac_sc);
1968
1969	if (way == BWN_SHARED) {
1970		KASSERT((offset & 0x0001) == 0,
1971		    ("%s:%d warn", __func__, __LINE__));
1972		if (offset & 0x0003) {
1973			bwn_shm_ctlword(mac, way, offset >> 2);
1974			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1975				    (value >> 16) & 0xffff);
1976			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1977			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1978			return;
1979		}
1980		offset >>= 2;
1981	}
1982	bwn_shm_ctlword(mac, way, offset);
1983	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1984}
1985
1986static void
1987bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1988    uint16_t value)
1989{
1990	BWN_ASSERT_LOCKED(mac->mac_sc);
1991
1992	if (way == BWN_SHARED) {
1993		KASSERT((offset & 0x0001) == 0,
1994		    ("%s:%d warn", __func__, __LINE__));
1995		if (offset & 0x0003) {
1996			bwn_shm_ctlword(mac, way, offset >> 2);
1997			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1998			return;
1999		}
2000		offset >>= 2;
2001	}
2002	bwn_shm_ctlword(mac, way, offset);
2003	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
2004}
2005
2006static void
2007bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2008    int txpow)
2009{
2010
2011	c->ic_freq = freq;
2012	c->ic_flags = flags;
2013	c->ic_ieee = ieee;
2014	c->ic_minpower = 0;
2015	c->ic_maxpower = 2 * txpow;
2016	c->ic_maxregpower = txpow;
2017}
2018
2019static void
2020bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2021    const struct bwn_channelinfo *ci, int flags)
2022{
2023	struct ieee80211_channel *c;
2024	int i;
2025
2026	c = &chans[*nchans];
2027
2028	for (i = 0; i < ci->nchannels; i++) {
2029		const struct bwn_channel *hc;
2030
2031		hc = &ci->channels[i];
2032		if (*nchans >= maxchans)
2033			break;
2034		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2035		c++, (*nchans)++;
2036		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2037			/* g channel have a separate b-only entry */
2038			if (*nchans >= maxchans)
2039				break;
2040			c[0] = c[-1];
2041			c[-1].ic_flags = IEEE80211_CHAN_B;
2042			c++, (*nchans)++;
2043		}
2044		if (flags == IEEE80211_CHAN_HTG) {
2045			/* HT g channel have a separate g-only entry */
2046			if (*nchans >= maxchans)
2047				break;
2048			c[-1].ic_flags = IEEE80211_CHAN_G;
2049			c[0] = c[-1];
2050			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2051			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2052			c++, (*nchans)++;
2053		}
2054		if (flags == IEEE80211_CHAN_HTA) {
2055			/* HT a channel have a separate a-only entry */
2056			if (*nchans >= maxchans)
2057				break;
2058			c[-1].ic_flags = IEEE80211_CHAN_A;
2059			c[0] = c[-1];
2060			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2061			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2062			c++, (*nchans)++;
2063		}
2064	}
2065}
2066
2067static int
2068bwn_phy_g_attach(struct bwn_mac *mac)
2069{
2070	struct bwn_softc *sc = mac->mac_sc;
2071	struct bwn_phy *phy = &mac->mac_phy;
2072	struct bwn_phy_g *pg = &phy->phy_g;
2073	struct siba_dev_softc *sd = mac->mac_sd;
2074	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
2075	unsigned int i;
2076	int16_t pab0 = (int16_t)(sprom->pa0b0), pab1 = (int16_t)(sprom->pa0b1),
2077	    pab2 = (int16_t)(sprom->pa0b2);
2078	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2079	int8_t bg = (int8_t)sprom->tssi_bg;
2080
2081	if ((sd->sd_bus->siba_chipid == 0x4301) && (phy->rf_ver != 0x2050))
2082		device_printf(sc->sc_dev, "not supported anymore\n");
2083
2084	pg->pg_flags = 0;
2085	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2086	    pab2 == -1) {
2087		pg->pg_idletssi = 52;
2088		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2089		return (0);
2090	}
2091
2092	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2093	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2094	if (pg->pg_tssi2dbm == NULL) {
2095		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2096		return (ENOMEM);
2097	}
2098	for (i = 0; i < 64; i++) {
2099		int32_t m1, m2, f, q, delta;
2100		int8_t j = 0;
2101
2102		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2103		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2104		f = 256;
2105
2106		do {
2107			if (j > 15) {
2108				device_printf(sc->sc_dev,
2109				    "failed to generate tssi2dBm\n");
2110				free(pg->pg_tssi2dbm, M_DEVBUF);
2111				return (ENOMEM);
2112			}
2113			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2114			    f, 2048);
2115			delta = abs(q - f);
2116			f = q;
2117			j++;
2118		} while (delta >= 2);
2119
2120		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2121		    128);
2122	}
2123
2124	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2125	return (0);
2126}
2127
2128static void
2129bwn_phy_g_detach(struct bwn_mac *mac)
2130{
2131	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2132
2133	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2134		free(pg->pg_tssi2dbm, M_DEVBUF);
2135		pg->pg_tssi2dbm = NULL;
2136	}
2137	pg->pg_flags = 0;
2138}
2139
2140static void
2141bwn_phy_g_init_pre(struct bwn_mac *mac)
2142{
2143	struct bwn_phy *phy = &mac->mac_phy;
2144	struct bwn_phy_g *pg = &phy->phy_g;
2145	void *tssi2dbm;
2146	int idletssi;
2147	unsigned int i;
2148
2149	tssi2dbm = pg->pg_tssi2dbm;
2150	idletssi = pg->pg_idletssi;
2151
2152	memset(pg, 0, sizeof(*pg));
2153
2154	pg->pg_tssi2dbm = tssi2dbm;
2155	pg->pg_idletssi = idletssi;
2156
2157	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2158
2159	for (i = 0; i < N(pg->pg_nrssi); i++)
2160		pg->pg_nrssi[i] = -1000;
2161	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2162		pg->pg_nrssi_lt[i] = i;
2163	pg->pg_lofcal = 0xffff;
2164	pg->pg_initval = 0xffff;
2165	pg->pg_immode = BWN_IMMODE_NONE;
2166	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2167	pg->pg_avgtssi = 0xff;
2168
2169	pg->pg_loctl.tx_bias = 0xff;
2170	TAILQ_INIT(&pg->pg_loctl.calib_list);
2171}
2172
2173static int
2174bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2175{
2176	struct bwn_phy *phy = &mac->mac_phy;
2177	struct bwn_phy_g *pg = &phy->phy_g;
2178	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2179	struct siba_softc *bus = mac->mac_sd->sd_bus;
2180	static const struct bwn_rfatt rfatt0[] = {
2181		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2182		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2183		{ 3, 1 }, { 4, 1 }
2184	};
2185	static const struct bwn_rfatt rfatt1[] = {
2186		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2187		{ 14, 1 }
2188	};
2189	static const struct bwn_rfatt rfatt2[] = {
2190		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2191		{ 9, 1 }
2192	};
2193	static const struct bwn_bbatt bbatt_0[] = {
2194		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2195	};
2196
2197	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2198
2199	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2200		pg->pg_bbatt.att = 0;
2201	else
2202		pg->pg_bbatt.att = 2;
2203
2204	/* prepare Radio Attenuation */
2205	pg->pg_rfatt.padmix = 0;
2206
2207	if (bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
2208	    bus->siba_board_type == SIBA_BOARD_BCM4309G) {
2209		if (bus->siba_board_rev < 0x43) {
2210			pg->pg_rfatt.att = 2;
2211			goto done;
2212		} else if (bus->siba_board_rev < 0x51) {
2213			pg->pg_rfatt.att = 3;
2214			goto done;
2215		}
2216	}
2217
2218	if (phy->type == BWN_PHYTYPE_A) {
2219		pg->pg_rfatt.att = 0x60;
2220		goto done;
2221	}
2222
2223	switch (phy->rf_ver) {
2224	case 0x2050:
2225		switch (phy->rf_rev) {
2226		case 0:
2227			pg->pg_rfatt.att = 5;
2228			goto done;
2229		case 1:
2230			if (phy->type == BWN_PHYTYPE_G) {
2231				if (bus->siba_board_vendor ==
2232				    SIBA_BOARDVENDOR_BCM &&
2233				    bus->siba_board_type ==
2234				    SIBA_BOARD_BCM4309G &&
2235				    bus->siba_board_rev >= 30)
2236					pg->pg_rfatt.att = 3;
2237				else if (bus->siba_board_vendor ==
2238				    SIBA_BOARDVENDOR_BCM &&
2239				    bus->siba_board_type == SIBA_BOARD_BU4306)
2240					pg->pg_rfatt.att = 3;
2241				else
2242					pg->pg_rfatt.att = 1;
2243			} else {
2244				if (bus->siba_board_vendor ==
2245				    SIBA_BOARDVENDOR_BCM &&
2246				    bus->siba_board_type ==
2247				    SIBA_BOARD_BCM4309G &&
2248				    bus->siba_board_rev >= 30)
2249					pg->pg_rfatt.att = 7;
2250				else
2251					pg->pg_rfatt.att = 6;
2252			}
2253			goto done;
2254		case 2:
2255			if (phy->type == BWN_PHYTYPE_G) {
2256				if (bus->siba_board_vendor ==
2257				    SIBA_BOARDVENDOR_BCM &&
2258				    bus->siba_board_type ==
2259				    SIBA_BOARD_BCM4309G &&
2260				    bus->siba_board_rev >= 30)
2261					pg->pg_rfatt.att = 3;
2262				else if (bus->siba_board_vendor ==
2263				    SIBA_BOARDVENDOR_BCM &&
2264				    bus->siba_board_type == SIBA_BOARD_BU4306)
2265					pg->pg_rfatt.att = 5;
2266				else if (bus->siba_chipid == 0x4320)
2267					pg->pg_rfatt.att = 4;
2268				else
2269					pg->pg_rfatt.att = 3;
2270			} else
2271				pg->pg_rfatt.att = 6;
2272			goto done;
2273		case 3:
2274			pg->pg_rfatt.att = 5;
2275			goto done;
2276		case 4:
2277		case 5:
2278			pg->pg_rfatt.att = 1;
2279			goto done;
2280		case 6:
2281		case 7:
2282			pg->pg_rfatt.att = 5;
2283			goto done;
2284		case 8:
2285			pg->pg_rfatt.att = 0xa;
2286			pg->pg_rfatt.padmix = 1;
2287			goto done;
2288		case 9:
2289		default:
2290			pg->pg_rfatt.att = 5;
2291			goto done;
2292		}
2293		break;
2294	case 0x2053:
2295		switch (phy->rf_rev) {
2296		case 1:
2297			pg->pg_rfatt.att = 6;
2298			goto done;
2299		}
2300		break;
2301	}
2302	pg->pg_rfatt.att = 5;
2303done:
2304	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2305
2306	if (!bwn_has_hwpctl(mac)) {
2307		lo->rfatt.array = rfatt0;
2308		lo->rfatt.len = N(rfatt0);
2309		lo->rfatt.min = 0;
2310		lo->rfatt.max = 9;
2311		goto genbbatt;
2312	}
2313	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2314		lo->rfatt.array = rfatt1;
2315		lo->rfatt.len = N(rfatt1);
2316		lo->rfatt.min = 0;
2317		lo->rfatt.max = 14;
2318		goto genbbatt;
2319	}
2320	lo->rfatt.array = rfatt2;
2321	lo->rfatt.len = N(rfatt2);
2322	lo->rfatt.min = 0;
2323	lo->rfatt.max = 9;
2324genbbatt:
2325	lo->bbatt.array = bbatt_0;
2326	lo->bbatt.len = N(bbatt_0);
2327	lo->bbatt.min = 0;
2328	lo->bbatt.max = 8;
2329
2330	BWN_READ_4(mac, BWN_MACCTL);
2331	if (phy->rev == 1) {
2332		phy->gmode = 0;
2333		bwn_reset_core(mac, 0);
2334		bwn_phy_g_init_sub(mac);
2335		phy->gmode = 1;
2336		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2337	}
2338	return (0);
2339}
2340
2341static uint16_t
2342bwn_phy_g_txctl(struct bwn_mac *mac)
2343{
2344	struct bwn_phy *phy = &mac->mac_phy;
2345
2346	if (phy->rf_ver != 0x2050)
2347		return (0);
2348	if (phy->rf_rev == 1)
2349		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2350	if (phy->rf_rev < 6)
2351		return (BWN_TXCTL_PA2DB);
2352	if (phy->rf_rev == 8)
2353		return (BWN_TXCTL_TXMIX);
2354	return (0);
2355}
2356
2357static int
2358bwn_phy_g_init(struct bwn_mac *mac)
2359{
2360
2361	bwn_phy_g_init_sub(mac);
2362	return (0);
2363}
2364
2365static void
2366bwn_phy_g_exit(struct bwn_mac *mac)
2367{
2368	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2369	struct bwn_lo_calib *cal, *tmp;
2370
2371	if (lo == NULL)
2372		return;
2373	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2374		TAILQ_REMOVE(&lo->calib_list, cal, list);
2375		free(cal, M_DEVBUF);
2376	}
2377}
2378
2379static uint16_t
2380bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2381{
2382
2383	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2384	return (BWN_READ_2(mac, BWN_PHYDATA));
2385}
2386
2387static void
2388bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2389{
2390
2391	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2392	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2393}
2394
2395static uint16_t
2396bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2397{
2398
2399	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2400	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2401	return (BWN_READ_2(mac, BWN_RFDATALO));
2402}
2403
2404static void
2405bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2406{
2407
2408	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2409	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2410	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2411}
2412
2413static int
2414bwn_phy_g_hwpctl(struct bwn_mac *mac)
2415{
2416
2417	return (mac->mac_phy.rev >= 6);
2418}
2419
2420static void
2421bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2422{
2423	struct bwn_phy *phy = &mac->mac_phy;
2424	struct bwn_phy_g *pg = &phy->phy_g;
2425	unsigned int channel;
2426	uint16_t rfover, rfoverval;
2427
2428	if (on) {
2429		if (phy->rf_on)
2430			return;
2431
2432		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2433		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2434		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2435		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2436			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2437			    pg->pg_radioctx_over);
2438			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2439			    pg->pg_radioctx_overval);
2440			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2441		}
2442		channel = phy->chan;
2443		bwn_phy_g_switch_chan(mac, 6, 1);
2444		bwn_phy_g_switch_chan(mac, channel, 0);
2445		return;
2446	}
2447
2448	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2449	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2450	pg->pg_radioctx_over = rfover;
2451	pg->pg_radioctx_overval = rfoverval;
2452	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2453	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2454	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2455}
2456
2457static int
2458bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2459{
2460
2461	if ((newchan < 1) || (newchan > 14))
2462		return (EINVAL);
2463	bwn_phy_g_switch_chan(mac, newchan, 0);
2464
2465	return (0);
2466}
2467
2468static uint32_t
2469bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2470{
2471
2472	return (1);
2473}
2474
2475static void
2476bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2477{
2478	struct bwn_phy *phy = &mac->mac_phy;
2479	uint64_t hf;
2480	int autodiv = 0;
2481	uint16_t tmp;
2482
2483	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2484		autodiv = 1;
2485
2486	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2487	bwn_hf_write(mac, hf);
2488
2489	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2490	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2491	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2492		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2493
2494	if (autodiv) {
2495		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2496		if (antenna == BWN_ANTAUTO1)
2497			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2498		else
2499			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2500		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2501	}
2502	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2503	if (autodiv)
2504		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2505	else
2506		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2507	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2508	if (phy->rev >= 2) {
2509		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2510		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2511		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2512		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2513		    0x15);
2514		if (phy->rev == 2)
2515			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2516		else
2517			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2518			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2519			    8);
2520	}
2521	if (phy->rev >= 6)
2522		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2523
2524	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2525	bwn_hf_write(mac, hf);
2526}
2527
2528static int
2529bwn_phy_g_im(struct bwn_mac *mac, int mode)
2530{
2531	struct bwn_phy *phy = &mac->mac_phy;
2532	struct bwn_phy_g *pg = &phy->phy_g;
2533
2534	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2535	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2536
2537	if (phy->rev == 0 || !phy->gmode)
2538		return (ENODEV);
2539
2540	pg->pg_aci_wlan_automatic = 0;
2541	return (0);
2542}
2543
2544static int
2545bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2546{
2547	struct bwn_phy *phy = &mac->mac_phy;
2548	struct bwn_phy_g *pg = &phy->phy_g;
2549	struct bwn_softc *sc = mac->mac_sc;
2550	struct siba_softc *siba = mac->mac_sd->sd_bus;
2551	unsigned int tssi;
2552	int cck, ofdm;
2553	int power;
2554	int rfatt, bbatt;
2555	unsigned int max;
2556
2557	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2558
2559	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2560	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2561	if (cck < 0 && ofdm < 0) {
2562		if (ignore_tssi == 0)
2563			return (BWN_TXPWR_RES_DONE);
2564		cck = 0;
2565		ofdm = 0;
2566	}
2567	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2568	if (pg->pg_avgtssi != 0xff)
2569		tssi = (tssi + pg->pg_avgtssi) / 2;
2570	pg->pg_avgtssi = tssi;
2571	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2572
2573	max = siba->siba_sprom.maxpwr_bg;
2574	if (siba->siba_sprom.bf_lo & BWN_BFL_PACTRL)
2575		max -= 3;
2576	if (max >= 120) {
2577		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2578		siba->siba_sprom.maxpwr_bg = max = 80;
2579	}
2580
2581	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2582	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2583	     tssi, 0x00), 0x3f)]);
2584	if (power == 0)
2585		return (BWN_TXPWR_RES_DONE);
2586
2587	rfatt = -((power + 7) / 8);
2588	bbatt = (-(power / 2)) - (4 * rfatt);
2589	if ((rfatt == 0) && (bbatt == 0))
2590		return (BWN_TXPWR_RES_DONE);
2591	pg->pg_bbatt_delta = bbatt;
2592	pg->pg_rfatt_delta = rfatt;
2593	return (BWN_TXPWR_RES_NEED_ADJUST);
2594}
2595
2596static void
2597bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2598{
2599	struct bwn_phy *phy = &mac->mac_phy;
2600	struct bwn_phy_g *pg = &phy->phy_g;
2601	struct bwn_softc *sc = mac->mac_sc;
2602	int rfatt, bbatt;
2603	uint8_t txctl;
2604
2605	bwn_mac_suspend(mac);
2606
2607	BWN_ASSERT_LOCKED(sc);
2608
2609	bbatt = pg->pg_bbatt.att;
2610	bbatt += pg->pg_bbatt_delta;
2611	rfatt = pg->pg_rfatt.att;
2612	rfatt += pg->pg_rfatt_delta;
2613
2614	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2615	txctl = pg->pg_txctl;
2616	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2617		if (rfatt <= 1) {
2618			if (txctl == 0) {
2619				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2620				rfatt += 2;
2621				bbatt += 2;
2622			} else if (mac->mac_sd->sd_bus->siba_sprom.
2623				   bf_lo &
2624				   BWN_BFL_PACTRL) {
2625				bbatt += 4 * (rfatt - 2);
2626				rfatt = 2;
2627			}
2628		} else if (rfatt > 4 && txctl) {
2629			txctl = 0;
2630			if (bbatt < 3) {
2631				rfatt -= 3;
2632				bbatt += 2;
2633			} else {
2634				rfatt -= 2;
2635				bbatt -= 2;
2636			}
2637		}
2638	}
2639	pg->pg_txctl = txctl;
2640	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2641	pg->pg_rfatt.att = rfatt;
2642	pg->pg_bbatt.att = bbatt;
2643
2644	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2645
2646	bwn_phy_lock(mac);
2647	bwn_rf_lock(mac);
2648	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2649	    pg->pg_txctl);
2650	bwn_rf_unlock(mac);
2651	bwn_phy_unlock(mac);
2652
2653	bwn_mac_enable(mac);
2654}
2655
2656static void
2657bwn_phy_g_task_15s(struct bwn_mac *mac)
2658{
2659	struct bwn_phy *phy = &mac->mac_phy;
2660	struct bwn_phy_g *pg = &phy->phy_g;
2661	struct bwn_softc *sc = mac->mac_sc;
2662	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2663	unsigned long expire, now;
2664	struct bwn_lo_calib *cal, *tmp;
2665	uint8_t expired = 0;
2666
2667	bwn_mac_suspend(mac);
2668
2669	if (lo == NULL)
2670		goto fail;
2671
2672	BWN_GETTIME(now);
2673	if (bwn_has_hwpctl(mac)) {
2674		expire = now - BWN_LO_PWRVEC_EXPIRE;
2675		if (time_before(lo->pwr_vec_read_time, expire)) {
2676			bwn_lo_get_powervector(mac);
2677			bwn_phy_g_dc_lookup_init(mac, 0);
2678		}
2679		goto fail;
2680	}
2681
2682	expire = now - BWN_LO_CALIB_EXPIRE;
2683	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2684		if (!time_before(cal->calib_time, expire))
2685			continue;
2686		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2687		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2688			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2689			expired = 1;
2690		}
2691
2692		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2693		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2694		    cal->ctl.i, cal->ctl.q);
2695
2696		TAILQ_REMOVE(&lo->calib_list, cal, list);
2697		free(cal, M_DEVBUF);
2698	}
2699	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2700		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2701		    &pg->pg_rfatt);
2702		if (cal == NULL) {
2703			device_printf(sc->sc_dev,
2704			    "failed to recalibrate LO\n");
2705			goto fail;
2706		}
2707		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2708		bwn_lo_write(mac, &cal->ctl);
2709	}
2710
2711fail:
2712	bwn_mac_enable(mac);
2713}
2714
2715static void
2716bwn_phy_g_task_60s(struct bwn_mac *mac)
2717{
2718	struct bwn_phy *phy = &mac->mac_phy;
2719	uint8_t old = phy->chan;
2720
2721	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI))
2722		return;
2723
2724	bwn_mac_suspend(mac);
2725	bwn_nrssi_slope_11g(mac);
2726	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2727		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2728		bwn_switch_channel(mac, old);
2729	}
2730	bwn_mac_enable(mac);
2731}
2732
2733static void
2734bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2735{
2736
2737	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2738}
2739
2740static int
2741bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2742	const struct ieee80211_bpf_params *params)
2743{
2744	struct ieee80211com *ic = ni->ni_ic;
2745	struct ifnet *ifp = ic->ic_ifp;
2746	struct bwn_softc *sc = ifp->if_softc;
2747	struct bwn_mac *mac = sc->sc_curmac;
2748
2749	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2750	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2751		ieee80211_free_node(ni);
2752		m_freem(m);
2753		return (ENETDOWN);
2754	}
2755
2756	BWN_LOCK(sc);
2757	if (bwn_tx_isfull(sc, m)) {
2758		ieee80211_free_node(ni);
2759		m_freem(m);
2760		ifp->if_oerrors++;
2761		BWN_UNLOCK(sc);
2762		return (ENOBUFS);
2763	}
2764
2765	if (bwn_tx_start(sc, ni, m) != 0) {
2766		if (ni != NULL)
2767			ieee80211_free_node(ni);
2768		ifp->if_oerrors++;
2769	}
2770	sc->sc_watchdog_timer = 5;
2771	BWN_UNLOCK(sc);
2772	return (0);
2773}
2774
2775/*
2776 * Setup driver-specific state for a newly associated node.
2777 * Note that we're called also on a re-associate, the isnew
2778 * param tells us if this is the first time or not.
2779 */
2780static void
2781bwn_newassoc(struct ieee80211_node *ni, int isnew)
2782{
2783	struct ieee80211vap *vap = ni->ni_vap;
2784
2785	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2786	    &BWN_NODE(ni)->bn_amn, ni);
2787}
2788
2789/*
2790 * Callback from the 802.11 layer to update the slot time
2791 * based on the current setting.  We use it to notify the
2792 * firmware of ERP changes and the f/w takes care of things
2793 * like slot time and preamble.
2794 */
2795static void
2796bwn_updateslot(struct ifnet *ifp)
2797{
2798	struct bwn_softc *sc = ifp->if_softc;
2799	struct ieee80211com *ic = ifp->if_l2com;
2800	struct bwn_mac *mac;
2801
2802	BWN_LOCK(sc);
2803	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2804		mac = (struct bwn_mac *)sc->sc_curmac;
2805		bwn_set_slot_time(mac,
2806		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2807	}
2808	BWN_UNLOCK(sc);
2809}
2810
2811/*
2812 * Callback from the 802.11 layer after a promiscuous mode change.
2813 * Note this interface does not check the operating mode as this
2814 * is an internal callback and we are expected to honor the current
2815 * state (e.g. this is used for setting the interface in promiscuous
2816 * mode when operating in hostap mode to do ACS).
2817 */
2818static void
2819bwn_update_promisc(struct ifnet *ifp)
2820{
2821	struct bwn_softc *sc = ifp->if_softc;
2822	struct bwn_mac *mac = sc->sc_curmac;
2823
2824	BWN_LOCK(sc);
2825	mac = sc->sc_curmac;
2826	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2827		if (ifp->if_flags & IFF_PROMISC)
2828			sc->sc_filters |= BWN_MACCTL_PROMISC;
2829		else
2830			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2831		bwn_set_opmode(mac);
2832	}
2833	BWN_UNLOCK(sc);
2834}
2835
2836/*
2837 * Callback from the 802.11 layer to update WME parameters.
2838 */
2839static int
2840bwn_wme_update(struct ieee80211com *ic)
2841{
2842	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2843	struct bwn_mac *mac = sc->sc_curmac;
2844	struct wmeParams *wmep;
2845	int i;
2846
2847	BWN_LOCK(sc);
2848	mac = sc->sc_curmac;
2849	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2850		bwn_mac_suspend(mac);
2851		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2852			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2853			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2854		}
2855		bwn_mac_enable(mac);
2856	}
2857	BWN_UNLOCK(sc);
2858	return (0);
2859}
2860
2861static struct ieee80211_node *
2862bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2863{
2864	struct ieee80211com *ic = vap->iv_ic;
2865	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2866	const size_t space = sizeof(struct bwn_node);
2867	struct bwn_node *bn;
2868
2869	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2870	if (bn == NULL) {
2871		/* XXX stat+msg */
2872		return (NULL);
2873	}
2874	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2875	return (&bn->bn_node);
2876}
2877
2878static void
2879bwn_node_cleanup(struct ieee80211_node *ni)
2880{
2881	struct ieee80211com *ic = ni->ni_ic;
2882	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2883
2884	sc->sc_node_cleanup(ni);
2885}
2886
2887static void
2888bwn_scan_start(struct ieee80211com *ic)
2889{
2890	struct ifnet *ifp = ic->ic_ifp;
2891	struct bwn_softc *sc = ifp->if_softc;
2892	struct bwn_mac *mac;
2893
2894	BWN_LOCK(sc);
2895	mac = sc->sc_curmac;
2896	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2897		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2898		bwn_set_opmode(mac);
2899		/* disable CFP update during scan */
2900		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2901	}
2902	BWN_UNLOCK(sc);
2903}
2904
2905static void
2906bwn_scan_end(struct ieee80211com *ic)
2907{
2908	struct ifnet *ifp = ic->ic_ifp;
2909	struct bwn_softc *sc = ifp->if_softc;
2910	struct bwn_mac *mac;
2911
2912	BWN_LOCK(sc);
2913	mac = sc->sc_curmac;
2914	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2915		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2916		bwn_set_opmode(mac);
2917		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2918	}
2919	BWN_UNLOCK(sc);
2920}
2921
2922static void
2923bwn_set_channel(struct ieee80211com *ic)
2924{
2925	struct ifnet *ifp = ic->ic_ifp;
2926	struct bwn_softc *sc = ifp->if_softc;
2927	struct bwn_mac *mac = sc->sc_curmac;
2928	struct bwn_phy *phy = &mac->mac_phy;
2929	int chan, error;
2930
2931	BWN_LOCK(sc);
2932
2933	error = bwn_switch_band(sc, ic->ic_curchan);
2934	if (error)
2935		goto fail;;
2936	bwn_mac_suspend(mac);
2937	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2938	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2939	if (chan != phy->chan)
2940		bwn_switch_channel(mac, chan);
2941
2942	/* TX power level */
2943	if (ic->ic_curchan->ic_maxpower != 0 &&
2944	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2945		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2946		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2947		    BWN_TXPWR_IGNORE_TSSI);
2948	}
2949
2950	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2951	if (phy->set_antenna)
2952		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2953
2954	if (sc->sc_rf_enabled != phy->rf_on) {
2955		if (sc->sc_rf_enabled) {
2956			bwn_rf_turnon(mac);
2957			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2958				device_printf(sc->sc_dev,
2959				    "please turns on the RF switch\n");
2960		} else
2961			bwn_rf_turnoff(mac);
2962	}
2963
2964	bwn_mac_enable(mac);
2965
2966fail:
2967	/*
2968	 * Setup radio tap channel freq and flags
2969	 */
2970	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2971		htole16(ic->ic_curchan->ic_freq);
2972	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2973		htole16(ic->ic_curchan->ic_flags & 0xffff);
2974
2975	BWN_UNLOCK(sc);
2976}
2977
2978static struct ieee80211vap *
2979bwn_vap_create(struct ieee80211com *ic,
2980	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2981	const uint8_t bssid[IEEE80211_ADDR_LEN],
2982	const uint8_t mac0[IEEE80211_ADDR_LEN])
2983{
2984	struct ifnet *ifp = ic->ic_ifp;
2985	struct bwn_softc *sc = ifp->if_softc;
2986	struct ieee80211vap *vap;
2987	struct bwn_vap *bvp;
2988	uint8_t mac[IEEE80211_ADDR_LEN];
2989
2990	IEEE80211_ADDR_COPY(mac, mac0);
2991	switch (opmode) {
2992	case IEEE80211_M_HOSTAP:
2993	case IEEE80211_M_MBSS:
2994	case IEEE80211_M_STA:
2995	case IEEE80211_M_WDS:
2996	case IEEE80211_M_MONITOR:
2997	case IEEE80211_M_IBSS:
2998	case IEEE80211_M_AHDEMO:
2999		break;
3000	default:
3001		return (NULL);
3002	}
3003
3004	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3005
3006	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3007	    M_80211_VAP, M_NOWAIT | M_ZERO);
3008	if (bvp == NULL) {
3009		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3010		return (NULL);
3011	}
3012	vap = &bvp->bv_vap;
3013	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3014	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3015	/* override with driver methods */
3016	bvp->bv_newstate = vap->iv_newstate;
3017	vap->iv_newstate = bwn_newstate;
3018
3019	/* override max aid so sta's cannot assoc when we're out of sta id's */
3020	vap->iv_max_aid = BWN_STAID_MAX;
3021
3022	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3023	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3024	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3025	    500 /*ms*/);
3026
3027	/* complete setup */
3028	ieee80211_vap_attach(vap, ieee80211_media_change,
3029	    ieee80211_media_status);
3030	return (vap);
3031}
3032
3033static void
3034bwn_vap_delete(struct ieee80211vap *vap)
3035{
3036	struct bwn_vap *bvp = BWN_VAP(vap);
3037
3038	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3039	ieee80211_vap_detach(vap);
3040	free(bvp, M_80211_VAP);
3041}
3042
3043static void
3044bwn_init(void *arg)
3045{
3046	struct bwn_softc *sc = arg;
3047	struct ifnet *ifp = sc->sc_ifp;
3048	struct ieee80211com *ic = ifp->if_l2com;
3049	int error = 0;
3050
3051	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3052		__func__, ifp->if_flags);
3053
3054	BWN_LOCK(sc);
3055	error = bwn_init_locked(sc);
3056	BWN_UNLOCK(sc);
3057
3058	if (error == 0)
3059		ieee80211_start_all(ic);	/* start all vap's */
3060}
3061
3062static int
3063bwn_init_locked(struct bwn_softc *sc)
3064{
3065	struct bwn_mac *mac;
3066	struct ifnet *ifp = sc->sc_ifp;
3067	int error;
3068
3069	BWN_ASSERT_LOCKED(sc);
3070
3071	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3072	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3073	sc->sc_filters = 0;
3074	bwn_wme_clear(sc);
3075	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3076	sc->sc_rf_enabled = 1;
3077
3078	mac = sc->sc_curmac;
3079	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3080		error = bwn_core_init(mac);
3081		if (error != 0)
3082			return (error);
3083	}
3084	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3085		bwn_core_start(mac);
3086
3087	bwn_set_opmode(mac);
3088	bwn_set_pretbtt(mac);
3089	bwn_spu_setdelay(mac, 0);
3090	bwn_set_macaddr(mac);
3091
3092	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3093	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3094	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3095
3096	return (0);
3097}
3098
3099static void
3100bwn_stop(struct bwn_softc *sc, int statechg)
3101{
3102
3103	BWN_LOCK(sc);
3104	bwn_stop_locked(sc, statechg);
3105	BWN_UNLOCK(sc);
3106}
3107
3108static void
3109bwn_stop_locked(struct bwn_softc *sc, int statechg)
3110{
3111	struct bwn_mac *mac = sc->sc_curmac;
3112	struct ifnet *ifp = sc->sc_ifp;
3113
3114	BWN_ASSERT_LOCKED(sc);
3115
3116	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3117		/* XXX FIXME opmode not based on VAP */
3118		bwn_set_opmode(mac);
3119		bwn_set_macaddr(mac);
3120	}
3121
3122	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3123		bwn_core_stop(mac);
3124
3125	callout_stop(&sc->sc_led_blink_ch);
3126	sc->sc_led_blinking = 0;
3127
3128	bwn_core_exit(mac);
3129	sc->sc_rf_enabled = 0;
3130
3131	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3132}
3133
3134static void
3135bwn_wme_clear(struct bwn_softc *sc)
3136{
3137#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3138	struct wmeParams *p;
3139	unsigned int i;
3140
3141	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3142	    ("%s:%d: fail", __func__, __LINE__));
3143
3144	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3145		p = &(sc->sc_wmeParams[i]);
3146
3147		switch (bwn_wme_shm_offsets[i]) {
3148		case BWN_WME_VOICE:
3149			p->wmep_txopLimit = 0;
3150			p->wmep_aifsn = 2;
3151			/* XXX FIXME: log2(cwmin) */
3152			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3153			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3154			break;
3155		case BWN_WME_VIDEO:
3156			p->wmep_txopLimit = 0;
3157			p->wmep_aifsn = 2;
3158			/* XXX FIXME: log2(cwmin) */
3159			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3160			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3161			break;
3162		case BWN_WME_BESTEFFORT:
3163			p->wmep_txopLimit = 0;
3164			p->wmep_aifsn = 3;
3165			/* XXX FIXME: log2(cwmin) */
3166			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3167			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3168			break;
3169		case BWN_WME_BACKGROUND:
3170			p->wmep_txopLimit = 0;
3171			p->wmep_aifsn = 7;
3172			/* XXX FIXME: log2(cwmin) */
3173			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3174			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3175			break;
3176		default:
3177			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3178		}
3179	}
3180}
3181
3182static int
3183bwn_core_init(struct bwn_mac *mac)
3184{
3185#ifdef BWN_DEBUG
3186	struct bwn_softc *sc = mac->mac_sc;
3187#endif
3188	struct siba_dev_softc *sd = mac->mac_sd;
3189	struct siba_softc *siba = sd->sd_bus;
3190	struct siba_sprom *sprom = &siba->siba_sprom;
3191	uint64_t hf;
3192	int error;
3193
3194	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3195	    ("%s:%d: fail", __func__, __LINE__));
3196
3197	siba_powerup(siba, 0);
3198	if (!siba_dev_isup(sd))
3199		bwn_reset_core(mac,
3200		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3201
3202	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3203	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3204	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3205	BWN_GETTIME(mac->mac_phy.nexttime);
3206	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3207	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3208	mac->mac_stats.link_noise = -95;
3209	mac->mac_reason_intr = 0;
3210	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3211	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3212#ifdef BWN_DEBUG
3213	if (sc->sc_debug & BWN_DEBUG_XMIT)
3214		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3215#endif
3216	mac->mac_suspended = 1;
3217	mac->mac_task_state = 0;
3218	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3219
3220	mac->mac_phy.init_pre(mac);
3221
3222	siba_pcicore_intr(&siba->siba_pci, sd);
3223
3224	bwn_fix_imcfglobug(mac);
3225	bwn_bt_disable(mac);
3226	if (mac->mac_phy.prepare_hw) {
3227		error = mac->mac_phy.prepare_hw(mac);
3228		if (error)
3229			goto fail0;
3230	}
3231	error = bwn_chip_init(mac);
3232	if (error)
3233		goto fail0;
3234	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3235	    mac->mac_sd->sd_id.sd_rev);
3236	hf = bwn_hf_read(mac);
3237	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3238		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3239		if (sprom->bf_lo & BWN_BFL_PACTRL)
3240			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3241		if (mac->mac_phy.rev == 1)
3242			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3243	}
3244	if (mac->mac_phy.rf_ver == 0x2050) {
3245		if (mac->mac_phy.rf_rev < 6)
3246			hf |= BWN_HF_FORCE_VCO_RECALC;
3247		if (mac->mac_phy.rf_rev == 6)
3248			hf |= BWN_HF_4318_TSSI;
3249	}
3250	if (sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW)
3251		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3252	if ((siba->siba_type == SIBA_TYPE_PCI) &&
3253	    (siba->siba_pci.spc_dev->sd_id.sd_rev <= 10))
3254		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3255	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3256	bwn_hf_write(mac, hf);
3257
3258	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3259	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3260	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3261	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3262
3263	bwn_rate_init(mac);
3264	bwn_set_phytxctl(mac);
3265
3266	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3267	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3268	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3269
3270	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3271		bwn_pio_init(mac);
3272	else
3273		bwn_dma_init(mac);
3274	if (error)
3275		goto fail1;
3276	bwn_wme_init(mac);
3277	bwn_spu_setdelay(mac, 1);
3278	bwn_bt_enable(mac);
3279
3280	siba_powerup(siba, !(sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW));
3281	bwn_set_macaddr(mac);
3282	bwn_crypt_init(mac);
3283
3284	/* XXX LED initializatin */
3285
3286	mac->mac_status = BWN_MAC_STATUS_INITED;
3287
3288	return (error);
3289
3290fail1:
3291	bwn_chip_exit(mac);
3292fail0:
3293	siba_powerdown(siba);
3294	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3295	    ("%s:%d: fail", __func__, __LINE__));
3296	return (error);
3297}
3298
3299static void
3300bwn_core_start(struct bwn_mac *mac)
3301{
3302	struct bwn_softc *sc = mac->mac_sc;
3303	uint32_t tmp;
3304
3305	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3306	    ("%s:%d: fail", __func__, __LINE__));
3307
3308	if (mac->mac_sd->sd_id.sd_rev < 5)
3309		return;
3310
3311	while (1) {
3312		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3313		if (!(tmp & 0x00000001))
3314			break;
3315		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3316	}
3317
3318	bwn_mac_enable(mac);
3319	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3320	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3321
3322	mac->mac_status = BWN_MAC_STATUS_STARTED;
3323}
3324
3325static void
3326bwn_core_exit(struct bwn_mac *mac)
3327{
3328	uint32_t macctl;
3329
3330	BWN_ASSERT_LOCKED(mac->mac_sc);
3331
3332	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3333	    ("%s:%d: fail", __func__, __LINE__));
3334
3335	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3336		return;
3337	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3338
3339	macctl = BWN_READ_4(mac, BWN_MACCTL);
3340	macctl &= ~BWN_MACCTL_MCODE_RUN;
3341	macctl |= BWN_MACCTL_MCODE_JMP0;
3342	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3343
3344	bwn_dma_stop(mac);
3345	bwn_pio_stop(mac);
3346	bwn_chip_exit(mac);
3347	mac->mac_phy.switch_analog(mac, 0);
3348	siba_dev_down(mac->mac_sd, 0);
3349	siba_powerdown(mac->mac_sd->sd_bus);
3350}
3351
3352static void
3353bwn_fix_imcfglobug(struct bwn_mac *mac)
3354{
3355	struct siba_dev_softc *sd = mac->mac_sd;
3356	struct siba_softc *siba = sd->sd_bus;
3357	uint32_t tmp;
3358
3359	if (siba->siba_pci.spc_dev == NULL)
3360		return;
3361	if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI ||
3362	    siba->siba_pci.spc_dev->sd_id.sd_rev > 5)
3363		return;
3364
3365	tmp = siba_read_4(sd, SIBA_IMCFGLO) &
3366	    ~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO);
3367	switch (siba->siba_type) {
3368	case SIBA_TYPE_PCI:
3369	case SIBA_TYPE_PCMCIA:
3370		tmp |= 0x32;
3371		break;
3372	case SIBA_TYPE_SSB:
3373		tmp |= 0x53;
3374		break;
3375	}
3376	siba_write_4(sd, SIBA_IMCFGLO, tmp);
3377}
3378
3379static void
3380bwn_bt_disable(struct bwn_mac *mac)
3381{
3382	struct bwn_softc *sc = mac->mac_sc;
3383
3384	(void)sc;
3385	/* XXX do nothing yet */
3386}
3387
3388static int
3389bwn_chip_init(struct bwn_mac *mac)
3390{
3391	struct bwn_phy *phy = &mac->mac_phy;
3392	uint32_t macctl;
3393	int error;
3394
3395	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3396	if (phy->gmode)
3397		macctl |= BWN_MACCTL_GMODE;
3398	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3399
3400	error = bwn_fw_fillinfo(mac);
3401	if (error)
3402		return (error);
3403	error = bwn_fw_loaducode(mac);
3404	if (error)
3405		return (error);
3406
3407	error = bwn_gpio_init(mac);
3408	if (error)
3409		return (error);
3410
3411	error = bwn_fw_loadinitvals(mac);
3412	if (error) {
3413		bwn_gpio_cleanup(mac);
3414		return (error);
3415	}
3416	phy->switch_analog(mac, 1);
3417	error = bwn_phy_init(mac);
3418	if (error) {
3419		bwn_gpio_cleanup(mac);
3420		return (error);
3421	}
3422	if (phy->set_im)
3423		phy->set_im(mac, BWN_IMMODE_NONE);
3424	if (phy->set_antenna)
3425		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3426	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3427
3428	if (phy->type == BWN_PHYTYPE_B)
3429		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3430	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3431	if (mac->mac_sd->sd_id.sd_rev < 5)
3432		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3433
3434	BWN_WRITE_4(mac, BWN_MACCTL,
3435	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3436	BWN_WRITE_4(mac, BWN_MACCTL,
3437	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3438	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3439
3440	bwn_set_opmode(mac);
3441	if (mac->mac_sd->sd_id.sd_rev < 3) {
3442		BWN_WRITE_2(mac, 0x060e, 0x0000);
3443		BWN_WRITE_2(mac, 0x0610, 0x8000);
3444		BWN_WRITE_2(mac, 0x0604, 0x0000);
3445		BWN_WRITE_2(mac, 0x0606, 0x0200);
3446	} else {
3447		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3448		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3449	}
3450	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3451	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3452	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3453	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3454	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3455	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3456	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3457	siba_write_4(mac->mac_sd, SIBA_TGSLOW,
3458	    siba_read_4(mac->mac_sd, SIBA_TGSLOW) | 0x00100000);
3459	BWN_WRITE_2(mac, BWN_POWERUP_DELAY,
3460	    mac->mac_sd->sd_bus->siba_cc.scc_powerup_delay);
3461	return (error);
3462}
3463
3464/* read hostflags */
3465static uint64_t
3466bwn_hf_read(struct bwn_mac *mac)
3467{
3468	uint64_t ret;
3469
3470	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3471	ret <<= 16;
3472	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3473	ret <<= 16;
3474	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3475	return (ret);
3476}
3477
3478static void
3479bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3480{
3481
3482	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3483	    (value & 0x00000000ffffull));
3484	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3485	    (value & 0x0000ffff0000ull) >> 16);
3486	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3487	    (value & 0xffff00000000ULL) >> 32);
3488}
3489
3490static void
3491bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3492{
3493
3494	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3495	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3496}
3497
3498static void
3499bwn_rate_init(struct bwn_mac *mac)
3500{
3501
3502	switch (mac->mac_phy.type) {
3503	case BWN_PHYTYPE_A:
3504	case BWN_PHYTYPE_G:
3505	case BWN_PHYTYPE_LP:
3506	case BWN_PHYTYPE_N:
3507		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3508		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3509		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3510		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3511		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3512		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3513		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3514		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3515			break;
3516		/* FALLTHROUGH */
3517	case BWN_PHYTYPE_B:
3518		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3519		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3520		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3521		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3522		break;
3523	default:
3524		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3525	}
3526}
3527
3528static void
3529bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3530{
3531	uint16_t offset;
3532
3533	if (ofdm) {
3534		offset = 0x480;
3535		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3536	} else {
3537		offset = 0x4c0;
3538		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3539	}
3540	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3541	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3542}
3543
3544static uint8_t
3545bwn_plcp_getcck(const uint8_t bitrate)
3546{
3547
3548	switch (bitrate) {
3549	case BWN_CCK_RATE_1MB:
3550		return (0x0a);
3551	case BWN_CCK_RATE_2MB:
3552		return (0x14);
3553	case BWN_CCK_RATE_5MB:
3554		return (0x37);
3555	case BWN_CCK_RATE_11MB:
3556		return (0x6e);
3557	}
3558	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3559	return (0);
3560}
3561
3562static uint8_t
3563bwn_plcp_getofdm(const uint8_t bitrate)
3564{
3565
3566	switch (bitrate) {
3567	case BWN_OFDM_RATE_6MB:
3568		return (0xb);
3569	case BWN_OFDM_RATE_9MB:
3570		return (0xf);
3571	case BWN_OFDM_RATE_12MB:
3572		return (0xa);
3573	case BWN_OFDM_RATE_18MB:
3574		return (0xe);
3575	case BWN_OFDM_RATE_24MB:
3576		return (0x9);
3577	case BWN_OFDM_RATE_36MB:
3578		return (0xd);
3579	case BWN_OFDM_RATE_48MB:
3580		return (0x8);
3581	case BWN_OFDM_RATE_54MB:
3582		return (0xc);
3583	}
3584	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3585	return (0);
3586}
3587
3588static void
3589bwn_set_phytxctl(struct bwn_mac *mac)
3590{
3591	uint16_t ctl;
3592
3593	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3594	    BWN_TX_PHY_TXPWR);
3595	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3596	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3597	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3598}
3599
3600static void
3601bwn_pio_init(struct bwn_mac *mac)
3602{
3603	struct bwn_pio *pio = &mac->mac_method.pio;
3604
3605	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3606	    & ~BWN_MACCTL_BIGENDIAN);
3607	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3608
3609	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3610	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3611	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3612	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3613	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3614	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3615}
3616
3617static void
3618bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3619    int index)
3620{
3621	struct bwn_pio_txpkt *tp;
3622	unsigned int i;
3623
3624	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3625	tq->tq_index = index;
3626
3627	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3628	if (mac->mac_sd->sd_id.sd_rev >= 8)
3629		tq->tq_size = 1920;
3630	else {
3631		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3632		tq->tq_size -= 80;
3633	}
3634
3635	TAILQ_INIT(&tq->tq_pktlist);
3636	for (i = 0; i < N(tq->tq_pkts); i++) {
3637		tp = &(tq->tq_pkts[i]);
3638		tp->tp_index = i;
3639		tp->tp_queue = tq;
3640		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3641	}
3642}
3643
3644static uint16_t
3645bwn_pio_idx2base(struct bwn_mac *mac, int index)
3646{
3647	struct bwn_softc *sc = mac->mac_sc;
3648	static const uint16_t bases[] = {
3649		BWN_PIO_BASE0,
3650		BWN_PIO_BASE1,
3651		BWN_PIO_BASE2,
3652		BWN_PIO_BASE3,
3653		BWN_PIO_BASE4,
3654		BWN_PIO_BASE5,
3655		BWN_PIO_BASE6,
3656		BWN_PIO_BASE7,
3657	};
3658	static const uint16_t bases_rev11[] = {
3659		BWN_PIO11_BASE0,
3660		BWN_PIO11_BASE1,
3661		BWN_PIO11_BASE2,
3662		BWN_PIO11_BASE3,
3663		BWN_PIO11_BASE4,
3664		BWN_PIO11_BASE5,
3665	};
3666
3667	if (mac->mac_sd->sd_id.sd_rev >= 11) {
3668		if (index >= N(bases_rev11))
3669			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3670		return (bases_rev11[index]);
3671	}
3672	if (index >= N(bases))
3673		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3674	return (bases[index]);
3675}
3676
3677static void
3678bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3679    int index)
3680{
3681
3682	prq->prq_mac = mac;
3683	prq->prq_rev = mac->mac_sd->sd_id.sd_rev;
3684	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3685	bwn_dma_rxdirectfifo(mac, index, 1);
3686}
3687
3688static void
3689bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3690{
3691	if (tq == NULL)
3692		return;
3693	bwn_pio_cancel_tx_packets(tq);
3694}
3695
3696static void
3697bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3698{
3699
3700	bwn_destroy_pioqueue_tx(pio);
3701}
3702
3703static uint16_t
3704bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3705    uint16_t offset)
3706{
3707
3708	return (BWN_READ_2(mac, tq->tq_base + offset));
3709}
3710
3711static void
3712bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3713{
3714	uint32_t ctl;
3715	int type;
3716	uint16_t base;
3717
3718	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3719	base = bwn_dma_base(type, idx);
3720	if (type == BWN_DMA_64BIT) {
3721		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3722		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3723		if (enable)
3724			ctl |= BWN_DMA64_RXDIRECTFIFO;
3725		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3726	} else {
3727		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3728		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3729		if (enable)
3730			ctl |= BWN_DMA32_RXDIRECTFIFO;
3731		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3732	}
3733}
3734
3735static uint64_t
3736bwn_dma_mask(struct bwn_mac *mac)
3737{
3738	uint32_t tmp;
3739	uint16_t base;
3740
3741	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3742	if (tmp & SIBA_TGSHIGH_DMA64)
3743		return (BWN_DMA_BIT_MASK(64));
3744	base = bwn_dma_base(0, 0);
3745	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3746	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3747	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3748		return (BWN_DMA_BIT_MASK(32));
3749
3750	return (BWN_DMA_BIT_MASK(30));
3751}
3752
3753static int
3754bwn_dma_mask2type(uint64_t dmamask)
3755{
3756
3757	if (dmamask == BWN_DMA_BIT_MASK(30))
3758		return (BWN_DMA_30BIT);
3759	if (dmamask == BWN_DMA_BIT_MASK(32))
3760		return (BWN_DMA_32BIT);
3761	if (dmamask == BWN_DMA_BIT_MASK(64))
3762		return (BWN_DMA_64BIT);
3763	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3764	return (BWN_DMA_30BIT);
3765}
3766
3767static void
3768bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3769{
3770	struct bwn_pio_txpkt *tp;
3771	unsigned int i;
3772
3773	for (i = 0; i < N(tq->tq_pkts); i++) {
3774		tp = &(tq->tq_pkts[i]);
3775		if (tp->tp_m) {
3776			m_freem(tp->tp_m);
3777			tp->tp_m = NULL;
3778		}
3779	}
3780}
3781
3782static uint16_t
3783bwn_dma_base(int type, int controller_idx)
3784{
3785	static const uint16_t map64[] = {
3786		BWN_DMA64_BASE0,
3787		BWN_DMA64_BASE1,
3788		BWN_DMA64_BASE2,
3789		BWN_DMA64_BASE3,
3790		BWN_DMA64_BASE4,
3791		BWN_DMA64_BASE5,
3792	};
3793	static const uint16_t map32[] = {
3794		BWN_DMA32_BASE0,
3795		BWN_DMA32_BASE1,
3796		BWN_DMA32_BASE2,
3797		BWN_DMA32_BASE3,
3798		BWN_DMA32_BASE4,
3799		BWN_DMA32_BASE5,
3800	};
3801
3802	if (type == BWN_DMA_64BIT) {
3803		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3804		    ("%s:%d: fail", __func__, __LINE__));
3805		return (map64[controller_idx]);
3806	}
3807	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3808	    ("%s:%d: fail", __func__, __LINE__));
3809	return (map32[controller_idx]);
3810}
3811
3812static void
3813bwn_dma_init(struct bwn_mac *mac)
3814{
3815	struct bwn_dma *dma = &mac->mac_method.dma;
3816
3817	/* setup TX DMA channels. */
3818	bwn_dma_setup(dma->wme[WME_AC_BK]);
3819	bwn_dma_setup(dma->wme[WME_AC_BE]);
3820	bwn_dma_setup(dma->wme[WME_AC_VI]);
3821	bwn_dma_setup(dma->wme[WME_AC_VO]);
3822	bwn_dma_setup(dma->mcast);
3823	/* setup RX DMA channel. */
3824	bwn_dma_setup(dma->rx);
3825}
3826
3827static struct bwn_dma_ring *
3828bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3829    int for_tx, int type)
3830{
3831	struct bwn_dma *dma = &mac->mac_method.dma;
3832	struct bwn_dma_ring *dr;
3833	struct bwn_dmadesc_generic *desc;
3834	struct bwn_dmadesc_meta *mt;
3835	struct bwn_softc *sc = mac->mac_sc;
3836	int error, i;
3837
3838	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3839	if (dr == NULL)
3840		goto out;
3841	dr->dr_numslots = BWN_RXRING_SLOTS;
3842	if (for_tx)
3843		dr->dr_numslots = BWN_TXRING_SLOTS;
3844
3845	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3846	    M_DEVBUF, M_NOWAIT | M_ZERO);
3847	if (dr->dr_meta == NULL)
3848		goto fail0;
3849
3850	dr->dr_type = type;
3851	dr->dr_mac = mac;
3852	dr->dr_base = bwn_dma_base(type, controller_index);
3853	dr->dr_index = controller_index;
3854	if (type == BWN_DMA_64BIT) {
3855		dr->getdesc = bwn_dma_64_getdesc;
3856		dr->setdesc = bwn_dma_64_setdesc;
3857		dr->start_transfer = bwn_dma_64_start_transfer;
3858		dr->suspend = bwn_dma_64_suspend;
3859		dr->resume = bwn_dma_64_resume;
3860		dr->get_curslot = bwn_dma_64_get_curslot;
3861		dr->set_curslot = bwn_dma_64_set_curslot;
3862	} else {
3863		dr->getdesc = bwn_dma_32_getdesc;
3864		dr->setdesc = bwn_dma_32_setdesc;
3865		dr->start_transfer = bwn_dma_32_start_transfer;
3866		dr->suspend = bwn_dma_32_suspend;
3867		dr->resume = bwn_dma_32_resume;
3868		dr->get_curslot = bwn_dma_32_get_curslot;
3869		dr->set_curslot = bwn_dma_32_set_curslot;
3870	}
3871	if (for_tx) {
3872		dr->dr_tx = 1;
3873		dr->dr_curslot = -1;
3874	} else {
3875		if (dr->dr_index == 0) {
3876			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3877			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3878		} else
3879			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3880	}
3881
3882	error = bwn_dma_allocringmemory(dr);
3883	if (error)
3884		goto fail2;
3885
3886	if (for_tx) {
3887		/*
3888		 * Assumption: BWN_TXRING_SLOTS can be divided by
3889		 * BWN_TX_SLOTS_PER_FRAME
3890		 */
3891		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3892		    ("%s:%d: fail", __func__, __LINE__));
3893
3894		dr->dr_txhdr_cache =
3895		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3896			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3897		KASSERT(dr->dr_txhdr_cache != NULL,
3898		    ("%s:%d: fail", __func__, __LINE__));
3899
3900		/*
3901		 * Create TX ring DMA stuffs
3902		 */
3903		error = bus_dma_tag_create(dma->parent_dtag,
3904				    BWN_ALIGN, 0,
3905				    BUS_SPACE_MAXADDR,
3906				    BUS_SPACE_MAXADDR,
3907				    NULL, NULL,
3908				    BWN_HDRSIZE(mac),
3909				    1,
3910				    BUS_SPACE_MAXSIZE_32BIT,
3911				    0,
3912				    NULL, NULL,
3913				    &dr->dr_txring_dtag);
3914		if (error) {
3915			device_printf(sc->sc_dev,
3916			    "can't create TX ring DMA tag: TODO frees\n");
3917			goto fail1;
3918		}
3919
3920		for (i = 0; i < dr->dr_numslots; i += 2) {
3921			dr->getdesc(dr, i, &desc, &mt);
3922
3923			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3924			mt->mt_m = NULL;
3925			mt->mt_ni = NULL;
3926			mt->mt_islast = 0;
3927			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3928			    &mt->mt_dmap);
3929			if (error) {
3930				device_printf(sc->sc_dev,
3931				     "can't create RX buf DMA map\n");
3932				goto fail1;
3933			}
3934
3935			dr->getdesc(dr, i + 1, &desc, &mt);
3936
3937			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3938			mt->mt_m = NULL;
3939			mt->mt_ni = NULL;
3940			mt->mt_islast = 1;
3941			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3942			    &mt->mt_dmap);
3943			if (error) {
3944				device_printf(sc->sc_dev,
3945				     "can't create RX buf DMA map\n");
3946				goto fail1;
3947			}
3948		}
3949	} else {
3950		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3951		    &dr->dr_spare_dmap);
3952		if (error) {
3953			device_printf(sc->sc_dev,
3954			    "can't create RX buf DMA map\n");
3955			goto out;		/* XXX wrong! */
3956		}
3957
3958		for (i = 0; i < dr->dr_numslots; i++) {
3959			dr->getdesc(dr, i, &desc, &mt);
3960
3961			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3962			    &mt->mt_dmap);
3963			if (error) {
3964				device_printf(sc->sc_dev,
3965				    "can't create RX buf DMA map\n");
3966				goto out;	/* XXX wrong! */
3967			}
3968			error = bwn_dma_newbuf(dr, desc, mt, 1);
3969			if (error) {
3970				device_printf(sc->sc_dev,
3971				    "failed to allocate RX buf\n");
3972				goto out;	/* XXX wrong! */
3973			}
3974		}
3975
3976		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3977		    BUS_DMASYNC_PREWRITE);
3978
3979		dr->dr_usedslot = dr->dr_numslots;
3980	}
3981
3982      out:
3983	return (dr);
3984
3985fail2:
3986	free(dr->dr_txhdr_cache, M_DEVBUF);
3987fail1:
3988	free(dr->dr_meta, M_DEVBUF);
3989fail0:
3990	free(dr, M_DEVBUF);
3991	return (NULL);
3992}
3993
3994static void
3995bwn_dma_ringfree(struct bwn_dma_ring **dr)
3996{
3997
3998	if (dr == NULL)
3999		return;
4000
4001	bwn_dma_free_descbufs(*dr);
4002	bwn_dma_free_ringmemory(*dr);
4003
4004	free((*dr)->dr_txhdr_cache, M_DEVBUF);
4005	free((*dr)->dr_meta, M_DEVBUF);
4006	free(*dr, M_DEVBUF);
4007
4008	*dr = NULL;
4009}
4010
4011static void
4012bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
4013    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4014{
4015	struct bwn_dmadesc32 *desc;
4016
4017	*meta = &(dr->dr_meta[slot]);
4018	desc = dr->dr_ring_descbase;
4019	desc = &(desc[slot]);
4020
4021	*gdesc = (struct bwn_dmadesc_generic *)desc;
4022}
4023
4024static void
4025bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
4026    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4027    int start, int end, int irq)
4028{
4029	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
4030	uint32_t addr, addrext, ctl;
4031	int slot;
4032
4033	slot = (int)(&(desc->dma.dma32) - descbase);
4034	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4035	    ("%s:%d: fail", __func__, __LINE__));
4036
4037	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4038	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4039	addr |= siba_dma_translation(dr->dr_mac->mac_sd);
4040	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4041	if (slot == dr->dr_numslots - 1)
4042		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4043	if (start)
4044		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4045	if (end)
4046		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4047	if (irq)
4048		ctl |= BWN_DMA32_DCTL_IRQ;
4049	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4050	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4051
4052	desc->dma.dma32.control = htole32(ctl);
4053	desc->dma.dma32.address = htole32(addr);
4054}
4055
4056static void
4057bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4058{
4059
4060	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4061	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4062}
4063
4064static void
4065bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4066{
4067
4068	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4069	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4070}
4071
4072static void
4073bwn_dma_32_resume(struct bwn_dma_ring *dr)
4074{
4075
4076	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4077	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4078}
4079
4080static int
4081bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4082{
4083	uint32_t val;
4084
4085	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4086	val &= BWN_DMA32_RXDPTR;
4087
4088	return (val / sizeof(struct bwn_dmadesc32));
4089}
4090
4091static void
4092bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4093{
4094
4095	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4096	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4097}
4098
4099static void
4100bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4101    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4102{
4103	struct bwn_dmadesc64 *desc;
4104
4105	*meta = &(dr->dr_meta[slot]);
4106	desc = dr->dr_ring_descbase;
4107	desc = &(desc[slot]);
4108
4109	*gdesc = (struct bwn_dmadesc_generic *)desc;
4110}
4111
4112static void
4113bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4114    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4115    int start, int end, int irq)
4116{
4117	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4118	int slot;
4119	uint32_t ctl0 = 0, ctl1 = 0;
4120	uint32_t addrlo, addrhi;
4121	uint32_t addrext;
4122
4123	slot = (int)(&(desc->dma.dma64) - descbase);
4124	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4125	    ("%s:%d: fail", __func__, __LINE__));
4126
4127	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4128	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4129	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4130	    30;
4131	addrhi |= (siba_dma_translation(dr->dr_mac->mac_sd) << 1);
4132	if (slot == dr->dr_numslots - 1)
4133		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4134	if (start)
4135		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4136	if (end)
4137		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4138	if (irq)
4139		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4140	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4141	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4142	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4143
4144	desc->dma.dma64.control0 = htole32(ctl0);
4145	desc->dma.dma64.control1 = htole32(ctl1);
4146	desc->dma.dma64.address_low = htole32(addrlo);
4147	desc->dma.dma64.address_high = htole32(addrhi);
4148}
4149
4150static void
4151bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4152{
4153
4154	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4155	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4156}
4157
4158static void
4159bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4160{
4161
4162	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4163	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4164}
4165
4166static void
4167bwn_dma_64_resume(struct bwn_dma_ring *dr)
4168{
4169
4170	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4171	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4172}
4173
4174static int
4175bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4176{
4177	uint32_t val;
4178
4179	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4180	val &= BWN_DMA64_RXSTATDPTR;
4181
4182	return (val / sizeof(struct bwn_dmadesc64));
4183}
4184
4185static void
4186bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4187{
4188
4189	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4190	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4191}
4192
4193static int
4194bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4195{
4196	struct bwn_mac *mac = dr->dr_mac;
4197	struct bwn_dma *dma = &mac->mac_method.dma;
4198	struct bwn_softc *sc = mac->mac_sc;
4199	int error;
4200
4201	error = bus_dma_tag_create(dma->parent_dtag,
4202			    BWN_ALIGN, 0,
4203			    BUS_SPACE_MAXADDR,
4204			    BUS_SPACE_MAXADDR,
4205			    NULL, NULL,
4206			    BWN_DMA_RINGMEMSIZE,
4207			    1,
4208			    BUS_SPACE_MAXSIZE_32BIT,
4209			    0,
4210			    NULL, NULL,
4211			    &dr->dr_ring_dtag);
4212	if (error) {
4213		device_printf(sc->sc_dev,
4214		    "can't create TX ring DMA tag: TODO frees\n");
4215		return (-1);
4216	}
4217
4218	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4219	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4220	    &dr->dr_ring_dmap);
4221	if (error) {
4222		device_printf(sc->sc_dev,
4223		    "can't allocate DMA mem: TODO frees\n");
4224		return (-1);
4225	}
4226	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4227	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4228	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4229	if (error) {
4230		device_printf(sc->sc_dev,
4231		    "can't load DMA mem: TODO free\n");
4232		return (-1);
4233	}
4234
4235	return (0);
4236}
4237
4238static void
4239bwn_dma_setup(struct bwn_dma_ring *dr)
4240{
4241	uint64_t ring64;
4242	uint32_t addrext, ring32, value;
4243	uint32_t trans = siba_dma_translation(dr->dr_mac->mac_sd);
4244
4245	if (dr->dr_tx) {
4246		dr->dr_curslot = -1;
4247
4248		if (dr->dr_type == BWN_DMA_64BIT) {
4249			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4250			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4251			    >> 30;
4252			value = BWN_DMA64_TXENABLE;
4253			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4254			    & BWN_DMA64_TXADDREXT_MASK;
4255			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4256			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4257			    (ring64 & 0xffffffff));
4258			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4259			    ((ring64 >> 32) &
4260			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4261		} else {
4262			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4263			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4264			value = BWN_DMA32_TXENABLE;
4265			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4266			    & BWN_DMA32_TXADDREXT_MASK;
4267			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4268			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4269			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4270		}
4271		return;
4272	}
4273
4274	/*
4275	 * set for RX
4276	 */
4277	dr->dr_usedslot = dr->dr_numslots;
4278
4279	if (dr->dr_type == BWN_DMA_64BIT) {
4280		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4281		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4282		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4283		value |= BWN_DMA64_RXENABLE;
4284		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4285		    & BWN_DMA64_RXADDREXT_MASK;
4286		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4287		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4288		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4289		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4290		    | (trans << 1));
4291		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4292		    sizeof(struct bwn_dmadesc64));
4293	} else {
4294		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4295		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4296		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4297		value |= BWN_DMA32_RXENABLE;
4298		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4299		    & BWN_DMA32_RXADDREXT_MASK;
4300		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4301		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4302		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4303		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4304		    sizeof(struct bwn_dmadesc32));
4305	}
4306}
4307
4308static void
4309bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4310{
4311
4312	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4313	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4314	    dr->dr_ring_dmap);
4315}
4316
4317static void
4318bwn_dma_cleanup(struct bwn_dma_ring *dr)
4319{
4320
4321	if (dr->dr_tx) {
4322		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4323		if (dr->dr_type == BWN_DMA_64BIT) {
4324			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4325			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4326		} else
4327			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4328	} else {
4329		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4330		if (dr->dr_type == BWN_DMA_64BIT) {
4331			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4332			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4333		} else
4334			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4335	}
4336}
4337
4338static void
4339bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4340{
4341	struct bwn_dmadesc_generic *desc;
4342	struct bwn_dmadesc_meta *meta;
4343	struct bwn_mac *mac = dr->dr_mac;
4344	struct bwn_dma *dma = &mac->mac_method.dma;
4345	struct bwn_softc *sc = mac->mac_sc;
4346	int i;
4347
4348	if (!dr->dr_usedslot)
4349		return;
4350	for (i = 0; i < dr->dr_numslots; i++) {
4351		dr->getdesc(dr, i, &desc, &meta);
4352
4353		if (meta->mt_m == NULL) {
4354			if (!dr->dr_tx)
4355				device_printf(sc->sc_dev, "%s: not TX?\n",
4356				    __func__);
4357			continue;
4358		}
4359		if (dr->dr_tx) {
4360			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4361				bus_dmamap_unload(dr->dr_txring_dtag,
4362				    meta->mt_dmap);
4363			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4364				bus_dmamap_unload(dma->txbuf_dtag,
4365				    meta->mt_dmap);
4366		} else
4367			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4368		bwn_dma_free_descbuf(dr, meta);
4369	}
4370}
4371
4372static int
4373bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4374    int type)
4375{
4376	struct bwn_softc *sc = mac->mac_sc;
4377	uint32_t value;
4378	int i;
4379	uint16_t offset;
4380
4381	for (i = 0; i < 10; i++) {
4382		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4383		    BWN_DMA32_TXSTATUS;
4384		value = BWN_READ_4(mac, base + offset);
4385		if (type == BWN_DMA_64BIT) {
4386			value &= BWN_DMA64_TXSTAT;
4387			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4388			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4389			    value == BWN_DMA64_TXSTAT_STOPPED)
4390				break;
4391		} else {
4392			value &= BWN_DMA32_TXSTATE;
4393			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4394			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4395			    value == BWN_DMA32_TXSTAT_STOPPED)
4396				break;
4397		}
4398		DELAY(1000);
4399	}
4400	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4401	BWN_WRITE_4(mac, base + offset, 0);
4402	for (i = 0; i < 10; i++) {
4403		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4404						   BWN_DMA32_TXSTATUS;
4405		value = BWN_READ_4(mac, base + offset);
4406		if (type == BWN_DMA_64BIT) {
4407			value &= BWN_DMA64_TXSTAT;
4408			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4409				i = -1;
4410				break;
4411			}
4412		} else {
4413			value &= BWN_DMA32_TXSTATE;
4414			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4415				i = -1;
4416				break;
4417			}
4418		}
4419		DELAY(1000);
4420	}
4421	if (i != -1) {
4422		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4423		return (ENODEV);
4424	}
4425	DELAY(1000);
4426
4427	return (0);
4428}
4429
4430static int
4431bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4432    int type)
4433{
4434	struct bwn_softc *sc = mac->mac_sc;
4435	uint32_t value;
4436	int i;
4437	uint16_t offset;
4438
4439	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4440	BWN_WRITE_4(mac, base + offset, 0);
4441	for (i = 0; i < 10; i++) {
4442		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4443		    BWN_DMA32_RXSTATUS;
4444		value = BWN_READ_4(mac, base + offset);
4445		if (type == BWN_DMA_64BIT) {
4446			value &= BWN_DMA64_RXSTAT;
4447			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4448				i = -1;
4449				break;
4450			}
4451		} else {
4452			value &= BWN_DMA32_RXSTATE;
4453			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4454				i = -1;
4455				break;
4456			}
4457		}
4458		DELAY(1000);
4459	}
4460	if (i != -1) {
4461		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4462		return (ENODEV);
4463	}
4464
4465	return (0);
4466}
4467
4468static void
4469bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4470    struct bwn_dmadesc_meta *meta)
4471{
4472
4473	if (meta->mt_m != NULL) {
4474		m_freem(meta->mt_m);
4475		meta->mt_m = NULL;
4476	}
4477	if (meta->mt_ni != NULL) {
4478		ieee80211_free_node(meta->mt_ni);
4479		meta->mt_ni = NULL;
4480	}
4481}
4482
4483static void
4484bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4485{
4486	struct bwn_rxhdr4 *rxhdr;
4487	unsigned char *frame;
4488
4489	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4490	rxhdr->frame_len = 0;
4491
4492	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4493	    sizeof(struct bwn_plcp6) + 2,
4494	    ("%s:%d: fail", __func__, __LINE__));
4495	frame = mtod(m, char *) + dr->dr_frameoffset;
4496	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4497}
4498
4499static uint8_t
4500bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4501{
4502	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4503
4504	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4505	    == 0xff);
4506}
4507
4508static void
4509bwn_wme_init(struct bwn_mac *mac)
4510{
4511
4512	bwn_wme_load(mac);
4513
4514	/* enable WME support. */
4515	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4516	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4517	    BWN_IFSCTL_USE_EDCF);
4518}
4519
4520static void
4521bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4522{
4523	struct bwn_softc *sc = mac->mac_sc;
4524	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4525	uint16_t delay;	/* microsec */
4526
4527	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4528	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4529		delay = 500;
4530	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4531		delay = max(delay, (uint16_t)2400);
4532
4533	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4534}
4535
4536static void
4537bwn_bt_enable(struct bwn_mac *mac)
4538{
4539	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
4540	uint64_t hf;
4541
4542	if (bwn_bluetooth == 0)
4543		return;
4544	if ((sprom->bf_lo & BWN_BFL_BTCOEXIST) == 0)
4545		return;
4546	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4547		return;
4548
4549	hf = bwn_hf_read(mac);
4550	if (sprom->bf_lo & BWN_BFL_BTCMOD)
4551		hf |= BWN_HF_BT_COEXISTALT;
4552	else
4553		hf |= BWN_HF_BT_COEXIST;
4554	bwn_hf_write(mac, hf);
4555}
4556
4557static void
4558bwn_set_macaddr(struct bwn_mac *mac)
4559{
4560
4561	bwn_mac_write_bssid(mac);
4562	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4563}
4564
4565static void
4566bwn_clear_keys(struct bwn_mac *mac)
4567{
4568	int i;
4569
4570	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4571		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4572		    ("%s:%d: fail", __func__, __LINE__));
4573
4574		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4575		    NULL, BWN_SEC_KEYSIZE, NULL);
4576		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4577			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4578			    NULL, BWN_SEC_KEYSIZE, NULL);
4579		}
4580		mac->mac_key[i].keyconf = NULL;
4581	}
4582}
4583
4584static void
4585bwn_crypt_init(struct bwn_mac *mac)
4586{
4587
4588	mac->mac_max_nr_keys = (mac->mac_sd->sd_id.sd_rev >= 5) ? 58 : 20;
4589	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4590	    ("%s:%d: fail", __func__, __LINE__));
4591	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4592	mac->mac_ktp *= 2;
4593	if (mac->mac_sd->sd_id.sd_rev >= 5) {
4594		BWN_WRITE_2(mac, BWN_RCMTA_COUNT,
4595		    mac->mac_max_nr_keys - 8);
4596	}
4597	bwn_clear_keys(mac);
4598}
4599
4600static void
4601bwn_chip_exit(struct bwn_mac *mac)
4602{
4603
4604	bwn_phy_exit(mac);
4605	bwn_gpio_cleanup(mac);
4606}
4607
4608static int
4609bwn_fw_fillinfo(struct bwn_mac *mac)
4610{
4611	int error;
4612
4613	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4614	if (error == 0)
4615		return (0);
4616	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4617	if (error == 0)
4618		return (0);
4619	return (error);
4620}
4621
4622static int
4623bwn_gpio_init(struct bwn_mac *mac)
4624{
4625	struct siba_softc *bus = mac->mac_sd->sd_bus;
4626	struct siba_dev_softc *sd;
4627	uint32_t mask = 0x0000001f, set = 0x0000000f;
4628
4629	BWN_WRITE_4(mac, BWN_MACCTL,
4630	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4631	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4632	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4633
4634	if (bus->siba_chipid == 0x4301) {
4635		mask |= 0x0060;
4636		set |= 0x0060;
4637	}
4638	if (bus->siba_sprom.bf_lo & BWN_BFL_PACTRL) {
4639		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4640		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4641		mask |= 0x0200;
4642		set |= 0x0200;
4643	}
4644	if (mac->mac_sd->sd_id.sd_rev >= 2)
4645		mask |= 0x0010;
4646	sd = (bus->siba_cc.scc_dev != NULL) ? bus->siba_cc.scc_dev :
4647	    bus->siba_pci.spc_dev;
4648	if (sd == NULL)
4649		return (0);
4650	siba_write_4(sd, BWN_GPIOCTL,
4651	    (siba_read_4(sd, BWN_GPIOCTL) & mask) | set);
4652
4653	return (0);
4654}
4655
4656static int
4657bwn_fw_loadinitvals(struct bwn_mac *mac)
4658{
4659#define	GETFWOFFSET(fwp, offset)				\
4660	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4661	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4662	const struct bwn_fwhdr *hdr;
4663	struct bwn_fw *fw = &mac->mac_fw;
4664	int error;
4665
4666	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4667	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4668	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4669	if (error)
4670		return (error);
4671	if (fw->initvals_band.fw) {
4672		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4673		error = bwn_fwinitvals_write(mac,
4674		    GETFWOFFSET(fw->initvals_band, hdr_len),
4675		    be32toh(hdr->size),
4676		    fw->initvals_band.fw->datasize - hdr_len);
4677	}
4678	return (error);
4679#undef GETFWOFFSET
4680}
4681
4682static int
4683bwn_phy_init(struct bwn_mac *mac)
4684{
4685	struct bwn_softc *sc = mac->mac_sc;
4686	int error;
4687
4688	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4689	mac->mac_phy.rf_onoff(mac, 1);
4690	error = mac->mac_phy.init(mac);
4691	if (error) {
4692		device_printf(sc->sc_dev, "PHY init failed\n");
4693		goto fail0;
4694	}
4695	error = bwn_switch_channel(mac,
4696	    mac->mac_phy.get_default_chan(mac));
4697	if (error) {
4698		device_printf(sc->sc_dev,
4699		    "failed to switch default channel\n");
4700		goto fail1;
4701	}
4702	return (0);
4703fail1:
4704	if (mac->mac_phy.exit)
4705		mac->mac_phy.exit(mac);
4706fail0:
4707	mac->mac_phy.rf_onoff(mac, 0);
4708
4709	return (error);
4710}
4711
4712static void
4713bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4714{
4715	uint16_t ant;
4716	uint16_t tmp;
4717
4718	ant = bwn_ant2phy(antenna);
4719
4720	/* For ACK/CTS */
4721	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4722	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4723	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4724	/* For Probe Resposes */
4725	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4726	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4727	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4728}
4729
4730static void
4731bwn_set_opmode(struct bwn_mac *mac)
4732{
4733	struct bwn_softc *sc = mac->mac_sc;
4734	struct ifnet *ifp = sc->sc_ifp;
4735	struct ieee80211com *ic = ifp->if_l2com;
4736	uint32_t ctl;
4737	uint16_t cfp_pretbtt;
4738
4739	ctl = BWN_READ_4(mac, BWN_MACCTL);
4740	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4741	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4742	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4743	ctl |= BWN_MACCTL_STA;
4744
4745	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4746	    ic->ic_opmode == IEEE80211_M_MBSS)
4747		ctl |= BWN_MACCTL_HOSTAP;
4748	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4749		ctl &= ~BWN_MACCTL_STA;
4750	ctl |= sc->sc_filters;
4751
4752	if (mac->mac_sd->sd_id.sd_rev <= 4)
4753		ctl |= BWN_MACCTL_PROMISC;
4754
4755	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4756
4757	cfp_pretbtt = 2;
4758	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4759		if (mac->mac_sd->sd_bus->siba_chipid == 0x4306 &&
4760		    mac->mac_sd->sd_bus->siba_chiprev == 3)
4761			cfp_pretbtt = 100;
4762		else
4763			cfp_pretbtt = 50;
4764	}
4765	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4766}
4767
4768static void
4769bwn_gpio_cleanup(struct bwn_mac *mac)
4770{
4771	struct siba_softc *bus = mac->mac_sd->sd_bus;
4772	struct siba_dev_softc *gpiodev, *pcidev = NULL;
4773
4774	pcidev = bus->siba_pci.spc_dev;
4775	gpiodev = bus->siba_cc.scc_dev ? bus->siba_cc.scc_dev : pcidev;
4776	if (!gpiodev)
4777		return;
4778	siba_write_4(gpiodev, BWN_GPIOCTL, 0);
4779}
4780
4781static int
4782bwn_dma_gettype(struct bwn_mac *mac)
4783{
4784	uint32_t tmp;
4785	uint16_t base;
4786
4787	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4788	if (tmp & SIBA_TGSHIGH_DMA64)
4789		return (BWN_DMA_64BIT);
4790	base = bwn_dma_base(0, 0);
4791	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4792	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4793	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4794		return (BWN_DMA_32BIT);
4795
4796	return (BWN_DMA_30BIT);
4797}
4798
4799static void
4800bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4801{
4802	if (!error) {
4803		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4804		*((bus_addr_t *)arg) = seg->ds_addr;
4805	}
4806}
4807
4808static void
4809bwn_phy_g_init_sub(struct bwn_mac *mac)
4810{
4811	struct bwn_phy *phy = &mac->mac_phy;
4812	struct bwn_phy_g *pg = &phy->phy_g;
4813	uint16_t i, tmp;
4814
4815	if (phy->rev == 1)
4816		bwn_phy_init_b5(mac);
4817	else
4818		bwn_phy_init_b6(mac);
4819
4820	if (phy->rev >= 2 || phy->gmode)
4821		bwn_phy_init_a(mac);
4822
4823	if (phy->rev >= 2) {
4824		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4825		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4826	}
4827	if (phy->rev == 2) {
4828		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4829		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4830	}
4831	if (phy->rev > 5) {
4832		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4833		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4834	}
4835	if (phy->gmode || phy->rev >= 2) {
4836		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4837		tmp &= BWN_PHYVER_VERSION;
4838		if (tmp == 3 || tmp == 5) {
4839			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4840			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4841		}
4842		if (tmp == 5) {
4843			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4844			    0x1f00);
4845		}
4846	}
4847	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4848		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4849	if (phy->rf_rev == 8) {
4850		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4851		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4852	}
4853	if (BWN_HAS_LOOPBACK(phy))
4854		bwn_loopback_calcgain(mac);
4855
4856	if (phy->rf_rev != 8) {
4857		if (pg->pg_initval == 0xffff)
4858			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4859		else
4860			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4861	}
4862	bwn_lo_g_init(mac);
4863	if (BWN_HAS_TXMAG(phy)) {
4864		BWN_RF_WRITE(mac, 0x52,
4865		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4866		    | pg->pg_loctl.tx_bias |
4867		    pg->pg_loctl.tx_magn);
4868	} else {
4869		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4870	}
4871	if (phy->rev >= 6) {
4872		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4873		    (pg->pg_loctl.tx_bias << 12));
4874	}
4875	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL)
4876		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4877	else
4878		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4879	if (phy->rev < 2)
4880		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4881	else
4882		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4883	if (phy->gmode || phy->rev >= 2) {
4884		bwn_lo_g_adjust(mac);
4885		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4886	}
4887
4888	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
4889		for (i = 0; i < 64; i++) {
4890			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4891			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4892			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4893			    -32), 31));
4894		}
4895		bwn_nrssi_threshold(mac);
4896	} else if (phy->gmode || phy->rev >= 2) {
4897		if (pg->pg_nrssi[0] == -1000) {
4898			KASSERT(pg->pg_nrssi[1] == -1000,
4899			    ("%s:%d: fail", __func__, __LINE__));
4900			bwn_nrssi_slope_11g(mac);
4901		} else
4902			bwn_nrssi_threshold(mac);
4903	}
4904	if (phy->rf_rev == 8)
4905		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4906	bwn_phy_hwpctl_init(mac);
4907	if ((mac->mac_sd->sd_bus->siba_chipid == 0x4306
4908	     && mac->mac_sd->sd_bus->siba_chippkg == 2) || 0) {
4909		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4910		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4911	}
4912}
4913
4914static uint8_t
4915bwn_has_hwpctl(struct bwn_mac *mac)
4916{
4917
4918	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4919		return (0);
4920	return (mac->mac_phy.use_hwpctl(mac));
4921}
4922
4923static void
4924bwn_phy_init_b5(struct bwn_mac *mac)
4925{
4926	struct siba_softc *bus = mac->mac_sd->sd_bus;
4927	struct bwn_phy *phy = &mac->mac_phy;
4928	struct bwn_phy_g *pg = &phy->phy_g;
4929	uint16_t offset, value;
4930	uint8_t old_channel;
4931
4932	if (phy->analog == 1)
4933		BWN_RF_SET(mac, 0x007a, 0x0050);
4934	if ((bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM) &&
4935	    (bus->siba_board_type != SIBA_BOARD_BU4306)) {
4936		value = 0x2120;
4937		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4938			BWN_PHY_WRITE(mac, offset, value);
4939			value += 0x202;
4940		}
4941	}
4942	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4943	if (phy->rf_ver == 0x2050)
4944		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4945
4946	if (phy->gmode || phy->rev >= 2) {
4947		if (phy->rf_ver == 0x2050) {
4948			BWN_RF_SET(mac, 0x007a, 0x0020);
4949			BWN_RF_SET(mac, 0x0051, 0x0004);
4950		}
4951		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4952
4953		BWN_PHY_SET(mac, 0x0802, 0x0100);
4954		BWN_PHY_SET(mac, 0x042b, 0x2000);
4955
4956		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4957
4958		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4959		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4960		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4961	}
4962
4963	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4964		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4965
4966	if (phy->analog == 1) {
4967		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4968		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4969		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4970		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4971		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4972	} else
4973		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4974	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4975	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4976
4977	if (phy->analog == 1)
4978		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4979	else
4980		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4981
4982	if (phy->analog == 0)
4983		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4984
4985	old_channel = phy->chan;
4986	bwn_phy_g_switch_chan(mac, 7, 0);
4987
4988	if (phy->rf_ver != 0x2050) {
4989		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4990		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4991	}
4992
4993	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4994	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4995
4996	if (phy->rf_ver == 0x2050) {
4997		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4998		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4999	}
5000
5001	BWN_RF_WRITE(mac, 0x005b, 0x007b);
5002	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
5003	BWN_RF_SET(mac, 0x007a, 0x0007);
5004
5005	bwn_phy_g_switch_chan(mac, old_channel, 0);
5006	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
5007	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
5008	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
5009
5010	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5011	    pg->pg_txctl);
5012
5013	if (phy->rf_ver == 0x2050)
5014		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5015
5016	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
5017}
5018
5019static void
5020bwn_loopback_calcgain(struct bwn_mac *mac)
5021{
5022	struct bwn_phy *phy = &mac->mac_phy;
5023	struct bwn_phy_g *pg = &phy->phy_g;
5024	uint16_t backup_phy[16] = { 0 };
5025	uint16_t backup_radio[3];
5026	uint16_t backup_bband;
5027	uint16_t i, j, loop_i_max;
5028	uint16_t trsw_rx;
5029	uint16_t loop1_outer_done, loop1_inner_done;
5030
5031	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5032	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
5033	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5034	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5035	if (phy->rev != 1) {
5036		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5037		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5038	}
5039	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5040	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5041	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5042	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5043	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5044	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5045	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5046	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5047	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5048	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5049	backup_bband = pg->pg_bbatt.att;
5050	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5051	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5052	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5053
5054	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5055	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5056	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5057	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5058	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5059	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5060	if (phy->rev != 1) {
5061		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5062		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5063		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5064		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5065	}
5066	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5067	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5068	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5069	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5070
5071	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5072	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5073	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5074
5075	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5076	if (phy->rev != 1) {
5077		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5078		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5079	}
5080	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5081
5082	if (phy->rf_rev == 8)
5083		BWN_RF_WRITE(mac, 0x43, 0x000f);
5084	else {
5085		BWN_RF_WRITE(mac, 0x52, 0);
5086		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5087	}
5088	bwn_phy_g_set_bbatt(mac, 11);
5089
5090	if (phy->rev >= 3)
5091		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5092	else
5093		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5094	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5095
5096	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5097	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5098
5099	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5100	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5101
5102	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) {
5103		if (phy->rev >= 7) {
5104			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5105			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5106		}
5107	}
5108	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5109
5110	j = 0;
5111	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5112	for (i = 0; i < loop_i_max; i++) {
5113		for (j = 0; j < 16; j++) {
5114			BWN_RF_WRITE(mac, 0x43, i);
5115			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5116			    (j << 8));
5117			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5118			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5119			DELAY(20);
5120			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5121				goto done0;
5122		}
5123	}
5124done0:
5125	loop1_outer_done = i;
5126	loop1_inner_done = j;
5127	if (j >= 8) {
5128		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5129		trsw_rx = 0x1b;
5130		for (j = j - 8; j < 16; j++) {
5131			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5132			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5133			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5134			DELAY(20);
5135			trsw_rx -= 3;
5136			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5137				goto done1;
5138		}
5139	} else
5140		trsw_rx = 0x18;
5141done1:
5142
5143	if (phy->rev != 1) {
5144		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5145		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5146	}
5147	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5148	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5149	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5150	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5151	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5152	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5153	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5154	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5155	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5156
5157	bwn_phy_g_set_bbatt(mac, backup_bband);
5158
5159	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5160	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5161	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5162
5163	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5164	DELAY(10);
5165	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5166	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5167	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5168	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5169
5170	pg->pg_max_lb_gain =
5171	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5172	pg->pg_trsw_rx_gain = trsw_rx * 2;
5173}
5174
5175static uint16_t
5176bwn_rf_init_bcm2050(struct bwn_mac *mac)
5177{
5178	struct bwn_phy *phy = &mac->mac_phy;
5179	uint32_t tmp1 = 0, tmp2 = 0;
5180	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5181	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5182	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5183	static const uint8_t rcc_table[] = {
5184		0x02, 0x03, 0x01, 0x0f,
5185		0x06, 0x07, 0x05, 0x0f,
5186		0x0a, 0x0b, 0x09, 0x0f,
5187		0x0e, 0x0f, 0x0d, 0x0f,
5188	};
5189
5190	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5191	    rfoverval = rfover = cck3 = 0;
5192	radio0 = BWN_RF_READ(mac, 0x43);
5193	radio1 = BWN_RF_READ(mac, 0x51);
5194	radio2 = BWN_RF_READ(mac, 0x52);
5195	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5196	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5197	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5198	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5199
5200	if (phy->type == BWN_PHYTYPE_B) {
5201		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5202		reg0 = BWN_READ_2(mac, 0x3ec);
5203
5204		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5205		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5206	} else if (phy->gmode || phy->rev >= 2) {
5207		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5208		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5209		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5210		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5211		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5212		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5213
5214		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5215		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5216		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5217		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5218		if (BWN_HAS_LOOPBACK(phy)) {
5219			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5220			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5221			if (phy->rev >= 3)
5222				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5223			else
5224				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5225			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5226		}
5227
5228		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5229		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5230			BWN_LPD(0, 1, 1)));
5231		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5232		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5233	}
5234	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5235
5236	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5237	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5238	reg1 = BWN_READ_2(mac, 0x3e6);
5239	reg2 = BWN_READ_2(mac, 0x3f4);
5240
5241	if (phy->analog == 0)
5242		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5243	else {
5244		if (phy->analog >= 2)
5245			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5246		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5247		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5248	}
5249
5250	reg = BWN_RF_READ(mac, 0x60);
5251	index = (reg & 0x001e) >> 1;
5252	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5253
5254	if (phy->type == BWN_PHYTYPE_B)
5255		BWN_RF_WRITE(mac, 0x78, 0x26);
5256	if (phy->gmode || phy->rev >= 2) {
5257		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5258		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5259			BWN_LPD(0, 1, 1)));
5260	}
5261	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5262	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5263	if (phy->gmode || phy->rev >= 2) {
5264		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5265		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5266			BWN_LPD(0, 0, 1)));
5267	}
5268	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5269	BWN_RF_SET(mac, 0x51, 0x0004);
5270	if (phy->rf_rev == 8)
5271		BWN_RF_WRITE(mac, 0x43, 0x1f);
5272	else {
5273		BWN_RF_WRITE(mac, 0x52, 0);
5274		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5275	}
5276	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5277
5278	for (i = 0; i < 16; i++) {
5279		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5280		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5281		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5282		if (phy->gmode || phy->rev >= 2) {
5283			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5284			    bwn_rf_2050_rfoverval(mac,
5285				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5286		}
5287		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5288		DELAY(10);
5289		if (phy->gmode || phy->rev >= 2) {
5290			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5291			    bwn_rf_2050_rfoverval(mac,
5292				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5293		}
5294		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5295		DELAY(10);
5296		if (phy->gmode || phy->rev >= 2) {
5297			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5298			    bwn_rf_2050_rfoverval(mac,
5299				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5300		}
5301		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5302		DELAY(20);
5303		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5304		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5305		if (phy->gmode || phy->rev >= 2) {
5306			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5307			    bwn_rf_2050_rfoverval(mac,
5308				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5309		}
5310		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5311	}
5312	DELAY(10);
5313
5314	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5315	tmp1++;
5316	tmp1 >>= 9;
5317
5318	for (i = 0; i < 16; i++) {
5319		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5320		BWN_RF_WRITE(mac, 0x78, radio78);
5321		DELAY(10);
5322		for (j = 0; j < 16; j++) {
5323			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5324			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5325			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5326			if (phy->gmode || phy->rev >= 2) {
5327				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5328				    bwn_rf_2050_rfoverval(mac,
5329					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5330			}
5331			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5332			DELAY(10);
5333			if (phy->gmode || phy->rev >= 2) {
5334				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5335				    bwn_rf_2050_rfoverval(mac,
5336					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5337			}
5338			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5339			DELAY(10);
5340			if (phy->gmode || phy->rev >= 2) {
5341				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5342				    bwn_rf_2050_rfoverval(mac,
5343					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5344			}
5345			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5346			DELAY(10);
5347			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5348			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5349			if (phy->gmode || phy->rev >= 2) {
5350				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5351				    bwn_rf_2050_rfoverval(mac,
5352					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5353			}
5354			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5355		}
5356		tmp2++;
5357		tmp2 >>= 8;
5358		if (tmp1 < tmp2)
5359			break;
5360	}
5361
5362	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5363	BWN_RF_WRITE(mac, 0x51, radio1);
5364	BWN_RF_WRITE(mac, 0x52, radio2);
5365	BWN_RF_WRITE(mac, 0x43, radio0);
5366	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5367	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5368	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5369	BWN_WRITE_2(mac, 0x3e6, reg1);
5370	if (phy->analog != 0)
5371		BWN_WRITE_2(mac, 0x3f4, reg2);
5372	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5373	bwn_spu_workaround(mac, phy->chan);
5374	if (phy->type == BWN_PHYTYPE_B) {
5375		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5376		BWN_WRITE_2(mac, 0x3ec, reg0);
5377	} else if (phy->gmode) {
5378		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5379			    BWN_READ_2(mac, BWN_PHY_RADIO)
5380			    & 0x7fff);
5381		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5382		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5383		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5384		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5385			      analogoverval);
5386		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5387		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5388		if (BWN_HAS_LOOPBACK(phy)) {
5389			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5390			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5391		}
5392	}
5393
5394	return ((i > 15) ? radio78 : rcc);
5395}
5396
5397static void
5398bwn_phy_init_b6(struct bwn_mac *mac)
5399{
5400	struct bwn_phy *phy = &mac->mac_phy;
5401	struct bwn_phy_g *pg = &phy->phy_g;
5402	uint16_t offset, val;
5403	uint8_t old_channel;
5404
5405	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5406	    ("%s:%d: fail", __func__, __LINE__));
5407
5408	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5409	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5410	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5411		BWN_RF_WRITE(mac, 0x51, 0x37);
5412		BWN_RF_WRITE(mac, 0x52, 0x70);
5413		BWN_RF_WRITE(mac, 0x53, 0xb3);
5414		BWN_RF_WRITE(mac, 0x54, 0x9b);
5415		BWN_RF_WRITE(mac, 0x5a, 0x88);
5416		BWN_RF_WRITE(mac, 0x5b, 0x88);
5417		BWN_RF_WRITE(mac, 0x5d, 0x88);
5418		BWN_RF_WRITE(mac, 0x5e, 0x88);
5419		BWN_RF_WRITE(mac, 0x7d, 0x88);
5420		bwn_hf_write(mac,
5421		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5422	}
5423	if (phy->rf_rev == 8) {
5424		BWN_RF_WRITE(mac, 0x51, 0);
5425		BWN_RF_WRITE(mac, 0x52, 0x40);
5426		BWN_RF_WRITE(mac, 0x53, 0xb7);
5427		BWN_RF_WRITE(mac, 0x54, 0x98);
5428		BWN_RF_WRITE(mac, 0x5a, 0x88);
5429		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5430		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5431		if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_ALTIQ) {
5432			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5433			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5434		} else {
5435			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5436			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5437		}
5438		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5439		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5440		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5441		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5442	}
5443	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5444		BWN_PHY_WRITE(mac, offset, val);
5445		val -= 0x0202;
5446	}
5447	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5448		BWN_PHY_WRITE(mac, offset, val);
5449		val -= 0x0202;
5450	}
5451	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5452		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5453		val += 0x0202;
5454	}
5455	if (phy->type == BWN_PHYTYPE_G) {
5456		BWN_RF_SET(mac, 0x007a, 0x0020);
5457		BWN_RF_SET(mac, 0x0051, 0x0004);
5458		BWN_PHY_SET(mac, 0x0802, 0x0100);
5459		BWN_PHY_SET(mac, 0x042b, 0x2000);
5460		BWN_PHY_WRITE(mac, 0x5b, 0);
5461		BWN_PHY_WRITE(mac, 0x5c, 0);
5462	}
5463
5464	old_channel = phy->chan;
5465	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5466
5467	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5468	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5469	DELAY(40);
5470	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5471		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5472		BWN_RF_WRITE(mac, 0x50, 0x20);
5473	}
5474	if (phy->rf_rev <= 2) {
5475		BWN_RF_WRITE(mac, 0x7c, 0x20);
5476		BWN_RF_WRITE(mac, 0x5a, 0x70);
5477		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5478		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5479	}
5480	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5481
5482	bwn_phy_g_switch_chan(mac, old_channel, 0);
5483
5484	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5485	if (phy->rf_rev >= 6)
5486		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5487	else
5488		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5489	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5490	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5491	    pg->pg_txctl);
5492	if (phy->rf_rev <= 5)
5493		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5494	if (phy->rf_rev <= 2)
5495		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5496
5497	if (phy->analog == 4) {
5498		BWN_WRITE_2(mac, 0x3e4, 9);
5499		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5500	} else
5501		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5502	if (phy->type == BWN_PHYTYPE_B)
5503		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5504	else if (phy->type == BWN_PHYTYPE_G)
5505		BWN_WRITE_2(mac, 0x03e6, 0x0);
5506}
5507
5508static void
5509bwn_phy_init_a(struct bwn_mac *mac)
5510{
5511	struct bwn_phy *phy = &mac->mac_phy;
5512
5513	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5514	    ("%s:%d: fail", __func__, __LINE__));
5515
5516	if (phy->rev >= 6) {
5517		if (phy->type == BWN_PHYTYPE_A)
5518			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5519		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5520			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5521		else
5522			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5523	}
5524
5525	bwn_wa_init(mac);
5526
5527	if (phy->type == BWN_PHYTYPE_G &&
5528	    (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL))
5529		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5530}
5531
5532static void
5533bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5534{
5535	int i;
5536
5537	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5538		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5539}
5540
5541static void
5542bwn_wa_agc(struct bwn_mac *mac)
5543{
5544	struct bwn_phy *phy = &mac->mac_phy;
5545
5546	if (phy->rev == 1) {
5547		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5548		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5549		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5550		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5551		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5552		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5553		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5554		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5555		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5556	} else {
5557		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5558		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5559		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5560		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5561	}
5562
5563	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5564	    0x5700);
5565	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5566	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5567	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5568	BWN_RF_SET(mac, 0x7a, 0x0008);
5569	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5570	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5571	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5572	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5573	if (phy->rev == 1)
5574		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5575	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5576	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5577	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5578	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5579	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5580	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5581	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5582	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5583	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5584	if (phy->rev == 1) {
5585		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5586		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5587	} else {
5588		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5589		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5590		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5591		if (phy->rev >= 6) {
5592			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5593			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5594			    (uint16_t)~0xf000, 0x3000);
5595		}
5596	}
5597	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5598	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5599	if (phy->rev == 1) {
5600		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5601		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5602		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5603		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5604		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5605		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5606		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5607		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5608	} else {
5609		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5610		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5611		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5612		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5613	}
5614	if (phy->rev >= 6) {
5615		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5616		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5617	}
5618	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5619}
5620
5621static void
5622bwn_wa_grev1(struct bwn_mac *mac)
5623{
5624	struct bwn_phy *phy = &mac->mac_phy;
5625	int i;
5626	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5627	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5628	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5629
5630	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5631
5632	/* init CRSTHRES and ANTDWELL */
5633	if (phy->rev == 1) {
5634		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5635	} else if (phy->rev == 2) {
5636		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5637		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5638		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5639	} else {
5640		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5641		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5642		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5643		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5644	}
5645	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5646	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5647	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5648
5649	/* XXX support PHY-A??? */
5650	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5651		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5652		    bwn_tab_finefreqg[i]);
5653
5654	/* XXX support PHY-A??? */
5655	if (phy->rev == 1)
5656		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5657			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5658			    bwn_tab_noise_g1[i]);
5659	else
5660		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5661			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5662			    bwn_tab_noise_g2[i]);
5663
5664
5665	for (i = 0; i < N(bwn_tab_rotor); i++)
5666		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5667		    bwn_tab_rotor[i]);
5668
5669	/* XXX support PHY-A??? */
5670	if (phy->rev >= 6) {
5671		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5672		    BWN_PHY_ENCORE_EN)
5673			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5674		else
5675			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5676	} else
5677		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5678
5679	for (i = 0; i < N(bwn_tab_retard); i++)
5680		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5681		    bwn_tab_retard[i]);
5682
5683	if (phy->rev == 1) {
5684		for (i = 0; i < 16; i++)
5685			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5686			    i, 0x0020);
5687	} else {
5688		for (i = 0; i < 32; i++)
5689			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5690	}
5691
5692	bwn_wa_agc(mac);
5693}
5694
5695static void
5696bwn_wa_grev26789(struct bwn_mac *mac)
5697{
5698	struct bwn_phy *phy = &mac->mac_phy;
5699	int i;
5700	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5701	uint16_t ofdmrev;
5702
5703	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5704
5705	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5706
5707	/* init CRSTHRES and ANTDWELL */
5708	if (phy->rev == 1)
5709		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5710	else if (phy->rev == 2) {
5711		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5712		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5713		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5714	} else {
5715		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5716		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5717		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5718		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5719	}
5720
5721	for (i = 0; i < 64; i++)
5722		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5723
5724	/* XXX support PHY-A??? */
5725	if (phy->rev == 1)
5726		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5727			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5728			    bwn_tab_noise_g1[i]);
5729	else
5730		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5731			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5732			    bwn_tab_noise_g2[i]);
5733
5734	/* XXX support PHY-A??? */
5735	if (phy->rev >= 6) {
5736		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5737		    BWN_PHY_ENCORE_EN)
5738			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5739		else
5740			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5741	} else
5742		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5743
5744	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5745		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5746		    bwn_tab_sigmasqr2[i]);
5747
5748	if (phy->rev == 1) {
5749		for (i = 0; i < 16; i++)
5750			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5751			    0x0020);
5752	} else {
5753		for (i = 0; i < 32; i++)
5754			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5755	}
5756
5757	bwn_wa_agc(mac);
5758
5759	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5760	if (ofdmrev > 2) {
5761		if (phy->type == BWN_PHYTYPE_A)
5762			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5763		else
5764			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5765	} else {
5766		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5767		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5768		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5769	}
5770
5771	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5772	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5773}
5774
5775static void
5776bwn_wa_init(struct bwn_mac *mac)
5777{
5778	struct bwn_phy *phy = &mac->mac_phy;
5779	struct siba_softc *bus = mac->mac_sd->sd_bus;
5780
5781	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5782
5783	switch (phy->rev) {
5784	case 1:
5785		bwn_wa_grev1(mac);
5786		break;
5787	case 2:
5788	case 6:
5789	case 7:
5790	case 8:
5791	case 9:
5792		bwn_wa_grev26789(mac);
5793		break;
5794	default:
5795		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5796	}
5797
5798	if (bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM ||
5799	    bus->siba_board_type != SIBA_BOARD_BU4306 ||
5800	    bus->siba_board_rev != 0x17) {
5801		if (phy->rev < 2) {
5802			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5803			    0x0002);
5804			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5805			    0x0001);
5806		} else {
5807			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5808			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5809			if ((bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) &&
5810			    (phy->rev >= 7)) {
5811				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5812				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5813				    0x0020, 0x0001);
5814				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5815				    0x0021, 0x0001);
5816				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5817				    0x0022, 0x0001);
5818				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5819				    0x0023, 0x0000);
5820				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5821				    0x0000, 0x0000);
5822				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5823				    0x0003, 0x0002);
5824			}
5825		}
5826	}
5827	if (bus->siba_sprom.bf_lo & BWN_BFL_FEM) {
5828		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5829		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5830	}
5831
5832	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5833	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5834}
5835
5836static void
5837bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5838    uint16_t value)
5839{
5840	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5841	uint16_t addr;
5842
5843	addr = table + offset;
5844	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5845	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5846		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5847		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5848	}
5849	pg->pg_ofdmtab_addr = addr;
5850	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5851}
5852
5853static void
5854bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5855    uint32_t value)
5856{
5857	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5858	uint16_t addr;
5859
5860	addr = table + offset;
5861	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5862	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5863		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5864		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5865	}
5866	pg->pg_ofdmtab_addr = addr;
5867
5868	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5869	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5870}
5871
5872static void
5873bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5874    uint16_t value)
5875{
5876
5877	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5878	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5879}
5880
5881static void
5882bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5883{
5884	struct bwn_phy *phy = &mac->mac_phy;
5885	unsigned int i, max_loop;
5886	uint16_t value;
5887	uint32_t buffer[5] = {
5888		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5889	};
5890
5891	if (ofdm) {
5892		max_loop = 0x1e;
5893		buffer[0] = 0x000201cc;
5894	} else {
5895		max_loop = 0xfa;
5896		buffer[0] = 0x000b846e;
5897	}
5898
5899	BWN_ASSERT_LOCKED(mac->mac_sc);
5900
5901	for (i = 0; i < 5; i++)
5902		bwn_ram_write(mac, i * 4, buffer[i]);
5903
5904	BWN_WRITE_2(mac, 0x0568, 0x0000);
5905	BWN_WRITE_2(mac, 0x07c0,
5906	    (mac->mac_sd->sd_id.sd_rev < 11) ? 0x0000 : 0x0100);
5907	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5908	BWN_WRITE_2(mac, 0x050c, value);
5909	if (phy->type == BWN_PHYTYPE_LP)
5910		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5911	BWN_WRITE_2(mac, 0x0508, 0x0000);
5912	BWN_WRITE_2(mac, 0x050a, 0x0000);
5913	BWN_WRITE_2(mac, 0x054c, 0x0000);
5914	BWN_WRITE_2(mac, 0x056a, 0x0014);
5915	BWN_WRITE_2(mac, 0x0568, 0x0826);
5916	BWN_WRITE_2(mac, 0x0500, 0x0000);
5917	if (phy->type == BWN_PHYTYPE_LP)
5918		BWN_WRITE_2(mac, 0x0502, 0x0050);
5919	else
5920		BWN_WRITE_2(mac, 0x0502, 0x0030);
5921
5922	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5923		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5924	for (i = 0x00; i < max_loop; i++) {
5925		value = BWN_READ_2(mac, 0x050e);
5926		if (value & 0x0080)
5927			break;
5928		DELAY(10);
5929	}
5930	for (i = 0x00; i < 0x0a; i++) {
5931		value = BWN_READ_2(mac, 0x050e);
5932		if (value & 0x0400)
5933			break;
5934		DELAY(10);
5935	}
5936	for (i = 0x00; i < 0x19; i++) {
5937		value = BWN_READ_2(mac, 0x0690);
5938		if (!(value & 0x0100))
5939			break;
5940		DELAY(10);
5941	}
5942	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5943		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5944}
5945
5946static void
5947bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5948{
5949	uint32_t macctl;
5950
5951	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5952
5953	macctl = BWN_READ_4(mac, BWN_MACCTL);
5954	if (macctl & BWN_MACCTL_BIGENDIAN)
5955		printf("TODO: need swap\n");
5956
5957	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5958	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5959	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5960}
5961
5962static void
5963bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5964{
5965	uint16_t value;
5966
5967	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5968	    ("%s:%d: fail", __func__, __LINE__));
5969
5970	value = (uint8_t) (ctl->q);
5971	value |= ((uint8_t) (ctl->i)) << 8;
5972	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5973}
5974
5975static uint16_t
5976bwn_lo_calcfeed(struct bwn_mac *mac,
5977    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5978{
5979	struct bwn_phy *phy = &mac->mac_phy;
5980	uint16_t rfover;
5981	uint16_t feedthrough;
5982
5983	if (phy->gmode) {
5984		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5985		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5986
5987		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5988		    ("%s:%d: fail", __func__, __LINE__));
5989		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5990		    ("%s:%d: fail", __func__, __LINE__));
5991
5992		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5993
5994		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5995		if ((mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA)
5996		    && phy->rev > 6)
5997			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5998
5999		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6000		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6001		DELAY(10);
6002		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
6003		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6004		DELAY(10);
6005		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
6006		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6007		DELAY(10);
6008		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
6009	} else {
6010		pga |= BWN_PHY_PGACTL_UNKNOWN;
6011		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6012		DELAY(10);
6013		pga |= BWN_PHY_PGACTL_LOWBANDW;
6014		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6015		DELAY(10);
6016		pga |= BWN_PHY_PGACTL_LPF;
6017		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6018	}
6019	DELAY(21);
6020	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
6021
6022	return (feedthrough);
6023}
6024
6025static uint16_t
6026bwn_lo_txctl_regtable(struct bwn_mac *mac,
6027    uint16_t *value, uint16_t *pad_mix_gain)
6028{
6029	struct bwn_phy *phy = &mac->mac_phy;
6030	uint16_t reg, v, padmix;
6031
6032	if (phy->type == BWN_PHYTYPE_B) {
6033		v = 0x30;
6034		if (phy->rf_rev <= 5) {
6035			reg = 0x43;
6036			padmix = 0;
6037		} else {
6038			reg = 0x52;
6039			padmix = 5;
6040		}
6041	} else {
6042		if (phy->rev >= 2 && phy->rf_rev == 8) {
6043			reg = 0x43;
6044			v = 0x10;
6045			padmix = 2;
6046		} else {
6047			reg = 0x52;
6048			v = 0x30;
6049			padmix = 5;
6050		}
6051	}
6052	if (value)
6053		*value = v;
6054	if (pad_mix_gain)
6055		*pad_mix_gain = padmix;
6056
6057	return (reg);
6058}
6059
6060static void
6061bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6062{
6063	struct bwn_phy *phy = &mac->mac_phy;
6064	struct bwn_phy_g *pg = &phy->phy_g;
6065	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6066	uint16_t reg, mask;
6067	uint16_t trsw_rx, pga;
6068	uint16_t rf_pctl_reg;
6069
6070	static const uint8_t tx_bias_values[] = {
6071		0x09, 0x08, 0x0a, 0x01, 0x00,
6072		0x02, 0x05, 0x04, 0x06,
6073	};
6074	static const uint8_t tx_magn_values[] = {
6075		0x70, 0x40,
6076	};
6077
6078	if (!BWN_HAS_LOOPBACK(phy)) {
6079		rf_pctl_reg = 6;
6080		trsw_rx = 2;
6081		pga = 0;
6082	} else {
6083		int lb_gain;
6084
6085		trsw_rx = 0;
6086		lb_gain = pg->pg_max_lb_gain / 2;
6087		if (lb_gain > 10) {
6088			rf_pctl_reg = 0;
6089			pga = abs(10 - lb_gain) / 6;
6090			pga = MIN(MAX(pga, 0), 15);
6091		} else {
6092			int cmp_val;
6093			int tmp;
6094
6095			pga = 0;
6096			cmp_val = 0x24;
6097			if ((phy->rev >= 2) &&
6098			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6099				cmp_val = 0x3c;
6100			tmp = lb_gain;
6101			if ((10 - lb_gain) < cmp_val)
6102				tmp = (10 - lb_gain);
6103			if (tmp < 0)
6104				tmp += 6;
6105			else
6106				tmp += 3;
6107			cmp_val /= 4;
6108			tmp /= 4;
6109			if (tmp >= cmp_val)
6110				rf_pctl_reg = cmp_val;
6111			else
6112				rf_pctl_reg = tmp;
6113		}
6114	}
6115	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6116	bwn_phy_g_set_bbatt(mac, 2);
6117
6118	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6119	mask = ~mask;
6120	BWN_RF_MASK(mac, reg, mask);
6121
6122	if (BWN_HAS_TXMAG(phy)) {
6123		int i, j;
6124		int feedthrough;
6125		int min_feedth = 0xffff;
6126		uint8_t tx_magn, tx_bias;
6127
6128		for (i = 0; i < N(tx_magn_values); i++) {
6129			tx_magn = tx_magn_values[i];
6130			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6131			for (j = 0; j < N(tx_bias_values); j++) {
6132				tx_bias = tx_bias_values[j];
6133				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6134				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6135				    trsw_rx);
6136				if (feedthrough < min_feedth) {
6137					lo->tx_bias = tx_bias;
6138					lo->tx_magn = tx_magn;
6139					min_feedth = feedthrough;
6140				}
6141				if (lo->tx_bias == 0)
6142					break;
6143			}
6144			BWN_RF_WRITE(mac, 0x52,
6145					  (BWN_RF_READ(mac, 0x52)
6146					   & 0xff00) | lo->tx_bias | lo->
6147					  tx_magn);
6148		}
6149	} else {
6150		lo->tx_magn = 0;
6151		lo->tx_bias = 0;
6152		BWN_RF_MASK(mac, 0x52, 0xfff0);
6153	}
6154
6155	BWN_GETTIME(lo->txctl_measured_time);
6156}
6157
6158static void
6159bwn_lo_get_powervector(struct bwn_mac *mac)
6160{
6161	struct bwn_phy *phy = &mac->mac_phy;
6162	struct bwn_phy_g *pg = &phy->phy_g;
6163	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6164	int i;
6165	uint64_t tmp;
6166	uint64_t power_vector = 0;
6167
6168	for (i = 0; i < 8; i += 2) {
6169		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6170		power_vector |= (tmp << (i * 8));
6171		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6172	}
6173	if (power_vector)
6174		lo->power_vector = power_vector;
6175
6176	BWN_GETTIME(lo->pwr_vec_read_time);
6177}
6178
6179static void
6180bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6181    int use_trsw_rx)
6182{
6183	struct bwn_phy *phy = &mac->mac_phy;
6184	struct bwn_phy_g *pg = &phy->phy_g;
6185	uint16_t tmp;
6186
6187	if (max_rx_gain < 0)
6188		max_rx_gain = 0;
6189
6190	if (BWN_HAS_LOOPBACK(phy)) {
6191		int trsw_rx = 0;
6192		int trsw_rx_gain;
6193
6194		if (use_trsw_rx) {
6195			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6196			if (max_rx_gain >= trsw_rx_gain) {
6197				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6198				trsw_rx = 0x20;
6199			}
6200		} else
6201			trsw_rx_gain = max_rx_gain;
6202		if (trsw_rx_gain < 9) {
6203			pg->pg_lna_lod_gain = 0;
6204		} else {
6205			pg->pg_lna_lod_gain = 1;
6206			trsw_rx_gain -= 8;
6207		}
6208		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6209		pg->pg_pga_gain = trsw_rx_gain / 3;
6210		if (pg->pg_pga_gain >= 5) {
6211			pg->pg_pga_gain -= 5;
6212			pg->pg_lna_gain = 2;
6213		} else
6214			pg->pg_lna_gain = 0;
6215	} else {
6216		pg->pg_lna_gain = 0;
6217		pg->pg_trsw_rx_gain = 0x20;
6218		if (max_rx_gain >= 0x14) {
6219			pg->pg_lna_lod_gain = 1;
6220			pg->pg_pga_gain = 2;
6221		} else if (max_rx_gain >= 0x12) {
6222			pg->pg_lna_lod_gain = 1;
6223			pg->pg_pga_gain = 1;
6224		} else if (max_rx_gain >= 0xf) {
6225			pg->pg_lna_lod_gain = 1;
6226			pg->pg_pga_gain = 0;
6227		} else {
6228			pg->pg_lna_lod_gain = 0;
6229			pg->pg_pga_gain = 0;
6230		}
6231	}
6232
6233	tmp = BWN_RF_READ(mac, 0x7a);
6234	if (pg->pg_lna_lod_gain == 0)
6235		tmp &= ~0x0008;
6236	else
6237		tmp |= 0x0008;
6238	BWN_RF_WRITE(mac, 0x7a, tmp);
6239}
6240
6241static void
6242bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6243{
6244	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
6245	struct bwn_phy *phy = &mac->mac_phy;
6246	struct bwn_phy_g *pg = &phy->phy_g;
6247	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6248	struct timespec ts;
6249	uint16_t tmp;
6250
6251	if (bwn_has_hwpctl(mac)) {
6252		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6253		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6254		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6255		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6256		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6257
6258		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6259		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6260		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6261		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6262	}
6263	if (phy->type == BWN_PHYTYPE_B &&
6264	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6265		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6266		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6267	}
6268	if (phy->rev >= 2) {
6269		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6270		sav->phy_analogoverval =
6271		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6272		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6273		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6274		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6275		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6276		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6277
6278		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6279		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6280		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6281		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6282		if (phy->type == BWN_PHYTYPE_G) {
6283			if ((phy->rev >= 7) &&
6284			    (sprom->bf_lo & BWN_BFL_EXTLNA)) {
6285				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6286			} else {
6287				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6288			}
6289		} else {
6290			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6291		}
6292		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6293	}
6294	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6295	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6296	sav->rf0 = BWN_RF_READ(mac, 0x43);
6297	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6298	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6299	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6300	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6301	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6302
6303	if (!BWN_HAS_TXMAG(phy)) {
6304		sav->rf2 = BWN_RF_READ(mac, 0x52);
6305		sav->rf2 &= 0x00f0;
6306	}
6307	if (phy->type == BWN_PHYTYPE_B) {
6308		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6309		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6310		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6311		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6312	} else {
6313		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6314			    | 0x8000);
6315	}
6316	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6317		    & 0xf000);
6318
6319	tmp =
6320	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6321	BWN_PHY_WRITE(mac, tmp, 0x007f);
6322
6323	tmp = sav->phy_syncctl;
6324	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6325	tmp = sav->rf1;
6326	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6327
6328	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6329	if (phy->type == BWN_PHYTYPE_G ||
6330	    (phy->type == BWN_PHYTYPE_B &&
6331	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6332		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6333	} else
6334		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6335	if (phy->rev >= 2)
6336		bwn_dummy_transmission(mac, 0, 1);
6337	bwn_phy_g_switch_chan(mac, 6, 0);
6338	BWN_RF_READ(mac, 0x51);
6339	if (phy->type == BWN_PHYTYPE_G)
6340		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6341
6342	nanouptime(&ts);
6343	if (time_before(lo->txctl_measured_time,
6344	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6345		bwn_lo_measure_txctl_values(mac);
6346
6347	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6348		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6349	else {
6350		if (phy->type == BWN_PHYTYPE_B)
6351			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6352		else
6353			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6354	}
6355}
6356
6357static void
6358bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6359{
6360	struct bwn_phy *phy = &mac->mac_phy;
6361	struct bwn_phy_g *pg = &phy->phy_g;
6362	uint16_t tmp;
6363
6364	if (phy->rev >= 2) {
6365		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6366		tmp = (pg->pg_pga_gain << 8);
6367		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6368		DELAY(5);
6369		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6370		DELAY(2);
6371		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6372	} else {
6373		tmp = (pg->pg_pga_gain | 0xefa0);
6374		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6375	}
6376	if (phy->type == BWN_PHYTYPE_G) {
6377		if (phy->rev >= 3)
6378			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6379		else
6380			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6381		if (phy->rev >= 2)
6382			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6383		else
6384			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6385	}
6386	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6387	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6388	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6389	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6390	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6391	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6392	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6393	if (!BWN_HAS_TXMAG(phy)) {
6394		tmp = sav->rf2;
6395		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6396	}
6397	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6398	if (phy->type == BWN_PHYTYPE_B &&
6399	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6400		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6401		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6402	}
6403	if (phy->rev >= 2) {
6404		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6405		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6406			      sav->phy_analogoverval);
6407		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6408		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6409		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6410		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6411		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6412	}
6413	if (bwn_has_hwpctl(mac)) {
6414		tmp = (sav->phy_lomask & 0xbfff);
6415		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6416		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6417		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6418		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6419		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6420	}
6421	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6422}
6423
6424static int
6425bwn_lo_probe_loctl(struct bwn_mac *mac,
6426    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6427{
6428	struct bwn_phy *phy = &mac->mac_phy;
6429	struct bwn_phy_g *pg = &phy->phy_g;
6430	struct bwn_loctl orig, test;
6431	struct bwn_loctl prev = { -100, -100 };
6432	static const struct bwn_loctl modifiers[] = {
6433		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6434		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6435	};
6436	int begin, end, lower = 0, i;
6437	uint16_t feedth;
6438
6439	if (d->curstate == 0) {
6440		begin = 1;
6441		end = 8;
6442	} else if (d->curstate % 2 == 0) {
6443		begin = d->curstate - 1;
6444		end = d->curstate + 1;
6445	} else {
6446		begin = d->curstate - 2;
6447		end = d->curstate + 2;
6448	}
6449	if (begin < 1)
6450		begin += 8;
6451	if (end > 8)
6452		end -= 8;
6453
6454	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6455	i = begin;
6456	d->curstate = i;
6457	while (1) {
6458		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6459		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6460		test.i += modifiers[i - 1].i * d->multipler;
6461		test.q += modifiers[i - 1].q * d->multipler;
6462		if ((test.i != prev.i || test.q != prev.q) &&
6463		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6464			bwn_lo_write(mac, &test);
6465			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6466			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6467			if (feedth < d->feedth) {
6468				memcpy(probe, &test,
6469				    sizeof(struct bwn_loctl));
6470				lower = 1;
6471				d->feedth = feedth;
6472				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6473					break;
6474			}
6475		}
6476		memcpy(&prev, &test, sizeof(prev));
6477		if (i == end)
6478			break;
6479		if (i == 8)
6480			i = 1;
6481		else
6482			i++;
6483		d->curstate = i;
6484	}
6485
6486	return (lower);
6487}
6488
6489static void
6490bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6491{
6492	struct bwn_phy *phy = &mac->mac_phy;
6493	struct bwn_phy_g *pg = &phy->phy_g;
6494	struct bwn_lo_g_sm d;
6495	struct bwn_loctl probe;
6496	int lower, repeat, cnt = 0;
6497	uint16_t feedth;
6498
6499	d.nmeasure = 0;
6500	d.multipler = 1;
6501	if (BWN_HAS_LOOPBACK(phy))
6502		d.multipler = 3;
6503
6504	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6505	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6506
6507	do {
6508		bwn_lo_write(mac, &d.loctl);
6509		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6510		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6511		if (feedth < 0x258) {
6512			if (feedth >= 0x12c)
6513				*rxgain += 6;
6514			else
6515				*rxgain += 3;
6516			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6517			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6518		}
6519		d.feedth = feedth;
6520		d.curstate = 0;
6521		do {
6522			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6523			    ("%s:%d: fail", __func__, __LINE__));
6524			memcpy(&probe, &d.loctl,
6525			       sizeof(struct bwn_loctl));
6526			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6527			if (!lower)
6528				break;
6529			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6530				break;
6531			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6532			d.nmeasure++;
6533		} while (d.nmeasure < 24);
6534		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6535
6536		if (BWN_HAS_LOOPBACK(phy)) {
6537			if (d.feedth > 0x1194)
6538				*rxgain -= 6;
6539			else if (d.feedth < 0x5dc)
6540				*rxgain += 3;
6541			if (cnt == 0) {
6542				if (d.feedth <= 0x5dc) {
6543					d.multipler = 1;
6544					cnt++;
6545				} else
6546					d.multipler = 2;
6547			} else if (cnt == 2)
6548				d.multipler = 1;
6549		}
6550		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6551	} while (++cnt < repeat);
6552}
6553
6554static struct bwn_lo_calib *
6555bwn_lo_calibset(struct bwn_mac *mac,
6556    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6557{
6558	struct bwn_phy *phy = &mac->mac_phy;
6559	struct bwn_phy_g *pg = &phy->phy_g;
6560	struct bwn_loctl loctl = { 0, 0 };
6561	struct bwn_lo_calib *cal;
6562	struct bwn_lo_g_value sval = { 0 };
6563	int rxgain;
6564	uint16_t pad, reg, value;
6565
6566	sval.old_channel = phy->chan;
6567	bwn_mac_suspend(mac);
6568	bwn_lo_save(mac, &sval);
6569
6570	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6571	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6572	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6573
6574	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6575	if (rfatt->padmix)
6576		rxgain -= pad;
6577	if (BWN_HAS_LOOPBACK(phy))
6578		rxgain += pg->pg_max_lb_gain;
6579	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6580	bwn_phy_g_set_bbatt(mac, bbatt->att);
6581	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6582
6583	bwn_lo_restore(mac, &sval);
6584	bwn_mac_enable(mac);
6585
6586	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6587	if (!cal) {
6588		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6589		return (NULL);
6590	}
6591	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6592	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6593	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6594
6595	BWN_GETTIME(cal->calib_time);
6596
6597	return (cal);
6598}
6599
6600static struct bwn_lo_calib *
6601bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6602    const struct bwn_rfatt *rfatt)
6603{
6604	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6605	struct bwn_lo_calib *c;
6606
6607	TAILQ_FOREACH(c, &lo->calib_list, list) {
6608		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6609			continue;
6610		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6611			continue;
6612		return (c);
6613	}
6614
6615	c = bwn_lo_calibset(mac, bbatt, rfatt);
6616	if (!c)
6617		return (NULL);
6618	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6619
6620	return (c);
6621}
6622
6623static void
6624bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6625{
6626	struct bwn_phy *phy = &mac->mac_phy;
6627	struct bwn_phy_g *pg = &phy->phy_g;
6628	struct bwn_softc *sc = mac->mac_sc;
6629	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6630	const struct bwn_rfatt *rfatt;
6631	const struct bwn_bbatt *bbatt;
6632	uint64_t pvector;
6633	int i;
6634	int rf_offset, bb_offset;
6635	uint8_t changed = 0;
6636
6637	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6638	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6639	    ("%s:%d: fail", __func__, __LINE__));
6640
6641	pvector = lo->power_vector;
6642	if (!update && !pvector)
6643		return;
6644
6645	bwn_mac_suspend(mac);
6646
6647	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6648		struct bwn_lo_calib *cal;
6649		int idx;
6650		uint16_t val;
6651
6652		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6653			continue;
6654		bb_offset = i / lo->rfatt.len;
6655		rf_offset = i % lo->rfatt.len;
6656		bbatt = &(lo->bbatt.array[bb_offset]);
6657		rfatt = &(lo->rfatt.array[rf_offset]);
6658
6659		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6660		if (!cal) {
6661			device_printf(sc->sc_dev, "LO: Could not "
6662			    "calibrate DC table entry\n");
6663			continue;
6664		}
6665		val = (uint8_t)(cal->ctl.q);
6666		val |= ((uint8_t)(cal->ctl.i)) << 4;
6667		free(cal, M_DEVBUF);
6668
6669		idx = i / 2;
6670		if (i % 2)
6671			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6672			    | ((val & 0x00ff) << 8);
6673		else
6674			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6675			    | (val & 0x00ff);
6676		changed = 1;
6677	}
6678	if (changed) {
6679		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6680			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6681	}
6682	bwn_mac_enable(mac);
6683}
6684
6685static void
6686bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6687{
6688
6689	if (!rf->padmix)
6690		return;
6691	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6692		rf->att = 4;
6693}
6694
6695static void
6696bwn_lo_g_adjust(struct bwn_mac *mac)
6697{
6698	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6699	struct bwn_lo_calib *cal;
6700	struct bwn_rfatt rf;
6701
6702	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6703	bwn_lo_fixup_rfatt(&rf);
6704
6705	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6706	if (!cal)
6707		return;
6708	bwn_lo_write(mac, &cal->ctl);
6709}
6710
6711static void
6712bwn_lo_g_init(struct bwn_mac *mac)
6713{
6714
6715	if (!bwn_has_hwpctl(mac))
6716		return;
6717
6718	bwn_lo_get_powervector(mac);
6719	bwn_phy_g_dc_lookup_init(mac, 1);
6720}
6721
6722static void
6723bwn_mac_suspend(struct bwn_mac *mac)
6724{
6725	struct bwn_softc *sc = mac->mac_sc;
6726	int i;
6727	uint32_t tmp;
6728
6729	KASSERT(mac->mac_suspended >= 0,
6730	    ("%s:%d: fail", __func__, __LINE__));
6731
6732	if (mac->mac_suspended == 0) {
6733		bwn_psctl(mac, BWN_PS_AWAKE);
6734		BWN_WRITE_4(mac, BWN_MACCTL,
6735			    BWN_READ_4(mac, BWN_MACCTL)
6736			    & ~BWN_MACCTL_ON);
6737		BWN_READ_4(mac, BWN_MACCTL);
6738		for (i = 35; i; i--) {
6739			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6740			if (tmp & BWN_INTR_MAC_SUSPENDED)
6741				goto out;
6742			DELAY(10);
6743		}
6744		for (i = 40; i; i--) {
6745			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6746			if (tmp & BWN_INTR_MAC_SUSPENDED)
6747				goto out;
6748			DELAY(1000);
6749		}
6750		device_printf(sc->sc_dev, "MAC suspend failed\n");
6751	}
6752out:
6753	mac->mac_suspended++;
6754}
6755
6756static void
6757bwn_mac_enable(struct bwn_mac *mac)
6758{
6759	struct bwn_softc *sc = mac->mac_sc;
6760	uint16_t state;
6761
6762	state = bwn_shm_read_2(mac, BWN_SHARED,
6763	    BWN_SHARED_UCODESTAT);
6764	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6765	    state != BWN_SHARED_UCODESTAT_SLEEP)
6766		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6767
6768	mac->mac_suspended--;
6769	KASSERT(mac->mac_suspended >= 0,
6770	    ("%s:%d: fail", __func__, __LINE__));
6771	if (mac->mac_suspended == 0) {
6772		BWN_WRITE_4(mac, BWN_MACCTL,
6773		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6774		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6775		BWN_READ_4(mac, BWN_MACCTL);
6776		BWN_READ_4(mac, BWN_INTR_REASON);
6777		bwn_psctl(mac, 0);
6778	}
6779}
6780
6781static void
6782bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6783{
6784	int i;
6785	uint16_t ucstat;
6786
6787	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6788	    ("%s:%d: fail", __func__, __LINE__));
6789	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6790	    ("%s:%d: fail", __func__, __LINE__));
6791
6792	/* XXX forcibly awake and hwps-off */
6793
6794	BWN_WRITE_4(mac, BWN_MACCTL,
6795	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6796	    ~BWN_MACCTL_HWPS);
6797	BWN_READ_4(mac, BWN_MACCTL);
6798	if (mac->mac_sd->sd_id.sd_rev >= 5) {
6799		for (i = 0; i < 100; i++) {
6800			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6801			    BWN_SHARED_UCODESTAT);
6802			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6803				break;
6804			DELAY(10);
6805		}
6806	}
6807}
6808
6809static int16_t
6810bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6811{
6812
6813	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6814	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6815}
6816
6817static void
6818bwn_nrssi_threshold(struct bwn_mac *mac)
6819{
6820	struct bwn_phy *phy = &mac->mac_phy;
6821	struct bwn_phy_g *pg = &phy->phy_g;
6822	struct siba_softc *siba = mac->mac_sd->sd_bus;
6823	int32_t a, b;
6824	int16_t tmp16;
6825	uint16_t tmpu16;
6826
6827	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6828
6829	if (phy->gmode && (siba->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
6830		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6831			a = 0x13;
6832			b = 0x12;
6833		} else {
6834			a = 0xe;
6835			b = 0x11;
6836		}
6837
6838		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6839		a += (pg->pg_nrssi[0] << 6);
6840		a += (a < 32) ? 31 : 32;
6841		a = a >> 6;
6842		a = MIN(MAX(a, -31), 31);
6843
6844		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6845		b += (pg->pg_nrssi[0] << 6);
6846		if (b < 32)
6847			b += 31;
6848		else
6849			b += 32;
6850		b = b >> 6;
6851		b = MIN(MAX(b, -31), 31);
6852
6853		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6854		tmpu16 |= ((uint32_t)b & 0x0000003f);
6855		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6856		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6857		return;
6858	}
6859
6860	tmp16 = bwn_nrssi_read(mac, 0x20);
6861	if (tmp16 >= 0x20)
6862		tmp16 -= 0x40;
6863	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6864}
6865
6866static void
6867bwn_nrssi_slope_11g(struct bwn_mac *mac)
6868{
6869#define	SAVE_RF_MAX		3
6870#define	SAVE_PHY_COMM_MAX	4
6871#define	SAVE_PHY3_MAX		8
6872	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6873		{ 0x7a, 0x52, 0x43 };
6874	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6875		{ 0x15, 0x5a, 0x59, 0x58 };
6876	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6877		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6878		0x0801, 0x0060, 0x0014, 0x0478
6879	};
6880	struct bwn_phy *phy = &mac->mac_phy;
6881	struct bwn_phy_g *pg = &phy->phy_g;
6882	int32_t i, tmp32, phy3_idx = 0;
6883	uint16_t delta, tmp;
6884	uint16_t save_rf[SAVE_RF_MAX];
6885	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6886	uint16_t save_phy3[SAVE_PHY3_MAX];
6887	uint16_t ant_div, phy0, chan_ex;
6888	int16_t nrssi0, nrssi1;
6889
6890	KASSERT(phy->type == BWN_PHYTYPE_G,
6891	    ("%s:%d: fail", __func__, __LINE__));
6892
6893	if (phy->rf_rev >= 9)
6894		return;
6895	if (phy->rf_rev == 8)
6896		bwn_nrssi_offset(mac);
6897
6898	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6899	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6900
6901	/*
6902	 * Save RF/PHY registers for later restoration
6903	 */
6904	ant_div = BWN_READ_2(mac, 0x03e2);
6905	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6906	for (i = 0; i < SAVE_RF_MAX; ++i)
6907		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6908	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6909		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6910
6911	phy0 = BWN_READ_2(mac, BWN_PHY0);
6912	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6913	if (phy->rev >= 3) {
6914		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6915			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6916		BWN_PHY_WRITE(mac, 0x002e, 0);
6917		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6918		switch (phy->rev) {
6919		case 4:
6920		case 6:
6921		case 7:
6922			BWN_PHY_SET(mac, 0x0478, 0x0100);
6923			BWN_PHY_SET(mac, 0x0801, 0x0040);
6924			break;
6925		case 3:
6926		case 5:
6927			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6928			break;
6929		}
6930		BWN_PHY_SET(mac, 0x0060, 0x0040);
6931		BWN_PHY_SET(mac, 0x0014, 0x0200);
6932	}
6933	/*
6934	 * Calculate nrssi0
6935	 */
6936	BWN_RF_SET(mac, 0x007a, 0x0070);
6937	bwn_set_all_gains(mac, 0, 8, 0);
6938	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6939	if (phy->rev >= 2) {
6940		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6941		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6942	}
6943	BWN_RF_SET(mac, 0x007a, 0x0080);
6944	DELAY(20);
6945
6946	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6947	if (nrssi0 >= 0x0020)
6948		nrssi0 -= 0x0040;
6949
6950	/*
6951	 * Calculate nrssi1
6952	 */
6953	BWN_RF_MASK(mac, 0x007a, 0x007f);
6954	if (phy->rev >= 2)
6955		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6956
6957	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6958	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6959	BWN_RF_SET(mac, 0x007a, 0x000f);
6960	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6961	if (phy->rev >= 2) {
6962		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6963		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6964	}
6965
6966	bwn_set_all_gains(mac, 3, 0, 1);
6967	if (phy->rf_rev == 8) {
6968		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6969	} else {
6970		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6971		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6972		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6973		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6974	}
6975	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6976	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6977	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6978	DELAY(20);
6979	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6980
6981	/*
6982	 * Install calculated narrow RSSI values
6983	 */
6984	if (nrssi1 >= 0x0020)
6985		nrssi1 -= 0x0040;
6986	if (nrssi0 == nrssi1)
6987		pg->pg_nrssi_slope = 0x00010000;
6988	else
6989		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6990	if (nrssi0 >= -4) {
6991		pg->pg_nrssi[0] = nrssi1;
6992		pg->pg_nrssi[1] = nrssi0;
6993	}
6994
6995	/*
6996	 * Restore saved RF/PHY registers
6997	 */
6998	if (phy->rev >= 3) {
6999		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
7000			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7001			    save_phy3[phy3_idx]);
7002		}
7003	}
7004	if (phy->rev >= 2) {
7005		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
7006		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
7007	}
7008
7009	for (i = 0; i < SAVE_RF_MAX; ++i)
7010		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7011
7012	BWN_WRITE_2(mac, 0x03e2, ant_div);
7013	BWN_WRITE_2(mac, 0x03e6, phy0);
7014	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
7015
7016	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7017		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7018
7019	bwn_spu_workaround(mac, phy->chan);
7020	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
7021	bwn_set_original_gains(mac);
7022	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
7023	if (phy->rev >= 3) {
7024		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
7025			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7026			    save_phy3[phy3_idx]);
7027		}
7028	}
7029
7030	delta = 0x1f - pg->pg_nrssi[0];
7031	for (i = 0; i < 64; i++) {
7032		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
7033		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7034		pg->pg_nrssi_lt[i] = tmp32;
7035	}
7036
7037	bwn_nrssi_threshold(mac);
7038#undef SAVE_RF_MAX
7039#undef SAVE_PHY_COMM_MAX
7040#undef SAVE_PHY3_MAX
7041}
7042
7043static void
7044bwn_nrssi_offset(struct bwn_mac *mac)
7045{
7046#define	SAVE_RF_MAX		2
7047#define	SAVE_PHY_COMM_MAX	10
7048#define	SAVE_PHY6_MAX		8
7049	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7050		{ 0x7a, 0x43 };
7051	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7052		0x0001, 0x0811, 0x0812, 0x0814,
7053		0x0815, 0x005a, 0x0059, 0x0058,
7054		0x000a, 0x0003
7055	};
7056	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7057		0x002e, 0x002f, 0x080f, 0x0810,
7058		0x0801, 0x0060, 0x0014, 0x0478
7059	};
7060	struct bwn_phy *phy = &mac->mac_phy;
7061	int i, phy6_idx = 0;
7062	uint16_t save_rf[SAVE_RF_MAX];
7063	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7064	uint16_t save_phy6[SAVE_PHY6_MAX];
7065	int16_t nrssi;
7066	uint16_t saved = 0xffff;
7067
7068	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7069		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7070	for (i = 0; i < SAVE_RF_MAX; ++i)
7071		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7072
7073	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7074	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7075	BWN_PHY_SET(mac, 0x0811, 0x000c);
7076	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7077	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7078	if (phy->rev >= 6) {
7079		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7080			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7081
7082		BWN_PHY_WRITE(mac, 0x002e, 0);
7083		BWN_PHY_WRITE(mac, 0x002f, 0);
7084		BWN_PHY_WRITE(mac, 0x080f, 0);
7085		BWN_PHY_WRITE(mac, 0x0810, 0);
7086		BWN_PHY_SET(mac, 0x0478, 0x0100);
7087		BWN_PHY_SET(mac, 0x0801, 0x0040);
7088		BWN_PHY_SET(mac, 0x0060, 0x0040);
7089		BWN_PHY_SET(mac, 0x0014, 0x0200);
7090	}
7091	BWN_RF_SET(mac, 0x007a, 0x0070);
7092	BWN_RF_SET(mac, 0x007a, 0x0080);
7093	DELAY(30);
7094
7095	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7096	if (nrssi >= 0x20)
7097		nrssi -= 0x40;
7098	if (nrssi == 31) {
7099		for (i = 7; i >= 4; i--) {
7100			BWN_RF_WRITE(mac, 0x007b, i);
7101			DELAY(20);
7102			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7103			    0x003f);
7104			if (nrssi >= 0x20)
7105				nrssi -= 0x40;
7106			if (nrssi < 31 && saved == 0xffff)
7107				saved = i;
7108		}
7109		if (saved == 0xffff)
7110			saved = 4;
7111	} else {
7112		BWN_RF_MASK(mac, 0x007a, 0x007f);
7113		if (phy->rev != 1) {
7114			BWN_PHY_SET(mac, 0x0814, 0x0001);
7115			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7116		}
7117		BWN_PHY_SET(mac, 0x0811, 0x000c);
7118		BWN_PHY_SET(mac, 0x0812, 0x000c);
7119		BWN_PHY_SET(mac, 0x0811, 0x0030);
7120		BWN_PHY_SET(mac, 0x0812, 0x0030);
7121		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7122		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7123		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7124		if (phy->rev == 0)
7125			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7126		else
7127			BWN_PHY_SET(mac, 0x000a, 0x2000);
7128		if (phy->rev != 1) {
7129			BWN_PHY_SET(mac, 0x0814, 0x0004);
7130			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7131		}
7132		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7133		BWN_RF_SET(mac, 0x007a, 0x000f);
7134		bwn_set_all_gains(mac, 3, 0, 1);
7135		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7136		DELAY(30);
7137		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7138		if (nrssi >= 0x20)
7139			nrssi -= 0x40;
7140		if (nrssi == -32) {
7141			for (i = 0; i < 4; i++) {
7142				BWN_RF_WRITE(mac, 0x007b, i);
7143				DELAY(20);
7144				nrssi = (int16_t)((BWN_PHY_READ(mac,
7145				    0x047f) >> 8) & 0x003f);
7146				if (nrssi >= 0x20)
7147					nrssi -= 0x40;
7148				if (nrssi > -31 && saved == 0xffff)
7149					saved = i;
7150			}
7151			if (saved == 0xffff)
7152				saved = 3;
7153		} else
7154			saved = 0;
7155	}
7156	BWN_RF_WRITE(mac, 0x007b, saved);
7157
7158	/*
7159	 * Restore saved RF/PHY registers
7160	 */
7161	if (phy->rev >= 6) {
7162		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7163			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7164			    save_phy6[phy6_idx]);
7165		}
7166	}
7167	if (phy->rev != 1) {
7168		for (i = 3; i < 5; i++)
7169			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7170			    save_phy_comm[i]);
7171	}
7172	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7173		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7174
7175	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7176		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7177
7178	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7179	BWN_PHY_SET(mac, 0x0429, 0x8000);
7180	bwn_set_original_gains(mac);
7181	if (phy->rev >= 6) {
7182		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7183			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7184			    save_phy6[phy6_idx]);
7185		}
7186	}
7187
7188	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7189	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7190	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7191}
7192
7193static void
7194bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7195    int16_t third)
7196{
7197	struct bwn_phy *phy = &mac->mac_phy;
7198	uint16_t i;
7199	uint16_t start = 0x08, end = 0x18;
7200	uint16_t tmp;
7201	uint16_t table;
7202
7203	if (phy->rev <= 1) {
7204		start = 0x10;
7205		end = 0x20;
7206	}
7207
7208	table = BWN_OFDMTAB_GAINX;
7209	if (phy->rev <= 1)
7210		table = BWN_OFDMTAB_GAINX_R1;
7211	for (i = 0; i < 4; i++)
7212		bwn_ofdmtab_write_2(mac, table, i, first);
7213
7214	for (i = start; i < end; i++)
7215		bwn_ofdmtab_write_2(mac, table, i, second);
7216
7217	if (third != -1) {
7218		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7219		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7220		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7221		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7222	}
7223	bwn_dummy_transmission(mac, 0, 1);
7224}
7225
7226static void
7227bwn_set_original_gains(struct bwn_mac *mac)
7228{
7229	struct bwn_phy *phy = &mac->mac_phy;
7230	uint16_t i, tmp;
7231	uint16_t table;
7232	uint16_t start = 0x0008, end = 0x0018;
7233
7234	if (phy->rev <= 1) {
7235		start = 0x0010;
7236		end = 0x0020;
7237	}
7238
7239	table = BWN_OFDMTAB_GAINX;
7240	if (phy->rev <= 1)
7241		table = BWN_OFDMTAB_GAINX_R1;
7242	for (i = 0; i < 4; i++) {
7243		tmp = (i & 0xfffc);
7244		tmp |= (i & 0x0001) << 1;
7245		tmp |= (i & 0x0002) >> 1;
7246
7247		bwn_ofdmtab_write_2(mac, table, i, tmp);
7248	}
7249
7250	for (i = start; i < end; i++)
7251		bwn_ofdmtab_write_2(mac, table, i, i - start);
7252
7253	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7254	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7255	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7256	bwn_dummy_transmission(mac, 0, 1);
7257}
7258
7259static void
7260bwn_phy_hwpctl_init(struct bwn_mac *mac)
7261{
7262	struct siba_softc *bus = mac->mac_sd->sd_bus;
7263	struct bwn_phy *phy = &mac->mac_phy;
7264	struct bwn_phy_g *pg = &phy->phy_g;
7265	struct bwn_rfatt old_rfatt, rfatt;
7266	struct bwn_bbatt old_bbatt, bbatt;
7267	uint8_t old_txctl = 0;
7268
7269	KASSERT(phy->type == BWN_PHYTYPE_G,
7270	    ("%s:%d: fail", __func__, __LINE__));
7271
7272	if ((bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM) &&
7273	    (bus->siba_board_type == SIBA_BOARD_BU4306))
7274		return;
7275
7276	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7277
7278	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7279
7280	if (!phy->gmode)
7281		return;
7282	bwn_hwpctl_early_init(mac);
7283	if (pg->pg_curtssi == 0) {
7284		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7285			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7286		} else {
7287			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7288			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7289			old_txctl = pg->pg_txctl;
7290
7291			bbatt.att = 11;
7292			if (phy->rf_rev == 8) {
7293				rfatt.att = 15;
7294				rfatt.padmix = 1;
7295			} else {
7296				rfatt.att = 9;
7297				rfatt.padmix = 0;
7298			}
7299			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7300		}
7301		bwn_dummy_transmission(mac, 0, 1);
7302		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7303		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7304			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7305		else
7306			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7307			    &old_rfatt, old_txctl);
7308	}
7309	bwn_hwpctl_init_gphy(mac);
7310
7311	/* clear TSSI */
7312	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7313	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7314	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7315	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7316}
7317
7318static void
7319bwn_hwpctl_early_init(struct bwn_mac *mac)
7320{
7321	struct bwn_phy *phy = &mac->mac_phy;
7322
7323	if (!bwn_has_hwpctl(mac)) {
7324		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7325		return;
7326	}
7327
7328	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7329	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7330	BWN_PHY_SET(mac, 0x047c, 0x0002);
7331	BWN_PHY_SET(mac, 0x047a, 0xf000);
7332	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7333		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7334		BWN_PHY_SET(mac, 0x005d, 0x8000);
7335		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7336		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7337		BWN_PHY_SET(mac, 0x0036, 0x0400);
7338	} else {
7339		BWN_PHY_SET(mac, 0x0036, 0x0200);
7340		BWN_PHY_SET(mac, 0x0036, 0x0400);
7341		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7342		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7343		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7344		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7345		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7346	}
7347}
7348
7349static void
7350bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7351{
7352	struct bwn_phy *phy = &mac->mac_phy;
7353	struct bwn_phy_g *pg = &phy->phy_g;
7354	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7355	int i;
7356	uint16_t nr_written = 0, tmp, value;
7357	uint8_t rf, bb;
7358
7359	if (!bwn_has_hwpctl(mac)) {
7360		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7361		return;
7362	}
7363
7364	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7365	    (pg->pg_idletssi - pg->pg_curtssi));
7366	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7367	    (pg->pg_idletssi - pg->pg_curtssi));
7368
7369	for (i = 0; i < 32; i++)
7370		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7371	for (i = 32; i < 64; i++)
7372		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7373	for (i = 0; i < 64; i += 2) {
7374		value = (uint16_t) pg->pg_tssi2dbm[i];
7375		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7376		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7377	}
7378
7379	for (rf = 0; rf < lo->rfatt.len; rf++) {
7380		for (bb = 0; bb < lo->bbatt.len; bb++) {
7381			if (nr_written >= 0x40)
7382				return;
7383			tmp = lo->bbatt.array[bb].att;
7384			tmp <<= 8;
7385			if (phy->rf_rev == 8)
7386				tmp |= 0x50;
7387			else
7388				tmp |= 0x40;
7389			tmp |= lo->rfatt.array[rf].att;
7390			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7391			nr_written++;
7392		}
7393	}
7394
7395	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7396	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7397
7398	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7399	BWN_PHY_SET(mac, 0x0478, 0x0800);
7400	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7401	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7402
7403	bwn_phy_g_dc_lookup_init(mac, 1);
7404	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7405}
7406
7407static void
7408bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7409{
7410	struct siba_softc *siba = mac->mac_sd->sd_bus;
7411
7412	if (spu != 0)
7413		bwn_spu_workaround(mac, channel);
7414
7415	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7416
7417	if (channel == 14) {
7418		if (siba->siba_sprom.ccode == SIBA_CCODE_JAPAN)
7419			bwn_hf_write(mac,
7420			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7421		else
7422			bwn_hf_write(mac,
7423			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7424		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7425		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7426		return;
7427	}
7428
7429	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7430	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7431}
7432
7433static uint16_t
7434bwn_phy_g_chan2freq(uint8_t channel)
7435{
7436	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7437
7438	KASSERT(channel >= 1 && channel <= 14,
7439	    ("%s:%d: fail", __func__, __LINE__));
7440
7441	return (bwn_phy_g_rf_channels[channel - 1]);
7442}
7443
7444static void
7445bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7446    const struct bwn_rfatt *rfatt, uint8_t txctl)
7447{
7448	struct bwn_phy *phy = &mac->mac_phy;
7449	struct bwn_phy_g *pg = &phy->phy_g;
7450	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7451	uint16_t bb, rf;
7452	uint16_t tx_bias, tx_magn;
7453
7454	bb = bbatt->att;
7455	rf = rfatt->att;
7456	tx_bias = lo->tx_bias;
7457	tx_magn = lo->tx_magn;
7458	if (tx_bias == 0xff)
7459		tx_bias = 0;
7460
7461	pg->pg_txctl = txctl;
7462	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7463	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7464	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7465	bwn_phy_g_set_bbatt(mac, bb);
7466	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7467	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7468		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7469	else {
7470		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7471		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7472	}
7473	if (BWN_HAS_TXMAG(phy))
7474		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7475	else
7476		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7477	bwn_lo_g_adjust(mac);
7478}
7479
7480static void
7481bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7482    uint16_t bbatt)
7483{
7484	struct bwn_phy *phy = &mac->mac_phy;
7485
7486	if (phy->analog == 0) {
7487		BWN_WRITE_2(mac, BWN_PHY0,
7488		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7489		return;
7490	}
7491	if (phy->analog > 1) {
7492		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7493		return;
7494	}
7495	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7496}
7497
7498static uint16_t
7499bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7500{
7501	struct bwn_phy *phy = &mac->mac_phy;
7502	struct bwn_phy_g *pg = &phy->phy_g;
7503	struct siba_sprom *sprom = &(mac->mac_sd->sd_bus->siba_sprom);
7504	int max_lb_gain;
7505	uint16_t extlna;
7506	uint16_t i;
7507
7508	if (phy->gmode == 0)
7509		return (0);
7510
7511	if (BWN_HAS_LOOPBACK(phy)) {
7512		max_lb_gain = pg->pg_max_lb_gain;
7513		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7514		if (max_lb_gain >= 0x46) {
7515			extlna = 0x3000;
7516			max_lb_gain -= 0x46;
7517		} else if (max_lb_gain >= 0x3a) {
7518			extlna = 0x1000;
7519			max_lb_gain -= 0x3a;
7520		} else if (max_lb_gain >= 0x2e) {
7521			extlna = 0x2000;
7522			max_lb_gain -= 0x2e;
7523		} else {
7524			extlna = 0;
7525			max_lb_gain -= 0x10;
7526		}
7527
7528		for (i = 0; i < 16; i++) {
7529			max_lb_gain -= (i * 6);
7530			if (max_lb_gain < 6)
7531				break;
7532		}
7533
7534		if ((phy->rev < 7) || !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7535			if (reg == BWN_PHY_RFOVER) {
7536				return (0x1b3);
7537			} else if (reg == BWN_PHY_RFOVERVAL) {
7538				extlna |= (i << 8);
7539				switch (lpd) {
7540				case BWN_LPD(0, 1, 1):
7541					return (0x0f92);
7542				case BWN_LPD(0, 0, 1):
7543				case BWN_LPD(1, 0, 1):
7544					return (0x0092 | extlna);
7545				case BWN_LPD(1, 0, 0):
7546					return (0x0093 | extlna);
7547				}
7548				KASSERT(0 == 1,
7549				    ("%s:%d: fail", __func__, __LINE__));
7550			}
7551			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7552		} else {
7553			if (reg == BWN_PHY_RFOVER)
7554				return (0x9b3);
7555			if (reg == BWN_PHY_RFOVERVAL) {
7556				if (extlna)
7557					extlna |= 0x8000;
7558				extlna |= (i << 8);
7559				switch (lpd) {
7560				case BWN_LPD(0, 1, 1):
7561					return (0x8f92);
7562				case BWN_LPD(0, 0, 1):
7563					return (0x8092 | extlna);
7564				case BWN_LPD(1, 0, 1):
7565					return (0x2092 | extlna);
7566				case BWN_LPD(1, 0, 0):
7567					return (0x2093 | extlna);
7568				}
7569				KASSERT(0 == 1,
7570				    ("%s:%d: fail", __func__, __LINE__));
7571			}
7572			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7573		}
7574		return (0);
7575	}
7576
7577	if ((phy->rev < 7) ||
7578	    !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7579		if (reg == BWN_PHY_RFOVER) {
7580			return (0x1b3);
7581		} else if (reg == BWN_PHY_RFOVERVAL) {
7582			switch (lpd) {
7583			case BWN_LPD(0, 1, 1):
7584				return (0x0fb2);
7585			case BWN_LPD(0, 0, 1):
7586				return (0x00b2);
7587			case BWN_LPD(1, 0, 1):
7588				return (0x30b2);
7589			case BWN_LPD(1, 0, 0):
7590				return (0x30b3);
7591			}
7592			KASSERT(0 == 1,
7593			    ("%s:%d: fail", __func__, __LINE__));
7594		}
7595		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7596	} else {
7597		if (reg == BWN_PHY_RFOVER) {
7598			return (0x9b3);
7599		} else if (reg == BWN_PHY_RFOVERVAL) {
7600			switch (lpd) {
7601			case BWN_LPD(0, 1, 1):
7602				return (0x8fb2);
7603			case BWN_LPD(0, 0, 1):
7604				return (0x80b2);
7605			case BWN_LPD(1, 0, 1):
7606				return (0x20b2);
7607			case BWN_LPD(1, 0, 0):
7608				return (0x20b3);
7609			}
7610			KASSERT(0 == 1,
7611			    ("%s:%d: fail", __func__, __LINE__));
7612		}
7613		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7614	}
7615	return (0);
7616}
7617
7618static void
7619bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7620{
7621
7622	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7623		return;
7624	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7625	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7626	DELAY(1000);
7627	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7628}
7629
7630static int
7631bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7632{
7633	struct bwn_softc *sc = mac->mac_sc;
7634	struct bwn_fw *fw = &mac->mac_fw;
7635	const uint8_t rev = mac->mac_sd->sd_id.sd_rev;
7636	const char *filename;
7637	uint32_t high;
7638	int error;
7639
7640	/* microcode */
7641	if (rev >= 5 && rev <= 10)
7642		filename = "ucode5";
7643	else if (rev >= 11 && rev <= 12)
7644		filename = "ucode11";
7645	else if (rev == 13)
7646		filename = "ucode13";
7647	else if (rev == 14)
7648		filename = "ucode14";
7649	else if (rev >= 15)
7650		filename = "ucode15";
7651	else {
7652		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7653		bwn_release_firmware(mac);
7654		return (EOPNOTSUPP);
7655	}
7656	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7657	if (error) {
7658		bwn_release_firmware(mac);
7659		return (error);
7660	}
7661
7662	/* PCM */
7663	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7664	if (rev >= 5 && rev <= 10) {
7665		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7666		if (error == ENOENT)
7667			fw->no_pcmfile = 1;
7668		else if (error) {
7669			bwn_release_firmware(mac);
7670			return (error);
7671		}
7672	} else if (rev < 11) {
7673		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7674		return (EOPNOTSUPP);
7675	}
7676
7677	/* initvals */
7678	high = siba_read_4(mac->mac_sd, SIBA_TGSHIGH);
7679	switch (mac->mac_phy.type) {
7680	case BWN_PHYTYPE_A:
7681		if (rev < 5 || rev > 10)
7682			goto fail1;
7683		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7684			filename = "a0g1initvals5";
7685		else
7686			filename = "a0g0initvals5";
7687		break;
7688	case BWN_PHYTYPE_G:
7689		if (rev >= 5 && rev <= 10)
7690			filename = "b0g0initvals5";
7691		else if (rev >= 13)
7692			filename = "b0g0initvals13";
7693		else
7694			goto fail1;
7695		break;
7696	case BWN_PHYTYPE_LP:
7697		if (rev == 13)
7698			filename = "lp0initvals13";
7699		else if (rev == 14)
7700			filename = "lp0initvals14";
7701		else if (rev >= 15)
7702			filename = "lp0initvals15";
7703		else
7704			goto fail1;
7705		break;
7706	case BWN_PHYTYPE_N:
7707		if (rev >= 11 && rev <= 12)
7708			filename = "n0initvals11";
7709		else
7710			goto fail1;
7711		break;
7712	default:
7713		goto fail1;
7714	}
7715	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7716	if (error) {
7717		bwn_release_firmware(mac);
7718		return (error);
7719	}
7720
7721	/* bandswitch initvals */
7722	switch (mac->mac_phy.type) {
7723	case BWN_PHYTYPE_A:
7724		if (rev >= 5 && rev <= 10) {
7725			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7726				filename = "a0g1bsinitvals5";
7727			else
7728				filename = "a0g0bsinitvals5";
7729		} else if (rev >= 11)
7730			filename = NULL;
7731		else
7732			goto fail1;
7733		break;
7734	case BWN_PHYTYPE_G:
7735		if (rev >= 5 && rev <= 10)
7736			filename = "b0g0bsinitvals5";
7737		else if (rev >= 11)
7738			filename = NULL;
7739		else
7740			goto fail1;
7741		break;
7742	case BWN_PHYTYPE_LP:
7743		if (rev == 13)
7744			filename = "lp0bsinitvals13";
7745		else if (rev == 14)
7746			filename = "lp0bsinitvals14";
7747		else if (rev >= 15)
7748			filename = "lp0bsinitvals15";
7749		else
7750			goto fail1;
7751		break;
7752	case BWN_PHYTYPE_N:
7753		if (rev >= 11 && rev <= 12)
7754			filename = "n0bsinitvals11";
7755		else
7756			goto fail1;
7757		break;
7758	default:
7759		goto fail1;
7760	}
7761	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7762	if (error) {
7763		bwn_release_firmware(mac);
7764		return (error);
7765	}
7766	return (0);
7767fail1:
7768	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7769	bwn_release_firmware(mac);
7770	return (EOPNOTSUPP);
7771}
7772
7773static int
7774bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7775    const char *name, struct bwn_fwfile *bfw)
7776{
7777	const struct bwn_fwhdr *hdr;
7778	struct bwn_softc *sc = mac->mac_sc;
7779	const struct firmware *fw;
7780	char namebuf[64];
7781
7782	if (name == NULL) {
7783		bwn_do_release_fw(bfw);
7784		return (0);
7785	}
7786	if (bfw->filename != NULL) {
7787		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7788			return (0);
7789		bwn_do_release_fw(bfw);
7790	}
7791
7792	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s",
7793	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "", name);
7794	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7795	fw = firmware_get(namebuf);
7796	if (fw == NULL) {
7797		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7798		    namebuf);
7799		return (ENOENT);
7800	}
7801	if (fw->datasize < sizeof(struct bwn_fwhdr))
7802		goto fail;
7803	hdr = (const struct bwn_fwhdr *)(fw->data);
7804	switch (hdr->type) {
7805	case BWN_FWTYPE_UCODE:
7806	case BWN_FWTYPE_PCM:
7807		if (be32toh(hdr->size) !=
7808		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7809			goto fail;
7810		/* FALLTHROUGH */
7811	case BWN_FWTYPE_IV:
7812		if (hdr->ver != 1)
7813			goto fail;
7814		break;
7815	default:
7816		goto fail;
7817	}
7818	bfw->filename = name;
7819	bfw->fw = fw;
7820	bfw->type = type;
7821	return (0);
7822fail:
7823	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7824	if (fw != NULL)
7825		firmware_put(fw, FIRMWARE_UNLOAD);
7826	return (EPROTO);
7827}
7828
7829static void
7830bwn_release_firmware(struct bwn_mac *mac)
7831{
7832
7833	bwn_do_release_fw(&mac->mac_fw.ucode);
7834	bwn_do_release_fw(&mac->mac_fw.pcm);
7835	bwn_do_release_fw(&mac->mac_fw.initvals);
7836	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7837}
7838
7839static void
7840bwn_do_release_fw(struct bwn_fwfile *bfw)
7841{
7842
7843	if (bfw->fw != NULL)
7844		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7845	bfw->fw = NULL;
7846	bfw->filename = NULL;
7847}
7848
7849static int
7850bwn_fw_loaducode(struct bwn_mac *mac)
7851{
7852#define	GETFWOFFSET(fwp, offset)	\
7853	((const uint32_t *)((const char *)fwp.fw->data + offset))
7854#define	GETFWSIZE(fwp, offset)	\
7855	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7856	struct bwn_softc *sc = mac->mac_sc;
7857	const uint32_t *data;
7858	unsigned int i;
7859	uint32_t ctl;
7860	uint16_t date, fwcaps, time;
7861	int error = 0;
7862
7863	ctl = BWN_READ_4(mac, BWN_MACCTL);
7864	ctl |= BWN_MACCTL_MCODE_JMP0;
7865	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7866	    __LINE__));
7867	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7868	for (i = 0; i < 64; i++)
7869		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7870	for (i = 0; i < 4096; i += 2)
7871		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7872
7873	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7874	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7875	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7876	     i++) {
7877		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7878		DELAY(10);
7879	}
7880
7881	if (mac->mac_fw.pcm.fw) {
7882		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7883		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7884		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7885		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7886		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7887		    sizeof(struct bwn_fwhdr)); i++) {
7888			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7889			DELAY(10);
7890		}
7891	}
7892
7893	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7894	BWN_WRITE_4(mac, BWN_MACCTL,
7895	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7896	    BWN_MACCTL_MCODE_RUN);
7897
7898	for (i = 0; i < 21; i++) {
7899		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7900			break;
7901		if (i >= 20) {
7902			device_printf(sc->sc_dev, "ucode timeout\n");
7903			error = ENXIO;
7904			goto error;
7905		}
7906		DELAY(50000);
7907	}
7908	BWN_READ_4(mac, BWN_INTR_REASON);
7909
7910	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7911	if (mac->mac_fw.rev <= 0x128) {
7912		device_printf(sc->sc_dev, "the firmware is too old\n");
7913		error = EOPNOTSUPP;
7914		goto error;
7915	}
7916	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7917	    BWN_SHARED_UCODE_PATCH);
7918	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7919	mac->mac_fw.opensource = (date == 0xffff);
7920	if (bwn_wme != 0)
7921		mac->mac_flags |= BWN_MAC_FLAG_WME;
7922	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7923
7924	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7925	if (mac->mac_fw.opensource == 0) {
7926		device_printf(sc->sc_dev,
7927		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7928		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7929		if (mac->mac_fw.no_pcmfile)
7930			device_printf(sc->sc_dev,
7931			    "no HW crypto acceleration due to pcm5\n");
7932	} else {
7933		mac->mac_fw.patch = time;
7934		fwcaps = bwn_fwcaps_read(mac);
7935		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7936			device_printf(sc->sc_dev,
7937			    "disabling HW crypto acceleration\n");
7938			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7939		}
7940		if (!(fwcaps & BWN_FWCAPS_WME)) {
7941			device_printf(sc->sc_dev, "disabling WME support\n");
7942			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7943		}
7944	}
7945
7946	if (BWN_ISOLDFMT(mac))
7947		device_printf(sc->sc_dev, "using old firmware image\n");
7948
7949	return (0);
7950
7951error:
7952	BWN_WRITE_4(mac, BWN_MACCTL,
7953	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7954	    BWN_MACCTL_MCODE_JMP0);
7955
7956	return (error);
7957#undef GETFWSIZE
7958#undef GETFWOFFSET
7959}
7960
7961/* OpenFirmware only */
7962static uint16_t
7963bwn_fwcaps_read(struct bwn_mac *mac)
7964{
7965
7966	KASSERT(mac->mac_fw.opensource == 1,
7967	    ("%s:%d: fail", __func__, __LINE__));
7968	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7969}
7970
7971static int
7972bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7973    size_t count, size_t array_size)
7974{
7975#define	GET_NEXTIV16(iv)						\
7976	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7977	    sizeof(uint16_t) + sizeof(uint16_t)))
7978#define	GET_NEXTIV32(iv)						\
7979	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7980	    sizeof(uint16_t) + sizeof(uint32_t)))
7981	struct bwn_softc *sc = mac->mac_sc;
7982	const struct bwn_fwinitvals *iv;
7983	uint16_t offset;
7984	size_t i;
7985	uint8_t bit32;
7986
7987	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7988	    ("%s:%d: fail", __func__, __LINE__));
7989	iv = ivals;
7990	for (i = 0; i < count; i++) {
7991		if (array_size < sizeof(iv->offset_size))
7992			goto fail;
7993		array_size -= sizeof(iv->offset_size);
7994		offset = be16toh(iv->offset_size);
7995		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7996		offset &= BWN_FWINITVALS_OFFSET_MASK;
7997		if (offset >= 0x1000)
7998			goto fail;
7999		if (bit32) {
8000			if (array_size < sizeof(iv->data.d32))
8001				goto fail;
8002			array_size -= sizeof(iv->data.d32);
8003			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
8004			iv = GET_NEXTIV32(iv);
8005		} else {
8006
8007			if (array_size < sizeof(iv->data.d16))
8008				goto fail;
8009			array_size -= sizeof(iv->data.d16);
8010			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
8011
8012			iv = GET_NEXTIV16(iv);
8013		}
8014	}
8015	if (array_size != 0)
8016		goto fail;
8017	return (0);
8018fail:
8019	device_printf(sc->sc_dev, "initvals: invalid format\n");
8020	return (EPROTO);
8021#undef GET_NEXTIV16
8022#undef GET_NEXTIV32
8023}
8024
8025static int
8026bwn_switch_channel(struct bwn_mac *mac, int chan)
8027{
8028	struct bwn_phy *phy = &(mac->mac_phy);
8029	struct bwn_softc *sc = mac->mac_sc;
8030	struct ifnet *ifp = sc->sc_ifp;
8031	struct ieee80211com *ic = ifp->if_l2com;
8032	uint16_t channelcookie, savedcookie;
8033	int error;
8034
8035	if (chan == 0xffff)
8036		chan = phy->get_default_chan(mac);
8037
8038	channelcookie = chan;
8039	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8040		channelcookie |= 0x100;
8041	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8042	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8043	error = phy->switch_channel(mac, chan);
8044	if (error)
8045		goto fail;
8046
8047	mac->mac_phy.chan = chan;
8048	DELAY(8000);
8049	return (0);
8050fail:
8051	device_printf(sc->sc_dev, "failed to switch channel\n");
8052	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8053	return (error);
8054}
8055
8056static uint16_t
8057bwn_ant2phy(int antenna)
8058{
8059
8060	switch (antenna) {
8061	case BWN_ANT0:
8062		return (BWN_TX_PHY_ANT0);
8063	case BWN_ANT1:
8064		return (BWN_TX_PHY_ANT1);
8065	case BWN_ANT2:
8066		return (BWN_TX_PHY_ANT2);
8067	case BWN_ANT3:
8068		return (BWN_TX_PHY_ANT3);
8069	case BWN_ANTAUTO:
8070		return (BWN_TX_PHY_ANT01AUTO);
8071	}
8072	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8073	return (0);
8074}
8075
8076static void
8077bwn_wme_load(struct bwn_mac *mac)
8078{
8079	struct bwn_softc *sc = mac->mac_sc;
8080	int i;
8081
8082	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8083	    ("%s:%d: fail", __func__, __LINE__));
8084
8085	bwn_mac_suspend(mac);
8086	for (i = 0; i < N(sc->sc_wmeParams); i++)
8087		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8088		    bwn_wme_shm_offsets[i]);
8089	bwn_mac_enable(mac);
8090}
8091
8092static void
8093bwn_wme_loadparams(struct bwn_mac *mac,
8094    const struct wmeParams *p, uint16_t shm_offset)
8095{
8096#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8097	struct bwn_softc *sc = mac->mac_sc;
8098	uint16_t params[BWN_NR_WMEPARAMS];
8099	int slot, tmp;
8100	unsigned int i;
8101
8102	slot = BWN_READ_2(mac, BWN_RNG) &
8103	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8104
8105	memset(&params, 0, sizeof(params));
8106
8107	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8108	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8109	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8110
8111	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8112	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8113	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8114	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8115	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8116	params[BWN_WMEPARAM_BSLOTS] = slot;
8117	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8118
8119	for (i = 0; i < N(params); i++) {
8120		if (i == BWN_WMEPARAM_STATUS) {
8121			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8122			    shm_offset + (i * 2));
8123			tmp |= 0x100;
8124			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8125			    tmp);
8126		} else {
8127			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8128			    params[i]);
8129		}
8130	}
8131}
8132
8133static void
8134bwn_mac_write_bssid(struct bwn_mac *mac)
8135{
8136	struct bwn_softc *sc = mac->mac_sc;
8137	uint32_t tmp;
8138	int i;
8139	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8140
8141	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8142	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8143	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8144	    IEEE80211_ADDR_LEN);
8145
8146	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8147		tmp = (uint32_t) (mac_bssid[i + 0]);
8148		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8149		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8150		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8151		bwn_ram_write(mac, 0x20 + i, tmp);
8152	}
8153}
8154
8155static void
8156bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8157    const uint8_t *macaddr)
8158{
8159	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8160	uint16_t data;
8161
8162	if (!mac)
8163		macaddr = zero;
8164
8165	offset |= 0x0020;
8166	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8167
8168	data = macaddr[0];
8169	data |= macaddr[1] << 8;
8170	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8171	data = macaddr[2];
8172	data |= macaddr[3] << 8;
8173	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8174	data = macaddr[4];
8175	data |= macaddr[5] << 8;
8176	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8177}
8178
8179static void
8180bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8181    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8182{
8183	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8184	uint8_t per_sta_keys_start = 8;
8185
8186	if (BWN_SEC_NEWAPI(mac))
8187		per_sta_keys_start = 4;
8188
8189	KASSERT(index < mac->mac_max_nr_keys,
8190	    ("%s:%d: fail", __func__, __LINE__));
8191	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8192	    ("%s:%d: fail", __func__, __LINE__));
8193
8194	if (index >= per_sta_keys_start)
8195		bwn_key_macwrite(mac, index, NULL);
8196	if (key)
8197		memcpy(buf, key, key_len);
8198	bwn_key_write(mac, index, algorithm, buf);
8199	if (index >= per_sta_keys_start)
8200		bwn_key_macwrite(mac, index, mac_addr);
8201
8202	mac->mac_key[index].algorithm = algorithm;
8203}
8204
8205static void
8206bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8207{
8208	uint32_t addrtmp[2] = { 0, 0 };
8209	uint8_t start = 8;
8210
8211	if (BWN_SEC_NEWAPI(mac))
8212		start = 4;
8213
8214	KASSERT(index >= start,
8215	    ("%s:%d: fail", __func__, __LINE__));
8216	index -= start;
8217
8218	if (addr) {
8219		addrtmp[0] = addr[0];
8220		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8221		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8222		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8223		addrtmp[1] = addr[4];
8224		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8225	}
8226
8227	if (mac->mac_sd->sd_id.sd_rev >= 5) {
8228		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8229		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8230	} else {
8231		if (index >= 8) {
8232			bwn_shm_write_4(mac, BWN_SHARED,
8233			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8234			bwn_shm_write_2(mac, BWN_SHARED,
8235			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8236		}
8237	}
8238}
8239
8240static void
8241bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8242    const uint8_t *key)
8243{
8244	unsigned int i;
8245	uint32_t offset;
8246	uint16_t kidx, value;
8247
8248	kidx = BWN_SEC_KEY2FW(mac, index);
8249	bwn_shm_write_2(mac, BWN_SHARED,
8250	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8251
8252	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8253	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8254		value = key[i];
8255		value |= (uint16_t)(key[i + 1]) << 8;
8256		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8257	}
8258}
8259
8260static void
8261bwn_phy_exit(struct bwn_mac *mac)
8262{
8263
8264	mac->mac_phy.rf_onoff(mac, 0);
8265	if (mac->mac_phy.exit != NULL)
8266		mac->mac_phy.exit(mac);
8267}
8268
8269static void
8270bwn_dma_free(struct bwn_mac *mac)
8271{
8272	struct bwn_dma *dma;
8273
8274	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8275		return;
8276	dma = &mac->mac_method.dma;
8277
8278	bwn_dma_ringfree(&dma->rx);
8279	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8280	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8281	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8282	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8283	bwn_dma_ringfree(&dma->mcast);
8284}
8285
8286static void
8287bwn_core_stop(struct bwn_mac *mac)
8288{
8289	struct bwn_softc *sc = mac->mac_sc;
8290
8291	BWN_ASSERT_LOCKED(sc);
8292
8293	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8294		return;
8295
8296	callout_stop(&sc->sc_rfswitch_ch);
8297	callout_stop(&sc->sc_task_ch);
8298	callout_stop(&sc->sc_watchdog_ch);
8299	sc->sc_watchdog_timer = 0;
8300	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8301	BWN_READ_4(mac, BWN_INTR_MASK);
8302	bwn_mac_suspend(mac);
8303
8304	mac->mac_status = BWN_MAC_STATUS_INITED;
8305}
8306
8307static int
8308bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8309{
8310	struct bwn_mac *up_dev = NULL;
8311	struct bwn_mac *down_dev;
8312	struct bwn_mac *mac;
8313	int err, status;
8314	uint8_t gmode;
8315
8316	BWN_ASSERT_LOCKED(sc);
8317
8318	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8319		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8320		    mac->mac_phy.supports_2ghz) {
8321			up_dev = mac;
8322			gmode = 1;
8323		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8324		    mac->mac_phy.supports_5ghz) {
8325			up_dev = mac;
8326			gmode = 0;
8327		} else {
8328			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8329			return (EINVAL);
8330		}
8331		if (up_dev != NULL)
8332			break;
8333	}
8334	if (up_dev == NULL) {
8335		device_printf(sc->sc_dev, "Could not find a device\n");
8336		return (ENODEV);
8337	}
8338	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8339		return (0);
8340
8341	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8342	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8343
8344	down_dev = sc->sc_curmac;;
8345	status = down_dev->mac_status;
8346	if (status >= BWN_MAC_STATUS_STARTED)
8347		bwn_core_stop(down_dev);
8348	if (status >= BWN_MAC_STATUS_INITED)
8349		bwn_core_exit(down_dev);
8350
8351	if (down_dev != up_dev)
8352		bwn_phy_reset(down_dev);
8353
8354	up_dev->mac_phy.gmode = gmode;
8355	if (status >= BWN_MAC_STATUS_INITED) {
8356		err = bwn_core_init(up_dev);
8357		if (err) {
8358			device_printf(sc->sc_dev,
8359			    "fatal: failed to initialize for %s-GHz\n",
8360			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8361			goto fail;
8362		}
8363	}
8364	if (status >= BWN_MAC_STATUS_STARTED)
8365		bwn_core_start(up_dev);
8366	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8367	sc->sc_curmac = up_dev;
8368
8369	return (0);
8370fail:
8371	sc->sc_curmac = NULL;
8372	return (err);
8373}
8374
8375static void
8376bwn_rf_turnon(struct bwn_mac *mac)
8377{
8378
8379	bwn_mac_suspend(mac);
8380	mac->mac_phy.rf_onoff(mac, 1);
8381	mac->mac_phy.rf_on = 1;
8382	bwn_mac_enable(mac);
8383}
8384
8385static void
8386bwn_rf_turnoff(struct bwn_mac *mac)
8387{
8388
8389	bwn_mac_suspend(mac);
8390	mac->mac_phy.rf_onoff(mac, 0);
8391	mac->mac_phy.rf_on = 0;
8392	bwn_mac_enable(mac);
8393}
8394
8395static void
8396bwn_phy_reset(struct bwn_mac *mac)
8397{
8398	struct siba_dev_softc *sd = mac->mac_sd;
8399
8400	siba_write_4(sd, SIBA_TGSLOW,
8401	    ((siba_read_4(sd, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8402	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8403	DELAY(1000);
8404	siba_write_4(sd, SIBA_TGSLOW,
8405	    (siba_read_4(sd, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8406	    BWN_TGSLOW_PHYRESET);
8407	DELAY(1000);
8408}
8409
8410static int
8411bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8412{
8413	struct bwn_vap *bvp = BWN_VAP(vap);
8414	struct ieee80211com *ic= vap->iv_ic;
8415	struct ifnet *ifp = ic->ic_ifp;
8416	enum ieee80211_state ostate = vap->iv_state;
8417	struct bwn_softc *sc = ifp->if_softc;
8418	struct bwn_mac *mac = sc->sc_curmac;
8419	int error;
8420
8421	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8422	    ieee80211_state_name[vap->iv_state],
8423	    ieee80211_state_name[nstate]);
8424
8425	error = bvp->bv_newstate(vap, nstate, arg);
8426	if (error != 0)
8427		return (error);
8428
8429	BWN_LOCK(sc);
8430
8431	bwn_led_newstate(mac, nstate);
8432
8433	/*
8434	 * Clear the BSSID when we stop a STA
8435	 */
8436	if (vap->iv_opmode == IEEE80211_M_STA) {
8437		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8438			/*
8439			 * Clear out the BSSID.  If we reassociate to
8440			 * the same AP, this will reinialize things
8441			 * correctly...
8442			 */
8443			if (ic->ic_opmode == IEEE80211_M_STA &&
8444			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8445				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8446				bwn_set_macaddr(mac);
8447			}
8448		}
8449	}
8450
8451	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8452	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8453		/* XXX nothing to do? */
8454	} else if (nstate == IEEE80211_S_RUN) {
8455		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8456		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8457		bwn_set_opmode(mac);
8458		bwn_set_pretbtt(mac);
8459		bwn_spu_setdelay(mac, 0);
8460		bwn_set_macaddr(mac);
8461	}
8462
8463	BWN_UNLOCK(sc);
8464
8465	return (error);
8466}
8467
8468static void
8469bwn_set_pretbtt(struct bwn_mac *mac)
8470{
8471	struct bwn_softc *sc = mac->mac_sc;
8472	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8473	uint16_t pretbtt;
8474
8475	if (ic->ic_opmode == IEEE80211_M_IBSS)
8476		pretbtt = 2;
8477	else
8478		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8479	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8480	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8481}
8482
8483static int
8484bwn_intr(void *arg)
8485{
8486	struct bwn_mac *mac = arg;
8487	struct bwn_softc *sc = mac->mac_sc;
8488	struct siba_softc *siba = mac->mac_sd->sd_bus;
8489	uint32_t reason;
8490
8491	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid)
8492		return (FILTER_STRAY);
8493
8494	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8495	if (reason == 0xffffffff)	/* shared IRQ */
8496		return (FILTER_STRAY);
8497	reason &= mac->mac_intr_mask;
8498	if (reason == 0)
8499		return (FILTER_HANDLED);
8500
8501	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8502	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8503	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8504	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8505	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8506	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8507	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8508	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8509	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8510	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8511	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8512
8513	/* Disable interrupts. */
8514	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8515
8516	mac->mac_reason_intr = reason;
8517
8518	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8519	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8520
8521	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8522	return (FILTER_HANDLED);
8523}
8524
8525static void
8526bwn_intrtask(void *arg, int npending)
8527{
8528	struct bwn_mac *mac = arg;
8529	struct bwn_softc *sc = mac->mac_sc;
8530	struct ifnet *ifp = sc->sc_ifp;
8531	struct siba_softc *siba = mac->mac_sd->sd_bus;
8532	uint32_t merged = 0;
8533	int i, tx = 0, rx = 0;
8534
8535	BWN_LOCK(sc);
8536	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid) {
8537		BWN_UNLOCK(sc);
8538		return;
8539	}
8540
8541	for (i = 0; i < N(mac->mac_reason); i++)
8542		merged |= mac->mac_reason[i];
8543
8544	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8545		device_printf(sc->sc_dev, "MAC trans error\n");
8546
8547	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8548		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8549		mac->mac_phy.txerrors--;
8550		if (mac->mac_phy.txerrors == 0) {
8551			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8552			bwn_restart(mac, "PHY TX errors");
8553		}
8554	}
8555
8556	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8557		if (merged & BWN_DMAINTR_FATALMASK) {
8558			device_printf(sc->sc_dev,
8559			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8560			    mac->mac_reason[0], mac->mac_reason[1],
8561			    mac->mac_reason[2], mac->mac_reason[3],
8562			    mac->mac_reason[4], mac->mac_reason[5]);
8563			bwn_restart(mac, "DMA error");
8564			BWN_UNLOCK(sc);
8565			return;
8566		}
8567		if (merged & BWN_DMAINTR_NONFATALMASK) {
8568			device_printf(sc->sc_dev,
8569			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8570			    mac->mac_reason[0], mac->mac_reason[1],
8571			    mac->mac_reason[2], mac->mac_reason[3],
8572			    mac->mac_reason[4], mac->mac_reason[5]);
8573		}
8574	}
8575
8576	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8577		bwn_intr_ucode_debug(mac);
8578	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8579		bwn_intr_tbtt_indication(mac);
8580	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8581		bwn_intr_atim_end(mac);
8582	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8583		bwn_intr_beacon(mac);
8584	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8585		bwn_intr_pmq(mac);
8586	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8587		bwn_intr_noise(mac);
8588
8589	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8590		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8591			bwn_dma_rx(mac->mac_method.dma.rx);
8592			rx = 1;
8593		}
8594	} else
8595		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8596
8597	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8598	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8599	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8600	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8601	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8602
8603	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8604		bwn_intr_txeof(mac);
8605		tx = 1;
8606	}
8607
8608	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8609
8610	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8611		int evt = BWN_LED_EVENT_NONE;
8612
8613		if (tx && rx) {
8614			if (sc->sc_rx_rate > sc->sc_tx_rate)
8615				evt = BWN_LED_EVENT_RX;
8616			else
8617				evt = BWN_LED_EVENT_TX;
8618		} else if (tx) {
8619			evt = BWN_LED_EVENT_TX;
8620		} else if (rx) {
8621			evt = BWN_LED_EVENT_RX;
8622		} else if (rx == 0) {
8623			evt = BWN_LED_EVENT_POLL;
8624		}
8625
8626		if (evt != BWN_LED_EVENT_NONE)
8627			bwn_led_event(mac, evt);
8628       }
8629
8630	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8631		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8632			bwn_start_locked(ifp);
8633	}
8634
8635	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8636	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8637
8638	BWN_UNLOCK(sc);
8639}
8640
8641static void
8642bwn_restart(struct bwn_mac *mac, const char *msg)
8643{
8644	struct bwn_softc *sc = mac->mac_sc;
8645	struct ifnet *ifp = sc->sc_ifp;
8646	struct ieee80211com *ic = ifp->if_l2com;
8647
8648	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8649		return;
8650
8651	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8652	ieee80211_runtask(ic, &mac->mac_hwreset);
8653}
8654
8655static void
8656bwn_intr_ucode_debug(struct bwn_mac *mac)
8657{
8658	struct bwn_softc *sc = mac->mac_sc;
8659	uint16_t reason;
8660
8661	if (mac->mac_fw.opensource == 0)
8662		return;
8663
8664	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8665	switch (reason) {
8666	case BWN_DEBUGINTR_PANIC:
8667		bwn_handle_fwpanic(mac);
8668		break;
8669	case BWN_DEBUGINTR_DUMP_SHM:
8670		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8671		break;
8672	case BWN_DEBUGINTR_DUMP_REGS:
8673		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8674		break;
8675	case BWN_DEBUGINTR_MARKER:
8676		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8677		break;
8678	default:
8679		device_printf(sc->sc_dev,
8680		    "ucode debug unknown reason: %#x\n", reason);
8681	}
8682
8683	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8684	    BWN_DEBUGINTR_ACK);
8685}
8686
8687static void
8688bwn_intr_tbtt_indication(struct bwn_mac *mac)
8689{
8690	struct bwn_softc *sc = mac->mac_sc;
8691	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8692
8693	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8694		bwn_psctl(mac, 0);
8695	if (ic->ic_opmode == IEEE80211_M_IBSS)
8696		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8697}
8698
8699static void
8700bwn_intr_atim_end(struct bwn_mac *mac)
8701{
8702
8703	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8704		BWN_WRITE_4(mac, BWN_MACCMD,
8705		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8706		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8707	}
8708}
8709
8710static void
8711bwn_intr_beacon(struct bwn_mac *mac)
8712{
8713	struct bwn_softc *sc = mac->mac_sc;
8714	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8715	uint32_t cmd, beacon0, beacon1;
8716
8717	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8718	    ic->ic_opmode == IEEE80211_M_MBSS)
8719		return;
8720
8721	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8722
8723	cmd = BWN_READ_4(mac, BWN_MACCMD);
8724	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8725	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8726
8727	if (beacon0 && beacon1) {
8728		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8729		mac->mac_intr_mask |= BWN_INTR_BEACON;
8730		return;
8731	}
8732
8733	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8734		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8735		bwn_load_beacon0(mac);
8736		bwn_load_beacon1(mac);
8737		cmd = BWN_READ_4(mac, BWN_MACCMD);
8738		cmd |= BWN_MACCMD_BEACON0_VALID;
8739		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8740	} else {
8741		if (!beacon0) {
8742			bwn_load_beacon0(mac);
8743			cmd = BWN_READ_4(mac, BWN_MACCMD);
8744			cmd |= BWN_MACCMD_BEACON0_VALID;
8745			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8746		} else if (!beacon1) {
8747			bwn_load_beacon1(mac);
8748			cmd = BWN_READ_4(mac, BWN_MACCMD);
8749			cmd |= BWN_MACCMD_BEACON1_VALID;
8750			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8751		}
8752	}
8753}
8754
8755static void
8756bwn_intr_pmq(struct bwn_mac *mac)
8757{
8758	uint32_t tmp;
8759
8760	while (1) {
8761		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8762		if (!(tmp & 0x00000008))
8763			break;
8764	}
8765	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8766}
8767
8768static void
8769bwn_intr_noise(struct bwn_mac *mac)
8770{
8771	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8772	uint16_t tmp;
8773	uint8_t noise[4];
8774	uint8_t i, j;
8775	int32_t average;
8776
8777	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8778		return;
8779
8780	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8781	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8782	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8783	    noise[3] == 0x7f)
8784		goto new;
8785
8786	KASSERT(mac->mac_noise.noi_nsamples < 8,
8787	    ("%s:%d: fail", __func__, __LINE__));
8788	i = mac->mac_noise.noi_nsamples;
8789	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8790	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8791	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8792	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8793	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8794	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8795	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8796	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8797	mac->mac_noise.noi_nsamples++;
8798	if (mac->mac_noise.noi_nsamples == 8) {
8799		average = 0;
8800		for (i = 0; i < 8; i++) {
8801			for (j = 0; j < 4; j++)
8802				average += mac->mac_noise.noi_samples[i][j];
8803		}
8804		average = (((average / 32) * 125) + 64) / 128;
8805		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8806		if (tmp >= 8)
8807			average += 2;
8808		else
8809			average -= 25;
8810		average -= (tmp == 8) ? 72 : 48;
8811
8812		mac->mac_stats.link_noise = average;
8813		mac->mac_noise.noi_running = 0;
8814		return;
8815	}
8816new:
8817	bwn_noise_gensample(mac);
8818}
8819
8820static int
8821bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8822{
8823	struct bwn_mac *mac = prq->prq_mac;
8824	struct bwn_softc *sc = mac->mac_sc;
8825	unsigned int i;
8826
8827	BWN_ASSERT_LOCKED(sc);
8828
8829	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8830		return (0);
8831
8832	for (i = 0; i < 5000; i++) {
8833		if (bwn_pio_rxeof(prq) == 0)
8834			break;
8835	}
8836	if (i >= 5000)
8837		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8838	return ((i > 0) ? 1 : 0);
8839}
8840
8841static void
8842bwn_dma_rx(struct bwn_dma_ring *dr)
8843{
8844	int slot, curslot;
8845
8846	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8847	curslot = dr->get_curslot(dr);
8848	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8849	    ("%s:%d: fail", __func__, __LINE__));
8850
8851	slot = dr->dr_curslot;
8852	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8853		bwn_dma_rxeof(dr, &slot);
8854
8855	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8856	    BUS_DMASYNC_PREWRITE);
8857
8858	dr->set_curslot(dr, slot);
8859	dr->dr_curslot = slot;
8860}
8861
8862static void
8863bwn_intr_txeof(struct bwn_mac *mac)
8864{
8865	struct bwn_txstatus stat;
8866	uint32_t stat0, stat1;
8867	uint16_t tmp;
8868
8869	BWN_ASSERT_LOCKED(mac->mac_sc);
8870
8871	while (1) {
8872		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8873		if (!(stat0 & 0x00000001))
8874			break;
8875		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8876
8877		stat.cookie = (stat0 >> 16);
8878		stat.seq = (stat1 & 0x0000ffff);
8879		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8880		tmp = (stat0 & 0x0000ffff);
8881		stat.framecnt = ((tmp & 0xf000) >> 12);
8882		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8883		stat.sreason = ((tmp & 0x001c) >> 2);
8884		stat.pm = (tmp & 0x0080) ? 1 : 0;
8885		stat.im = (tmp & 0x0040) ? 1 : 0;
8886		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8887		stat.ack = (tmp & 0x0002) ? 1 : 0;
8888
8889		bwn_handle_txeof(mac, &stat);
8890	}
8891}
8892
8893static void
8894bwn_hwreset(void *arg, int npending)
8895{
8896	struct bwn_mac *mac = arg;
8897	struct bwn_softc *sc = mac->mac_sc;
8898	int error = 0;
8899	int prev_status;
8900
8901	BWN_LOCK(sc);
8902
8903	prev_status = mac->mac_status;
8904	if (prev_status >= BWN_MAC_STATUS_STARTED)
8905		bwn_core_stop(mac);
8906	if (prev_status >= BWN_MAC_STATUS_INITED)
8907		bwn_core_exit(mac);
8908
8909	if (prev_status >= BWN_MAC_STATUS_INITED) {
8910		error = bwn_core_init(mac);
8911		if (error)
8912			goto out;
8913	}
8914	if (prev_status >= BWN_MAC_STATUS_STARTED)
8915		bwn_core_start(mac);
8916out:
8917	if (error) {
8918		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8919		sc->sc_curmac = NULL;
8920	}
8921	BWN_UNLOCK(sc);
8922}
8923
8924static void
8925bwn_handle_fwpanic(struct bwn_mac *mac)
8926{
8927	struct bwn_softc *sc = mac->mac_sc;
8928	uint16_t reason;
8929
8930	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8931	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8932
8933	if (reason == BWN_FWPANIC_RESTART)
8934		bwn_restart(mac, "ucode panic");
8935}
8936
8937static void
8938bwn_load_beacon0(struct bwn_mac *mac)
8939{
8940
8941	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8942}
8943
8944static void
8945bwn_load_beacon1(struct bwn_mac *mac)
8946{
8947
8948	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8949}
8950
8951static uint32_t
8952bwn_jssi_read(struct bwn_mac *mac)
8953{
8954	uint32_t val = 0;
8955
8956	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8957	val <<= 16;
8958	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8959
8960	return (val);
8961}
8962
8963static void
8964bwn_noise_gensample(struct bwn_mac *mac)
8965{
8966	uint32_t jssi = 0x7f7f7f7f;
8967
8968	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8969	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8970	BWN_WRITE_4(mac, BWN_MACCMD,
8971	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8972}
8973
8974static int
8975bwn_dma_freeslot(struct bwn_dma_ring *dr)
8976{
8977	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8978
8979	return (dr->dr_numslots - dr->dr_usedslot);
8980}
8981
8982static int
8983bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8984{
8985	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8986
8987	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8988	    ("%s:%d: fail", __func__, __LINE__));
8989	if (slot == dr->dr_numslots - 1)
8990		return (0);
8991	return (slot + 1);
8992}
8993
8994static void
8995bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8996{
8997	struct bwn_mac *mac = dr->dr_mac;
8998	struct bwn_softc *sc = mac->mac_sc;
8999	struct bwn_dma *dma = &mac->mac_method.dma;
9000	struct bwn_dmadesc_generic *desc;
9001	struct bwn_dmadesc_meta *meta;
9002	struct bwn_rxhdr4 *rxhdr;
9003	struct ifnet *ifp = sc->sc_ifp;
9004	struct mbuf *m;
9005	uint32_t macstat;
9006	int32_t tmp;
9007	int cnt = 0;
9008	uint16_t len;
9009
9010	dr->getdesc(dr, *slot, &desc, &meta);
9011
9012	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
9013	m = meta->mt_m;
9014
9015	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
9016		ifp->if_ierrors++;
9017		return;
9018	}
9019
9020	rxhdr = mtod(m, struct bwn_rxhdr4 *);
9021	len = le16toh(rxhdr->frame_len);
9022	if (len <= 0) {
9023		ifp->if_ierrors++;
9024		return;
9025	}
9026	if (bwn_dma_check_redzone(dr, m)) {
9027		device_printf(sc->sc_dev, "redzone error.\n");
9028		bwn_dma_set_redzone(dr, m);
9029		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9030		    BUS_DMASYNC_PREWRITE);
9031		return;
9032	}
9033	if (len > dr->dr_rx_bufsize) {
9034		tmp = len;
9035		while (1) {
9036			dr->getdesc(dr, *slot, &desc, &meta);
9037			bwn_dma_set_redzone(dr, meta->mt_m);
9038			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9039			    BUS_DMASYNC_PREWRITE);
9040			*slot = bwn_dma_nextslot(dr, *slot);
9041			cnt++;
9042			tmp -= dr->dr_rx_bufsize;
9043			if (tmp <= 0)
9044				break;
9045		}
9046		device_printf(sc->sc_dev, "too small buffer "
9047		       "(len %u buffer %u dropped %d)\n",
9048		       len, dr->dr_rx_bufsize, cnt);
9049		return;
9050	}
9051	macstat = le32toh(rxhdr->mac_status);
9052	if (macstat & BWN_RX_MAC_FCSERR) {
9053		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9054			device_printf(sc->sc_dev, "RX drop\n");
9055			return;
9056		}
9057	}
9058
9059	m->m_pkthdr.rcvif = ifp;
9060	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9061	m_adj(m, dr->dr_frameoffset);
9062
9063	bwn_rxeof(dr->dr_mac, m, rxhdr);
9064}
9065
9066static void
9067bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9068{
9069	struct bwn_dma_ring *dr;
9070	struct bwn_dmadesc_generic *desc;
9071	struct bwn_dmadesc_meta *meta;
9072	struct bwn_node *bn;
9073	struct bwn_pio_txqueue *tq;
9074	struct bwn_pio_txpkt *tp = NULL;
9075	struct bwn_softc *sc = mac->mac_sc;
9076	struct bwn_stats *stats = &mac->mac_stats;
9077	struct ieee80211_node *ni;
9078	int slot;
9079
9080	BWN_ASSERT_LOCKED(mac->mac_sc);
9081
9082	if (status->im)
9083		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9084	if (status->ampdu)
9085		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9086	if (status->rtscnt) {
9087		if (status->rtscnt == 0xf)
9088			stats->rtsfail++;
9089		else
9090			stats->rts++;
9091	}
9092
9093	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9094		if (status->ack) {
9095			dr = bwn_dma_parse_cookie(mac, status,
9096			    status->cookie, &slot);
9097			if (dr == NULL) {
9098				device_printf(sc->sc_dev,
9099				    "failed to parse cookie\n");
9100				return;
9101			}
9102			while (1) {
9103				dr->getdesc(dr, slot, &desc, &meta);
9104				if (meta->mt_islast) {
9105					ni = meta->mt_ni;
9106					bn = (struct bwn_node *)ni;
9107					ieee80211_amrr_tx_complete(&bn->bn_amn,
9108					    status->ack, 0);
9109					break;
9110				}
9111				slot = bwn_dma_nextslot(dr, slot);
9112			}
9113		}
9114		bwn_dma_handle_txeof(mac, status);
9115	} else {
9116		if (status->ack) {
9117			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9118			if (tq == NULL) {
9119				device_printf(sc->sc_dev,
9120				    "failed to parse cookie\n");
9121				return;
9122			}
9123			ni = tp->tp_ni;
9124			bn = (struct bwn_node *)ni;
9125			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9126		}
9127		bwn_pio_handle_txeof(mac, status);
9128	}
9129
9130	bwn_phy_txpower_check(mac, 0);
9131}
9132
9133static uint8_t
9134bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9135{
9136	struct bwn_mac *mac = prq->prq_mac;
9137	struct bwn_softc *sc = mac->mac_sc;
9138	struct bwn_rxhdr4 rxhdr;
9139	struct ifnet *ifp = sc->sc_ifp;
9140	struct mbuf *m;
9141	uint32_t ctl32, macstat, v32;
9142	unsigned int i, padding;
9143	uint16_t ctl16, len, v16;
9144	unsigned char *mp;
9145	char *data;
9146
9147	memset(&rxhdr, 0, sizeof(rxhdr));
9148
9149	if (prq->prq_rev >= 8) {
9150		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9151		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9152			return (0);
9153		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9154		    BWN_PIO8_RXCTL_FRAMEREADY);
9155		for (i = 0; i < 10; i++) {
9156			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9157			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9158				goto ready;
9159			DELAY(10);
9160		}
9161	} else {
9162		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9163		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9164			return (0);
9165		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9166		    BWN_PIO_RXCTL_FRAMEREADY);
9167		for (i = 0; i < 10; i++) {
9168			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9169			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9170				goto ready;
9171			DELAY(10);
9172		}
9173	}
9174	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9175	return (1);
9176ready:
9177	if (prq->prq_rev >= 8)
9178		siba_read_multi_4(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9179		    prq->prq_base + BWN_PIO8_RXDATA);
9180	else
9181		siba_read_multi_2(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9182		    prq->prq_base + BWN_PIO_RXDATA);
9183	len = le16toh(rxhdr.frame_len);
9184	if (len > 0x700) {
9185		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9186		goto error;
9187	}
9188	if (len == 0) {
9189		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9190		goto error;
9191	}
9192
9193	macstat = le32toh(rxhdr.mac_status);
9194	if (macstat & BWN_RX_MAC_FCSERR) {
9195		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9196			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9197			goto error;
9198		}
9199	}
9200
9201	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9202	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9203	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9204	if (m == NULL) {
9205		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9206		goto error;
9207	}
9208	mp = mtod(m, unsigned char *);
9209	if (prq->prq_rev >= 8) {
9210		siba_read_multi_4(mac->mac_sd, mp + padding, (len & ~3),
9211		    prq->prq_base + BWN_PIO8_RXDATA);
9212		if (len & 3) {
9213			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9214			data = &(mp[len + padding - 1]);
9215			switch (len & 3) {
9216			case 3:
9217				*data = (v32 >> 16);
9218				data--;
9219			case 2:
9220				*data = (v32 >> 8);
9221				data--;
9222			case 1:
9223				*data = v32;
9224			}
9225		}
9226	} else {
9227		siba_read_multi_2(mac->mac_sd, mp + padding, (len & ~1),
9228		    prq->prq_base + BWN_PIO_RXDATA);
9229		if (len & 1) {
9230			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9231			mp[len + padding - 1] = v16;
9232		}
9233	}
9234
9235	m->m_pkthdr.rcvif = ifp;
9236	m->m_len = m->m_pkthdr.len = len + padding;
9237
9238	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9239
9240	return (1);
9241error:
9242	if (prq->prq_rev >= 8)
9243		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9244		    BWN_PIO8_RXCTL_DATAREADY);
9245	else
9246		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9247	return (1);
9248}
9249
9250static int
9251bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9252    struct bwn_dmadesc_meta *meta, int init)
9253{
9254	struct bwn_mac *mac = dr->dr_mac;
9255	struct bwn_dma *dma = &mac->mac_method.dma;
9256	struct bwn_rxhdr4 *hdr;
9257	bus_dmamap_t map;
9258	bus_addr_t paddr;
9259	struct mbuf *m;
9260	int error;
9261
9262	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9263	if (m == NULL) {
9264		error = ENOBUFS;
9265
9266		/*
9267		 * If the NIC is up and running, we need to:
9268		 * - Clear RX buffer's header.
9269		 * - Restore RX descriptor settings.
9270		 */
9271		if (init)
9272			return (error);
9273		else
9274			goto back;
9275	}
9276	m->m_len = m->m_pkthdr.len = MCLBYTES;
9277
9278	bwn_dma_set_redzone(dr, m);
9279
9280	/*
9281	 * Try to load RX buf into temporary DMA map
9282	 */
9283	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9284	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9285	if (error) {
9286		m_freem(m);
9287
9288		/*
9289		 * See the comment above
9290		 */
9291		if (init)
9292			return (error);
9293		else
9294			goto back;
9295	}
9296
9297	if (!init)
9298		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9299	meta->mt_m = m;
9300	meta->mt_paddr = paddr;
9301
9302	/*
9303	 * Swap RX buf's DMA map with the loaded temporary one
9304	 */
9305	map = meta->mt_dmap;
9306	meta->mt_dmap = dr->dr_spare_dmap;
9307	dr->dr_spare_dmap = map;
9308
9309back:
9310	/*
9311	 * Clear RX buf header
9312	 */
9313	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9314	bzero(hdr, sizeof(*hdr));
9315	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9316	    BUS_DMASYNC_PREWRITE);
9317
9318	/*
9319	 * Setup RX buf descriptor
9320	 */
9321	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9322	    sizeof(*hdr), 0, 0, 0);
9323	return (error);
9324}
9325
9326static void
9327bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9328		 bus_size_t mapsz __unused, int error)
9329{
9330
9331	if (!error) {
9332		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9333		*((bus_addr_t *)arg) = seg->ds_addr;
9334	}
9335}
9336
9337static int
9338bwn_hwrate2ieeerate(int rate)
9339{
9340
9341	switch (rate) {
9342	case BWN_CCK_RATE_1MB:
9343		return (2);
9344	case BWN_CCK_RATE_2MB:
9345		return (4);
9346	case BWN_CCK_RATE_5MB:
9347		return (11);
9348	case BWN_CCK_RATE_11MB:
9349		return (22);
9350	case BWN_OFDM_RATE_6MB:
9351		return (12);
9352	case BWN_OFDM_RATE_9MB:
9353		return (18);
9354	case BWN_OFDM_RATE_12MB:
9355		return (24);
9356	case BWN_OFDM_RATE_18MB:
9357		return (36);
9358	case BWN_OFDM_RATE_24MB:
9359		return (48);
9360	case BWN_OFDM_RATE_36MB:
9361		return (72);
9362	case BWN_OFDM_RATE_48MB:
9363		return (96);
9364	case BWN_OFDM_RATE_54MB:
9365		return (108);
9366	default:
9367		printf("Ooops\n");
9368		return (0);
9369	}
9370}
9371
9372static void
9373bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9374{
9375	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9376	struct bwn_plcp6 *plcp;
9377	struct bwn_softc *sc = mac->mac_sc;
9378	struct ieee80211_frame_min *wh;
9379	struct ieee80211_node *ni;
9380	struct ifnet *ifp = sc->sc_ifp;
9381	struct ieee80211com *ic = ifp->if_l2com;
9382	uint32_t macstat;
9383	int padding, rate, rssi = 0, noise = 0, type;
9384	uint16_t phytype, phystat0, phystat3, chanstat;
9385	unsigned char *mp = mtod(m, unsigned char *);
9386	static int rx_mac_dec_rpt = 0;
9387
9388	BWN_ASSERT_LOCKED(sc);
9389
9390	phystat0 = le16toh(rxhdr->phy_status0);
9391	phystat3 = le16toh(rxhdr->phy_status3);
9392	macstat = le32toh(rxhdr->mac_status);
9393	chanstat = le16toh(rxhdr->channel);
9394	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9395
9396	if (macstat & BWN_RX_MAC_FCSERR)
9397		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9398	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9399		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9400	if (macstat & BWN_RX_MAC_DECERR)
9401		goto drop;
9402
9403	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9404	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9405		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9406		    m->m_pkthdr.len);
9407		goto drop;
9408	}
9409	plcp = (struct bwn_plcp6 *)(mp + padding);
9410	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9411	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9412		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9413		    m->m_pkthdr.len);
9414		goto drop;
9415	}
9416	wh = mtod(m, struct ieee80211_frame_min *);
9417
9418	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9419		device_printf(sc->sc_dev,
9420		    "RX decryption attempted (old %d keyidx %#x)\n",
9421		    BWN_ISOLDFMT(mac),
9422		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9423
9424	/* XXX calculating RSSI & noise & antenna */
9425
9426	if (phystat0 & BWN_RX_PHYST0_OFDM)
9427		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9428		    phytype == BWN_PHYTYPE_A);
9429	else
9430		rate = bwn_plcp_get_cckrate(mac, plcp);
9431	if (rate == -1) {
9432		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9433			goto drop;
9434	}
9435	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9436
9437	/* RX radio tap */
9438	if (ieee80211_radiotap_active(ic))
9439		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9440	m_adj(m, -IEEE80211_CRC_LEN);
9441
9442	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9443	noise = mac->mac_stats.link_noise;
9444
9445	BWN_UNLOCK(sc);
9446
9447	ni = ieee80211_find_rxnode(ic, wh);
9448	if (ni != NULL) {
9449		type = ieee80211_input(ni, m, rssi, noise);
9450		ieee80211_free_node(ni);
9451	} else
9452		type = ieee80211_input_all(ic, m, rssi, noise);
9453
9454	BWN_LOCK(sc);
9455	return;
9456drop:
9457	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9458}
9459
9460static void
9461bwn_dma_handle_txeof(struct bwn_mac *mac,
9462    const struct bwn_txstatus *status)
9463{
9464	struct bwn_dma *dma = &mac->mac_method.dma;
9465	struct bwn_dma_ring *dr;
9466	struct bwn_dmadesc_generic *desc;
9467	struct bwn_dmadesc_meta *meta;
9468	struct bwn_softc *sc = mac->mac_sc;
9469	struct ieee80211_node *ni;
9470	struct ifnet *ifp = sc->sc_ifp;
9471	struct mbuf *m;
9472	int slot;
9473
9474	BWN_ASSERT_LOCKED(sc);
9475
9476	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9477	if (dr == NULL) {
9478		device_printf(sc->sc_dev, "failed to parse cookie\n");
9479		return;
9480	}
9481	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9482
9483	while (1) {
9484		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9485		    ("%s:%d: fail", __func__, __LINE__));
9486		dr->getdesc(dr, slot, &desc, &meta);
9487
9488		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9489			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9490		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9491			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9492
9493		if (meta->mt_islast) {
9494			KASSERT(meta->mt_m != NULL,
9495			    ("%s:%d: fail", __func__, __LINE__));
9496
9497			ni = meta->mt_ni;
9498			m = meta->mt_m;
9499			if (ni != NULL) {
9500				/*
9501				 * Do any tx complete callback. Note this must
9502				 * be done before releasing the node reference.
9503				 */
9504				if (m->m_flags & M_TXCB)
9505					ieee80211_process_callback(ni, m, 0);
9506				ieee80211_free_node(ni);
9507				meta->mt_ni = NULL;
9508			}
9509			m_freem(m);
9510			meta->mt_m = NULL;
9511		} else {
9512			KASSERT(meta->mt_m == NULL,
9513			    ("%s:%d: fail", __func__, __LINE__));
9514		}
9515
9516		dr->dr_usedslot--;
9517		if (meta->mt_islast) {
9518			ifp->if_opackets++;
9519			break;
9520		}
9521		slot = bwn_dma_nextslot(dr, slot);
9522	}
9523	sc->sc_watchdog_timer = 0;
9524	if (dr->dr_stop) {
9525		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9526		    ("%s:%d: fail", __func__, __LINE__));
9527		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9528		dr->dr_stop = 0;
9529	}
9530}
9531
9532static void
9533bwn_pio_handle_txeof(struct bwn_mac *mac,
9534    const struct bwn_txstatus *status)
9535{
9536	struct bwn_pio_txqueue *tq;
9537	struct bwn_pio_txpkt *tp = NULL;
9538	struct bwn_softc *sc = mac->mac_sc;
9539	struct ifnet *ifp = sc->sc_ifp;
9540
9541	BWN_ASSERT_LOCKED(sc);
9542
9543	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9544	if (tq == NULL)
9545		return;
9546
9547	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9548	tq->tq_free++;
9549
9550	if (tp->tp_ni != NULL) {
9551		/*
9552		 * Do any tx complete callback.  Note this must
9553		 * be done before releasing the node reference.
9554		 */
9555		if (tp->tp_m->m_flags & M_TXCB)
9556			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9557		ieee80211_free_node(tp->tp_ni);
9558		tp->tp_ni = NULL;
9559	}
9560	m_freem(tp->tp_m);
9561	tp->tp_m = NULL;
9562	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9563
9564	ifp->if_opackets++;
9565
9566	sc->sc_watchdog_timer = 0;
9567	if (tq->tq_stop) {
9568		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9569		tq->tq_stop = 0;
9570	}
9571}
9572
9573static void
9574bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9575{
9576	struct bwn_softc *sc = mac->mac_sc;
9577	struct bwn_phy *phy = &mac->mac_phy;
9578	struct ifnet *ifp = sc->sc_ifp;
9579	struct ieee80211com *ic = ifp->if_l2com;
9580	struct siba_softc *siba = mac->mac_sd->sd_bus;
9581	unsigned long now;
9582	int result;
9583
9584	BWN_GETTIME(now);
9585
9586	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9587		return;
9588	phy->nexttime = now + 2 * 1000;
9589
9590	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
9591	    siba->siba_board_type == SIBA_BOARD_BU4306)
9592		return;
9593
9594	if (phy->recalc_txpwr != NULL) {
9595		result = phy->recalc_txpwr(mac,
9596		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9597		if (result == BWN_TXPWR_RES_DONE)
9598			return;
9599		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9600		    ("%s: fail", __func__));
9601		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9602
9603		ieee80211_runtask(ic, &mac->mac_txpower);
9604	}
9605}
9606
9607static uint16_t
9608bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9609{
9610
9611	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9612}
9613
9614static uint32_t
9615bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9616{
9617
9618	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9619}
9620
9621static void
9622bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9623{
9624
9625	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9626}
9627
9628static void
9629bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9630{
9631
9632	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9633}
9634
9635static int
9636bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9637{
9638
9639	switch (rate) {
9640	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9641	case 12:
9642		return (BWN_OFDM_RATE_6MB);
9643	case 18:
9644		return (BWN_OFDM_RATE_9MB);
9645	case 24:
9646		return (BWN_OFDM_RATE_12MB);
9647	case 36:
9648		return (BWN_OFDM_RATE_18MB);
9649	case 48:
9650		return (BWN_OFDM_RATE_24MB);
9651	case 72:
9652		return (BWN_OFDM_RATE_36MB);
9653	case 96:
9654		return (BWN_OFDM_RATE_48MB);
9655	case 108:
9656		return (BWN_OFDM_RATE_54MB);
9657	/* CCK rates (NB: not IEEE std, device-specific) */
9658	case 2:
9659		return (BWN_CCK_RATE_1MB);
9660	case 4:
9661		return (BWN_CCK_RATE_2MB);
9662	case 11:
9663		return (BWN_CCK_RATE_5MB);
9664	case 22:
9665		return (BWN_CCK_RATE_11MB);
9666	}
9667
9668	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9669	return (BWN_CCK_RATE_1MB);
9670}
9671
9672static int
9673bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9674    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9675{
9676	const struct bwn_phy *phy = &mac->mac_phy;
9677	struct bwn_softc *sc = mac->mac_sc;
9678	struct ieee80211_frame *wh;
9679	struct ieee80211_frame *protwh;
9680	struct ieee80211_frame_cts *cts;
9681	struct ieee80211_frame_rts *rts;
9682	const struct ieee80211_txparam *tp;
9683	struct ieee80211vap *vap = ni->ni_vap;
9684	struct ifnet *ifp = sc->sc_ifp;
9685	struct ieee80211com *ic = ifp->if_l2com;
9686	struct mbuf *mprot;
9687	unsigned int len;
9688	uint32_t macctl = 0;
9689	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9690	uint16_t phyctl = 0;
9691	uint8_t rate, rate_fb;
9692
9693	wh = mtod(m, struct ieee80211_frame *);
9694	memset(txhdr, 0, sizeof(*txhdr));
9695
9696	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9697	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9698	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9699
9700	/*
9701	 * Find TX rate
9702	 */
9703	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9704	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9705		rate = rate_fb = tp->mgmtrate;
9706	else if (ismcast)
9707		rate = rate_fb = tp->mcastrate;
9708	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9709		rate = rate_fb = tp->ucastrate;
9710	else {
9711		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9712		rate = ni->ni_txrate;
9713
9714		if (rix > 0)
9715			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9716			    IEEE80211_RATE_VAL;
9717		else
9718			rate_fb = rate;
9719	}
9720
9721	sc->sc_tx_rate = rate;
9722
9723	rate = bwn_ieeerate2hwrate(sc, rate);
9724	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9725
9726	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9727	    bwn_plcp_getcck(rate);
9728	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9729	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9730
9731	if ((rate_fb == rate) ||
9732	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9733	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9734		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9735	else
9736		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9737		    m->m_pkthdr.len, rate, isshort);
9738
9739	/* XXX TX encryption */
9740	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9741	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9742	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9743	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9744	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9745	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9746
9747	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9748	    BWN_TX_EFT_FB_CCK;
9749	txhdr->chan = phy->chan;
9750	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9751	    BWN_TX_PHY_ENC_CCK;
9752	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9753	     rate == BWN_CCK_RATE_11MB))
9754		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9755
9756	/* XXX TX antenna selection */
9757
9758	switch (bwn_antenna_sanitize(mac, 0)) {
9759	case 0:
9760		phyctl |= BWN_TX_PHY_ANT01AUTO;
9761		break;
9762	case 1:
9763		phyctl |= BWN_TX_PHY_ANT0;
9764		break;
9765	case 2:
9766		phyctl |= BWN_TX_PHY_ANT1;
9767		break;
9768	case 3:
9769		phyctl |= BWN_TX_PHY_ANT2;
9770		break;
9771	case 4:
9772		phyctl |= BWN_TX_PHY_ANT3;
9773		break;
9774	default:
9775		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9776	}
9777
9778	if (!ismcast)
9779		macctl |= BWN_TX_MAC_ACK;
9780
9781	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9782	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9783	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9784		macctl |= BWN_TX_MAC_LONGFRAME;
9785
9786	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9787		/* XXX RTS rate is always 1MB??? */
9788		rts_rate = BWN_CCK_RATE_1MB;
9789		rts_rate_fb = bwn_get_fbrate(rts_rate);
9790
9791		protdur = ieee80211_compute_duration(ic->ic_rt,
9792		    m->m_pkthdr.len, rate, isshort) +
9793		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9794
9795		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9796			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9797			    (txhdr->body.old.rts_frame) :
9798			    (txhdr->body.new.rts_frame));
9799			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9800			    protdur);
9801			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9802			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9803			    mprot->m_pkthdr.len);
9804			m_freem(mprot);
9805			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9806			len = sizeof(struct ieee80211_frame_cts);
9807		} else {
9808			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9809			    (txhdr->body.old.rts_frame) :
9810			    (txhdr->body.new.rts_frame));
9811			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9812			    isshort);
9813			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9814			    wh->i_addr2, protdur);
9815			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9816			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9817			    mprot->m_pkthdr.len);
9818			m_freem(mprot);
9819			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9820			len = sizeof(struct ieee80211_frame_rts);
9821		}
9822		len += IEEE80211_CRC_LEN;
9823		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9824		    &txhdr->body.old.rts_plcp :
9825		    &txhdr->body.new.rts_plcp), len, rts_rate);
9826		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9827		    rts_rate_fb);
9828
9829		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9830		    (&txhdr->body.old.rts_frame) :
9831		    (&txhdr->body.new.rts_frame));
9832		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9833
9834		if (BWN_ISOFDMRATE(rts_rate)) {
9835			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9836			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9837		} else {
9838			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9839			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9840		}
9841		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9842		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9843	}
9844
9845	if (BWN_ISOLDFMT(mac))
9846		txhdr->body.old.cookie = htole16(cookie);
9847	else
9848		txhdr->body.new.cookie = htole16(cookie);
9849
9850	txhdr->macctl = htole32(macctl);
9851	txhdr->phyctl = htole16(phyctl);
9852
9853	/*
9854	 * TX radio tap
9855	 */
9856	if (ieee80211_radiotap_active_vap(vap)) {
9857		sc->sc_tx_th.wt_flags = 0;
9858		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9859			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9860		if (isshort &&
9861		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9862		     rate == BWN_CCK_RATE_11MB))
9863			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9864		sc->sc_tx_th.wt_rate = rate;
9865
9866		ieee80211_radiotap_tx(vap, m);
9867	}
9868
9869	return (0);
9870}
9871
9872static void
9873bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9874    const uint8_t rate)
9875{
9876	uint32_t d, plen;
9877	uint8_t *raw = plcp->o.raw;
9878
9879	if (BWN_ISOFDMRATE(rate)) {
9880		d = bwn_plcp_getofdm(rate);
9881		KASSERT(!(octets & 0xf000),
9882		    ("%s:%d: fail", __func__, __LINE__));
9883		d |= (octets << 5);
9884		plcp->o.data = htole32(d);
9885	} else {
9886		plen = octets * 16 / rate;
9887		if ((octets * 16 % rate) > 0) {
9888			plen++;
9889			if ((rate == BWN_CCK_RATE_11MB)
9890			    && ((octets * 8 % 11) < 4)) {
9891				raw[1] = 0x84;
9892			} else
9893				raw[1] = 0x04;
9894		} else
9895			raw[1] = 0x04;
9896		plcp->o.data |= htole32(plen << 16);
9897		raw[0] = bwn_plcp_getcck(rate);
9898	}
9899}
9900
9901static uint8_t
9902bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9903{
9904	uint8_t mask;
9905
9906	if (n == 0)
9907		return (0);
9908	if (mac->mac_phy.gmode)
9909		mask = mac->mac_sd->sd_bus->siba_sprom.ant_bg;
9910	else
9911		mask = mac->mac_sd->sd_bus->siba_sprom.ant_a;
9912	if (!(mask & (1 << (n - 1))))
9913		return (0);
9914	return (n);
9915}
9916
9917static uint8_t
9918bwn_get_fbrate(uint8_t bitrate)
9919{
9920	switch (bitrate) {
9921	case BWN_CCK_RATE_1MB:
9922		return (BWN_CCK_RATE_1MB);
9923	case BWN_CCK_RATE_2MB:
9924		return (BWN_CCK_RATE_1MB);
9925	case BWN_CCK_RATE_5MB:
9926		return (BWN_CCK_RATE_2MB);
9927	case BWN_CCK_RATE_11MB:
9928		return (BWN_CCK_RATE_5MB);
9929	case BWN_OFDM_RATE_6MB:
9930		return (BWN_CCK_RATE_5MB);
9931	case BWN_OFDM_RATE_9MB:
9932		return (BWN_OFDM_RATE_6MB);
9933	case BWN_OFDM_RATE_12MB:
9934		return (BWN_OFDM_RATE_9MB);
9935	case BWN_OFDM_RATE_18MB:
9936		return (BWN_OFDM_RATE_12MB);
9937	case BWN_OFDM_RATE_24MB:
9938		return (BWN_OFDM_RATE_18MB);
9939	case BWN_OFDM_RATE_36MB:
9940		return (BWN_OFDM_RATE_24MB);
9941	case BWN_OFDM_RATE_48MB:
9942		return (BWN_OFDM_RATE_36MB);
9943	case BWN_OFDM_RATE_54MB:
9944		return (BWN_OFDM_RATE_48MB);
9945	}
9946	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9947	return (0);
9948}
9949
9950static uint32_t
9951bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9952    uint32_t ctl, const void *_data, int len)
9953{
9954	uint32_t value = 0;
9955	const uint8_t *data = _data;
9956
9957	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9958	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9959	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9960
9961	siba_write_multi_4(mac->mac_sd, data, (len & ~3),
9962	    tq->tq_base + BWN_PIO8_TXDATA);
9963	if (len & 3) {
9964		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9965		    BWN_PIO8_TXCTL_24_31);
9966		data = &(data[len - 1]);
9967		switch (len & 3) {
9968		case 3:
9969			ctl |= BWN_PIO8_TXCTL_16_23;
9970			value |= (uint32_t)(*data) << 16;
9971			data--;
9972		case 2:
9973			ctl |= BWN_PIO8_TXCTL_8_15;
9974			value |= (uint32_t)(*data) << 8;
9975			data--;
9976		case 1:
9977			value |= (uint32_t)(*data);
9978		}
9979		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9980		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9981	}
9982
9983	return (ctl);
9984}
9985
9986static void
9987bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9988    uint16_t offset, uint32_t value)
9989{
9990
9991	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9992}
9993
9994static uint16_t
9995bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9996    uint16_t ctl, const void *_data, int len)
9997{
9998	const uint8_t *data = _data;
9999
10000	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10001	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10002
10003	siba_write_multi_2(mac->mac_sd, data, (len & ~1),
10004	    tq->tq_base + BWN_PIO_TXDATA);
10005	if (len & 1) {
10006		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10007		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10008		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
10009	}
10010
10011	return (ctl);
10012}
10013
10014static uint16_t
10015bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10016    uint16_t ctl, struct mbuf *m0)
10017{
10018	int i, j = 0;
10019	uint16_t data = 0;
10020	const uint8_t *buf;
10021	struct mbuf *m = m0;
10022
10023	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10024	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10025
10026	for (; m != NULL; m = m->m_next) {
10027		buf = mtod(m, const uint8_t *);
10028		for (i = 0; i < m->m_len; i++) {
10029			if (!((j++) % 2))
10030				data |= buf[i];
10031			else {
10032				data |= (buf[i] << 8);
10033				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10034				data = 0;
10035			}
10036		}
10037	}
10038	if (m0->m_pkthdr.len % 2) {
10039		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10040		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10041		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10042	}
10043
10044	return (ctl);
10045}
10046
10047static void
10048bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10049{
10050
10051	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10052		return;
10053	BWN_WRITE_2(mac, 0x684, 510 + time);
10054	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10055}
10056
10057static struct bwn_dma_ring *
10058bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10059{
10060
10061	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10062		return (mac->mac_method.dma.wme[WME_AC_BE]);
10063
10064	switch (prio) {
10065	case 3:
10066		return (mac->mac_method.dma.wme[WME_AC_VO]);
10067	case 2:
10068		return (mac->mac_method.dma.wme[WME_AC_VI]);
10069	case 0:
10070		return (mac->mac_method.dma.wme[WME_AC_BE]);
10071	case 1:
10072		return (mac->mac_method.dma.wme[WME_AC_BK]);
10073	}
10074	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10075	return (NULL);
10076}
10077
10078static int
10079bwn_dma_getslot(struct bwn_dma_ring *dr)
10080{
10081	int slot;
10082
10083	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10084
10085	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10086	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10087	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10088
10089	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10090	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10091	dr->dr_curslot = slot;
10092	dr->dr_usedslot++;
10093
10094	return (slot);
10095}
10096
10097static int
10098bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10099{
10100	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10101	unsigned int a, b, c, d;
10102	unsigned int avg;
10103	uint32_t tmp;
10104
10105	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10106	a = tmp & 0xff;
10107	b = (tmp >> 8) & 0xff;
10108	c = (tmp >> 16) & 0xff;
10109	d = (tmp >> 24) & 0xff;
10110	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10111	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10112		return (ENOENT);
10113	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10114	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10115	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10116
10117	if (ofdm) {
10118		a = (a + 32) & 0x3f;
10119		b = (b + 32) & 0x3f;
10120		c = (c + 32) & 0x3f;
10121		d = (d + 32) & 0x3f;
10122	}
10123
10124	avg = (a + b + c + d + 2) / 4;
10125	if (ofdm) {
10126		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10127		    & BWN_HF_4DB_CCK_POWERBOOST)
10128			avg = (avg >= 13) ? (avg - 13) : 0;
10129	}
10130	return (avg);
10131}
10132
10133static void
10134bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10135{
10136	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10137	int rfatt = *rfattp;
10138	int bbatt = *bbattp;
10139
10140	while (1) {
10141		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10142			break;
10143		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10144			break;
10145		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10146			break;
10147		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10148			break;
10149		if (bbatt > lo->bbatt.max) {
10150			bbatt -= 4;
10151			rfatt += 1;
10152			continue;
10153		}
10154		if (bbatt < lo->bbatt.min) {
10155			bbatt += 4;
10156			rfatt -= 1;
10157			continue;
10158		}
10159		if (rfatt > lo->rfatt.max) {
10160			rfatt -= 1;
10161			bbatt += 4;
10162			continue;
10163		}
10164		if (rfatt < lo->rfatt.min) {
10165			rfatt += 1;
10166			bbatt -= 4;
10167			continue;
10168		}
10169		break;
10170	}
10171
10172	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10173	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10174}
10175
10176static void
10177bwn_phy_lock(struct bwn_mac *mac)
10178{
10179	struct bwn_softc *sc = mac->mac_sc;
10180	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10181
10182	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10183	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10184
10185	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10186		bwn_psctl(mac, BWN_PS_AWAKE);
10187}
10188
10189static void
10190bwn_phy_unlock(struct bwn_mac *mac)
10191{
10192	struct bwn_softc *sc = mac->mac_sc;
10193	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10194
10195	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10196	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10197
10198	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10199		bwn_psctl(mac, 0);
10200}
10201
10202static void
10203bwn_rf_lock(struct bwn_mac *mac)
10204{
10205
10206	BWN_WRITE_4(mac, BWN_MACCTL,
10207	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10208	BWN_READ_4(mac, BWN_MACCTL);
10209	DELAY(10);
10210}
10211
10212static void
10213bwn_rf_unlock(struct bwn_mac *mac)
10214{
10215
10216	BWN_READ_2(mac, BWN_PHYVER);
10217	BWN_WRITE_4(mac, BWN_MACCTL,
10218	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10219}
10220
10221static struct bwn_pio_txqueue *
10222bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10223    struct bwn_pio_txpkt **pack)
10224{
10225	struct bwn_pio *pio = &mac->mac_method.pio;
10226	struct bwn_pio_txqueue *tq = NULL;
10227	unsigned int index;
10228
10229	switch (cookie & 0xf000) {
10230	case 0x1000:
10231		tq = &pio->wme[WME_AC_BK];
10232		break;
10233	case 0x2000:
10234		tq = &pio->wme[WME_AC_BE];
10235		break;
10236	case 0x3000:
10237		tq = &pio->wme[WME_AC_VI];
10238		break;
10239	case 0x4000:
10240		tq = &pio->wme[WME_AC_VO];
10241		break;
10242	case 0x5000:
10243		tq = &pio->mcast;
10244		break;
10245	}
10246	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10247	if (tq == NULL)
10248		return (NULL);
10249	index = (cookie & 0x0fff);
10250	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10251	if (index >= N(tq->tq_pkts))
10252		return (NULL);
10253	*pack = &tq->tq_pkts[index];
10254	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10255	return (tq);
10256}
10257
10258static void
10259bwn_txpwr(void *arg, int npending)
10260{
10261	struct bwn_mac *mac = arg;
10262	struct bwn_softc *sc = mac->mac_sc;
10263
10264	BWN_LOCK(sc);
10265	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10266	    mac->mac_phy.set_txpwr != NULL)
10267		mac->mac_phy.set_txpwr(mac);
10268	BWN_UNLOCK(sc);
10269}
10270
10271static void
10272bwn_task_15s(struct bwn_mac *mac)
10273{
10274	uint16_t reg;
10275
10276	if (mac->mac_fw.opensource) {
10277		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10278		if (reg) {
10279			bwn_restart(mac, "fw watchdog");
10280			return;
10281		}
10282		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10283	}
10284	if (mac->mac_phy.task_15s)
10285		mac->mac_phy.task_15s(mac);
10286
10287	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10288}
10289
10290static void
10291bwn_task_30s(struct bwn_mac *mac)
10292{
10293
10294	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10295		return;
10296	mac->mac_noise.noi_running = 1;
10297	mac->mac_noise.noi_nsamples = 0;
10298
10299	bwn_noise_gensample(mac);
10300}
10301
10302static void
10303bwn_task_60s(struct bwn_mac *mac)
10304{
10305
10306	if (mac->mac_phy.task_60s)
10307		mac->mac_phy.task_60s(mac);
10308	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10309}
10310
10311static void
10312bwn_tasks(void *arg)
10313{
10314	struct bwn_mac *mac = arg;
10315	struct bwn_softc *sc = mac->mac_sc;
10316
10317	BWN_ASSERT_LOCKED(sc);
10318	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10319		return;
10320
10321	if (mac->mac_task_state % 4 == 0)
10322		bwn_task_60s(mac);
10323	if (mac->mac_task_state % 2 == 0)
10324		bwn_task_30s(mac);
10325	bwn_task_15s(mac);
10326
10327	mac->mac_task_state++;
10328	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10329}
10330
10331static int
10332bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10333{
10334	struct bwn_softc *sc = mac->mac_sc;
10335
10336	KASSERT(a == 0, ("not support APHY\n"));
10337
10338	switch (plcp->o.raw[0] & 0xf) {
10339	case 0xb:
10340		return (BWN_OFDM_RATE_6MB);
10341	case 0xf:
10342		return (BWN_OFDM_RATE_9MB);
10343	case 0xa:
10344		return (BWN_OFDM_RATE_12MB);
10345	case 0xe:
10346		return (BWN_OFDM_RATE_18MB);
10347	case 0x9:
10348		return (BWN_OFDM_RATE_24MB);
10349	case 0xd:
10350		return (BWN_OFDM_RATE_36MB);
10351	case 0x8:
10352		return (BWN_OFDM_RATE_48MB);
10353	case 0xc:
10354		return (BWN_OFDM_RATE_54MB);
10355	}
10356	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10357	    plcp->o.raw[0] & 0xf);
10358	return (-1);
10359}
10360
10361static int
10362bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10363{
10364	struct bwn_softc *sc = mac->mac_sc;
10365
10366	switch (plcp->o.raw[0]) {
10367	case 0x0a:
10368		return (BWN_CCK_RATE_1MB);
10369	case 0x14:
10370		return (BWN_CCK_RATE_2MB);
10371	case 0x37:
10372		return (BWN_CCK_RATE_5MB);
10373	case 0x6e:
10374		return (BWN_CCK_RATE_11MB);
10375	}
10376	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10377	return (-1);
10378}
10379
10380static void
10381bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10382    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10383    int rssi, int noise)
10384{
10385	struct bwn_softc *sc = mac->mac_sc;
10386	const struct ieee80211_frame_min *wh;
10387	uint64_t tsf;
10388	uint16_t low_mactime_now;
10389
10390	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10391		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10392
10393	wh = mtod(m, const struct ieee80211_frame_min *);
10394	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10395		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10396
10397	bwn_tsf_read(mac, &tsf);
10398	low_mactime_now = tsf;
10399	tsf = tsf & ~0xffffULL;
10400	tsf += le16toh(rxhdr->mac_time);
10401	if (low_mactime_now < le16toh(rxhdr->mac_time))
10402		tsf -= 0x10000;
10403
10404	sc->sc_rx_th.wr_tsf = tsf;
10405	sc->sc_rx_th.wr_rate = rate;
10406	sc->sc_rx_th.wr_antsignal = rssi;
10407	sc->sc_rx_th.wr_antnoise = noise;
10408}
10409
10410static void
10411bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10412{
10413	uint32_t low, high;
10414
10415	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10416	    ("%s:%d: fail", __func__, __LINE__));
10417
10418	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10419	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10420	*tsf = high;
10421	*tsf <<= 32;
10422	*tsf |= low;
10423}
10424
10425static int
10426bwn_dma_attach(struct bwn_mac *mac)
10427{
10428	struct bwn_dma *dma = &mac->mac_method.dma;
10429	struct bwn_softc *sc = mac->mac_sc;
10430	struct siba_dev_softc *sd = mac->mac_sd;
10431	struct siba_softc *siba = sd->sd_bus;
10432	bus_addr_t lowaddr = 0;
10433	int error;
10434
10435	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10436		return (0);
10437
10438	KASSERT(mac->mac_sd->sd_id.sd_rev >= 5, ("%s: fail", __func__));
10439
10440	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10441
10442	dma->dmatype = bwn_dma_gettype(mac);
10443	if (dma->dmatype == BWN_DMA_30BIT)
10444		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10445	else if (dma->dmatype == BWN_DMA_32BIT)
10446		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10447	else
10448		lowaddr = BUS_SPACE_MAXADDR;
10449
10450	/*
10451	 * Create top level DMA tag
10452	 */
10453	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10454			       BWN_ALIGN, 0,		/* alignment, bounds */
10455			       lowaddr,			/* lowaddr */
10456			       BUS_SPACE_MAXADDR,	/* highaddr */
10457			       NULL, NULL,		/* filter, filterarg */
10458			       MAXBSIZE,		/* maxsize */
10459			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10460			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10461			       0,			/* flags */
10462			       NULL, NULL,		/* lockfunc, lockarg */
10463			       &dma->parent_dtag);
10464	if (error) {
10465		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10466		return (error);
10467	}
10468
10469	/*
10470	 * Create TX/RX mbuf DMA tag
10471	 */
10472	error = bus_dma_tag_create(dma->parent_dtag,
10473				1,
10474				0,
10475				BUS_SPACE_MAXADDR,
10476				BUS_SPACE_MAXADDR,
10477				NULL, NULL,
10478				MCLBYTES,
10479				1,
10480				BUS_SPACE_MAXSIZE_32BIT,
10481				0,
10482				NULL, NULL,
10483				&dma->rxbuf_dtag);
10484	if (error) {
10485		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10486		goto fail0;
10487	}
10488	error = bus_dma_tag_create(dma->parent_dtag,
10489				1,
10490				0,
10491				BUS_SPACE_MAXADDR,
10492				BUS_SPACE_MAXADDR,
10493				NULL, NULL,
10494				MCLBYTES,
10495				1,
10496				BUS_SPACE_MAXSIZE_32BIT,
10497				0,
10498				NULL, NULL,
10499				&dma->txbuf_dtag);
10500	if (error) {
10501		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10502		goto fail1;
10503	}
10504
10505	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10506	if (!dma->wme[WME_AC_BK])
10507		goto fail2;
10508
10509	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10510	if (!dma->wme[WME_AC_BE])
10511		goto fail3;
10512
10513	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10514	if (!dma->wme[WME_AC_VI])
10515		goto fail4;
10516
10517	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10518	if (!dma->wme[WME_AC_VO])
10519		goto fail5;
10520
10521	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10522	if (!dma->mcast)
10523		goto fail6;
10524	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10525	if (!dma->rx)
10526		goto fail7;
10527
10528	return (error);
10529
10530fail7:	bwn_dma_ringfree(&dma->mcast);
10531fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10532fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10533fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10534fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10535fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10536fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10537fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10538	return (error);
10539}
10540
10541static struct bwn_dma_ring *
10542bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10543    uint16_t cookie, int *slot)
10544{
10545	struct bwn_dma *dma = &mac->mac_method.dma;
10546	struct bwn_dma_ring *dr;
10547	struct bwn_softc *sc = mac->mac_sc;
10548
10549	BWN_ASSERT_LOCKED(mac->mac_sc);
10550
10551	switch (cookie & 0xf000) {
10552	case 0x1000:
10553		dr = dma->wme[WME_AC_BK];
10554		break;
10555	case 0x2000:
10556		dr = dma->wme[WME_AC_BE];
10557		break;
10558	case 0x3000:
10559		dr = dma->wme[WME_AC_VI];
10560		break;
10561	case 0x4000:
10562		dr = dma->wme[WME_AC_VO];
10563		break;
10564	case 0x5000:
10565		dr = dma->mcast;
10566		break;
10567	default:
10568		dr = NULL;
10569		KASSERT(0 == 1,
10570		    ("invalid cookie value %d", cookie & 0xf000));
10571	}
10572	*slot = (cookie & 0x0fff);
10573	if (*slot < 0 || *slot >= dr->dr_numslots) {
10574		/*
10575		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10576		 * that it occurs events which have same H/W sequence numbers.
10577		 * When it's occurred just prints a WARNING msgs and ignores.
10578		 */
10579		KASSERT(status->seq == dma->lastseq,
10580		    ("%s:%d: fail", __func__, __LINE__));
10581		device_printf(sc->sc_dev,
10582		    "out of slot ranges (0 < %d < %d)\n", *slot,
10583		    dr->dr_numslots);
10584		return (NULL);
10585	}
10586	dma->lastseq = status->seq;
10587	return (dr);
10588}
10589
10590static void
10591bwn_dma_stop(struct bwn_mac *mac)
10592{
10593	struct bwn_dma *dma;
10594
10595	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10596		return;
10597	dma = &mac->mac_method.dma;
10598
10599	bwn_dma_ringstop(&dma->rx);
10600	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10601	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10602	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10603	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10604	bwn_dma_ringstop(&dma->mcast);
10605}
10606
10607static void
10608bwn_dma_ringstop(struct bwn_dma_ring **dr)
10609{
10610
10611	if (dr == NULL)
10612		return;
10613
10614	bwn_dma_cleanup(*dr);
10615}
10616
10617static void
10618bwn_pio_stop(struct bwn_mac *mac)
10619{
10620	struct bwn_pio *pio;
10621
10622	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10623		return;
10624	pio = &mac->mac_method.pio;
10625
10626	bwn_destroy_queue_tx(&pio->mcast);
10627	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10628	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10629	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10630	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10631}
10632
10633static void
10634bwn_led_attach(struct bwn_mac *mac)
10635{
10636	struct bwn_softc *sc = mac->mac_sc;
10637	struct siba_softc *siba = mac->mac_sd->sd_bus;
10638	const uint8_t *led_act = NULL;
10639	uint16_t val[BWN_LED_MAX];
10640	int i;
10641
10642	sc->sc_led_idle = (2350 * hz) / 1000;
10643	sc->sc_led_blink = 1;
10644
10645	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10646		if (siba->siba_pci_subvid == bwn_vendor_led_act[i].vid) {
10647			led_act = bwn_vendor_led_act[i].led_act;
10648			break;
10649		}
10650	}
10651	if (led_act == NULL)
10652		led_act = bwn_default_led_act;
10653
10654	val[0] = siba->siba_sprom.gpio0;
10655	val[1] = siba->siba_sprom.gpio1;
10656	val[2] = siba->siba_sprom.gpio2;
10657	val[3] = siba->siba_sprom.gpio3;
10658
10659	for (i = 0; i < BWN_LED_MAX; ++i) {
10660		struct bwn_led *led = &sc->sc_leds[i];
10661
10662		if (val[i] == 0xff) {
10663			led->led_act = led_act[i];
10664		} else {
10665			if (val[i] & BWN_LED_ACT_LOW)
10666				led->led_flags |= BWN_LED_F_ACTLOW;
10667			led->led_act = val[i] & BWN_LED_ACT_MASK;
10668		}
10669		led->led_mask = (1 << i);
10670
10671		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10672		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10673		    led->led_act == BWN_LED_ACT_BLINK) {
10674			led->led_flags |= BWN_LED_F_BLINK;
10675			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10676				led->led_flags |= BWN_LED_F_POLLABLE;
10677			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10678				led->led_flags |= BWN_LED_F_SLOW;
10679
10680			if (sc->sc_blink_led == NULL) {
10681				sc->sc_blink_led = led;
10682				if (led->led_flags & BWN_LED_F_SLOW)
10683					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10684			}
10685		}
10686
10687		DPRINTF(sc, BWN_DEBUG_LED,
10688		    "%dth led, act %d, lowact %d\n", i,
10689		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10690	}
10691	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10692}
10693
10694static __inline uint16_t
10695bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10696{
10697
10698	if (led->led_flags & BWN_LED_F_ACTLOW)
10699		on = !on;
10700	if (on)
10701		val |= led->led_mask;
10702	else
10703		val &= ~led->led_mask;
10704	return val;
10705}
10706
10707static void
10708bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10709{
10710	struct bwn_softc *sc = mac->mac_sc;
10711	struct ifnet *ifp = sc->sc_ifp;
10712	struct ieee80211com *ic = ifp->if_l2com;
10713	uint16_t val;
10714	int i;
10715
10716	if (nstate == IEEE80211_S_INIT) {
10717		callout_stop(&sc->sc_led_blink_ch);
10718		sc->sc_led_blinking = 0;
10719	}
10720
10721	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10722		return;
10723
10724	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10725	for (i = 0; i < BWN_LED_MAX; ++i) {
10726		struct bwn_led *led = &sc->sc_leds[i];
10727		int on;
10728
10729		if (led->led_act == BWN_LED_ACT_UNKN ||
10730		    led->led_act == BWN_LED_ACT_NULL)
10731			continue;
10732
10733		if ((led->led_flags & BWN_LED_F_BLINK) &&
10734		    nstate != IEEE80211_S_INIT)
10735			continue;
10736
10737		switch (led->led_act) {
10738		case BWN_LED_ACT_ON:    /* Always on */
10739			on = 1;
10740			break;
10741		case BWN_LED_ACT_OFF:   /* Always off */
10742		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10743			on = 0;
10744			break;
10745		default:
10746			on = 1;
10747			switch (nstate) {
10748			case IEEE80211_S_INIT:
10749				on = 0;
10750				break;
10751			case IEEE80211_S_RUN:
10752				if (led->led_act == BWN_LED_ACT_11G &&
10753				    ic->ic_curmode != IEEE80211_MODE_11G)
10754					on = 0;
10755				break;
10756			default:
10757				if (led->led_act == BWN_LED_ACT_ASSOC)
10758					on = 0;
10759				break;
10760			}
10761			break;
10762		}
10763
10764		val = bwn_led_onoff(led, val, on);
10765	}
10766	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10767}
10768
10769static void
10770bwn_led_event(struct bwn_mac *mac, int event)
10771{
10772	struct bwn_softc *sc = mac->mac_sc;
10773        struct bwn_led *led = sc->sc_blink_led;
10774        int rate;
10775
10776        if (event == BWN_LED_EVENT_POLL) {
10777                if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10778                        return;
10779                if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10780                        return;
10781        }
10782
10783        sc->sc_led_ticks = ticks;
10784        if (sc->sc_led_blinking)
10785                return;
10786
10787        switch (event) {
10788        case BWN_LED_EVENT_RX:
10789                rate = sc->sc_rx_rate;
10790                break;
10791        case BWN_LED_EVENT_TX:
10792                rate = sc->sc_tx_rate;
10793                break;
10794        case BWN_LED_EVENT_POLL:
10795                rate = 0;
10796                break;
10797        default:
10798                panic("unknown LED event %d\n", event);
10799                break;
10800        }
10801        bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10802            bwn_led_duration[rate].off_dur);
10803}
10804
10805static void
10806bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10807{
10808	struct bwn_softc *sc = mac->mac_sc;
10809        struct bwn_led *led = sc->sc_blink_led;
10810        uint16_t val;
10811
10812        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10813        val = bwn_led_onoff(led, val, 1);
10814        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10815
10816        if (led->led_flags & BWN_LED_F_SLOW) {
10817                BWN_LED_SLOWDOWN(on_dur);
10818                BWN_LED_SLOWDOWN(off_dur);
10819        }
10820
10821        sc->sc_led_blinking = 1;
10822        sc->sc_led_blink_offdur = off_dur;
10823
10824        callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10825}
10826
10827static void
10828bwn_led_blink_next(void *arg)
10829{
10830	struct bwn_mac *mac = arg;
10831        struct bwn_softc *sc = mac->mac_sc;
10832        uint16_t val;
10833
10834        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10835        val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10836        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10837
10838        callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10839            bwn_led_blink_end, mac);
10840}
10841
10842static void
10843bwn_led_blink_end(void *arg)
10844{
10845	struct bwn_mac *mac = arg;
10846        struct bwn_softc *sc = mac->mac_sc;
10847
10848        sc->sc_led_blinking = 0;
10849}
10850
10851static int
10852bwn_suspend(device_t dev)
10853{
10854	struct bwn_softc *sc = device_get_softc(dev);
10855
10856	bwn_stop(sc, 1);
10857	return (0);
10858}
10859
10860static int
10861bwn_resume(device_t dev)
10862{
10863	struct bwn_softc *sc = device_get_softc(dev);
10864	struct ifnet *ifp = sc->sc_ifp;
10865
10866	if (ifp->if_flags & IFF_UP)
10867		bwn_init(sc);
10868	return (0);
10869}
10870
10871static void
10872bwn_rfswitch(void *arg)
10873{
10874	struct bwn_softc *sc = arg;
10875	struct bwn_mac *mac = sc->sc_curmac;
10876	int cur = 0, prev = 0;
10877
10878	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10879	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10880
10881	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10882		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10883			& BWN_RF_HWENABLED_HI_MASK))
10884			cur = 1;
10885	} else {
10886		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10887		    & BWN_RF_HWENABLED_LO_MASK)
10888			cur = 1;
10889	}
10890
10891	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10892		prev = 1;
10893
10894	if (cur != prev) {
10895		if (cur)
10896			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10897		else
10898			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10899
10900		device_printf(sc->sc_dev,
10901		    "status of RF switch is changed to %s\n",
10902		    cur ? "ON" : "OFF");
10903		if (cur != mac->mac_phy.rf_on) {
10904			if (cur)
10905				bwn_rf_turnon(mac);
10906			else
10907				bwn_rf_turnoff(mac);
10908		}
10909	}
10910
10911	callout_schedule(&sc->sc_rfswitch_ch, hz);
10912}
10913
10914static void
10915bwn_phy_lp_init_pre(struct bwn_mac *mac)
10916{
10917	struct bwn_phy *phy = &mac->mac_phy;
10918	struct bwn_phy_lp *plp = &phy->phy_lp;
10919
10920	plp->plp_antenna = BWN_ANT_DEFAULT;
10921}
10922
10923static int
10924bwn_phy_lp_init(struct bwn_mac *mac)
10925{
10926	static const struct bwn_stxtable tables[] = {
10927		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10928		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10929		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10930		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10931		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10932		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10933		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10934		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10935		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10936		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10937		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10938		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10939		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10940		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10941		{ 2, 11, 0x40, 0, 0x0f }
10942	};
10943	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10944	struct bwn_softc *sc = mac->mac_sc;
10945	const struct bwn_stxtable *st;
10946	struct ifnet *ifp = sc->sc_ifp;
10947	struct ieee80211com *ic = ifp->if_l2com;
10948	int i, error;
10949	uint16_t tmp;
10950
10951	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10952	bwn_phy_lp_bbinit(mac);
10953
10954	/* initialize RF */
10955	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10956	DELAY(1);
10957	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10958	DELAY(1);
10959
10960	if (mac->mac_phy.rf_ver == 0x2062)
10961		bwn_phy_lp_b2062_init(mac);
10962	else {
10963		bwn_phy_lp_b2063_init(mac);
10964
10965		/* synchronize stx table. */
10966		for (i = 0; i < N(tables); i++) {
10967			st = &tables[i];
10968			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10969			tmp >>= st->st_rfshift;
10970			tmp <<= st->st_physhift;
10971			BWN_PHY_SETMASK(mac,
10972			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10973			    ~(st->st_mask << st->st_physhift), tmp);
10974		}
10975
10976		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10977		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10978	}
10979
10980	/* calibrate RC */
10981	if (mac->mac_phy.rev >= 2)
10982		bwn_phy_lp_rxcal_r2(mac);
10983	else if (!plp->plp_rccap) {
10984		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10985			bwn_phy_lp_rccal_r12(mac);
10986	} else
10987		bwn_phy_lp_set_rccap(mac);
10988
10989	error = bwn_phy_lp_switch_channel(mac, 7);
10990	if (error)
10991		device_printf(sc->sc_dev,
10992		    "failed to change channel 7 (%d)\n", error);
10993	bwn_phy_lp_txpctl_init(mac);
10994	bwn_phy_lp_calib(mac);
10995	return (0);
10996}
10997
10998static uint16_t
10999bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
11000{
11001
11002	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11003	return (BWN_READ_2(mac, BWN_PHYDATA));
11004}
11005
11006static void
11007bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11008{
11009
11010	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11011	BWN_WRITE_2(mac, BWN_PHYDATA, value);
11012}
11013
11014static void
11015bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
11016    uint16_t set)
11017{
11018
11019	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11020	BWN_WRITE_2(mac, BWN_PHYDATA,
11021	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
11022}
11023
11024static uint16_t
11025bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
11026{
11027
11028	KASSERT(reg != 1, ("unaccessible register %d", reg));
11029	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11030		reg |= 0x100;
11031	if (mac->mac_phy.rev >= 2)
11032		reg |= 0x200;
11033	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11034	return BWN_READ_2(mac, BWN_RFDATALO);
11035}
11036
11037static void
11038bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11039{
11040
11041	KASSERT(reg != 1, ("unaccessible register %d", reg));
11042	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11043	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11044}
11045
11046static void
11047bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11048{
11049
11050	if (on) {
11051		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11052		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11053		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11054		return;
11055	}
11056
11057	if (mac->mac_phy.rev >= 2) {
11058		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11059		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11060		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11061		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11062		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11063		return;
11064	}
11065
11066	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11067	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11068	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11069	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11070}
11071
11072static int
11073bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11074{
11075	struct bwn_phy *phy = &mac->mac_phy;
11076	struct bwn_phy_lp *plp = &phy->phy_lp;
11077	int error;
11078
11079	if (phy->rf_ver == 0x2063) {
11080		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11081		if (error)
11082			return (error);
11083	} else {
11084		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11085		if (error)
11086			return (error);
11087		bwn_phy_lp_set_anafilter(mac, chan);
11088		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11089	}
11090
11091	plp->plp_chan = chan;
11092	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11093	return (0);
11094}
11095
11096static uint32_t
11097bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11098{
11099	struct bwn_softc *sc = mac->mac_sc;
11100	struct ifnet *ifp = sc->sc_ifp;
11101	struct ieee80211com *ic = ifp->if_l2com;
11102
11103	device_printf(sc->sc_dev, "correct?\n");
11104
11105	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11106}
11107
11108static void
11109bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11110{
11111	struct bwn_phy *phy = &mac->mac_phy;
11112	struct bwn_phy_lp *plp = &phy->phy_lp;
11113
11114	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11115		return;
11116
11117	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11118	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11119	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11120	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11121	plp->plp_antenna = antenna;
11122}
11123
11124static void
11125bwn_phy_lp_task_60s(struct bwn_mac *mac)
11126{
11127
11128	bwn_phy_lp_calib(mac);
11129}
11130
11131static void
11132bwn_phy_lp_readsprom(struct bwn_mac *mac)
11133{
11134	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11135	struct bwn_softc *sc = mac->mac_sc;
11136	struct ifnet *ifp = sc->sc_ifp;
11137	struct ieee80211com *ic = ifp->if_l2com;
11138	struct siba_dev_softc *sd = mac->mac_sd;
11139	struct siba_softc *siba = sd->sd_bus;
11140	struct siba_sprom *sprom = &siba->siba_sprom;
11141
11142	device_printf(sc->sc_dev, "XXX using %dghz\n",
11143	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 2 : 5);
11144
11145	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11146		plp->plp_txisoband_m = sprom->tri2g;
11147		plp->plp_bxarch = sprom->bxa2g;
11148		plp->plp_rxpwroffset = sprom->rxpo2g;
11149		plp->plp_rssivf = sprom->rssismf2g;
11150		plp->plp_rssivc = sprom->rssismc2g;
11151		plp->plp_rssigs = sprom->rssisav2g;
11152		return;
11153	}
11154
11155	plp->plp_txisoband_l = sprom->tri5gl;
11156	plp->plp_txisoband_m = sprom->tri5g;
11157	plp->plp_txisoband_h = sprom->tri5gh;
11158	plp->plp_bxarch = sprom->bxa5g;
11159	plp->plp_rxpwroffset = sprom->rxpo5g;
11160	plp->plp_rssivf = sprom->rssismf5g;
11161	plp->plp_rssivc = sprom->rssismc5g;
11162	plp->plp_rssigs = sprom->rssisav5g;
11163}
11164
11165static void
11166bwn_phy_lp_bbinit(struct bwn_mac *mac)
11167{
11168
11169	bwn_phy_lp_tblinit(mac);
11170	if (mac->mac_phy.rev >= 2)
11171		bwn_phy_lp_bbinit_r2(mac);
11172	else
11173		bwn_phy_lp_bbinit_r01(mac);
11174}
11175
11176static void
11177bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11178{
11179	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11180	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11181	struct bwn_softc *sc = mac->mac_sc;
11182	struct ifnet *ifp = sc->sc_ifp;
11183	struct ieee80211com *ic = ifp->if_l2com;
11184
11185	bwn_phy_lp_set_txgain(mac,
11186	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11187	bwn_phy_lp_set_bbmult(mac, 150);
11188}
11189
11190static void
11191bwn_phy_lp_calib(struct bwn_mac *mac)
11192{
11193	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11194	struct siba_dev_softc *sd = mac->mac_sd;
11195	struct siba_softc *siba = sd->sd_bus;
11196	struct bwn_softc *sc = mac->mac_sc;
11197	struct ifnet *ifp = sc->sc_ifp;
11198	struct ieee80211com *ic = ifp->if_l2com;
11199	const struct bwn_rxcompco *rc = NULL;
11200	struct bwn_txgain ogain;
11201	int i, omode, oafeovr, orf, obbmult;
11202	uint8_t mode, fc = 0;
11203
11204	if (plp->plp_chanfullcal != plp->plp_chan) {
11205		plp->plp_chanfullcal = plp->plp_chan;
11206		fc = 1;
11207	}
11208
11209	bwn_mac_suspend(mac);
11210
11211	/* BlueTooth Coexistance Override */
11212	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11213	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11214
11215	if (mac->mac_phy.rev >= 2)
11216		bwn_phy_lp_digflt_save(mac);
11217	bwn_phy_lp_get_txpctlmode(mac);
11218	mode = plp->plp_txpctlmode;
11219	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11220	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11221		bwn_phy_lp_bugfix(mac);
11222	if (mac->mac_phy.rev >= 2 && fc == 1) {
11223		bwn_phy_lp_get_txpctlmode(mac);
11224		omode = plp->plp_txpctlmode;
11225		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11226		if (oafeovr)
11227			ogain = bwn_phy_lp_get_txgain(mac);
11228		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11229		obbmult = bwn_phy_lp_get_bbmult(mac);
11230		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11231		if (oafeovr)
11232			bwn_phy_lp_set_txgain(mac, &ogain);
11233		bwn_phy_lp_set_bbmult(mac, obbmult);
11234		bwn_phy_lp_set_txpctlmode(mac, omode);
11235		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11236	}
11237	bwn_phy_lp_set_txpctlmode(mac, mode);
11238	if (mac->mac_phy.rev >= 2)
11239		bwn_phy_lp_digflt_restore(mac);
11240
11241	/* do RX IQ Calculation; assumes that noise is true. */
11242	if (siba->siba_chipid == 0x5354) {
11243		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11244			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11245				rc = &bwn_rxcompco_5354[i];
11246		}
11247	} else if (mac->mac_phy.rev >= 2)
11248		rc = &bwn_rxcompco_r2;
11249	else {
11250		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11251			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11252				rc = &bwn_rxcompco_r12[i];
11253		}
11254	}
11255	if (rc == NULL)
11256		goto fail;
11257
11258	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11259	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11260
11261	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11262
11263	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11264		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11265		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11266	} else {
11267		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11268		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11269	}
11270
11271	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11272	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11273	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11274	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11275	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11276	bwn_phy_lp_set_deaf(mac, 0);
11277	/* XXX no checking return value? */
11278	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11279	bwn_phy_lp_clear_deaf(mac, 0);
11280	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11281	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11282	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11283
11284	/* disable RX GAIN override. */
11285	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11286	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11287	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11288	if (mac->mac_phy.rev >= 2) {
11289		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11290		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11291			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11292			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11293		}
11294	} else {
11295		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11296	}
11297
11298	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11299	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11300fail:
11301	bwn_mac_enable(mac);
11302}
11303
11304static void
11305bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11306{
11307
11308       if (on) {
11309               BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11310	       return;
11311       }
11312
11313       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11314       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11315}
11316
11317static int
11318bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11319{
11320	struct siba_dev_softc *sd = mac->mac_sd;
11321	struct siba_softc *siba = sd->sd_bus;
11322	static const struct bwn_b206x_chan *bc = NULL;
11323	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11324	    tmp[6];
11325	uint16_t old, scale, tmp16;
11326	int i, div;
11327
11328	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11329		if (bwn_b2063_chantable[i].bc_chan == chan) {
11330			bc = &bwn_b2063_chantable[i];
11331			break;
11332		}
11333	}
11334	if (bc == NULL)
11335		return (EINVAL);
11336
11337	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11338	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11339	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11340	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11341	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11342	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11343	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11344	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11345	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11346	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11347	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11348	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11349
11350	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11351	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11352
11353	freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11354	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11355	freqref = freqxtal * 3;
11356	div = (freqxtal <= 26000000 ? 1 : 2);
11357	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11358	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11359		999999) / 1000000) + 1;
11360
11361	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11362	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11363	    0xfff8, timeout >> 2);
11364	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11365	    0xff9f,timeout << 5);
11366	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11367
11368	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11369	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11370	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11371
11372	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11373	    (timeoutref + 1)) - 1;
11374	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11375	    0xf0, count >> 8);
11376	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11377
11378	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11379	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11380	while (tmp[1] >= freqref) {
11381		tmp[0]++;
11382		tmp[1] -= freqref;
11383	}
11384	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11385	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11386	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11387	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11388	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11389
11390	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11391	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11392	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11393	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11394
11395	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11396	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11397
11398	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11399		scale = 1;
11400		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11401	} else {
11402		scale = 0;
11403		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11404	}
11405	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11406	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11407
11408	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11409	    (scale + 1);
11410	if (tmp[5] > 150)
11411		tmp[5] = 0;
11412
11413	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11414	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11415
11416	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11417	if (freqxtal > 26000000)
11418		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11419	else
11420		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11421
11422	if (val[0] == 45)
11423		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11424	else
11425		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11426
11427	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11428	DELAY(1);
11429	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11430
11431	/* VCO Calibration */
11432	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11433	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11434	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11435	DELAY(1);
11436	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11437	DELAY(1);
11438	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11439	DELAY(1);
11440	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11441	DELAY(300);
11442	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11443
11444	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11445	return (0);
11446}
11447
11448static int
11449bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11450{
11451	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11452	struct siba_dev_softc *sd = mac->mac_sd;
11453	struct siba_softc *siba = sd->sd_bus;
11454	const struct bwn_b206x_chan *bc = NULL;
11455	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11456	uint32_t tmp[9];
11457	int i;
11458
11459	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11460		if (bwn_b2062_chantable[i].bc_chan == chan) {
11461			bc = &bwn_b2062_chantable[i];
11462			break;
11463		}
11464	}
11465
11466	if (bc == NULL)
11467		return (EINVAL);
11468
11469	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11470	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11471	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11472	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11473	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11474	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11475	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11476	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11477	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11478	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11479
11480	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11481	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11482	bwn_phy_lp_b2062_reset_pllbias(mac);
11483	tmp[0] = freqxtal / 1000;
11484	tmp[1] = plp->plp_div * 1000;
11485	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11486	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11487		tmp[2] *= 2;
11488	tmp[3] = 48 * tmp[0];
11489	tmp[5] = tmp[2] / tmp[3];
11490	tmp[6] = tmp[2] % tmp[3];
11491	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11492	tmp[4] = tmp[6] * 0x100;
11493	tmp[5] = tmp[4] / tmp[3];
11494	tmp[6] = tmp[4] % tmp[3];
11495	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11496	tmp[4] = tmp[6] * 0x100;
11497	tmp[5] = tmp[4] / tmp[3];
11498	tmp[6] = tmp[4] % tmp[3];
11499	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11500	tmp[4] = tmp[6] * 0x100;
11501	tmp[5] = tmp[4] / tmp[3];
11502	tmp[6] = tmp[4] % tmp[3];
11503	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11504	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11505	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11506	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11507	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11508	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11509
11510	bwn_phy_lp_b2062_vco_calib(mac);
11511	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11512		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11513		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11514		bwn_phy_lp_b2062_reset_pllbias(mac);
11515		bwn_phy_lp_b2062_vco_calib(mac);
11516		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11517			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11518			return (EIO);
11519		}
11520	}
11521	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11522	return (0);
11523}
11524
11525static void
11526bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11527{
11528	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11529	uint16_t tmp = (channel == 14);
11530
11531	if (mac->mac_phy.rev < 2) {
11532		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11533		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11534			bwn_phy_lp_set_rccap(mac);
11535		return;
11536	}
11537
11538	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11539}
11540
11541static void
11542bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11543{
11544	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11545	struct bwn_softc *sc = mac->mac_sc;
11546	struct ifnet *ifp = sc->sc_ifp;
11547	struct ieee80211com *ic = ifp->if_l2com;
11548	uint16_t iso, tmp[3];
11549
11550	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11551
11552	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11553		iso = plp->plp_txisoband_m;
11554	else if (freq <= 5320)
11555		iso = plp->plp_txisoband_l;
11556	else if (freq <= 5700)
11557		iso = plp->plp_txisoband_m;
11558	else
11559		iso = plp->plp_txisoband_h;
11560
11561	tmp[0] = ((iso - 26) / 12) << 12;
11562	tmp[1] = tmp[0] + 0x1000;
11563	tmp[2] = tmp[0] + 0x2000;
11564
11565	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11566	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11567}
11568
11569static void
11570bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11571{
11572	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11573	int i;
11574	static const uint16_t addr[] = {
11575		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11576		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11577		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11578		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11579		BWN_PHY_OFDM(0xcf),
11580	};
11581	static const uint16_t val[] = {
11582		0xde5e, 0xe832, 0xe331, 0x4d26,
11583		0x0026, 0x1420, 0x0020, 0xfe08,
11584		0x0008,
11585	};
11586
11587	for (i = 0; i < N(addr); i++) {
11588		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11589		BWN_PHY_WRITE(mac, addr[i], val[i]);
11590	}
11591}
11592
11593static void
11594bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11595{
11596	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11597	struct bwn_softc *sc = mac->mac_sc;
11598	uint16_t ctl;
11599
11600	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11601	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11602	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11603		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11604		break;
11605	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11606		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11607		break;
11608	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11609		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11610		break;
11611	default:
11612		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11613		device_printf(sc->sc_dev, "unknown command mode\n");
11614		break;
11615	}
11616}
11617
11618static void
11619bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11620{
11621	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11622	uint16_t ctl;
11623	uint8_t old;
11624
11625	bwn_phy_lp_get_txpctlmode(mac);
11626	old = plp->plp_txpctlmode;
11627	if (old == mode)
11628		return;
11629	plp->plp_txpctlmode = mode;
11630
11631	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11632		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11633		    plp->plp_tssiidx);
11634		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11635		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11636
11637		/* disable TX GAIN override */
11638		if (mac->mac_phy.rev < 2)
11639			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11640		else {
11641			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11642			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11643		}
11644		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11645
11646		plp->plp_txpwridx = -1;
11647	}
11648	if (mac->mac_phy.rev >= 2) {
11649		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11650			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11651		else
11652			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11653	}
11654
11655	/* writes TX Power Control mode */
11656	switch (plp->plp_txpctlmode) {
11657	case BWN_PHYLP_TXPCTL_OFF:
11658		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11659		break;
11660	case BWN_PHYLP_TXPCTL_ON_HW:
11661		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11662		break;
11663	case BWN_PHYLP_TXPCTL_ON_SW:
11664		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11665		break;
11666	default:
11667		ctl = 0;
11668		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11669	}
11670	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11671	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11672}
11673
11674static void
11675bwn_phy_lp_bugfix(struct bwn_mac *mac)
11676{
11677	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11678	struct bwn_softc *sc = mac->mac_sc;
11679	const unsigned int size = 256;
11680	struct bwn_txgain tg;
11681	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11682	uint16_t tssinpt, tssiidx, value[2];
11683	uint8_t mode;
11684	int8_t txpwridx;
11685
11686	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11687	    M_NOWAIT | M_ZERO);
11688	if (tabs == NULL) {
11689		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11690		return;
11691	}
11692
11693	bwn_phy_lp_get_txpctlmode(mac);
11694	mode = plp->plp_txpctlmode;
11695	txpwridx = plp->plp_txpwridx;
11696	tssinpt = plp->plp_tssinpt;
11697	tssiidx = plp->plp_tssiidx;
11698
11699	bwn_tab_read_multi(mac,
11700	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11701	    BWN_TAB_4(7, 0x140), size, tabs);
11702
11703	bwn_phy_lp_tblinit(mac);
11704	bwn_phy_lp_bbinit(mac);
11705	bwn_phy_lp_txpctl_init(mac);
11706	bwn_phy_lp_rf_onoff(mac, 1);
11707	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11708
11709	bwn_tab_write_multi(mac,
11710	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11711	    BWN_TAB_4(7, 0x140), size, tabs);
11712
11713	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11714	plp->plp_tssinpt = tssinpt;
11715	plp->plp_tssiidx = tssiidx;
11716	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11717	if (txpwridx != -1) {
11718		/* set TX power by index */
11719		plp->plp_txpwridx = txpwridx;
11720		bwn_phy_lp_get_txpctlmode(mac);
11721		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11722			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11723		if (mac->mac_phy.rev >= 2) {
11724			rxcomp = bwn_tab_read(mac,
11725			    BWN_TAB_4(7, txpwridx + 320));
11726			txgain = bwn_tab_read(mac,
11727			    BWN_TAB_4(7, txpwridx + 192));
11728			tg.tg_pad = (txgain >> 16) & 0xff;
11729			tg.tg_gm = txgain & 0xff;
11730			tg.tg_pga = (txgain >> 8) & 0xff;
11731			tg.tg_dac = (rxcomp >> 28) & 0xff;
11732			bwn_phy_lp_set_txgain(mac, &tg);
11733		} else {
11734			rxcomp = bwn_tab_read(mac,
11735			    BWN_TAB_4(10, txpwridx + 320));
11736			txgain = bwn_tab_read(mac,
11737			    BWN_TAB_4(10, txpwridx + 192));
11738			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11739			    0xf800, (txgain >> 4) & 0x7fff);
11740			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11741			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11742		}
11743		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11744
11745		/* set TX IQCC */
11746		value[0] = (rxcomp >> 10) & 0x3ff;
11747		value[1] = rxcomp & 0x3ff;
11748		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11749
11750		coeff = bwn_tab_read(mac,
11751		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11752		    BWN_TAB_4(10, txpwridx + 448));
11753		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11754		if (mac->mac_phy.rev >= 2) {
11755			rfpwr = bwn_tab_read(mac,
11756			    BWN_TAB_4(7, txpwridx + 576));
11757			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11758			    rfpwr & 0xffff);
11759		}
11760		bwn_phy_lp_set_txgain_override(mac);
11761	}
11762	if (plp->plp_rccap)
11763		bwn_phy_lp_set_rccap(mac);
11764	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11765	bwn_phy_lp_set_txpctlmode(mac, mode);
11766	free(tabs, M_DEVBUF);
11767}
11768
11769static void
11770bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11771{
11772	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11773	int i;
11774	static const uint16_t addr[] = {
11775		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11776		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11777		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11778		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11779		BWN_PHY_OFDM(0xcf),
11780	};
11781
11782	for (i = 0; i < N(addr); i++)
11783		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11784}
11785
11786static void
11787bwn_phy_lp_tblinit(struct bwn_mac *mac)
11788{
11789	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11790
11791	if (mac->mac_phy.rev < 2) {
11792		bwn_phy_lp_tblinit_r01(mac);
11793		bwn_phy_lp_tblinit_txgain(mac);
11794		bwn_phy_lp_set_gaintbl(mac, freq);
11795		return;
11796	}
11797
11798	bwn_phy_lp_tblinit_r2(mac);
11799	bwn_phy_lp_tblinit_txgain(mac);
11800}
11801
11802struct bwn_wpair {
11803	uint16_t		reg;
11804	uint16_t		value;
11805};
11806
11807struct bwn_smpair {
11808	uint16_t		offset;
11809	uint16_t		mask;
11810	uint16_t		set;
11811};
11812
11813static void
11814bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11815{
11816	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11817	struct siba_dev_softc *sd = mac->mac_sd;
11818	struct siba_softc *siba = sd->sd_bus;
11819	struct bwn_softc *sc = mac->mac_sc;
11820	struct ifnet *ifp = sc->sc_ifp;
11821	struct ieee80211com *ic = ifp->if_l2com;
11822	static const struct bwn_wpair v1[] = {
11823		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11824		{ BWN_PHY_AFE_CTL, 0x8800 },
11825		{ BWN_PHY_AFE_CTL_OVR, 0 },
11826		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11827		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11828		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11829		{ BWN_PHY_OFDM(0xf9), 0 },
11830		{ BWN_PHY_TR_LOOKUP_1, 0 }
11831	};
11832	static const struct bwn_smpair v2[] = {
11833		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11834		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11835		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11836		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11837		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11838	};
11839	static const struct bwn_smpair v3[] = {
11840		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11841		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11842		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11843		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11844		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11845		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11846		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11847		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11848		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11849		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11850
11851	};
11852	int i;
11853
11854	for (i = 0; i < N(v1); i++)
11855		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11856	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11857	for (i = 0; i < N(v2); i++)
11858		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11859
11860	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11861	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11862	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11863	if (siba->siba_board_rev >= 0x18) {
11864		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11865		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11866	} else {
11867		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11868	}
11869	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11870	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11871	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11872	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11873	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11874	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11875	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11876	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11877	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11878	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11879	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11880	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11881		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11882		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11883	} else {
11884		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11885		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11886	}
11887	for (i = 0; i < N(v3); i++)
11888		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11889	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11890		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11891		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11892	}
11893
11894	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11895		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11896		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11897		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11898		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11899		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11900		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11901	} else
11902		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11903
11904	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11905	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11906	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11907	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11908	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11909	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11910	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11911	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11912	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11913
11914	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11915		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11916		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11917		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11918	}
11919
11920	bwn_phy_lp_digflt_save(mac);
11921}
11922
11923static void
11924bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11925{
11926	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11927	struct siba_dev_softc *sd = mac->mac_sd;
11928	struct siba_softc *siba = sd->sd_bus;
11929	struct bwn_softc *sc = mac->mac_sc;
11930	struct ifnet *ifp = sc->sc_ifp;
11931	struct ieee80211com *ic = ifp->if_l2com;
11932	static const struct bwn_smpair v1[] = {
11933		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11934		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11935		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11936		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11937		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11938		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11939		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11940	};
11941	static const struct bwn_smpair v2[] = {
11942		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11943		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11944		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11945		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11946		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11947		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11948		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11949		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11950		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11951		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11952		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11953		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11954		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11955		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11956		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11957		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11958	};
11959	static const struct bwn_smpair v3[] = {
11960		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11961		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11962		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11963		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11964		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11965		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11966		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11967		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11968	};
11969	static const struct bwn_smpair v4[] = {
11970		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11971		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11972		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11973		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11974		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11975		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11976		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11977		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11978	};
11979	static const struct bwn_smpair v5[] = {
11980		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11981		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11982		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11983		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11984		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11985		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11986		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11987		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11988	};
11989	int i;
11990	uint16_t tmp, tmp2;
11991
11992	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11993	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11994	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11995	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11996	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11997	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11998	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11999	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
12000	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
12001	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
12002	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
12003	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
12004	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
12005	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
12006	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
12007	for (i = 0; i < N(v1); i++)
12008		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
12009	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
12010	    0xff00, plp->plp_rxpwroffset);
12011	if ((siba->siba_sprom.bf_lo & BWN_BFL_FEM) &&
12012	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
12013	   (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF))) {
12014		siba_cc_pmu_set_ldovolt(&siba->siba_cc, SIBA_LDO_PAREF, 0x28);
12015		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 1);
12016		if (mac->mac_phy.rev == 0)
12017			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
12018			    0xffcf, 0x0010);
12019		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
12020	} else {
12021		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 0);
12022		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
12023		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
12024	}
12025	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
12026	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
12027	if (siba->siba_sprom.bf_hi & BWN_BFH_RSSIINV)
12028		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
12029	else
12030		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
12031	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
12032	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
12033	    0xfff9, (plp->plp_bxarch << 1));
12034	if (mac->mac_phy.rev == 1 &&
12035	    (siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT)) {
12036		for (i = 0; i < N(v2); i++)
12037			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
12038			    v2[i].set);
12039	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
12040	    (siba->siba_board_type == 0x048a) || ((mac->mac_phy.rev == 0) &&
12041	    (siba->siba_sprom.bf_lo & BWN_BFL_FEM))) {
12042		for (i = 0; i < N(v3); i++)
12043			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12044			    v3[i].set);
12045	} else if (mac->mac_phy.rev == 1 ||
12046		  (siba->siba_sprom.bf_lo & BWN_BFL_FEM)) {
12047		for (i = 0; i < N(v4); i++)
12048			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12049			    v4[i].set);
12050	} else {
12051		for (i = 0; i < N(v5); i++)
12052			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12053			    v5[i].set);
12054	}
12055	if (mac->mac_phy.rev == 1 &&
12056	    (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF)) {
12057		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12058		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12059		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12060		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12061	}
12062	if ((siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT) &&
12063	    (siba->siba_chipid == 0x5354) &&
12064	    (siba->siba_chippkg == SIBA_CHIPPACK_BCM4712S)) {
12065		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12066		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12067		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12068		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12069	}
12070	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12071		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12072		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12073		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12074		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12075		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12076		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12077		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12078		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12079	} else {
12080		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12081		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12082	}
12083	if (mac->mac_phy.rev == 1) {
12084		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12085		tmp2 = (tmp & 0x03e0) >> 5;
12086		tmp2 |= tmp2 << 5;
12087		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12088		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12089		tmp2 = (tmp & 0x1f00) >> 8;
12090		tmp2 |= tmp2 << 5;
12091		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12092		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12093		tmp2 = tmp & 0x00ff;
12094		tmp2 |= tmp << 8;
12095		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12096	}
12097}
12098
12099struct bwn_b2062_freq {
12100	uint16_t		freq;
12101	uint8_t			value[6];
12102};
12103
12104static void
12105bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12106{
12107#define	CALC_CTL7(freq, div)						\
12108	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12109#define	CALC_CTL18(freq, div)						\
12110	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12111#define	CALC_CTL19(freq, div)						\
12112	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12113	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12114	struct siba_dev_softc *sd = mac->mac_sd;
12115	struct siba_softc *siba = sd->sd_bus;
12116	struct bwn_softc *sc = mac->mac_sc;
12117	struct ifnet *ifp = sc->sc_ifp;
12118	struct ieee80211com *ic = ifp->if_l2com;
12119	static const struct bwn_b2062_freq freqdata_tab[] = {
12120		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12121		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12122		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12123		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12124		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12125		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12126	};
12127	static const struct bwn_wpair v1[] = {
12128		{ BWN_B2062_N_TXCTL3, 0 },
12129		{ BWN_B2062_N_TXCTL4, 0 },
12130		{ BWN_B2062_N_TXCTL5, 0 },
12131		{ BWN_B2062_N_TXCTL6, 0 },
12132		{ BWN_B2062_N_PDNCTL0, 0x40 },
12133		{ BWN_B2062_N_PDNCTL0, 0 },
12134		{ BWN_B2062_N_CALIB_TS, 0x10 },
12135		{ BWN_B2062_N_CALIB_TS, 0 }
12136	};
12137	const struct bwn_b2062_freq *f = NULL;
12138	uint32_t xtalfreq, ref;
12139	unsigned int i;
12140
12141	bwn_phy_lp_b2062_tblinit(mac);
12142
12143	for (i = 0; i < N(v1); i++)
12144		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12145	if (mac->mac_phy.rev > 0)
12146		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12147		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12148	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12149		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12150	else
12151		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12152
12153	KASSERT(siba->siba_cc.scc_caps & SIBA_CC_CAPS_PMU,
12154	    ("%s:%d: fail", __func__, __LINE__));
12155	xtalfreq = siba->siba_cc.scc_pmu.freq * 1000;
12156	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12157
12158	if (xtalfreq <= 30000000) {
12159		plp->plp_div = 1;
12160		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12161	} else {
12162		plp->plp_div = 2;
12163		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12164	}
12165
12166	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12167	    CALC_CTL7(xtalfreq, plp->plp_div));
12168	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12169	    CALC_CTL18(xtalfreq, plp->plp_div));
12170	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12171	    CALC_CTL19(xtalfreq, plp->plp_div));
12172
12173	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12174	ref &= 0xffff;
12175	for (i = 0; i < N(freqdata_tab); i++) {
12176		if (ref < freqdata_tab[i].freq) {
12177			f = &freqdata_tab[i];
12178			break;
12179		}
12180	}
12181	if (f == NULL)
12182		f = &freqdata_tab[N(freqdata_tab) - 1];
12183	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12184	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12185	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12186	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12187	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12188	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12189#undef CALC_CTL7
12190#undef CALC_CTL18
12191#undef CALC_CTL19
12192}
12193
12194static void
12195bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12196{
12197
12198	bwn_phy_lp_b2063_tblinit(mac);
12199	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12200	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12201	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12202	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12203	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12204	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12205	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12206	if (mac->mac_phy.rev == 2) {
12207		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12208		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12209		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12210	} else {
12211		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12212		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12213	}
12214}
12215
12216static void
12217bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12218{
12219	struct siba_dev_softc *sd = mac->mac_sd;
12220	struct siba_softc *siba = sd->sd_bus;
12221	static const struct bwn_wpair v1[] = {
12222		{ BWN_B2063_RX_BB_SP8, 0x0 },
12223		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12224		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12225		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12226		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12227		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12228		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12229		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12230	};
12231	static const struct bwn_wpair v2[] = {
12232		{ BWN_B2063_TX_BB_SP3, 0x0 },
12233		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12234		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12235		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12236		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12237	};
12238	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
12239	int i;
12240	uint8_t tmp;
12241
12242	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12243
12244	for (i = 0; i < 2; i++)
12245		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12246	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12247	for (i = 2; i < N(v1); i++)
12248		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12249	for (i = 0; i < 10000; i++) {
12250		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12251			break;
12252		DELAY(1000);
12253	}
12254
12255	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12256		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12257
12258	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12259
12260	for (i = 0; i < N(v2); i++)
12261		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12262	if (freqxtal == 24000000) {
12263		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12264		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12265	} else {
12266		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12267		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12268	}
12269	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12270	for (i = 0; i < 10000; i++) {
12271		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12272			break;
12273		DELAY(1000);
12274	}
12275	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12276		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12277	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12278}
12279
12280static void
12281bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12282{
12283	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12284	struct bwn_softc *sc = mac->mac_sc;
12285	struct bwn_phy_lp_iq_est ie;
12286	struct bwn_txgain tx_gains;
12287	static const uint32_t pwrtbl[21] = {
12288		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12289		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12290		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12291		0x0004c, 0x0002c, 0x0001a,
12292	};
12293	uint32_t npwr, ipwr, sqpwr, tmp;
12294	int loopback, i, j, sum, error;
12295	uint16_t save[7];
12296	uint8_t txo, bbmult, txpctlmode;
12297
12298	error = bwn_phy_lp_switch_channel(mac, 7);
12299	if (error)
12300		device_printf(sc->sc_dev,
12301		    "failed to change channel to 7 (%d)\n", error);
12302	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12303	bbmult = bwn_phy_lp_get_bbmult(mac);
12304	if (txo)
12305		tx_gains = bwn_phy_lp_get_txgain(mac);
12306
12307	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12308	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12309	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12310	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12311	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12312	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12313	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12314
12315	bwn_phy_lp_get_txpctlmode(mac);
12316	txpctlmode = plp->plp_txpctlmode;
12317	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12318
12319	/* disable CRS */
12320	bwn_phy_lp_set_deaf(mac, 1);
12321	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12322	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12323	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12324	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12325	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12326	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12327	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12328	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12329	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12330	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12331	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12332	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12333	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12334	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12335	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12336	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12337	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12338	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12339	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12340	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12341	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12342	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12343	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12344	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12345
12346	loopback = bwn_phy_lp_loopback(mac);
12347	if (loopback == -1)
12348		goto done;
12349	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12350	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12351	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12352	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12353	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12354
12355	tmp = 0;
12356	memset(&ie, 0, sizeof(ie));
12357	for (i = 128; i <= 159; i++) {
12358		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12359		sum = 0;
12360		for (j = 5; j <= 25; j++) {
12361			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12362			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12363				goto done;
12364			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12365			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12366			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12367			    12);
12368			sum += ((ipwr - npwr) * (ipwr - npwr));
12369			if ((i == 128) || (sum < tmp)) {
12370				plp->plp_rccap = i;
12371				tmp = sum;
12372			}
12373		}
12374	}
12375	bwn_phy_lp_ddfs_turnoff(mac);
12376done:
12377	/* restore CRS */
12378	bwn_phy_lp_clear_deaf(mac, 1);
12379	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12380	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12381
12382	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12383	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12384	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12385	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12386	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12387	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12388	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12389
12390	bwn_phy_lp_set_bbmult(mac, bbmult);
12391	if (txo)
12392		bwn_phy_lp_set_txgain(mac, &tx_gains);
12393	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12394	if (plp->plp_rccap)
12395		bwn_phy_lp_set_rccap(mac);
12396}
12397
12398static void
12399bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12400{
12401	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12402	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12403
12404	if (mac->mac_phy.rev == 1)
12405		rc_cap = MIN(rc_cap + 5, 15);
12406
12407	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12408	    MAX(plp->plp_rccap - 4, 0x80));
12409	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12410	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12411	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12412}
12413
12414static uint32_t
12415bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12416{
12417	uint32_t i, q, r;
12418
12419	if (div == 0)
12420		return (0);
12421
12422	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12423		q <<= 1;
12424		if (r << 1 >= div) {
12425			q++;
12426			r = (r << 1) - div;
12427		}
12428	}
12429	if (r << 1 >= div)
12430		q++;
12431	return (q);
12432}
12433
12434static void
12435bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12436{
12437	struct siba_dev_softc *sd = mac->mac_sd;
12438	struct siba_softc *siba = sd->sd_bus;
12439
12440	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12441	DELAY(20);
12442	if (siba->siba_chipid == 0x5354) {
12443		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12444		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12445	} else {
12446		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12447	}
12448	DELAY(5);
12449}
12450
12451static void
12452bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12453{
12454
12455	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12456	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12457	DELAY(200);
12458}
12459
12460static void
12461bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12462{
12463#define	FLAG_A	0x01
12464#define	FLAG_G	0x02
12465	struct bwn_softc *sc = mac->mac_sc;
12466	struct ifnet *ifp = sc->sc_ifp;
12467	struct ieee80211com *ic = ifp->if_l2com;
12468	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12469		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12470		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12471		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12472		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12473		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12474		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12475		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12476		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12477		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12478		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12479		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12480		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12481		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12482		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12483		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12484		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12485		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12486		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12487		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12488		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12489		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12490		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12491		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12492		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12493		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12494		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12495		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12496		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12497		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12498		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12499		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12500		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12501		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12502		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12503		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12504		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12505		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12506		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12507		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12508		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12509		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12510		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12511		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12512		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12513		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12514		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12515		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12516	};
12517	const struct bwn_b206x_rfinit_entry *br;
12518	unsigned int i;
12519
12520	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12521		br = &bwn_b2062_init_tab[i];
12522		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12523			if (br->br_flags & FLAG_G)
12524				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12525		} else {
12526			if (br->br_flags & FLAG_A)
12527				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12528		}
12529	}
12530#undef FLAG_A
12531#undef FLAG_B
12532}
12533
12534static void
12535bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12536{
12537#define	FLAG_A	0x01
12538#define	FLAG_G	0x02
12539	struct bwn_softc *sc = mac->mac_sc;
12540	struct ifnet *ifp = sc->sc_ifp;
12541	struct ieee80211com *ic = ifp->if_l2com;
12542	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12543		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12544		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12545		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12546		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12547		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12548		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12549		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12550		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12551		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12552		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12553		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12554		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12555		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12556		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12557		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12558		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12559		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12560		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12561		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12562		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12563		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12564		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12565		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12566		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12567		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12568		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12569		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12570		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12571		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12572		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12573		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12574		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12575		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12576		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12577		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12578		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12579		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12580		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12581		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12582		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12583		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12584		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12585	};
12586	const struct bwn_b206x_rfinit_entry *br;
12587	unsigned int i;
12588
12589	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12590		br = &bwn_b2063_init_tab[i];
12591		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12592			if (br->br_flags & FLAG_G)
12593				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12594		} else {
12595			if (br->br_flags & FLAG_A)
12596				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12597		}
12598	}
12599#undef FLAG_A
12600#undef FLAG_B
12601}
12602
12603static void
12604bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12605    int count, void *_data)
12606{
12607	unsigned int i;
12608	uint32_t offset, type;
12609	uint8_t *data = _data;
12610
12611	type = BWN_TAB_GETTYPE(typenoffset);
12612	offset = BWN_TAB_GETOFFSET(typenoffset);
12613	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12614
12615	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12616
12617	for (i = 0; i < count; i++) {
12618		switch (type) {
12619		case BWN_TAB_8BIT:
12620			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12621			data++;
12622			break;
12623		case BWN_TAB_16BIT:
12624			*((uint16_t *)data) = BWN_PHY_READ(mac,
12625			    BWN_PHY_TABLEDATALO);
12626			data += 2;
12627			break;
12628		case BWN_TAB_32BIT:
12629			*((uint32_t *)data) = BWN_PHY_READ(mac,
12630			    BWN_PHY_TABLEDATAHI);
12631			*((uint32_t *)data) <<= 16;
12632			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12633			    BWN_PHY_TABLEDATALO);
12634			data += 4;
12635			break;
12636		default:
12637			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12638		}
12639	}
12640}
12641
12642static void
12643bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12644    int count, const void *_data)
12645{
12646	uint32_t offset, type, value;
12647	const uint8_t *data = _data;
12648	unsigned int i;
12649
12650	type = BWN_TAB_GETTYPE(typenoffset);
12651	offset = BWN_TAB_GETOFFSET(typenoffset);
12652	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12653
12654	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12655
12656	for (i = 0; i < count; i++) {
12657		switch (type) {
12658		case BWN_TAB_8BIT:
12659			value = *data;
12660			data++;
12661			KASSERT(!(value & ~0xff),
12662			    ("%s:%d: fail", __func__, __LINE__));
12663			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12664			break;
12665		case BWN_TAB_16BIT:
12666			value = *((const uint16_t *)data);
12667			data += 2;
12668			KASSERT(!(value & ~0xffff),
12669			    ("%s:%d: fail", __func__, __LINE__));
12670			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12671			break;
12672		case BWN_TAB_32BIT:
12673			value = *((const uint32_t *)data);
12674			data += 4;
12675			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12676			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12677			break;
12678		default:
12679			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12680		}
12681	}
12682}
12683
12684static struct bwn_txgain
12685bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12686{
12687	struct bwn_txgain tg;
12688	uint16_t tmp;
12689
12690	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12691	if (mac->mac_phy.rev < 2) {
12692		tmp = BWN_PHY_READ(mac,
12693		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12694		tg.tg_gm = tmp & 0x0007;
12695		tg.tg_pga = (tmp & 0x0078) >> 3;
12696		tg.tg_pad = (tmp & 0x780) >> 7;
12697		return (tg);
12698	}
12699
12700	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12701	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12702	tg.tg_gm = tmp & 0xff;
12703	tg.tg_pga = (tmp >> 8) & 0xff;
12704	return (tg);
12705}
12706
12707static uint8_t
12708bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12709{
12710
12711	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12712}
12713
12714static void
12715bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12716{
12717	uint16_t pa;
12718
12719	if (mac->mac_phy.rev < 2) {
12720		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12721		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12722		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12723		bwn_phy_lp_set_txgain_override(mac);
12724		return;
12725	}
12726
12727	pa = bwn_phy_lp_get_pa_gain(mac);
12728	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12729	    (tg->tg_pga << 8) | tg->tg_gm);
12730	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12731	    tg->tg_pad | (pa << 6));
12732	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12733	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12734	    tg->tg_pad | (pa << 8));
12735	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12736	bwn_phy_lp_set_txgain_override(mac);
12737}
12738
12739static void
12740bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12741{
12742
12743	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12744}
12745
12746static void
12747bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12748{
12749	uint16_t trsw = (tx << 1) | rx;
12750
12751	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12752	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12753}
12754
12755static void
12756bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12757{
12758	struct bwn_softc *sc = mac->mac_sc;
12759	struct ifnet *ifp = sc->sc_ifp;
12760	struct ieee80211com *ic = ifp->if_l2com;
12761	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12762
12763	if (mac->mac_phy.rev < 2) {
12764		trsw = gain & 0x1;
12765		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12766		ext_lna = (gain & 2) >> 1;
12767
12768		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12769		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12770		    0xfbff, ext_lna << 10);
12771		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12772		    0xf7ff, ext_lna << 11);
12773		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12774	} else {
12775		low_gain = gain & 0xffff;
12776		high_gain = (gain >> 16) & 0xf;
12777		ext_lna = (gain >> 21) & 0x1;
12778		trsw = ~(gain >> 20) & 0x1;
12779
12780		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12781		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12782		    0xfdff, ext_lna << 9);
12783		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12784		    0xfbff, ext_lna << 10);
12785		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12786		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12787		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12788			tmp = (gain >> 2) & 0x3;
12789			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12790			    0xe7ff, tmp<<11);
12791			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12792			    tmp << 3);
12793		}
12794	}
12795
12796	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12797	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12798	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12799	if (mac->mac_phy.rev >= 2) {
12800		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12801		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12802			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12803			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12804		}
12805		return;
12806	}
12807	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12808}
12809
12810static void
12811bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12812{
12813	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12814
12815	if (user)
12816		plp->plp_crsusr_off = 1;
12817	else
12818		plp->plp_crssys_off = 1;
12819
12820	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12821}
12822
12823static void
12824bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12825{
12826	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12827	struct bwn_softc *sc = mac->mac_sc;
12828	struct ifnet *ifp = sc->sc_ifp;
12829	struct ieee80211com *ic = ifp->if_l2com;
12830
12831	if (user)
12832		plp->plp_crsusr_off = 0;
12833	else
12834		plp->plp_crssys_off = 0;
12835
12836	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12837		return;
12838
12839	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12840		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12841	else
12842		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12843}
12844
12845static unsigned int
12846bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12847{
12848	struct bwn_softc *sc = mac->mac_sc;
12849	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12850	static uint8_t sqrt_table[256] = {
12851		10, 14, 17, 20, 22, 24, 26, 28,
12852		30, 31, 33, 34, 36, 37, 38, 40,
12853		41, 42, 43, 44, 45, 46, 47, 48,
12854		50, 50, 51, 52, 53, 54, 55, 56,
12855		57, 58, 59, 60, 60, 61, 62, 63,
12856		64, 64, 65, 66, 67, 67, 68, 69,
12857		70, 70, 71, 72, 72, 73, 74, 74,
12858		75, 76, 76, 77, 78, 78, 79, 80,
12859		80, 81, 81, 82, 83, 83, 84, 84,
12860		85, 86, 86, 87, 87, 88, 88, 89,
12861		90, 90, 91, 91, 92, 92, 93, 93,
12862		94, 94, 95, 95, 96, 96, 97, 97,
12863		98, 98, 99, 100, 100, 100, 101, 101,
12864		102, 102, 103, 103, 104, 104, 105, 105,
12865		106, 106, 107, 107, 108, 108, 109, 109,
12866		110, 110, 110, 111, 111, 112, 112, 113,
12867		113, 114, 114, 114, 115, 115, 116, 116,
12868		117, 117, 117, 118, 118, 119, 119, 120,
12869		120, 120, 121, 121, 122, 122, 122, 123,
12870		123, 124, 124, 124, 125, 125, 126, 126,
12871		126, 127, 127, 128, 128, 128, 129, 129,
12872		130, 130, 130, 131, 131, 131, 132, 132,
12873		133, 133, 133, 134, 134, 134, 135, 135,
12874		136, 136, 136, 137, 137, 137, 138, 138,
12875		138, 139, 139, 140, 140, 140, 141, 141,
12876		141, 142, 142, 142, 143, 143, 143, 144,
12877		144, 144, 145, 145, 145, 146, 146, 146,
12878		147, 147, 147, 148, 148, 148, 149, 149,
12879		150, 150, 150, 150, 151, 151, 151, 152,
12880		152, 152, 153, 153, 153, 154, 154, 154,
12881		155, 155, 155, 156, 156, 156, 157, 157,
12882		157, 158, 158, 158, 159, 159, 159, 160
12883	};
12884
12885	if (x == 0)
12886		return (0);
12887	if (x >= 256) {
12888		device_printf(sc->sc_dev,
12889		    "out of bounds of the square-root table (%d)\n", x);
12890		return (16);
12891	}
12892	return (sqrt_table[x - 1] / 10);
12893}
12894
12895static int
12896bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12897{
12898#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12899	int _t;								\
12900	_t = _x - 20;							\
12901	if (_t >= 0) {							\
12902		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12903	} else {							\
12904		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12905	}								\
12906} while (0)
12907#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12908	int _t;								\
12909	_t = _x - 11;							\
12910	if (_t >= 0)							\
12911		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12912	else								\
12913		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12914} while (0)
12915	struct bwn_phy_lp_iq_est ie;
12916	uint16_t v0, v1;
12917	int tmp[2], ret;
12918
12919	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12920	v0 = v1 >> 8;
12921	v1 |= 0xff;
12922
12923	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12924	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12925
12926	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12927	if (ret == 0)
12928		goto done;
12929
12930	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12931		ret = 0;
12932		goto done;
12933	}
12934
12935	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12936	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12937
12938	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12939	v0 = tmp[0] >> 3;
12940	v1 = tmp[1] >> 4;
12941done:
12942	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12943	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12944	return ret;
12945#undef CALC_COEFF
12946#undef CALC_COEFF2
12947}
12948
12949static void
12950bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12951{
12952	static const uint16_t noisescale[] = {
12953		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12954		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12955		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12956		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12957		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12958	};
12959	static const uint16_t crsgainnft[] = {
12960		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12961		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12962		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12963		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12964		0x013d,
12965	};
12966	static const uint16_t filterctl[] = {
12967		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12968		0xff53, 0x0127,
12969	};
12970	static const uint32_t psctl[] = {
12971		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12972		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12973		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12974		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12975		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12976		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12977		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12978		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12979	};
12980	static const uint16_t ofdmcckgain_r0[] = {
12981		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12982		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12983		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12984		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12985		0x755d,
12986	};
12987	static const uint16_t ofdmcckgain_r1[] = {
12988		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12989		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12990		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12991		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12992		0x755d,
12993	};
12994	static const uint16_t gaindelta[] = {
12995		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12996		0x0000,
12997	};
12998	static const uint32_t txpwrctl[] = {
12999		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
13000		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
13001		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
13002		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
13003		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
13004		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
13005		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
13006		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
13007		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
13008		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
13009		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
13010		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
13011		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
13012		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13013		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13014		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13015		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13016		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13017		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13018		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13019		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13020		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13021		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13022		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13023		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13024		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13025		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13026		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13027		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13028		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13029		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13030		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13031		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13032		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13033		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13034		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13035		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13036		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13037		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
13038		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
13039		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
13040		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
13041		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
13042		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
13043		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13044		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13045		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13046		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13047		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13048		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13049		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13050		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13051		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13052		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13053		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13054		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13055		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13056		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13057		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13058		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13059		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13060		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13061		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13062		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13063		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13064		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13065		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13066		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13067		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13068		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13069		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13070		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13071		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13072		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13073		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13074		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13075		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13076		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13077		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13078		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13079		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13080		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13081		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13082		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13083		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13084		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13085		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13086		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13087		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13088		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13089		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13090		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13091		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13092		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13093		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13094		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13095		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13096		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13097		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13098		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13099		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13100		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13101		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13102		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13103		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13104		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13105		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13106		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13107		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13108		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13109		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13110		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13111		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13112		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13113		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13114		0x00000702,
13115	};
13116
13117	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13118
13119	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13120	    bwn_tab_sigsq_tbl);
13121	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13122	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13123	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13124	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13125	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13126	    bwn_tab_pllfrac_tbl);
13127	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13128	    bwn_tabl_iqlocal_tbl);
13129	if (mac->mac_phy.rev == 0) {
13130		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13131		    ofdmcckgain_r0);
13132		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13133		    ofdmcckgain_r0);
13134	} else {
13135		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13136		    ofdmcckgain_r1);
13137		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13138		    ofdmcckgain_r1);
13139	}
13140	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13141	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13142}
13143
13144static void
13145bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13146{
13147	struct siba_dev_softc *sd = mac->mac_sd;
13148	struct siba_softc *siba = sd->sd_bus;
13149	int i;
13150	static const uint16_t noisescale[] = {
13151		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13152		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13153		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13154		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13155		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13156		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13157		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13158	};
13159	static const uint32_t filterctl[] = {
13160		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13161		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13162	};
13163	static const uint32_t psctl[] = {
13164		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13165		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13166		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13167		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13168	};
13169	static const uint32_t gainidx[] = {
13170		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13171		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13172		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13173		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13174		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13175		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13176		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13177		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13178		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13179		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13180		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13181		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13182		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13183		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13184		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13185		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13186		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13187		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13188		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13189		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13190		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13191		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13192		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13193		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13194		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13195		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13196		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13197		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13198		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13199		0x0000001a, 0x64ca55ad, 0x0000001a
13200	};
13201	static const uint16_t auxgainidx[] = {
13202		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13203		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13204		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13205		0x0004, 0x0016
13206	};
13207	static const uint16_t swctl[] = {
13208		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13209		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13210		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13211		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13212		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13213		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13214		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13215		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13216	};
13217	static const uint8_t hf[] = {
13218		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13219		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13220	};
13221	static const uint32_t gainval[] = {
13222		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13223		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13224		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13225		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13226		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13227		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13228		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13229		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13230		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13231		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13232		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13233		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13234		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13235		0x000000f1, 0x00000000, 0x00000000
13236	};
13237	static const uint16_t gain[] = {
13238		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13239		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13240		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13241		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13242		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13243		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13244		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13245		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13246		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13247		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13248		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13249		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13250	};
13251	static const uint32_t papdeps[] = {
13252		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13253		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13254		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13255		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13256		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13257		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13258		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13259		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13260		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13261		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13262		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13263		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13264		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13265	};
13266	static const uint32_t papdmult[] = {
13267		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13268		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13269		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13270		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13271		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13272		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13273		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13274		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13275		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13276		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13277		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13278		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13279		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13280	};
13281	static const uint32_t gainidx_a0[] = {
13282		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13283		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13284		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13285		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13286		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13287		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13288		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13289		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13290		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13291		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13292		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13293		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13294		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13295	};
13296	static const uint16_t auxgainidx_a0[] = {
13297		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13298		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13299		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13300		0x0002, 0x0014
13301	};
13302	static const uint32_t gainval_a0[] = {
13303		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13304		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13305		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13306		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13307		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13308		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13309		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13310		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13311		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13312		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13313		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13314		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13315		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13316		0x000000f7, 0x00000000, 0x00000000
13317	};
13318	static const uint16_t gain_a0[] = {
13319		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13320		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13321		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13322		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13323		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13324		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13325		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13326		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13327		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13328		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13329		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13330		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13331	};
13332
13333	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13334
13335	for (i = 0; i < 704; i++)
13336		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13337
13338	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13339	    bwn_tab_sigsq_tbl);
13340	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13341	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13342	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13343	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13344	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13345	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13346	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13347	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13348	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13349	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13350	    bwn_tab_pllfrac_tbl);
13351	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13352	    bwn_tabl_iqlocal_tbl);
13353	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13354	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13355
13356	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
13357		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13358		    gainidx_a0);
13359		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13360		    auxgainidx_a0);
13361		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13362		    gainval_a0);
13363		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13364	}
13365}
13366
13367static void
13368bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13369{
13370	struct siba_dev_softc *sd = mac->mac_sd;
13371	struct siba_softc *siba = sd->sd_bus;
13372	struct bwn_softc *sc = mac->mac_sc;
13373	struct ifnet *ifp = sc->sc_ifp;
13374	struct ieee80211com *ic = ifp->if_l2com;
13375	static struct bwn_txgain_entry txgain_r2[] = {
13376		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13377		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13378		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13379		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13380		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13381		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13382		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13383		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13384		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13385		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13386		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13387		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13388		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13389		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13390		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13391		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13392		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13393		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13394		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13395		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13396		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13397		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13398		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13399		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13400		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13401		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13402		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13403		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13404		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13405		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13406		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13407		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13408		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13409		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13410		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13411		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13412		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13413		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13414		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13415		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13416		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13417		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13418		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13419		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13420		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13421		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13422		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13423		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13424		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13425		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13426		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13427		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13428		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13429		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13430		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13431		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13432		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13433		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13434		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13435		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13436		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13437		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13438		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13439		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13440	};
13441	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13442		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13443		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13444		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13445		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13446		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13447		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13448		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13449		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13450		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13451		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13452		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13453		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13454		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13455		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13456		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13457		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13458		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13459		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13460		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13461		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13462		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13463		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13464		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13465		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13466		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13467		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13468		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13469		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13470		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13471		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13472		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13473		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13474		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13475		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13476		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13477		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13478		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13479		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13480		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13481		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13482		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13483		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13484		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13485		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13486		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13487		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13488		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13489		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13490		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13491		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13492		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13493		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13494		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13495		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13496		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13497		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13498		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13499		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13500		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13501		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13502		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13503		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13504		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13505		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13506	};
13507	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13508		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13509		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13510		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13511		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13512		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13513		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13514		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13515		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13516		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13517		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13518		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13519		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13520		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13521		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13522		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13523		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13524		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13525		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13526		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13527		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13528		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13529		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13530		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13531		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13532		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13533		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13534		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13535		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13536		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13537		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13538		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13539		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13540		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13541		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13542		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13543		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13544		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13545		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13546		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13547		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13548		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13549		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13550		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13551		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13552		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13553		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13554		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13555		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13556		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13557		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13558		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13559		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13560		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13561		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13562		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13563		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13564		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13565		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13566		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13567		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13568		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13569		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13570		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13571		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13572	};
13573	static struct bwn_txgain_entry txgain_r0[] = {
13574		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13575		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13576		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13577		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13578		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13579		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13580		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13581		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13582		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13583		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13584		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13585		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13586		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13587		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13588		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13589		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13590		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13591		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13592		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13593		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13594		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13595		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13596		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13597		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13598		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13599		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13600		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13601		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13602		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13603		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13604		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13605		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13606		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13607		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13608		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13609		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13610		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13611		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13612		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13613		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13614		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13615		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13616		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13617		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13618		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13619		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13620		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13621		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13622		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13623		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13624		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13625		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13626		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13627		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13628		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13629		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13630		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13631		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13632		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13633		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13634		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13635		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13636		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13637		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13638	};
13639	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13640		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13641		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13642		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13643		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13644		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13645		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13646		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13647		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13648		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13649		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13650		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13651		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13652		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13653		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13654		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13655		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13656		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13657		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13658		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13659		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13660		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13661		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13662		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13663		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13664		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13665		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13666		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13667		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13668		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13669		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13670		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13671		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13672		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13673		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13674		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13675		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13676		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13677		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13678		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13679		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13680		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13681		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13682		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13683		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13684		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13685		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13686		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13687		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13688		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13689		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13690		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13691		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13692		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13693		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13694		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13695		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13696		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13697		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13698		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13699		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13700		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13701		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13702		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13703		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13704	};
13705	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13706		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13707		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13708		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13709		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13710		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13711		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13712		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13713		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13714		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13715		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13716		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13717		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13718		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13719		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13720		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13721		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13722		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13723		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13724		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13725		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13726		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13727		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13728		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13729		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13730		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13731		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13732		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13733		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13734		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13735		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13736		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13737		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13738		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13739		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13740		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13741		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13742		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13743		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13744		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13745		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13746		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13747		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13748		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13749		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13750		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13751		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13752		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13753		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13754		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13755		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13756		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13757		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13758		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13759		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13760		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13761		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13762		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13763		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13764		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13765		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13766		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13767		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13768		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13769		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13770	};
13771	static struct bwn_txgain_entry txgain_r1[] = {
13772		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13773		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13774		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13775		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13776		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13777		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13778		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13779		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13780		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13781		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13782		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13783		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13784		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13785		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13786		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13787		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13788		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13789		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13790		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13791		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13792		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13793		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13794		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13795		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13796		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13797		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13798		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13799		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13800		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13801		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13802		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13803		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13804		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13805		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13806		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13807		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13808		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13809		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13810		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13811		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13812		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13813		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13814		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13815		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13816		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13817		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13818		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13819		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13820		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13821		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13822		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13823		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13824		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13825		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13826		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13827		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13828		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13829		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13830		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13831		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13832		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13833		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13834		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13835		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13836		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13837		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13838		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13839		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13840		{ 7, 11, 6, 0, 71 }
13841	};
13842	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13843		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13844		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13845		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13846		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13847		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13848		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13849		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13850		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13851		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13852		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13853		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13854		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13855		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13856		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13857		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13858		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13859		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13860		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13861		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13862		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13863		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13864		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13865		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13866		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13867		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13868		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13869		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13870		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13871		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13872		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13873		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13874		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13875		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13876		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13877		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13878		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13879		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13880		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13881		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13882		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13883		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13884		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13885		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13886		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13887		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13888		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13889		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13890		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13891		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13892		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13893		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13894		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13895		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13896		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13897		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13898		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13899		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13900		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13901		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13902		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13903		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13904		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13905		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13906		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13907	};
13908	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13909		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13910		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13911		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13912		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13913		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13914		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13915		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13916		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13917		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13918		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13919		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13920		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13921		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13922		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13923		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13924		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13925		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13926		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13927		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13928		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13929		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13930		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13931		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13932		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13933		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13934		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13935		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13936		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13937		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13938		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13939		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13940		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13941		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13942		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13943		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13944		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13945		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13946		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13947		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13948		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13949		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13950		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13951		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13952		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13953		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13954		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13955		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13956		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13957		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13958		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13959		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13960		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13961		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13962		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13963		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13964		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13965		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13966		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13967		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13968		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13969		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13970		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13971		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13972		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13973	};
13974
13975	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13976		if (siba->siba_sprom.bf_hi & BWN_BFH_NOPA)
13977			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13978		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13979			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13980			    txgain_2ghz_r2);
13981		else
13982			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13983			    txgain_5ghz_r2);
13984		return;
13985	}
13986
13987	if (mac->mac_phy.rev == 0) {
13988		if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
13989		    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
13990			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13991		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13992			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13993			    txgain_2ghz_r0);
13994		else
13995			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13996			    txgain_5ghz_r0);
13997		return;
13998	}
13999
14000	if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
14001	    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
14002		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
14003	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
14004		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
14005	else
14006		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
14007}
14008
14009static void
14010bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
14011{
14012	uint32_t offset, type;
14013
14014	type = BWN_TAB_GETTYPE(typeoffset);
14015	offset = BWN_TAB_GETOFFSET(typeoffset);
14016	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14017
14018	switch (type) {
14019	case BWN_TAB_8BIT:
14020		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
14021		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14022		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14023		break;
14024	case BWN_TAB_16BIT:
14025		KASSERT(!(value & ~0xffff),
14026		    ("%s:%d: fail", __func__, __LINE__));
14027		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14028		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14029		break;
14030	case BWN_TAB_32BIT:
14031		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14032		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
14033		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14034		break;
14035	default:
14036		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14037	}
14038}
14039
14040static int
14041bwn_phy_lp_loopback(struct bwn_mac *mac)
14042{
14043	struct bwn_phy_lp_iq_est ie;
14044	int i, index = -1;
14045	uint32_t tmp;
14046
14047	memset(&ie, 0, sizeof(ie));
14048
14049	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14050	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14051	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14052	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14053	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14054	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14055	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14056	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14057	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14058	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14059	for (i = 0; i < 32; i++) {
14060		bwn_phy_lp_set_rxgain_idx(mac, i);
14061		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14062		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14063			continue;
14064		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14065		if ((tmp > 4000) && (tmp < 10000)) {
14066			index = i;
14067			break;
14068		}
14069	}
14070	bwn_phy_lp_ddfs_turnoff(mac);
14071	return (index);
14072}
14073
14074static void
14075bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14076{
14077
14078	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14079}
14080
14081static void
14082bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14083    int incr1, int incr2, int scale_idx)
14084{
14085
14086	bwn_phy_lp_ddfs_turnoff(mac);
14087	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14088	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14089	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14090	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14091	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14092	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14093	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14094	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14095	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14096	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14097}
14098
14099static uint8_t
14100bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14101    struct bwn_phy_lp_iq_est *ie)
14102{
14103	int i;
14104
14105	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14106	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14107	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14108	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14109	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14110
14111	for (i = 0; i < 500; i++) {
14112		if (!(BWN_PHY_READ(mac,
14113		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14114			break;
14115		DELAY(1000);
14116	}
14117	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14118		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14119		return 0;
14120	}
14121
14122	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14123	ie->ie_iqprod <<= 16;
14124	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14125	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14126	ie->ie_ipwr <<= 16;
14127	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14128	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14129	ie->ie_qpwr <<= 16;
14130	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14131
14132	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14133	return 1;
14134}
14135
14136static uint32_t
14137bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14138{
14139	uint32_t offset, type, value;
14140
14141	type = BWN_TAB_GETTYPE(typeoffset);
14142	offset = BWN_TAB_GETOFFSET(typeoffset);
14143	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14144
14145	switch (type) {
14146	case BWN_TAB_8BIT:
14147		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14148		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14149		break;
14150	case BWN_TAB_16BIT:
14151		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14152		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14153		break;
14154	case BWN_TAB_32BIT:
14155		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14156		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14157		value <<= 16;
14158		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14159		break;
14160	default:
14161		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14162		value = 0;
14163	}
14164
14165	return (value);
14166}
14167
14168static void
14169bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14170{
14171
14172	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14173	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14174}
14175
14176static void
14177bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14178{
14179	uint16_t ctl;
14180
14181	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14182	ctl |= dac << 7;
14183	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14184}
14185
14186static void
14187bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14188{
14189
14190	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14191	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14192}
14193
14194static void
14195bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14196{
14197
14198	if (mac->mac_phy.rev < 2)
14199		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14200	else {
14201		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14202		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14203	}
14204	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14205}
14206
14207static uint16_t
14208bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14209{
14210
14211	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14212}
14213
14214static uint8_t
14215bwn_nbits(int32_t val)
14216{
14217	uint32_t tmp;
14218	uint8_t nbits = 0;
14219
14220	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14221		nbits++;
14222	return (nbits);
14223}
14224
14225static void
14226bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14227    struct bwn_txgain_entry *table)
14228{
14229	int i;
14230
14231	for (i = offset; i < count; i++)
14232		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14233}
14234
14235static void
14236bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14237    struct bwn_txgain_entry data)
14238{
14239
14240	if (mac->mac_phy.rev >= 2)
14241		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14242	else
14243		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14244}
14245
14246static void
14247bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14248    struct bwn_txgain_entry te)
14249{
14250	struct bwn_softc *sc = mac->mac_sc;
14251	struct ifnet *ifp = sc->sc_ifp;
14252	struct ieee80211com *ic = ifp->if_l2com;
14253	uint32_t tmp;
14254
14255	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14256
14257	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14258	if (mac->mac_phy.rev >= 3) {
14259		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14260		    (0x10 << 24) : (0x70 << 24));
14261	} else {
14262		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14263		    (0x14 << 24) : (0x7f << 24));
14264	}
14265	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14266	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14267	    te.te_bbmult << 20 | te.te_dac << 28);
14268}
14269
14270static void
14271bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14272    struct bwn_txgain_entry te)
14273{
14274
14275	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14276
14277	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14278	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14279	    te.te_dac);
14280	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14281}
14282
14283static void
14284bwn_sysctl_node(struct bwn_softc *sc)
14285{
14286	device_t dev = sc->sc_dev;
14287	struct bwn_mac *mac;
14288	struct bwn_stats *stats;
14289
14290	/* XXX assume that count of MAC is only 1. */
14291
14292	if ((mac = sc->sc_curmac) == NULL)
14293		return;
14294	stats = &mac->mac_stats;
14295
14296	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14297	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14298	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14299	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14300	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14301	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14302	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14303	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14304	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14305
14306#ifdef BWN_DEBUG
14307	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14308	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14309	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14310#endif
14311}
14312
14313static void
14314bwn_identify(driver_t *driver, device_t parent)
14315{
14316
14317	BUS_ADD_CHILD(parent, 0, "bwn", -1);
14318}
14319
14320static device_method_t bwn_methods[] = {
14321	/* Device interface */
14322	DEVMETHOD(device_identify,	bwn_identify),
14323	DEVMETHOD(device_probe,		bwn_probe),
14324	DEVMETHOD(device_attach,	bwn_attach),
14325	DEVMETHOD(device_detach,	bwn_detach),
14326	DEVMETHOD(device_suspend,	bwn_suspend),
14327	DEVMETHOD(device_resume,	bwn_resume),
14328	{ 0,0 }
14329};
14330static driver_t bwn_driver = {
14331	"bwn",
14332	bwn_methods,
14333	sizeof(struct bwn_softc)
14334};
14335static devclass_t bwn_devclass;
14336DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14337MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14338MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14339MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14340MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14341